From 5e54ace306e7be5b3b74fbc2fd7f7edbd33472bd Mon Sep 17 00:00:00 2001 From: Mukul Sabharwal Date: Wed, 6 May 2020 02:59:37 -0700 Subject: [PATCH] Update CoreCLR Headers for .NET 5 --- .../native/BPerfProfilerCallback.cpp | 2 +- .../native/BPerfProfilerCallback.h | 2 +- CoreCLRProfiler/native/CMakeLists.txt | 2 +- .../coreclr_headers/src/inc/CMakeLists.txt | 68 +- .../coreclr_headers/src/inc/CrstTypeTool.cs | 18 +- .../coreclr_headers/src/inc/CrstTypes.def | 57 +- .../coreclr_headers/src/inc/MSCOREE.IDL | 113 +- .../coreclr_headers/src/inc/OpCodeGen.pl | 18 +- .../coreclr_headers/src/inc/allocacheck.h | 18 +- .../src/inc/apithreadstress.cpp | 171 - .../coreclr_headers/src/inc/apithreadstress.h | 57 - .../native/coreclr_headers/src/inc/appxutil.h | 5 - .../coreclr_headers/src/inc/arrayholder.h | 4 +- .../coreclr_headers/src/inc/arraylist.h | 42 +- .../native/coreclr_headers/src/inc/bbsweep.h | 54 +- .../native/coreclr_headers/src/inc/bitmask.h | 10 +- .../coreclr_headers/src/inc/bitmask.inl | 14 +- .../coreclr_headers/src/inc/bitposition.h | 4 +- .../coreclr_headers/src/inc/bitvector.h | 32 +- .../coreclr_headers/src/inc/blobfetcher.h | 6 +- .../native/coreclr_headers/src/inc/cahlpr.h | 2 +- .../native/coreclr_headers/src/inc/caparser.h | 6 +- .../src/inc/ceefilegenwriter.h | 12 +- .../native/coreclr_headers/src/inc/ceegen.h | 14 +- .../src/inc/ceegentokenmapper.h | 12 +- .../src/inc/ceesectionstring.h | 2 +- .../native/coreclr_headers/src/inc/check.h | 99 +- .../native/coreclr_headers/src/inc/check.inl | 55 +- .../coreclr_headers/src/inc/circularlog.h | 38 - .../native/coreclr_headers/src/inc/clr/fs.h | 2 - .../coreclr_headers/src/inc/clr/fs/dir.h | 129 - .../coreclr_headers/src/inc/clr/fs/file.h | 40 - .../coreclr_headers/src/inc/clr/fs/path.h | 77 +- .../coreclr_headers/src/inc/clr_std/algorithm | 4 +- .../src/inc/clr_std/type_traits | 102 +- .../coreclr_headers/src/inc/clr_std/vector | 10 +- .../coreclr_headers/src/inc/clrconfig.h | 96 +- .../coreclr_headers/src/inc/clrconfigvalues.h | 425 +- .../coreclr_headers/src/inc/clrdata.idl | 32 +- .../native/coreclr_headers/src/inc/clrhost.h | 299 +- .../coreclr_headers/src/inc/clrinternal.idl | 215 +- .../native/coreclr_headers/src/inc/clrnt.h | 85 +- .../src/inc/clrprivappxhosting.idl | 66 - .../src/inc/clrprivbinderutil.h | 536 +- .../src/inc/clrprivbinding.idl | 86 +- .../src/inc/clrprivhosting.idl | 92 - .../src/inc/clrprivruntimebinders.idl | 39 - .../native/coreclr_headers/src/inc/clrtypes.h | 31 +- .../coreclr_headers/src/inc/clrversion.h | 30 + .../native/coreclr_headers/src/inc/complex.h | 6 +- .../coreclr_headers/src/inc/configuration.h | 10 +- .../native/coreclr_headers/src/inc/contract.h | 171 +- .../coreclr_headers/src/inc/contract.inl | 42 +- .../native/coreclr_headers/src/inc/contxt.h | 1216 ++-- .../native/coreclr_headers/src/inc/cor.h | 333 +- .../coreclr_headers/src/inc/corbbtprof.h | 48 +- .../coreclr_headers/src/inc/corcompile.h | 143 +- .../coreclr_headers/src/inc/cordebug.idl | 26 +- .../coreclr_headers/src/inc/cordebuginfo.h | 18 +- .../coreclr_headers/src/inc/coredistools.h | 2 +- .../coreclr_headers/src/inc/corerror.xml | 24 +- .../native/coreclr_headers/src/inc/corexcep.h | 2 +- .../native/coreclr_headers/src/inc/corhdr.h | 124 +- .../coreclr_headers/src/inc/corhlpr.cpp | 14 +- .../native/coreclr_headers/src/inc/corhlpr.h | 166 +- .../coreclr_headers/src/inc/corhlprpriv.cpp | 4 +- .../coreclr_headers/src/inc/corhlprpriv.h | 134 +- .../native/coreclr_headers/src/inc/corhost.h | 147 +- .../native/coreclr_headers/src/inc/corimage.h | 4 +- .../native/coreclr_headers/src/inc/corinfo.h | 436 +- .../src/inc/corinfoinstructionset.h | 514 ++ .../native/coreclr_headers/src/inc/corjit.h | 190 +- .../coreclr_headers/src/inc/corjitflags.h | 127 +- .../coreclr_headers/src/inc/corjithost.h | 8 +- .../native/coreclr_headers/src/inc/corpriv.h | 43 +- .../coreclr_headers/src/inc/corprof.idl | 415 +- .../native/coreclr_headers/src/inc/corpub.idl | 48 +- .../native/coreclr_headers/src/inc/corsym.idl | 70 +- .../coreclr_headers/src/inc/cortypeinfo.h | 2 +- .../coreclr_headers/src/inc/crosscomp.h | 142 +- .../coreclr_headers/src/inc/crsttypes.h | 288 +- .../native/coreclr_headers/src/inc/crtwrap.h | 2 +- .../native/coreclr_headers/src/inc/cvconst.h | 224 +- .../native/coreclr_headers/src/inc/cvinfo.h | 112 +- .../coreclr_headers/src/inc/cycletimer.h | 2 +- .../native/coreclr_headers/src/inc/daccess.h | 285 +- .../coreclr_headers/src/inc/dacprivate.h | 866 +-- .../native/coreclr_headers/src/inc/dacvars.h | 63 +- .../src/inc/dbgenginemetrics.h | 4 +- .../coreclr_headers/src/inc/debugmacros.h | 51 +- .../coreclr_headers/src/inc/debugreturn.h | 2 +- .../src/inc/delayloadhelpers.h | 6 +- .../native/coreclr_headers/src/inc/dlwrap.h | 92 +- .../native/coreclr_headers/src/inc/ecmakey.h | 9 + .../native/coreclr_headers/src/inc/eetwain.h | 117 +- .../native/coreclr_headers/src/inc/eexcp.h | 34 +- .../coreclr_headers/src/inc/eventtrace.h | 40 +- .../coreclr_headers/src/inc/eventtracebase.h | 149 +- .../native/coreclr_headers/src/inc/ex.h | 136 +- .../native/coreclr_headers/src/inc/factory.h | 4 +- .../coreclr_headers/src/inc/factory.inl | 4 +- .../coreclr_headers/src/inc/fixuppointer.h | 12 +- .../coreclr_headers/src/inc/formattype.cpp | 513 +- .../coreclr_headers/src/inc/formattype.h | 36 +- .../native/coreclr_headers/src/inc/fstream.h | 6 +- .../native/coreclr_headers/src/inc/fstring.h | 2 +- .../native/coreclr_headers/src/inc/fusion.idl | 138 +- .../coreclr_headers/src/inc/gcdecoder.cpp | 22 +- .../native/coreclr_headers/src/inc/gcdump.h | 16 +- .../native/coreclr_headers/src/inc/gcinfo.h | 31 +- .../coreclr_headers/src/inc/gcinfoarraylist.h | 2 +- .../coreclr_headers/src/inc/gcinfodecoder.h | 76 +- .../coreclr_headers/src/inc/gcinfodumper.h | 2 +- .../coreclr_headers/src/inc/gcinfoencoder.h | 58 +- .../coreclr_headers/src/inc/gcinfotypes.h | 108 +- .../native/coreclr_headers/src/inc/gcrefmap.h | 20 +- .../coreclr_headers/src/inc/genheaders.cs | 70 +- .../native/coreclr_headers/src/inc/genrops.pl | 2 +- .../src/inc/getproductversionnumber.h | 8 +- .../native/coreclr_headers/src/inc/holder.h | 148 +- .../coreclr_headers/src/inc/iallocator.h | 4 +- .../coreclr_headers/src/inc/iceefilegen.h | 36 +- .../native/coreclr_headers/src/inc/il_kywd.h | 12 +- .../coreclr_headers/src/inc/ilformatter.h | 6 +- .../src/inc/internalunknownimpl.h | 533 +- .../native/coreclr_headers/src/inc/iterator.h | 32 +- .../coreclr_headers/src/inc/jithelpers.h | 93 +- .../native/coreclr_headers/src/inc/jitperf.h | 97 - .../native/coreclr_headers/src/inc/lazycow.h | 99 - .../coreclr_headers/src/inc/livedatatarget.h | 22 +- .../coreclr_headers/src/inc/loaderheap.h | 31 +- .../native/coreclr_headers/src/inc/log.h | 5 +- .../native/coreclr_headers/src/inc/loglf.h | 2 +- .../src/inc/longfilepathwrappers.h | 53 +- .../native/coreclr_headers/src/inc/md5.h | 14 +- .../native/coreclr_headers/src/inc/mdcommon.h | 2 +- .../coreclr_headers/src/inc/mdfileformat.h | 272 + .../coreclr_headers/src/inc/memorypool.h | 4 +- .../coreclr_headers/src/inc/memoryrange.h | 26 +- .../native/coreclr_headers/src/inc/metadata.h | 575 +- .../coreclr_headers/src/inc/metadataexports.h | 10 +- .../coreclr_headers/src/inc/metadatatracker.h | 18 +- .../coreclr_headers/src/inc/metahost.idl | 26 +- .../coreclr_headers/src/inc/metamodelpub.h | 35 +- .../coreclr_headers/src/inc/mpl/type_list | 6 +- .../coreclr_headers/src/inc/mscorsvc.idl | 86 +- .../src/inc/nativevaraccessors.h | 20 +- .../native/coreclr_headers/src/inc/ngen.h | 16 +- .../coreclr_headers/src/inc/nibblemapmacros.h | 4 +- .../coreclr_headers/src/inc/nibblestream.h | 32 +- .../coreclr_headers/src/inc/nsutilpriv.h | 30 +- .../native/coreclr_headers/src/inc/openum.h | 6 +- .../native/coreclr_headers/src/inc/opinfo.h | 12 +- .../src/inc/optsmallperfcritical.h | 6 +- .../native/coreclr_headers/src/inc/ostype.h | 14 +- .../coreclr_headers/src/inc/outstring.h | 40 +- .../native/coreclr_headers/src/inc/palclr.h | 63 +- .../coreclr_headers/src/inc/palclr_win.h | 14 +- .../coreclr_headers/src/inc/patchpointinfo.h | 145 + .../coreclr_headers/src/inc/pedecoder.h | 13 +- .../coreclr_headers/src/inc/pedecoder.inl | 45 +- .../coreclr_headers/src/inc/peinformation.h | 12 +- .../native/coreclr_headers/src/inc/perflog.h | 142 - .../coreclr_headers/src/inc/pesectionman.h | 52 +- .../coreclr_headers/src/inc/posterror.h | 10 +- .../coreclr_headers/src/inc/predeftlsslot.h | 52 +- .../coreclr_headers/src/inc/prettyprintsig.h | 4 +- .../coreclr_headers/src/inc/profilepriv.h | 30 +- .../coreclr_headers/src/inc/profilepriv.inl | 84 +- .../native/coreclr_headers/src/inc/random.h | 44 +- .../coreclr_headers/src/inc/rangetree.h | 14 +- .../native/coreclr_headers/src/inc/readme.md | 4 +- .../coreclr_headers/src/inc/readytorun.h | 120 +- .../src/inc/readytorunhelpers.h | 13 +- .../src/inc/readytoruninstructionset.h | 39 + .../native/coreclr_headers/src/inc/regdisp.h | 143 +- .../coreclr_headers/src/inc/regex_base.h | 20 +- .../coreclr_headers/src/inc/registrywrapper.h | 2 +- .../coreclr_headers/src/inc/releaseholder.h | 8 +- .../native/coreclr_headers/src/inc/safemath.h | 111 +- .../native/coreclr_headers/src/inc/safewrap.h | 28 +- .../native/coreclr_headers/src/inc/sarray.h | 22 +- .../native/coreclr_headers/src/inc/sarray.inl | 8 +- .../native/coreclr_headers/src/inc/sbuffer.h | 86 +- .../coreclr_headers/src/inc/sbuffer.inl | 242 +- .../coreclr_headers/src/inc/securityutil.h | 12 +- .../coreclr_headers/src/inc/securitywrapper.h | 10 +- .../native/coreclr_headers/src/inc/sha1.h | 50 + .../native/coreclr_headers/src/inc/shash.h | 259 +- .../native/coreclr_headers/src/inc/shash.inl | 156 +- .../src/inc/shim/locationinfo.h | 4 +- .../src/inc/shim/runtimeselector.h | 2 +- .../src/inc/shim/runtimeselector.inl | 22 +- .../src/inc/shim/shimselector.inl | 20 +- .../src/inc/shim/versionandlocationinfo.h | 2 +- .../src/inc/shim/versionandlocationinfo.inl | 10 +- .../src/inc/shim/versioninfo.h | 8 +- .../src/inc/shim/versioninfo.inl | 44 +- .../native/coreclr_headers/src/inc/shimload.h | 4 +- .../coreclr_headers/src/inc/sigbuilder.h | 4 +- .../coreclr_headers/src/inc/sigparser.h | 190 +- .../coreclr_headers/src/inc/simplerhash.h | 36 +- .../coreclr_headers/src/inc/simplerhash.inl | 28 +- .../native/coreclr_headers/src/inc/slist.h | 48 +- .../coreclr_headers/src/inc/sospriv.idl | 55 +- .../native/coreclr_headers/src/inc/sstring.h | 57 +- .../coreclr_headers/src/inc/sstring.inl | 109 +- .../native/coreclr_headers/src/inc/stack.h | 6 +- .../coreclr_headers/src/inc/stackframe.h | 18 +- .../coreclr_headers/src/inc/stacktrace.h | 22 +- .../coreclr_headers/src/inc/static_assert.h | 2 +- .../coreclr_headers/src/inc/staticcontract.h | 18 +- .../coreclr_headers/src/inc/stdmacros.h | 74 +- .../native/coreclr_headers/src/inc/stgpool.h | 366 +- .../native/coreclr_headers/src/inc/stgpooli.h | 46 +- .../coreclr_headers/src/inc/stresslog.h | 185 +- .../coreclr_headers/src/inc/stringarraylist.h | 6 +- .../src/inc/stringarraylist.inl | 12 +- .../coreclr_headers/src/inc/strongname.h | 9 - .../src/inc/strongnameholders.h | 23 + .../src/inc/strongnameinternal.h | 36 + .../native/coreclr_headers/src/inc/switches.h | 49 +- .../native/coreclr_headers/src/inc/thekey.h | 54 + .../native/coreclr_headers/src/inc/tls.h | 4 +- .../coreclr_headers/src/inc/unreachable.h | 26 + .../native/coreclr_headers/src/inc/utilcode.h | 595 +- .../native/coreclr_headers/src/inc/utsem.h | 21 +- .../native/coreclr_headers/src/inc/vererror.h | 137 - .../native/coreclr_headers/src/inc/volatile.h | 179 +- .../coreclr_headers/src/inc/vptr_list.h | 29 +- .../coreclr_headers/src/inc/warningcontrol.h | 48 - .../coreclr_headers/src/inc/win64unwind.h | 14 +- .../coreclr_headers/src/inc/winrt/ntassert.h | 8 +- .../src/inc/winrt/paraminstanceapi.h | 624 +- .../src/inc/winrt/windowsstring.h | 50 +- .../src/inc/winrtprojectedtypes.h | 14 +- .../native/coreclr_headers/src/inc/winwrap.h | 54 +- .../coreclr_headers/src/inc/xclrdata.idl | 168 +- .../coreclr_headers/src/inc/xcordebug.idl | 14 +- .../native/coreclr_headers/src/inc/zapper.h | 14 +- .../coreclr_headers/src/pal/CMakeLists.txt | 17 + .../coreclr_headers/src/pal/inc/mbusafecrt.h | 9 +- .../native/coreclr_headers/src/pal/inc/pal.h | 871 +-- .../coreclr_headers/src/pal/inc/pal_char16.h | 55 - .../coreclr_headers/src/pal/inc/pal_endian.h | 22 +- .../coreclr_headers/src/pal/inc/pal_error.h | 23 + .../coreclr_headers/src/pal/inc/pal_mstypes.h | 69 +- .../coreclr_headers/src/pal/inc/pal_unwind.h | 91 - .../coreclr_headers/src/pal/inc/palprivate.h | 59 +- .../coreclr_headers/src/pal/inc/rt/accctrl.h | 2 +- .../coreclr_headers/src/pal/inc/rt/aclapi.h | 2 +- .../coreclr_headers/src/pal/inc/rt/atl.h | 557 -- .../coreclr_headers/src/pal/inc/rt/atlcom.h | 13 - .../coreclr_headers/src/pal/inc/rt/atlwin.h | 13 - .../coreclr_headers/src/pal/inc/rt/commctrl.h | 2 +- .../coreclr_headers/src/pal/inc/rt/commdlg.h | 2 +- .../coreclr_headers/src/pal/inc/rt/conio.h | 4 +- .../src/pal/inc/rt/cpp/assert.h | 2 +- .../src/pal/inc/rt/cpp/cstdlib | 2 +- .../src/pal/inc/rt/cpp/ctype.h | 2 +- .../src/pal/inc/rt/cpp/emmintrin.h | 2 +- .../src/pal/inc/rt/cpp/fcntl.h | 2 +- .../src/pal/inc/rt/cpp/float.h | 2 +- .../coreclr_headers/src/pal/inc/rt/cpp/io.h | 2 +- .../src/pal/inc/rt/cpp/limits.h | 2 +- .../src/pal/inc/rt/cpp/malloc.h | 2 +- .../coreclr_headers/src/pal/inc/rt/cpp/math.h | 4 +- .../src/pal/inc/rt/cpp/memory.h | 2 +- .../src/pal/inc/rt/cpp/stdarg.h | 4 +- .../src/pal/inc/rt/cpp/stddef.h | 6 +- .../src/pal/inc/rt/cpp/stdio.h | 2 +- .../src/pal/inc/rt/cpp/stdlib.h | 2 +- .../src/pal/inc/rt/cpp/string.h | 2 +- .../coreclr_headers/src/pal/inc/rt/cpp/time.h | 2 +- .../src/pal/inc/rt/cpp/wchar.h | 2 +- .../coreclr_headers/src/pal/inc/rt/crtdbg.h | 2 +- .../coreclr_headers/src/pal/inc/rt/guiddef.h | 2 +- .../coreclr_headers/src/pal/inc/rt/htmlhelp.h | 4 +- .../coreclr_headers/src/pal/inc/rt/intsafe.h | 75 +- .../coreclr_headers/src/pal/inc/rt/mbstring.h | 4 +- .../coreclr_headers/src/pal/inc/rt/new.h | 2 +- .../coreclr_headers/src/pal/inc/rt/no_sal2.h | 2 +- .../coreclr_headers/src/pal/inc/rt/ntimage.h | 20 +- .../coreclr_headers/src/pal/inc/rt/oaidl.h | 52 +- .../coreclr_headers/src/pal/inc/rt/objidl.h | 159 +- .../coreclr_headers/src/pal/inc/rt/ocidl.h | 2 +- .../coreclr_headers/src/pal/inc/rt/oleauto.h | 4 +- .../coreclr_headers/src/pal/inc/rt/olectl.h | 2 +- .../coreclr_headers/src/pal/inc/rt/oleidl.h | 2 +- .../coreclr_headers/src/pal/inc/rt/palrt.h | 217 +- .../coreclr_headers/src/pal/inc/rt/poppack.h | 2 +- .../coreclr_headers/src/pal/inc/rt/process.h | 2 +- .../coreclr_headers/src/pal/inc/rt/pshpack1.h | 2 +- .../coreclr_headers/src/pal/inc/rt/pshpack2.h | 2 +- .../coreclr_headers/src/pal/inc/rt/pshpack4.h | 4 +- .../coreclr_headers/src/pal/inc/rt/pshpack8.h | 4 +- .../coreclr_headers/src/pal/inc/rt/pshpck16.h | 4 +- .../coreclr_headers/src/pal/inc/rt/richedit.h | 4 +- .../coreclr_headers/src/pal/inc/rt/rpc.h | 9 +- .../coreclr_headers/src/pal/inc/rt/rpcndr.h | 4 +- .../coreclr_headers/src/pal/inc/rt/safecrt.h | 454 +- .../coreclr_headers/src/pal/inc/rt/sal.h | 112 +- .../coreclr_headers/src/pal/inc/rt/servprov.h | 8 +- .../coreclr_headers/src/pal/inc/rt/shellapi.h | 4 +- .../coreclr_headers/src/pal/inc/rt/shlobj.h | 4 +- .../coreclr_headers/src/pal/inc/rt/shlwapi.h | 4 +- .../src/pal/inc/rt/specstrings.h | 8 +- .../src/pal/inc/rt/specstrings_adt.h | 4 +- .../src/pal/inc/rt/specstrings_strict.h | 482 +- .../src/pal/inc/rt/specstrings_undef.h | 2 +- .../coreclr_headers/src/pal/inc/rt/symcrypt.h | 2 +- .../coreclr_headers/src/pal/inc/rt/tlhelp32.h | 2 +- .../coreclr_headers/src/pal/inc/rt/unknwn.h | 26 +- .../coreclr_headers/src/pal/inc/rt/urlmon.h | 2 +- .../coreclr_headers/src/pal/inc/rt/verrsrc.h | 2 +- .../coreclr_headers/src/pal/inc/rt/vsassert.h | 93 - .../src/pal/inc/rt/winapifamily.h | 10 +- .../coreclr_headers/src/pal/inc/rt/winbase.h | 2 +- .../coreclr_headers/src/pal/inc/rt/wincrypt.h | 2 +- .../coreclr_headers/src/pal/inc/rt/windef.h | 2 +- .../coreclr_headers/src/pal/inc/rt/windows.h | 2 +- .../coreclr_headers/src/pal/inc/rt/winerror.h | 2 +- .../coreclr_headers/src/pal/inc/rt/wininet.h | 2 +- .../coreclr_headers/src/pal/inc/rt/winnls.h | 2 +- .../coreclr_headers/src/pal/inc/rt/winnt.h | 2 +- .../coreclr_headers/src/pal/inc/rt/winresrc.h | 2 +- .../coreclr_headers/src/pal/inc/rt/winternl.h | 2 +- .../coreclr_headers/src/pal/inc/rt/winuser.h | 2 +- .../coreclr_headers/src/pal/inc/rt/winver.h | 2 +- .../coreclr_headers/src/pal/inc/rt/wtsapi32.h | 2 +- .../coreclr_headers/src/pal/inc/strsafe.h | 775 +-- .../src/pal/inc/unixasmmacros.inc | 12 +- .../src/pal/inc/unixasmmacrosamd64.inc | 8 +- .../src/pal/inc/unixasmmacrosarm.inc | 2 +- .../src/pal/inc/unixasmmacrosarm64.inc | 2 +- .../src/pal/inc/unixasmmacrosx86.inc | 2 +- .../pal/prebuilt/corerror/makecorerror.bat | 11 + .../src/pal/prebuilt/corerror/mscorurt.rc | 333 ++ .../src/pal/prebuilt/corerror/readme.txt | 7 + .../src/pal/prebuilt/idl/clrdata_i.cpp | 102 + .../src/pal/prebuilt/idl/clrinternal_i.cpp | 73 + .../pal/prebuilt/idl/clrprivappxhosting_i.cpp | 76 + .../src/pal/prebuilt/idl/clrprivbinding_i.cpp | 91 + .../src/pal/prebuilt/idl/cordebug_i.cpp | 469 ++ .../src/pal/prebuilt/idl/corprof_i.cpp | 157 + .../src/pal/prebuilt/idl/corpub_i.cpp | 94 + .../src/pal/prebuilt/idl/corsym_i.cpp | 175 + .../src/pal/prebuilt/idl/mscorsvc_i.cpp | 142 + .../src/pal/prebuilt/idl/sospriv_i.cpp | 103 + .../src/pal/prebuilt/idl/xclrdata_i.cpp | 145 + .../src/pal/prebuilt/idl/xcordebug_i.cpp | 73 + .../src/pal/prebuilt/inc/CMakeLists.txt | 2 - .../src/pal/prebuilt/inc/asm_version.h | 22 - .../src/pal/prebuilt/inc/buildnumber.h | 23 - .../src/pal/prebuilt/inc/clrdata.h | 109 +- .../src/pal/prebuilt/inc/clrinternal.h | 671 +-- .../src/pal/prebuilt/inc/clrprivbinding.h | 312 +- .../src/pal/prebuilt/inc/clrprivhosting.h | 236 - .../pal/prebuilt/inc/clrprivruntimebinders.h | 107 - .../src/pal/prebuilt/inc/corprof.h | 2099 ++++++- .../src/pal/prebuilt/inc/corsym.h | 12 +- .../src/pal/prebuilt/inc/fusion.h | 149 +- .../src/pal/prebuilt/inc/fxver.h | 188 +- .../src/pal/prebuilt/inc/fxver.rc | 60 +- .../src/pal/prebuilt/inc/fxverstrings.h | 17 - .../src/pal/prebuilt/inc/mscoree.h | 74 - .../pal/prebuilt/inc/ndpversion_generated.h | 15 - .../src/pal/prebuilt/inc/product_version.h | 113 - .../src/pal/prebuilt/inc/sospriv.h | 589 +- .../src/pal/prebuilt/inc/version.h | 17 - .../src/pal/prebuilt/inc/xclrdata.h | 12 +- .../src/pal/prebuilt/inc/xcordebug.h | 93 - .../coreclr_headers/src/pal/src/.tpattributes | 1 + .../src/pal/src/CMakeLists.txt | 341 ++ .../src/arch/amd64/activationhandlerwrapper.S | 30 + .../src/pal/src/arch/amd64/asmconstants.h | 106 + .../src/arch/amd64/callsignalhandlerwrapper.S | 31 + .../src/pal/src/arch/amd64/context.S | 21 + .../src/pal/src/arch/amd64/context2.S | 238 + .../src/pal/src/arch/amd64/debugbreak.S | 12 + .../src/arch/amd64/dispatchexceptionwrapper.S | 51 + .../src/pal/src/arch/amd64/exceptionhelper.S | 52 + .../src/pal/src/arch/amd64/processor.cpp | 51 + .../src/arch/amd64/signalhandlerhelper.cpp | 76 + .../src/pal/src/arch/arm/asmconstants.h | 61 + .../src/arch/arm/callsignalhandlerwrapper.S | 47 + .../src/pal/src/arch/arm/context2.S | 193 + .../src/pal/src/arch/arm/debugbreak.S | 14 + .../src/pal/src/arch/arm/exceptionhelper.S | 47 + .../src/pal/src/arch/arm/processor.cpp | 22 + .../pal/src/arch/arm/signalhandlerhelper.cpp | 87 + .../src/pal/src/arch/arm64/asmconstants.h | 95 + .../src/arch/arm64/callsignalhandlerwrapper.S | 32 + .../src/pal/src/arch/arm64/context2.S | 213 + .../src/pal/src/arch/arm64/debugbreak.S | 11 + .../src/pal/src/arch/arm64/exceptionhelper.S | 52 + .../src/pal/src/arch/arm64/processor.cpp | 22 + .../src/arch/arm64/signalhandlerhelper.cpp | 74 + .../src/pal/src/arch/i386/asmconstants.h | 30 + .../src/arch/i386/callsignalhandlerwrapper.S | 47 + .../src/pal/src/arch/i386/context2.S | 137 + .../src/pal/src/arch/i386/debugbreak.S | 12 + .../src/pal/src/arch/i386/exceptionhelper.S | 50 + .../src/pal/src/arch/i386/processor.cpp | 22 + .../pal/src/arch/i386/signalhandlerhelper.cpp | 83 + .../src/pal/src/build_tools/mdtool_dummy | 7 + .../src/pal/src/build_tools/mdtool_gcc.in | 43 + .../coreclr_headers/src/pal/src/config.h.in | 172 + .../src/pal/src/configure.cmake | 1442 +++++ .../src/pal/src/cruntime/file.cpp | 725 +++ .../src/pal/src/cruntime/filecrt.cpp | 475 ++ .../src/pal/src/cruntime/malloc.cpp | 116 + .../src/pal/src/cruntime/math.cpp | 1009 ++++ .../src/pal/src/cruntime/mbstring.cpp | 204 + .../src/pal/src/cruntime/misc.cpp | 278 + .../src/pal/src/cruntime/path.cpp | 114 + .../src/pal/src/cruntime/printf.cpp | 1222 ++++ .../src/pal/src/cruntime/printfcpp.cpp | 1773 ++++++ .../src/pal/src/cruntime/silent_printf.cpp | 709 +++ .../src/pal/src/cruntime/string.cpp | 205 + .../src/pal/src/cruntime/stringtls.cpp | 78 + .../src/pal/src/cruntime/thread.cpp | 39 + .../src/pal/src/cruntime/wchar.cpp | 1039 ++++ .../src/pal/src/cruntime/wchartls.cpp | 126 + .../src/pal/src/eventprovider/CMakeLists.txt | 7 + .../dummyprovider/CMakeLists.txt | 43 + .../lttngprovider/CMakeLists.txt | 74 + .../lttngprovider/eventproviderhelpers.cpp | 85 + .../src/pal/src/exception/machexception.cpp | 1491 +++++ .../src/pal/src/exception/machexception.h | 45 + .../src/pal/src/exception/machmessage.cpp | 1383 +++++ .../src/pal/src/exception/machmessage.h | 441 ++ .../src/pal/src/exception/remote-unwind.cpp | 482 ++ .../src/pal/src/exception/seh-unwind.cpp | 521 ++ .../src/pal/src/exception/seh.cpp | 407 ++ .../src/pal/src/exception/signal.cpp | 1002 ++++ .../src/pal/src/file/directory.cpp | 725 +++ .../coreclr_headers/src/pal/src/file/file.cpp | 4182 ++++++++++++++ .../src/pal/src/file/filetime.cpp | 317 + .../coreclr_headers/src/pal/src/file/find.cpp | 1007 ++++ .../coreclr_headers/src/pal/src/file/path.cpp | 978 ++++ .../src/pal/src/handlemgr/handleapi.cpp | 332 ++ .../src/pal/src/handlemgr/handlemgr.cpp | 321 ++ .../src/pal/src/include/pal/cert.hpp | 33 + .../src/pal/src/include/pal/cgroup.h | 37 + .../src/pal/src/include/pal/context.h | 825 +++ .../src/pal/src/include/pal/corunix.hpp | 1272 ++++ .../src/pal/src/include/pal/corunix.inl | 55 + .../src/pal/src/include/pal/critsect.h | 45 + .../src/pal/src/include/pal/cruntime.h | 185 + .../src/pal/src/include/pal/cs.hpp | 54 + .../src/pal/src/include/pal/dbgmsg.h | 529 ++ .../src/pal/src/include/pal/debug.h | 86 + .../src/pal/src/include/pal/environ.h | 78 + .../src/pal/src/include/pal/event.hpp | 60 + .../src/pal/src/include/pal/fakepoll.h | 68 + .../src/pal/src/include/pal/file.h | 225 + .../src/pal/src/include/pal/file.hpp | 272 + .../src/pal/src/include/pal/filetime.h | 88 + .../src/pal/src/include/pal/handleapi.hpp | 47 + .../src/pal/src/include/pal/handlemgr.hpp | 174 + .../src/pal/src/include/pal/init.h | 115 + .../src/pal/src/include/pal/list.h | 141 + .../src/pal/src/include/pal/malloc.hpp | 166 + .../src/pal/src/include/pal/map.h | 52 + .../src/pal/src/include/pal/map.hpp | 207 + .../src/pal/src/include/pal/misc.h | 83 + .../src/pal/src/include/pal/module.h | 203 + .../src/pal/src/include/pal/modulename.h | 36 + .../src/pal/src/include/pal/mutex.hpp | 189 + .../src/pal/src/include/pal/numa.h | 39 + .../src/pal/src/include/pal/palinternal.h | 733 +++ .../src/pal/src/include/pal/perftrace.h | 70 + .../src/pal/src/include/pal/printfcpp.hpp | 78 + .../src/pal/src/include/pal/process.h | 196 + .../src/pal/src/include/pal/procobj.hpp | 124 + .../src/pal/src/include/pal/seh.hpp | 150 + .../src/pal/src/include/pal/semaphore.hpp | 65 + .../src/pal/src/include/pal/sharedmemory.h | 283 + .../src/pal/src/include/pal/sharedmemory.inl | 22 + .../src/pal/src/include/pal/shm.hpp | 40 + .../src/pal/src/include/pal/shmemory.h | 125 + .../src/pal/src/include/pal/signal.hpp | 121 + .../src/pal/src/include/pal/stackstring.hpp | 268 + .../src/pal/src/include/pal/synchcache.hpp | 397 ++ .../src/pal/src/include/pal/synchobjects.hpp | 219 + .../src/pal/src/include/pal/thread.hpp | 791 +++ .../src/pal/src/include/pal/threadinfo.hpp | 101 + .../src/pal/src/include/pal/threadsusp.hpp | 384 ++ .../src/pal/src/include/pal/unicodedata.h | 32 + .../src/pal/src/include/pal/utf8.h | 53 + .../src/pal/src/include/pal/utils.h | 215 + .../src/pal/src/include/pal/virtual.h | 215 + .../coreclr_headers/src/pal/src/init/pal.cpp | 1368 +++++ .../coreclr_headers/src/pal/src/init/sxs.cpp | 98 + .../src/pal/src/libunwind/.gitignore | 79 + .../src/pal/src/libunwind/.travis.yml | 18 + .../src/pal/src/libunwind/AUTHORS | 1 + .../src/pal/src/libunwind/CMakeLists.txt | 22 + .../src/pal/src/libunwind/COPYING | 20 + .../src/pal/src/libunwind/ChangeLog | 55 + .../src/pal/src/libunwind/LICENSE | 18 + .../src/pal/src/libunwind/Makefile.am | 106 + .../src/pal/src/libunwind/NEWS | 247 + .../src/pal/src/libunwind/README | 207 + .../src/pal/src/libunwind/README.md | 1 + .../src/pal/src/libunwind/TODO | 97 + .../src/pal/src/libunwind/acinclude.m4 | 32 + .../src/pal/src/libunwind/autogen.sh | 9 + .../src/pal/src/libunwind/aux_/config.guess | 1321 +++++ .../src/pal/src/libunwind/aux_/config.sub | 1443 +++++ .../src/pal/src/libunwind/aux_/ltmain.sh | 5107 ++++++++++++++++ .../src/pal/src/libunwind/configure.ac | 445 ++ .../src/pal/src/libunwind/doc/Makefile.am | 80 + .../src/pal/src/libunwind/doc/NOTES | 127 + .../pal/src/libunwind/doc/_U_dyn_cancel.man | 66 + .../pal/src/libunwind/doc/_U_dyn_cancel.tex | 46 + .../pal/src/libunwind/doc/_U_dyn_register.man | 68 + .../pal/src/libunwind/doc/_U_dyn_register.tex | 47 + .../src/pal/src/libunwind/doc/common.tex.in | 11 + .../src/libunwind/doc/libunwind-dynamic.man | 538 ++ .../src/libunwind/doc/libunwind-dynamic.tex | 401 ++ .../pal/src/libunwind/doc/libunwind-ia64.man | 314 + .../pal/src/libunwind/doc/libunwind-ia64.tex | 216 + .../src/libunwind/doc/libunwind-ptrace.man | 220 + .../src/libunwind/doc/libunwind-ptrace.tex | 134 + .../src/libunwind/doc/libunwind-setjmp.man | 132 + .../src/libunwind/doc/libunwind-setjmp.tex | 87 + .../src/pal/src/libunwind/doc/libunwind.man | 508 ++ .../src/pal/src/libunwind/doc/libunwind.tex | 359 ++ .../src/pal/src/libunwind/doc/libunwind.trans | 34 + .../src/libunwind/doc/unw_apply_reg_state.man | 90 + .../src/libunwind/doc/unw_apply_reg_state.tex | 63 + .../pal/src/libunwind/doc/unw_backtrace.man | 86 + .../pal/src/libunwind/doc/unw_backtrace.tex | 54 + .../libunwind/doc/unw_create_addr_space.man | 457 ++ .../libunwind/doc/unw_create_addr_space.tex | 265 + .../libunwind/doc/unw_destroy_addr_space.man | 57 + .../libunwind/doc/unw_destroy_addr_space.tex | 40 + .../pal/src/libunwind/doc/unw_flush_cache.man | 93 + .../pal/src/libunwind/doc/unw_flush_cache.tex | 58 + .../src/libunwind/doc/unw_get_accessors.man | 79 + .../src/libunwind/doc/unw_get_accessors.tex | 55 + .../pal/src/libunwind/doc/unw_get_fpreg.man | 111 + .../pal/src/libunwind/doc/unw_get_fpreg.tex | 77 + .../src/libunwind/doc/unw_get_proc_info.man | 203 + .../src/libunwind/doc/unw_get_proc_info.tex | 123 + .../libunwind/doc/unw_get_proc_info_by_ip.man | 134 + .../libunwind/doc/unw_get_proc_info_by_ip.tex | 91 + .../src/libunwind/doc/unw_get_proc_name.man | 123 + .../src/libunwind/doc/unw_get_proc_name.tex | 82 + .../src/pal/src/libunwind/doc/unw_get_reg.man | 112 + .../src/pal/src/libunwind/doc/unw_get_reg.tex | 77 + .../pal/src/libunwind/doc/unw_getcontext.man | 93 + .../pal/src/libunwind/doc/unw_getcontext.tex | 63 + .../pal/src/libunwind/doc/unw_init_local.man | 124 + .../pal/src/libunwind/doc/unw_init_local.tex | 80 + .../pal/src/libunwind/doc/unw_init_local2.man | 1 + .../pal/src/libunwind/doc/unw_init_remote.man | 123 + .../pal/src/libunwind/doc/unw_init_remote.tex | 79 + .../pal/src/libunwind/doc/unw_is_fpreg.man | 73 + .../pal/src/libunwind/doc/unw_is_fpreg.tex | 52 + .../src/libunwind/doc/unw_is_signal_frame.man | 88 + .../src/libunwind/doc/unw_is_signal_frame.tex | 67 + .../libunwind/doc/unw_reg_states_iterate.man | 137 + .../libunwind/doc/unw_reg_states_iterate.tex | 83 + .../src/pal/src/libunwind/doc/unw_regname.man | 68 + .../src/pal/src/libunwind/doc/unw_regname.tex | 47 + .../src/pal/src/libunwind/doc/unw_resume.man | 146 + .../src/pal/src/libunwind/doc/unw_resume.tex | 99 + .../src/libunwind/doc/unw_set_cache_size.man | 88 + .../src/libunwind/doc/unw_set_cache_size.tex | 59 + .../libunwind/doc/unw_set_caching_policy.man | 119 + .../libunwind/doc/unw_set_caching_policy.tex | 81 + .../pal/src/libunwind/doc/unw_set_fpreg.man | 117 + .../pal/src/libunwind/doc/unw_set_fpreg.tex | 79 + .../src/pal/src/libunwind/doc/unw_set_reg.man | 117 + .../src/pal/src/libunwind/doc/unw_set_reg.tex | 79 + .../src/pal/src/libunwind/doc/unw_step.man | 106 + .../src/pal/src/libunwind/doc/unw_step.tex | 68 + .../pal/src/libunwind/doc/unw_strerror.man | 63 + .../pal/src/libunwind/doc/unw_strerror.tex | 42 + .../src/pal/src/libunwind/include/compiler.h | 72 + .../src/pal/src/libunwind/include/dwarf-eh.h | 128 + .../src/pal/src/libunwind/include/dwarf.h | 450 ++ .../src/libunwind/include/libunwind-aarch64.h | 210 + .../pal/src/libunwind/include/libunwind-arm.h | 303 + .../libunwind/include/libunwind-common.h.in | 281 + .../libunwind/include/libunwind-coredump.h | 73 + .../src/libunwind/include/libunwind-dynamic.h | 214 + .../src/libunwind/include/libunwind-hppa.h | 125 + .../src/libunwind/include/libunwind-ia64.h | 194 + .../src/libunwind/include/libunwind-mips.h | 160 + .../src/libunwind/include/libunwind-ppc32.h | 207 + .../src/libunwind/include/libunwind-ppc64.h | 271 + .../src/libunwind/include/libunwind-ptrace.h | 63 + .../pal/src/libunwind/include/libunwind-sh.h | 114 + .../src/libunwind/include/libunwind-tilegx.h | 161 + .../pal/src/libunwind/include/libunwind-x86.h | 187 + .../src/libunwind/include/libunwind-x86_64.h | 141 + .../pal/src/libunwind/include/libunwind.h.in | 36 + .../src/pal/src/libunwind/include/mempool.h | 89 + .../src/pal/src/libunwind/include/remote.h | 129 + .../include/tdep-aarch64/dwarf-config.h | 52 + .../libunwind/include/tdep-aarch64/jmpbuf.h | 33 + .../libunwind/include/tdep-arm/dwarf-config.h | 51 + .../libunwind/include/tdep-arm/ex_tables.h | 55 + .../src/libunwind/include/tdep-arm/jmpbuf.h | 32 + .../include/tdep-hppa/dwarf-config.h | 54 + .../src/libunwind/include/tdep-hppa/jmpbuf.h | 33 + .../src/libunwind/include/tdep-ia64/jmpbuf.h | 32 + .../pal/src/libunwind/include/tdep-ia64/rse.h | 67 + .../src/libunwind/include/tdep-ia64/script.h | 85 + .../include/tdep-mips/dwarf-config.h | 54 + .../src/libunwind/include/tdep-mips/jmpbuf.h | 32 + .../include/tdep-ppc32/dwarf-config.h | 56 + .../src/libunwind/include/tdep-ppc32/jmpbuf.h | 37 + .../include/tdep-ppc64/dwarf-config.h | 56 + .../src/libunwind/include/tdep-ppc64/jmpbuf.h | 37 + .../libunwind/include/tdep-sh/dwarf-config.h | 49 + .../src/libunwind/include/tdep-sh/jmpbuf.h | 48 + .../include/tdep-tilegx/dwarf-config.h | 50 + .../libunwind/include/tdep-tilegx/jmpbuf.h | 33 + .../libunwind/include/tdep-x86/dwarf-config.h | 52 + .../src/libunwind/include/tdep-x86/jmpbuf.h | 42 + .../include/tdep-x86_64/dwarf-config.h | 57 + .../libunwind/include/tdep-x86_64/jmpbuf.h | 43 + .../src/libunwind/include/tdep/dwarf-config.h | 28 + .../pal/src/libunwind/include/tdep/jmpbuf.h | 30 + .../libunwind/include/tdep/libunwind_i.h.in | 37 + .../src/pal/src/libunwind/include/unwind.h | 154 + .../pal/src/libunwind/scripts/kernel-diff.sh | 10 + .../src/libunwind/scripts/kernel-files.txt | 19 + .../pal/src/libunwind/scripts/make-L-files | 30 + .../src/pal/src/libunwind/src/CMakeLists.txt | 354 ++ .../src/pal/src/libunwind/src/Makefile.am | 750 +++ .../libunwind/src/aarch64/Gapply_reg_state.c | 37 + .../src/aarch64/Gcreate_addr_space.c | 60 + .../libunwind/src/aarch64/Gget_proc_info.c | 39 + .../src/libunwind/src/aarch64/Gget_save_loc.c | 100 + .../pal/src/libunwind/src/aarch64/Gglobal.c | 57 + .../src/pal/src/libunwind/src/aarch64/Ginit.c | 190 + .../src/libunwind/src/aarch64/Ginit_local.c | 78 + .../src/libunwind/src/aarch64/Ginit_remote.c | 45 + .../libunwind/src/aarch64/Gis_signal_frame.c | 64 + .../src/aarch64/Greg_states_iterate.c | 37 + .../src/pal/src/libunwind/src/aarch64/Gregs.c | 118 + .../pal/src/libunwind/src/aarch64/Gresume.c | 198 + .../src/libunwind/src/aarch64/Gstash_frame.c | 89 + .../src/pal/src/libunwind/src/aarch64/Gstep.c | 189 + .../pal/src/libunwind/src/aarch64/Gtrace.c | 548 ++ .../libunwind/src/aarch64/Lapply_reg_state.c | 5 + .../src/aarch64/Lcreate_addr_space.c | 5 + .../libunwind/src/aarch64/Lget_proc_info.c | 5 + .../src/libunwind/src/aarch64/Lget_save_loc.c | 5 + .../pal/src/libunwind/src/aarch64/Lglobal.c | 5 + .../src/pal/src/libunwind/src/aarch64/Linit.c | 5 + .../src/libunwind/src/aarch64/Linit_local.c | 5 + .../src/libunwind/src/aarch64/Linit_remote.c | 5 + .../libunwind/src/aarch64/Lis_signal_frame.c | 5 + .../src/aarch64/Lreg_states_iterate.c | 5 + .../src/pal/src/libunwind/src/aarch64/Lregs.c | 5 + .../pal/src/libunwind/src/aarch64/Lresume.c | 5 + .../src/libunwind/src/aarch64/Lstash_frame.c | 5 + .../src/pal/src/libunwind/src/aarch64/Lstep.c | 5 + .../pal/src/libunwind/src/aarch64/Ltrace.c | 5 + .../src/libunwind/src/aarch64/gen-offsets.c | 68 + .../src/libunwind/src/aarch64/getcontext.S | 52 + .../src/pal/src/libunwind/src/aarch64/init.h | 126 + .../pal/src/libunwind/src/aarch64/is_fpreg.c | 32 + .../pal/src/libunwind/src/aarch64/offsets.h | 49 + .../pal/src/libunwind/src/aarch64/regname.c | 106 + .../src/libunwind/src/aarch64/siglongjmp.S | 12 + .../src/libunwind/src/arm/Gapply_reg_state.c | 37 + .../libunwind/src/arm/Gcreate_addr_space.c | 60 + .../pal/src/libunwind/src/arm/Gex_tables.c | 548 ++ .../src/libunwind/src/arm/Gget_proc_info.c | 41 + .../pal/src/libunwind/src/arm/Gget_save_loc.c | 81 + .../src/pal/src/libunwind/src/arm/Gglobal.c | 65 + .../src/pal/src/libunwind/src/arm/Ginit.c | 235 + .../pal/src/libunwind/src/arm/Ginit_local.c | 78 + .../pal/src/libunwind/src/arm/Ginit_remote.c | 45 + .../pal/src/libunwind/src/arm/Gos-freebsd.c | 129 + .../src/pal/src/libunwind/src/arm/Gos-linux.c | 182 + .../src/pal/src/libunwind/src/arm/Gos-other.c | 48 + .../libunwind/src/arm/Greg_states_iterate.c | 37 + .../src/pal/src/libunwind/src/arm/Gregs.c | 83 + .../src/pal/src/libunwind/src/arm/Gresume.c | 154 + .../pal/src/libunwind/src/arm/Gstash_frame.c | 90 + .../src/pal/src/libunwind/src/arm/Gstep.c | 192 + .../src/pal/src/libunwind/src/arm/Gtrace.c | 557 ++ .../src/libunwind/src/arm/Lapply_reg_state.c | 5 + .../libunwind/src/arm/Lcreate_addr_space.c | 5 + .../pal/src/libunwind/src/arm/Lex_tables.c | 5 + .../src/libunwind/src/arm/Lget_proc_info.c | 5 + .../pal/src/libunwind/src/arm/Lget_save_loc.c | 5 + .../src/pal/src/libunwind/src/arm/Lglobal.c | 5 + .../src/pal/src/libunwind/src/arm/Linit.c | 5 + .../pal/src/libunwind/src/arm/Linit_local.c | 5 + .../pal/src/libunwind/src/arm/Linit_remote.c | 5 + .../src/libunwind/src/arm/Lis_signal_frame.c | 5 + .../pal/src/libunwind/src/arm/Los-freebsd.c | 5 + .../src/pal/src/libunwind/src/arm/Los-linux.c | 5 + .../src/pal/src/libunwind/src/arm/Los-other.c | 5 + .../libunwind/src/arm/Lreg_states_iterate.c | 5 + .../src/pal/src/libunwind/src/arm/Lregs.c | 5 + .../src/pal/src/libunwind/src/arm/Lresume.c | 5 + .../pal/src/libunwind/src/arm/Lstash_frame.c | 5 + .../src/pal/src/libunwind/src/arm/Lstep.c | 5 + .../src/pal/src/libunwind/src/arm/Ltrace.c | 6 + .../pal/src/libunwind/src/arm/gen-offsets.c | 54 + .../pal/src/libunwind/src/arm/getcontext.S | 63 + .../src/pal/src/libunwind/src/arm/init.h | 77 + .../src/pal/src/libunwind/src/arm/is_fpreg.c | 39 + .../src/pal/src/libunwind/src/arm/offsets.h | 42 + .../src/pal/src/libunwind/src/arm/regname.c | 90 + .../pal/src/libunwind/src/arm/siglongjmp.S | 12 + .../src/pal/src/libunwind/src/config.h.in | 18 + .../src/pal/src/libunwind/src/configure.cmake | 33 + .../src/pal/src/libunwind/src/coredump/README | 8 + .../libunwind/src/coredump/_UCD_access_mem.c | 98 + .../src/coredump/_UCD_access_reg_freebsd.c | 137 + .../src/coredump/_UCD_access_reg_linux.c | 146 + .../libunwind/src/coredump/_UCD_accessors.c | 36 + .../src/libunwind/src/coredump/_UCD_create.c | 417 ++ .../src/libunwind/src/coredump/_UCD_destroy.c | 52 + .../src/coredump/_UCD_elf_map_image.c | 98 + .../src/coredump/_UCD_find_proc_info.c | 163 + .../src/coredump/_UCD_get_proc_name.c | 70 + .../libunwind/src/coredump/_UCD_internal.h | 105 + .../pal/src/libunwind/src/coredump/_UCD_lib.h | 57 + .../src/coredump/_UPT_access_fpreg.c | 34 + .../pal/src/libunwind/src/coredump/_UPT_elf.c | 5 + .../coredump/_UPT_get_dyn_info_list_addr.c | 108 + .../src/coredump/_UPT_put_unwind_info.c | 36 + .../src/libunwind/src/coredump/_UPT_resume.c | 35 + .../src/coredump/libunwind-coredump.pc.in | 11 + .../src/pal/src/libunwind/src/dwarf/Gexpr.c | 696 +++ .../src/pal/src/libunwind/src/dwarf/Gfde.c | 359 ++ .../libunwind/src/dwarf/Gfind_proc_info-lsb.c | 935 +++ .../libunwind/src/dwarf/Gfind_unwind_table.c | 230 + .../src/pal/src/libunwind/src/dwarf/Gparser.c | 1059 ++++ .../src/pal/src/libunwind/src/dwarf/Gpe.c | 39 + .../src/pal/src/libunwind/src/dwarf/Lexpr.c | 5 + .../src/pal/src/libunwind/src/dwarf/Lfde.c | 5 + .../libunwind/src/dwarf/Lfind_proc_info-lsb.c | 5 + .../libunwind/src/dwarf/Lfind_unwind_table.c | 5 + .../src/pal/src/libunwind/src/dwarf/Lparser.c | 5 + .../src/pal/src/libunwind/src/dwarf/Lpe.c | 5 + .../src/pal/src/libunwind/src/dwarf/global.c | 37 + .../src/pal/src/libunwind/src/elf32.c | 4 + .../src/pal/src/libunwind/src/elf32.h | 9 + .../src/pal/src/libunwind/src/elf64.c | 4 + .../src/pal/src/libunwind/src/elf64.h | 9 + .../src/pal/src/libunwind/src/elfxx.c | 481 ++ .../src/pal/src/libunwind/src/elfxx.h | 101 + .../src/libunwind/src/hppa/Gapply_reg_state.c | 37 + .../libunwind/src/hppa/Gcreate_addr_space.c | 54 + .../src/libunwind/src/hppa/Gget_proc_info.c | 46 + .../src/libunwind/src/hppa/Gget_save_loc.c | 59 + .../src/pal/src/libunwind/src/hppa/Gglobal.c | 55 + .../src/pal/src/libunwind/src/hppa/Ginit.c | 194 + .../pal/src/libunwind/src/hppa/Ginit_local.c | 77 + .../pal/src/libunwind/src/hppa/Ginit_remote.c | 46 + .../src/libunwind/src/hppa/Gis_signal_frame.c | 74 + .../libunwind/src/hppa/Greg_states_iterate.c | 37 + .../src/pal/src/libunwind/src/hppa/Gregs.c | 87 + .../src/pal/src/libunwind/src/hppa/Gresume.c | 145 + .../src/pal/src/libunwind/src/hppa/Gstep.c | 95 + .../src/libunwind/src/hppa/Lapply_reg_state.c | 5 + .../libunwind/src/hppa/Lcreate_addr_space.c | 5 + .../src/libunwind/src/hppa/Lget_proc_info.c | 5 + .../src/libunwind/src/hppa/Lget_save_loc.c | 5 + .../src/pal/src/libunwind/src/hppa/Lglobal.c | 5 + .../src/pal/src/libunwind/src/hppa/Linit.c | 5 + .../pal/src/libunwind/src/hppa/Linit_local.c | 5 + .../pal/src/libunwind/src/hppa/Linit_remote.c | 5 + .../src/libunwind/src/hppa/Lis_signal_frame.c | 5 + .../libunwind/src/hppa/Lreg_states_iterate.c | 5 + .../src/pal/src/libunwind/src/hppa/Lregs.c | 5 + .../src/pal/src/libunwind/src/hppa/Lresume.c | 5 + .../src/pal/src/libunwind/src/hppa/Lstep.c | 5 + .../src/libunwind/src/hppa/get_accessors.c | 38 + .../pal/src/libunwind/src/hppa/getcontext.S | 74 + .../src/pal/src/libunwind/src/hppa/init.h | 47 + .../src/pal/src/libunwind/src/hppa/offsets.h | 17 + .../src/pal/src/libunwind/src/hppa/regname.c | 50 + .../pal/src/libunwind/src/hppa/setcontext.S | 77 + .../pal/src/libunwind/src/hppa/siglongjmp.S | 16 + .../src/pal/src/libunwind/src/hppa/tables.c | 43 + .../src/libunwind/src/ia64/Gapply_reg_state.c | 39 + .../libunwind/src/ia64/Gcreate_addr_space.c | 63 + .../libunwind/src/ia64/Gfind_unwind_table.c | 143 + .../src/libunwind/src/ia64/Gget_proc_info.c | 38 + .../src/libunwind/src/ia64/Gget_save_loc.c | 168 + .../src/pal/src/libunwind/src/ia64/Gglobal.c | 122 + .../src/pal/src/libunwind/src/ia64/Ginit.c | 505 ++ .../pal/src/libunwind/src/ia64/Ginit_local.c | 110 + .../pal/src/libunwind/src/ia64/Ginit_remote.c | 61 + .../src/libunwind/src/ia64/Ginstall_cursor.S | 348 ++ .../src/libunwind/src/ia64/Gis_signal_frame.c | 54 + .../src/pal/src/libunwind/src/ia64/Gparser.c | 1131 ++++ .../src/pal/src/libunwind/src/ia64/Grbs.c | 319 + .../libunwind/src/ia64/Greg_states_iterate.c | 39 + .../src/pal/src/libunwind/src/ia64/Gregs.c | 612 ++ .../src/pal/src/libunwind/src/ia64/Gresume.c | 274 + .../src/pal/src/libunwind/src/ia64/Gscript.c | 765 +++ .../src/pal/src/libunwind/src/ia64/Gstep.c | 359 ++ .../src/pal/src/libunwind/src/ia64/Gtables.c | 731 +++ .../src/libunwind/src/ia64/Lapply_reg_state.c | 5 + .../libunwind/src/ia64/Lcreate_addr_space.c | 5 + .../libunwind/src/ia64/Lfind_unwind_table.c | 5 + .../src/libunwind/src/ia64/Lget_proc_info.c | 5 + .../src/libunwind/src/ia64/Lget_save_loc.c | 5 + .../src/pal/src/libunwind/src/ia64/Lglobal.c | 5 + .../src/pal/src/libunwind/src/ia64/Linit.c | 5 + .../pal/src/libunwind/src/ia64/Linit_local.c | 5 + .../pal/src/libunwind/src/ia64/Linit_remote.c | 5 + .../src/libunwind/src/ia64/Linstall_cursor.S | 6 + .../src/libunwind/src/ia64/Lis_signal_frame.c | 5 + .../src/pal/src/libunwind/src/ia64/Lparser.c | 5 + .../src/pal/src/libunwind/src/ia64/Lrbs.c | 5 + .../libunwind/src/ia64/Lreg_states_iterate.c | 5 + .../src/pal/src/libunwind/src/ia64/Lregs.c | 5 + .../src/pal/src/libunwind/src/ia64/Lresume.c | 5 + .../src/pal/src/libunwind/src/ia64/Lscript.c | 5 + .../src/pal/src/libunwind/src/ia64/Lstep.c | 5 + .../src/pal/src/libunwind/src/ia64/Ltables.c | 5 + .../src/pal/src/libunwind/src/ia64/NOTES | 65 + .../src/libunwind/src/ia64/dyn_info_list.S | 26 + .../pal/src/libunwind/src/ia64/getcontext.S | 177 + .../src/pal/src/libunwind/src/ia64/init.h | 132 + .../src/pal/src/libunwind/src/ia64/longjmp.S | 42 + .../pal/src/libunwind/src/ia64/mk_cursor_i | 7 + .../src/pal/src/libunwind/src/ia64/offsets.h | 137 + .../src/pal/src/libunwind/src/ia64/regname.c | 189 + .../src/pal/src/libunwind/src/ia64/regs.h | 73 + .../src/pal/src/libunwind/src/ia64/setjmp.S | 51 + .../pal/src/libunwind/src/ia64/siglongjmp.S | 69 + .../pal/src/libunwind/src/ia64/sigsetjmp.S | 69 + .../src/libunwind/src/ia64/unwind_decoder.h | 477 ++ .../src/libunwind/src/libunwind-generic.pc.in | 11 + .../libunwind/src/mi/Gdestroy_addr_space.c | 37 + .../pal/src/libunwind/src/mi/Gdyn-extract.c | 64 + .../pal/src/libunwind/src/mi/Gdyn-remote.c | 326 ++ .../src/mi/Gfind_dynamic_proc_info.c | 91 + .../pal/src/libunwind/src/mi/Gget_accessors.c | 37 + .../src/pal/src/libunwind/src/mi/Gget_fpreg.c | 34 + .../libunwind/src/mi/Gget_proc_info_by_ip.c | 39 + .../pal/src/libunwind/src/mi/Gget_proc_name.c | 118 + .../src/pal/src/libunwind/src/mi/Gget_reg.c | 41 + .../src/mi/Gput_dynamic_unwind_info.c | 55 + .../src/libunwind/src/mi/Gset_cache_size.c | 72 + .../libunwind/src/mi/Gset_caching_policy.c | 46 + .../src/pal/src/libunwind/src/mi/Gset_fpreg.c | 34 + .../src/pal/src/libunwind/src/mi/Gset_reg.c | 34 + .../libunwind/src/mi/Ldestroy_addr_space.c | 5 + .../pal/src/libunwind/src/mi/Ldyn-extract.c | 5 + .../pal/src/libunwind/src/mi/Ldyn-remote.c | 5 + .../src/mi/Lfind_dynamic_proc_info.c | 5 + .../pal/src/libunwind/src/mi/Lget_accessors.c | 5 + .../src/pal/src/libunwind/src/mi/Lget_fpreg.c | 5 + .../libunwind/src/mi/Lget_proc_info_by_ip.c | 5 + .../pal/src/libunwind/src/mi/Lget_proc_name.c | 5 + .../src/pal/src/libunwind/src/mi/Lget_reg.c | 5 + .../src/mi/Lput_dynamic_unwind_info.c | 5 + .../src/libunwind/src/mi/Lset_cache_size.c | 5 + .../libunwind/src/mi/Lset_caching_policy.c | 5 + .../src/pal/src/libunwind/src/mi/Lset_fpreg.c | 5 + .../src/pal/src/libunwind/src/mi/Lset_reg.c | 5 + .../src/pal/src/libunwind/src/mi/_ReadSLEB.c | 25 + .../src/pal/src/libunwind/src/mi/_ReadULEB.c | 20 + .../src/pal/src/libunwind/src/mi/backtrace.c | 81 + .../src/pal/src/libunwind/src/mi/dyn-cancel.c | 46 + .../pal/src/libunwind/src/mi/dyn-info-list.c | 34 + .../pal/src/libunwind/src/mi/dyn-register.c | 44 + .../pal/src/libunwind/src/mi/flush_cache.c | 59 + .../src/pal/src/libunwind/src/mi/init.c | 60 + .../src/pal/src/libunwind/src/mi/mempool.c | 184 + .../src/pal/src/libunwind/src/mi/strerror.c | 51 + .../src/libunwind/src/mips/Gapply_reg_state.c | 37 + .../libunwind/src/mips/Gcreate_addr_space.c | 66 + .../src/libunwind/src/mips/Gget_proc_info.c | 41 + .../src/libunwind/src/mips/Gget_save_loc.c | 100 + .../src/pal/src/libunwind/src/mips/Gglobal.c | 55 + .../src/pal/src/libunwind/src/mips/Ginit.c | 210 + .../pal/src/libunwind/src/mips/Ginit_local.c | 76 + .../pal/src/libunwind/src/mips/Ginit_remote.c | 45 + .../src/libunwind/src/mips/Gis_signal_frame.c | 78 + .../libunwind/src/mips/Greg_states_iterate.c | 37 + .../src/pal/src/libunwind/src/mips/Gregs.c | 105 + .../src/pal/src/libunwind/src/mips/Gresume.c | 45 + .../src/pal/src/libunwind/src/mips/Gstep.c | 132 + .../src/libunwind/src/mips/Lapply_reg_state.c | 5 + .../libunwind/src/mips/Lcreate_addr_space.c | 5 + .../src/libunwind/src/mips/Lget_proc_info.c | 5 + .../src/libunwind/src/mips/Lget_save_loc.c | 5 + .../src/pal/src/libunwind/src/mips/Lglobal.c | 5 + .../src/pal/src/libunwind/src/mips/Linit.c | 5 + .../pal/src/libunwind/src/mips/Linit_local.c | 5 + .../pal/src/libunwind/src/mips/Linit_remote.c | 5 + .../src/libunwind/src/mips/Lis_signal_frame.c | 5 + .../libunwind/src/mips/Lreg_states_iterate.c | 5 + .../src/pal/src/libunwind/src/mips/Lregs.c | 5 + .../src/pal/src/libunwind/src/mips/Lresume.c | 5 + .../src/pal/src/libunwind/src/mips/Lstep.c | 5 + .../src/pal/src/libunwind/src/mips/elfxx.c | 27 + .../pal/src/libunwind/src/mips/gen-offsets.c | 30 + .../pal/src/libunwind/src/mips/getcontext.S | 93 + .../src/pal/src/libunwind/src/mips/init.h | 59 + .../src/pal/src/libunwind/src/mips/is_fpreg.c | 35 + .../src/pal/src/libunwind/src/mips/offsets.h | 86 + .../src/pal/src/libunwind/src/mips/regname.c | 48 + .../pal/src/libunwind/src/mips/siglongjmp.S | 8 + .../libunwind/src/oop/_OOP_find_proc_info.c | 104 + .../pal/src/libunwind/src/oop/_OOP_internal.h | 25 + .../src/pal/src/libunwind/src/os-freebsd.c | 166 + .../src/pal/src/libunwind/src/os-hpux.c | 78 + .../src/pal/src/libunwind/src/os-linux.c | 73 + .../src/pal/src/libunwind/src/os-linux.h | 297 + .../src/pal/src/libunwind/src/os-qnx.c | 117 + .../src/libunwind/src/ppc/Gapply_reg_state.c | 37 + .../src/libunwind/src/ppc/Gget_proc_info.c | 41 + .../pal/src/libunwind/src/ppc/Gget_save_loc.c | 34 + .../pal/src/libunwind/src/ppc/Ginit_local.c | 88 + .../pal/src/libunwind/src/ppc/Ginit_remote.c | 60 + .../src/libunwind/src/ppc/Gis_signal_frame.c | 78 + .../libunwind/src/ppc/Greg_states_iterate.c | 37 + .../src/libunwind/src/ppc/Lapply_reg_state.c | 5 + .../src/libunwind/src/ppc/Lget_proc_info.c | 5 + .../pal/src/libunwind/src/ppc/Lget_save_loc.c | 5 + .../pal/src/libunwind/src/ppc/Linit_local.c | 5 + .../pal/src/libunwind/src/ppc/Linit_remote.c | 5 + .../src/libunwind/src/ppc/Lis_signal_frame.c | 5 + .../libunwind/src/ppc/Lreg_states_iterate.c | 5 + .../src/pal/src/libunwind/src/ppc/longjmp.S | 36 + .../pal/src/libunwind/src/ppc/siglongjmp.S | 31 + .../libunwind/src/ppc32/Gapply_reg_state.c | 37 + .../libunwind/src/ppc32/Gcreate_addr_space.c | 56 + .../src/pal/src/libunwind/src/ppc32/Gglobal.c | 135 + .../src/pal/src/libunwind/src/ppc32/Ginit.c | 216 + .../libunwind/src/ppc32/Greg_states_iterate.c | 37 + .../src/pal/src/libunwind/src/ppc32/Gregs.c | 90 + .../src/pal/src/libunwind/src/ppc32/Gresume.c | 77 + .../src/pal/src/libunwind/src/ppc32/Gstep.c | 309 + .../libunwind/src/ppc32/Lapply_reg_state.c | 5 + .../libunwind/src/ppc32/Lcreate_addr_space.c | 5 + .../src/pal/src/libunwind/src/ppc32/Lglobal.c | 5 + .../src/pal/src/libunwind/src/ppc32/Linit.c | 5 + .../libunwind/src/ppc32/Lreg_states_iterate.c | 5 + .../src/pal/src/libunwind/src/ppc32/Lregs.c | 5 + .../src/pal/src/libunwind/src/ppc32/Lresume.c | 5 + .../src/pal/src/libunwind/src/ppc32/Lstep.c | 5 + .../pal/src/libunwind/src/ppc32/Make-arch.in | 11 + .../src/libunwind/src/ppc32/get_func_addr.c | 36 + .../src/pal/src/libunwind/src/ppc32/init.h | 72 + .../pal/src/libunwind/src/ppc32/is_fpreg.c | 34 + .../src/pal/src/libunwind/src/ppc32/regname.c | 112 + .../pal/src/libunwind/src/ppc32/setcontext.S | 9 + .../libunwind/src/ppc64/Gapply_reg_state.c | 37 + .../libunwind/src/ppc64/Gcreate_addr_space.c | 71 + .../src/pal/src/libunwind/src/ppc64/Gglobal.c | 182 + .../src/pal/src/libunwind/src/ppc64/Ginit.c | 229 + .../libunwind/src/ppc64/Greg_states_iterate.c | 37 + .../src/pal/src/libunwind/src/ppc64/Gregs.c | 141 + .../src/pal/src/libunwind/src/ppc64/Gresume.c | 111 + .../src/pal/src/libunwind/src/ppc64/Gstep.c | 466 ++ .../libunwind/src/ppc64/Lapply_reg_state.c | 5 + .../libunwind/src/ppc64/Lcreate_addr_space.c | 5 + .../src/pal/src/libunwind/src/ppc64/Lglobal.c | 5 + .../src/pal/src/libunwind/src/ppc64/Linit.c | 5 + .../libunwind/src/ppc64/Lreg_states_iterate.c | 5 + .../src/pal/src/libunwind/src/ppc64/Lregs.c | 5 + .../src/pal/src/libunwind/src/ppc64/Lresume.c | 5 + .../src/pal/src/libunwind/src/ppc64/Lstep.c | 5 + .../src/libunwind/src/ppc64/get_func_addr.c | 51 + .../src/pal/src/libunwind/src/ppc64/init.h | 82 + .../pal/src/libunwind/src/ppc64/is_fpreg.c | 34 + .../src/pal/src/libunwind/src/ppc64/regname.c | 164 + .../pal/src/libunwind/src/ppc64/setcontext.S | 9 + .../libunwind/src/ptrace/_UPT_access_fpreg.c | 121 + .../libunwind/src/ptrace/_UPT_access_mem.c | 123 + .../libunwind/src/ptrace/_UPT_access_reg.c | 352 ++ .../src/libunwind/src/ptrace/_UPT_accessors.c | 38 + .../src/libunwind/src/ptrace/_UPT_create.c | 46 + .../src/libunwind/src/ptrace/_UPT_destroy.c | 34 + .../pal/src/libunwind/src/ptrace/_UPT_elf.c | 5 + .../src/ptrace/_UPT_find_proc_info.c | 145 + .../src/ptrace/_UPT_get_dyn_info_list_addr.c | 105 + .../libunwind/src/ptrace/_UPT_get_proc_name.c | 42 + .../src/libunwind/src/ptrace/_UPT_internal.h | 59 + .../src/ptrace/_UPT_put_unwind_info.c | 35 + .../libunwind/src/ptrace/_UPT_reg_offset.c | 638 ++ .../src/libunwind/src/ptrace/_UPT_resume.c | 40 + .../src/ptrace/libunwind-ptrace.pc.in | 11 + .../src/setjmp/libunwind-setjmp.pc.in | 11 + .../pal/src/libunwind/src/setjmp/longjmp.c | 115 + .../src/pal/src/libunwind/src/setjmp/setjmp.c | 49 + .../pal/src/libunwind/src/setjmp/siglongjmp.c | 127 + .../pal/src/libunwind/src/setjmp/sigsetjmp.c | 50 + .../src/libunwind/src/sh/Gapply_reg_state.c | 37 + .../src/libunwind/src/sh/Gcreate_addr_space.c | 59 + .../pal/src/libunwind/src/sh/Gget_proc_info.c | 39 + .../pal/src/libunwind/src/sh/Gget_save_loc.c | 83 + .../src/pal/src/libunwind/src/sh/Gglobal.c | 56 + .../src/pal/src/libunwind/src/sh/Ginit.c | 186 + .../pal/src/libunwind/src/sh/Ginit_local.c | 78 + .../pal/src/libunwind/src/sh/Ginit_remote.c | 45 + .../src/libunwind/src/sh/Gis_signal_frame.c | 119 + .../libunwind/src/sh/Greg_states_iterate.c | 37 + .../src/pal/src/libunwind/src/sh/Gregs.c | 81 + .../src/pal/src/libunwind/src/sh/Gresume.c | 165 + .../src/pal/src/libunwind/src/sh/Gstep.c | 117 + .../src/libunwind/src/sh/Lapply_reg_state.c | 5 + .../src/libunwind/src/sh/Lcreate_addr_space.c | 5 + .../pal/src/libunwind/src/sh/Lget_proc_info.c | 5 + .../pal/src/libunwind/src/sh/Lget_save_loc.c | 5 + .../src/pal/src/libunwind/src/sh/Lglobal.c | 5 + .../src/pal/src/libunwind/src/sh/Linit.c | 5 + .../pal/src/libunwind/src/sh/Linit_local.c | 5 + .../pal/src/libunwind/src/sh/Linit_remote.c | 5 + .../src/libunwind/src/sh/Lis_signal_frame.c | 5 + .../libunwind/src/sh/Lreg_states_iterate.c | 5 + .../src/pal/src/libunwind/src/sh/Lregs.c | 5 + .../src/pal/src/libunwind/src/sh/Lresume.c | 5 + .../src/pal/src/libunwind/src/sh/Lstep.c | 5 + .../pal/src/libunwind/src/sh/gen-offsets.c | 51 + .../src/pal/src/libunwind/src/sh/init.h | 73 + .../src/pal/src/libunwind/src/sh/is_fpreg.c | 32 + .../src/pal/src/libunwind/src/sh/offsets.h | 32 + .../src/pal/src/libunwind/src/sh/regname.c | 56 + .../src/pal/src/libunwind/src/sh/siglongjmp.S | 8 + .../libunwind/src/tilegx/Gapply_reg_state.c | 37 + .../libunwind/src/tilegx/Gcreate_addr_space.c | 65 + .../src/libunwind/src/tilegx/Gget_proc_info.c | 48 + .../src/libunwind/src/tilegx/Gget_save_loc.c | 62 + .../pal/src/libunwind/src/tilegx/Gglobal.c | 64 + .../src/pal/src/libunwind/src/tilegx/Ginit.c | 167 + .../src/libunwind/src/tilegx/Ginit_local.c | 80 + .../src/libunwind/src/tilegx/Ginit_remote.c | 47 + .../libunwind/src/tilegx/Gis_signal_frame.c | 115 + .../src/tilegx/Greg_states_iterate.c | 37 + .../src/pal/src/libunwind/src/tilegx/Gregs.c | 76 + .../pal/src/libunwind/src/tilegx/Gresume.c | 94 + .../src/pal/src/libunwind/src/tilegx/Gstep.c | 53 + .../libunwind/src/tilegx/Lapply_reg_state.c | 5 + .../libunwind/src/tilegx/Lcreate_addr_space.c | 5 + .../src/libunwind/src/tilegx/Lget_proc_info.c | 5 + .../src/libunwind/src/tilegx/Lget_save_loc.c | 5 + .../pal/src/libunwind/src/tilegx/Lglobal.c | 5 + .../src/pal/src/libunwind/src/tilegx/Linit.c | 5 + .../src/libunwind/src/tilegx/Linit_local.c | 5 + .../src/libunwind/src/tilegx/Linit_remote.c | 5 + .../libunwind/src/tilegx/Lis_signal_frame.c | 5 + .../src/tilegx/Lreg_states_iterate.c | 5 + .../src/pal/src/libunwind/src/tilegx/Lregs.c | 5 + .../pal/src/libunwind/src/tilegx/Lresume.c | 5 + .../src/pal/src/libunwind/src/tilegx/Lstep.c | 5 + .../src/pal/src/libunwind/src/tilegx/elfxx.c | 27 + .../src/libunwind/src/tilegx/gen-offsets.c | 30 + .../pal/src/libunwind/src/tilegx/getcontext.S | 36 + .../src/pal/src/libunwind/src/tilegx/init.h | 63 + .../pal/src/libunwind/src/tilegx/is_fpreg.c | 33 + .../pal/src/libunwind/src/tilegx/offsets.h | 12 + .../pal/src/libunwind/src/tilegx/regname.c | 55 + .../pal/src/libunwind/src/tilegx/siglongjmp.S | 7 + .../pal/src/libunwind/src/unwind/Backtrace.c | 56 + .../libunwind/src/unwind/DeleteException.c | 38 + .../src/unwind/FindEnclosingFunction.c | 42 + .../src/libunwind/src/unwind/ForcedUnwind.c | 52 + .../src/pal/src/libunwind/src/unwind/GetBSP.c | 42 + .../src/pal/src/libunwind/src/unwind/GetCFA.c | 38 + .../src/libunwind/src/unwind/GetDataRelBase.c | 39 + .../src/pal/src/libunwind/src/unwind/GetGR.c | 43 + .../src/pal/src/libunwind/src/unwind/GetIP.c | 38 + .../pal/src/libunwind/src/unwind/GetIPInfo.c | 42 + .../src/unwind/GetLanguageSpecificData.c | 40 + .../src/libunwind/src/unwind/GetRegionStart.c | 39 + .../src/libunwind/src/unwind/GetTextRelBase.c | 35 + .../src/libunwind/src/unwind/RaiseException.c | 103 + .../src/pal/src/libunwind/src/unwind/Resume.c | 42 + .../libunwind/src/unwind/Resume_or_Rethrow.c | 47 + .../src/pal/src/libunwind/src/unwind/SetGR.c | 47 + .../src/pal/src/libunwind/src/unwind/SetIP.c | 35 + .../src/libunwind/src/unwind/libunwind.pc.in | 11 + .../libunwind/src/unwind/unwind-internal.h | 140 + .../libunwind/src/x86_64/Gapply_reg_state.c | 37 + .../libunwind/src/x86_64/Gcreate_addr_space.c | 61 + .../src/libunwind/src/x86_64/Gget_proc_info.c | 48 + .../src/libunwind/src/x86_64/Gget_save_loc.c | 73 + .../pal/src/libunwind/src/x86_64/Gglobal.c | 102 + .../src/pal/src/libunwind/src/x86_64/Ginit.c | 342 ++ .../src/libunwind/src/x86_64/Ginit_local.c | 81 + .../src/libunwind/src/x86_64/Ginit_remote.c | 57 + .../src/libunwind/src/x86_64/Gos-freebsd.c | 218 + .../pal/src/libunwind/src/x86_64/Gos-linux.c | 156 + .../src/x86_64/Greg_states_iterate.c | 37 + .../src/pal/src/libunwind/src/x86_64/Gregs.c | 138 + .../pal/src/libunwind/src/x86_64/Gresume.c | 123 + .../src/libunwind/src/x86_64/Gstash_frame.c | 119 + .../src/pal/src/libunwind/src/x86_64/Gstep.c | 227 + .../src/pal/src/libunwind/src/x86_64/Gtrace.c | 551 ++ .../libunwind/src/x86_64/Lapply_reg_state.c | 5 + .../libunwind/src/x86_64/Lcreate_addr_space.c | 5 + .../src/libunwind/src/x86_64/Lget_proc_info.c | 5 + .../src/libunwind/src/x86_64/Lget_save_loc.c | 5 + .../pal/src/libunwind/src/x86_64/Lglobal.c | 6 + .../src/pal/src/libunwind/src/x86_64/Linit.c | 5 + .../src/libunwind/src/x86_64/Linit_local.c | 5 + .../src/libunwind/src/x86_64/Linit_remote.c | 5 + .../src/libunwind/src/x86_64/Los-freebsd.c | 5 + .../pal/src/libunwind/src/x86_64/Los-linux.c | 5 + .../src/x86_64/Lreg_states_iterate.c | 5 + .../src/pal/src/libunwind/src/x86_64/Lregs.c | 5 + .../pal/src/libunwind/src/x86_64/Lresume.c | 5 + .../src/libunwind/src/x86_64/Lstash_frame.c | 5 + .../src/pal/src/libunwind/src/x86_64/Lstep.c | 5 + .../src/pal/src/libunwind/src/x86_64/Ltrace.c | 5 + .../pal/src/libunwind/src/x86_64/getcontext.S | 134 + .../src/pal/src/libunwind/src/x86_64/init.h | 89 + .../pal/src/libunwind/src/x86_64/is_fpreg.c | 38 + .../pal/src/libunwind/src/x86_64/longjmp.S | 34 + .../pal/src/libunwind/src/x86_64/offsets.h | 3 + .../pal/src/libunwind/src/x86_64/regname.c | 56 + .../pal/src/libunwind/src/x86_64/setcontext.S | 83 + .../pal/src/libunwind/src/x86_64/siglongjmp.S | 32 + .../pal/src/libunwind/tests/Gia64-test-nat.c | 626 ++ .../pal/src/libunwind/tests/Gia64-test-rbs.c | 193 + .../src/libunwind/tests/Gia64-test-readonly.c | 89 + .../src/libunwind/tests/Gia64-test-stack.c | 176 + .../pal/src/libunwind/tests/Gperf-simple.c | 264 + .../src/pal/src/libunwind/tests/Gperf-trace.c | 250 + .../src/pal/src/libunwind/tests/Gtest-bt.c | 263 + .../src/libunwind/tests/Gtest-concurrent.c | 136 + .../src/pal/src/libunwind/tests/Gtest-dyn1.c | 223 + .../src/pal/src/libunwind/tests/Gtest-exc.c | 162 + .../pal/src/libunwind/tests/Gtest-init.cxx | 107 + .../pal/src/libunwind/tests/Gtest-nomalloc.c | 110 + .../src/libunwind/tests/Gtest-resume-sig-rt.c | 31 + .../src/libunwind/tests/Gtest-resume-sig.c | 200 + .../src/pal/src/libunwind/tests/Gtest-trace.c | 282 + .../pal/src/libunwind/tests/Lia64-test-nat.c | 5 + .../pal/src/libunwind/tests/Lia64-test-rbs.c | 5 + .../src/libunwind/tests/Lia64-test-readonly.c | 5 + .../src/libunwind/tests/Lia64-test-stack.c | 5 + .../pal/src/libunwind/tests/Lperf-simple.c | 5 + .../src/pal/src/libunwind/tests/Lperf-trace.c | 5 + .../src/pal/src/libunwind/tests/Lrs-race.c | 1514 +++++ .../src/pal/src/libunwind/tests/Ltest-bt.c | 5 + .../src/libunwind/tests/Ltest-concurrent.c | 5 + .../libunwind/tests/Ltest-cxx-exceptions.cxx | 80 + .../src/pal/src/libunwind/tests/Ltest-dyn1.c | 5 + .../src/pal/src/libunwind/tests/Ltest-exc.c | 5 + .../tests/Ltest-init-local-signal-lib.c | 6 + .../libunwind/tests/Ltest-init-local-signal.c | 60 + .../pal/src/libunwind/tests/Ltest-init.cxx | 5 + .../src/libunwind/tests/Ltest-mem-validate.c | 143 + .../pal/src/libunwind/tests/Ltest-nocalloc.c | 137 + .../pal/src/libunwind/tests/Ltest-nomalloc.c | 5 + .../src/libunwind/tests/Ltest-resume-sig-rt.c | 5 + .../src/libunwind/tests/Ltest-resume-sig.c | 5 + .../src/pal/src/libunwind/tests/Ltest-trace.c | 5 + .../pal/src/libunwind/tests/Ltest-varargs.c | 84 + .../src/pal/src/libunwind/tests/Makefile.am | 234 + .../src/libunwind/tests/check-namespace.sh.in | 367 ++ .../src/pal/src/libunwind/tests/crasher.c | 124 + .../src/pal/src/libunwind/tests/flush-cache.S | 104 + .../src/pal/src/libunwind/tests/flush-cache.h | 38 + .../src/pal/src/libunwind/tests/forker.c | 76 + .../pal/src/libunwind/tests/ia64-dyn-asm.S | 102 + .../pal/src/libunwind/tests/ia64-test-dyn1.c | 223 + .../src/libunwind/tests/ia64-test-nat-asm.S | 508 ++ .../src/libunwind/tests/ia64-test-rbs-asm.S | 275 + .../pal/src/libunwind/tests/ia64-test-rbs.h | 3 + .../libunwind/tests/ia64-test-readonly-asm.S | 55 + .../src/libunwind/tests/ia64-test-setjmp.c | 155 + .../pal/src/libunwind/tests/ia64-test-sig.c | 102 + .../src/libunwind/tests/ia64-test-stack-asm.S | 183 + .../pal/src/libunwind/tests/ia64-test-stack.h | 3 + .../src/pal/src/libunwind/tests/ident.c | 5 + .../src/pal/src/libunwind/tests/mapper.c | 78 + .../src/pal/src/libunwind/tests/perf-startup | 19 + .../tests/ppc64-test-altivec-utils.c | 32 + .../src/libunwind/tests/ppc64-test-altivec.c | 177 + .../src/libunwind/tests/run-check-namespace | 3 + .../src/libunwind/tests/run-coredump-unwind | 53 + .../libunwind/tests/run-coredump-unwind-mdi | 8 + .../src/libunwind/tests/run-ia64-test-dyn1 | 2 + .../pal/src/libunwind/tests/run-ptrace-mapper | 2 + .../pal/src/libunwind/tests/run-ptrace-misc | 2 + .../pal/src/libunwind/tests/test-async-sig.c | 193 + .../libunwind/tests/test-coredump-unwind.c | 395 ++ .../src/libunwind/tests/test-flush-cache.c | 143 + .../src/libunwind/tests/test-init-remote.c | 103 + .../src/pal/src/libunwind/tests/test-mem.c | 103 + .../pal/src/libunwind/tests/test-proc-info.c | 171 + .../src/libunwind/tests/test-ptrace-misc.c | 120 + .../src/pal/src/libunwind/tests/test-ptrace.c | 370 ++ .../pal/src/libunwind/tests/test-reg-state.c | 133 + .../src/pal/src/libunwind/tests/test-setjmp.c | 285 + .../libunwind/tests/test-static-link-gen.c | 74 + .../libunwind/tests/test-static-link-loc.c | 102 + .../pal/src/libunwind/tests/test-strerror.c | 18 + .../src/pal/src/loader/module.cpp | 1812 ++++++ .../src/pal/src/loader/modulename.cpp | 69 + .../src/pal/src/locale/unicode.cpp | 495 ++ .../src/pal/src/locale/unicodedata.cpp | 2362 ++++++++ .../src/pal/src/locale/unicodedata.cs | 65 + .../src/pal/src/locale/utf8.cpp | 2946 ++++++++++ .../src/pal/src/map/common.cpp | 66 + .../coreclr_headers/src/pal/src/map/common.h | 43 + .../coreclr_headers/src/pal/src/map/map.cpp | 2726 +++++++++ .../src/pal/src/map/virtual.cpp | 2290 ++++++++ .../src/pal/src/memory/local.cpp | 140 + .../src/pal/src/misc/cgroup.cpp | 686 +++ .../src/pal/src/misc/dbgmsg.cpp | 862 +++ .../src/pal/src/misc/environ.cpp | 1125 ++++ .../src/pal/src/misc/error.cpp | 126 + .../src/pal/src/misc/errorstrings.cpp | 172 + .../ndpversion.h => src/misc/errorstrings.h} | 8 +- .../src/pal/src/misc/fmtmessage.cpp | 692 +++ .../src/pal/src/misc/jitsupport.cpp | 131 + .../src/pal/src/misc/miscpalapi.cpp | 313 + .../src/pal/src/misc/msgbox.cpp | 416 ++ .../src/pal/src/misc/perfjitdump.cpp | 413 ++ .../src/pal/src/misc/perftrace.cpp | 1345 +++++ .../src/pal/src/misc/strutil.cpp | 96 + .../src/pal/src/misc/sysinfo.cpp | 629 ++ .../coreclr_headers/src/pal/src/misc/time.cpp | 404 ++ .../src/pal/src/misc/tracepointprovider.cpp | 121 + .../src/pal/src/misc/utils.cpp | 365 ++ .../coreclr_headers/src/pal/src/numa/numa.cpp | 289 + .../src/pal/src/numa/numashim.h | 37 + .../src/pal/src/objmgr/palobjbase.cpp | 369 ++ .../src/pal/src/objmgr/palobjbase.hpp | 191 + .../src/pal/src/objmgr/shmobject.cpp | 1229 ++++ .../src/pal/src/objmgr/shmobject.hpp | 375 ++ .../src/pal/src/objmgr/shmobjectmanager.cpp | 1130 ++++ .../src/pal/src/objmgr/shmobjectmanager.hpp | 143 + .../src/pal/src/poll/fakepoll.cpp | 133 + .../src/pal/src/safecrt/cruntime.h | 98 + .../src/pal/src/safecrt/input.inl | 1317 +++++ .../src/pal/src/safecrt/internal.h | 1088 ++++ .../src/pal/src/safecrt/internal_securecrt.h | 292 + .../src/pal/src/safecrt/makepath_s.cpp | 31 + .../src/pal/src/safecrt/mbusafecrt.cpp | 249 + .../src/pal/src/safecrt/mbusafecrt_internal.h | 98 + .../src/pal/src/safecrt/memcpy_s.cpp | 82 + .../src/pal/src/safecrt/memmove_s.cpp | 69 + .../src/pal/src/safecrt/output.inl | 1575 +++++ .../src/pal/src/safecrt/safecrt_input_s.cpp | 46 + .../src/pal/src/safecrt/safecrt_output_l.cpp | 1467 +++++ .../src/pal/src/safecrt/safecrt_output_s.cpp | 46 + .../src/pal/src/safecrt/safecrt_winput_s.cpp | 55 + .../src/pal/src/safecrt/safecrt_woutput_s.cpp | 59 + .../src/pal/src/safecrt/snprintf.cpp | 18 + .../src/pal/src/safecrt/splitpath_s.cpp | 31 + .../src/pal/src/safecrt/sprintf_s.cpp | 97 + .../src/pal/src/safecrt/sscanf_s.cpp | 218 + .../src/pal/src/safecrt/strcat_s.cpp | 33 + .../src/pal/src/safecrt/strcpy_s.cpp | 29 + .../src/pal/src/safecrt/strlen_s.cpp | 58 + .../src/pal/src/safecrt/strncat_s.cpp | 31 + .../src/pal/src/safecrt/strncpy_s.cpp | 30 + .../src/pal/src/safecrt/strtok_s.cpp | 27 + .../src/pal/src/safecrt/swprintf.cpp | 120 + .../src/pal/src/safecrt/tcscat_s.inl | 51 + .../src/pal/src/safecrt/tcscpy_s.inl | 39 + .../src/pal/src/safecrt/tcsncat_s.inl | 81 + .../src/pal/src/safecrt/tcsncpy_s.inl | 71 + .../src/pal/src/safecrt/tcstok_s.inl | 71 + .../src/pal/src/safecrt/tmakepath_s.inl | 116 + .../src/pal/src/safecrt/tsplitpath_s.inl | 280 + .../src/pal/src/safecrt/vsprintf.cpp | 268 + .../src/pal/src/safecrt/vswprint.cpp | 211 + .../src/pal/src/safecrt/wcscat_s.cpp | 36 + .../src/pal/src/safecrt/wcscpy_s.cpp | 33 + .../src/pal/src/safecrt/wcslen_s.cpp | 58 + .../src/pal/src/safecrt/wcsncat_s.cpp | 35 + .../src/pal/src/safecrt/wcsncpy_s.cpp | 34 + .../src/pal/src/safecrt/wcstok_s.cpp | 27 + .../src/pal/src/safecrt/wmakepath_s.cpp | 30 + .../src/pal/src/safecrt/wsplitpath_s.cpp | 30 + .../src/pal/src/safecrt/xtoa_s.cpp | 29 + .../src/pal/src/safecrt/xtow_s.cpp | 28 + .../src/pal/src/safecrt/xtox_s.inl | 415 ++ .../src/pal/src/sharedmemory/sharedmemory.cpp | 1227 ++++ .../src/pal/src/shmemory/shmemory.cpp | 388 ++ .../coreclr_headers/src/pal/src/sync/cs.cpp | 1607 ++++++ .../src/pal/src/synchmgr/synchcontrollers.cpp | 2046 +++++++ .../src/pal/src/synchmgr/synchmanager.cpp | 4624 +++++++++++++++ .../src/pal/src/synchmgr/synchmanager.hpp | 1024 ++++ .../src/pal/src/synchmgr/wait.cpp | 896 +++ .../src/pal/src/synchobj/event.cpp | 543 ++ .../src/pal/src/synchobj/mutex.cpp | 1614 ++++++ .../src/pal/src/synchobj/semaphore.cpp | 597 ++ .../src/pal/src/thread/context.cpp | 1426 +++++ .../src/pal/src/thread/process.cpp | 5058 ++++++++++++++++ .../src/pal/src/thread/procprivate.hpp | 78 + .../src/pal/src/thread/thread.cpp | 2971 ++++++++++ .../src/pal/src/thread/threadsusp.cpp | 1045 ++++ .../src/pal/tests/CMakeLists.txt | 20 + .../src/pal/tests/palsuite/CMakeLists.txt | 44 + .../src/pal/tests/palsuite/DisabledTests.txt | 51 + .../src/pal/tests/palsuite/README.txt | 116 + .../tests/palsuite/c_runtime/CMakeLists.txt | 171 + .../c_runtime/__iscsym/CMakeLists.txt | 2 + .../c_runtime/__iscsym/test1/CMakeLists.txt | 13 + .../c_runtime/__iscsym/test1/__iscsym.cpp | 93 + .../c_runtime/__iscsym/test1/testinfo.dat | 12 + .../palsuite/c_runtime/_alloca/CMakeLists.txt | 2 + .../c_runtime/_alloca/test1/CMakeLists.txt | 13 + .../c_runtime/_alloca/test1/test1.cpp | 62 + .../c_runtime/_alloca/test1/testinfo.dat | 13 + .../palsuite/c_runtime/_fdopen/CMakeLists.txt | 2 + .../c_runtime/_fdopen/test1/CMakeLists.txt | 13 + .../c_runtime/_fdopen/test1/test1.cpp | 112 + .../c_runtime/_fdopen/test1/testinfo.dat | 23 + .../palsuite/c_runtime/_finite/CMakeLists.txt | 1 + .../c_runtime/_finite/test1/CMakeLists.txt | 13 + .../c_runtime/_finite/test1/test1.cpp | 119 + .../c_runtime/_finite/test1/testinfo.dat | 13 + .../c_runtime/_finitef/CMakeLists.txt | 1 + .../c_runtime/_finitef/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/_finitef/test1/test1.c | 119 + .../c_runtime/_finitef/test1/testinfo.dat | 13 + .../palsuite/c_runtime/_gcvt/CMakeLists.txt | 3 + .../c_runtime/_gcvt/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/_gcvt/test1/_gcvt.cpp | 58 + .../c_runtime/_gcvt/test1/testinfo.dat | 13 + .../c_runtime/_gcvt/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/_gcvt/test2/test2.cpp | 83 + .../c_runtime/_gcvt/test2/testinfo.dat | 15 + .../palsuite/c_runtime/_isnan/CMakeLists.txt | 1 + .../c_runtime/_isnan/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/_isnan/test1/test1.cpp | 115 + .../c_runtime/_isnan/test1/testinfo.dat | 16 + .../palsuite/c_runtime/_isnanf/CMakeLists.txt | 1 + .../c_runtime/_isnanf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/_isnanf/test1/test1.c | 115 + .../c_runtime/_isnanf/test1/testinfo.dat | 16 + .../palsuite/c_runtime/_itow/CMakeLists.txt | 2 + .../c_runtime/_itow/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/_itow/test1/test1.cpp | 101 + .../c_runtime/_itow/test1/testinfo.dat | 18 + .../palsuite/c_runtime/_mbsdec/CMakeLists.txt | 2 + .../c_runtime/_mbsdec/test1/CMakeLists.txt | 13 + .../c_runtime/_mbsdec/test1/test1.cpp | 77 + .../c_runtime/_mbsdec/test1/testinfo.dat | 18 + .../palsuite/c_runtime/_mbsinc/CMakeLists.txt | 2 + .../c_runtime/_mbsinc/test1/CMakeLists.txt | 13 + .../c_runtime/_mbsinc/test1/test1.cpp | 62 + .../c_runtime/_mbsinc/test1/testinfo.dat | 15 + .../c_runtime/_mbsninc/CMakeLists.txt | 2 + .../c_runtime/_mbsninc/test1/CMakeLists.txt | 13 + .../c_runtime/_mbsninc/test1/test1.cpp | 65 + .../c_runtime/_mbsninc/test1/testinfo.dat | 17 + .../palsuite/c_runtime/_putenv/CMakeLists.txt | 5 + .../c_runtime/_putenv/test1/CMakeLists.txt | 13 + .../c_runtime/_putenv/test1/test1.cpp | 99 + .../c_runtime/_putenv/test1/testinfo.dat | 13 + .../c_runtime/_putenv/test2/CMakeLists.txt | 13 + .../c_runtime/_putenv/test2/test2.cpp | 76 + .../c_runtime/_putenv/test2/testinfo.dat | 13 + .../c_runtime/_putenv/test3/CMakeLists.txt | 13 + .../c_runtime/_putenv/test3/test3.cpp | 102 + .../c_runtime/_putenv/test3/testinfo.dat | 14 + .../c_runtime/_putenv/test4/CMakeLists.txt | 13 + .../c_runtime/_putenv/test4/test4.cpp | 75 + .../c_runtime/_putenv/test4/testinfo.dat | 14 + .../palsuite/c_runtime/_rotl/CMakeLists.txt | 2 + .../c_runtime/_rotl/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/_rotl/test1/test1.cpp | 55 + .../c_runtime/_rotl/test1/testinfo.dat | 17 + .../palsuite/c_runtime/_rotr/CMakeLists.txt | 2 + .../c_runtime/_rotr/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/_rotr/test1/test1.cpp | 60 + .../c_runtime/_rotr/test1/testinfo.dat | 17 + .../c_runtime/_snprintf_s/CMakeLists.txt | 19 + .../c_runtime/_snprintf_s/_snprintf_s.h | 194 + .../_snprintf_s/test1/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test1/test1.cpp | 58 + .../c_runtime/_snprintf_s/test1/testinfo.dat | 12 + .../_snprintf_s/test10/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test10/test10.cpp | 55 + .../c_runtime/_snprintf_s/test10/testinfo.dat | 12 + .../_snprintf_s/test11/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test11/test11.cpp | 54 + .../c_runtime/_snprintf_s/test11/testinfo.dat | 12 + .../_snprintf_s/test12/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test12/test12.cpp | 55 + .../c_runtime/_snprintf_s/test12/testinfo.dat | 12 + .../_snprintf_s/test13/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test13/test13.cpp | 55 + .../c_runtime/_snprintf_s/test13/testinfo.dat | 12 + .../_snprintf_s/test14/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test14/test14.cpp | 57 + .../c_runtime/_snprintf_s/test14/testinfo.dat | 12 + .../_snprintf_s/test15/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test15/test15.cpp | 56 + .../c_runtime/_snprintf_s/test15/testinfo.dat | 12 + .../_snprintf_s/test16/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test16/test16.cpp | 52 + .../c_runtime/_snprintf_s/test16/testinfo.dat | 12 + .../_snprintf_s/test17/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test17/test17.cpp | 53 + .../c_runtime/_snprintf_s/test17/testinfo.dat | 12 + .../_snprintf_s/test18/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test18/test18.cpp | 53 + .../c_runtime/_snprintf_s/test18/testinfo.dat | 12 + .../_snprintf_s/test19/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test19/test19.cpp | 70 + .../c_runtime/_snprintf_s/test19/testinfo.dat | 12 + .../_snprintf_s/test2/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test2/test2.cpp | 50 + .../c_runtime/_snprintf_s/test2/testinfo.dat | 12 + .../_snprintf_s/test3/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test3/test3.cpp | 51 + .../c_runtime/_snprintf_s/test3/testinfo.dat | 12 + .../_snprintf_s/test4/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test4/test4.cpp | 69 + .../c_runtime/_snprintf_s/test4/testinfo.dat | 12 + .../_snprintf_s/test6/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test6/test6.cpp | 47 + .../c_runtime/_snprintf_s/test6/testinfo.dat | 12 + .../_snprintf_s/test7/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test7/test7.cpp | 47 + .../c_runtime/_snprintf_s/test7/testinfo.dat | 12 + .../_snprintf_s/test8/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test8/test8.cpp | 56 + .../c_runtime/_snprintf_s/test8/testinfo.dat | 12 + .../_snprintf_s/test9/CMakeLists.txt | 13 + .../c_runtime/_snprintf_s/test9/test9.cpp | 55 + .../c_runtime/_snprintf_s/test9/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/_snwprintf_s.h | 199 + .../_snwprintf_s/test1/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test1/test1.cpp | 62 + .../c_runtime/_snwprintf_s/test1/testinfo.dat | 12 + .../_snwprintf_s/test10/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test10/test10.cpp | 54 + .../_snwprintf_s/test10/testinfo.dat | 12 + .../_snwprintf_s/test11/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test11/test11.cpp | 54 + .../_snwprintf_s/test11/testinfo.dat | 12 + .../_snwprintf_s/test12/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test12/test12.cpp | 54 + .../_snwprintf_s/test12/testinfo.dat | 12 + .../_snwprintf_s/test13/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test13/test13.cpp | 54 + .../_snwprintf_s/test13/testinfo.dat | 12 + .../_snwprintf_s/test14/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test14/test14.cpp | 66 + .../_snwprintf_s/test14/testinfo.dat | 12 + .../_snwprintf_s/test15/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test15/test15.cpp | 67 + .../_snwprintf_s/test15/testinfo.dat | 12 + .../_snwprintf_s/test16/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test16/test16.cpp | 65 + .../_snwprintf_s/test16/testinfo.dat | 12 + .../_snwprintf_s/test17/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test17/test17.cpp | 68 + .../_snwprintf_s/test17/testinfo.dat | 12 + .../_snwprintf_s/test18/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test18/test18.cpp | 69 + .../_snwprintf_s/test18/testinfo.dat | 12 + .../_snwprintf_s/test19/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test19/test19.cpp | 82 + .../_snwprintf_s/test19/testinfo.dat | 12 + .../_snwprintf_s/test2/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test2/test2.cpp | 50 + .../c_runtime/_snwprintf_s/test2/testinfo.dat | 12 + .../_snwprintf_s/test3/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test3/test3.cpp | 50 + .../c_runtime/_snwprintf_s/test3/testinfo.dat | 12 + .../_snwprintf_s/test4/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test4/test4.cpp | 71 + .../c_runtime/_snwprintf_s/test4/testinfo.dat | 12 + .../_snwprintf_s/test6/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test6/test6.cpp | 46 + .../c_runtime/_snwprintf_s/test6/testinfo.dat | 12 + .../_snwprintf_s/test7/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test7/test7.cpp | 46 + .../c_runtime/_snwprintf_s/test7/testinfo.dat | 12 + .../_snwprintf_s/test8/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test8/test8.cpp | 53 + .../c_runtime/_snwprintf_s/test8/testinfo.dat | 12 + .../_snwprintf_s/test9/CMakeLists.txt | 13 + .../c_runtime/_snwprintf_s/test9/test9.cpp | 53 + .../c_runtime/_snwprintf_s/test9/testinfo.dat | 12 + .../c_runtime/_stricmp/CMakeLists.txt | 2 + .../c_runtime/_stricmp/test1/CMakeLists.txt | 13 + .../c_runtime/_stricmp/test1/test1.cpp | 70 + .../c_runtime/_stricmp/test1/testinfo.dat | 15 + .../c_runtime/_strnicmp/CMakeLists.txt | 2 + .../c_runtime/_strnicmp/test1/CMakeLists.txt | 13 + .../c_runtime/_strnicmp/test1/test1.cpp | 85 + .../c_runtime/_strnicmp/test1/testinfo.dat | 18 + .../c_runtime/_vsnprintf_s/CMakeLists.txt | 19 + .../c_runtime/_vsnprintf_s/_vsnprintf_s.h | 124 + .../_vsnprintf_s/test1/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test1/test1.cpp | 55 + .../c_runtime/_vsnprintf_s/test1/testinfo.dat | 13 + .../_vsnprintf_s/test10/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test10/test10.cpp | 50 + .../_vsnprintf_s/test10/testinfo.dat | 14 + .../_vsnprintf_s/test11/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test11/test11.cpp | 50 + .../_vsnprintf_s/test11/testinfo.dat | 14 + .../_vsnprintf_s/test12/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test12/test12.cpp | 52 + .../_vsnprintf_s/test12/testinfo.dat | 14 + .../_vsnprintf_s/test13/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test13/test13.cpp | 52 + .../_vsnprintf_s/test13/testinfo.dat | 14 + .../_vsnprintf_s/test14/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test14/test14.cpp | 50 + .../_vsnprintf_s/test14/testinfo.dat | 14 + .../_vsnprintf_s/test15/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test15/test15.cpp | 49 + .../_vsnprintf_s/test15/testinfo.dat | 14 + .../_vsnprintf_s/test16/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test16/test16.cpp | 49 + .../_vsnprintf_s/test16/testinfo.dat | 14 + .../_vsnprintf_s/test17/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test17/test17.cpp | 50 + .../_vsnprintf_s/test17/testinfo.dat | 14 + .../_vsnprintf_s/test18/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test18/test18.cpp | 50 + .../_vsnprintf_s/test18/testinfo.dat | 14 + .../_vsnprintf_s/test19/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test19/test19.cpp | 103 + .../_vsnprintf_s/test19/testinfo.dat | 14 + .../_vsnprintf_s/test2/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test2/test2.cpp | 50 + .../c_runtime/_vsnprintf_s/test2/testinfo.dat | 14 + .../_vsnprintf_s/test3/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test3/test3.cpp | 49 + .../c_runtime/_vsnprintf_s/test3/testinfo.dat | 14 + .../_vsnprintf_s/test4/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test4/test4.cpp | 98 + .../c_runtime/_vsnprintf_s/test4/testinfo.dat | 14 + .../_vsnprintf_s/test6/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test6/test6.cpp | 44 + .../c_runtime/_vsnprintf_s/test6/testinfo.dat | 14 + .../_vsnprintf_s/test7/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test7/test7.cpp | 44 + .../c_runtime/_vsnprintf_s/test7/testinfo.dat | 14 + .../_vsnprintf_s/test8/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test8/test8.cpp | 52 + .../c_runtime/_vsnprintf_s/test8/testinfo.dat | 14 + .../_vsnprintf_s/test9/CMakeLists.txt | 13 + .../c_runtime/_vsnprintf_s/test9/test9.cpp | 51 + .../c_runtime/_vsnprintf_s/test9/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/_vsnwprintf_s.h | 133 + .../_vsnwprintf_s/test1/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test1/test1.cpp | 60 + .../_vsnwprintf_s/test1/testinfo.dat | 14 + .../_vsnwprintf_s/test10/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test10/test10.cpp | 50 + .../_vsnwprintf_s/test10/testinfo.dat | 14 + .../_vsnwprintf_s/test11/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test11/test11.cpp | 50 + .../_vsnwprintf_s/test11/testinfo.dat | 14 + .../_vsnwprintf_s/test12/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test12/test12.cpp | 50 + .../_vsnwprintf_s/test12/testinfo.dat | 14 + .../_vsnwprintf_s/test13/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test13/test13.cpp | 50 + .../_vsnwprintf_s/test13/testinfo.dat | 14 + .../_vsnwprintf_s/test14/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test14/test14.cpp | 63 + .../_vsnwprintf_s/test14/testinfo.dat | 14 + .../_vsnwprintf_s/test15/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test15/test15.cpp | 64 + .../_vsnwprintf_s/test15/testinfo.dat | 14 + .../_vsnwprintf_s/test16/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test16/test16.cpp | 63 + .../_vsnwprintf_s/test16/testinfo.dat | 14 + .../_vsnwprintf_s/test17/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test17/test17.cpp | 65 + .../_vsnwprintf_s/test17/testinfo.dat | 14 + .../_vsnwprintf_s/test18/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test18/test18.cpp | 65 + .../_vsnwprintf_s/test18/testinfo.dat | 14 + .../_vsnwprintf_s/test19/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test19/test19.cpp | 139 + .../_vsnwprintf_s/test19/testinfo.dat | 14 + .../_vsnwprintf_s/test2/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test2/test2.cpp | 46 + .../_vsnwprintf_s/test2/testinfo.dat | 14 + .../_vsnwprintf_s/test3/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test3/test3.cpp | 46 + .../_vsnwprintf_s/test3/testinfo.dat | 14 + .../_vsnwprintf_s/test4/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test4/test4.cpp | 121 + .../_vsnwprintf_s/test4/testinfo.dat | 14 + .../_vsnwprintf_s/test6/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test6/test6.cpp | 43 + .../_vsnwprintf_s/test6/testinfo.dat | 14 + .../_vsnwprintf_s/test7/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test7/test7.cpp | 43 + .../_vsnwprintf_s/test7/testinfo.dat | 14 + .../_vsnwprintf_s/test8/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test8/test8.cpp | 49 + .../_vsnwprintf_s/test8/testinfo.dat | 14 + .../_vsnwprintf_s/test9/CMakeLists.txt | 13 + .../c_runtime/_vsnwprintf_s/test9/test9.cpp | 49 + .../_vsnwprintf_s/test9/testinfo.dat | 14 + .../c_runtime/_wcsicmp/CMakeLists.txt | 2 + .../c_runtime/_wcsicmp/test1/CMakeLists.txt | 13 + .../c_runtime/_wcsicmp/test1/test1.cpp | 68 + .../c_runtime/_wcsicmp/test1/testinfo.dat | 12 + .../palsuite/c_runtime/_wcslwr/CMakeLists.txt | 2 + .../c_runtime/_wcslwr/test1/CMakeLists.txt | 13 + .../c_runtime/_wcslwr/test1/test1.cpp | 50 + .../c_runtime/_wcslwr/test1/testinfo.dat | 14 + .../c_runtime/_wcsnicmp/CMakeLists.txt | 2 + .../c_runtime/_wcsnicmp/test1/CMakeLists.txt | 13 + .../c_runtime/_wcsnicmp/test1/test1.cpp | 95 + .../c_runtime/_wcsnicmp/test1/testinfo.dat | 18 + .../palsuite/c_runtime/_wfopen/CMakeLists.txt | 8 + .../c_runtime/_wfopen/test1/CMakeLists.txt | 13 + .../c_runtime/_wfopen/test1/test1.cpp | 79 + .../c_runtime/_wfopen/test1/testinfo.dat | 15 + .../c_runtime/_wfopen/test2/CMakeLists.txt | 13 + .../c_runtime/_wfopen/test2/test2.cpp | 68 + .../c_runtime/_wfopen/test2/testinfo.dat | 15 + .../c_runtime/_wfopen/test3/CMakeLists.txt | 13 + .../c_runtime/_wfopen/test3/test3.cpp | 70 + .../c_runtime/_wfopen/test3/testinfo.dat | 15 + .../c_runtime/_wfopen/test4/CMakeLists.txt | 13 + .../c_runtime/_wfopen/test4/test4.cpp | 87 + .../c_runtime/_wfopen/test4/testinfo.dat | 15 + .../c_runtime/_wfopen/test5/CMakeLists.txt | 13 + .../c_runtime/_wfopen/test5/test5.cpp | 82 + .../c_runtime/_wfopen/test5/testinfo.dat | 15 + .../c_runtime/_wfopen/test6/CMakeLists.txt | 13 + .../c_runtime/_wfopen/test6/test6.cpp | 152 + .../c_runtime/_wfopen/test6/testinfo.dat | 15 + .../c_runtime/_wfopen/test7/CMakeLists.txt | 13 + .../c_runtime/_wfopen/test7/test7.cpp | 119 + .../c_runtime/_wfopen/test7/testinfo.dat | 15 + .../palsuite/c_runtime/_wtoi/CMakeLists.txt | 2 + .../c_runtime/_wtoi/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/_wtoi/test1/test1.cpp | 79 + .../c_runtime/_wtoi/test1/testinfo.dat | 17 + .../palsuite/c_runtime/abs/CMakeLists.txt | 2 + .../c_runtime/abs/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/abs/test1/abs.cpp | 54 + .../palsuite/c_runtime/abs/test1/testinfo.dat | 13 + .../palsuite/c_runtime/acos/CMakeLists.txt | 1 + .../c_runtime/acos/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/acos/test1/test1.cpp | 130 + .../c_runtime/acos/test1/testinfo.dat | 14 + .../palsuite/c_runtime/acosf/CMakeLists.txt | 1 + .../c_runtime/acosf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/acosf/test1/test1.c | 129 + .../c_runtime/acosf/test1/testinfo.dat | 14 + .../palsuite/c_runtime/acosh/CMakeLists.txt | 1 + .../c_runtime/acosh/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/acosh/test1/test1.cpp | 129 + .../c_runtime/acosh/test1/testinfo.dat | 14 + .../palsuite/c_runtime/acoshf/CMakeLists.txt | 1 + .../c_runtime/acoshf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/acoshf/test1/test1.c | 128 + .../c_runtime/acoshf/test1/testinfo.dat | 14 + .../palsuite/c_runtime/asin/CMakeLists.txt | 1 + .../c_runtime/asin/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/asin/test1/test1.cpp | 146 + .../c_runtime/asin/test1/testinfo.dat | 14 + .../palsuite/c_runtime/asinf/CMakeLists.txt | 1 + .../c_runtime/asinf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/asinf/test1/test1.c | 145 + .../c_runtime/asinf/test1/testinfo.dat | 14 + .../palsuite/c_runtime/asinh/CMakeLists.txt | 1 + .../c_runtime/asinh/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/asinh/test1/test1.cpp | 146 + .../c_runtime/asinh/test1/testinfo.dat | 14 + .../palsuite/c_runtime/asinhf/CMakeLists.txt | 1 + .../c_runtime/asinhf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/asinhf/test1/test1.c | 145 + .../c_runtime/asinhf/test1/testinfo.dat | 14 + .../palsuite/c_runtime/atan/CMakeLists.txt | 1 + .../c_runtime/atan/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/atan/test1/test1.cpp | 128 + .../c_runtime/atan/test1/testinfo.dat | 13 + .../palsuite/c_runtime/atan2/CMakeLists.txt | 1 + .../c_runtime/atan2/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/atan2/test1/test1.cpp | 148 + .../c_runtime/atan2/test1/testinfo.dat | 14 + .../palsuite/c_runtime/atan2f/CMakeLists.txt | 1 + .../c_runtime/atan2f/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/atan2f/test1/test1.c | 147 + .../c_runtime/atan2f/test1/testinfo.dat | 14 + .../palsuite/c_runtime/atanf/CMakeLists.txt | 1 + .../c_runtime/atanf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/atanf/test1/test1.c | 127 + .../c_runtime/atanf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/atanh/CMakeLists.txt | 1 + .../c_runtime/atanh/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/atanh/test1/test1.cpp | 130 + .../c_runtime/atanh/test1/testinfo.dat | 13 + .../palsuite/c_runtime/atanhf/CMakeLists.txt | 1 + .../c_runtime/atanhf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/atanhf/test1/test1.c | 129 + .../c_runtime/atanhf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/atof/CMakeLists.txt | 2 + .../c_runtime/atof/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/atof/test1/test1.cpp | 75 + .../c_runtime/atof/test1/testinfo.dat | 16 + .../palsuite/c_runtime/atoi/CMakeLists.txt | 2 + .../c_runtime/atoi/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/atoi/test1/test1.cpp | 86 + .../c_runtime/atoi/test1/testinfo.dat | 17 + .../palsuite/c_runtime/bsearch/CMakeLists.txt | 3 + .../c_runtime/bsearch/test1/CMakeLists.txt | 13 + .../c_runtime/bsearch/test1/test1.cpp | 48 + .../c_runtime/bsearch/test1/testinfo.dat | 14 + .../c_runtime/bsearch/test2/CMakeLists.txt | 13 + .../c_runtime/bsearch/test2/test2.cpp | 57 + .../c_runtime/bsearch/test2/testinfo.dat | 14 + .../palsuite/c_runtime/cbrt/CMakeLists.txt | 2 + .../c_runtime/cbrt/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/cbrt/test1/test1.cpp | 123 + .../c_runtime/cbrt/test1/testinfo.dat | 17 + .../palsuite/c_runtime/cbrtf/CMakeLists.txt | 2 + .../c_runtime/cbrtf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/cbrtf/test1/test1.c | 122 + .../c_runtime/cbrtf/test1/testinfo.dat | 17 + .../palsuite/c_runtime/ceil/CMakeLists.txt | 1 + .../c_runtime/ceil/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/ceil/test1/test1.cpp | 132 + .../c_runtime/ceil/test1/testinfo.dat | 14 + .../palsuite/c_runtime/ceilf/CMakeLists.txt | 1 + .../c_runtime/ceilf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/ceilf/test1/test1.c | 131 + .../c_runtime/ceilf/test1/testinfo.dat | 14 + .../palsuite/c_runtime/cos/CMakeLists.txt | 1 + .../c_runtime/cos/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/cos/test1/test1.cpp | 131 + .../palsuite/c_runtime/cos/test1/testinfo.dat | 13 + .../palsuite/c_runtime/cosf/CMakeLists.txt | 1 + .../c_runtime/cosf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/cosf/test1/test1.c | 130 + .../c_runtime/cosf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/cosh/CMakeLists.txt | 1 + .../c_runtime/cosh/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/cosh/test1/test1.cpp | 130 + .../c_runtime/cosh/test1/testinfo.dat | 13 + .../palsuite/c_runtime/coshf/CMakeLists.txt | 1 + .../c_runtime/coshf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/coshf/test1/test1.c | 129 + .../c_runtime/coshf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/errno/CMakeLists.txt | 3 + .../c_runtime/errno/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/errno/test1/test1.cpp | 43 + .../c_runtime/errno/test1/testinfo.dat | 13 + .../c_runtime/errno/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/errno/test2/test2.cpp | 76 + .../c_runtime/errno/test2/testinfo.dat | 12 + .../palsuite/c_runtime/exit/CMakeLists.txt | 3 + .../c_runtime/exit/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/exit/test1/test1.cpp | 37 + .../c_runtime/exit/test1/testinfo.dat | 12 + .../c_runtime/exit/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/exit/test2/test2.cpp | 38 + .../c_runtime/exit/test2/testinfo.dat | 13 + .../palsuite/c_runtime/exp/CMakeLists.txt | 1 + .../c_runtime/exp/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/exp/test1/test1.cpp | 138 + .../palsuite/c_runtime/exp/test1/testinfo.dat | 12 + .../palsuite/c_runtime/expf/CMakeLists.txt | 1 + .../c_runtime/expf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/expf/test1/test1.c | 137 + .../c_runtime/expf/test1/testinfo.dat | 12 + .../palsuite/c_runtime/fabs/CMakeLists.txt | 1 + .../c_runtime/fabs/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/fabs/test1/test1.cpp | 130 + .../c_runtime/fabs/test1/testinfo.dat | 13 + .../palsuite/c_runtime/fabsf/CMakeLists.txt | 1 + .../c_runtime/fabsf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/fabsf/test1/test1.cpp | 130 + .../c_runtime/fabsf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/fclose/CMakeLists.txt | 3 + .../c_runtime/fclose/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/fclose/test1/test1.cpp | 79 + .../c_runtime/fclose/test1/testinfo.dat | 18 + .../c_runtime/fclose/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/fclose/test2/test2.cpp | 77 + .../c_runtime/fclose/test2/testinfo.dat | 15 + .../palsuite/c_runtime/ferror/CMakeLists.txt | 3 + .../c_runtime/ferror/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/ferror/test1/test1.cpp | 74 + .../palsuite/c_runtime/ferror/test1/testfile | 1 + .../c_runtime/ferror/test1/testinfo.dat | 16 + .../c_runtime/ferror/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/ferror/test2/test2.cpp | 69 + .../palsuite/c_runtime/ferror/test2/testfile | 1 + .../c_runtime/ferror/test2/testinfo.dat | 13 + .../palsuite/c_runtime/fflush/CMakeLists.txt | 2 + .../c_runtime/fflush/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/fflush/test1/test1.cpp | 80 + .../c_runtime/fflush/test1/testinfo.dat | 15 + .../palsuite/c_runtime/fgets/CMakeLists.txt | 4 + .../c_runtime/fgets/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/fgets/test1/test1.cpp | 102 + .../c_runtime/fgets/test1/testinfo.dat | 15 + .../c_runtime/fgets/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/fgets/test2/test2.cpp | 97 + .../c_runtime/fgets/test2/testinfo.dat | 14 + .../c_runtime/fgets/test3/CMakeLists.txt | 13 + .../palsuite/c_runtime/fgets/test3/test3.cpp | 73 + .../c_runtime/fgets/test3/testinfo.dat | 14 + .../palsuite/c_runtime/floor/CMakeLists.txt | 1 + .../c_runtime/floor/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/floor/test1/test1.cpp | 132 + .../c_runtime/floor/test1/testinfo.dat | 13 + .../palsuite/c_runtime/floorf/CMakeLists.txt | 1 + .../c_runtime/floorf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/floorf/test1/test1.c | 131 + .../c_runtime/floorf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/fma/CMakeLists.txt | 1 + .../c_runtime/fma/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/fma/test1/test1.cpp | 146 + .../palsuite/c_runtime/fma/test1/testinfo.dat | 17 + .../palsuite/c_runtime/fmaf/CMakeLists.txt | 1 + .../c_runtime/fmaf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/fmaf/test1/test1.c | 145 + .../c_runtime/fmaf/test1/testinfo.dat | 17 + .../palsuite/c_runtime/fmod/CMakeLists.txt | 1 + .../c_runtime/fmod/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/fmod/test1/test1.cpp | 157 + .../c_runtime/fmod/test1/testinfo.dat | 13 + .../palsuite/c_runtime/fmodf/CMakeLists.txt | 1 + .../c_runtime/fmodf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/fmodf/test1/test1.cpp | 156 + .../c_runtime/fmodf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/fopen/CMakeLists.txt | 8 + .../c_runtime/fopen/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/fopen/test1/test1.cpp | 82 + .../c_runtime/fopen/test1/testinfo.dat | 15 + .../c_runtime/fopen/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/fopen/test2/test2.cpp | 65 + .../c_runtime/fopen/test2/testinfo.dat | 15 + .../c_runtime/fopen/test3/CMakeLists.txt | 13 + .../palsuite/c_runtime/fopen/test3/test3.cpp | 66 + .../c_runtime/fopen/test3/testinfo.dat | 15 + .../c_runtime/fopen/test4/CMakeLists.txt | 13 + .../palsuite/c_runtime/fopen/test4/test4.cpp | 82 + .../c_runtime/fopen/test4/testinfo.dat | 15 + .../c_runtime/fopen/test5/CMakeLists.txt | 13 + .../palsuite/c_runtime/fopen/test5/test5.cpp | 78 + .../c_runtime/fopen/test5/testinfo.dat | 15 + .../c_runtime/fopen/test6/CMakeLists.txt | 13 + .../palsuite/c_runtime/fopen/test6/test6.cpp | 131 + .../c_runtime/fopen/test6/testinfo.dat | 15 + .../c_runtime/fopen/test7/CMakeLists.txt | 13 + .../palsuite/c_runtime/fopen/test7/test7.cpp | 117 + .../c_runtime/fopen/test7/testinfo.dat | 15 + .../palsuite/c_runtime/fprintf/CMakeLists.txt | 20 + .../palsuite/c_runtime/fprintf/fprintf.h | 177 + .../c_runtime/fprintf/test1/CMakeLists.txt | 13 + .../c_runtime/fprintf/test1/test1.cpp | 80 + .../c_runtime/fprintf/test1/testinfo.dat | 13 + .../c_runtime/fprintf/test10/CMakeLists.txt | 13 + .../c_runtime/fprintf/test10/test10.cpp | 49 + .../c_runtime/fprintf/test10/testinfo.dat | 13 + .../c_runtime/fprintf/test11/CMakeLists.txt | 13 + .../c_runtime/fprintf/test11/test11.cpp | 49 + .../c_runtime/fprintf/test11/testinfo.dat | 13 + .../c_runtime/fprintf/test12/CMakeLists.txt | 13 + .../c_runtime/fprintf/test12/test12.cpp | 50 + .../c_runtime/fprintf/test12/testinfo.dat | 13 + .../c_runtime/fprintf/test13/CMakeLists.txt | 13 + .../c_runtime/fprintf/test13/test13.cpp | 50 + .../c_runtime/fprintf/test13/testinfo.dat | 13 + .../c_runtime/fprintf/test14/CMakeLists.txt | 13 + .../c_runtime/fprintf/test14/test14.cpp | 49 + .../c_runtime/fprintf/test14/testinfo.dat | 14 + .../c_runtime/fprintf/test15/CMakeLists.txt | 13 + .../c_runtime/fprintf/test15/test15.cpp | 49 + .../c_runtime/fprintf/test15/testinfo.dat | 14 + .../c_runtime/fprintf/test16/CMakeLists.txt | 13 + .../c_runtime/fprintf/test16/test16.cpp | 48 + .../c_runtime/fprintf/test16/testinfo.dat | 13 + .../c_runtime/fprintf/test17/CMakeLists.txt | 13 + .../c_runtime/fprintf/test17/test17.cpp | 49 + .../c_runtime/fprintf/test17/testinfo.dat | 13 + .../c_runtime/fprintf/test18/CMakeLists.txt | 13 + .../c_runtime/fprintf/test18/test18.cpp | 49 + .../c_runtime/fprintf/test18/testinfo.dat | 13 + .../c_runtime/fprintf/test19/CMakeLists.txt | 13 + .../c_runtime/fprintf/test19/test19.cpp | 153 + .../c_runtime/fprintf/test19/testinfo.dat | 13 + .../c_runtime/fprintf/test2/CMakeLists.txt | 13 + .../c_runtime/fprintf/test2/test2.cpp | 49 + .../c_runtime/fprintf/test2/testinfo.dat | 13 + .../c_runtime/fprintf/test3/CMakeLists.txt | 13 + .../c_runtime/fprintf/test3/test3.cpp | 49 + .../c_runtime/fprintf/test3/testinfo.dat | 13 + .../c_runtime/fprintf/test4/CMakeLists.txt | 13 + .../c_runtime/fprintf/test4/test4.cpp | 110 + .../c_runtime/fprintf/test4/testinfo.dat | 13 + .../c_runtime/fprintf/test5/CMakeLists.txt | 13 + .../c_runtime/fprintf/test5/test5.cpp | 131 + .../c_runtime/fprintf/test5/testinfo.dat | 13 + .../c_runtime/fprintf/test6/CMakeLists.txt | 13 + .../c_runtime/fprintf/test6/test6.cpp | 46 + .../c_runtime/fprintf/test6/testinfo.dat | 13 + .../c_runtime/fprintf/test7/CMakeLists.txt | 13 + .../c_runtime/fprintf/test7/test7.cpp | 44 + .../c_runtime/fprintf/test7/testinfo.dat | 13 + .../c_runtime/fprintf/test8/CMakeLists.txt | 13 + .../c_runtime/fprintf/test8/test8.cpp | 49 + .../c_runtime/fprintf/test8/testinfo.dat | 13 + .../c_runtime/fprintf/test9/CMakeLists.txt | 13 + .../c_runtime/fprintf/test9/test9.cpp | 49 + .../c_runtime/fprintf/test9/testinfo.dat | 13 + .../palsuite/c_runtime/fputs/CMakeLists.txt | 3 + .../c_runtime/fputs/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/fputs/test1/test1.cpp | 100 + .../c_runtime/fputs/test1/testinfo.dat | 14 + .../c_runtime/fputs/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/fputs/test2/test2.cpp | 88 + .../c_runtime/fputs/test2/testinfo.dat | 13 + .../palsuite/c_runtime/fread/CMakeLists.txt | 4 + .../c_runtime/fread/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/fread/test1/test1.cpp | 135 + .../palsuite/c_runtime/fread/test1/testfile | 1 + .../c_runtime/fread/test1/testinfo.dat | 15 + .../c_runtime/fread/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/fread/test2/test2.cpp | 143 + .../palsuite/c_runtime/fread/test2/testfile | 1 + .../c_runtime/fread/test2/testinfo.dat | 16 + .../c_runtime/fread/test3/CMakeLists.txt | 13 + .../palsuite/c_runtime/fread/test3/test3.cpp | 131 + .../palsuite/c_runtime/fread/test3/testfile | 1 + .../c_runtime/fread/test3/testinfo.dat | 15 + .../palsuite/c_runtime/free/CMakeLists.txt | 2 + .../c_runtime/free/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/free/test1/test1.cpp | 62 + .../c_runtime/free/test1/testinfo.dat | 14 + .../palsuite/c_runtime/fseek/CMakeLists.txt | 2 + .../c_runtime/fseek/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/fseek/test1/test1.cpp | 193 + .../c_runtime/fseek/test1/testinfo.dat | 15 + .../palsuite/c_runtime/ftell/CMakeLists.txt | 2 + .../c_runtime/ftell/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/ftell/test1/ftell.cpp | 145 + .../c_runtime/ftell/test1/testfile.txt | 1 + .../c_runtime/ftell/test1/testinfo.dat | 16 + .../c_runtime/fwprintf/CMakeLists.txt | 20 + .../palsuite/c_runtime/fwprintf/fwprintf.h | 453 ++ .../c_runtime/fwprintf/test1/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test1/test1.cpp | 71 + .../c_runtime/fwprintf/test1/testinfo.dat | 13 + .../c_runtime/fwprintf/test10/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test10/test10.cpp | 51 + .../c_runtime/fwprintf/test10/testinfo.dat | 13 + .../c_runtime/fwprintf/test11/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test11/test11.cpp | 51 + .../c_runtime/fwprintf/test11/testinfo.dat | 13 + .../c_runtime/fwprintf/test12/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test12/test12.cpp | 52 + .../c_runtime/fwprintf/test12/testinfo.dat | 13 + .../c_runtime/fwprintf/test13/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test13/test13.cpp | 52 + .../c_runtime/fwprintf/test13/testinfo.dat | 13 + .../c_runtime/fwprintf/test14/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test14/test14.cpp | 66 + .../c_runtime/fwprintf/test14/testinfo.dat | 14 + .../c_runtime/fwprintf/test15/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test15/test15.cpp | 66 + .../c_runtime/fwprintf/test15/testinfo.dat | 14 + .../c_runtime/fwprintf/test16/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test16/test16.cpp | 65 + .../c_runtime/fwprintf/test16/testinfo.dat | 13 + .../c_runtime/fwprintf/test17/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test17/test17.cpp | 51 + .../c_runtime/fwprintf/test17/testinfo.dat | 13 + .../c_runtime/fwprintf/test18/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test18/test18.cpp | 51 + .../c_runtime/fwprintf/test18/testinfo.dat | 13 + .../c_runtime/fwprintf/test19/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test19/test19.cpp | 81 + .../c_runtime/fwprintf/test19/testinfo.dat | 13 + .../c_runtime/fwprintf/test2/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test2/test2.cpp | 51 + .../c_runtime/fwprintf/test2/testinfo.dat | 13 + .../c_runtime/fwprintf/test3/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test3/test3.cpp | 51 + .../c_runtime/fwprintf/test3/testinfo.dat | 13 + .../c_runtime/fwprintf/test4/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test4/test4.cpp | 85 + .../c_runtime/fwprintf/test4/testinfo.dat | 13 + .../c_runtime/fwprintf/test5/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test5/test5.cpp | 63 + .../c_runtime/fwprintf/test5/testinfo.dat | 13 + .../c_runtime/fwprintf/test6/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test6/test6.cpp | 48 + .../c_runtime/fwprintf/test6/testinfo.dat | 13 + .../c_runtime/fwprintf/test7/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test7/test7.cpp | 47 + .../c_runtime/fwprintf/test7/testinfo.dat | 13 + .../c_runtime/fwprintf/test8/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test8/test8.cpp | 51 + .../c_runtime/fwprintf/test8/testinfo.dat | 13 + .../c_runtime/fwprintf/test9/CMakeLists.txt | 13 + .../c_runtime/fwprintf/test9/test9.cpp | 51 + .../c_runtime/fwprintf/test9/testinfo.dat | 13 + .../palsuite/c_runtime/fwrite/CMakeLists.txt | 2 + .../c_runtime/fwrite/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/fwrite/test1/test1.cpp | 104 + .../c_runtime/fwrite/test1/testinfo.dat | 12 + .../palsuite/c_runtime/getenv/CMakeLists.txt | 4 + .../c_runtime/getenv/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/getenv/test1/test1.cpp | 78 + .../c_runtime/getenv/test1/testinfo.dat | 16 + .../c_runtime/getenv/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/getenv/test2/test2.cpp | 101 + .../c_runtime/getenv/test2/testinfo.dat | 14 + .../c_runtime/getenv/test3/CMakeLists.txt | 13 + .../palsuite/c_runtime/getenv/test3/test3.cpp | 75 + .../c_runtime/getenv/test3/testinfo.dat | 14 + .../palsuite/c_runtime/ilogb/CMakeLists.txt | 1 + .../c_runtime/ilogb/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/ilogb/test1/test1.cpp | 101 + .../c_runtime/ilogb/test1/testinfo.dat | 17 + .../palsuite/c_runtime/ilogbf/CMakeLists.txt | 1 + .../c_runtime/ilogbf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/ilogbf/test1/test1.cpp | 101 + .../c_runtime/ilogbf/test1/testinfo.dat | 17 + .../palsuite/c_runtime/isalnum/CMakeLists.txt | 2 + .../c_runtime/isalnum/test1/CMakeLists.txt | 13 + .../c_runtime/isalnum/test1/test1.cpp | 88 + .../c_runtime/isalnum/test1/testinfo.dat | 19 + .../palsuite/c_runtime/isalpha/CMakeLists.txt | 2 + .../c_runtime/isalpha/test1/CMakeLists.txt | 13 + .../c_runtime/isalpha/test1/test1.cpp | 86 + .../c_runtime/isalpha/test1/testinfo.dat | 19 + .../palsuite/c_runtime/isdigit/CMakeLists.txt | 2 + .../c_runtime/isdigit/test1/CMakeLists.txt | 13 + .../c_runtime/isdigit/test1/test1.cpp | 47 + .../c_runtime/isdigit/test1/testinfo.dat | 12 + .../palsuite/c_runtime/islower/CMakeLists.txt | 2 + .../c_runtime/islower/test1/CMakeLists.txt | 13 + .../c_runtime/islower/test1/test1.cpp | 85 + .../c_runtime/islower/test1/testinfo.dat | 19 + .../palsuite/c_runtime/isprint/CMakeLists.txt | 3 + .../c_runtime/isprint/test1/CMakeLists.txt | 13 + .../c_runtime/isprint/test1/isprint.cpp | 42 + .../c_runtime/isprint/test1/testinfo.dat | 12 + .../c_runtime/isprint/test2/CMakeLists.txt | 13 + .../c_runtime/isprint/test2/test2.cpp | 59 + .../c_runtime/isprint/test2/testinfo.dat | 13 + .../palsuite/c_runtime/isspace/CMakeLists.txt | 2 + .../c_runtime/isspace/test1/CMakeLists.txt | 13 + .../c_runtime/isspace/test1/test1.cpp | 82 + .../c_runtime/isspace/test1/testinfo.dat | 15 + .../palsuite/c_runtime/isupper/CMakeLists.txt | 2 + .../c_runtime/isupper/test1/CMakeLists.txt | 13 + .../c_runtime/isupper/test1/test1.cpp | 88 + .../c_runtime/isupper/test1/testinfo.dat | 19 + .../c_runtime/iswdigit/CMakeLists.txt | 2 + .../c_runtime/iswdigit/test1/CMakeLists.txt | 13 + .../c_runtime/iswdigit/test1/test1.cpp | 69 + .../c_runtime/iswdigit/test1/testinfo.dat | 19 + .../c_runtime/iswprint/CMakeLists.txt | 2 + .../c_runtime/iswprint/test1/CMakeLists.txt | 13 + .../c_runtime/iswprint/test1/test1.cpp | 59 + .../c_runtime/iswprint/test1/testinfo.dat | 13 + .../c_runtime/iswspace/CMakeLists.txt | 2 + .../c_runtime/iswspace/test1/CMakeLists.txt | 13 + .../c_runtime/iswspace/test1/test1.cpp | 78 + .../c_runtime/iswspace/test1/testinfo.dat | 12 + .../c_runtime/iswupper/CMakeLists.txt | 2 + .../c_runtime/iswupper/test1/CMakeLists.txt | 13 + .../c_runtime/iswupper/test1/test1.cpp | 91 + .../c_runtime/iswupper/test1/testinfo.dat | 19 + .../c_runtime/isxdigit/CMakeLists.txt | 2 + .../c_runtime/isxdigit/test1/CMakeLists.txt | 13 + .../c_runtime/isxdigit/test1/test1.cpp | 58 + .../c_runtime/isxdigit/test1/testinfo.dat | 15 + .../palsuite/c_runtime/llabs/CMakeLists.txt | 2 + .../c_runtime/llabs/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/llabs/test1/test1.cpp | 65 + .../c_runtime/llabs/test1/testinfo.dat | 14 + .../palsuite/c_runtime/log10/CMakeLists.txt | 1 + .../c_runtime/log10/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/log10/test1/test1.cpp | 146 + .../c_runtime/log10/test1/testinfo.dat | 17 + .../palsuite/c_runtime/log10f/CMakeLists.txt | 1 + .../c_runtime/log10f/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/log10f/test1/test1.c | 144 + .../c_runtime/log10f/test1/testinfo.dat | 17 + .../palsuite/c_runtime/log2/CMakeLists.txt | 1 + .../c_runtime/log2/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/log2/test1/test1.cpp | 139 + .../c_runtime/log2/test1/testinfo.dat | 17 + .../palsuite/c_runtime/log2f/CMakeLists.txt | 1 + .../c_runtime/log2f/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/log2f/test1/test1.c | 138 + .../c_runtime/log2f/test1/testinfo.dat | 17 + .../palsuite/c_runtime/logf/CMakeLists.txt | 1 + .../c_runtime/logf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/logf/test1/test1.c | 139 + .../c_runtime/logf/test1/testinfo.dat | 14 + .../palsuite/c_runtime/malloc/CMakeLists.txt | 3 + .../c_runtime/malloc/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/malloc/test1/test1.cpp | 52 + .../c_runtime/malloc/test1/testinfo.dat | 12 + .../c_runtime/malloc/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/malloc/test2/test2.cpp | 41 + .../c_runtime/malloc/test2/testinfo.dat | 12 + .../palsuite/c_runtime/memchr/CMakeLists.txt | 2 + .../c_runtime/memchr/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/memchr/test1/test1.cpp | 122 + .../c_runtime/memchr/test1/testinfo.dat | 19 + .../palsuite/c_runtime/memcmp/CMakeLists.txt | 2 + .../c_runtime/memcmp/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/memcmp/test1/test1.cpp | 57 + .../c_runtime/memcmp/test1/testinfo.dat | 13 + .../palsuite/c_runtime/memcpy/CMakeLists.txt | 2 + .../c_runtime/memcpy/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/memcpy/test1/test1.cpp | 87 + .../c_runtime/memcpy/test1/testinfo.dat | 12 + .../palsuite/c_runtime/memmove/CMakeLists.txt | 2 + .../c_runtime/memmove/test1/CMakeLists.txt | 13 + .../c_runtime/memmove/test1/test1.cpp | 116 + .../c_runtime/memmove/test1/testinfo.dat | 19 + .../palsuite/c_runtime/memset/CMakeLists.txt | 2 + .../c_runtime/memset/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/memset/test1/test1.cpp | 60 + .../c_runtime/memset/test1/testinfo.dat | 13 + .../palsuite/c_runtime/modf/CMakeLists.txt | 2 + .../c_runtime/modf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/modf/test1/test1.cpp | 136 + .../c_runtime/modf/test1/testinfo.dat | 16 + .../palsuite/c_runtime/modff/CMakeLists.txt | 2 + .../c_runtime/modff/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/modff/test1/test1.cpp | 135 + .../c_runtime/modff/test1/testinfo.dat | 13 + .../palsuite/c_runtime/pow/CMakeLists.txt | 1 + .../c_runtime/pow/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/pow/test1/test1.cpp | 230 + .../palsuite/c_runtime/pow/test1/testinfo.dat | 17 + .../palsuite/c_runtime/powf/CMakeLists.txt | 1 + .../c_runtime/powf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/powf/test1/test1.c | 229 + .../c_runtime/powf/test1/testinfo.dat | 17 + .../palsuite/c_runtime/printf/CMakeLists.txt | 20 + .../tests/palsuite/c_runtime/printf/printf.h | 182 + .../c_runtime/printf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/printf/test1/test1.cpp | 43 + .../c_runtime/printf/test1/testinfo.dat | 12 + .../c_runtime/printf/test10/CMakeLists.txt | 13 + .../c_runtime/printf/test10/test10.cpp | 52 + .../c_runtime/printf/test10/testinfo.dat | 12 + .../c_runtime/printf/test11/CMakeLists.txt | 13 + .../c_runtime/printf/test11/test11.cpp | 51 + .../c_runtime/printf/test11/testinfo.dat | 12 + .../c_runtime/printf/test12/CMakeLists.txt | 13 + .../c_runtime/printf/test12/test12.cpp | 53 + .../c_runtime/printf/test12/testinfo.dat | 12 + .../c_runtime/printf/test13/CMakeLists.txt | 13 + .../c_runtime/printf/test13/test13.cpp | 54 + .../c_runtime/printf/test13/testinfo.dat | 12 + .../c_runtime/printf/test14/CMakeLists.txt | 13 + .../c_runtime/printf/test14/test14.cpp | 54 + .../c_runtime/printf/test14/testinfo.dat | 12 + .../c_runtime/printf/test15/CMakeLists.txt | 13 + .../c_runtime/printf/test15/test15.cpp | 54 + .../c_runtime/printf/test15/testinfo.dat | 12 + .../c_runtime/printf/test16/CMakeLists.txt | 13 + .../c_runtime/printf/test16/test16.cpp | 50 + .../c_runtime/printf/test16/testinfo.dat | 12 + .../c_runtime/printf/test17/CMakeLists.txt | 13 + .../c_runtime/printf/test17/test17.cpp | 52 + .../c_runtime/printf/test17/testinfo.dat | 12 + .../c_runtime/printf/test18/CMakeLists.txt | 13 + .../c_runtime/printf/test18/test18.cpp | 51 + .../c_runtime/printf/test18/testinfo.dat | 12 + .../c_runtime/printf/test19/CMakeLists.txt | 13 + .../c_runtime/printf/test19/test19.cpp | 76 + .../c_runtime/printf/test19/testinfo.dat | 12 + .../c_runtime/printf/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/printf/test2/test2.cpp | 51 + .../c_runtime/printf/test2/testinfo.dat | 12 + .../c_runtime/printf/test3/CMakeLists.txt | 13 + .../palsuite/c_runtime/printf/test3/test3.cpp | 51 + .../c_runtime/printf/test3/testinfo.dat | 12 + .../c_runtime/printf/test4/CMakeLists.txt | 13 + .../palsuite/c_runtime/printf/test4/test4.cpp | 66 + .../c_runtime/printf/test4/testinfo.dat | 12 + .../c_runtime/printf/test5/CMakeLists.txt | 13 + .../palsuite/c_runtime/printf/test5/test5.cpp | 60 + .../c_runtime/printf/test5/testinfo.dat | 12 + .../c_runtime/printf/test6/CMakeLists.txt | 13 + .../palsuite/c_runtime/printf/test6/test6.cpp | 48 + .../c_runtime/printf/test6/testinfo.dat | 12 + .../c_runtime/printf/test7/CMakeLists.txt | 13 + .../palsuite/c_runtime/printf/test7/test7.cpp | 47 + .../c_runtime/printf/test7/testinfo.dat | 12 + .../c_runtime/printf/test8/CMakeLists.txt | 13 + .../palsuite/c_runtime/printf/test8/test8.cpp | 53 + .../c_runtime/printf/test8/testinfo.dat | 12 + .../c_runtime/printf/test9/CMakeLists.txt | 13 + .../palsuite/c_runtime/printf/test9/test9.cpp | 53 + .../c_runtime/printf/test9/testinfo.dat | 12 + .../palsuite/c_runtime/qsort/CMakeLists.txt | 3 + .../c_runtime/qsort/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/qsort/test1/test1.cpp | 48 + .../c_runtime/qsort/test1/testinfo.dat | 12 + .../c_runtime/qsort/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/qsort/test2/test2.cpp | 49 + .../c_runtime/qsort/test2/testinfo.dat | 12 + .../c_runtime/rand_srand/CMakeLists.txt | 2 + .../c_runtime/rand_srand/test1/CMakeLists.txt | 13 + .../c_runtime/rand_srand/test1/test1.cpp | 100 + .../c_runtime/rand_srand/test1/testinfo.dat | 16 + .../palsuite/c_runtime/realloc/CMakeLists.txt | 2 + .../c_runtime/realloc/test1/CMakeLists.txt | 13 + .../c_runtime/realloc/test1/test1.cpp | 66 + .../c_runtime/realloc/test1/testinfo.dat | 14 + .../palsuite/c_runtime/scalbn/CMakeLists.txt | 1 + .../c_runtime/scalbn/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/scalbn/test1/test1.cpp | 140 + .../c_runtime/scalbn/test1/testinfo.dat | 17 + .../palsuite/c_runtime/scalbnf/CMakeLists.txt | 1 + .../c_runtime/scalbnf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/scalbnf/test1/test1.c | 139 + .../c_runtime/scalbnf/test1/testinfo.dat | 17 + .../palsuite/c_runtime/sin/CMakeLists.txt | 1 + .../c_runtime/sin/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/sin/test1/test1.cpp | 131 + .../palsuite/c_runtime/sin/test1/testinfo.dat | 13 + .../palsuite/c_runtime/sinf/CMakeLists.txt | 1 + .../c_runtime/sinf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/sinf/test1/test1.c | 130 + .../c_runtime/sinf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/sinh/CMakeLists.txt | 1 + .../c_runtime/sinh/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/sinh/test1/test1.cpp | 130 + .../c_runtime/sinh/test1/testinfo.dat | 13 + .../palsuite/c_runtime/sinhf/CMakeLists.txt | 1 + .../c_runtime/sinhf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/sinhf/test1/test1.c | 129 + .../c_runtime/sinhf/test1/testinfo.dat | 13 + .../c_runtime/sprintf_s/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/sprintf_s.h | 195 + .../c_runtime/sprintf_s/test1/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test1/test1.cpp | 45 + .../c_runtime/sprintf_s/test1/testinfo.dat | 12 + .../c_runtime/sprintf_s/test10/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test10/test10.cpp | 55 + .../c_runtime/sprintf_s/test10/testinfo.dat | 12 + .../c_runtime/sprintf_s/test11/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test11/test11.cpp | 55 + .../c_runtime/sprintf_s/test11/testinfo.dat | 12 + .../c_runtime/sprintf_s/test12/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test12/test12.cpp | 56 + .../c_runtime/sprintf_s/test12/testinfo.dat | 12 + .../c_runtime/sprintf_s/test13/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test13/test13.cpp | 56 + .../c_runtime/sprintf_s/test13/testinfo.dat | 12 + .../c_runtime/sprintf_s/test14/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test14/test14.cpp | 53 + .../c_runtime/sprintf_s/test14/testinfo.dat | 12 + .../c_runtime/sprintf_s/test15/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test15/test15.cpp | 53 + .../c_runtime/sprintf_s/test15/testinfo.dat | 12 + .../c_runtime/sprintf_s/test16/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test16/test16.cpp | 52 + .../c_runtime/sprintf_s/test16/testinfo.dat | 12 + .../c_runtime/sprintf_s/test17/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test17/test17.cpp | 54 + .../c_runtime/sprintf_s/test17/testinfo.dat | 12 + .../c_runtime/sprintf_s/test18/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test18/test18.cpp | 53 + .../c_runtime/sprintf_s/test18/testinfo.dat | 12 + .../c_runtime/sprintf_s/test19/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test19/test19.cpp | 71 + .../c_runtime/sprintf_s/test19/testinfo.dat | 12 + .../c_runtime/sprintf_s/test2/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test2/test2.cpp | 53 + .../c_runtime/sprintf_s/test2/testinfo.dat | 12 + .../c_runtime/sprintf_s/test3/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test3/test3.cpp | 53 + .../c_runtime/sprintf_s/test3/testinfo.dat | 12 + .../c_runtime/sprintf_s/test4/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test4/test4.cpp | 69 + .../c_runtime/sprintf_s/test4/testinfo.dat | 12 + .../c_runtime/sprintf_s/test6/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test6/test6.cpp | 50 + .../c_runtime/sprintf_s/test6/testinfo.dat | 12 + .../c_runtime/sprintf_s/test7/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test7/test7.cpp | 49 + .../c_runtime/sprintf_s/test7/testinfo.dat | 12 + .../c_runtime/sprintf_s/test8/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test8/test8.cpp | 55 + .../c_runtime/sprintf_s/test8/testinfo.dat | 12 + .../c_runtime/sprintf_s/test9/CMakeLists.txt | 13 + .../c_runtime/sprintf_s/test9/test9.cpp | 55 + .../c_runtime/sprintf_s/test9/testinfo.dat | 12 + .../palsuite/c_runtime/sqrt/CMakeLists.txt | 2 + .../c_runtime/sqrt/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/sqrt/test1/test1.cpp | 123 + .../c_runtime/sqrt/test1/testinfo.dat | 17 + .../palsuite/c_runtime/sqrtf/CMakeLists.txt | 2 + .../c_runtime/sqrtf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/sqrtf/test1/test1.c | 122 + .../c_runtime/sqrtf/test1/testinfo.dat | 17 + .../c_runtime/sscanf_s/CMakeLists.txt | 18 + .../palsuite/c_runtime/sscanf_s/sscanf_s.h | 246 + .../c_runtime/sscanf_s/test1/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test1/test1.cpp | 53 + .../c_runtime/sscanf_s/test1/testinfo.dat | 12 + .../c_runtime/sscanf_s/test10/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test10/test10.cpp | 37 + .../c_runtime/sscanf_s/test10/testinfo.dat | 12 + .../c_runtime/sscanf_s/test11/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test11/test11.cpp | 36 + .../c_runtime/sscanf_s/test11/testinfo.dat | 12 + .../c_runtime/sscanf_s/test12/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test12/test12.cpp | 35 + .../c_runtime/sscanf_s/test12/testinfo.dat | 12 + .../c_runtime/sscanf_s/test13/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test13/test13.cpp | 37 + .../c_runtime/sscanf_s/test13/testinfo.dat | 12 + .../c_runtime/sscanf_s/test14/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test14/test14.cpp | 36 + .../c_runtime/sscanf_s/test14/testinfo.dat | 12 + .../c_runtime/sscanf_s/test15/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test15/test15.cpp | 36 + .../c_runtime/sscanf_s/test15/testinfo.dat | 12 + .../c_runtime/sscanf_s/test16/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test16/test16.cpp | 37 + .../c_runtime/sscanf_s/test16/testinfo.dat | 12 + .../c_runtime/sscanf_s/test17/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test17/test17.cpp | 37 + .../c_runtime/sscanf_s/test17/testinfo.dat | 12 + .../c_runtime/sscanf_s/test2/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test2/test2.cpp | 44 + .../c_runtime/sscanf_s/test2/testinfo.dat | 12 + .../c_runtime/sscanf_s/test3/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test3/test3.cpp | 35 + .../c_runtime/sscanf_s/test3/testinfo.dat | 12 + .../c_runtime/sscanf_s/test4/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test4/test4.cpp | 44 + .../c_runtime/sscanf_s/test4/testinfo.dat | 12 + .../c_runtime/sscanf_s/test5/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test5/test5.cpp | 43 + .../c_runtime/sscanf_s/test5/testinfo.dat | 12 + .../c_runtime/sscanf_s/test6/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test6/test6.cpp | 43 + .../c_runtime/sscanf_s/test6/testinfo.dat | 12 + .../c_runtime/sscanf_s/test7/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test7/test7.cpp | 43 + .../c_runtime/sscanf_s/test7/testinfo.dat | 12 + .../c_runtime/sscanf_s/test8/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test8/test8.cpp | 43 + .../c_runtime/sscanf_s/test8/testinfo.dat | 12 + .../c_runtime/sscanf_s/test9/CMakeLists.txt | 13 + .../c_runtime/sscanf_s/test9/test9.cpp | 38 + .../c_runtime/sscanf_s/test9/testinfo.dat | 12 + .../palsuite/c_runtime/strcat/CMakeLists.txt | 2 + .../c_runtime/strcat/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/strcat/test1/test1.cpp | 66 + .../c_runtime/strcat/test1/testinfo.dat | 15 + .../palsuite/c_runtime/strchr/CMakeLists.txt | 2 + .../c_runtime/strchr/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/strchr/test1/test1.cpp | 86 + .../c_runtime/strchr/test1/testinfo.dat | 15 + .../palsuite/c_runtime/strcmp/CMakeLists.txt | 2 + .../c_runtime/strcmp/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/strcmp/test1/test1.cpp | 73 + .../c_runtime/strcmp/test1/testinfo.dat | 13 + .../palsuite/c_runtime/strcpy/CMakeLists.txt | 2 + .../c_runtime/strcpy/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/strcpy/test1/test1.cpp | 51 + .../c_runtime/strcpy/test1/testinfo.dat | 14 + .../palsuite/c_runtime/strcspn/CMakeLists.txt | 2 + .../c_runtime/strcspn/test1/CMakeLists.txt | 13 + .../c_runtime/strcspn/test1/test1.cpp | 59 + .../c_runtime/strcspn/test1/testinfo.dat | 15 + .../palsuite/c_runtime/strlen/CMakeLists.txt | 2 + .../c_runtime/strlen/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/strlen/test1/test1.cpp | 33 + .../c_runtime/strlen/test1/testinfo.dat | 13 + .../palsuite/c_runtime/strncat/CMakeLists.txt | 2 + .../c_runtime/strncat/test1/CMakeLists.txt | 13 + .../c_runtime/strncat/test1/test1.cpp | 77 + .../c_runtime/strncat/test1/testinfo.dat | 14 + .../palsuite/c_runtime/strncmp/CMakeLists.txt | 2 + .../c_runtime/strncmp/test1/CMakeLists.txt | 13 + .../c_runtime/strncmp/test1/test1.cpp | 80 + .../c_runtime/strncmp/test1/testinfo.dat | 14 + .../palsuite/c_runtime/strncpy/CMakeLists.txt | 2 + .../c_runtime/strncpy/test1/CMakeLists.txt | 13 + .../c_runtime/strncpy/test1/test1.cpp | 85 + .../c_runtime/strncpy/test1/testinfo.dat | 15 + .../palsuite/c_runtime/strpbrk/CMakeLists.txt | 2 + .../c_runtime/strpbrk/test1/CMakeLists.txt | 13 + .../c_runtime/strpbrk/test1/test1.cpp | 85 + .../c_runtime/strpbrk/test1/testinfo.dat | 14 + .../palsuite/c_runtime/strrchr/CMakeLists.txt | 2 + .../c_runtime/strrchr/test1/CMakeLists.txt | 13 + .../c_runtime/strrchr/test1/test1.cpp | 55 + .../c_runtime/strrchr/test1/testinfo.dat | 16 + .../palsuite/c_runtime/strspn/CMakeLists.txt | 2 + .../c_runtime/strspn/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/strspn/test1/test1.cpp | 60 + .../c_runtime/strspn/test1/testinfo.dat | 15 + .../palsuite/c_runtime/strstr/CMakeLists.txt | 2 + .../c_runtime/strstr/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/strstr/test1/test1.cpp | 83 + .../c_runtime/strstr/test1/testinfo.dat | 16 + .../palsuite/c_runtime/strtod/CMakeLists.txt | 3 + .../c_runtime/strtod/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/strtod/test1/test1.cpp | 93 + .../c_runtime/strtod/test1/testinfo.dat | 17 + .../c_runtime/strtod/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/strtod/test2/test2.cpp | 65 + .../c_runtime/strtod/test2/testinfo.dat | 16 + .../palsuite/c_runtime/strtok/CMakeLists.txt | 2 + .../c_runtime/strtok/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/strtok/test1/test1.cpp | 78 + .../c_runtime/strtok/test1/testinfo.dat | 14 + .../palsuite/c_runtime/strtoul/CMakeLists.txt | 2 + .../c_runtime/strtoul/test1/CMakeLists.txt | 13 + .../c_runtime/strtoul/test1/test1.cpp | 73 + .../c_runtime/strtoul/test1/testinfo.dat | 13 + .../c_runtime/swprintf/CMakeLists.txt | 19 + .../palsuite/c_runtime/swprintf/swprintf.h | 162 + .../c_runtime/swprintf/test1/CMakeLists.txt | 13 + .../c_runtime/swprintf/test1/test1.cpp | 44 + .../c_runtime/swprintf/test1/testinfo.dat | 12 + .../c_runtime/swprintf/test10/CMakeLists.txt | 13 + .../c_runtime/swprintf/test10/test10.cpp | 55 + .../c_runtime/swprintf/test10/testinfo.dat | 12 + .../c_runtime/swprintf/test11/CMakeLists.txt | 13 + .../c_runtime/swprintf/test11/test11.cpp | 55 + .../c_runtime/swprintf/test11/testinfo.dat | 12 + .../c_runtime/swprintf/test12/CMakeLists.txt | 13 + .../c_runtime/swprintf/test12/test12.cpp | 56 + .../c_runtime/swprintf/test12/testinfo.dat | 12 + .../c_runtime/swprintf/test13/CMakeLists.txt | 13 + .../c_runtime/swprintf/test13/test13.cpp | 55 + .../c_runtime/swprintf/test13/testinfo.dat | 12 + .../c_runtime/swprintf/test14/CMakeLists.txt | 13 + .../c_runtime/swprintf/test14/test14.cpp | 67 + .../c_runtime/swprintf/test14/testinfo.dat | 12 + .../c_runtime/swprintf/test15/CMakeLists.txt | 13 + .../c_runtime/swprintf/test15/test15.cpp | 67 + .../c_runtime/swprintf/test15/testinfo.dat | 12 + .../c_runtime/swprintf/test16/CMakeLists.txt | 13 + .../c_runtime/swprintf/test16/test16.cpp | 67 + .../c_runtime/swprintf/test16/testinfo.dat | 12 + .../c_runtime/swprintf/test17/CMakeLists.txt | 13 + .../c_runtime/swprintf/test17/test17.cpp | 69 + .../c_runtime/swprintf/test17/testinfo.dat | 12 + .../c_runtime/swprintf/test18/CMakeLists.txt | 13 + .../c_runtime/swprintf/test18/test18.cpp | 69 + .../c_runtime/swprintf/test18/testinfo.dat | 12 + .../c_runtime/swprintf/test19/CMakeLists.txt | 13 + .../c_runtime/swprintf/test19/test19.cpp | 101 + .../c_runtime/swprintf/test19/testinfo.dat | 12 + .../c_runtime/swprintf/test2/CMakeLists.txt | 13 + .../c_runtime/swprintf/test2/test2.cpp | 52 + .../c_runtime/swprintf/test2/testinfo.dat | 12 + .../c_runtime/swprintf/test3/CMakeLists.txt | 13 + .../c_runtime/swprintf/test3/test3.cpp | 49 + .../c_runtime/swprintf/test3/testinfo.dat | 12 + .../c_runtime/swprintf/test4/CMakeLists.txt | 13 + .../c_runtime/swprintf/test4/test4.cpp | 71 + .../c_runtime/swprintf/test4/testinfo.dat | 12 + .../c_runtime/swprintf/test6/CMakeLists.txt | 13 + .../c_runtime/swprintf/test6/test6.cpp | 47 + .../c_runtime/swprintf/test6/testinfo.dat | 12 + .../c_runtime/swprintf/test7/CMakeLists.txt | 13 + .../c_runtime/swprintf/test7/test7.cpp | 48 + .../c_runtime/swprintf/test7/testinfo.dat | 12 + .../c_runtime/swprintf/test8/CMakeLists.txt | 13 + .../c_runtime/swprintf/test8/test8.cpp | 55 + .../c_runtime/swprintf/test8/testinfo.dat | 12 + .../c_runtime/swprintf/test9/CMakeLists.txt | 13 + .../c_runtime/swprintf/test9/test9.cpp | 55 + .../c_runtime/swprintf/test9/testinfo.dat | 12 + .../palsuite/c_runtime/swscanf/CMakeLists.txt | 18 + .../palsuite/c_runtime/swscanf/swscanf.h | 262 + .../c_runtime/swscanf/test1/CMakeLists.txt | 13 + .../c_runtime/swscanf/test1/test1.cpp | 53 + .../c_runtime/swscanf/test1/testinfo.dat | 12 + .../c_runtime/swscanf/test10/CMakeLists.txt | 13 + .../c_runtime/swscanf/test10/test10.cpp | 36 + .../c_runtime/swscanf/test10/testinfo.dat | 12 + .../c_runtime/swscanf/test11/CMakeLists.txt | 13 + .../c_runtime/swscanf/test11/test11.cpp | 35 + .../c_runtime/swscanf/test11/testinfo.dat | 12 + .../c_runtime/swscanf/test12/CMakeLists.txt | 13 + .../c_runtime/swscanf/test12/test12.cpp | 35 + .../c_runtime/swscanf/test12/testinfo.dat | 12 + .../c_runtime/swscanf/test13/CMakeLists.txt | 13 + .../c_runtime/swscanf/test13/test13.cpp | 37 + .../c_runtime/swscanf/test13/testinfo.dat | 12 + .../c_runtime/swscanf/test14/CMakeLists.txt | 13 + .../c_runtime/swscanf/test14/test14.cpp | 38 + .../c_runtime/swscanf/test14/testinfo.dat | 12 + .../c_runtime/swscanf/test15/CMakeLists.txt | 13 + .../c_runtime/swscanf/test15/test15.cpp | 37 + .../c_runtime/swscanf/test15/testinfo.dat | 12 + .../c_runtime/swscanf/test16/CMakeLists.txt | 13 + .../c_runtime/swscanf/test16/test16.cpp | 37 + .../c_runtime/swscanf/test16/testinfo.dat | 12 + .../c_runtime/swscanf/test17/CMakeLists.txt | 13 + .../c_runtime/swscanf/test17/test17.cpp | 37 + .../c_runtime/swscanf/test17/testinfo.dat | 12 + .../c_runtime/swscanf/test2/CMakeLists.txt | 13 + .../c_runtime/swscanf/test2/test2.cpp | 43 + .../c_runtime/swscanf/test2/testinfo.dat | 12 + .../c_runtime/swscanf/test3/CMakeLists.txt | 13 + .../c_runtime/swscanf/test3/test3.cpp | 36 + .../c_runtime/swscanf/test3/testinfo.dat | 12 + .../c_runtime/swscanf/test4/CMakeLists.txt | 13 + .../c_runtime/swscanf/test4/test4.cpp | 44 + .../c_runtime/swscanf/test4/testinfo.dat | 12 + .../c_runtime/swscanf/test5/CMakeLists.txt | 13 + .../c_runtime/swscanf/test5/test5.cpp | 44 + .../c_runtime/swscanf/test5/testinfo.dat | 12 + .../c_runtime/swscanf/test6/CMakeLists.txt | 13 + .../c_runtime/swscanf/test6/test6.cpp | 44 + .../c_runtime/swscanf/test6/testinfo.dat | 12 + .../c_runtime/swscanf/test7/CMakeLists.txt | 13 + .../c_runtime/swscanf/test7/test7.cpp | 44 + .../c_runtime/swscanf/test7/testinfo.dat | 12 + .../c_runtime/swscanf/test8/CMakeLists.txt | 13 + .../c_runtime/swscanf/test8/test8.cpp | 44 + .../c_runtime/swscanf/test8/testinfo.dat | 12 + .../c_runtime/swscanf/test9/CMakeLists.txt | 13 + .../c_runtime/swscanf/test9/test9.cpp | 37 + .../c_runtime/swscanf/test9/testinfo.dat | 12 + .../palsuite/c_runtime/tan/CMakeLists.txt | 1 + .../c_runtime/tan/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/tan/test1/test1.cpp | 137 + .../palsuite/c_runtime/tan/test1/testinfo.dat | 13 + .../palsuite/c_runtime/tanf/CMakeLists.txt | 1 + .../c_runtime/tanf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/tanf/test1/test1.c | 136 + .../c_runtime/tanf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/tanh/CMakeLists.txt | 1 + .../c_runtime/tanh/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/tanh/test1/test1.cpp | 130 + .../c_runtime/tanh/test1/testinfo.dat | 13 + .../palsuite/c_runtime/tanhf/CMakeLists.txt | 1 + .../c_runtime/tanhf/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/tanhf/test1/test1.c | 129 + .../c_runtime/tanhf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/time/CMakeLists.txt | 2 + .../c_runtime/time/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/time/test1/test1.cpp | 51 + .../c_runtime/time/test1/testinfo.dat | 14 + .../palsuite/c_runtime/tolower/CMakeLists.txt | 2 + .../c_runtime/tolower/test1/CMakeLists.txt | 13 + .../c_runtime/tolower/test1/test1.cpp | 79 + .../c_runtime/tolower/test1/testinfo.dat | 19 + .../palsuite/c_runtime/toupper/CMakeLists.txt | 2 + .../c_runtime/toupper/test1/CMakeLists.txt | 13 + .../c_runtime/toupper/test1/test1.cpp | 64 + .../c_runtime/toupper/test1/testinfo.dat | 19 + .../c_runtime/towlower/CMakeLists.txt | 2 + .../c_runtime/towlower/test1/CMakeLists.txt | 13 + .../c_runtime/towlower/test1/test1.cpp | 79 + .../c_runtime/towlower/test1/testinfo.dat | 19 + .../c_runtime/towupper/CMakeLists.txt | 2 + .../c_runtime/towupper/test1/CMakeLists.txt | 13 + .../c_runtime/towupper/test1/test1.cpp | 65 + .../c_runtime/towupper/test1/testinfo.dat | 19 + .../c_runtime/vfprintf/CMakeLists.txt | 20 + .../c_runtime/vfprintf/test1/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test1/test1.cpp | 68 + .../c_runtime/vfprintf/test1/testinfo.dat | 12 + .../c_runtime/vfprintf/test10/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test10/test10.cpp | 52 + .../c_runtime/vfprintf/test10/testinfo.dat | 12 + .../c_runtime/vfprintf/test11/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test11/test11.cpp | 51 + .../c_runtime/vfprintf/test11/testinfo.dat | 12 + .../c_runtime/vfprintf/test12/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test12/test12.cpp | 53 + .../c_runtime/vfprintf/test12/testinfo.dat | 12 + .../c_runtime/vfprintf/test13/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test13/test13.cpp | 54 + .../c_runtime/vfprintf/test13/testinfo.dat | 12 + .../c_runtime/vfprintf/test14/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test14/test14.cpp | 54 + .../c_runtime/vfprintf/test14/testinfo.dat | 12 + .../c_runtime/vfprintf/test15/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test15/test15.cpp | 54 + .../c_runtime/vfprintf/test15/testinfo.dat | 12 + .../c_runtime/vfprintf/test16/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test16/test16.cpp | 50 + .../c_runtime/vfprintf/test16/testinfo.dat | 12 + .../c_runtime/vfprintf/test17/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test17/test17.cpp | 52 + .../c_runtime/vfprintf/test17/testinfo.dat | 12 + .../c_runtime/vfprintf/test18/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test18/test18.cpp | 51 + .../c_runtime/vfprintf/test18/testinfo.dat | 12 + .../c_runtime/vfprintf/test19/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test19/test19.cpp | 76 + .../c_runtime/vfprintf/test19/testinfo.dat | 12 + .../c_runtime/vfprintf/test2/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test2/test2.cpp | 51 + .../c_runtime/vfprintf/test2/testinfo.dat | 12 + .../c_runtime/vfprintf/test3/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test3/test3.cpp | 51 + .../c_runtime/vfprintf/test3/testinfo.dat | 12 + .../c_runtime/vfprintf/test4/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test4/test4.cpp | 70 + .../c_runtime/vfprintf/test4/testinfo.dat | 12 + .../c_runtime/vfprintf/test5/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test5/test5.cpp | 60 + .../c_runtime/vfprintf/test5/testinfo.dat | 12 + .../c_runtime/vfprintf/test6/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test6/test6.cpp | 48 + .../c_runtime/vfprintf/test6/testinfo.dat | 12 + .../c_runtime/vfprintf/test7/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test7/test7.cpp | 47 + .../c_runtime/vfprintf/test7/testinfo.dat | 12 + .../c_runtime/vfprintf/test8/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test8/test8.cpp | 53 + .../c_runtime/vfprintf/test8/testinfo.dat | 12 + .../c_runtime/vfprintf/test9/CMakeLists.txt | 13 + .../c_runtime/vfprintf/test9/test9.cpp | 53 + .../c_runtime/vfprintf/test9/testinfo.dat | 12 + .../palsuite/c_runtime/vfprintf/vfprintf.h | 463 ++ .../palsuite/c_runtime/vprintf/CMakeLists.txt | 21 + .../c_runtime/vprintf/test1/CMakeLists.txt | 13 + .../c_runtime/vprintf/test1/test1.cpp | 43 + .../c_runtime/vprintf/test1/testinfo.dat | 12 + .../c_runtime/vprintf/test10/CMakeLists.txt | 13 + .../c_runtime/vprintf/test10/test10.cpp | 52 + .../c_runtime/vprintf/test10/testinfo.dat | 12 + .../c_runtime/vprintf/test11/CMakeLists.txt | 13 + .../c_runtime/vprintf/test11/test11.cpp | 51 + .../c_runtime/vprintf/test11/testinfo.dat | 12 + .../c_runtime/vprintf/test12/CMakeLists.txt | 13 + .../c_runtime/vprintf/test12/test12.cpp | 53 + .../c_runtime/vprintf/test12/testinfo.dat | 12 + .../c_runtime/vprintf/test13/CMakeLists.txt | 13 + .../c_runtime/vprintf/test13/test13.cpp | 54 + .../c_runtime/vprintf/test13/testinfo.dat | 12 + .../c_runtime/vprintf/test14/CMakeLists.txt | 13 + .../c_runtime/vprintf/test14/test14.cpp | 54 + .../c_runtime/vprintf/test14/testinfo.dat | 12 + .../c_runtime/vprintf/test15/CMakeLists.txt | 13 + .../c_runtime/vprintf/test15/test15.cpp | 54 + .../c_runtime/vprintf/test15/testinfo.dat | 12 + .../c_runtime/vprintf/test16/CMakeLists.txt | 13 + .../c_runtime/vprintf/test16/test16.cpp | 50 + .../c_runtime/vprintf/test16/testinfo.dat | 12 + .../c_runtime/vprintf/test17/CMakeLists.txt | 13 + .../c_runtime/vprintf/test17/test17.cpp | 52 + .../c_runtime/vprintf/test17/testinfo.dat | 12 + .../c_runtime/vprintf/test18/CMakeLists.txt | 13 + .../c_runtime/vprintf/test18/test18.cpp | 51 + .../c_runtime/vprintf/test18/testinfo.dat | 12 + .../c_runtime/vprintf/test19/CMakeLists.txt | 13 + .../c_runtime/vprintf/test19/test19.cpp | 76 + .../c_runtime/vprintf/test19/testinfo.dat | 12 + .../c_runtime/vprintf/test2/CMakeLists.txt | 13 + .../c_runtime/vprintf/test2/test2.cpp | 51 + .../c_runtime/vprintf/test2/testinfo.dat | 12 + .../c_runtime/vprintf/test3/CMakeLists.txt | 13 + .../c_runtime/vprintf/test3/test3.cpp | 51 + .../c_runtime/vprintf/test3/testinfo.dat | 12 + .../c_runtime/vprintf/test4/CMakeLists.txt | 13 + .../c_runtime/vprintf/test4/test4.cpp | 70 + .../c_runtime/vprintf/test4/testinfo.dat | 12 + .../c_runtime/vprintf/test5/CMakeLists.txt | 13 + .../c_runtime/vprintf/test5/test5.cpp | 60 + .../c_runtime/vprintf/test5/testinfo.dat | 12 + .../c_runtime/vprintf/test6/CMakeLists.txt | 13 + .../c_runtime/vprintf/test6/test6.cpp | 48 + .../c_runtime/vprintf/test6/testinfo.dat | 12 + .../c_runtime/vprintf/test7/CMakeLists.txt | 13 + .../c_runtime/vprintf/test7/test7.cpp | 47 + .../c_runtime/vprintf/test7/testinfo.dat | 12 + .../c_runtime/vprintf/test8/CMakeLists.txt | 13 + .../c_runtime/vprintf/test8/test8.cpp | 53 + .../c_runtime/vprintf/test8/testinfo.dat | 12 + .../c_runtime/vprintf/test9/CMakeLists.txt | 13 + .../c_runtime/vprintf/test9/test9.cpp | 53 + .../c_runtime/vprintf/test9/testinfo.dat | 12 + .../palsuite/c_runtime/vprintf/vprintf.h | 193 + .../c_runtime/vsprintf/CMakeLists.txt | 19 + .../c_runtime/vsprintf/test1/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test1/test1.cpp | 55 + .../c_runtime/vsprintf/test1/testinfo.dat | 13 + .../c_runtime/vsprintf/test10/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test10/test10.cpp | 50 + .../c_runtime/vsprintf/test10/testinfo.dat | 14 + .../c_runtime/vsprintf/test11/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test11/test11.cpp | 50 + .../c_runtime/vsprintf/test11/testinfo.dat | 14 + .../c_runtime/vsprintf/test12/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test12/test12.cpp | 52 + .../c_runtime/vsprintf/test12/testinfo.dat | 14 + .../c_runtime/vsprintf/test13/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test13/test13.cpp | 52 + .../c_runtime/vsprintf/test13/testinfo.dat | 14 + .../c_runtime/vsprintf/test14/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test14/test14.cpp | 50 + .../c_runtime/vsprintf/test14/testinfo.dat | 14 + .../c_runtime/vsprintf/test15/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test15/test15.cpp | 64 + .../c_runtime/vsprintf/test15/testinfo.dat | 14 + .../c_runtime/vsprintf/test16/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test16/test16.cpp | 49 + .../c_runtime/vsprintf/test16/testinfo.dat | 14 + .../c_runtime/vsprintf/test17/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test17/test17.cpp | 50 + .../c_runtime/vsprintf/test17/testinfo.dat | 14 + .../c_runtime/vsprintf/test18/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test18/test18.cpp | 50 + .../c_runtime/vsprintf/test18/testinfo.dat | 14 + .../c_runtime/vsprintf/test19/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test19/test19.cpp | 67 + .../c_runtime/vsprintf/test19/testinfo.dat | 14 + .../c_runtime/vsprintf/test2/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test2/test2.cpp | 48 + .../c_runtime/vsprintf/test2/testinfo.dat | 14 + .../c_runtime/vsprintf/test3/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test3/test3.cpp | 49 + .../c_runtime/vsprintf/test3/testinfo.dat | 14 + .../c_runtime/vsprintf/test4/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test4/test4.cpp | 72 + .../c_runtime/vsprintf/test4/testinfo.dat | 14 + .../c_runtime/vsprintf/test6/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test6/test6.cpp | 44 + .../c_runtime/vsprintf/test6/testinfo.dat | 14 + .../c_runtime/vsprintf/test7/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test7/test7.cpp | 44 + .../c_runtime/vsprintf/test7/testinfo.dat | 14 + .../c_runtime/vsprintf/test8/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test8/test8.cpp | 52 + .../c_runtime/vsprintf/test8/testinfo.dat | 14 + .../c_runtime/vsprintf/test9/CMakeLists.txt | 13 + .../c_runtime/vsprintf/test9/test9.cpp | 51 + .../c_runtime/vsprintf/test9/testinfo.dat | 14 + .../palsuite/c_runtime/vsprintf/vsprintf.h | 218 + .../c_runtime/vswprintf/CMakeLists.txt | 19 + .../c_runtime/vswprintf/test1/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test1/test1.cpp | 40 + .../c_runtime/vswprintf/test1/testinfo.dat | 14 + .../c_runtime/vswprintf/test10/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test10/test10.cpp | 48 + .../c_runtime/vswprintf/test10/testinfo.dat | 14 + .../c_runtime/vswprintf/test11/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test11/test11.cpp | 48 + .../c_runtime/vswprintf/test11/testinfo.dat | 14 + .../c_runtime/vswprintf/test12/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test12/test12.cpp | 48 + .../c_runtime/vswprintf/test12/testinfo.dat | 14 + .../c_runtime/vswprintf/test13/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test13/test13.cpp | 48 + .../c_runtime/vswprintf/test13/testinfo.dat | 14 + .../c_runtime/vswprintf/test14/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test14/test14.cpp | 61 + .../c_runtime/vswprintf/test14/testinfo.dat | 14 + .../c_runtime/vswprintf/test15/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test15/test15.cpp | 62 + .../c_runtime/vswprintf/test15/testinfo.dat | 14 + .../c_runtime/vswprintf/test16/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test16/test16.cpp | 61 + .../c_runtime/vswprintf/test16/testinfo.dat | 14 + .../c_runtime/vswprintf/test17/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test17/test17.cpp | 63 + .../c_runtime/vswprintf/test17/testinfo.dat | 14 + .../c_runtime/vswprintf/test18/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test18/test18.cpp | 63 + .../c_runtime/vswprintf/test18/testinfo.dat | 14 + .../c_runtime/vswprintf/test19/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test19/test19.cpp | 137 + .../c_runtime/vswprintf/test19/testinfo.dat | 14 + .../c_runtime/vswprintf/test2/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test2/test2.cpp | 46 + .../c_runtime/vswprintf/test2/testinfo.dat | 14 + .../c_runtime/vswprintf/test3/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test3/test3.cpp | 46 + .../c_runtime/vswprintf/test3/testinfo.dat | 14 + .../c_runtime/vswprintf/test4/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test4/test4.cpp | 118 + .../c_runtime/vswprintf/test4/testinfo.dat | 14 + .../c_runtime/vswprintf/test6/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test6/test6.cpp | 41 + .../c_runtime/vswprintf/test6/testinfo.dat | 14 + .../c_runtime/vswprintf/test7/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test7/test7.cpp | 41 + .../c_runtime/vswprintf/test7/testinfo.dat | 14 + .../c_runtime/vswprintf/test8/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test8/test8.cpp | 47 + .../c_runtime/vswprintf/test8/testinfo.dat | 14 + .../c_runtime/vswprintf/test9/CMakeLists.txt | 13 + .../c_runtime/vswprintf/test9/test9.cpp | 47 + .../c_runtime/vswprintf/test9/testinfo.dat | 14 + .../palsuite/c_runtime/vswprintf/vswprintf.h | 132 + .../palsuite/c_runtime/wcscat/CMakeLists.txt | 2 + .../c_runtime/wcscat/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/wcscat/test1/test1.cpp | 71 + .../c_runtime/wcscat/test1/testinfo.dat | 13 + .../palsuite/c_runtime/wcschr/CMakeLists.txt | 2 + .../c_runtime/wcschr/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/wcschr/test1/test1.cpp | 51 + .../c_runtime/wcschr/test1/testinfo.dat | 13 + .../palsuite/c_runtime/wcscmp/CMakeLists.txt | 2 + .../c_runtime/wcscmp/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/wcscmp/test1/test1.cpp | 57 + .../c_runtime/wcscmp/test1/testinfo.dat | 12 + .../palsuite/c_runtime/wcscpy/CMakeLists.txt | 2 + .../c_runtime/wcscpy/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/wcscpy/test1/test1.cpp | 47 + .../c_runtime/wcscpy/test1/testinfo.dat | 12 + .../palsuite/c_runtime/wcslen/CMakeLists.txt | 2 + .../c_runtime/wcslen/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/wcslen/test1/test1.cpp | 49 + .../c_runtime/wcslen/test1/testinfo.dat | 13 + .../palsuite/c_runtime/wcsncmp/CMakeLists.txt | 2 + .../c_runtime/wcsncmp/test1/CMakeLists.txt | 13 + .../c_runtime/wcsncmp/test1/test1.cpp | 73 + .../c_runtime/wcsncmp/test1/testinfo.dat | 13 + .../palsuite/c_runtime/wcsncpy/CMakeLists.txt | 2 + .../c_runtime/wcsncpy/test1/CMakeLists.txt | 13 + .../c_runtime/wcsncpy/test1/test1.cpp | 84 + .../c_runtime/wcsncpy/test1/testinfo.dat | 15 + .../palsuite/c_runtime/wcspbrk/CMakeLists.txt | 2 + .../c_runtime/wcspbrk/test1/CMakeLists.txt | 13 + .../c_runtime/wcspbrk/test1/test1.cpp | 61 + .../c_runtime/wcspbrk/test1/testinfo.dat | 13 + .../palsuite/c_runtime/wcsrchr/CMakeLists.txt | 2 + .../c_runtime/wcsrchr/test1/CMakeLists.txt | 13 + .../c_runtime/wcsrchr/test1/test1.cpp | 50 + .../c_runtime/wcsrchr/test1/testinfo.dat | 13 + .../palsuite/c_runtime/wcsstr/CMakeLists.txt | 2 + .../c_runtime/wcsstr/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/wcsstr/test1/test1.cpp | 72 + .../c_runtime/wcsstr/test1/testinfo.dat | 13 + .../palsuite/c_runtime/wcstod/CMakeLists.txt | 3 + .../c_runtime/wcstod/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/wcstod/test1/test1.cpp | 79 + .../c_runtime/wcstod/test1/testinfo.dat | 13 + .../c_runtime/wcstod/test2/CMakeLists.txt | 13 + .../palsuite/c_runtime/wcstod/test2/test2.cpp | 59 + .../c_runtime/wcstod/test2/testinfo.dat | 13 + .../palsuite/c_runtime/wcstok/CMakeLists.txt | 2 + .../c_runtime/wcstok/test1/CMakeLists.txt | 13 + .../palsuite/c_runtime/wcstok/test1/test1.cpp | 114 + .../c_runtime/wcstok/test1/testinfo.dat | 14 + .../palsuite/c_runtime/wcstoul/CMakeLists.txt | 7 + .../c_runtime/wcstoul/test1/CMakeLists.txt | 13 + .../c_runtime/wcstoul/test1/test1.cpp | 49 + .../c_runtime/wcstoul/test1/testinfo.dat | 12 + .../c_runtime/wcstoul/test2/CMakeLists.txt | 13 + .../c_runtime/wcstoul/test2/test2.cpp | 49 + .../c_runtime/wcstoul/test2/testinfo.dat | 12 + .../c_runtime/wcstoul/test3/CMakeLists.txt | 13 + .../c_runtime/wcstoul/test3/test3.cpp | 49 + .../c_runtime/wcstoul/test3/testinfo.dat | 12 + .../c_runtime/wcstoul/test4/CMakeLists.txt | 13 + .../c_runtime/wcstoul/test4/test4.cpp | 52 + .../c_runtime/wcstoul/test4/testinfo.dat | 12 + .../c_runtime/wcstoul/test5/CMakeLists.txt | 13 + .../c_runtime/wcstoul/test5/test5.cpp | 69 + .../c_runtime/wcstoul/test5/testinfo.dat | 13 + .../c_runtime/wcstoul/test6/CMakeLists.txt | 13 + .../c_runtime/wcstoul/test6/test6.cpp | 83 + .../c_runtime/wcstoul/test6/testinfo.dat | 12 + .../palsuite/c_runtime/wprintf/CMakeLists.txt | 3 + .../c_runtime/wprintf/test1/CMakeLists.txt | 13 + .../c_runtime/wprintf/test1/test1.cpp | 47 + .../c_runtime/wprintf/test1/testinfo.dat | 12 + .../c_runtime/wprintf/test2/CMakeLists.txt | 13 + .../c_runtime/wprintf/test2/test2.cpp | 51 + .../c_runtime/wprintf/test2/testinfo.dat | 12 + .../palsuite/c_runtime/wprintf/wprintf.h | 171 + .../tests/palsuite/common/ResultBuffer.cpp | 69 + .../pal/tests/palsuite/common/ResultBuffer.h | 43 + .../pal/tests/palsuite/common/ResultTime.h | 83 + .../pal/tests/palsuite/common/pal_stdclib.h | 24 + .../src/pal/tests/palsuite/common/palsuite.h | 186 + .../tests/palsuite/composite/CMakeLists.txt | 5 + .../object_management/CMakeLists.txt | 4 + .../object_management/event/CMakeLists.txt | 3 + .../event/nonshared/CMakeLists.txt | 15 + .../event/nonshared/event.cpp | 358 ++ .../event/nonshared/main.cpp | 228 + .../event/shared/CMakeLists.txt | 15 + .../object_management/event/shared/event.cpp | 373 ++ .../object_management/event/shared/main.cpp | 265 + .../object_management/mutex/CMakeLists.txt | 3 + .../mutex/nonshared/CMakeLists.txt | 15 + .../mutex/nonshared/main.cpp | 230 + .../mutex/nonshared/mutex.cpp | 340 ++ .../mutex/shared/CMakeLists.txt | 15 + .../object_management/mutex/shared/main.cpp | 265 + .../object_management/mutex/shared/mutex.cpp | 354 ++ .../composite/object_management/readme.txt | 29 + .../semaphore/CMakeLists.txt | 3 + .../semaphore/nonshared/CMakeLists.txt | 15 + .../semaphore/nonshared/main.cpp | 228 + .../semaphore/nonshared/semaphore.cpp | 342 ++ .../semaphore/shared/CMakeLists.txt | 15 + .../semaphore/shared/main.cpp | 275 + .../semaphore/shared/semaphore.cpp | 351 ++ .../composite/synchronization/CMakeLists.txt | 4 + .../criticalsection/CMakeLists.txt | 14 + .../criticalsection/criticalsection.cpp | 418 ++ .../criticalsection/mainWrapper.cpp | 255 + .../criticalsection/readme.txt | 11 + .../nativecriticalsection/CMakeLists.txt | 15 + .../nativecriticalsection/mtx_critsect.cpp | 111 + .../nativecriticalsection/mtx_critsect.h | 51 + .../pal_composite_native_cs.cpp | 467 ++ .../nativecriticalsection/readme.txt | 19 + .../nativecriticalsection/resultbuffer.cpp | 69 + .../nativecriticalsection/resultbuffer.h | 43 + .../nativecs_interlocked/CMakeLists.txt | 16 + .../nativecs_interlocked/hpitinterlock.s | 168 + .../nativecs_interlocked/interlocked.cpp | 27 + .../nativecs_interlocked/makefile | 70 + .../nativecs_interlocked/mtx_critsect.cpp | 112 + .../nativecs_interlocked/mtx_critsect.h | 67 + .../nativecs_interlocked/notes.txt | 15 + .../pal_composite_native_cs.cpp | 471 ++ .../nativecs_interlocked/readme.txt | 39 + .../nativecs_interlocked/resultbuffer.cpp | 69 + .../nativecs_interlocked/resultbuffer.h | 43 + .../nativecs_interlocked/sparcinterloc.s | 73 + .../composite/threading/CMakeLists.txt | 3 + .../threading/threadsuspension/CMakeLists.txt | 14 + .../threadsuspension/mainWrapper.cpp | 274 + .../threading/threadsuspension/readme.txt | 11 + .../threading/threadsuspension/samplefile.dat | 5124 +++++++++++++++++ .../threadsuspension/threadsuspension.cpp | 907 +++ .../CMakeLists.txt | 14 + .../mainWrapper.cpp | 274 + .../threadsuspension_switchthread/readme.txt | 11 + .../samplefile.dat | 5124 +++++++++++++++++ .../threadsuspension.cpp | 914 +++ .../palsuite/composite/wfmo/CMakeLists.txt | 15 + .../tests/palsuite/composite/wfmo/main.cpp | 239 + .../tests/palsuite/composite/wfmo/mutex.cpp | 365 ++ .../tests/palsuite/composite/wfmo/readme.txt | 22 + .../tests/palsuite/debug_api/CMakeLists.txt | 7 + .../debug_api/DebugBreak/CMakeLists.txt | 2 + .../debug_api/DebugBreak/test1/CMakeLists.txt | 13 + .../debug_api/DebugBreak/test1/test1.cpp | 47 + .../debug_api/DebugBreak/test1/testinfo.dat | 13 + .../OutputDebugStringA/CMakeLists.txt | 2 + .../OutputDebugStringA/test1/CMakeLists.txt | 30 + .../OutputDebugStringA/test1/helper.cpp | 35 + .../OutputDebugStringA/test1/test1.cpp | 94 + .../OutputDebugStringA/test1/testinfo.dat | 13 + .../OutputDebugStringW/CMakeLists.txt | 2 + .../OutputDebugStringW/test1/CMakeLists.txt | 13 + .../OutputDebugStringW/test1/test1.cpp | 41 + .../OutputDebugStringW/test1/testinfo.dat | 12 + .../WriteProcessMemory/CMakeLists.txt | 4 + .../WriteProcessMemory/test1/CMakeLists.txt | 28 + .../WriteProcessMemory/test1/commonconsts.h | 46 + .../WriteProcessMemory/test1/helper.cpp | 243 + .../WriteProcessMemory/test1/test1.cpp | 189 + .../WriteProcessMemory/test1/testinfo.dat | 16 + .../WriteProcessMemory/test3/CMakeLists.txt | 28 + .../WriteProcessMemory/test3/commonconsts.h | 50 + .../WriteProcessMemory/test3/helper.cpp | 256 + .../WriteProcessMemory/test3/test3.cpp | 205 + .../WriteProcessMemory/test3/testinfo.dat | 17 + .../WriteProcessMemory/test4/CMakeLists.txt | 28 + .../WriteProcessMemory/test4/helper.cpp | 67 + .../WriteProcessMemory/test4/test4.cpp | 124 + .../WriteProcessMemory/test4/testinfo.dat | 17 + .../palsuite/eventprovider/CMakeLists.txt | 39 + .../exception_handling/CMakeLists.txt | 10 + .../PAL_EXCEPT_FILTER/CMakeLists.txt | 4 + .../PAL_EXCEPT_FILTER/test1/CMakeLists.txt | 13 + .../test1/PAL_EXCEPT_FILTER.cpp | 118 + .../PAL_EXCEPT_FILTER/test1/testinfo.dat | 16 + .../PAL_EXCEPT_FILTER/test2/CMakeLists.txt | 13 + .../test2/pal_except_filter.cpp | 154 + .../PAL_EXCEPT_FILTER/test2/testinfo.dat | 15 + .../PAL_EXCEPT_FILTER/test3/CMakeLists.txt | 13 + .../test3/pal_except_filter.cpp | 206 + .../PAL_EXCEPT_FILTER/test3/testinfo.dat | 19 + .../PAL_EXCEPT_FILTER_EX/CMakeLists.txt | 4 + .../PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt | 13 + .../test1/PAL_EXCEPT_FILTER_EX.cpp | 197 + .../PAL_EXCEPT_FILTER_EX/test1/testinfo.dat | 18 + .../PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt | 13 + .../test2/pal_except_filter_ex.cpp | 142 + .../PAL_EXCEPT_FILTER_EX/test2/testinfo.dat | 17 + .../PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt | 13 + .../test3/pal_except_filter.cpp | 208 + .../PAL_EXCEPT_FILTER_EX/test3/testinfo.dat | 18 + .../PAL_TRY_EXCEPT/CMakeLists.txt | 3 + .../PAL_TRY_EXCEPT/test1/CMakeLists.txt | 13 + .../PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.cpp | 82 + .../PAL_TRY_EXCEPT/test1/testinfo.dat | 16 + .../PAL_TRY_EXCEPT/test2/CMakeLists.txt | 13 + .../PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.cpp | 68 + .../PAL_TRY_EXCEPT/test2/testinfo.dat | 15 + .../PAL_TRY_EXCEPT_EX/CMakeLists.txt | 4 + .../PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt | 13 + .../test1/PAL_TRY_EXCEPT_EX.cpp | 133 + .../PAL_TRY_EXCEPT_EX/test1/testinfo.dat | 16 + .../PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt | 13 + .../test2/PAL_TRY_EXCEPT_EX.cpp | 123 + .../PAL_TRY_EXCEPT_EX/test2/testinfo.dat | 15 + .../PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt | 13 + .../test3/PAL_TRY_EXCEPT_EX.cpp | 130 + .../PAL_TRY_EXCEPT_EX/test3/testinfo.dat | 16 + .../PAL_TRY_LEAVE_FINALLY/CMakeLists.txt | 2 + .../test1/CMakeLists.txt | 13 + .../test1/PAL_TRY_LEAVE_FINALLY.cpp | 77 + .../PAL_TRY_LEAVE_FINALLY/test1/testinfo.dat | 17 + .../RaiseException/CMakeLists.txt | 4 + .../RaiseException/test1/CMakeLists.txt | 13 + .../RaiseException/test1/test1.cpp | 130 + .../RaiseException/test1/testinfo.dat | 13 + .../RaiseException/test2/CMakeLists.txt | 13 + .../RaiseException/test2/test2.cpp | 224 + .../RaiseException/test2/testinfo.dat | 28 + .../RaiseException/test3/CMakeLists.txt | 13 + .../RaiseException/test3/test.cpp | 115 + .../RaiseException/test3/testinfo.dat | 14 + .../pal_except/CMakeLists.txt | 8 + .../pal_except/test1/CMakeLists.txt | 13 + .../pal_except/test1/test1.cpp | 67 + .../pal_except/test1/testinfo.dat | 23 + .../pal_except/test2/CMakeLists.txt | 13 + .../pal_except/test2/test2.cpp | 111 + .../pal_except/test2/testinfo.dat | 25 + .../pal_except/test3/CMakeLists.txt | 13 + .../pal_except/test3/test3.cpp | 120 + .../pal_except/test3/testinfo.dat | 27 + .../pal_except/test4/CMakeLists.txt | 13 + .../pal_except/test4/test4.cpp | 105 + .../pal_except/test4/testinfo.dat | 27 + .../pal_except/test5/CMakeLists.txt | 13 + .../pal_except/test5/test5.cpp | 112 + .../pal_except/test5/testinfo.dat | 27 + .../pal_except/test6/CMakeLists.txt | 13 + .../pal_except/test6/test6.cpp | 160 + .../pal_except/test6/testinfo.dat | 25 + .../pal_except/test7/CMakeLists.txt | 13 + .../pal_except/test7/test7.cpp | 67 + .../pal_except/test7/testinfo.dat | 24 + .../pal_finally/CMakeLists.txt | 2 + .../pal_finally/test1/CMakeLists.txt | 13 + .../pal_finally/test1/pal_finally.cpp | 302 + .../pal_finally/test1/testinfo.dat | 19 + .../exception_handling/pal_sxs/CMakeLists.txt | 2 + .../pal_sxs/test1/CMakeLists.txt | 94 + .../pal_sxs/test1/dlltest1.cpp | 92 + .../pal_sxs/test1/dlltest1.src | 3 + .../pal_sxs/test1/dlltest2.cpp | 92 + .../pal_sxs/test1/dlltest2.src | 3 + .../pal_sxs/test1/exceptionsxs.cpp | 117 + .../pal_sxs/test1/testinfo.dat | 13 + .../pal/tests/palsuite/file_io/CMakeLists.txt | 39 + .../palsuite/file_io/CopyFileA/CMakeLists.txt | 5 + .../file_io/CopyFileA/test1/CMakeLists.txt | 13 + .../file_io/CopyFileA/test1/CopyFileA.cpp | 159 + .../file_io/CopyFileA/test1/testinfo.dat | 12 + .../file_io/CopyFileA/test2/CMakeLists.txt | 13 + .../file_io/CopyFileA/test2/test2.cpp | 120 + .../file_io/CopyFileA/test2/testinfo.dat | 14 + .../file_io/CopyFileA/test3/CMakeLists.txt | 13 + .../file_io/CopyFileA/test3/test3.cpp | 141 + .../file_io/CopyFileA/test3/testinfo.dat | 16 + .../file_io/CopyFileA/test4/CMakeLists.txt | 13 + .../file_io/CopyFileA/test4/test4.cpp | 180 + .../file_io/CopyFileA/test4/testinfo.dat | 16 + .../palsuite/file_io/CopyFileW/CMakeLists.txt | 4 + .../file_io/CopyFileW/test1/CMakeLists.txt | 13 + .../file_io/CopyFileW/test1/CopyFileW.cpp | 155 + .../CopyFileW/test1/ExpectedResults.txt | 1 + .../file_io/CopyFileW/test1/testinfo.dat | 13 + .../file_io/CopyFileW/test2/CMakeLists.txt | 13 + .../file_io/CopyFileW/test2/test2.cpp | 124 + .../file_io/CopyFileW/test2/testinfo.dat | 15 + .../file_io/CopyFileW/test3/CMakeLists.txt | 13 + .../file_io/CopyFileW/test3/test3.cpp | 196 + .../file_io/CopyFileW/test3/testinfo.dat | 16 + .../file_io/CreateDirectoryA/CMakeLists.txt | 3 + .../CreateDirectoryA/test2/CMakeLists.txt | 13 + .../file_io/CreateDirectoryW/CMakeLists.txt | 3 + .../CreateDirectoryW/test2/CMakeLists.txt | 13 + .../file_io/CreateFileA/CMakeLists.txt | 2 + .../file_io/CreateFileA/test1/CMakeLists.txt | 13 + .../file_io/CreateFileA/test1/CreateFileA.cpp | 145 + .../file_io/CreateFileA/test1/testinfo.dat | 13 + .../file_io/CreateFileA/test1/winoutput | 1 + .../file_io/CreateFileW/CMakeLists.txt | 2 + .../file_io/CreateFileW/test1/CMakeLists.txt | 13 + .../file_io/CreateFileW/test1/CreateFileW.cpp | 152 + .../file_io/CreateFileW/test1/testinfo.dat | 13 + .../file_io/CreateFileW/test1/winoutput | 1 + .../file_io/DeleteFileA/CMakeLists.txt | 2 + .../file_io/DeleteFileA/test1/CMakeLists.txt | 13 + .../file_io/DeleteFileA/test1/DeleteFileA.cpp | 182 + .../file_io/DeleteFileA/test1/testinfo.dat | 13 + .../file_io/DeleteFileW/CMakeLists.txt | 2 + .../file_io/DeleteFileW/test1/CMakeLists.txt | 13 + .../file_io/DeleteFileW/test1/DeleteFileW.cpp | 164 + .../file_io/DeleteFileW/test1/testinfo.dat | 13 + .../FILECanonicalizePath/CMakeLists.txt | 13 + .../FILECanonicalizePath.cpp | 83 + .../file_io/FILECanonicalizePath/testinfo.dat | 12 + .../palsuite/file_io/FindClose/CMakeLists.txt | 2 + .../file_io/FindClose/test1/CMakeLists.txt | 13 + .../file_io/FindClose/test1/FindClose.cpp | 275 + .../file_io/FindClose/test1/testinfo.dat | 13 + .../file_io/FindFirstFileA/CMakeLists.txt | 2 + .../FindFirstFileA/test1/CMakeLists.txt | 13 + .../FindFirstFileA/test1/FindFirstFileA.cpp | 206 + .../file_io/FindFirstFileA/test1/testinfo.dat | 13 + .../file_io/FindFirstFileW/CMakeLists.txt | 2 + .../FindFirstFileW/test1/CMakeLists.txt | 13 + .../FindFirstFileW/test1/FindFirstFileW.cpp | 212 + .../file_io/FindFirstFileW/test1/testinfo.dat | 13 + .../file_io/FindNextFileA/CMakeLists.txt | 3 + .../FindNextFileA/test1/CMakeLists.txt | 13 + .../FindNextFileA/test1/FindNextFileA.cpp | 243 + .../file_io/FindNextFileA/test1/testinfo.dat | 13 + .../FindNextFileA/test2/CMakeLists.txt | 13 + .../FindNextFileA/test2/findnextfilea.cpp | 107 + .../file_io/FindNextFileA/test2/testinfo.dat | 14 + .../file_io/FindNextFileW/CMakeLists.txt | 3 + .../FindNextFileW/test1/CMakeLists.txt | 13 + .../FindNextFileW/test1/FindNextFileW.cpp | 249 + .../file_io/FindNextFileW/test1/testinfo.dat | 13 + .../FindNextFileW/test2/CMakeLists.txt | 13 + .../FindNextFileW/test2/findnextfilew.cpp | 107 + .../file_io/FindNextFileW/test2/testinfo.dat | 14 + .../file_io/FlushFileBuffers/CMakeLists.txt | 2 + .../FlushFileBuffers/test1/CMakeLists.txt | 13 + .../test1/FlushFileBuffers.cpp | 130 + .../FlushFileBuffers/test1/testinfo.dat | 17 + .../file_io/GetConsoleOutputCP/CMakeLists.txt | 2 + .../GetConsoleOutputCP/test1/CMakeLists.txt | 13 + .../test1/GetConsoleOutputCP.cpp | 35 + .../GetConsoleOutputCP/test1/testinfo.dat | 13 + .../GetCurrentDirectoryA/CMakeLists.txt | 2 + .../GetCurrentDirectoryA/test1/CMakeLists.txt | 13 + .../test1/GetCurrentDirectoryA.cpp | 97 + .../GetCurrentDirectoryA/test1/testinfo.dat | 14 + .../GetCurrentDirectoryW/CMakeLists.txt | 2 + .../GetCurrentDirectoryW/test1/CMakeLists.txt | 13 + .../test1/GetCurrentDirectoryW.cpp | 106 + .../GetCurrentDirectoryW/test1/testinfo.dat | 14 + .../file_io/GetFileAttributesA/CMakeLists.txt | 2 + .../test1/.hidden_directory/CMakeLists.txt | 0 .../test1/.hidden_directory/keepme | 1 + .../GetFileAttributesA/test1/.hidden_file | 1 + .../test1/.hidden_ro_directory/CMakeLists.txt | 0 .../test1/.hidden_ro_directory/keepme | 1 + .../GetFileAttributesA/test1/.hidden_ro_file | 1 + .../GetFileAttributesA/test1/CMakeLists.txt | 20 + .../test1/GetFileAttributesA.cpp | 340 ++ .../test1/no_directory/CMakeLists.txt | 0 .../test1/no_directory/keepme | 1 + .../file_io/GetFileAttributesA/test1/no_file | 1 + .../normal_test_directory/CMakeLists.txt | 0 .../test1/normal_test_directory/keepme | 1 + .../GetFileAttributesA/test1/normal_test_file | 6 + .../test1/ro_test_directory/CMakeLists.txt | 0 .../test1/ro_test_directory/keepme | 1 + .../GetFileAttributesA/test1/ro_test_file | 6 + .../test1/rw_directory/CMakeLists.txt | 0 .../test1/rw_directory/keepme | 1 + .../file_io/GetFileAttributesA/test1/rw_file | 1 + .../GetFileAttributesA/test1/testinfo.dat | 20 + .../GetFileAttributesExW/CMakeLists.txt | 3 + .../test1/.hidden_directory/CMakeLists.txt | 0 .../test1/.hidden_directory/anchor.txt | 2 + .../GetFileAttributesExW/test1/.hidden_file | 1 + .../GetFileAttributesExW/test1/CMakeLists.txt | 17 + .../normal_test_directory/CMakeLists.txt | 0 .../test1/normal_test_directory/keepme | 1 + .../test1/normal_test_file | 6 + .../test1/ro_test_directory/CMakeLists.txt | 0 .../test1/ro_test_directory/keepme | 1 + .../GetFileAttributesExW/test1/ro_test_file | 6 + .../GetFileAttributesExW/test1/test1.cpp | 176 + .../GetFileAttributesExW/test1/testinfo.dat | 16 + .../GetFileAttributesExW/test2/CMakeLists.txt | 13 + .../GetFileAttributesExW/test2/test2.cpp | 170 + .../GetFileAttributesExW/test2/testinfo.dat | 14 + .../file_io/GetFileAttributesW/CMakeLists.txt | 2 + .../test1/.hidden_directory/CMakeLists.txt | 0 .../test1/.hidden_directory/keepme | 1 + .../GetFileAttributesW/test1/.hidden_file | 1 + .../test1/.hidden_ro_directory/CMakeLists.txt | 0 .../test1/.hidden_ro_directory/keepme | 1 + .../GetFileAttributesW/test1/.hidden_ro_file | 1 + .../GetFileAttributesW/test1/CMakeLists.txt | 20 + .../test1/GetFileAttributesW.cpp | 345 ++ .../test1/no_directory/CMakeLists.txt | 0 .../test1/no_directory/keepme | 1 + .../file_io/GetFileAttributesW/test1/no_file | 1 + .../normal_test_directory/CMakeLists.txt | 0 .../test1/normal_test_directory/keepme | 1 + .../GetFileAttributesW/test1/normal_test_file | 6 + .../test1/ro_test_directory/CMakeLists.txt | 0 .../test1/ro_test_directory/keepme | 1 + .../GetFileAttributesW/test1/ro_test_file | 6 + .../file_io/GetFileAttributesW/test1/rw_file | 1 + .../test1/rw_test_directory/CMakeLists.txt | 0 .../test1/rw_test_directory/keepme | 1 + .../GetFileAttributesW/test1/testinfo.dat | 20 + .../file_io/GetFileSize/CMakeLists.txt | 2 + .../file_io/GetFileSize/test1/CMakeLists.txt | 13 + .../file_io/GetFileSize/test1/GetFileSize.cpp | 173 + .../file_io/GetFileSize/test1/testinfo.dat | 13 + .../file_io/GetFileSizeEx/CMakeLists.txt | 2 + .../GetFileSizeEx/test1/CMakeLists.txt | 13 + .../GetFileSizeEx/test1/GetFileSizeEx.cpp | 173 + .../file_io/GetFileSizeEx/test1/testinfo.dat | 13 + .../file_io/GetFullPathNameA/CMakeLists.txt | 5 + .../GetFullPathNameA/test1/CMakeLists.txt | 13 + .../test1/GetFullPathNameA.cpp | 122 + .../GetFullPathNameA/test1/testinfo.dat | 15 + .../GetFullPathNameA/test2/CMakeLists.txt | 13 + .../file_io/GetFullPathNameA/test2/test2.cpp | 143 + .../GetFullPathNameA/test2/testinfo.dat | 18 + .../GetFullPathNameA/test3/CMakeLists.txt | 13 + .../file_io/GetFullPathNameA/test3/test3.cpp | 241 + .../GetFullPathNameA/test3/testinfo.dat | 19 + .../GetFullPathNameA/test4/CMakeLists.txt | 13 + .../file_io/GetFullPathNameA/test4/test4.cpp | 203 + .../GetFullPathNameA/test4/testinfo.dat | 19 + .../file_io/GetFullPathNameW/CMakeLists.txt | 5 + .../GetFullPathNameW/test1/CMakeLists.txt | 13 + .../test1/GetFullPathNameW.cpp | 157 + .../GetFullPathNameW/test1/testinfo.dat | 14 + .../GetFullPathNameW/test2/CMakeLists.txt | 13 + .../file_io/GetFullPathNameW/test2/test2.cpp | 159 + .../GetFullPathNameW/test2/testinfo.dat | 15 + .../GetFullPathNameW/test3/CMakeLists.txt | 13 + .../file_io/GetFullPathNameW/test3/test3.cpp | 240 + .../GetFullPathNameW/test3/testinfo.dat | 19 + .../GetFullPathNameW/test4/CMakeLists.txt | 13 + .../file_io/GetFullPathNameW/test4/test4.cpp | 201 + .../GetFullPathNameW/test4/testinfo.dat | 19 + .../file_io/GetStdHandle/CMakeLists.txt | 3 + .../file_io/GetStdHandle/test1/CMakeLists.txt | 13 + .../GetStdHandle/test1/GetStdHandle.cpp | 123 + .../file_io/GetStdHandle/test1/testinfo.dat | 13 + .../file_io/GetStdHandle/test2/CMakeLists.txt | 13 + .../GetStdHandle/test2/GetStdHandle.cpp | 79 + .../file_io/GetStdHandle/test2/testinfo.dat | 13 + .../file_io/GetSystemTime/CMakeLists.txt | 2 + .../GetSystemTime/test1/CMakeLists.txt | 13 + .../file_io/GetSystemTime/test1/test.cpp | 124 + .../file_io/GetSystemTime/test1/testinfo.dat | 12 + .../GetSystemTimeAsFileTime/CMakeLists.txt | 2 + .../test1/CMakeLists.txt | 13 + .../test1/GetSystemTimeAsFileTime.cpp | 86 + .../test1/testinfo.dat | 14 + .../file_io/GetTempFileNameA/CMakeLists.txt | 4 + .../GetTempFileNameA/test1/CMakeLists.txt | 13 + .../test1/GetTempFileNameA.cpp | 125 + .../GetTempFileNameA/test1/testinfo.dat | 13 + .../GetTempFileNameA/test2/CMakeLists.txt | 13 + .../test2/GetTempFileNameA.cpp | 80 + .../GetTempFileNameA/test2/testinfo.dat | 17 + .../GetTempFileNameA/test3/CMakeLists.txt | 13 + .../test3/gettempfilenamea.cpp | 159 + .../GetTempFileNameA/test3/testinfo.dat | 15 + .../file_io/GetTempFileNameW/CMakeLists.txt | 4 + .../GetTempFileNameW/test1/CMakeLists.txt | 13 + .../test1/GetTempFileNameW.cpp | 129 + .../GetTempFileNameW/test1/testinfo.dat | 13 + .../GetTempFileNameW/test2/CMakeLists.txt | 13 + .../test2/GetTempFileNameW.cpp | 84 + .../GetTempFileNameW/test2/testinfo.dat | 15 + .../GetTempFileNameW/test3/CMakeLists.txt | 13 + .../test3/gettempfilenamew.cpp | 161 + .../GetTempFileNameW/test3/testinfo.dat | 15 + .../file_io/GetTempPathW/CMakeLists.txt | 2 + .../file_io/GetTempPathW/test1/CMakeLists.txt | 13 + .../GetTempPathW/test1/GetTempPathW.cpp | 103 + .../file_io/GetTempPathW/test1/testinfo.dat | 15 + .../file_io/MoveFileExA/CMakeLists.txt | 2 + .../file_io/MoveFileExA/test1/CMakeLists.txt | 13 + .../MoveFileExA/test1/ExpectedResults.txt | 1 + .../file_io/MoveFileExA/test1/MoveFileExA.cpp | 360 ++ .../file_io/MoveFileExA/test1/testinfo.dat | 13 + .../file_io/MoveFileExW/CMakeLists.txt | 2 + .../file_io/MoveFileExW/test1/CMakeLists.txt | 13 + .../MoveFileExW/test1/ExpectedResults.txt | 1 + .../file_io/MoveFileExW/test1/MoveFileExW.cpp | 431 ++ .../file_io/MoveFileExW/test1/testinfo.dat | 13 + .../palsuite/file_io/ReadFile/CMakeLists.txt | 5 + .../file_io/ReadFile/test1/CMakeLists.txt | 13 + .../ReadFile/test1/NonReadableFile.txt | 1 + .../file_io/ReadFile/test1/ReadFile.cpp | 82 + .../file_io/ReadFile/test1/testinfo.dat | 13 + .../file_io/ReadFile/test2/CMakeLists.txt | 13 + .../file_io/ReadFile/test2/ReadFile.cpp | 194 + .../file_io/ReadFile/test2/testinfo.dat | 13 + .../file_io/ReadFile/test3/CMakeLists.txt | 13 + .../file_io/ReadFile/test3/ReadFile.cpp | 184 + .../file_io/ReadFile/test3/testinfo.dat | 13 + .../file_io/ReadFile/test4/CMakeLists.txt | 13 + .../file_io/ReadFile/test4/readfile.cpp | 147 + .../file_io/ReadFile/test4/testinfo.dat | 17 + .../file_io/RemoveDirectoryA/CMakeLists.txt | 2 + .../file_io/RemoveDirectoryW/CMakeLists.txt | 2 + .../file_io/SearchPathA/CMakeLists.txt | 2 + .../file_io/SearchPathW/CMakeLists.txt | 2 + .../file_io/SearchPathW/test1/CMakeLists.txt | 13 + .../file_io/SearchPathW/test1/SearchPathW.cpp | 193 + .../file_io/SearchPathW/test1/testinfo.dat | 12 + .../file_io/SetEndOfFile/CMakeLists.txt | 6 + .../file_io/SetEndOfFile/test1/CMakeLists.txt | 13 + .../SetEndOfFile/test1/SetEndOfFile.cpp | 85 + .../file_io/SetEndOfFile/test1/testinfo.dat | 13 + .../file_io/SetEndOfFile/test2/CMakeLists.txt | 13 + .../SetEndOfFile/test2/SetEndOfFile.cpp | 154 + .../file_io/SetEndOfFile/test2/testinfo.dat | 12 + .../file_io/SetEndOfFile/test3/CMakeLists.txt | 13 + .../SetEndOfFile/test3/SetEndOfFile.cpp | 109 + .../file_io/SetEndOfFile/test3/testinfo.dat | 14 + .../file_io/SetEndOfFile/test4/CMakeLists.txt | 13 + .../SetEndOfFile/test4/setendoffile.cpp | 138 + .../file_io/SetEndOfFile/test4/testinfo.dat | 15 + .../file_io/SetEndOfFile/test5/CMakeLists.txt | 13 + .../file_io/SetEndOfFile/test5/test5.cpp | 183 + .../file_io/SetEndOfFile/test5/testinfo.dat | 16 + .../file_io/SetFilePointer/CMakeLists.txt | 8 + .../SetFilePointer/test1/CMakeLists.txt | 13 + .../SetFilePointer/test1/SetFilePointer.cpp | 123 + .../file_io/SetFilePointer/test1/testinfo.dat | 13 + .../SetFilePointer/test2/CMakeLists.txt | 13 + .../SetFilePointer/test2/SetFilePointer.cpp | 356 ++ .../file_io/SetFilePointer/test2/testinfo.dat | 13 + .../SetFilePointer/test3/CMakeLists.txt | 13 + .../SetFilePointer/test3/SetFilePointer.cpp | 350 ++ .../file_io/SetFilePointer/test3/testinfo.dat | 13 + .../SetFilePointer/test4/CMakeLists.txt | 13 + .../SetFilePointer/test4/SetFilePointer.cpp | 242 + .../file_io/SetFilePointer/test4/testinfo.dat | 13 + .../SetFilePointer/test5/CMakeLists.txt | 13 + .../SetFilePointer/test5/SetFilePointer.cpp | 182 + .../file_io/SetFilePointer/test5/testinfo.dat | 14 + .../SetFilePointer/test6/CMakeLists.txt | 13 + .../SetFilePointer/test6/SetFilePointer.cpp | 213 + .../file_io/SetFilePointer/test6/testinfo.dat | 14 + .../SetFilePointer/test7/CMakeLists.txt | 13 + .../SetFilePointer/test7/SetFilePointer.cpp | 213 + .../file_io/SetFilePointer/test7/testinfo.dat | 14 + .../palsuite/file_io/WriteFile/CMakeLists.txt | 6 + .../file_io/WriteFile/test1/CMakeLists.txt | 13 + .../file_io/WriteFile/test1/WriteFile.cpp | 114 + .../file_io/WriteFile/test1/testinfo.dat | 13 + .../file_io/WriteFile/test2/CMakeLists.txt | 13 + .../file_io/WriteFile/test2/Results.txt | 1 + .../file_io/WriteFile/test2/WriteFile.cpp | 105 + .../file_io/WriteFile/test2/testinfo.dat | 13 + .../file_io/WriteFile/test3/CMakeLists.txt | 13 + .../file_io/WriteFile/test3/WriteFile.cpp | 136 + .../file_io/WriteFile/test3/testinfo.dat | 13 + .../file_io/WriteFile/test4/CMakeLists.txt | 13 + .../file_io/WriteFile/test4/testinfo.dat | 13 + .../file_io/WriteFile/test4/writefile.cpp | 155 + .../file_io/WriteFile/test5/CMakeLists.txt | 13 + .../file_io/WriteFile/test5/testinfo.dat | 15 + .../file_io/WriteFile/test5/writefile.cpp | 117 + .../file_io/errorpathnotfound/CMakeLists.txt | 3 + .../errorpathnotfound/test1/CMakeLists.txt | 13 + .../file_io/errorpathnotfound/test1/test1.cpp | 783 +++ .../errorpathnotfound/test1/testinfo.dat | 31 + .../errorpathnotfound/test2/CMakeLists.txt | 13 + .../file_io/errorpathnotfound/test2/test2.cpp | 526 ++ .../errorpathnotfound/test2/testinfo.dat | 32 + .../file_io/gettemppatha/CMakeLists.txt | 2 + .../file_io/gettemppatha/test1/CMakeLists.txt | 13 + .../gettemppatha/test1/gettemppatha.cpp | 103 + .../file_io/gettemppatha/test1/testinfo.dat | 15 + .../filemapping_memmgt/CMakeLists.txt | 18 + .../CreateFileMappingA/CMakeLists.txt | 9 + .../CreateFileMappingA/test1/CMakeLists.txt | 13 + .../test1/CreateFileMapping.cpp | 173 + .../CreateFileMappingA/test1/testinfo.dat | 13 + .../CreateFileMappingA/test3/CMakeLists.txt | 13 + .../test3/CreateFileMapping.cpp | 155 + .../CreateFileMappingA/test3/testinfo.dat | 13 + .../CreateFileMappingA/test4/CMakeLists.txt | 13 + .../test4/CreateFileMapping.cpp | 181 + .../CreateFileMappingA/test4/testinfo.dat | 13 + .../CreateFileMappingA/test5/CMakeLists.txt | 13 + .../test5/CreateFileMapping.cpp | 193 + .../CreateFileMappingA/test5/testinfo.dat | 14 + .../CreateFileMappingA/test6/CMakeLists.txt | 13 + .../test6/CreateFileMapping.cpp | 164 + .../CreateFileMappingA/test6/testinfo.dat | 13 + .../CreateFileMappingA/test7/CMakeLists.txt | 13 + .../test7/createfilemapping.cpp | 164 + .../CreateFileMappingA/test7/testinfo.dat | 13 + .../CreateFileMappingA/test8/CMakeLists.txt | 13 + .../test8/createfilemapping.cpp | 79 + .../CreateFileMappingA/test8/testinfo.dat | 14 + .../CreateFileMappingA/test9/CMakeLists.txt | 13 + .../test9/createfilemapping.cpp | 150 + .../CreateFileMappingA/test9/testinfo.dat | 12 + .../CreateFileMappingW/CMakeLists.txt | 14 + .../CreateFileMapping_neg1/CMakeLists.txt | 13 + .../CreateFileMapping_neg.cpp | 93 + .../CreateFileMapping_neg1/testinfo.dat | 12 + .../CreateFileMappingW/test1/CMakeLists.txt | 13 + .../test1/CreateFileMappingW.cpp | 174 + .../CreateFileMappingW/test1/testinfo.dat | 13 + .../CreateFileMappingW/test2/CMakeLists.txt | 13 + .../test2/CreateFileMappingW.cpp | 124 + .../CreateFileMappingW/test3/CMakeLists.txt | 13 + .../test3/CreateFileMappingW.cpp | 156 + .../CreateFileMappingW/test3/testinfo.dat | 13 + .../CreateFileMappingW/test4/CMakeLists.txt | 13 + .../test4/CreateFileMappingW.cpp | 182 + .../CreateFileMappingW/test4/testinfo.dat | 13 + .../CreateFileMappingW/test5/CMakeLists.txt | 13 + .../test5/CreateFileMappingW.cpp | 194 + .../CreateFileMappingW/test5/testinfo.dat | 14 + .../CreateFileMappingW/test6/CMakeLists.txt | 13 + .../test6/CreateFileMappingW.cpp | 165 + .../CreateFileMappingW/test6/testinfo.dat | 14 + .../CreateFileMappingW/test7/CMakeLists.txt | 13 + .../test7/createfilemapping.cpp | 165 + .../CreateFileMappingW/test7/testinfo.dat | 14 + .../CreateFileMappingW/test8/CMakeLists.txt | 13 + .../test8/createfilemapping.cpp | 82 + .../CreateFileMappingW/test8/testinfo.dat | 13 + .../CreateFileMappingW/test9/CMakeLists.txt | 13 + .../test9/createfilemapping.cpp | 151 + .../CreateFileMappingW/test9/testinfo.dat | 12 + .../FreeLibrary/CMakeLists.txt | 3 + .../FreeLibrary/test1/CMakeLists.txt | 14 + .../FreeLibrary/test1/FreeLibrary.cpp | 128 + .../FreeLibrary/test1/dlltest.cpp | 32 + .../FreeLibrary/test1/testinfo.dat | 14 + .../FreeLibrary/test2/CMakeLists.txt | 13 + .../FreeLibrary/test2/test2.cpp | 52 + .../FreeLibrary/test2/testinfo.dat | 14 + .../FreeLibraryAndExitThread/CMakeLists.txt | 2 + .../test1/CMakeLists.txt | 14 + .../test1/dlltest.cpp | 32 + .../FreeLibraryAndExitThread/test1/test1.cpp | 183 + .../test1/testinfo.dat | 17 + .../GetModuleFileNameA/CMakeLists.txt | 3 + .../GetModuleFileNameA/test1/CMakeLists.txt | 13 + .../test1/GetModuleFileNameA.cpp | 92 + .../GetModuleFileNameA/test1/testinfo.dat | 13 + .../GetModuleFileNameA/test2/CMakeLists.txt | 13 + .../test2/GetModuleFileNameA.cpp | 49 + .../GetModuleFileNameA/test2/testinfo.dat | 13 + .../GetModuleFileNameW/CMakeLists.txt | 3 + .../GetModuleFileNameW/test1/CMakeLists.txt | 13 + .../test1/GetModuleFileNameW.cpp | 112 + .../GetModuleFileNameW/test1/testinfo.dat | 13 + .../GetModuleFileNameW/test2/CMakeLists.txt | 13 + .../test2/GetModuleFileNameW.cpp | 57 + .../GetModuleFileNameW/test2/testinfo.dat | 13 + .../GetProcAddress/CMakeLists.txt | 3 + .../GetProcAddress/test1/CMakeLists.txt | 14 + .../GetProcAddress/test1/test1.cpp | 111 + .../GetProcAddress/test1/testinfo.dat | 19 + .../GetProcAddress/test1/testlib.cpp | 33 + .../GetProcAddress/test2/CMakeLists.txt | 14 + .../GetProcAddress/test2/test2.cpp | 152 + .../GetProcAddress/test2/testinfo.dat | 18 + .../GetProcAddress/test2/testlib.cpp | 33 + .../LocalAlloc/CMakeLists.txt | 2 + .../LocalAlloc/test1/CMakeLists.txt | 13 + .../LocalAlloc/test1/LocalAlloc.cpp | 49 + .../LocalAlloc/test1/testinfo.dat | 12 + .../LocalFree/CMakeLists.txt | 3 + .../LocalFree/test1/CMakeLists.txt | 13 + .../LocalFree/test1/LocalFree.cpp | 49 + .../LocalFree/test1/testinfo.dat | 12 + .../LocalFree/test2/CMakeLists.txt | 13 + .../LocalFree/test2/LocalFree.cpp | 39 + .../LocalFree/test2/testinfo.dat | 13 + .../MapViewOfFile/CMakeLists.txt | 7 + .../MapViewOfFile/test1/CMakeLists.txt | 13 + .../MapViewOfFile/test1/MapViewOfFile.cpp | 244 + .../MapViewOfFile/test1/testinfo.dat | 12 + .../MapViewOfFile/test2/CMakeLists.txt | 13 + .../MapViewOfFile/test2/MapViewOfFile.cpp | 203 + .../MapViewOfFile/test2/testinfo.dat | 12 + .../MapViewOfFile/test3/CMakeLists.txt | 13 + .../MapViewOfFile/test3/MapViewOfFile.cpp | 209 + .../MapViewOfFile/test3/testinfo.dat | 12 + .../MapViewOfFile/test4/CMakeLists.txt | 13 + .../MapViewOfFile/test4/mapviewoffile.cpp | 166 + .../MapViewOfFile/test4/testinfo.dat | 14 + .../MapViewOfFile/test5/CMakeLists.txt | 13 + .../MapViewOfFile/test5/mapviewoffile.cpp | 131 + .../MapViewOfFile/test5/testinfo.dat | 13 + .../MapViewOfFile/test6/CMakeLists.txt | 13 + .../MapViewOfFile/test6/mapviewoffile.cpp | 85 + .../MapViewOfFile/test6/testinfo.dat | 13 + .../OpenFileMappingA/CMakeLists.txt | 4 + .../OpenFileMappingA/test1/CMakeLists.txt | 13 + .../test1/OpenFileMappingA.cpp | 157 + .../OpenFileMappingA/test1/testinfo.dat | 12 + .../OpenFileMappingA/test2/CMakeLists.txt | 13 + .../test2/OpenFileMappingA.cpp | 214 + .../OpenFileMappingA/test2/testinfo.dat | 12 + .../OpenFileMappingA/test3/CMakeLists.txt | 13 + .../test3/OpenFileMappingA.cpp | 217 + .../OpenFileMappingA/test3/testinfo.dat | 12 + .../OpenFileMappingW/CMakeLists.txt | 4 + .../OpenFileMappingW/test1/CMakeLists.txt | 13 + .../test1/OpenFileMappingW.cpp | 155 + .../OpenFileMappingW/test1/testinfo.dat | 12 + .../OpenFileMappingW/test2/CMakeLists.txt | 13 + .../test2/OpenFileMappingW.cpp | 217 + .../OpenFileMappingW/test2/testinfo.dat | 12 + .../OpenFileMappingW/test3/CMakeLists.txt | 13 + .../test3/OpenFileMappingW.cpp | 210 + .../OpenFileMappingW/test3/testinfo.dat | 12 + .../ProbeMemory/CMakeLists.txt | 3 + .../ProbeMemory_neg1/CMakeLists.txt | 13 + .../ProbeMemory_neg1/ProbeMemory_neg.cpp | 95 + .../ProbeMemory/ProbeMemory_neg1/testinfo.dat | 12 + .../ProbeMemory/test1/CMakeLists.txt | 13 + .../ProbeMemory/test1/ProbeMemory.cpp | 94 + .../ProbeMemory/test1/testinfo.dat | 12 + .../UnmapViewOfFile/CMakeLists.txt | 3 + .../UnmapViewOfFile/test1/CMakeLists.txt | 13 + .../UnmapViewOfFile/test1/UnmapViewOfFile.cpp | 184 + .../UnmapViewOfFile/test1/testinfo.dat | 13 + .../UnmapViewOfFile/test2/CMakeLists.txt | 13 + .../UnmapViewOfFile/test2/testinfo.dat | 13 + .../UnmapViewOfFile/test2/unmapviewoffile.cpp | 42 + .../VirtualAlloc/CMakeLists.txt | 23 + .../VirtualAlloc/test1/CMakeLists.txt | 13 + .../VirtualAlloc/test1/VirtualAlloc.cpp | 50 + .../VirtualAlloc/test1/testinfo.dat | 13 + .../VirtualAlloc/test10/CMakeLists.txt | 13 + .../VirtualAlloc/test10/VirtualAlloc.cpp | 48 + .../VirtualAlloc/test10/testinfo.dat | 13 + .../VirtualAlloc/test11/CMakeLists.txt | 13 + .../VirtualAlloc/test11/VirtualAlloc.cpp | 49 + .../VirtualAlloc/test11/testinfo.dat | 13 + .../VirtualAlloc/test12/CMakeLists.txt | 13 + .../VirtualAlloc/test12/VirtualAlloc.cpp | 48 + .../VirtualAlloc/test12/testinfo.dat | 13 + .../VirtualAlloc/test13/CMakeLists.txt | 13 + .../VirtualAlloc/test13/VirtualAlloc.cpp | 48 + .../VirtualAlloc/test13/testinfo.dat | 13 + .../VirtualAlloc/test14/CMakeLists.txt | 13 + .../VirtualAlloc/test14/VirtualAlloc.cpp | 48 + .../VirtualAlloc/test14/testinfo.dat | 13 + .../VirtualAlloc/test15/CMakeLists.txt | 13 + .../VirtualAlloc/test15/VirtualAlloc.cpp | 48 + .../VirtualAlloc/test15/testinfo.dat | 13 + .../VirtualAlloc/test16/CMakeLists.txt | 13 + .../VirtualAlloc/test16/VirtualAlloc.cpp | 48 + .../VirtualAlloc/test16/testinfo.dat | 13 + .../VirtualAlloc/test17/CMakeLists.txt | 13 + .../VirtualAlloc/test17/VirtualAlloc.cpp | 49 + .../VirtualAlloc/test17/testinfo.dat | 13 + .../VirtualAlloc/test18/CMakeLists.txt | 13 + .../VirtualAlloc/test18/VirtualAlloc.cpp | 49 + .../VirtualAlloc/test18/testinfo.dat | 13 + .../VirtualAlloc/test19/CMakeLists.txt | 13 + .../VirtualAlloc/test19/VirtualAlloc.cpp | 51 + .../VirtualAlloc/test19/testinfo.dat | 14 + .../VirtualAlloc/test2/CMakeLists.txt | 13 + .../VirtualAlloc/test2/VirtualAlloc.cpp | 49 + .../VirtualAlloc/test2/testinfo.dat | 13 + .../VirtualAlloc/test20/CMakeLists.txt | 13 + .../VirtualAlloc/test20/testinfo.dat | 12 + .../VirtualAlloc/test20/virtualalloc.cpp | 50 + .../VirtualAlloc/test21/CMakeLists.txt | 13 + .../VirtualAlloc/test21/testinfo.dat | 12 + .../VirtualAlloc/test21/virtualalloc.cpp | 54 + .../VirtualAlloc/test22/CMakeLists.txt | 13 + .../VirtualAlloc/test22/VirtualAlloc.cpp | 44 + .../VirtualAlloc/test22/testinfo.dat | 13 + .../VirtualAlloc/test3/CMakeLists.txt | 13 + .../VirtualAlloc/test3/VirtualAlloc.cpp | 48 + .../VirtualAlloc/test3/testinfo.dat | 13 + .../VirtualAlloc/test4/CMakeLists.txt | 13 + .../VirtualAlloc/test4/VirtualAlloc.cpp | 49 + .../VirtualAlloc/test4/testinfo.dat | 13 + .../VirtualAlloc/test5/CMakeLists.txt | 13 + .../VirtualAlloc/test5/VirtualAlloc.cpp | 50 + .../VirtualAlloc/test5/testinfo.dat | 13 + .../VirtualAlloc/test6/CMakeLists.txt | 13 + .../VirtualAlloc/test6/VirtualAlloc.cpp | 48 + .../VirtualAlloc/test6/testinfo.dat | 13 + .../VirtualAlloc/test7/CMakeLists.txt | 13 + .../VirtualAlloc/test7/VirtualAlloc.cpp | 53 + .../VirtualAlloc/test7/testinfo.dat | 13 + .../VirtualAlloc/test8/CMakeLists.txt | 13 + .../VirtualAlloc/test8/VirtualAlloc.cpp | 48 + .../VirtualAlloc/test8/testinfo.dat | 13 + .../VirtualAlloc/test9/CMakeLists.txt | 13 + .../VirtualAlloc/test9/VirtualAlloc.cpp | 48 + .../VirtualAlloc/test9/testinfo.dat | 13 + .../VirtualFree/CMakeLists.txt | 4 + .../VirtualFree/test1/CMakeLists.txt | 13 + .../VirtualFree/test1/VirtualFree.cpp | 48 + .../VirtualFree/test1/testinfo.dat | 13 + .../VirtualFree/test2/CMakeLists.txt | 13 + .../VirtualFree/test2/VirtualFree.cpp | 54 + .../VirtualFree/test2/testinfo.dat | 13 + .../VirtualFree/test3/CMakeLists.txt | 13 + .../VirtualFree/test3/VirtualFree.cpp | 53 + .../VirtualFree/test3/testinfo.dat | 13 + .../VirtualProtect/CMakeLists.txt | 7 + .../VirtualProtect/test1/CMakeLists.txt | 13 + .../VirtualProtect/test1/VirtualProtect.cpp | 69 + .../VirtualProtect/test1/testinfo.dat | 13 + .../VirtualProtect/test2/CMakeLists.txt | 13 + .../VirtualProtect/test2/VirtualProtect.cpp | 69 + .../VirtualProtect/test2/testinfo.dat | 13 + .../VirtualProtect/test3/CMakeLists.txt | 13 + .../VirtualProtect/test3/VirtualProtect.cpp | 69 + .../VirtualProtect/test3/testinfo.dat | 13 + .../VirtualProtect/test4/CMakeLists.txt | 13 + .../VirtualProtect/test4/VirtualProtect.cpp | 68 + .../VirtualProtect/test4/testinfo.dat | 13 + .../VirtualProtect/test6/CMakeLists.txt | 13 + .../VirtualProtect/test6/VirtualProtect.cpp | 68 + .../VirtualProtect/test6/testinfo.dat | 13 + .../VirtualProtect/test7/CMakeLists.txt | 13 + .../VirtualProtect/test7/VirtualProtect.cpp | 69 + .../VirtualProtect/test7/testinfo.dat | 13 + .../VirtualQuery/CMakeLists.txt | 2 + .../VirtualQuery/test1/CMakeLists.txt | 13 + .../VirtualQuery/test1/VirtualQuery.cpp | 68 + .../VirtualQuery/test1/testinfo.dat | 12 + .../pal/tests/palsuite/loader/CMakeLists.txt | 3 + .../loader/LoadLibraryA/CMakeLists.txt | 6 + .../loader/LoadLibraryA/test1/CMakeLists.txt | 13 + .../LoadLibraryA/test1/LoadLibraryA.cpp | 53 + .../loader/LoadLibraryA/test1/testinfo.dat | 13 + .../loader/LoadLibraryA/test2/CMakeLists.txt | 13 + .../LoadLibraryA/test2/LoadLibraryA.cpp | 52 + .../loader/LoadLibraryA/test2/MyModule.cpp | 19 + .../loader/LoadLibraryA/test2/testinfo.dat | 13 + .../loader/LoadLibraryA/test3/CMakeLists.txt | 13 + .../LoadLibraryA/test3/loadlibrarya.cpp | 40 + .../loader/LoadLibraryA/test3/testinfo.dat | 14 + .../loader/LoadLibraryA/test5/CMakeLists.txt | 13 + .../LoadLibraryA/test5/loadlibrarya.cpp | 67 + .../loader/LoadLibraryA/test5/testinfo.dat | 14 + .../loader/LoadLibraryA/test6/CMakeLists.txt | 28 + .../loader/LoadLibraryA/test6/dlltest.cpp | 72 + .../LoadLibraryA/test6/loadlibrarya.cpp | 172 + .../loader/LoadLibraryA/test6/testinfo.dat | 17 + .../loader/LoadLibraryA/test7/CMakeLists.txt | 13 + .../LoadLibraryA/test7/LoadLibraryA.cpp | 83 + .../loader/LoadLibraryA/test7/testinfo.dat | 13 + .../loader/LoadLibraryA/test8/CMakeLists.txt | 28 + .../loader/LoadLibraryA/test8/dlltest.cpp | 72 + .../LoadLibraryA/test8/loadlibrarya.cpp | 235 + .../loader/LoadLibraryA/test8/testinfo.dat | 17 + .../loader/LoadLibraryW/CMakeLists.txt | 5 + .../loader/LoadLibraryW/test1/CMakeLists.txt | 13 + .../LoadLibraryW/test1/LoadLibraryW.cpp | 62 + .../loader/LoadLibraryW/test1/testinfo.dat | 12 + .../loader/LoadLibraryW/test2/CMakeLists.txt | 13 + .../LoadLibraryW/test2/loadlibraryw.cpp | 62 + .../loader/LoadLibraryW/test2/testinfo.dat | 13 + .../loader/LoadLibraryW/test3/CMakeLists.txt | 13 + .../LoadLibraryW/test3/loadlibraryw.cpp | 41 + .../loader/LoadLibraryW/test3/testinfo.dat | 12 + .../loader/LoadLibraryW/test5/CMakeLists.txt | 13 + .../LoadLibraryW/test5/loadlibraryw.cpp | 71 + .../loader/LoadLibraryW/test5/testinfo.dat | 14 + .../tests/palsuite/locale_info/CMakeLists.txt | 15 + .../locale_info/CompareStringA/CMakeLists.txt | 2 + .../CompareStringA/test1/CMakeLists.txt | 13 + .../CompareStringA/test1/test1.cpp | 99 + .../CompareStringA/test1/testinfo.dat | 13 + .../locale_info/CompareStringW/CMakeLists.txt | 2 + .../CompareStringW/test1/CMakeLists.txt | 13 + .../CompareStringW/test1/test1.cpp | 99 + .../CompareStringW/test1/testinfo.dat | 13 + .../locale_info/GetACP/CMakeLists.txt | 2 + .../locale_info/GetACP/test1/CMakeLists.txt | 13 + .../locale_info/GetACP/test1/test1.cpp | 42 + .../locale_info/GetACP/test1/testinfo.dat | 12 + .../locale_info/GetCPInfo/CMakeLists.txt | 4 + .../GetCPInfo/test1/CMakeLists.txt | 13 + .../locale_info/GetCPInfo/test1/test1.cpp | 54 + .../locale_info/GetCPInfo/test1/testinfo.dat | 13 + .../GetCPInfo/test2/CMakeLists.txt | 13 + .../locale_info/GetCPInfo/test2/test2.cpp | 60 + .../locale_info/GetCPInfo/test2/testinfo.dat | 9 + .../GetCPInfo/test3/CMakeLists.txt | 13 + .../locale_info/GetCPInfo/test3/test3.cpp | 41 + .../locale_info/GetCPInfo/test3/testinfo.dat | 8 + .../locale_info/GetLocaleInfoW/CMakeLists.txt | 3 + .../GetLocaleInfoW/test1/CMakeLists.txt | 13 + .../GetLocaleInfoW/test1/test1.cpp | 89 + .../GetLocaleInfoW/test1/testinfo.dat | 12 + .../GetLocaleInfoW/test2/CMakeLists.txt | 13 + .../GetLocaleInfoW/test2/test2.cpp | 51 + .../GetLocaleInfoW/test2/testinfo.dat | 14 + .../locale_info/IsDBCSLeadByte/CMakeLists.txt | 2 + .../IsDBCSLeadByte/test1/CMakeLists.txt | 13 + .../IsDBCSLeadByte/test1/test1.cpp | 64 + .../IsDBCSLeadByte/test1/testinfo.dat | 13 + .../IsDBCSLeadByteEx/CMakeLists.txt | 2 + .../IsDBCSLeadByteEx/test1/CMakeLists.txt | 13 + .../IsDBCSLeadByteEx/test1/test1.cpp | 72 + .../IsDBCSLeadByteEx/test1/testinfo.dat | 14 + .../MultiByteToWideChar/CMakeLists.txt | 4 + .../MultiByteToWideChar/test1/CMakeLists.txt | 13 + .../MultiByteToWideChar/test1/test1.cpp | 81 + .../MultiByteToWideChar/test1/testinfo.dat | 14 + .../MultiByteToWideChar/test2/CMakeLists.txt | 13 + .../MultiByteToWideChar/test2/test2.cpp | 68 + .../MultiByteToWideChar/test2/testinfo.dat | 13 + .../MultiByteToWideChar/test3/CMakeLists.txt | 13 + .../MultiByteToWideChar/test3/test3.cpp | 73 + .../MultiByteToWideChar/test3/testinfo.dat | 15 + .../MultiByteToWideChar/test4/CMakeLists.txt | 13 + .../MultiByteToWideChar/test4/test4.cpp | 230 + .../MultiByteToWideChar/test4/testinfo.dat | 13 + .../WideCharToMultiByte/CMakeLists.txt | 5 + .../WideCharToMultiByte/test1/CMakeLists.txt | 13 + .../WideCharToMultiByte/test1/test1.cpp | 102 + .../WideCharToMultiByte/test1/testinfo.dat | 14 + .../WideCharToMultiByte/test2/CMakeLists.txt | 13 + .../WideCharToMultiByte/test2/test2.cpp | 88 + .../WideCharToMultiByte/test2/testinfo.dat | 13 + .../WideCharToMultiByte/test3/CMakeLists.txt | 13 + .../WideCharToMultiByte/test3/test3.cpp | 100 + .../WideCharToMultiByte/test3/testinfo.dat | 14 + .../WideCharToMultiByte/test4/CMakeLists.txt | 13 + .../WideCharToMultiByte/test4/test4.cpp | 131 + .../WideCharToMultiByte/test4/testinfo.dat | 12 + .../WideCharToMultiByte/test5/CMakeLists.txt | 13 + .../WideCharToMultiByte/test5/test5.cpp | 154 + .../WideCharToMultiByte/test5/testinfo.dat | 13 + .../src/pal/tests/palsuite/manual-inspect.dat | 17 + .../tests/palsuite/manual-unautomatable.dat | 33 + .../miscellaneous/CGroup/CMakeLists.txt | 2 + .../miscellaneous/CGroup/test1/CMakeLists.txt | 13 + .../miscellaneous/CGroup/test1/test.cpp | 53 + .../miscellaneous/CGroup/test1/testinfo.dat | 12 + .../palsuite/miscellaneous/CMakeLists.txt | 33 + .../miscellaneous/CharNextA/CMakeLists.txt | 3 + .../CharNextA/test1/CMakeLists.txt | 13 + .../CharNextA/test2/CMakeLists.txt | 13 + .../miscellaneous/CharNextExA/CMakeLists.txt | 3 + .../CharNextExA/test1/CMakeLists.txt | 13 + .../CharNextExA/test2/CMakeLists.txt | 13 + .../miscellaneous/CloseHandle/CMakeLists.txt | 3 + .../CloseHandle/test1/CMakeLists.txt | 13 + .../miscellaneous/CloseHandle/test1/test.cpp | 64 + .../CloseHandle/test1/testinfo.dat | 15 + .../CloseHandle/test2/CMakeLists.txt | 13 + .../miscellaneous/CloseHandle/test2/test.cpp | 46 + .../CloseHandle/test2/testinfo.dat | 15 + .../miscellaneous/CreatePipe/CMakeLists.txt | 2 + .../CreatePipe/test1/CMakeLists.txt | 13 + .../miscellaneous/CreatePipe/test1/test1.cpp | 113 + .../CreatePipe/test1/testinfo.dat | 15 + .../FlushInstructionCache/CMakeLists.txt | 2 + .../test1/CMakeLists.txt | 13 + .../FlushInstructionCache/test1/test1.cpp | 66 + .../FlushInstructionCache/test1/testinfo.dat | 13 + .../FormatMessageW/CMakeLists.txt | 7 + .../FormatMessageW/test1/CMakeLists.txt | 13 + .../FormatMessageW/test1/test.cpp | 63 + .../FormatMessageW/test1/testinfo.dat | 16 + .../FormatMessageW/test2/CMakeLists.txt | 13 + .../FormatMessageW/test2/test.cpp | 581 ++ .../FormatMessageW/test2/testinfo.dat | 15 + .../FormatMessageW/test3/CMakeLists.txt | 13 + .../FormatMessageW/test3/test.cpp | 85 + .../FormatMessageW/test3/testinfo.dat | 15 + .../FormatMessageW/test4/CMakeLists.txt | 13 + .../FormatMessageW/test4/test.cpp | 77 + .../FormatMessageW/test4/testinfo.dat | 15 + .../FormatMessageW/test5/CMakeLists.txt | 13 + .../FormatMessageW/test5/test.cpp | 76 + .../FormatMessageW/test5/testinfo.dat | 12 + .../FormatMessageW/test6/CMakeLists.txt | 13 + .../FormatMessageW/test6/test.cpp | 78 + .../FormatMessageW/test6/testinfo.dat | 15 + .../FreeEnvironmentStringsW/CMakeLists.txt | 3 + .../test1/CMakeLists.txt | 13 + .../FreeEnvironmentStringsW/test1/test.cpp | 53 + .../test1/testinfo.dat | 15 + .../test2/CMakeLists.txt | 13 + .../FreeEnvironmentStringsW/test2/test.cpp | 71 + .../test2/testinfo.dat | 16 + .../GetCommandLineW/CMakeLists.txt | 2 + .../GetCommandLineW/test1/CMakeLists.txt | 13 + .../GetCommandLineW/test1/test.cpp | 71 + .../GetCommandLineW/test1/testinfo.dat | 15 + .../GetEnvironmentStringsW/CMakeLists.txt | 2 + .../test1/CMakeLists.txt | 13 + .../GetEnvironmentStringsW/test1/test.cpp | 81 + .../GetEnvironmentStringsW/test1/testinfo.dat | 16 + .../GetEnvironmentVariableA/CMakeLists.txt | 7 + .../test1/CMakeLists.txt | 13 + .../GetEnvironmentVariableA/test1/test.cpp | 84 + .../test1/testinfo.dat | 16 + .../test2/CMakeLists.txt | 13 + .../GetEnvironmentVariableA/test2/test.cpp | 56 + .../test2/testinfo.dat | 16 + .../test3/CMakeLists.txt | 13 + .../GetEnvironmentVariableA/test3/test.cpp | 67 + .../test3/testinfo.dat | 16 + .../test4/CMakeLists.txt | 13 + .../GetEnvironmentVariableA/test4/test.cpp | 75 + .../test4/testinfo.dat | 16 + .../test5/CMakeLists.txt | 13 + .../GetEnvironmentVariableA/test5/test5.cpp | 145 + .../test5/testinfo.dat | 17 + .../test6/CMakeLists.txt | 13 + .../GetEnvironmentVariableA/test6/test6.cpp | 99 + .../test6/testinfo.dat | 15 + .../GetEnvironmentVariableW/CMakeLists.txt | 7 + .../test1/CMakeLists.txt | 13 + .../GetEnvironmentVariableW/test1/test.cpp | 79 + .../test1/testinfo.dat | 16 + .../test2/CMakeLists.txt | 13 + .../GetEnvironmentVariableW/test2/test.cpp | 56 + .../test2/testinfo.dat | 16 + .../test3/CMakeLists.txt | 13 + .../GetEnvironmentVariableW/test3/test.cpp | 71 + .../test3/testinfo.dat | 16 + .../test4/CMakeLists.txt | 13 + .../GetEnvironmentVariableW/test4/test.cpp | 63 + .../test4/testinfo.dat | 16 + .../test5/CMakeLists.txt | 13 + .../GetEnvironmentVariableW/test5/test5.cpp | 144 + .../test5/testinfo.dat | 17 + .../test6/CMakeLists.txt | 13 + .../GetEnvironmentVariableW/test6/test6.cpp | 99 + .../test6/testinfo.dat | 15 + .../miscellaneous/GetLastError/CMakeLists.txt | 2 + .../GetLastError/test1/CMakeLists.txt | 13 + .../miscellaneous/GetLastError/test1/test.cpp | 63 + .../GetLastError/test1/testinfo.dat | 15 + .../GetSystemInfo/CMakeLists.txt | 2 + .../GetSystemInfo/test1/CMakeLists.txt | 13 + .../GetSystemInfo/test1/test.cpp | 70 + .../GetSystemInfo/test1/testinfo.dat | 16 + .../miscellaneous/GetTickCount/CMakeLists.txt | 2 + .../GetTickCount/test1/CMakeLists.txt | 13 + .../miscellaneous/GetTickCount/test1/test.cpp | 58 + .../GetTickCount/test1/testinfo.dat | 16 + .../GlobalMemoryStatusEx/CMakeLists.txt | 2 + .../GlobalMemoryStatusEx/test1/CMakeLists.txt | 13 + .../GlobalMemoryStatusEx/test1/test.cpp | 55 + .../GlobalMemoryStatusEx/test1/testinfo.dat | 14 + .../InterLockedExchangeAdd/CMakeLists.txt | 2 + .../test1/CMakeLists.txt | 13 + .../InterLockedExchangeAdd/test1/test.cpp | 102 + .../InterlockedBit/CMakeLists.txt | 3 + .../InterlockedBit/test1/CMakeLists.txt | 13 + .../InterlockedBit/test1/test.cpp | 77 + .../InterlockedBit/test1/testinfo.dat | 14 + .../InterlockedBit/test2/CMakeLists.txt | 13 + .../InterlockedBit/test2/test.cpp | 77 + .../InterlockedBit/test2/testinfo.dat | 14 + .../InterlockedCompareExchange/CMakeLists.txt | 3 + .../test1/CMakeLists.txt | 13 + .../InterlockedCompareExchange/test1/test.cpp | 100 + .../test1/testinfo.dat | 16 + .../test2/CMakeLists.txt | 13 + .../InterlockedCompareExchange/test2/test.cpp | 168 + .../CMakeLists.txt | 3 + .../test1/CMakeLists.txt | 13 + .../test1/test.cpp | 101 + .../test1/testinfo.dat | 16 + .../test2/CMakeLists.txt | 13 + .../test2/test.cpp | 104 + .../CMakeLists.txt | 2 + .../test1/CMakeLists.txt | 13 + .../test1/test.cpp | 80 + .../test1/testinfo.dat | 16 + .../InterlockedDecrement/CMakeLists.txt | 3 + .../InterlockedDecrement/test1/CMakeLists.txt | 13 + .../InterlockedDecrement/test1/test.cpp | 60 + .../InterlockedDecrement/test1/testinfo.dat | 16 + .../InterlockedDecrement/test2/CMakeLists.txt | 13 + .../InterlockedDecrement/test2/test.cpp | 94 + .../InterlockedDecrement64/CMakeLists.txt | 3 + .../test1/CMakeLists.txt | 13 + .../InterlockedDecrement64/test1/test.cpp | 67 + .../InterlockedDecrement64/test1/testinfo.dat | 16 + .../test2/CMakeLists.txt | 13 + .../InterlockedDecrement64/test2/test.cpp | 99 + .../InterlockedExchange/CMakeLists.txt | 2 + .../InterlockedExchange/test1/CMakeLists.txt | 13 + .../InterlockedExchange/test1/test.cpp | 69 + .../InterlockedExchange/test1/testinfo.dat | 16 + .../InterlockedExchange64/CMakeLists.txt | 2 + .../test1/CMakeLists.txt | 13 + .../InterlockedExchange64/test1/test.cpp | 74 + .../InterlockedExchange64/test1/testinfo.dat | 16 + .../InterlockedExchangePointer/CMakeLists.txt | 2 + .../test1/CMakeLists.txt | 13 + .../test1/InterlockedExchangePointer.cpp | 64 + .../test1/testinfo.dat | 12 + .../InterlockedIncrement/CMakeLists.txt | 3 + .../InterlockedIncrement/test1/CMakeLists.txt | 13 + .../InterlockedIncrement/test1/test.cpp | 62 + .../InterlockedIncrement/test1/testinfo.dat | 16 + .../InterlockedIncrement/test2/CMakeLists.txt | 13 + .../InterlockedIncrement/test2/test.cpp | 95 + .../InterlockedIncrement64/CMakeLists.txt | 3 + .../test1/CMakeLists.txt | 13 + .../InterlockedIncrement64/test1/test.cpp | 67 + .../InterlockedIncrement64/test1/testinfo.dat | 16 + .../test2/CMakeLists.txt | 13 + .../InterlockedIncrement64/test2/test.cpp | 101 + .../miscellaneous/IsBadCodePtr/CMakeLists.txt | 2 + .../IsBadCodePtr/test1/CMakeLists.txt | 13 + .../IsBadCodePtr/test1/test1.cpp | 60 + .../IsBadCodePtr/test1/testinfo.dat | 13 + .../miscellaneous/IsBadReadPtr/CMakeLists.txt | 2 + .../IsBadReadPtr/test1/CMakeLists.txt | 13 + .../miscellaneous/IsBadReadPtr/test1/test.cpp | 138 + .../IsBadReadPtr/test1/testinfo.dat | 15 + .../IsBadWritePtr/CMakeLists.txt | 4 + .../IsBadWritePtr/test1/CMakeLists.txt | 13 + .../IsBadWritePtr/test1/test.cpp | 81 + .../IsBadWritePtr/test1/testinfo.dat | 16 + .../IsBadWritePtr/test2/CMakeLists.txt | 13 + .../IsBadWritePtr/test2/test2.cpp | 127 + .../IsBadWritePtr/test2/testinfo.dat | 19 + .../IsBadWritePtr/test3/CMakeLists.txt | 13 + .../IsBadWritePtr/test3/test3.cpp | 56 + .../IsBadWritePtr/test3/testinfo.dat | 17 + .../miscellaneous/MessageBoxW/CMakeLists.txt | 3 + .../MessageBoxW/test1/CMakeLists.txt | 13 + .../miscellaneous/MessageBoxW/test1/test.cpp | 81 + .../MessageBoxW/test1/testinfo.dat | 15 + .../MessageBoxW/test2/CMakeLists.txt | 13 + .../miscellaneous/MessageBoxW/test2/test.cpp | 76 + .../MessageBoxW/test2/testinfo.dat | 15 + .../SetEnvironmentVariableA/CMakeLists.txt | 5 + .../test1/CMakeLists.txt | 13 + .../SetEnvironmentVariableA/test1/test1.cpp | 168 + .../test1/testinfo.dat | 19 + .../test2/CMakeLists.txt | 13 + .../SetEnvironmentVariableA/test2/test2.cpp | 85 + .../test2/testinfo.dat | 19 + .../test3/CMakeLists.txt | 13 + .../SetEnvironmentVariableA/test3/test3.cpp | 144 + .../test3/testinfo.dat | 18 + .../test4/CMakeLists.txt | 13 + .../SetEnvironmentVariableA/test4/test4.cpp | 100 + .../test4/testinfo.dat | 18 + .../SetEnvironmentVariableW/CMakeLists.txt | 5 + .../test1/CMakeLists.txt | 13 + .../SetEnvironmentVariableW/test1/test.cpp | 142 + .../test1/testinfo.dat | 18 + .../test2/CMakeLists.txt | 13 + .../SetEnvironmentVariableW/test2/test.cpp | 88 + .../test2/testinfo.dat | 18 + .../test3/CMakeLists.txt | 13 + .../SetEnvironmentVariableW/test3/test3.cpp | 143 + .../test3/testinfo.dat | 14 + .../test4/CMakeLists.txt | 13 + .../SetEnvironmentVariableW/test4/test4.cpp | 99 + .../test4/testinfo.dat | 15 + .../miscellaneous/SetLastError/CMakeLists.txt | 2 + .../SetLastError/test1/CMakeLists.txt | 13 + .../miscellaneous/SetLastError/test1/test.cpp | 59 + .../SetLastError/test1/testinfo.dat | 16 + .../miscellaneous/_i64tow/CMakeLists.txt | 2 + .../_i64tow/test1/CMakeLists.txt | 13 + .../miscellaneous/_i64tow/test1/test1.cpp | 76 + .../miscellaneous/_i64tow/test1/testinfo.dat | 13 + .../queryperformancecounter/CMakeLists.txt | 2 + .../test1/CMakeLists.txt | 13 + .../queryperformancecounter/test1/test1.cpp | 107 + .../test1/testinfo.dat | 11 + .../queryperformancefrequency/CMakeLists.txt | 2 + .../test1/CMakeLists.txt | 13 + .../queryperformancefrequency/test1/test1.cpp | 59 + .../test1/testinfo.dat | 12 + .../palsuite/pal_specific/CMakeLists.txt | 9 + .../PAL_GetPALDirectoryW/CMakeLists.txt | 2 + .../PAL_GetPALDirectoryW/test1/CMakeLists.txt | 13 + .../test1/PAL_GetPALDirectoryW.cpp | 78 + .../PAL_GetPALDirectoryW/test1/testinfo.dat | 12 + .../PAL_GetUserTempDirectoryW/CMakeLists.txt | 2 + .../test1/CMakeLists.txt | 13 + .../test1/PAL_GetUserTempDirectoryW.cpp | 58 + .../test1/testinfo.dat | 13 + .../PAL_Initialize_Terminate/CMakeLists.txt | 3 + .../test1/CMakeLists.txt | 13 + .../test1/PAL_Initialize_Terminate.cpp | 33 + .../test1/testinfo.dat | 13 + .../test2/CMakeLists.txt | 13 + .../test2/pal_initialize_twice.cpp | 41 + .../test2/testinfo.dat | 15 + .../CMakeLists.txt | 3 + .../test1/CMakeLists.txt | 13 + ...AL_RegisterLibraryW_UnregisterLibraryW.cpp | 64 + .../test1/testinfo.dat | 13 + .../test2_neg/CMakeLists.txt | 13 + .../test2_neg/reg_unreg_libraryw_neg.cpp | 62 + .../test2_neg/testinfo.dat | 14 + .../pal_specific/PAL_errno/CMakeLists.txt | 2 + .../PAL_errno/test1/CMakeLists.txt | 13 + .../PAL_errno/test1/PAL_errno.cpp | 53 + .../pal_specific/PAL_errno/test1/testinfo.dat | 12 + .../PAL_get_stderr/CMakeLists.txt | 2 + .../PAL_get_stderr/test1/CMakeLists.txt | 13 + .../PAL_get_stderr/test1/PAL_get_stderr.cpp | 52 + .../PAL_get_stderr/test1/testinfo.dat | 14 + .../pal_specific/PAL_get_stdin/CMakeLists.txt | 2 + .../PAL_get_stdin/test1/CMakeLists.txt | 13 + .../PAL_get_stdin/test1/PAL_get_stdin.cpp | 68 + .../PAL_get_stdin/test1/testinfo.dat | 14 + .../PAL_get_stdout/CMakeLists.txt | 2 + .../PAL_get_stdout/test1/CMakeLists.txt | 13 + .../PAL_get_stdout/test1/PAL_get_stdout.cpp | 52 + .../PAL_get_stdout/test1/testinfo.dat | 13 + .../src/pal/tests/palsuite/paltestlist.txt | 716 +++ .../palsuite/paltestlist_to_be_reviewed.txt | 163 + .../src/pal/tests/palsuite/runpaltests.sh | 213 + .../pal/tests/palsuite/samples/CMakeLists.txt | 3 + .../palsuite/samples/test1/CMakeLists.txt | 13 + .../pal/tests/palsuite/samples/test1/test.cpp | 41 + .../tests/palsuite/samples/test1/testinfo.dat | 14 + .../palsuite/samples/test2/CMakeLists.txt | 13 + .../pal/tests/palsuite/samples/test2/test.cpp | 48 + .../tests/palsuite/samples/test2/testinfo.dat | 13 + .../src/pal/tests/palsuite/smoketest.script | 100 + .../src/pal/tests/palsuite/tests-manual.dat | 12 + .../tests/palsuite/threading/CMakeLists.txt | 42 + .../threading/CreateEventA/CMakeLists.txt | 4 + .../CreateEventA/test1/CMakeLists.txt | 13 + .../threading/CreateEventA/test1/test1.cpp | 95 + .../threading/CreateEventA/test1/testinfo.dat | 14 + .../CreateEventA/test2/CMakeLists.txt | 13 + .../threading/CreateEventA/test2/test2.cpp | 84 + .../threading/CreateEventA/test2/testinfo.dat | 14 + .../CreateEventA/test3/CMakeLists.txt | 13 + .../threading/CreateEventA/test3/test3.cpp | 219 + .../threading/CreateEventA/test3/testinfo.dat | 16 + .../threading/CreateEventW/CMakeLists.txt | 4 + .../CreateEventW/test1/CMakeLists.txt | 13 + .../threading/CreateEventW/test1/test1.cpp | 93 + .../threading/CreateEventW/test1/testinfo.dat | 14 + .../CreateEventW/test2/CMakeLists.txt | 13 + .../threading/CreateEventW/test2/test2.cpp | 85 + .../threading/CreateEventW/test2/testinfo.dat | 14 + .../CreateEventW/test3/CMakeLists.txt | 13 + .../threading/CreateEventW/test3/test3.cpp | 233 + .../threading/CreateEventW/test3/testinfo.dat | 16 + .../CreateMutexA_ReleaseMutex/CMakeLists.txt | 3 + .../test1/CMakeLists.txt | 13 + .../test1/CreateMutexA.cpp | 344 ++ .../test1/testinfo.dat | 33 + .../test2/CMakeLists.txt | 13 + .../test2/CreateMutexA.cpp | 331 ++ .../test2/testinfo.dat | 24 + .../CreateMutexW_ReleaseMutex/CMakeLists.txt | 3 + .../test1/CMakeLists.txt | 13 + .../test1/CreateMutexW.cpp | 344 ++ .../test1/testinfo.dat | 33 + .../test2/CMakeLists.txt | 13 + .../test2/CreateMutexW.cpp | 340 ++ .../test2/testinfo.dat | 24 + .../threading/CreateProcessA/CMakeLists.txt | 3 + .../CreateProcessA/test1/CMakeLists.txt | 28 + .../CreateProcessA/test1/childProcess.cpp | 131 + .../CreateProcessA/test1/parentProcess.cpp | 201 + .../CreateProcessA/test1/testinfo.dat | 17 + .../CreateProcessA/test2/CMakeLists.txt | 28 + .../CreateProcessA/test2/childprocess.cpp | 69 + .../CreateProcessA/test2/parentprocess.cpp | 243 + .../threading/CreateProcessA/test2/test2.h | 72 + .../CreateProcessA/test2/testinfo.dat | 20 + .../threading/CreateProcessW/CMakeLists.txt | 3 + .../CreateProcessW/test1/CMakeLists.txt | 28 + .../CreateProcessW/test1/childProcess.cpp | 150 + .../CreateProcessW/test1/parentProcess.cpp | 210 + .../CreateProcessW/test1/testinfo.dat | 17 + .../CreateProcessW/test2/CMakeLists.txt | 28 + .../CreateProcessW/test2/childprocess.cpp | 78 + .../CreateProcessW/test2/parentprocess.cpp | 245 + .../threading/CreateProcessW/test2/test2.h | 31 + .../CreateProcessW/test2/testinfo.dat | 20 + .../CMakeLists.txt | 4 + .../test1/CMakeLists.txt | 13 + .../test1/CreateSemaphore.cpp | 322 ++ .../test1/testinfo.dat | 18 + .../test2/CMakeLists.txt | 13 + .../test2/CreateSemaphore.cpp | 313 + .../test2/testinfo.dat | 18 + .../test3/CMakeLists.txt | 13 + .../test3/createsemaphore.cpp | 200 + .../test3/testinfo.dat | 20 + .../CMakeLists.txt | 4 + .../test1/CMakeLists.txt | 13 + .../test1/CreateSemaphore.cpp | 323 ++ .../test1/testinfo.dat | 18 + .../test2/CMakeLists.txt | 13 + .../test2/CreateSemaphore.cpp | 314 + .../test2/testinfo.dat | 18 + .../test3/CMakeLists.txt | 13 + .../test3/createsemaphore.cpp | 201 + .../test3/testinfo.dat | 20 + .../threading/CreateThread/CMakeLists.txt | 4 + .../CreateThread/test1/CMakeLists.txt | 13 + .../threading/CreateThread/test1/test1.cpp | 115 + .../threading/CreateThread/test1/testinfo.dat | 14 + .../CreateThread/test2/CMakeLists.txt | 13 + .../threading/CreateThread/test2/test2.cpp | 184 + .../threading/CreateThread/test2/testinfo.dat | 13 + .../CreateThread/test3/CMakeLists.txt | 13 + .../threading/CreateThread/test3/test3.cpp | 101 + .../threading/CreateThread/test3/testinfo.dat | 14 + .../CriticalSectionFunctions/CMakeLists.txt | 9 + .../test1/CMakeLists.txt | 13 + .../test1/InitializeCriticalSection.cpp | 235 + .../test1/testinfo.dat | 21 + .../test2/CMakeLists.txt | 13 + .../CriticalSectionFunctions/test2/test2.cpp | 226 + .../test2/testinfo.dat | 18 + .../test3/CMakeLists.txt | 13 + .../CriticalSectionFunctions/test3/test3.cpp | 376 ++ .../test3/testinfo.dat | 29 + .../test4/CMakeLists.txt | 13 + .../CriticalSectionFunctions/test4/test4.cpp | 241 + .../test4/testinfo.dat | 17 + .../test5/CMakeLists.txt | 13 + .../CriticalSectionFunctions/test5/test5.cpp | 187 + .../test5/testinfo.dat | 12 + .../test6/CMakeLists.txt | 13 + .../CriticalSectionFunctions/test6/test6.cpp | 190 + .../test6/testinfo.dat | 12 + .../test7/CMakeLists.txt | 13 + .../CriticalSectionFunctions/test7/test7.cpp | 188 + .../test7/testinfo.dat | 12 + .../test8/CMakeLists.txt | 13 + .../CriticalSectionFunctions/test8/test8.cpp | 217 + .../test8/thistest.dat | 2 + .../DisableThreadLibraryCalls/test1/test1.cpp | 145 + .../test1/testinfo.dat | 15 + .../test1/testlib.cpp | 47 + .../test2/dllmain1.cpp | 66 + .../test2/dllmain2.cpp | 66 + .../DisableThreadLibraryCalls/test2/test2.cpp | 237 + .../test2/testinfo.dat | 18 + .../threading/DuplicateHandle/CMakeLists.txt | 12 + .../DuplicateHandle/test1/CMakeLists.txt | 13 + .../threading/DuplicateHandle/test1/test1.cpp | 152 + .../DuplicateHandle/test1/testinfo.dat | 15 + .../DuplicateHandle/test10/CMakeLists.txt | 13 + .../DuplicateHandle/test10/test10.cpp | 239 + .../DuplicateHandle/test10/testinfo.dat | 17 + .../DuplicateHandle/test11/CMakeLists.txt | 28 + .../DuplicateHandle/test11/childprocess.cpp | 74 + .../DuplicateHandle/test11/myexitcode.h | 13 + .../DuplicateHandle/test11/test11.cpp | 364 ++ .../DuplicateHandle/test11/testinfo.dat | 19 + .../DuplicateHandle/test12/CMakeLists.txt | 13 + .../DuplicateHandle/test12/test12.cpp | 129 + .../DuplicateHandle/test12/testinfo.dat | 15 + .../DuplicateHandle/test2/CMakeLists.txt | 13 + .../threading/DuplicateHandle/test2/test2.cpp | 96 + .../DuplicateHandle/test2/testinfo.dat | 17 + .../DuplicateHandle/test3/CMakeLists.txt | 13 + .../threading/DuplicateHandle/test3/test3.cpp | 123 + .../DuplicateHandle/test3/testinfo.dat | 17 + .../DuplicateHandle/test4/CMakeLists.txt | 13 + .../threading/DuplicateHandle/test4/test4.cpp | 239 + .../DuplicateHandle/test4/testinfo.dat | 19 + .../DuplicateHandle/test5/CMakeLists.txt | 13 + .../threading/DuplicateHandle/test5/test5.cpp | 145 + .../DuplicateHandle/test5/testinfo.dat | 14 + .../DuplicateHandle/test6/CMakeLists.txt | 13 + .../threading/DuplicateHandle/test6/test6.cpp | 146 + .../DuplicateHandle/test6/testinfo.dat | 15 + .../DuplicateHandle/test7/CMakeLists.txt | 13 + .../threading/DuplicateHandle/test7/test7.cpp | 178 + .../DuplicateHandle/test7/testinfo.dat | 16 + .../DuplicateHandle/test8/CMakeLists.txt | 13 + .../threading/DuplicateHandle/test8/test8.cpp | 164 + .../DuplicateHandle/test8/testinfo.dat | 16 + .../DuplicateHandle/test9/CMakeLists.txt | 13 + .../threading/DuplicateHandle/test9/test9.cpp | 127 + .../DuplicateHandle/test9/testinfo.dat | 17 + .../threading/ExitProcess/CMakeLists.txt | 4 + .../ExitProcess/test1/CMakeLists.txt | 13 + .../ExitProcess/test1/ExitProcess.cpp | 32 + .../threading/ExitProcess/test1/testinfo.dat | 13 + .../ExitProcess/test2/CMakeLists.txt | 13 + .../threading/ExitProcess/test2/test2.cpp | 30 + .../threading/ExitProcess/test2/testinfo.dat | 14 + .../ExitProcess/test3/CMakeLists.txt | 13 + .../threading/ExitProcess/test3/test3.cpp | 40 + .../threading/ExitProcess/test3/testinfo.dat | 14 + .../threading/ExitThread/CMakeLists.txt | 3 + .../threading/ExitThread/test1/CMakeLists.txt | 13 + .../threading/ExitThread/test1/test1.cpp | 114 + .../threading/ExitThread/test1/testinfo.dat | 14 + .../threading/ExitThread/test2/CMakeLists.txt | 28 + .../ExitThread/test2/childprocess.cpp | 41 + .../threading/ExitThread/test2/myexitcode.h | 14 + .../threading/ExitThread/test2/test2.cpp | 168 + .../threading/ExitThread/test2/testinfo.dat | 19 + .../threading/ExitThread/test3/dllmain.cpp | 65 + .../threading/ExitThread/test3/test3.cpp | 162 + .../threading/ExitThread/test3/testinfo.dat | 16 + .../GetCurrentProcess/CMakeLists.txt | 2 + .../GetCurrentProcess/test1/CMakeLists.txt | 13 + .../GetCurrentProcess/test1/process.cpp | 40 + .../GetCurrentProcess/test1/testinfo.dat | 13 + .../GetCurrentProcessId/CMakeLists.txt | 2 + .../GetCurrentProcessId/test1/CMakeLists.txt | 13 + .../GetCurrentProcessId/test1/processId.cpp | 41 + .../GetCurrentProcessId/test1/testinfo.dat | 13 + .../threading/GetCurrentThread/CMakeLists.txt | 3 + .../GetCurrentThread/test1/CMakeLists.txt | 13 + .../GetCurrentThread/test1/testinfo.dat | 12 + .../GetCurrentThread/test1/thread.cpp | 93 + .../GetCurrentThread/test2/CMakeLists.txt | 13 + .../GetCurrentThread/test2/test2.cpp | 144 + .../GetCurrentThread/test2/testinfo.dat | 18 + .../GetCurrentThreadId/CMakeLists.txt | 2 + .../GetCurrentThreadId/test1/CMakeLists.txt | 13 + .../GetCurrentThreadId/test1/testinfo.dat | 13 + .../GetCurrentThreadId/test1/threadId.cpp | 82 + .../GetExitCodeProcess/CMakeLists.txt | 2 + .../GetExitCodeProcess/test1/CMakeLists.txt | 28 + .../GetExitCodeProcess/test1/childProcess.cpp | 31 + .../GetExitCodeProcess/test1/myexitcode.h | 14 + .../GetExitCodeProcess/test1/test1.cpp | 163 + .../GetExitCodeProcess/test1/testinfo.dat | 16 + .../threading/GetProcessTimes/CMakeLists.txt | 2 + .../GetProcessTimes/test2/CMakeLists.txt | 13 + .../threading/GetProcessTimes/test2/test2.cpp | 122 + .../GetProcessTimes/test2/testinfo.dat | 15 + .../threading/GetThreadTimes/CMakeLists.txt | 1 + .../GetThreadTimes/test1/CMakeLists.txt | 13 + .../threading/GetThreadTimes/test1/test1.cpp | 102 + .../threading/NamedMutex/CMakeLists.txt | 2 + .../threading/NamedMutex/test1/CMakeLists.txt | 14 + .../threading/NamedMutex/test1/namedmutex.cpp | 1130 ++++ .../threading/NamedMutex/test1/nopal.cpp | 66 + .../threading/NamedMutex/test1/testinfo.dat | 14 + .../threading/OpenEventW/CMakeLists.txt | 6 + .../threading/OpenEventW/test1/CMakeLists.txt | 13 + .../threading/OpenEventW/test1/test1.cpp | 134 + .../threading/OpenEventW/test1/testinfo.dat | 15 + .../threading/OpenEventW/test2/CMakeLists.txt | 13 + .../threading/OpenEventW/test2/test2.cpp | 194 + .../threading/OpenEventW/test2/testinfo.dat | 17 + .../threading/OpenEventW/test3/CMakeLists.txt | 28 + .../OpenEventW/test3/childprocess.cpp | 81 + .../threading/OpenEventW/test3/test3.cpp | 187 + .../threading/OpenEventW/test3/testinfo.dat | 21 + .../threading/OpenEventW/test4/CMakeLists.txt | 13 + .../threading/OpenEventW/test4/test4.cpp | 112 + .../threading/OpenEventW/test4/testinfo.dat | 14 + .../threading/OpenEventW/test5/CMakeLists.txt | 13 + .../threading/OpenEventW/test5/test5.cpp | 197 + .../threading/OpenEventW/test5/testinfo.dat | 19 + .../threading/OpenProcess/CMakeLists.txt | 2 + .../OpenProcess/test1/CMakeLists.txt | 28 + .../OpenProcess/test1/childProcess.cpp | 75 + .../threading/OpenProcess/test1/myexitcode.h | 14 + .../threading/OpenProcess/test1/test1.cpp | 282 + .../threading/OpenProcess/test1/testinfo.dat | 19 + .../QueryThreadCycleTime/CMakeLists.txt | 1 + .../QueryThreadCycleTime/test1/CMakeLists.txt | 13 + .../QueryThreadCycleTime/test1/test1.cpp | 98 + .../threading/QueueUserAPC/CMakeLists.txt | 8 + .../QueueUserAPC/test1/CMakeLists.txt | 13 + .../threading/QueueUserAPC/test1/test1.cpp | 313 + .../threading/QueueUserAPC/test1/testinfo.dat | 15 + .../QueueUserAPC/test2/CMakeLists.txt | 13 + .../threading/QueueUserAPC/test2/test2.cpp | 224 + .../threading/QueueUserAPC/test2/testinfo.dat | 13 + .../QueueUserAPC/test3/CMakeLists.txt | 13 + .../threading/QueueUserAPC/test3/test3.cpp | 33 + .../threading/QueueUserAPC/test3/testinfo.dat | 12 + .../QueueUserAPC/test4/CMakeLists.txt | 13 + .../threading/QueueUserAPC/test4/test4.cpp | 72 + .../threading/QueueUserAPC/test4/testinfo.dat | 14 + .../QueueUserAPC/test5/CMakeLists.txt | 13 + .../threading/QueueUserAPC/test5/test5.cpp | 200 + .../threading/QueueUserAPC/test5/testinfo.dat | 20 + .../QueueUserAPC/test6/CMakeLists.txt | 13 + .../threading/QueueUserAPC/test6/test6.cpp | 129 + .../threading/QueueUserAPC/test6/testinfo.dat | 14 + .../QueueUserAPC/test7/CMakeLists.txt | 13 + .../threading/QueueUserAPC/test7/test7.cpp | 253 + .../threading/QueueUserAPC/test7/testinfo.dat | 14 + .../threading/ReleaseMutex/CMakeLists.txt | 2 + .../ReleaseMutex/test3/CMakeLists.txt | 13 + .../ReleaseMutex/test3/ReleaseMutex.cpp | 103 + .../threading/ReleaseMutex/test3/testinfo.dat | 13 + .../threading/ResetEvent/CMakeLists.txt | 5 + .../threading/ResetEvent/test1/CMakeLists.txt | 13 + .../threading/ResetEvent/test1/test1.cpp | 99 + .../threading/ResetEvent/test1/testinfo.dat | 14 + .../threading/ResetEvent/test2/CMakeLists.txt | 13 + .../threading/ResetEvent/test2/test2.cpp | 89 + .../threading/ResetEvent/test2/testinfo.dat | 14 + .../threading/ResetEvent/test3/CMakeLists.txt | 13 + .../threading/ResetEvent/test3/test3.cpp | 86 + .../threading/ResetEvent/test3/testinfo.dat | 15 + .../threading/ResetEvent/test4/CMakeLists.txt | 13 + .../threading/ResetEvent/test4/test4.cpp | 161 + .../threading/ResetEvent/test4/testinfo.dat | 15 + .../threading/ResumeThread/CMakeLists.txt | 2 + .../ResumeThread/test1/CMakeLists.txt | 13 + .../threading/ResumeThread/test1/test1.cpp | 141 + .../threading/ResumeThread/test1/testinfo.dat | 14 + .../threading/SetErrorMode/CMakeLists.txt | 2 + .../SetErrorMode/test1/CMakeLists.txt | 13 + .../threading/SetErrorMode/test1/test1.cpp | 50 + .../threading/SetErrorMode/test1/testinfo.dat | 16 + .../threading/SetEvent/CMakeLists.txt | 5 + .../threading/SetEvent/test1/CMakeLists.txt | 13 + .../threading/SetEvent/test1/test1.cpp | 94 + .../threading/SetEvent/test1/testinfo.dat | 14 + .../threading/SetEvent/test2/CMakeLists.txt | 13 + .../threading/SetEvent/test2/test2.cpp | 125 + .../threading/SetEvent/test2/testinfo.dat | 13 + .../threading/SetEvent/test3/CMakeLists.txt | 13 + .../threading/SetEvent/test3/test3.cpp | 85 + .../threading/SetEvent/test3/testinfo.dat | 15 + .../threading/SetEvent/test4/CMakeLists.txt | 13 + .../threading/SetEvent/test4/test4.cpp | 161 + .../threading/SetEvent/test4/testinfo.dat | 15 + .../SignalObjectAndWait/CMakeLists.txt | 13 + .../SignalObjectAndWaitTest.cpp | 414 ++ .../palsuite/threading/Sleep/CMakeLists.txt | 3 + .../threading/Sleep/test1/CMakeLists.txt | 13 + .../palsuite/threading/Sleep/test1/Sleep.cpp | 80 + .../threading/Sleep/test1/testinfo.dat | 13 + .../threading/Sleep/test2/CMakeLists.txt | 13 + .../palsuite/threading/Sleep/test2/sleep.cpp | 73 + .../threading/Sleep/test2/testinfo.dat | 13 + .../palsuite/threading/SleepEx/CMakeLists.txt | 3 + .../threading/SleepEx/test1/CMakeLists.txt | 13 + .../threading/SleepEx/test1/test1.cpp | 89 + .../threading/SleepEx/test1/testinfo.dat | 13 + .../threading/SleepEx/test2/CMakeLists.txt | 13 + .../threading/SleepEx/test2/test2.cpp | 183 + .../threading/SleepEx/test2/testinfo.dat | 14 + .../threading/SwitchToThread/CMakeLists.txt | 2 + .../SwitchToThread/test1/CMakeLists.txt | 13 + .../threading/SwitchToThread/test1/test1.cpp | 97 + .../SwitchToThread/test1/testinfo.dat | 13 + .../threading/TerminateProcess/CMakeLists.txt | 2 + .../TerminateProcess/test1/CMakeLists.txt | 13 + .../test1/TerminateProcess.cpp | 41 + .../TerminateProcess/test1/testinfo.dat | 14 + .../threading/ThreadPriority/CMakeLists.txt | 2 + .../ThreadPriority/test1/CMakeLists.txt | 13 + .../ThreadPriority/test1/ThreadPriority.cpp | 83 + .../ThreadPriority/test1/testinfo.dat | 17 + .../WaitForMultipleObjects/CMakeLists.txt | 2 + .../test1/CMakeLists.txt | 13 + .../WaitForMultipleObjects/test1/test1.cpp | 224 + .../WaitForMultipleObjects/test1/testinfo.dat | 14 + .../WaitForMultipleObjectsEx/CMakeLists.txt | 7 + .../test1/CMakeLists.txt | 13 + .../WaitForMultipleObjectsEx/test1/test1.cpp | 226 + .../test1/testinfo.dat | 14 + .../test2/CMakeLists.txt | 13 + .../WaitForMultipleObjectsEx/test2/test2.cpp | 188 + .../test2/testinfo.dat | 14 + .../test3/CMakeLists.txt | 13 + .../WaitForMultipleObjectsEx/test3/test3.cpp | 106 + .../test3/testinfo.dat | 14 + .../test4/CMakeLists.txt | 13 + .../WaitForMultipleObjectsEx/test4/test4.cpp | 101 + .../test4/testinfo.dat | 14 + .../test5/CMakeLists.txt | 28 + .../test5/commonconsts.h | 42 + .../WaitForMultipleObjectsEx/test5/helper.cpp | 122 + .../WaitForMultipleObjectsEx/test5/test5.cpp | 506 ++ .../test5/testinfo.dat | 18 + .../test6/CMakeLists.txt | 28 + .../WaitForMultipleObjectsEx/test6/child6.cpp | 211 + .../WaitForMultipleObjectsEx/test6/test6.cpp | 709 +++ .../test6/thistest.dat | 2 + .../WaitForSingleObject/CMakeLists.txt | 9 + .../WFSOExMutexTest/CMakeLists.txt | 13 + .../WFSOExMutexTest/WFSOExMutexTest.cpp | 214 + .../WFSOExSemaphoreTest/CMakeLists.txt | 13 + .../WFSOExSemaphoreTest.cpp | 184 + .../WFSOExThreadTest/CMakeLists.txt | 13 + .../WFSOExThreadTest/WFSOExThreadTest.cpp | 204 + .../WFSOMutexTest/CMakeLists.txt | 13 + .../WFSOMutexTest/WFSOMutexTest.cpp | 184 + .../WFSOProcessTest/CMakeLists.txt | 28 + .../WFSOProcessTest/ChildProcess.cpp | 50 + .../WFSOProcessTest/WFSOProcessTest.cpp | 119 + .../WFSOSemaphoreTest/CMakeLists.txt | 13 + .../WFSOSemaphoreTest/WFSOSemaphoreTest.cpp | 183 + .../WFSOThreadTest/CMakeLists.txt | 13 + .../WFSOThreadTest/WFSOThreadTest.cpp | 179 + .../WaitForSingleObject/test1/CMakeLists.txt | 13 + .../WaitForSingleObject/test1/test1.cpp | 121 + .../WaitForSingleObject/test1/testinfo.dat | 14 + .../threading/YieldProcessor/CMakeLists.txt | 2 + .../YieldProcessor/test1/CMakeLists.txt | 13 + .../threading/YieldProcessor/test1/test1.cpp | 92 + .../YieldProcessor/test1/testinfo.dat | 13 + .../threading/releasesemaphore/CMakeLists.txt | 2 + .../releasesemaphore/test1/CMakeLists.txt | 13 + .../threading/releasesemaphore/test1/test.cpp | 68 + .../releasesemaphore/test1/testinfo.dat | 15 + .../src/pal/tools/gen-buildsys.cmd | 52 + .../src/pal/tools/gen-dactable-rva.sh | 1 + .../src/pal/tools/preptests.sh | 69 + .../src/pal/tools/set-cmake-path.ps1 | 76 + .../src/pal/tools/setup-ubuntuvm.sh | 27 + .../coreclr_headers/src/pal/tools/smarty.sh | 26 + CoreCLRProfiler/native/profiler_pal.h | 2 - 4440 files changed, 323922 insertions(+), 16461 deletions(-) delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/apithreadstress.cpp delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/apithreadstress.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/circularlog.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs/dir.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs/file.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivappxhosting.idl delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivhosting.idl delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivruntimebinders.idl create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/clrversion.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/corinfoinstructionset.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/ecmakey.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/jitperf.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/lazycow.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/mdfileformat.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/patchpointinfo.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/perflog.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/readytoruninstructionset.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/sha1.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/strongname.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/strongnameholders.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/strongnameinternal.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/thekey.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/unreachable.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/vererror.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/inc/warningcontrol.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/CMakeLists.txt delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal_char16.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal_unwind.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/atl.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/atlcom.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/atlwin.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/vsassert.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/corerror/makecorerror.bat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/corerror/mscorurt.rc create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/corerror/readme.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrdata_i.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrinternal_i.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrprivappxhosting_i.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrprivbinding_i.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/cordebug_i.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/corprof_i.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/corpub_i.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/corsym_i.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/mscorsvc_i.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/sospriv_i.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/xclrdata_i.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/xcordebug_i.cpp delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/asm_version.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/buildnumber.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrprivhosting.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrprivruntimebinders.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fxverstrings.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/ndpversion_generated.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/product_version.h delete mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/version.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/.tpattributes create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/activationhandlerwrapper.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/asmconstants.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/callsignalhandlerwrapper.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/context.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/context2.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/debugbreak.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/dispatchexceptionwrapper.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/exceptionhelper.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/processor.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/signalhandlerhelper.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/asmconstants.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/callsignalhandlerwrapper.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/context2.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/debugbreak.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/exceptionhelper.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/processor.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/signalhandlerhelper.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/asmconstants.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/callsignalhandlerwrapper.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/context2.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/debugbreak.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/exceptionhelper.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/processor.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/signalhandlerhelper.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/asmconstants.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/callsignalhandlerwrapper.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/context2.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/debugbreak.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/exceptionhelper.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/processor.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/signalhandlerhelper.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/build_tools/mdtool_dummy create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/build_tools/mdtool_gcc.in create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/config.h.in create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/configure.cmake create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/file.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/filecrt.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/malloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/math.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/mbstring.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/misc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/path.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/printf.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/printfcpp.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/silent_printf.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/string.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/stringtls.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/thread.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/wchar.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/wchartls.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/dummyprovider/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/lttngprovider/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/lttngprovider/eventproviderhelpers.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machexception.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machexception.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machmessage.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machmessage.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/remote-unwind.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/seh-unwind.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/seh.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/signal.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/directory.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/file.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/filetime.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/find.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/path.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/handlemgr/handleapi.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/handlemgr/handlemgr.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cert.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cgroup.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/context.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/corunix.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/corunix.inl create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/critsect.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cruntime.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cs.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/dbgmsg.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/debug.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/environ.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/event.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/fakepoll.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/file.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/file.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/filetime.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/handleapi.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/handlemgr.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/init.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/list.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/malloc.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/map.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/map.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/misc.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/module.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/modulename.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/mutex.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/numa.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/palinternal.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/perftrace.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/printfcpp.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/process.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/procobj.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/seh.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/semaphore.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/sharedmemory.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/sharedmemory.inl create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/shm.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/shmemory.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/signal.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/stackstring.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/synchcache.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/synchobjects.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/thread.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/threadinfo.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/threadsusp.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/unicodedata.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/utf8.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/utils.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/virtual.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/init/pal.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/init/sxs.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/.gitignore create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/.travis.yml create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/AUTHORS create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/COPYING create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/ChangeLog create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/LICENSE create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/Makefile.am create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/NEWS create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/README create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/README.md create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/TODO create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/acinclude.m4 create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/autogen.sh create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/aux_/config.guess create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/aux_/config.sub create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/aux_/ltmain.sh create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/configure.ac create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/Makefile.am create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/NOTES create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_cancel.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_cancel.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_register.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_register.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/common.tex.in create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-dynamic.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-dynamic.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ia64.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ia64.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ptrace.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ptrace.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-setjmp.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-setjmp.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind.trans create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_apply_reg_state.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_apply_reg_state.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_backtrace.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_backtrace.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_create_addr_space.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_create_addr_space.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_destroy_addr_space.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_destroy_addr_space.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_flush_cache.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_flush_cache.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_accessors.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_accessors.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_fpreg.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_fpreg.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_name.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_name.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_reg.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_reg.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_getcontext.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_getcontext.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_local.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_local.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_local2.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_remote.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_remote.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_fpreg.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_fpreg.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_signal_frame.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_signal_frame.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_reg_states_iterate.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_reg_states_iterate.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_regname.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_regname.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_resume.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_resume.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_cache_size.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_cache_size.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_caching_policy.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_caching_policy.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_fpreg.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_fpreg.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_reg.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_reg.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_step.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_step.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_strerror.man create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_strerror.tex create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/compiler.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/dwarf-eh.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/dwarf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-aarch64.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-arm.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-common.h.in create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-coredump.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-dynamic.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-hppa.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ia64.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-mips.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ppc32.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ppc64.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ptrace.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-sh.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-tilegx.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-x86.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-x86_64.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind.h.in create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/mempool.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/remote.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-aarch64/dwarf-config.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-aarch64/jmpbuf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-arm/dwarf-config.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-arm/ex_tables.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-arm/jmpbuf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-hppa/dwarf-config.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-hppa/jmpbuf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ia64/jmpbuf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ia64/rse.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ia64/script.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-mips/dwarf-config.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-mips/jmpbuf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc32/dwarf-config.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc32/jmpbuf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc64/dwarf-config.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc64/jmpbuf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-sh/dwarf-config.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-sh/jmpbuf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-tilegx/dwarf-config.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-tilegx/jmpbuf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86/dwarf-config.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86/jmpbuf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86_64/dwarf-config.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86_64/jmpbuf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep/dwarf-config.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep/jmpbuf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep/libunwind_i.h.in create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/unwind.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/scripts/kernel-diff.sh create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/scripts/kernel-files.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/scripts/make-L-files create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/Makefile.am create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ginit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ginit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ginit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Greg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gstash_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gtrace.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Linit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Linit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Linit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lreg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lstash_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ltrace.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/gen-offsets.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/getcontext.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/init.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/is_fpreg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/offsets.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/regname.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/siglongjmp.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gex_tables.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ginit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ginit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ginit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gos-freebsd.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gos-linux.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gos-other.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Greg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gstash_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gtrace.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lex_tables.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Linit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Linit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Linit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Los-freebsd.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Los-linux.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Los-other.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lreg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lstash_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ltrace.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/gen-offsets.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/getcontext.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/init.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/is_fpreg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/offsets.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/regname.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/siglongjmp.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/config.h.in create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/configure.cmake create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/README create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_access_mem.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_access_reg_freebsd.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_accessors.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_create.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_destroy.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_elf_map_image.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_find_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_get_proc_name.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_internal.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_lib.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_access_fpreg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_elf.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_get_dyn_info_list_addr.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_put_unwind_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_resume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/libunwind-coredump.pc.in create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gexpr.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gfde.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gfind_proc_info-lsb.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gfind_unwind_table.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gparser.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gpe.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lexpr.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lfde.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lfind_proc_info-lsb.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lfind_unwind_table.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lparser.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lpe.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/global.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf32.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf32.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf64.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf64.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elfxx.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elfxx.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Ginit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Ginit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Ginit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Greg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Linit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Linit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Linit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lreg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/get_accessors.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/getcontext.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/init.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/offsets.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/regname.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/setcontext.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/siglongjmp.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/tables.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gfind_unwind_table.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginstall_cursor.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gparser.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Grbs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Greg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gscript.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gtables.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lfind_unwind_table.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linstall_cursor.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lparser.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lrbs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lreg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lscript.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ltables.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/NOTES create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/dyn_info_list.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/getcontext.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/init.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/longjmp.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/mk_cursor_i create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/offsets.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/regname.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/regs.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/setjmp.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/siglongjmp.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/sigsetjmp.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/unwind_decoder.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/libunwind-generic.pc.in create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gdestroy_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gdyn-extract.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gdyn-remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gfind_dynamic_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_accessors.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_fpreg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_proc_info_by_ip.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_proc_name.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_reg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gput_dynamic_unwind_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_cache_size.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_caching_policy.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_fpreg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_reg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Ldestroy_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Ldyn-extract.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Ldyn-remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lfind_dynamic_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_accessors.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_fpreg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_proc_info_by_ip.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_proc_name.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_reg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lput_dynamic_unwind_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_cache_size.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_caching_policy.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_fpreg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_reg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/_ReadSLEB.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/_ReadULEB.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/backtrace.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/dyn-cancel.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/dyn-info-list.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/dyn-register.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/flush_cache.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/init.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/mempool.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/strerror.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Ginit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Ginit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Ginit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Greg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Linit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Linit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Linit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lreg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/elfxx.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/gen-offsets.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/getcontext.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/init.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/is_fpreg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/offsets.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/regname.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/siglongjmp.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/oop/_OOP_find_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/oop/_OOP_internal.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-freebsd.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-hpux.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-linux.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-linux.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-qnx.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Ginit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Ginit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Greg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Linit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Linit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lreg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/longjmp.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/siglongjmp.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Ginit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Greg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Linit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lreg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Make-arch.in create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/get_func_addr.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/init.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/is_fpreg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/regname.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/setcontext.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Ginit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Greg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Linit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lreg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/get_func_addr.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/init.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/is_fpreg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/regname.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/setcontext.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_access_fpreg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_access_mem.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_access_reg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_accessors.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_create.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_destroy.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_elf.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_find_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_get_dyn_info_list_addr.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_get_proc_name.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_internal.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_put_unwind_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_resume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/libunwind-ptrace.pc.in create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/libunwind-setjmp.pc.in create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/longjmp.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/setjmp.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/siglongjmp.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/sigsetjmp.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Ginit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Ginit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Ginit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Greg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Linit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Linit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Linit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lreg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/gen-offsets.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/init.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/is_fpreg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/offsets.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/regname.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/siglongjmp.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Ginit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Ginit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Ginit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Greg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Linit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Linit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Linit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lis_signal_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lreg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/elfxx.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/gen-offsets.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/getcontext.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/init.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/is_fpreg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/offsets.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/regname.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/siglongjmp.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/Backtrace.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/DeleteException.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/FindEnclosingFunction.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/ForcedUnwind.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetBSP.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetCFA.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetDataRelBase.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetGR.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetIP.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetIPInfo.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetLanguageSpecificData.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetRegionStart.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetTextRelBase.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/RaiseException.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/Resume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/Resume_or_Rethrow.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/SetGR.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/SetIP.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/libunwind.pc.in create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/unwind-internal.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ginit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ginit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ginit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gos-freebsd.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gos-linux.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Greg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gstash_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gtrace.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lapply_reg_state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lcreate_addr_space.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lget_proc_info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lget_save_loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lglobal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Linit.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Linit_local.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Linit_remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Los-freebsd.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Los-linux.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lreg_states_iterate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lregs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lresume.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lstash_frame.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lstep.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ltrace.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/getcontext.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/init.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/is_fpreg.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/longjmp.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/offsets.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/regname.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/setcontext.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/siglongjmp.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-nat.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-rbs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-readonly.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-stack.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gperf-simple.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gperf-trace.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-bt.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-concurrent.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-dyn1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-exc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-init.cxx create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-nomalloc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-resume-sig-rt.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-resume-sig.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-trace.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-nat.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-rbs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-readonly.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-stack.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lperf-simple.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lperf-trace.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lrs-race.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-bt.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-concurrent.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-cxx-exceptions.cxx create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-dyn1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-exc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-init-local-signal-lib.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-init-local-signal.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-init.cxx create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-mem-validate.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-nocalloc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-nomalloc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-resume-sig-rt.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-resume-sig.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-trace.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-varargs.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Makefile.am create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/check-namespace.sh.in create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/crasher.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/flush-cache.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/flush-cache.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/forker.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-dyn-asm.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-dyn1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-nat-asm.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-rbs-asm.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-rbs.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-readonly-asm.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-setjmp.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-sig.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-stack-asm.S create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-stack.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ident.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/mapper.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/perf-startup create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ppc64-test-altivec-utils.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ppc64-test-altivec.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-check-namespace create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-coredump-unwind create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-coredump-unwind-mdi create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-ia64-test-dyn1 create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-ptrace-mapper create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-ptrace-misc create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-async-sig.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-coredump-unwind.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-flush-cache.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-init-remote.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-mem.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-proc-info.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-ptrace-misc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-ptrace.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-reg-state.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-setjmp.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-static-link-gen.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-static-link-loc.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-strerror.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/loader/module.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/loader/modulename.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/unicode.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/unicodedata.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/unicodedata.cs create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/utf8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/common.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/common.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/map.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/virtual.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/memory/local.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/cgroup.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/dbgmsg.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/environ.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/error.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/errorstrings.cpp rename CoreCLRProfiler/native/coreclr_headers/src/pal/{prebuilt/inc/ndpversion.h => src/misc/errorstrings.h} (63%) create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/fmtmessage.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/jitsupport.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/miscpalapi.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/msgbox.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/perfjitdump.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/perftrace.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/strutil.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/sysinfo.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/time.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/tracepointprovider.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/utils.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/numa/numa.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/numa/numashim.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/palobjbase.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/palobjbase.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobject.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobject.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobjectmanager.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobjectmanager.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/poll/fakepoll.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/cruntime.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/input.inl create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/internal.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/internal_securecrt.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/makepath_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/mbusafecrt.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/mbusafecrt_internal.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/memcpy_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/memmove_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/output.inl create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_input_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_output_l.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_output_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_winput_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_woutput_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/snprintf.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/splitpath_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/sprintf_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/sscanf_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strcat_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strcpy_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strlen_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strncat_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strncpy_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strtok_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/swprintf.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcscat_s.inl create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcscpy_s.inl create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcsncat_s.inl create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcsncpy_s.inl create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcstok_s.inl create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tmakepath_s.inl create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tsplitpath_s.inl create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/vsprintf.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/vswprint.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcscat_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcscpy_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcslen_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcsncat_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcsncpy_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcstok_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wmakepath_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wsplitpath_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/xtoa_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/xtow_s.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/xtox_s.inl create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/sharedmemory/sharedmemory.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/shmemory/shmemory.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/sync/cs.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/synchcontrollers.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/synchmanager.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/synchmanager.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/wait.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchobj/event.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchobj/mutex.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchobj/semaphore.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/context.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/process.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/procprivate.hpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/thread.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/threadsusp.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/DisabledTests.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/README.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/test1/__iscsym.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finite/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finite/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finite/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finite/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finitef/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finitef/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finitef/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finitef/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test1/_gcvt.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/_snprintf_s.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/test18.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/test19.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/_snwprintf_s.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/test18.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/test19.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/_vsnprintf_s.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test18/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test18/test18.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test18/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test19/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test19/test19.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test19/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/_vsnwprintf_s.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/test18.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/test19.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/test1/abs.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/testfile create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/testfile create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/fprintf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test18/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test18/test18.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test18/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test19/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test19/test19.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test19/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/testfile create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/testfile create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/testfile create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/ftell.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/testfile.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/fwprintf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test18/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test18/test18.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test18/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test19/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test19/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test1/isprint.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isspace/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isspace/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isspace/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isspace/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/printf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test18/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test18/test18.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test18/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test19/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test19/test19.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test19/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/sprintf_s.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/test18.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/test19.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/sscanf_s.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcspn/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcspn/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcspn/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcspn/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strlen/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strlen/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strlen/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strlen/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strspn/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strspn/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strspn/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strspn/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strstr/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strstr/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strstr/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strstr/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtoul/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtoul/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtoul/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtoul/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/swprintf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test18/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test18/test18.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test18/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test19/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test19/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/swscanf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/test1/test1.c create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test18/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test18/test18.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test18/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test19/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test19/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/vfprintf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test18/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test18/test18.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test18/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test19/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test19/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/vprintf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test18/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test18/test18.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test18/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test19/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test19/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/vsprintf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test13/test13.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test14/test14.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test15/test15.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test16/test16.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test17/test17.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test18/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test18/test18.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test18/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test19/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test19/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/vswprintf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/wprintf.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/ResultBuffer.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/ResultBuffer.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/ResultTime.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/pal_stdclib.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/palsuite.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/nonshared/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/nonshared/event.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/nonshared/main.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/shared/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/shared/event.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/shared/main.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/main.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/mutex.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/shared/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/shared/main.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/shared/mutex.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/readme.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/main.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/semaphore.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/shared/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/shared/main.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/shared/semaphore.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/readme.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/readme.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/hpitinterlock.s create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/interlocked.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/makefile create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/notes.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/readme.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/sparcinterloc.s create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/mainWrapper.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/readme.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/samplefile.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/threadsuspension.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/mainWrapper.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/readme.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/samplefile.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/threadsuspension.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/main.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/mutex.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/readme.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/helper.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/commonconsts.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/commonconsts.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/helper.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/helper.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/eventprovider/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.src create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.src create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/ExpectedResults.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/winoutput create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/winoutput create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/test1/DeleteFileA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/test1/DeleteFileW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FILECanonicalizePath/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FILECanonicalizePath/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/test1/FindClose.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/FindFirstFileA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/FindFirstFileW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test1/FindNextFileA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test2/findnextfilea.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test1/FindNextFileW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test2/findnextfilew.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/FlushFileBuffers.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/GetConsoleOutputCP.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/GetCurrentDirectoryA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/GetCurrentDirectoryW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/keepme create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/keepme create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/GetFileAttributesA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/keepme create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/keepme create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/keepme create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/keepme create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/anchor.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/keepme create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/keepme create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/keepme create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/keepme create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/GetFileAttributesW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/keepme create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/keepme create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/keepme create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_file create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/keepme create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/test1/GetFileSize.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/GetFileSizeEx.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/GetFullPathNameA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/GetFullPathNameW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test1/GetStdHandle.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test2/GetStdHandle.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/GetSystemTimeAsFileTime.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/ExpectedResults.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/MoveFileExA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/ExpectedResults.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/MoveFileExW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/NonReadableFile.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/ReadFile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test3/ReadFile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test4/readfile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/RemoveDirectoryA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/RemoveDirectoryW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/SetEndOfFile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/SetEndOfFile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/SetEndOfFile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/setendoffile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test1/SetFilePointer.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test2/SetFilePointer.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test3/SetFilePointer.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test4/SetFilePointer.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test5/SetFilePointer.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test6/SetFilePointer.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test7/SetFilePointer.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/Results.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test3/WriteFile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test4/writefile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test5/writefile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/test1/gettemppatha.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CreateFileMapping.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CreateFileMapping.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CreateFileMapping.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CreateFileMapping.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CreateFileMapping.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/createfilemapping.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/createfilemapping.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/createfilemapping.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CreateFileMapping_neg.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CreateFileMappingW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CreateFileMappingW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CreateFileMappingW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CreateFileMappingW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CreateFileMappingW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/createfilemapping.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/createfilemapping.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/createfilemapping.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/FreeLibrary.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/dlltest.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/dlltest.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/GetModuleFileNameA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/GetModuleFileNameA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testlib.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testlib.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/MapViewOfFile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/MapViewOfFile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/mapviewoffile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/mapviewoffile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/mapviewoffile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/OpenFileMappingA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/OpenFileMappingA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/OpenFileMappingA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/OpenFileMappingW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/OpenFileMappingW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/OpenFileMappingW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/ProbeMemory_neg.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/ProbeMemory.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/UnmapViewOfFile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/unmapviewoffile.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/virtualalloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/virtualalloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/VirtualAlloc.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/VirtualFree.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/VirtualFree.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/VirtualFree.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/VirtualProtect.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/VirtualProtect.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/VirtualProtect.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/VirtualProtect.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/VirtualProtect.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/VirtualProtect.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/VirtualQuery.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test1/LoadLibraryA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/LoadLibraryA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/MyModule.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test3/loadlibrarya.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/dlltest.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test7/LoadLibraryA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/dlltest.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test1/LoadLibraryW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test2/loadlibraryw.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test3/loadlibraryw.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/manual-inspect.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/manual-unautomatable.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextExA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/InterlockedExchangePointer.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/_i64tow/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/PAL_Initialize_Terminate.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/pal_initialize_twice.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/PAL_errno.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/PAL_get_stderr.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/PAL_get_stdin.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/PAL_get_stdout.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/paltestlist.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/runpaltests.sh create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test2/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/smoketest.script create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/tests-manual.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CreateMutexA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CreateMutexA.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CreateMutexW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CreateMutexW.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/childProcess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/parentProcess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/childprocess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/parentprocess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/test2.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/parentProcess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/childprocess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/parentprocess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/test2.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CreateSemaphore.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CreateSemaphore.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/createsemaphore.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CreateSemaphore.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/createsemaphore.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/thistest.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testlib.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test10/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test10/test10.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test10/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/childprocess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/myexitcode.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/test11.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test12/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test12/test12.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test12/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test8/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test8/test8.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test8/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test9/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test9/test9.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test9/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test1/ExitProcess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/childprocess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/myexitcode.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test3/dllmain.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/process.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/processId.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test1/thread.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/threadId.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/childProcess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/myexitcode.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetThreadTimes/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetThreadTimes/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/childprocess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/childProcess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/myexitcode.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueryThreadCycleTime/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test6/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test7/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test7/test7.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test7/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/test3/ReleaseMutex.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SignalObjectAndWait/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SignalObjectAndWait/SignalObjectAndWaitTest.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test1/Sleep.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test2/sleep.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/test1/TerminateProcess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/test1/ThreadPriority.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/test3.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/test4.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/commonconsts.h create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/child6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/test6.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/thistest.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/WFSOMutexTest.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/ChildProcess.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/WFSOProcessTest.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/WFSOSemaphoreTest.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/WFSOThreadTest.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/test1/test1.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/test1/CMakeLists.txt create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/test1/test.cpp create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/test1/testinfo.dat create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tools/gen-buildsys.cmd create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tools/gen-dactable-rva.sh create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tools/preptests.sh create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tools/set-cmake-path.ps1 create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tools/setup-ubuntuvm.sh create mode 100644 CoreCLRProfiler/native/coreclr_headers/src/pal/tools/smarty.sh diff --git a/CoreCLRProfiler/native/BPerfProfilerCallback.cpp b/CoreCLRProfiler/native/BPerfProfilerCallback.cpp index 7bac365..8f9a6be 100644 --- a/CoreCLRProfiler/native/BPerfProfilerCallback.cpp +++ b/CoreCLRProfiler/native/BPerfProfilerCallback.cpp @@ -82,7 +82,7 @@ BPerfProfilerCallback::~BPerfProfilerCallback() HRESULT STDMETHODCALLTYPE BPerfProfilerCallback::Initialize(IUnknown* pICorProfilerInfoUnk) { - const HRESULT queryInterfaceResult = pICorProfilerInfoUnk->QueryInterface(__uuidof(ICorProfilerInfo10), reinterpret_cast(&this->corProfilerInfo)); + const HRESULT queryInterfaceResult = pICorProfilerInfoUnk->QueryInterface(__uuidof(ICorProfilerInfo11), reinterpret_cast(&this->corProfilerInfo)); if (FAILED(queryInterfaceResult)) { diff --git a/CoreCLRProfiler/native/BPerfProfilerCallback.h b/CoreCLRProfiler/native/BPerfProfilerCallback.h index 67e3b72..3df9778 100644 --- a/CoreCLRProfiler/native/BPerfProfilerCallback.h +++ b/CoreCLRProfiler/native/BPerfProfilerCallback.h @@ -222,7 +222,7 @@ public: private: std::atomic refCount; - ICorProfilerInfo10* corProfilerInfo; + ICorProfilerInfo11* corProfilerInfo; /* Exception Counters */ std::atomic numberOfExceptionsThrown; diff --git a/CoreCLRProfiler/native/CMakeLists.txt b/CoreCLRProfiler/native/CMakeLists.txt index 8f215ed..4d41844 100644 --- a/CoreCLRProfiler/native/CMakeLists.txt +++ b/CoreCLRProfiler/native/CMakeLists.txt @@ -13,4 +13,4 @@ if ("${LINK_TYPE}" STREQUAL "Static") add_compile_options(/MT$<$:d>) add_link_options(/SOURCELINK:${SourceLinkJson}) endif() -add_library (Microsoft.BPerf.CoreCLRProfiler SHARED "BPerfProfilerCallback.cpp" "BPerfProfilerCallback.h" "Microsoft.BPerf.CoreCLRProfiler.cpp" "ETWHeaders.h" "CQuickBytes.h" "CQuickBytes.cpp" "PrettyPrintSig.cpp" "sha1.cpp" "sha1.h" "profiler_pal.h" "PortableString.h" "exports.def") +add_library (Microsoft.BPerf.CoreCLRProfiler SHARED "BPerfProfilerCallback.cpp" "BPerfProfilerCallback.h" "Microsoft.BPerf.CoreCLRProfiler.cpp" "ETWHeaders.h" "CQuickBytes.h" "CQuickBytes.cpp" "PrettyPrintSig.cpp" "sha1.cpp" "sha1.h" "profiler_pal.h" "PortableString.h" "coreclr_headers/src/pal/prebuilt/idl/corprof_i.cpp" "exports.def") diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/inc/CMakeLists.txt index c38d595..60fad88 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/CMakeLists.txt +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/CMakeLists.txt @@ -7,63 +7,51 @@ set( CORGUIDS_IDL_SOURCES corprof.idl corpub.idl mscorsvc.idl - clrprivappxhosting.idl clrprivbinding.idl - clrprivhosting.idl - clrprivruntimebinders.idl corsym.idl sospriv.idl ) -if(WIN32) -#Build for corguids is done in two steps: -#1. compile .idl to *_i.c : This is done using custom midl command -#2. compile *_i.c to .lib +if(CLR_CMAKE_HOST_WIN32) + #Build for corguids is done in two steps: + #1. compile .idl to *_i.c : This is done using custom midl command + #2. compile *_i.c to .lib -# Get the current list of definitions to pass to midl -get_compile_definitions(MIDL_DEFINITIONS) -get_include_directories(MIDL_INCLUDE_DIRECTORIES) + # Get the current list of definitions to pass to midl + get_compile_definitions(MIDL_DEFINITIONS) + get_include_directories(MIDL_INCLUDE_DIRECTORIES) -# Run custom midl command over each idl file -FIND_PROGRAM( MIDL midl.exe ) -foreach(GENERATE_IDL IN LISTS CORGUIDS_IDL_SOURCES) - get_filename_component(IDLNAME ${GENERATE_IDL} NAME_WE) - set(OUT_NAME ${CMAKE_CURRENT_BINARY_DIR}/idls_out/${IDLNAME}_i.c) - list(APPEND CORGUIDS_SOURCES ${OUT_NAME}) - add_custom_command(OUTPUT ${OUT_NAME} + # Run custom midl command over each idl file + FIND_PROGRAM( MIDL midl.exe ) + foreach(GENERATE_IDL IN LISTS CORGUIDS_IDL_SOURCES) + get_filename_component(IDLNAME ${GENERATE_IDL} NAME_WE) + set(OUT_NAME ${CMAKE_CURRENT_BINARY_DIR}/idls_out/${IDLNAME}_i.c) + list(APPEND CORGUIDS_SOURCES ${OUT_NAME}) + add_custom_command(OUTPUT ${OUT_NAME} COMMAND ${MIDL} ${MIDL_INCLUDE_DIRECTORIES} /h ${CMAKE_CURRENT_BINARY_DIR}/idls_out/${IDLNAME}.h ${MIDL_DEFINITIONS} /out ${CMAKE_CURRENT_BINARY_DIR}/idls_out ${CMAKE_CURRENT_SOURCE_DIR}/${GENERATE_IDL} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${GENERATE_IDL} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${GENERATE_IDL} COMMENT "Compiling ${GENERATE_IDL}") -endforeach(GENERATE_IDL) + endforeach(GENERATE_IDL) -set_source_files_properties(${CORGUIDS_SOURCES} + set_source_files_properties(${CORGUIDS_SOURCES} PROPERTIES GENERATED TRUE) -# Compile *_i.c as C files -add_compile_options(/TC) + # Compile *_i.c as C files + add_compile_options(/TC) -else() +else(CLR_CMAKE_HOST_WIN32) -#The MIDL tool exists for Windows only, so for other systems, we have the prebuilt xxx_i.cpp files checked in + #The MIDL tool exists for Windows only, so for other systems, we have the prebuilt xxx_i.cpp files checked in -# The prebuilt files contain extra '!_MIDL_USE_GUIDDEF_' after the #endif, but not in the comment. -# In order to not to have to modify these prebuilt files, we disable the extra tokens warning. -if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") -add_compile_options(-Wno-extra-tokens) -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") -add_compile_options(-Wno-endif-labels) -endif() + add_compile_options(-D_MIDL_USE_GUIDDEF_) + foreach(IDL_SOURCE IN LISTS CORGUIDS_IDL_SOURCES) + get_filename_component(IDLNAME ${IDL_SOURCE} NAME_WE) + set(C_SOURCE ../pal/prebuilt/idl/${IDLNAME}_i.cpp) + list(APPEND CORGUIDS_SOURCES ${C_SOURCE}) + endforeach(IDL_SOURCE) -add_compile_options(-D_MIDL_USE_GUIDDEF_) -foreach(IDL_SOURCE IN LISTS CORGUIDS_IDL_SOURCES) - get_filename_component(IDLNAME ${IDL_SOURCE} NAME_WE) - set(C_SOURCE ../pal/prebuilt/idl/${IDLNAME}_i.cpp) - list(APPEND CORGUIDS_SOURCES ${C_SOURCE}) -endforeach(IDL_SOURCE) - -add_compile_options(-fPIC) -endif(WIN32) +endif(CLR_CMAKE_HOST_WIN32) if(FEATURE_JIT_PITCHING) add_definitions(-DFEATURE_JIT_PITCHING) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/CrstTypeTool.cs b/CoreCLRProfiler/native/coreclr_headers/src/inc/CrstTypeTool.cs index 0310ec3..f32ade2 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/CrstTypeTool.cs +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/CrstTypeTool.cs @@ -2,13 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// +// // This tool exists to transform a high level description of Crst dependencies (i.e. which Crst type may be // acquired before or after other Crst types) into a header file that defines a enum to describe each Crst // type and tables that map type to numerical ranking and a string based name. // // To use the tool, run "csc.exe CrstTypeTool.cs" and run the resulting executable. -// +// // The Crst type definition file is written in a very simple language. Comments begin with '//' and continue // to the end of the line. All remaining tokens after comment removal are simply sequences of non-whitespace // characters separated by whitespace. Keywords are case-insensitive and identifiers (which are always Crst @@ -65,7 +65,7 @@ class CrstTypeTool { // Calculate the filenames of the input and output files. string inputFile = "CrstTypes.def"; - string outputFile = "CrstTypes.h"; + string outputFile = "crsttypes.h"; // A common error is to forget to check out the CrstTypes.h file first. Handle this case specially // so we can give a good error message. @@ -143,7 +143,7 @@ class CrstTypeTool writer.WriteLine(); writer.WriteLine("// This file describes the range of Crst types available and their mapping to a numeric level (used by the"); writer.WriteLine("// runtime in debug mode to validate we're deadlock free). To modify these settings edit the"); - writer.WriteLine("// file:CrstTypes.def file and run the clr\\bin\\CrstTypeTool utility to generate a new version of this file."); + writer.WriteLine("// file:CrstTypes.def file and run the clr\\artifacts\\CrstTypeTool utility to generate a new version of this file."); writer.WriteLine(); // Emit the CrstType enum to define a value for each crst type (along with the kNumberOfCrstTypes @@ -173,10 +173,10 @@ class CrstTypeTool writer.WriteLine("int g_rgCrstLevelMap[] ="); writer.WriteLine("{"); foreach (CrstType crst in crsts) - { - string crstLine = " " + crst.Level + ","; - crstLine = crstLine + new string(' ', 16 - crstLine.Length); - writer.WriteLine(crstLine + "// Crst" + crst.Name); + { + string crstLine = " " + crst.Level + ","; + crstLine = crstLine + new string(' ', 16 - crstLine.Length); + writer.WriteLine(crstLine + "// Crst" + crst.Name); } writer.WriteLine("};"); writer.WriteLine(); @@ -803,7 +803,7 @@ class TypeFileParser for (int i = 0; i < expected.Length - 1; i++) message.Append(String.Format("{0}, ", IdToName(expected[i]))); message.Append(IdToName(expected[expected.Length - 1])); - + } return message.ToString(); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/CrstTypes.def b/CoreCLRProfiler/native/coreclr_headers/src/inc/CrstTypes.def index 4dce8f2..06f900a 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/CrstTypes.def +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/CrstTypes.def @@ -105,7 +105,7 @@ Crst AssemblyDependencyGraph End Crst AvailableParamTypes - AcquiredBefore IbcProfile LoaderHeap + AcquiredBefore ModuleLookupTable IbcProfile LoaderHeap End Crst BaseDomain @@ -156,12 +156,8 @@ Crst Contexts StubUnwindInfoHeapSegments SyncBlockCache TypeIDMap UnresolvedClassLock End -Crst CoreCLRBinderLog - Unordered -End - Crst CSPCache - AcquiredBefore JumpStubCache + AcquiredBefore JumpStubCache End Crst DeadlockDetection @@ -169,14 +165,14 @@ End Crst DebuggerController // AcquiredBefore DebuggerHeapLock DebuggerJitInfo LoaderHeap - - // See bug: 581892. This has a conflict with CrstInstMethodHashTableRanking. + + // See bug: 581892. This has a conflict with CrstInstMethodHashTableRanking. // The controller logic will be moved to OOP in V3, and so this lock will no longer be necessary. // Fixing this in-proc would be difficult, and it would all be throwaway as we go oop. Unordered End -// This is a leaf debugger lock. +// This is a leaf debugger lock. Crst DebuggerFavorLock AcquiredAfter DebuggerJitInfo DebuggerMutex End @@ -189,32 +185,32 @@ End Crst DebuggerHeapLock AcquiredAfter DebuggerFavorLock DebuggerJitInfo DebuggerMutex // Disabled per bug 581892 - // AcquiredAfter DebuggerController + // AcquiredAfter DebuggerController End Crst DebuggerJitInfo AcquiredBefore DebuggerHeapLock End -// This is the major debugger lock. +// This is the major debugger lock. // It's the largest of the debugger locks. Crst DebuggerMutex - AcquiredBefore AvailableParamTypes ConnectionNameTable + AcquiredBefore AvailableParamTypes ConnectionNameTable DynamicIL LoaderHeap ModuleLookupTable // Disabled per bug 581892 - // AcquiredBefore DebuggerController + // AcquiredBefore DebuggerController AcquiredBefore DebuggerHeapLock DebuggerJitInfo End -// This lock is used only for testing data consistency (see code:DataTest::TestDataSafety) +// This lock is used only for testing data consistency (see code:DataTest::TestDataSafety) // and is released before taking any other lock except for CrstDataTest2 Crst DataTest1 AcquiredAfter DebuggerMutex End -// This lock is used only for testing data consistency (see code:DataTest::TestDataSafety) +// This lock is used only for testing data consistency (see code:DataTest::TestDataSafety) // and is released before taking any other lockCrst DataTest2 Crst DataTest2 AcquiredAfter DataTest1 @@ -284,7 +280,7 @@ Crst NativeImageCache End Crst GCCover - AcquiredBefore LoaderHeap ReJITDomainTable + AcquiredBefore LoaderHeap CodeVersioning End Crst GCMemoryPressure @@ -355,14 +351,18 @@ End Crst JitGenericHandleCache End +Crst JitPatchpoint + AcquiredBefore LoaderHeap +End + Crst JitPerf Unordered End Crst JumpStubCache AcquiredBefore ExecuteManRangeLock LoaderHeap SingleUseLock - AcquiredAfter AppDomainCache ExecuteManLock - ILStubGen ThreadpoolTimerQueue ThreadpoolWaitThreads + AcquiredAfter AppDomainCache ExecuteManLock + ILStubGen ThreadpoolTimerQueue ThreadpoolWaitThreads TPMethodTable TypeIDMap BaseDomain AssemblyLoader End @@ -482,6 +482,9 @@ End Crst RCWCleanupList End +Crst ExternalObjectContextCache +End + Crst ReDacl End @@ -490,7 +493,7 @@ Crst Reflection End // Used to synchronize all rejit information stored in a given AppDomain. -Crst ReJITDomainTable +Crst CodeVersioning AcquiredBefore LoaderHeap SingleUseLock DeadlockDetection JumpStubCache DebuggerController FuncPtrStubs AcquiredAfter ReJITGlobalRequest ThreadStore GlobalStrLiteralMap SystemDomain DebuggerMutex MethodDescBackpatchInfoTracker End @@ -499,7 +502,7 @@ End // new functions to rejit tables, or request Reverts on existing functions in the rejit // tables. One of these crsts exist per runtime. Crst ReJITGlobalRequest - AcquiredBefore ThreadStore ReJITDomainTable SystemDomain + AcquiredBefore ThreadStore CodeVersioning SystemDomain JitInlineTrackingMap End // ETW infrastructure uses this crst to protect a hash table of TypeHandles which is @@ -507,7 +510,7 @@ End // same type). Crst EtwTypeLogHash AcquiredAfter ThreadStore AllowedFiles Cer TPMethodTable - AcquiredBefore AvailableParamTypes ConnectionNameTable DeadlockDetection DebuggerController + AcquiredBefore AvailableParamTypes ConnectionNameTable DeadlockDetection DebuggerController DebuggerHeapLock DebuggerJitInfo DynamicIL ExecuteManRangeLock HandleTable IbcProfile JitGenericHandleCache JumpStubCache LoaderHeap ModuleLookupTable ProfilingAPIStatus ProfilerGCRefDataFreeList RWLock SingleUseLock SyncBlockCache SystemDomainDelayedUnloadList @@ -616,7 +619,7 @@ Crst ThreadStaticDataHashTable End Crst ThreadStore - AcquiredBefore AvailableParamTypes ConnectionNameTable DeadlockDetection DebuggerController + AcquiredBefore AvailableParamTypes ConnectionNameTable DeadlockDetection DebuggerController DebuggerHeapLock DebuggerJitInfo DynamicIL ExecuteManRangeLock HandleTable IbcProfile JitGenericHandleCache JumpStubCache LoaderHeap ModuleLookupTable ProfilingAPIStatus ProfilerGCRefDataFreeList RWLock SingleUseLock SyncBlockCache SystemDomainDelayedUnloadList @@ -669,10 +672,10 @@ Crst MulticoreJitManager End Crst WinRTFactoryCache - AcquiredBefore HandleTable + AcquiredBefore HandleTable End -Crst SqmManager +Crst SqmManager End Crst StackSampler @@ -683,7 +686,7 @@ Crst InlineTrackingMap End Crst JitInlineTrackingMap - AcquiredBefore ReJITDomainTable ThreadStore LoaderAllocator + AcquiredBefore CodeVersioning ThreadStore LoaderAllocator End Crst EventPipe @@ -699,6 +702,7 @@ Crst ReadyToRunEntryPointToMethodDescMap End Crst TieredCompilation + AcquiredAfter CodeVersioning AcquiredBefore ThreadpoolTimerQueue End @@ -709,3 +713,6 @@ Crst MethodDescBackpatchInfoTracker AcquiredBefore FuncPtrStubs ThreadStore SystemDomain AcquiredAfter ReJITGlobalRequest End + +Crst NativeImageEagerFixups +End diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/MSCOREE.IDL b/CoreCLRProfiler/native/coreclr_headers/src/inc/MSCOREE.IDL index ce368f3..6c2c512 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/MSCOREE.IDL +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/MSCOREE.IDL @@ -10,11 +10,6 @@ ** ** **************************************************************************************/ -cpp_quote("#define DECLARE_DEPRECATED ") -cpp_quote("#define DEPRECATED_CLR_STDAPI STDAPI") - -cpp_quote("") - // // Interface descriptions // @@ -29,9 +24,6 @@ interface IHostControl; cpp_quote("struct ICLRControl;") interface ICLRControl; -// CLSID ComCallUnmarshal2 -cpp_quote("EXTERN_GUID(CLSID_ComCallUnmarshalV4, 0x45fb4600,0xe6e8,0x4928,0xb2,0x5e,0x50,0x47,0x6f,0xf7,0x94,0x25);") - // IID ICLRRuntimeHost: uuid(90F1A06C-7712-4762-86B5-7A5EBA6BDB02) cpp_quote("EXTERN_GUID(IID_ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02);") @@ -63,27 +55,27 @@ typedef enum { STARTUP_SINGLE_VERSION_HOSTING_INTERFACE = 0x4000, // Disallow mixing hosting interface STARTUP_LEGACY_IMPERSONATION = 0x10000, // Do not flow impersonation across async points by default STARTUP_DISABLE_COMMITTHREADSTACK = 0x20000, // Don't eagerly commit thread stack - STARTUP_ALWAYSFLOW_IMPERSONATION = 0x40000, // Force flow impersonation across async points - // (impersonations achieved thru p/invoke and managed will flow. + STARTUP_ALWAYSFLOW_IMPERSONATION = 0x40000, // Force flow impersonation across async points + // (impersonations achieved thru p/invoke and managed will flow. // default is to flow only managed impersonation) STARTUP_TRIM_GC_COMMIT = 0x80000, // GC uses less committed space when system memory low STARTUP_ETW = 0x100000, STARTUP_ARM = 0x400000, // Enable the ARM feature. - STARTUP_SINGLE_APPDOMAIN = 0x800000, // application runs in default domain, no more domains are created + STARTUP_SINGLE_APPDOMAIN = 0x800000, // application runs in default domain, no more domains are created STARTUP_APPX_APP_MODEL = 0x1000000, // jupiter app STARTUP_DISABLE_RANDOMIZED_STRING_HASHING = 0x2000000 // Disable the randomized string hashing (not supported) } STARTUP_FLAGS; typedef enum { - APPDOMAIN_SECURITY_DEFAULT =0x0, + APPDOMAIN_SECURITY_DEFAULT =0x0, APPDOMAIN_SECURITY_SANDBOXED = 0x1, // appdomain is sandboxed APPDOMAIN_SECURITY_FORBID_CROSSAD_REVERSE_PINVOKE = 0x2, // no cross ad reverse pinvokes APPDOMAIN_IGNORE_UNHANDLED_EXCEPTIONS = 0x4, // APPDOMAIN_FORCE_TRIVIAL_WAIT_OPERATIONS = 0x08, // do not pump messages during wait operations, do not call sync context // When passed by the host, this flag will allow any assembly to perform PInvoke or COMInterop operations. // Otherwise, by default, only platform assemblies can perform those operations. - APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP = 0x10, + APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP = 0x10, APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS = 0x40, APPDOMAIN_ENABLE_ASSEMBLY_LOADFILE = 0x80, @@ -97,35 +89,19 @@ typedef enum { WAIT_NOTINDEADLOCK = 0x4 }WAIT_OPTION; -typedef enum ETaskType -{ - TT_DEBUGGERHELPER = 0x1, - TT_GC = 0x2, - TT_FINALIZER = 0x4, - TT_THREADPOOL_TIMER = 0x8, - TT_THREADPOOL_GATE = 0x10, - TT_THREADPOOL_WORKER = 0x20, - TT_THREADPOOL_IOCOMPLETION = 0x40, - TT_ADUNLOAD = 0x80, - TT_USER = 0x100, - TT_THREADPOOL_WAIT = 0x200, - - TT_UNKNOWN = 0x80000000, -} ETaskType; - typedef enum { // Default to minidump DUMP_FLAVOR_Mini = 0, - + // Include critical CLR state DUMP_FLAVOR_CriticalCLRState = 1, - + // Include critical CLR state and ngen images without including hosted heap // It is host's responsibility to report hosted heap. DUMP_FLAVOR_NonHeapCLRState = 2, DUMP_FLAVOR_Default = DUMP_FLAVOR_Mini - + } ECustomDumpFlavor; const DWORD BucketParamsCount = 10; @@ -153,61 +129,6 @@ typedef struct _BucketParameters WCHAR pszParams[BucketParamsCount][BucketParamLength]; // Parameter strings. } BucketParameters; - -typedef enum -{ - OPR_ThreadAbort, - OPR_ThreadRudeAbortInNonCriticalRegion, - OPR_ThreadRudeAbortInCriticalRegion, - OPR_AppDomainUnload, - OPR_AppDomainRudeUnload, - OPR_ProcessExit, - OPR_FinalizerRun, - MaxClrOperation - // Do not add anything after this -} EClrOperation; - -typedef enum -{ - FAIL_NonCriticalResource, - FAIL_CriticalResource, - FAIL_FatalRuntime, - FAIL_OrphanedLock, - FAIL_StackOverflow, - // In CoreCLR, we will treat AV specially, based upon the escalation policy. - // Currently only used in CoreCLR. - FAIL_AccessViolation, - FAIL_CodeContract, - MaxClrFailure - // Do not add anything after this -} EClrFailure; - -typedef enum -{ - eRuntimeDeterminedPolicy, // default - eHostDeterminedPolicy, // revert back to Everett behavior, i.e. swallow all exception -} EClrUnhandledException; - -typedef enum -{ - // !!! Please keep these ordered by severity - // !!! If you don't, you need to change EEPolicy::IsValidActionForOperation - // !!! and EEPolicy::IsValidActionForFailure - eNoAction, - eThrowException, - eAbortThread, - eRudeAbortThread, - eUnloadAppDomain, - eRudeUnloadAppDomain, - eExitProcess, - // Look at CorHost2::Stop. For eFastExitProcess, eRudeExitProcess, eDisableRuntime, - // Stop bypasses finalizer run. - eFastExitProcess, - eRudeExitProcess, - MaxPolicyAction -} EPolicyAction; - - //***************************************************************************** // New interface for hosting mscoree //***************************************************************************** @@ -273,16 +194,16 @@ interface ICLRRuntimeHost2 : ICLRRuntimeHost // set of properties. HRESULT CreateAppDomainWithManager([in] LPCWSTR wszFriendlyName, [in] DWORD dwFlags, - [in] LPCWSTR wszAppDomainManagerAssemblyName, - [in] LPCWSTR wszAppDomainManagerTypeName, - [in] int nProperties, - [in] LPCWSTR* pPropertyNames, - [in] LPCWSTR* pPropertyValues, + [in] LPCWSTR wszAppDomainManagerAssemblyName, + [in] LPCWSTR wszAppDomainManagerTypeName, + [in] int nProperties, + [in] LPCWSTR* pPropertyNames, + [in] LPCWSTR* pPropertyValues, [out] DWORD* pAppDomainID); HRESULT CreateDelegate([in] DWORD appDomainID, - [in] LPCWSTR wszAssemblyName, - [in] LPCWSTR wszClassName, + [in] LPCWSTR wszAssemblyName, + [in] LPCWSTR wszClassName, [in] LPCWSTR wszMethodName, [out] INT_PTR* fnPtr); @@ -320,7 +241,3 @@ interface ICLRRuntimeHost4 : ICLRRuntimeHost2 [in] BOOL fWaitUntilDone, [out] int *pLatchedExitCode); }; - -cpp_quote("#undef DEPRECATED_CLR_STDAPI") -cpp_quote("#undef DECLARE_DEPRECATED") -cpp_quote("#undef DEPRECATED_CLR_API_MESG") diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/OpCodeGen.pl b/CoreCLRProfiler/native/coreclr_headers/src/inc/OpCodeGen.pl index 64ba130..4615548 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/OpCodeGen.pl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/OpCodeGen.pl @@ -49,7 +49,7 @@ $endHeaderComment .= "========================================================== $usingAndRefEmitNmsp = "namespace System.Reflection.Emit\n{\n\n"; $obsoleteAttr = " [Obsolete(\"This API has been deprecated. https://go.microsoft.com/fwlink/?linkid=14202\")]\n"; -# Open source file and target files +# Open source file and target files open (OPCODE, "opcode.def") or die "Couldn't open opcode.def: $!\n"; open (OUTPUT, ">OpCodes.cs") or die "Couldn't open OpCodes.cs: $!\n"; @@ -116,7 +116,7 @@ while () s/^OPDEF\(\s*//; # Strip off "OP(" s/,\s*/,/g; # Remove whitespace s/\).*$//; # Strip off ")" and everything behind it at end - + # Split the line up into its basic parts ($enumname, $stringname, $pop, $push, $operand, $type, $size, $s1, $s2, $ctrl) = split(/,/); $s1 =~ s/0x//; @@ -252,7 +252,7 @@ while () my $opcodeName = $enumname; # Tailcall OpCode enum name does not comply with convention - # that all enum names are exactly the same as names in opcode.def + # that all enum names are exactly the same as names in opcode.def # file less leading CEE_ and changed casing convention $enumname = substr $enumname, 0, 4 unless $enumname !~ m/Tailcall$/; @@ -266,12 +266,12 @@ while () } my $lineEnum; - if ($size == 1) + if ($size == 1) { $lineEnum = sprintf(" %s = 0x%.2x,\n", $enumname, $s2); $opcodeEnum{$s2} = $lineEnum; } - elsif ($size == 2) + elsif ($size == 2) { $lineEnum = sprintf(" %s = 0x%.4x,\n", $enumname, $s2 + 256 * $s1); $opcodeEnum{$s2 + 256 * $s1} = $lineEnum; @@ -314,7 +314,7 @@ while () $line .= sprintf(" (%s << OpCode.SizeShift) |\n", $size); if ($ctrl =~ m/Return/ || $ctrl =~ m/^Branch/ || $ctrl =~ m/^Throw/ || $enumname =~ m/Jmp/){ - $line .= sprintf(" OpCode.EndsUncondJmpBlkFlag |\n", $size); + $line .= sprintf(" OpCode.EndsUncondJmpBlkFlag |\n", $size); } $line .= sprintf(" (%d << OpCode.StackChangeShift)\n", $popstate); $line .= sprintf(" );\n\n"); @@ -363,7 +363,7 @@ foreach $key (sort {$a cmp $b} keys (%controlFlow)) print FCOUTPUT $obsoleteAttr; print FCOUTPUT " Phi"; print FCOUTPUT " = $ctrlflowcount,\n"; - $ctrlflowcount++; + $ctrlflowcount++; } } #end the flowcontrol enum @@ -390,7 +390,7 @@ foreach $key (sort {$a cmp $b} keys (%opcodetype)) if ($ctrlflowcount == 0){ print OCOUTPUT $obsoleteAttr; print OCOUTPUT " Annotation = 0,\n"; - $ctrlflowcount++; + $ctrlflowcount++; } print OCOUTPUT " $key"; print OCOUTPUT " = $ctrlflowcount,\n"; @@ -409,7 +409,7 @@ foreach $key (sort {$a cmp $b} keys (%operandtype)) if ($key =~ m/InlineNone/){ print OPOUTPUT $obsoleteAttr; print OPOUTPUT " InlinePhi = 6,\n"; - $ctrlflowcount++; + $ctrlflowcount++; } if ($key =~ m/^InlineR$/){ $ctrlflowcount++; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/allocacheck.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/allocacheck.h index 3ba2e4d..93d57d9 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/allocacheck.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/allocacheck.h @@ -6,17 +6,17 @@ /*********************************************************************/ /* check for alloca overruns (which otherwise are hard to track down - and often only repro on optimized builds). + and often only repro on optimized builds). USAGE: - void foo() { + void foo() { ALLOCA_CHECK(); // Declare at function level scope .... - void* mem = ALLOCA(size); // does an alloca, + void* mem = ALLOCA(size); // does an alloca, - } // destructor of ALLOCA_CHECK for buffer overruns. + } // destructor of ALLOCA_CHECK for buffer overruns. */ /* */ @@ -45,11 +45,11 @@ public: public: /***************************************************/ - AllocaCheck() { - sentinals = 0; + AllocaCheck() { + sentinals = 0; } - ~AllocaCheck() { + ~AllocaCheck() { AllocaSentinal* ptr = sentinals; while (ptr != 0) { if (ptr->check != (int)CheckBytes) @@ -76,9 +76,9 @@ private: #else -#define ALLOCA_CHECK() +#define ALLOCA_CHECK() #define ALLOCA(size) _alloca(size) #endif - + #endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/apithreadstress.cpp b/CoreCLRProfiler/native/coreclr_headers/src/inc/apithreadstress.cpp deleted file mode 100644 index 0a802a2..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/apithreadstress.cpp +++ /dev/null @@ -1,171 +0,0 @@ -// 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. - -// --------------------------------------------------------------------------- -// APIThreadStress.cpp (API thread stresser) -// --------------------------------------------------------------------------- - -#include "stdafx.h" - -#ifdef _DEBUG -#define LOGGING 1 -#endif - -#include "apithreadstress.h" -#include "clrhost.h" -#include "ex.h" -#include "log.h" - - - -// For now, thread stress is incompatible with hosting. We need a host CreateThread -// to fix this. -#undef SetEvent -#undef ResetEvent - -int APIThreadStress::s_threadStressCount = 0; - -APIThreadStress::APIThreadStress() -{ - m_threadCount = 0; - - // Don't "fork" stress threads - if (ClrFlsGetValue(TlsIdx_StressThread) == NULL) - m_threadCount = s_threadStressCount; - - if (m_threadCount != 0) - { - m_setupOK = TRUE; - - m_hThreadArray = new (nothrow) HANDLE [ m_threadCount ]; - if (m_hThreadArray == NULL) - m_setupOK = FALSE; - else - { - HANDLE *p = m_hThreadArray; - HANDLE *pEnd = p + m_threadCount; - - while (p < pEnd) - { - DWORD id; - *p = ::CreateThread(NULL, 0, StartThread, this, 0, &id); - if (*p == NULL) - m_setupOK = FALSE; - p++; - } - } - - m_syncEvent = ClrCreateManualEvent(FALSE); - if (m_syncEvent == INVALID_HANDLE_VALUE) - m_setupOK = FALSE; - } -} - -APIThreadStress::~APIThreadStress() -{ - if (m_threadCount > 0) - { - HANDLE *p = m_hThreadArray; - HANDLE *pEnd = p + m_threadCount; - - if (p != NULL) - { - while (p < pEnd) - { - if (*p != NULL) - { - if (m_threadCount > 0 && m_setupOK) - WaitForSingleObjectEx(*p, INFINITE, FALSE); - - ::CloseHandle(*p); - } - p++; - } - delete [] m_hThreadArray; - } - - if (m_syncEvent != INVALID_HANDLE_VALUE) - CloseHandle(m_syncEvent); - } -} - -void APIThreadStress::SetThreadStressCount(int threadCount) -{ - s_threadStressCount = threadCount; -} - - -DWORD WINAPI APIThreadStress::StartThread(void *arg) -{ - APIThreadStress *pThis = (APIThreadStress *) arg; - - ClrFlsSetValue(TlsIdx_StressThread, pThis); - - EX_TRY - { - // Perform initial synchronization - WaitForSingleObjectEx(pThis->m_syncEvent, INFINITE, FALSE); - InterlockedIncrement(&pThis->m_runCount); - - LOG((LF_SYNC, LL_INFO100, "Stressing operation on thread %d\n", GetCurrentThreadId())); - ((APIThreadStress *)arg)->Invoke(); - LOG((LF_SYNC, LL_INFO100, "End stress operation on thread %d\n", GetCurrentThreadId())); - - if (InterlockedDecrement(&pThis->m_runCount) == 0) - ::SetEvent(pThis->m_syncEvent); - } - EX_CATCH - { - LOG((LF_SYNC, LL_ERROR, "Exception during stress operation on thread %d\n", GetCurrentThreadId())); - } - EX_END_CATCH(SwallowAllExceptions); - - return 0; -} - -BOOL APIThreadStress::DoThreadStress() -{ - if (m_threadCount > 0 && m_setupOK) - { - HANDLE *p = m_hThreadArray; - HANDLE *pEnd = p + m_threadCount; - - while (p < pEnd) - { - ::ResumeThread(*p); - p++; - } - - // Start the threads at the same time - ::SetEvent(m_syncEvent); - - return TRUE; - } - else - { - SyncThreadStress(); - return FALSE; - } -} - -void APIThreadStress::SyncThreadStress() -{ - APIThreadStress *pThis = (APIThreadStress *) ClrFlsGetValue(TlsIdx_StressThread); - - if (pThis != NULL) - { - LOG((LF_SYNC, LL_INFO1000, "Syncing stress operation on thread %d\n", GetCurrentThreadId())); - - ::ResetEvent(pThis->m_syncEvent); - - if (InterlockedDecrement(&pThis->m_runCount) == 0) - ::SetEvent(pThis->m_syncEvent); - else - WaitForSingleObjectEx(pThis->m_syncEvent, INFINITE, FALSE); - InterlockedIncrement(&pThis->m_runCount); - - LOG((LF_SYNC, LL_INFO1000, "Resuming stress operation on thread %d\n", GetCurrentThreadId())); - } -} - diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/apithreadstress.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/apithreadstress.h deleted file mode 100644 index a0c6cde..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/apithreadstress.h +++ /dev/null @@ -1,57 +0,0 @@ -// 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. -// --------------------------------------------------------------------------- -// APIThreadStress.h (API thread stresser) -// --------------------------------------------------------------------------- - -// --------------------------------------------------------------------------- -// This class provides a simple base to wrap "thread stress" logic around an API, -// which will (in thread stress mode) cause an API to "fork" onto many threads -// executing the same operation simulatenously. This can help to expose race -// conditions. -// -// Usage: -// -// First, subtype APIThreadStress and override Invoke to implement the operation. -// You will likely need to add data members for the arguments. -// -// Next, inside the API, write code like this: -// -// void MyRoutine(int a1, void *a2) -// { -// class stress : APIThreadStress -// { -// int a1; -// void *a2; -// stress(int a1, void *a2) : a1(a1), a2(a2) -// { DoThreadStress(); } -// void Invoke() { MyRoutine(a1, a2); } -// } ts (a1, a2); -// -// // implementation -// -// // perhaps we have a common sub-point in the routine where we want the threads to -// // queue up and race again -// -// ts.SyncThreadStress(); -// -// // more implementation -// } -// --------------------------------------------------------------------------- - - -#ifndef _APITHREADSTRESS_H_ -#define _APITHREADSTRESS_H_ - -#include "utilcode.h" - -class APIThreadStress -{ - public: - BOOL DoThreadStress() { return FALSE; } - static void SyncThreadStress() { } - static void SetThreadStressCount(int count) { } -}; - -#endif // _APITHREADSTRESS_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/appxutil.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/appxutil.h index 411c18b..c5fce69 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/appxutil.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/appxutil.h @@ -11,11 +11,6 @@ #include "clrtypes.h" #include "appmodel.h" -#define PACKAGE_FILTER_CLR_DEFAULT (PACKAGE_FILTER_HEAD|PACKAGE_FILTER_DIRECT) - - -typedef PACKAGE_INFO * PPACKAGE_INFO; -typedef PACKAGE_INFO const * PCPACKAGE_INFO; //--------------------------------------------------------------------------------------------- // Forward declarations diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/arrayholder.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/arrayholder.h index 681014f..0523a41 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/arrayholder.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/arrayholder.h @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. template -class ArrayHolder +class ArrayHolder { public: ArrayHolder(T *ptr) @@ -15,7 +15,7 @@ public: { Clear(); } - + ArrayHolder(const ArrayHolder &rhs) { m_ptr = const_cast(&rhs)->Detach(); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/arraylist.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/arraylist.h index b8c149f..a4c6b2c 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/arraylist.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/arraylist.h @@ -15,7 +15,7 @@ // list of pointers, stored in chunks. Modification is by appending // only currently. Access is by index (efficient if the number of // elements stays small) and iteration (efficient in all cases). -// +// // An important property of an ArrayList is that the list remains // coherent while it is being modified. This means that readers // never need to lock when accessing it. @@ -41,7 +41,7 @@ class ArrayListBase { SPTR(ArrayListBlock) m_next; DWORD m_blockSize; -#ifdef _WIN64 +#ifdef HOST_64BIT DWORD m_padding; #endif PTR_VOID m_array[0]; @@ -61,7 +61,7 @@ class ArrayListBase { PTR_ArrayListBlock m_next; DWORD m_blockSize; -#ifdef _WIN64 +#ifdef HOST_64BIT DWORD m_padding; #endif void * m_array[ARRAY_BLOCK_SIZE_START]; @@ -75,18 +75,18 @@ class ArrayListBase public: PTR_VOID *GetPtr(DWORD index) const; - PTR_VOID Get(DWORD index) const - { + PTR_VOID Get(DWORD index) const + { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - - return *GetPtr(index); + + return *GetPtr(index); } - - void Set(DWORD index, PTR_VOID element) - { - WRAPPER_NO_CONTRACT; - *GetPtr(index) = element; + + void Set(DWORD index, PTR_VOID element) + { + WRAPPER_NO_CONTRACT; + *GetPtr(index) = element; } DWORD GetCount() const { LIMITED_METHOD_DAC_CONTRACT; return m_count; } @@ -101,7 +101,7 @@ class ArrayListBase void Init() { LIMITED_METHOD_CONTRACT; - + m_count = 0; m_firstBlock.m_next = NULL; m_firstBlock.m_blockSize = ARRAY_BLOCK_SIZE_START; @@ -116,10 +116,10 @@ class ArrayListBase #ifdef DACCESS_COMPILE void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); #endif - + class ConstIterator; - class Iterator + class Iterator { friend class ArrayListBase; friend class ConstIterator; @@ -130,13 +130,13 @@ class ArrayListBase void SetEmpty() { LIMITED_METHOD_CONTRACT; - + m_block = NULL; m_index = (DWORD)-1; m_remaining = 0; m_total = 0; } - + PTR_VOID GetElement() {LIMITED_METHOD_DAC_CONTRACT; return m_block->m_array[m_index]; } PTR_VOID * GetElementPtr() {LIMITED_METHOD_CONTRACT; return m_block->m_array + m_index; } DWORD GetIndex() {LIMITED_METHOD_CONTRACT; return m_index + m_total; } @@ -211,7 +211,7 @@ class ArrayListBase } public: - + BOOL Next() { if (m_block != NULL) @@ -231,7 +231,7 @@ class ArrayListBase { if (m_remaining < m_block->m_blockSize) ZeroMemory(&(m_block->m_array[m_remaining]), (m_block->m_blockSize - m_remaining) * sizeof(void*)); -#ifdef _WIN64 +#ifdef HOST_64BIT m_block->m_padding = 0; #endif } @@ -245,7 +245,7 @@ class ArrayListBase { return m_block; } - + SIZE_T GetBlockSize() { return offsetof(ArrayListBlock, m_array) + (m_block->m_blockSize * sizeof(void*)); @@ -282,7 +282,7 @@ public: #endif }; -/* to be used as static variable - no constructor/destructor, assumes zero +/* to be used as static variable - no constructor/destructor, assumes zero initialized memory */ class ArrayListStatic : public ArrayListBase { diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/bbsweep.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/bbsweep.h index d5526d8..b24cf23 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/bbsweep.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/bbsweep.h @@ -19,9 +19,9 @@ #ifndef _BBSWEEP_H_ #define _BBSWEEP_H_ -#ifndef FEATURE_PAL +#ifndef TARGET_UNIX #include -#endif // !FEATURE_PAL +#endif // !TARGET_UNIX // The CLR headers don't allow us to use methods like SetEvent directly (instead // we need to use the host APIs). However, this file is included both in the CLR @@ -55,7 +55,7 @@ public: /* BBSweep is used by both the CLR and the BBSweep utility. * BBSweep: calls the PerformSweep method which returns after all the CLR processes - * have written their profile data to disk. + * have written their profile data to disk. * CLR: starts up a sweeper thread which calls WatchForSweepEvents and waits until the * sweeper program is invoked. At that point, all the CLR processes will synchronize * and write their profile data to disk one at a time. The sweeper threads will then @@ -66,7 +66,7 @@ public: class BBSweep { public: - BBSweep() + BBSweep() { // The BBSweep constructor could be called even the the object is not used, so // don't do any work here. @@ -99,12 +99,12 @@ public: { success = success && ::SetEvent(hSweepEvent); { - for (int i=0; i= GetMaskArraySize()) GrowArray(index+1); - + GetMaskArray()[index] |= (1 << BitToShift(bit)); } @@ -141,7 +141,7 @@ inline void BitMask::ClearBit(int bit) if (index >= GetMaskArraySize()) return; - + GetMaskArray()[index] &= ~(1 << BitToShift(bit)); } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/bitposition.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/bitposition.h index df79155..423c4ed 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/bitposition.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/bitposition.h @@ -25,11 +25,11 @@ inline unsigned BitPosition(unsigned value) { _ASSERTE((value != 0) && ((value & (value-1)) == 0)); -#if defined(_ARM_) && defined(__llvm__) +#if defined(HOST_ARM) && defined(__llvm__) // use intrinsic functions for arm32 // this is applied for LLVM only but it may work for some compilers DWORD index = __builtin_clz(__builtin_arm_rbit(value)); -#elif !defined(_AMD64_) +#elif !defined(HOST_AMD64) const unsigned PRIME = 37; static const char hashTable[PRIME] = diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/bitvector.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/bitvector.h index a4181db..43fd2bc 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/bitvector.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/bitvector.h @@ -46,13 +46,13 @@ Uses one machine word if vector fits in machine word (minus a bit) Some caveates: - You should use mutator operators &=, |= ... instead of the + You should use mutator operators &=, |= ... instead of the non-mutators whenever possible to avoid creating a temps Specifically did NOT supply automatic coersions to and from short types so that the programmer is aware of - when code was being injected on his behalf. The upshot of this - is that you have to use the BitVector() toUnsigned() to convert + when code was being injected on their behalf. The upshot of this + is that you have to use the BitVector() toUnsigned() to convert */ /***************************************************************************/ @@ -60,7 +60,7 @@ class BitVector { // Set this to be unsigned char to do testing, should be UINT_PTR for real life - typedef UINT_PTR ChunkType; // The size of integer type that the machine can operate on directly + typedef UINT_PTR ChunkType; // The size of integer type that the machine can operate on directly // typedef BYTE ChunkType; // Use for testing // Maximum number of bits in our bitvector @@ -76,7 +76,7 @@ class BitVector { public: BitVector() - { + { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; @@ -111,7 +111,7 @@ public: { doBigInit(arg); } - else + else { m_val = ChunkType(arg << 1); } @@ -149,7 +149,7 @@ public: m_val = arg.m_val; } } - + void operator <<=(unsigned shift) { WRAPPER_NO_CONTRACT; @@ -162,7 +162,7 @@ public: { doBigLeftShiftAssign(shift); } - else + else { m_val <<= shift; } @@ -183,7 +183,7 @@ public: m_val &= ~IS_BIG; // clear the isBig bit if it got set } } - + void operator |=(const BitVector& arg) { WRAPPER_NO_CONTRACT; @@ -252,7 +252,7 @@ public: return ((arg1.m_val & arg2.m_val) != 0); } } - + BOOL operator ==(const BitVector& arg) const { WRAPPER_NO_CONTRACT; @@ -277,7 +277,7 @@ public: } friend ChunkType toUnsigned(const BitVector& arg) - { + { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; @@ -285,7 +285,7 @@ public: { return arg.m_vals.m_chunks[0]; // Note truncation } - else + else { return arg.smallBits(); } @@ -318,11 +318,11 @@ private: static const ChunkType MaxVal = ((ChunkType)1 << SMALL_BITS) - 1; // Maximum value that can be stored in m_val - // This is the structure that we use when the bit vector overflows. - // It is a simple vector. + // This is the structure that we use when the bit vector overflows. + // It is a simple vector. struct Vals { unsigned m_encodedLength; // An encoding of the current length of the 'm_chunks' array - ChunkType m_chunks[VALS_COUNT]; + ChunkType m_chunks[VALS_COUNT]; BOOL isBig() const { @@ -336,7 +336,7 @@ private: { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; - + if (isBig()) { unsigned length = (m_encodedLength >> 1); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/blobfetcher.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/blobfetcher.h index 0c640f0..a7f65c4 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/blobfetcher.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/blobfetcher.h @@ -63,7 +63,7 @@ protected: CBlobFetcher& operator=(const CBlobFetcher & src); public: -#if defined(_WIN64) +#if defined(HOST_64BIT) // needs to be 64 so that we can purposefully cache align code in ngen'd images enum { maxAlign = 64 }; // maximum alignment we support #else @@ -90,7 +90,7 @@ public: // Write out the section to memory HRESULT WriteMem(void ** pMem); -// Get the total length of all our data (sum of all the pillar's data length's) +// Get the total length of all our data (sum of all the pillar's data length's) // cached value, so light weight & no computations unsigned GetDataLen() const; @@ -138,7 +138,7 @@ inline ULONG32 CBlobFetcher::CPillar::GetOffset(__in char *ptr) { LIMITED_METHOD_CONTRACT; _ASSERTE(Contains(ptr)); - + return (ULONG32)(ptr - m_dataStart); } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/cahlpr.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/cahlpr.h index 903d3ab..c35f64d 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/cahlpr.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/cahlpr.h @@ -4,7 +4,7 @@ //***************************************************************************** // File: CAHLPR.H // -// +// // //***************************************************************************** #ifndef __CAHLPR_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/caparser.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/caparser.h index 0dfbb91..a263dcb 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/caparser.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/caparser.h @@ -135,7 +135,7 @@ public: *pVal = GetI1(); return S_OK; } - + HRESULT GetTag(CorSerializationType *pVal) { WRAPPER_NO_CONTRACT; @@ -257,7 +257,7 @@ public: HRESULT hr; unsigned __int16 val; IfFailRet(GetProlog(&val)); - + if (val != 0x0001) return META_E_CA_INVALID_BLOB; @@ -364,7 +364,7 @@ public: int BytesLeft() { - LIMITED_METHOD_CONTRACT; + LIMITED_METHOD_CONTRACT; return (int)(m_cbBlob - (m_pbCur - m_pbBlob)); } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/ceefilegenwriter.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/ceefilegenwriter.h index 8bfea46..3316738 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/ceefilegenwriter.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/ceefilegenwriter.h @@ -83,7 +83,7 @@ class CeeFileGenWriter : public CCeeGen HRESULT allocateIAT(); public: // Create with one of these two methods, not operator new - static HRESULT CreateNewInstance(CCeeGen *pCeeFileGenFrom, CeeFileGenWriter* & pGenWriter, + static HRESULT CreateNewInstance(CCeeGen *pCeeFileGenFrom, CeeFileGenWriter* & pGenWriter, DWORD createFlags = ICEE_CREATE_FILE_PURE_IL); // See ICeeFileGen.h for the definition of the bits used in createFlags static HRESULT CreateNewInstanceEx(CCeeGen *pCeeFileGenFrom, CeeFileGenWriter* & pGenWriter, @@ -189,7 +189,10 @@ inline LPWSTR CeeFileGenWriter::getResourceFileName() { } inline HRESULT CeeFileGenWriter::setDllSwitch(bool dllSwitch) { - if((m_dllSwitch = dllSwitch)) m_objSwitch = FALSE; return S_OK; + if((m_dllSwitch = dllSwitch)) + m_objSwitch = FALSE; + + return S_OK; } inline bool CeeFileGenWriter::getDllSwitch() { @@ -197,7 +200,10 @@ inline bool CeeFileGenWriter::getDllSwitch() { } inline HRESULT CeeFileGenWriter::setObjSwitch(bool objSwitch) { - if((m_objSwitch = objSwitch)) m_dllSwitch = FALSE; return S_OK; + if((m_objSwitch = objSwitch)) + m_dllSwitch = FALSE; + + return S_OK; } inline bool CeeFileGenWriter::getObjSwitch() { diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/ceegen.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/ceegen.h index c7d2af2..3bd729e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/ceegen.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/ceegen.h @@ -25,7 +25,7 @@ typedef DWORD StringRef; This is a description of the current implementation of these types for generating CLR modules. - + ICeeGen - interface to generate in-memory CLR module. CCeeGen - implementation of ICeeGen. Currently it uses both CeeSections @@ -98,16 +98,16 @@ class CeeSectionImpl { public: virtual unsigned dataLen() = 0; virtual char * getBlock( - unsigned len, + unsigned len, unsigned align = 1) = 0; virtual HRESULT addSectReloc( - unsigned offset, - CeeSection & relativeTo, - CeeSectionRelocType reloc = srRelocAbsolute, + unsigned offset, + CeeSection & relativeTo, + CeeSectionRelocType reloc = srRelocAbsolute, CeeSectionRelocExtra * extra = NULL) = 0; virtual HRESULT addBaseReloc( - unsigned offset, - CeeSectionRelocType reloc = srRelocHighLow, + unsigned offset, + CeeSectionRelocType reloc = srRelocHighLow, CeeSectionRelocExtra * extra = NULL) = 0; virtual HRESULT directoryEntry(unsigned num) = 0; virtual unsigned char * name() = 0; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/ceegentokenmapper.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/ceegentokenmapper.h index b323ee4..a0b7680 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/ceegentokenmapper.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/ceegentokenmapper.h @@ -48,18 +48,18 @@ public: }; static int IndexForType(mdToken tk); - + CeeGenTokenMapper() : m_pIImport(0), m_cRefs(1), m_pIMapToken(NULL) { LIMITED_METHOD_CONTRACT; } virtual ~CeeGenTokenMapper() {} //***************************************************************************** -// IUnknown implementation. +// IUnknown implementation. //***************************************************************************** virtual ULONG STDMETHODCALLTYPE AddRef() {LIMITED_METHOD_CONTRACT; return ++m_cRefs; } virtual ULONG STDMETHODCALLTYPE Release() - { + { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; SUPPORTS_DAC_HOST_ONLY; @@ -72,7 +72,7 @@ public: m_pIMapToken->Release(); m_pIMapToken = NULL; } - + delete this; } return cRefs; @@ -99,7 +99,7 @@ public: IUnknown *GetMapTokenIface() const { LIMITED_METHOD_CONTRACT; return ((IUnknown *) this); } - + //***************************************************************************** // Hand out a copy of the meta data information. //***************************************************************************** @@ -136,7 +136,7 @@ protected: IMetaDataImport *m_pIImport; ULONG m_cRefs; // Ref count. IMapToken *m_pIMapToken; - + }; #endif // __CeeGenTokenMapper_h__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/ceesectionstring.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/ceesectionstring.h index 06a534a..0ec466d 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/ceesectionstring.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/ceesectionstring.h @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. // =========================================================================== // File: CeeSectionString.h -// +// // =========================================================================== #ifndef CeeSectionString_H diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/check.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/check.h index a05960f..9e012de 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/check.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/check.h @@ -15,6 +15,7 @@ #include "static_assert.h" #include "daccess.h" +#include "unreachable.h" #ifdef _DEBUG @@ -28,7 +29,7 @@ #if !defined(DISABLE_CONTRACTS) #define CHECK_INVARIANTS 1 #define VALIDATE_OBJECTS 1 -#endif +#endif #endif // _DEBUG @@ -39,7 +40,7 @@ #ifdef _DEBUG #define DEBUG_ARG(x) , x #else -#define DEBUG_ARG(x) +#define DEBUG_ARG(x) #endif #define CHECK_STRESS 1 @@ -49,12 +50,12 @@ // failure. It not only contains the result of the check, but if the check fails, // also records information about the condition and call site. // -// CHECK also serves as a holder to prevent recursive CHECKS. These can be +// CHECK also serves as a holder to prevent recursive CHECKS. These can be // particularly common when putting preconditions inside predicates, especially // routines called by an invariant. // // Note that using CHECK is perfectly efficient in a free build - the CHECK becomes -// a simple string constant pointer (typically either NULL or (LPCSTR)1, although some +// a simple string constant pointer (typically either NULL or (LPCSTR)1, although some // check failures may include messages) // // NOTE: you should NEVER use the CHECK class API directly - use the macros below. @@ -79,6 +80,8 @@ protected: // Keep leakage counters. static size_t s_cLeakedBytes; static size_t s_cNumFailures; + + static thread_local LONG t_count; #endif static BOOL s_neverEnforceAsserts; @@ -143,10 +146,7 @@ public: // !!! NOTE: Called from macros only!!! static void SetAssertEnforcement(BOOL value); - static void ReleaseTls(void* pCountTLS); - private: - static LONG* InitTls(); #ifdef _DEBUG static LPCSTR AllocateDynamicMessage(const SString &s); #endif @@ -157,14 +157,14 @@ public: // !!! NOTE: Called from macros only!!! // These CHECK macros are the correct way to propagate an assertion. These // routines are designed for use inside "Check" routines. Such routines may // be Invariants, Validate routines, or any other assertional predicates. -// -// A Check routine should return a value of type CHECK. // -// It should consist of multiple CHECK or CHECK_MSG statements (along with appropritate +// A Check routine should return a value of type CHECK. +// +// It should consist of multiple CHECK or CHECK_MSG statements (along with appropritate // control flow) and should end with CHECK_OK() if all other checks pass. // // It may contain a CONTRACT_CHECK contract, but this is only appropriate if the -// check is used for non-assertional purposes (otherwise the contract will never execute). +// check is used for non-assertional purposes (otherwise the contract will never execute). // Note that CONTRACT_CHECK contracts do not support postconditions. // // CHECK: Check the given condition, return a CHECK failure if FALSE @@ -175,7 +175,7 @@ public: // !!! NOTE: Called from macros only!!! #ifdef _DEBUG #define DEBUG_ONLY_MESSAGE(msg) msg #else -// On retail, we don't want to add a bunch of string literals to the image, +// On retail, we don't want to add a bunch of string literals to the image, // so we just use the same one everywhere. #define DEBUG_ONLY_MESSAGE(msg) ((LPCSTR)1) #endif @@ -217,14 +217,14 @@ do \ return CHECK::OK() //-------------------------------------------------------------------------------- -// ASSERT_CHECK is the proper way to trigger a check result. If the CHECK -// has failed, the diagnostic assertion routines will fire with appropriate +// ASSERT_CHECK is the proper way to trigger a check result. If the CHECK +// has failed, the diagnostic assertion routines will fire with appropriate // context information. // // Note that the condition may either be a raw boolean expression or a CHECK result // returned from a Check routine. // -// Recursion note: ASSERT_CHECKs are only performed if there is no current check in +// Recursion note: ASSERT_CHECKs are only performed if there is no current check in // progress. //-------------------------------------------------------------------------------- @@ -259,24 +259,24 @@ do \ // ex: ASSERT_CHECKF(1+2==4, "my reason", ("Woah %d", 1+3)); // note that the double parenthesis, the 'args' param below will include one pair of parens. #define ASSERT_CHECKF(_condition, _reason, _args) \ - ASSERT_CHECK(_condition, CHECK::FormatMessage _args, _reason) + ASSERT_CHECK(_condition, CHECK::FormatMessage _args, _reason) //-------------------------------------------------------------------------------- // INVARIANTS are descriptions of conditions which are always true at well defined // points of execution. Invariants may be checked by the caller or callee at any -// time as paranoia requires. +// time as paranoia requires. // // There are really two flavors of invariant. The "public invariant" describes -// to the caller invariant behavior about the abstraction which is visible from -// the public API (and of course it should be expressible in that public API). -// -// The "internal invariant" (or representation invariant), on the other hand, is -// a description of the private implementation of the abstraction, which may examine +// to the caller invariant behavior about the abstraction which is visible from +// the public API (and of course it should be expressible in that public API). +// +// The "internal invariant" (or representation invariant), on the other hand, is +// a description of the private implementation of the abstraction, which may examine // internal state of the abstraction or use private entry points. // -// Classes with invariants should introduce methods called +// Classes with invariants should introduce methods called // void Invariant(); -// and +// and // void InternalInvariant(); // to allow invariant checks. //-------------------------------------------------------------------------------- @@ -310,18 +310,18 @@ CHECK CheckInvariant(TYPENAME &obj) #endif //-------------------------------------------------------------------------------- -// VALIDATE is a check to be made on an object type which identifies a pointer as -// a valid instance of the object, by calling CheckPointer on it. Normally a null -// pointer is treated as an error; VALIDATE_NULL (or CheckPointer(o, NULL_OK)) -// may be used when a null pointer is acceptible. -// -// In addition to the null/non-null check, a type may provide a specific Check method -// for more sophisticated identification. In general, the Check method +// VALIDATE is a check to be made on an object type which identifies a pointer as +// a valid instance of the object, by calling CheckPointer on it. Normally a null +// pointer is treated as an error; VALIDATE_NULL (or CheckPointer(o, NULL_OK)) +// may be used when a null pointer is acceptible. +// +// In addition to the null/non-null check, a type may provide a specific Check method +// for more sophisticated identification. In general, the Check method // should answer the question -// "Is this a valid instance of its declared compile-time type?". For instance, if +// "Is this a valid instance of its declared compile-time type?". For instance, if // runtype type identification were supported for the type, it should be invoked here. -// -// Note that CheckPointer will also check the invariant(s) if appropriate, so the +// +// Note that CheckPointer will also check the invariant(s) if appropriate, so the // invariants should NOT be explicitly invoked from the Check method. //-------------------------------------------------------------------------------- @@ -394,7 +394,7 @@ CHECK CheckValue(TYPENAME &val) #if VALIDATE_OBJECTS #define VALIDATE(o) \ - ASSERT_CHECK(CheckPointer(o), "Validation failure") + ASSERT_CHECK(CheckPointer(o), "Validation failure") #define VALIDATE_NULL(o) \ ASSERT_CHECK(CheckPointer(o, NULL_OK), "Validation failure") @@ -474,8 +474,8 @@ CHECK CheckValue(TYPENAME &val) #endif // !_DEBUG_IMPL //-------------------------------------------------------------------------------- -// COMPILER_ASSUME_MSG is a statement that tells the compiler to assume the -// condition is true. In a checked build these turn into asserts; +// COMPILER_ASSUME_MSG is a statement that tells the compiler to assume the +// condition is true. In a checked build these turn into asserts; // in a free build they are passed through to the compiler to use in optimization. //-------------------------------------------------------------------------------- @@ -509,7 +509,7 @@ CHECK CheckValue(TYPENAME &val) //-------------------------------------------------------------------------------- -// PREFIX_ASSUME_MSG and PREFAST_ASSUME_MSG are just another name +// PREFIX_ASSUME_MSG and PREFAST_ASSUME_MSG are just another name // for COMPILER_ASSUME_MSG // In a checked build these turn into asserts; in a free build // they are passed through to the compiler to use in optimization; @@ -535,8 +535,8 @@ CHECK CheckValue(TYPENAME &val) COMPILER_ASSUME_MSG(_condition, "") //-------------------------------------------------------------------------------- -// UNREACHABLE points are locations in the code which should not be able to be -// reached under any circumstances (e.g. a default in a switch which is supposed to +// UNREACHABLE points are locations in the code which should not be able to be +// reached under any circumstances (e.g. a default in a switch which is supposed to // cover all cases.). This macro tells the compiler this, and also embeds a check // to make sure it is always true. //-------------------------------------------------------------------------------- @@ -557,19 +557,6 @@ CHECK CheckValue(TYPENAME &val) #endif // __llvm__ else -#if defined(_MSC_VER) || defined(_PREFIX_) -#if defined(_TARGET_AMD64_) -// Empty methods that consist of UNREACHABLE() result in a zero-sized declspec(noreturn) method -// which causes the pdb file to make the next method declspec(noreturn) as well, thus breaking BBT -// Remove when we get a VC compiler that fixes VSW 449170 -# define __UNREACHABLE() DebugBreak(); __assume(0); -#else -# define __UNREACHABLE() __assume(0) -#endif -#else -#define __UNREACHABLE() __builtin_unreachable() -#endif - #ifdef _DEBUG_IMPL // Note that the "do { } while (0)" syntax trick here doesn't work, as the compiler @@ -619,8 +606,8 @@ CHECK CheckValue(TYPENAME &val) //-------------------------------------------------------------------------------- // CCHECK is used for Check functions which may fail due to out of memory -// or other transient failures. These failures should be ignored when doing -// assertions, but they cannot be ignored when the Check function is used in +// or other transient failures. These failures should be ignored when doing +// assertions, but they cannot be ignored when the Check function is used in // normal code. // @todo: really crufty to have 2 sets of CHECK macros //-------------------------------------------------------------------------------- @@ -725,7 +712,7 @@ CHECK CheckUnderflow(const void *address, void *address2); CHECK CheckZeroedMemory(const void *memory, SIZE_T size); -// These include overflow checks +// These include overflow checks CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset); CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset, UINT32 size); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/check.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/check.inl index 9a3597e..84a9be2 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/check.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/check.inl @@ -10,51 +10,13 @@ #include "debugmacros.h" #include "clrtypes.h" -inline LONG *CHECK::InitTls() -{ -#pragma push_macro("HeapAlloc") -#pragma push_macro("GetProcessHeap") -#undef HeapAlloc -#undef GetProcessHeap - - LONG *pCount = (LONG *)::HeapAlloc(GetProcessHeap(), 0, sizeof(LONG)); - if (pCount) - *pCount = 0; - -#pragma pop_macro("HeapAlloc") -#pragma pop_macro("GetProcessHeap") - ClrFlsSetValue(TlsIdx_Check, pCount); - ClrFlsAssociateCallback(TlsIdx_Check, ReleaseCheckTls); - return pCount; -} - -inline void CHECK::ReleaseTls(void* pCountTLS) -{ -#pragma push_macro("HeapFree") -#pragma push_macro("GetProcessHeap") -#undef HeapFree -#undef GetProcessHeap - LONG* pCount = (LONG*) pCountTLS; - if (pCount) - ::HeapFree(GetProcessHeap(), 0, pCount); - -#pragma pop_macro("HeapFree") -#pragma pop_macro("GetProcessHeap") -} - FORCEINLINE BOOL CHECK::EnterAssert() { if (s_neverEnforceAsserts) return FALSE; #ifdef _DEBUG_IMPL - m_pCount = (LONG *)ClrFlsGetValue(TlsIdx_Check); - if (!m_pCount) - { - m_pCount = InitTls(); - if (!m_pCount) - return FALSE; - } + m_pCount = &t_count; if (!*m_pCount) { @@ -81,12 +43,9 @@ FORCEINLINE BOOL CHECK::IsInAssert() { #ifdef _DEBUG_IMPL if (!m_pCount) - m_pCount = (LONG *)ClrFlsGetValue(TlsIdx_Check); + m_pCount = &t_count; - if (!m_pCount) - return FALSE; - else - return *m_pCount; + return *m_pCount; #else return FALSE; #endif @@ -180,7 +139,7 @@ inline CHECK CheckAligned(UINT value, UINT alignment) CHECK_OK; } -#ifndef PLATFORM_UNIX +#ifndef HOST_UNIX // For Unix this and the previous function get the same types. // So, exclude this one. inline CHECK CheckAligned(ULONG value, UINT alignment) @@ -189,7 +148,7 @@ inline CHECK CheckAligned(ULONG value, UINT alignment) CHECK(AlignmentTrim(value, alignment) == 0); CHECK_OK; } -#endif // PLATFORM_UNIX +#endif // HOST_UNIX inline CHECK CheckAligned(UINT64 value, UINT alignment) { @@ -270,7 +229,7 @@ inline CHECK CheckUnderflow(UINT value1, UINT value2) CHECK_OK; } -#ifndef PLATFORM_UNIX +#ifndef HOST_UNIX // For Unix this and the previous function get the same types. // So, exclude this one. inline CHECK CheckUnderflow(ULONG value1, ULONG value2) @@ -279,7 +238,7 @@ inline CHECK CheckUnderflow(ULONG value1, ULONG value2) CHECK_OK; } -#endif // PLATFORM_UNIX +#endif // HOST_UNIX inline CHECK CheckUnderflow(UINT64 value1, UINT64 value2) { diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/circularlog.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/circularlog.h deleted file mode 100644 index 4ee8d2f..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/circularlog.h +++ /dev/null @@ -1,38 +0,0 @@ -// 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. - - -#ifndef _CIRCULARLOG_H__ - -#define _CIRCULARLOG_H__ - -#include "sstring.h" - -class CircularLog -{ -public: - CircularLog(); - ~CircularLog(); - - bool Init(const WCHAR* logname, const WCHAR* logHeader, DWORD maxSize = 1024*1024); - void Shutdown(); - void Log(const WCHAR* string); - -protected: - - void CheckForLogReset(BOOL fOverflow); - BOOL CheckLogHeader(); - HANDLE OpenFile(); - void CloseFile(); - - bool m_bInit; - SString m_LogFilename; - SString m_LogHeader; - SString m_OldLogFilename; - SString m_LockFilename; - DWORD m_MaxSize; - unsigned m_uLogCount; -}; - -#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs.h index d6bcb75..6ff1750 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs.h @@ -10,7 +10,5 @@ #define _clr_fs_h_ #include "fs/path.h" -#include "fs/file.h" -#include "fs/dir.h" #endif // _clr_fs_h_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs/dir.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs/dir.h deleted file mode 100644 index 2516151..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs/dir.h +++ /dev/null @@ -1,129 +0,0 @@ -// 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. -// - -// -// This header provides general directory-related file system services. - -#ifndef _clr_fs_Dir_h_ -#define _clr_fs_Dir_h_ - -#include "clrtypes.h" -#include "clr/str.h" -#include "strsafe.h" - -#ifndef countof - #define countof(x) (sizeof(x) / sizeof(x[0])) -#endif // !countof - -namespace clr -{ - namespace fs - { - class Dir - { - public: - static inline bool Exists( - LPCWSTR wzDirPath) - { - DWORD attrs = WszGetFileAttributes(wzDirPath); - return (attrs != INVALID_FILE_ATTRIBUTES) && (attrs & FILE_ATTRIBUTE_DIRECTORY); - } - - //----------------------------------------------------------------------------------------- - // Creates new directory indicated by wzDirPath. - // - // Returns: - // S_OK - on success directory creation - // S_FALSE - when directory previously existed - // HR(ERROR_PATH_NOT_FOUND) - when creation of dir fails. - static inline HRESULT Create( - LPCWSTR wzDirPath) - { - HRESULT hr = S_OK; - - if (!WszCreateDirectory(wzDirPath, nullptr)) - { - hr = HRESULT_FROM_GetLastError(); - if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) - { - hr = S_FALSE; - } - } - return hr; - } - - //----------------------------------------------------------------------------------------- - // Creates the specified directory and all required subdirectories. wzDirPath will be - // temporarily modified in the process. - // - // Returns: - // S_OK - on success directory creation - // S_FALSE - when directory previously existed - // HR(ERROR_PATH_NOT_FOUND) - when creation of any dir fails. - static inline HRESULT CreateRecursively( - __inout_z LPWSTR wzDirPath, - size_t cchDirPath = 0) - { - HRESULT hr = S_OK; - - if (wzDirPath == nullptr) - { - return E_POINTER; - } - - if (cchDirPath == 0) - { - cchDirPath = wcslen(wzDirPath); - } - - // Try to create the path. If it fails, assume that's because the parent folder does - // not exist. Try to create the parent then re-attempt. - WCHAR chOrig = wzDirPath[cchDirPath]; - hr = Create(wzDirPath); - if (hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) - { - for (WCHAR* pCurCh = wzDirPath + cchDirPath - 1; pCurCh != wzDirPath; --pCurCh) - { - if (*pCurCh == W('\\') || *pCurCh == W('\0')) - { - WCHAR chOrig = *pCurCh; - *pCurCh = W('\0'); - IfFailRet(CreateRecursively(wzDirPath, pCurCh - wzDirPath)); - *pCurCh = chOrig; - break; - } - } - IfFailRet(Create(wzDirPath)); - } - - return hr; - } - - //----------------------------------------------------------------------------------------- - // Creates the specified directory and all required subdirectories. - static inline HRESULT CreateRecursively( - LPCWSTR wzDirPath) - { - HRESULT hr = S_OK; - - if (wzDirPath == nullptr) - { - return E_POINTER; - } - - // Make a writable copy of wzDirPath - size_t cchDirPath = wcslen(wzDirPath); - CQuickWSTR wzBuffer; - IfFailRet(wzBuffer.ReSizeNoThrow(cchDirPath + 1)); - wcscpy_s(wzBuffer.Ptr(), wzBuffer.Size(), wzDirPath); - IfFailRet(CreateRecursively(wzBuffer.Ptr(), cchDirPath)); - - return hr; - } - }; - } -} - -#endif // _clr_fs_Dir_h_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs/file.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs/file.h deleted file mode 100644 index 70f22a2..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs/file.h +++ /dev/null @@ -1,40 +0,0 @@ -// 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. -// - -// -// This header provides general filename-related file system services. - -#ifndef _clr_fs_File_h_ -#define _clr_fs_File_h_ - -#include "clrtypes.h" -#include "cor.h" // SELECTANY - -namespace clr -{ - namespace fs - { - // This list taken from ndp/clr/src/bcl/system/io/path.cs - SELECTANY WCHAR const g_rgInvalidFileNameChars[] = - { W('"'), W('<'), W('>'), W('|'), W('\0'), (WCHAR)1, (WCHAR)2, (WCHAR)3, (WCHAR)4, (WCHAR)5, (WCHAR)6, - (WCHAR)7, (WCHAR)8, (WCHAR)9, (WCHAR)10, (WCHAR)11, (WCHAR)12, (WCHAR)13, (WCHAR)14, - (WCHAR)15, (WCHAR)16, (WCHAR)17, (WCHAR)18, (WCHAR)19, (WCHAR)20, (WCHAR)21, (WCHAR)22, - (WCHAR)23, (WCHAR)24, (WCHAR)25, (WCHAR)26, (WCHAR)27, (WCHAR)28, (WCHAR)29, (WCHAR)30, - (WCHAR)31, W(':'), W('*'), W('?'), W('\\'), W('/') }; - - class File - { - public: - static inline bool Exists( - LPCWSTR wzFilePath) - { - DWORD attrs = WszGetFileAttributes(wzFilePath); - return (attrs != INVALID_FILE_ATTRIBUTES) && !(attrs & FILE_ATTRIBUTE_DIRECTORY); - } - }; - } -} - -#endif // _clr_fs_File_h_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs/path.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs/path.h index 7c1995e..dd4ed9e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs/path.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clr/fs/path.h @@ -16,43 +16,13 @@ #include "clr/str.h" -#ifndef LONG_FORMAT_PATH_PREFIX - #define LONG_FORMAT_PATH_PREFIX W("\\\\?\\") -#endif - namespace clr { namespace fs { - // This list taken from ndp/clr/src/bcl/system/io/path.cs - SELECTANY WCHAR const g_rgInvalidPathChars[] = - { W('"'), W('<'), W('>'), W('|'), W('\0'), (WCHAR)1, (WCHAR)2, (WCHAR)3, (WCHAR)4, (WCHAR)5, (WCHAR)6, - (WCHAR)7, (WCHAR)8, (WCHAR)9, (WCHAR)10, (WCHAR)11, (WCHAR)12, (WCHAR)13, (WCHAR)14, - (WCHAR)15, (WCHAR)16, (WCHAR)17, (WCHAR)18, (WCHAR)19, (WCHAR)20, (WCHAR)21, (WCHAR)22, - (WCHAR)23, (WCHAR)24, (WCHAR)25, (WCHAR)26, (WCHAR)27, (WCHAR)28, (WCHAR)29, (WCHAR)30, - (WCHAR)31 }; - class Path { public: - //----------------------------------------------------------------------------------------- - static inline bool - Exists( - LPCWSTR wzPath) - { - DWORD attrs = WszGetFileAttributes(wzPath); - return (attrs != INVALID_FILE_ATTRIBUTES); - } - - //----------------------------------------------------------------------------------------- - // Returns true if wzPath represents a long format path (i.e., prefixed with '\\?\'). - static inline bool - HasLongFormatPrefix(LPCWSTR wzPath) - { - _ASSERTE(!clr::str::IsNullOrEmpty(wzPath)); // Must check this first. - return wcscmp(wzPath, LONG_FORMAT_PATH_PREFIX) == 0; - } - //----------------------------------------------------------------------------------------- // Returns true if wzPath represents a relative path. static inline bool @@ -61,7 +31,7 @@ namespace clr _ASSERTE(wzPath != nullptr); // Similar to System.IO.Path.IsRelative() -#if PLATFORM_UNIX +#if TARGET_UNIX if(wzPath[0] == VOLUME_SEPARATOR_CHAR_W) { return false; @@ -89,51 +59,6 @@ namespace clr return true; } - - //----------------------------------------------------------------------------------------- - // Combines two path parts. wzPathLeft must be a directory path and may be either absolute - // or relative. wzPathRight may be a directory or file path and must be relative. The - // result is placed in wzBuffer and the number of chars written is placed in pcchBuffer on - // success; otherwise an error HRESULT is returned. - static HRESULT - Combine(LPCWSTR wzPathLeft, LPCWSTR wzPathRight, __in DWORD *pcchBuffer, __out_ecount(*pcchBuffer) LPWSTR wzBuffer) - { - STATIC_CONTRACT_NOTHROW; - - HRESULT hr = S_OK; - - if (clr::str::IsNullOrEmpty(wzPathLeft) || clr::str::IsNullOrEmpty(wzPathRight) || pcchBuffer == nullptr) - return E_INVALIDARG; - - LPWSTR wzBuf = wzBuffer; - size_t cchBuf = *pcchBuffer; - - IfFailRet(StringCchCopyExW(wzBuf, cchBuf, wzPathLeft, &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE)); - IfFailRet(StringCchCatExW(wzBuf, cchBuf, wzBuf[-1] == DIRECTORY_SEPARATOR_CHAR_W ? W("") : DIRECTORY_SEPARATOR_STR_W, &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE)); - IfFailRet(StringCchCatExW(wzBuf, cchBuf, wzPathRight, &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE)); - - return S_OK; - } - - //----------------------------------------------------------------------------------------- - // Checks if the path provided is valid within the specified constraints. - // ***NOTE: does not yet check for invalid path characters. - static bool - IsValid(LPCWSTR wzPath, DWORD cchPath, bool fAllowLongFormat) - { - if (clr::str::IsNullOrEmpty(wzPath)) - return false; - - bool fIsLongFormat = HasLongFormatPrefix(wzPath); - - if (fIsLongFormat && !fAllowLongFormat) - return false; - - if (!fIsLongFormat && cchPath > _MAX_PATH) - return false; - - return true; - } }; } } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clr_std/algorithm b/CoreCLRProfiler/native/coreclr_headers/src/inc/clr_std/algorithm index 92b4e8e..653d67e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clr_std/algorithm +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clr_std/algorithm @@ -22,8 +22,8 @@ namespace std template iter find_if ( iter first, iter last, CompareFunc comp ) { - for ( ; first!=last ; first++ ) - if ( comp(*first) ) + for ( ; first!=last ; first++ ) + if ( comp(*first) ) break; return first; } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clr_std/type_traits b/CoreCLRProfiler/native/coreclr_headers/src/inc/clr_std/type_traits index 090694e..357fb1f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clr_std/type_traits +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clr_std/type_traits @@ -186,6 +186,70 @@ namespace std typedef _Ty1 type; }; + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS make_unsigned + template + struct make_unsigned + { + }; + + template<> + struct make_unsigned + { + typedef unsigned int type; + }; + +#ifndef TARGET_UNIX + + template<> + struct make_unsigned + { + typedef unsigned long type; + }; + +#endif // !TARGET_UNIX + + template<> + struct make_unsigned<__int64> + { + typedef unsigned __int64 type; + }; + + template<> + struct make_unsigned + { + typedef size_t type; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS make_signed + template + struct make_signed + { + }; + + template<> + struct make_signed + { + typedef signed int type; + }; + +#ifndef TARGET_UNIX + + template<> + struct make_signed + { + typedef signed long type; + }; + +#endif // !TARGET_UNIX + + template<> + struct make_signed + { + typedef signed __int64 type; + }; + //----------------------------------------------------------------------------------------- // TEMPLATE CLASS is_lvalue_reference template @@ -269,14 +333,6 @@ namespace std { // determine whether _Ty is integral }; - #ifdef _NATIVE_WCHAR_T_DEFINED - template<> - struct _Is_integral - : true_type - { // determine whether _Ty is integral - }; - #endif /* _NATIVE_WCHAR_T_DEFINED */ - template<> struct _Is_integral : true_type @@ -303,7 +359,7 @@ namespace std // On Unix 'long' is a 64-bit type (same as __int64) and the following two definitions // conflict with _Is_integral and _Is_integral. -#ifndef PLATFORM_UNIX +#ifndef TARGET_UNIX template<> struct _Is_integral : true_type @@ -315,7 +371,7 @@ namespace std : true_type { // determine whether _Ty is integral }; -#endif /* PLATFORM_UNIX */ +#endif /* TARGET_UNIX */ #if _HAS_CHAR16_T_LANGUAGE_SUPPORT template<> @@ -371,7 +427,7 @@ namespace std // In PAL, we define long as int and so this becomes int double, // which is a nonsense -#ifndef FEATURE_PAL +#ifndef TARGET_UNIX template<> struct _Is_floating_point : true_type @@ -460,7 +516,7 @@ namespace std }; template - struct conversion + struct conversion { static const bool exists = true; static const bool exists2Way = true; @@ -468,7 +524,7 @@ namespace std }; template - struct conversion + struct conversion { static const bool exists = false; static const bool exists2Way = false; @@ -476,7 +532,7 @@ namespace std }; template - struct conversion + struct conversion { static const bool exists = false; static const bool exists2Way = false; @@ -484,7 +540,7 @@ namespace std }; template <> - struct conversion + struct conversion { static const bool exists = true; static const bool exists2Way = true; @@ -516,22 +572,6 @@ namespace std #endif - // Use to determine if a template type parameter is a string. - template - struct is_cstr - : public std::false_type - {}; - - template - struct is_cstr< T* > - : public std::conditional< - std::is_same::type, char>::value || - std::is_same::type, wchar_t>::value, - std::true_type, - std::false_type>::type - - { }; - } // namespace std #endif // !USE_STL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clr_std/vector b/CoreCLRProfiler/native/coreclr_headers/src/inc/clr_std/vector index c816746..447166c 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clr_std/vector +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clr_std/vector @@ -43,9 +43,9 @@ namespace std typedef ptrdiff_t difference_type; typedef T* pointer; typedef T& reference; - + typedef class vector::iterator _MyIter; - + _MyIter &operator++() { m_ptr++; @@ -140,7 +140,7 @@ namespace std public: typedef class vector::const_iterator _MyIter; typedef class vector::iterator _MyNonConstIter; - + _MyIter &operator++() { m_ptr++; @@ -408,7 +408,7 @@ namespace std private: size_t m_size; //# of elements - size_t m_capacity; //# of elements allocated + size_t m_capacity; //# of elements allocated T *m_pelements; //actual array // invariants: // dimensions == m_capacity @@ -422,7 +422,7 @@ namespace std }; // class vector }; // namespace std - + #endif /* __clr_std_vector_h__ */ #endif // !USE_STL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrconfig.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrconfig.h index 7e74e65..42d8a24 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrconfig.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrconfig.h @@ -1,19 +1,19 @@ // 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. -// +// // -------------------------------------------------------------------------------------------------- // CLRConfig.h -// +// // // Unified method of accessing configuration values from environment variables, registry and config file(s). // This class replaces all GetConfigDWORD and GetConfigString methods in EEConfig and REGUTIL. To define a // flag, add an entry in the table in file:CLRConfigValues.h. -// -// -// -// +// +// +// +// // -------------------------------------------------------------------------------------------------- @@ -26,9 +26,9 @@ class CLRConfig { public: - // + // // Types - // + // // Setting each option results in some change to the config value lookup method. Default behavior is (in // the following order): @@ -39,40 +39,30 @@ public: // Link to BOTR documentation enum LookupOptions { // If set, don't look in environment variables. - IgnoreEnv = 0x1, + IgnoreEnv = 0x1, // If set, do not prepend "COMPlus_" when doing environment variable lookup. - DontPrependCOMPlus_ = 0x2, + DontPrependCOMPlus_ = 0x2, // If set, don't look in HKLM in the registry. - IgnoreHKLM = 0x4, + IgnoreHKLM = 0x4, // If set, don't look in HKCU in the registry. - IgnoreHKCU = 0x8, - // If set, don't look in any config files - IgnoreConfigFiles = 0x10, - // If set, look in config file(s) before looking in env/registry. - FavorConfigFile = 0x20, - // If set, look only in the system config file, ignoring other config files. + IgnoreHKCU = 0x8, + // If set, look only in the system config file, ignoring other config files. // (This option does not affect environment variable and registry lookups) - ConfigFile_SystemOnly = 0x40, - // If set, reverse the order of config file lookups (application config file first). + ConfigFile_SystemOnly = 0x40, + // If set, reverse the order of config file lookups (application config file first). // (This option does not affect environment variable and registry lookups) - ConfigFile_ApplicationFirst = 0x80, + ConfigFile_ApplicationFirst = 0x80, // Remove any whitespace at beginning and end of value. (Only applicable for // *string* configuration values.) TrimWhiteSpaceFromStringValue = 0x100, - // Legacy REGUTIL-style lookup. - REGUTIL_default = IgnoreConfigFiles, // Legacy EEConfig-style lookup. EEConfig_default = 0, }; - // Function pointer definition used for calling EEConfig::GetConfigValueCallback . - typedef HRESULT (* GetConfigValueFunction) - (__in_z LPCWSTR /*pKey*/, __deref_out_opt LPCWSTR* /*value*/, BOOL /*systemOnly*/, BOOL /*applicationFirst*/); - // Struct used to store information about where/how to find a Config DWORD. // NOTE: Please do NOT create instances of this struct. Use the macros in file:CLRConfigValues.h instead. - typedef struct ConfigDWORDInfo + typedef struct ConfigDWORDInfo { LPCWSTR name; DWORD defaultValue; @@ -86,17 +76,17 @@ public: LPCWSTR name; LookupOptions options; } ConfigStringInfo; - - // + + // // Declaring structs using the macro table in CLRConfigValues.h - // - + // + // These macros declare ConfigDWORDInfo structs. #define RETAIL_CONFIG_DWORD_INFO(symbol, name, defaultValue, description) \ static const ConfigDWORDInfo symbol; #define RETAIL_CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions) \ static const ConfigDWORDInfo symbol; - + // These macros declare ConfigStringInfo structs. #define RETAIL_CONFIG_STRING_INFO(symbol, name, description) \ static const ConfigStringInfo symbol; @@ -109,16 +99,16 @@ public: #define RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(symbol, name, description) \ static const LPCWSTR symbol; #define RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(symbol, name, description) \ - static const LPCWSTR symbol; + static const LPCWSTR symbol; - // + // // Debug versions of the macros - // + // #ifdef _DEBUG #define CONFIG_DWORD_INFO(symbol, name, defaultValue, description) \ static const ConfigDWORDInfo symbol; #define CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions) \ - static const ConfigDWORDInfo symbol; + static const ConfigDWORDInfo symbol; #define CONFIG_STRING_INFO(symbol, name, description) \ static const ConfigStringInfo symbol; #define CONFIG_STRING_INFO_EX(symbol, name, description, lookupOptions) \ @@ -128,12 +118,12 @@ public: #define CONFIG_STRING_INFO_DIRECT_ACCESS(symbol, name, description) \ static const LPCWSTR symbol; #else - #define CONFIG_DWORD_INFO(symbol, name, defaultValue, description) - #define CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions) - #define CONFIG_STRING_INFO(symbol, name, description) - #define CONFIG_STRING_INFO_EX(symbol, name, description, lookupOptions) + #define CONFIG_DWORD_INFO(symbol, name, defaultValue, description) + #define CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions) + #define CONFIG_STRING_INFO(symbol, name, description) + #define CONFIG_STRING_INFO_EX(symbol, name, description, lookupOptions) #define CONFIG_DWORD_INFO_DIRECT_ACCESS(symbol, name, description) - #define CONFIG_STRING_INFO_DIRECT_ACCESS(symbol, name, description) + #define CONFIG_STRING_INFO_DIRECT_ACCESS(symbol, name, description) #endif // _DEBUG // Now that we have defined what what the macros in file:CLRConfigValues.h mean, include it to generate the code. #include "clrconfigvalues.h" @@ -141,19 +131,19 @@ public: #undef RETAIL_CONFIG_DWORD_INFO #undef RETAIL_CONFIG_STRING_INFO #undef RETAIL_CONFIG_DWORD_INFO_EX - #undef RETAIL_CONFIG_STRING_INFO_EX + #undef RETAIL_CONFIG_STRING_INFO_EX #undef RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS #undef RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS #undef CONFIG_DWORD_INFO #undef CONFIG_STRING_INFO #undef CONFIG_DWORD_INFO_EX - #undef CONFIG_STRING_INFO_EX + #undef CONFIG_STRING_INFO_EX #undef CONFIG_DWORD_INFO_DIRECT_ACCESS #undef CONFIG_STRING_INFO_DIRECT_ACCESS - // + // // Methods to do config value (DWORD and String) lookups. - // + // static BOOL IsConfigEnabled(const ConfigDWORDInfo & info); // Look up a DWORD config value. @@ -165,9 +155,9 @@ public: // Look up a string config value. // You own the string that's returned. static LPWSTR GetConfigValue(const ConfigStringInfo & info); - + // Look up a string config value, passing it out through a pointer reference. Reports out of memory - // errors (HRESULT E_OUTOFMEMORY). + // errors (HRESULT E_OUTOFMEMORY). // You own the string that's returned. static HRESULT GetConfigValue(const ConfigStringInfo & info, __deref_out_z LPWSTR * outVal); @@ -182,21 +172,15 @@ public: // Free a string returned by GetConfigValue static void FreeConfigString(__in __in_z LPWSTR name); - // Register EEConfig's GetConfigValueCallback function so CLRConfig can look in config files. - static void RegisterGetConfigValueCallback(GetConfigValueFunction func); - private: - // Function pointer to EEConfig's GetConfigValueCallback function (can't static bind from utilcode to VM) - static GetConfigValueFunction s_GetConfigValueCallback; - // Helper method to translate LookupOptions to REGUTIL::CORConfigLevel static REGUTIL::CORConfigLevel GetConfigLevel(LookupOptions options); - // + // // Helper methods. - // - + // + // Helper method to check if a certain option is set in a ConfigDWORDInfo struct. static inline BOOL CheckLookupOption(const ConfigDWORDInfo & info, LookupOptions option) { diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrconfigvalues.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrconfigvalues.h index a97e53d..51b47e4 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrconfigvalues.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrconfigvalues.h @@ -102,7 +102,6 @@ /// /// AppDomain /// -RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_AddRejitNops, W("AddRejitNops"), "Control for the profiler rejit feature infrastructure") CONFIG_DWORD_INFO(INTERNAL_ADDumpSB, W("ADDumpSB"), 0, "Not used") CONFIG_DWORD_INFO(INTERNAL_ADForceSB, W("ADForceSB"), 0, "Forces sync block creation for all objects") CONFIG_DWORD_INFO(INTERNAL_ADLogMemory, W("ADLogMemory"), 0, "Superseded by test hooks") @@ -124,104 +123,104 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchMaxVal, W("JitPitchMaxVal"), (DWORD)0x /// /// Assembly Loader /// -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_DesignerNamespaceResolutionEnabled, W("designerNamespaceResolution"), FALSE, "Set it to 1 to enable DesignerNamespaceResolve event for WinRT types", CLRConfig::IgnoreEnv | CLRConfig::IgnoreHKLM | CLRConfig::IgnoreHKCU | CLRConfig::FavorConfigFile) -CONFIG_DWORD_INFO_EX(INTERNAL_GetAssemblyIfLoadedIgnoreRidMap, W("GetAssemblyIfLoadedIgnoreRidMap"), 0, "Used to force loader to ignore assemblies cached in the rid-map", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_DesignerNamespaceResolutionEnabled, W("designerNamespaceResolution"), FALSE, "Set it to 1 to enable DesignerNamespaceResolve event for WinRT types", CLRConfig::IgnoreEnv | CLRConfig::IgnoreHKLM | CLRConfig::IgnoreHKCU) +CONFIG_DWORD_INFO_EX(INTERNAL_GetAssemblyIfLoadedIgnoreRidMap, W("GetAssemblyIfLoadedIgnoreRidMap"), 0, "Used to force loader to ignore assemblies cached in the rid-map", CLRConfig::EEConfig_default) /// /// Conditional breakpoints /// -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_BreakOnBadExit, W("BreakOnBadExit"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_BreakOnBadExit, W("BreakOnBadExit"), 0, "", CLRConfig::EEConfig_default) CONFIG_STRING_INFO(INTERNAL_BreakOnClassBuild, W("BreakOnClassBuild"), "Very useful for debugging class layout code.") CONFIG_STRING_INFO(INTERNAL_BreakOnClassLoad, W("BreakOnClassLoad"), "Very useful for debugging class loading code.") CONFIG_STRING_INFO(INTERNAL_BreakOnComToClrNativeInfoInit, W("BreakOnComToClrNativeInfoInit"), "Throws an assert when native information about a COM -> CLR call are about to be gathered.") -CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnDebugBreak, W("BreakOnDebugBreak"), 0, "Allows an assert in debug builds when a user break is hit", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnDILoad, W("BreakOnDILoad"), 0, "Allows an assert when the DI is loaded", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnDumpToken, W("BreakOnDumpToken"), 0xffffffff, "Breaks when using internal logging on a particular token value.", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_BreakOnEELoad, W("BreakOnEELoad"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnDebugBreak, W("BreakOnDebugBreak"), 0, "Allows an assert in debug builds when a user break is hit", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnDILoad, W("BreakOnDILoad"), 0, "Allows an assert when the DI is loaded", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnDumpToken, W("BreakOnDumpToken"), 0xffffffff, "Breaks when using internal logging on a particular token value.", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_BreakOnEELoad, W("BreakOnEELoad"), 0, "", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO(INTERNAL_BreakOnEEShutdown, W("BreakOnEEShutdown"), 0, "") -CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnExceptionInGetThrowable, W("BreakOnExceptionInGetThrowable"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnExceptionInGetThrowable, W("BreakOnExceptionInGetThrowable"), 0, "", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO(INTERNAL_BreakOnFindMethod, W("BreakOnFindMethod"), 0, "Breaks in findMethodInternal when it searches for the specified token.") -CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnFirstPass, W("BreakOnFirstPass"), 0, "", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnHR, W("BreakOnHR"), 0, "Debug.cpp, IfFailxxx use this macro to stop if hr matches ", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnFirstPass, W("BreakOnFirstPass"), 0, "", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnHR, W("BreakOnHR"), 0, "Debug.cpp, IfFailxxx use this macro to stop if hr matches ", CLRConfig::EEConfig_default) CONFIG_STRING_INFO(INTERNAL_BreakOnInstantiation, W("BreakOnInstantiation"), "Very useful for debugging generic class instantiation.") CONFIG_STRING_INFO(INTERNAL_BreakOnInteropStubSetup, W("BreakOnInteropStubSetup"), "Throws an assert when marshaling stub for the given method is about to be built.") -CONFIG_STRING_INFO_EX(INTERNAL_BreakOnInteropVTableBuild, W("BreakOnInteropVTableBuild"), "Specifies a type name for which an assert should be thrown when building interop v-table.", CLRConfig::REGUTIL_default) +CONFIG_STRING_INFO_EX(INTERNAL_BreakOnInteropVTableBuild, W("BreakOnInteropVTableBuild"), "Specifies a type name for which an assert should be thrown when building interop v-table.", CLRConfig::EEConfig_default) CONFIG_STRING_INFO(INTERNAL_BreakOnMethodName, W("BreakOnMethodName"), "Very useful for debugging method override placement code.") -CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnNotify, W("BreakOnNotify"), 0, "", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnRetailAssert, W("BreakOnRetailAssert"), 0, "Used for debugging \"retail\" asserts (fatal errors)", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnSecondPass, W("BreakOnSecondPass"), 0, "", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_BreakOnSO, W("BreakOnSO"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnNotify, W("BreakOnNotify"), 0, "", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnRetailAssert, W("BreakOnRetailAssert"), 0, "Used for debugging \"retail\" asserts (fatal errors)", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnSecondPass, W("BreakOnSecondPass"), 0, "", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_BreakOnSO, W("BreakOnSO"), 0, "", CLRConfig::EEConfig_default) CONFIG_STRING_INFO(INTERNAL_BreakOnStructMarshalSetup, W("BreakOnStructMarshalSetup"), "Throws an assert when field marshalers for the given type with layout are about to be created.") -CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnUEF, W("BreakOnUEF"), 0, "", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnUncaughtException, W("BreakOnUncaughtException"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnUEF, W("BreakOnUEF"), 0, "", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnUncaughtException, W("BreakOnUncaughtException"), 0, "", CLRConfig::EEConfig_default) /// /// Debugger /// -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_EnableDiagnostics, W("EnableDiagnostics"), 1, "Allows the debugger and profiler diagnostics to be disabled", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_D__FCE, W("D::FCE"), 0, "Allows an assert when crawling the managed stack for an exception handler", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakIfLocksUnavailable, W("DbgBreakIfLocksUnavailable"), 0, "Allows an assert when the debugger can't take a lock ", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnErr, W("DbgBreakOnErr"), 0, "Allows an assert when we get a failing hresult", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnMapPatchToDJI, W("DbgBreakOnMapPatchToDJI"), 0, "Allows an assert when mapping a patch to an address", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnRawInt3, W("DbgBreakOnRawInt3"), 0, "Allows an assert for test coverage for debug break or other int3 breaks", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnSendBreakpoint, W("DbgBreakOnSendBreakpoint"), 0, "Allows an assert when sending a breakpoint to the right side", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnSetIP, W("DbgBreakOnSetIP"), 0, "Allows an assert when setting the IP", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgCheckInt3, W("DbgCheckInt3"), 0, "Asserts if the debugger explicitly writes int3 instead of calling SetUnmanagedBreakpoint", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_EnableDiagnostics, W("EnableDiagnostics"), 1, "Allows the debugger, profiler, and EventPipe diagnostics to be disabled", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_D__FCE, W("D::FCE"), 0, "Allows an assert when crawling the managed stack for an exception handler", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakIfLocksUnavailable, W("DbgBreakIfLocksUnavailable"), 0, "Allows an assert when the debugger can't take a lock ", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnErr, W("DbgBreakOnErr"), 0, "Allows an assert when we get a failing hresult", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnMapPatchToDJI, W("DbgBreakOnMapPatchToDJI"), 0, "Allows an assert when mapping a patch to an address", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnRawInt3, W("DbgBreakOnRawInt3"), 0, "Allows an assert for test coverage for debug break or other int3 breaks", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnSendBreakpoint, W("DbgBreakOnSendBreakpoint"), 0, "Allows an assert when sending a breakpoint to the right side", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnSetIP, W("DbgBreakOnSetIP"), 0, "Allows an assert when setting the IP", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgCheckInt3, W("DbgCheckInt3"), 0, "Asserts if the debugger explicitly writes int3 instead of calling SetUnmanagedBreakpoint", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_DbgDACAssertOnMismatch, W("DbgDACAssertOnMismatch"), "Allows an assert when the mscordacwks and mscorwks dll versions don't match") -CONFIG_DWORD_INFO_EX(INTERNAL_DbgDACEnableAssert, W("DbgDACEnableAssert"), 0, "Enables extra validity checking in DAC - assumes target isn't corrupt", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_DbgDACSkipVerifyDlls, W("DbgDACSkipVerifyDlls"), 0, "Allows disabling the check to ensure mscordacwks and mscorwks dll versions match", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgDelayHelper, W("DbgDelayHelper"), 0, "Varies the wait in the helper thread startup for testing race between threads", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_DbgDisableDynamicSymsCompat, W("DbgDisableDynamicSymsCompat"), 0, "", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgDisableTargetConsistencyAsserts, W("DbgDisableTargetConsistencyAsserts"), 0, "Allows explicitly testing with corrupt targets", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_DbgEnableMixedModeDebugging, W("DbgEnableMixedModeDebuggingInternalOnly"), 0, "", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgExtraThreads, W("DbgExtraThreads"), 0, "Allows extra unmanaged threads to run and throw debug events for stress testing", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgExtraThreadsCantStop, W("DbgExtraThreadsCantStop"), 0, "Allows extra unmanaged threads in can't stop region to run and throw debug events for stress testing", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgExtraThreadsIB, W("DbgExtraThreadsIB"), 0, "Allows extra in-band unmanaged threads to run and throw debug events for stress testing", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgExtraThreadsOOB, W("DbgExtraThreadsOOB"), 0, "Allows extra out of band unmanaged threads to run and throw debug events for stress testing", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgFaultInHandleIPCEvent, W("DbgFaultInHandleIPCEvent"), 0, "Allows testing the unhandled event filter", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgInjectFEE, W("DbgInjectFEE"), 0, "Allows injecting a fatal execution error for testing Watson", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgLeakCheck, W("DbgLeakCheck"), 0, "Allows checking for leaked Cordb objects", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgNo2ndChance, W("DbgNo2ndChance"), 0, "Allows breaking on (and catching bogus) 2nd chance exceptions", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgNoDebugger, W("DbgNoDebugger"), 0, "Allows breaking if we don't want to lazily initialize the debugger", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DbgNoForceContinue, W("DbgNoForceContinue"), 1, "Used to force a continue on longhorn", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgNoOpenMDByFile, W("DbgNoOpenMDByFile"), 0, "Allows opening MD by memory for perf testing", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgDACEnableAssert, W("DbgDACEnableAssert"), 0, "Enables extra validity checking in DAC - assumes target isn't corrupt", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_DbgDACSkipVerifyDlls, W("DbgDACSkipVerifyDlls"), 0, "Allows disabling the check to ensure mscordacwks and mscorwks dll versions match", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgDelayHelper, W("DbgDelayHelper"), 0, "Varies the wait in the helper thread startup for testing race between threads", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_DbgDisableDynamicSymsCompat, W("DbgDisableDynamicSymsCompat"), 0, "", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgDisableTargetConsistencyAsserts, W("DbgDisableTargetConsistencyAsserts"), 0, "Allows explicitly testing with corrupt targets", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_DbgEnableMixedModeDebugging, W("DbgEnableMixedModeDebuggingInternalOnly"), 0, "", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgExtraThreads, W("DbgExtraThreads"), 0, "Allows extra unmanaged threads to run and throw debug events for stress testing", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgExtraThreadsCantStop, W("DbgExtraThreadsCantStop"), 0, "Allows extra unmanaged threads in can't stop region to run and throw debug events for stress testing", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgExtraThreadsIB, W("DbgExtraThreadsIB"), 0, "Allows extra in-band unmanaged threads to run and throw debug events for stress testing", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgExtraThreadsOOB, W("DbgExtraThreadsOOB"), 0, "Allows extra out of band unmanaged threads to run and throw debug events for stress testing", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgFaultInHandleIPCEvent, W("DbgFaultInHandleIPCEvent"), 0, "Allows testing the unhandled event filter", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgInjectFEE, W("DbgInjectFEE"), 0, "Allows injecting a fatal execution error for testing Watson", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgLeakCheck, W("DbgLeakCheck"), 0, "Allows checking for leaked Cordb objects", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgNo2ndChance, W("DbgNo2ndChance"), 0, "Allows breaking on (and catching bogus) 2nd chance exceptions", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgNoDebugger, W("DbgNoDebugger"), 0, "Allows breaking if we don't want to lazily initialize the debugger", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DbgNoForceContinue, W("DbgNoForceContinue"), 1, "Used to force a continue on longhorn", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgNoOpenMDByFile, W("DbgNoOpenMDByFile"), 0, "Allows opening MD by memory for perf testing", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO(INTERNAL_DbgOOBinFEEE, W("DbgOOBinFEEE"), 0, "Allows forcing oob breakpoints when a fatal error occurs") RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(EXTERNAL_DbgPackShimPath, W("DbgPackShimPath"), "CoreCLR path to dbgshim.dll - we are trying to figure out if we can remove this") -CONFIG_DWORD_INFO_EX(INTERNAL_DbgPingInterop, W("DbgPingInterop"), 0, "Allows checking for deadlocks in interop debugging", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgRace, W("DbgRace"), 0, "Allows pausing for native debug events to get hijicked", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DbgRedirect, W("DbgRedirect"), 0, "Allows for redirecting the event pipeline", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgPingInterop, W("DbgPingInterop"), 0, "Allows checking for deadlocks in interop debugging", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgRace, W("DbgRace"), 0, "Allows pausing for native debug events to get hijicked", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DbgRedirect, W("DbgRedirect"), 0, "Allows for redirecting the event pipeline", CLRConfig::EEConfig_default) RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(EXTERNAL_DbgRedirectApplication, W("DbgRedirectApplication"), "Specifies the auxiliary debugger application to launch.") RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(EXTERNAL_DbgRedirectAttachCmd, W("DbgRedirectAttachCmd"), "Specifies command parameters for attaching the auxiliary debugger.") RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(EXTERNAL_DbgRedirectCommonCmd, W("DbgRedirectCommonCmd"), "Specifies a command line format string for the auxiliary debugger.") RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(EXTERNAL_DbgRedirectCreateCmd, W("DbgRedirectCreateCmd"), "Specifies command parameters when creating the auxiliary debugger.") -CONFIG_DWORD_INFO_EX(INTERNAL_DbgShortcutCanary, W("DbgShortcutCanary"), 0, "Allows a way to force canary to fail to be able to test failure paths", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgSkipMEOnStep, W("DbgSkipMEOnStep"), 0, "Turns off MethodEnter checks", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgSkipVerCheck, W("DbgSkipVerCheck"), 0, "Allows different RS and LS versions (for servicing work)", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgTC, W("DbgTC"), 0, "Allows checking boundary compression for offset mappings", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgTransportFaultInject, W("DbgTransportFaultInject"), 0, "Allows injecting a fault for testing the debug transport", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgShortcutCanary, W("DbgShortcutCanary"), 0, "Allows a way to force canary to fail to be able to test failure paths", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgSkipMEOnStep, W("DbgSkipMEOnStep"), 0, "Turns off MethodEnter checks", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgSkipVerCheck, W("DbgSkipVerCheck"), 0, "Allows different RS and LS versions (for servicing work)", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgTC, W("DbgTC"), 0, "Allows checking boundary compression for offset mappings", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgTransportFaultInject, W("DbgTransportFaultInject"), 0, "Allows injecting a fault for testing the debug transport", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_DbgTransportLog, W("DbgTransportLog"), "Turns on logging for the debug transport") CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_DbgTransportLogClass, W("DbgTransportLogClass"), "Mask to control what is logged in DbgTransportLog") -RETAIL_CONFIG_STRING_INFO_EX(UNSUPPORTED_DbgTransportProxyAddress, W("DbgTransportProxyAddress"), "Allows specifying the transport proxy address", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgTrapOnSkip, W("DbgTrapOnSkip"), 0, "Allows breaking when we skip a breakpoint", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DbgWaitTimeout, W("DbgWaitTimeout"), 1, "Specifies the timeout value for waits", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DbgWFDETimeout, W("DbgWFDETimeout"), 25, "Specifies the timeout value for wait when waiting for a debug event", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_RaiseExceptionOnAssert, W("RaiseExceptionOnAssert"), 0, "Raise a first chance (if set to 1) or second chance (if set to 2) exception on asserts.", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DebugBreakOnAssert, W("DebugBreakOnAssert"), 0, "If DACCESS_COMPILE is defined, break on asserts.", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_DebugBreakOnVerificationFailure, W("DebugBreakOnVerificationFailure"), 0, "Halts the jit on verification failure", CLRConfig::REGUTIL_default) -CONFIG_STRING_INFO_EX(INTERNAL_DebuggerBreakPoint, W("DebuggerBreakPoint"), "Allows counting various debug events", CLRConfig::REGUTIL_default) -CONFIG_STRING_INFO_EX(INTERNAL_DebugVerify, W("DebugVerify"), "Control for tracing in peverify", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO_EX(UNSUPPORTED_DbgTransportProxyAddress, W("DbgTransportProxyAddress"), "Allows specifying the transport proxy address", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgTrapOnSkip, W("DbgTrapOnSkip"), 0, "Allows breaking when we skip a breakpoint", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgWaitTimeout, W("DbgWaitTimeout"), 1, "Specifies the timeout value for waits", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DbgWFDETimeout, W("DbgWFDETimeout"), 25, "Specifies the timeout value for wait when waiting for a debug event", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_RaiseExceptionOnAssert, W("RaiseExceptionOnAssert"), 0, "Raise a first chance (if set to 1) or second chance (if set to 2) exception on asserts.", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DebugBreakOnAssert, W("DebugBreakOnAssert"), 0, "If DACCESS_COMPILE is defined, break on asserts.", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DebugBreakOnVerificationFailure, W("DebugBreakOnVerificationFailure"), 0, "Halts the jit on verification failure", CLRConfig::EEConfig_default) +CONFIG_STRING_INFO_EX(INTERNAL_DebuggerBreakPoint, W("DebuggerBreakPoint"), "Allows counting various debug events", CLRConfig::EEConfig_default) +CONFIG_STRING_INFO_EX(INTERNAL_DebugVerify, W("DebugVerify"), "Control for tracing in peverify", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO(INTERNAL_EncApplyChanges, W("EncApplyChanges"), 0, "Allows breaking when ApplyEditAndContinue is called") -CONFIG_DWORD_INFO_EX(INTERNAL_EnCBreakOnRemapComplete, W("EnCBreakOnRemapComplete"), 0, "Allows breaking after N RemapCompletes", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_EnCBreakOnRemapOpportunity, W("EnCBreakOnRemapOpportunity"), 0, "Allows breaking after N RemapOpportunities", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_EnCBreakOnRemapComplete, W("EnCBreakOnRemapComplete"), 0, "Allows breaking after N RemapCompletes", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_EnCBreakOnRemapOpportunity, W("EnCBreakOnRemapOpportunity"), 0, "Allows breaking after N RemapOpportunities", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO(INTERNAL_EncDumpApplyChanges, W("EncDumpApplyChanges"), 0, "Allows dumping edits in delta metadata and il files") CONFIG_DWORD_INFO(INTERNAL_EncFixupFieldBreak, W("EncFixupFieldBreak"), 0, "Unlikely that this is used anymore.") CONFIG_DWORD_INFO(INTERNAL_EncJitUpdatedFunction, W("EncJitUpdatedFunction"), 0, "Allows breaking when an updated function is jitted") CONFIG_DWORD_INFO(INTERNAL_EnCResolveField, W("EnCResolveField"), 0, "Allows breaking when computing the address of an EnC-added field") CONFIG_DWORD_INFO(INTERNAL_EncResumeInUpdatedFunction, W("EncResumeInUpdatedFunction"), 0, "Allows breaking when execution resumes in a new EnC version of a function") -CONFIG_DWORD_INFO_EX(INTERNAL_DbgAssertOnDebuggeeDebugBreak, W("DbgAssertOnDebuggeeDebugBreak"), 0, "If non-zero causes the managed-only debugger to assert on unhandled breakpoints in the debuggee", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgAssertOnDebuggeeDebugBreak, W("DbgAssertOnDebuggeeDebugBreak"), 0, "If non-zero causes the managed-only debugger to assert on unhandled breakpoints in the debuggee", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_DbgDontResumeThreadsOnUnhandledException, W("UNSUPPORTED_DbgDontResumeThreadsOnUnhandledException"), 0, "If non-zero, then don't try to unsuspend threads after continuing a 2nd-chance native exception") -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DbgSkipStackCheck, W("DbgSkipStackCheck"), 0, "Skip the stack pointer check during stackwalking", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DbgSkipStackCheck, W("DbgSkipStackCheck"), 0, "Skip the stack pointer check during stackwalking", CLRConfig::EEConfig_default) #ifdef DACCESS_COMPILE CONFIG_DWORD_INFO(INTERNAL_DumpGeneration_IntentionallyCorruptDataFromTarget, W("IntentionallyCorruptDataFromTarget"), 0, "Intentionally fakes bad data retrieved from target to try and break dump generation.") #endif @@ -232,31 +231,31 @@ CONFIG_DWORD_INFO(UNSUPPORTED_Debugging_RequiredVersion, W("UNSUPPORTED_Debuggin RETAIL_CONFIG_DWORD_INFO(INTERNAL_MiniMdBufferCapacity, W("MiniMdBufferCapacity"), 64 * 1024, "The max size of the buffer to store mini metadata information for triage- and mini-dumps.") #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS -CONFIG_DWORD_INFO_EX(INTERNAL_DbgNativeCodeBpBindsAcrossVersions, W("DbgNativeCodeBpBindsAcrossVersions"), 0, "If non-zero causes native breakpoints at offset 0 to bind in all tiered compilation versions of the given method", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgNativeCodeBpBindsAcrossVersions, W("DbgNativeCodeBpBindsAcrossVersions"), 0, "If non-zero causes native breakpoints at offset 0 to bind in all tiered compilation versions of the given method", CLRConfig::EEConfig_default) /// /// Diagnostics (internal general-purpose) /// CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_ConditionalContracts, W("ConditionalContracts"), "If ENABLE_CONTRACTS_IMPL is defined, sets whether contracts are conditional. (?)") CONFIG_DWORD_INFO(INTERNAL_ConsistencyCheck, W("ConsistencyCheck"), 0, "") -CONFIG_DWORD_INFO_EX(INTERNAL_ContinueOnAssert, W("ContinueOnAssert"), 0, "If set, doesn't break on asserts.", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_disableStackOverflowProbing, W("disableStackOverflowProbing"), 0, "", CLRConfig::FavorConfigFile) +CONFIG_DWORD_INFO_EX(INTERNAL_ContinueOnAssert, W("ContinueOnAssert"), 0, "If set, doesn't break on asserts.", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_disableStackOverflowProbing, W("disableStackOverflowProbing"), 0, "", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_InjectFatalError, W("InjectFatalError"), "") -CONFIG_DWORD_INFO_EX(INTERNAL_InjectFault, W("InjectFault"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_InjectFault, W("InjectFault"), 0, "", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_SuppressChecks, W("SuppressChecks"), "") -#ifdef WIN64EXCEPTIONS +#ifdef FEATURE_EH_FUNCLETS CONFIG_DWORD_INFO(INTERNAL_SuppressLockViolationsOnReentryFromOS, W("SuppressLockViolationsOnReentryFromOS"), 0, "64 bit OOM tests re-enter the CLR via RtlVirtualUnwind. This indicates whether to suppress resulting locking violations.") -#endif // WIN64EXCEPTIONS +#endif // FEATURE_EH_FUNCLETS /// /// Exception Handling /// CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_AssertOnFailFast, W("AssertOnFailFast"), "") -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_legacyCorruptedStateExceptionsPolicy, W("legacyCorruptedStateExceptionsPolicy"), 0, "Enabled Pre-V4 CSE behavior", CLRConfig::FavorConfigFile) -CONFIG_DWORD_INFO_EX(INTERNAL_SuppressLostExceptionTypeAssert, W("SuppressLostExceptionTypeAssert"), 0, "", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_FailFastOnCorruptedStateException, W("FailFastOnCorruptedStateException"), 0, "Failfast if a CSE is encountered", CLRConfig::FavorConfigFile) -RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_UseEntryPointFilter, W("UseEntryPointFilter"), 0, "", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_Corhost_Swallow_Uncaught_Exceptions, W("Corhost_Swallow_Uncaught_Exceptions"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_legacyCorruptedStateExceptionsPolicy, W("legacyCorruptedStateExceptionsPolicy"), 0, "Enabled Pre-V4 CSE behavior", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_SuppressLostExceptionTypeAssert, W("SuppressLostExceptionTypeAssert"), 0, "", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_FailFastOnCorruptedStateException, W("FailFastOnCorruptedStateException"), 0, "Failfast if a CSE is encountered", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_UseEntryPointFilter, W("UseEntryPointFilter"), 0, "", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_Corhost_Swallow_Uncaught_Exceptions, W("Corhost_Swallow_Uncaught_Exceptions"), 0, "", CLRConfig::EEConfig_default) /// /// Garbage collector @@ -272,83 +271,49 @@ RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_gcConservative, W("gcConservative"), 0, "En RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_gcServer, W("gcServer"), 0, "Enables server GC") CONFIG_STRING_INFO(INTERNAL_GcCoverage, W("GcCoverage"), "Specify a method or regular expression of method names to run with GCStress") CONFIG_STRING_INFO(INTERNAL_SkipGCCoverage, W("SkipGcCoverage"), "Specify a list of assembly names to skip with GC Coverage") -RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_gcForceCompact, W("gcForceCompact"), "When set to true, always do compacting GC") -RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_GCgen0size, W("GCgen0size"), "Specifies the smallest gen0 size") -RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_GCGen0MaxBudget, W("GCGen0MaxBudget"), "Specifies the largest gen0 allocation budget") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCStressMix, W("GCStressMix"), 0, "Specifies whether the GC mix mode is enabled or not") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCStressStep, W("GCStressStep"), 1, "Specifies how often StressHeap will actually do a GC in GCStressMix mode") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCStressMaxFGCsPerBGC, W("GCStressMaxFGCsPerBGC"), ~0U, "Specifies how many FGCs will occur during one BGC in GCStressMix mode") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StatsUpdatePeriod, W("StatsUpdatePeriod"), 60, "Specifies the interval, in seconds, at which to update the statistics") -RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_SuspendTimeLog, W("SuspendTimeLog"), "Specifies the name of the log file for suspension statistics") -RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_GCMixLog, W("GCMixLog"), "Specifies the name of the log file for GC mix statistics") -CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_GCLatencyMode, W("GCLatencyMode"), "Specifies the GC latency mode - batch, interactive or low latency (note that the same thing can be specified via API which is the supported way)") -RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCLatencyLevel, W("GCLatencyLevel"), 1, "Specifies the GC latency level that you want to optimize for") -RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCConfigLogEnabled, W("GCConfigLogEnabled"), 0, "Specifies if you want to turn on config logging in GC") -RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCLogEnabled, W("GCLogEnabled"), 0, "Specifies if you want to turn on logging in GC") -RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_GCLogFile, W("GCLogFile"), "Specifies the name of the GC log file") -RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_GCConfigLogFile, W("GCConfigLogFile"), "Specifies the name of the GC config log file") -RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCLogFileSize, W("GCLogFileSize"), 0, "Specifies the GC log file size") -RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCCompactRatio, W("GCCompactRatio"), 0, "Specifies the ratio compacting GCs vs sweeping ") RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCPollType, W("GCPollType"), "") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCRetainVM, W("GCRetainVM"), 0, "When set we put the segments that should be deleted on a standby list (instead of releasing them back to the OS) which will be considered to satisfy new segment requests (note that the same thing can be specified via API which is the supported way)") -RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_GCSegmentSize, W("GCSegmentSize"), "Specifies the managed heap segment size") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCLOHThreshold, W("GCLOHThreshold"), 0, "Specifies the size that will make objects go on LOH") -RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_GCLOHCompact, W("GCLOHCompact"), "Specifies the LOH compaction mode") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_gcAllowVeryLargeObjects, W("gcAllowVeryLargeObjects"), 1, "Allow allocation of 2GB+ objects on GC heap") -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_GCStress, W("GCStress"), 0, "Trigger GCs at regular intervals", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_GcStressOnDirectCalls, W("GcStressOnDirectCalls"), 0, "Whether to trigger a GC on direct calls", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCStressStart, W("GCStressStart"), 0, "Start GCStress after N stress GCs have been attempted") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCStressStartAtJit, W("GCStressStartAtJit"), 0, "Start GCStress after N items are jitted") -RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_gcTrimCommitOnLowMemory, W("gcTrimCommitOnLowMemory"), "When set we trim the committed space more aggressively for the ephemeral seg. This is used for running many instances of server processes where they want to keep as little memory committed as possible") -RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_BGCSpinCount, W("BGCSpinCount"), 140, "Specifies the bgc spin count") -RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_BGCSpin, W("BGCSpin"), 2, "Specifies the bgc spin time") +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_GCStress, W("GCStress"), 0, "Trigger GCs at regular intervals", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_GcStressOnDirectCalls, W("GcStressOnDirectCalls"), 0, "Whether to trigger a GC on direct calls", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_HeapVerify, W("HeapVerify"), "When set verifies the integrity of the managed heap on entry and exit of each GC") -RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_SetupGcCoverage, W("SetupGcCoverage"), "This doesn't appear to be a config flag", CLRConfig::REGUTIL_default) RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCNumaAware, W("GCNumaAware"), 1, "Specifies if to enable GC NUMA aware") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCCpuGroup, W("GCCpuGroup"), 0, "Specifies if to enable GC to support CPU groups") -RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCHeapCount, W("GCHeapCount"), 0, "") -RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCNoAffinitize, W("GCNoAffinitize"), 0, "") -// this config is only in effect if the process is not running in multiple CPU groups. -RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCHeapAffinitizeMask, W("GCHeapAffinitizeMask"), "Specifies processor mask for Server GC threads") -RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCProvModeStress, W("GCProvModeStress"), 0, "Stress the provisional modes") -RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCHighMemPercent, W("GCHighMemPercent"), 0, "Specifies the percent for GC to consider as high memory") RETAIL_CONFIG_STRING_INFO(EXTERNAL_GCName, W("GCName"), "") -RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCHeapHardLimit, W("GCHeapHardLimit"), "Specifies the maximum commit size for the GC heap") -RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCHeapHardLimitPercent, W("GCHeapHardLimitPercent"), "Specifies the GC heap usage as a percentage of the total memory") -RETAIL_CONFIG_STRING_INFO(EXTERNAL_GCHeapAffinitizeRanges, W("GCHeapAffinitizeRanges"), "Specifies list of processors for Server GC threads. The format is a comma separated list of processor numbers or ranges of processor numbers. Example: 1,3,5,7-9,12") -RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCLargePages, W("GCLargePages"), "Specifies whether large pages should be used when a heap hard limit is set") /// /// IBC /// -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_ConvertIbcData, W("ConvertIbcData"), 1, "Converts between v1 and v2 IBC data", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_ConvertIbcData, W("ConvertIbcData"), 1, "Converts between v1 and v2 IBC data", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_DisableHotCold, W("DisableHotCold"), "Master hot/cold splitting switch in Jit64") -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DisableIBC, W("DisableIBC"), 0, "Disables the use of IBC data", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_UseIBCFile, W("UseIBCFile"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DisableIBC, W("DisableIBC"), 0, "Disables the use of IBC data", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_UseIBCFile, W("UseIBCFile"), 0, "", CLRConfig::EEConfig_default) /// /// JIT /// RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_JitAlignLoops, W("JitAlignLoops"), "Aligns loop targets to 8 byte boundaries") -CONFIG_DWORD_INFO_EX(INTERNAL_JitBreakEmit, W("JitBreakEmit"), (DWORD)-1, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_JitBreakEmit, W("JitBreakEmit"), (DWORD)-1, "", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_JitDebuggable, W("JitDebuggable"), "") #if !defined(DEBUG) && !defined(_DEBUG) #define INTERNAL_JitEnableNoWayAssert_Default 0 #else #define INTERNAL_JitEnableNoWayAssert_Default 1 #endif -RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_JitEnableNoWayAssert, W("JitEnableNoWayAssert"), INTERNAL_JitEnableNoWayAssert_Default, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_JitEnableNoWayAssert, W("JitEnableNoWayAssert"), INTERNAL_JitEnableNoWayAssert_Default, "", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_JitFramed, W("JitFramed"), "Forces EBP frames") -CONFIG_DWORD_INFO_EX(INTERNAL_JitGCStress, W("JitGCStress"), 0, "GC stress mode for jit", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_JitGCStress, W("JitGCStress"), 0, "GC stress mode for jit", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO(INTERNAL_JitHeartbeat, W("JitHeartbeat"), 0, "") CONFIG_DWORD_INFO(INTERNAL_JitHelperLogging, W("JitHelperLogging"), 0, "") RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_JITMinOpts, W("JITMinOpts"), "Forces MinOpts") RETAIL_CONFIG_STRING_INFO(EXTERNAL_JitName, W("JitName"), "Primary Jit to use") #if defined(ALLOW_SXS_JIT) -RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_AltJitName, W("AltJitName"), "Alternative Jit to use, will fall back to primary jit.", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_AltJit, W("AltJit"), "Enables AltJit and selectively limits it to the specified methods.", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_AltJitExcludeAssemblies, W("AltJitExcludeAssemblies"), "Do not use AltJit on this semicolon-delimited list of assemblies.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_AltJitName, W("AltJitName"), "Alternative Jit to use, will fall back to primary jit.", CLRConfig::EEConfig_default) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_AltJit, W("AltJit"), "Enables AltJit and selectively limits it to the specified methods.", CLRConfig::EEConfig_default) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_AltJitExcludeAssemblies, W("AltJitExcludeAssemblies"), "Do not use AltJit on this semicolon-delimited list of assemblies.", CLRConfig::EEConfig_default) #endif // defined(ALLOW_SXS_JIT) #if defined(FEATURE_STACK_SAMPLING) @@ -359,49 +324,49 @@ RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StackSamplingNumMethods, W("StackSamplingNu #endif // defined(FEATURE_JIT_SAMPLING) #if defined(ALLOW_SXS_JIT_NGEN) -RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_AltJitNgen, W("AltJitNgen"), "Enables AltJit for NGEN and selectively limits it to the specified methods.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_AltJitNgen, W("AltJitNgen"), "Enables AltJit for NGEN and selectively limits it to the specified methods.", CLRConfig::EEConfig_default) #endif // defined(ALLOW_SXS_JIT_NGEN) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitHostMaxSlabCache, W("JitHostMaxSlabCache"), 0x1000000, "Sets jit host max slab cache size, 16MB default") RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_JitOptimizeType, W("JitOptimizeType"), "") -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_JitPrintInlinedMethods, W("JitPrintInlinedMethods"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_JitPrintInlinedMethods, W("JitPrintInlinedMethods"), 0, "", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitTelemetry, W("JitTelemetry"), 1, "If non-zero, gather JIT telemetry data") RETAIL_CONFIG_STRING_INFO(INTERNAL_JitTimeLogFile, W("JitTimeLogFile"), "If set, gather JIT throughput data and write to this file.") RETAIL_CONFIG_STRING_INFO(INTERNAL_JitTimeLogCsv, W("JitTimeLogCsv"), "If set, gather JIT throughput data and write to a CSV file. This mode must be used in internal retail builds.") RETAIL_CONFIG_STRING_INFO(INTERNAL_JitFuncInfoLogFile, W("JitFuncInfoLogFile"), "If set, gather JIT function info and write to this file.") CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_JitVerificationDisable, W("JitVerificationDisable"), "") RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitLockWrite, W("JitLockWrite"), 0, "Force all volatile writes to be 'locked'") -CONFIG_STRING_INFO_EX(INTERNAL_TailCallMax, W("TailCallMax"), "", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_TailCallOpt, W("TailCallOpt"), "", CLRConfig::REGUTIL_default) +CONFIG_STRING_INFO_EX(INTERNAL_TailCallMax, W("TailCallMax"), "", CLRConfig::EEConfig_default) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_TailCallOpt, W("TailCallOpt"), "", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TailCallLoopOpt, W("TailCallLoopOpt"), 1, "Convert recursive tail calls to loops") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Jit_NetFx40PInvokeStackResilience, W("NetFx40_PInvokeStackResilience"), (DWORD)-1, "Makes P/Invoke resilient against mismatched signature and calling convention (significant perf penalty).") // AltJitAssertOnNYI should be 0 on targets where JIT is under development or bring up stage, so as to facilitate fallback to main JIT on hitting a NYI. -#if defined(_TARGET_X86_) +#if defined(TARGET_X86) RETAIL_CONFIG_DWORD_INFO(INTERNAL_AltJitAssertOnNYI, W("AltJitAssertOnNYI"), 0, "Controls the AltJit behavior of NYI stuff") #else RETAIL_CONFIG_DWORD_INFO(INTERNAL_AltJitAssertOnNYI, W("AltJitAssertOnNYI"), 1, "Controls the AltJit behavior of NYI stuff") #endif -CONFIG_DWORD_INFO_EX(INTERNAL_JitLargeBranches, W("JitLargeBranches"), 0, "Force using the largest conditional branch format", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_JitRegisterFP, W("JitRegisterFP"), 3, "Control FP enregistration", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_JitLargeBranches, W("JitLargeBranches"), 0, "Force using the largest conditional branch format", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_JitRegisterFP, W("JitRegisterFP"), 3, "Control FP enregistration", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitELTHookEnabled, W("JitELTHookEnabled"), 0, "On ARM, setting this will emit Enter/Leave/TailCall callbacks") -RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_JitMemStats, W("JitMemStats"), 0, "Display JIT memory usage statistics", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_JitMemStats, W("JitMemStats"), 0, "Display JIT memory usage statistics", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitVNMapSelBudget, W("JitVNMapSelBudget"), 100, "Max # of MapSelect's considered for a particular top-level invocation.") -#if defined(_TARGET_AMD64_) || defined(_TARGET_X86_) || defined(_TARGET_ARM64_) +#if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_ARM64) #define EXTERNAL_FeatureSIMD_Default 1 -#else // !(defined(_TARGET_AMD64_) || defined(_TARGET_X86_) || defined(_TARGET_ARM64_)) +#else // !(defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_ARM64)) #define EXTERNAL_FeatureSIMD_Default 0 -#endif // !(defined(_TARGET_AMD64_) || defined(_TARGET_X86_) || defined(_TARGET_ARM64_)) -#if defined(_TARGET_AMD64_) || defined(_TARGET_X86_) +#endif // !(defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_ARM64)) +#if defined(TARGET_AMD64) || defined(TARGET_X86) #define EXTERNAL_JitEnableAVX_Default 1 -#else // !(defined(_TARGET_AMD64_) || defined(_TARGET_X86_) +#else // !(defined(TARGET_AMD64) || defined(TARGET_X86) #define EXTERNAL_JitEnableAVX_Default 0 -#endif // !(defined(_TARGET_AMD64_) || defined(_TARGET_X86_) -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_FeatureSIMD, W("FeatureSIMD"), EXTERNAL_FeatureSIMD_Default, "Enable SIMD intrinsics recognition in System.Numerics.dll and/or System.Numerics.Vectors.dll", CLRConfig::REGUTIL_default) +#endif // !(defined(TARGET_AMD64) || defined(TARGET_X86) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_FeatureSIMD, W("FeatureSIMD"), EXTERNAL_FeatureSIMD_Default, "Enable SIMD intrinsics recognition in System.Numerics.dll and/or System.Numerics.Vectors.dll", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(INTERNAL_SIMD16ByteOnly, W("SIMD16ByteOnly"), 0, "Limit maximum SIMD vector length to 16 bytes (used by x64_arm64_altjit)") -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_EnableAVX, W("EnableAVX"), EXTERNAL_JitEnableAVX_Default, "Enable AVX instruction set for wide operations as default", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_TrackDynamicMethodDebugInfo, W("TrackDynamicMethodDebugInfo"), 0, "Specifies whether debug info should be generated and tracked for dynamic methods", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_EnableAVX, W("EnableAVX"), EXTERNAL_JitEnableAVX_Default, "Enable AVX instruction set for wide operations as default", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_TrackDynamicMethodDebugInfo, W("TrackDynamicMethodDebugInfo"), 0, "Specifies whether debug info should be generated and tracked for dynamic methods", CLRConfig::EEConfig_default) #ifdef FEATURE_MULTICOREJIT @@ -414,18 +379,18 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_MultiCoreJitProfileWriteDelay, W("MultiCoreJit /// /// Interpreter /// -RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_Interpret, W("Interpret"), "Selectively uses the interpreter to execute the specified methods", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_InterpretExclude, W("InterpretExclude"), "Excludes the specified methods from the set selected by 'Interpret'", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_Interpret, W("Interpret"), "Selectively uses the interpreter to execute the specified methods", CLRConfig::EEConfig_default) +RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_InterpretExclude, W("InterpretExclude"), "Excludes the specified methods from the set selected by 'Interpret'", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterMethHashMin, W("InterpreterMethHashMin"), 0, "Only interpret methods selected by 'Interpret' whose hash is at least this value. or after nth") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterMethHashMax, W("InterpreterMethHashMax"), UINT32_MAX, "If non-zero, only interpret methods selected by 'Interpret' whose hash is at most this value") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterStubMin, W("InterpreterStubMin"), 0, "Only interpret methods selected by 'Interpret' whose stub num is at least this value.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterStubMax, W("InterpreterStubMax"), UINT32_MAX, "If non-zero, only interpret methods selected by 'Interpret' whose stub number is at most this value.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterJITThreshold, W("InterpreterJITThreshold"), 10, "The number of times a method should be interpreted before being JITted") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterDoLoopMethods, W("InterpreterDoLoopMethods"), 0, "If set, don't check for loops, start by interpreting *all* methods") -RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_InterpreterUseCaching, W("InterpreterUseCaching"), 1, "If non-zero, use the caching mechanism.", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_InterpreterLooseRules, W("InterpreterLooseRules"), 1, "If non-zero, allow ECMA spec violations required by managed C++.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_InterpreterUseCaching, W("InterpreterUseCaching"), 1, "If non-zero, use the caching mechanism.", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_InterpreterLooseRules, W("InterpreterLooseRules"), 1, "If non-zero, allow ECMA spec violations required by managed C++.", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterPrintPostMortem, W("InterpreterPrintPostMortem"), 0, "Prints summary information about the execution to the console") -RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_InterpreterLogFile, W("InterpreterLogFile"), "If non-null, append interpreter logging to this file, else use stdout", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_InterpreterLogFile, W("InterpreterLogFile"), "If non-null, append interpreter logging to this file, else use stdout", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(INTERNAL_DumpInterpreterStubs, W("DumpInterpreterStubs"), 0, "Prints all interpreter stubs that are created to the console") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterEntries, W("TraceInterpreterEntries"), 0, "Logs entries to interpreted methods to the console") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterIL, W("TraceInterpreterIL"), 0, "Logs individual instructions of interpreted methods to the console") @@ -439,15 +404,12 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterFallback, W("InterpreterFallback"), /// /// Loader /// -CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_APIThreadStress, W("APIThreadStress"), "Used to test Loader for race conditions") -RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_ForceLog, W("ForceLog"), "Fusion flag to enforce assembly binding log. Heavily used and documented in MSDN and BLOGS.") -RETAIL_CONFIG_STRING_INFO(INTERNAL_CoreClrBinderLog, W("CoreClrBinderLog"), "Debug flag that enabled detailed log for new binder (similar to stress logging).") RETAIL_CONFIG_STRING_INFO(INTERNAL_WinMDPath, W("WinMDPath"), "Path for Windows WinMD files") /// /// Loader heap /// -CONFIG_DWORD_INFO_EX(INTERNAL_LoaderHeapCallTracing, W("LoaderHeapCallTracing"), 0, "Loader heap troubleshooting", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_LoaderHeapCallTracing, W("LoaderHeapCallTracing"), 0, "Loader heap troubleshooting", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(INTERNAL_CodeHeapReserveForJumpStubs, W("CodeHeapReserveForJumpStubs"), 1, "Percentage of code heap to reserve for jump stubs") RETAIL_CONFIG_DWORD_INFO(INTERNAL_NGenReserveForJumpStubs, W("NGenReserveForJumpStubs"), 0, "Percentage of ngen image size to reserve for jump stubs") RETAIL_CONFIG_DWORD_INFO(INTERNAL_BreakOnOutOfMemoryWithinRange, W("BreakOnOutOfMemoryWithinRange"), 0, "Break before out of memory within range exception is thrown") @@ -459,11 +421,10 @@ RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogEnable, W("LogEnable"), "Turn RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogFacility, W("LogFacility"), "Specifies a facility mask for CLR log. (See 'loglf.h'; VM interprets string value as hex number.) Also used by stresslog.") RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogFacility2, W("LogFacility2"), "Specifies a facility mask for CLR log. (See 'loglf.h'; VM interprets string value as hex number.) Also used by stresslog.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_logFatalError, W("logFatalError"), 1, "Specifies whether EventReporter logs fatal errors in the Windows event log.") -CONFIG_STRING_INFO_EX(INTERNAL_LogFile, W("LogFile"), "Specifies a file name for the CLR log.", CLRConfig::REGUTIL_default) +CONFIG_STRING_INFO_EX(INTERNAL_LogFile, W("LogFile"), "Specifies a file name for the CLR log.", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogFileAppend, W("LogFileAppend"), "Specifies whether to append to or replace the CLR log file.") CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogFlushFile, W("LogFlushFile"), "Specifies whether to flush the CLR log file on each write.") RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_LogLevel, W("LogLevel"), "4=10 msgs, 9=1000000, 10=everything") -RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(INTERNAL_LogPath, W("LogPath"), "?Fusion debug log path.") RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogToConsole, W("LogToConsole"), "Writes the CLR log to console.") CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogToDebugger, W("LogToDebugger"), "Writes the CLR log to debugger (OutputDebugStringA).") CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogToFile, W("LogToFile"), "Writes the CLR log to a file.") @@ -472,22 +433,22 @@ CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogWithPid, W("LogWithPid"), "Appends p /// /// MetaData /// -CONFIG_DWORD_INFO_EX(INTERNAL_MD_ApplyDeltaBreak, W("MD_ApplyDeltaBreak"), 0, "ASSERT when applying EnC", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_ApplyDeltaBreak, W("MD_ApplyDeltaBreak"), 0, "ASSERT when applying EnC", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_AssertOnBadImageFormat, W("AssertOnBadImageFormat"), "ASSERT when invalid MD read") -RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_MD_DeltaCheck, W("MD_DeltaCheck"), 1, "Some checks of GUID when applying EnC (?)", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_MD_EncDelta, W("MD_EncDelta"), 0, "Forces EnC Delta format in MD (?)", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_MD_ForceNoColDesSharing, W("MD_ForceNoColDesSharing"), 0, "Don't know - the only usage I could find is #if 0 (?)", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_MD_KeepKnownCA, W("MD_KeepKnownCA"), 0, "Something with known CAs (?)", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_MD_MiniMDBreak, W("MD_MiniMDBreak"), 0, "ASSERT when creating CMiniMdRw class", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_MD_PreSaveBreak, W("MD_PreSaveBreak"), 0, "ASSERT when calling CMiniMdRw::PreSave", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_MD_RegMetaBreak, W("MD_RegMetaBreak"), 0, "ASSERT when creating RegMeta class", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_MD_RegMetaDump, W("MD_RegMetaDump"), 0, "Dump MD in 4 functions (?)", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_MD_DeltaCheck, W("MD_DeltaCheck"), 1, "Some checks of GUID when applying EnC (?)", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_EncDelta, W("MD_EncDelta"), 0, "Forces EnC Delta format in MD (?)", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_MD_ForceNoColDesSharing, W("MD_ForceNoColDesSharing"), 0, "Don't know - the only usage I could find is #if 0 (?)", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_KeepKnownCA, W("MD_KeepKnownCA"), 0, "Something with known CAs (?)", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_MiniMDBreak, W("MD_MiniMDBreak"), 0, "ASSERT when creating CMiniMdRw class", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_PreSaveBreak, W("MD_PreSaveBreak"), 0, "ASSERT when calling CMiniMdRw::PreSave", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_RegMetaBreak, W("MD_RegMetaBreak"), 0, "ASSERT when creating RegMeta class", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_RegMetaDump, W("MD_RegMetaDump"), 0, "Dump MD in 4 functions (?)", CLRConfig::EEConfig_default) // MetaData - Desktop-only -CONFIG_DWORD_INFO_EX(INTERNAL_MD_WinMD_Disable, W("MD_WinMD_Disable"), 0, "Never activate the WinMD import adapter", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_MD_WinMD_AssertOnIllegalUsage, W("MD_WinMD_AssertOnIllegalUsage"), 0, "ASSERT if a WinMD import adapter detects a tool incompatibility", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_WinMD_Disable, W("MD_WinMD_Disable"), 0, "Never activate the WinMD import adapter", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_WinMD_AssertOnIllegalUsage, W("MD_WinMD_AssertOnIllegalUsage"), 0, "ASSERT if a WinMD import adapter detects a tool incompatibility", CLRConfig::EEConfig_default) // Metadata - mscordbi only - this flag is only intended to mitigate potential issues in bug fix 458597. -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_MD_PreserveDebuggerMetadataMemory, W("MD_PreserveDebuggerMetadataMemory"), 0, "Save all versions of metadata memory in the debugger when debuggee metadata is updated", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_MD_PreserveDebuggerMetadataMemory, W("MD_PreserveDebuggerMetadataMemory"), 0, "Save all versions of metadata memory in the debugger when debuggee metadata is updated", CLRConfig::EEConfig_default) /// /// Spinning heuristics @@ -509,20 +470,20 @@ CONFIG_DWORD_INFO(INTERNAL_NgenBind_ZapForbid, W("NgenBind_ZapForbid CONFIG_STRING_INFO(INTERNAL_NgenBind_ZapForbidExcludeList, W("NgenBind_ZapForbidExcludeList"), "") CONFIG_STRING_INFO(INTERNAL_NgenBind_ZapForbidList, W("NgenBind_ZapForbidList"), "") -CONFIG_DWORD_INFO_EX(INTERNAL_SymDiffDump, W("SymDiffDump"), 0, "Used to create the map file while binding the assembly. Used by SemanticDiffer", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_SymDiffDump, W("SymDiffDump"), 0, "Used to create the map file while binding the assembly. Used by SemanticDiffer", CLRConfig::EEConfig_default) /// /// NGEN /// -RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_NGen_JitName, W("NGen_JitName"), "", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_NGenFramed, W("NGenFramed"), (DWORD)-1, "Same as JitFramed, but for ngen", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_NGenOnlyOneMethod, W("NGenOnlyOneMethod"), 0, "", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_NgenOrder, W("NgenOrder"), 0, "", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_partialNGenStress, W("partialNGenStress"), 0, "", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_ZapDoNothing, W("ZapDoNothing"), 0, "", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_NgenForceFailureMask, W("NgenForceFailureMask"), (DWORD)-1, "Bitmask used to control which locations will check and raise the failure (defaults to bits: -1)", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_NgenForceFailureCount, W("NgenForceFailureCount"), 0, "If set to >0 and we have IBC data we will force a failure after we reference an IBC data item times", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_NgenForceFailureKind, W("NgenForceFailureKind"), 1, "If set to 1, We will throw a TypeLoad exception; If set to 2, We will cause an A/V", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_NGen_JitName, W("NGen_JitName"), "", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_NGenFramed, W("NGenFramed"), (DWORD)-1, "Same as JitFramed, but for ngen", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_NGenOnlyOneMethod, W("NGenOnlyOneMethod"), 0, "", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_NgenOrder, W("NgenOrder"), 0, "", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_partialNGenStress, W("partialNGenStress"), 0, "", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_ZapDoNothing, W("ZapDoNothing"), 0, "", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_NgenForceFailureMask, W("NgenForceFailureMask"), (DWORD)-1, "Bitmask used to control which locations will check and raise the failure (defaults to bits: -1)", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_NgenForceFailureCount, W("NgenForceFailureCount"), 0, "If set to >0 and we have IBC data we will force a failure after we reference an IBC data item times", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_NgenForceFailureKind, W("NgenForceFailureKind"), 1, "If set to 1, We will throw a TypeLoad exception; If set to 2, We will cause an A/V", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_NGenEnableCreatePdb, W("NGenEnableCreatePdb"), 0, "If set to >0 ngen.exe displays help on, recognizes createpdb in the command line") RETAIL_CONFIG_DWORD_INFO(INTERNAL_NGenSimulateDiskFull, W("NGenSimulateDiskFull"), 0, "If set to 1, ngen will throw a Disk full exception in ZapWriter.cpp:Save()") RETAIL_CONFIG_DWORD_INFO(INTERNAL_PartialNGen, W("PartialNGen"), (DWORD)-1, "Generate partial NGen images") @@ -536,17 +497,17 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_CrossGenAssumeInputSigned, W("CrossGenAssumeIn /// /// Profiling API / ETW /// -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_COR_ENABLE_PROFILING, W("COR_ENABLE_PROFILING"), 0, "Flag to indicate whether profiling should be enabled for the currently running process.", CLRConfig::DontPrependCOMPlus_ | CLRConfig::IgnoreConfigFiles) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_COR_ENABLE_PROFILING, W("COR_ENABLE_PROFILING"), 0, "Flag to indicate whether profiling should be enabled for the currently running process.", CLRConfig::DontPrependCOMPlus_) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_COR_PROFILER, W("COR_PROFILER"), "Specifies GUID of profiler to load into currently running process", CLRConfig::DontPrependCOMPlus_) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_COR_PROFILER_PATH, W("COR_PROFILER_PATH"), "Specifies the path to the DLL of profiler to load into currently running process", CLRConfig::DontPrependCOMPlus_) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_COR_PROFILER_PATH_32, W("COR_PROFILER_PATH_32"), "Specifies the path to the DLL of profiler to load into currently running 32 bits process", CLRConfig::DontPrependCOMPlus_) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_COR_PROFILER_PATH_64, W("COR_PROFILER_PATH_64"), "Specifies the path to the DLL of profiler to load into currently running 64 bits process", CLRConfig::DontPrependCOMPlus_) -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_CORECLR_ENABLE_PROFILING, W("CORECLR_ENABLE_PROFILING"), 0, "CoreCLR only: Flag to indicate whether profiling should be enabled for the currently running process.", CLRConfig::DontPrependCOMPlus_ | CLRConfig::IgnoreConfigFiles) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_CORECLR_ENABLE_PROFILING, W("CORECLR_ENABLE_PROFILING"), 0, "CoreCLR only: Flag to indicate whether profiling should be enabled for the currently running process.", CLRConfig::DontPrependCOMPlus_) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER, W("CORECLR_PROFILER"), "CoreCLR only: Specifies GUID of profiler to load into currently running process", CLRConfig::DontPrependCOMPlus_) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH, W("CORECLR_PROFILER_PATH"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running process", CLRConfig::DontPrependCOMPlus_) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_32, W("CORECLR_PROFILER_PATH_32"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running 32 process", CLRConfig::DontPrependCOMPlus_) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_64, W("CORECLR_PROFILER_PATH_64"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running 64 process", CLRConfig::DontPrependCOMPlus_) -RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_ProfAPI_ProfilerCompatibilitySetting, W("ProfAPI_ProfilerCompatibilitySetting"), "Specifies the profiler loading policy (the default is not to load a V2 profiler in V4)", CLRConfig::REGUTIL_default | CLRConfig::TrimWhiteSpaceFromStringValue) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_ProfAPI_ProfilerCompatibilitySetting, W("ProfAPI_ProfilerCompatibilitySetting"), "Specifies the profiler loading policy (the default is not to load a V2 profiler in V4)", CLRConfig::EEConfig_default | CLRConfig::TrimWhiteSpaceFromStringValue) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_DetachMinSleepMs, W("ProfAPI_DetachMinSleepMs"), 0, "The minimum time, in milliseconds, the CLR will wait before checking whether a profiler that is in the process of detaching is ready to be unloaded.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_DetachMaxSleepMs, W("ProfAPI_DetachMaxSleepMs"), 0, "The maximum time, in milliseconds, the CLR will wait before checking whether a profiler that is in the process of detaching is ready to be unloaded.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_RejitOnAttach, W("ProfApi_RejitOnAttach"), 1, "Enables the ability for profilers to rejit methods on attach.") @@ -558,13 +519,15 @@ CONFIG_DWORD_INFO(INTERNAL_TestOnlyEnableICorProfilerInfo, W("ProfAPI_TestOnlyEn CONFIG_DWORD_INFO(INTERNAL_TestOnlyEnableObjectAllocatedHook, W("TestOnlyEnableObjectAllocatedHook"), 0, "Test-only flag that forces CLR to initialize on startup as if ObjectAllocated callback were requested, to enable post-attach ObjectAllocated functionality.") CONFIG_DWORD_INFO(INTERNAL_TestOnlyEnableSlowELTHooks, W("TestOnlyEnableSlowELTHooks"), 0, "Test-only flag that forces CLR to initialize on startup as if slow-ELT were requested, to enable post-attach ELT functionality.") -RETAIL_CONFIG_STRING_INFO_EX(UNSUPPORTED_ETW_ObjectAllocationEventsPerTypePerSec, W("ETW_ObjectAllocationEventsPerTypePerSec"), "Desired number of GCSampledObjectAllocation ETW events to be logged per type per second. If 0, then the default built in to the implementation for the enabled event (e.g., High, Low), will be used.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO_EX(UNSUPPORTED_ETW_ObjectAllocationEventsPerTypePerSec, W("ETW_ObjectAllocationEventsPerTypePerSec"), "Desired number of GCSampledObjectAllocation ETW events to be logged per type per second. If 0, then the default built in to the implementation for the enabled event (e.g., High, Low), will be used.", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_ProfAPI_ValidateNGENInstrumentation, W("ProfAPI_ValidateNGENInstrumentation"), 0, "This flag enables additional validations when using the IMetaDataEmit APIs for NGEN'ed images to ensure only supported edits are made.") #ifdef FEATURE_PERFMAP -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_PerfMapEnabled, W("PerfMapEnabled"), 0, "This flag is used on Linux to enable writing /tmp/perf-$pid.map. It is disabled by default", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_PerfMapIgnoreSignal, W("PerfMapIgnoreSignal"), 0, "When perf map is enabled, this option will configure the specified signal to be accepted and ignored as a marker in the perf logs. It is disabled by default", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_PerfMapEnabled, W("PerfMapEnabled"), 0, "This flag is used on Linux to enable writing /tmp/perf-$pid.map. It is disabled by default", CLRConfig::EEConfig_default) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_PerfMapJitDumpPath, W("PerfMapJitDumpPath"), "Specifies a path to write the perf jitdump file. Defaults to GetTempPathA()", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_PerfMapIgnoreSignal, W("PerfMapIgnoreSignal"), 0, "When perf map is enabled, this option will configure the specified signal to be accepted and ignored as a marker in the perf logs. It is disabled by default", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapShowOptimizationTiers, W("PerfMapShowOptimizationTiers"), 1, "Shows optimization tiers in the perf map for methods, as part of the symbol name. Useful for seeing separate stack frames for different optimization tiers of each method.") +RETAIL_CONFIG_STRING_INFO(EXTERNAL_NativeImagePerfMapFormat, W("NativeImagePerfMapFormat"), "Specifies the format of native image perfmap files generated by crossgen. Valid options are RVA or OFFSET.") #endif RETAIL_CONFIG_STRING_INFO(EXTERNAL_StartupDelayMS, W("StartupDelayMS"), "") @@ -572,12 +535,11 @@ RETAIL_CONFIG_STRING_INFO(EXTERNAL_StartupDelayMS, W("StartupDelayMS"), "") /// /// Stress /// -CONFIG_DWORD_INFO_EX(INTERNAL_StressCOMCall, W("StressCOMCall"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_StressCOMCall, W("StressCOMCall"), 0, "", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_StressLog, W("StressLog"), "Turns on the stress log.") RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_ForceEnc, W("ForceEnc"), "Forces Edit and Continue to be on for all eligible modules.") RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_StressLogSize, W("StressLogSize"), "Stress log size in bytes per thread.") -CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_StressOn, W("StressOn"), "Enables the STRESS_ASSERT macro that stops runtime quickly (to prevent the clr state from changing significantly before breaking)") -CONFIG_DWORD_INFO_EX(INTERNAL_stressSynchronized, W("stressSynchronized"), 0, "Unknown if or where this is used; unless a test is specifically depending on this, it can be removed.", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_stressSynchronized, W("stressSynchronized"), 0, "Unknown if or where this is used; unless a test is specifically depending on this, it can be removed.", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_StressThreadCount, W("StressThreadCount"), "") /// @@ -603,12 +565,12 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_ForceMaxWorkerThreads, W("ThreadPoo RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_DisableStarvationDetection, W("ThreadPool_DisableStarvationDetection"), 0, "Disables the ThreadPool feature that forces new threads to be added when workitems run for too long") RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_DebugBreakOnWorkerStarvation, W("ThreadPool_DebugBreakOnWorkerStarvation"), 0, "Breaks into the debugger if the ThreadPool detects work queue starvation") RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_EnableWorkerTracking, W("ThreadPool_EnableWorkerTracking"), 0, "Enables extra expensive tracking of how many workers threads are working simultaneously") -#ifdef _TARGET_ARM64_ +#ifdef TARGET_ARM64 // Spinning scheme is currently different on ARM64, see CLRLifoSemaphore::Wait(DWORD, UINT32, UINT32) RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_UnfairSemaphoreSpinLimit, W("ThreadPool_UnfairSemaphoreSpinLimit"), 0x32, "Maximum number of spins per processor a thread pool worker thread performs before waiting for work") -#else // !_TARGET_ARM64_ +#else // !TARGET_ARM64 RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_UnfairSemaphoreSpinLimit, W("ThreadPool_UnfairSemaphoreSpinLimit"), 0x46, "Maximum number of spins a thread pool worker thread performs before waiting for work") -#endif // _TARGET_ARM64_ +#endif // TARGET_ARM64 RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Thread_UseAllCpuGroups, W("Thread_UseAllCpuGroups"), 0, "Specifies if to automatically distribute thread across CPU Groups") CONFIG_DWORD_INFO(INTERNAL_ThreadpoolTickCountAdjustment, W("ThreadpoolTickCountAdjustment"), 0, "") @@ -635,10 +597,27 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_GainExponent, RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TieredCompilation, W("TieredCompilation"), 1, "Enables tiered compilation") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_QuickJit, W("TC_QuickJit"), 1, "For methods that would be jitted, enable using quick JIT when appropriate.") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_QuickJitForLoops, W("TC_QuickJitForLoops"), 0, "When quick JIT is enabled, quick JIT may also be used for methods that contain loops.") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_AggressiveTiering, W("TC_AggressiveTiering"), 0, "Transition through tiers aggressively.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountThreshold, W("TC_CallCountThreshold"), 30, "Number of times a method must be called in tier 0 after which it is promoted to the next tier.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountingDelayMs, W("TC_CallCountingDelayMs"), 100, "A perpetual delay in milliseconds that is applied call counting in tier 0 and jitting at higher tiers, while there is startup-like activity.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DelaySingleProcMultiplier, W("TC_DelaySingleProcMultiplier"), 10, "Multiplier for TC_CallCountingDelayMs that is applied on a single-processor machine or when the process is affinitized to a single processor.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCounting, W("TC_CallCounting"), 1, "Enabled by default (only activates when TieredCompilation is also enabled). If disabled immediately backpatches prestub, and likely prevents any promotion to higher tiers") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_UseCallCountingStubs, W("TC_UseCallCountingStubs"), 1, "Uses call counting stubs for faster call counting.") +#ifdef _DEBUG +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DeleteCallCountingStubsAfter, W("TC_DeleteCallCountingStubsAfter"), 1, "Deletes call counting stubs after this many have completed. Zero to disable deleting.") +#else +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DeleteCallCountingStubsAfter, W("TC_DeleteCallCountingStubsAfter"), 4096, "Deletes call counting stubs after this many have completed. Zero to disable deleting.") +#endif +#endif + +/// +/// On-Stack Replacement +/// +#ifdef FEATURE_ON_STACK_REPLACEMENT +RETAIL_CONFIG_DWORD_INFO(INTERNAL_OSR_CounterBump, W("OSR_CounterBump"), 1000, "Counter reload value when a patchpoint is hit") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_OSR_HitLimit, W("OSR_HitLimit"), 10, "Number of times a patchpoint must call back to trigger an OSR transition") +CONFIG_DWORD_INFO(INTERNAL_OSR_LowId, W("OSR_LowId"), (DWORD)-1, "Low end of enabled patchpoint range (inclusive)"); +CONFIG_DWORD_INFO(INTERNAL_OSR_HighId, W("OSR_HighId"), 10000000, "High end of enabled patchpoint range (inclusive)"); #endif /// @@ -656,37 +635,40 @@ CONFIG_DWORD_INFO(INTERNAL_TypeLoader_InjectInterfaceDuplicates, W("INTERNAL_Typ /// /// Virtual call stubs /// -CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubCollideMonoPct, W("VirtualCallStubCollideMonoPct"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubCollideWritePct, W("VirtualCallStubCollideWritePct"), 100, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubDumpLogCounter, W("VirtualCallStubDumpLogCounter"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubDumpLogIncr, W("VirtualCallStubDumpLogIncr"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_VirtualCallStubLogging, W("VirtualCallStubLogging"), 0, "Worth keeping, but should be moved into \"#ifdef STUB_LOGGING\" blocks. This goes for most (or all) of the stub logging infrastructure.", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubMissCount, W("VirtualCallStubMissCount"), 100, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubResetCacheCounter, W("VirtualCallStubResetCacheCounter"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubResetCacheIncr, W("VirtualCallStubResetCacheIncr"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubCollideMonoPct, W("VirtualCallStubCollideMonoPct"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubCollideWritePct, W("VirtualCallStubCollideWritePct"), 100, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubDumpLogCounter, W("VirtualCallStubDumpLogCounter"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubDumpLogIncr, W("VirtualCallStubDumpLogIncr"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_VirtualCallStubLogging, W("VirtualCallStubLogging"), 0, "Worth keeping, but should be moved into \"#ifdef STUB_LOGGING\" blocks. This goes for most (or all) of the stub logging infrastructure.", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubMissCount, W("VirtualCallStubMissCount"), 100, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubResetCacheCounter, W("VirtualCallStubResetCacheCounter"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubResetCacheIncr, W("VirtualCallStubResetCacheIncr"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::EEConfig_default) /// /// Watson /// RETAIL_CONFIG_DWORD_INFO(INTERNAL_DisableWatsonForManagedExceptions, W("DisableWatsonForManagedExceptions"), 0, "Disable Watson and debugger launching for managed exceptions") +/// +/// Dump generation +/// +RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgEnableMiniDump, W("DbgEnableMiniDump"), 0, "Enable unhandled exception crash dump generation") +RETAIL_CONFIG_STRING_INFO(INTERNAL_DbgMiniDumpName, W("DbgMiniDumpName"), "Crash dump name") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgMiniDumpType, W("DbgMiniDumpType"), 0, "Crash dump type: 1 normal, 2 withheap, 3 triage, 4 full") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_CreateDumpDiagnostics, W("CreateDumpDiagnostics"), 0, "Enable crash dump generation diagnostic logging") + /// /// Zap /// -RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_ZapBBInstr, W("ZapBBInstr"), "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_ZapBBInstr, W("ZapBBInstr"), "", CLRConfig::EEConfig_default) RETAIL_CONFIG_STRING_INFO(EXTERNAL_ZapBBInstrDir, W("ZapBBInstrDir"), "") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ZapDisable, W("ZapDisable"), 0, "") -CONFIG_STRING_INFO_EX(INTERNAL_ZapExclude, W("ZapExclude"), "", CLRConfig::REGUTIL_default) -CONFIG_STRING_INFO_EX(INTERNAL_ZapOnly, W("ZapOnly"), "", CLRConfig::REGUTIL_default) +CONFIG_STRING_INFO_EX(INTERNAL_ZapExclude, W("ZapExclude"), "", CLRConfig::EEConfig_default) +CONFIG_STRING_INFO_EX(INTERNAL_ZapOnly, W("ZapOnly"), "", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_ZapRequire, W("ZapRequire"), "") RETAIL_CONFIG_STRING_INFO(EXTERNAL_ZapRequireExcludeList, W("ZapRequireExcludeList"), "") RETAIL_CONFIG_STRING_INFO(EXTERNAL_ZapRequireList, W("ZapRequireList"), "") -RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_ZapSet, W("ZapSet"), "", CLRConfig::REGUTIL_default) - -#ifdef FEATURE_LAZY_COW_PAGES -RETAIL_CONFIG_DWORD_INFO(INTERNAL_ZapLazyCOWPagesEnabled, W("ZapLazyCOWPagesEnabled"), 1, ""); -CONFIG_DWORD_INFO(INTERNAL_DebugAssertOnMissedCOWPage, W("DebugAssertOnMissedCOWPage"), 1, ""); -#endif //FEATURE_LAZY_COW_PAGES +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_ZapSet, W("ZapSet"), "", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ReadyToRun, W("ReadyToRun"), 1, "Enable/disable use of ReadyToRun native code") // On by default for CoreCLR RETAIL_CONFIG_STRING_INFO(EXTERNAL_ReadyToRunExcludeList, W("ReadyToRunExcludeList"), "List of assemblies that cannot use Ready to Run images") @@ -702,7 +684,7 @@ RETAIL_CONFIG_STRING_INFO(INTERNAL_EventNameFilter, W("EventNameFilter"), "") /// Interop /// CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_ExposeExceptionsInCOM, W("ExposeExceptionsInCOM"), "") -RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_PInvokeInline, W("PInvokeInline"), "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_PInvokeInline, W("PInvokeInline"), "", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_InteropValidatePinnedObjects, W("InteropValidatePinnedObjects"), 0, "After returning from a managed-to-unmanaged interop call, validate GC heap around objects pinned by IL stubs.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_InteropLogArguments, W("InteropLogArguments"), 0, "Log all pinned arguments passed to an interop call") RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_LogCCWRefCountChange, W("LogCCWRefCountChange"), "Outputs debug information and calls LogCCWRefCountChange_BREAKPOINT when AddRef or Release is called on a CCW.") @@ -721,6 +703,11 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeRundown, W("EventPipeRundown"), 1, "E RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeCircularMB, W("EventPipeCircularMB"), 1024, "The EventPipe circular buffer size in megabytes.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeProcNumbers, W("EventPipeProcNumbers"), 0, "Enable/disable capturing processor numbers in EventPipe event headers") +// +// Diagnostics Server +// +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_DOTNET_DiagnosticsServerAddress, W("DOTNET_DiagnosticsServerAddress"), "The full path including filename for the OS transport (NamedPipe on Windows; Unix Domain Socket on Linux) to be used by the Diagnostics Server", CLRConfig::DontPrependCOMPlus_); + // // LTTng // @@ -750,40 +737,36 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_GDBJitEmitDebugFrame, W("GDBJitEmitDebugFrame" // // DO NOT ADD ANY MORE CONFIG SWITCHES TO THIS SECTION! // ** -CONFIG_DWORD_INFO_EX(INTERNAL_ActivatePatchSkip, W("ActivatePatchSkip"), 0, "Allows an assert when ActivatePatchSkip is called", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_ActivatePatchSkip, W("ActivatePatchSkip"), 0, "Allows an assert when ActivatePatchSkip is called", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_AlwaysUseMetadataInterfaceMapLayout, W("AlwaysUseMetadataInterfaceMapLayout"), "Used for debugging generic interface map layout.") CONFIG_DWORD_INFO(INTERNAL_AssertOnUnneededThis, W("AssertOnUnneededThis"), 0, "While the ConfigDWORD is unnecessary, the contained ASSERT should be kept. This may result in some work tracking down violating MethodDescCallSites.") -CONFIG_DWORD_INFO_EX(INTERNAL_AssertStacktrace, W("AssertStacktrace"), 1, "", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_clearNativeImageStress, W("clearNativeImageStress"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_AssertStacktrace, W("AssertStacktrace"), 1, "", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_clearNativeImageStress, W("clearNativeImageStress"), 0, "", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_CPUFamily, W("CPUFamily"), "") CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_CPUFeatures, W("CPUFeatures"), "") -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_DisableConfigCache, W("DisableConfigCache"), 0, "Used to disable the \"probabilistic\" config cache, which walks through the appropriate config registry keys on init and probabilistically keeps track of which exist.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_DisableConfigCache, W("DisableConfigCache"), 0, "Used to disable the \"probabilistic\" config cache, which walks through the appropriate config registry keys on init and probabilistically keeps track of which exist.", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_DisableStackwalkCache, W("DisableStackwalkCache"), "") RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_DoubleArrayToLargeObjectHeap, W("DoubleArrayToLargeObjectHeap"), "Controls double[] placement") -CONFIG_DWORD_INFO(INTERNAL_DumpConfiguration, W("DumpConfiguration"), 0, "Dumps runtime properties of xml configuration files to the log.") CONFIG_STRING_INFO(INTERNAL_DumpOnClassLoad, W("DumpOnClassLoad"), "Dumps information about loaded class to log.") CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_ExpandAllOnLoad, W("ExpandAllOnLoad"), "") CONFIG_STRING_INFO_DIRECT_ACCESS(INTERNAL_ForcedRuntime, W("ForcedRuntime"), "Verify version of CLR loaded") -CONFIG_DWORD_INFO_EX(INTERNAL_ForceRelocs, W("ForceRelocs"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_ForceRelocs, W("ForceRelocs"), 0, "", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_GenerateLongJumpDispatchStubRatio, W("GenerateLongJumpDispatchStubRatio"), "Useful for testing VSD on AMD64") -CONFIG_DWORD_INFO_EX(INTERNAL_HashStack, W("HashStack"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_HashStack, W("HashStack"), 0, "", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO(INTERNAL_HostManagerConfig, W("HostManagerConfig"), (DWORD)-1, "") CONFIG_DWORD_INFO(INTERNAL_HostTestThreadAbort, W("HostTestThreadAbort"), 0, "") RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_IgnoreDllMainReturn, W("IgnoreDllMainReturn"), 0, "Don't check the return value of DllMain if this is set", CLRConfig::ConfigFile_ApplicationFirst) CONFIG_STRING_INFO(INTERNAL_InvokeHalt, W("InvokeHalt"), "Throws an assert when the given method is invoked through reflection.") -RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_legacyNullReferenceExceptionPolicy, W("legacyNullReferenceExceptionPolicy"), "") -RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_legacyUnhandledExceptionPolicy, W("legacyUnhandledExceptionPolicy"), "") CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_MaxStackDepth, W("MaxStackDepth"), "") CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_MaxStubUnwindInfoSegmentSize, W("MaxStubUnwindInfoSegmentSize"), "") CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_MaxThreadRecord, W("MaxThreadRecord"), "") CONFIG_DWORD_INFO(INTERNAL_MessageDebugOut, W("MessageDebugOut"), 0, "") -CONFIG_DWORD_INFO_EX(INTERNAL_MscorsnLogging, W("MscorsnLogging"), 0, "Enables strong name logging", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_NativeImageRequire, W("NativeImageRequire"), 0, "", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_NestedEhOom, W("NestedEhOom"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_NativeImageRequire, W("NativeImageRequire"), 0, "", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_NestedEhOom, W("NestedEhOom"), 0, "", CLRConfig::EEConfig_default) #define INTERNAL_NoGuiOnAssert_Default 1 -RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_NoGuiOnAssert, W("NoGuiOnAssert"), INTERNAL_NoGuiOnAssert_Default, "", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_NoProcedureSplitting, W("NoProcedureSplitting"), 0, "", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_NoStringInterning, W("NoStringInterning"), 1, "Disallows string interning. I see no value in it anymore.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_NoGuiOnAssert, W("NoGuiOnAssert"), INTERNAL_NoGuiOnAssert_Default, "", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_NoProcedureSplitting, W("NoProcedureSplitting"), 0, "", CLRConfig::EEConfig_default) +CONFIG_DWORD_INFO_EX(INTERNAL_NoStringInterning, W("NoStringInterning"), 1, "Disallows string interning. I see no value in it anymore.", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_NotifyBadAppCfg, W("NotifyBadAppCfg"), "Whether to show a message box for bad application config file.") CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_PauseOnLoad, W("PauseOnLoad"), "Stops in SystemDomain::init. I think it can be removed.") CONFIG_DWORD_INFO(INTERNAL_PerfAllocsSizeThreshold, W("PerfAllocsSizeThreshold"), 0x3FFFFFFF, "Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler.") @@ -793,8 +776,8 @@ RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Prepopulate1, W("Prepopulate1"), 1, "") CONFIG_STRING_INFO(INTERNAL_PrestubGC, W("PrestubGC"), "") CONFIG_STRING_INFO(INTERNAL_PrestubHalt, W("PrestubHalt"), "") RETAIL_CONFIG_STRING_INFO(EXTERNAL_RestrictedGCStressExe, W("RestrictedGCStressExe"), "") -CONFIG_DWORD_INFO_EX(INTERNAL_ReturnSourceTypeForTesting, W("ReturnSourceTypeForTesting"), 0, "Allows returning the (internal only) source type of an IL to Native mapping for debugging purposes", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_RSStressLog, W("RSStressLog"), 0, "Allows turning on logging for RS startup", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_ReturnSourceTypeForTesting, W("ReturnSourceTypeForTesting"), 0, "Allows returning the (internal only) source type of an IL to Native mapping for debugging purposes", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_RSStressLog, W("RSStressLog"), 0, "Allows turning on logging for RS startup", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_SaveThreadInfo, W("SaveThreadInfo"), "") CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_SaveThreadInfoMask, W("SaveThreadInfoMask"), "") CONFIG_DWORD_INFO(INTERNAL_SBDumpOnNewIndex, W("SBDumpOnNewIndex"), 0, "Used for Syncblock debugging. It's been a while since any of those have been used.") @@ -803,11 +786,11 @@ CONFIG_DWORD_INFO(INTERNAL_SBDumpStyle, W("SBDumpStyle"), 0, "Used for Syncblock RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(UNSUPPORTED_ShimDatabaseVersion, W("ShimDatabaseVersion"), "Force using shim database version in registry") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_SleepOnExit, W("SleepOnExit"), 0, "Used for lrak detection. I'd say deprecated by umdh.") CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_StubLinkerUnwindInfoVerificationOn, W("StubLinkerUnwindInfoVerificationOn"), "") -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_SuccessExit, W("SuccessExit"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_SuccessExit, W("SuccessExit"), 0, "", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_SymbolReadingPolicy, W("SymbolReadingPolicy"), "Specifies when PDBs may be read") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TestDataConsistency, W("TestDataConsistency"), FALSE, "Allows ensuring the left side is not holding locks (and may thus be in an inconsistent state) when inspection occurs") -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_ThreadGuardPages, W("ThreadGuardPages"), 0, "", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_Timeline, W("Timeline"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_ThreadGuardPages, W("ThreadGuardPages"), 0, "", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_Timeline, W("Timeline"), 0, "", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_TotalStressLogSize, W("TotalStressLogSize"), "Total stress log size in bytes.") #ifdef _DEBUG diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrdata.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrdata.idl index 6ef8ddb..95bc6c8 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrdata.idl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrdata.idl @@ -112,7 +112,7 @@ interface ICLRDataTarget : IUnknown * implementation this can fail. */ HRESULT GetCurrentThreadID([out] ULONG32* threadID); - + /* * Thread context. */ @@ -137,7 +137,7 @@ interface ICLRDataTarget : IUnknown }; /* - * Interface used by the data access services layer to manipulate + * Interface used by the data access services layer to manipulate * virtual memory regions in the target. The target may not support * modification. */ @@ -197,9 +197,23 @@ interface ICLRDataTarget3 : ICLRDataTarget2 HRESULT GetExceptionThreadID([out] ULONG32* threadID); }; +[ + object, + local, + uuid(b760bf44-9377-4597-8be7-58083bdc5146), + pointer_default(unique) +] +interface ICLRRuntimeLocator : IUnknown +{ + /* + Returns the base address of the module containing the runtime. + */ + HRESULT GetRuntimeBase([out] CLRDATA_ADDRESS* baseAddress); +}; + /* - * Interface used by the data access services layer to locate metadata - * of assemblies in a target. + * Interface used by the data access services layer to locate metadata + * of assemblies in a target. * * The API client must implement this interface as appropriate for the * particular target (for example, a live process or a memory dump). @@ -217,7 +231,7 @@ interface ICLRDataTarget3 : ICLRDataTarget2 interface ICLRMetadataLocator : IUnknown { /* - * Ask the target to retrieve metadata for an image. + * Ask the target to retrieve metadata for an image. */ HRESULT GetMetadata([in] LPCWSTR imagePath, [in] ULONG32 imageTimestamp, @@ -265,8 +279,8 @@ interface ICLRDataEnumMemoryRegionsCallback2 : ICLRDataEnumMemoryRegionsCallback { /* * ICLRDataEnumMemoryRegions::EnumMemoryRegions will call this function - * for every memory regions it needs to overwrite/poison with the specified - * data buffer passed as input argument. + * for every memory regions it needs to overwrite/poison with the specified + * data buffer passed as input argument. */ HRESULT UpdateMemoryRegion( [in] CLRDATA_ADDRESS address, @@ -280,10 +294,10 @@ interface ICLRDataEnumMemoryRegionsCallback2 : ICLRDataEnumMemoryRegionsCallback typedef enum CLRDataEnumMemoryFlags { CLRDATA_ENUM_MEM_DEFAULT = 0x0, - CLRDATA_ENUM_MEM_MINI = CLRDATA_ENUM_MEM_DEFAULT, // generating skinny mini-dump + CLRDATA_ENUM_MEM_MINI = CLRDATA_ENUM_MEM_DEFAULT, // generating skinny mini-dump CLRDATA_ENUM_MEM_HEAP = 0x1, // generating heap dump CLRDATA_ENUM_MEM_TRIAGE = 0x2, // generating triage mini-dump - + /* More bits to be added here later */ } CLRDataEnumMemoryFlags; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrhost.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrhost.h index 88a917d..76523b0 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrhost.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrhost.h @@ -56,176 +56,20 @@ #endif // _DEBUG -IExecutionEngine *GetExecutionEngine(); -IEEMemoryManager *GetEEMemoryManager(); LPVOID ClrVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); BOOL ClrVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); SIZE_T ClrVirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength); BOOL ClrVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); -LPVOID ClrDebugAlloc (size_t size, LPCSTR pszFile, int iLineNo); -HANDLE ClrGetProcessHeap(); -HANDLE ClrHeapCreate(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize); -BOOL ClrHeapDestroy(HANDLE hHeap); -LPVOID ClrHeapAlloc(HANDLE hHeap, DWORD dwFlags, S_SIZE_T dwBytes); -BOOL ClrHeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem); -BOOL ClrHeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem); -HANDLE ClrGetProcessExecutableHeap(); +#ifdef HOST_WINDOWS +HANDLE ClrGetProcessExecutableHeap(); +#endif #ifdef FAILPOINTS_ENABLED extern int RFS_HashStack(); #endif - -void ClrFlsAssociateCallback(DWORD slot, PTLS_CALLBACK_FUNCTION callback); - -typedef LPVOID* (*CLRFLSGETBLOCK)(); -extern CLRFLSGETBLOCK __ClrFlsGetBlock; - -// Combining getter/setter into a single call -inline void ClrFlsIncrementValue(DWORD slot, int increment) -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_MODE_ANY; - STATIC_CONTRACT_CANNOT_TAKE_LOCK; - - _ASSERTE(increment != 0); - - void **block = (*__ClrFlsGetBlock)(); - size_t value; - - if (block != NULL) - { - value = (size_t) block[slot]; - - _ASSERTE((increment > 0) || (value + increment < value)); - block[slot] = (void *) (value + increment); - } - else - { - BEGIN_PRESERVE_LAST_ERROR; - - IExecutionEngine * pEngine = GetExecutionEngine(); - value = (size_t) pEngine->TLS_GetValue(slot); - - _ASSERTE((increment > 0) || (value + increment < value)); - pEngine->TLS_SetValue(slot, (void *) (value + increment)); - - END_PRESERVE_LAST_ERROR; - } -} - - -inline void * ClrFlsGetValue (DWORD slot) -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_MODE_ANY; - STATIC_CONTRACT_CANNOT_TAKE_LOCK; - - void **block = (*__ClrFlsGetBlock)(); - if (block != NULL) - { - return block[slot]; - } - else - { - void * value = GetExecutionEngine()->TLS_GetValue(slot); - return value; - } -} - - -inline BOOL ClrFlsCheckValue(DWORD slot, void ** pValue) -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_MODE_ANY; - -#ifdef _DEBUG - *pValue = ULongToPtr(0xcccccccc); -#endif //_DEBUG - void **block = (*__ClrFlsGetBlock)(); - if (block != NULL) - { - *pValue = block[slot]; - return TRUE; - } - else - { - BOOL result = GetExecutionEngine()->TLS_CheckValue(slot, pValue); - return result; - } -} - -inline void ClrFlsSetValue(DWORD slot, void *pData) -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_MODE_ANY; - STATIC_CONTRACT_CANNOT_TAKE_LOCK; - - void **block = (*__ClrFlsGetBlock)(); - if (block != NULL) - { - block[slot] = pData; - } - else - { - BEGIN_PRESERVE_LAST_ERROR; - - GetExecutionEngine()->TLS_SetValue(slot, pData); - - END_PRESERVE_LAST_ERROR; - } -} - -#ifndef SELF_NO_HOST -LPVOID EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes); -BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem); -#endif - -inline LPVOID ClrAllocInProcessHeap(DWORD dwFlags, S_SIZE_T dwBytes) -{ - STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; - if (dwBytes.IsOverflow()) - { - return NULL; - } - -#ifndef SELF_NO_HOST - return EEHeapAllocInProcessHeap(dwFlags, dwBytes.Value()); -#else -#undef HeapAlloc -#undef GetProcessHeap - static HANDLE ProcessHeap = NULL; - if (ProcessHeap == NULL) - ProcessHeap = GetProcessHeap(); - return ::HeapAlloc(ProcessHeap,dwFlags,dwBytes.Value()); -#define HeapAlloc(hHeap, dwFlags, dwBytes) Dont_Use_HeapAlloc(hHeap, dwFlags, dwBytes) -#define GetProcessHeap() Dont_Use_GetProcessHeap() -#endif -} - -inline BOOL ClrFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem) -{ - STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; -#ifndef SELF_NO_HOST - return EEHeapFreeInProcessHeap(dwFlags, lpMem); -#else -#undef HeapFree -#undef GetProcessHeap - static HANDLE ProcessHeap = NULL; - if (ProcessHeap == NULL) - ProcessHeap = GetProcessHeap(); - return (BOOL)(BYTE)::HeapFree(ProcessHeap, dwFlags, lpMem); -#define HeapFree(hHeap, dwFlags, lpMem) Dont_Use_HeapFree(hHeap, dwFlags, lpMem) -#define GetProcessHeap() Dont_Use_GetProcessHeap() -#endif -} - // Critical section support for CLR DLLs other than the the EE. // Include the header defining each Crst type and its corresponding level (relative rank). This is // auto-generated from a tool that takes a high-level description of each Crst type and its dependencies. @@ -233,29 +77,10 @@ inline BOOL ClrFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem) // critical section api CRITSEC_COOKIE ClrCreateCriticalSection(CrstType type, CrstFlags flags); -HRESULT ClrDeleteCriticalSection(CRITSEC_COOKIE cookie); +void ClrDeleteCriticalSection(CRITSEC_COOKIE cookie); void ClrEnterCriticalSection(CRITSEC_COOKIE cookie); void ClrLeaveCriticalSection(CRITSEC_COOKIE cookie); -// event api -EVENT_COOKIE ClrCreateAutoEvent(BOOL bInitialState); -EVENT_COOKIE ClrCreateManualEvent(BOOL bInitialState); -void ClrCloseEvent(EVENT_COOKIE event); -BOOL ClrSetEvent(EVENT_COOKIE event); -BOOL ClrResetEvent(EVENT_COOKIE event); -DWORD ClrWaitEvent(EVENT_COOKIE event, DWORD dwMilliseconds, BOOL bAlertable); - -// semaphore api -SEMAPHORE_COOKIE ClrCreateSemaphore(DWORD dwInitial, DWORD dwMax); -void ClrCloseSemaphore(SEMAPHORE_COOKIE semaphore); -BOOL ClrReleaseSemaphore(SEMAPHORE_COOKIE semaphore, LONG lReleaseCount, LONG *lpPreviousCount); -DWORD ClrWaitSemaphore(SEMAPHORE_COOKIE semaphore, DWORD dwMilliseconds, BOOL bAlertable); - -// mutex api -MUTEX_COOKIE ClrCreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCTSTR lpName); -void ClrCloseMutex(MUTEX_COOKIE mutex); -BOOL ClrReleaseMutex(MUTEX_COOKIE mutex); -DWORD ClrWaitForMutex(MUTEX_COOKIE mutex,DWORD dwMilliseconds,BOOL bAlertable); DWORD ClrSleepEx(DWORD dwMilliseconds, BOOL bAlertable); // Rather than use the above APIs directly, it is recommended that holder classes @@ -268,98 +93,19 @@ typedef Holder, VoidClrDeleteCriticalSection, NULL> CRITSEC_AllocationHolder; -class Event { -public: - Event () - : m_event(NULL) - {STATIC_CONTRACT_LEAF;} - ~Event () - { - STATIC_CONTRACT_WRAPPER; - CloseEvent(); - } - - void CreateAutoEvent(BOOL bInitialState) - { - STATIC_CONTRACT_WRAPPER; - m_event = ClrCreateAutoEvent(bInitialState); - } - void CreateManualEvent(BOOL bInitialState) - { - STATIC_CONTRACT_WRAPPER; - m_event = ClrCreateManualEvent(bInitialState); - } - void CloseEvent() - { - STATIC_CONTRACT_WRAPPER; - if (m_event != NULL) - ClrCloseEvent(m_event); - m_event = NULL; - } - - BOOL Set() - { - STATIC_CONTRACT_WRAPPER; - return ClrSetEvent(m_event); - } - BOOL Reset() - { - STATIC_CONTRACT_WRAPPER; - return ClrResetEvent(m_event); - } - DWORD Wait(DWORD dwMilliseconds, BOOL bAlertable) - { - STATIC_CONTRACT_WRAPPER; - return ClrWaitEvent(m_event, dwMilliseconds, bAlertable); - } - -private: - EVENT_COOKIE m_event; -}; - -class Semaphore { -public: - Semaphore () - : m_semaphore(NULL) - {STATIC_CONTRACT_LEAF;} - ~Semaphore () - { - STATIC_CONTRACT_WRAPPER; - Close(); - } - - void Create(DWORD dwInitial, DWORD dwMax) - { - STATIC_CONTRACT_WRAPPER; - m_semaphore = ClrCreateSemaphore(dwInitial, dwMax); - } - void Close() - { - STATIC_CONTRACT_WRAPPER; - if (m_semaphore != NULL) - ClrCloseSemaphore(m_semaphore); - m_semaphore = NULL; - } - - BOOL Release(LONG lReleaseCount, LONG* lpPreviousCount) - { - STATIC_CONTRACT_WRAPPER; - return ClrReleaseSemaphore(m_semaphore, lReleaseCount, lpPreviousCount); - } - DWORD Wait(DWORD dwMilliseconds, BOOL bAlertable) - { - STATIC_CONTRACT_WRAPPER; - return ClrWaitSemaphore(m_semaphore, dwMilliseconds, bAlertable); - } - -private: - SEMAPHORE_COOKIE m_semaphore; -}; - HMODULE GetCLRModule (); -extern void IncCantAllocCount(); -extern void DecCantAllocCount(); +extern thread_local int t_CantAllocCount; + +inline void IncCantAllocCount() +{ + t_CantAllocCount++; +} + +inline void DecCantAllocCount() +{ + t_CantAllocCount--; +} class CantAllocHolder { @@ -375,18 +121,13 @@ public: }; // At places where want to allocate stress log, we need to first check if we are allowed to do so. -// If ClrTlsInfo doesn't exist for this thread, we take it as can alloc inline bool IsInCantAllocRegion () { - size_t count = 0; - if (ClrFlsCheckValue(TlsIdx_CantAllocCount, (LPVOID *)&count)) - { - _ASSERTE (count >= 0); - return count > 0; - } - return false; + return t_CantAllocCount != 0; +} +inline BOOL IsInCantAllocStressLogRegion() +{ + return t_CantAllocCount != 0; } -// for stress log the rule is more restrict, we have to check the global counter too -extern BOOL IsInCantAllocStressLogRegion(); #endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrinternal.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrinternal.idl index 0c93f4a..27a3c0a 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrinternal.idl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrinternal.idl @@ -16,45 +16,6 @@ import "unknwn.idl"; // import mscoree.idl for BucketParameters definition import "mscoree.idl"; - - -cpp_quote("#if 0") - -typedef struct _OSVERSIONINFOA { - DWORD dwOSVersionInfoSize; - DWORD dwMajorVersion; - DWORD dwMinorVersion; - DWORD dwBuildNumber; - DWORD dwPlatformId; - CHAR szCSDVersion[ 128 ]; // Maintenance string for PSS usage -} OSVERSIONINFOA, *POSVERSIONINFOA, *LPOSVERSIONINFOA; - -typedef struct _OSVERSIONINFOW { - DWORD dwOSVersionInfoSize; - DWORD dwMajorVersion; - DWORD dwMinorVersion; - DWORD dwBuildNumber; - DWORD dwPlatformId; - WCHAR szCSDVersion[ 128 ]; // Maintenance string for PSS usage -} OSVERSIONINFOW, *POSVERSIONINFOW, *LPOSVERSIONINFOW, RTL_OSVERSIONINFOW, *PRTL_OSVERSIONINFOW; -#ifdef UNICODE -typedef OSVERSIONINFOW OSVERSIONINFO; -typedef POSVERSIONINFOW POSVERSIONINFO; -typedef LPOSVERSIONINFOW LPOSVERSIONINFO; -#else -typedef OSVERSIONINFOA OSVERSIONINFO; -typedef POSVERSIONINFOA POSVERSIONINFO; -typedef LPOSVERSIONINFOA LPOSVERSIONINFO; -#endif // UNICODE - -cpp_quote("#endif") - -// IID IExecutionEngine : uuid(7AF02DAC-2A33-494b-A09F-25E00A93C6F8) -cpp_quote("EXTERN_GUID(IID_IExecutionEngine, 0x7AF02DAC, 0x2A33, 0x494b, 0xA0, 0x9F, 0x25, 0xE0, 0x0A, 0x93, 0xC6, 0xF8);") - -// IID IEEMemoryManager : uuid{17713B61-B59F-4e13-BAAF-91623DC8ADC0} -cpp_quote("EXTERN_GUID(IID_IEEMemoryManager, 0x17713b61, 0xb59f, 0x4e13, 0xba, 0xaf, 0x91, 0x62, 0x3d, 0xc8, 0xad, 0xc0);") - // This ID is embedded in the CLRDEBUGINFO resource so that the shim can differentiate dlls which happen to be named // clr.dll from official Microsoft clr.dll implementations. This is not intended to authenticate a CLR in a strong // security sense but short of deliberate 3rd party spoofing it should provide a good identity. @@ -62,8 +23,8 @@ cpp_quote("EXTERN_GUID(IID_IEEMemoryManager, 0x17713b61, 0xb59f, 0x4e13, 0xba, 0 // Using a different ID allows us to completely hide different CLR SKUs from each other. The recommendation is to keep // the ID contant between different versions of the same SKU and use mscordbi's logic to determine whether a given // version is compatible. This allows debuggers to give different errors for 'future version of the CLR I don't -// support' vs. 'No CLR is loaded at all.' -// +// support' vs. 'No CLR is loaded at all.' +// // This guid first appears in version 4.0 of CLR on x86 and amd64 - earlier versions had no resource // GUID CLR_ID_V4_DESKTOP : uuid{267F3989-D786-4b9a-9AF6-D19E42D557EC} cpp_quote("EXTERN_GUID(CLR_ID_V4_DESKTOP, 0x267f3989, 0xd786, 0x4b9a, 0x9a, 0xf6, 0xd1, 0x9e, 0x42, 0xd5, 0x57, 0xec);") @@ -92,9 +53,6 @@ cpp_quote("EXTERN_GUID(IID_IPrivateManagedExceptionReporting, 0xad76a023, 0x332d // Interface for exposing services from the EE to other DLLs of the CLR. //***************************************************************************** typedef void * CRITSEC_COOKIE; -typedef void * EVENT_COOKIE; -typedef void * SEMAPHORE_COOKIE; -typedef void * MUTEX_COOKIE; typedef enum { CRST_DEFAULT = 0x0, @@ -107,178 +65,15 @@ typedef enum { CRST_HOST_BREAKABLE = 0x20, // This lock is held while running managed code. It can be terminated by a host. // CRST_UNUSED = 0x40, CRST_TAKEN_DURING_SHUTDOWN = 0x80, // This lock is taken during the shutdown sequence in EEShutdown(helper) - CRST_GC_NOTRIGGER_WHEN_TAKEN = 0x100, + CRST_GC_NOTRIGGER_WHEN_TAKEN = 0x100, // User of this lock cannot trigger GC, while it is locked. // Note that Enter on this lock can trigger GC if called from COOPERATIVE mode. // It is useful for locks which can be taken on GC or debugger threads. CRST_DEBUG_ONLY_CHECK_FORBID_SUSPEND_THREAD = 0x200, - // Some rare locks should be taken only in ForbidSuspend region (i.e. profiler cannot walk the stack), + // Some rare locks should be taken only in ForbidSuspend region (i.e. profiler cannot walk the stack), // this option will assert it in debug mode. } CrstFlags; -// Callback function for cleaning up TLS -typedef VOID (__stdcall *PTLS_CALLBACK_FUNCTION)(PVOID); - - -[ - uuid(7AF02DAC-2A33-494b-A09F-25E00A93C6F8), - helpstring("CLR Coordination Interface"), - pointer_default(unique), - local -] -interface IExecutionEngine : IUnknown -{ - // Thread Local Storage is based on logical threads. The underlying - // implementation could be threads, fibers, or something more exotic. - // Slot numbers are predefined. This is not a general extensibility - // mechanism. - - // Associate a callback function for releasing TLS on thread/fiber death. - // This can be NULL. - void TLS_AssociateCallback([in] DWORD slot, [in] PTLS_CALLBACK_FUNCTION callback); - - // Get the TLS block for fast Get/Set operations - PVOID* TLS_GetDataBlock(); - - // Get the value at a slot - PVOID TLS_GetValue([in] DWORD slot); - - // Get the value at a slot, return FALSE if TLS info block doesn't exist - BOOL TLS_CheckValue([in] DWORD slot, [out] PVOID * pValue); - - // Set the value at a slot - void TLS_SetValue([in] DWORD slot, [in] PVOID pData); - - // Free TLS memory block and make callback - void TLS_ThreadDetaching(); - - // Critical Sections are sometimes exposed to the host and therefore need to be - // reflected from all CLR DLLs to the EE. - // - // In addition, we always monitor interactions between the lock & the GC, based - // on the GC mode in which the lock is acquired and we restrict what operations - // are permitted while holding the lock based on this. - // - // Finally, we we rank all our locks to prevent deadlock across all the DLLs of - // the CLR. This is the level argument to CreateLock. - // - // All usage of these locks must be exception-safe. To achieve this, we suggest - // using Holders (see holder.h & crst.h). In fact, within the EE code cannot - // hold locks except by using exception-safe holders. - - CRITSEC_COOKIE CreateLock([in] LPCSTR szTag, [in] LPCSTR level, [in] CrstFlags flags); - - void DestroyLock([in] CRITSEC_COOKIE lock); - - void AcquireLock([in] CRITSEC_COOKIE lock); - - void ReleaseLock([in] CRITSEC_COOKIE lock); - - EVENT_COOKIE CreateAutoEvent([in] BOOL bInitialState); - EVENT_COOKIE CreateManualEvent([in] BOOL bInitialState); - void CloseEvent([in] EVENT_COOKIE event); - BOOL ClrSetEvent([in] EVENT_COOKIE event); - BOOL ClrResetEvent([in] EVENT_COOKIE event); - DWORD WaitForEvent([in] EVENT_COOKIE event, [in] DWORD dwMilliseconds, [in] BOOL bAlertable); - DWORD WaitForSingleObject([in] HANDLE handle, [in] DWORD dwMilliseconds); - - // OS header file defines CreateSemaphore. - SEMAPHORE_COOKIE ClrCreateSemaphore([in] DWORD dwInitial, [in] DWORD dwMax); - void ClrCloseSemaphore([in] SEMAPHORE_COOKIE semaphore); - DWORD ClrWaitForSemaphore([in] SEMAPHORE_COOKIE semaphore, [in] DWORD dwMilliseconds, [in] BOOL bAlertable); - BOOL ClrReleaseSemaphore([in] SEMAPHORE_COOKIE semaphore, [in] LONG lReleaseCount, [in] LONG *lpPreviousCount); - - MUTEX_COOKIE ClrCreateMutex([in]LPSECURITY_ATTRIBUTES lpMutexAttributes, [in]BOOL bInitialOwner, [in]LPCTSTR lpName); - DWORD ClrWaitForMutex([in] MUTEX_COOKIE mutex, [in] DWORD dwMilliseconds, [in] BOOL bAlertable); - BOOL ClrReleaseMutex([in] MUTEX_COOKIE mutex); - void ClrCloseMutex([in] MUTEX_COOKIE mutex); - - DWORD ClrSleepEx([in] DWORD dwMilliseconds, [in] BOOL bAlertable); - - BOOL ClrAllocationDisallowed(); - - void GetLastThrownObjectExceptionFromThread([out] void **ppvException); - -}; // interface IExecutionEngine - - -//***************************************************************************** -// Interface for exposing memory services from the EE to other DLLs of the CLR. -//***************************************************************************** - -cpp_quote("#if !defined(_WINNT_) && !defined(_NTMMAPI_)") -typedef void* PMEMORY_BASIC_INFORMATION; -cpp_quote("#endif") - - -[ - uuid(17713B61-B59F-4e13-BAAF-91623DC8ADC0), - helpstring("CLR Memory Manager Interface"), - pointer_default(unique), - local -] -interface IEEMemoryManager : IUnknown -{ - LPVOID ClrVirtualAlloc( - [in] LPVOID lpAddress, // region to reserve or commit - [in] SIZE_T dwSize, // size of region - [in] DWORD flAllocationType, // type of allocation - [in] DWORD flProtect // type of access protection - ); - - BOOL ClrVirtualFree( - [in] LPVOID lpAddress, // address of region - [in] SIZE_T dwSize, // size of region - [in] DWORD dwFreeType // operation type - ); - - SIZE_T ClrVirtualQuery( - [in] const void* lpAddress, // address of region - [in] PMEMORY_BASIC_INFORMATION lpBuffer, // information buffer - [in] SIZE_T dwLength // size of buffer - ); - - BOOL ClrVirtualProtect( - [in] LPVOID lpAddress, // region of committed pages - [in] SIZE_T dwSize, // size of the region - [in] DWORD flNewProtect, // desired access protection - [in] DWORD* lpflOldProtect // old protection - ); - - HANDLE ClrGetProcessHeap(); - - HANDLE ClrHeapCreate( - [in] DWORD flOptions, // heap allocation attributes - [in] SIZE_T dwInitialSize, // initial heap size - [in] SIZE_T dwMaximumSize // maximum heap size - ); - - BOOL ClrHeapDestroy( - [in] HANDLE hHeap // handle to heap - ); - - LPVOID ClrHeapAlloc( - [in] HANDLE hHeap, // handle to private heap block - [in] DWORD dwFlags, // heap allocation control - [in] SIZE_T dwBytes // number of bytes to allocate - ); - - BOOL ClrHeapFree( - [in] HANDLE hHeap, // handle to heap - [in] DWORD dwFlags, // heap free options - [in] LPVOID lpMem // pointer to memory - ); - - BOOL ClrHeapValidate( - [in] HANDLE hHeap, // handle to heap - [in] DWORD dwFlags, // heap access options - [in] const void* lpMem // optional pointer to memory block - ); - - HANDLE ClrGetProcessExecutableHeap(); - -}; // interface IEEMemoryManager - //******************************************************************************************** // Interface for exposing GetBucketParametersForCurrentException to Watson testing harness. //******************************************************************************************** @@ -292,5 +87,3 @@ interface IPrivateManagedExceptionReporting : IUnknown { HRESULT GetBucketParametersForCurrentException([out]BucketParameters *pParams); } - - diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrnt.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrnt.h index 1356666..26a33d5 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrnt.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrnt.h @@ -31,7 +31,7 @@ #define STATUS_UNWIND ((NTSTATUS)0x80000027L) #endif -#ifndef DBG_PRINTEXCEPTION_C +#ifndef DBG_PRINTEXCEPTION_C #define DBG_PRINTEXCEPTION_C ((DWORD)0x40010006L) #endif @@ -58,22 +58,22 @@ #ifndef __out_xcount_opt #define __out_xcount_opt(var) __out -#endif +#endif #ifndef __encoded_pointer #define __encoded_pointer -#endif +#endif #ifndef __range #define __range(min, man) -#endif +#endif #ifndef __field_bcount #define __field_bcount(size) #endif #ifndef __field_ecount_opt -#define __field_ecount_opt(nFields) +#define __field_ecount_opt(nFields) #endif #ifndef __field_ecount @@ -81,7 +81,7 @@ #endif #undef _Ret_bytecap_ -#define _Ret_bytecap_(_Size) +#define _Ret_bytecap_(_Size) #ifndef NT_SUCCESS #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) @@ -96,7 +96,7 @@ typedef signed char SCHAR; typedef SCHAR *PSCHAR; typedef LONG NTSTATUS; -#ifndef FEATURE_PAL +#ifndef HOST_UNIX #define TLS_MINIMUM_AVAILABLE 64 // winnt #define TLS_EXPANSION_SLOTS 1024 @@ -284,7 +284,7 @@ typedef ANSI_STRING64 *PANSI_STRING64; #define GDI_HANDLE_BUFFER_SIZE32 34 #define GDI_HANDLE_BUFFER_SIZE64 60 -#if !defined(_TARGET_AMD64_) +#if !defined(TARGET_AMD64) #define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE32 #else #define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE64 @@ -587,7 +587,7 @@ typedef struct _TEB { PVOID SystemReserved1[54]; // Used by FP emulator NTSTATUS ExceptionCode; // for RaiseUserException ACTIVATION_CONTEXT_STACK ActivationContextStack; // Fusion activation stack - // sizeof(PVOID) is a way to express processor-dependence, more generally than #ifdef _WIN64 + // sizeof(PVOID) is a way to express processor-dependence, more generally than #ifdef HOST_64BIT UCHAR SpareBytes1[48 - sizeof(PVOID) - sizeof(ACTIVATION_CONTEXT_STACK)]; GDI_TEB_BATCH GdiTebBatch; // Gdi batching CLIENT_ID RealClientId; @@ -748,9 +748,9 @@ typedef VM_COUNTERS *PVM_COUNTERS; #undef TYPE3 -#endif // !defined(FEATURE_PAL) +#endif // !defined(HOST_UNIX) -#if !defined(_TARGET_X86_) +#if !defined(TARGET_X86) typedef enum _FUNCTION_TABLE_TYPE { RF_SORTED, @@ -762,8 +762,8 @@ typedef struct _DYNAMIC_FUNCTION_TABLE { LIST_ENTRY Links; PT_RUNTIME_FUNCTION FunctionTable; LARGE_INTEGER TimeStamp; - -#ifdef _TARGET_ARM_ + +#ifdef TARGET_ARM ULONG MinimumAddress; ULONG MaximumAddress; ULONG BaseAddress; @@ -780,12 +780,12 @@ typedef struct _DYNAMIC_FUNCTION_TABLE { ULONG EntryCount; } DYNAMIC_FUNCTION_TABLE, *PDYNAMIC_FUNCTION_TABLE; -#endif // !_TARGET_X86_ +#endif // !TARGET_X86 // // AMD64 // -#ifdef _TARGET_AMD64_ +#ifdef TARGET_AMD64 #define RUNTIME_FUNCTION__BeginAddress(prf) (prf)->BeginAddress #define RUNTIME_FUNCTION__SetBeginAddress(prf,address) ((prf)->BeginAddress = (address)) @@ -811,9 +811,9 @@ PEXCEPTION_ROUTINE IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL ); -#ifndef FEATURE_PAL +#ifndef HOST_UNIX extern RtlVirtualUnwindFn* RtlVirtualUnwind_Unsafe; -#else // !FEATURE_PAL +#else // !HOST_UNIX PEXCEPTION_ROUTINE RtlVirtualUnwind_Unsafe( IN ULONG HandlerType, @@ -825,16 +825,16 @@ RtlVirtualUnwind_Unsafe( OUT PULONG64 EstablisherFrame, IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL ); -#endif // !FEATURE_PAL +#endif // !HOST_UNIX -#endif // _TARGET_AMD64_ +#endif // TARGET_AMD64 // // X86 // -#ifdef _TARGET_X86_ -#ifndef FEATURE_PAL +#ifdef TARGET_X86 +#ifndef TARGET_UNIX // // x86 ABI does not define RUNTIME_FUNCTION. Define our own to allow unification between x86 and other platforms. // @@ -847,13 +847,14 @@ typedef struct _DISPATCHER_CONTEXT { _EXCEPTION_REGISTRATION_RECORD* RegistrationPointer; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; -#endif // !FEATURE_PAL +#endif // !TARGET_UNIX #define RUNTIME_FUNCTION__BeginAddress(prf) (prf)->BeginAddress #define RUNTIME_FUNCTION__SetBeginAddress(prf,addr) ((prf)->BeginAddress = (addr)) -#ifdef WIN64EXCEPTIONS +#ifdef FEATURE_EH_FUNCLETS #include "win64unwind.h" +#include "daccess.h" FORCEINLINE DWORD @@ -886,11 +887,11 @@ RtlVirtualUnwind ( __out PDWORD EstablisherFrame, __inout_opt PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers ); -#endif // WIN64EXCEPTIONS +#endif // FEATURE_EH_FUNCLETS -#endif // _TARGET_X86_ +#endif // TARGET_X86 -#ifdef _TARGET_ARM_ +#ifdef TARGET_ARM #include "daccess.h" // @@ -900,7 +901,7 @@ RtlVirtualUnwind ( #define UNW_FLAG_NHANDLER 0x0 /* any handler */ #define UNW_FLAG_EHANDLER 0x1 /* filter handler */ #define UNW_FLAG_UHANDLER 0x2 /* unwind handler */ - + // This function returns the length of a function using the new unwind info on arm. // Taken from minkernel\ntos\rtl\arm\ntrtlarm.h. FORCEINLINE @@ -911,14 +912,14 @@ RtlpGetFunctionEndAddress ( ) { ULONG FunctionLength; - + FunctionLength = FunctionEntry->UnwindData; if ((FunctionLength & 3) != 0) { FunctionLength = (FunctionLength >> 2) & 0x7ff; } else { FunctionLength = *(PTR_ULONG)(ImageBase + FunctionLength) & 0x3ffff; } - + return FunctionEntry->BeginAddress + 2 * FunctionLength; } @@ -933,19 +934,7 @@ typedef struct _UNWIND_INFO { // dummy } UNWIND_INFO, *PUNWIND_INFO; -#if defined(FEATURE_PAL) || defined(_X86_) -EXTERN_C -NTSYSAPI -VOID -NTAPI -RtlUnwindEx ( - __in_opt PVOID TargetFrame, - __in_opt PVOID TargetIp, - __in_opt PEXCEPTION_RECORD ExceptionRecord, - __in PVOID ReturnValue, - __in PT_CONTEXT ContextRecord, - __in_opt PUNWIND_HISTORY_TABLE HistoryTable - ); +#if defined(TARGET_UNIX) || defined(HOST_X86) EXTERN_C NTSYSAPI @@ -955,19 +944,19 @@ RtlVirtualUnwind ( __in DWORD HandlerType, __in DWORD ImageBase, __in DWORD ControlPc, - __in PRUNTIME_FUNCTION FunctionEntry, + __in PT_RUNTIME_FUNCTION FunctionEntry, __inout PT_CONTEXT ContextRecord, __out PVOID *HandlerData, __out PDWORD EstablisherFrame, __inout_opt PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers ); -#endif // FEATURE_PAL || _X86_ +#endif // TARGET_UNIX || HOST_X86 #define UNW_FLAG_NHANDLER 0x0 -#endif // _TARGET_ARM_ +#endif // TARGET_ARM -#ifdef _TARGET_ARM64_ +#ifdef TARGET_ARM64 #include "daccess.h" #define UNW_FLAG_NHANDLER 0x0 /* any handler */ @@ -984,14 +973,14 @@ RtlpGetFunctionEndAddress ( ) { ULONG64 FunctionLength; - + FunctionLength = FunctionEntry->UnwindData; if ((FunctionLength & 3) != 0) { FunctionLength = (FunctionLength >> 2) & 0x7ff; } else { FunctionLength = *(PTR_ULONG64)(ImageBase + FunctionLength) & 0x3ffff; } - + return FunctionEntry->BeginAddress + 4 * FunctionLength; } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivappxhosting.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivappxhosting.idl deleted file mode 100644 index 04a4cf9..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivappxhosting.idl +++ /dev/null @@ -1,66 +0,0 @@ -// 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. - -import "unknwn.idl"; - -// Forward declarations -interface ICLRPrivAppXDomain; -interface ICLRPrivAppXRuntime; - -/************************************************************************************** - ** ICLRPrivAppXRuntime - **************************************************************************************/ -[ - uuid(6D2DF5A4-FA3A-4481-8BA0-0422FD21720F), - version(1.0), - local -] -interface ICLRPrivAppXRuntime : IUnknown -{ - /********************************************************************************** - ** Use to create and initialize the AppX domain. Should only be called once; all - ** subsequent calls will fail. Thread safe. - ** - ** wzFriendlyName - the domain friendly name. - **********************************************************************************/ - HRESULT InitializeAppXDomain( - [in] LPCWSTR wzFriendlyName); - - /********************************************************************************** - ** Use to retrieve the AppX domain. InitializeAppXDomain must have been - ** successfully called previously. May be called multiple times. Thread safe. - ** - ** riidDomain - the IID of the interface to be returned in ppvDomain. - ** ppIAppXDomain - receives the ICLRPrivAppXDomain interface. - **********************************************************************************/ - HRESULT GetAppXDomain( - [in] REFIID riidDomain, - [out] LPVOID * ppvDomain); -} - -/************************************************************************************** - ** ICLRPrivAppXDomain - **************************************************************************************/ -[ - uuid(6633398E-823D-4361-B30E-824043BD4686), - version(1.0), - local -] -interface ICLRPrivAppXDomain : IUnknown -{ - /********************************************************************************** - ** Use to create a delegate to a static method. - ** - ** wzAssemblyName - the name of the assembly that contains the target type. - ** wzTypeName - the name of the type that contains the target method. - ** wzMethodName - the static method for which to create a delegate. - ** ppvDelegate - receives the native-callable function pointer corresponding to - ** the specified static method. - **********************************************************************************/ - HRESULT CreateDelegate( - [in] LPCWSTR wzAssemblyName, - [in] LPCWSTR wzTypeName, - [in] LPCWSTR wzMethodName, - [out] LPVOID * ppvDelegate); -}; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivbinderutil.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivbinderutil.h index 023f72c..cdc24a5 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivbinderutil.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivbinderutil.h @@ -31,8 +31,6 @@ interface ICLRPrivAssembly; typedef DPTR(ICLRPrivAssembly) PTR_ICLRPrivAssembly; typedef DPTR(ICLRPrivBinder) PTR_ICLRPrivBinder; -class PEAssembly; -class AssemblySpec; //===================================================================================================================== #define VALIDATE_CONDITION(condition, fail_op) \ @@ -42,407 +40,17 @@ class AssemblySpec; fail_op; \ } while (false) -#define VALIDATE_PTR_RET(val) VALIDATE_CONDITION(val != nullptr, return E_POINTER) -#define VALIDATE_PTR_THROW(val) VALIDATE_CONDITION(val != nullptr, ThrowHR(E_POINTER)) +#define VALIDATE_PTR_RET(val) VALIDATE_CONDITION((val) != nullptr, return E_POINTER) +#define VALIDATE_PTR_THROW(val) VALIDATE_CONDITION((val) != nullptr, ThrowHR(E_POINTER)) #define VALIDATE_ARG_RET(condition) VALIDATE_CONDITION(condition, return E_INVALIDARG) #define VALIDATE_ARG_THROW(condition) VALIDATE_CONDITION(condition, ThrowHR(E_INVALIDARG)) //===================================================================================================================== namespace CLRPrivBinderUtil { - //================================================================================================================= - enum BindFlags - { - BF_BindIL = 1, - BF_BindNI = 2, - BF_Default = BF_BindIL | BF_BindNI, - }; - - //================================================================================================================= - template - inline ItfT * ToInterface( - ObjT * && pObj) - { - STATIC_CONTRACT_THROWS; - - ItfT * pItf = nullptr; - IfFailThrow(pObj->QueryInterface(__uuidof(ItfT), (void **)&pItf)); - return pItf; - } - - //================================================================================================================= - template - inline ItfT * ToInterface_NoThrow( - ObjT * && pObj) - { - LIMITED_METHOD_CONTRACT; - - ItfT * pItf = nullptr; - if (FAILED(pObj->QueryInterface(__uuidof(ItfT), (void **)&pItf))) - { - return nullptr; - } - return pItf; - } - - //===================================================================================================================== - - //================================================================================================================= - // Used to create an identity-only ICLRPrivAssembly from an ICLRPrivBinder. This is currently used when - // creating dynamic assemblies as these use the parent assembly's ICLRPrivBinder object to provide binding - // functionaltiy. - - class CLRPrivBinderAsAssemblyWrapper : - public IUnknownCommon - { - public: - //----------------------------------------------------------------------------------------------------------------- - CLRPrivBinderAsAssemblyWrapper( - ICLRPrivBinder *pWrapped) - : _pWrapped(clr::SafeAddRef(pWrapped)) - { - STANDARD_VM_CONTRACT; - VALIDATE_ARG_THROW(pWrapped); - } - - //----------------------------------------------------------------------------------------------------------------- - // Forwards to wrapped binder. - STDMETHOD(BindAssemblyByName)( - IAssemblyName * pAssemblyName, - ICLRPrivAssembly ** ppAssembly) - { - WRAPPER_NO_CONTRACT; - return _pWrapped->BindAssemblyByName(pAssemblyName, ppAssembly); - } - - //----------------------------------------------------------------------------------------------------------------- - // Forwards to wrapped binder. - STDMETHOD(GetBinderID)( - UINT_PTR *pBinderId) - { - WRAPPER_NO_CONTRACT; - return _pWrapped->GetBinderID(pBinderId); - } - - //----------------------------------------------------------------------------------------------------------------- - // Forwards to wrapped binder. - STDMETHOD(GetLoaderAllocator)( - LPVOID * pLoaderAllocator) - { - WRAPPER_NO_CONTRACT; - return _pWrapped->GetLoaderAllocator(pLoaderAllocator); - } - - //----------------------------------------------------------------------------------------------------------------- - // ICLRPrivAssembly method is unsupported. - STDMETHOD(IsShareable)( - BOOL * pbIsShareable) - { - LIMITED_METHOD_CONTRACT; - _ASSERTE_MSG(false, "CLRPrivBinderAsAssemblyWrapper does not support ICLRPrivAssembly methods (just ICLRPrivBinder ones)!"); - VALIDATE_ARG_RET(pbIsShareable); - *pbIsShareable = FALSE; - return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); - } - - //----------------------------------------------------------------------------------------------------------------- - // ICLRPrivAssembly method is unsupported. - STDMETHOD(GetAvailableImageTypes)( - LPDWORD pdwImageTypes) - { - LIMITED_METHOD_CONTRACT; - _ASSERTE_MSG(false, "CLRPrivBinderAsAssemblyWrapper does not support ICLRPrivAssembly methods (just ICLRPrivBinder ones)!"); - VALIDATE_ARG_RET(pdwImageTypes); - *pdwImageTypes = 0; - return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); - } - - //----------------------------------------------------------------------------------------------------------------- - // ICLRPrivAssembly method is unsupported. - STDMETHOD(GetImageResource)( - DWORD dwImageType, - DWORD* pdwImageType, - ICLRPrivResource ** ppIResource) - { - LIMITED_METHOD_CONTRACT; - _ASSERTE_MSG(false, "CLRPrivBinderAsAssemblyWrapper does not support ICLRPrivAssembly methods (just ICLRPrivBinder ones)!"); - VALIDATE_ARG_RET(pdwImageType); - *pdwImageType = 0; - return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); - } - - private: - ReleaseHolder _pWrapped; - }; - - //================================================================================================================= - // Provides a struct that can be accessed at the QWORD, DWORD, or WORD level, and is structured - - struct AssemblyVersion - { -#if BIGENDIAN - union - { - UINT64 qwMajorMinorBuildRevision; - struct - { - union - { - DWORD dwMajorMinor; - struct - { - WORD wMajor; - WORD wMinor; - }; - }; - union - { - DWORD dwBuildRevision; - struct - { - WORD wBuild; - WORD wRevision; - }; - }; - }; - }; -#else - union - { - UINT64 qwMajorMinorBuildRevision; - struct - { - union - { - DWORD dwBuildRevision; - struct - { - WORD wRevision; - WORD wBuild; - }; - }; - union - { - DWORD dwMajorMinor; - struct - { - WORD wMinor; - WORD wMajor; - }; - }; - }; - }; -#endif - - // Default value is 0.0.0.0 - AssemblyVersion() - : qwMajorMinorBuildRevision(static_cast(0)) - { LIMITED_METHOD_CONTRACT; } - - // Copy constructor - AssemblyVersion(AssemblyVersion const & other) - : qwMajorMinorBuildRevision(other.qwMajorMinorBuildRevision) - { LIMITED_METHOD_CONTRACT; } - - // Initialize version using an IAssemblyName object. - HRESULT Initialize(IAssemblyName * pName); - - // Initialize version using an ICLRPrivAssemblyInfo object. - HRESULT Initialize(ICLRPrivAssemblyInfo * pInfo); - - // Relative ordering of versions. - static inline int Compare( - AssemblyVersion const & left, - AssemblyVersion const & right) - { - LIMITED_METHOD_CONTRACT; - - if (left.qwMajorMinorBuildRevision < right.qwMajorMinorBuildRevision) - return -1; - else if (left.qwMajorMinorBuildRevision == right.qwMajorMinorBuildRevision) - return 0; - else - return 1; - } - }; // struct AssemblyVersion - - inline bool operator ==(AssemblyVersion const & lhs, AssemblyVersion const & rhs) - { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision == rhs.qwMajorMinorBuildRevision; } - - inline bool operator !=(AssemblyVersion const & lhs, AssemblyVersion const & rhs) - { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision != rhs.qwMajorMinorBuildRevision; } - - inline bool operator <(AssemblyVersion const & lhs, AssemblyVersion const & rhs) - { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision < rhs.qwMajorMinorBuildRevision; } - - inline bool operator <=(AssemblyVersion const & lhs, AssemblyVersion const & rhs) - { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision <= rhs.qwMajorMinorBuildRevision; } - - inline bool operator >(AssemblyVersion const & lhs, AssemblyVersion const & rhs) - { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision > rhs.qwMajorMinorBuildRevision; } - - inline bool operator >=(AssemblyVersion const & lhs, AssemblyVersion const & rhs) - { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision >= rhs.qwMajorMinorBuildRevision; } - - //================================================================================================================= - // Encapsulates PublicKey value, can be initialized using a variety of data sources. - - struct PublicKey - { - // Defaults to empty value. - PublicKey() - : m_key(nullptr) - , m_key_owned(false) - , m_size((DWORD)-1) - { LIMITED_METHOD_CONTRACT; } - - // Construct directly from existing public key data. - PublicKey(PBYTE pbKey, DWORD cbKey) - : m_key(pbKey) - , m_key_owned(false) - , m_size(cbKey) - { LIMITED_METHOD_CONTRACT; } - - ~PublicKey() - { WRAPPER_NO_CONTRACT; Uninitialize(); } - - // Frees any public key data and resets to default value. - void Uninitialize() - { - LIMITED_METHOD_CONTRACT; - - if (m_key_owned) - { - delete [] m_key; - m_key_owned = false; - } - m_key = nullptr; - m_size = 0; - } - - // Initialize PK data form an ICLRPrivAssemblyInfo object. - HRESULT Initialize(ICLRPrivAssemblyInfo * pAssemblyInfo); - - // Returns PK data pointer. - inline BYTE const * GetKey() const - { LIMITED_METHOD_CONTRACT; return m_key; } - - // Returns size in bytes of the PK data. - inline DWORD GetSize() const - { LIMITED_METHOD_CONTRACT; return m_size; } - - private: - PBYTE m_key; - bool m_key_owned; - DWORD m_size; - }; - - //================================================================================================================= - // Encapsulates PublicKeyToken value, can be initialized using a variety of data sources. - // - // Constraints: assumes that non-empty PKT data will always be 8 bytes long. - // - - struct PublicKeyToken - { - PublicKeyToken() - : m_cbKeyToken(0) - { LIMITED_METHOD_CONTRACT; ZeroMemory(&m_rbKeyToken, sizeof(m_rbKeyToken)); } - - PublicKeyToken(PublicKeyToken const & other) - : m_cbKeyToken(other.m_cbKeyToken) - { LIMITED_METHOD_CONTRACT; CopyMemory(m_rbKeyToken, other.m_rbKeyToken, sizeof(m_rbKeyToken)); } - - // Initialize directly from PKT data. - HRESULT Initialize(BYTE * pbKeyToken, DWORD cbKeyToken); - - // Converts PK data to PKT data. - HRESULT Initialize(PublicKey const & pk); - - // Initialize using the PKT value contained by pName; returns S_FALSE if there is no associated PKT. - HRESULT Initialize(IAssemblyName * pName); - - // Initialize using the PK data contained by pInfo; returns S_FALSE if there is no associated PK. - HRESULT Initialize(ICLRPrivAssemblyInfo * pInfo); - - // PKT data. - BYTE const * GetToken() const - { LIMITED_METHOD_CONTRACT; return m_rbKeyToken; } - - // Size in bytes of the PKT (should always be 0 or 8). - DWORD GetSize() const - { LIMITED_METHOD_CONTRACT; return m_cbKeyToken; } - - private: - static const DWORD PUBLIC_KEY_TOKEN_LEN1 = 8; - BYTE m_rbKeyToken[PUBLIC_KEY_TOKEN_LEN1]; - DWORD m_cbKeyToken; - }; - - bool operator==(PublicKeyToken const & lhs, PublicKeyToken const & rhs); - - inline bool operator!=(PublicKeyToken const & lhs, PublicKeyToken const & rhs) - { WRAPPER_NO_CONTRACT; return !(lhs == rhs); } - - //================================================================================================================= - // Encapsulates data required for packaged assembly identity: simple name, version, and public key token. - // - // Constraints: assumes that the assembly simple name is no longer than _MAX_PATH - // - - struct AssemblyIdentity - { - AssemblyIdentity() - { LIMITED_METHOD_CONTRACT; Name[0] = W('\0'); } - - AssemblyIdentity(AssemblyIdentity const & other) - : Version(other.Version) - , KeyToken(other.KeyToken) - { LIMITED_METHOD_CONTRACT; CopyMemory(Name, other.Name, sizeof(Name)); } - - // Initialize from assembly simple name; default version and empty PKT values are used. - HRESULT Initialize(LPCWSTR wzName); - - // Initialize from an ICLRPrivAssemblyInfo object. - HRESULT Initialize(ICLRPrivAssemblyInfo * pAssemblyInfo); - - // Initialize from an IAssemblyName object. - HRESULT Initialize(IAssemblyName * pAssemblyName); - - // Initialize from an AssemblySpec object. - HRESULT Initialize(AssemblySpec * pSpec); - - // Assembly simple name - WCHAR Name[_MAX_PATH]; - - // Assembly version; defaults to 0.0.0.0. - CLRPrivBinderUtil::AssemblyVersion Version; - - // Assembly public key token; defaults to none. - CLRPrivBinderUtil::PublicKeyToken KeyToken; - }; - - //================================================================================================= - template - struct CLRPrivResourceBase : - public IUnknownCommon - { - //--------------------------------------------------------------------------------------------- - STDMETHOD(GetResourceType)( - IID *pIID) - { - LIMITED_METHOD_CONTRACT; - if (pIID == nullptr) - return E_INVALIDARG; - *pIID = __uuidof(ItfT); - return S_OK; - } - }; - //================================================================================================================= class CLRPrivResourcePathImpl : - public IUnknownCommon< ItfBase< CLRPrivResourceBase< ICLRPrivResourcePath > >, - ICLRPrivResourcePath > + public IUnknownCommon2 { public: //--------------------------------------------------------------------------------------------- @@ -452,9 +60,16 @@ namespace CLRPrivBinderUtil LPCWSTR GetPath() { return m_wzPath; } - // - // ICLRPrivResourcePath methods - // + //--------------------------------------------------------------------------------------------- + STDMETHOD(GetResourceType)( + IID* pIID) + { + LIMITED_METHOD_CONTRACT; + if (pIID == nullptr) + return E_INVALIDARG; + *pIID = __uuidof(ICLRPrivResourcePath); + return S_OK; + } //--------------------------------------------------------------------------------------------- STDMETHOD(GetPath)( @@ -467,77 +82,17 @@ namespace CLRPrivBinderUtil NewArrayHolder m_wzPath; }; - //================================================================================================================= - class CLRPrivResourceStreamImpl : - public IUnknownCommon< ItfBase< CLRPrivResourceBase >, - ICLRPrivResourceStream> - { - public: - //--------------------------------------------------------------------------------------------- - CLRPrivResourceStreamImpl(IStream * pStream); - - //--------------------------------------------------------------------------------------------- - STDMETHOD(GetStream)( - REFIID riid, - LPVOID * ppvStream); - - private: - //--------------------------------------------------------------------------------------------- - ReleaseHolder m_pStream; - }; - - //================================================================================================================= - // Helper to prioritize binder errors. This class will ensure that all other errors have priority over - // CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT. This class should be used just like an HRESULT variable. - class BinderHRESULT - { - public: - BinderHRESULT() - : m_hr(S_OK) - {} - - BinderHRESULT(HRESULT hr) - : m_hr(hr) - {} - - operator HRESULT() const - { return m_hr; } - - BinderHRESULT & operator=(HRESULT hr) - { - // Always record change in success/failure status. - if (FAILED(hr) != FAILED(m_hr)) - m_hr = hr; - - if (FAILED(hr)) - { - if (SUCCEEDED(m_hr)) - m_hr = hr; - else if (m_hr == CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT) - m_hr = hr; - } - else - { - m_hr = hr; - } - return *this; - } - - private: - HRESULT m_hr; - }; // class BinderHRESULT - //================================================================================================================= // Types for WStringList (used in WinRT binders) - + typedef SListElem< PTR_WSTR > WStringListElem; typedef DPTR(WStringListElem) PTR_WStringListElem; typedef SList< WStringListElem, false /* = fHead default value */, PTR_WStringListElem > WStringList; typedef DPTR(WStringList) PTR_WStringList; - + // Destroys list of strings (code:WStringList). void WStringList_Delete(WStringList * pList); - + #ifndef DACCESS_COMPILE //===================================================================================================================== // Holder of allocated code:WStringList (helper class for WinRT binders - e.g. code:CLRPrivBinderWinRT::GetFileNameListForNamespace). @@ -554,7 +109,7 @@ namespace CLRPrivBinderUtil LIMITED_METHOD_CONTRACT; Destroy(); } - + void InsertTail(LPCWSTR wszValue) { CONTRACTL @@ -564,52 +119,52 @@ namespace CLRPrivBinderUtil MODE_ANY; } CONTRACTL_END; - + NewArrayHolder wszElemValue = DuplicateStringThrowing(wszValue); NewHolder pElem = new WStringListElem(wszElemValue); - + if (m_pList == nullptr) { m_pList = new WStringList(); } - + m_pList->InsertTail(pElem.Extract()); // The string is now owned by the list wszElemValue.SuppressRelease(); } - + WStringList * GetValue() { LIMITED_METHOD_CONTRACT; return m_pList; } - + WStringList * Extract() { LIMITED_METHOD_CONTRACT; - + WStringList * pList = m_pList; m_pList = nullptr; return pList; } - + private: void Destroy() { LIMITED_METHOD_CONTRACT; - + if (m_pList != nullptr) { WStringList_Delete(m_pList); m_pList = nullptr; } } - + private: WStringList * m_pList; }; // class WStringListHolder #endif //!DACCESS_COMPILE - + #ifdef FEATURE_COMINTEROP //===================================================================================================================== // Holder of allocated array of HSTRINGs (helper class for WinRT binders - e.g. code:CLRPrivBinderWinRT::m_rgAltPaths). @@ -619,7 +174,7 @@ namespace CLRPrivBinderUtil HSTRINGArrayHolder() { LIMITED_METHOD_CONTRACT; - + m_cValues = 0; m_rgValues = nullptr; } @@ -629,20 +184,20 @@ namespace CLRPrivBinderUtil LIMITED_METHOD_CONTRACT; Destroy(); } - + // Destroys current array and allocates a new one with cValues elements. void Allocate(DWORD cValues) { STANDARD_VM_CONTRACT; - + Destroy(); _ASSERTE(m_cValues == 0); - + if (cValues > 0) { m_rgValues = new HSTRING[cValues]; m_cValues = cValues; - + // Initialize the array values for (DWORD i = 0; i < cValues; i++) { @@ -657,25 +212,25 @@ namespace CLRPrivBinderUtil LIMITED_METHOD_CONTRACT; return m_rgValues[index]; } - + HSTRING * GetRawArray() { LIMITED_METHOD_CONTRACT; return m_rgValues; } - + DWORD GetCount() { LIMITED_METHOD_CONTRACT; return m_cValues; } - + private: #ifndef DACCESS_COMPILE void Destroy() { LIMITED_METHOD_CONTRACT; - + for (DWORD i = 0; i < m_cValues; i++) { if (m_rgValues[i] != nullptr) @@ -684,7 +239,7 @@ namespace CLRPrivBinderUtil } } m_cValues = 0; - + if (m_rgValues != nullptr) { delete [] m_rgValues; @@ -692,26 +247,13 @@ namespace CLRPrivBinderUtil } } #endif //!DACCESS_COMPILE - + private: DWORD m_cValues; HSTRING * m_rgValues; }; // class HSTRINGArrayHolder - + #endif // FEATURE_COMINTEROP - - //////////////////////////////////////////////////////////////////////////////////////////////////// - ///// ----------------------------- Questionable stuff ------------------------------------------- - //////////////////////////////////////////////////////////////////////////////////////////////////// - - /** probably should be exposed on an instance (of something) method rather that magically calling GetAppDomain() **/ - ICLRPrivAssembly* RaiseAssemblyResolveEvent(IAssemblyName *pAssemblyName, ICLRPrivAssembly* pRequestingAssembly); - - /** Ultimately, only the binder can do ref-def matching, and it should be opaque to CLR. - This is not trivial to do, however, since we cannot do data conversion as the function is nofault **/ - BOOL CompareHostBinderSpecs(AssemblySpec* a1, AssemblySpec* a2); - - /** PLACEHOLDER - the same issue as CompareHostBinderSpecs applies to hashing assemblyspecs **/ } // namespace CLRPrivBinderUtil #endif // __CLRPRIVBINDERUTIL_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivbinding.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivbinding.idl index c30ed62..7c812b6 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivbinding.idl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivbinding.idl @@ -12,8 +12,6 @@ interface ICLRPrivAssembly; interface ICLRPrivResource; interface ICLRPrivResourcePath; -interface ICLRPrivResourceStream; -interface ICLRPrivResourceHMODULE; interface ICLRPrivAssemblyInfo; @@ -54,7 +52,7 @@ interface ICLRPrivBinder : IUnknown ** GetBinderID ** pBinderId, pointer to binder id. The binder id has the following properties ** It is a pointer that does not change over the lifetime of a binder object - ** It points at an object in memory that will remain allocated for the lifetime of the binder. + ** It points at an object in memory that will remain allocated for the lifetime of the binder. ** This value should be the same for a set of binder objects that represent the same binder behavior. **********************************************************************************/ HRESULT GetBinderID( @@ -97,19 +95,6 @@ enum ASSEMBLY_IMAGE_TYPES ] interface ICLRPrivAssembly : ICLRPrivBinder { - /********************************************************************************** - ** IsShareable - Use to determine if the assembly should be shared. - ** NOTE: This method is required to be idempotent. See general comment above. - ** - ** A binder must adhere to the following contract when marking an assembly as - ** shareable: - ** - all assemblies in the full static binding closure must also be shareable. - ** - ** pbIsShareable - set to TRUE if the assembly can be shared; FALSE otherwise. - **********************************************************************************/ - HRESULT IsShareable( - [out, retval] BOOL * pbIsShareable); - /********************************************************************************** ** GetAvailableImageTypes - Use to retrieve the set of images available for an ** assembly. @@ -177,48 +162,6 @@ interface ICLRPrivResourcePath : IUnknown [out, size_is(cchBuffer), length_is(*pcchBuffer), string, optional] LPWSTR wzBuffer); }; -/************************************************************************************** - ** ICLRPrivResourceStream - Encapsulates a resource identified by IStream. - **************************************************************************************/ -[ - uuid(2601F621-E462-404C-B299-3E1DE72F8545), - version(1.0), - local -] -interface ICLRPrivResourceStream : IUnknown -{ - /********************************************************************************** - ** GetStream - Use to retrieve IStream instance corresponding to the resource. - ** NOTE: This method is required to be idempotent. See general comment above. - ** - ** riid - the IID of the interface to return. Typically IID_IStream. - ** ppvStream - contains the returned interface. - **********************************************************************************/ - HRESULT GetStream( - [in] REFIID riid, - [out, iid_is(riid), retval] LPVOID * ppvStream); -}; - -/************************************************************************************** - ** ICLRPrivResourceHMODULE - Encapsulates a resource identified by HMODULE. - **************************************************************************************/ -[ - uuid(2601F621-E462-404C-B299-3E1DE72F8546), - version(1.0), - local -] -interface ICLRPrivResourceHMODULE : IUnknown -{ - /********************************************************************************** - ** GetStream - Use to retrieve the resource's HMODULE value. The HMODULE's - ** reference count is not changed; the ICLRPrivResourceHMODULE instance must be - ** kept until the HMODULE is either reference counted or no longer used. - ** NOTE: This method is required to be idempotent. See general comment above. - **********************************************************************************/ - HRESULT GetHMODULE( - [out, retval] HMODULE * phModule); -}; - [ uuid(8d2d3cc9-1249-4ad4-977d-b772bd4e8a94), version(1.0), @@ -227,7 +170,7 @@ interface ICLRPrivResourceHMODULE : IUnknown interface ICLRPrivResourceAssembly : IUnknown { /********************************************************************************** - ** GetAssembly - Use to retrieve the resource's BINDER_SPACE::Assembly value. + ** GetAssembly - Use to retrieve the resource's BINDER_SPACE::Assembly value. ** NOTE: This method is required to be idempotent. See general comment above. **********************************************************************************/ HRESULT GetAssembly( @@ -265,31 +208,10 @@ interface ICLRPrivAssemblyInfo : IUnknown ** ICLRPrivAssemblyID_WinRT - Provides identification for WinRT assembly - allows dynamic casting inside code:CLRPrivAssemblyWinRT. **************************************************************************************/ [ - uuid(4372D277-9906-4FED-BF53-30C0B4010896), - version(1.0), + uuid(4372D277-9906-4FED-BF53-30C0B4010896), + version(1.0), local ] interface ICLRPrivAssemblyID_WinRT : IUnknown { }; - -/************************************************************************************** - ** ICLRPrivWinRtTypeBinder - Provides binding to WinRT types that are already loaded. - **************************************************************************************/ -[ - uuid(6DE2A085-EFF4-4078-9F60-B9D366736398), - version(1.0), - local -] -interface ICLRPrivWinRtTypeBinder : IUnknown -{ - /********************************************************************************** - ** FindAssemblyForWinRtTypeIfLoaded - ** Finds Assembly * for type in AppDomain * if it is loaded. - ** Returns NULL if assembly is not loaded or type is not found. - **********************************************************************************/ - void * FindAssemblyForWinRtTypeIfLoaded( - void * pAppDomain, - LPCUTF8 szNamespace, - LPCUTF8 szClassName); -}; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivhosting.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivhosting.idl deleted file mode 100644 index b288c28..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivhosting.idl +++ /dev/null @@ -1,92 +0,0 @@ -// 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. - -import "unknwn.idl"; -import "CLRPrivBinding.idl"; - -//===================================================================================================================== -// Forward declarations -interface ICLRPrivRuntime; - -//===================================================================================================================== -// CLRPrivHosting coclass -//===================================================================================================================== -[ - uuid("EDA73987-E6C0-42BF-A6B7-073F7B24D8C7") -] -library CLRPrivHosting -{ - //================================================================================================================= - // CLRPrivRuntime - //================================================================================================================= - [ - uuid(BC1B53A8-DCBC-43B2-BB17-1E4061447AE8) - ] - coclass CLRPrivRuntime - { - [default] interface ICLRPrivRuntime; - }; -}; - -//===================================================================================================================== -// ICLRPrivRuntime -//===================================================================================================================== -[ - uuid(BC1B53A8-DCBC-43B2-BB17-1E4061447AE9), - version(1.0), - local -] -interface ICLRPrivRuntime : IUnknown -{ - /********************************************************************************** - ** Used for accessing additional hosting functionality. - ** - ** rclsid - the CoClass from which to request the interface. - ** riid - the IID of the interface being requested. - ** ppUnk - receives the interface pointer value. - **********************************************************************************/ - HRESULT GetInterface( - [in] REFCLSID rclsid, - [in] REFIID riid, - [out, iid_is(riid), retval] LPVOID *ppUnk); - - /********************************************************************************** - ** Creates a domain using the provided binder for the root default bind context. - ** - ** pwzFriendlyName - the name to associate with the domain. - ** pBinder - the binder to use for root-level binds in the default context. - ** pdwAppDomainId - receives the ID of the created domain. - **********************************************************************************/ - HRESULT CreateAppDomain( - [in, string] LPCWSTR pwzFriendlyName, - [in] ICLRPrivBinder * pBinder, - [out, retval] LPDWORD pdwAppDomainId); - - /********************************************************************************** - ** Creates a native-callable function pointer to the specified method. - ** - ** appDomainID - the domain in which to create the delegate. - ** wszAssemblyName - the name of the assembly in which the method is defined. - ** wszClassName - the name of the class (including namespace) in which the method - ** is defined. - ** wszMethodName - the name of the method for which to create a delegate. - ** ppvDelegate - receives the delegate pointer value. - **********************************************************************************/ - HRESULT CreateDelegate( - [in] DWORD appDomainID, - [in, string] LPCWSTR wszAssemblyName, - [in, string] LPCWSTR wszClassName, - [in, string] LPCWSTR wszMethodName, - [out, retval] LPVOID * ppvDelegate); - - /********************************************************************************** - ** Creates an AppX appdomain and executes entrypoint method of an executable there - ** - **********************************************************************************/ - HRESULT ExecuteMain( - [in] ICLRPrivBinder * pBinder, - [out, retval] int * pRetVal - ); -}; - diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivruntimebinders.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivruntimebinders.idl deleted file mode 100644 index 0da7e3a..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrprivruntimebinders.idl +++ /dev/null @@ -1,39 +0,0 @@ -// 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. - -import "CLRPrivBinding.idl"; - -//===================================================================================================================== -// CLRPrivRuntime -//===================================================================================================================== -[ - uuid("EA6A2170-8F6A-4007-87A9-02429F615958") -] -library CLRPrivRuntimeBinders -{ - //================================================================================================================= - // CLRPrivAppXBinder - //================================================================================================================= - [ - uuid(E990F732-2D0A-48AC-87FC-EF12B618981A), - helpstring("Runtime-provided package-based assembly binder for AppX."), - ] - coclass CLRPrivAppXBinder - { - [default] interface ICLRPrivBinder; - }; - - //================================================================================================================= - // CLRPrivFusionBinder - //================================================================================================================= - [ - uuid(E990F732-2D0A-48AC-87FC-EF12B618981C), - helpstring("Runtime-provided binder for wrapping ICLRPrivBinder-compatible subset of fusion functionality."), - ] - coclass CLRPrivFusionBinder - { - [default] interface ICLRPrivBinder; - }; -}; - diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrtypes.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrtypes.h index 15387aa..a83fb9e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrtypes.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrtypes.h @@ -23,10 +23,10 @@ #include "staticcontract.h" #include "static_assert.h" -#if _WIN64 - #define POINTER_BITS 64 +#if HOST_64BIT + #define POINTER_BITS (64) #else - #define POINTER_BITS 32 + #define POINTER_BITS (32) #endif // ================================================================================ @@ -60,7 +60,7 @@ #define INT16_MAX 32767i16 #define INT32_MAX 2147483647i32 #define INT64_MAX 9223372036854775807i64 - + #define UINT8_MAX 0xffui8 #define UINT16_MAX 0xffffui16 #define UINT32_MAX 0xffffffffui32 @@ -117,13 +117,13 @@ #if POINTER_BITS == 64 #define SIZE_T_MAX UINT64_MAX #define SIZE_T_MIN UINT64_MIN - + #define SSIZE_T_MAX INT64_MAX #define SSIZE_T_MIN INT64_MIN #else #define SIZE_T_MAX UINT32_MAX #define SIZE_T_MIN UINT32_MIN - + #define SSIZE_T_MAX INT32_MAX #define SSIZE_T_MIN INT32_MIN #endif @@ -142,10 +142,10 @@ #ifndef COUNT_T_MAX typedef UINT32 COUNT_T; typedef INT32 SCOUNT_T; - + #define COUNT_T_MAX UINT32_MAX #define COUNT_T_MIN UINT32_MIN - + #define SCOUNT_T_MAX INT32_MAX #define SCOUNT_T_MIN INT32_MIN #endif @@ -159,15 +159,15 @@ #if NEED_BOOL_TYPEDEF typedef bool BOOL; #endif - + #define BOOL_MAX 1 #define BOOL_MIN 0 - + #define TRUE 1 #define FALSE 0 - + typedef UINT8 BYTE; - + #define BYTE_MAX UINT8_MAX #define BYTE_MIN UINT8_MIN #endif @@ -180,7 +180,6 @@ typedef char CHAR; typedef signed char SCHAR; typedef unsigned char UCHAR; -typedef wchar_t WCHAR; typedef CHAR ASCII; typedef CHAR ANSI; @@ -307,7 +306,7 @@ T Max(T v1, T v2) // -------------------------------------------------------------------------------- // Alignment bit twiddling macros - "alignment" must be power of 2 -// +// // AlignUp - align value to given increment, rounding up // AlignmentPad - amount adjusted by AlignUp // AlignUp(value, x) == value + AlignmentPad(value, x) @@ -390,7 +389,7 @@ inline UINT AlignmentTrim(UINT value, UINT alignment) return value&(alignment-1); } -#ifndef PLATFORM_UNIX +#ifndef HOST_UNIX // For Unix this and the previous function get the same types. // So, exclude this one. inline UINT AlignmentTrim(ULONG value, UINT alignment) @@ -399,7 +398,7 @@ inline UINT AlignmentTrim(ULONG value, UINT alignment) STATIC_CONTRACT_SUPPORTS_DAC; return value&(alignment-1); } -#endif // PLATFORM_UNIX +#endif // HOST_UNIX inline UINT AlignmentTrim(UINT64 value, UINT alignment) { diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/clrversion.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrversion.h new file mode 100644 index 0000000..def0568 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/clrversion.h @@ -0,0 +1,30 @@ +// 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. + +#include "runtime_version.h" + +#ifndef QUOTE_MACRO +#define QUOTE_MACRO_HELPER(x) #x +#define QUOTE_MACRO(x) QUOTE_MACRO_HELPER(x) +#endif + +#ifndef QUOTE_MACRO_L +#define QUOTE_MACRO_L_HELPER(x) L###x +#define QUOTE_MACRO_L(x) QUOTE_MACRO_L_HELPER(x) +#endif + +#define CLR_METADATA_VERSION "v4.0.30319" +#define CLR_METADATA_VERSION_L W("v4.0.30319") + +#define CLR_PRODUCT_VERSION QUOTE_MACRO(RuntimeProductVersion) +#define CLR_PRODUCT_VERSION_L QUOTE_MACRO_L(RuntimeProductVersion) + +#define VER_ASSEMBLYVERSION_STR QUOTE_MACRO(RuntimeAssemblyMajorVersion.RuntimeAssemblyMinorVersion.0.0) +#define VER_ASSEMBLYVERSION_STR_L QUOTE_MACRO_L(RuntimeAssemblyMajorVersion.RuntimeAssemblyMinorVersion.0.0) + +#define VER_FILEVERSION_STR QUOTE_MACRO(RuntimeFileMajorVersion.RuntimeFileMinorVersion.RuntimeFileBuildVersion.RuntimeFileRevisionVersion) +#define VER_FILEVERSION_STR_L QUOTE_MACRO_L(RuntimeFileMajorVersion.RuntimeFileMinorVersion.RuntimeFileBuildVersion.RuntimeFileRevisionVersion) + +#define VER_LEGALCOPYRIGHT_LOGO_STR "Copyright (c) Microsoft Corporation. All rights reserved." +#define VER_LEGALCOPYRIGHT_LOGO_STR_L L"Copyright (c) Microsoft Corporation. All rights reserved." diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/complex.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/complex.h index 159c81d..7af09fc 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/complex.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/complex.h @@ -3,9 +3,9 @@ // See the LICENSE file in the project root for more information. // // complex.h -// +// -// +// // Defines a basic complex number data type. We cannot use the standard C++ library's // complex implementation, because the CLR links to the wrong CRT. // @@ -17,7 +17,7 @@ // // Default compilation mode is /fp:precise, which disables fp intrinsics. This causes us to pull in FP stuff (sqrt,etc.) from -// The CRT, and increases our download size. We don't need the extra precision this gets us, so let's switch to +// The CRT, and increases our download size. We don't need the extra precision this gets us, so let's switch to // the intrinsic versions. // #ifdef _MSC_VER diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/configuration.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/configuration.h index 876abf2..94f0168 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/configuration.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/configuration.h @@ -1,13 +1,13 @@ // 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. -// +// // -------------------------------------------------------------------------------------------------- // configuration.h -// -// +// +// // Access and update configuration values, falling back on legacy CLRConfig methods where necessary. -// +// // -------------------------------------------------------------------------------------------------- #include "clrconfig.h" @@ -35,7 +35,7 @@ public: // in the traditional way separately if you need to. // // Returns value for name if found in config. - static ULONGLONG GetKnobULONGLONGValue(LPCWSTR name); + static ULONGLONG GetKnobULONGLONGValue(LPCWSTR name, ULONGLONG defaultValue); // Returns (in priority order): // - The value of the ConfigStringInfo if it's set diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/contract.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/contract.h index 3913e56..082d41d 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/contract.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/contract.h @@ -5,7 +5,7 @@ // Contract.h // -// ! I am the owner for issues in the contract *infrastructure*, not for every +// ! I am the owner for issues in the contract *infrastructure*, not for every // ! CONTRACT_VIOLATION dialog that comes up. If you interrupt my work for a routine // ! CONTRACT_VIOLATION, you will become the new owner of this file. //-------------------------------------------------------------------------------- @@ -30,7 +30,7 @@ // // // -// INJECT_FAULT(statement) function might require its caller to handle an OOM +// INJECT_FAULT(statement) function might require its caller to handle an OOM // -or- FAULT_FORBID function will NOT require its caller to handle an OOM // // @@ -48,8 +48,8 @@ // // CAN_TAKE_LOCK the function has a code path that takes a lock // _or_ (CAN_TAKE_LOCK and CANNOT_RETAKE_LOCK) -// the function has a code path that takes a lock, but never tries to reenter -// locks held at the time this function was called. +// the function has a code path that takes a lock, but never tries to reenter +// locks held at the time this function was called. // -or- CANNOT_TAKE_LOCK the function will never allow a lock to be taken // -or- the default is WRAPPER(CAN_TAKE_LOCK). i.e., if any callees take locks, // then it's ok for this function to as well. If LIMITED_METHOD_CONTRACT is specified, @@ -75,10 +75,10 @@ // SUPPORTS_DAC The function has been written to be callable from out-of-process using DAC. // In builds where DACCESS_COMPILE is defined, such functions can only call // other such functions (and a few primitives like new). Functions that support -// DAC must be carefully written to conform to the rules in daccess.h. +// DAC must be carefully written to conform to the rules in daccess.h. // -// SUPPORTS_DAC_HOST_ONLY The function and its call graph has been written to be callable from out of process -// using DAC, but it differs from SUPPORTS_DAC in that these functions won't perform +// SUPPORTS_DAC_HOST_ONLY The function and its call graph has been written to be callable from out of process +// using DAC, but it differs from SUPPORTS_DAC in that these functions won't perform // any marshalling. Because it does no marshalling, SUPPORTS_DAC_HOST_ONLY functions // and their call graph won't be checked by DacCop. This should only be used by utility // functions which will never marshal anything. @@ -121,7 +121,7 @@ // instead. // // Static: -// LIMITED_METHOD_CONTRACT +// LIMITED_METHOD_CONTRACT // A static contract equivalent to NOTHROW/GC_NOTRIGGER/FORBID_FAULT/MODE_ANY. // Use only for trivial functions that call only functions with LIMITED_METHOD_CONTRACTs // (as long as there is no cycle that may introduce infinite recursion). @@ -144,7 +144,7 @@ // // // CONTRACT_VIOLATION(violationmask): -// +// // A bandaid used to suppress contract assertions. A contract violation // is always a bug and you're expected to remove it before shipping. // If a violation cannot be fixed immediately, however, it's better @@ -156,10 +156,10 @@ // GCViolation // ModeViolation // FaultViolation -// FaultNotFatal -// HostViolation -// LoadsTypeViolation -// TakesLockViolation +// FaultNotFatal +// HostViolation +// LoadsTypeViolation +// TakesLockViolation // // The associated assertion will be suppressed until you leave the scope // containing the CONTRACT_VIOLATION. Note, however, that any called @@ -171,14 +171,14 @@ // PERMANENT_CONTRACT_VIOLATION(violationmask, permanentContractViolationReason): // // Like a CONTRACT_VIOLATION but also indicates that the violation was a deliberate decision -// and we don't plan on removing the violation in the next release. The reason +// and we don't plan on removing the violation in the next release. The reason // for the violation should be given as the second parameter to the macro. Reasons // are currently for documentation purposes only and do not have an effect on the binary. // Valid values are listed below in the definition of PermanentContractViolationReason. // -// +// // CONDITIONAL_CONTRACT_VIOLATION(violationmask, condition): -// +// // Similar to CONTRACT_VIOLATION, but only suppresses the contract if the // condition evaluates to non-zero. The need for this macro should be very // rare, but it can be useful if a contract should be suppressed based on a @@ -190,7 +190,7 @@ // // A do-nothing contract used by functions that trivially wrap another. // -// +// // "LEGACY" stuff - these features have been mostly superceded by better solutions // so their use should be discouraged. // @@ -361,23 +361,23 @@ struct DbgStateLockData void SetStartingValues(); void LockTaken(DbgStateLockType dbgStateLockType, - UINT cEntrances, - void * pvLock, - __in_z const char * szFunction, - __in_z const char * szFile, + UINT cEntrances, + void * pvLock, + __in_z const char * szFunction, + __in_z const char * szFile, int lineNum); void LockReleased(DbgStateLockType dbgStateLockType, UINT cExits, void * pvLock); UINT GetLockCount(DbgStateLockType dbgStateLockType); UINT GetCombinedLockCount(); }; -// This struct contains all lock contract information. It is created and destroyed along with -// ClrDebugState. m_pLockData points to a DbgStateLockData object that is allocated per thread +// This struct contains all lock contract information. It is created and destroyed along with +// ClrDebugState. m_pLockData points to a DbgStateLockData object that is allocated per thread // and persists across function enters and exists. struct DbgStateLockState { -private: - // Count of locks taken at the time the function with CANNOT_RETAKE_LOCK contract +private: + // Count of locks taken at the time the function with CANNOT_RETAKE_LOCK contract // was called UINT m_cLocksEnteringCannotRetakeLock; @@ -409,8 +409,6 @@ public: #define CONTRACT_BITMASK_RESET(whichbit) (m_flags &= ~(whichbit)) #define CONTRACT_BITMASK_UPDATE(whichbit, value) ((value)?CONTRACT_BITMASK_SET(whichbit):CONTRACT_BITMASK_RESET(whichbit)) - -// Stored in the FLS under TlsIdx_ClrDebugState. struct ClrDebugState { private: @@ -421,7 +419,7 @@ private: UINT m_GCForbidCount; UINT m_maxLoadTypeLevel; // taken from enum ClassLoadLevel BOOL m_allowGetThread; // TRUE if GetThread() is ok in this scope - DbgStateLockState m_LockState; + DbgStateLockState m_LockState; public: // Use an explicit Init rather than ctor as we don't want automatic @@ -429,7 +427,7 @@ public: void SetStartingValues() { m_violationmask = 0; // No violations allowed - + // Default is we're in a THROWS scope. This is not ideal, but there are // just too many places that I'd have to go clean up right now // (hundreds) in order to make this FALSE by default. @@ -469,7 +467,7 @@ public: { return &m_violationmask; } - + UINT_PTR ViolationMask() { return m_violationmask; @@ -503,7 +501,7 @@ public: CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_OK_TO_THROW, value); return prevState; } - + void ResetOkToThrow() { CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_OK_TO_THROW); @@ -525,7 +523,7 @@ public: { BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_FAULT_FORBID); CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_FAULT_FORBID, value); - return prevState; + return prevState; } void ResetFaultForbid() @@ -625,22 +623,22 @@ public: CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_OK_TO_LOCK, value); return prevState; } - + void ResetOkToLock() { CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_OK_TO_LOCK); - } + } //--// BOOL IsOkToRetakeLock() { return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_RETAKE_LOCK); } - + void ResetOkToRetakeLock() { CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_OK_TO_RETAKE_LOCK); - } + } //--// @@ -672,7 +670,7 @@ public: { m_GCNoTriggerCount--; } - + void IncrementGCNoTriggerCount() { m_GCNoTriggerCount++; @@ -688,12 +686,12 @@ public: { m_GCForbidCount--; } - + void IncrementGCForbidCount() { m_GCForbidCount++; } - + UINT GetMaxLoadTypeLevel() { return m_maxLoadTypeLevel; @@ -705,7 +703,7 @@ public: } //--// - + void SetDbgStateLockData(DbgStateLockData * pDbgStateLockData) { m_LockState.SetDbgStateLockData(pDbgStateLockData); @@ -724,10 +722,10 @@ public: void CheckOkayToLock(__in_z const char *szFunction, __in_z const char *szFile, int lineNum); // Asserts if its not okay to lock BOOL CheckOkayToLockNoAssert(); // Returns if OK to lock void LockTaken(DbgStateLockType dbgStateLockType, - UINT cEntrances, - void * pvLock, - __in_z const char * szFunction, - __in_z const char * szFile, + UINT cEntrances, + void * pvLock, + __in_z const char * szFunction, + __in_z const char * szFile, int lineNum); void LockReleased(DbgStateLockType dbgStateLockType, UINT cExits, void * pvLock); UINT GetLockCount(DbgStateLockType dbgStateLockType); @@ -744,13 +742,13 @@ public: ClrDebugState *CLRInitDebugState(); ClrDebugState *GetClrDebugState(BOOL fAlloc = TRUE); +extern thread_local ClrDebugState* t_pClrDebugState; // This function returns a ClrDebugState if one has been created, but will not create one itself. inline ClrDebugState *CheckClrDebugState() { STATIC_CONTRACT_LIMITED_METHOD; - ClrDebugState *ret = (ClrDebugState*)ClrFlsGetValue(TlsIdx_ClrDebugState); - return ret; + return t_pClrDebugState; } void CONTRACT_ASSERT(const char *szElaboration, @@ -828,7 +826,7 @@ public: Enter(); }; - + DEBUG_NOINLINE ~AutoCleanupDebugOnlyCodeHolder() { SCAN_SCOPE_END; @@ -854,7 +852,7 @@ public: #else // ENABLE_CONTRACTS_IMPL #define DEBUG_ONLY_FUNCTION STATIC_CONTRACT_DEBUG_ONLY -#define DEBUG_ONLY_REGION() +#define DEBUG_ONLY_REGION() #define BEGIN_DEBUG_ONLY_CODE #define END_DEBUG_ONLY_CODE #define ENTER_DEBUG_ONLY_CODE @@ -862,7 +860,7 @@ public: #endif #else // _DEBUG -#define DEBUG_ONLY_REGION() +#define DEBUG_ONLY_REGION() #endif @@ -903,7 +901,7 @@ class ___maybetemplate class BaseContract { // Really private, but used by macros - public: + public: // We use a single integer to specify all the settings for intrinsic tests // such as THROWS and GC_TRIGGERS. The compiler should be able to fold all @@ -1308,7 +1306,7 @@ typedef __SafeToUsePostCondition __PostConditionOK; UINT ___testmask = 0; \ #else // #ifndef __FORCE_NORUNTIME_CONTRACTS__ - + #define CONTRACT_SETUP(_contracttype, _returntype, _returnexp) \ _returntype RETVAL; \ Contract::Returner<_returntype> ___returner(RETVAL); \ @@ -1375,7 +1373,7 @@ typedef __SafeToUsePostCondition __PostConditionOK; #define CUSTOM_CONTRACT(_contracttype, _returntype) \ typedef Contract::PseudoTemplate<_returntype> ___maybetemplate; \ CONTRACT_SETUP(_contracttype, _returntype, RETVAL) - + #define CUSTOM_CONTRACT_VOID(_contracttype) \ CONTRACT_SETUP(_contracttype, int, ;) @@ -1529,7 +1527,7 @@ typedef __SafeToUsePostCondition __PostConditionOK; ___CheckMustBeInside_CONTRACT; \ } -#else +#else #define CONTRACTL_END \ if (___op & Contract::Setup) \ @@ -1719,7 +1717,7 @@ public: }; protected: - // We require that violationMask is passed as a parameter here to hopefully defeat the + // We require that violationMask is passed as a parameter here to hopefully defeat the // compiler's desire to fold all the Enter and Ctor implementations together. FORCEINLINE void EnterInternal(UINT_PTR violationMask) { @@ -1784,7 +1782,7 @@ public: AutoCleanupContractViolationHolder __violationHolder_onlyOneAllowedPerScope; -// Reasons for having the violation. Use one of these values as an additional parameter to +// Reasons for having the violation. Use one of these values as an additional parameter to // E.g. PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonContractInfrastructure) // New values and explanations can be added when needed. enum PermanentContractViolationReason @@ -1999,26 +1997,13 @@ class LoadsTypeHolder #define TRIGGERS_TYPE_LOAD(newLevel) #define MAYBE_TRIGGERS_TYPE_LOAD(newLevel, fEnable) #define OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel) -#define MAYBE_OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel, fEnable) +#define MAYBE_OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel, fEnable) #endif // ENABLE_CONTRACTS_IMPL #ifdef ENABLE_CONTRACTS_IMPL -class PAL_TryMarker -{ -public: - DEBUG_NOINLINE void Enter(); - DEBUG_NOINLINE void Leave(); -}; - -#define PAL_ENTER_THROWS_REGION \ - PAL_TryMarker __throwsHolder_onlyOneAllowedPerScope; \ - __throwsHolder_onlyOneAllowedPerScope.Enter(); - -#define PAL_LEAVE_THROWS_REGION \ - __throwsHolder_onlyOneAllowedPerScope.Leave(); // This sets up a marker that says its okay to throw on this thread. This is not a public macro, and should only be // used from within the implementation of various try/catch macros. @@ -2052,8 +2037,6 @@ private: #else // ENABLE_CONTRACTS_IMPL #define CLR_TRY_MARKER() -#define PAL_ENTER_THROWS_REGION -#define PAL_LEAVE_THROWS_REGION #endif @@ -2093,7 +2076,7 @@ class HostNoCallHolder m_clrDebugState = GetClrDebugState(); m_previousState = m_clrDebugState->SetHostCaller(FALSE); } - + DEBUG_NOINLINE ~HostNoCallHolder() { SCAN_SCOPE_END; @@ -2104,7 +2087,7 @@ class HostNoCallHolder private: BOOL m_previousState; ClrDebugState* m_clrDebugState; - + }; #define BEGIN_HOST_NOCALL_CODE \ @@ -2114,7 +2097,7 @@ class HostNoCallHolder #define END_HOST_NOCALL_CODE \ } - + #else // ENABLE_CONTRACTS_IMPL #define BEGIN_HOST_NOCALL_CODE \ { \ @@ -2134,7 +2117,7 @@ class GetThreadAllowedHolder m_clrDebugState = ::GetClrDebugState(); m_previousState = m_clrDebugState->SetGetThreadAllowed(newState); } - + ~GetThreadAllowedHolder() { m_clrDebugState->SetGetThreadAllowed(m_previousState); @@ -2167,7 +2150,7 @@ private: #define END_GETTHREAD_ALLOWED \ } - + // These are lighter-weight versions of BEGIN_GETTHREAD_ALLOWED / // END_GETTHREAD_ALLOWED. These don't use holders, so be sure only to // use these to bracket code that won't throw exceptions @@ -2230,18 +2213,18 @@ private: #define LOCK_TAKEN_MULTIPLE(dbgStateLockType, cEntrances, pvLock) #define LOCK_RELEASED_MULTIPLE(dbgStateLockType, cExits, pvLock) -#define EE_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock) -#define EE_LOCK_RELEASED_MULTIPLE(cExits, pvLock) -#define HOST_BREAKABLE_CRST_TAKEN_MULTIPLE(cEntrances, pvLock) +#define EE_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock) +#define EE_LOCK_RELEASED_MULTIPLE(cExits, pvLock) +#define HOST_BREAKABLE_CRST_TAKEN_MULTIPLE(cEntrances, pvLock) #define HOST_BREAKABLE_CRST_RELEASED_MULTIPLE(cExits, pvLock) -#define USER_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock) -#define USER_LOCK_RELEASED_MULTIPLE(cExits, pvLock) -#define EE_LOCK_TAKEN(pvLock) -#define EE_LOCK_RELEASED(pvLock) +#define USER_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock) +#define USER_LOCK_RELEASED_MULTIPLE(cExits, pvLock) +#define EE_LOCK_TAKEN(pvLock) +#define EE_LOCK_RELEASED(pvLock) #define HOST_BREAKABLE_CRST_TAKEN(pvLock) #define HOST_BREAKABLE_CRST_RELEASED(pvLock) -#define USER_LOCK_TAKEN(pvLock) -#define USER_LOCK_RELEASED(pvLock) +#define USER_LOCK_TAKEN(pvLock) +#define USER_LOCK_RELEASED(pvLock) #endif // defined(ENABLE_CONTRACTS_IMPL) @@ -2300,22 +2283,22 @@ extern Volatile g_DbgSuppressAllocationAsserts; // analysis tools that run on mscordacwks.dll like DacCop. // Note that we want these static contracts in both DEBUG and retail builds. // We also already get simple static contracts like WRAPPER and LEAF. -// +// //----------------------------------------------------------------------------- #if defined(DACCESS_COMPILE) // SUPPORTS_DAC is an annotation that says the function is designed to be used in DAC builds. -// This enables full DacCop analysis on the function, including verifying that all functions that are +// This enables full DacCop analysis on the function, including verifying that all functions that are // called also support DAC. #define SUPPORTS_DAC do { STATIC_CONTRACT_SUPPORTS_DAC; } while(0) // Normally a function can be annotated just with WRAPPER_NO_CONTRACT, which (in addition to the normal // contract meaning) indicates to DacCop that the function should be considered to support DAC when // it is called from a supports-dac function. This is to avoid having to add a DAC-specific contract -// to all the trivial one-line wrapper functions we have. +// to all the trivial one-line wrapper functions we have. // However, we occasionally want these semantics even for functions which are not appropriate to label // as WRAPPER_NO_CONTRACT. For example, a template function may support DAC for certain template arguments, -// but not others (due to the functions it calls). We want to ensure that when such a function is called +// but not others (due to the functions it calls). We want to ensure that when such a function is called // in a DAC code path, analysis is enabled on that particular instantiation including checking all of the // call targets specific to this template instantiation. But we don't want to require that the call targets // for ALL instantiations support dac, since we may not even be using them in DAC code paths. Ideally we'd @@ -2325,17 +2308,17 @@ extern Volatile g_DbgSuppressAllocationAsserts; // SUPPORTS_DAC_HOST_ONLY indicates that a function is allowed to be called in DAC builds, but rather // than being a normal DAC function which operates on marshalled data, it is a host-only utility function // that knows nothing about DAC and operates solely on the host. For example, DbgAssertDialog is a utility -// function for popping assert dialogs - there is nothing DAC-specific about this. Ideally such utility +// function for popping assert dialogs - there is nothing DAC-specific about this. Ideally such utility // functions would be confined to their own library which had no access to DAC functionality, and which -// is not analyzed by DacCop. At the moment splitting utilcode into two variations like this is too +// is not analyzed by DacCop. At the moment splitting utilcode into two variations like this is too // painful, but we hope to do it in the future (primarily to support functions which can be used in either // DAC or host-only mode). -// WARNING: This contract disables DacCop analysis on the function and any functions it calls, so it -// should be used very carefully. +// WARNING: This contract disables DacCop analysis on the function and any functions it calls, so it +// should be used very carefully. #define SUPPORTS_DAC_HOST_ONLY do { STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; } while(0) #else -#define SUPPORTS_DAC +#define SUPPORTS_DAC #define SUPPORTS_DAC_HOST_ONLY #define SUPPORTS_DAC_WRAPPER #endif // DACCESS_COMPILE diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/contract.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/contract.inl index 3c79494..ee223b6 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/contract.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/contract.inl @@ -5,7 +5,7 @@ // Contract.inl // -// ! I am the owner for issues in the contract *infrastructure*, not for every +// ! I am the owner for issues in the contract *infrastructure*, not for every // ! CONTRACT_VIOLATION dialog that comes up. If you interrupt my work for a routine // ! CONTRACT_VIOLATION, you will become the new owner of this file. // --------------------------------------------------------------------------- @@ -129,7 +129,7 @@ inline void BaseContract::DoChecks(UINT testmask, __in_z const char *szFunction, } m_pClrDebugState->SetMaxLoadTypeLevel(newTypeLoadLevel); m_pClrDebugState->ViolationMaskReset(LoadsTypeViolation); - + } break; } @@ -142,7 +142,7 @@ inline void BaseContract::DoChecks(UINT testmask, __in_z const char *szFunction, switch (testmask & CAN_TAKE_LOCK_Mask) { - case CAN_TAKE_LOCK_Yes: + case CAN_TAKE_LOCK_Yes: m_pClrDebugState->CheckOkayToLock(m_contractStackRecord.m_szFunction, m_contractStackRecord.m_szFile, m_contractStackRecord.m_lineNum); @@ -223,16 +223,16 @@ inline void ClrDebugState::CheckOkayToLock(__in_z const char *szFunction, __in_z szFunction, szFile, lineNum); - + } } inline void ClrDebugState::LockTaken(DbgStateLockType dbgStateLockType, - UINT cTakes, - void * pvLock, - __in_z const char * szFunction, - __in_z const char * szFile, + UINT cTakes, + void * pvLock, + __in_z const char * szFunction, + __in_z const char * szFile, int lineNum) { STATIC_CONTRACT_DEBUG_ONLY; @@ -281,7 +281,7 @@ inline void ClrDebugState::LockReleased(DbgStateLockType dbgStateLockType, UINT if (!IsOkToRetakeLock()) { - // It is very suspicious to release any locks being hold at the time this function was + // It is very suspicious to release any locks being hold at the time this function was // called in a CANNOT_RETAKE_LOCK scope _ASSERTE(m_LockState.IsSafeToRelease(cReleases)); } @@ -321,9 +321,9 @@ inline UINT ClrDebugState::GetCombinedLockCount() inline void DbgStateLockData::LockTaken(DbgStateLockType dbgStateLockType, UINT cTakes, // # times we're taking this lock (usually 1) - void * pvLock, - __in_z const char * szFunction, - __in_z const char * szFile, + void * pvLock, + __in_z const char * szFunction, + __in_z const char * szFile, int lineNum) { STATIC_CONTRACT_NOTHROW; @@ -399,7 +399,7 @@ inline void DbgStateLockData::LockReleased(DbgStateLockType dbgStateLockType, UI // were released out of order. However, it will eventually correct itself once all // the out-of-order locks have been released. And our count // (i.e., m_rgcLocksTaken[dbgStateLockType]) will always be accurate - memset(&(m_rgTakenLockInfos[i]), + memset(&(m_rgTakenLockInfos[i]), 0, sizeof(m_rgTakenLockInfos[i])); } @@ -415,7 +415,7 @@ inline void DbgStateLockData::SetStartingValues() inline UINT DbgStateLockData::GetLockCount(DbgStateLockType dbgStateLockType) { _ASSERTE(UINT(dbgStateLockType) < kDbgStateLockType_Count); - return m_rgcLocksTaken[dbgStateLockType]; + return m_rgcLocksTaken[dbgStateLockType]; } inline UINT DbgStateLockData::GetCombinedLockCount() @@ -433,7 +433,7 @@ inline void DbgStateLockState::SetStartingValues() m_pLockData = NULL; // Will get filled in by CLRInitDebugState() } -// We set a marker to record the number of locks that have been taken when +// We set a marker to record the number of locks that have been taken when // CANNOT_RETAKE_LOCK contract is constructed. inline void DbgStateLockState::OnEnterCannotRetakeLockFunction() { @@ -447,8 +447,8 @@ inline BOOL DbgStateLockState::IsLockRetaken(void * pvLock) // m_cLocksEnteringCannotRetakeLock records the number of locks that were taken // when CANNOT_RETAKE_LOCK contract was constructed. - for (UINT i = 0; - i < min(_countof(m_pLockData->m_rgTakenLockInfos), m_cLocksEnteringCannotRetakeLock); + for (UINT i = 0; + i < min(_countof(m_pLockData->m_rgTakenLockInfos), m_cLocksEnteringCannotRetakeLock); ++i) { if (m_pLockData->m_rgTakenLockInfos[i].m_pvLock == pvLock) @@ -476,7 +476,7 @@ inline DbgStateLockData * DbgStateLockState::GetDbgStateLockData() inline void CONTRACT_ASSERT(const char *szElaboration, - UINT whichTest, + UINT whichTest, UINT whichTestMask, const char *szFunction, const char *szFile, @@ -542,7 +542,7 @@ void CONTRACT_ASSERT(const char *szElaboration, pRec->m_szFile, pRec->m_lineNum ); - + strcat_s(Buf, _countof(Buf), tmpbuf); } @@ -579,7 +579,7 @@ void CONTRACT_ASSERT(const char *szElaboration, "\n" ); } - + strcat_s(Buf,_countof(Buf), "\n\n"); if (!foundconflict && count != 0) @@ -604,7 +604,7 @@ FORCEINLINE BOOL BaseContract::EnforceContract() { if (s_alwaysEnforceContracts) return TRUE; - else + else return CHECK::EnforceAssert(); } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/contxt.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/contxt.h index 98240b3..b9b4121 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/contxt.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/contxt.h @@ -10,7 +10,7 @@ */ /* Compiler settings for contxt.idl: Os (OptLev=s), W1, Zp8, env=Win32, ms_ext, c_ext - error checks: allocation ref bounds_check enum stub_data + error checks: allocation ref bounds_check enum stub_data */ //@@MIDL_FILE_HEADING( ) @@ -37,9 +37,9 @@ #ifdef __cplusplus extern "C"{ -#endif +#endif -/* Forward Declarations */ +/* Forward Declarations */ #ifndef __IEnumContextProps_FWD_DEFINED__ #define __IEnumContextProps_FWD_DEFINED__ @@ -160,10 +160,10 @@ typedef interface IComDispatchInfo IComDispatchInfo; #include "objidl.h" void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t); -void __RPC_USER MIDL_user_free( void __RPC_FAR * ); +void __RPC_USER MIDL_user_free( void __RPC_FAR * ); /* interface __MIDL_itf_contxt_0000 */ -/* [local] */ +/* [local] */ enum tagCONTEXTEVENT { CONTEXTEVENT_NONE = 0, @@ -215,7 +215,7 @@ extern RPC_IF_HANDLE __MIDL_itf_contxt_0000_v0_0_s_ifspec; #define __IEnumContextProps_INTERFACE_DEFINED__ /* interface IEnumContextProps */ -/* [unique][uuid][object] */ +/* [unique][uuid][object] */ typedef /* [unique] */ IEnumContextProps __RPC_FAR *LPENUMCONTEXTPROPS; @@ -223,67 +223,67 @@ typedef /* [unique] */ IEnumContextProps __RPC_FAR *LPENUMCONTEXTPROPS; EXTERN_C const IID IID_IEnumContextProps; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001c1-0000-0000-C000-000000000046") IEnumContextProps : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ContextProperty __RPC_FAR *pContextProperties, /* [out] */ ULONG __RPC_FAR *pceltFetched) = 0; - - virtual HRESULT STDMETHODCALLTYPE Skip( + + virtual HRESULT STDMETHODCALLTYPE Skip( /* [in] */ ULONG celt) = 0; - + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE Clone( + + virtual HRESULT STDMETHODCALLTYPE Clone( /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps) = 0; - - virtual HRESULT STDMETHODCALLTYPE Count( + + virtual HRESULT STDMETHODCALLTYPE Count( /* [out] */ ULONG __RPC_FAR *pcelt) = 0; - + }; - + #else /* C style interface */ typedef struct IEnumContextPropsVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IEnumContextProps __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IEnumContextProps __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IEnumContextProps __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Next )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Next )( IEnumContextProps __RPC_FAR * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ContextProperty __RPC_FAR *pContextProperties, /* [out] */ ULONG __RPC_FAR *pceltFetched); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Skip )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Skip )( IEnumContextProps __RPC_FAR * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Reset )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Reset )( IEnumContextProps __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Clone )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Clone )( IEnumContextProps __RPC_FAR * This, /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Count )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Count )( IEnumContextProps __RPC_FAR * This, /* [out] */ ULONG __RPC_FAR *pcelt); - + END_INTERFACE } IEnumContextPropsVtbl; @@ -292,7 +292,7 @@ EXTERN_C const IID IID_IEnumContextProps; CONST_VTBL struct IEnumContextPropsVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -329,7 +329,7 @@ EXTERN_C const IID IID_IEnumContextProps; -HRESULT STDMETHODCALLTYPE IEnumContextProps_Next_Proxy( +HRESULT STDMETHODCALLTYPE IEnumContextProps_Next_Proxy( IEnumContextProps __RPC_FAR * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ContextProperty __RPC_FAR *pContextProperties, @@ -343,7 +343,7 @@ void __RPC_STUB IEnumContextProps_Next_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IEnumContextProps_Skip_Proxy( +HRESULT STDMETHODCALLTYPE IEnumContextProps_Skip_Proxy( IEnumContextProps __RPC_FAR * This, /* [in] */ ULONG celt); @@ -355,7 +355,7 @@ void __RPC_STUB IEnumContextProps_Skip_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IEnumContextProps_Reset_Proxy( +HRESULT STDMETHODCALLTYPE IEnumContextProps_Reset_Proxy( IEnumContextProps __RPC_FAR * This); @@ -366,7 +366,7 @@ void __RPC_STUB IEnumContextProps_Reset_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IEnumContextProps_Clone_Proxy( +HRESULT STDMETHODCALLTYPE IEnumContextProps_Clone_Proxy( IEnumContextProps __RPC_FAR * This, /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); @@ -378,7 +378,7 @@ void __RPC_STUB IEnumContextProps_Clone_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IEnumContextProps_Count_Proxy( +HRESULT STDMETHODCALLTYPE IEnumContextProps_Count_Proxy( IEnumContextProps __RPC_FAR * This, /* [out] */ ULONG __RPC_FAR *pcelt); @@ -398,72 +398,72 @@ void __RPC_STUB IEnumContextProps_Count_Stub( #define __IContext_INTERFACE_DEFINED__ /* interface IContext */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ EXTERN_C const IID IID_IContext; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001c0-0000-0000-C000-000000000046") IContext : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE SetProperty( + virtual HRESULT STDMETHODCALLTYPE SetProperty( /* [in] */ REFGUID rpolicyId, /* [in] */ CPFLAGS flags, /* [in] */ IUnknown __RPC_FAR *pUnk) = 0; - - virtual HRESULT STDMETHODCALLTYPE RemoveProperty( + + virtual HRESULT STDMETHODCALLTYPE RemoveProperty( /* [in] */ REFGUID rPolicyId) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetProperty( + + virtual HRESULT STDMETHODCALLTYPE GetProperty( /* [in] */ REFGUID rGuid, /* [out] */ CPFLAGS __RPC_FAR *pFlags, /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumContextProps( + + virtual HRESULT STDMETHODCALLTYPE EnumContextProps( /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps) = 0; - + }; - + #else /* C style interface */ typedef struct IContextVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IContext __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IContext __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IContext __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetProperty )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetProperty )( IContext __RPC_FAR * This, /* [in] */ REFGUID rpolicyId, /* [in] */ CPFLAGS flags, /* [in] */ IUnknown __RPC_FAR *pUnk); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RemoveProperty )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RemoveProperty )( IContext __RPC_FAR * This, /* [in] */ REFGUID rPolicyId); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetProperty )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetProperty )( IContext __RPC_FAR * This, /* [in] */ REFGUID rGuid, /* [out] */ CPFLAGS __RPC_FAR *pFlags, /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnumContextProps )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnumContextProps )( IContext __RPC_FAR * This, /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); - + END_INTERFACE } IContextVtbl; @@ -472,7 +472,7 @@ EXTERN_C const IID IID_IContext; CONST_VTBL struct IContextVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -506,7 +506,7 @@ EXTERN_C const IID IID_IContext; -HRESULT STDMETHODCALLTYPE IContext_SetProperty_Proxy( +HRESULT STDMETHODCALLTYPE IContext_SetProperty_Proxy( IContext __RPC_FAR * This, /* [in] */ REFGUID rpolicyId, /* [in] */ CPFLAGS flags, @@ -520,7 +520,7 @@ void __RPC_STUB IContext_SetProperty_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IContext_RemoveProperty_Proxy( +HRESULT STDMETHODCALLTYPE IContext_RemoveProperty_Proxy( IContext __RPC_FAR * This, /* [in] */ REFGUID rPolicyId); @@ -532,7 +532,7 @@ void __RPC_STUB IContext_RemoveProperty_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IContext_GetProperty_Proxy( +HRESULT STDMETHODCALLTYPE IContext_GetProperty_Proxy( IContext __RPC_FAR * This, /* [in] */ REFGUID rGuid, /* [out] */ CPFLAGS __RPC_FAR *pFlags, @@ -546,7 +546,7 @@ void __RPC_STUB IContext_GetProperty_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IContext_EnumContextProps_Proxy( +HRESULT STDMETHODCALLTYPE IContext_EnumContextProps_Proxy( IContext __RPC_FAR * This, /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); @@ -566,7 +566,7 @@ void __RPC_STUB IContext_EnumContextProps_Stub( #define __IContextMarshaler_INTERFACE_DEFINED__ /* interface IContextMarshaler */ -/* [uuid][object][local] */ +/* [uuid][object][local] */ typedef /* [unique] */ IContextMarshaler __RPC_FAR *LPCTXMARSHALER; @@ -574,47 +574,47 @@ typedef /* [unique] */ IContextMarshaler __RPC_FAR *LPCTXMARSHALER; EXTERN_C const IID IID_IContextMarshaler; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001D8-0000-0000-C000-000000000046") IContextMarshaler : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetMarshalSizeMax( + virtual HRESULT STDMETHODCALLTYPE GetMarshalSizeMax( /* [in] */ REFIID riid, /* [unique][in] */ void __RPC_FAR *pv, /* [in] */ DWORD dwDestContext, /* [unique][in] */ void __RPC_FAR *pvDestContext, /* [in] */ DWORD mshlflags, /* [out] */ DWORD __RPC_FAR *pSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE MarshalInterface( + + virtual HRESULT STDMETHODCALLTYPE MarshalInterface( /* [unique][in] */ IStream __RPC_FAR *pStm, /* [in] */ REFIID riid, /* [unique][in] */ void __RPC_FAR *pv, /* [in] */ DWORD dwDestContext, /* [unique][in] */ void __RPC_FAR *pvDestContext, /* [in] */ DWORD mshlflags) = 0; - + }; - + #else /* C style interface */ typedef struct IContextMarshalerVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IContextMarshaler __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IContextMarshaler __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IContextMarshaler __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetMarshalSizeMax )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetMarshalSizeMax )( IContextMarshaler __RPC_FAR * This, /* [in] */ REFIID riid, /* [unique][in] */ void __RPC_FAR *pv, @@ -622,8 +622,8 @@ EXTERN_C const IID IID_IContextMarshaler; /* [unique][in] */ void __RPC_FAR *pvDestContext, /* [in] */ DWORD mshlflags, /* [out] */ DWORD __RPC_FAR *pSize); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *MarshalInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *MarshalInterface )( IContextMarshaler __RPC_FAR * This, /* [unique][in] */ IStream __RPC_FAR *pStm, /* [in] */ REFIID riid, @@ -631,7 +631,7 @@ EXTERN_C const IID IID_IContextMarshaler; /* [in] */ DWORD dwDestContext, /* [unique][in] */ void __RPC_FAR *pvDestContext, /* [in] */ DWORD mshlflags); - + END_INTERFACE } IContextMarshalerVtbl; @@ -640,7 +640,7 @@ EXTERN_C const IID IID_IContextMarshaler; CONST_VTBL struct IContextMarshalerVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -668,7 +668,7 @@ EXTERN_C const IID IID_IContextMarshaler; -HRESULT STDMETHODCALLTYPE IContextMarshaler_GetMarshalSizeMax_Proxy( +HRESULT STDMETHODCALLTYPE IContextMarshaler_GetMarshalSizeMax_Proxy( IContextMarshaler __RPC_FAR * This, /* [in] */ REFIID riid, /* [unique][in] */ void __RPC_FAR *pv, @@ -685,7 +685,7 @@ void __RPC_STUB IContextMarshaler_GetMarshalSizeMax_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IContextMarshaler_MarshalInterface_Proxy( +HRESULT STDMETHODCALLTYPE IContextMarshaler_MarshalInterface_Proxy( IContextMarshaler __RPC_FAR * This, /* [unique][in] */ IStream __RPC_FAR *pStm, /* [in] */ REFIID riid, @@ -714,7 +714,7 @@ void __RPC_STUB IContextMarshaler_MarshalInterface_Stub( // section. #ifndef __PFNCTXCALLBACK_HACK #define __PFNCTXCALLBACK_HACK -typedef /* [ref] */ HRESULT ( __stdcall __RPC_FAR *PFNCTXCALLBACK )( +typedef /* [ref] */ HRESULT ( __stdcall __RPC_FAR *PFNCTXCALLBACK )( void __RPC_FAR *pParam); #endif @@ -722,109 +722,109 @@ typedef /* [ref] */ HRESULT ( __stdcall __RPC_FAR *PFNCTXCALLBACK )( #define __IObjContext_INTERFACE_DEFINED__ /* interface IObjContext */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ EXTERN_C const IID IID_IObjContext; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001c6-0000-0000-C000-000000000046") IObjContext : public IContext { public: virtual HRESULT STDMETHODCALLTYPE Freeze( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE DoCallback( + + virtual HRESULT STDMETHODCALLTYPE DoCallback( /* [in] */ PFNCTXCALLBACK pfnCallback, /* [in] */ void __RPC_FAR *pParam, /* [in] */ REFIID riid, /* [in] */ unsigned int iMethod) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetContextMarshaler( + + virtual HRESULT STDMETHODCALLTYPE SetContextMarshaler( /* [in] */ IContextMarshaler __RPC_FAR *pICM) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetContextMarshaler( + + virtual HRESULT STDMETHODCALLTYPE GetContextMarshaler( /* [out] */ IContextMarshaler __RPC_FAR *__RPC_FAR *pICM) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetContextFlags( + + virtual HRESULT STDMETHODCALLTYPE SetContextFlags( /* [in] */ DWORD dwFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE ClearContextFlags( + + virtual HRESULT STDMETHODCALLTYPE ClearContextFlags( /* [in] */ DWORD dwFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetContextFlags( + + virtual HRESULT STDMETHODCALLTYPE GetContextFlags( /* [out] */ DWORD __RPC_FAR *pdwFlags) = 0; - + }; - + #else /* C style interface */ typedef struct IObjContextVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IObjContext __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IObjContext __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IObjContext __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetProperty )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetProperty )( IObjContext __RPC_FAR * This, /* [in] */ REFGUID rpolicyId, /* [in] */ CPFLAGS flags, /* [in] */ IUnknown __RPC_FAR *pUnk); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RemoveProperty )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RemoveProperty )( IObjContext __RPC_FAR * This, /* [in] */ REFGUID rPolicyId); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetProperty )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetProperty )( IObjContext __RPC_FAR * This, /* [in] */ REFGUID rGuid, /* [out] */ CPFLAGS __RPC_FAR *pFlags, /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnumContextProps )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnumContextProps )( IObjContext __RPC_FAR * This, /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Freeze )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Freeze )( IObjContext __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DoCallback )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DoCallback )( IObjContext __RPC_FAR * This, /* [in] */ PFNCTXCALLBACK pfnCallback, /* [in] */ void __RPC_FAR *pParam, /* [in] */ REFIID riid, /* [in] */ unsigned int iMethod); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetContextMarshaler )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetContextMarshaler )( IObjContext __RPC_FAR * This, /* [in] */ IContextMarshaler __RPC_FAR *pICM); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetContextMarshaler )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetContextMarshaler )( IObjContext __RPC_FAR * This, /* [out] */ IContextMarshaler __RPC_FAR *__RPC_FAR *pICM); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetContextFlags )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetContextFlags )( IObjContext __RPC_FAR * This, /* [in] */ DWORD dwFlags); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ClearContextFlags )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ClearContextFlags )( IObjContext __RPC_FAR * This, /* [in] */ DWORD dwFlags); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetContextFlags )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetContextFlags )( IObjContext __RPC_FAR * This, /* [out] */ DWORD __RPC_FAR *pdwFlags); - + END_INTERFACE } IObjContextVtbl; @@ -833,7 +833,7 @@ EXTERN_C const IID IID_IObjContext; CONST_VTBL struct IObjContextVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -889,7 +889,7 @@ EXTERN_C const IID IID_IObjContext; -HRESULT STDMETHODCALLTYPE IObjContext_Freeze_Proxy( +HRESULT STDMETHODCALLTYPE IObjContext_Freeze_Proxy( IObjContext __RPC_FAR * This); @@ -900,7 +900,7 @@ void __RPC_STUB IObjContext_Freeze_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IObjContext_DoCallback_Proxy( +HRESULT STDMETHODCALLTYPE IObjContext_DoCallback_Proxy( IObjContext __RPC_FAR * This, /* [in] */ PFNCTXCALLBACK pfnCallback, /* [in] */ void __RPC_FAR *pParam, @@ -915,7 +915,7 @@ void __RPC_STUB IObjContext_DoCallback_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IObjContext_SetContextMarshaler_Proxy( +HRESULT STDMETHODCALLTYPE IObjContext_SetContextMarshaler_Proxy( IObjContext __RPC_FAR * This, /* [in] */ IContextMarshaler __RPC_FAR *pICM); @@ -927,7 +927,7 @@ void __RPC_STUB IObjContext_SetContextMarshaler_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IObjContext_GetContextMarshaler_Proxy( +HRESULT STDMETHODCALLTYPE IObjContext_GetContextMarshaler_Proxy( IObjContext __RPC_FAR * This, /* [out] */ IContextMarshaler __RPC_FAR *__RPC_FAR *pICM); @@ -939,7 +939,7 @@ void __RPC_STUB IObjContext_GetContextMarshaler_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IObjContext_SetContextFlags_Proxy( +HRESULT STDMETHODCALLTYPE IObjContext_SetContextFlags_Proxy( IObjContext __RPC_FAR * This, /* [in] */ DWORD dwFlags); @@ -951,7 +951,7 @@ void __RPC_STUB IObjContext_SetContextFlags_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IObjContext_ClearContextFlags_Proxy( +HRESULT STDMETHODCALLTYPE IObjContext_ClearContextFlags_Proxy( IObjContext __RPC_FAR * This, /* [in] */ DWORD dwFlags); @@ -963,7 +963,7 @@ void __RPC_STUB IObjContext_ClearContextFlags_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IObjContext_GetContextFlags_Proxy( +HRESULT STDMETHODCALLTYPE IObjContext_GetContextFlags_Proxy( IObjContext __RPC_FAR * This, /* [out] */ DWORD __RPC_FAR *pdwFlags); @@ -983,43 +983,43 @@ void __RPC_STUB IObjContext_GetContextFlags_Stub( #define __IGetContextId_INTERFACE_DEFINED__ /* interface IGetContextId */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ EXTERN_C const IID IID_IGetContextId; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001dd-0000-0000-C000-000000000046") IGetContextId : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetContextId( + virtual HRESULT STDMETHODCALLTYPE GetContextId( /* [out] */ GUID __RPC_FAR *pguidCtxtId) = 0; - + }; - + #else /* C style interface */ typedef struct IGetContextIdVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IGetContextId __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IGetContextId __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IGetContextId __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetContextId )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetContextId )( IGetContextId __RPC_FAR * This, /* [out] */ GUID __RPC_FAR *pguidCtxtId); - + END_INTERFACE } IGetContextIdVtbl; @@ -1028,7 +1028,7 @@ EXTERN_C const IID IID_IGetContextId; CONST_VTBL struct IGetContextIdVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -1053,7 +1053,7 @@ EXTERN_C const IID IID_IGetContextId; -HRESULT STDMETHODCALLTYPE IGetContextId_GetContextId_Proxy( +HRESULT STDMETHODCALLTYPE IGetContextId_GetContextId_Proxy( IGetContextId __RPC_FAR * This, /* [out] */ GUID __RPC_FAR *pguidCtxtId); @@ -1073,7 +1073,7 @@ void __RPC_STUB IGetContextId_GetContextId_Stub( #define __IAggregator_INTERFACE_DEFINED__ /* interface IAggregator */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ typedef /* [unique] */ IAggregator __RPC_FAR *IAGGREGATOR; @@ -1081,37 +1081,37 @@ typedef /* [unique] */ IAggregator __RPC_FAR *IAGGREGATOR; EXTERN_C const IID IID_IAggregator; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001d8-0000-0000-C000-000000000046") IAggregator : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE Aggregate( + virtual HRESULT STDMETHODCALLTYPE Aggregate( /* [in] */ IUnknown __RPC_FAR *pInnerUnk) = 0; - + }; - + #else /* C style interface */ typedef struct IAggregatorVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IAggregator __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IAggregator __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IAggregator __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Aggregate )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Aggregate )( IAggregator __RPC_FAR * This, /* [in] */ IUnknown __RPC_FAR *pInnerUnk); - + END_INTERFACE } IAggregatorVtbl; @@ -1120,7 +1120,7 @@ EXTERN_C const IID IID_IAggregator; CONST_VTBL struct IAggregatorVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -1145,7 +1145,7 @@ EXTERN_C const IID IID_IAggregator; -HRESULT STDMETHODCALLTYPE IAggregator_Aggregate_Proxy( +HRESULT STDMETHODCALLTYPE IAggregator_Aggregate_Proxy( IAggregator __RPC_FAR * This, /* [in] */ IUnknown __RPC_FAR *pInnerUnk); @@ -1165,7 +1165,7 @@ void __RPC_STUB IAggregator_Aggregate_Stub( #define __ICall_INTERFACE_DEFINED__ /* interface ICall */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ typedef /* [unique] */ ICall __RPC_FAR *LPCALL; @@ -1173,57 +1173,57 @@ typedef /* [unique] */ ICall __RPC_FAR *LPCALL; EXTERN_C const IID IID_ICall; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001d6-0000-0000-C000-000000000046") ICall : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetCallInfo( + virtual HRESULT STDMETHODCALLTYPE GetCallInfo( /* [out] */ const void __RPC_FAR *__RPC_FAR *ppIdentity, /* [out] */ IID __RPC_FAR *piid, /* [out] */ DWORD __RPC_FAR *pdwMethod, /* [out] */ HRESULT __RPC_FAR *phr) = 0; - - virtual HRESULT STDMETHODCALLTYPE Nullify( + + virtual HRESULT STDMETHODCALLTYPE Nullify( /* [in] */ HRESULT hr) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetServerHR( + + virtual HRESULT STDMETHODCALLTYPE GetServerHR( /* [out] */ HRESULT __RPC_FAR *phr) = 0; - + }; - + #else /* C style interface */ typedef struct ICallVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( ICall __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( ICall __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( ICall __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCallInfo )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCallInfo )( ICall __RPC_FAR * This, /* [out] */ const void __RPC_FAR *__RPC_FAR *ppIdentity, /* [out] */ IID __RPC_FAR *piid, /* [out] */ DWORD __RPC_FAR *pdwMethod, /* [out] */ HRESULT __RPC_FAR *phr); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Nullify )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Nullify )( ICall __RPC_FAR * This, /* [in] */ HRESULT hr); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetServerHR )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetServerHR )( ICall __RPC_FAR * This, /* [out] */ HRESULT __RPC_FAR *phr); - + END_INTERFACE } ICallVtbl; @@ -1232,7 +1232,7 @@ EXTERN_C const IID IID_ICall; CONST_VTBL struct ICallVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -1263,7 +1263,7 @@ EXTERN_C const IID IID_ICall; -HRESULT STDMETHODCALLTYPE ICall_GetCallInfo_Proxy( +HRESULT STDMETHODCALLTYPE ICall_GetCallInfo_Proxy( ICall __RPC_FAR * This, /* [out] */ const void __RPC_FAR *__RPC_FAR *ppIdentity, /* [out] */ IID __RPC_FAR *piid, @@ -1278,7 +1278,7 @@ void __RPC_STUB ICall_GetCallInfo_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE ICall_Nullify_Proxy( +HRESULT STDMETHODCALLTYPE ICall_Nullify_Proxy( ICall __RPC_FAR * This, /* [in] */ HRESULT hr); @@ -1290,7 +1290,7 @@ void __RPC_STUB ICall_Nullify_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE ICall_GetServerHR_Proxy( +HRESULT STDMETHODCALLTYPE ICall_GetServerHR_Proxy( ICall __RPC_FAR * This, /* [out] */ HRESULT __RPC_FAR *phr); @@ -1310,7 +1310,7 @@ void __RPC_STUB ICall_GetServerHR_Stub( #define __IRpcCall_INTERFACE_DEFINED__ /* interface IRpcCall */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ typedef /* [unique] */ IRpcCall __RPC_FAR *LPRPCCALL; @@ -1318,37 +1318,37 @@ typedef /* [unique] */ IRpcCall __RPC_FAR *LPRPCCALL; EXTERN_C const IID IID_IRpcCall; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001c5-0000-0000-C000-000000000046") IRpcCall : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetRpcOleMessage( + virtual HRESULT STDMETHODCALLTYPE GetRpcOleMessage( /* [out] */ RPCOLEMESSAGE __RPC_FAR *__RPC_FAR *ppMessage) = 0; - + }; - + #else /* C style interface */ typedef struct IRpcCallVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IRpcCall __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IRpcCall __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IRpcCall __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetRpcOleMessage )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetRpcOleMessage )( IRpcCall __RPC_FAR * This, /* [out] */ RPCOLEMESSAGE __RPC_FAR *__RPC_FAR *ppMessage); - + END_INTERFACE } IRpcCallVtbl; @@ -1357,7 +1357,7 @@ EXTERN_C const IID IID_IRpcCall; CONST_VTBL struct IRpcCallVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -1382,7 +1382,7 @@ EXTERN_C const IID IID_IRpcCall; -HRESULT STDMETHODCALLTYPE IRpcCall_GetRpcOleMessage_Proxy( +HRESULT STDMETHODCALLTYPE IRpcCall_GetRpcOleMessage_Proxy( IRpcCall __RPC_FAR * This, /* [out] */ RPCOLEMESSAGE __RPC_FAR *__RPC_FAR *ppMessage); @@ -1399,9 +1399,9 @@ void __RPC_STUB IRpcCall_GetRpcOleMessage_Stub( /* interface __MIDL_itf_contxt_0083 */ -/* [local] */ +/* [local] */ -typedef +typedef enum _CALLSOURCE { CALLSOURCE_CROSSAPT = 0, CALLSOURCE_CROSSCTX = 1 @@ -1416,43 +1416,43 @@ extern RPC_IF_HANDLE __MIDL_itf_contxt_0083_v0_0_s_ifspec; #define __ICallInfo_INTERFACE_DEFINED__ /* interface ICallInfo */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ EXTERN_C const IID IID_ICallInfo; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001dc-0000-0000-C000-000000000046") ICallInfo : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetCallSource( + virtual HRESULT STDMETHODCALLTYPE GetCallSource( /* [out] */ CALLSOURCE __RPC_FAR *pCallSource) = 0; - + }; - + #else /* C style interface */ typedef struct ICallInfoVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( ICallInfo __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( ICallInfo __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( ICallInfo __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCallSource )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCallSource )( ICallInfo __RPC_FAR * This, /* [out] */ CALLSOURCE __RPC_FAR *pCallSource); - + END_INTERFACE } ICallInfoVtbl; @@ -1461,7 +1461,7 @@ EXTERN_C const IID IID_ICallInfo; CONST_VTBL struct ICallInfoVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -1486,7 +1486,7 @@ EXTERN_C const IID IID_ICallInfo; -HRESULT STDMETHODCALLTYPE ICallInfo_GetCallSource_Proxy( +HRESULT STDMETHODCALLTYPE ICallInfo_GetCallSource_Proxy( ICallInfo __RPC_FAR * This, /* [out] */ CALLSOURCE __RPC_FAR *pCallSource); @@ -1506,136 +1506,136 @@ void __RPC_STUB ICallInfo_GetCallSource_Stub( #define __IPolicy_INTERFACE_DEFINED__ /* interface IPolicy */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ EXTERN_C const IID IID_IPolicy; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001c2-0000-0000-C000-000000000046") IPolicy : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE Call( + virtual HRESULT STDMETHODCALLTYPE Call( /* [in] */ ICall __RPC_FAR *pCall) = 0; - - virtual HRESULT STDMETHODCALLTYPE Enter( + + virtual HRESULT STDMETHODCALLTYPE Enter( /* [in] */ ICall __RPC_FAR *pCall) = 0; - - virtual HRESULT STDMETHODCALLTYPE Leave( + + virtual HRESULT STDMETHODCALLTYPE Leave( /* [in] */ ICall __RPC_FAR *pCall) = 0; - - virtual HRESULT STDMETHODCALLTYPE Return( + + virtual HRESULT STDMETHODCALLTYPE Return( /* [in] */ ICall __RPC_FAR *pCall) = 0; - - virtual HRESULT STDMETHODCALLTYPE CallGetSize( + + virtual HRESULT STDMETHODCALLTYPE CallGetSize( /* [in] */ ICall __RPC_FAR *pCall, /* [out] */ ULONG __RPC_FAR *pcb) = 0; - - virtual HRESULT STDMETHODCALLTYPE CallFillBuffer( + + virtual HRESULT STDMETHODCALLTYPE CallFillBuffer( /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [out] */ ULONG __RPC_FAR *pcb) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnterWithBuffer( + + virtual HRESULT STDMETHODCALLTYPE EnterWithBuffer( /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [in] */ ULONG cb) = 0; - - virtual HRESULT STDMETHODCALLTYPE LeaveGetSize( + + virtual HRESULT STDMETHODCALLTYPE LeaveGetSize( /* [in] */ ICall __RPC_FAR *pCall, /* [out] */ ULONG __RPC_FAR *pcb) = 0; - - virtual HRESULT STDMETHODCALLTYPE LeaveFillBuffer( + + virtual HRESULT STDMETHODCALLTYPE LeaveFillBuffer( /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [out] */ ULONG __RPC_FAR *pcb) = 0; - - virtual HRESULT STDMETHODCALLTYPE ReturnWithBuffer( + + virtual HRESULT STDMETHODCALLTYPE ReturnWithBuffer( /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [in] */ ULONG cb) = 0; - + virtual ULONG STDMETHODCALLTYPE AddRefPolicy( void) = 0; - + virtual ULONG STDMETHODCALLTYPE ReleasePolicy( void) = 0; - + }; - + #else /* C style interface */ typedef struct IPolicyVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IPolicy __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IPolicy __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IPolicy __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Call )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Call )( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Enter )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Enter )( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Leave )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Leave )( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Return )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Return )( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CallGetSize )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CallGetSize )( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [out] */ ULONG __RPC_FAR *pcb); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CallFillBuffer )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CallFillBuffer )( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [out] */ ULONG __RPC_FAR *pcb); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnterWithBuffer )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnterWithBuffer )( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [in] */ ULONG cb); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *LeaveGetSize )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *LeaveGetSize )( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [out] */ ULONG __RPC_FAR *pcb); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *LeaveFillBuffer )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *LeaveFillBuffer )( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [out] */ ULONG __RPC_FAR *pcb); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ReturnWithBuffer )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ReturnWithBuffer )( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [in] */ ULONG cb); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRefPolicy )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRefPolicy )( IPolicy __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *ReleasePolicy )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *ReleasePolicy )( IPolicy __RPC_FAR * This); - + END_INTERFACE } IPolicyVtbl; @@ -1644,7 +1644,7 @@ EXTERN_C const IID IID_IPolicy; CONST_VTBL struct IPolicyVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -1702,7 +1702,7 @@ EXTERN_C const IID IID_IPolicy; -HRESULT STDMETHODCALLTYPE IPolicy_Call_Proxy( +HRESULT STDMETHODCALLTYPE IPolicy_Call_Proxy( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); @@ -1714,7 +1714,7 @@ void __RPC_STUB IPolicy_Call_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicy_Enter_Proxy( +HRESULT STDMETHODCALLTYPE IPolicy_Enter_Proxy( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); @@ -1726,7 +1726,7 @@ void __RPC_STUB IPolicy_Enter_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicy_Leave_Proxy( +HRESULT STDMETHODCALLTYPE IPolicy_Leave_Proxy( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); @@ -1738,7 +1738,7 @@ void __RPC_STUB IPolicy_Leave_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicy_Return_Proxy( +HRESULT STDMETHODCALLTYPE IPolicy_Return_Proxy( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); @@ -1750,7 +1750,7 @@ void __RPC_STUB IPolicy_Return_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicy_CallGetSize_Proxy( +HRESULT STDMETHODCALLTYPE IPolicy_CallGetSize_Proxy( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [out] */ ULONG __RPC_FAR *pcb); @@ -1763,7 +1763,7 @@ void __RPC_STUB IPolicy_CallGetSize_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicy_CallFillBuffer_Proxy( +HRESULT STDMETHODCALLTYPE IPolicy_CallFillBuffer_Proxy( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, @@ -1777,7 +1777,7 @@ void __RPC_STUB IPolicy_CallFillBuffer_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicy_EnterWithBuffer_Proxy( +HRESULT STDMETHODCALLTYPE IPolicy_EnterWithBuffer_Proxy( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, @@ -1791,7 +1791,7 @@ void __RPC_STUB IPolicy_EnterWithBuffer_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicy_LeaveGetSize_Proxy( +HRESULT STDMETHODCALLTYPE IPolicy_LeaveGetSize_Proxy( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [out] */ ULONG __RPC_FAR *pcb); @@ -1804,7 +1804,7 @@ void __RPC_STUB IPolicy_LeaveGetSize_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicy_LeaveFillBuffer_Proxy( +HRESULT STDMETHODCALLTYPE IPolicy_LeaveFillBuffer_Proxy( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, @@ -1818,7 +1818,7 @@ void __RPC_STUB IPolicy_LeaveFillBuffer_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicy_ReturnWithBuffer_Proxy( +HRESULT STDMETHODCALLTYPE IPolicy_ReturnWithBuffer_Proxy( IPolicy __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, @@ -1832,7 +1832,7 @@ void __RPC_STUB IPolicy_ReturnWithBuffer_Stub( DWORD *_pdwStubPhase); -ULONG STDMETHODCALLTYPE IPolicy_AddRefPolicy_Proxy( +ULONG STDMETHODCALLTYPE IPolicy_AddRefPolicy_Proxy( IPolicy __RPC_FAR * This); @@ -1843,7 +1843,7 @@ void __RPC_STUB IPolicy_AddRefPolicy_Stub( DWORD *_pdwStubPhase); -ULONG STDMETHODCALLTYPE IPolicy_ReleasePolicy_Proxy( +ULONG STDMETHODCALLTYPE IPolicy_ReleasePolicy_Proxy( IPolicy __RPC_FAR * This); @@ -1862,154 +1862,154 @@ void __RPC_STUB IPolicy_ReleasePolicy_Stub( #define __IPolicyAsync_INTERFACE_DEFINED__ /* interface IPolicyAsync */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ EXTERN_C const IID IID_IPolicyAsync; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001cd-0000-0000-C000-000000000046") IPolicyAsync : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE BeginCallGetSize( + virtual HRESULT STDMETHODCALLTYPE BeginCallGetSize( /* [in] */ ICall __RPC_FAR *pCall, /* [out] */ ULONG __RPC_FAR *pcb) = 0; - - virtual HRESULT STDMETHODCALLTYPE BeginCall( + + virtual HRESULT STDMETHODCALLTYPE BeginCall( /* [in] */ ICall __RPC_FAR *pCall) = 0; - - virtual HRESULT STDMETHODCALLTYPE BeginCallFillBuffer( + + virtual HRESULT STDMETHODCALLTYPE BeginCallFillBuffer( /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [out] */ ULONG __RPC_FAR *pcb) = 0; - - virtual HRESULT STDMETHODCALLTYPE BeginEnter( + + virtual HRESULT STDMETHODCALLTYPE BeginEnter( /* [in] */ ICall __RPC_FAR *pCall) = 0; - - virtual HRESULT STDMETHODCALLTYPE BeginEnterWithBuffer( + + virtual HRESULT STDMETHODCALLTYPE BeginEnterWithBuffer( /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [in] */ ULONG cb) = 0; - - virtual HRESULT STDMETHODCALLTYPE BeginLeave( + + virtual HRESULT STDMETHODCALLTYPE BeginLeave( /* [in] */ ICall __RPC_FAR *pCall) = 0; - - virtual HRESULT STDMETHODCALLTYPE BeginReturn( + + virtual HRESULT STDMETHODCALLTYPE BeginReturn( /* [in] */ ICall __RPC_FAR *pCall) = 0; - - virtual HRESULT STDMETHODCALLTYPE FinishCall( + + virtual HRESULT STDMETHODCALLTYPE FinishCall( /* [in] */ ICall __RPC_FAR *pCall) = 0; - - virtual HRESULT STDMETHODCALLTYPE FinishEnter( + + virtual HRESULT STDMETHODCALLTYPE FinishEnter( /* [in] */ ICall __RPC_FAR *pCall) = 0; - - virtual HRESULT STDMETHODCALLTYPE FinishLeaveGetSize( + + virtual HRESULT STDMETHODCALLTYPE FinishLeaveGetSize( /* [in] */ ICall __RPC_FAR *pCall, /* [out] */ ULONG __RPC_FAR *pcb) = 0; - - virtual HRESULT STDMETHODCALLTYPE FinishLeave( + + virtual HRESULT STDMETHODCALLTYPE FinishLeave( /* [in] */ ICall __RPC_FAR *pCall) = 0; - - virtual HRESULT STDMETHODCALLTYPE FinishLeaveFillBuffer( + + virtual HRESULT STDMETHODCALLTYPE FinishLeaveFillBuffer( /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [out] */ ULONG __RPC_FAR *pcb) = 0; - - virtual HRESULT STDMETHODCALLTYPE FinishReturn( + + virtual HRESULT STDMETHODCALLTYPE FinishReturn( /* [in] */ ICall __RPC_FAR *pCall) = 0; - - virtual HRESULT STDMETHODCALLTYPE FinishReturnWithBuffer( + + virtual HRESULT STDMETHODCALLTYPE FinishReturnWithBuffer( /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [in] */ ULONG cb) = 0; - + }; - + #else /* C style interface */ typedef struct IPolicyAsyncVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IPolicyAsync __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IPolicyAsync __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IPolicyAsync __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginCallGetSize )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginCallGetSize )( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [out] */ ULONG __RPC_FAR *pcb); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginCall )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginCall )( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginCallFillBuffer )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginCallFillBuffer )( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [out] */ ULONG __RPC_FAR *pcb); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginEnter )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginEnter )( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginEnterWithBuffer )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginEnterWithBuffer )( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [in] */ ULONG cb); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginLeave )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginLeave )( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginReturn )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginReturn )( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishCall )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishCall )( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishEnter )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishEnter )( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishLeaveGetSize )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishLeaveGetSize )( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [out] */ ULONG __RPC_FAR *pcb); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishLeave )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishLeave )( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishLeaveFillBuffer )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishLeaveFillBuffer )( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [out] */ ULONG __RPC_FAR *pcb); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishReturn )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishReturn )( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishReturnWithBuffer )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishReturnWithBuffer )( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, /* [in] */ ULONG cb); - + END_INTERFACE } IPolicyAsyncVtbl; @@ -2018,7 +2018,7 @@ EXTERN_C const IID IID_IPolicyAsync; CONST_VTBL struct IPolicyAsyncVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -2082,7 +2082,7 @@ EXTERN_C const IID IID_IPolicyAsync; -HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginCallGetSize_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginCallGetSize_Proxy( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [out] */ ULONG __RPC_FAR *pcb); @@ -2095,7 +2095,7 @@ void __RPC_STUB IPolicyAsync_BeginCallGetSize_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginCall_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginCall_Proxy( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); @@ -2107,7 +2107,7 @@ void __RPC_STUB IPolicyAsync_BeginCall_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginCallFillBuffer_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginCallFillBuffer_Proxy( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, @@ -2121,7 +2121,7 @@ void __RPC_STUB IPolicyAsync_BeginCallFillBuffer_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginEnter_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginEnter_Proxy( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); @@ -2133,7 +2133,7 @@ void __RPC_STUB IPolicyAsync_BeginEnter_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginEnterWithBuffer_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginEnterWithBuffer_Proxy( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, @@ -2147,7 +2147,7 @@ void __RPC_STUB IPolicyAsync_BeginEnterWithBuffer_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginLeave_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginLeave_Proxy( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); @@ -2159,7 +2159,7 @@ void __RPC_STUB IPolicyAsync_BeginLeave_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginReturn_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginReturn_Proxy( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); @@ -2171,7 +2171,7 @@ void __RPC_STUB IPolicyAsync_BeginReturn_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishCall_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishCall_Proxy( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); @@ -2183,7 +2183,7 @@ void __RPC_STUB IPolicyAsync_FinishCall_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishEnter_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishEnter_Proxy( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); @@ -2195,7 +2195,7 @@ void __RPC_STUB IPolicyAsync_FinishEnter_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishLeaveGetSize_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishLeaveGetSize_Proxy( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [out] */ ULONG __RPC_FAR *pcb); @@ -2208,7 +2208,7 @@ void __RPC_STUB IPolicyAsync_FinishLeaveGetSize_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishLeave_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishLeave_Proxy( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); @@ -2220,7 +2220,7 @@ void __RPC_STUB IPolicyAsync_FinishLeave_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishLeaveFillBuffer_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishLeaveFillBuffer_Proxy( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, @@ -2234,7 +2234,7 @@ void __RPC_STUB IPolicyAsync_FinishLeaveFillBuffer_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishReturn_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishReturn_Proxy( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall); @@ -2246,7 +2246,7 @@ void __RPC_STUB IPolicyAsync_FinishReturn_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishReturnWithBuffer_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishReturnWithBuffer_Proxy( IPolicyAsync __RPC_FAR * This, /* [in] */ ICall __RPC_FAR *pCall, /* [in] */ void __RPC_FAR *pvBuf, @@ -2268,47 +2268,47 @@ void __RPC_STUB IPolicyAsync_FinishReturnWithBuffer_Stub( #define __IPolicySet_INTERFACE_DEFINED__ /* interface IPolicySet */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ EXTERN_C const IID IID_IPolicySet; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001c3-0000-0000-C000-000000000046") IPolicySet : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE AddPolicy( + virtual HRESULT STDMETHODCALLTYPE AddPolicy( /* [in] */ ContextEvent ctxEvent, /* [in] */ REFGUID rguid, /* [in] */ IPolicy __RPC_FAR *pPolicy) = 0; - + }; - + #else /* C style interface */ typedef struct IPolicySetVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IPolicySet __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IPolicySet __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IPolicySet __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddPolicy )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddPolicy )( IPolicySet __RPC_FAR * This, /* [in] */ ContextEvent ctxEvent, /* [in] */ REFGUID rguid, /* [in] */ IPolicy __RPC_FAR *pPolicy); - + END_INTERFACE } IPolicySetVtbl; @@ -2317,7 +2317,7 @@ EXTERN_C const IID IID_IPolicySet; CONST_VTBL struct IPolicySetVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -2342,7 +2342,7 @@ EXTERN_C const IID IID_IPolicySet; -HRESULT STDMETHODCALLTYPE IPolicySet_AddPolicy_Proxy( +HRESULT STDMETHODCALLTYPE IPolicySet_AddPolicy_Proxy( IPolicySet __RPC_FAR * This, /* [in] */ ContextEvent ctxEvent, /* [in] */ REFGUID rguid, @@ -2364,53 +2364,53 @@ void __RPC_STUB IPolicySet_AddPolicy_Stub( #define __IComObjIdentity_INTERFACE_DEFINED__ /* interface IComObjIdentity */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ EXTERN_C const IID IID_IComObjIdentity; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001d7-0000-0000-C000-000000000046") IComObjIdentity : public IUnknown { public: virtual BOOL STDMETHODCALLTYPE IsServer( void) = 0; - + virtual BOOL STDMETHODCALLTYPE IsDeactivated( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetIdentity( + + virtual HRESULT STDMETHODCALLTYPE GetIdentity( /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk) = 0; - + }; - + #else /* C style interface */ typedef struct IComObjIdentityVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IComObjIdentity __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IComObjIdentity __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IComObjIdentity __RPC_FAR * This); - - BOOL ( STDMETHODCALLTYPE __RPC_FAR *IsServer )( + + BOOL ( STDMETHODCALLTYPE __RPC_FAR *IsServer )( IComObjIdentity __RPC_FAR * This); - - BOOL ( STDMETHODCALLTYPE __RPC_FAR *IsDeactivated )( + + BOOL ( STDMETHODCALLTYPE __RPC_FAR *IsDeactivated )( IComObjIdentity __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIdentity )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIdentity )( IComObjIdentity __RPC_FAR * This, /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk); - + END_INTERFACE } IComObjIdentityVtbl; @@ -2419,7 +2419,7 @@ EXTERN_C const IID IID_IComObjIdentity; CONST_VTBL struct IComObjIdentityVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -2450,7 +2450,7 @@ EXTERN_C const IID IID_IComObjIdentity; -BOOL STDMETHODCALLTYPE IComObjIdentity_IsServer_Proxy( +BOOL STDMETHODCALLTYPE IComObjIdentity_IsServer_Proxy( IComObjIdentity __RPC_FAR * This); @@ -2461,7 +2461,7 @@ void __RPC_STUB IComObjIdentity_IsServer_Stub( DWORD *_pdwStubPhase); -BOOL STDMETHODCALLTYPE IComObjIdentity_IsDeactivated_Proxy( +BOOL STDMETHODCALLTYPE IComObjIdentity_IsDeactivated_Proxy( IComObjIdentity __RPC_FAR * This); @@ -2472,7 +2472,7 @@ void __RPC_STUB IComObjIdentity_IsDeactivated_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IComObjIdentity_GetIdentity_Proxy( +HRESULT STDMETHODCALLTYPE IComObjIdentity_GetIdentity_Proxy( IComObjIdentity __RPC_FAR * This, /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk); @@ -2492,104 +2492,104 @@ void __RPC_STUB IComObjIdentity_GetIdentity_Stub( #define __IPolicyMaker_INTERFACE_DEFINED__ /* interface IPolicyMaker */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ EXTERN_C const IID IID_IPolicyMaker; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001c4-0000-0000-C000-000000000046") IPolicyMaker : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE AddClientPoliciesToSet( + virtual HRESULT STDMETHODCALLTYPE AddClientPoliciesToSet( /* [in] */ IPolicySet __RPC_FAR *pPS, /* [in] */ IContext __RPC_FAR *pClientContext, /* [in] */ IContext __RPC_FAR *pServerContext) = 0; - - virtual HRESULT STDMETHODCALLTYPE AddEnvoyPoliciesToSet( + + virtual HRESULT STDMETHODCALLTYPE AddEnvoyPoliciesToSet( /* [in] */ IPolicySet __RPC_FAR *pPS, /* [in] */ IContext __RPC_FAR *pClientContext, /* [in] */ IContext __RPC_FAR *pServerContext) = 0; - - virtual HRESULT STDMETHODCALLTYPE AddServerPoliciesToSet( + + virtual HRESULT STDMETHODCALLTYPE AddServerPoliciesToSet( /* [in] */ IPolicySet __RPC_FAR *pPS, /* [in] */ IContext __RPC_FAR *pClientContext, /* [in] */ IContext __RPC_FAR *pServerContext) = 0; - - virtual HRESULT STDMETHODCALLTYPE Freeze( + + virtual HRESULT STDMETHODCALLTYPE Freeze( /* [in] */ IObjContext __RPC_FAR *pObjContext) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateStub( + + virtual HRESULT STDMETHODCALLTYPE CreateStub( /* [in] */ IComObjIdentity __RPC_FAR *pID) = 0; - - virtual HRESULT STDMETHODCALLTYPE DestroyStub( + + virtual HRESULT STDMETHODCALLTYPE DestroyStub( /* [in] */ IComObjIdentity __RPC_FAR *pID) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateProxy( + + virtual HRESULT STDMETHODCALLTYPE CreateProxy( /* [in] */ IComObjIdentity __RPC_FAR *pID) = 0; - - virtual HRESULT STDMETHODCALLTYPE DestroyProxy( + + virtual HRESULT STDMETHODCALLTYPE DestroyProxy( /* [in] */ IComObjIdentity __RPC_FAR *pID) = 0; - + }; - + #else /* C style interface */ typedef struct IPolicyMakerVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IPolicyMaker __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IPolicyMaker __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IPolicyMaker __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddClientPoliciesToSet )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddClientPoliciesToSet )( IPolicyMaker __RPC_FAR * This, /* [in] */ IPolicySet __RPC_FAR *pPS, /* [in] */ IContext __RPC_FAR *pClientContext, /* [in] */ IContext __RPC_FAR *pServerContext); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddEnvoyPoliciesToSet )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddEnvoyPoliciesToSet )( IPolicyMaker __RPC_FAR * This, /* [in] */ IPolicySet __RPC_FAR *pPS, /* [in] */ IContext __RPC_FAR *pClientContext, /* [in] */ IContext __RPC_FAR *pServerContext); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddServerPoliciesToSet )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddServerPoliciesToSet )( IPolicyMaker __RPC_FAR * This, /* [in] */ IPolicySet __RPC_FAR *pPS, /* [in] */ IContext __RPC_FAR *pClientContext, /* [in] */ IContext __RPC_FAR *pServerContext); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Freeze )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Freeze )( IPolicyMaker __RPC_FAR * This, /* [in] */ IObjContext __RPC_FAR *pObjContext); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CreateStub )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CreateStub )( IPolicyMaker __RPC_FAR * This, /* [in] */ IComObjIdentity __RPC_FAR *pID); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DestroyStub )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DestroyStub )( IPolicyMaker __RPC_FAR * This, /* [in] */ IComObjIdentity __RPC_FAR *pID); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CreateProxy )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CreateProxy )( IPolicyMaker __RPC_FAR * This, /* [in] */ IComObjIdentity __RPC_FAR *pID); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DestroyProxy )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DestroyProxy )( IPolicyMaker __RPC_FAR * This, /* [in] */ IComObjIdentity __RPC_FAR *pID); - + END_INTERFACE } IPolicyMakerVtbl; @@ -2598,7 +2598,7 @@ EXTERN_C const IID IID_IPolicyMaker; CONST_VTBL struct IPolicyMakerVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -2644,7 +2644,7 @@ EXTERN_C const IID IID_IPolicyMaker; -HRESULT STDMETHODCALLTYPE IPolicyMaker_AddClientPoliciesToSet_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyMaker_AddClientPoliciesToSet_Proxy( IPolicyMaker __RPC_FAR * This, /* [in] */ IPolicySet __RPC_FAR *pPS, /* [in] */ IContext __RPC_FAR *pClientContext, @@ -2658,7 +2658,7 @@ void __RPC_STUB IPolicyMaker_AddClientPoliciesToSet_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyMaker_AddEnvoyPoliciesToSet_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyMaker_AddEnvoyPoliciesToSet_Proxy( IPolicyMaker __RPC_FAR * This, /* [in] */ IPolicySet __RPC_FAR *pPS, /* [in] */ IContext __RPC_FAR *pClientContext, @@ -2672,7 +2672,7 @@ void __RPC_STUB IPolicyMaker_AddEnvoyPoliciesToSet_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyMaker_AddServerPoliciesToSet_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyMaker_AddServerPoliciesToSet_Proxy( IPolicyMaker __RPC_FAR * This, /* [in] */ IPolicySet __RPC_FAR *pPS, /* [in] */ IContext __RPC_FAR *pClientContext, @@ -2686,7 +2686,7 @@ void __RPC_STUB IPolicyMaker_AddServerPoliciesToSet_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyMaker_Freeze_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyMaker_Freeze_Proxy( IPolicyMaker __RPC_FAR * This, /* [in] */ IObjContext __RPC_FAR *pObjContext); @@ -2698,7 +2698,7 @@ void __RPC_STUB IPolicyMaker_Freeze_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyMaker_CreateStub_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyMaker_CreateStub_Proxy( IPolicyMaker __RPC_FAR * This, /* [in] */ IComObjIdentity __RPC_FAR *pID); @@ -2710,7 +2710,7 @@ void __RPC_STUB IPolicyMaker_CreateStub_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyMaker_DestroyStub_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyMaker_DestroyStub_Proxy( IPolicyMaker __RPC_FAR * This, /* [in] */ IComObjIdentity __RPC_FAR *pID); @@ -2722,7 +2722,7 @@ void __RPC_STUB IPolicyMaker_DestroyStub_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyMaker_CreateProxy_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyMaker_CreateProxy_Proxy( IPolicyMaker __RPC_FAR * This, /* [in] */ IComObjIdentity __RPC_FAR *pID); @@ -2734,7 +2734,7 @@ void __RPC_STUB IPolicyMaker_CreateProxy_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IPolicyMaker_DestroyProxy_Proxy( +HRESULT STDMETHODCALLTYPE IPolicyMaker_DestroyProxy_Proxy( IPolicyMaker __RPC_FAR * This, /* [in] */ IComObjIdentity __RPC_FAR *pID); @@ -2754,43 +2754,43 @@ void __RPC_STUB IPolicyMaker_DestroyProxy_Stub( #define __IExceptionNotification_INTERFACE_DEFINED__ /* interface IExceptionNotification */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ EXTERN_C const IID IID_IExceptionNotification; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001db-0000-0000-C000-000000000046") IExceptionNotification : public IUnknown { public: - virtual void STDMETHODCALLTYPE ServerException( + virtual void STDMETHODCALLTYPE ServerException( /* [in] */ void __RPC_FAR *pExcepPtrs) = 0; - + }; - + #else /* C style interface */ typedef struct IExceptionNotificationVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IExceptionNotification __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IExceptionNotification __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IExceptionNotification __RPC_FAR * This); - - void ( STDMETHODCALLTYPE __RPC_FAR *ServerException )( + + void ( STDMETHODCALLTYPE __RPC_FAR *ServerException )( IExceptionNotification __RPC_FAR * This, /* [in] */ void __RPC_FAR *pExcepPtrs); - + END_INTERFACE } IExceptionNotificationVtbl; @@ -2799,7 +2799,7 @@ EXTERN_C const IID IID_IExceptionNotification; CONST_VTBL struct IExceptionNotificationVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -2824,7 +2824,7 @@ EXTERN_C const IID IID_IExceptionNotification; -void STDMETHODCALLTYPE IExceptionNotification_ServerException_Proxy( +void STDMETHODCALLTYPE IExceptionNotification_ServerException_Proxy( IExceptionNotification __RPC_FAR * This, /* [in] */ void __RPC_FAR *pExcepPtrs); @@ -2844,74 +2844,74 @@ void __RPC_STUB IExceptionNotification_ServerException_Stub( #define __IMarshalEnvoy_INTERFACE_DEFINED__ /* interface IMarshalEnvoy */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ EXTERN_C const IID IID_IMarshalEnvoy; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001c8-0000-0000-C000-000000000046") IMarshalEnvoy : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetEnvoyUnmarshalClass( + virtual HRESULT STDMETHODCALLTYPE GetEnvoyUnmarshalClass( /* [in] */ DWORD dwDestContext, /* [out] */ CLSID __RPC_FAR *pClsid) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetEnvoySizeMax( + + virtual HRESULT STDMETHODCALLTYPE GetEnvoySizeMax( /* [in] */ DWORD dwDestContext, /* [out] */ DWORD __RPC_FAR *pcb) = 0; - - virtual HRESULT STDMETHODCALLTYPE MarshalEnvoy( + + virtual HRESULT STDMETHODCALLTYPE MarshalEnvoy( /* [in] */ IStream __RPC_FAR *pStream, /* [in] */ DWORD dwDestContext) = 0; - - virtual HRESULT STDMETHODCALLTYPE UnmarshalEnvoy( + + virtual HRESULT STDMETHODCALLTYPE UnmarshalEnvoy( /* [in] */ IStream __RPC_FAR *pStream, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppunk) = 0; - + }; - + #else /* C style interface */ typedef struct IMarshalEnvoyVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IMarshalEnvoy __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IMarshalEnvoy __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IMarshalEnvoy __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetEnvoyUnmarshalClass )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetEnvoyUnmarshalClass )( IMarshalEnvoy __RPC_FAR * This, /* [in] */ DWORD dwDestContext, /* [out] */ CLSID __RPC_FAR *pClsid); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetEnvoySizeMax )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetEnvoySizeMax )( IMarshalEnvoy __RPC_FAR * This, /* [in] */ DWORD dwDestContext, /* [out] */ DWORD __RPC_FAR *pcb); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *MarshalEnvoy )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *MarshalEnvoy )( IMarshalEnvoy __RPC_FAR * This, /* [in] */ IStream __RPC_FAR *pStream, /* [in] */ DWORD dwDestContext); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *UnmarshalEnvoy )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *UnmarshalEnvoy )( IMarshalEnvoy __RPC_FAR * This, /* [in] */ IStream __RPC_FAR *pStream, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppunk); - + END_INTERFACE } IMarshalEnvoyVtbl; @@ -2920,7 +2920,7 @@ EXTERN_C const IID IID_IMarshalEnvoy; CONST_VTBL struct IMarshalEnvoyVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -2954,7 +2954,7 @@ EXTERN_C const IID IID_IMarshalEnvoy; -HRESULT STDMETHODCALLTYPE IMarshalEnvoy_GetEnvoyUnmarshalClass_Proxy( +HRESULT STDMETHODCALLTYPE IMarshalEnvoy_GetEnvoyUnmarshalClass_Proxy( IMarshalEnvoy __RPC_FAR * This, /* [in] */ DWORD dwDestContext, /* [out] */ CLSID __RPC_FAR *pClsid); @@ -2967,7 +2967,7 @@ void __RPC_STUB IMarshalEnvoy_GetEnvoyUnmarshalClass_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IMarshalEnvoy_GetEnvoySizeMax_Proxy( +HRESULT STDMETHODCALLTYPE IMarshalEnvoy_GetEnvoySizeMax_Proxy( IMarshalEnvoy __RPC_FAR * This, /* [in] */ DWORD dwDestContext, /* [out] */ DWORD __RPC_FAR *pcb); @@ -2980,7 +2980,7 @@ void __RPC_STUB IMarshalEnvoy_GetEnvoySizeMax_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IMarshalEnvoy_MarshalEnvoy_Proxy( +HRESULT STDMETHODCALLTYPE IMarshalEnvoy_MarshalEnvoy_Proxy( IMarshalEnvoy __RPC_FAR * This, /* [in] */ IStream __RPC_FAR *pStream, /* [in] */ DWORD dwDestContext); @@ -2993,7 +2993,7 @@ void __RPC_STUB IMarshalEnvoy_MarshalEnvoy_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IMarshalEnvoy_UnmarshalEnvoy_Proxy( +HRESULT STDMETHODCALLTYPE IMarshalEnvoy_UnmarshalEnvoy_Proxy( IMarshalEnvoy __RPC_FAR * This, /* [in] */ IStream __RPC_FAR *pStream, /* [in] */ REFIID riid, @@ -3015,58 +3015,58 @@ void __RPC_STUB IMarshalEnvoy_UnmarshalEnvoy_Stub( #define __IWrapperInfo_INTERFACE_DEFINED__ /* interface IWrapperInfo */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ EXTERN_C const IID IID_IWrapperInfo; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("5052f924-7ab8-11d3-b93f-00c04f990176") IWrapperInfo : public IUnknown { public: - virtual void STDMETHODCALLTYPE SetMapping( + virtual void STDMETHODCALLTYPE SetMapping( void __RPC_FAR *pv) = 0; - + virtual void __RPC_FAR *STDMETHODCALLTYPE GetMapping( void) = 0; - + virtual IObjContext __RPC_FAR *STDMETHODCALLTYPE GetServerObjectContext( void) = 0; - + virtual IUnknown __RPC_FAR *STDMETHODCALLTYPE GetServerObject( void) = 0; - + }; - + #else /* C style interface */ typedef struct IWrapperInfoVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IWrapperInfo __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IWrapperInfo __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IWrapperInfo __RPC_FAR * This); - - void ( STDMETHODCALLTYPE __RPC_FAR *SetMapping )( + + void ( STDMETHODCALLTYPE __RPC_FAR *SetMapping )( IWrapperInfo __RPC_FAR * This, void __RPC_FAR *pv); - - void __RPC_FAR *( STDMETHODCALLTYPE __RPC_FAR *GetMapping )( + + void __RPC_FAR *( STDMETHODCALLTYPE __RPC_FAR *GetMapping )( IWrapperInfo __RPC_FAR * This); - - IObjContext __RPC_FAR *( STDMETHODCALLTYPE __RPC_FAR *GetServerObjectContext )( + + IObjContext __RPC_FAR *( STDMETHODCALLTYPE __RPC_FAR *GetServerObjectContext )( IWrapperInfo __RPC_FAR * This); - - IUnknown __RPC_FAR *( STDMETHODCALLTYPE __RPC_FAR *GetServerObject )( + + IUnknown __RPC_FAR *( STDMETHODCALLTYPE __RPC_FAR *GetServerObject )( IWrapperInfo __RPC_FAR * This); - + END_INTERFACE } IWrapperInfoVtbl; @@ -3075,7 +3075,7 @@ EXTERN_C const IID IID_IWrapperInfo; CONST_VTBL struct IWrapperInfoVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -3109,7 +3109,7 @@ EXTERN_C const IID IID_IWrapperInfo; -void STDMETHODCALLTYPE IWrapperInfo_SetMapping_Proxy( +void STDMETHODCALLTYPE IWrapperInfo_SetMapping_Proxy( IWrapperInfo __RPC_FAR * This, void __RPC_FAR *pv); @@ -3121,7 +3121,7 @@ void __RPC_STUB IWrapperInfo_SetMapping_Stub( DWORD *_pdwStubPhase); -void __RPC_FAR *STDMETHODCALLTYPE IWrapperInfo_GetMapping_Proxy( +void __RPC_FAR *STDMETHODCALLTYPE IWrapperInfo_GetMapping_Proxy( IWrapperInfo __RPC_FAR * This); @@ -3132,7 +3132,7 @@ void __RPC_STUB IWrapperInfo_GetMapping_Stub( DWORD *_pdwStubPhase); -IObjContext __RPC_FAR *STDMETHODCALLTYPE IWrapperInfo_GetServerObjectContext_Proxy( +IObjContext __RPC_FAR *STDMETHODCALLTYPE IWrapperInfo_GetServerObjectContext_Proxy( IWrapperInfo __RPC_FAR * This); @@ -3143,7 +3143,7 @@ void __RPC_STUB IWrapperInfo_GetServerObjectContext_Stub( DWORD *_pdwStubPhase); -IUnknown __RPC_FAR *STDMETHODCALLTYPE IWrapperInfo_GetServerObject_Proxy( +IUnknown __RPC_FAR *STDMETHODCALLTYPE IWrapperInfo_GetServerObject_Proxy( IWrapperInfo __RPC_FAR * This); @@ -3159,7 +3159,7 @@ void __RPC_STUB IWrapperInfo_GetServerObject_Stub( /* interface __MIDL_itf_contxt_0092 */ -/* [local] */ +/* [local] */ typedef DWORD APARTMENTID; @@ -3173,64 +3173,64 @@ extern RPC_IF_HANDLE __MIDL_itf_contxt_0092_v0_0_s_ifspec; #define __IComThreadingInfo_INTERFACE_DEFINED__ /* interface IComThreadingInfo */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ EXTERN_C const IID IID_IComThreadingInfo; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001ce-0000-0000-C000-000000000046") IComThreadingInfo : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetCurrentApartmentType( + virtual HRESULT STDMETHODCALLTYPE GetCurrentApartmentType( /* [out] */ APTTYPE __RPC_FAR *pAptType) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadType( + + virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadType( /* [out] */ THDTYPE __RPC_FAR *pThreadType) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCurrentLogicalThreadId( + + virtual HRESULT STDMETHODCALLTYPE GetCurrentLogicalThreadId( /* [out] */ GUID __RPC_FAR *pguidLogicalThreadId) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetCurrentLogicalThreadId( + + virtual HRESULT STDMETHODCALLTYPE SetCurrentLogicalThreadId( /* [in] */ REFGUID rguid) = 0; - + }; - + #else /* C style interface */ typedef struct IComThreadingInfoVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IComThreadingInfo __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IComThreadingInfo __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IComThreadingInfo __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCurrentApartmentType )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCurrentApartmentType )( IComThreadingInfo __RPC_FAR * This, /* [out] */ APTTYPE __RPC_FAR *pAptType); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCurrentThreadType )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCurrentThreadType )( IComThreadingInfo __RPC_FAR * This, /* [out] */ THDTYPE __RPC_FAR *pThreadType); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCurrentLogicalThreadId )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCurrentLogicalThreadId )( IComThreadingInfo __RPC_FAR * This, /* [out] */ GUID __RPC_FAR *pguidLogicalThreadId); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetCurrentLogicalThreadId )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetCurrentLogicalThreadId )( IComThreadingInfo __RPC_FAR * This, /* [in] */ REFGUID rguid); - + END_INTERFACE } IComThreadingInfoVtbl; @@ -3239,7 +3239,7 @@ EXTERN_C const IID IID_IComThreadingInfo; CONST_VTBL struct IComThreadingInfoVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -3273,7 +3273,7 @@ EXTERN_C const IID IID_IComThreadingInfo; -HRESULT STDMETHODCALLTYPE IComThreadingInfo_GetCurrentApartmentType_Proxy( +HRESULT STDMETHODCALLTYPE IComThreadingInfo_GetCurrentApartmentType_Proxy( IComThreadingInfo __RPC_FAR * This, /* [out] */ APTTYPE __RPC_FAR *pAptType); @@ -3285,7 +3285,7 @@ void __RPC_STUB IComThreadingInfo_GetCurrentApartmentType_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IComThreadingInfo_GetCurrentThreadType_Proxy( +HRESULT STDMETHODCALLTYPE IComThreadingInfo_GetCurrentThreadType_Proxy( IComThreadingInfo __RPC_FAR * This, /* [out] */ THDTYPE __RPC_FAR *pThreadType); @@ -3297,7 +3297,7 @@ void __RPC_STUB IComThreadingInfo_GetCurrentThreadType_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IComThreadingInfo_GetCurrentLogicalThreadId_Proxy( +HRESULT STDMETHODCALLTYPE IComThreadingInfo_GetCurrentLogicalThreadId_Proxy( IComThreadingInfo __RPC_FAR * This, /* [out] */ GUID __RPC_FAR *pguidLogicalThreadId); @@ -3309,7 +3309,7 @@ void __RPC_STUB IComThreadingInfo_GetCurrentLogicalThreadId_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IComThreadingInfo_SetCurrentLogicalThreadId_Proxy( +HRESULT STDMETHODCALLTYPE IComThreadingInfo_SetCurrentLogicalThreadId_Proxy( IComThreadingInfo __RPC_FAR * This, /* [in] */ REFGUID rguid); @@ -3329,50 +3329,50 @@ void __RPC_STUB IComThreadingInfo_SetCurrentLogicalThreadId_Stub( #define __IComDispatchInfo_INTERFACE_DEFINED__ /* interface IComDispatchInfo */ -/* [unique][uuid][object][local] */ +/* [unique][uuid][object][local] */ EXTERN_C const IID IID_IComDispatchInfo; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("000001d9-0000-0000-C000-000000000046") IComDispatchInfo : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE EnableComInits( + virtual HRESULT STDMETHODCALLTYPE EnableComInits( /* [out] */ void __RPC_FAR *__RPC_FAR *ppvCookie) = 0; - - virtual HRESULT STDMETHODCALLTYPE DisableComInits( + + virtual HRESULT STDMETHODCALLTYPE DisableComInits( /* [in] */ void __RPC_FAR *pvCookie) = 0; - + }; - + #else /* C style interface */ typedef struct IComDispatchInfoVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( IComDispatchInfo __RPC_FAR * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( IComDispatchInfo __RPC_FAR * This); - - ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( IComDispatchInfo __RPC_FAR * This); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnableComInits )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnableComInits )( IComDispatchInfo __RPC_FAR * This, /* [out] */ void __RPC_FAR *__RPC_FAR *ppvCookie); - - HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DisableComInits )( + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DisableComInits )( IComDispatchInfo __RPC_FAR * This, /* [in] */ void __RPC_FAR *pvCookie); - + END_INTERFACE } IComDispatchInfoVtbl; @@ -3381,7 +3381,7 @@ EXTERN_C const IID IID_IComDispatchInfo; CONST_VTBL struct IComDispatchInfoVtbl __RPC_FAR *lpVtbl; }; - + #ifdef COBJMACROS @@ -3409,7 +3409,7 @@ EXTERN_C const IID IID_IComDispatchInfo; -HRESULT STDMETHODCALLTYPE IComDispatchInfo_EnableComInits_Proxy( +HRESULT STDMETHODCALLTYPE IComDispatchInfo_EnableComInits_Proxy( IComDispatchInfo __RPC_FAR * This, /* [out] */ void __RPC_FAR *__RPC_FAR *ppvCookie); @@ -3421,7 +3421,7 @@ void __RPC_STUB IComDispatchInfo_EnableComInits_Stub( DWORD *_pdwStubPhase); -HRESULT STDMETHODCALLTYPE IComDispatchInfo_DisableComInits_Proxy( +HRESULT STDMETHODCALLTYPE IComDispatchInfo_DisableComInits_Proxy( IComDispatchInfo __RPC_FAR * This, /* [in] */ void __RPC_FAR *pvCookie); @@ -3438,7 +3438,7 @@ void __RPC_STUB IComDispatchInfo_DisableComInits_Stub( /* interface __MIDL_itf_contxt_0094 */ -/* [local] */ +/* [local] */ typedef DWORD HActivator; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/cor.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/cor.h index 034801b..2ed0cc5 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/cor.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/cor.h @@ -131,7 +131,7 @@ typedef UNALIGNED void const *UVCP_CONSTANT; // Constant for connection id and task id #define INVALID_CONNECTION_ID 0x0 -#define INVALID_TASK_ID 0x0 +#define INVALID_TASK_ID 0x0 #define MAX_CONNECTION_NAME MAX_PATH @@ -141,22 +141,11 @@ typedef UNALIGNED void const *UVCP_CONSTANT; #define MAIN_CLR_DLL_NAME_W MAKEDLLNAME_W(MAIN_CLR_MODULE_NAME_W) #define MAIN_CLR_DLL_NAME_A MAKEDLLNAME_A(MAIN_CLR_MODULE_NAME_A) - -#define MSCOREE_SHIM_W MAIN_CLR_DLL_NAME_W -#define MSCOREE_SHIM_A MAIN_CLR_DLL_NAME_A +#define TARGET_MAIN_CLR_DLL_NAME_W MAKE_TARGET_DLLNAME_W(MAIN_CLR_MODULE_NAME_W) +#define TARGET_MAIN_CLR_DLL_NAME_A MAKE_TARGET_DLLNAME_A(MAIN_CLR_MODULE_NAME_A) #define SWITCHOUT_HANDLE_VALUE ((HANDLE)(LONG_PTR)-2) -// -// CoInitializeEE flags. -// -typedef enum tagCOINITEE -{ - COINITEE_DEFAULT = 0x0, // Default initialization mode. - COINITEE_DLL = 0x1, // Initialization mode for loading DLL. - COINITEE_MAIN = 0x2 // Initialize prior to entering the main routine -} COINITIEE; - //***************************************************************************** //***************************************************************************** // @@ -166,7 +155,7 @@ typedef enum tagCOINITEE //***************************************************************************** -// +// #ifndef _WINDOWS_UPDATES_ #include #endif // updates @@ -284,14 +273,14 @@ DECLARE_INTERFACE_(IMetaDataEmit, IUnknown) STDMETHOD(DefineTypeDef)( // S_OK or error. LPCWSTR szTypeDef, // [IN] Name of TypeDef DWORD dwTypeDefFlags, // [IN] CustomAttribute flags - mdToken tkExtends, // [IN] extends this TypeDef or typeref + mdToken tkExtends, // [IN] extends this TypeDef or typeref mdToken rtkImplements[], // [IN] Implements interfaces mdTypeDef *ptd) PURE; // [OUT] Put TypeDef token here STDMETHOD(DefineNestedType)( // S_OK or error. LPCWSTR szTypeDef, // [IN] Name of TypeDef DWORD dwTypeDefFlags, // [IN] CustomAttribute flags - mdToken tkExtends, // [IN] extends this TypeDef or typeref + mdToken tkExtends, // [IN] extends this TypeDef or typeref mdToken rtkImplements[], // [IN] Implements interfaces mdTypeDef tdEncloser, // [IN] TypeDef token of the enclosing type. mdTypeDef *ptd) PURE; // [OUT] Put TypeDef token here @@ -299,11 +288,11 @@ DECLARE_INTERFACE_(IMetaDataEmit, IUnknown) STDMETHOD(SetHandler)( // S_OK. IUnknown *pUnk) PURE; // [IN] The new error handler. - STDMETHOD(DefineMethod)( // S_OK or error. + STDMETHOD(DefineMethod)( // S_OK or error. mdTypeDef td, // Parent TypeDef LPCWSTR szName, // Name of member DWORD dwMethodFlags, // Member attributes - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob ULONG ulCodeRVA, DWORD dwImplFlags, @@ -331,7 +320,7 @@ DECLARE_INTERFACE_(IMetaDataEmit, IUnknown) STDMETHOD(DefineMemberRef)( // S_OK or error mdToken tkImport, // [IN] ClassRef or ClassDef importing a member. LPCWSTR szName, // [IN] member's name - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob mdMemberRef *pmr) PURE; // [OUT] memberref token @@ -346,19 +335,19 @@ DECLARE_INTERFACE_(IMetaDataEmit, IUnknown) mdMemberRef *pmr) PURE; // [OUT] Put member ref here. STDMETHOD(DefineEvent) ( - mdTypeDef td, // [IN] the class/interface on which the event is being defined + mdTypeDef td, // [IN] the class/interface on which the event is being defined LPCWSTR szEvent, // [IN] Name of the event DWORD dwEventFlags, // [IN] CorEventAttr - mdToken tkEventType, // [IN] a reference (mdTypeRef or mdTypeRef) to the Event class - mdMethodDef mdAddOn, // [IN] required add method + mdToken tkEventType, // [IN] a reference (mdTypeRef or mdTypeRef) to the Event class + mdMethodDef mdAddOn, // [IN] required add method mdMethodDef mdRemoveOn, // [IN] required remove method mdMethodDef mdFire, // [IN] optional fire method mdMethodDef rmdOtherMethods[], // [IN] optional array of other methods associate with the event - mdEvent *pmdEvent) PURE; // [OUT] output event token + mdEvent *pmdEvent) PURE; // [OUT] output event token STDMETHOD(SetClassLayout) ( - mdTypeDef td, // [IN] typedef - DWORD dwPackSize, // [IN] packing size specified as 1, 2, 4, 8, or 16 + mdTypeDef td, // [IN] typedef + DWORD dwPackSize, // [IN] packing size specified as 1, 2, 4, 8, or 16 COR_FIELD_OFFSET rFieldOffsets[], // [IN] array of layout specification ULONG ulClassSize) PURE; // [IN] size of the class @@ -374,11 +363,11 @@ DECLARE_INTERFACE_(IMetaDataEmit, IUnknown) mdToken tk) PURE; // [IN] given a fieldDef or paramDef token STDMETHOD(DefinePermissionSet) ( - mdToken tk, // [IN] the object to be decorated. + mdToken tk, // [IN] the object to be decorated. DWORD dwAction, // [IN] CorDeclSecurity. void const *pvPermission, // [IN] permission blob. - ULONG cbPermission, // [IN] count of bytes of pvPermission. - mdPermission *ppm) PURE; // [OUT] returned permission token. + ULONG cbPermission, // [IN] count of bytes of pvPermission. + mdPermission *ppm) PURE; // [OUT] returned permission token. STDMETHOD(SetRVA)( // S_OK or error. mdMethodDef md, // [IN] Method for which to set offset @@ -386,7 +375,7 @@ DECLARE_INTERFACE_(IMetaDataEmit, IUnknown) STDMETHOD(GetTokenFromSig)( // S_OK or error. PCCOR_SIGNATURE pvSig, // [IN] Signature to define. - ULONG cbSig, // [IN] Size of signature data. + ULONG cbSig, // [IN] Size of signature data. mdSignature *pmsig) PURE; // [OUT] returned signature token. STDMETHOD(DefineModuleRef)( // S_OK or error. @@ -396,11 +385,11 @@ DECLARE_INTERFACE_(IMetaDataEmit, IUnknown) // @FUTURE: This should go away once everyone starts using SetMemberRefProps. STDMETHOD(SetParent)( // S_OK or error. mdMemberRef mr, // [IN] Token for the ref to be fixed up. - mdToken tk) PURE; // [IN] The ref parent. + mdToken tk) PURE; // [IN] The ref parent. STDMETHOD(GetTokenFromTypeSpec)( // S_OK or error. PCCOR_SIGNATURE pvSig, // [IN] TypeSpec Signature to define. - ULONG cbSig, // [IN] Size of signature data. + ULONG cbSig, // [IN] Size of signature data. mdTypeSpec *ptypespec) PURE; // [OUT] returned TypeSpec token. STDMETHOD(SaveToMemory)( // S_OK or error. @@ -471,35 +460,35 @@ DECLARE_INTERFACE_(IMetaDataEmit, IUnknown) void const *pCustomAttribute, // [IN] The custom value data. ULONG cbCustomAttribute) PURE;// [IN] The custom value data length. - STDMETHOD(DefineField)( // S_OK or error. + STDMETHOD(DefineField)( // S_OK or error. mdTypeDef td, // Parent TypeDef LPCWSTR szName, // Name of member DWORD dwFieldFlags, // Member attributes - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_* void const *pValue, // [IN] constant value ULONG cchValue, // [IN] size of constant value (string, in wide chars). mdFieldDef *pmd) PURE; // [OUT] Put member token here - STDMETHOD(DefineProperty)( + STDMETHOD(DefineProperty)( mdTypeDef td, // [IN] the class/interface on which the property is being defined LPCWSTR szProperty, // [IN] Name of the property - DWORD dwPropFlags, // [IN] CorPropertyAttr - PCCOR_SIGNATURE pvSig, // [IN] the required type signature - ULONG cbSig, // [IN] the size of the type signature blob + DWORD dwPropFlags, // [IN] CorPropertyAttr + PCCOR_SIGNATURE pvSig, // [IN] the required type signature + ULONG cbSig, // [IN] the size of the type signature blob DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_* void const *pValue, // [IN] constant value ULONG cchValue, // [IN] size of constant value (string, in wide chars). - mdMethodDef mdSetter, // [IN] optional setter of the property - mdMethodDef mdGetter, // [IN] optional getter of the property + mdMethodDef mdSetter, // [IN] optional setter of the property + mdMethodDef mdGetter, // [IN] optional getter of the property mdMethodDef rmdOtherMethods[], // [IN] an optional array of other methods mdProperty *pmdProp) PURE; // [OUT] output property token STDMETHOD(DefineParam)( mdMethodDef md, // [IN] Owning method - ULONG ulParamSeq, // [IN] Which param - LPCWSTR szName, // [IN] Optional param name + ULONG ulParamSeq, // [IN] Which param + LPCWSTR szName, // [IN] Optional param name DWORD dwParamFlags, // [IN] Optional param flags DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_* void const *pValue, // [IN] constant value @@ -555,7 +544,7 @@ DECLARE_INTERFACE_(IMetaDataEmit, IUnknown) ULONG *pcbTranslatedSig) PURE;// [OUT] count of bytes in the translated signature STDMETHOD(SetMethodImplFlags)( // [IN] S_OK or error. - mdMethodDef md, // [IN] Method for which to set ImplFlags + mdMethodDef md, // [IN] Method for which to set ImplFlags DWORD dwImplFlags) PURE; STDMETHOD(SetFieldRVA)( // [IN] S_OK or error. @@ -586,7 +575,7 @@ DECLARE_INTERFACE_(IMetaDataEmit2, IMetaDataEmit) { STDMETHOD(DefineMethodSpec)( mdToken tkParent, // [IN] MethodDef or MemberRef - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob mdMethodSpec *pmi) PURE; // [OUT] method instantiation token @@ -621,7 +610,7 @@ DECLARE_INTERFACE_(IMetaDataEmit2, IMetaDataEmit) LPCWSTR szName, // [IN] Optional name DWORD reserved, // [IN] For future use (e.g. non-type parameters) mdToken rtkConstraints[]) PURE;// [IN] Array of type constraints (TypeDef,TypeRef,TypeSpec) - + STDMETHOD(ResetENCLog)() PURE; // S_OK or error. }; @@ -676,7 +665,7 @@ DECLARE_INTERFACE_(IMetaDataImport, IUnknown) mdInterfaceImpl iiImpl, // [IN] InterfaceImpl token. mdTypeDef *pClass, // [OUT] Put implementing class token here. mdToken *ptkIface) PURE; // [OUT] Put implemented interface token here. - + STDMETHOD(GetTypeRefProps)( // S_OK or error. mdTypeRef tr, // [IN] TypeRef token. mdToken *ptkResolutionScope, // [OUT] Resolution scope, ModuleRef or AssemblyRef. @@ -687,7 +676,7 @@ DECLARE_INTERFACE_(IMetaDataImport, IUnknown) STDMETHOD(ResolveTypeRef)(mdTypeRef tr, REFIID riid, IUnknown **ppIScope, mdTypeDef *ptd) PURE; - STDMETHOD(EnumMembers)( // S_OK, S_FALSE, or error. + STDMETHOD(EnumMembers)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdTypeDef cl, // [IN] TypeDef to scope the enumeration. mdToken rMembers[], // [OUT] Put MemberDefs here. @@ -702,7 +691,7 @@ DECLARE_INTERFACE_(IMetaDataImport, IUnknown) ULONG cMax, // [IN] Max MemberDefs to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. - STDMETHOD(EnumMethods)( // S_OK, S_FALSE, or error. + STDMETHOD(EnumMethods)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdTypeDef cl, // [IN] TypeDef to scope the enumeration. mdMethodDef rMethods[], // [OUT] Put MethodDefs here. @@ -733,14 +722,14 @@ DECLARE_INTERFACE_(IMetaDataImport, IUnknown) ULONG *pcTokens) PURE; // [OUT] Put # put here. - STDMETHOD(EnumParams)( // S_OK, S_FALSE, or error. + STDMETHOD(EnumParams)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdMethodDef mb, // [IN] MethodDef to scope the enumeration. + mdMethodDef mb, // [IN] MethodDef to scope the enumeration. mdParamDef rParams[], // [OUT] Put ParamDefs here. ULONG cMax, // [IN] Max ParamDefs to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. - STDMETHOD(EnumMemberRefs)( // S_OK, S_FALSE, or error. + STDMETHOD(EnumMemberRefs)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdToken tkParent, // [IN] Parent token to scope the enumeration. mdMemberRef rMemberRefs[], // [OUT] Put MemberRefs here. @@ -755,49 +744,49 @@ DECLARE_INTERFACE_(IMetaDataImport, IUnknown) ULONG cMax, // [IN] Max tokens to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. - STDMETHOD(EnumPermissionSets)( // S_OK, S_FALSE, or error. + STDMETHOD(EnumPermissionSets)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdToken tk, // [IN] if !NIL, token to scope the enumeration. DWORD dwActions, // [IN] if !0, return only these actions. mdPermission rPermission[], // [OUT] Put Permissions here. - ULONG cMax, // [IN] Max Permissions to put. + ULONG cMax, // [IN] Max Permissions to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(FindMember)( mdTypeDef td, // [IN] given typedef - LPCWSTR szName, // [IN] member name - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + LPCWSTR szName, // [IN] member name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob - mdToken *pmb) PURE; // [OUT] matching memberdef + mdToken *pmb) PURE; // [OUT] matching memberdef STDMETHOD(FindMethod)( mdTypeDef td, // [IN] given typedef - LPCWSTR szName, // [IN] member name - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + LPCWSTR szName, // [IN] member name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob - mdMethodDef *pmb) PURE; // [OUT] matching memberdef + mdMethodDef *pmb) PURE; // [OUT] matching memberdef STDMETHOD(FindField)( mdTypeDef td, // [IN] given typedef - LPCWSTR szName, // [IN] member name - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + LPCWSTR szName, // [IN] member name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob - mdFieldDef *pmb) PURE; // [OUT] matching memberdef + mdFieldDef *pmb) PURE; // [OUT] matching memberdef STDMETHOD(FindMemberRef)( mdTypeRef td, // [IN] given typeRef - LPCWSTR szName, // [IN] member name - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + LPCWSTR szName, // [IN] member name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob - mdMemberRef *pmr) PURE; // [OUT] matching memberref + mdMemberRef *pmr) PURE; // [OUT] matching memberref - STDMETHOD (GetMethodProps)( + STDMETHOD (GetMethodProps)( mdMethodDef mb, // The method for which to get props. - mdTypeDef *pClass, // Put method's class here. + mdTypeDef *pClass, // Put method's class here. _Out_writes_to_opt_(cchMethod, *pchMethod) LPWSTR szMethod, // Put method's name here. ULONG cchMethod, // Size of szMethod buffer in wide chars. - ULONG *pchMethod, // Put actual size here + ULONG *pchMethod, // Put actual size here DWORD *pdwAttr, // Put flags here. PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data ULONG *pcbSigBlob, // [OUT] actual size of signature blob @@ -805,8 +794,8 @@ DECLARE_INTERFACE_(IMetaDataImport, IUnknown) DWORD *pdwImplFlags) PURE; // [OUT] Impl. Flags STDMETHOD(GetMemberRefProps)( // S_OK or error. - mdMemberRef mr, // [IN] given memberref - mdToken *ptk, // [OUT] Put classref or classdef here. + mdMemberRef mr, // [IN] given memberref + mdToken *ptk, // [OUT] Put classref or classdef here. _Out_writes_to_opt_(cchMember, *pchMember) LPWSTR szMember, // [OUT] buffer to fill for member's name ULONG cchMember, // [IN] the count of char of szMember @@ -814,26 +803,26 @@ DECLARE_INTERFACE_(IMetaDataImport, IUnknown) PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to meta data blob value ULONG *pbSig) PURE; // [OUT] actual size of signature blob - STDMETHOD(EnumProperties)( // S_OK, S_FALSE, or error. + STDMETHOD(EnumProperties)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdTypeDef td, // [IN] TypeDef to scope the enumeration. mdProperty rProperties[], // [OUT] Put Properties here. ULONG cMax, // [IN] Max properties to put. ULONG *pcProperties) PURE; // [OUT] Put # put here. - STDMETHOD(EnumEvents)( // S_OK, S_FALSE, or error. + STDMETHOD(EnumEvents)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdTypeDef td, // [IN] TypeDef to scope the enumeration. mdEvent rEvents[], // [OUT] Put events here. ULONG cMax, // [IN] Max events to put. ULONG *pcEvents) PURE; // [OUT] Put # put here. - STDMETHOD(GetEventProps)( // S_OK, S_FALSE, or error. - mdEvent ev, // [IN] event token + STDMETHOD(GetEventProps)( // S_OK, S_FALSE, or error. + mdEvent ev, // [IN] event token mdTypeDef *pClass, // [OUT] typedef containing the event declarion. - LPCWSTR szEvent, // [OUT] Event name + LPCWSTR szEvent, // [OUT] Event name ULONG cchEvent, // [IN] the count of wchar of szEvent - ULONG *pchEvent, // [OUT] actual count of wchar for event's name + ULONG *pchEvent, // [OUT] actual count of wchar for event's name DWORD *pdwEventFlags, // [OUT] Event flags. mdToken *ptkEventType, // [OUT] EventType class mdMethodDef *pmdAddOn, // [OUT] AddOn method of the event @@ -841,24 +830,24 @@ DECLARE_INTERFACE_(IMetaDataImport, IUnknown) mdMethodDef *pmdFire, // [OUT] Fire method of the event mdMethodDef rmdOtherMethod[], // [OUT] other method of the event ULONG cMax, // [IN] size of rmdOtherMethod - ULONG *pcOtherMethod) PURE; // [OUT] total number of other method of this event + ULONG *pcOtherMethod) PURE; // [OUT] total number of other method of this event - STDMETHOD(EnumMethodSemantics)( // S_OK, S_FALSE, or error. + STDMETHOD(EnumMethodSemantics)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdMethodDef mb, // [IN] MethodDef to scope the enumeration. + mdMethodDef mb, // [IN] MethodDef to scope the enumeration. mdToken rEventProp[], // [OUT] Put Event/Property here. ULONG cMax, // [IN] Max properties to put. ULONG *pcEventProp) PURE; // [OUT] Put # put here. - STDMETHOD(GetMethodSemantics)( // S_OK, S_FALSE, or error. + STDMETHOD(GetMethodSemantics)( // S_OK, S_FALSE, or error. mdMethodDef mb, // [IN] method token mdToken tkEventProp, // [IN] event/property token. - DWORD *pdwSemanticsFlags) PURE; // [OUT] the role flags for the method/propevent pair + DWORD *pdwSemanticsFlags) PURE; // [OUT] the role flags for the method/propevent pair - STDMETHOD(GetClassLayout) ( + STDMETHOD(GetClassLayout) ( mdTypeDef td, // [IN] give typedef DWORD *pdwPackSize, // [OUT] 1, 2, 4, 8, or 16 - COR_FIELD_OFFSET rFieldOffset[], // [OUT] field offset array + COR_FIELD_OFFSET rFieldOffset[], // [OUT] field offset array ULONG cMax, // [IN] size of the array ULONG *pcFieldOffset, // [OUT] needed array size ULONG *pulClassSize) PURE; // [OUT] the size of the class @@ -871,7 +860,7 @@ DECLARE_INTERFACE_(IMetaDataImport, IUnknown) STDMETHOD(GetRVA)( // S_OK or error. mdToken tk, // Member for which to set offset ULONG *pulCodeRVA, // The offset - DWORD *pdwImplFlags) PURE; // the implementation flags + DWORD *pdwImplFlags) PURE; // the implementation flags STDMETHOD(GetPermissionSetProps) ( mdPermission pm, // [IN] the permission token. @@ -906,7 +895,7 @@ DECLARE_INTERFACE_(IMetaDataImport, IUnknown) mdToken tk, // [IN] Token to get name from. Must have a name. MDUTF8CSTR *pszUtf8NamePtr) PURE; // [OUT] Return pointer to UTF8 name in heap. - STDMETHOD(EnumUnresolvedMethods)( // S_OK, S_FALSE, or error. + STDMETHOD(EnumUnresolvedMethods)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdToken rMethods[], // [OUT] Put MemberDefs here. ULONG cMax, // [IN] Max MemberDefs to put. @@ -973,18 +962,18 @@ DECLARE_INTERFACE_(IMetaDataImport, IUnknown) STDMETHOD(GetMemberProps)( mdToken mb, // The member for which to get props. - mdTypeDef *pClass, // Put member's class here. + mdTypeDef *pClass, // Put member's class here. _Out_writes_to_opt_(cchMember, *pchMember) LPWSTR szMember, // Put member's name here. ULONG cchMember, // Size of szMember buffer in wide chars. - ULONG *pchMember, // Put actual size here + ULONG *pchMember, // Put actual size here DWORD *pdwAttr, // Put flags here. PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data ULONG *pcbSigBlob, // [OUT] actual size of signature blob ULONG *pulCodeRVA, // [OUT] codeRVA DWORD *pdwImplFlags, // [OUT] Impl. Flags DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* - UVCP_CONSTANT *ppValue, // [OUT] constant value + UVCP_CONSTANT *ppValue, // [OUT] constant value ULONG *pcchValue) PURE; // [OUT] size of constant string in chars, 0 for non-strings. STDMETHOD(GetFieldProps)( @@ -993,25 +982,25 @@ DECLARE_INTERFACE_(IMetaDataImport, IUnknown) _Out_writes_to_opt_(cchField, *pchField) LPWSTR szField, // Put field's name here. ULONG cchField, // Size of szField buffer in wide chars. - ULONG *pchField, // Put actual size here + ULONG *pchField, // Put actual size here DWORD *pdwAttr, // Put flags here. PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data ULONG *pcbSigBlob, // [OUT] actual size of signature blob DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* - UVCP_CONSTANT *ppValue, // [OUT] constant value + UVCP_CONSTANT *ppValue, // [OUT] constant value ULONG *pcchValue) PURE; // [OUT] size of constant string in chars, 0 for non-strings. - STDMETHOD(GetPropertyProps)( // S_OK, S_FALSE, or error. + STDMETHOD(GetPropertyProps)( // S_OK, S_FALSE, or error. mdProperty prop, // [IN] property token - mdTypeDef *pClass, // [OUT] typedef containing the property declarion. + mdTypeDef *pClass, // [OUT] typedef containing the property declarion. LPCWSTR szProperty, // [OUT] Property name ULONG cchProperty, // [IN] the count of wchar of szProperty ULONG *pchProperty, // [OUT] actual count of wchar for property name DWORD *pdwPropFlags, // [OUT] property flags. - PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob + PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob ULONG *pbSig, // [OUT] count of bytes in *ppvSig DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* - UVCP_CONSTANT *ppDefaultValue, // [OUT] constant value + UVCP_CONSTANT *ppDefaultValue, // [OUT] constant value ULONG *pcchDefaultValue, // [OUT] size of constant string in chars, 0 for non-strings. mdMethodDef *pmdSetter, // [OUT] setter method of the property mdMethodDef *pmdGetter, // [OUT] getter method of the property @@ -1455,7 +1444,7 @@ DECLARE_INTERFACE_(IMetaDataDispenserEx, IMetaDataDispenser) LPCWSTR szPrivateBin, // [IN] optional - can be NULL LPCWSTR szGlobalBin, // [IN] optional - can be NULL LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting - LPCWSTR szName, // [OUT] buffer - to hold name + LPCWSTR szName, // [OUT] buffer - to hold name ULONG cchName, // [IN] the name buffer's size ULONG *pcName) PURE; // [OUT] the number of characters returend in the buffer @@ -1466,7 +1455,7 @@ DECLARE_INTERFACE_(IMetaDataDispenserEx, IMetaDataDispenser) LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting LPCWSTR szModuleName, // [IN] required - the name of the module _Out_writes_to_opt_(cchName, *pcName) - LPWSTR szName, // [OUT] buffer - to hold name + LPWSTR szName, // [OUT] buffer - to hold name ULONG cchName, // [IN] the name buffer's size ULONG *pcName) PURE; // [OUT] the number of characters returend in the buffer @@ -1476,16 +1465,16 @@ DECLARE_INTERFACE_(IMetaDataDispenserEx, IMetaDataDispenser) //***************************************************************************** // // Registration declarations. Will be replace by Services' Registration -// implementation. +// implementation. // //***************************************************************************** //***************************************************************************** // Various flags for use in installing a module or a composite -typedef enum +typedef enum { regNoCopy = 0x00000001, // Don't copy files into destination regConfig = 0x00000002, // Is a configuration - regHasRefs = 0x00000004 // Has class references + regHasRefs = 0x00000004 // Has class references } CorRegFlags; typedef GUID CVID; @@ -1523,7 +1512,7 @@ typedef enum { // generate only a section-relative reloc, nothing into .reloc section srRelocAbsolute, - // generate a .reloc for a pointer sized location, + // generate a .reloc for a pointer sized location, // This is transformed into BASED_HIGHLOW or BASED_DIR64 based on the platform srRelocHighLow = 3, @@ -1531,7 +1520,7 @@ typedef enum { // bottom 16 bits are included in the next word in the .reloc table srRelocHighAdj, // Never Used - // generate a token map relocation, nothing into .reloc section + // generate a token map relocation, nothing into .reloc section srRelocMapToken, // relative address fixup @@ -1545,23 +1534,23 @@ typedef enum { // code relative address fixup srRelocCodeRelative, - // generate a .reloc for a 64 bit address in an ia64 movl instruction + // generate a .reloc for a 64 bit address in an ia64 movl instruction srRelocIA64Imm64, // generate a .reloc for a 64 bit address srRelocDir64, - // generate a .reloc for a 25-bit PC relative address in an ia64 br.call instruction + // generate a .reloc for a 25-bit PC relative address in an ia64 br.call instruction srRelocIA64PcRel25, - // generate a .reloc for a 64-bit PC relative address in an ia64 brl.call instruction + // generate a .reloc for a 64-bit PC relative address in an ia64 brl.call instruction srRelocIA64PcRel64, // generate a 30-bit section-relative reloc, used for tagged pointer values srRelocAbsoluteTagged, - // A sentinel value to help ensure any additions to this enum are reflected + // A sentinel value to help ensure any additions to this enum are reflected // in PEWriter.cpp's RelocName array. srRelocSentinel, @@ -1569,7 +1558,7 @@ typedef enum { // do not emit base reloc srNoBaseReloc = 0x4000, - + // pre-fixup contents of memory are ptr rather than a section offset srRelocPtr = 0x8000, @@ -1607,7 +1596,7 @@ DECLARE_INTERFACE_(ICeeGen, IUnknown) STDMETHOD (AllocateMethodBuffer) ( ULONG cchBuffer, // [IN] Length of buffer to create UCHAR **lpBuffer, // [OUT] Returned buffer - ULONG *RVA) PURE; // [OUT] RVA for method + ULONG *RVA) PURE; // [OUT] RVA for method STDMETHOD (GetMethodBuffer) ( ULONG RVA, // [IN] RVA for method to return @@ -1619,43 +1608,43 @@ DECLARE_INTERFACE_(ICeeGen, IUnknown) STDMETHOD (GenerateCeeFile) () PURE; STDMETHOD (GetIlSection) ( - HCEESECTION *section) PURE; + HCEESECTION *section) PURE; STDMETHOD (GetStringSection) ( - HCEESECTION *section) PURE; + HCEESECTION *section) PURE; STDMETHOD (AddSectionReloc) ( - HCEESECTION section, - ULONG offset, - HCEESECTION relativeTo, + HCEESECTION section, + ULONG offset, + HCEESECTION relativeTo, CeeSectionRelocType relocType) PURE; // use these only if you have special section requirements not handled // by other APIs STDMETHOD (GetSectionCreate) ( - const char *name, - DWORD flags, - HCEESECTION *section) PURE; + const char *name, + DWORD flags, + HCEESECTION *section) PURE; STDMETHOD (GetSectionDataLen) ( - HCEESECTION section, + HCEESECTION section, ULONG *dataLen) PURE; STDMETHOD (GetSectionBlock) ( - HCEESECTION section, - ULONG len, - ULONG align=1, - void **ppBytes=0) PURE; + HCEESECTION section, + ULONG len, + ULONG align=1, + void **ppBytes=0) PURE; STDMETHOD (TruncateSection) ( - HCEESECTION section, + HCEESECTION section, ULONG len) PURE; STDMETHOD (GenerateCeeMemoryImage) ( void **ppImage) PURE; STDMETHOD (ComputePointer) ( - HCEESECTION section, + HCEESECTION section, ULONG RVA, // [IN] RVA for method to return UCHAR **lpBuffer) PURE; // [OUT] Returned buffer @@ -1827,7 +1816,7 @@ DECLARE_INTERFACE_(IMetaDataInfo, IUnknown) { // Return Values: // S_OK - All parameters are filled. - // COR_E_NOTSUPPORTED - The API is not supported for this particular scope (e.g. .obj files, scope + // COR_E_NOTSUPPORTED - The API is not supported for this particular scope (e.g. .obj files, scope // opened without whole file via code:IMetaDataDispenser::OpenScopeOnMemory, etc.). // E_INVALIDARG - If NULL is passed as parameter. STDMETHOD(GetFileMapping)( @@ -1874,7 +1863,7 @@ DECLARE_INTERFACE_(IMetaDataWinMDImport, IUnknown) #define COR_NATIVE_LINK_CUSTOM_VALUE_CC 18 #include -typedef struct +typedef struct { BYTE m_linkType; // see CorNativeLinkType below BYTE m_flags; // see CorNativeLinkFlags below @@ -1882,7 +1871,7 @@ typedef struct } COR_NATIVE_LINK; #include -typedef enum +typedef enum { nltNone = 1, // none of the keywords are specified nltAnsi = 2, // ansi keyword specified @@ -1891,9 +1880,9 @@ typedef enum nltMaxValue = 7, // used so we can assert how many bits are required for this enum } CorNativeLinkType; -typedef enum +typedef enum { - nlfNone = 0x00, // no flags + nlfNone = 0x00, // no flags nlfLastError = 0x01, // setLastError keyword specified nlfNoMangle = 0x02, // nomangle keyword specified nlfMaxValue = 0x03, // used so we can assert how many bits are required for this enum @@ -1981,9 +1970,9 @@ FORCEINLINE int CorIsPrimitiveType(CorElementType elementtype) } -// Return true if element type is a modifier, i.e. ELEMENT_TYPE_MODIFIER bits are +// Return true if element type is a modifier, i.e. ELEMENT_TYPE_MODIFIER bits are // turned on. For now, it is checking for ELEMENT_TYPE_PTR and ELEMENT_TYPE_BYREF -// as well. This will be removed when we turn on ELEMENT_TYPE_MODIFIER bits for +// as well. This will be removed when we turn on ELEMENT_TYPE_MODIFIER bits for // these two enum members. // FORCEINLINE int CorIsModifierElementType(CorElementType elementtype) @@ -2015,7 +2004,7 @@ inline ULONG CorSigUncompressedDataSize( // (*pBytes & 0xE0) == 0XE0. ///////////////////////////////////////////////////////////////////////////////////////////// inline ULONG CorSigUncompressBigData( - PCCOR_SIGNATURE & pData) // [IN,OUT] compressed data + PCCOR_SIGNATURE & pData) // [IN,OUT] compressed data { ULONG res; @@ -2028,32 +2017,32 @@ inline ULONG CorSigUncompressBigData( res = (ULONG)((*pData++ & 0x3f) << 8); res |= *pData++; } - else // 110? ???? + else // 110? ???? { res = (*pData++ & 0x1f) << 24; res |= *pData++ << 16; res |= *pData++ << 8; res |= *pData++; } - return res; + return res; } FORCEINLINE ULONG CorSigUncompressData( - PCCOR_SIGNATURE & pData) // [IN,OUT] compressed data + PCCOR_SIGNATURE & pData) // [IN,OUT] compressed data { - // Handle smallest data inline. + // Handle smallest data inline. if ((*pData & 0x80) == 0x00) // 0??? ???? return *pData++; return CorSigUncompressBigData(pData); } -inline HRESULT CorSigUncompressData(// return S_OK or E_BADIMAGEFORMAT if the signature is bad +inline HRESULT CorSigUncompressData(// return S_OK or E_BADIMAGEFORMAT if the signature is bad PCCOR_SIGNATURE pData, // [IN] compressed data DWORD len, // [IN] length of the signature ULONG * pDataOut, // [OUT] the expanded *pData ULONG * pDataLen) // [OUT] length of the expanded *pData { HRESULT hr = S_OK; - BYTE const *pBytes = reinterpret_cast(pData); + BYTE const *pBytes = reinterpret_cast(pData); // Smallest. if ((*pBytes & 0x80) == 0x00) // 0??? ???? @@ -2067,7 +2056,7 @@ inline HRESULT CorSigUncompressData(// return S_OK or E_BADIMAGEFORMAT if the si else { *pDataOut = *pBytes; - *pDataLen = 1; + *pDataLen = 1; } } // Medium. @@ -2082,7 +2071,7 @@ inline HRESULT CorSigUncompressData(// return S_OK or E_BADIMAGEFORMAT if the si else { *pDataOut = (ULONG)(((*pBytes & 0x3f) << 8 | *(pBytes+1))); - *pDataLen = 2; + *pDataLen = 2; } } else if ((*pBytes & 0xE0) == 0xC0) // 110? ???? @@ -2096,7 +2085,7 @@ inline HRESULT CorSigUncompressData(// return S_OK or E_BADIMAGEFORMAT if the si else { *pDataOut = (ULONG)(((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3))); - *pDataLen = 4; + *pDataLen = 4; } } else // We don't recognize this encoding @@ -2105,23 +2094,23 @@ inline HRESULT CorSigUncompressData(// return S_OK or E_BADIMAGEFORMAT if the si *pDataLen = 0; hr = META_E_BAD_SIGNATURE; } - + return hr; } -inline ULONG CorSigUncompressData( // return number of bytes of that compressed data occupied in pData - PCCOR_SIGNATURE pData, // [IN] compressed data +inline ULONG CorSigUncompressData( // return number of bytes of that compressed data occupied in pData + PCCOR_SIGNATURE pData, // [IN] compressed data ULONG *pDataOut) // [OUT] the expanded *pData { ULONG dwSizeOfData = 0; - + // We don't know how big the signature is, so we'll just say that it's big enough if (FAILED(CorSigUncompressData(pData, 0xff, pDataOut, &dwSizeOfData))) { *pDataOut = 0; return (ULONG)-1; } - + return dwSizeOfData; } @@ -2138,35 +2127,35 @@ SELECTANY const mdToken g_tkCorEncodeToken[4] ={mdtTypeDef, mdtTypeRef, mdtTypeS // uncompress a token inline mdToken CorSigUncompressToken( // return the token. - PCCOR_SIGNATURE &pData) // [IN,OUT] compressed data + PCCOR_SIGNATURE &pData) // [IN,OUT] compressed data { mdToken tk; mdToken tkType; tk = CorSigUncompressData(pData); tkType = g_tkCorEncodeToken[tk & 0x3]; - tk = TokenFromRid(tk >> 2, tkType); + tk = TokenFromRid(tk >> 2, tkType); return tk; } -inline ULONG CorSigUncompressToken( // return number of bytes of that compressed data occupied in pData - PCCOR_SIGNATURE pData, // [IN] compressed data +inline ULONG CorSigUncompressToken( // return number of bytes of that compressed data occupied in pData + PCCOR_SIGNATURE pData, // [IN] compressed data mdToken * pToken) // [OUT] the expanded *pData { ULONG cb; mdToken tk; mdToken tkType; - cb = CorSigUncompressData(pData, (ULONG *)&tk); + cb = CorSigUncompressData(pData, (ULONG *)&tk); tkType = g_tkCorEncodeToken[tk & 0x3]; - tk = TokenFromRid(tk >> 2, tkType); + tk = TokenFromRid(tk >> 2, tkType); *pToken = tk; return cb; } inline HRESULT CorSigUncompressToken( - PCCOR_SIGNATURE pData, // [IN] compressed data + PCCOR_SIGNATURE pData, // [IN] compressed data DWORD dwLen, // [IN] Remaining length of sigature mdToken * pToken, // [OUT] the expanded *pData DWORD * dwTokenLength) // [OUT] The length of the token in the sigature @@ -2179,7 +2168,7 @@ inline HRESULT CorSigUncompressToken( if (SUCCEEDED(hr)) { tkType = g_tkCorEncodeToken[tk & 0x3]; - tk = TokenFromRid(tk >> 2, tkType); + tk = TokenFromRid(tk >> 2, tkType); *pToken = tk; } else @@ -2223,8 +2212,8 @@ enum { // uncompress a signed integer inline ULONG CorSigUncompressSignedInt( // return number of bytes of that compressed data occupied in pData - PCCOR_SIGNATURE pData, // [IN] compressed data - int * pInt) // [OUT] the expanded *pInt + PCCOR_SIGNATURE pData, // [IN] compressed data + int * pInt) // [OUT] the expanded *pInt { ULONG cb; ULONG ulSigned; @@ -2232,17 +2221,17 @@ inline ULONG CorSigUncompressSignedInt( // return number of bytes of that compre cb = CorSigUncompressData(pData, &iData); if (cb == (ULONG) -1) return cb; - ulSigned = iData & 0x1; - iData = iData >> 1; + ulSigned = iData & 0x1; + iData = iData >> 1; if (ulSigned) { if (cb == 1) { - iData |= SIGN_MASK_ONEBYTE; + iData |= SIGN_MASK_ONEBYTE; } else if (cb == 2) { - iData |= SIGN_MASK_TWOBYTE; + iData |= SIGN_MASK_TWOBYTE; } else { @@ -2256,13 +2245,13 @@ inline ULONG CorSigUncompressSignedInt( // return number of bytes of that compre // uncompress encoded element type FORCEINLINE CorElementType CorSigUncompressElementType( // Element type - PCCOR_SIGNATURE & pData) // [IN,OUT] Compressed data + PCCOR_SIGNATURE & pData) // [IN,OUT] Compressed data { return (CorElementType)*pData++; } inline ULONG CorSigUncompressElementType( // Return number of bytes of that compressed data occupied in pData - PCCOR_SIGNATURE pData, // [IN] Compressed data + PCCOR_SIGNATURE pData, // [IN] Compressed data CorElementType * pElementType) // [OUT] The expanded *pData { *pElementType = (CorElementType)(*pData & 0x7f); @@ -2285,20 +2274,20 @@ inline ULONG CorSigCompressData( // return number of bytes that compressed fo void * pDataOut) // [OUT] buffer where iLen will be compressed and stored. { BYTE *pBytes = reinterpret_cast(pDataOut); - + if (iLen <= 0x7F) { *pBytes = BYTE(iLen); return 1; } - + if (iLen <= 0x3FFF) { *pBytes = BYTE((iLen >> 8) | 0x80); *(pBytes+1) = BYTE(iLen & 0xff); return 2; } - + if (iLen <= 0x1FFFFFFF) { *pBytes = BYTE((iLen >> 24) | 0xC0); @@ -2317,15 +2306,15 @@ inline ULONG CorSigCompressToken( // return number of bytes that compressed fo mdToken tk, // [IN] given token void * pDataOut) // [OUT] buffer where the token will be compressed and stored. { - RID rid = RidFromToken(tk); + RID rid = RidFromToken(tk); ULONG32 ulTyp = TypeFromToken(tk); - + if (rid > 0x3FFFFFF) // token is too big to be compressed return (ULONG) -1; - + rid = (rid << 2); - + // TypeDef is encoded with low bits 00 // TypeRef is encoded with low bits 01 // TypeSpec is encoded with low bits 10 @@ -2357,11 +2346,11 @@ inline ULONG CorSigCompressSignedInt( // return number of bytes that compresse { ULONG isSigned = 0; BYTE *pBytes = reinterpret_cast(pDataOut); - + if (iData < 0) isSigned = 0x1; - - // Note that we cannot use code:CorSigCompressData to pack the iData value, because of negative values + + // Note that we cannot use code:CorSigCompressData to pack the iData value, because of negative values // like: 0xffffe000 (-8192) which has to be encoded as 1 in 2 bytes, i.e. 0x81 0x00 // However CorSigCompressedData would store value 1 as 1 byte: 0x01 if ((iData & SIGN_MASK_ONEBYTE) == 0 || (iData & SIGN_MASK_ONEBYTE) == SIGN_MASK_ONEBYTE) @@ -2396,11 +2385,11 @@ inline ULONG CorSigCompressSignedInt( // return number of bytes that compresse // uncompress encoded element type inline ULONG CorSigCompressElementType( // return number of bytes of that compressed data occupied in pData - CorElementType et, // [OUT] the expanded *pData + CorElementType et, // [OUT] the expanded *pData void * pData) // [IN] compressed data { BYTE *pBytes = (BYTE *)(pData); - + *pBytes = BYTE(et); return 1; } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corbbtprof.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/corbbtprof.h index 419a7f0..35816bb 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corbbtprof.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corbbtprof.h @@ -47,13 +47,13 @@ typedef mdToken idMethodSpec; // MethodSpec token in the IBC data // File format: // // CORBBTPROF_FILE_HEADER -// CORBBTPROF_SECTION_TABLE_HEADER +// CORBBTPROF_SECTION_TABLE_HEADER // CORBBTPROF_SECTION_TABLE_ENTRY // ... (can be multiple entries) // // Method block counts section: -// CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER -// CORBBTPROF_METHOD_HEADER +// CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER +// CORBBTPROF_METHOD_HEADER // CORBBTPROF_BLOCK_DATA // ... (can be multiple method header/block data entries) // @@ -147,7 +147,7 @@ enum TypeProfilingDataFlags ReadDispatchMap = 7, // 0x00080 ReadDispatchTable = 8, // 0x00100 ReadMethodTableWriteableData = 9, // 0x00200 - ReadFieldMarshalers = 10, // 0x00400 +// ReadFieldMarshalers = 10, // 0x00400 // obsolete // WriteDispatchTable = 11, // 0x00800 // obsolete // WriteMethodTable = 12, // 0x01000 // obsolete WriteMethodTableWriteableData = 13, // 0x02000 @@ -198,7 +198,7 @@ enum GeneralProfilingDataFlags enum BlobType { /* IMPORTANT: Keep the first four enums together in the same order and at - the very begining of this enum. See MetaModelPub.h for the order */ + the very beginning of this enum. See MetaModelPub.h for the order */ MetadataStringPool = 0, MetadataGuidPool = 1, MetadataBlobPool = 2, @@ -208,13 +208,13 @@ enum BlobType LastMetadataPool = 3, // SectionFormat only supports tokens, which have to already exist in the module. - // For instantiated paramterized types, there may be no corresponding token + // For instantiated parameterized types, there may be no corresponding token // in the module, if a dependent module caused the type to be instantiated. // For such instantiated types, we save a blob/signature to identify the type. - // + // ParamTypeSpec = 4, // Instantiated Type Signature ParamMethodSpec = 5, // Instantiated Method Signature - ExternalNamespaceDef = 6, // External Namespace Token Definition + ExternalNamespaceDef = 6, // External Namespace Token Definition ExternalTypeDef = 7, // External Type Token Definition ExternalSignatureDef = 8, // External Signature Definition ExternalMethodDef = 9, // External Method Token Definition @@ -262,7 +262,7 @@ enum SectionFormat BlobPoolProfilingData, UserStringPoolProfilingData, - FirstMetadataPoolSection = StringPoolProfilingData, + FirstMetadataPoolSection = StringPoolProfilingData, LastMetadataPoolSection = UserStringPoolProfilingData, LastTokenFlagSection = LastMetadataPoolSection, @@ -295,11 +295,11 @@ struct CORBBTPROF_SECTION_TABLE_HEADER struct CORBBTPROF_SCENARIO_RUN { - FILETIME runTime; // the FILETIME when the scenario was cnt + FILETIME runTime; // the FILETIME when the scenario was cnt GUID mvid; // The GUID of this assembly when the scenario was run (useful for incremental ibcdata) DWORD cCmdLine; // the count of WCHAR's in the cmdLine for this run of the scenario - DWORD cSystemInfo; // the count of WCHAR's in the systemInfo string for this run of the scenario - WCHAR cmdLine[0]; // the command line used, the array is 'cName' in length + DWORD cSystemInfo; // the count of WCHAR's in the systemInfo string for this run of the scenario + WCHAR cmdLine[0]; // the command line used, the array is 'cName' in length // WCHAR systemInfo[]; // the system information, the array is 'cSystemInfo' in length DWORD sizeofCmdLine() @@ -328,7 +328,7 @@ struct CORBBTPROF_SCENARIO_INFO { DWORD ordinal; // the id number for this scenario DWORD mask; // the one-bit mask use to identify this scenario - DWORD priority; // the priority of this scenario + DWORD priority; // the priority of this scenario DWORD numRuns; // the number of times this scenario was run DWORD cName; // the count of WCHAR's in name[] WCHAR name[0]; // the name of this scenario, the array is 'cName' in length @@ -412,12 +412,12 @@ struct CORBBTPROF_BLOCK_DATA // This struct is also defined by: ICorJitInfo. struct CORBBTPROF_METHOD_DETAIL_HEADER { - DWORD size; // Size to skip to get to the next CORBBTPROF_METHOD_DETAIL_HEADER at this level + DWORD size; // Size to skip to get to the next CORBBTPROF_METHOD_DETAIL_HEADER at this level DWORD kind; // Identifier that specifies what kind this CORBBTPROF_METHOD_DETAIL_HEADER actually represents size_t Size() { - return size; + return size; } }; @@ -429,16 +429,16 @@ struct CORBBTPROF_METHOD_INFO DWORD token; // token for this method DWORD ILSize; // IL size for this method DWORD cBlock; // count for block[] - CORBBTPROF_BLOCK_DATA block[0]; // actually 'cBlock' in length + CORBBTPROF_BLOCK_DATA block[0]; // actually 'cBlock' in length size_t Size() - { - return sizeof(CORBBTPROF_METHOD_INFO) + sizeofBlock(); + { + return sizeof(CORBBTPROF_METHOD_INFO) + sizeofBlock(); } - size_t sizeofBlock() + size_t sizeofBlock() { - return cBlock * sizeof(CORBBTPROF_BLOCK_DATA); + return cBlock * sizeof(CORBBTPROF_BLOCK_DATA); } }; @@ -452,13 +452,13 @@ struct CORBBTPROF_METHOD_HEADER_V1 struct CORBBTPROF_METHOD_HEADER { DWORD size; // Size to skip to get to the next CORBBTPROF_METHOD_HEADER - DWORD cDetail; // the count of CORBBTPROF_METHOD_DETAIL_HEADER records that folow this record + DWORD cDetail; // the count of CORBBTPROF_METHOD_DETAIL_HEADER records that follow this record CORBBTPROF_METHOD_INFO method; // Basic block execution counts for a method - // ... followed by 'cDetail' occurances of CORBBTPROF_METHOD_DETAIL_HEADER + // ... followed by 'cDetail' occurrences of CORBBTPROF_METHOD_DETAIL_HEADER size_t Size() { - return sizeof(CORBBTPROF_METHOD_HEADER) + method.sizeofBlock(); + return sizeof(CORBBTPROF_METHOD_HEADER) + method.sizeofBlock(); } }; @@ -485,7 +485,7 @@ struct CORBBTPROF_TOKEN_INFO // Was CORBBTPROF_TOKEN_LIST_ENTR , flags(0) , scenarios(0) {} - + CORBBTPROF_TOKEN_INFO( mdToken t, DWORD f = 0, DWORD s = 0) : token(t) , flags(f) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corcompile.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/corcompile.h index 755c846..2973b7a 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corcompile.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corcompile.h @@ -18,12 +18,6 @@ #ifndef _COR_COMPILE_H_ #define _COR_COMPILE_H_ -#if !defined(_TARGET_X86_) || defined(FEATURE_PAL) -#ifndef WIN64EXCEPTIONS -#define WIN64EXCEPTIONS -#endif -#endif // !_TARGET_X86_ || FEATURE_PAL - #include #include #include @@ -60,7 +54,7 @@ typedef DPTR(struct CORCOMPILE_VIRTUAL_SECTION_INFO) typedef DPTR(struct CORCOMPILE_IMPORT_SECTION) PTR_CORCOMPILE_IMPORT_SECTION; -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 typedef DPTR(RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; @@ -68,12 +62,12 @@ typedef DPTR(RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; // Chained unwind info. Used for cold methods. #define RUNTIME_FUNCTION_INDIRECT 0x80000000 -#endif // _TARGET_X86_ +#endif // TARGET_X86 -// The stride is choosen as maximum value that still gives good page locality of RUNTIME_FUNCTION table touches (only one page of +// The stride is choosen as maximum value that still gives good page locality of RUNTIME_FUNCTION table touches (only one page of // RUNTIME_FUNCTION table is going to be touched during most IP2MD lookups). // -// Smaller stride values also improve speed of IP2MD lookups, but this improvement is not significant (5% when going +// Smaller stride values also improve speed of IP2MD lookups, but this improvement is not significant (5% when going // from 8192 to 1024), so the working set / page locality was used as the metric to choose the optimum value. // #define RUNTIME_FUNCTION_LOOKUP_STRIDE 8192 @@ -94,7 +88,7 @@ typedef DPTR(struct COR_ILMETHOD) PTR_COR_ILMETHOD; // // CORCOMPILE_IMPORT_SECTION describes image range with references to other assemblies or runtime data structures // -// There is number of different types of these ranges: eagerly initialized at image load vs. lazily initialized at method entry +// There is number of different types of these ranges: eagerly initialized at image load vs. lazily initialized at method entry // vs. lazily initialized on first use; hot vs. cold, handles vs. code pointers, etc. // struct CORCOMPILE_IMPORT_SECTION @@ -144,7 +138,7 @@ enum CorCompileImportFlags #define CORCOMPILE_TAG_TOKEN(token) ((SIZE_T)(((token)<<1)|CORCOMPILE_TOKEN_TAG)) #define CORCOMPILE_UNTAG_TOKEN(token) ((((SIZE_T)(token))&~CORCOMPILE_TOKEN_TAG)>>1) -#ifdef _TARGET_ARM_ +#ifdef TARGET_ARM // Tagging of code pointers on ARM uses inverse logic because of the thumb bit. #define CORCOMPILE_IS_PCODE_TAGGED(token) ((((SIZE_T)(token)) & 0x00000001) == 0x00000000) #define CORCOMPILE_TAG_PCODE(token) ((SIZE_T)(((token)<<1)|0x80000000)) @@ -155,7 +149,7 @@ enum CorCompileImportFlags inline BOOL CORCOMPILE_IS_FIXUP_TAGGED(SIZE_T fixup, PTR_CORCOMPILE_IMPORT_SECTION pSection) { -#ifdef _TARGET_ARM_ +#ifdef TARGET_ARM // Tagging of code pointers on ARM has to use inverse logic because of the thumb bit if (pSection->Flags & CORCOMPILE_IMPORT_FLAGS_PCODE) { @@ -211,7 +205,7 @@ enum CorCompileHeaderFlags CORCOMPILE_HEADER_IS_READY_TO_RUN = 0x00000004, }; -// +// // !!! INCREMENT THE MAJOR VERSION ANY TIME THERE IS CHANGE IN CORCOMPILE_HEADER STRUCTURE !!! // #define CORCOMPILE_SIGNATURE 0x0045474E // 'NGEN' @@ -269,8 +263,8 @@ struct CORCOMPILE_HEADER IMAGE_DATA_DIRECTORY Dummy4; }; -// CORCOMPILE_VIRTUAL_SECTION_INFO describes virtual section ranges. This data is used by nidump -// and to fire ETW that are used for diagnostics and performance purposes. Some of the questions +// CORCOMPILE_VIRTUAL_SECTION_INFO describes virtual section ranges. This data is used by nidump +// and to fire ETW that are used for diagnostics and performance purposes. Some of the questions // these events help answer are like : how effective is IBC training data. struct CORCOMPILE_VIRTUAL_SECTION_INFO { @@ -330,7 +324,7 @@ struct CORCOMPILE_VIRTUAL_SECTION_INFO // Hot: Items are frequently accessed ( Indicated by either IBC data, or // statically known ) -// Warm : Items are less frequently accessed, or frequently accessed +// Warm : Items are less frequently accessed, or frequently accessed // but were not touched during IBC profiling. // Cold : Least frequently accessed /shouldn't not be accessed @@ -338,7 +332,7 @@ struct CORCOMPILE_VIRTUAL_SECTION_INFO // training ( training scenario ) // HotColdSorted : Sections marked with this category means they contain both -// Hot items and Cold items. The hot items are placed before +// Hot items and Cold items. The hot items are placed before // the cold items (Sorted) #define CORCOMPILE_SECTION_RANGE_TYPES() \ @@ -350,12 +344,12 @@ struct CORCOMPILE_VIRTUAL_SECTION_INFO // IBCUnProfiled: Items in this VirtualSection are statically determined to be cold. // (IBC Profiling wouldn't have helped put these item in a hot section). -// Items that currently doesn't have IBC probs, or are always put in a specific section +// Items that currently doesn't have IBC probs, or are always put in a specific section // regardless of IBC data should fall in this category. // IBCProfiled: IBC profiling placed items in this section, or // items are NOT placed into a hot section they didn't have IBC profiling data -// ( IBC profiling would have helped put these items in a hot section ) +// ( IBC profiling would have helped put these items in a hot section ) #define CORCOMPILE_SECTION_IBCTYPES() \ CORCOMPILE_SECTION_IBCTYPE(IBCUnProfiled, 0x01000000) \ @@ -370,42 +364,42 @@ struct CORCOMPILE_VIRTUAL_SECTION_INFO // 1 byte 1 byte 2 bytes -- // -- // --------------------------------------------------- -// -// +// +// // VirtualSections are a CLR concept to aggregate data // items that share common properties together (Hot/Cold/Warm, Writeable/ // Readonly ...etc.). VirtualSections are tagged with some categories when they // are created (code:NewVirtualSection) // The VirtualSection categorize are described more in VirtualSectionType enum. // The categories describe 2 important aspects for each VirtualSection -// +// // *********************************************** // IBCProfiled v.s NonIBCProfiled Categories. // ********************************************** -// -// IBCProfiled: Distinguish between sections that IBC profiling data has been used -// to decide the layout of the data items in this section. +// +// IBCProfiled: Distinguish between sections that IBC profiling data has been used +// to decide the layout of the data items in this section. // NonIBCProfiled: We don't have IBC data for all our datastructures. // The access pattern/frequency for some data structures -// are statically determined. Sections that contain these data items -// are marked as NonIBCProfiled. +// are statically determined. Sections that contain these data items +// are marked as NonIBCProfiled. // //*************************************************** -// Access Frequency categories +// Access Frequency categories // ************************************************** // Hot: Data is frequently accessed // Warm: Less frequently accessed than Hot // Cold: Should be rarely accessed. -// -// The combination of these 2 sub-categories gives us the following valid categories +// +// The combination of these 2 sub-categories gives us the following valid categories // 1-IBCProfiled | Hot: Hot based on IBC profiling data. // 2-IBCProfiled | Cold: IBC profiling could have helped make this section hot. // 3-NonIBCProfiled | Hot: Statically determined hot. // 4-NonIBCProfiled | Warm: Staticaly determined warm. // 5-NonIBCProfiled | Cold: Statically determined cold. -// -// We should try to place data items into the correct section based on -// the above categorization, this could mean that we might split +// +// We should try to place data items into the correct section based on +// the above categorization, this could mean that we might split // a virtual section into 2 sections if it contains multiple heterogeneous items. enum ZapVirtualSectionType @@ -415,7 +409,7 @@ enum ZapVirtualSectionType #define CORCOMPILE_SECTION_IBCTYPE(ibcType, flag) ibcType##Section = flag, CORCOMPILE_SECTION_IBCTYPES() #undef CORCOMPILE_SECTION_IBCTYPE - + // RangeTypeReservedFlag = 0x00FF0000, #define CORCOMPILE_SECTION_RANGE_TYPE(rangeType, flag) rangeType##Range = flag, @@ -439,9 +433,9 @@ public : static UINT8 IBCType(DWORD sectionType) { return (UINT8) ((sectionType & IBCTypeReservedFlag) >> 24); } static UINT8 RangeType(DWORD sectionType) { return (UINT8) ((sectionType & RangeTypeReservedFlag) >> 16); } static UINT16 VirtualSectionType(DWORD sectionType) { return (UINT16) ((sectionType & VirtualSectionTypeReservedFlag)); } - static BOOL IsIBCProfiledColdSection(DWORD sectionType) + static BOOL IsIBCProfiledColdSection(DWORD sectionType) { - return ((sectionType & ColdRange) == ColdRange) && ((sectionType & IBCProfiledSection) == IBCProfiledSection); + return ((sectionType & ColdRange) == ColdRange) && ((sectionType & IBCProfiledSection) == IBCProfiledSection); } }; @@ -534,7 +528,7 @@ struct CORCOMPILE_CODE_MANAGER_ENTRY ULONG ColdUntrainedMethodOffset; }; -#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) +#if defined(TARGET_X86) || defined(TARGET_AMD64) #define _PRECODE_EXTERNAL_METHOD_THUNK 0x41 #define _PRECODE_VIRTUAL_IMPORT_THUNK 0x42 @@ -553,7 +547,7 @@ struct CORCOMPILE_CODE_MANAGER_ENTRY WORD padding; }; -#elif defined(_TARGET_ARM_) +#elif defined(TARGET_ARM) struct CORCOMPILE_VIRTUAL_IMPORT_THUNK { @@ -587,14 +581,14 @@ struct CORCOMPILE_CODE_MANAGER_ENTRY // Post patchup by the stub, it will point to the actual method body. PCODE m_pTarget; }; - -#elif defined(_TARGET_ARM64_) + +#elif defined(TARGET_ARM64) struct CORCOMPILE_VIRTUAL_IMPORT_THUNK { // Array of words to do the following: // // adr x12, #0 ; Save the current address relative to which we will get slot ID and address to patch. - // ldr x10, [x12, #16] ; Load the target address. + // ldr x10, [x12, #16] ; Load the target address. // br x10 ; Jump to the target DWORD m_rgCode[3]; @@ -610,7 +604,7 @@ struct CORCOMPILE_CODE_MANAGER_ENTRY { // Array of words to do the following: // adr x12, #0 ; Save the current address relative to which we will get slot ID and address to patch. - // ldr x10, [x12, #16] ; Load the target address. + // ldr x10, [x12, #16] ; Load the target address. // br x10 ; Jump to the target DWORD m_rgCode[3]; @@ -625,7 +619,7 @@ struct CORCOMPILE_CODE_MANAGER_ENTRY // // GCRefMap blob starts with DWORDs lookup index of relative offsets into the blob. This lookup index is used to limit amount -// of linear scanning required to find entry in the GCRefMap. The size of this lookup index is +// of linear scanning required to find entry in the GCRefMap. The size of this lookup index is // / GCREFMAP_LOOKUP_STRIDE. // #define GCREFMAP_LOOKUP_STRIDE 1024 @@ -644,7 +638,7 @@ enum CORCOMPILE_GCREFMAP_TOKENS enum CORCOMPILE_FIXUP_BLOB_KIND { ENCODE_NONE = 0, - + ENCODE_MODULE_OVERRIDE = 0x80, /* When the high bit is set, override of the module immediately follows */ ENCODE_DICTIONARY_LOOKUP_THISOBJ = 0x07, @@ -694,7 +688,10 @@ enum CORCOMPILE_FIXUP_BLOB_KIND ENCODE_DECLARINGTYPE_HANDLE, - ENCODE_INDIRECT_PINVOKE_TARGET, /* For calling a pinvoke method ptr */ + ENCODE_INDIRECT_PINVOKE_TARGET, /* For calling a pinvoke method ptr indirectly */ + ENCODE_PINVOKE_TARGET, /* For calling a pinvoke method ptr */ + + ENCODE_CHECK_INSTRUCTION_SET_SUPPORT, /* Define the set of instruction sets that must be supported/unsupported to use the fixup */ ENCODE_MODULE_HANDLE = 0x50, /* Module token */ ENCODE_STATIC_FIELD_ADDRESS, /* For accessing a static field */ @@ -707,7 +704,6 @@ enum CORCOMPILE_FIXUP_BLOB_KIND ENCODE_VARARGS_METHODREF, ENCODE_VARARGS_SIG, ENCODE_ACTIVE_DEPENDENCY, /* Conditional active dependency */ - ENCODE_METHOD_NATIVE_ENTRY, /* NativeCallable method token */ }; enum EncodeMethodSigFlags @@ -744,7 +740,7 @@ struct CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY struct CORCOMPILE_EXCEPTION_LOOKUP_TABLE { - // pointer to the first element of m_numLookupEntries elements + // pointer to the first element of m_numLookupEntries elements CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY m_Entries[1]; CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY* ExceptionLookupEntry(unsigned i) @@ -759,12 +755,12 @@ struct CORCOMPILE_EXCEPTION_CLAUSE CorExceptionFlag Flags; DWORD TryStartPC; DWORD TryEndPC; - DWORD HandlerStartPC; - DWORD HandlerEndPC; + DWORD HandlerStartPC; + DWORD HandlerEndPC; union { mdToken ClassToken; DWORD FilterOffset; - }; + }; }; //lower order bit (HAS_EXCEPTION_INFO_MASK) used to determine if the method has any exception handling @@ -772,7 +768,7 @@ struct CORCOMPILE_EXCEPTION_CLAUSE struct CORCOMPILE_COLD_METHOD_ENTRY { -#ifdef WIN64EXCEPTIONS +#ifdef FEATURE_EH_FUNCLETS DWORD mainFunctionEntryRVA; #endif // TODO: hotCodeSize should be encoded in GC info @@ -876,11 +872,11 @@ struct CORCOMPILE_DEPENDENCY /*********************************************************************************/ // Flags used to encode HelperTable -#if defined(_TARGET_ARM64_) +#if defined(TARGET_ARM64) #define HELPER_TABLE_ENTRY_LEN 16 #else #define HELPER_TABLE_ENTRY_LEN 8 -#endif //defined(_TARGET_ARM64_) +#endif //defined(TARGET_ARM64) #define HELPER_TABLE_ALIGN 8 #define CORCOMPILE_HELPER_PTR 0x80000000 // The entry is pointer to the helper (jump thunk otherwise) @@ -905,22 +901,16 @@ public: struct CORBBTPROF_TOKEN_INFO * GetTokenFlagsData(SectionFormat section) { - if (this == NULL) - return NULL; return this->profilingTokenFlagsData[section].data; } DWORD GetTokenFlagsCount(SectionFormat section) { - if (this == NULL) - return 0; return this->profilingTokenFlagsData[section].count; } CORBBTPROF_BLOB_ENTRY * GetBlobStream() { - if (this == NULL) - return NULL; return this->blobStream; } @@ -1186,6 +1176,8 @@ class ICorCompilePreloader virtual BOOL IsUncompiledMethod(CORINFO_METHOD_HANDLE handle) = 0; + virtual BOOL ShouldSuppressGCTransition(CORINFO_METHOD_HANDLE handle) = 0; + // Return a method handle that was previously registered and // hasn't been compiled already, and remove it from the set // of uncompiled methods. @@ -1281,11 +1273,11 @@ class ICorCompilePreloader ) = 0; virtual void NoteDeduplicatedCode( - CORINFO_METHOD_HANDLE method, + CORINFO_METHOD_HANDLE method, CORINFO_METHOD_HANDLE duplicateMethod) = 0; #ifdef FEATURE_READYTORUN_COMPILER - // Returns a compressed encoding of the inline tracking map + // Returns a compressed encoding of the inline tracking map // for this compilation virtual void GetSerializedInlineTrackingMap( IN OUT SBuffer * pSerializedInlineTrackingMap @@ -1468,7 +1460,7 @@ class ICorCompileInfo #ifdef FEATURE_COMINTEROP // Loads a WinRT typeref into the EE and returns // a handle to it. We have to load all typerefs - // during dependency computation since assemblyrefs + // during dependency computation since assemblyrefs // are meaningless to WinRT. virtual HRESULT LoadTypeRefWinRT( IMDInternalImport *pAssemblyImport, @@ -1644,7 +1636,7 @@ class ICorCompileInfo // Returns non-null methoddef or memberref token if it is sufficient to encode the method (no generic instantiations, etc.) virtual mdToken TryEncodeMethodAsToken( - CORINFO_METHOD_HANDLE handle, + CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_MODULE_HANDLE * referencingModule) = 0; @@ -1736,15 +1728,15 @@ class ICorCompileInfo // to 1 on the clone. The buffer has to be large enough to hold the stub object and the code virtual HRESULT GetStubClone(void *pStub, BYTE *pBuffer, DWORD dwBufferSize) = 0; - // true if the method has [NativeCallableAttribute] - virtual BOOL IsNativeCallableMethod(CORINFO_METHOD_HANDLE handle) = 0; + // true if the method has [UnmanagedCallersOnlyAttribute] + virtual BOOL IsUnmanagedCallersOnlyMethod(CORINFO_METHOD_HANDLE handle) = 0; virtual BOOL GetIsGeneratingNgenPDB() = 0; virtual void SetIsGeneratingNgenPDB(BOOL fGeneratingNgenPDB) = 0; #ifdef FEATURE_READYTORUN_COMPILER virtual CORCOMPILE_FIXUP_BLOB_KIND GetFieldBaseOffset( - CORINFO_CLASS_HANDLE classHnd, + CORINFO_CLASS_HANDLE classHnd, DWORD * pBaseOffset ) = 0; @@ -1766,23 +1758,6 @@ class ICorCompileInfo virtual BOOL HasCustomAttribute(CORINFO_METHOD_HANDLE method, LPCSTR customAttributeName) = 0; }; -/*****************************************************************************/ -// This function determines the compile flags to use for a generic intatiation -// since only the open instantiation can be verified. -// See the comment associated with CORJIT_FLAG_SKIP_VERIFICATION for details. -// -// On return: -// if *raiseVerificationException=TRUE, the caller should raise a VerificationException. -// if *unverifiableGenericCode=TRUE, the method is a generic instantiation with -// unverifiable code - -CORJIT_FLAGS GetCompileFlagsIfGenericInstantiation( - CORINFO_METHOD_HANDLE method, - CORJIT_FLAGS compileFlags, - ICorJitInfo * pCorJitInfo, - BOOL * raiseVerificationException, - BOOL * unverifiableGenericCode); - // Returns the global instance of JIT->EE interface for NGen extern "C" ICorDynamicInfo * __stdcall GetZapJitInfo(); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/cordebug.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/cordebug.idl index c0dcb76..87e1458 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/cordebug.idl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/cordebug.idl @@ -1361,10 +1361,10 @@ interface ICorDebugManagedCallback4 : IUnknown { // // Callback indicating a garbage collection is about to start. - // + // // Parameters // pProcess - the process that is going to perform garbage collection. - // + // // Returns // S_OK - on success // @@ -1372,10 +1372,10 @@ interface ICorDebugManagedCallback4 : IUnknown // // Callback indicating a garbage collection is about to complete. - // + // // Parameters // pProcess - the process that is going to complete garbage collection. - // + // // Returns // S_OK - on success // @@ -1383,13 +1383,13 @@ interface ICorDebugManagedCallback4 : IUnknown // // Callback indicating a data breakpoint is hit - // + // // Parameters // pProcess - the process that hits the data breakpoint // pThread - the thread that hits the data breakpoint // pContext - a pointer to the CONTEXT structure // contextSize - the size of the CONTEXT structure - // + // // Returns // S_OK - on success // @@ -3302,13 +3302,13 @@ interface ICorDebugProcess10 : IUnknown // // Enable or disable the GC notification events. The GC notification events are turned off by default // They will be delivered through ICorDebugManagedCallback4 - // + // // Parameters // fEnable - true to enable the events, false to disable - // + // // Returns - // S_OK - on success - // + // S_OK - on success + // HRESULT EnableGCNotificationEvents(BOOL fEnable); } @@ -6507,7 +6507,7 @@ interface ICorDebugDelegateObjectValue : IUnknown * - NULL if the delegate function is a static function or an open delegate * - HRESULT CORDBG_E_UNSUPPORTED_DELEGATE for curently unsupported delegates. * In this case, the value of ppObject should not be used. Some of these - * include: Secure wrappers, Open Virual delegates. + * include: Wrapper delegates, Open Virual delegates. */ HRESULT GetTarget([out] ICorDebugReferenceValue **ppObject); @@ -6516,10 +6516,10 @@ interface ICorDebugDelegateObjectValue : IUnknown * - S_OK: * - The ICorDebugFunction function for the function the delegate would invoke. * - There are a few cases where the ICorDebugFunction can be different from what's expected, - * such as generic methods, which won't contain the instantiation. + * such as generic methods, which won't contain the instantiation. * - HRESULT CORDBG_E_UNSUPPORTED_DELEGATE for curently unsupported delegates. * In this case, the value of ppObject should not be used. Some of these - * include: Secure wrappers, Open Virual delegates. + * include: Wrapper delegates, Open Virual delegates. */ HRESULT GetFunction([out] ICorDebugFunction **ppFunction); } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/cordebuginfo.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/cordebuginfo.h index bbe4de8..32df253 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/cordebuginfo.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/cordebuginfo.h @@ -69,7 +69,7 @@ public: // contained in debug/inc/DbgIPCEvents.h. enum RegNum { -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 REGNUM_EAX, REGNUM_ECX, REGNUM_EDX, @@ -78,7 +78,7 @@ public: REGNUM_EBP, REGNUM_ESI, REGNUM_EDI, -#elif _TARGET_ARM_ +#elif TARGET_ARM REGNUM_R0, REGNUM_R1, REGNUM_R2, @@ -95,7 +95,7 @@ public: REGNUM_SP, REGNUM_LR, REGNUM_PC, -#elif _TARGET_ARM64_ +#elif TARGET_ARM64 REGNUM_X0, REGNUM_X1, REGNUM_X2, @@ -129,7 +129,7 @@ public: REGNUM_LR, REGNUM_SP, REGNUM_PC, -#elif _TARGET_AMD64_ +#elif TARGET_AMD64 REGNUM_RAX, REGNUM_RCX, REGNUM_RDX, @@ -153,18 +153,18 @@ public: REGNUM_AMBIENT_SP, // ambient SP support. Ambient SP is the original SP in the non-BP based frame. // Ambient SP should not change even if there are push/pop operations in the method. -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 REGNUM_FP = REGNUM_EBP, REGNUM_SP = REGNUM_ESP, -#elif _TARGET_AMD64_ +#elif TARGET_AMD64 REGNUM_SP = REGNUM_RSP, -#elif _TARGET_ARM_ +#elif TARGET_ARM #ifdef REDHAWK REGNUM_FP = REGNUM_R7, #else REGNUM_FP = REGNUM_R11, #endif //REDHAWK -#elif _TARGET_ARM64_ +#elif TARGET_ARM64 //Nothing to do here. FP is already alloted. #else // RegNum values should be properly defined for this platform @@ -174,7 +174,7 @@ public: }; - // VarLoc describes the location of a native variable. Note that currently, VLT_REG_BYREF and VLT_STK_BYREF + // VarLoc describes the location of a native variable. Note that currently, VLT_REG_BYREF and VLT_STK_BYREF // are only used for value types on X64. enum VarLocType diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/coredistools.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/coredistools.h index 5414605..fbca14f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/coredistools.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/coredistools.h @@ -70,7 +70,7 @@ typedef bool(__cdecl *OffsetComparator)(const void *UserData, size_t BlockOffset uint64_t Offset2); // The Export/Import definitions for CoreDistools library are defined below. -// A typedef for each interface function's type is defined in order to aid +// A typedef for each interface function's type is defined in order to aid // the importer. // Initialize the disassembler, using default print controls diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corerror.xml b/CoreCLRProfiler/native/coreclr_headers/src/inc/corerror.xml index 38efe0d..94fe6a1 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corerror.xml +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corerror.xml @@ -303,7 +303,7 @@ "The native image could not be loaded, because it was generated for use by a different version of the runtime." The native image could not be loaded, because it was generated for use by a different version of the runtime. - + COR_E_LOADING_WINMD_REFERENCE_ASSEMBLY "Contract Windows Runtime assemblies cannot be loaded for execution. Make sure your application only contains non-contract Windows Runtime assemblies." @@ -845,13 +845,13 @@ CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY_ON_WIN64 - "SetIP is not possible because it would move EIP from within a finally clause to a point outside of one on WIN64 platforms." + "SetIP is not possible because it would move EIP from within a finally clause to a point outside of one on this platforms." SetIP isn't possible because it would move CORDBG_E_CANT_SET_IP_OUT_OF_CATCH_ON_WIN64 - "SetIP is not possible because it would move EIP from within a catch clause to a point outside of one on WIN64 platforms." + "SetIP is not possible because it would move EIP from within a catch clause to a point outside of one on this platforms." SetIP isn't possible because it would move @@ -876,11 +876,11 @@ CORDBG_E_NON_MATCHING_CONTEXT "The provided CONTEXT does not match the specified thread." - The provided CONTEXT does not match the specified thread. - The stack pointer in the provided CONTEXT must match the cached stack base and stack limit of the thread. + The provided CONTEXT does not match the specified thread. + The stack pointer in the provided CONTEXT must match the cached stack base and stack limit of the thread. - + CORDBG_E_PAST_END_OF_STACK "The stackwalker is now past the end of stack. No information is available." @@ -1018,7 +1018,7 @@ "The debugger can only handle a finite number of debuggees." The debugger can only handle a finite number of debuggees. - + CORDBG_E_INTEROP_NOT_SUPPORTED "Interop debugging is not supported." @@ -1175,7 +1175,7 @@ CORPROF_E_UNSUPPORTED_FOR_ATTACHING_PROFILER This call was attempted by a profiler that attached to the process after startup, but this call is only supported by profilers that are loaded into the process on startup. - + CORPROF_E_IRREVERSIBLE_INSTRUMENTATION_PRESENT Detach is impossible because the profiler has either instrumented IL or inserted enter/leave hooks. Detach was not attempted; the profiler is still fully attached. @@ -1245,7 +1245,7 @@ CORPROF_E_CALLBACK6_REQUIRED Profiler must implement ICorProfilerCallback6 interface for this call to be supported. - + - + CORPROF_E_CALLBACK7_REQUIRED Profiler must implement ICorProfilerCallback7 interface for this call to be supported. @@ -2059,7 +2059,7 @@ CORDBG_E_DETACH_FAILED_OUTSTANDING_TARGET_RESOURCES "Detach failed because there are outstanding resources in the target." - The debugger is holding resource in the target (such as GC handles, function evaluations, etc). + The debugger is holding resource in the target (such as GC handles, function evaluations, etc). These resources must be released through the appropriate ICorDebug API before detach can succeed. @@ -2164,7 +2164,7 @@ "The specified action is unsupported by this version of the runtime." The specified action is unsupported by this version of the runtime. - + CORDBG_E_MISSING_DEBUGGER_EXPORTS "The debuggee memory space does not have the expected debugging export table." diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corexcep.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/corexcep.h index 9235a98..bdfa8cf 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corexcep.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corexcep.h @@ -30,7 +30,7 @@ #endif // This is the exception code to report SetupThread failure to caller of reverse pinvoke -// It is misleading to use our COM+ exception code, since this is not a managed exception. +// It is misleading to use our COM+ exception code, since this is not a managed exception. // In the end, we picked e0455858 (EXX). #define EXCEPTION_EXX 0xe0455858 // 0xe0000000 | 'EXX' #endif // __COREXCEP_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corhdr.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/corhdr.h index 18b4dec..abef978 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corhdr.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corhdr.h @@ -5,14 +5,14 @@ /***************************************************************************** ** ** ** CorHdr.h - contains definitions for the Runtime structures, ** -** +** ** needed to work with metadata. ** ** ** *****************************************************************************/ // -// The top most managed code structure in a EXE or DLL is the IMAGE_COR20_HEADER -// see code:#ManagedHeader for more +// The top most managed code structure in a EXE or DLL is the IMAGE_COR20_HEADER +// see code:#ManagedHeader for more #ifndef __CORHDR_H__ #define __CORHDR_H__ @@ -21,7 +21,7 @@ #define FRAMEWORK_REGISTRY_KEY_W W("Software\\Microsoft\\.NETFramework") // keys for HKCU -#ifdef _WIN64 +#ifdef HOST_64BIT #define USER_FRAMEWORK_REGISTRY_KEY "Software\\Microsoft\\.NETFramework64" #define USER_FRAMEWORK_REGISTRY_KEY_W W("Software\\Microsoft\\.NETFramework64") #else @@ -145,7 +145,7 @@ typedef enum ReplacesCorHdrNumericDefines COMIMAGE_FLAGS_NATIVE_ENTRYPOINT =0x00000010, COMIMAGE_FLAGS_TRACKDEBUGDATA =0x00010000, COMIMAGE_FLAGS_32BITPREFERRED =0x00020000, // *** Do not manipulate this bit directly (see notes above) - + // Version flags for image. COR_VERSION_MAJOR_V2 =2, @@ -155,12 +155,12 @@ typedef enum ReplacesCorHdrNumericDefines COR_VTABLEGAP_NAME_LENGTH =8, // Maximum size of a NativeType descriptor. - NATIVE_TYPE_MAX_CB =1, + NATIVE_TYPE_MAX_CB =1, COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE=0xFF, // V-table constants - COR_VTABLE_32BIT =0x01, // V-table slots are 32-bits in size. - COR_VTABLE_64BIT =0x02, // V-table slots are 64-bits in size. + COR_VTABLE_32BIT =0x01, // V-table slots are 32-bits in size. + COR_VTABLE_64BIT =0x02, // V-table slots are 64-bits in size. COR_VTABLE_FROM_UNMANAGED =0x04, // If set, transition from unmanaged. COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN=0x08, // NEW COR_VTABLE_CALL_MOST_DERIVED =0x10, // Call most derived method described by @@ -168,73 +168,73 @@ typedef enum ReplacesCorHdrNumericDefines // EATJ constants IMAGE_COR_EATJ_THUNK_SIZE = 32, // Size of a jump thunk reserved range. -// Max name lengths +// Max name lengths //@todo: Change to unlimited name lengths. MAX_CLASS_NAME =1024, MAX_PACKAGE_NAME =1024, } ReplacesCorHdrNumericDefines; // #ManagedHeader -// +// // A managed code EXE or DLL uses the same basic format that unmanaged executables use call the Portable // Executable (PE) format. See http://en.wikipedia.org/wiki/Portable_Executable or // http://msdn.microsoft.com/msdnmag/issues/02/02/PE/default.aspx for more on this format and RVAs. -// +// // PE files define fixed table of well known entry pointers call Directory entries. Each entry holds the // relative virtual address (RVA) and length of a blob of data within the PE file. You can see these using // the command -// +// // link /dump /headers -// -// +// +// // Managed code has defined one of these entries (the 14th see code:IMAGE_DIRECTORY_ENTRY_COMHEADER) and the RVA points // that the IMAGE_COR20_HEADER. This header shows up in the previous dump as the following line -// +// // // Managed code is identified by is following line -// +// // 2008 [ 48] RVA [size] of COM Descriptor Directory // -// The IMAGE_COR20_HEADER is mostly just RVA:Length pairs (pointers) to other interesting data structures. +// The IMAGE_COR20_HEADER is mostly just RVA:Length pairs (pointers) to other interesting data structures. // The most important of these is the MetaData tables. The easiest way of looking at meta-data is using -// the IlDasm.exe tool. -// +// the IlDasm.exe tool. +// // MetaData holds most of the information in the IL image. The exceptions are resource blobs and the IL // instructions streams for individual methods. Instead the Meta-data for a method holds an RVA to a -// code:IMAGE_COR_ILMETHOD which holds all the IL stream (and exception handling information). -// +// code:IMAGE_COR_ILMETHOD which holds all the IL stream (and exception handling information). +// // Precompiled (NGEN) images use the same IMAGE_COR20_HEADER but also use the ManagedNativeHeader field to -// point at structures that only exist in precompiled images. -// +// point at structures that only exist in precompiled images. +// typedef struct IMAGE_COR20_HEADER { // Header versioning - DWORD cb; + DWORD cb; WORD MajorRuntimeVersion; WORD MinorRuntimeVersion; - + // Symbol table and startup information - IMAGE_DATA_DIRECTORY MetaData; - DWORD Flags; - + IMAGE_DATA_DIRECTORY MetaData; + DWORD Flags; + // The main program if it is an EXE (not used if a DLL?) // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set, EntryPointToken represents a managed entrypoint. // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set, EntryPointRVA represents an RVA to a native entrypoint - // (depricated for DLLs, use modules constructors intead). + // (depricated for DLLs, use modules constructors intead). union { DWORD EntryPointToken; DWORD EntryPointRVA; }; - + // This is the blob of managed resources. Fetched using code:AssemblyNative.GetResource and // code:PEFile.GetResource and accessible from managed code from // System.Assembly.GetManifestResourceStream. The meta data has a table that maps names to offsets into - // this blob, so logically the blob is a set of resources. + // this blob, so logically the blob is a set of resources. IMAGE_DATA_DIRECTORY Resources; // IL assemblies can be signed with a public-private key to validate who created it. The signature goes - // here if this feature is used. + // here if this feature is used. IMAGE_DATA_DIRECTORY StrongNameSignature; - IMAGE_DATA_DIRECTORY CodeManagerTable; // Depricated, not used + IMAGE_DATA_DIRECTORY CodeManagerTable; // Depricated, not used // Used for manged codee that has unmaanaged code inside it (or exports methods as unmanaged entry points) IMAGE_DATA_DIRECTORY VTableFixups; IMAGE_DATA_DIRECTORY ExportAddressTableJumps; @@ -242,14 +242,14 @@ typedef struct IMAGE_COR20_HEADER // null for ordinary IL images. In NGEN images it points at a code:CORCOMPILE_HEADER structure. // In Ready2Run images it points to a READYTORUN_HEADER. IMAGE_DATA_DIRECTORY ManagedNativeHeader; - + } IMAGE_COR20_HEADER, *PIMAGE_COR20_HEADER; #else // !__IMAGE_COR20_HEADER_DEFINED__ // @TODO: This is required because we pull in the COM+ 2.0 PE header // definition from WinNT.h, and these constants have not yet propogated to there. -// +// #define COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN 0x08 #define COMIMAGE_FLAGS_32BITPREFERRED 0x00020000 @@ -742,7 +742,7 @@ typedef enum CorPinvokeMap typedef enum CorAssemblyFlags { afPublicKey = 0x0001, // The assembly ref holds the full (unhashed) public key. - + afPA_None = 0x0000, // Processor Architecture unspecified afPA_MSIL = 0x0010, // Processor Architecture: neutral (PE32) afPA_x86 = 0x0020, // Processor Architecture: x86 (PE32) @@ -763,8 +763,8 @@ typedef enum CorAssemblyFlags afRetargetable = 0x0100, // The assembly can be retargeted (at runtime) to an // assembly from a different publisher. - afContentType_Default = 0x0000, - afContentType_WindowsRuntime = 0x0200, + afContentType_Default = 0x0000, + afContentType_WindowsRuntime = 0x0200, afContentType_Mask = 0x0E00, // Bits describing ContentType } CorAssemblyFlags; @@ -833,16 +833,16 @@ typedef enum CorPEKind // GenericParam bits, used by DefineGenericParam. typedef enum CorGenericParamAttr { - // Variance of type parameters, only applicable to generic parameters + // Variance of type parameters, only applicable to generic parameters // for generic interfaces and delegates gpVarianceMask = 0x0003, - gpNonVariant = 0x0000, + gpNonVariant = 0x0000, gpCovariant = 0x0001, gpContravariant = 0x0002, // Special constraints, applicable to any type parameters gpSpecialConstraintMask = 0x001C, - gpNoSpecialConstraint = 0x0000, + gpNoSpecialConstraint = 0x0000, gpReferenceTypeConstraint = 0x0004, // type argument must be a reference type gpNotNullableValueTypeConstraint = 0x0008, // type argument must be a value type but not Nullable gpDefaultConstructorConstraint = 0x0010, // type argument must have a public default constructor @@ -1176,9 +1176,9 @@ typedef struct IMAGE_COR_ILMETHOD_SECT_EH_FAT /***********************************/ typedef struct IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL { -#ifdef _WIN64 +#ifdef HOST_64BIT unsigned Flags : 16; -#else // !_WIN64 +#else // !HOST_64BIT CorExceptionFlag Flags : 16; #endif unsigned TryOffset : 16; @@ -1209,17 +1209,17 @@ typedef union IMAGE_COR_ILMETHOD_SECT_EH /***********************************************************************************/ -// Legal values for -// * code:IMAGE_COR_ILMETHOD_FAT::Flags or -// * code:IMAGE_COR_ILMETHOD_TINY::Flags_CodeSize fields. -// +// Legal values for +// * code:IMAGE_COR_ILMETHOD_FAT::Flags or +// * code:IMAGE_COR_ILMETHOD_TINY::Flags_CodeSize fields. +// // The only semantic flag at present is CorILMethod_InitLocals typedef enum CorILMethodFlags { CorILMethod_InitLocals = 0x0010, // call default constructor on all local vars CorILMethod_MoreSects = 0x0008, // there is another attribute after this one - CorILMethod_CompressedIL = 0x0040, // Not used. + CorILMethod_CompressedIL = 0x0040, // Not used. // Indicates the format for the COR_ILMETHOD header CorILMethod_FormatShift = 3, @@ -1253,7 +1253,7 @@ typedef struct IMAGE_COR_ILMETHOD_FAT // an IMAGE_COR_ILMETHOD holds the IL instructions for a individual method. To save space they come in two // flavors Fat and Tiny. Conceptually Tiny is just a compressed version of Fat, so code:IMAGE_COR_ILMETHOD_FAT // is the logical structure for all headers. Conceptually this blob holds the IL, the Exception Handling -// Tables, the local variable information and some flags. +// Tables, the local variable information and some flags. typedef union IMAGE_COR_ILMETHOD { IMAGE_COR_ILMETHOD_TINY Tiny; @@ -1444,7 +1444,7 @@ typedef enum CorLinkerOptions typedef enum MergeFlags { MergeFlagsNone = 0, - MergeManifest = 0x00000001, + MergeManifest = 0x00000001, DropMemberRefCAs = 0x00000002, NoDupCheck = 0x00000004, MergeExportedTypes = 0x00000008 @@ -1563,7 +1563,7 @@ typedef enum CorOpenFlags ofReadOnly = 0x00000010, // Open scope for read. Will be unable to QI for a IMetadataEmit* interface ofTakeOwnership = 0x00000020, // The memory was allocated with CoTaskMemAlloc and will be freed by the metadata - + // These are obsolete and are ignored. // ofCacheImage = 0x00000004, // EE maps but does not do relocations or verify image // ofManifestMetadata = 0x00000008, // Open scope on ngen image, return the manifest metadata instead of the IL metadata @@ -1588,14 +1588,14 @@ typedef enum CorOpenFlags #define IsOfReserved(x) (((x) & ofReserved) != 0) -// +// // Type of file mapping returned by code:IMetaDataInfo::GetFileMapping. -// +// typedef enum CorFileMapping { - fmFlat = 0, // Flat file mapping - file is mapped as data file (code:SEC_IMAGE flag was not + fmFlat = 0, // Flat file mapping - file is mapped as data file (code:SEC_IMAGE flag was not // passed to code:CreateFileMapping). - fmExecutableImage = 1, // Executable image file mapping - file is mapped for execution + fmExecutableImage = 1, // Executable image file mapping - file is mapped for execution // (either via code:LoadLibrary or code:CreateFileMapping with code:SEC_IMAGE flag). } CorFileMapping; @@ -1827,7 +1827,7 @@ typedef enum CorAttributeTargets typedef enum CompilationRelaxationsEnum { CompilationRelaxations_NoStringInterning = 0x0008, - + } CompilationRelaxationEnum; #define COMPILATIONRELAXATIONS_TYPE_W W("System.Runtime.CompilerServices.CompilationRelaxationsAttribute") @@ -1842,12 +1842,12 @@ typedef enum CompilationRelaxationsEnum // Keep in sync with AssemblySettingAttributes.cs typedef enum NGenHintEnum -{ +{ NGenDefault = 0x0000, // No preference specified NGenEager = 0x0001, // NGen at install time NGenLazy = 0x0002, // NGen after install time - NGenNever = 0x0003 // Assembly should not be ngened + NGenNever = 0x0003 // Assembly should not be ngened } NGenHintEnum; typedef enum LoadHintEnum @@ -1894,10 +1894,10 @@ typedef enum CorSaveSize } CorSaveSize; #endif -#define COR_IS_METHOD_MANAGED_IL(flags) ((flags & 0xf) == (miIL | miManaged)) -#define COR_IS_METHOD_MANAGED_OPTIL(flags) ((flags & 0xf) == (miOPTIL | miManaged)) -#define COR_IS_METHOD_MANAGED_NATIVE(flags) ((flags & 0xf) == (miNative | miManaged)) -#define COR_IS_METHOD_UNMANAGED_NATIVE(flags) ((flags & 0xf) == (miNative | miUnmanaged)) +#define COR_IS_METHOD_MANAGED_IL(flags) (((flags) & 0xf) == (miIL | miManaged)) +#define COR_IS_METHOD_MANAGED_OPTIL(flags) (((flags) & 0xf) == (miOPTIL | miManaged)) +#define COR_IS_METHOD_MANAGED_NATIVE(flags) (((flags) & 0xf) == (miNative | miManaged)) +#define COR_IS_METHOD_UNMANAGED_NATIVE(flags) (((flags) & 0xf) == (miNative | miUnmanaged)) // // Enum used with NATIVE_TYPE_ARRAY. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlpr.cpp b/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlpr.cpp index ba803a5..da6700c 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlpr.cpp +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlpr.cpp @@ -34,7 +34,7 @@ extern "C" { void __stdcall DecoderInit(void *pThis, COR_ILMETHOD *header) { COR_ILMETHOD_DECODER *decoder = (COR_ILMETHOD_DECODER *)pThis; - + memset(decoder, 0, sizeof(COR_ILMETHOD_DECODER)); if (header->Tiny.IsTiny()) { @@ -46,7 +46,7 @@ void __stdcall DecoderInit(void *pThis, COR_ILMETHOD *header) } if (header->Fat.IsFat()) { -#ifdef _WIN64 +#ifdef HOST_64BIT if((((size_t) header) & 3) == 0) // header is aligned #else _ASSERTE((((size_t) header) & 3) == 0); // header is aligned @@ -75,10 +75,10 @@ void __stdcall DecoderInit(void *pThis, COR_ILMETHOD *header) int __stdcall DecoderGetOnDiskSize(void * pThis, COR_ILMETHOD* header) { COR_ILMETHOD_DECODER* decoder = (COR_ILMETHOD_DECODER*)pThis; - + if (decoder->Code == NULL) return 0; - + BYTE *lastAddr = (BYTE*)decoder->Code + decoder->GetCodeSize(); // addr of end of code const COR_ILMETHOD_SECT *sect = decoder->EH; if (sect != 0 && sect->Next() == 0) @@ -119,7 +119,7 @@ unsigned __stdcall IlmethodSize(COR_ILMETHOD_FAT* header, BOOL moreSections) unsigned __stdcall IlmethodEmit(unsigned size, COR_ILMETHOD_FAT* header, BOOL moreSections, BYTE* outBuff) { -#ifndef SOS_INCLUDE +#ifndef SOS_INCLUDE #ifdef _DEBUG BYTE* origBuff = outBuff; #endif @@ -140,7 +140,7 @@ unsigned __stdcall IlmethodEmit(unsigned size, COR_ILMETHOD_FAT* header, fatHeader->SetFlags(fatHeader->GetFlags() | CorILMethod_MoreSects); fatHeader->SetSize(sizeof(COR_ILMETHOD_FAT) / 4); } -#ifndef SOS_INCLUDE +#ifndef SOS_INCLUDE _ASSERTE(&origBuff[size] == outBuff); #endif // !SOS_INCLUDE return(size); @@ -254,7 +254,7 @@ unsigned __stdcall SectEH_Emit(unsigned size, unsigned ehCount, EHSect->Kind = CorILMethod_Sect_EHTable; if (moreSections) EHSect->Kind |= CorILMethod_Sect_MoreSects; -#ifndef SOS_INCLUDE +#ifndef SOS_INCLUDE EHSect->DataSize = EHSect->Size(ehCount); #else EHSect->DataSize = (BYTE) EHSect->Size(ehCount); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlpr.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlpr.h index 5b263a5..0ef8fbf 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlpr.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlpr.h @@ -12,8 +12,8 @@ #ifndef __CORHLPR_H__ #define __CORHLPR_H__ -#if defined(_MSC_VER) && defined(_X86_) && !defined(FPO_ON) -#pragma optimize("y", on) // Small critical routines, don't put in EBP frame +#if defined(_MSC_VER) && defined(HOST_X86) && !defined(FPO_ON) +#pragma optimize("y", on) // Small critical routines, don't put in EBP frame #define FPO_ON 1 #define CORHLPR_TURNED_FPO_ON 1 #endif @@ -21,6 +21,7 @@ #include "cor.h" #include "corhdr.h" #include "corerror.h" +#include "unreachable.h" // This header is consumed both within the runtime and externally. In the former // case we need to wrap memory allocations, in the latter there is no @@ -43,6 +44,7 @@ inline void DECLSPEC_NORETURN THROW_OUT_OF_MEMORY() static inline void DECLSPEC_NORETURN __CorHlprThrowOOM() { RaiseException(STATUS_NO_MEMORY, 0, 0, NULL); + __UNREACHABLE(); } static inline BYTE *__CorHlprNewThrows(size_t bytes) { @@ -135,13 +137,13 @@ inline bool isCallConv(unsigned sigByte, CorCallingConvention conv) //***************************************************************************** typedef struct tagCOR_ILMETHOD_SECT_SMALL : IMAGE_COR_ILMETHOD_SECT_SMALL { //Data follows - const BYTE* Data() const - { - return(((const BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_SECT_SMALL)); + const BYTE* Data() const + { + return(((const BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_SECT_SMALL)); } bool IsSmall() const - { + { return (Kind & CorILMethod_Sect_FatFormat) == 0; } @@ -156,9 +158,9 @@ typedef struct tagCOR_ILMETHOD_SECT_SMALL : IMAGE_COR_ILMETHOD_SECT_SMALL { /* NOTE this structure must be DWORD aligned!! */ typedef struct tagCOR_ILMETHOD_SECT_FAT : IMAGE_COR_ILMETHOD_SECT_FAT { //Data follows - const BYTE* Data() const - { - return(((const BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_SECT_FAT)); + const BYTE* Data() const + { + return(((const BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_SECT_FAT)); } //Endian-safe wrappers @@ -322,23 +324,23 @@ struct COR_ILMETHOD_SECT_EH_SMALL : public COR_ILMETHOD_SECT_SMALL { /* NOTE this structure must be DWORD aligned!! */ struct COR_ILMETHOD_SECT { - bool More() const - { - return((AsSmall()->Kind & CorILMethod_Sect_MoreSects) != 0); + bool More() const + { + return((AsSmall()->Kind & CorILMethod_Sect_MoreSects) != 0); } CorILMethodSect Kind() const - { - return((CorILMethodSect) (AsSmall()->Kind & CorILMethod_Sect_KindMask)); + { + return((CorILMethodSect) (AsSmall()->Kind & CorILMethod_Sect_KindMask)); } - const COR_ILMETHOD_SECT* Next() const + const COR_ILMETHOD_SECT* Next() const { if (!More()) return(0); return ((COR_ILMETHOD_SECT*)(((BYTE *)this) + DataSize()))->Align(); } - const BYTE* Data() const + const BYTE* Data() const { if (IsFat()) return(AsFat()->Data()); return(AsSmall()->Data()); @@ -346,11 +348,11 @@ struct COR_ILMETHOD_SECT unsigned DataSize() const { - if (Kind() == CorILMethod_Sect_EHTable) + if (Kind() == CorILMethod_Sect_EHTable) { // VB and MC++ shipped with bug where they have not accounted for size of COR_ILMETHOD_SECT_EH_XXX // in DataSize. To avoid breaking these images, we will align the size of EH sections up. This works - // because IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_XXX is bigger than COR_ILMETHOD_SECT_EH_XXX + // because IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_XXX is bigger than COR_ILMETHOD_SECT_EH_XXX // (see VSWhidbey #99031 and related bugs for details). if (IsFat()) @@ -368,25 +370,25 @@ struct COR_ILMETHOD_SECT friend struct COR_ILMETHOD; friend struct tagCOR_ILMETHOD_FAT; friend struct tagCOR_ILMETHOD_TINY; - bool IsFat() const - { - return((AsSmall()->Kind & CorILMethod_Sect_FatFormat) != 0); + bool IsFat() const + { + return((AsSmall()->Kind & CorILMethod_Sect_FatFormat) != 0); } - const COR_ILMETHOD_SECT* Align() const - { - return((COR_ILMETHOD_SECT*) ((((UINT_PTR) this) + 3) & ~3)); + const COR_ILMETHOD_SECT* Align() const + { + return((COR_ILMETHOD_SECT*) ((((UINT_PTR) this) + 3) & ~3)); } protected: - const COR_ILMETHOD_SECT_FAT* AsFat() const - { - return((COR_ILMETHOD_SECT_FAT*) this); + const COR_ILMETHOD_SECT_FAT* AsFat() const + { + return((COR_ILMETHOD_SECT_FAT*) this); } const COR_ILMETHOD_SECT_SMALL* AsSmall() const - { - return((COR_ILMETHOD_SECT_SMALL*) this); + { + return((COR_ILMETHOD_SECT_SMALL*) this); } public: @@ -424,7 +426,7 @@ unsigned __stdcall SectEH_Emit(unsigned size, unsigned ehCount, struct COR_ILMETHOD_SECT_EH : public COR_ILMETHOD_SECT { - unsigned EHCount() const + unsigned EHCount() const { return (unsigned)(IsFat() ? (Fat.GetDataSize() / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT)) : (Small.DataSize / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL))); @@ -432,27 +434,27 @@ struct COR_ILMETHOD_SECT_EH : public COR_ILMETHOD_SECT // return one clause in its fat form. Use 'buff' if needed const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* EHClause(unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff) const - { - return SectEH_EHClause((void *)this, idx, buff); + { + return SectEH_EHClause((void *)this, idx, buff); }; // compute the size of the section (best format) // codeSize is the size of the method // deprecated unsigned static Size(unsigned ehCount, unsigned codeSize) - { - return SectEH_SizeWithCode(ehCount, codeSize); + { + return SectEH_SizeWithCode(ehCount, codeSize); }; // will return worse-case size and then Emit will return actual size unsigned static Size(unsigned ehCount) - { - return SectEH_SizeWorst(ehCount); + { + return SectEH_SizeWorst(ehCount); }; // will return exact size which will match the size returned by Emit unsigned static Size(unsigned ehCount, const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses) - { - return SectEH_SizeExact(ehCount, (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)clauses); + { + return SectEH_SizeExact(ehCount, (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)clauses); }; // emit the section (best format); @@ -460,10 +462,10 @@ struct COR_ILMETHOD_SECT_EH : public COR_ILMETHOD_SECT const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses, bool moreSections, BYTE* outBuff, ULONG* ehTypeOffsets = 0) - { + { return SectEH_Emit(size, ehCount, (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)clauses, - moreSections, outBuff, ehTypeOffsets); + moreSections, outBuff, ehTypeOffsets); }; }; @@ -472,34 +474,34 @@ struct COR_ILMETHOD_SECT_EH : public COR_ILMETHOD_SECT /* Used when the method is tiny (< 64 bytes), and there are no local vars */ typedef struct tagCOR_ILMETHOD_TINY : IMAGE_COR_ILMETHOD_TINY { - bool IsTiny() const - { - return((Flags_CodeSize & (CorILMethod_FormatMask >> 1)) == CorILMethod_TinyFormat); + bool IsTiny() const + { + return((Flags_CodeSize & (CorILMethod_FormatMask >> 1)) == CorILMethod_TinyFormat); } - unsigned GetCodeSize() const - { - return(((unsigned) Flags_CodeSize) >> (CorILMethod_FormatShift-1)); + unsigned GetCodeSize() const + { + return(((unsigned) Flags_CodeSize) >> (CorILMethod_FormatShift-1)); } - unsigned GetMaxStack() const - { - return(8); + unsigned GetMaxStack() const + { + return(8); } - BYTE* GetCode() const - { - return(((BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_TINY)); + BYTE* GetCode() const + { + return(((BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_TINY)); } - DWORD GetLocalVarSigTok() const - { - return(0); + DWORD GetLocalVarSigTok() const + { + return(0); } - COR_ILMETHOD_SECT* GetSect() const - { - return(0); + COR_ILMETHOD_SECT* GetSect() const + { + return(0); } } COR_ILMETHOD_TINY; @@ -547,24 +549,24 @@ typedef struct tagCOR_ILMETHOD_FAT : IMAGE_COR_ILMETHOD_FAT *(USHORT*)((BYTE*)this+2) = VAL16((USHORT)maxStack); } - unsigned GetCodeSize() const - { - return VAL32(CodeSize); + unsigned GetCodeSize() const + { + return VAL32(CodeSize); } - void SetCodeSize(DWORD Size) - { - CodeSize = VAL32(Size); + void SetCodeSize(DWORD Size) + { + CodeSize = VAL32(Size); } - mdToken GetLocalVarSigTok() const - { - return VAL32(LocalVarSigTok); + mdToken GetLocalVarSigTok() const + { + return VAL32(LocalVarSigTok); } - void SetLocalVarSigTok(mdSignature tok) - { - LocalVarSigTok = VAL32(tok); + void SetLocalVarSigTok(mdSignature tok) + { + LocalVarSigTok = VAL32(tok); } BYTE* GetCode() const { @@ -600,14 +602,14 @@ struct COR_ILMETHOD // compute the size of the header (best format) unsigned static Size(const COR_ILMETHOD_FAT* header, bool MoreSections) - { - return IlmethodSize((COR_ILMETHOD_FAT*)header,MoreSections); + { + return IlmethodSize((COR_ILMETHOD_FAT*)header,MoreSections); }; // emit the header (bestFormat) return amount emitted unsigned static Emit(unsigned size, const COR_ILMETHOD_FAT* header, bool moreSections, BYTE* outBuff) - { - return IlmethodEmit(size, (COR_ILMETHOD_FAT*)header, moreSections, outBuff); + { + return IlmethodEmit(size, (COR_ILMETHOD_FAT*)header, moreSections, outBuff); }; //private: @@ -639,9 +641,9 @@ public: // Typically the ONLY way you should access COR_ILMETHOD is through // this constructor so format changes are easier. - COR_ILMETHOD_DECODER(const COR_ILMETHOD* header) - { - DecoderInit(this,(COR_ILMETHOD*)header); + COR_ILMETHOD_DECODER(const COR_ILMETHOD* header) + { + DecoderInit(this,(COR_ILMETHOD*)header); }; // The above variant of the constructor can not do a 'complete' job, because @@ -659,11 +661,11 @@ public: // Because we may be able to demand SkipVerification and thus it was OK // to have had a verification error. - COR_ILMETHOD_DECODER(COR_ILMETHOD* header, + COR_ILMETHOD_DECODER(COR_ILMETHOD* header, void *pInternalImport, DecoderStatus* wbStatus); - unsigned EHCount() const + unsigned EHCount() const { return (EH != 0) ? EH->EHCount() : 0; } @@ -674,9 +676,9 @@ public: } // returns total size of method for use in copying - int GetOnDiskSize(const COR_ILMETHOD* header) - { - return DecoderGetOnDiskSize(this,(COR_ILMETHOD*)header); + int GetOnDiskSize(const COR_ILMETHOD* header) + { + return DecoderGetOnDiskSize(this,(COR_ILMETHOD*)header); } // Flags these are available because we inherit COR_ILMETHOD_FAT diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlprpriv.cpp b/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlprpriv.cpp index 47e0cb1..51f49e1 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlprpriv.cpp +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlprpriv.cpp @@ -47,7 +47,7 @@ HRESULT CQuickMemoryBase::ReSizeNoThrow(SIZE_T iItems) iSize = iItems; return NOERROR; } - + #ifdef _BLD_CLR #ifndef DACCESS_COMPILE // not allowed to do allocation if current thread suspends EE @@ -259,7 +259,7 @@ HRESULT _GetFixedSigOfVarArg( // S_OK or error. { return E_INVALIDARG; } - + cbCur += cbArgsNumber; // how many bytes to represent the return type diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlprpriv.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlprpriv.h index 5eeec20..8fcafd0 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlprpriv.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corhlprpriv.h @@ -14,7 +14,7 @@ #include "corhlpr.h" #include "fstring.h" -#if defined(_MSC_VER) && defined(_TARGET_X86_) +#if defined(_MSC_VER) && defined(TARGET_X86) #pragma optimize("y", on) // If routines don't get inlined, don't pay the EBP frame penalty #endif @@ -226,7 +226,7 @@ public: iSize = cbTotal; } - + // Convert UTF8 string to UNICODE string, optimized for speed HRESULT ConvertUtf8_UnicodeNoThrow(const char * utf8str) { @@ -309,7 +309,7 @@ public: } #ifdef DACCESS_COMPILE - void + void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) { // Assume that 'this' is enumerated, either explicitly @@ -317,7 +317,7 @@ public: DacEnumMemoryRegion(dac_cast(pbBuff), iSize); } #endif // DACCESS_COMPILE - + BYTE *pbBuff; SIZE_T iSize; // number of bytes used SIZE_T cbTotal; // total bytes allocated in the buffer @@ -385,68 +385,68 @@ template class CQuickArrayBase : public CQuickBytesBase { public: T* AllocThrows(SIZE_T iItems) - { + { CheckOverflowThrows(iItems); - return (T*)CQuickBytesBase::AllocThrows(iItems * sizeof(T)); + return (T*)CQuickBytesBase::AllocThrows(iItems * sizeof(T)); } void ReSizeThrows(SIZE_T iItems) - { + { CheckOverflowThrows(iItems); CQuickBytesBase::ReSizeThrows(iItems * sizeof(T)); } T* AllocNoThrow(SIZE_T iItems) - { + { if (!CheckOverflowNoThrow(iItems)) - { + { return NULL; } - return (T*)CQuickBytesBase::AllocNoThrow(iItems * sizeof(T)); + return (T*)CQuickBytesBase::AllocNoThrow(iItems * sizeof(T)); } HRESULT ReSizeNoThrow(SIZE_T iItems) - { + { if (!CheckOverflowNoThrow(iItems)) { return E_OUTOFMEMORY; } - return CQuickBytesBase::ReSizeNoThrow(iItems * sizeof(T)); + return CQuickBytesBase::ReSizeNoThrow(iItems * sizeof(T)); } - - void Shrink(SIZE_T iItems) - { - CQuickBytesBase::Shrink(iItems * sizeof(T)); + + void Shrink(SIZE_T iItems) + { + CQuickBytesBase::Shrink(iItems * sizeof(T)); } T* Ptr() - { - return (T*) CQuickBytesBase::Ptr(); + { + return (T*) CQuickBytesBase::Ptr(); } const T* Ptr() const - { - return (T*) CQuickBytesBase::Ptr(); + { + return (T*) CQuickBytesBase::Ptr(); } SIZE_T Size() const - { - return CQuickBytesBase::Size() / sizeof(T); + { + return CQuickBytesBase::Size() / sizeof(T); } SIZE_T MaxSize() const - { - return CQuickBytesBase::cbTotal / sizeof(T); + { + return CQuickBytesBase::cbTotal / sizeof(T); } T& operator[] (SIZE_T ix) - { + { _ASSERTE(ix < Size()); return *(Ptr() + ix); } const T& operator[] (SIZE_T ix) const - { + { _ASSERTE(ix < Size()); return *(Ptr() + ix); } @@ -521,14 +521,14 @@ public: // Can only access values that have been pushed. T& operator[] (SIZE_T ix) - { + { _ASSERTE(ix < m_curSize); return CQuickArray::operator[](ix); } // Can only access values that have been pushed. const T& operator[] (SIZE_T ix) const - { + { _ASSERTE(ix < m_curSize); return CQuickArray::operator[](ix); } @@ -614,7 +614,7 @@ public: void Reset() { - if (buffer.Size()) + if (buffer.Size()) { memset(&buffer[0], 0, buffer.Size()); } @@ -642,19 +642,19 @@ HRESULT _GetFixedSigOfVarArg( // S_OK or error. #endif //!SOS_INCLUDE -#if defined(_MSC_VER) && defined(_TARGET_X86_) +#if defined(_MSC_VER) && defined(TARGET_X86) #pragma optimize("", on) // restore command line default optimizations #endif //--------------------------------------------------------------------------------------- -// +// // Reads compressed integer from buffer pData, fills the result to *pnDataOut. Advances buffer pointer. // Doesn't read behind the end of the buffer (the end starts at pDataEnd). -// -inline -__checkReturn -HRESULT +// +inline +__checkReturn +HRESULT CorSigUncompressData_EndPtr( PCCOR_SIGNATURE & pData, // [IN,OUT] Buffer PCCOR_SIGNATURE pDataEnd, // End of buffer @@ -662,40 +662,40 @@ CorSigUncompressData_EndPtr( { _ASSERTE(pData <= pDataEnd); HRESULT hr = S_OK; - + INT_PTR cbDataSize = pDataEnd - pData; if (cbDataSize > 4) { // Compressed integer cannot be bigger than 4 bytes cbDataSize = 4; } DWORD dwDataSize = (DWORD)cbDataSize; - + ULONG cbDataOutLength; IfFailRet(CorSigUncompressData( - pData, - dwDataSize, - pnDataOut, + pData, + dwDataSize, + pnDataOut, &cbDataOutLength)); pData += cbDataOutLength; - + return hr; } // CorSigUncompressData_EndPtr //--------------------------------------------------------------------------------------- -// +// // Reads CorElementType (1 byte) from buffer pData, fills the result to *pTypeOut. Advances buffer pointer. // Doesn't read behind the end of the buffer (the end starts at pDataEnd). -// -inline -__checkReturn -HRESULT +// +inline +__checkReturn +HRESULT CorSigUncompressElementType_EndPtr( PCCOR_SIGNATURE & pData, // [IN,OUT] Buffer PCCOR_SIGNATURE pDataEnd, // End of buffer CorElementType * pTypeOut) // [OUT] ELEMENT_TYPE_* value read from the buffer { _ASSERTE(pData <= pDataEnd); - // We don't expect pData > pDataEnd, but the runtime check doesn't cost much and it is more secure in + // We don't expect pData > pDataEnd, but the runtime check doesn't cost much and it is more secure in // case caller has a bug if (pData >= pDataEnd) { // No data @@ -704,26 +704,26 @@ CorSigUncompressElementType_EndPtr( // Read 'type' as 1 byte *pTypeOut = (CorElementType)*pData; pData++; - + return S_OK; } // CorSigUncompressElementType_EndPtr //--------------------------------------------------------------------------------------- -// +// // Reads pointer (4/8 bytes) from buffer pData, fills the result to *ppvPointerOut. Advances buffer pointer. // Doesn't read behind the end of the buffer (the end starts at pDataEnd). -// -inline -__checkReturn -HRESULT +// +inline +__checkReturn +HRESULT CorSigUncompressPointer_EndPtr( PCCOR_SIGNATURE & pData, // [IN,OUT] Buffer PCCOR_SIGNATURE pDataEnd, // End of buffer void ** ppvPointerOut) // [OUT] Pointer value read from the buffer { _ASSERTE(pData <= pDataEnd); - // We could just skip this check as pointers should be only in trusted (and therefore correct) - // signatures and we check for that on the caller side, but it won't hurt to have this check and it will + // We could just skip this check as pointers should be only in trusted (and therefore correct) + // signatures and we check for that on the caller side, but it won't hurt to have this check and it will // make it easier to catch invalid signatures in trusted code (e.g. IL stubs, NGEN images, etc.) if (pData + sizeof(void *) > pDataEnd) { // Not enough data in the buffer @@ -732,18 +732,18 @@ CorSigUncompressPointer_EndPtr( } *ppvPointerOut = *(void * UNALIGNED *)pData; pData += sizeof(void *); - + return S_OK; } // CorSigUncompressPointer_EndPtr //--------------------------------------------------------------------------------------- -// +// // Reads compressed TypeDef/TypeRef/TypeSpec token, fills the result to *pnDataOut. Advances buffer pointer. // Doesn't read behind the end of the buffer (the end starts at pDataEnd). -// -inline -__checkReturn -HRESULT +// +inline +__checkReturn +HRESULT CorSigUncompressToken_EndPtr( PCCOR_SIGNATURE & pData, // [IN,OUT] Buffer PCCOR_SIGNATURE pDataEnd, // End of buffer @@ -751,22 +751,22 @@ CorSigUncompressToken_EndPtr( { _ASSERTE(pData <= pDataEnd); HRESULT hr = S_OK; - + INT_PTR cbDataSize = pDataEnd - pData; if (cbDataSize > 4) { // Compressed token cannot be bigger than 4 bytes cbDataSize = 4; } DWORD dwDataSize = (DWORD)cbDataSize; - + ULONG cbTokenOutLength; IfFailRet(CorSigUncompressToken( - pData, - dwDataSize, - ptkTokenOut, + pData, + dwDataSize, + ptkTokenOut, &cbTokenOutLength)); pData += cbTokenOutLength; - + return hr; } // CorSigUncompressToken_EndPtr diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corhost.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/corhost.h index 09ea994..81b000e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corhost.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corhost.h @@ -28,85 +28,19 @@ #include "holder.h" -#include "clrprivhosting.h" +#include "clrprivbinding.h" #ifdef FEATURE_COMINTEROP #include "activation.h" // WinRT activation. #endif -class DangerousNonHostedSpinLock; - -#define INVALID_STACK_BASE_MARKER_FOR_CHECK_STATE 2 - class AppDomain; class Assembly; - -class CorRuntimeHostBase -{ -protected: - CorRuntimeHostBase() - :m_Started(FALSE), - m_cRef(0) - {LIMITED_METHOD_CONTRACT;} - - STDMETHODIMP_(ULONG) AddRef(void); - - // Starts the runtime. This is equivalent to CoInitializeCor() - STDMETHODIMP Start(); - - STDMETHODIMP MapFile( // Return code. - HANDLE hFile, // [in] Handle for file - HMODULE *hMapAddress // [out] HINSTANCE for mapped file - ); - - STDMETHODIMP LocksHeldByLogicalThread( // Return code. - DWORD *pCount // [out] Number of locks that the current thread holds. - ); - -protected: - BOOL m_Started; // Has START been called? - - LONG m_cRef; // Ref count. - - static ULONG m_Version; // Version of ICorRuntimeHost. - // Some functions are only available in ICLRRuntimeHost. - // Some functions are no-op in ICLRRuntimeHost. - - STDMETHODIMP UnloadAppDomain(DWORD dwDomainId, BOOL fWaitUntilDone); - - STDMETHODIMP UnloadAppDomain2(DWORD dwDomainId, BOOL fWaitUntilDone, int *pLatchedExitCode); -public: - static ULONG GetHostVersion() - { - LIMITED_METHOD_CONTRACT; - _ASSERTE (m_Version != 0); - return m_Version; - } - -}; - - -class ConnectionNameTable; -typedef DPTR(class ConnectionNameTable) PTR_ConnectionNameTable; - -class CrstStatic; - -// Defines the precedence (in increading oder) of the two symbol reading knobs -enum ESymbolReadingSetBy -{ - eSymbolReadingSetByDefault, - eSymbolReadingSetByConfig, // EEConfig - config file, env var, etc. - eSymbolReadingSetByHost, // Hosting API - highest precedence - eSymbolReadingSetBy_COUNT -}; - -class CorHost2 : - public CorRuntimeHostBase -#ifndef FEATURE_PAL +class CorHost2 : ICLRRuntimeHost4 +#ifndef TARGET_UNIX , public IPrivateManagedExceptionReporting /* This interface is for internal Watson testing only*/ -#endif // FEATURE_PAL - , public ICLRRuntimeHost4 +#endif // TARGET_UNIX { friend struct _DacGlobals; @@ -116,20 +50,16 @@ public: // *** IUnknown methods *** STDMETHODIMP QueryInterface(REFIID riid, void** ppv); - STDMETHODIMP_(ULONG) AddRef(void) - { - WRAPPER_NO_CONTRACT; - return CorRuntimeHostBase::AddRef(); - } + STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); // *** ICorRuntimeHost methods *** -#ifndef FEATURE_PAL +#ifndef TARGET_UNIX // defined in IPrivateManagedExceptionReporting interface for internal Watson testing only STDMETHODIMP GetBucketParametersForCurrentException(BucketParameters *pParams); -#endif // FEATURE_PAL +#endif // TARGET_UNIX // Starts the runtime. This is equivalent to CoInitializeCor(). STDMETHODIMP Start(); @@ -139,26 +69,9 @@ public: FExecuteInAppDomainCallback pCallback, void * cookie); - STDMETHODIMP LocksHeldByLogicalThread( // Return code. - DWORD *pCount // [out] Number of locks that the current thread holds. - ) - { - WRAPPER_NO_CONTRACT; - return CorRuntimeHostBase::LocksHeldByLogicalThread(pCount); - } - // Class factory hook-up. static HRESULT CreateObject(REFIID riid, void **ppUnk); - STDMETHODIMP MapFile( // Return code. - HANDLE hFile, // [in] Handle for file - HMODULE *hMapAddress // [out] HINSTANCE for mapped file - ) - { - WRAPPER_NO_CONTRACT; - return CorRuntimeHostBase::MapFile(hFile,hMapAddress); - } - STDMETHODIMP STDMETHODCALLTYPE SetHostControl( IHostControl* pHostControl); @@ -188,17 +101,17 @@ public: STDMETHODIMP CreateAppDomainWithManager( LPCWSTR wszFriendlyName, DWORD dwSecurityFlags, - LPCWSTR wszAppDomainManagerAssemblyName, - LPCWSTR wszAppDomainManagerTypeName, - int nProperties, - LPCWSTR* pPropertyNames, - LPCWSTR* pPropertyValues, + LPCWSTR wszAppDomainManagerAssemblyName, + LPCWSTR wszAppDomainManagerTypeName, + int nProperties, + LPCWSTR* pPropertyNames, + LPCWSTR* pPropertyValues, DWORD* pAppDomainID); STDMETHODIMP CreateDelegate( DWORD appDomainID, - LPCWSTR wszAssemblyName, - LPCWSTR wszClassName, + LPCWSTR wszAssemblyName, + LPCWSTR wszClassName, LPCWSTR wszMethodName, INT_PTR* fnPtr); @@ -207,7 +120,7 @@ public: STDMETHODIMP RegisterMacEHPort(); STDMETHODIMP SetStartupFlags(STARTUP_FLAGS flag); STDMETHODIMP DllGetActivationFactory( - DWORD appDomainID, + DWORD appDomainID, LPCWSTR wszTypeName, IActivationFactory ** factory); @@ -226,6 +139,8 @@ public: } private: + LONG m_cRef; // COM ref count. + // This flag indicates if this instance was the first to load and start CoreCLR BOOL m_fFirstToLoadCLR; @@ -233,24 +148,6 @@ private: BOOL m_fStarted; BOOL m_fAppDomainCreated; // this flag is used when an appdomain can only create a single appdomain - // Helpers for both ICLRRuntimeHost2 and ICLRPrivRuntime - HRESULT _CreateAppDomain( - LPCWSTR wszFriendlyName, - DWORD dwFlags, - LPCWSTR wszAppDomainManagerAssemblyName, - LPCWSTR wszAppDomainManagerTypeName, - int nProperties, - LPCWSTR* pPropertyNames, - LPCWSTR* pPropertyValues, - DWORD* pAppDomainID); - - HRESULT _CreateDelegate( - DWORD appDomainID, - LPCWSTR wszAssemblyName, - LPCWSTR wszClassName, - LPCWSTR wszMethodName, - INT_PTR* fnPtr); - // entrypoint helper to be wrapped in a filter to process unhandled exceptions VOID ExecuteMainInner(Assembly* pRootAssembly); @@ -262,17 +159,11 @@ private: #ifdef FEATURE_COMINTEROP extern "C" HRESULT STDMETHODCALLTYPE DllGetActivationFactoryImpl( - LPCWSTR wszAssemblyName, - LPCWSTR wszTypeName, + LPCWSTR wszAssemblyName, + LPCWSTR wszTypeName, LPCWSTR wszCodeBase, IActivationFactory ** factory); #endif // defined(FEATURE_COMINTEROP) -extern SIZE_T Host_SegmentSize; -extern SIZE_T Host_MaxGen0Size; -extern BOOL Host_fSegmentSizeSet; -extern BOOL Host_fMaxGen0SizeSet; - -#define PARTIAL_TRUST_VISIBLE_ASSEMBLIES_PROPERTY W("PARTIAL_TRUST_VISIBLE_ASSEMBLIES") #endif // __CorHost__h__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corimage.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/corimage.h index 554eb20..8ec2755 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corimage.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corimage.h @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. -// +// /*============================================================ ** @@ -29,7 +29,7 @@ PIMAGE_SECTION_HEADER Cor_RtlImageRvaToSection(PTR_IMAGE_NT_HEADERS NtHeaders, ULONG Rva, ULONG FileLength); - + PIMAGE_SECTION_HEADER Cor_RtlImageRvaRangeToSection(PTR_IMAGE_NT_HEADERS NtHeaders, ULONG Rva, diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corinfo.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/corinfo.h index 9cc8490..2c8c126 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corinfo.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corinfo.h @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// +// /*****************************************************************************\ * * @@ -22,7 +22,7 @@ // The JIT/EE interface is versioned. By "interface", we mean mean any and all communication between the // JIT and the EE. Any time a change is made to the interface, the JIT/EE interface version identifier // must be updated. See code:JITEEVersionIdentifier for more information. -// +// // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE // ////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -38,9 +38,9 @@ code:EEStartup#TableOfContents for information on the runtime as a whole. ------------------------------------------------------------------------------- #Tokens -The tokens in IL stream needs to be resolved to EE handles (CORINFO_CLASS/METHOD/FIELD_HANDLE) that -the runtime operates with. ICorStaticInfo::resolveToken is the method that resolves the found in IL stream -to set of EE handles (CORINFO_RESOLVED_TOKEN). All other APIs take resolved token as input. This design +The tokens in IL stream needs to be resolved to EE handles (CORINFO_CLASS/METHOD/FIELD_HANDLE) that +the runtime operates with. ICorStaticInfo::resolveToken is the method that resolves the found in IL stream +to set of EE handles (CORINFO_RESOLVED_TOKEN). All other APIs take resolved token as input. This design avoids redundant token resolutions. The token validation is done as part of token resolution. The JIT is not required to do explicit upfront @@ -51,19 +51,19 @@ token validation. First of all class contruction comes in two flavors precise and 'beforeFieldInit'. In C# you get the former if you declare an explicit class constructor method and the later if you declaratively initialize static -fields. Precise class construction guarentees that the .cctor is run precisely before the first access to any -method or field of the class. 'beforeFieldInit' semantics guarentees only that the .cctor will be run some -time before the first static field access (note that calling methods (static or insance) or accessing +fields. Precise class construction guarantees that the .cctor is run precisely before the first access to any +method or field of the class. 'beforeFieldInit' semantics guarantees only that the .cctor will be run some +time before the first static field access (note that calling methods (static or instance) or accessing instance fields does not cause .cctors to be run). Next you need to know that there are two kinds of code generation that can happen in the JIT: appdomain neutral and appdomain specialized. The difference between these two kinds of code is how statics are handled. -For appdomain specific code, the address of a particular static variable is embeded in the code. This makes +For appdomain specific code, the address of a particular static variable is embedded in the code. This makes it usable only for one appdomain (since every appdomain gets a own copy of its statics). Appdomain neutral code calls a helper that looks up static variables off of a thread local variable. Thus the same code can be -used by mulitple appdomains in the same process. +used by multiple appdomains in the same process. -Generics also introduce a similar issue. Code for generic classes might be specialised for a particular set +Generics also introduce a similar issue. Code for generic classes might be specialized for a particular set of type arguments, or it could use helpers to access data that depends on type parameters and thus be shared across several instantiations of the generic type. @@ -98,7 +98,7 @@ Nevertheless, the cost of plugging these holes is considered to high and the ben ---------------------------------------------------------------------- -#ClassConstructionFlags +#ClassConstructionFlags Thus the JIT's cctor responsibilities require it to check with the EE on every static field access using initClass and before jitting any method to see if a .cctor check must be placed in the prolog. @@ -109,20 +109,20 @@ initClass and before jitting any method to see if a .cctor check must be placed classes with precise .cctor semantics do not allow this optimization. Inlining also complicates things. Because the class could have precise semantics it is also required that the -inlining of any constructor or static method must also do the initClass check. The inliner has the option of +inlining of any constructor or static method must also do the initClass check. The inliner has the option of inserting any required runtime check or simply not inlining the function. ------------------------------------------------------------------------------- #StaticFields -The first 4 options are mutially exclusive +The first 4 options are mutually exclusive * CORINFO_FLG_HELPER If the field has this set, then the JIT must call getFieldHelper and call the returned helper with the object ref (for an instance field) and a fieldDesc. Note that this should be able to handle ANY field so to get a JIT up quickly, it has the option of using helper calls for all field access (and skip the complexity below). Note that for statics it is assumed that you will - alwasy ask for the ADDRESSS helper and to the fetch in the JIT. + always ask for the ADDRESS helper and to the fetch in the JIT. * CORINFO_FLG_SHARED_HELPER This is currently only used for static fields. If this bit is set it means that the field is feched by a helper call that takes a module identifier (see getModuleDomainID) and @@ -156,11 +156,11 @@ by addr = (*addr+sizeof(OBJECTREF)) Instance fields * CORINFO_FLG_HELPER This is used if the class is MarshalByRef, which means that the object might be a - proxyt to the real object in some other appdomain or process. If the field has this set, then the JIT + proxy to the real object in some other appdomain or process. If the field has this set, then the JIT must call getFieldHelper and call the returned helper with the object ref. If the helper returned is helpers that are for structures the args are as follows - * CORINFO_HELP_GETFIELDSTRUCT - args are: retBuff, object, fieldDesc + * CORINFO_HELP_GETFIELDSTRUCT - args are: retBuff, object, fieldDesc * CORINFO_HELP_SETFIELDSTRUCT - args are object fieldDesc value The other GET helpers take an object fieldDesc and return the value The other SET helpers take an object @@ -172,11 +172,11 @@ fieldDesc and value CORINFO_FLG_EnC This is to support adding new field for edit and continue. This field also indicates that a helper is needed to access this field. However this helper is always CORINFO_HELP_GETFIELDADDR, and this helper always takes the object and field handle and returns the address of the field. It is the - JIT's responcibility to do the fetch or set. + JIT's responsibility to do the fetch or set. ------------------------------------------------------------------------------- -TODO: Talk about initializing strutures before use +TODO: Talk about initializing strutures before use ******************************************************************************* @@ -217,11 +217,11 @@ TODO: Talk about initializing strutures before use #endif #endif -SELECTANY const GUID JITEEVersionIdentifier = { /* d609bed1-7831-49fc-bd49-b6f054dd4d46 */ - 0xd609bed1, - 0x7831, - 0x49fc, - {0xbd, 0x49, 0xb6, 0xf0, 0x54, 0xdd, 0x4d, 0x46} +SELECTANY const GUID JITEEVersionIdentifier = { /* 8b2226a2-ac30-4f5c-ae5c-926c792ecdb9 */ + 0x8b2226a2, + 0xac30, + 0x4f5c, + { 0xae, 0x5c, 0x92, 0x6c, 0x79, 0x2e, 0xcd, 0xb9 } }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -232,12 +232,12 @@ SELECTANY const GUID JITEEVersionIdentifier = { /* d609bed1-7831-49fc-bd49-b6f05 // For System V on the CLR type system number of registers to pass in and return a struct is the same. // The CLR type system allows only up to 2 eightbytes to be passed in registers. There is no SSEUP classification types. -#define CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS 2 +#define CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS 2 #define CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_RETURN_IN_REGISTERS 2 #define CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS 16 // System V struct passing -// The Classification types are described in the ABI spec at http://www.x86-64.org/documentation/abi.pdf +// The Classification types are described in the ABI spec at https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf enum SystemVClassificationType : unsigned __int8 { SystemVClassificationTypeUnknown = 0, @@ -252,20 +252,6 @@ enum SystemVClassificationType : unsigned __int8 // SystemVClassificationTypeX87 = Unused, // Not supported by the CLR. // SystemVClassificationTypeX87Up = Unused, // Not supported by the CLR. // SystemVClassificationTypeComplexX87 = Unused, // Not supported by the CLR. - - // Internal flags - never returned outside of the classification implementation. - - // This value represents a very special type with two eightbytes. - // First ByRef, second Integer (platform int). - // The VM has a special Elem type for this type - ELEMENT_TYPE_TYPEDBYREF. - // This is the classification counterpart for that element type. It is used to detect - // the special TypedReference type and specialize its classification. - // This type is represented as a struct with two fields. The classification needs to do - // special handling of it since the source/methadata type of the fieds is IntPtr. - // The VM changes the first to ByRef. The second is left as IntPtr (TYP_I_IMPL really). The classification needs to match this and - // special handling is warranted (similar thing is done in the getGCLayout function for this type). - SystemVClassificationTypeTypedReference = 8, - SystemVClassificationTypeMAX = 9, }; // Represents classification information for a struct. @@ -311,7 +297,7 @@ struct SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR // // Return value: // returns true if we the eightbyte at index slotIndex is of integral type. - // + // bool IsIntegralSlot(unsigned slotIndex) const { @@ -328,8 +314,8 @@ struct SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR // // Return value: // returns true if we the eightbyte at index slotIndex is of SSE type. - // - // Follows the rules of the AMD64 System V ABI specification at www.x86-64.org/documentation/abi.pdf. + // + // Follows the rules of the AMD64 System V ABI specification at https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf. // Please refer to it for definitions/examples. // bool IsSseSlot(unsigned slotIndex) const @@ -352,6 +338,8 @@ private: } }; +#include "corinfoinstructionset.h" + // CorInfoHelpFunc defines the set of helpers (accessed via the ICorDynamicInfo::getHelperFtn()) // These helpers can be called by native code which executes in the runtime. // Compilers can emit calls to these helpers. @@ -394,10 +382,9 @@ enum CorInfoHelpFunc CORINFO_HELP_FLTROUND, CORINFO_HELP_DBLROUND, - /* Allocating a new object. Always use ICorClassInfo::getNewHelper() to decide + /* Allocating a new object. Always use ICorClassInfo::getNewHelper() to decide which is the right helper to use to allocate an object of a given type. */ - CORINFO_HELP_NEW_CROSSCONTEXT, // cross context new object CORINFO_HELP_NEWFAST, CORINFO_HELP_NEWSFAST, // allocator for small, non-finalizer, non-array object CORINFO_HELP_NEWSFAST_FINALIZE, // allocator for small, finalizable, non-array object @@ -407,7 +394,6 @@ enum CorInfoHelpFunc CORINFO_HELP_NEW_MDARR, // multi-dim array helper (with or without lower bounds - dimensions passed in as vararg) CORINFO_HELP_NEW_MDARR_NONVARARG,// multi-dim array helper (with or without lower bounds - dimensions passed in as unmanaged array) CORINFO_HELP_NEWARR_1_DIRECT, // helper for any one dimensional array creation - CORINFO_HELP_NEWARR_1_R2R_DIRECT, // wrapper for R2R direct call, which extracts method table from ArrayTypeDesc CORINFO_HELP_NEWARR_1_OBJ, // optimized 1-D object arrays CORINFO_HELP_NEWARR_1_VC, // optimized 1-D value class arrays CORINFO_HELP_NEWARR_1_ALIGN8, // like VC, but aligns the array start @@ -432,7 +418,7 @@ enum CorInfoHelpFunc CORINFO_HELP_CHKCASTARRAY, CORINFO_HELP_CHKCASTCLASS, CORINFO_HELP_CHKCASTANY, - CORINFO_HELP_CHKCASTCLASS_SPECIAL, // Optimized helper for classes. Assumes that the trivial cases + CORINFO_HELP_CHKCASTCLASS_SPECIAL, // Optimized helper for classes. Assumes that the trivial cases // has been taken care of by the inlined check CORINFO_HELP_BOX, @@ -473,24 +459,9 @@ enum CorInfoHelpFunc CORINFO_HELP_MON_EXIT_STATIC, CORINFO_HELP_GETCLASSFROMMETHODPARAM, // Given a generics method handle, returns a class handle - CORINFO_HELP_GETSYNCFROMCLASSHANDLE, // Given a generics class handle, returns the sync monitor + CORINFO_HELP_GETSYNCFROMCLASSHANDLE, // Given a generics class handle, returns the sync monitor // in its ManagedClassObject - /* Security callout support */ - - CORINFO_HELP_SECURITY_PROLOG, // Required if CORINFO_FLG_SECURITYCHECK is set, or CORINFO_FLG_NOSECURITYWRAP is not set - CORINFO_HELP_SECURITY_PROLOG_FRAMED, // Slow version of CORINFO_HELP_SECURITY_PROLOG. Used for instrumentation. - - CORINFO_HELP_METHOD_ACCESS_CHECK, // Callouts to runtime security access checks - CORINFO_HELP_FIELD_ACCESS_CHECK, - CORINFO_HELP_CLASS_ACCESS_CHECK, - - CORINFO_HELP_DELEGATE_SECURITY_CHECK, // Callout to delegate security transparency check - - /* Verification runtime callout support */ - - CORINFO_HELP_VERIFICATION_RUNTIME_CHECK, // Do a Demand for UnmanagedCode permission at runtime - /* GC support */ CORINFO_HELP_STOP_FOR_GC, // Call GC (force a GC) @@ -535,7 +506,7 @@ enum CorInfoHelpFunc CORINFO_HELP_GETSTATICFIELDADDR_CONTEXT, // Helper for context-static fields CORINFO_HELP_GETSTATICFIELDADDR_TLS, // Helper for PE TLS fields - // There are a variety of specialized helpers for accessing static fields. The JIT should use + // There are a variety of specialized helpers for accessing static fields. The JIT should use // ICorClassInfo::getSharedStaticsOrCCtorHelper to determine which helper to use // Helpers for regular statics @@ -567,7 +538,7 @@ enum CorInfoHelpFunc /* Profiling enter/leave probe addresses */ CORINFO_HELP_PROF_FCN_ENTER, // record the entry to a method (caller) CORINFO_HELP_PROF_FCN_LEAVE, // record the completion of current method (caller) - CORINFO_HELP_PROF_FCN_TAILCALL, // record the completionof current method through tailcall (caller) + CORINFO_HELP_PROF_FCN_TAILCALL, // record the completion of current method through tailcall (caller) /* Miscellaneous */ @@ -575,7 +546,7 @@ enum CorInfoHelpFunc CORINFO_HELP_PINVOKE_CALLI, // Indirect pinvoke call CORINFO_HELP_TAILCALL, // Perform a tail call - + CORINFO_HELP_GETCURRENTMANAGEDTHREADID, CORINFO_HELP_INIT_PINVOKE_FRAME, // initialize an inlined PInvoke Frame for the JIT-compiler @@ -658,7 +629,11 @@ enum CorInfoHelpFunc CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, // Transition to cooperative mode in reverse P/Invoke prolog, frame is the first argument CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, // Transition to preemptive mode in reverse P/Invoke epilog, frame is the first argument - CORINFO_HELP_GVMLOOKUP_FOR_SLOT, // Resolve a generic virtual method target from this pointer and runtime method handle + CORINFO_HELP_GVMLOOKUP_FOR_SLOT, // Resolve a generic virtual method target from this pointer and runtime method handle + + CORINFO_HELP_STACK_PROBE, // Probes each page of the allocated stack frame + + CORINFO_HELP_PATCHPOINT, // Notify runtime that code has reached a patchpoint CORINFO_HELP_COUNT, }; @@ -725,7 +700,7 @@ enum CorInfoType enum CorInfoTypeWithMod { CORINFO_TYPE_MASK = 0x3F, // lower 6 bits are type mask - CORINFO_TYPE_MOD_PINNED = 0x40, // can be applied to CLASS, or BYREF to indiate pinned + CORINFO_TYPE_MOD_PINNED = 0x40, // can be applied to CLASS, or BYREF to indicate pinned }; inline CorInfoType strip(CorInfoTypeWithMod val) { @@ -827,13 +802,14 @@ enum CorInfoFlag CORINFO_FLG_SHAREDINST = 0x00020000, // the code for this method is shared between different generic instantiations (also set on classes/types) CORINFO_FLG_DELEGATE_INVOKE = 0x00040000, // "Delegate CORINFO_FLG_PINVOKE = 0x00080000, // Is a P/Invoke call - CORINFO_FLG_SECURITYCHECK = 0x00100000, // Is one of the security routines that does a stackwalk (e.g. Assert, Demand) +// CORINFO_FLG_UNUSED = 0x00100000, CORINFO_FLG_NOGCCHECK = 0x00200000, // This method is FCALL that has no GC check. Don't put alone in loops CORINFO_FLG_INTRINSIC = 0x00400000, // This method MAY have an intrinsic ID CORINFO_FLG_CONSTRUCTOR = 0x00800000, // This method is an instance or type initializer CORINFO_FLG_AGGRESSIVE_OPT = 0x01000000, // The method may contain hot code and should be aggressively optimized if possible CORINFO_FLG_DISABLE_TIER0_FOR_LOOPS = 0x02000000, // Indicates that tier 0 JIT should not be used for a method that contains a loop - CORINFO_FLG_NOSECURITYWRAP = 0x04000000, // The method requires no security checks +// CORINFO_FLG_UNUSED = 0x04000000, +// CORINFO_FLG_UNUSED = 0x08000000, CORINFO_FLG_DONT_INLINE = 0x10000000, // The method should not be inlined CORINFO_FLG_DONT_INLINE_CALLER = 0x20000000, // The method should not be inlined, nor should its callers. It cannot be tail called. CORINFO_FLG_JIT_INTRINSIC = 0x40000000, // Method is a potential jit intrinsic; verify identity by name check @@ -846,11 +822,11 @@ enum CorInfoFlag CORINFO_FLG_ARRAY = 0x00080000, // class is an array class (initialized differently) CORINFO_FLG_OVERLAPPING_FIELDS = 0x00100000, // struct or class has fields that overlap (aka union) CORINFO_FLG_INTERFACE = 0x00200000, // it is an interface - CORINFO_FLG_CONTEXTFUL = 0x00400000, // is this a contextful class? + // unused = 0x00400000, CORINFO_FLG_CUSTOMLAYOUT = 0x00800000, // does this struct have custom layout? CORINFO_FLG_CONTAINS_GC_PTR = 0x01000000, // does the class contain a gc ptr ? CORINFO_FLG_DELEGATE = 0x02000000, // is this a subclass of delegate or multicast delegate ? - CORINFO_FLG_MARSHAL_BYREF = 0x04000000, // is this a subclass of MarshalByRef ? + // CORINFO_FLG_UNUSED = 0x04000000, CORINFO_FLG_CONTAINS_STACK_PTR = 0x08000000, // This class has a stack pointer inside it CORINFO_FLG_VARIANCE = 0x10000000, // MethodTable::HasVariance (sealed does *not* mean uncast-able) CORINFO_FLG_BEFOREFIELDINIT = 0x20000000, // Additional flexibility for when to run .cctor (see code:#ClassConstructionFlags) @@ -862,8 +838,8 @@ enum CorInfoFlag enum CorInfoMethodRuntimeFlags { CORINFO_FLG_BAD_INLINEE = 0x00000001, // The method is not suitable for inlining - CORINFO_FLG_VERIFIABLE = 0x00000002, // The method has verifiable code - CORINFO_FLG_UNVERIFIABLE = 0x00000004, // The method has unverifiable code + // unused = 0x00000002, + // unused = 0x00000004, CORINFO_FLG_SWITCHED_TO_MIN_OPT = 0x00000008, // The JIT decided to switch to MinOpt for this method, when it was not requested CORINFO_FLG_SWITCHED_TO_OPTIMIZED = 0x00000010, // The JIT decided to switch to tier 1 for this method, when a different tier was requested }; @@ -873,7 +849,7 @@ enum CORINFO_ACCESS_FLAGS { CORINFO_ACCESS_ANY = 0x0000, // Normal access CORINFO_ACCESS_THIS = 0x0001, // Accessed via the this reference - CORINFO_ACCESS_UNWRAP = 0x0002, // Accessed via an unwrap reference + // UNUSED = 0x0002, CORINFO_ACCESS_NONNULL = 0x0004, // Instance is guaranteed non-null @@ -961,6 +937,7 @@ enum CorInfoIntrinsics CORINFO_INTRINSIC_StubHelpers_GetStubContext, CORINFO_INTRINSIC_StubHelpers_GetStubContextAddr, CORINFO_INTRINSIC_StubHelpers_GetNDirectTarget, + CORINFO_INTRINSIC_StubHelpers_NextCallReturnAddress, CORINFO_INTRINSIC_InterlockedAdd32, CORINFO_INTRINSIC_InterlockedAdd64, CORINFO_INTRINSIC_InterlockedXAdd32, @@ -970,6 +947,7 @@ enum CorInfoIntrinsics CORINFO_INTRINSIC_InterlockedCmpXchg32, CORINFO_INTRINSIC_InterlockedCmpXchg64, CORINFO_INTRINSIC_MemoryBarrier, + CORINFO_INTRINSIC_MemoryBarrierLoad, CORINFO_INTRINSIC_GetCurrentManagedThread, CORINFO_INTRINSIC_GetManagedThreadId, CORINFO_INTRINSIC_ByReference_Ctor, @@ -1055,26 +1033,15 @@ enum CorInfoTailCall TAILCALL_FAIL = -1, // Couldn't do a tail call }; -enum CorInfoCanSkipVerificationResult -{ - CORINFO_VERIFICATION_CANNOT_SKIP = 0, // Cannot skip verification during jit time. - CORINFO_VERIFICATION_CAN_SKIP = 1, // Can skip verification during jit time. - CORINFO_VERIFICATION_RUNTIME_CHECK = 2, // Cannot skip verification during jit time, - // but need to insert a callout to the VM to ask during runtime - // whether to raise a verification or not (if the method is unverifiable). - CORINFO_VERIFICATION_DONT_JIT = 3, // Cannot skip verification during jit time, - // but do not jit the method if is is unverifiable. -}; - enum CorInfoInitClassResult { - CORINFO_INITCLASS_NOT_REQUIRED = 0x00, // No class initialization required, but the class is not actually initialized yet + CORINFO_INITCLASS_NOT_REQUIRED = 0x00, // No class initialization required, but the class is not actually initialized yet // (e.g. we are guaranteed to run the static constructor in method prolog) CORINFO_INITCLASS_INITIALIZED = 0x01, // Class initialized CORINFO_INITCLASS_SPECULATIVE = 0x02, // Class may be initialized speculatively CORINFO_INITCLASS_USE_HELPER = 0x04, // The JIT must insert class initialization helper call. - CORINFO_INITCLASS_DONT_INLINE = 0x08, // The JIT should not inline the method requesting the class initialization. The class - // initialization requires helper class now, but will not require initialization + CORINFO_INITCLASS_DONT_INLINE = 0x08, // The JIT should not inline the method requesting the class initialization. The class + // initialization requires helper class now, but will not require initialization // if the method is compiled standalone. Or the method cannot be inlined due to some // requirement around class initialization such as shared generics. }; @@ -1109,39 +1076,15 @@ enum CorInfoIndirectCallReason CORINFO_INDIRECT_CALL_COUNT }; -// This is for use when the JIT is compiling an instantiation -// of generic code. The JIT needs to know if the generic code itself -// (which can be verified once and for all independently of the -// instantiations) passed verification. -enum CorInfoInstantiationVerification -{ - // The method is NOT a concrete instantiation (eg. List.Add()) of a method - // in a generic class or a generic method. It is either the typical instantiation - // (eg. List.Add()) or entirely non-generic. - INSTVER_NOT_INSTANTIATION = 0, - - // The method is an instantiation of a method in a generic class or a generic method, - // and the generic class was successfully verified - INSTVER_GENERIC_PASSED_VERIFICATION = 1, - - // The method is an instantiation of a method in a generic class or a generic method, - // and the generic class failed verification - INSTVER_GENERIC_FAILED_VERIFICATION = 2, -}; - -// When using CORINFO_HELPER_TAILCALL, the JIT needs to pass certain special -// calling convention/argument passing/handling details to the helper -enum CorInfoHelperTailCallSpecialHandling -{ - CORINFO_TAILCALL_NORMAL = 0x00000000, - CORINFO_TAILCALL_STUB_DISPATCH_ARG = 0x00000001, -}; - - inline bool dontInline(CorInfoInline val) { return(val < 0); } +// Patchpoint info is passed back and forth across the interface +// but is opaque. + +struct PatchpointInfo; + // Cookie types consumed by the code generator (these are opaque values // not inspected by the code generator): @@ -1162,14 +1105,14 @@ typedef struct CORINFO_VarArgInfo * CORINFO_VARARGS_HANDLE; // Generic tokens are resolved with respect to a context, which is usually the method // being compiled. The CORINFO_CONTEXT_HANDLE indicates which exact instantiation // (or the open instantiation) is being referred to. -// CORINFO_CONTEXT_HANDLE is more tightly scoped than CORINFO_MODULE_HANDLE. For cases +// CORINFO_CONTEXT_HANDLE is more tightly scoped than CORINFO_MODULE_HANDLE. For cases // where the exact instantiation does not matter, CORINFO_MODULE_HANDLE is used. typedef CORINFO_METHOD_HANDLE CORINFO_CONTEXT_HANDLE; typedef struct CORINFO_DEPENDENCY_STRUCT_ { CORINFO_MODULE_HANDLE moduleFrom; - CORINFO_MODULE_HANDLE moduleTo; + CORINFO_MODULE_HANDLE moduleTo; } CORINFO_DEPENDENCY; // Bit-twiddling of contexts assumes word-alignment of method handles and type handles @@ -1186,8 +1129,10 @@ enum CorInfoContextFlags enum CorInfoSigInfoFlags { - CORINFO_SIGFLAG_IS_LOCAL_SIG = 0x01, - CORINFO_SIGFLAG_IL_STUB = 0x02, + CORINFO_SIGFLAG_IS_LOCAL_SIG = 0x01, + CORINFO_SIGFLAG_IL_STUB = 0x02, + CORINFO_SIGFLAG_SUPPRESS_GC_TRANSITION = 0x04, + CORINFO_SIGFLAG_FAT_CALL = 0x08, }; struct CORINFO_SIG_INST @@ -1289,7 +1234,7 @@ struct CORINFO_METHOD_INFO struct CORINFO_CONST_LOOKUP { // If the handle is obtained at compile-time, then this handle is the "exact" handle (class, method, or field) - // Otherwise, it's a representative... + // Otherwise, it's a representative... // If accessType is // IAT_VALUE --> "handle" stores the real handle or "addr " stores the computed address // IAT_PVALUE --> "addr" stores a pointer to a location which will hold the real handle @@ -1332,6 +1277,7 @@ struct CORINFO_LOOKUP_KIND // #define CORINFO_MAXINDIRECTIONS 4 #define CORINFO_USEHELPER ((WORD) 0xffff) +#define CORINFO_NO_SIZE_CHECK ((WORD) 0xffff) struct CORINFO_RUNTIME_LOOKUP { @@ -1354,6 +1300,7 @@ struct CORINFO_RUNTIME_LOOKUP // If set, test the lowest bit and dereference if set (see code:FixupPointer) bool testForFixup; + WORD sizeOffset; SIZE_T offsets[CORINFO_MAXINDIRECTIONS]; // If set, first offset is indirect. @@ -1525,7 +1472,7 @@ struct CORINFO_HELPER_DESC // thisTransform and constraint calls // ---------------------------------- // -// For evertyhing besides "constrained." calls "thisTransform" is set to +// For everything besides "constrained." calls "thisTransform" is set to // CORINFO_NO_THIS_TRANSFORM. // // For "constrained." calls the EE attempts to resolve the call at compile @@ -1586,12 +1533,11 @@ enum CorInfoIsAccessAllowedResult { CORINFO_ACCESS_ALLOWED = 0, // Call allowed CORINFO_ACCESS_ILLEGAL = 1, // Call not allowed - CORINFO_ACCESS_RUNTIME_CHECK = 2, // Ask at runtime whether to allow the call or not }; // This enum is used for JIT to tell EE where this token comes from. -// E.g. Depending on different opcodes, we might allow/disallow certain types of tokens or +// E.g. Depending on different opcodes, we might allow/disallow certain types of tokens or // return different types of handles (e.g. boxed vs. regular entrypoints) enum CorInfoTokenKind { @@ -1633,10 +1579,10 @@ struct CORINFO_RESOLVED_TOKEN CorInfoTokenKind tokenType; // - // [Out] arguments of resolveToken. + // [Out] arguments of resolveToken. // - Type handle is always non-NULL. // - At most one of method and field handles is non-NULL (according to the token type). - // - Method handle is an instantiating stub only for generic methods. Type handle + // - Method handle is an instantiating stub only for generic methods. Type handle // is required to provide the full context for methods in generic types. // CORINFO_CLASS_HANDLE hClass; @@ -1659,7 +1605,7 @@ struct CORINFO_CALL_INFO unsigned classFlags; //flags for CORINFO_RESOLVED_TOKEN::hClass - CORINFO_SIG_INFO sig; + CORINFO_SIG_INFO sig; //Verification information unsigned verMethodFlags; // flags for CORINFO_RESOLVED_TOKEN::hMethod @@ -1673,8 +1619,6 @@ struct CORINFO_CALL_INFO // JIT may either insert the callsiteCalloutHelper into the code (as per a verification error) or // call throwExceptionFromHelper on the callsiteCalloutHelper. In this case callsiteCalloutHelper // is guaranteed not to return. - // - CORINFO_ACCESS_RUNTIME_CHECK - The jit must insert the callsiteCalloutHelper at the call site. - // the helper may return CorInfoIsAccessAllowedResult accessAllowed; CORINFO_HELPER_DESC callsiteCalloutHelper; @@ -1699,7 +1643,7 @@ struct CORINFO_CALL_INFO CORINFO_CONST_LOOKUP instParamLookup; // Used by Ready-to-Run - BOOL secureDelegateInvoke; + BOOL wrapperDelegateInvoke; }; //---------------------------------------------------------------------------- @@ -1778,7 +1722,7 @@ struct CORINFO_EH_CLAUSE enum CORINFO_OS { CORINFO_WINNT, - CORINFO_PAL, + CORINFO_UNIX, }; struct CORINFO_CPU @@ -1826,15 +1770,8 @@ struct CORINFO_EE_INFO unsigned offsetOfDelegateInstance; unsigned offsetOfDelegateFirstTarget; - // Secure delegate offsets - unsigned offsetOfSecureDelegateIndirectCell; - - // Remoting offsets - unsigned offsetOfTransparentProxyRP; - unsigned offsetOfRealProxyServer; - - // Array offsets - unsigned offsetOfObjArrayData; + // Wrapper delegate offsets + unsigned offsetOfWrapperDelegateIndirectCell; // Reverse PInvoke offsets unsigned sizeOfReversePInvokeFrame; @@ -1850,12 +1787,33 @@ struct CORINFO_EE_INFO CORINFO_RUNTIME_ABI targetAbi; CORINFO_OS osType; - unsigned osMajor; - unsigned osMinor; - unsigned osBuild; }; -// This is used to indicate that a finally has been called +// Flags passed from JIT to runtime. +enum CORINFO_GET_TAILCALL_HELPERS_FLAGS +{ + // The callsite is a callvirt instruction. + CORINFO_TAILCALL_IS_CALLVIRT = 0x00000001, + CORINFO_TAILCALL_THIS_ARG_IS_BYREF = 0x00000002, +}; + +// Flags passed from runtime to JIT. +enum CORINFO_TAILCALL_HELPERS_FLAGS +{ + // The StoreArgs stub needs to be passed the target function pointer as the + // first argument. + CORINFO_TAILCALL_STORE_TARGET = 0x00000001, +}; + +struct CORINFO_TAILCALL_HELPERS +{ + CORINFO_TAILCALL_HELPERS_FLAGS flags; + CORINFO_METHOD_HANDLE hStoreArgs; + CORINFO_METHOD_HANDLE hCallTarget; + CORINFO_METHOD_HANDLE hDispatcher; +}; + +// This is used to indicate that a finally has been called // "locally" by the try block enum { LCL_FINALLY_MARK = 0xFC }; // FC = "Finally Call" @@ -1876,15 +1834,15 @@ struct CORINFO_Object struct CORINFO_String : public CORINFO_Object { unsigned stringLen; - wchar_t chars[1]; // actually of variable size + WCHAR chars[1]; // actually of variable size }; struct CORINFO_Array : public CORINFO_Object { unsigned length; -#ifdef _WIN64 +#ifdef HOST_64BIT unsigned alignpad; -#endif // _WIN64 +#endif // HOST_64BIT #if 0 /* Multi-dimensional arrays have the lengths and bounds here */ @@ -1908,9 +1866,9 @@ struct CORINFO_Array : public CORINFO_Object struct CORINFO_Array8 : public CORINFO_Object { unsigned length; -#ifdef _WIN64 +#ifdef HOST_64BIT unsigned alignpad; -#endif // _WIN64 +#endif // HOST_64BIT union { @@ -1925,9 +1883,9 @@ struct CORINFO_Array8 : public CORINFO_Object struct CORINFO_RefArray : public CORINFO_Object { unsigned length; -#ifdef _WIN64 +#ifdef HOST_64BIT unsigned alignpad; -#endif // _WIN64 +#endif // HOST_64BIT #if 0 /* Multi-dimensional arrays have the lengths and bounds here */ @@ -1956,7 +1914,7 @@ struct CORINFO_VarArgInfo #define SIZEOF__CORINFO_Object TARGET_POINTER_SIZE /* methTable */ #define OFFSETOF__CORINFO_Array__length SIZEOF__CORINFO_Object -#ifdef _TARGET_64BIT_ +#ifdef TARGET_64BIT #define OFFSETOF__CORINFO_Array__data (OFFSETOF__CORINFO_Array__length + sizeof(unsigned __int32) /* length */ + sizeof(unsigned __int32) /* alignpad */) #else #define OFFSETOF__CORINFO_Array__data (OFFSETOF__CORINFO_Array__length + sizeof(unsigned __int32) /* length */) @@ -1968,12 +1926,6 @@ struct CORINFO_VarArgInfo #define OFFSETOF__CORINFO_String__stringLen SIZEOF__CORINFO_Object #define OFFSETOF__CORINFO_String__chars (OFFSETOF__CORINFO_String__stringLen + sizeof(unsigned __int32) /* stringLen */) -enum CorInfoSecurityRuntimeChecks -{ - CORINFO_ACCESS_SECURITY_NONE = 0, - CORINFO_ACCESS_SECURITY_TRANSPARENCY = 0x0001 // check that transparency rules are enforced between the caller and callee -}; - /* data to optimize delegate construction */ struct DelegateCtorArgs @@ -2008,9 +1960,9 @@ enum class TypeCompareState }; // -// This interface is logically split into sections for each class of information +// This interface is logically split into sections for each class of information // (ICorMethodInfo, ICorModuleInfo, etc.). This split used to exist physically as well -// using virtual inheritance, but was eliminated to improve efficiency of the JIT-EE +// using virtual inheritance, but was eliminated to improve efficiency of the JIT-EE // interface calls. // class ICorStaticInfo @@ -2022,7 +1974,7 @@ public: // /**********************************************************************************/ - // return flags (defined above, CORINFO_FLG_PUBLIC ...) + // return flags (a bitfield of CorInfoFlags values) virtual DWORD getMethodAttribs ( CORINFO_METHOD_HANDLE ftn /* IN */ ) = 0; @@ -2152,8 +2104,8 @@ public: // Given resolved token that corresponds to an intrinsic classified as // a CORINFO_INTRINSIC_GetRawHandle intrinsic, fetch the handle associated - // with the token. If this is not possible at compile-time (because the current method's - // code is shared and the token contains generic parameters) then indicate + // with the token. If this is not possible at compile-time (because the current method's + // code is shared and the token contains generic parameters) then indicate // how the handle should be looked up at runtime. virtual void expandRawHandleIntrinsic( CORINFO_RESOLVED_TOKEN * pResolvedToken, @@ -2167,9 +2119,9 @@ public: bool* pMustExpand = NULL /* OUT */ ) = 0; - // Is the given module the System.Numerics.Vectors module? + // Is the given type in System.Private.Corelib and marked with IntrinsicAttribute? // This defaults to false. - virtual bool isInSIMDModule( + virtual bool isIntrinsicType( CORINFO_CLASS_HANDLE classHnd ) { return false; } @@ -2203,26 +2155,6 @@ public: BOOL *pfIsOpenDelegate /* is the delegate open */ ) = 0; - // Indicates if the method is an instance of the generic - // method that passes (or has passed) verification - virtual CorInfoInstantiationVerification isInstantiationOfVerifiedGeneric ( - CORINFO_METHOD_HANDLE method /* IN */ - ) = 0; - - // Loads the constraints on a typical method definition, detecting cycles; - // for use in verification. - virtual void initConstraintsForVerification( - CORINFO_METHOD_HANDLE method, /* IN */ - BOOL *pfHasCircularClassConstraints, /* OUT */ - BOOL *pfHasCircularMethodConstraint /* OUT */ - ) = 0; - - // Returns enum whether the method does not require verification - // Also see ICorModuleInfo::canSkipVerification - virtual CorInfoCanSkipVerificationResult canSkipMethodVerification ( - CORINFO_METHOD_HANDLE ftnHandle - ) = 0; - // load and restore the method virtual void methodMustBeLoadedBeforeCodeIsRun( CORINFO_METHOD_HANDLE method @@ -2239,6 +2171,16 @@ public: GSCookie ** ppCookieVal // OUT ) = 0; + // Provide patchpoint info for the method currently being jitted. + virtual void setPatchpointInfo( + PatchpointInfo* patchpointInfo + ) = 0; + + // Get patchpoint info and il offset for the method currently being jitted. + virtual PatchpointInfo* getOSRInfo( + unsigned *ilOffset // [OUT] il offset of OSR entry point + ) = 0; + /**********************************************************************************/ // // ICorModuleInfo @@ -2277,21 +2219,6 @@ public: virtual CORINFO_CLASS_HANDLE getTokenTypeAsHandle ( CORINFO_RESOLVED_TOKEN * pResolvedToken /* IN */) = 0; - // Returns true if the module does not require verification - // - // If fQuickCheckOnlyWithoutCommit=TRUE, the function only checks that the - // module does not currently require verification in the current AppDomain. - // This decision could change in the future, and so should not be cached. - // If it is cached, it should only be used as a hint. - // This is only used by ngen for calculating certain hints. - // - - // Returns enum whether the module does not require verification - // Also see ICorMethodInfo::canSkipMethodVerification(); - virtual CorInfoCanSkipVerificationResult canSkipVerification ( - CORINFO_MODULE_HANDLE module /* IN */ - ) = 0; - // Checks if the given metadata token is valid virtual BOOL isValidToken ( CORINFO_MODULE_HANDLE module, /* IN */ @@ -2304,8 +2231,12 @@ public: unsigned metaTOK /* IN */ ) = 0; - virtual BOOL shouldEnforceCallvirtRestriction( - CORINFO_MODULE_HANDLE scope + // Returns string length and content (can be null for dynamic context) + // for given metaTOK and module, length `-1` means input is incorrect + virtual LPCWSTR getStringLiteral ( + CORINFO_MODULE_HANDLE module, /* IN */ + unsigned metaTOK, /* IN */ + int* length /* OUT */ ) = 0; /**********************************************************************************/ @@ -2335,10 +2266,10 @@ public: // Return the type argument of the instantiated generic class, // which is specified by the index virtual CORINFO_CLASS_HANDLE getTypeInstantiationArgument( - CORINFO_CLASS_HANDLE cls, + CORINFO_CLASS_HANDLE cls, unsigned index ) = 0; - + // Append a (possibly truncated) representation of the type cls to the preallocated buffer ppBuf of length pnBufLen // If fNamespace=TRUE, include the namespace/enclosing classes @@ -2346,7 +2277,7 @@ public: // If fAssembly=TRUE, suffix with a comma and the full assembly qualification // return size of representation virtual int appendClassName( - __deref_inout_ecount(*pnBufLen) WCHAR** ppBuf, + __deref_inout_ecount(*pnBufLen) WCHAR** ppBuf, int* pnBufLen, CORINFO_CLASS_HANDLE cls, BOOL fNamespace, @@ -2362,17 +2293,13 @@ public: // GetTypeFromHandle(X) == GetTypeFromHandle(Y) (for CORINFO_INLINE_TYPECHECK_SOURCE_TOKEN) virtual CorInfoInlineTypeCheck canInlineTypeCheck(CORINFO_CLASS_HANDLE cls, CorInfoInlineTypeCheckSource source) = 0; - // If this method returns true, JIT will do optimization to inline the check for - // GetTypeFromHandle(handle) == obj.GetType() - virtual BOOL canInlineTypeCheckWithObjectVTable(CORINFO_CLASS_HANDLE cls) = 0; - - // return flags (defined above, CORINFO_FLG_PUBLIC ...) + // return flags (a bitfield of CorInfoFlags values) virtual DWORD getClassAttribs ( CORINFO_CLASS_HANDLE cls ) = 0; // Returns "TRUE" iff "cls" is a struct type such that return buffers used for returning a value - // of this type must be stack-allocated. This will generally be true only if the struct + // of this type must be stack-allocated. This will generally be true only if the struct // contains GC pointers, and does not exceed some size limit. Maintaining this as an invariant allows // an optimization: the JIT may assume that return buffer pointers for return types for which this predicate // returns TRUE are always stack allocated, and thus, that stores to the GC-pointer fields of such return @@ -2401,8 +2328,8 @@ public: virtual void LongLifetimeFree(void* obj) = 0; virtual size_t getClassModuleIdForStatics ( - CORINFO_CLASS_HANDLE cls, - CORINFO_MODULE_HANDLE *pModule, + CORINFO_CLASS_HANDLE cls, + CORINFO_MODULE_HANDLE *pModule, void **ppIndirection ) = 0; @@ -2478,10 +2405,6 @@ public: CORINFO_CLASS_HANDLE clsHnd ) = 0; - virtual CorInfoHelpFunc getSecurityPrologHelper( - CORINFO_METHOD_HANDLE ftn - ) = 0; - // This is not pretty. Boxing nullable actually returns // a boxed not a boxed Nullable. This call allows the verifier // to call back to the EE on the 'box' instruction and get the transformed @@ -2491,23 +2414,23 @@ public: ) = 0; // returns the correct box helper for a particular class. Note - // that if this returns CORINFO_HELP_BOX, the JIT can assume + // that if this returns CORINFO_HELP_BOX, the JIT can assume // 'standard' boxing (allocate object and copy), and optimize virtual CorInfoHelpFunc getBoxHelper( CORINFO_CLASS_HANDLE cls ) = 0; - // returns the unbox helper. If 'helperCopies' points to a true + // returns the unbox helper. If 'helperCopies' points to a true // value it means the JIT is requesting a helper that unboxes the // value into a particular location and thus has the signature // void unboxHelper(void* dest, CORINFO_CLASS_HANDLE cls, Object* obj) - // Otherwise (it is null or points at a FALSE value) it is requesting - // a helper that returns a pointer to the unboxed data + // Otherwise (it is null or points at a FALSE value) it is requesting + // a helper that returns a pointer to the unboxed data // void* unboxHelper(CORINFO_CLASS_HANDLE cls, Object* obj) // The EE has the option of NOT returning the copy style helper // (But must be able to always honor the non-copy style helper) // The EE set 'helperCopies' on return to indicate what kind of - // helper has been created. + // helper has been created. virtual CorInfoHelpFunc getUnBoxHelper( CORINFO_CLASS_HANDLE cls @@ -2531,7 +2454,7 @@ public: ) = 0; // This function tries to initialize the class (run the class constructor). - // this function returns whether the JIT must insert helper calls before + // this function returns whether the JIT must insert helper calls before // accessing static field or method. // // See code:ICorClassInfo#ClassConstruction. @@ -2642,7 +2565,7 @@ public: CORINFO_CLASS_HANDLE cls ) = 0; - // Get the numbmer of dimensions in an array + // Get the numbmer of dimensions in an array virtual unsigned getArrayRank( CORINFO_CLASS_HANDLE cls ) = 0; @@ -2697,12 +2620,6 @@ public: CORINFO_FIELD_HANDLE field ) = 0; - // TODO: jit64 should be switched to the same plan as the i386 jits - use - // getClassGClayout to figure out the need for writebarrier helper, and inline the copying. - // The interpretted value class copy is slow. Once this happens, USE_WRITE_BARRIER_HELPERS - virtual bool isWriteBarrierHelperRequired( - CORINFO_FIELD_HANDLE field) = 0; - virtual void getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_ACCESS_FLAGS flags, @@ -2781,7 +2698,7 @@ public: // For eg, use this to allocated memory for reporting debug info, // which will be handed to the EE by setVars() and setBoundaries() virtual void * allocateArray( - ULONG cBytes + size_t cBytes ) = 0; // JitCompiler will free arrays passed by the EE using this @@ -2916,7 +2833,7 @@ public: ) = 0; // Return method name as in metadata, or nullptr if there is none, - // and optionally return the class, enclosing class, and namespace names + // and optionally return the class, enclosing class, and namespace names // as in metadata. // Suitable for non-debugging use. virtual const char* getMethodNameFromMetadata( @@ -3020,7 +2937,7 @@ public: void **ppIndirection = NULL ) = 0; - // get slow lazy string literal helper to use (CORINFO_HELP_STRCNS*). + // get slow lazy string literal helper to use (CORINFO_HELP_STRCNS*). // Returns CORINFO_HELP_UNDEF if lazy string literal helper cannot be used. virtual CorInfoHelpFunc getLazyStringLiteralHelper( CORINFO_MODULE_HANDLE handle @@ -3065,24 +2982,9 @@ public: // CORINFO_LOOKUP_THISOBJ use vtable pointer of 'this' param // CORINFO_LOOKUP_CLASSPARAM use vtable hidden param // CORINFO_LOOKUP_METHODPARAM use enclosing type of method-desc hidden param - virtual CORINFO_LOOKUP_KIND getLocationOfThisType( - CORINFO_METHOD_HANDLE context - ) = 0; - - // NOTE: the two methods below--getPInvokeUnmanagedTarget and getAddressOfPInvokeFixup--are - // deprecated. New code should instead use getAddressOfPInvokeTarget, which subsumes the - // functionality of these methods. - - // return the unmanaged target *if method has already been prelinked.* - virtual void* getPInvokeUnmanagedTarget( - CORINFO_METHOD_HANDLE method, - void **ppIndirection = NULL - ) = 0; - - // return address of fixup area for late-bound PInvoke calls. - virtual void* getAddressOfPInvokeFixup( - CORINFO_METHOD_HANDLE method, - void **ppIndirection = NULL + virtual void getLocationOfThisType( + CORINFO_METHOD_HANDLE context, + CORINFO_LOOKUP_KIND* pLookupKind ) = 0; // return the address of the PInvoke target. May be a fixup area in the @@ -3162,7 +3064,7 @@ public: // If pIsSpeculative is NULL, return the class handle for the value of ref-class typed // static readonly fields, if there is a unique location for the static and the class // is already initialized. - // + // // If pIsSpeculative is not NULL, fetch the class handle for the value of all ref-class // typed static fields, if there is a unique location for the static and the field is // not null. @@ -3199,7 +3101,7 @@ public: ) = 0; // (static fields only) given that 'field' refers to thread local store, - // return the ID (TLS index), which is used to find the begining of the + // return the ID (TLS index), which is used to find the beginning of the // TLS data area for the particular DLL 'field' is associated with. virtual DWORD getFieldThreadLocalStoreID ( CORINFO_FIELD_HANDLE field, @@ -3230,17 +3132,31 @@ public: CORINFO_METHOD_HANDLE methHnd ) = 0; - // return a thunk that will copy the arguments for the given signature. - virtual void* getTailCallCopyArgsThunk ( - CORINFO_SIG_INFO *pSig, - CorInfoHelperTailCallSpecialHandling flags - ) = 0; + // Obtain tailcall help for the specified call site. + virtual bool getTailCallHelpers( + + // The resolved token for the call. Can be null for calli. + CORINFO_RESOLVED_TOKEN* callToken, + + // The signature at the callsite. + CORINFO_SIG_INFO* sig, + + // Flags for the tailcall site. + CORINFO_GET_TAILCALL_HELPERS_FLAGS flags, + + // The resulting help. + CORINFO_TAILCALL_HELPERS* pResult) = 0; // Optionally, convert calli to regular method call. This is for PInvoke argument marshalling. virtual bool convertPInvokeCalliToCall( CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fMustConvert ) = 0; + + virtual void notifyInstructionSetUsage( + CORINFO_InstructionSet instructionSet, + bool supportEnabled + ) = 0; }; /**********************************************************************************/ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corinfoinstructionset.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/corinfoinstructionset.h new file mode 100644 index 0000000..8040819 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corinfoinstructionset.h @@ -0,0 +1,514 @@ + +// 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. + +// DO NOT EDIT THIS FILE! IT IS AUTOGENERATED +// FROM /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt +// using /src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat + +#ifndef CORINFOINSTRUCTIONSET_H +#define CORINFOINSTRUCTIONSET_H + +#include "readytoruninstructionset.h" +#include + +enum CORINFO_InstructionSet +{ + InstructionSet_ILLEGAL = 0, + InstructionSet_NONE = 63, +#ifdef TARGET_ARM64 + InstructionSet_ArmBase=1, + InstructionSet_ArmBase_Arm64=2, + InstructionSet_AdvSimd=3, + InstructionSet_AdvSimd_Arm64=4, + InstructionSet_Aes=5, + InstructionSet_Crc32=6, + InstructionSet_Crc32_Arm64=7, + InstructionSet_Sha1=8, + InstructionSet_Sha256=9, + InstructionSet_Atomics=10, + InstructionSet_Vector64=11, + InstructionSet_Vector128=12, +#endif // TARGET_ARM64 +#ifdef TARGET_AMD64 + InstructionSet_X86Base=1, + InstructionSet_SSE=2, + InstructionSet_SSE2=3, + InstructionSet_SSE3=4, + InstructionSet_SSSE3=5, + InstructionSet_SSE41=6, + InstructionSet_SSE42=7, + InstructionSet_AVX=8, + InstructionSet_AVX2=9, + InstructionSet_AES=10, + InstructionSet_BMI1=11, + InstructionSet_BMI2=12, + InstructionSet_FMA=13, + InstructionSet_LZCNT=14, + InstructionSet_PCLMULQDQ=15, + InstructionSet_POPCNT=16, + InstructionSet_Vector128=17, + InstructionSet_Vector256=18, + InstructionSet_X86Base_X64=19, + InstructionSet_BMI1_X64=20, + InstructionSet_BMI2_X64=21, + InstructionSet_LZCNT_X64=22, + InstructionSet_POPCNT_X64=23, + InstructionSet_SSE_X64=24, + InstructionSet_SSE2_X64=25, + InstructionSet_SSE41_X64=26, + InstructionSet_SSE42_X64=27, +#endif // TARGET_AMD64 +#ifdef TARGET_X86 + InstructionSet_X86Base=1, + InstructionSet_SSE=2, + InstructionSet_SSE2=3, + InstructionSet_SSE3=4, + InstructionSet_SSSE3=5, + InstructionSet_SSE41=6, + InstructionSet_SSE42=7, + InstructionSet_AVX=8, + InstructionSet_AVX2=9, + InstructionSet_AES=10, + InstructionSet_BMI1=11, + InstructionSet_BMI2=12, + InstructionSet_FMA=13, + InstructionSet_LZCNT=14, + InstructionSet_PCLMULQDQ=15, + InstructionSet_POPCNT=16, + InstructionSet_Vector128=17, + InstructionSet_Vector256=18, + InstructionSet_X86Base_X64=19, + InstructionSet_BMI1_X64=20, + InstructionSet_BMI2_X64=21, + InstructionSet_LZCNT_X64=22, + InstructionSet_POPCNT_X64=23, + InstructionSet_SSE_X64=24, + InstructionSet_SSE2_X64=25, + InstructionSet_SSE41_X64=26, + InstructionSet_SSE42_X64=27, +#endif // TARGET_X86 + +}; + +struct CORINFO_InstructionSetFlags +{ +private: + uint64_t _flags = 0; +public: + void AddInstructionSet(CORINFO_InstructionSet instructionSet) + { + _flags = _flags | (((uint64_t)1) << instructionSet); + } + + void RemoveInstructionSet(CORINFO_InstructionSet instructionSet) + { + _flags = _flags & ~(((uint64_t)1) << instructionSet); + } + + bool HasInstructionSet(CORINFO_InstructionSet instructionSet) const + { + return _flags & (((uint64_t)1) << instructionSet); + } + + bool Equals(CORINFO_InstructionSetFlags other) const + { + return _flags == other._flags; + } + + void Add(CORINFO_InstructionSetFlags other) + { + _flags |= other._flags; + } + + bool IsEmpty() const + { + return _flags == 0; + } + + void Reset() + { + _flags = 0; + } + + void Set64BitInstructionSetVariants() + { +#ifdef TARGET_ARM64 + if (HasInstructionSet(InstructionSet_ArmBase)) + AddInstructionSet(InstructionSet_ArmBase_Arm64); + if (HasInstructionSet(InstructionSet_AdvSimd)) + AddInstructionSet(InstructionSet_AdvSimd_Arm64); + if (HasInstructionSet(InstructionSet_Crc32)) + AddInstructionSet(InstructionSet_Crc32_Arm64); +#endif // TARGET_ARM64 +#ifdef TARGET_AMD64 + if (HasInstructionSet(InstructionSet_X86Base)) + AddInstructionSet(InstructionSet_X86Base_X64); + if (HasInstructionSet(InstructionSet_SSE)) + AddInstructionSet(InstructionSet_SSE_X64); + if (HasInstructionSet(InstructionSet_SSE2)) + AddInstructionSet(InstructionSet_SSE2_X64); + if (HasInstructionSet(InstructionSet_SSE41)) + AddInstructionSet(InstructionSet_SSE41_X64); + if (HasInstructionSet(InstructionSet_SSE42)) + AddInstructionSet(InstructionSet_SSE42_X64); + if (HasInstructionSet(InstructionSet_BMI1)) + AddInstructionSet(InstructionSet_BMI1_X64); + if (HasInstructionSet(InstructionSet_BMI2)) + AddInstructionSet(InstructionSet_BMI2_X64); + if (HasInstructionSet(InstructionSet_LZCNT)) + AddInstructionSet(InstructionSet_LZCNT_X64); + if (HasInstructionSet(InstructionSet_POPCNT)) + AddInstructionSet(InstructionSet_POPCNT_X64); +#endif // TARGET_AMD64 +#ifdef TARGET_X86 +#endif // TARGET_X86 + + } + + uint64_t GetFlagsRaw() + { + return _flags; + } + + void SetFromFlagsRaw(uint64_t flags) + { + _flags = flags; + } +}; + +inline CORINFO_InstructionSetFlags EnsureInstructionSetFlagsAreValid(CORINFO_InstructionSetFlags input) +{ + CORINFO_InstructionSetFlags oldflags = input; + CORINFO_InstructionSetFlags resultflags = input; + do + { + oldflags = resultflags; +#ifdef TARGET_ARM64 + if (resultflags.HasInstructionSet(InstructionSet_ArmBase) && !resultflags.HasInstructionSet(InstructionSet_ArmBase_Arm64)) + resultflags.RemoveInstructionSet(InstructionSet_ArmBase); + if (resultflags.HasInstructionSet(InstructionSet_ArmBase_Arm64) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) + resultflags.RemoveInstructionSet(InstructionSet_ArmBase_Arm64); + if (resultflags.HasInstructionSet(InstructionSet_AdvSimd) && !resultflags.HasInstructionSet(InstructionSet_AdvSimd_Arm64)) + resultflags.RemoveInstructionSet(InstructionSet_AdvSimd); + if (resultflags.HasInstructionSet(InstructionSet_AdvSimd_Arm64) && !resultflags.HasInstructionSet(InstructionSet_AdvSimd)) + resultflags.RemoveInstructionSet(InstructionSet_AdvSimd_Arm64); + if (resultflags.HasInstructionSet(InstructionSet_Crc32) && !resultflags.HasInstructionSet(InstructionSet_Crc32_Arm64)) + resultflags.RemoveInstructionSet(InstructionSet_Crc32); + if (resultflags.HasInstructionSet(InstructionSet_Crc32_Arm64) && !resultflags.HasInstructionSet(InstructionSet_Crc32)) + resultflags.RemoveInstructionSet(InstructionSet_Crc32_Arm64); + if (resultflags.HasInstructionSet(InstructionSet_AdvSimd) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) + resultflags.RemoveInstructionSet(InstructionSet_AdvSimd); + if (resultflags.HasInstructionSet(InstructionSet_Aes) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) + resultflags.RemoveInstructionSet(InstructionSet_Aes); + if (resultflags.HasInstructionSet(InstructionSet_Crc32) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) + resultflags.RemoveInstructionSet(InstructionSet_Crc32); + if (resultflags.HasInstructionSet(InstructionSet_Sha1) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) + resultflags.RemoveInstructionSet(InstructionSet_Sha1); + if (resultflags.HasInstructionSet(InstructionSet_Sha256) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) + resultflags.RemoveInstructionSet(InstructionSet_Sha256); +#endif // TARGET_ARM64 +#ifdef TARGET_AMD64 + if (resultflags.HasInstructionSet(InstructionSet_X86Base) && !resultflags.HasInstructionSet(InstructionSet_X86Base_X64)) + resultflags.RemoveInstructionSet(InstructionSet_X86Base); + if (resultflags.HasInstructionSet(InstructionSet_X86Base_X64) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) + resultflags.RemoveInstructionSet(InstructionSet_X86Base_X64); + if (resultflags.HasInstructionSet(InstructionSet_SSE) && !resultflags.HasInstructionSet(InstructionSet_SSE_X64)) + resultflags.RemoveInstructionSet(InstructionSet_SSE); + if (resultflags.HasInstructionSet(InstructionSet_SSE_X64) && !resultflags.HasInstructionSet(InstructionSet_SSE)) + resultflags.RemoveInstructionSet(InstructionSet_SSE_X64); + if (resultflags.HasInstructionSet(InstructionSet_SSE2) && !resultflags.HasInstructionSet(InstructionSet_SSE2_X64)) + resultflags.RemoveInstructionSet(InstructionSet_SSE2); + if (resultflags.HasInstructionSet(InstructionSet_SSE2_X64) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_SSE2_X64); + if (resultflags.HasInstructionSet(InstructionSet_SSE41) && !resultflags.HasInstructionSet(InstructionSet_SSE41_X64)) + resultflags.RemoveInstructionSet(InstructionSet_SSE41); + if (resultflags.HasInstructionSet(InstructionSet_SSE41_X64) && !resultflags.HasInstructionSet(InstructionSet_SSE41)) + resultflags.RemoveInstructionSet(InstructionSet_SSE41_X64); + if (resultflags.HasInstructionSet(InstructionSet_SSE42) && !resultflags.HasInstructionSet(InstructionSet_SSE42_X64)) + resultflags.RemoveInstructionSet(InstructionSet_SSE42); + if (resultflags.HasInstructionSet(InstructionSet_SSE42_X64) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) + resultflags.RemoveInstructionSet(InstructionSet_SSE42_X64); + if (resultflags.HasInstructionSet(InstructionSet_BMI1) && !resultflags.HasInstructionSet(InstructionSet_BMI1_X64)) + resultflags.RemoveInstructionSet(InstructionSet_BMI1); + if (resultflags.HasInstructionSet(InstructionSet_BMI1_X64) && !resultflags.HasInstructionSet(InstructionSet_BMI1)) + resultflags.RemoveInstructionSet(InstructionSet_BMI1_X64); + if (resultflags.HasInstructionSet(InstructionSet_BMI2) && !resultflags.HasInstructionSet(InstructionSet_BMI2_X64)) + resultflags.RemoveInstructionSet(InstructionSet_BMI2); + if (resultflags.HasInstructionSet(InstructionSet_BMI2_X64) && !resultflags.HasInstructionSet(InstructionSet_BMI2)) + resultflags.RemoveInstructionSet(InstructionSet_BMI2_X64); + if (resultflags.HasInstructionSet(InstructionSet_LZCNT) && !resultflags.HasInstructionSet(InstructionSet_LZCNT_X64)) + resultflags.RemoveInstructionSet(InstructionSet_LZCNT); + if (resultflags.HasInstructionSet(InstructionSet_LZCNT_X64) && !resultflags.HasInstructionSet(InstructionSet_LZCNT)) + resultflags.RemoveInstructionSet(InstructionSet_LZCNT_X64); + if (resultflags.HasInstructionSet(InstructionSet_POPCNT) && !resultflags.HasInstructionSet(InstructionSet_POPCNT_X64)) + resultflags.RemoveInstructionSet(InstructionSet_POPCNT); + if (resultflags.HasInstructionSet(InstructionSet_POPCNT_X64) && !resultflags.HasInstructionSet(InstructionSet_POPCNT)) + resultflags.RemoveInstructionSet(InstructionSet_POPCNT_X64); + if (resultflags.HasInstructionSet(InstructionSet_SSE) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) + resultflags.RemoveInstructionSet(InstructionSet_SSE); + if (resultflags.HasInstructionSet(InstructionSet_SSE2) && !resultflags.HasInstructionSet(InstructionSet_SSE)) + resultflags.RemoveInstructionSet(InstructionSet_SSE2); + if (resultflags.HasInstructionSet(InstructionSet_SSE3) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_SSE3); + if (resultflags.HasInstructionSet(InstructionSet_SSSE3) && !resultflags.HasInstructionSet(InstructionSet_SSE3)) + resultflags.RemoveInstructionSet(InstructionSet_SSSE3); + if (resultflags.HasInstructionSet(InstructionSet_SSE41) && !resultflags.HasInstructionSet(InstructionSet_SSSE3)) + resultflags.RemoveInstructionSet(InstructionSet_SSE41); + if (resultflags.HasInstructionSet(InstructionSet_SSE42) && !resultflags.HasInstructionSet(InstructionSet_SSE41)) + resultflags.RemoveInstructionSet(InstructionSet_SSE42); + if (resultflags.HasInstructionSet(InstructionSet_AVX) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) + resultflags.RemoveInstructionSet(InstructionSet_AVX); + if (resultflags.HasInstructionSet(InstructionSet_AVX2) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_AVX2); + if (resultflags.HasInstructionSet(InstructionSet_AES) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_AES); + if (resultflags.HasInstructionSet(InstructionSet_BMI1) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_BMI1); + if (resultflags.HasInstructionSet(InstructionSet_BMI2) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_BMI2); + if (resultflags.HasInstructionSet(InstructionSet_FMA) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_FMA); + if (resultflags.HasInstructionSet(InstructionSet_PCLMULQDQ) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_PCLMULQDQ); + if (resultflags.HasInstructionSet(InstructionSet_POPCNT) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) + resultflags.RemoveInstructionSet(InstructionSet_POPCNT); +#endif // TARGET_AMD64 +#ifdef TARGET_X86 + if (resultflags.HasInstructionSet(InstructionSet_SSE) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) + resultflags.RemoveInstructionSet(InstructionSet_SSE); + if (resultflags.HasInstructionSet(InstructionSet_SSE2) && !resultflags.HasInstructionSet(InstructionSet_SSE)) + resultflags.RemoveInstructionSet(InstructionSet_SSE2); + if (resultflags.HasInstructionSet(InstructionSet_SSE3) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_SSE3); + if (resultflags.HasInstructionSet(InstructionSet_SSSE3) && !resultflags.HasInstructionSet(InstructionSet_SSE3)) + resultflags.RemoveInstructionSet(InstructionSet_SSSE3); + if (resultflags.HasInstructionSet(InstructionSet_SSE41) && !resultflags.HasInstructionSet(InstructionSet_SSSE3)) + resultflags.RemoveInstructionSet(InstructionSet_SSE41); + if (resultflags.HasInstructionSet(InstructionSet_SSE42) && !resultflags.HasInstructionSet(InstructionSet_SSE41)) + resultflags.RemoveInstructionSet(InstructionSet_SSE42); + if (resultflags.HasInstructionSet(InstructionSet_AVX) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) + resultflags.RemoveInstructionSet(InstructionSet_AVX); + if (resultflags.HasInstructionSet(InstructionSet_AVX2) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_AVX2); + if (resultflags.HasInstructionSet(InstructionSet_AES) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_AES); + if (resultflags.HasInstructionSet(InstructionSet_BMI1) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_BMI1); + if (resultflags.HasInstructionSet(InstructionSet_BMI2) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_BMI2); + if (resultflags.HasInstructionSet(InstructionSet_FMA) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_FMA); + if (resultflags.HasInstructionSet(InstructionSet_PCLMULQDQ) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_PCLMULQDQ); + if (resultflags.HasInstructionSet(InstructionSet_POPCNT) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) + resultflags.RemoveInstructionSet(InstructionSet_POPCNT); +#endif // TARGET_X86 + + } while (!oldflags.Equals(resultflags)); + return resultflags; +} + +inline const char *InstructionSetToString(CORINFO_InstructionSet instructionSet) +{ +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4065) // disable warning for switch statement with only default label. +#endif + + switch (instructionSet) + { +#ifdef TARGET_ARM64 + case InstructionSet_ArmBase : + return "ArmBase"; + case InstructionSet_ArmBase_Arm64 : + return "ArmBase_Arm64"; + case InstructionSet_AdvSimd : + return "AdvSimd"; + case InstructionSet_AdvSimd_Arm64 : + return "AdvSimd_Arm64"; + case InstructionSet_Aes : + return "Aes"; + case InstructionSet_Crc32 : + return "Crc32"; + case InstructionSet_Crc32_Arm64 : + return "Crc32_Arm64"; + case InstructionSet_Sha1 : + return "Sha1"; + case InstructionSet_Sha256 : + return "Sha256"; + case InstructionSet_Atomics : + return "Atomics"; + case InstructionSet_Vector64 : + return "Vector64"; + case InstructionSet_Vector128 : + return "Vector128"; +#endif // TARGET_ARM64 +#ifdef TARGET_AMD64 + case InstructionSet_X86Base : + return "X86Base"; + case InstructionSet_X86Base_X64 : + return "X86Base_X64"; + case InstructionSet_SSE : + return "SSE"; + case InstructionSet_SSE_X64 : + return "SSE_X64"; + case InstructionSet_SSE2 : + return "SSE2"; + case InstructionSet_SSE2_X64 : + return "SSE2_X64"; + case InstructionSet_SSE3 : + return "SSE3"; + case InstructionSet_SSSE3 : + return "SSSE3"; + case InstructionSet_SSE41 : + return "SSE41"; + case InstructionSet_SSE41_X64 : + return "SSE41_X64"; + case InstructionSet_SSE42 : + return "SSE42"; + case InstructionSet_SSE42_X64 : + return "SSE42_X64"; + case InstructionSet_AVX : + return "AVX"; + case InstructionSet_AVX2 : + return "AVX2"; + case InstructionSet_AES : + return "AES"; + case InstructionSet_BMI1 : + return "BMI1"; + case InstructionSet_BMI1_X64 : + return "BMI1_X64"; + case InstructionSet_BMI2 : + return "BMI2"; + case InstructionSet_BMI2_X64 : + return "BMI2_X64"; + case InstructionSet_FMA : + return "FMA"; + case InstructionSet_LZCNT : + return "LZCNT"; + case InstructionSet_LZCNT_X64 : + return "LZCNT_X64"; + case InstructionSet_PCLMULQDQ : + return "PCLMULQDQ"; + case InstructionSet_POPCNT : + return "POPCNT"; + case InstructionSet_POPCNT_X64 : + return "POPCNT_X64"; + case InstructionSet_Vector128 : + return "Vector128"; + case InstructionSet_Vector256 : + return "Vector256"; +#endif // TARGET_AMD64 +#ifdef TARGET_X86 + case InstructionSet_X86Base : + return "X86Base"; + case InstructionSet_SSE : + return "SSE"; + case InstructionSet_SSE2 : + return "SSE2"; + case InstructionSet_SSE3 : + return "SSE3"; + case InstructionSet_SSSE3 : + return "SSSE3"; + case InstructionSet_SSE41 : + return "SSE41"; + case InstructionSet_SSE42 : + return "SSE42"; + case InstructionSet_AVX : + return "AVX"; + case InstructionSet_AVX2 : + return "AVX2"; + case InstructionSet_AES : + return "AES"; + case InstructionSet_BMI1 : + return "BMI1"; + case InstructionSet_BMI2 : + return "BMI2"; + case InstructionSet_FMA : + return "FMA"; + case InstructionSet_LZCNT : + return "LZCNT"; + case InstructionSet_PCLMULQDQ : + return "PCLMULQDQ"; + case InstructionSet_POPCNT : + return "POPCNT"; + case InstructionSet_Vector128 : + return "Vector128"; + case InstructionSet_Vector256 : + return "Vector256"; +#endif // TARGET_X86 + + default: + return "UnknownInstructionSet"; + } +#ifdef _MSC_VER +#pragma warning(pop) +#endif +} + +inline CORINFO_InstructionSet InstructionSetFromR2RInstructionSet(ReadyToRunInstructionSet r2rSet) +{ +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4065) // disable warning for switch statement with only default label. +#endif + + switch (r2rSet) + { +#ifdef TARGET_ARM64 + case READYTORUN_INSTRUCTION_ArmBase: return InstructionSet_ArmBase; + case READYTORUN_INSTRUCTION_AdvSimd: return InstructionSet_AdvSimd; + case READYTORUN_INSTRUCTION_Aes: return InstructionSet_Aes; + case READYTORUN_INSTRUCTION_Crc32: return InstructionSet_Crc32; + case READYTORUN_INSTRUCTION_Sha1: return InstructionSet_Sha1; + case READYTORUN_INSTRUCTION_Sha256: return InstructionSet_Sha256; + case READYTORUN_INSTRUCTION_Atomics: return InstructionSet_Atomics; +#endif // TARGET_ARM64 +#ifdef TARGET_AMD64 + case READYTORUN_INSTRUCTION_X86Base: return InstructionSet_X86Base; + case READYTORUN_INSTRUCTION_Sse: return InstructionSet_SSE; + case READYTORUN_INSTRUCTION_Sse2: return InstructionSet_SSE2; + case READYTORUN_INSTRUCTION_Sse3: return InstructionSet_SSE3; + case READYTORUN_INSTRUCTION_Ssse3: return InstructionSet_SSSE3; + case READYTORUN_INSTRUCTION_Sse41: return InstructionSet_SSE41; + case READYTORUN_INSTRUCTION_Sse42: return InstructionSet_SSE42; + case READYTORUN_INSTRUCTION_Avx: return InstructionSet_AVX; + case READYTORUN_INSTRUCTION_Avx2: return InstructionSet_AVX2; + case READYTORUN_INSTRUCTION_Aes: return InstructionSet_AES; + case READYTORUN_INSTRUCTION_Bmi1: return InstructionSet_BMI1; + case READYTORUN_INSTRUCTION_Bmi2: return InstructionSet_BMI2; + case READYTORUN_INSTRUCTION_Fma: return InstructionSet_FMA; + case READYTORUN_INSTRUCTION_Lzcnt: return InstructionSet_LZCNT; + case READYTORUN_INSTRUCTION_Pclmulqdq: return InstructionSet_PCLMULQDQ; + case READYTORUN_INSTRUCTION_Popcnt: return InstructionSet_POPCNT; +#endif // TARGET_AMD64 +#ifdef TARGET_X86 + case READYTORUN_INSTRUCTION_X86Base: return InstructionSet_X86Base; + case READYTORUN_INSTRUCTION_Sse: return InstructionSet_SSE; + case READYTORUN_INSTRUCTION_Sse2: return InstructionSet_SSE2; + case READYTORUN_INSTRUCTION_Sse3: return InstructionSet_SSE3; + case READYTORUN_INSTRUCTION_Ssse3: return InstructionSet_SSSE3; + case READYTORUN_INSTRUCTION_Sse41: return InstructionSet_SSE41; + case READYTORUN_INSTRUCTION_Sse42: return InstructionSet_SSE42; + case READYTORUN_INSTRUCTION_Avx: return InstructionSet_AVX; + case READYTORUN_INSTRUCTION_Avx2: return InstructionSet_AVX2; + case READYTORUN_INSTRUCTION_Aes: return InstructionSet_AES; + case READYTORUN_INSTRUCTION_Bmi1: return InstructionSet_BMI1; + case READYTORUN_INSTRUCTION_Bmi2: return InstructionSet_BMI2; + case READYTORUN_INSTRUCTION_Fma: return InstructionSet_FMA; + case READYTORUN_INSTRUCTION_Lzcnt: return InstructionSet_LZCNT; + case READYTORUN_INSTRUCTION_Pclmulqdq: return InstructionSet_PCLMULQDQ; + case READYTORUN_INSTRUCTION_Popcnt: return InstructionSet_POPCNT; +#endif // TARGET_X86 + + default: + return InstructionSet_ILLEGAL; + } +#ifdef _MSC_VER +#pragma warning(pop) +#endif +} + +#endif // CORINFOINSTRUCTIONSET_H diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corjit.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/corjit.h index 6892e06..857fa5b 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corjit.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corjit.h @@ -20,7 +20,7 @@ // The JIT/EE interface is versioned. By "interface", we mean mean any and all communication between the // JIT and the EE. Any time a change is made to the interface, the JIT/EE interface version identifier // must be updated. See code:JITEEVersionIdentifier for more information. -// +// // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE // ////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -48,129 +48,6 @@ enum CorJitResult CORJIT_RECOVERABLEERROR = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 5), }; -/***************************************************************************** -Here is how CORJIT_FLAG_SKIP_VERIFICATION should be interepreted. -Note that even if any method is inlined, it need not be verified. - -if (CORJIT_FLAG_SKIP_VERIFICATION is passed in to ICorJitCompiler::compileMethod()) -{ - No verification needs to be done. - Just compile the method, generating unverifiable code if necessary -} -else -{ - switch(ICorMethodInfo::isInstantiationOfVerifiedGeneric()) - { - case INSTVER_NOT_INSTANTIATION: - - // - // Non-generic case, or open generic instantiation - // - - switch(canSkipMethodVerification()) - { - case CORINFO_VERIFICATION_CANNOT_SKIP: - { - ICorMethodInfo::initConstraintsForVerification(&circularConstraints) - if (circularConstraints) - { - Just emit code to call CORINFO_HELP_VERIFICATION - The IL will not be compiled - } - else - { - Verify the method. - if (unverifiable code is detected) - { - In place of branches with unverifiable code, emit code to call CORINFO_HELP_VERIFICATION - Mark the method (and any of its instantiations) as unverifiable - } - Compile the rest of the verifiable code - } - } - - case CORINFO_VERIFICATION_CAN_SKIP: - { - No verification needs to be done. - Just compile the method, generating unverifiable code if necessary - } - - case CORINFO_VERIFICATION_RUNTIME_CHECK: - { - ICorMethodInfo::initConstraintsForVerification(&circularConstraints) - if (circularConstraints) - { - Just emit code to call CORINFO_HELP_VERIFICATION - The IL will not be compiled - - TODO: This could be changed to call CORINFO_HELP_VERIFICATION_RUNTIME_CHECK - } - else - { - Verify the method. - if (unverifiable code is detected) - { - In the prolog, emit code to call CORINFO_HELP_VERIFICATION_RUNTIME_CHECK - Mark the method (and any of its instantiations) as unverifiable - } - Compile the method, generating unverifiable code if necessary - } - } - case CORINFO_VERIFICATION_DONT_JIT: - { - ICorMethodInfo::initConstraintsForVerification(&circularConstraints) - if (circularConstraints) - { - Just emit code to call CORINFO_HELP_VERIFICATION - The IL will not be compiled - } - else - { - Verify the method. - if (unverifiable code is detected) - { - Fail the jit - } - } - } - } - - case INSTVER_GENERIC_PASSED_VERIFICATION: - { - This cannot ever happen because the VM would pass in CORJIT_FLAG_SKIP_VERIFICATION. - } - - case INSTVER_GENERIC_FAILED_VERIFICATION: - - switch(canSkipMethodVerification()) - { - case CORINFO_VERIFICATION_CANNOT_SKIP: - { - This cannot be supported because the compiler does not know which branches should call CORINFO_HELP_VERIFICATION. - The CLR will throw a VerificationException instead of trying to compile this method - } - - case CORINFO_VERIFICATION_CAN_SKIP: - { - This cannot ever happen because the CLR would pass in CORJIT_FLAG_SKIP_VERIFICATION. - } - - case CORINFO_VERIFICATION_RUNTIME_CHECK: - { - No verification needs to be done. - In the prolog, emit code to call CORINFO_HELP_VERIFICATION_RUNTIME_CHECK - Compile the method, generating unverifiable code if necessary - } - case CORINFO_VERIFICATION_DONT_JIT: - { - Fail the jit - } - } - } -} - -*/ - /*****************************************************************************/ // These are flags passed to ICorJitInfo::allocMem // to guide the memory allocation for the code, readonly data, and read-write data @@ -179,6 +56,8 @@ enum CorJitAllocMemFlag CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN = 0x00000000, // The code will be use the normal alignment CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN = 0x00000001, // The code will be 16-byte aligned CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN = 0x00000002, // The read-only data will be 16-byte aligned + CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN = 0x00000004, // The code will be 32-byte aligned + CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN = 0x00000008, // The read-only data will be 32-byte aligned }; inline CorJitAllocMemFlag operator |(CorJitAllocMemFlag a, CorJitAllocMemFlag b) @@ -210,7 +89,6 @@ extern "C" void __stdcall jitStartup(ICorJitHost* host); class ICorJitCompiler; class ICorJitInfo; -struct IEEMemoryManager; extern "C" ICorJitCompiler* __stdcall getJit(); @@ -218,9 +96,9 @@ extern "C" ICorJitCompiler* __stdcall getJit(); // ICorJitCompiler is the interface that the EE uses to get IL bytecode converted to native code. Note that // to accomplish this the JIT has to call back to the EE to get symbolic information. The code:ICorJitInfo // type passed as 'comp' to compileMethod is the mechanism to get this information. This is often the more -// interesting interface. -// -// +// interesting interface. +// +// class ICorJitCompiler { public: @@ -230,10 +108,10 @@ public: // nativeSizeOfCode are just for convenience because the JIT asks the EE for the memory to emit code into // (see code:ICorJitInfo.allocMem), so really the EE already knows where the method starts and how big // it is (in fact, it could be in more than one chunk). - // + // // * In the 32 bit jit this is implemented by code:CILJit.compileMethod // * For the 64 bit jit this is implemented by code:PreJit.compileMethod - // + // // Note: Obfuscators that are hacking the JIT depend on this method having __stdcall calling convention virtual CorJitResult __stdcall compileMethod ( ICorJitInfo *comp, /* IN */ @@ -243,21 +121,13 @@ public: ULONG *nativeSizeOfCode /* OUT */ ) = 0; - // Some JIT compilers (most notably Phoenix), cache information about EE structures from one invocation - // of the compiler to the next. This can be a problem when appdomains are unloaded, as some of this - // cached information becomes stale. The code:ICorJitCompiler.isCacheCleanupRequired is called by the EE - // early first to see if jit needs these notifications, and if so, the EE will call ClearCache is called - // whenever the compiler should abandon its cache (eg on appdomain unload) - virtual void clearCache() = 0; - virtual BOOL isCacheCleanupRequired() = 0; - // Do any appropriate work at process shutdown. Default impl is to do nothing. virtual void ProcessShutdownWork(ICorStaticInfo* info) {}; // The EE asks the JIT for a "version identifier". This represents the version of the JIT/EE interface. // If the JIT doesn't implement the same JIT/EE interface expected by the EE (because the JIT doesn't // return the version identifier that the EE expects), then the EE fails to load the JIT. - // + // virtual void getVersionIdentifier( GUID* versionIdentifier /* OUT */ ) = 0; @@ -266,35 +136,23 @@ public: // SIMD vector it supports as an intrinsic type. Zero means that the JIT does not support SIMD // intrinsics, so the EE should use the default size (i.e. the size of the IL implementation). virtual unsigned getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags) { return 0; } - - // IL obfuscators sometimes interpose on the EE-JIT interface. This function allows the VM to - // tell the JIT to use a particular ICorJitCompiler to implement the methods of this interface, - // and not to implement those methods itself. The JIT must not return this method when getJit() - // is called. Instead, it must pass along all calls to this interface from within its own - // ICorJitCompiler implementation. If 'realJitCompiler' is nullptr, then the JIT should resume - // executing all the functions itself. - virtual void setRealJit(ICorJitCompiler* realJitCompiler) { } - }; //------------------------------------------------------------------------------------------ // #JitToEEInterface -// +// // ICorJitInfo is the main interface that the JIT uses to call back to the EE and get information. It is // the companion to code:ICorJitCompiler#EEToJitInterface. The concrete implementation of this in the -// runtime is the code:CEEJitInfo type. There is also a version of this for the NGEN case. -// -// See code:ICorMethodInfo#EEJitContractDetails for subtle conventions used by this interface. -// -// There is more information on the JIT in the book of the runtime entry +// runtime is the code:CEEJitInfo type. There is also a version of this for the NGEN case. +// +// See code:ICorMethodInfo#EEJitContractDetails for subtle conventions used by this interface. +// +// There is more information on the JIT in the book of the runtime entry // http://devdiv/sites/CLR/Product%20Documentation/2.0/BookOfTheRuntime/JIT/JIT%20Design.doc -// +// class ICorJitInfo : public ICorDynamicInfo { public: - // OBSOLETE: return memory manager that the JIT can use to allocate a regular memory - virtual IEEMemoryManager* getMemoryManager() = 0; - // get a block of memory for the code, readonly data, and read-write data virtual void allocMem ( ULONG hotCodeSize, /* IN */ @@ -332,7 +190,7 @@ public: // Parameters: // // pHotCode main method code buffer, always filled in - // pColdCode cold code buffer, only filled in if this is cold code, + // pColdCode cold code buffer, only filled in if this is cold code, // null otherwise // startOffset start of code block, relative to appropriate code buffer // (e.g. pColdCode if cold, pHotCode if hot). @@ -359,8 +217,6 @@ public: size_t size /* IN */ ) = 0; - virtual void yieldExecution() = 0; - // Indicate how many exception handler blocks are to be returned. // This is guaranteed to be called before any 'setEHinfo' call. // Note that allocMem must be called before this method can be called. @@ -386,7 +242,7 @@ public: // do an assert. will return true if the code should retry (DebugBreak) // returns false, if the assert should be igored. virtual int doAssert(const char* szFile, int iLine, const char* szExpr) = 0; - + virtual void reportFatalError(CorJitResult result) = 0; struct BlockCounts // Also defined by: CORBBTPROF_BLOCK_DATA @@ -433,19 +289,11 @@ public: virtual WORD getRelocTypeHint(void * target) = 0; - // A callback to identify the range of address known to point to - // compiler-generated native entry points that call back into - // MSIL. - virtual void getModuleNativeEntryPointRange( - void ** pStart, /* OUT */ - void ** pEnd /* OUT */ - ) = 0; - // For what machine does the VM expect the JIT to generate code? The VM // returns one of the IMAGE_FILE_MACHINE_* values. Note that if the VM // is cross-compiling (such as the case for crossgen), it will return a // different value than if it was compiling for the host architecture. - // + // virtual DWORD getExpectedTargetArchitecture() = 0; // Fetches extended flags for a particular compilation instance. Returns diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corjitflags.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/corjitflags.h index 84fb42f..c363f73 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corjitflags.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corjitflags.h @@ -17,6 +17,8 @@ #ifndef _COR_JIT_FLAGS_H_ #define _COR_JIT_FLAGS_H_ +#include "corinfoinstructionset.h" + class CORJIT_FLAGS { public: @@ -34,15 +36,14 @@ public: CORJIT_FLAG_GCPOLL_CALLS = 6, // Emit calls to JIT_POLLGC for thread suspension. CORJIT_FLAG_MCJIT_BACKGROUND = 7, // Calling from multicore JIT background thread, do not call JitComplete - #if defined(_TARGET_X86_) + #if defined(TARGET_X86) CORJIT_FLAG_PINVOKE_RESTORE_ESP = 8, // Restore ESP after returning from inlined PInvoke CORJIT_FLAG_TARGET_P4 = 9, CORJIT_FLAG_USE_FCOMI = 10, // Generated code may use fcomi(p) instruction CORJIT_FLAG_USE_CMOV = 11, // Generated code may use cmov instruction - CORJIT_FLAG_USE_SSE2 = 12, // Generated code may use SSE-2 instructions - #else // !defined(_TARGET_X86_) + #else // !defined(TARGET_X86) CORJIT_FLAG_UNUSED1 = 8, CORJIT_FLAG_UNUSED2 = 9, @@ -50,29 +51,20 @@ public: CORJIT_FLAG_UNUSED4 = 11, CORJIT_FLAG_UNUSED5 = 12, - #endif // !defined(_TARGET_X86_) + #endif // !defined(TARGET_X86) - CORJIT_FLAG_UNUSED6 = 13, - - #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) - - CORJIT_FLAG_USE_AVX = 14, - CORJIT_FLAG_USE_AVX2 = 15, - CORJIT_FLAG_USE_AVX_512 = 16, - - #else // !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) + CORJIT_FLAG_OSR = 13, // Generate alternate method for On Stack Replacement CORJIT_FLAG_UNUSED7 = 14, CORJIT_FLAG_UNUSED8 = 15, CORJIT_FLAG_UNUSED9 = 16, - #endif // !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) - #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) + #if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) CORJIT_FLAG_FEATURE_SIMD = 17, #else CORJIT_FLAG_UNUSED10 = 17, - #endif // !(defined(_TARGET_X86_) || defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)) + #endif // !(defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64)) CORJIT_FLAG_MAKEFINALCODE = 18, // Use the final code generator, i.e., not the interpreter. CORJIT_FLAG_READYTORUN = 19, // Use version-resilient code generation @@ -94,69 +86,18 @@ public: CORJIT_FLAG_SAMPLING_JIT_BACKGROUND = 35, // JIT is being invoked as a result of stack sampling for hot methods in the background CORJIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions CORJIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog - CORJIT_FLAG_DESKTOP_QUIRKS = 38, // The JIT should generate desktop-quirk-compatible code + // CORJIT_FLAG_UNUSED = 38, CORJIT_FLAG_TIER0 = 39, // This is the initial tier for tiered compilation which should generate code as quickly as possible CORJIT_FLAG_TIER1 = 40, // This is the final tier (for now) for tiered compilation which should generate high quality code -#if defined(_TARGET_ARM_) +#if defined(TARGET_ARM) CORJIT_FLAG_RELATIVE_CODE_RELOCS = 41, // JIT should generate PC-relative address computations instead of EE relocation records -#else // !defined(_TARGET_ARM_) +#else // !defined(TARGET_ARM) CORJIT_FLAG_UNUSED11 = 41, -#endif // !defined(_TARGET_ARM_) +#endif // !defined(TARGET_ARM) CORJIT_FLAG_NO_INLINING = 42, // JIT should not inline any called method into this method -#if defined(_TARGET_ARM64_) - - CORJIT_FLAG_HAS_ARM64_AES = 43, // ID_AA64ISAR0_EL1.AES is 1 or better - CORJIT_FLAG_HAS_ARM64_ATOMICS = 44, // ID_AA64ISAR0_EL1.Atomic is 2 or better - CORJIT_FLAG_HAS_ARM64_CRC32 = 45, // ID_AA64ISAR0_EL1.CRC32 is 1 or better - CORJIT_FLAG_HAS_ARM64_DCPOP = 46, // ID_AA64ISAR1_EL1.DPB is 1 or better - CORJIT_FLAG_HAS_ARM64_DP = 47, // ID_AA64ISAR0_EL1.DP is 1 or better - CORJIT_FLAG_HAS_ARM64_FCMA = 48, // ID_AA64ISAR1_EL1.FCMA is 1 or better - CORJIT_FLAG_HAS_ARM64_FP = 49, // ID_AA64PFR0_EL1.FP is 0 or better - CORJIT_FLAG_HAS_ARM64_FP16 = 50, // ID_AA64PFR0_EL1.FP is 1 or better - CORJIT_FLAG_HAS_ARM64_JSCVT = 51, // ID_AA64ISAR1_EL1.JSCVT is 1 or better - CORJIT_FLAG_HAS_ARM64_LRCPC = 52, // ID_AA64ISAR1_EL1.LRCPC is 1 or better - CORJIT_FLAG_HAS_ARM64_PMULL = 53, // ID_AA64ISAR0_EL1.AES is 2 or better - CORJIT_FLAG_HAS_ARM64_SHA1 = 54, // ID_AA64ISAR0_EL1.SHA1 is 1 or better - CORJIT_FLAG_HAS_ARM64_SHA256 = 55, // ID_AA64ISAR0_EL1.SHA2 is 1 or better - CORJIT_FLAG_HAS_ARM64_SHA512 = 56, // ID_AA64ISAR0_EL1.SHA2 is 2 or better - CORJIT_FLAG_HAS_ARM64_SHA3 = 57, // ID_AA64ISAR0_EL1.SHA3 is 1 or better - CORJIT_FLAG_HAS_ARM64_SIMD = 58, // ID_AA64PFR0_EL1.AdvSIMD is 0 or better - CORJIT_FLAG_HAS_ARM64_SIMD_V81 = 59, // ID_AA64ISAR0_EL1.RDM is 1 or better - CORJIT_FLAG_HAS_ARM64_SIMD_FP16 = 60, // ID_AA64PFR0_EL1.AdvSIMD is 1 or better - CORJIT_FLAG_HAS_ARM64_SM3 = 61, // ID_AA64ISAR0_EL1.SM3 is 1 or better - CORJIT_FLAG_HAS_ARM64_SM4 = 62, // ID_AA64ISAR0_EL1.SM4 is 1 or better - CORJIT_FLAG_HAS_ARM64_SVE = 63 // ID_AA64PFR0_EL1.SVE is 1 or better - -#elif defined(_TARGET_X86_) || defined(_TARGET_AMD64_) - - CORJIT_FLAG_USE_SSE3 = 43, - CORJIT_FLAG_USE_SSSE3 = 44, - CORJIT_FLAG_USE_SSE41 = 45, - CORJIT_FLAG_USE_SSE42 = 46, - CORJIT_FLAG_USE_AES = 47, - CORJIT_FLAG_USE_BMI1 = 48, - CORJIT_FLAG_USE_BMI2 = 49, - CORJIT_FLAG_USE_FMA = 50, - CORJIT_FLAG_USE_LZCNT = 51, - CORJIT_FLAG_USE_PCLMULQDQ = 52, - CORJIT_FLAG_USE_POPCNT = 53, - CORJIT_FLAG_UNUSED23 = 54, - CORJIT_FLAG_UNUSED24 = 55, - CORJIT_FLAG_UNUSED25 = 56, - CORJIT_FLAG_UNUSED26 = 57, - CORJIT_FLAG_UNUSED27 = 58, - CORJIT_FLAG_UNUSED28 = 59, - CORJIT_FLAG_UNUSED29 = 60, - CORJIT_FLAG_UNUSED30 = 61, - CORJIT_FLAG_UNUSED31 = 62, - CORJIT_FLAG_UNUSED32 = 63 - - -#else // !defined(_TARGET_ARM64_) &&!defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) - CORJIT_FLAG_UNUSED12 = 43, CORJIT_FLAG_UNUSED13 = 44, CORJIT_FLAG_UNUSED14 = 45, @@ -178,8 +119,6 @@ public: CORJIT_FLAG_UNUSED30 = 61, CORJIT_FLAG_UNUSED31 = 62, CORJIT_FLAG_UNUSED32 = 63 - -#endif // !defined(_TARGET_ARM64_) &&!defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) }; CORJIT_FLAGS() @@ -198,11 +137,33 @@ public: CORJIT_FLAGS(const CORJIT_FLAGS& other) { corJitFlags = other.corJitFlags; + instructionSetFlags = other.instructionSetFlags; } void Reset() { corJitFlags = 0; + instructionSetFlags.Reset(); + } + + void Set(CORINFO_InstructionSet instructionSet) + { + instructionSetFlags.AddInstructionSet(instructionSet); + } + + bool IsSet(CORINFO_InstructionSet instructionSet) const + { + return instructionSetFlags.HasInstructionSet(instructionSet); + } + + void Clear(CORINFO_InstructionSet instructionSet) + { + instructionSetFlags.RemoveInstructionSet(instructionSet); + } + + void Set64BitInstructionSetVariants() + { + instructionSetFlags.Set64BitInstructionSetVariants(); } void Set(CorJitFlag flag) @@ -223,16 +184,17 @@ public: void Add(const CORJIT_FLAGS& other) { corJitFlags |= other.corJitFlags; - } - - void Remove(const CORJIT_FLAGS& other) - { - corJitFlags &= ~other.corJitFlags; + instructionSetFlags.Add(other.instructionSetFlags); } bool IsEmpty() const { - return corJitFlags == 0; + return corJitFlags == 0 && instructionSetFlags.IsEmpty(); + } + + void EnsureValidInstructionSetSupport() + { + instructionSetFlags = EnsureInstructionSetFlagsAreValid(instructionSetFlags); } // DO NOT USE THIS FUNCTION! (except in very restricted special cases) @@ -241,9 +203,16 @@ public: return corJitFlags; } + // DO NOT USE THIS FUNCTION! (except in very restricted special cases) + unsigned __int64 GetInstructionSetFlagsRaw() + { + return instructionSetFlags.GetFlagsRaw(); + } + private: unsigned __int64 corJitFlags; + CORINFO_InstructionSetFlags instructionSetFlags; }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corjithost.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/corjithost.h index b2ab806..9ed7f7b 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corjithost.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corjithost.h @@ -23,13 +23,13 @@ public: // Return an integer config value for the given key, if any exists. virtual int getIntConfigValue( - const wchar_t* name, + const WCHAR* name, int defaultValue ) = 0; // Return a string config value for the given key, if any exists. - virtual const wchar_t* getStringConfigValue( - const wchar_t* name + virtual const WCHAR* getStringConfigValue( + const WCHAR* name ) = 0; // Free a string ConfigValue returned by the runtime. @@ -37,7 +37,7 @@ public: // to return the string values to the runtime for deletion. // This avoids leaking the memory in the JIT. virtual void freeStringConfigValue( - const wchar_t* value + const WCHAR* value ) = 0; // Allocate memory slab of the given size in bytes. The host is expected to pool diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corpriv.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/corpriv.h index cb504bd..f0261b3 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corpriv.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corpriv.h @@ -148,7 +148,7 @@ DECLARE_INTERFACE_(IMetaDataHelper, IUnknown) // helper functions // This function is exposing the ability to translate signature from a given // source scope to a given target scope. - // + // STDMETHOD(TranslateSigWithScope)( IMetaDataAssemblyImport *pAssemImport, // [IN] importing assembly interface const void *pbHashValue, // [IN] Hash Blob for Assembly. @@ -231,23 +231,19 @@ typedef enum CorElementTypeZapSig // by the RID of a GenericParam token, encoded as a compressed integer. ELEMENT_TYPE_VAR_ZAPSIG = 0x3b, - // ZapSig encoding for an array MethodTable to allow it to remain such after decoding - // (rather than being transformed into the TypeHandle representing that array) - // - // The element is always followed by ELEMENT_TYPE_SZARRAY or ELEMENT_TYPE_ARRAY - ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG = 0x3c, + // UNUSED = 0x3c, // ZapSig encoding for native value types in IL stubs. IL stub signatures may contain // ELEMENT_TYPE_INTERNAL followed by ParamTypeDesc with ELEMENT_TYPE_VALUETYPE element // type. It acts like a modifier to the underlying structure making it look like its // unmanaged view (size determined by unmanaged layout, blittable, no GC pointers). - // + // // ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG is used when encoding such types to NGEN images. // The signature looks like this: ET_NATIVE_VALUETYPE_ZAPSIG ET_VALUETYPE . // See code:ZapSig.GetSignatureForTypeHandle and code:SigPointer.GetTypeHandleThrowing // where the encoding/decoding takes place. ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG = 0x3d, - + ELEMENT_TYPE_CANON_ZAPSIG = 0x3e, // zapsig encoding for [mscorlib]System.__Canon ELEMENT_TYPE_MODULE_ZAPSIG = 0x3f, // zapsig encoding for external module id# @@ -271,16 +267,16 @@ typedef enum CorCallingConventionInternal #define ELEMENT_TYPE_VALUEARRAY_UNSUPPORTED ((CorElementType) 0x17) #define ELEMENT_TYPE_R_UNSUPPORTED ((CorElementType) 0x1a) -// Use this guid in the SetOption if Reflection.Emit wants to control size of the initially allocated +// Use this guid in the SetOption if Reflection.Emit wants to control size of the initially allocated // MetaData. See values: code:CorMetaDataInitialSize. -// +// // {2675b6bf-f504-4cb4-a4d5-084eea770ddc} EXTERN_GUID(MetaDataInitialSize, 0x2675b6bf, 0xf504, 0x4cb4, 0xa4, 0xd5, 0x08, 0x4e, 0xea, 0x77, 0x0d, 0xdc); // Allowed values for code:MetaDataInitialSize option. typedef enum CorMetaDataInitialSize { - MDInitialSizeDefault = 0, + MDInitialSizeDefault = 0, MDInitialSizeMinimal = 1 } CorMetaDataInitialSize; @@ -290,7 +286,7 @@ typedef enum CorOpenFlagsInternal #ifdef FEATURE_METADATA_LOAD_TRUSTED_IMAGES // Flag code:ofTrustedImage is used by mscordbi.dll, therefore defined in file:CorPriv.h ofTrustedImage = ofReserved3 // We trust this PE file (we are willing to do a LoadLibrary on it). - // It is optional and only an (VM) optimization - typically for NGEN images + // It is optional and only an (VM) optimization - typically for NGEN images // opened by debugger. #endif } CorOpenFlagsInternal; @@ -322,11 +318,11 @@ STDAPI RuntimeGetAssemblyStrongNameHashForModule(HCORMODULE hModule, IMetaDataImport *pMDimport, BYTE *pbSNHash, DWORD *pcbSNHash); -STDAPI RuntimeGetMDInternalImport(HCORMODULE hHandle, +STDAPI RuntimeGetMDInternalImport(HCORMODULE hHandle, MDInternalImportFlags flags, IMDInternalImport** ppMDImport); -FORCEINLINE +FORCEINLINE void ReleaseHCorModule(HCORMODULE hModule) { HRESULT hr = RuntimeReleaseHandle(hModule); @@ -347,7 +343,7 @@ typedef Wrapper, ReleaseHCorModule, (UINT_PTR) // {848845BC-0C4A-42e3-8915-DC850112443D} EXTERN_GUID(IID_ISNAssemblySignature, 0x848845BC, 0x0C4A, 0x42e3, 0x89, 0x15, 0xDC, 0x85, 0x01, 0x12, 0x44, 0x3D); - + #undef INTERFACE #define INTERFACE ISNAssemblySignature DECLARE_INTERFACE_(ISNAssemblySignature, IUnknown) @@ -356,8 +352,8 @@ DECLARE_INTERFACE_(ISNAssemblySignature, IUnknown) // Returns the MVID if the assembly is delay-signed. // Fails if the assembly is not signed at all. STDMETHOD(GetSNAssemblySignature) ( - BYTE *pbSig, // [IN, OUT] Buffer to write signature - DWORD *pcbSig // [IN, OUT] Size of buffer, bytes written + BYTE *pbSig, // [IN, OUT] Buffer to write signature + DWORD *pcbSig // [IN, OUT] Size of buffer, bytes written ) PURE; }; @@ -406,7 +402,7 @@ DECLARE_INTERFACE_(IGetIMDInternalImport, IUnknown) * NGen logger * --------------------------------------------------------------------------- */ #include "mscorsvc.h" - + struct ICorSvcLogger; class SvcLogger { @@ -424,7 +420,7 @@ public: void Printf(CorSvcLogLevel logLevel, const WCHAR *format, ...); void SvcPrintf(const WCHAR *format, ...); void Log(const WCHAR *message, CorSvcLogLevel logLevel = LogLevel_Warning); - //Need to add this to allocate StackSString, as we don't want static class + //Need to add this to allocate StackSString, as we don't want static class private: @@ -441,7 +437,7 @@ BOOL HasSvcLogger(); #endif // #ifndef DACCESS_COMPILE // =========================================================================== -#endif // #ifdef FEATURE_PREJIT +#endif // #ifdef FEATURE_PREJIT // =========================================================================== struct CORCOMPILE_ASSEMBLY_SIGNATURE; @@ -457,18 +453,13 @@ STDAPI GetCORSystemDirectoryInternaL( SString& pBuffer ); -//LONGPATH:TODO: Remove this once Desktop usage has been removed +//LONGPATH:TODO: Remove this once Desktop usage has been removed STDAPI GetCORSystemDirectoryInternal( __out_ecount_part_opt(cchBuffer, *pdwLength) LPWSTR pBuffer, DWORD cchBuffer, __out_opt DWORD* pdwLength ); -STDAPI GetCORVersionInternal( - __out_ecount_z_opt(cchBuffer) LPWSTR pBuffer, - DWORD cchBuffer, - __out DWORD *pdwLength); - #endif // _CORPRIV_H_ // EOF ======================================================================= diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corprof.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/corprof.idl index 1d66137..cc91068 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corprof.idl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corprof.idl @@ -164,14 +164,14 @@ typedef union {FunctionID functionID; UINT_PTR clientID;} FunctionIDOrClientID; * for the same functionId. The profiler should be certain to return * the same values from this callback when it is called multiple times * with the same functionId. - * + * */ typedef UINT_PTR __stdcall FunctionIDMapper( - FunctionID funcId, + FunctionID funcId, BOOL *pbHookFunction); typedef UINT_PTR __stdcall FunctionIDMapper2( - FunctionID funcId, + FunctionID funcId, void *clientData, BOOL *pbHookFunction); @@ -307,10 +307,10 @@ typedef struct _COR_PRF_METHOD */ typedef void STDMETHODCALLTYPE FunctionEnter( FunctionID funcID); - + typedef void STDMETHODCALLTYPE FunctionLeave( FunctionID funcID); - + typedef void STDMETHODCALLTYPE FunctionTailcall( FunctionID funcID); @@ -323,20 +323,20 @@ typedef void STDMETHODCALLTYPE FunctionTailcall( */ typedef void STDMETHODCALLTYPE FunctionEnter2( - FunctionID funcId, - UINT_PTR clientData, - COR_PRF_FRAME_INFO func, + FunctionID funcId, + UINT_PTR clientData, + COR_PRF_FRAME_INFO func, COR_PRF_FUNCTION_ARGUMENT_INFO *argumentInfo); - + typedef void STDMETHODCALLTYPE FunctionLeave2( - FunctionID funcId, - UINT_PTR clientData, - COR_PRF_FRAME_INFO func, + FunctionID funcId, + UINT_PTR clientData, + COR_PRF_FRAME_INFO func, COR_PRF_FUNCTION_ARGUMENT_RANGE *retvalRange); - + typedef void STDMETHODCALLTYPE FunctionTailcall2( - FunctionID funcId, - UINT_PTR clientData, + FunctionID funcId, + UINT_PTR clientData, COR_PRF_FRAME_INFO func); /* @@ -352,10 +352,10 @@ typedef void STDMETHODCALLTYPE FunctionTailcall2( typedef void STDMETHODCALLTYPE FunctionEnter3( FunctionIDOrClientID functionIDOrClientID); - + typedef void STDMETHODCALLTYPE FunctionLeave3( FunctionIDOrClientID functionIDOrClientID); - + typedef void STDMETHODCALLTYPE FunctionTailcall3( FunctionIDOrClientID functionIDOrClientID); @@ -369,18 +369,18 @@ typedef void STDMETHODCALLTYPE FunctionTailcall3( * FunctionIDMapper[2], then this is that remapped value; else it is the * true FunctionID of the function. * - * eltInfo is an opaque handle that represents information about a given stack frame. + * eltInfo is an opaque handle that represents information about a given stack frame. * It is only valid during the callback to which it is passed. */ typedef void STDMETHODCALLTYPE FunctionEnter3WithInfo( FunctionIDOrClientID functionIDOrClientID, COR_PRF_ELT_INFO eltInfo); - + typedef void STDMETHODCALLTYPE FunctionLeave3WithInfo( FunctionIDOrClientID functionIDOrClientID, COR_PRF_ELT_INFO eltInfo); - + typedef void STDMETHODCALLTYPE FunctionTailcall3WithInfo( FunctionIDOrClientID functionIDOrClientID, COR_PRF_ELT_INFO eltInfo); @@ -405,9 +405,9 @@ typedef void STDMETHODCALLTYPE FunctionTailcall3WithInfo( * * clientData is a void* passed straight through from DoStackSnapshot * - * NOTE: One must limit the complexity of work done in StackSnapshotCallback. - * For example, particularly when using DoStackSnapshot in an asynchronous manner, - * the target thread may be holding locks. Executing code within StackSnapshotCallback + * NOTE: One must limit the complexity of work done in StackSnapshotCallback. + * For example, particularly when using DoStackSnapshot in an asynchronous manner, + * the target thread may be holding locks. Executing code within StackSnapshotCallback * that requires the same locks could lead to deadlock. */ typedef HRESULT __stdcall StackSnapshotCallback( @@ -436,7 +436,7 @@ typedef enum // behavior changes in V2. COR_PRF_MONITOR_CLASS_LOADS = 0x00000002, - // MONITOR_MODULE_LOADS controls the + // MONITOR_MODULE_LOADS controls the // ModuleLoad*, ModuleUnload*, and ModuleAttachedToAssembly // callbacks. COR_PRF_MONITOR_MODULE_LOADS = 0x00000004, @@ -450,7 +450,7 @@ typedef enum COR_PRF_MONITOR_APPDOMAIN_LOADS = 0x00000010, // MONITOR_JIT_COMPILATION controls the - // JITCompilation*, JITFunctionPitched, and JITInlining + // JITCompilation*, JITFunctionPitched, and JITInlining // callbacks. COR_PRF_MONITOR_JIT_COMPILATION = 0x00000020, @@ -472,7 +472,7 @@ typedef enum COR_PRF_MONITOR_OBJECT_ALLOCATED = 0x00000100, // MONITOR_THREADS controls the ThreadCreated, - // ThreadDestroyed, ThreadAssignedToOSThread, + // ThreadDestroyed, ThreadAssignedToOSThread, // and ThreadNameChanged callbacks. COR_PRF_MONITOR_THREADS = 0x00000200, @@ -481,11 +481,11 @@ typedef enum COR_PRF_MONITOR_REMOTING = 0x00000400, // MONITOR_CODE_TRANSITIONS controls the - // UnmanagedToManagedTransition and + // UnmanagedToManagedTransition and // ManagedToUnmanagedTransition callbacks. COR_PRF_MONITOR_CODE_TRANSITIONS = 0x00000800, - // MONITOR_ENTERLEAVE controls the + // MONITOR_ENTERLEAVE controls the // FunctionEnter*/Leave*/Tailcall* callbacks COR_PRF_MONITOR_ENTERLEAVE = 0x00001000, @@ -502,7 +502,7 @@ typedef enum COR_PRF_MONITOR_REMOTING_ASYNC = 0x00008000 | COR_PRF_MONITOR_REMOTING, // MONITOR_SUSPENDS controls the RuntimeSuspend*, - // RuntimeResume*, RuntimeThreadSuspended, and + // RuntimeResume*, RuntimeThreadSuspended, and // RuntimeThreadResumed callbacks. COR_PRF_MONITOR_SUSPENDS = 0x00010000, @@ -579,8 +579,8 @@ typedef enum // COR_PRF_REQUIRE_PROFILE_IMAGE represents all flags that require profiler-enhanced // images. - COR_PRF_REQUIRE_PROFILE_IMAGE = COR_PRF_USE_PROFILE_IMAGES | - COR_PRF_MONITOR_CODE_TRANSITIONS | + COR_PRF_REQUIRE_PROFILE_IMAGE = COR_PRF_USE_PROFILE_IMAGES | + COR_PRF_MONITOR_CODE_TRANSITIONS | COR_PRF_MONITOR_ENTERLEAVE, COR_PRF_ALLOWABLE_AFTER_ATTACH = COR_PRF_MONITOR_THREADS | @@ -640,8 +640,8 @@ typedef enum // Enables the large object allocation monitoring according to the LOH threshold. COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED = 0x00000040, - COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | - COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS | + COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | + COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS | COR_PRF_HIGH_BASIC_GC | COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS | COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED, @@ -708,6 +708,7 @@ typedef enum COR_PRF_SUSPEND_FOR_INPROC_DEBUGGER = 6, COR_PRF_SUSPEND_FOR_GC_PREP = 7, COR_PRF_SUSPEND_FOR_REJIT = 8, + COR_PRF_SUSPEND_FOR_PROFILER = 9, } COR_PRF_SUSPEND_REASON; /* @@ -735,6 +736,51 @@ typedef enum COR_PRF_REJIT_INLINING_CALLBACKS = 0x2 } COR_PRF_REJIT_FLAGS; +typedef UINT_PTR EVENTPIPE_PROVIDER; +typedef UINT_PTR EVENTPIPE_EVENT; + +typedef enum +{ + COR_PRF_EVENTPIPE_BOOLEAN = 3, // Boolean + COR_PRF_EVENTPIPE_CHAR = 4, // Unicode character + COR_PRF_EVENTPIPE_SBYTE = 5, // Signed 8-bit integer + COR_PRF_EVENTPIPE_BYTE = 6, // Unsigned 8-bit integer + COR_PRF_EVENTPIPE_INT16 = 7, // Signed 16-bit integer + COR_PRF_EVENTPIPE_UINT16 = 8, // Unsigned 16-bit integer + COR_PRF_EVENTPIPE_INT32 = 9, // Signed 32-bit integer + COR_PRF_EVENTPIPE_UINT32 = 10, // Unsigned 32-bit integer + COR_PRF_EVENTPIPE_INT64 = 11, // Signed 64-bit integer + COR_PRF_EVENTPIPE_UINT64 = 12, // Unsigned 64-bit integer + COR_PRF_EVENTPIPE_SINGLE = 13, // IEEE 32-bit float + COR_PRF_EVENTPIPE_DOUBLE = 14, // IEEE 64-bit double + COR_PRF_EVENTPIPE_DECIMAL = 15, // Decimal + COR_PRF_EVENTPIPE_DATETIME = 16, // DateTime + COR_PRF_EVENTPIPE_GUID = 17, // Guid + COR_PRF_EVENTPIPE_STRING = 18, // Unicode character string +} COR_PRF_EVENTPIPE_PARAM_TYPE; + +typedef enum +{ + COR_PRF_EVENTPIPE_LOGALWAYS = 0, + COR_PRF_EVENTPIPE_CRITICAL = 1, + COR_PRF_EVENTPIPE_ERROR = 2, + COR_PRF_EVENTPIPE_WARNING = 3, + COR_PRF_EVENTPIPE_INFORMATIONAL = 4, + COR_PRF_EVENTPIPE_VERBOSE = 5 +} COR_PRF_EVENTPIPE_LEVEL; + +typedef struct +{ + UINT32 type; + const WCHAR *name; +} COR_PRF_EVENTPIPE_PARAM_DESC; + +typedef struct +{ + UINT64 ptr; + UINT32 size; + UINT32 reserved; +} COR_PRF_EVENT_DATA; /* -------------------------------------------------------------------------- * * Forward declarations @@ -929,9 +975,9 @@ interface ICorProfilerCallback : IUnknown * this module may start coming afterwards however internal safeguards * protecting the runtime from recursive loading are still present and so it is * a bad time to begin inquiries on this module. The notification is informational - * only. + * only. * - * Note: ModuleLoadFinished is a reasonable time to interrogate MetaData via API's + * Note: ModuleLoadFinished is a reasonable time to interrogate MetaData via API's * like GetModuleMetadata, however APIs that create (e.g. ClassID's and FunctionID's) * are not safe to use here. Profiler writers are advised to stay in the universe of * tokens. @@ -996,7 +1042,7 @@ interface ICorProfilerCallback : IUnknown * this class may start coming afterwards however internal safeguards * protecting the runtime from recursive loading are still present and so it is * a bad time to begin inquiries on this class. The notification is informational - * only. + * only. * */ HRESULT ClassLoadStarted( @@ -1096,7 +1142,7 @@ interface ICorProfilerCallback : IUnknown * The JITCachedFunctionSearchStarted/Finished callbacks * will now occur only for some functions in regular NGEN images; * only profiler-optimized NGEN images will generate callbacks for - * all functions in the image. Profilers which do not use these callbacks + * all functions in the image. Profilers which do not use these callbacks * to force a function to be JIT-compiled should move to using a lazy * strategy for gathering function information. * @@ -1135,7 +1181,7 @@ interface ICorProfilerCallback : IUnknown * The JITCachedFunctionSearchStarted/Finished callbacks * will now occur only for some functions in regular NGEN images; * only profiler-optimized NGEN images will generate callbacks for - * all functions in the image. Profilers which do not use these callbacks + * all functions in the image. Profilers which do not use these callbacks * to force a function to be JIT-compiled should move to using a lazy * strategy for gathering function information. * @@ -1431,6 +1477,8 @@ interface ICorProfilerCallback : IUnknown * the runtime is preparing for a GC. * COR_PRF_SUSPEND_FOR_INPROC_DEBUGGER * the runtime is suspending for in-process debugging. + * COR_PRF_SUSPEND_FOR_PROFILER + * the runtime is suspending because of ICorProfilerInfo10::SuspendRuntime. * COR_PRF_SUSPEND_OTHER * the runtime is suspending for a reason other than those above. */ @@ -1480,7 +1528,7 @@ interface ICorProfilerCallback : IUnknown /* * The CLR calls RuntimeThreadSuspended to notify the code profiler - * that a particular thread has been suspended. + * that a particular thread has been suspended. * * This notification may occur any time between the RuntimeSuspendStarted * and the associated RuntimeResumeStarted. Notifications that occur @@ -1543,11 +1591,11 @@ interface ICorProfilerCallback : IUnknown * * NOTE: None of the objectIDs returned by MovedReferences are valid during the callback * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers - * should not attempt to inspect objects during a MovedReferences call. At + * should not attempt to inspect objects during a MovedReferences call. At * GarbageCollectionFinished, all objects have been moved to their new locations, and * inspection may be done. * - * THIS CALLBACK IS OBSOLETE. It reports ranges for objects >4GB as ULONG_MAX + * THIS CALLBACK IS OBSOLETE. It reports ranges for objects >4GB as UINT32_MAX * on 64-bit platforms. Use ICorProfilerCallback4::MovedReferences2 instead. */ HRESULT MovedReferences( @@ -1602,7 +1650,7 @@ interface ICorProfilerCallback : IUnknown * * NOTE: None of the objectIDs returned by ObjectReferences are valid during the callback * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers - * should not attempt to inspect objects during an ObjectReferences call. At + * should not attempt to inspect objects during an ObjectReferences call. At * GarbageCollectionFinished, all objects have been moved to their new locations, and * inspection may be done. */ @@ -1624,7 +1672,7 @@ interface ICorProfilerCallback : IUnknown * * NOTE: None of the objectIDs returned by RootReferences are valid during the callback * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers - * should not attempt to inspect objects during a RootReferences call. At + * should not attempt to inspect objects during a RootReferences call. At * GarbageCollectionFinished, all objects have been moved to their new locations, and * inspection may be done. */ @@ -1874,7 +1922,7 @@ typedef enum */ typedef enum -{ +{ COR_PRF_GC_ROOT_PINNING = 0x1, // Prevents GC from moving the object COR_PRF_GC_ROOT_WEAKREF = 0x2, // Does not prevent collection COR_PRF_GC_ROOT_INTERIOR = 0x4, // Refers to a field of the object rather than the object itself @@ -1882,7 +1930,7 @@ typedef enum // COR_PRF_GC_ROOT_WEAKREF will be set also } COR_PRF_GC_ROOT_FLAGS; - + /* * COR_PRF_FINALIZER_FLAGS is used by FinalizableObjectQueued to describe * the finalizer for the object. @@ -1893,7 +1941,7 @@ typedef enum COR_PRF_FINALIZER_CRITICAL = 0x1 // Critical finalizer } COR_PRF_FINALIZER_FLAGS; - + /* * COR_PRF_GC_GENERATION contains the numbers used to represent each GC generation * in the GetGenerationBounds and GetObjectGeneration functions. @@ -1904,7 +1952,8 @@ typedef enum COR_PRF_GC_GEN_0 = 0, COR_PRF_GC_GEN_1 = 1, COR_PRF_GC_GEN_2 = 2, - COR_PRF_GC_LARGE_OBJECT_HEAP = 3 + COR_PRF_GC_LARGE_OBJECT_HEAP = 3, + COR_PRF_GC_PINNED_OBJECT_HEAP= 4 } COR_PRF_GC_GENERATION; @@ -1930,19 +1979,19 @@ typedef struct COR_PRF_GC_GENERATION_RANGE typedef enum { COR_PRF_CLAUSE_NONE = 0, // not a real clause (only used in error cases) - COR_PRF_CLAUSE_FILTER = 1, - COR_PRF_CLAUSE_CATCH = 2, - COR_PRF_CLAUSE_FINALLY = 3, + COR_PRF_CLAUSE_FILTER = 1, + COR_PRF_CLAUSE_CATCH = 2, + COR_PRF_CLAUSE_FINALLY = 3, } COR_PRF_CLAUSE_TYPE; /* - * COR_PRF_EX_CLAUSE_INFO identifies a specific exception clause instance and its associated frame. - * When an exception notification is received, GetNotifiedExceptionClauseInfo() may be used to get the - * native address and frame information for the exception clause (catch/finally/filter) that is - * about to be run (ExceptionCatchEnter, ExceptionUnwindFinallyEnter, ExceptionFilterEnter) or has just - * been run (ExceptionCatchLeave, ExceptionUnwindFinallyLeave, ExceptionFilterLeave). + * COR_PRF_EX_CLAUSE_INFO identifies a specific exception clause instance and its associated frame. + * When an exception notification is received, GetNotifiedExceptionClauseInfo() may be used to get the + * native address and frame information for the exception clause (catch/finally/filter) that is + * about to be run (ExceptionCatchEnter, ExceptionUnwindFinallyEnter, ExceptionFilterEnter) or has just + * been run (ExceptionCatchLeave, ExceptionUnwindFinallyLeave, ExceptionFilterLeave). */ -typedef struct COR_PRF_EX_CLAUSE_INFO +typedef struct COR_PRF_EX_CLAUSE_INFO { COR_PRF_CLAUSE_TYPE clauseType; // the type of clause we just entered or left UINT_PTR programCounter; // the native entry point of the clause handler (e.g. EIP) @@ -1963,25 +2012,25 @@ typedef enum * Bits from COR_PRF_MODULE_FLAGS are returned to the profiler in GetModuleInfo2's * pdwModuleFlags output parameter. Some combinations of 2 or more flags are possible, * though not all combinations are possible. - */ + */ typedef enum { // The module was loaded from disk COR_PRF_MODULE_DISK = 0x00000001, - + // The module had been generated via NGEN COR_PRF_MODULE_NGEN = 0x00000002, - + // The module was created via methods in the Reflection.Emit namespace COR_PRF_MODULE_DYNAMIC = 0x00000004, - + // The module's lifetime is managed by the garbage collector. COR_PRF_MODULE_COLLECTIBLE = 0x00000008, - + // The module contains no metadata and is used strictly as a resource. The managed // equivalent of this bit is the System.Reflection.Module.IsResource() method. COR_PRF_MODULE_RESOURCE = 0x00000010, - + // The module's layout in memory is flat, as opposed to mapped. For modules that have // this bit set, profilers that directly read information out of the PE header will // need to be careful when interpreting RVAs present in the PE header. @@ -2035,11 +2084,11 @@ interface ICorProfilerCallback2 : ICorProfilerCallback */ /* - * The CLR calls GarbageCollectionStarted before beginning a + * The CLR calls GarbageCollectionStarted before beginning a * garbage collection. All GC callbacks pertaining to this * collection will occur between the GarbageCollectionStarted * callback and the corresponding GarbageCollectionFinished - * callback. Corresponding GarbageCollectionStarted and + * callback. Corresponding GarbageCollectionStarted and * GarbageCollectionFinished callbacks need not occur on the same thread. * * cGenerations indicates the total number of entries in @@ -2052,7 +2101,7 @@ interface ICorProfilerCallback2 : ICorProfilerCallback * * NOTE: It is safe to inspect objects in their original locations * during this callback. The GC will begin moving objects after - * the profiler returns from this callback. Therefore, after + * the profiler returns from this callback. Therefore, after * returning, the profiler should consider all ObjectIDs to be invalid * until it receives a GarbageCollectionFinished callback. */ @@ -2090,7 +2139,7 @@ interface ICorProfilerCallback2 : ICorProfilerCallback * objectIDRangeStart[i] <= ObjectID < objectIDRangeStart[i] + cObjectIDRangeLength[i] * for 0 <= i < cMovedObjectIDRanges, then the ObjectID has survived the collection * - * THIS CALLBACK IS OBSOLETE. It reports ranges for objects >4GB as ULONG_MAX + * THIS CALLBACK IS OBSOLETE. It reports ranges for objects >4GB as UINT32_MAX * on 64-bit platforms. Use ICorProfilerCallback4::SurvivingReferences2 instead. */ HRESULT SurvivingReferences( @@ -2152,7 +2201,7 @@ interface ICorProfilerCallback2 : ICorProfilerCallback * * NOTE: None of the objectIDs returned by RootReferences2 are valid during the callback * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers - * should not attempt to inspect objects during a RootReferences2 call. At + * should not attempt to inspect objects during a RootReferences2 call. At * GarbageCollectionFinished, all objects have been moved to their new locations, and * inspection may be done. */ @@ -2237,7 +2286,7 @@ interface ICorProfilerCallback4 : ICorProfilerCallback3 /* * This is called to report an error encountered while processing a ReJIT request. - * This may either be called from within the RequestReJIT call itself, or called after + * This may either be called from within the RequestReJIT call itself, or called after * RequestReJIT returns, if the error was encountered later on. */ HRESULT ReJITError( @@ -2268,13 +2317,13 @@ interface ICorProfilerCallback4 : ICorProfilerCallback3 * * NOTE: None of the objectIDs returned by MovedReferences are valid during the callback * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers - * should not attempt to inspect objects during a MovedReferences call. At + * should not attempt to inspect objects during a MovedReferences call. At * GarbageCollectionFinished, all objects have been moved to their new locations, and * inspection may be done. * - * If the profiler implements ICorProfilerCallback4, ICorProfilerCallback4::MovedReferences2 - * is called first and ICorProfilerCallback::MovedReferences is called second but only if - * ICorProfilerCallback4::MovedReferences2 returned success. Profilers can return failure + * If the profiler implements ICorProfilerCallback4, ICorProfilerCallback4::MovedReferences2 + * is called first and ICorProfilerCallback::MovedReferences is called second but only if + * ICorProfilerCallback4::MovedReferences2 returned success. Profilers can return failure * from ICorProfilerCallback4::MovedReferences2 to save some chattiness. */ HRESULT MovedReferences2( @@ -2312,9 +2361,9 @@ interface ICorProfilerCallback4 : ICorProfilerCallback3 * objectIDRangeStart[i] <= ObjectID < objectIDRangeStart[i] + cObjectIDRangeLength[i] * for 0 <= i < cMovedObjectIDRanges, then the ObjectID has survived the collection * - * If the profiler implements ICorProfilerCallback4, ICorProfilerCallback4::SurvivingReferences2 - * is called first and ICorProfilerCallback2::SurvivingReferences is called second but only if - * ICorProfilerCallback4::SurvivingReferences2 returned success. Profilers can return failure + * If the profiler implements ICorProfilerCallback4, ICorProfilerCallback4::SurvivingReferences2 + * is called first and ICorProfilerCallback2::SurvivingReferences is called second but only if + * ICorProfilerCallback4::SurvivingReferences2 returned success. Profilers can return failure * from ICorProfilerCallback4::SurvivingReferences2 to save some chattiness. */ HRESULT SurvivingReferences2( @@ -2334,17 +2383,17 @@ interface ICorProfilerCallback4 : ICorProfilerCallback3 interface ICorProfilerCallback5 : ICorProfilerCallback4 { /* - * The CLR calls ConditionalWeakTableElementReferences with information + * The CLR calls ConditionalWeakTableElementReferences with information * about dependent handles after a garbage collection has occurred. * - * For each root ID in rootIds, keyRefIds will contain the ObjectID for + * For each root ID in rootIds, keyRefIds will contain the ObjectID for * the primary element in the dependent handle pair, and valueRefIds will - * contain the ObjectID for the secondary element (keyRefIds[i] keeps + * contain the ObjectID for the secondary element (keyRefIds[i] keeps * valueRefIds[i] alive). * * NOTE: None of the objectIDs returned by ConditionalWeakTableElementReferences - * are valid during the callback itself, as the GC may be in the middle - * of moving objects from old to new. Thus profilers should not attempt + * are valid during the callback itself, as the GC may be in the middle + * of moving objects from old to new. Thus profilers should not attempt * to inspect objects during a ConditionalWeakTableElementReferences call. * At GarbageCollectionFinished, all objects have been moved to their new * locations, and inspection may be done. @@ -2377,11 +2426,11 @@ interface ICorProfilerCallback6 : ICorProfilerCallback5 // // The profiler uses the ICorProfilerAssemblyReferenceProvider provided to add assembly references // to the CLR assembly reference closure walker. The ICorProfilerAssemblyReferenceProvider - // should only be used from within this callback. The profiler will still need to explicitly add assembly + // should only be used from within this callback. The profiler will still need to explicitly add assembly // references via IMetaDataAssemblyEmit, from within the ModuleLoadFinished callback for the referencing assembly, // even though the profiler implements this GetAssemblyReferences callback. This callback does not result in // modified metadata; only in a modified assembly reference closure walk. - // + // // The profiler should be prepared to receive duplicate calls to this callback for the same assembly, // and should respond identically for each such duplicate call (by making the same set of // ICorProfilerAssemblyReferenceProvider::AddAssemblyReference calls). @@ -2694,7 +2743,7 @@ interface ICorProfilerInfo : IUnknown * Retrieve information about a given module. * * When the module is loaded from disk, the name returned will be the filename; - * otherwise, the name will be the name from the metadata Module table (i.e., + * otherwise, the name will be the name from the metadata Module table (i.e., * the same as the managed System.Reflection.Module.ScopeName). * * NOTE: While this function may be called as soon as the moduleId is alive, @@ -2939,7 +2988,7 @@ interface ICorProfilerInfo2 : ICorProfilerInfo * will return CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX. Contexts are * only provided by profilers that hijack threads to force them to walk their * own stacks; profilers should not attempt to provide a context when walking - * another thread's stack. If context is NULL, the stack walk will begin at the + * another thread's stack. If context is NULL, the stack walk will begin at the * last available managed frame for the target thread. * * See the definition of StackSnapshotCallback for more information. @@ -2976,14 +3025,14 @@ interface ICorProfilerInfo2 : ICorProfilerInfo /* * GetFunctionInfo2 returns the parent class of a function, plus the * function's metadata token and the ClassIDs of its type arguments - * (if any). + * (if any). * * When a COR_PRF_FRAME_INFO obtained from a FunctionEnter2 * callback is passed, the ClassID and all type arguments will be exact. * - * When a COR_PRF_FRAME_INFO from any other source is passed, or - * when 0 is passed as the frameInfo argument, exact ClassID and type - * arguments cannot always be determined. The value returned in pClassId + * When a COR_PRF_FRAME_INFO from any other source is passed, or + * when 0 is passed as the frameInfo argument, exact ClassID and type + * arguments cannot always be determined. The value returned in pClassId * may be NULL and some type args will come back as System.Object. * */ @@ -3072,7 +3121,7 @@ interface ICorProfilerInfo2 : ICorProfilerInfo * Calling this function with a TypeRef token can have unpredictable results; callers * should resolve the TypeRef to a TypeDef and use that. * - * If the type is not already loaded, calling this function will cause it to be. + * If the type is not already loaded, calling this function will cause it to be. * Loading is a dangerous operation in many contexts. For example, calling * this function during loading of modules or other types could lead to an infinite * loop as the runtime attempts to circularly load things. @@ -3098,7 +3147,7 @@ interface ICorProfilerInfo2 : ICorProfilerInfo * Calling this function with a MethodRef token can have unpredictable results; callers * should resolve the MethodRef to a MethodDef and use that. * - * If the function is not already loaded, calling this function will cause it to be. + * If the function is not already loaded, calling this function will cause it to be. * Loading is a dangerous operation in many contexts. For example, calling * this function during loading of modules or types could lead to an infinite * loop as the runtime attempts to circularly load things. @@ -3164,7 +3213,7 @@ interface ICorProfilerInfo2 : ICorProfilerInfo /* * GetRVAStaticAddress gets the address of the home for the given - * RVA static. It must be called from a managed thread. Otherwise, + * RVA static. It must be called from a managed thread. Otherwise, * it will return CORPROF_E_NOT_MANAGED_THREAD. */ HRESULT GetRVAStaticAddress( @@ -3201,11 +3250,11 @@ interface ICorProfilerInfo2 : ICorProfilerInfo /* * GetContextStaticAddress gets the address of the home for the given - * Context static in the given context. It must be called from a managed + * Context static in the given context. It must be called from a managed * thread. Otherwise, it will return CORPROF_E_NOT_MANAGED_THREAD. * * This function may return CORPROF_E_DATAINCOMPLETE if the given static - * has not been assigned a home in the given Context. + * has not been assigned a home in the given Context. */ HRESULT GetContextStaticAddress( [in] ClassID classId, @@ -3259,7 +3308,7 @@ interface ICorProfilerInfo2 : ICorProfilerInfo [in] ULONG cObjectRanges, [out] ULONG *pcObjectRanges, [out, size_is(cObjectRanges), length_is(*pcObjectRanges)] COR_PRF_GC_GENERATION_RANGE ranges[]); - + /* * GetObjectGeneration returns which generation the given object is currently in, along * with the start and length of the segment containing the object. It may be called @@ -3272,24 +3321,24 @@ interface ICorProfilerInfo2 : ICorProfilerInfo /* - * When an exception notification is received, GetNotifiedExceptionClauseInfo() may be used + * When an exception notification is received, GetNotifiedExceptionClauseInfo() may be used * to get the native address and frame information for the exception clause (catch/finally/filter) * that is about to be run (ExceptionCatchEnter, ExceptionUnwindFinallyEnter, ExceptionFilterEnter) - * or has just been run (ExceptionCatchLeave, ExceptionUnwindFinallyLeave, ExceptionFilterLeave). + * or has just been run (ExceptionCatchLeave, ExceptionUnwindFinallyLeave, ExceptionFilterLeave). * * This call may be made at any time after one of the Enter calls above until either the matching * Leave call is received or until a nested exception throws out of the current clause in which case - * there will be no Leave notification for that clause. Note it is not possible for a throw to escape + * there will be no Leave notification for that clause. Note it is not possible for a throw to escape * a Filter so there is always a Leave in that case. * * Return values: * S_OK indicates success - * S_FALSE indicates that no exception clause is active - * CORPROF_E_NOT_MANAGED_THREAD indicates an unmanaged thread. + * S_FALSE indicates that no exception clause is active + * CORPROF_E_NOT_MANAGED_THREAD indicates an unmanaged thread. */ HRESULT GetNotifiedExceptionClauseInfo( - [out] COR_PRF_EX_CLAUSE_INFO *pinfo); + [out] COR_PRF_EX_CLAUSE_INFO *pinfo); } /* @@ -3316,7 +3365,7 @@ interface ICorProfilerInfo2 : ICorProfilerInfo local ] interface ICorProfilerInfo3 : ICorProfilerInfo2 -{ +{ /* * Returns an enumerator for all previously jitted functions. May overlap with * functions previously reported via CompilationStarted callbacks. @@ -3349,8 +3398,8 @@ interface ICorProfilerInfo3 : ICorProfilerInfo2 /* * The code profiler calls SetFunctionHooks3 to specify handlers - * for FunctionEnter3, FunctionLeave3, and FunctionTailcall3, and calls - * SetFunctionHooks3WithInfo to specify handlers for FunctionEnter3WithInfo, + * for FunctionEnter3, FunctionLeave3, and FunctionTailcall3, and calls + * SetFunctionHooks3WithInfo to specify handlers for FunctionEnter3WithInfo, * FunctionLeave3WithInfo, and FunctionTailcall3WithInfo. * * Note that only one set of callbacks may be active at a time. Thus, @@ -3376,34 +3425,34 @@ interface ICorProfilerInfo3 : ICorProfilerInfo2 [in] FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); /* - * The profiler can call GetFunctionEnter3Info to gather frame info and argument info - * in FunctionEnter3WithInfo callback. The profiler needs to allocate sufficient space - * for COR_PRF_FUNCTION_ARGUMENT_INFO of the function it's inspecting and indicate the + * The profiler can call GetFunctionEnter3Info to gather frame info and argument info + * in FunctionEnter3WithInfo callback. The profiler needs to allocate sufficient space + * for COR_PRF_FUNCTION_ARGUMENT_INFO of the function it's inspecting and indicate the * size in a ULONG pointed by pcbArgumentInfo. */ - HRESULT GetFunctionEnter3Info( - [in] FunctionID functionId, + HRESULT GetFunctionEnter3Info( + [in] FunctionID functionId, [in] COR_PRF_ELT_INFO eltInfo, [out] COR_PRF_FRAME_INFO *pFrameInfo, [in, out] ULONG *pcbArgumentInfo, [out, size_is(*pcbArgumentInfo)] COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); - + /* - * The profiler can call GetFunctionLeave3Info to gather frame info and return value - * in FunctionLeave3WithInfo callback. + * The profiler can call GetFunctionLeave3Info to gather frame info and return value + * in FunctionLeave3WithInfo callback. */ - HRESULT GetFunctionLeave3Info( - [in] FunctionID functionId, + HRESULT GetFunctionLeave3Info( + [in] FunctionID functionId, [in] COR_PRF_ELT_INFO eltInfo, [out] COR_PRF_FRAME_INFO *pFrameInfo, [out] COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); - + /* - * The profiler can call GetFunctionTailcall3Info to gather frame info in - * FunctionTailcall3WithInfo callback. + * The profiler can call GetFunctionTailcall3Info to gather frame info in + * FunctionTailcall3WithInfo callback. */ - HRESULT GetFunctionTailcall3Info( - [in] FunctionID functionId, + HRESULT GetFunctionTailcall3Info( + [in] FunctionID functionId, [in] COR_PRF_ELT_INFO eltInfo, [out] COR_PRF_FRAME_INFO *pFrameInfo); @@ -3411,7 +3460,7 @@ interface ICorProfilerInfo3 : ICorProfilerInfo2 /* * The profiler can call GetRuntimeInformation to query CLR version information. - * Passing NULL to any parameter is acceptable except pcchVersionString cannot + * Passing NULL to any parameter is acceptable except pcchVersionString cannot * be NULL if szVersionString is not NULL. */ HRESULT GetRuntimeInformation([out] USHORT *pClrInstanceId, @@ -3454,12 +3503,12 @@ interface ICorProfilerInfo3 : ICorProfilerInfo2 * Retrieve information about a given module. * * When the module is loaded from disk, the name returned will be the filename; - * otherwise, the name will be the name from the metadata Module table (i.e., + * otherwise, the name will be the name from the metadata Module table (i.e., * the same as the managed System.Reflection.Module.ScopeName). - * + * * *pdwModuleFlags will be filled in with a bitmask of values from COR_PRF_MODULE_FLAGS * that specify some properties of the module. - * + * * NOTE: While this function may be called as soon as the moduleId is alive, * the AssemblyID of the containing assembly will not be available until the * ModuleAttachedToAssembly callback. @@ -3493,12 +3542,12 @@ interface ICorProfilerObjectEnum : IUnknown { HRESULT Skip( [in] ULONG celt); - + HRESULT Reset(); - + HRESULT Clone( [out] ICorProfilerObjectEnum **ppEnum); - + HRESULT GetCount( [out] ULONG *pcelt); @@ -3522,11 +3571,11 @@ interface ICorProfilerObjectEnum : IUnknown interface ICorProfilerFunctionEnum : IUnknown { HRESULT Skip([in] ULONG celt); - + HRESULT Reset(); - + HRESULT Clone([out] ICorProfilerFunctionEnum **ppEnum); - + HRESULT GetCount([out] ULONG *pcelt); HRESULT Next([in] ULONG celt, @@ -3548,11 +3597,11 @@ interface ICorProfilerFunctionEnum : IUnknown interface ICorProfilerModuleEnum : IUnknown { HRESULT Skip([in] ULONG celt); - + HRESULT Reset(); - + HRESULT Clone([out] ICorProfilerModuleEnum **ppEnum); - + HRESULT GetCount([out] ULONG *pcelt); HRESULT Next([in] ULONG celt, @@ -3588,7 +3637,7 @@ interface IMethodMalloc : IUnknown /* * The CLR implements the ICorProfilerFunctionControl interface. This interface - * is used by a code profiler to communicate with the CLR to control how the + * is used by a code profiler to communicate with the CLR to control how the * JIT should generate code when rejitting a specific method. * * The ICorProfilerFunctionControl interface implemented by the CLR uses the @@ -3650,7 +3699,7 @@ interface ICorProfilerFunctionControl : IUnknown local ] interface ICorProfilerInfo4 : ICorProfilerInfo3 -{ +{ HRESULT EnumThreads([out] ICorProfilerThreadEnum **ppEnum); HRESULT InitializeCurrentThread(); @@ -3716,7 +3765,7 @@ interface ICorProfilerInfo4 : ICorProfilerInfo3 [in] FunctionID functionId, [in] ULONG cReJitIds, [out] ULONG * pcReJitIds, - [out, size_is(cReJitIds), length_is(*pcReJitIds)] + [out, size_is(cReJitIds), length_is(*pcReJitIds)] ReJITID reJitIds[]); /* @@ -3734,7 +3783,7 @@ interface ICorProfilerInfo4 : ICorProfilerInfo3 /* * Returns an enumerator for all previously jitted functions. May overlap with * functions previously reported via CompilationStarted callbacks. The returned - * enumeration will include values for the COR_PRF_FUNCTION::reJitId field + * enumeration will include values for the COR_PRF_FUNCTION::reJitId field */ HRESULT EnumJITedFunctions2([out] ICorProfilerFunctionEnum** ppEnum); @@ -3789,12 +3838,12 @@ interface ICorProfilerInfo5 : ICorProfilerInfo4 interface ICorProfilerInfo6 : ICorProfilerInfo5 { /* - * Returns an enumerator for all methods that - * - belong to a given NGen or R2R module (inlinersModuleId) and - * - inlined a body of a given method (inlineeModuleId / inlineeMethodId). + * Returns an enumerator for all methods that + * - belong to a given NGen or R2R module (inlinersModuleId) and + * - inlined a body of a given method (inlineeModuleId / inlineeMethodId). * - * If incompleteData is set to TRUE after function is called, it means that the methods enumerator - * doesn't contain all methods inlining a given method. + * If incompleteData is set to TRUE after function is called, it means that the methods enumerator + * doesn't contain all methods inlining a given method. * It can happen when one or more direct or indirect dependencies of inliners module haven't been loaded yet. * If profiler needs accurate data it should retry later when more modules are loaded (preferably on each module load). * @@ -3803,7 +3852,7 @@ interface ICorProfilerInfo6 : ICorProfilerInfo5 * NOTE: If the inlinee method is decorated with the System.Runtime.Versioning.NonVersionable attribute then * then some inliners may not ever be reported. If you need to get a full accounting you can avoid the issue * by disabling the use of all native images. - * + * */ HRESULT EnumNgenModuleMethodsInliningThisMethod( [in] ModuleID inlinersModuleId, @@ -3841,8 +3890,8 @@ interface ICorProfilerInfo7 : ICorProfilerInfo6 * * Returns S_OK if the length could be determined (even if it is 0) * - * Note: The current implementation does not support reflection.emit. - * CORPROF_E_MODULE_IS_DYNAMIC will be returned in that case. + * Note: The current implementation does not support reflection.emit. + * CORPROF_E_MODULE_IS_DYNAMIC will be returned in that case. */ HRESULT GetInMemorySymbolsLength( [in] ModuleID moduleId, @@ -3850,7 +3899,7 @@ interface ICorProfilerInfo7 : ICorProfilerInfo6 /* Reads bytes from an in-memory symbol stream * - * This function attempts to read countSymbolBytes of data starting at offset + * This function attempts to read countSymbolBytes of data starting at offset * symbolsReadOffset within the in-memory stream. The data will be copied into * pSymbolBytes which is expected to have countSymbolBytes of space available. * pCountSymbolsBytesRead contains the actual number of bytes read which @@ -3879,7 +3928,7 @@ interface ICorProfilerInfo7 : ICorProfilerInfo6 interface ICorProfilerInfo8 : ICorProfilerInfo7 { /* - * Determines if a function has associated metadata + * Determines if a function has associated metadata * * Certain methods like IL Stubs or LCG Methods do not have * associated metadata that can be retrieved using the IMetaDataImport APIs. @@ -3961,7 +4010,7 @@ interface ICorProfilerInfo10 : ICorProfilerInfo9 /* * This method will ReJIT the methods requested, as well as any inliners * of the methods requested. - * + * * RequestReJIT does not do any tracking of inlined methods. The profiler * was expected to track inlining and call RequestReJIT for all inliners * to make sure every instance of an inlined method was ReJITted. @@ -3982,6 +4031,74 @@ interface ICorProfilerInfo10 : ICorProfilerInfo9 HRESULT ResumeRuntime(); } +[ + object, + uuid(06398876-8987-4154-B621-40A00D6E4D04), + pointer_default(unique), + local +] +interface ICorProfilerInfo11 : ICorProfilerInfo10 +{ + /* + * Get environment variable for the running managed code. + */ + HRESULT GetEnvironmentVariable( + [in, string] const WCHAR *szName, + [in] ULONG cchValue, + [out] ULONG *pcchValue, + [out, annotation("_Out_writes_to_(cchValue, *pcchValue)")] + WCHAR szValue[]); + + /* + * Set environment variable for the running managed code. + * + * The code profiler calls this function to modify environment variables of the + * current managed process. For example, it can be used in the profiler's Initialize() + * or InitializeForAttach() callbacks. + * + * szName is the name of the environment variable, should not be NULL. + * + * szValue is the contents of the environment variable, or NULL if the variable should be deleted. + */ + HRESULT SetEnvironmentVariable( + [in, string] const WCHAR *szName, + [in, string] const WCHAR *szValue); +} + +[ + object, + uuid(27b24ccd-1cb1-47c5-96ee-98190dc30959), + pointer_default(unique), + local +] +interface ICorProfilerInfo12 : ICorProfilerInfo11 +{ + HRESULT EventPipeCreateProvider( + [in, string] const WCHAR *szName, + [out] EVENTPIPE_PROVIDER *pProviderHandle); + + HRESULT EventPipeDefineEvent( + [in] EVENTPIPE_PROVIDER provHandle, + [in, string] const WCHAR *szName, + [in] UINT32 eventID, + [in] UINT64 keywords, + [in] UINT32 eventVersion, + [in] UINT32 level, + [in] BOOL needStack, + [in] UINT32 cParamDescs, + [in, size_is(cParamDescs)] + COR_PRF_EVENTPIPE_PARAM_DESC pParamDescs[], + [out] EVENTPIPE_EVENT *pEventHandle); + + HRESULT EventPipeWriteEvent( + [in] EVENTPIPE_EVENT eventHandle, + [in, size_is(cData)] + COR_PRF_EVENT_DATA data[], + [in] UINT32 cData, + [in] LPCGUID pActivityId, + [in] LPCGUID pRelatedActivityId); +} + /* * This interface lets you iterate over methods in the runtime. */ @@ -4021,11 +4138,11 @@ interface ICorProfilerMethodEnum : IUnknown interface ICorProfilerThreadEnum : IUnknown { HRESULT Skip([in] ULONG celt); - + HRESULT Reset(); - + HRESULT Clone([out] ICorProfilerThreadEnum **ppEnum); - + HRESULT GetCount([out] ULONG *pcelt); HRESULT Next([in] ULONG celt, diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corpub.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/corpub.idl index f5f0e73..35f8206 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corpub.idl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corpub.idl @@ -15,7 +15,7 @@ cpp_quote("#endif") typedef enum { COR_PUB_MANAGEDONLY = 0x00000001 // Must always be set, - // only enumerates + // only enumerates // managed processes } COR_PUB_ENUMPROCESS; @@ -79,25 +79,25 @@ interface ICorPublish : IUnknown { /* * Retrieves a list of managed processes on this machine which - * the current user has permission to debug. In this version, - * Type must always be equal to COR_PUB_MANAGEDONLY. - * The list is based on a snapshot of the processes running when + * the current user has permission to debug. In this version, + * Type must always be equal to COR_PUB_MANAGEDONLY. + * The list is based on a snapshot of the processes running when * the enum method is called. The enumerator will not reflect any * processes that start before or terminate after EnumProcesses is called. * If EnumProcesses is called more than once on this ICorPublish - * instance, a new up-to-date enumeration will be returned without + * instance, a new up-to-date enumeration will be returned without * affecting any previous ones. */ HRESULT EnumProcesses([in] COR_PUB_ENUMPROCESS Type, [out] ICorPublishProcessEnum **ppIEnum); /* - * Gets a new ICorPublishProcess object for the managed process + * Gets a new ICorPublishProcess object for the managed process * with the given process ID. Returns failure if the process doesn't * exist, or isn't a managed process that can be debugged by the current - * user. + * user. */ - HRESULT GetProcess([in] unsigned pid, + HRESULT GetProcess([in] unsigned pid, [out] ICorPublishProcess **ppProcess); } @@ -151,37 +151,37 @@ interface ICorPublishProcess : IUnknown { /* * Returns true if the process is known to have managed code - * running in it. Since this version of ICorPublish only provides access + * running in it. Since this version of ICorPublish only provides access * to managed processes, this method always returns true. */ HRESULT IsManaged([out] BOOL *pbManaged); - + /* * Enumerates the list of known application domains in this process. * This list is based on a snapshot of the existing AppDomains when * this method is called. This method may be called more than * once to create a new up-to-date list. Existing enumerations will not - * be affected by calls to this method. If the process has been + * be affected by calls to this method. If the process has been * terminated, this will fail with CORDBG_E_PROCESS_TERMINATED. */ HRESULT EnumAppDomains([out] ICorPublishAppDomainEnum **ppEnum); - + /* * Returns the OS ID for this process. */ HRESULT GetProcessID([out] unsigned *pid); - + /* * Get the full path of the executable for this process. - * If szName is non-null, this copies up to cchName characters (including + * If szName is non-null, this copies up to cchName characters (including * the null terminator) into szName, and ensures it is null-terminated. * If pcchName is non-null, the actual number of characters in the name * (including the null terminator) is stored there. This method returns * S_OK regardless of how many characters were copied. */ - HRESULT GetDisplayName([in] ULONG32 cchName, + HRESULT GetDisplayName([in] ULONG32 cchName, [out] ULONG32 *pcchName, - [out, size_is(cchName), + [out, size_is(cchName), length_is(*pcchName)] WCHAR *szName); } #pragma warning(pop) @@ -200,23 +200,23 @@ interface ICorPublishProcess : IUnknown interface ICorPublishAppDomain : IUnknown { /* - * Gets the identification number of this application domain. - * Note that this number is unique to this AppDomain, but only + * Gets the identification number of this application domain. + * Note that this number is unique to this AppDomain, but only * within the containing process. */ HRESULT GetID([out] ULONG32 *puId); - + /* * Get the name for an application domain. - * If szName is non-null, this copies up to cchName characters (including + * If szName is non-null, this copies up to cchName characters (including * the null terminator) into szName, and ensures it is null-terminated. * If pcchName is non-null, the actual number of characters in the name * (including the null terminator) is stored there. This method returns * S_OK regardless of how many characters were copied. */ - HRESULT GetName([in] ULONG32 cchName, + HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, - [out, size_is(cchName), + [out, size_is(cchName), length_is(*pcchName)] WCHAR *szName); } #pragma warning(pop) @@ -238,7 +238,7 @@ interface ICorPublishProcessEnum : ICorPublishEnum * Gets the next "celt" processes in the enumeration. */ HRESULT Next([in] ULONG celt, - [out, size_is(celt), + [out, size_is(celt), length_is(*pceltFetched)] ICorPublishProcess **objects, [out] ULONG *pceltFetched); } @@ -258,7 +258,7 @@ interface ICorPublishAppDomainEnum : ICorPublishEnum * Gets the next "celt" application domains in the enumeration. */ HRESULT Next([in] ULONG celt, - [out, size_is(celt), + [out, size_is(celt), length_is(*pceltFetched)] ICorPublishAppDomain **objects, [out] ULONG *pceltFetched); } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/corsym.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/corsym.idl index 8d7aa3f..b8ab805 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/corsym.idl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/corsym.idl @@ -294,7 +294,7 @@ typedef enum CorSymSearchPolicyAttributes interface ISymUnmanagedBinder2 : ISymUnmanagedBinder { /* - * Given a metadata interface and a file name, returns the correct + * Given a metadata interface and a file name, returns the correct * ISymUnmanagedReader interface that will read the debugging symbols associated * with the module. * @@ -327,7 +327,7 @@ interface ISymUnmanagedBinder3 : ISymUnmanagedBinder2 { /* * GetReaderFromCallback allows the user to implement supply via callback either an - * IID_IDiaReadExeAtRVACallback or IID_IDiaReadExeAtOffsetCallback to obtain the + * IID_IDiaReadExeAtRVACallback or IID_IDiaReadExeAtOffsetCallback to obtain the * Debug directory information from memory. */ HRESULT GetReaderFromCallback([in] IUnknown *importer, @@ -445,7 +445,7 @@ interface ISymUnmanagedDocument : IUnknown /* ------------------------------------------------------------------------- * * ISymUnmanagedDocumentWriter interface - * + * * Provides functions for writing to a document referenced by a symbol * store. * ------------------------------------------------------------------------- */ @@ -608,7 +608,7 @@ interface ISymENCUnmanagedMethod : IUnknown * Get the documents this method has lines in. */ HRESULT GetDocumentsForMethod([in] ULONG32 cDocs, - [out] ULONG32 *pcDocs, + [out] ULONG32 *pcDocs, [in, size_is(cDocs)] ISymUnmanagedDocument* documents[]); /* * Get the smallest start line and largest end line, for the method, in a specific document. @@ -850,8 +850,8 @@ interface ISymUnmanagedSourceServerModule : IUnknown // returns the source server data for the module // caller must free using CoTaskMemFree() HRESULT GetSourceServerData( - [out] ULONG* pDataByteCount, - [out, size_is (, *pDataByteCount)] BYTE** ppData); + [out] ULONG* pDataByteCount, + [out, size_is (, *pDataByteCount)] BYTE** ppData); } @@ -927,7 +927,7 @@ interface ISymUnmanagedReaderSymbolSearchInfo : IUnknown /* ------------------------------------------------------------------------- * * ISymUnmanagedScope interface * - * Represents a lexical scope within a method. + * Represents a lexical scope within a method. * ------------------------------------------------------------------------- */ [ @@ -1005,12 +1005,12 @@ interface ISymUnmanagedConstant : IUnknown length_is(*pcchName)] WCHAR szName[]); HRESULT GetValue(VARIANT* pValue); - + HRESULT GetSignature([in] ULONG32 cSig, [out] ULONG32 *pcSig, [out, size_is(cSig), length_is(*pcSig)] BYTE sig[]); - + }; /* @@ -1134,7 +1134,7 @@ interface ISymUnmanagedSymbolSearchInfo : IUnknown /* ------------------------------------------------------------------------- * * ISymUnmanagedWriter interface * - * Represents a symbol writer. Provides methods to define documents, + * Represents a symbol writer. Provides methods to define documents, * sequence points, lexical scopes, and variables. * ------------------------------------------------------------------------- */ @@ -1496,7 +1496,7 @@ interface ISymUnmanagedWriter3 : ISymUnmanagedWriter2 { /* * Open a method, and also provide its real section offset in image - */ + */ HRESULT OpenMethod2( [in] mdMethodDef method, [in] ULONG32 isect, [in] ULONG32 offset); @@ -1560,11 +1560,11 @@ interface ISymUnmanagedWriter5 : ISymUnmanagedWriter4 /* * Maps the given metadata token to the given source line span in the specified - * source file. + * source file. * * Must be called between calls to OpenMapTokensToSourceSpans() and * CloseMapTokensToSourceSpans(). - */ + */ HRESULT MapTokenToSourceSpan([in] mdToken token, [in] ISymUnmanagedDocumentWriter* document, [in] ULONG32 line, @@ -1604,16 +1604,16 @@ interface ISymUnmanagedReader2 : ISymUnmanagedReader [out] ULONG32 *pcBuffer, [out, size_is(cBuffer), length_is(*pcBuffer)] BYTE buffer[]); - + /* - * Gets every method that has line information in the provided Document. - */ + * Gets every method that has line information in the provided Document. + */ HRESULT GetMethodsInDocument([in] ISymUnmanagedDocument *document, [in] ULONG32 cMethod, [out] ULONG32* pcMethod, [out, size_is(cMethod), length_is(*pcMethod)] ISymUnmanagedMethod* pRetVal[]); - + }; /* ------------------------------------------------------------------------- * @@ -1625,21 +1625,21 @@ interface ISymUnmanagedReader2 : ISymUnmanagedReader uuid(d682fd12-43de-411c-811b-be8404cea126), pointer_default(unique) ] -interface ISymNGenWriter : IUnknown +interface ISymNGenWriter : IUnknown { /* * Add a new public symbol to the NGEN PDB. */ - HRESULT AddSymbol([in] BSTR pSymbol, - [in] USHORT iSection, + HRESULT AddSymbol([in] BSTR pSymbol, + [in] USHORT iSection, [in] ULONGLONG rva); - + /* * Adds a new section to the NGEN PDB. */ - HRESULT AddSection([in] USHORT iSection, - [in] USHORT flags, - [in] long offset, + HRESULT AddSection([in] USHORT iSection, + [in] USHORT flags, + [in] long offset, [in] long cb); }; @@ -1655,25 +1655,25 @@ interface ISymNGenWriter : IUnknown ] interface ISymNGenWriter2 : ISymNGenWriter { - HRESULT OpenModW([in] const wchar_t* wszModule, - [in] const wchar_t* wszObjFile, + HRESULT OpenModW([in] LPCWSTR wszModule, + [in] LPCWSTR wszObjFile, [out] BYTE** ppmod); HRESULT CloseMod([in] BYTE* pmod); HRESULT ModAddSymbols([in] BYTE* pmod, [in] BYTE* pbSym, [in] long cb); - + HRESULT ModAddSecContribEx( - [in] BYTE* pmod, - [in] USHORT isect, - [in] long off, - [in] long cb, - [in] ULONG dwCharacteristics, - [in] DWORD dwDataCrc, + [in] BYTE* pmod, + [in] USHORT isect, + [in] long off, + [in] long cb, + [in] ULONG dwCharacteristics, + [in] DWORD dwDataCrc, [in] DWORD dwRelocCrc); HRESULT QueryPDBNameExW( - [out, size_is(cchMax)] wchar_t wszPDB[], + [out, size_is(cchMax)] WCHAR wszPDB[], [in] SIZE_T cchMax); }; @@ -1727,7 +1727,7 @@ interface ISymUnmanagedAsyncMethodPropertiesWriter : IUnknown */ HRESULT DefineAsyncStepInfo([in] ULONG32 count, [in, size_is(count)] ULONG32 yieldOffsets[], - [in, size_is(count)] ULONG32 breakpointOffset[], + [in, size_is(count)] ULONG32 breakpointOffset[], [in, size_is(count)] mdToken breakpointMethod[]); }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/cortypeinfo.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/cortypeinfo.h index 6cc7325..deff42f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/cortypeinfo.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/cortypeinfo.h @@ -6,7 +6,7 @@ // // Note: This file gets parsed by the Mono IL Linker (https://github.com/mono/linker/) which may throw an exception during parsing. -// Specifically, this (https://github.com/mono/linker/blob/master/corebuild/integration/ILLink.Tasks/CreateRuntimeRootDescriptorFile.cs) will try to +// Specifically, this (https://github.com/mono/linker/blob/master/corebuild/integration/ILLink.Tasks/CreateRuntimeRootDescriptorFile.cs) will try to // parse this header, and it may throw an exception while doing that. If you edit this file and get a build failure on msbuild.exe D:\repos\coreclr\build.proj // you might want to check out the parser linked above. // diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/crosscomp.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/crosscomp.h index 62d1175..93a164c 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/crosscomp.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/crosscomp.h @@ -8,11 +8,32 @@ #pragma once -#if (!defined(_WIN64) && defined(_TARGET_64BIT_)) || (defined(_WIN64) && !defined(_TARGET_64BIT_)) +#if (!defined(HOST_64BIT) && defined(TARGET_64BIT)) || (defined(HOST_64BIT) && !defined(TARGET_64BIT)) #define CROSSBITNESS_COMPILE #endif -#if !defined(_ARM_) && defined(_TARGET_ARM_) // Non-ARM Host managing ARM related code +// Target platform-specific library naming +// +#ifdef TARGET_WINDOWS +#define MAKE_TARGET_DLLNAME_W(name) name W(".dll") +#define MAKE_TARGET_DLLNAME_A(name) name ".dll" +#else // TARGET_WINDOWS +#ifdef TARGET_OSX +#define MAKE_TARGET_DLLNAME_W(name) W("lib") name W(".dylib") +#define MAKE_TARGET_DLLNAME_A(name) "lib" name ".dylib" +#else +#define MAKE_TARGET_DLLNAME_W(name) W("lib") name W(".so") +#define MAKE_TARGET_DLLNAME_A(name) "lib" name ".so" +#endif +#endif // TARGET_WINDOWS + +#ifdef UNICODE +#define MAKE_TARGET_DLLNAME(name) MAKE_TARGET_DLLNAME_W(name) +#else +#define MAKE_TARGET_DLLNAME(name) MAKE_TARGET_DLLNAME_A(name) +#endif + +#if !defined(HOST_ARM) && defined(TARGET_ARM) // Non-ARM Host managing ARM related code #ifndef CROSS_COMPILE #define CROSS_COMPILE @@ -82,7 +103,7 @@ typedef struct DECLSPEC_ALIGN(8) _T_CONTEXT { DWORD Bcr[ARM_MAX_BREAKPOINTS]; DWORD Wvr[ARM_MAX_WATCHPOINTS]; DWORD Wcr[ARM_MAX_WATCHPOINTS]; - + DWORD Padding2[2]; } T_CONTEXT, *PT_CONTEXT; @@ -92,37 +113,15 @@ typedef struct DECLSPEC_ALIGN(8) _T_CONTEXT { // each frame function. // -#ifndef FEATURE_PAL -#ifdef _X86_ -typedef struct _RUNTIME_FUNCTION { +#if defined(HOST_WINDOWS) +typedef struct _T_RUNTIME_FUNCTION { DWORD BeginAddress; DWORD UnwindData; -} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION; - -// -// Define unwind history table structure. -// - -#define UNWIND_HISTORY_TABLE_SIZE 12 - -typedef struct _UNWIND_HISTORY_TABLE_ENTRY { - DWORD ImageBase; - PRUNTIME_FUNCTION FunctionEntry; -} UNWIND_HISTORY_TABLE_ENTRY, *PUNWIND_HISTORY_TABLE_ENTRY; - -typedef struct _UNWIND_HISTORY_TABLE { - DWORD Count; - BYTE LocalHint; - BYTE GlobalHint; - BYTE Search; - BYTE Once; - DWORD LowAddress; - DWORD HighAddress; - UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE]; -} UNWIND_HISTORY_TABLE, *PUNWIND_HISTORY_TABLE; -#endif // _X86_ -#endif // !FEATURE_PAL - +} T_RUNTIME_FUNCTION, *PT_RUNTIME_FUNCTION; +#else // HOST_WINDOWS +#define T_RUNTIME_FUNCTION RUNTIME_FUNCTION +#define PT_RUNTIME_FUNCTION PRUNTIME_FUNCTION +#endif // HOST_WINDOWS // // Nonvolatile context pointer record. @@ -156,7 +155,7 @@ typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS { // typedef -PRUNTIME_FUNCTION +PT_RUNTIME_FUNCTION (*PGET_RUNTIME_FUNCTION_CALLBACK) ( IN DWORD64 ControlPc, IN PVOID Context @@ -165,29 +164,20 @@ PRUNTIME_FUNCTION typedef struct _T_DISPATCHER_CONTEXT { ULONG ControlPc; ULONG ImageBase; - PRUNTIME_FUNCTION FunctionEntry; + PT_RUNTIME_FUNCTION FunctionEntry; ULONG EstablisherFrame; ULONG TargetPc; PT_CONTEXT ContextRecord; PEXCEPTION_ROUTINE LanguageHandler; PVOID HandlerData; - PUNWIND_HISTORY_TABLE HistoryTable; + PVOID HistoryTable; ULONG ScopeIndex; BOOLEAN ControlPcIsUnwound; PUCHAR NonVolatileRegisters; } T_DISPATCHER_CONTEXT, *PT_DISPATCHER_CONTEXT; -#if defined(FEATURE_PAL) || defined(_X86_) -#define T_RUNTIME_FUNCTION RUNTIME_FUNCTION -#define PT_RUNTIME_FUNCTION PRUNTIME_FUNCTION -#else -typedef struct _T_RUNTIME_FUNCTION { - DWORD BeginAddress; - DWORD UnwindData; -} T_RUNTIME_FUNCTION, *PT_RUNTIME_FUNCTION; -#endif -#elif defined(_AMD64_) && defined(_TARGET_ARM64_) // Host amd64 managing ARM64 related code +#elif defined(HOST_AMD64) && defined(TARGET_ARM64) // Host amd64 managing ARM64 related code #ifndef CROSS_COMPILE #define CROSS_COMPILE @@ -318,7 +308,7 @@ typedef struct _T_DISPATCHER_CONTEXT { PCONTEXT ContextRecord; PEXCEPTION_ROUTINE LanguageHandler; PVOID HandlerData; - PUNWIND_HISTORY_TABLE HistoryTable; + PVOID HistoryTable; DWORD ScopeIndex; BOOLEAN ControlPcIsUnwound; PBYTE NonVolatileRegisters; @@ -370,8 +360,66 @@ typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS { #define T_RUNTIME_FUNCTION RUNTIME_FUNCTION #define PT_RUNTIME_FUNCTION PRUNTIME_FUNCTION -#endif +#endif +#if defined(DACCESS_COMPILE) && defined(TARGET_UNIX) +// This is a TARGET oriented copy of CRITICAL_SECTION and PAL_CS_NATIVE_DATA_SIZE +// It is configured based on TARGET configuration rather than HOST configuration +// There is validation code in src/coreclr/src/vm/crst.cpp to keep these from +// getting out of sync + +#define T_CRITICAL_SECTION_VALIDATION_MESSAGE "T_CRITICAL_SECTION validation failed. It is not in sync with CRITICAL_SECTION" + +#if defined(TARGET_OSX) && defined(TARGET_X86) +#define DAC_CS_NATIVE_DATA_SIZE 76 +#elif defined(TARGET_OSX) && defined(TARGET_AMD64) +#define DAC_CS_NATIVE_DATA_SIZE 120 +#elif defined(TARGET_FREEBSD) && defined(TARGET_X86) +#define DAC_CS_NATIVE_DATA_SIZE 12 +#elif defined(TARGET_FREEBSD) && defined(TARGET_AMD64) +#define DAC_CS_NATIVE_DATA_SIZE 24 +#elif defined(TARGET_LINUX) && defined(TARGET_ARM) +#define DAC_CS_NATIVE_DATA_SIZE 80 +#elif defined(TARGET_LINUX) && defined(TARGET_ARM64) +#define DAC_CS_NATIVE_DATA_SIZE 116 +#elif defined(TARGET_LINUX) && defined(TARGET_X86) +#define DAC_CS_NATIVE_DATA_SIZE 76 +#elif defined(TARGET_LINUX) && defined(TARGET_AMD64) +#define DAC_CS_NATIVE_DATA_SIZE 96 +#elif defined(TARGET_NETBSD) && defined(TARGET_AMD64) +#define DAC_CS_NATIVE_DATA_SIZE 96 +#elif defined(TARGET_NETBSD) && defined(TARGET_ARM) +#define DAC_CS_NATIVE_DATA_SIZE 56 +#elif defined(TARGET_NETBSD) && defined(TARGET_X86) +#define DAC_CS_NATIVE_DATA_SIZE 56 +#elif defined(__sun) && defined(TARGET_AMD64) +#define DAC_CS_NATIVE_DATA_SIZE 48 +#else +#warning +#error DAC_CS_NATIVE_DATA_SIZE is not defined for this architecture. This should be same value as PAL_CS_NATIVE_DATA_SIZE (aka sizeof(PAL_CS_NATIVE_DATA)). +#endif + +struct T_CRITICAL_SECTION { + PVOID DebugInfo; + LONG LockCount; + LONG RecursionCount; + HANDLE OwningThread; + ULONG_PTR SpinCount; + +#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA + BOOL bInternal; +#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA + volatile DWORD dwInitState; + + union CSNativeDataStorage + { + BYTE rgNativeDataStorage[DAC_CS_NATIVE_DATA_SIZE]; + PVOID pvAlign; // make sure the storage is machine-pointer-size aligned + } csnds; +}; +#else +#define T_CRITICAL_SECTION CRITICAL_SECTION +#endif #ifdef CROSSGEN_COMPILE void CrossGenNotSupported(const char * message); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/crsttypes.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/crsttypes.h index e02c120..98d24c2 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/crsttypes.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/crsttypes.h @@ -11,7 +11,7 @@ // This file describes the range of Crst types available and their mapping to a numeric level (used by the // runtime in debug mode to validate we're deadlock free). To modify these settings edit the -// file:CrstTypes.def file and run the clr\bin\CrstTypeTool utility to generate a new version of this file. +// file:CrstTypes.def file and run the clr\artifacts\CrstTypeTool utility to generate a new version of this file. // Each Crst type is declared as a value in the following CrstType enum. enum CrstType @@ -35,11 +35,11 @@ enum CrstType CrstCLRPrivBinderMaps = 16, CrstCLRPrivBinderMapsAdd = 17, CrstCodeFragmentHeap = 18, - CrstCOMCallWrapper = 19, - CrstCOMWrapperCache = 20, - CrstConnectionNameTable = 21, - CrstContexts = 22, - CrstCoreCLRBinderLog = 23, + CrstCodeVersioning = 19, + CrstCOMCallWrapper = 20, + CrstCOMWrapperCache = 21, + CrstConnectionNameTable = 22, + CrstContexts = 23, CrstCrstCLRPrivBinderLocalWinMDPath = 24, CrstCSPCache = 25, CrstDataTest1 = 26, @@ -63,113 +63,115 @@ enum CrstType CrstException = 44, CrstExecuteManLock = 45, CrstExecuteManRangeLock = 46, - CrstFCall = 47, - CrstFriendAccessCache = 48, - CrstFuncPtrStubs = 49, - CrstFusionAppCtx = 50, - CrstGCCover = 51, - CrstGCMemoryPressure = 52, - CrstGlobalStrLiteralMap = 53, - CrstHandleTable = 54, - CrstHostAssemblyMap = 55, - CrstHostAssemblyMapAdd = 56, - CrstIbcProfile = 57, - CrstIJWFixupData = 58, - CrstIJWHash = 59, - CrstILStubGen = 60, - CrstInlineTrackingMap = 61, - CrstInstMethodHashTable = 62, - CrstInterfaceVTableMap = 63, - CrstInterop = 64, - CrstInteropData = 65, - CrstIOThreadpoolWorker = 66, - CrstIsJMCMethod = 67, - CrstISymUnmanagedReader = 68, - CrstJit = 69, - CrstJitGenericHandleCache = 70, - CrstJitInlineTrackingMap = 71, - CrstJitPerf = 72, - CrstJumpStubCache = 73, - CrstLeafLock = 74, - CrstListLock = 75, - CrstLoaderAllocator = 76, - CrstLoaderAllocatorReferences = 77, - CrstLoaderHeap = 78, - CrstMda = 79, - CrstMetadataTracker = 80, - CrstMethodDescBackpatchInfoTracker = 81, - CrstModIntPairList = 82, - CrstModule = 83, - CrstModuleFixup = 84, - CrstModuleLookupTable = 85, - CrstMulticoreJitHash = 86, - CrstMulticoreJitManager = 87, - CrstMUThunkHash = 88, - CrstNativeBinderInit = 89, - CrstNativeImageCache = 90, - CrstNls = 91, - CrstNotifyGdb = 92, - CrstObjectList = 93, - CrstOnEventManager = 94, - CrstPatchEntryPoint = 95, - CrstPEImage = 96, - CrstPEImagePDBStream = 97, - CrstPendingTypeLoadEntry = 98, - CrstPinHandle = 99, - CrstPinnedByrefValidation = 100, - CrstProfilerGCRefDataFreeList = 101, - CrstProfilingAPIStatus = 102, - CrstPublisherCertificate = 103, - CrstRCWCache = 104, - CrstRCWCleanupList = 105, - CrstRCWRefCache = 106, - CrstReadyToRunEntryPointToMethodDescMap = 107, - CrstReDacl = 108, - CrstReflection = 109, - CrstReJITDomainTable = 110, - CrstReJITGlobalRequest = 111, - CrstRemoting = 112, - CrstRetThunkCache = 113, - CrstRWLock = 114, - CrstSavedExceptionInfo = 115, - CrstSaveModuleProfileData = 116, - CrstSecurityStackwalkCache = 117, - CrstSharedAssemblyCreate = 118, - CrstSigConvert = 119, - CrstSingleUseLock = 120, - CrstSpecialStatics = 121, - CrstSqmManager = 122, - CrstStackSampler = 123, - CrstStressLog = 124, - CrstStrongName = 125, - CrstStubCache = 126, - CrstStubDispatchCache = 127, - CrstStubUnwindInfoHeapSegments = 128, - CrstSyncBlockCache = 129, - CrstSyncHashLock = 130, - CrstSystemBaseDomain = 131, - CrstSystemDomain = 132, - CrstSystemDomainDelayedUnloadList = 133, - CrstThreadIdDispenser = 134, - CrstThreadpoolEventCache = 135, - CrstThreadpoolTimerQueue = 136, - CrstThreadpoolWaitThreads = 137, - CrstThreadpoolWorker = 138, - CrstThreadStaticDataHashTable = 139, - CrstThreadStore = 140, - CrstTieredCompilation = 141, - CrstTPMethodTable = 142, - CrstTypeEquivalenceMap = 143, - CrstTypeIDMap = 144, - CrstUMEntryThunkCache = 145, - CrstUMThunkHash = 146, - CrstUniqueStack = 147, - CrstUnresolvedClassLock = 148, - CrstUnwindInfoTableLock = 149, - CrstVSDIndirectionCellLock = 150, - CrstWinRTFactoryCache = 151, - CrstWrapperTemplate = 152, - kNumberOfCrstTypes = 153 + CrstExternalObjectContextCache = 47, + CrstFCall = 48, + CrstFriendAccessCache = 49, + CrstFuncPtrStubs = 50, + CrstFusionAppCtx = 51, + CrstGCCover = 52, + CrstGCMemoryPressure = 53, + CrstGlobalStrLiteralMap = 54, + CrstHandleTable = 55, + CrstHostAssemblyMap = 56, + CrstHostAssemblyMapAdd = 57, + CrstIbcProfile = 58, + CrstIJWFixupData = 59, + CrstIJWHash = 60, + CrstILStubGen = 61, + CrstInlineTrackingMap = 62, + CrstInstMethodHashTable = 63, + CrstInterfaceVTableMap = 64, + CrstInterop = 65, + CrstInteropData = 66, + CrstIOThreadpoolWorker = 67, + CrstIsJMCMethod = 68, + CrstISymUnmanagedReader = 69, + CrstJit = 70, + CrstJitGenericHandleCache = 71, + CrstJitInlineTrackingMap = 72, + CrstJitPatchpoint = 73, + CrstJitPerf = 74, + CrstJumpStubCache = 75, + CrstLeafLock = 76, + CrstListLock = 77, + CrstLoaderAllocator = 78, + CrstLoaderAllocatorReferences = 79, + CrstLoaderHeap = 80, + CrstMda = 81, + CrstMetadataTracker = 82, + CrstMethodDescBackpatchInfoTracker = 83, + CrstModIntPairList = 84, + CrstModule = 85, + CrstModuleFixup = 86, + CrstModuleLookupTable = 87, + CrstMulticoreJitHash = 88, + CrstMulticoreJitManager = 89, + CrstMUThunkHash = 90, + CrstNativeBinderInit = 91, + CrstNativeImageCache = 92, + CrstNativeImageEagerFixups = 93, + CrstNls = 94, + CrstNotifyGdb = 95, + CrstObjectList = 96, + CrstOnEventManager = 97, + CrstPatchEntryPoint = 98, + CrstPEImage = 99, + CrstPEImagePDBStream = 100, + CrstPendingTypeLoadEntry = 101, + CrstPinHandle = 102, + CrstPinnedByrefValidation = 103, + CrstProfilerGCRefDataFreeList = 104, + CrstProfilingAPIStatus = 105, + CrstPublisherCertificate = 106, + CrstRCWCache = 107, + CrstRCWCleanupList = 108, + CrstRCWRefCache = 109, + CrstReadyToRunEntryPointToMethodDescMap = 110, + CrstReDacl = 111, + CrstReflection = 112, + CrstReJITGlobalRequest = 113, + CrstRemoting = 114, + CrstRetThunkCache = 115, + CrstRWLock = 116, + CrstSavedExceptionInfo = 117, + CrstSaveModuleProfileData = 118, + CrstSecurityStackwalkCache = 119, + CrstSharedAssemblyCreate = 120, + CrstSigConvert = 121, + CrstSingleUseLock = 122, + CrstSpecialStatics = 123, + CrstSqmManager = 124, + CrstStackSampler = 125, + CrstStressLog = 126, + CrstStrongName = 127, + CrstStubCache = 128, + CrstStubDispatchCache = 129, + CrstStubUnwindInfoHeapSegments = 130, + CrstSyncBlockCache = 131, + CrstSyncHashLock = 132, + CrstSystemBaseDomain = 133, + CrstSystemDomain = 134, + CrstSystemDomainDelayedUnloadList = 135, + CrstThreadIdDispenser = 136, + CrstThreadpoolEventCache = 137, + CrstThreadpoolTimerQueue = 138, + CrstThreadpoolWaitThreads = 139, + CrstThreadpoolWorker = 140, + CrstThreadStaticDataHashTable = 141, + CrstThreadStore = 142, + CrstTieredCompilation = 143, + CrstTPMethodTable = 144, + CrstTypeEquivalenceMap = 145, + CrstTypeIDMap = 146, + CrstUMEntryThunkCache = 147, + CrstUMThunkHash = 148, + CrstUniqueStack = 149, + CrstUnresolvedClassLock = 150, + CrstUnwindInfoTableLock = 151, + CrstVSDIndirectionCellLock = 152, + CrstWinRTFactoryCache = 153, + CrstWrapperTemplate = 154, + kNumberOfCrstTypes = 155 }; #endif // __CRST_TYPES_INCLUDED @@ -182,28 +184,28 @@ int g_rgCrstLevelMap[] = { 9, // CrstAllowedFiles 9, // CrstAppDomainCache - 13, // CrstAppDomainHandleTable + 14, // CrstAppDomainHandleTable 0, // CrstArgBasedStubCache 0, // CrstAssemblyDependencyGraph 0, // CrstAssemblyIdentityCache 0, // CrstAssemblyList 7, // CrstAssemblyLoader 3, // CrstAvailableClass - 3, // CrstAvailableParamTypes + 4, // CrstAvailableParamTypes 7, // CrstBaseDomain -1, // CrstCCompRC 9, // CrstCer - 12, // CrstClassFactInfoHash + 13, // CrstClassFactInfoHash 8, // CrstClassInit -1, // CrstClrNotification 0, // CrstCLRPrivBinderMaps 3, // CrstCLRPrivBinderMapsAdd 6, // CrstCodeFragmentHeap + 10, // CrstCodeVersioning 0, // CrstCOMCallWrapper 4, // CrstCOMWrapperCache 0, // CrstConnectionNameTable - 16, // CrstContexts - -1, // CrstCoreCLRBinderLog + 17, // CrstContexts 0, // CrstCrstCLRPrivBinderLocalWinMDPath 7, // CrstCSPCache 3, // CrstDataTest1 @@ -215,25 +217,26 @@ int g_rgCrstLevelMap[] = 0, // CrstDebuggerHeapExecMemLock 0, // CrstDebuggerHeapLock 4, // CrstDebuggerJitInfo - 10, // CrstDebuggerMutex + 11, // CrstDebuggerMutex 0, // CrstDelegateToFPtrHash - 15, // CrstDomainLocalBlock + 16, // CrstDomainLocalBlock 0, // CrstDynamicIL 3, // CrstDynamicMT 3, // CrstDynLinkZapItems 7, // CrstEtwTypeLogHash - 17, // CrstEventPipe + 18, // CrstEventPipe 0, // CrstEventStore 0, // CrstException 7, // CrstExecuteManLock 0, // CrstExecuteManRangeLock + 0, // CrstExternalObjectContextCache 3, // CrstFCall 7, // CrstFriendAccessCache 7, // CrstFuncPtrStubs 5, // CrstFusionAppCtx - 10, // CrstGCCover + 11, // CrstGCCover 0, // CrstGCMemoryPressure - 12, // CrstGlobalStrLiteralMap + 13, // CrstGlobalStrLiteralMap 1, // CrstHandleTable 0, // CrstHostAssemblyMap 3, // CrstHostAssemblyMapAdd @@ -242,35 +245,37 @@ int g_rgCrstLevelMap[] = 0, // CrstIJWHash 7, // CrstILStubGen 3, // CrstInlineTrackingMap - 16, // CrstInstMethodHashTable + 17, // CrstInstMethodHashTable 0, // CrstInterfaceVTableMap - 17, // CrstInterop + 18, // CrstInterop 4, // CrstInteropData - 12, // CrstIOThreadpoolWorker + 13, // CrstIOThreadpoolWorker 0, // CrstIsJMCMethod 7, // CrstISymUnmanagedReader 8, // CrstJit 0, // CrstJitGenericHandleCache - 15, // CrstJitInlineTrackingMap + 16, // CrstJitInlineTrackingMap + 3, // CrstJitPatchpoint -1, // CrstJitPerf 6, // CrstJumpStubCache 0, // CrstLeafLock -1, // CrstListLock - 14, // CrstLoaderAllocator - 15, // CrstLoaderAllocatorReferences + 15, // CrstLoaderAllocator + 16, // CrstLoaderAllocatorReferences 0, // CrstLoaderHeap 0, // CrstMda -1, // CrstMetadataTracker - 13, // CrstMethodDescBackpatchInfoTracker + 14, // CrstMethodDescBackpatchInfoTracker 0, // CrstModIntPairList 4, // CrstModule - 14, // CrstModuleFixup + 15, // CrstModuleFixup 3, // CrstModuleLookupTable 0, // CrstMulticoreJitHash - 12, // CrstMulticoreJitManager + 13, // CrstMulticoreJitManager 0, // CrstMUThunkHash -1, // CrstNativeBinderInit -1, // CrstNativeImageCache + 0, // CrstNativeImageEagerFixups 0, // CrstNls 0, // CrstNotifyGdb 2, // CrstObjectList @@ -278,7 +283,7 @@ int g_rgCrstLevelMap[] = 0, // CrstPatchEntryPoint 4, // CrstPEImage 0, // CrstPEImagePDBStream - 18, // CrstPendingTypeLoadEntry + 19, // CrstPendingTypeLoadEntry 0, // CrstPinHandle 0, // CrstPinnedByrefValidation 0, // CrstProfilerGCRefDataFreeList @@ -290,9 +295,8 @@ int g_rgCrstLevelMap[] = 4, // CrstReadyToRunEntryPointToMethodDescMap 0, // CrstReDacl 9, // CrstReflection - 9, // CrstReJITDomainTable - 14, // CrstReJITGlobalRequest - 19, // CrstRemoting + 17, // CrstReJITGlobalRequest + 20, // CrstRemoting 3, // CrstRetThunkCache 0, // CrstRWLock 3, // CrstSavedExceptionInfo @@ -312,15 +316,15 @@ int g_rgCrstLevelMap[] = 3, // CrstSyncBlockCache 0, // CrstSyncHashLock 4, // CrstSystemBaseDomain - 12, // CrstSystemDomain + 13, // CrstSystemDomain 0, // CrstSystemDomainDelayedUnloadList 0, // CrstThreadIdDispenser 0, // CrstThreadpoolEventCache 7, // CrstThreadpoolTimerQueue 7, // CrstThreadpoolWaitThreads - 12, // CrstThreadpoolWorker + 13, // CrstThreadpoolWorker 4, // CrstThreadStaticDataHashTable - 11, // CrstThreadStore + 12, // CrstThreadStore 9, // CrstTieredCompilation 9, // CrstTPMethodTable 3, // CrstTypeEquivalenceMap @@ -357,11 +361,11 @@ LPCSTR g_rgCrstNameMap[] = "CrstCLRPrivBinderMaps", "CrstCLRPrivBinderMapsAdd", "CrstCodeFragmentHeap", + "CrstCodeVersioning", "CrstCOMCallWrapper", "CrstCOMWrapperCache", "CrstConnectionNameTable", "CrstContexts", - "CrstCoreCLRBinderLog", "CrstCrstCLRPrivBinderLocalWinMDPath", "CrstCSPCache", "CrstDataTest1", @@ -385,6 +389,7 @@ LPCSTR g_rgCrstNameMap[] = "CrstException", "CrstExecuteManLock", "CrstExecuteManRangeLock", + "CrstExternalObjectContextCache", "CrstFCall", "CrstFriendAccessCache", "CrstFuncPtrStubs", @@ -410,6 +415,7 @@ LPCSTR g_rgCrstNameMap[] = "CrstJit", "CrstJitGenericHandleCache", "CrstJitInlineTrackingMap", + "CrstJitPatchpoint", "CrstJitPerf", "CrstJumpStubCache", "CrstLeafLock", @@ -429,6 +435,7 @@ LPCSTR g_rgCrstNameMap[] = "CrstMUThunkHash", "CrstNativeBinderInit", "CrstNativeImageCache", + "CrstNativeImageEagerFixups", "CrstNls", "CrstNotifyGdb", "CrstObjectList", @@ -448,7 +455,6 @@ LPCSTR g_rgCrstNameMap[] = "CrstReadyToRunEntryPointToMethodDescMap", "CrstReDacl", "CrstReflection", - "CrstReJITDomainTable", "CrstReJITGlobalRequest", "CrstRemoting", "CrstRetThunkCache", diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/crtwrap.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/crtwrap.h index aca2437..4daa22f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/crtwrap.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/crtwrap.h @@ -21,7 +21,7 @@ #include #include -#ifndef FEATURE_PAL +#ifdef HOST_WINDOWS // CoreCLR.dll uses linker .def files to control the exported symbols. // Define DLLEXPORT macro as empty on Windows. #define DLLEXPORT diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/cvconst.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/cvconst.h index 98eb19e..61d7971 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/cvconst.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/cvconst.h @@ -206,7 +206,7 @@ typedef enum CV_modifier_e { CV_MOD_CONST = 0x0001, CV_MOD_VOLATILE = 0x0002, CV_MOD_UNALIGNED = 0x0003, - + // 0x0200 - 0x03ff - HLSL modifiers. CV_MOD_HLSL_UNIFORM = 0x0200, @@ -226,7 +226,7 @@ typedef enum CV_modifier_e { CV_MOD_HLSL_UAV_GLOBALLY_COHERENT = 0x020e, // 0x0400 - 0xffff - Unused. - + } CV_modifier_e; @@ -237,7 +237,7 @@ typedef enum CV_builtin_e { // 0x0000 - 0x01ff - Reserved. CV_BI_INVALID = 0x0000, - + // 0x0200 - 0x03ff - HLSL types. CV_BI_HLSL_INTERFACE_POINTER = 0x0200, @@ -278,7 +278,7 @@ typedef enum CV_builtin_e { CV_BI_HLSL_MIN16UINT = 0x0223, // 0x0400 - 0xffff - Unused. - + } CV_builtin_e; @@ -650,7 +650,7 @@ typedef enum CV_HREG_e { CV_REG_YMM7I1 = 297, CV_REG_YMM7I2 = 298, CV_REG_YMM7I3 = 299, - + CV_REG_YMM0F0 = 300, // AVX floating-point single precise registers CV_REG_YMM0F1 = 301, CV_REG_YMM0F2 = 302, @@ -715,7 +715,7 @@ typedef enum CV_HREG_e { CV_REG_YMM7F5 = 361, CV_REG_YMM7F6 = 362, CV_REG_YMM7F7 = 363, - + CV_REG_YMM0D0 = 364, // AVX floating-point double precise registers CV_REG_YMM0D1 = 365, CV_REG_YMM0D2 = 366, @@ -1328,10 +1328,10 @@ typedef enum CV_HREG_e { // // Registers for ARM VFP10 support // - + CV_ARM_FPSCR = 40, CV_ARM_FPEXC = 41, - + CV_ARM_FS0 = 50, CV_ARM_FS1 = 51, CV_ARM_FS2 = 52, @@ -1368,7 +1368,7 @@ typedef enum CV_HREG_e { // // ARM VFP Floating Point Extra control registers // - + CV_ARM_FPEXTRA0 = 90, CV_ARM_FPEXTRA1 = 91, CV_ARM_FPEXTRA2 = 92, @@ -1379,23 +1379,23 @@ typedef enum CV_HREG_e { CV_ARM_FPEXTRA7 = 97, // XSCALE Concan co-processor registers - CV_ARM_WR0 = 128, - CV_ARM_WR1 = 129, - CV_ARM_WR2 = 130, - CV_ARM_WR3 = 131, - CV_ARM_WR4 = 132, - CV_ARM_WR5 = 133, - CV_ARM_WR6 = 134, - CV_ARM_WR7 = 135, - CV_ARM_WR8 = 136, - CV_ARM_WR9 = 137, - CV_ARM_WR10 = 138, - CV_ARM_WR11 = 139, - CV_ARM_WR12 = 140, - CV_ARM_WR13 = 141, - CV_ARM_WR14 = 142, - CV_ARM_WR15 = 143, - + CV_ARM_WR0 = 128, + CV_ARM_WR1 = 129, + CV_ARM_WR2 = 130, + CV_ARM_WR3 = 131, + CV_ARM_WR4 = 132, + CV_ARM_WR5 = 133, + CV_ARM_WR6 = 134, + CV_ARM_WR7 = 135, + CV_ARM_WR8 = 136, + CV_ARM_WR9 = 137, + CV_ARM_WR10 = 138, + CV_ARM_WR11 = 139, + CV_ARM_WR12 = 140, + CV_ARM_WR13 = 141, + CV_ARM_WR14 = 142, + CV_ARM_WR15 = 143, + // XSCALE Concan co-processor control registers CV_ARM_WCID = 144, CV_ARM_WCON = 145, @@ -1417,7 +1417,7 @@ typedef enum CV_HREG_e { // // ARM VFPv3/Neon extended floating Point // - + CV_ARM_FS32 = 200, CV_ARM_FS33 = 201, CV_ARM_FS34 = 202, @@ -1453,57 +1453,57 @@ typedef enum CV_HREG_e { // ARM double-precision floating point - CV_ARM_ND0 = 300, - CV_ARM_ND1 = 301, - CV_ARM_ND2 = 302, - CV_ARM_ND3 = 303, - CV_ARM_ND4 = 304, + CV_ARM_ND0 = 300, + CV_ARM_ND1 = 301, + CV_ARM_ND2 = 302, + CV_ARM_ND3 = 303, + CV_ARM_ND4 = 304, CV_ARM_ND5 = 305, - CV_ARM_ND6 = 306, - CV_ARM_ND7 = 307, - CV_ARM_ND8 = 308, - CV_ARM_ND9 = 309, - CV_ARM_ND10 = 310, + CV_ARM_ND6 = 306, + CV_ARM_ND7 = 307, + CV_ARM_ND8 = 308, + CV_ARM_ND9 = 309, + CV_ARM_ND10 = 310, CV_ARM_ND11 = 311, - CV_ARM_ND12 = 312, - CV_ARM_ND13 = 313, - CV_ARM_ND14 = 314, - CV_ARM_ND15 = 315, + CV_ARM_ND12 = 312, + CV_ARM_ND13 = 313, + CV_ARM_ND14 = 314, + CV_ARM_ND15 = 315, CV_ARM_ND16 = 316, - CV_ARM_ND17 = 317, - CV_ARM_ND18 = 318, - CV_ARM_ND19 = 319, - CV_ARM_ND20 = 320, + CV_ARM_ND17 = 317, + CV_ARM_ND18 = 318, + CV_ARM_ND19 = 319, + CV_ARM_ND20 = 320, CV_ARM_ND21 = 321, - CV_ARM_ND22 = 322, - CV_ARM_ND23 = 323, - CV_ARM_ND24 = 324, - CV_ARM_ND25 = 325, + CV_ARM_ND22 = 322, + CV_ARM_ND23 = 323, + CV_ARM_ND24 = 324, + CV_ARM_ND25 = 325, CV_ARM_ND26 = 326, - CV_ARM_ND27 = 327, - CV_ARM_ND28 = 328, - CV_ARM_ND29 = 329, - CV_ARM_ND30 = 330, + CV_ARM_ND27 = 327, + CV_ARM_ND28 = 328, + CV_ARM_ND29 = 329, + CV_ARM_ND30 = 330, CV_ARM_ND31 = 331, // ARM extended precision floating point - CV_ARM_NQ0 = 400, - CV_ARM_NQ1 = 401, - CV_ARM_NQ2 = 402, - CV_ARM_NQ3 = 403, - CV_ARM_NQ4 = 404, + CV_ARM_NQ0 = 400, + CV_ARM_NQ1 = 401, + CV_ARM_NQ2 = 402, + CV_ARM_NQ3 = 403, + CV_ARM_NQ4 = 404, CV_ARM_NQ5 = 405, - CV_ARM_NQ6 = 406, - CV_ARM_NQ7 = 407, - CV_ARM_NQ8 = 408, - CV_ARM_NQ9 = 409, - CV_ARM_NQ10 = 410, + CV_ARM_NQ6 = 406, + CV_ARM_NQ7 = 407, + CV_ARM_NQ8 = 408, + CV_ARM_NQ9 = 409, + CV_ARM_NQ10 = 410, CV_ARM_NQ11 = 411, - CV_ARM_NQ12 = 412, - CV_ARM_NQ13 = 413, - CV_ARM_NQ14 = 414, - CV_ARM_NQ15 = 415, + CV_ARM_NQ12 = 412, + CV_ARM_NQ13 = 413, + CV_ARM_NQ14 = 414, + CV_ARM_NQ15 = 415, // // Register set for ARM64 @@ -1694,7 +1694,7 @@ typedef enum CV_HREG_e { // Floating point status register CV_ARM64_FPSR = 220, - + // // Register set for Intel IA64 // @@ -2757,7 +2757,7 @@ typedef enum CV_HREG_e { CV_SHMEDIA_R61 = 71, CV_SHMEDIA_R62 = 72, CV_SHMEDIA_R63 = 73, - + // Target Registers - 32 bit CV_SHMEDIA_TR0 = 74, CV_SHMEDIA_TR1 = 75, @@ -3319,7 +3319,7 @@ typedef enum CV_HREG_e { CV_AMD64_YMM5 = 373, CV_AMD64_YMM6 = 374, CV_AMD64_YMM7 = 375, - CV_AMD64_YMM8 = 376, + CV_AMD64_YMM8 = 376, CV_AMD64_YMM9 = 377, CV_AMD64_YMM10 = 378, CV_AMD64_YMM11 = 379, @@ -3337,7 +3337,7 @@ typedef enum CV_HREG_e { CV_AMD64_YMM5H = 389, CV_AMD64_YMM6H = 390, CV_AMD64_YMM7H = 391, - CV_AMD64_YMM8H = 392, + CV_AMD64_YMM8H = 392, CV_AMD64_YMM9H = 393, CV_AMD64_YMM10H = 394, CV_AMD64_YMM11H = 395, @@ -3576,7 +3576,7 @@ typedef enum CV_HREG_e { CV_AMD64_YMM15F5 = 621, CV_AMD64_YMM15F6 = 622, CV_AMD64_YMM15F7 = 623, - + CV_AMD64_YMM0D0 = 624, // AVX floating-point double precise registers CV_AMD64_YMM0D1 = 625, CV_AMD64_YMM0D2 = 626, @@ -3649,47 +3649,47 @@ typedef enum CV_HREG_e { } CV_HREG_e; typedef enum CV_HLSLREG_e { - CV_HLSLREG_TEMP = 0, - CV_HLSLREG_INPUT = 1, - CV_HLSLREG_OUTPUT = 2, - CV_HLSLREG_INDEXABLE_TEMP = 3, - CV_HLSLREG_IMMEDIATE32 = 4, - CV_HLSLREG_IMMEDIATE64 = 5, - CV_HLSLREG_SAMPLER = 6, - CV_HLSLREG_RESOURCE = 7, - CV_HLSLREG_CONSTANT_BUFFER = 8, - CV_HLSLREG_IMMEDIATE_CONSTANT_BUFFER = 9, - CV_HLSLREG_LABEL = 10, - CV_HLSLREG_INPUT_PRIMITIVEID = 11, - CV_HLSLREG_OUTPUT_DEPTH = 12, - CV_HLSLREG_NULL = 13, - CV_HLSLREG_RASTERIZER = 14, - CV_HLSLREG_OUTPUT_COVERAGE_MASK = 15, - CV_HLSLREG_STREAM = 16, - CV_HLSLREG_FUNCTION_BODY = 17, - CV_HLSLREG_FUNCTION_TABLE = 18, - CV_HLSLREG_INTERFACE = 19, - CV_HLSLREG_FUNCTION_INPUT = 20, - CV_HLSLREG_FUNCTION_OUTPUT = 21, - CV_HLSLREG_OUTPUT_CONTROL_POINT_ID = 22, - CV_HLSLREG_INPUT_FORK_INSTANCE_ID = 23, - CV_HLSLREG_INPUT_JOIN_INSTANCE_ID = 24, - CV_HLSLREG_INPUT_CONTROL_POINT = 25, - CV_HLSLREG_OUTPUT_CONTROL_POINT = 26, - CV_HLSLREG_INPUT_PATCH_CONSTANT = 27, - CV_HLSLREG_INPUT_DOMAIN_POINT = 28, - CV_HLSLREG_THIS_POINTER = 29, - CV_HLSLREG_UNORDERED_ACCESS_VIEW = 30, - CV_HLSLREG_THREAD_GROUP_SHARED_MEMORY = 31, - CV_HLSLREG_INPUT_THREAD_ID = 32, - CV_HLSLREG_INPUT_THREAD_GROUP_ID = 33, - CV_HLSLREG_INPUT_THREAD_ID_IN_GROUP = 34, - CV_HLSLREG_INPUT_COVERAGE_MASK = 35, + CV_HLSLREG_TEMP = 0, + CV_HLSLREG_INPUT = 1, + CV_HLSLREG_OUTPUT = 2, + CV_HLSLREG_INDEXABLE_TEMP = 3, + CV_HLSLREG_IMMEDIATE32 = 4, + CV_HLSLREG_IMMEDIATE64 = 5, + CV_HLSLREG_SAMPLER = 6, + CV_HLSLREG_RESOURCE = 7, + CV_HLSLREG_CONSTANT_BUFFER = 8, + CV_HLSLREG_IMMEDIATE_CONSTANT_BUFFER = 9, + CV_HLSLREG_LABEL = 10, + CV_HLSLREG_INPUT_PRIMITIVEID = 11, + CV_HLSLREG_OUTPUT_DEPTH = 12, + CV_HLSLREG_NULL = 13, + CV_HLSLREG_RASTERIZER = 14, + CV_HLSLREG_OUTPUT_COVERAGE_MASK = 15, + CV_HLSLREG_STREAM = 16, + CV_HLSLREG_FUNCTION_BODY = 17, + CV_HLSLREG_FUNCTION_TABLE = 18, + CV_HLSLREG_INTERFACE = 19, + CV_HLSLREG_FUNCTION_INPUT = 20, + CV_HLSLREG_FUNCTION_OUTPUT = 21, + CV_HLSLREG_OUTPUT_CONTROL_POINT_ID = 22, + CV_HLSLREG_INPUT_FORK_INSTANCE_ID = 23, + CV_HLSLREG_INPUT_JOIN_INSTANCE_ID = 24, + CV_HLSLREG_INPUT_CONTROL_POINT = 25, + CV_HLSLREG_OUTPUT_CONTROL_POINT = 26, + CV_HLSLREG_INPUT_PATCH_CONSTANT = 27, + CV_HLSLREG_INPUT_DOMAIN_POINT = 28, + CV_HLSLREG_THIS_POINTER = 29, + CV_HLSLREG_UNORDERED_ACCESS_VIEW = 30, + CV_HLSLREG_THREAD_GROUP_SHARED_MEMORY = 31, + CV_HLSLREG_INPUT_THREAD_ID = 32, + CV_HLSLREG_INPUT_THREAD_GROUP_ID = 33, + CV_HLSLREG_INPUT_THREAD_ID_IN_GROUP = 34, + CV_HLSLREG_INPUT_COVERAGE_MASK = 35, CV_HLSLREG_INPUT_THREAD_ID_IN_GROUP_FLATTENED = 36, - CV_HLSLREG_INPUT_GS_INSTANCE_ID = 37, - CV_HLSLREG_OUTPUT_DEPTH_GREATER_EQUAL = 38, - CV_HLSLREG_OUTPUT_DEPTH_LESS_EQUAL = 39, - CV_HLSLREG_CYCLE_COUNTER = 40, + CV_HLSLREG_INPUT_GS_INSTANCE_ID = 37, + CV_HLSLREG_OUTPUT_DEPTH_GREATER_EQUAL = 38, + CV_HLSLREG_OUTPUT_DEPTH_LESS_EQUAL = 39, + CV_HLSLREG_CYCLE_COUNTER = 40, } CV_HLSLREG_e; enum StackFrameTypeEnum diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/cvinfo.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/cvinfo.h index c2e42e5..1be6858 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/cvinfo.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/cvinfo.h @@ -945,7 +945,7 @@ typedef enum LEAF_ENUM_e { LF_UTF8STRING = 0x801b, LF_REAL16 = 0x801c, - + LF_PAD0 = 0xf0, LF_PAD1 = 0xf1, LF_PAD2 = 0xf2, @@ -1001,7 +1001,7 @@ typedef enum CV_ptrtype_e { // To support for l-value and r-value reference, we added CV_PTR_MODE_LVREF // and CV_PTR_MODE_RVREF. CV_PTR_MODE_REF should be removed at some point. // We keep it now so that old code that uses it won't be broken. -// +// typedef enum CV_ptrmode_e { CV_PTR_MODE_PTR = 0x00, // "normal" pointer @@ -1665,14 +1665,14 @@ typedef struct lfFuncId { unsigned short leaf; // LF_FUNC_ID CV_ItemId scopeId; // parent scope of the ID, 0 if global CV_typ_t type; // function type - unsigned char name[CV_ZEROLEN]; + unsigned char name[CV_ZEROLEN]; } lfFuncId; typedef struct lfMFuncId { unsigned short leaf; // LF_MFUNC_ID CV_typ_t parentType; // type index of parent CV_typ_t type; // function type - unsigned char name[CV_ZEROLEN]; + unsigned char name[CV_ZEROLEN]; } lfMFuncId; typedef struct lfStringId { @@ -1693,7 +1693,7 @@ typedef struct lfUdtModSrcLine { CV_typ_t type; // UDT's type index CV_ItemId src; // index into string table where source file name is saved unsigned long line; // line number - unsigned short imod; // module that contributes this UDT definition + unsigned short imod; // module that contributes this UDT definition } lfUdtModSrcLine; typedef enum CV_BuildInfo_e { @@ -2955,7 +2955,7 @@ typedef enum SYM_ENUM_e { S_DPC_SYM_TAG_MAP = 0x1158, // DPC pointer tag value to symbol record map #endif // CC_DP_CXX - + S_ARMSWITCHTABLE = 0x1159, S_CALLEES = 0x115a, S_CALLERS = 0x115b, @@ -3054,7 +3054,7 @@ typedef struct CV_LVARFLAGS { unsigned short fAddrTaken :1; // address is taken unsigned short fCompGenx :1; // variable is compiler generated unsigned short fIsAggregate :1; // the symbol is splitted in temporaries, - // which are treated by compiler as + // which are treated by compiler as // independent entities unsigned short fIsAggregated :1; // Counterpart of fIsAggregate - tells // that it is a part of a fIsAggregate symbol @@ -3089,7 +3089,7 @@ typedef struct CV_LVAR_ADDR_RANGE { // defines a range of addresses unsigned short cbRange; } CV_LVAR_ADDR_RANGE; -// Represents the holes in overall address range, all address is pre-bbt. +// Represents the holes in overall address range, all address is pre-bbt. // it is for compress and reduce the amount of relocations need. typedef struct CV_LVAR_ADDR_GAP { @@ -4088,9 +4088,9 @@ typedef struct FRAMEPROCSYM { } FRAMEPROCSYM; #ifdef __cplusplus -namespace CodeViewInfo +namespace CodeViewInfo { -__inline unsigned short ExpandEncodedBasePointerReg(unsigned machineType, unsigned encodedFrameReg) +__inline unsigned short ExpandEncodedBasePointerReg(unsigned machineType, unsigned encodedFrameReg) { static const unsigned short rgFramePointerRegX86[] = { CV_REG_NONE, CV_ALLREG_VFRAME, CV_REG_EBP, CV_REG_EBX}; @@ -4174,7 +4174,7 @@ typedef struct INLINESITESYM2 { typedef struct LOCALSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_LOCAL - CV_typ_t typind; // type index + CV_typ_t typind; // type index CV_LVARFLAGS flags; // local var flags unsigned char name[CV_ZEROLEN]; // Name of this symbol, a null terminated array of UTF8 characters. @@ -4183,7 +4183,7 @@ typedef struct LOCALSYM { typedef struct FILESTATICSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_FILESTATIC - CV_typ_t typind; // type index + CV_typ_t typind; // type index CV_uoff32_t modOffset; // index of mod filename in stringtable CV_LVARFLAGS flags; // local var flags @@ -4197,7 +4197,7 @@ typedef struct DEFRANGESYM { // A live range of sub field of variable CV_uoff32_t program; // DIA program to evaluate the value of the symbol CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid - CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. + CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. } DEFRANGESYM; typedef struct DEFRANGESYMSUBFIELD { // A live range of sub field of variable. like locala.i @@ -4209,7 +4209,7 @@ typedef struct DEFRANGESYMSUBFIELD { // A live range of sub field of variable. l CV_uoff32_t offParent; // Offset in parent variable. CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid - CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. + CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. } DEFRANGESYMSUBFIELD; typedef struct CV_RANGEATTR { @@ -4219,11 +4219,11 @@ typedef struct CV_RANGEATTR { typedef struct DEFRANGESYMREGISTER { // A live range of en-registed variable unsigned short reclen; // Record length - unsigned short rectyp; // S_DEFRANGE_REGISTER + unsigned short rectyp; // S_DEFRANGE_REGISTER unsigned short reg; // Register to hold the value of the symbol CV_RANGEATTR attr; // Attribute of the register range. CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid - CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. + CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. } DEFRANGESYMREGISTER; typedef struct DEFRANGESYMFRAMEPOINTERREL { // A live range of frame variable @@ -4233,10 +4233,10 @@ typedef struct DEFRANGESYMFRAMEPOINTERREL { // A live range of frame variable CV_off32_t offFramePointer; // offset to frame pointer CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid - CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. + CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. } DEFRANGESYMFRAMEPOINTERREL; -typedef struct DEFRANGESYMFRAMEPOINTERREL_FULL_SCOPE { // A frame variable valid in all function scope +typedef struct DEFRANGESYMFRAMEPOINTERREL_FULL_SCOPE { // A frame variable valid in all function scope unsigned short reclen; // Record length unsigned short rectyp; // S_DEFRANGE_FRAMEPOINTER_REL @@ -4245,17 +4245,17 @@ typedef struct DEFRANGESYMFRAMEPOINTERREL_FULL_SCOPE { // A frame variable valid #define CV_OFFSET_PARENT_LENGTH_LIMIT 12 -// Note DEFRANGESYMREGISTERREL and DEFRANGESYMSUBFIELDREGISTER had same layout. +// Note DEFRANGESYMREGISTERREL and DEFRANGESYMSUBFIELDREGISTER had same layout. typedef struct DEFRANGESYMSUBFIELDREGISTER { // A live range of sub field of variable. like locala.i unsigned short reclen; // Record length - unsigned short rectyp; // S_DEFRANGE_SUBFIELD_REGISTER + unsigned short rectyp; // S_DEFRANGE_SUBFIELD_REGISTER unsigned short reg; // Register to hold the value of the symbol CV_RANGEATTR attr; // Attribute of the register range. CV_uoff32_t offParent : CV_OFFSET_PARENT_LENGTH_LIMIT; // Offset in parent variable. CV_uoff32_t padding : 20; // Padding for future use. CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid - CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. + CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. } DEFRANGESYMSUBFIELDREGISTER; // Note DEFRANGESYMREGISTERREL and DEFRANGESYMSUBFIELDREGISTER had same layout. @@ -4284,7 +4284,7 @@ typedef struct DEFRANGESYMHLSL { // A live range of variable related to a sym unsigned short spilledUdtMember : 1; // this is a spilled member unsigned short memorySpace : 4; // memory space unsigned short padding : 9; // for future use - + unsigned short offsetParent; // Offset in parent variable. unsigned short sizeInParent; // Size of enregistered portion @@ -4298,7 +4298,7 @@ typedef struct DEFRANGESYMHLSL { // A live range of variable related to a sym (((x)->reclen + sizeof((x)->reclen) - sizeof(DEFRANGESYM)) / sizeof(CV_LVAR_ADDR_GAP)) #define CV_DEFRANGESYMSUBFIELD_GAPS_COUNT(x) \ - (((x)->reclen + sizeof((x)->reclen) - sizeof(DEFRANGESYMSUBFIELD)) / sizeof(CV_LVAR_ADDR_GAP)) + (((x)->reclen + sizeof((x)->reclen) - sizeof(DEFRANGESYMSUBFIELD)) / sizeof(CV_LVAR_ADDR_GAP)) #define CV_DEFRANGESYMHLSL_GAPS_COUNT(x) \ (((x)->reclen + sizeof((x)->reclen) - sizeof(DEFRANGESYMHLSL) - (x)->regIndices * sizeof(CV_uoff32_t)) / sizeof(CV_LVAR_ADDR_GAP)) @@ -4313,10 +4313,10 @@ typedef struct DEFRANGESYMHLSL { // A live range of variable related to a sym #define CV_DEFRANGESYMHLSL_OFFSET_PTR_BASE(x, t) \ reinterpret_cast(((CV_LVAR_ADDR_GAP*)(x)->data) + CV_DEFRANGESYMHLSL_GAPS_COUNT(x)) - + #define CV_DEFRANGESYMHLSL_OFFSET_CONST_PTR(x) \ CV_DEFRANGESYMHLSL_OFFSET_PTR_BASE(x, const CV_uoff32_t*) - + #define CV_DEFRANGESYMHLSL_OFFSET_PTR(x) \ CV_DEFRANGESYMHLSL_OFFSET_PTR_BASE(x, CV_uoff32_t*) @@ -4326,12 +4326,12 @@ typedef struct DEFRANGESYMHLSL { // A live range of variable related to a sym typedef struct LOCALDPCGROUPSHAREDSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_LOCAL_DPC_GROUPSHARED - CV_typ_t typind; // type index + CV_typ_t typind; // type index CV_LVARFLAGS flags; // local var flags unsigned short dataslot; // Base data (cbuffer, groupshared, etc.) slot unsigned short dataoff; // Base data byte offset start - + unsigned char name[CV_ZEROLEN]; // Name of this symbol, a null terminated array of UTF8 characters. } LOCALDPCGROUPSHAREDSYM; @@ -4494,13 +4494,13 @@ typedef struct HEAPALLOCSITE { typedef enum CV_cookietype_e { - CV_COOKIETYPE_COPY = 0, - CV_COOKIETYPE_XOR_SP, + CV_COOKIETYPE_COPY = 0, + CV_COOKIETYPE_XOR_SP, CV_COOKIETYPE_XOR_BP, CV_COOKIETYPE_XOR_R13, } CV_cookietype_e; -// Symbol for describing security cookie's position and type +// Symbol for describing security cookie's position and type // (raw, xor'd with esp, xor'd with ebp). typedef struct FRAMECOOKIE { @@ -4578,7 +4578,7 @@ enum DEBUG_S_SUBSECTION_TYPE { }; struct CV_DebugSSubsectionHeader_t { - enum DEBUG_S_SUBSECTION_TYPE type; + enum DEBUG_S_SUBSECTION_TYPE type; CV_off32_t cbLen; }; @@ -4640,14 +4640,14 @@ typedef struct tagXFIXUP_DATA { unsigned long rvaTarget; } XFIXUP_DATA; -// Those cross scope IDs are private convention, -// it used to delay the ID merging for frontend and backend even linker. -// It is transparent for DIA client. -// Use those ID will let DIA run a litter slower and but +// Those cross scope IDs are private convention, +// it used to delay the ID merging for frontend and backend even linker. +// It is transparent for DIA client. +// Use those ID will let DIA run a litter slower and but // avoid the copy type tree in some scenarios. #ifdef __cplusplus -namespace CodeViewInfo +namespace CodeViewInfo { typedef struct ComboID @@ -4690,7 +4690,7 @@ typedef struct CrossScopeId { static const unsigned int LocalIdBitWidth = 20; static const unsigned int IdScopeBitWidth = 11; - static const unsigned int StartCrossScopeId = + static const unsigned int StartCrossScopeId = (unsigned int) (1 << (LocalIdBitWidth + IdScopeBitWidth)); static const unsigned int LocalIdMask = (1 << LocalIdBitWidth) - 1; static const unsigned int ScopeIdMask = StartCrossScopeId - (1 << LocalIdBitWidth); @@ -4701,8 +4701,8 @@ typedef struct CrossScopeId // Compilation unit at most reference to another 2K compilation units. static const unsigned int MaxScopeId = (1 << IdScopeBitWidth) - 1; - CrossScopeId(unsigned short aIdScopeId, unsigned int aLocalId) - { + CrossScopeId(unsigned short aIdScopeId, unsigned int aLocalId) + { crossScopeId = StartCrossScopeId | (aIdScopeId << LocalIdBitWidth) | aLocalId; @@ -4720,12 +4720,12 @@ typedef struct CrossScopeId return (crossScopeId & ScopeIdMask) >> LocalIdBitWidth; } - static bool IsCrossScopeId(unsigned int i) + static bool IsCrossScopeId(unsigned int i) { return (StartCrossScopeId & i) != 0; } - static CrossScopeId Decode(unsigned int i) + static CrossScopeId Decode(unsigned int i) { CrossScopeId retval; retval.crossScopeId = i; @@ -4738,7 +4738,7 @@ private: unsigned int crossScopeId; -} CrossScopeId; +} CrossScopeId; // Combined encoding of TI or FuncId, In compiler implementation // Id prefixed by 1 if it is function ID. @@ -4761,12 +4761,12 @@ typedef struct DecoratedItemId return decoratedItemId; } - bool IsFuncId() + bool IsFuncId() { return (decoratedItemId & 0x80000000) == 0x80000000; } - CV_ItemId GetItemId() + CV_ItemId GetItemId() { return decoratedItemId & 0x7fffffff; } @@ -4781,20 +4781,20 @@ private: // Or compile time PDB full path typedef struct tagPdbIdScope { - CV_off32_t offObjectFilePath; + CV_off32_t offObjectFilePath; } PdbIdScope; // An array of all imports by import module. // List all cross reference for a specific ID scope. -// Format of DEBUG_S_CROSSSCOPEIMPORTS subsection is +// Format of DEBUG_S_CROSSSCOPEIMPORTS subsection is typedef struct tagCrossScopeReferences { PdbIdScope externalScope; // Module of definition Scope. - unsigned int countOfCrossReferences; // Count of following array. + unsigned int countOfCrossReferences; // Count of following array. CV_ItemId referenceIds[CV_ZEROLEN]; // CV_ItemId in another compilation unit. } CrossScopeReferences; // An array of all exports in this module. -// Format of DEBUG_S_CROSSSCOPEEXPORTS subsection is +// Format of DEBUG_S_CROSSSCOPEEXPORTS subsection is typedef struct tagLocalIdAndGlobalIdPair { CV_ItemId localId; // local id inside the compile time PDB scope. 0 based CV_ItemId globalId; // global id inside the link time PDB scope, if scope are different. @@ -4836,11 +4836,11 @@ typedef struct tagInlineeSourceLineEx { enum BinaryAnnotationOpcode { BA_OP_Invalid, // link time pdb contains PADDINGs - BA_OP_CodeOffset, // param : start offset + BA_OP_CodeOffset, // param : start offset BA_OP_ChangeCodeOffsetBase, // param : nth separated code chunk (main code chunk == 0) BA_OP_ChangeCodeOffset, // param : delta of offset BA_OP_ChangeCodeLength, // param : length of code, default next start - BA_OP_ChangeFile, // param : fileId + BA_OP_ChangeFile, // param : fileId BA_OP_ChangeLineOffset, // param : line offset (signed) BA_OP_ChangeLineEndDelta, // param : how many lines, default 1 BA_OP_ChangeRangeKind, // param : either 1 (default, for statement) @@ -4917,14 +4917,14 @@ inline UInt32 CVCompressData( // // Return value is the uncompressed unsigned integer. pData is incremented to // point to the next piece of uncompressed data. -// +// // Returns -1 if what is passed in is incorrectly compressed data, such as // (*pBytes & 0xE0) == 0xE0. // /////////////////////////////////////////////////////////////////////////////// inline UInt32 CVUncompressData( - PCompressedAnnotation & pData) // [IN,OUT] compressed data + PCompressedAnnotation & pData) // [IN,OUT] compressed data { UInt32 res = (UInt32)(-1); @@ -4940,7 +4940,7 @@ inline UInt32 CVUncompressData( res |= *pData++; } else if ((*pData & 0xE0) == 0xC0) { - // 110? ???? + // 110? ???? res = (*pData++ & 0x1f) << 24; res |= *pData++ << 16; @@ -4948,13 +4948,13 @@ inline UInt32 CVUncompressData( res |= *pData++; } - return res; + return res; } // Encode smaller absolute numbers with smaller buffer. // -// General compression only work for input < 0x1FFFFFFF -// algorithm will not work on 0x80000000 +// General compression only work for input < 0x1FFFFFFF +// algorithm will not work on 0x80000000 inline unsigned __int32 EncodeSignedInt32(__int32 input) { diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/cycletimer.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/cycletimer.h index 229fddb..0afa858 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/cycletimer.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/cycletimer.h @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// +// // CycleTimer has methods related to getting cycle timer values. // It uses an all-statics class as a namespace mechanism. // diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/daccess.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/daccess.h index e4deab9..2c68abf 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/daccess.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/daccess.h @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. //***************************************************************************** // File: daccess.h -// +// // // Support for external access of runtime data structures. These @@ -27,24 +27,24 @@ // way to write data back currently. // // DAC-ized code: -// - is read-only (non-invasive). So DACized codepaths can not trigger a GC. +// - is read-only (non-invasive). So DACized codepaths can not trigger a GC. // - has no Thread* object. In reality, DAC-ized codepaths are -// ReadProcessMemory calls from out-of-process. Conceptually, they -// are like a pure-native (preemptive) thread. +// ReadProcessMemory calls from out-of-process. Conceptually, they +// are like a pure-native (preemptive) thread. //// -// This means that in particular, you cannot DACize a GCTRIGGERS function. +// This means that in particular, you cannot DACize a GCTRIGGERS function. // Neither can you DACize a function that throws if this will involve -// allocating a new exception object. There may be -// exceptions to these rules if you can guarantee that the DACized -// part of the code path cannot cause a garbage collection (see -// EditAndContinueModule::ResolveField for an example). -// If you need to DACize a function that may trigger +// allocating a new exception object. There may be +// exceptions to these rules if you can guarantee that the DACized +// part of the code path cannot cause a garbage collection (see +// EditAndContinueModule::ResolveField for an example). +// If you need to DACize a function that may trigger // a GC, it is probably best to refactor the function so that the DACized // part of the code path is in a separate function. For instance, -// functions with GetOrCreate() semantics are hard to DAC-ize because +// functions with GetOrCreate() semantics are hard to DAC-ize because // they the Create portion is inherently invasive. Instead, consider refactoring -// into a GetOrFail() function that DAC can call; and then make GetOrCreate() -// a wrapper around that. +// into a GetOrFail() function that DAC can call; and then make GetOrCreate() +// a wrapper around that. // // This code works by hiding the details of access to target memory. @@ -87,7 +87,7 @@ // PTR_RangeSection pleft; // ... Other fields omitted ... // } RangeSection; -// +// // RangeSection* pRS = m_RangeTree; // // while (pRS != NULL) @@ -289,7 +289,7 @@ // ... // } // -// SystemDomain::m_appDomainIndexList; +// SystemDomain::m_appDomainIndexList; // // extern DWORD gThreadTLSIndex; // @@ -314,7 +314,7 @@ // SVAL_IMPL(ArrayListStatic, SystemDomain, m_appDomainIndexList); // // GVAL_DECL(DWORD, gThreadTLSIndex); -// +// // GVAL_IMPL_INIT(DWORD, gThreadTLSIndex, TLS_OUT_OF_INDEXES); // // When declaring the variable, the first argument declares the @@ -325,27 +325,27 @@ // // Things get slightly more complicated when declaring an embedded // array. In this case the data element is not a single element and -// therefore cannot be represented by a ?PTR. In the case of a global +// therefore cannot be represented by a ?PTR. In the case of a global // array, you should use the GARY_DECL and GARY_IMPL macros. // We durrently have no support for declaring static array data members // or initialized arrays. Array data members that are dynamically allocated // need to be treated as pointer members. To reference individual elements // you must use pointer arithmetic (see rule 2 above). An array declared -// as a local variable within a function does not need to be DACized. +// as a local variable within a function does not need to be DACized. // // // All uses of ?VAL_DECL must have a corresponding entry given in the // DacGlobals structure in src\inc\dacvars.h. For SVAL_DECL the entry -// is class__name. For GVAL_DECL the entry is dac__name. You must add +// is class__name. For GVAL_DECL the entry is dac__name. You must add // these entries in dacvars.h using the DEFINE_DACVAR macro. Note that -// these entries also are used for dumping memory in mini dumps and -// heap dumps. If it's not appropriate to dump a variable, (e.g., -// it's an array or some other value that is not important to have -// in a minidump) a second macro, DEFINE_DACVAR_NO_DUMP, will allow +// these entries also are used for dumping memory in mini dumps and +// heap dumps. If it's not appropriate to dump a variable, (e.g., +// it's an array or some other value that is not important to have +// in a minidump) a second macro, DEFINE_DACVAR_NO_DUMP, will allow // you to make the required entry in the DacGlobals structure without -// dumping its value. +// dumping its value. // -// For convenience, here is a list of the various variable declaration and +// For convenience, here is a list of the various variable declaration and // initialization macros: // SVAL_DECL(type, name) static non-pointer data class MyClass // member declared within { @@ -355,11 +355,11 @@ // // SVAL_IMPL(type, cls, name) static non-pointer data // int MyClass::i; // member defined outside SVAL_IMPL(int, MyClass, i); -// the class declaration +// the class declaration // // SVAL_IMPL_INIT(type, cls, static non-pointer data // int MyClass::i = 0; // name, val) member defined and SVAL_IMPL_INIT(int, MyClass, i, 0); -// initialized outside the +// initialized outside the // class declaration // ------------------------------------------------------------------------------------------------ // SPTR_DECL(type, name) static pointer data class MyClass @@ -370,27 +370,27 @@ // // SPTR_IMPL(type, cls, name) static pointer data // int * MyClass::pInt; // member defined outside SPTR_IMPL(int, MyClass, pInt); -// the class declaration +// the class declaration // // SPTR_IMPL_INIT(type, cls, static pointer data // int * MyClass::pInt = NULL; // name, val) member defined and SPTR_IMPL_INIT(int, MyClass, pInt, NULL); -// initialized outside the +// initialized outside the // class declaration // ------------------------------------------------------------------------------------------------ // GVAL_DECL(type, name) extern declaration of // extern int g_i // global non-pointer GVAL_DECL(int, g_i); -// variable +// variable // // GVAL_IMPL(type, name) declaration of a // int g_i // global non-pointer GVAL_IMPL(int, g_i); -// variable +// variable // // GVAL_IMPL_INIT (type, declaration and // int g_i = 0; // name, initialization of a GVAL_IMPL_INIT(int, g_i, 0); // val) global non-pointer // variable // ****Note**** -// If you use GVAL_? to declare a global variable of a structured type and you need to +// If you use GVAL_? to declare a global variable of a structured type and you need to // access a member of the type, you cannot use the dot operator. Instead, you must take the // address of the variable and use the arrow operator. For example: // struct @@ -400,14 +400,14 @@ // } MyStruct; // GVAL_IMPL(MyStruct, g_myStruct); // int i = (&g_myStruct)->x; -// ------------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------------ // GPTR_DECL(type, name) extern declaration of // extern int * g_pInt // global pointer GPTR_DECL(int, g_pInt); -// variable +// variable // // GPTR_IMPL(type, name) declaration of a // int * g_pInt // global pointer GPTR_IMPL(int, g_pInt); -// variable +// variable // // GPTR_IMPL_INIT (type, declaration and // int * g_pInt = 0; // name, initialization of a GPTR_IMPL_INIT(int, g_pInt, NULL); @@ -416,11 +416,11 @@ // ------------------------------------------------------------------------------------------------ // GARY_DECL(type, name) extern declaration of // extern int g_rgIntList[MAX_ELEMENTS]; // a global array GPTR_DECL(int, g_rgIntList, MAX_ELEMENTS); -// variable +// variable // // GARY_IMPL(type, name) declaration of a // int g_rgIntList[MAX_ELEMENTS]; // global pointer GPTR_IMPL(int, g_rgIntList, MAX_ELEMENTS); -// variable +// variable // // // Certain pieces of code, such as the stack walker, rely on identifying @@ -585,26 +585,26 @@ struct DacTableHeader // This requires special casting to ULONG64 to sign-extend if necessary. typedef ULONG_PTR TADDR; -// TSIZE_T used for counts or ranges that need to span the size of a +// TSIZE_T used for counts or ranges that need to span the size of a // target pointer. For cross-plat, this may be different than SIZE_T // which reflects the host pointer size. typedef SIZE_T TSIZE_T; // -// The following table contains all the global information that data access needs to begin -// operation. All of the values stored here are RVAs. DacGlobalBase() returns the current +// The following table contains all the global information that data access needs to begin +// operation. All of the values stored here are RVAs. DacGlobalBase() returns the current // base address to combine with to get a full target address. // typedef struct _DacGlobals { -#ifdef FEATURE_PAL +#ifdef TARGET_UNIX static void Initialize(); void InitializeEntries(TADDR baseAddress); -#endif // FEATURE_PAL +#endif // TARGET_UNIX -// These will define all of the dac related mscorwks static and global variables +// These will define all of the dac related mscorwks static and global variables #define DEFINE_DACVAR(id_type, size, id, var) id_type id; #define DEFINE_DACVAR_NO_DUMP(id_type, size, id, var) id_type id; #include "dacvars.h" @@ -614,9 +614,9 @@ typedef struct _DacGlobals ULONG fn__DACNotifyCompilationFinished; ULONG fn__ThePreStub; -#ifdef _TARGET_ARM_ +#ifdef TARGET_ARM ULONG fn__ThePreStubCompactARM; -#endif // _TARGET_ARM_ +#endif // TARGET_ARM ULONG fn__ThePreStubPatchLabel; ULONG fn__PrecodeFixupThunk; @@ -689,7 +689,7 @@ HRESULT DacWriteHostInstance(PVOID host, bool throwEx); // This is meant to mimic the RethrowTerminalExceptions/ // SwallowAllExceptions/RethrowTransientExceptions macros to allow minidump -// gathering cancelation for details see +// gathering cancelation for details see // code:ClrDataAccess.EnumMemoryRegionsWrapper // This is usable in EX_TRY exactly how RethrowTerminalExceptions et cetera @@ -697,7 +697,7 @@ HRESULT DacWriteHostInstance(PVOID host, bool throwEx); if (GET_EXCEPTION()->GetHR() == COR_E_OPERATIONCANCELED) \ { \ EX_RETHROW; \ - } + } // Occasionally it's necessary to allocate some host memory for // instance data that's created on the fly and so doesn't directly @@ -718,7 +718,7 @@ bool DacHostPtrHasEnumMark(LPCVOID host); // This helps perf for minidumps of apps with large managed stacks. bool DacHasMethodDescBeenEnumerated(LPCVOID pMD); -// Sets a flag indicating that EnumMemoryRegions on a method desciptor +// Sets a flag indicating that EnumMemoryRegions on a method desciptor // has been successfully called. The function returns true if // this flag had been previously set. bool DacSetMethodDescEnumerated(LPCVOID pMD); @@ -729,8 +729,8 @@ BOOL DacValidateMD(LPCVOID pMD); // Enumerate the instructions around a call site to help debugger stack walking heuristics void DacEnumCodeForStackwalk(TADDR taCallEnd); -// Given the address and the size of a memory range which is stored in the buffer, replace all the patches -// in the buffer with the real opcodes. This is especially important on X64 where the unwinder needs to +// Given the address and the size of a memory range which is stored in the buffer, replace all the patches +// in the buffer with the real opcodes. This is especially important on X64 where the unwinder needs to // disassemble the native instructions. class MemoryRange; HRESULT DacReplacePatchesInHostMemory(MemoryRange range, PVOID pBuffer); @@ -738,7 +738,7 @@ HRESULT DacReplacePatchesInHostMemory(MemoryRange range, PVOID pBuffer); // // Convenience macros for EnumMemoryRegions implementations. // - + // Enumerate the given host instance and return // true if the instance hasn't already been enumerated. #define DacEnumHostDPtrMem(host) \ @@ -766,29 +766,29 @@ HRESULT DacReplacePatchesInHostMemory(MemoryRange range, PVOID pBuffer); if (!DacEnumHostSPtrMem(this, type)) return #define DAC_ENUM_VTHIS() \ if (!DacEnumHostVPtrMem(this)) return - + #ifdef __cplusplus } class ReflectionModule; interface IMDInternalImport* DacGetMDImport(const class PEFile* peFile, bool throwEx); -interface IMDInternalImport* DacGetMDImport(const ReflectionModule* reflectionModule, +interface IMDInternalImport* DacGetMDImport(const ReflectionModule* reflectionModule, bool throwEx); int DacGetIlMethodSize(TADDR methAddr); struct COR_ILMETHOD* DacGetIlMethod(TADDR methAddr); -#ifdef WIN64EXCEPTIONS +#ifdef FEATURE_EH_FUNCLETS struct _UNWIND_INFO * DacGetUnwindInfo(TADDR taUnwindInfo); // virtually unwind a CONTEXT out-of-process struct _KNONVOLATILE_CONTEXT_POINTERS; BOOL DacUnwindStackFrame(T_CONTEXT * pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers); -#endif // WIN64EXCEPTIONS +#endif // FEATURE_EH_FUNCLETS -#if defined(FEATURE_PAL) +#if defined(TARGET_UNIX) // call back through data target to unwind out-of-process HRESULT DacVirtualUnwind(ULONG32 threadId, PT_CONTEXT context, PT_KNONVOLATILE_CONTEXT_POINTERS contextPointers); -#endif // FEATURE_PAL +#endif // TARGET_UNIX #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS class SString; @@ -796,17 +796,17 @@ void DacMdCacheAddEEName(TADDR taEE, const SString& ssEEName); bool DacMdCacheGetEEName(TADDR taEE, SString & ssEEName); #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS -// +// // Computes (taBase + (dwIndex * dwElementSize()), with overflow checks. -// +// // Arguments: // taBase the base TADDR value // dwIndex the index of the offset // dwElementSize the size of each element (to multiply the offset by) -// +// // Return value: // The resulting TADDR, or throws CORDB_E_TARGET_INCONSISTENT on overlow. -// +// // Notes: // The idea here is that overflows during address arithmetic suggest that we're operating on corrupt // pointers. It helps to improve reliability to detect the cases we can (like overflow) and fail. Note @@ -814,7 +814,7 @@ bool DacMdCacheGetEEName(TADDR taEE, SString & ssEEName); // failing on overflow is just one easy case of corruption to detect. There is no need to use checked // arithmetic everywhere in the DAC infrastructure, this is intended just for the places most likely to // help catch bugs (eg. __DPtr::operator[]). -// +// inline TADDR DacTAddrOffset( TADDR taBase, TSIZE_T dwIndex, TSIZE_T dwElementSize ) { ClrSafeInt t(taBase); @@ -847,10 +847,10 @@ public: return m_addr == 0; } // We'd like to have an implicit conversion to bool here since the C++ - // standard says all pointer types are implicitly converted to bool. + // standard says all pointer types are implicitly converted to bool. // Unfortunately, that would cause ambiguous overload errors for uses // of operator== and operator!=. Instead callers will have to compare - // directly against NULL. + // directly against NULL. bool operator==(TADDR addr) const { @@ -893,21 +893,21 @@ protected: // Pointer wrapper base class for various forms of normal data. // This has the common functionality between __DPtr and __ArrayDPtr. -// The DPtrType type parameter is the actual derived type in use. This is necessary so that -// inhereted functions preserve exact return types. +// The DPtrType type parameter is the actual derived type in use. This is necessary so that +// inhereted functions preserve exact return types. template class __DPtrBase : public __TPtrBase { public: typedef type _Type; typedef type* _Ptr; - + protected: - // Constructors + // Constructors // All protected - this type should not be used directly - use one of the derived types instead. __DPtrBase< type, DPtrType >(void) : __TPtrBase() {} __DPtrBase< type, DPtrType >(TADDR addr) : __TPtrBase(addr) {} - + explicit __DPtrBase< type, DPtrType >(__TPtrBase addr) { m_addr = addr.GetAddr(); @@ -969,7 +969,7 @@ public: // Array index operator // we want an operator[] for all possible numeric types (rather than rely on - // implicit numeric conversions on the argument) to prevent ambiguity with + // implicit numeric conversions on the argument) to prevent ambiguity with // DPtr's implicit conversion to type* and the built-in operator[]. // @dbgtodo : we could also use this technique to simplify other operators below. template @@ -1001,7 +1001,7 @@ public: //------------------------------------------------------------------------- // operator+ - + DPtrType operator+(unsigned short val) { return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type))); @@ -1019,7 +1019,7 @@ public: { return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type))); } -#if defined (_WIN64) +#if defined (HOST_64BIT) DPtrType operator+(unsigned int val) { return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type))); @@ -1045,7 +1045,7 @@ public: //------------------------------------------------------------------------- // operator- - + DPtrType operator-(unsigned short val) { return DPtrType(m_addr - val * sizeof(type)); @@ -1063,7 +1063,7 @@ public: { return DPtrType(m_addr - val * sizeof(type)); } -#ifdef _WIN64 +#ifdef HOST_64BIT DPtrType operator-(unsigned int val) { return DPtrType(m_addr - val * sizeof(type)); @@ -1092,7 +1092,7 @@ public: } //------------------------------------------------------------------------- - + DPtrType& operator+=(size_t val) { m_addr += val * sizeof(type); @@ -1103,7 +1103,7 @@ public: m_addr -= val * sizeof(type); return static_cast(*this); } - + DPtrType& operator++() { m_addr += sizeof(type); @@ -1158,8 +1158,8 @@ public: __DPtr< type >(__DPtr const & rhs) : __DPtrBase >(rhs.GetAddr()) {} // construct from GlobalPtr - explicit __DPtr< type >(__GlobalPtr< type*, __DPtr< type > > globalPtr) : - __DPtrBase >(globalPtr.GetAddr()) {} + explicit __DPtr< type >(__GlobalPtr< type*, __DPtr< type > > globalPtr) : + __DPtrBase >(globalPtr.GetAddr()) {} explicit __DPtr< type >(__TPtrBase addr) : __DPtrBase >(addr) {} explicit __DPtr< type >(type const * host) : __DPtrBase >(host) {} @@ -1179,7 +1179,7 @@ public: // A restricted form of DPtr that doesn't have any conversions to pointer types. // This is useful for pointer types that almost always represent arrays, as opposed // to pointers to single instances (eg. PTR_BYTE). In these cases, allowing implicit -// conversions to (for eg.) BYTE* would usually result in incorrect usage (eg. pointer +// conversions to (for eg.) BYTE* would usually result in incorrect usage (eg. pointer // arithmetic and array indexing), since only a single instance has been marshalled to the host. // If you really must marshal a single instance (eg. converting T* to PTR_T is too painful for now), // then use code:DacUnsafeMarshalSingleElement so we can identify such unsafe code. @@ -1193,7 +1193,7 @@ public: // construct const from non-const typedef typename std::remove_const::type mutable_type; - __ArrayDPtr< type >(__ArrayDPtr const & rhs) : __DPtrBase >(rhs.GetAddr()) {} + __ArrayDPtr< type >(__ArrayDPtr const & rhs) : __DPtrBase >(rhs.GetAddr()) {} explicit __ArrayDPtr< type >(__TPtrBase addr) : __DPtrBase >(addr) {} @@ -1214,7 +1214,7 @@ class __SPtr : public __TPtrBase public: typedef type _Type; typedef type* _Ptr; - + __SPtr< type >(void) : __TPtrBase() {} __SPtr< type >(TADDR addr) : __TPtrBase(addr) {} explicit __SPtr< type >(__TPtrBase addr) @@ -1269,7 +1269,7 @@ public: { DacError(E_INVALIDARG); } - + return *(type*)DacInstantiateTypeByAddress(m_addr, type::DacSize(m_addr), true); @@ -1306,7 +1306,7 @@ public: // This type is not expected to be used anyway. typedef type* _Type; typedef type* _Ptr; - + __VPtr< type >(void) : __TPtrBase() {} __VPtr< type >(TADDR addr) : __TPtrBase(addr) {} explicit __VPtr< type >(__TPtrBase addr) @@ -1317,7 +1317,7 @@ public: { m_addr = DacGetTargetAddrForHostAddr(host, true); } - + __VPtr< type >& operator=(const __TPtrBase& ptr) { m_addr = ptr.GetAddr(); @@ -1337,7 +1337,7 @@ public: { return (type*)DacInstantiateClassByVTable(m_addr, sizeof(type), true); } - + bool operator==(const __VPtr< type >& ptr) const { return m_addr == ptr.m_addr; @@ -1378,7 +1378,7 @@ class __Str8Ptr : public __DPtr public: typedef type _Type; typedef type* _Ptr; - + __Str8Ptr< type, maxChars >(void) : __DPtr() {} __Str8Ptr< type, maxChars >(TADDR addr) : __DPtr(addr) {} explicit __Str8Ptr< type, maxChars >(__TPtrBase addr) @@ -1431,7 +1431,7 @@ class __Str16Ptr : public __DPtr public: typedef type _Type; typedef type* _Ptr; - + __Str16Ptr< type, maxChars >(void) : __DPtr() {} __Str16Ptr< type, maxChars >(TADDR addr) : __DPtr(addr) {} explicit __Str16Ptr< type, maxChars >(__TPtrBase addr) @@ -1508,7 +1508,7 @@ public: DacWriteHostInstance(ptr, true); return *this; } - + bool IsValid(void) const { return __DPtr< type >(DacGlobalBase() + *m_rvaPtr).IsValid(); @@ -1536,12 +1536,12 @@ public: { return __DPtr< type >(DacGlobalBase() + *m_rvaPtr); } - + type& operator[](unsigned int index) const { return __DPtr< type >(DacGlobalBase() + *m_rvaPtr)[index]; } - + bool IsValid(void) const { // Only validates the base pointer, not the full array range. @@ -1569,7 +1569,7 @@ public: { return __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr); } - + store_type & operator=(store_type & val) { store_type* ptr = __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr); @@ -1579,7 +1579,7 @@ public: DacWriteHostInstance(ptr, true); return val; } - + acc_type operator->() const { return (acc_type)*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr); @@ -1601,7 +1601,7 @@ public: { return (*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr))[index]; } - + typename store_type::_Type& operator[](unsigned int index) { return (*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr))[index]; @@ -1616,7 +1616,7 @@ public: { return DacGlobalBase() + *m_rvaPtr; } - + // This is only testing the the pointer memory is available but does not verify // the memory that it points to. // @@ -1624,7 +1624,7 @@ public: { return __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr).IsValid(); } - + bool IsValid(void) const { return __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr).IsValid() && @@ -1672,7 +1672,7 @@ inline bool operator!=(acc_type host, } -// +// // __VoidPtr is a type that behaves like void* but for target pointers. // Behavior of PTR_VOID: // * has void* semantics. Will compile to void* in non-DAC builds (just like @@ -1683,14 +1683,14 @@ inline bool operator!=(acc_type host, // * like void*, no pointer arithmetic or dereferencing is allowed // * like TADDR, can be used to construct any __DPtr / __VPtr instance // * representation is the same as a void* (for marshalling / casting) -// +// // One way in which __VoidPtr is unlike void* is that it can't be cast to // pointer or integer types. On the one hand, this is a good thing as it forces // us to keep target pointers separate from other data types. On the other hand // in practice this means we have to use dac_cast in places where we used // to use a (TADDR) cast. Unfortunately C++ provides us no way to allow the // explicit cast to primitive types without also allowing implicit conversions. -// +// // This is very similar in spirit to TADDR. The primary difference is that // PTR_VOID has pointer semantics, where TADDR has integer semantics. When // dacizing uses of void* to TADDR, casts must be inserted everywhere back to @@ -1700,7 +1700,7 @@ inline bool operator!=(acc_type host, // instead etc.). Ideally we'd probably have just one type for this purpose // (named TADDR but with the semantics of PTR_VOID), but outright conversion // would require too much work. -// +// class __VoidPtr : public __TPtrBase { public: @@ -1714,7 +1714,7 @@ public: m_addr = addr.GetAddr(); } - // Like TPtrBase, VoidPtrs can also be created impicitly from all GlobalPtrs + // Like TPtrBase, VoidPtrs can also be created impicitly from all GlobalPtrs template __VoidPtr(__GlobalPtr globalPtr) { @@ -1778,7 +1778,7 @@ public: bool operator>=(const __TPtrBase& ptr) const { return m_addr >= ptr.GetAddr(); - } + } }; typedef __VoidPtr PTR_VOID; @@ -1805,21 +1805,21 @@ typedef __VoidPtr PTR_CVOID; // // VPTR_ANY_CLASS_METHODS - Defines the following methods for all VPTR classes -// -// VPtrSize +// +// VPtrSize // Returns the size of the dynamic type of the object (as opposed to sizeof -// which is based only on the static type). -// +// which is based only on the static type). +// // VPtrHostVTable // Returns the address of the vtable for this type. -// We create a temporary instance of this type in order to read it's vtable pointer +// We create a temporary instance of this type in order to read it's vtable pointer // (at offset 0). For this temporary instance, we do not want to initialize any fields, // so we use the marshalling ctor. Since we didn't initialize any fields, we also don't -// wan't to run the dtor (marshaled data structures don't normally expect their destructor -// or non-DAC constructors to be called in DAC builds anyway). So, rather than create a -// normal stack object, or put the object on the heap, we create the temporary object +// wan't to run the dtor (marshaled data structures don't normally expect their destructor +// or non-DAC constructors to be called in DAC builds anyway). So, rather than create a +// normal stack object, or put the object on the heap, we create the temporary object // on the stack using placement-new and alloca, and don't destruct it. -// +// #define VPTR_ANY_CLASS_METHODS(name) \ virtual ULONG32 VPtrSize(void) { SUPPORTS_DAC; return sizeof(name); } \ static PVOID VPtrHostVTable() { \ @@ -1970,15 +1970,15 @@ public: name(TADDR addr, TADDR vtAddr); // This value is used to intiailize target pointers to NULL. We want this to be TADDR type // (as opposed to, say, __TPtrBase) so that it can be used in the non-explicit ctor overloads, -// eg. as an argument default value. -// We can't always just use NULL because that's 0 which (in C++) can be any integer or pointer +// eg. as an argument default value. +// We can't always just use NULL because that's 0 which (in C++) can be any integer or pointer // type (causing an ambiguous overload compiler error when used in explicit ctor forms). #define PTR_NULL ((TADDR)0) // Provides an empty method implementation when compiled // for DACCESS_COMPILE. For example, use to stub out methods needed // for vtable entries but otherwise unused. -// Note that these functions are explicitly NOT marked SUPPORTS_DAC so that we'll get a +// Note that these functions are explicitly NOT marked SUPPORTS_DAC so that we'll get a // DacCop warning if any calls to them are detected. // @dbgtodo : It's probably almost always wrong to call any such function, so // we should probably throw a better error (DacNotImpl), and ideally mark the function @@ -2069,7 +2069,7 @@ enum DacCopWarningCode // if). // // Arguments: -// code: a literal value from DacCopWarningCode indicating which violation should be suppressed. +// code: a literal value from DacCopWarningCode indicating which violation should be suppressed. // szReasonString: a short description of why this exclusion is necessary. This is intended just // to help readers of the code understand the source of the problem, and what would be required // to fix it. More details can be provided in comments if desired. @@ -2087,10 +2087,10 @@ inline void DACCOP_IGNORE(DacCopWarningCode code, const char * szReasonString) // ******************************************************* // !!!!!!!!!!!!!!!!!!!!!!!!!NOTE!!!!!!!!!!!!!!!!!!!!!!!!!! -// -// Please search this file for the type name to find the +// +// Please search this file for the type name to find the // DAC versions of these definitions -// +// // !!!!!!!!!!!!!!!!!!!!!!!!!NOTE!!!!!!!!!!!!!!!!!!!!!!!!!! // ******************************************************* @@ -2099,7 +2099,7 @@ inline void DACCOP_IGNORE(DacCopWarningCode code, const char * szReasonString) // can be done on it directly, as with the DACCESS_COMPILE definition. // This also helps expose pointer usage that may need to be changed. typedef ULONG_PTR TADDR; - + typedef void* PTR_VOID; typedef LPVOID* PTR_PTR_VOID; typedef const void* PTR_CVOID; @@ -2113,7 +2113,7 @@ typedef const void* PTR_CVOID; #define S16PTR(type) type* #define S16PTRMAX(type, maxChars) type* -#if defined(FEATURE_PAL) +#if defined(TARGET_UNIX) #define VPTR_VTABLE_CLASS(name, base) \ friend struct _DacGlobals; \ @@ -2147,7 +2147,7 @@ public: name(int dummy) : base(dummy) {} VPTR_ABSTRACT_VTABLE_CLASS(name, base) \ name() : base() {} -#else // FEATURE_PAL +#else // TARGET_UNIX #define VPTR_VTABLE_CLASS(name, base) #define VPTR_VTABLE_CLASS_AND_CTOR(name, base) @@ -2158,15 +2158,14 @@ public: name(int dummy) : base(dummy) {} #define VPTR_ABSTRACT_VTABLE_CLASS(name, base) #define VPTR_ABSTRACT_VTABLE_CLASS_AND_CTOR(name, base) -#endif // FEATURE_PAL +#endif // TARGET_UNIX // helper macro to make the vtables unique for DAC #define VPTR_UNIQUE(unique) virtual int MakeVTableUniqueForDAC() { return unique; } #define VPTR_UNIQUE_BaseDomain (100000) #define VPTR_UNIQUE_SystemDomain (VPTR_UNIQUE_BaseDomain + 1) #define VPTR_UNIQUE_ComMethodFrame (VPTR_UNIQUE_SystemDomain + 1) -#define VPTR_UNIQUE_StubHelperFrame (VPTR_UNIQUE_ComMethodFrame + 1) -#define VPTR_UNIQUE_RedirectedThreadFrame (VPTR_UNIQUE_StubHelperFrame + 1) +#define VPTR_UNIQUE_RedirectedThreadFrame (VPTR_UNIQUE_ComMethodFrame + 1) #define VPTR_UNIQUE_HijackFrame (VPTR_UNIQUE_RedirectedThreadFrame + 1) #define PTR_TO_TADDR(ptr) ((TADDR)(ptr)) @@ -2222,7 +2221,7 @@ public: name(int dummy) : base(dummy) {} #define DAC_EMPTY() #define DAC_EMPTY_ERR() #define DAC_EMPTY_RET(retVal) -#define DAC_UNEXPECTED() +#define DAC_UNEXPECTED() #define DACCOP_IGNORE(warningCode, reasonString) @@ -2244,13 +2243,13 @@ public: name(int dummy) : base(dummy) {} // ?PTR(Tgt) <- TADDR - Create PTR type (DPtr etc.) from TADDR // ?PTR(Tgt) <- ?PTR(Src) - Convert one PTR type to another // ?PTR(Tgt) <- Src * - Create PTR type from dac host object instance -// TADDR <- ?PTR(Src) - Get TADDR of PTR object (DPtr etc.) -// TADDR <- Src * - Get TADDR of dac host object instance +// TADDR <- ?PTR(Src) - Get TADDR of PTR object (DPtr etc.) +// TADDR <- Src * - Get TADDR of dac host object instance // // Note that there is no direct convertion to other host-pointer types (because we don't // know if you want a DPTR or VPTR etc.). However, due to the implicit DAC conversions, // you can just use dac_cast and assign that to a Foo*. -// +// // The beauty of this syntax is that it is consistent regardless // of source and target casting types. You just use dac_cast // and the partial template specialization will do the right thing. @@ -2276,7 +2275,7 @@ public: name(int dummy) : base(dummy) {} // Example comparsions of some old and new syntax, where // h is a host pointer, such as "Foo *h;" // p is a DPTR, such as "PTR_Foo p;" -// +// // PTR_HOST_TO_TADDR(h) ==> dac_cast(h) // PTR_TO_TADDR(p) ==> dac_cast(p) // PTR_Foo(PTR_HOST_TO_TADDR(h)) ==> dac_cast(h) @@ -2294,7 +2293,7 @@ inline Tgt dac_cast(Src src) // In non-DAC builds, dac_cast is the same as a C-style cast because we need to support: // - casting away const // - conversions between pointers and TADDR - // Perhaps we should more precisely restrict it's usage, but we get the precise + // Perhaps we should more precisely restrict it's usage, but we get the precise // restrictions in DAC builds, so it wouldn't buy us much. return (Tgt)(src); #endif @@ -2393,19 +2392,19 @@ typedef DPTR(IMAGE_TLS_DIRECTORY) PTR_IMAGE_TLS_DIRECTORY; #include #endif -#if defined(_TARGET_X86_) && defined(FEATURE_PAL) +#if defined(TARGET_X86) && defined(TARGET_UNIX) typedef DPTR(struct _UNWIND_INFO) PTR_UNWIND_INFO; #endif -#ifdef _TARGET_64BIT_ +#ifdef TARGET_64BIT typedef DPTR(T_RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; typedef DPTR(struct _UNWIND_INFO) PTR_UNWIND_INFO; -#if defined(_TARGET_AMD64_) +#if defined(TARGET_AMD64) typedef DPTR(union _UNWIND_CODE) PTR_UNWIND_CODE; -#endif // _TARGET_AMD64_ -#endif // _TARGET_64BIT_ +#endif // TARGET_AMD64 +#endif // TARGET_64BIT -#ifdef _TARGET_ARM_ +#ifdef TARGET_ARM typedef DPTR(T_RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; #endif @@ -2419,7 +2418,7 @@ typedef TADDR PCODE; typedef DPTR(PCODE) PTR_PCODE; typedef DPTR(PTR_PCODE) PTR_PTR_PCODE; -// There is another concept we should have, "pointer to the start of an instruction" -- a PCODE with any mode bits masked off. +// There is another concept we should have, "pointer to the start of an instruction" -- a PCODE with any mode bits masked off. // Attempts to introduce this concept, and classify uses of PCODE as one or the other, // turned out to be too hard: either name choice required *many* code changes, and decisions in unfamiliar code. So despite the // the comment above, the PCODE is currently sometimes used for the PINSTR concept. @@ -2452,11 +2451,23 @@ typedef DPTR(PTR_PCODE) PTR_PTR_PCODE; #define MAIN_DAC_MODULE_NAME_W W("mscordaccore") #define MAIN_DAC_MODULE_DLL_NAME_W W("mscordaccore.dll") -// TARGET_CONSISTENCY_CHECK represents a condition that should not fail unless the DAC target is corrupt. +// TARGET_CONSISTENCY_CHECK represents a condition that should not fail unless the DAC target is corrupt. // This is in contrast to ASSERTs in DAC infrastructure code which shouldn't fail regardless of the memory // read from the target. At the moment we treat these the same, but in the future we will want a mechanism // for disabling just the target consistency checks (eg. for tests that intentionally use corrupted targets). // @dbgtodo : Separating asserts and target consistency checks is tracked by DevDiv Bugs 31674 #define TARGET_CONSISTENCY_CHECK(expr,msg) _ASSERTE_MSG(expr,msg) +// For cross compilation, controlling type layout is important +// We add a simple macro here which defines DAC_ALIGNAS to the C++11 alignas operator +// This helps force the alignment of the next member +// For most cross compilation cases the layout of types simply works +// There are a few cases (where this macro is helpful) which are not consistent accross platforms: +// - Base class whose size is padded to its align size. On Linux the gcc/clang +// layouts will reuse this padding in the derived class for the first member +// - Class with an vtable pointer and an alignment greater than the pointer size. +// The Windows compilers will align the first member to the alignment size of the +// class. Linux will align the first member to its natural alignment +#define DAC_ALIGNAS(a) alignas(a) + #endif // #ifndef __daccess_h__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/dacprivate.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/dacprivate.h index 7a12c64..eec8a37 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/dacprivate.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/dacprivate.h @@ -15,10 +15,10 @@ #include #include -#ifndef FEATURE_PAL +#ifndef TARGET_UNIX // It is unfortunate having to include this header just to get the definition of GenericModeBlock #include -#endif // FEATURE_PAL +#endif // TARGET_UNIX // // Whenever a structure is marshalled between different platforms, we need to ensure the @@ -37,26 +37,12 @@ // want to go changing the layout of, for example, structures defined in OS header files // so we explicitly opt-in with this attribute. // -#ifdef __GNUC__ +#if defined(__GNUC__) && defined(HOST_X86) #define MSLAYOUT __attribute__((__ms_struct__)) #else #define MSLAYOUT #endif -//---------------------------------------------------------------------------- -// -// Utility class to allow for zero initialization of our Dacp- structs. -// -//---------------------------------------------------------------------------- - -template -struct ZeroInit -{ - ZeroInit() - { memset(static_cast(this), 0, sizeof(T)); } -}; - - #include //---------------------------------------------------------------------------- @@ -81,39 +67,39 @@ enum }; enum DacpObjectType { OBJ_STRING=0,OBJ_FREE,OBJ_OBJECT,OBJ_ARRAY,OBJ_OTHER }; -struct MSLAYOUT DacpObjectData : ZeroInit +struct MSLAYOUT DacpObjectData { - CLRDATA_ADDRESS MethodTable; - DacpObjectType ObjectType; - ULONG64 Size; - CLRDATA_ADDRESS ElementTypeHandle; - CorElementType ElementType; - DWORD dwRank; - ULONG64 dwNumComponents; - ULONG64 dwComponentSize; - CLRDATA_ADDRESS ArrayDataPtr; - CLRDATA_ADDRESS ArrayBoundsPtr; - CLRDATA_ADDRESS ArrayLowerBoundsPtr; + CLRDATA_ADDRESS MethodTable = 0; + DacpObjectType ObjectType = DacpObjectType::OBJ_STRING; + ULONG64 Size = 0; + CLRDATA_ADDRESS ElementTypeHandle = 0; + CorElementType ElementType = CorElementType::ELEMENT_TYPE_END; + DWORD dwRank = 0; + ULONG64 dwNumComponents = 0; + ULONG64 dwComponentSize = 0; + CLRDATA_ADDRESS ArrayDataPtr = 0; + CLRDATA_ADDRESS ArrayBoundsPtr = 0; + CLRDATA_ADDRESS ArrayLowerBoundsPtr = 0; + + CLRDATA_ADDRESS RCW = 0; + CLRDATA_ADDRESS CCW = 0; - CLRDATA_ADDRESS RCW; - CLRDATA_ADDRESS CCW; - HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetObjectData(addr, this); } }; -struct MSLAYOUT DacpExceptionObjectData : ZeroInit +struct MSLAYOUT DacpExceptionObjectData { - CLRDATA_ADDRESS Message; - CLRDATA_ADDRESS InnerException; - CLRDATA_ADDRESS StackTrace; - CLRDATA_ADDRESS WatsonBuckets; - CLRDATA_ADDRESS StackTraceString; - CLRDATA_ADDRESS RemoteStackTraceString; - INT32 HResult; - INT32 XCode; + CLRDATA_ADDRESS Message = 0; + CLRDATA_ADDRESS InnerException = 0; + CLRDATA_ADDRESS StackTrace = 0; + CLRDATA_ADDRESS WatsonBuckets = 0; + CLRDATA_ADDRESS StackTraceString = 0; + CLRDATA_ADDRESS RemoteStackTraceString = 0; + INT32 HResult = 0; + INT32 XCode = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { @@ -128,31 +114,31 @@ struct MSLAYOUT DacpExceptionObjectData : ZeroInit } }; -struct MSLAYOUT DacpUsefulGlobalsData : ZeroInit +struct MSLAYOUT DacpUsefulGlobalsData { - CLRDATA_ADDRESS ArrayMethodTable; - CLRDATA_ADDRESS StringMethodTable; - CLRDATA_ADDRESS ObjectMethodTable; - CLRDATA_ADDRESS ExceptionMethodTable; - CLRDATA_ADDRESS FreeMethodTable; + CLRDATA_ADDRESS ArrayMethodTable = 0; + CLRDATA_ADDRESS StringMethodTable = 0; + CLRDATA_ADDRESS ObjectMethodTable = 0; + CLRDATA_ADDRESS ExceptionMethodTable = 0; + CLRDATA_ADDRESS FreeMethodTable = 0; }; -struct MSLAYOUT DacpFieldDescData : ZeroInit +struct MSLAYOUT DacpFieldDescData { - CorElementType Type; - CorElementType sigType; // ELEMENT_TYPE_XXX from signature. We need this to disply pretty name for String in minidump's case - CLRDATA_ADDRESS MTOfType; // NULL if Type is not loaded - - CLRDATA_ADDRESS ModuleOfType; - mdTypeDef TokenOfType; - - mdFieldDef mb; - CLRDATA_ADDRESS MTOfEnclosingClass; - DWORD dwOffset; - BOOL bIsThreadLocal; - BOOL bIsContextLocal; - BOOL bIsStatic; - CLRDATA_ADDRESS NextField; + CorElementType Type = CorElementType::ELEMENT_TYPE_END; + CorElementType sigType = CorElementType::ELEMENT_TYPE_END; // ELEMENT_TYPE_XXX from signature. We need this to disply pretty name for String in minidump's case + CLRDATA_ADDRESS MTOfType = 0; // NULL if Type is not loaded + + CLRDATA_ADDRESS ModuleOfType = 0; + mdTypeDef TokenOfType = 0; + + mdFieldDef mb = 0; + CLRDATA_ADDRESS MTOfEnclosingClass = 0; + DWORD dwOffset = 0; + BOOL bIsThreadLocal = FALSE; + BOOL bIsContextLocal = FALSE; + BOOL bIsStatic = FALSE; + CLRDATA_ADDRESS NextField = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { @@ -160,27 +146,27 @@ struct MSLAYOUT DacpFieldDescData : ZeroInit } }; -struct MSLAYOUT DacpMethodTableFieldData : ZeroInit +struct MSLAYOUT DacpMethodTableFieldData { - WORD wNumInstanceFields; - WORD wNumStaticFields; - WORD wNumThreadStaticFields; + WORD wNumInstanceFields = 0; + WORD wNumStaticFields = 0; + WORD wNumThreadStaticFields = 0; + + CLRDATA_ADDRESS FirstField = 0; // If non-null, you can retrieve more + + WORD wContextStaticOffset = 0; + WORD wContextStaticsSize = 0; - CLRDATA_ADDRESS FirstField; // If non-null, you can retrieve more - - WORD wContextStaticOffset; - WORD wContextStaticsSize; - HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetMethodTableFieldData(addr, this); } }; -struct MSLAYOUT DacpMethodTableCollectibleData : ZeroInit +struct MSLAYOUT DacpMethodTableCollectibleData { - CLRDATA_ADDRESS LoaderAllocatorObjectHandle; - BOOL bCollectible; + CLRDATA_ADDRESS LoaderAllocatorObjectHandle = 0; + BOOL bCollectible = FALSE; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { @@ -196,11 +182,11 @@ struct MSLAYOUT DacpMethodTableCollectibleData : ZeroInit +struct MSLAYOUT DacpMethodTableTransparencyData { - BOOL bHasCriticalTransparentInfo; - BOOL bIsCritical; - BOOL bIsTreatAsSafe; + BOOL bHasCriticalTransparentInfo = FALSE; + BOOL bIsCritical = FALSE; + BOOL bIsTreatAsSafe = FALSE; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { @@ -208,17 +194,17 @@ struct MSLAYOUT DacpMethodTableTransparencyData : ZeroInit +struct MSLAYOUT DacpDomainLocalModuleData { // These two parameters are used as input params when calling the // no-argument form of Request below. - CLRDATA_ADDRESS appDomainAddr; - ULONG64 ModuleID; - - CLRDATA_ADDRESS pClassData; - CLRDATA_ADDRESS pDynamicClassTable; - CLRDATA_ADDRESS pGCStaticDataStart; - CLRDATA_ADDRESS pNonGCStaticDataStart; + CLRDATA_ADDRESS appDomainAddr = 0; + ULONG64 ModuleID = 0; + + CLRDATA_ADDRESS pClassData = 0; + CLRDATA_ADDRESS pDynamicClassTable = 0; + CLRDATA_ADDRESS pGCStaticDataStart = 0; + CLRDATA_ADDRESS pNonGCStaticDataStart = 0; // Called when you have a pointer to the DomainLocalModule HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) @@ -228,52 +214,52 @@ struct MSLAYOUT DacpDomainLocalModuleData : ZeroInit }; -struct MSLAYOUT DacpThreadLocalModuleData : ZeroInit +struct MSLAYOUT DacpThreadLocalModuleData { // These two parameters are used as input params when calling the // no-argument form of Request below. - CLRDATA_ADDRESS threadAddr; - ULONG64 ModuleIndex; - - CLRDATA_ADDRESS pClassData; - CLRDATA_ADDRESS pDynamicClassTable; - CLRDATA_ADDRESS pGCStaticDataStart; - CLRDATA_ADDRESS pNonGCStaticDataStart; + CLRDATA_ADDRESS threadAddr = 0; + ULONG64 ModuleIndex = 0; + + CLRDATA_ADDRESS pClassData = 0; + CLRDATA_ADDRESS pDynamicClassTable = 0; + CLRDATA_ADDRESS pGCStaticDataStart = 0; + CLRDATA_ADDRESS pNonGCStaticDataStart = 0; }; -struct MSLAYOUT DacpModuleData : ZeroInit +struct MSLAYOUT DacpModuleData { - CLRDATA_ADDRESS Address; - CLRDATA_ADDRESS File; // A PEFile addr - CLRDATA_ADDRESS ilBase; - CLRDATA_ADDRESS metadataStart; - ULONG64 metadataSize; - CLRDATA_ADDRESS Assembly; // Assembly pointer - BOOL bIsReflection; - BOOL bIsPEFile; - ULONG64 dwBaseClassIndex; - ULONG64 dwModuleID; + CLRDATA_ADDRESS Address = 0; + CLRDATA_ADDRESS File = 0; // A PEFile addr + CLRDATA_ADDRESS ilBase = 0; + CLRDATA_ADDRESS metadataStart = 0; + ULONG64 metadataSize = 0; + CLRDATA_ADDRESS Assembly = 0; // Assembly pointer + BOOL bIsReflection = FALSE; + BOOL bIsPEFile = FALSE; + ULONG64 dwBaseClassIndex = 0; + ULONG64 dwModuleID = 0; - DWORD dwTransientFlags; - - CLRDATA_ADDRESS TypeDefToMethodTableMap; - CLRDATA_ADDRESS TypeRefToMethodTableMap; - CLRDATA_ADDRESS MethodDefToDescMap; - CLRDATA_ADDRESS FieldDefToDescMap; - CLRDATA_ADDRESS MemberRefToDescMap; - CLRDATA_ADDRESS FileReferencesMap; - CLRDATA_ADDRESS ManifestModuleReferencesMap; + DWORD dwTransientFlags = 0; - CLRDATA_ADDRESS pLookupTableHeap; - CLRDATA_ADDRESS pThunkHeap; + CLRDATA_ADDRESS TypeDefToMethodTableMap = 0; + CLRDATA_ADDRESS TypeRefToMethodTableMap = 0; + CLRDATA_ADDRESS MethodDefToDescMap = 0; + CLRDATA_ADDRESS FieldDefToDescMap = 0; + CLRDATA_ADDRESS MemberRefToDescMap = 0; + CLRDATA_ADDRESS FileReferencesMap = 0; + CLRDATA_ADDRESS ManifestModuleReferencesMap = 0; - ULONG64 dwModuleIndex; + CLRDATA_ADDRESS pLookupTableHeap = 0; + CLRDATA_ADDRESS pThunkHeap = 0; + + ULONG64 dwModuleIndex = 0; DacpModuleData() { } - + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetModuleData(addr, this); @@ -285,23 +271,23 @@ private: void operator=(const DacpModuleData&); }; -struct MSLAYOUT DacpMethodTableData : ZeroInit +struct MSLAYOUT DacpMethodTableData { - BOOL bIsFree; // everything else is NULL if this is true. - CLRDATA_ADDRESS Module; - CLRDATA_ADDRESS Class; - CLRDATA_ADDRESS ParentMethodTable; - WORD wNumInterfaces; - WORD wNumMethods; - WORD wNumVtableSlots; - WORD wNumVirtuals; - DWORD BaseSize; - DWORD ComponentSize; - mdTypeDef cl; // Metadata token - DWORD dwAttrClass; // cached metadata - BOOL bIsShared; // Always false, preserved for backward compatibility - BOOL bIsDynamic; - BOOL bContainsPointers; + BOOL bIsFree = FALSE; // everything else is NULL if this is true. + CLRDATA_ADDRESS Module = 0; + CLRDATA_ADDRESS Class = 0; + CLRDATA_ADDRESS ParentMethodTable = 0; + WORD wNumInterfaces = 0; + WORD wNumMethods = 0; + WORD wNumVtableSlots = 0; + WORD wNumVirtuals = 0; + DWORD BaseSize = 0; + DWORD ComponentSize = 0; + mdTypeDef cl = 0; // Metadata token + DWORD dwAttrClass = 0; // cached metadata + BOOL bIsShared = FALSE; // Always false, preserved for backward compatibility + BOOL bIsDynamic = FALSE; + BOOL bContainsPointers = FALSE; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { @@ -321,17 +307,17 @@ struct MSLAYOUT DacpMethodTableData : ZeroInit #define CLRSECURITYHOSTED 0x80 #define CLRHOSTED 0x80000000 -struct MSLAYOUT DacpThreadStoreData : ZeroInit +struct MSLAYOUT DacpThreadStoreData { - LONG threadCount; - LONG unstartedThreadCount; - LONG backgroundThreadCount; - LONG pendingThreadCount; - LONG deadThreadCount; - CLRDATA_ADDRESS firstThread; - CLRDATA_ADDRESS finalizerThread; - CLRDATA_ADDRESS gcThread; - DWORD fHostConfig; // Uses hosting flags defined above + LONG threadCount = 0; + LONG unstartedThreadCount = 0; + LONG backgroundThreadCount = 0; + LONG pendingThreadCount = 0; + LONG deadThreadCount = 0; + CLRDATA_ADDRESS firstThread = 0; + CLRDATA_ADDRESS finalizerThread = 0; + CLRDATA_ADDRESS gcThread = 0; + DWORD fHostConfig = 0; // Uses hosting flags defined above HRESULT Request(ISOSDacInterface *sos) { @@ -339,11 +325,11 @@ struct MSLAYOUT DacpThreadStoreData : ZeroInit } }; -struct MSLAYOUT DacpAppDomainStoreData : ZeroInit +struct MSLAYOUT DacpAppDomainStoreData { - CLRDATA_ADDRESS sharedDomain; - CLRDATA_ADDRESS systemDomain; - LONG DomainCount; + CLRDATA_ADDRESS sharedDomain = 0; + CLRDATA_ADDRESS systemDomain = 0; + LONG DomainCount = 0; HRESULT Request(ISOSDacInterface *sos) { @@ -351,33 +337,33 @@ struct MSLAYOUT DacpAppDomainStoreData : ZeroInit } }; -struct MSLAYOUT DacpCOMInterfacePointerData : ZeroInit +struct MSLAYOUT DacpCOMInterfacePointerData { - CLRDATA_ADDRESS methodTable; - CLRDATA_ADDRESS interfacePtr; - CLRDATA_ADDRESS comContext; + CLRDATA_ADDRESS methodTable = 0; + CLRDATA_ADDRESS interfacePtr = 0; + CLRDATA_ADDRESS comContext = 0; }; -struct MSLAYOUT DacpRCWData : ZeroInit +struct MSLAYOUT DacpRCWData { - CLRDATA_ADDRESS identityPointer; - CLRDATA_ADDRESS unknownPointer; - CLRDATA_ADDRESS managedObject; - CLRDATA_ADDRESS jupiterObject; - CLRDATA_ADDRESS vtablePtr; - CLRDATA_ADDRESS creatorThread; - CLRDATA_ADDRESS ctxCookie; - - LONG refCount; - LONG interfaceCount; + CLRDATA_ADDRESS identityPointer = 0; + CLRDATA_ADDRESS unknownPointer = 0; + CLRDATA_ADDRESS managedObject = 0; + CLRDATA_ADDRESS jupiterObject = 0; + CLRDATA_ADDRESS vtablePtr = 0; + CLRDATA_ADDRESS creatorThread = 0; + CLRDATA_ADDRESS ctxCookie = 0; + + LONG refCount = 0; + LONG interfaceCount = 0; + + BOOL isJupiterObject = FALSE; + BOOL supportsIInspectable = FALSE; + BOOL isAggregated = FALSE; + BOOL isContained = FALSE; + BOOL isFreeThreaded = FALSE; + BOOL isDisconnected = FALSE; - BOOL isJupiterObject; - BOOL supportsIInspectable; - BOOL isAggregated; - BOOL isContained; - BOOL isFreeThreaded; - BOOL isDisconnected; - HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS rcw) { return sos->GetRCWData(rcw, this); @@ -397,24 +383,24 @@ struct MSLAYOUT DacpRCWData : ZeroInit } }; -struct MSLAYOUT DacpCCWData : ZeroInit +struct MSLAYOUT DacpCCWData { - CLRDATA_ADDRESS outerIUnknown; - CLRDATA_ADDRESS managedObject; - CLRDATA_ADDRESS handle; - CLRDATA_ADDRESS ccwAddress; + CLRDATA_ADDRESS outerIUnknown = 0; + CLRDATA_ADDRESS managedObject = 0; + CLRDATA_ADDRESS handle = 0; + CLRDATA_ADDRESS ccwAddress = 0; - LONG refCount; - LONG interfaceCount; - BOOL isNeutered; + LONG refCount = 0; + LONG interfaceCount = 0; + BOOL isNeutered = FALSE; + + LONG jupiterRefCount = 0; + BOOL isPegged = FALSE; + BOOL isGlobalPegged = FALSE; + BOOL hasStrongRef = FALSE; + BOOL isExtendsCOMObject = FALSE; + BOOL isAggregated = FALSE; - LONG jupiterRefCount; - BOOL isPegged; - BOOL isGlobalPegged; - BOOL hasStrongRef; - BOOL isExtendsCOMObject; - BOOL isAggregated; - HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS ccw) { return sos->GetCCWData(ccw, this); @@ -438,42 +424,42 @@ enum DacpAppDomainDataStage { }; // Information about a BaseDomain (AppDomain, SharedDomain or SystemDomain). -// For types other than AppDomain, some fields (like dwID, DomainLocalBlock, etc.) will be 0/null. -struct MSLAYOUT DacpAppDomainData : ZeroInit +// For types other than AppDomain, some fields (like dwID, DomainLocalBlock, etc.) will be 0/null. +struct MSLAYOUT DacpAppDomainData { - // The pointer to the BaseDomain (not necessarily an AppDomain). + // The pointer to the BaseDomain (not necessarily an AppDomain). // It's useful to keep this around in the structure - CLRDATA_ADDRESS AppDomainPtr; - CLRDATA_ADDRESS AppSecDesc; - CLRDATA_ADDRESS pLowFrequencyHeap; - CLRDATA_ADDRESS pHighFrequencyHeap; - CLRDATA_ADDRESS pStubHeap; - CLRDATA_ADDRESS DomainLocalBlock; - CLRDATA_ADDRESS pDomainLocalModules; + CLRDATA_ADDRESS AppDomainPtr = 0; + CLRDATA_ADDRESS AppSecDesc = 0; + CLRDATA_ADDRESS pLowFrequencyHeap = 0; + CLRDATA_ADDRESS pHighFrequencyHeap = 0; + CLRDATA_ADDRESS pStubHeap = 0; + CLRDATA_ADDRESS DomainLocalBlock = 0; + CLRDATA_ADDRESS pDomainLocalModules = 0; // The creation sequence number of this app domain (starting from 1) - DWORD dwId; - LONG AssemblyCount; - LONG FailedAssemblyCount; - DacpAppDomainDataStage appDomainStage; - + DWORD dwId = 0; + LONG AssemblyCount = 0; + LONG FailedAssemblyCount = 0; + DacpAppDomainDataStage appDomainStage = DacpAppDomainDataStage::STAGE_CREATING; + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetAppDomainData(addr, this); } }; -struct MSLAYOUT DacpAssemblyData : ZeroInit +struct MSLAYOUT DacpAssemblyData { - CLRDATA_ADDRESS AssemblyPtr; //useful to have - CLRDATA_ADDRESS ClassLoader; - CLRDATA_ADDRESS ParentDomain; - CLRDATA_ADDRESS BaseDomainPtr; - CLRDATA_ADDRESS AssemblySecDesc; - BOOL isDynamic; - UINT ModuleCount; - UINT LoadContext; - BOOL isDomainNeutral; // Always false, preserved for backward compatibility - DWORD dwLocationFlags; + CLRDATA_ADDRESS AssemblyPtr = 0; //useful to have + CLRDATA_ADDRESS ClassLoader = 0; + CLRDATA_ADDRESS ParentDomain = 0; + CLRDATA_ADDRESS BaseDomainPtr = 0; + CLRDATA_ADDRESS AssemblySecDesc = 0; + BOOL isDynamic = FALSE; + UINT ModuleCount = FALSE; + UINT LoadContext = FALSE; + BOOL isDomainNeutral = FALSE; // Always false, preserved for backward compatibility + DWORD dwLocationFlags = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr, CLRDATA_ADDRESS baseDomainPtr) { @@ -487,23 +473,23 @@ struct MSLAYOUT DacpAssemblyData : ZeroInit }; -struct MSLAYOUT DacpThreadData : ZeroInit +struct MSLAYOUT DacpThreadData { - DWORD corThreadId; - DWORD osThreadId; - int state; - ULONG preemptiveGCDisabled; - CLRDATA_ADDRESS allocContextPtr; - CLRDATA_ADDRESS allocContextLimit; - CLRDATA_ADDRESS context; - CLRDATA_ADDRESS domain; - CLRDATA_ADDRESS pFrame; - DWORD lockCount; - CLRDATA_ADDRESS firstNestedException; // Pass this pointer to DacpNestedExceptionInfo - CLRDATA_ADDRESS teb; - CLRDATA_ADDRESS fiberData; - CLRDATA_ADDRESS lastThrownObjectHandle; - CLRDATA_ADDRESS nextThread; + DWORD corThreadId = 0; + DWORD osThreadId = 0; + int state = 0; + ULONG preemptiveGCDisabled = 0; + CLRDATA_ADDRESS allocContextPtr = 0; + CLRDATA_ADDRESS allocContextLimit = 0; + CLRDATA_ADDRESS context = 0; + CLRDATA_ADDRESS domain = 0; + CLRDATA_ADDRESS pFrame = 0; + DWORD lockCount = 0; + CLRDATA_ADDRESS firstNestedException = 0; // Pass this pointer to DacpNestedExceptionInfo + CLRDATA_ADDRESS teb = 0; + CLRDATA_ADDRESS fiberData = 0; + CLRDATA_ADDRESS lastThrownObjectHandle = 0; + CLRDATA_ADDRESS nextThread = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { @@ -512,7 +498,7 @@ struct MSLAYOUT DacpThreadData : ZeroInit }; -struct MSLAYOUT DacpReJitData : ZeroInit +struct MSLAYOUT DacpReJitData { enum Flags { @@ -522,47 +508,76 @@ struct MSLAYOUT DacpReJitData : ZeroInit kReverted, }; - CLRDATA_ADDRESS rejitID; - Flags flags; - CLRDATA_ADDRESS NativeCodeAddr; + CLRDATA_ADDRESS rejitID = 0; + Flags flags = Flags::kUnknown; + CLRDATA_ADDRESS NativeCodeAddr = 0; }; - -struct MSLAYOUT DacpMethodDescData : ZeroInit +struct MSLAYOUT DacpReJitData2 { - BOOL bHasNativeCode; - BOOL bIsDynamic; - WORD wSlotNumber; - CLRDATA_ADDRESS NativeCodeAddr; + enum Flags + { + kUnknown, + kRequested, + kActive, + kReverted, + }; + + ULONG rejitID = 0; + Flags flags = Flags::kUnknown; + CLRDATA_ADDRESS il = 0; + CLRDATA_ADDRESS ilCodeVersionNodePtr = 0; +}; + +struct MSLAYOUT DacpProfilerILData +{ + enum ModificationType + { + Unmodified, + ILModified, + ReJITModified, + }; + + ModificationType type = ModificationType::Unmodified; + CLRDATA_ADDRESS il = 0; + ULONG rejitID = 0; +}; + +struct MSLAYOUT DacpMethodDescData +{ + BOOL bHasNativeCode = FALSE; + BOOL bIsDynamic = FALSE; + WORD wSlotNumber = 0; + CLRDATA_ADDRESS NativeCodeAddr = 0; // Useful for breaking when a method is jitted. - CLRDATA_ADDRESS AddressOfNativeCodeSlot; - - CLRDATA_ADDRESS MethodDescPtr; - CLRDATA_ADDRESS MethodTablePtr; - CLRDATA_ADDRESS ModulePtr; - - mdToken MDToken; - CLRDATA_ADDRESS GCInfo; - CLRDATA_ADDRESS GCStressCodeCopy; + CLRDATA_ADDRESS AddressOfNativeCodeSlot = 0; + + CLRDATA_ADDRESS MethodDescPtr = 0; + CLRDATA_ADDRESS MethodTablePtr = 0; + CLRDATA_ADDRESS ModulePtr = 0; + + mdToken MDToken = 0; + CLRDATA_ADDRESS GCInfo = 0; + CLRDATA_ADDRESS GCStressCodeCopy = 0; // This is only valid if bIsDynamic is true - CLRDATA_ADDRESS managedDynamicMethodObject; + CLRDATA_ADDRESS managedDynamicMethodObject = 0; - CLRDATA_ADDRESS requestedIP; + CLRDATA_ADDRESS requestedIP = 0; // Gives info for the single currently active version of a method - DacpReJitData rejitDataCurrent; + DacpReJitData rejitDataCurrent = {}; // Gives info corresponding to requestedIP (for !ip2md) - DacpReJitData rejitDataRequested; - + DacpReJitData rejitDataRequested = {}; + // Total number of rejit versions that have been jitted - ULONG cJittedRejitVersions; + ULONG cJittedRejitVersions = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetMethodDescData( - addr, + addr, NULL, // IP address this, 0, // cRejitData @@ -573,11 +588,11 @@ struct MSLAYOUT DacpMethodDescData : ZeroInit }; -struct MSLAYOUT DacpMethodDescTransparencyData : ZeroInit +struct MSLAYOUT DacpMethodDescTransparencyData { - BOOL bHasCriticalTransparentInfo; - BOOL bIsCritical; - BOOL bIsTreatAsSafe; + BOOL bHasCriticalTransparentInfo = FALSE; + BOOL bIsCritical = FALSE; + BOOL bIsTreatAsSafe = FALSE; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { @@ -596,7 +611,7 @@ struct MSLAYOUT DacpTieredVersionData OptimizationTier_OptimizedTier1, OptimizationTier_ReadyToRun, }; - + CLRDATA_ADDRESS NativeCodeAddr; OptimizationTier OptimizationTier; CLRDATA_ADDRESS NativeCodeVersionNodePtr; @@ -605,128 +620,128 @@ struct MSLAYOUT DacpTieredVersionData // for JITType enum JITTypes {TYPE_UNKNOWN=0,TYPE_JIT,TYPE_PJIT}; -struct MSLAYOUT DacpCodeHeaderData : ZeroInit -{ - CLRDATA_ADDRESS GCInfo; - JITTypes JITType; - CLRDATA_ADDRESS MethodDescPtr; - CLRDATA_ADDRESS MethodStart; - DWORD MethodSize; - CLRDATA_ADDRESS ColdRegionStart; - DWORD ColdRegionSize; - DWORD HotRegionSize; - +struct MSLAYOUT DacpCodeHeaderData +{ + CLRDATA_ADDRESS GCInfo = 0; + JITTypes JITType = JITTypes::TYPE_UNKNOWN; + CLRDATA_ADDRESS MethodDescPtr = 0; + CLRDATA_ADDRESS MethodStart = 0; + DWORD MethodSize = 0; + CLRDATA_ADDRESS ColdRegionStart = 0; + DWORD ColdRegionSize = 0; + DWORD HotRegionSize = 0; + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS IPAddr) { return sos->GetCodeHeaderData(IPAddr, this); } }; -struct MSLAYOUT DacpWorkRequestData : ZeroInit +struct MSLAYOUT DacpWorkRequestData { - CLRDATA_ADDRESS Function; - CLRDATA_ADDRESS Context; - CLRDATA_ADDRESS NextWorkRequest; - + CLRDATA_ADDRESS Function = 0; + CLRDATA_ADDRESS Context = 0; + CLRDATA_ADDRESS NextWorkRequest = 0; + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetWorkRequestData(addr, this); } }; -struct MSLAYOUT DacpHillClimbingLogEntry : ZeroInit +struct MSLAYOUT DacpHillClimbingLogEntry { - DWORD TickCount; - int Transition; - int NewControlSetting; - int LastHistoryCount; - double LastHistoryMean; - + DWORD TickCount = 0; + int Transition = 0; + int NewControlSetting = 0; + int LastHistoryCount = 0; + double LastHistoryMean = 0; + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS entry) { - return sos->GetHillClimbingLogEntry(entry, this); + return sos->GetHillClimbingLogEntry(entry, this); } }; // Used for CLR versions >= 4.0 -struct MSLAYOUT DacpThreadpoolData : ZeroInit +struct MSLAYOUT DacpThreadpoolData { - LONG cpuUtilization; - int NumIdleWorkerThreads; - int NumWorkingWorkerThreads; - int NumRetiredWorkerThreads; - LONG MinLimitTotalWorkerThreads; - LONG MaxLimitTotalWorkerThreads; + LONG cpuUtilization = 0; + int NumIdleWorkerThreads = 0; + int NumWorkingWorkerThreads = 0; + int NumRetiredWorkerThreads = 0; + LONG MinLimitTotalWorkerThreads = 0; + LONG MaxLimitTotalWorkerThreads = 0; - CLRDATA_ADDRESS FirstUnmanagedWorkRequest; + CLRDATA_ADDRESS FirstUnmanagedWorkRequest = 0; - CLRDATA_ADDRESS HillClimbingLog; - int HillClimbingLogFirstIndex; - int HillClimbingLogSize; + CLRDATA_ADDRESS HillClimbingLog = 0; + int HillClimbingLogFirstIndex = 0; + int HillClimbingLogSize = 0; - DWORD NumTimers; + DWORD NumTimers = 0; // TODO: Add support to enumerate timers too. - LONG NumCPThreads; - LONG NumFreeCPThreads; - LONG MaxFreeCPThreads; - LONG NumRetiredCPThreads; - LONG MaxLimitTotalCPThreads; - LONG CurrentLimitTotalCPThreads; - LONG MinLimitTotalCPThreads; + LONG NumCPThreads = 0; + LONG NumFreeCPThreads = 0; + LONG MaxFreeCPThreads = 0; + LONG NumRetiredCPThreads = 0; + LONG MaxLimitTotalCPThreads = 0; + LONG CurrentLimitTotalCPThreads = 0; + LONG MinLimitTotalCPThreads = 0; + + CLRDATA_ADDRESS AsyncTimerCallbackCompletionFPtr = 0; - CLRDATA_ADDRESS AsyncTimerCallbackCompletionFPtr; - HRESULT Request(ISOSDacInterface *sos) { return sos->GetThreadpoolData(this); } }; -struct MSLAYOUT DacpGenerationData : ZeroInit -{ - CLRDATA_ADDRESS start_segment; - CLRDATA_ADDRESS allocation_start; +struct MSLAYOUT DacpGenerationData +{ + CLRDATA_ADDRESS start_segment = 0; + CLRDATA_ADDRESS allocation_start = 0; // These are examined only for generation 0, otherwise NULL - CLRDATA_ADDRESS allocContextPtr; - CLRDATA_ADDRESS allocContextLimit; + CLRDATA_ADDRESS allocContextPtr = 0; + CLRDATA_ADDRESS allocContextLimit = 0; }; #define DAC_NUMBERGENERATIONS 4 -struct MSLAYOUT DacpAllocData : ZeroInit +struct MSLAYOUT DacpAllocData { - CLRDATA_ADDRESS allocBytes; - CLRDATA_ADDRESS allocBytesLoh; + CLRDATA_ADDRESS allocBytes = 0; + CLRDATA_ADDRESS allocBytesLoh = 0; }; -struct MSLAYOUT DacpGenerationAllocData : ZeroInit +struct MSLAYOUT DacpGenerationAllocData { - DacpAllocData allocData[DAC_NUMBERGENERATIONS]; + DacpAllocData allocData[DAC_NUMBERGENERATIONS] = {}; }; -struct MSLAYOUT DacpGcHeapDetails : ZeroInit +struct MSLAYOUT DacpGcHeapDetails { - CLRDATA_ADDRESS heapAddr; // Only filled in in server mode, otherwise NULL - CLRDATA_ADDRESS alloc_allocated; + CLRDATA_ADDRESS heapAddr = 0; // Only filled in in server mode, otherwise NULL + CLRDATA_ADDRESS alloc_allocated = 0; - CLRDATA_ADDRESS mark_array; - CLRDATA_ADDRESS current_c_gc_state; - CLRDATA_ADDRESS next_sweep_obj; - CLRDATA_ADDRESS saved_sweep_ephemeral_seg; - CLRDATA_ADDRESS saved_sweep_ephemeral_start; - CLRDATA_ADDRESS background_saved_lowest_address; - CLRDATA_ADDRESS background_saved_highest_address; + CLRDATA_ADDRESS mark_array = 0; + CLRDATA_ADDRESS current_c_gc_state = 0; + CLRDATA_ADDRESS next_sweep_obj = 0; + CLRDATA_ADDRESS saved_sweep_ephemeral_seg = 0; + CLRDATA_ADDRESS saved_sweep_ephemeral_start = 0; + CLRDATA_ADDRESS background_saved_lowest_address = 0; + CLRDATA_ADDRESS background_saved_highest_address = 0; - DacpGenerationData generation_table [DAC_NUMBERGENERATIONS]; - CLRDATA_ADDRESS ephemeral_heap_segment; - CLRDATA_ADDRESS finalization_fill_pointers [DAC_NUMBERGENERATIONS + 3]; - CLRDATA_ADDRESS lowest_address; - CLRDATA_ADDRESS highest_address; - CLRDATA_ADDRESS card_table; + DacpGenerationData generation_table [DAC_NUMBERGENERATIONS] = {}; + CLRDATA_ADDRESS ephemeral_heap_segment = 0; + CLRDATA_ADDRESS finalization_fill_pointers [DAC_NUMBERGENERATIONS + 3] = {}; + CLRDATA_ADDRESS lowest_address = 0; + CLRDATA_ADDRESS highest_address = 0; + CLRDATA_ADDRESS card_table = 0; // Use this for workstation mode (DacpGcHeapDat.bServerMode==FALSE). HRESULT Request(ISOSDacInterface *sos) @@ -743,13 +758,12 @@ struct MSLAYOUT DacpGcHeapDetails : ZeroInit }; struct MSLAYOUT DacpGcHeapData - : ZeroInit { - BOOL bServerMode; - BOOL bGcStructuresValid; - UINT HeapCount; - UINT g_max_generation; - + BOOL bServerMode = FALSE; + BOOL bGcStructuresValid = FALSE; + UINT HeapCount = 0; + UINT g_max_generation = 0; + HRESULT Request(ISOSDacInterface *sos) { return sos->GetGCHeapData(this); @@ -757,22 +771,21 @@ struct MSLAYOUT DacpGcHeapData }; struct MSLAYOUT DacpHeapSegmentData - : ZeroInit { - CLRDATA_ADDRESS segmentAddr; - CLRDATA_ADDRESS allocated; - CLRDATA_ADDRESS committed; - CLRDATA_ADDRESS reserved; - CLRDATA_ADDRESS used; - CLRDATA_ADDRESS mem; + CLRDATA_ADDRESS segmentAddr = 0; + CLRDATA_ADDRESS allocated = 0; + CLRDATA_ADDRESS committed = 0; + CLRDATA_ADDRESS reserved = 0; + CLRDATA_ADDRESS used = 0; + CLRDATA_ADDRESS mem = 0; // pass this to request if non-null to get the next segments. - CLRDATA_ADDRESS next; - CLRDATA_ADDRESS gc_heap; // only filled in in server mode, otherwise NULL + CLRDATA_ADDRESS next = 0; + CLRDATA_ADDRESS gc_heap = 0; // only filled in in server mode, otherwise NULL // computed field: if this is the ephemeral segment highMark includes the ephemeral generation - CLRDATA_ADDRESS highAllocMark; + CLRDATA_ADDRESS highAllocMark = 0; - size_t flags; - CLRDATA_ADDRESS background_allocated; + size_t flags = 0; + CLRDATA_ADDRESS background_allocated = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr, const DacpGcHeapDetails& heap) { @@ -786,20 +799,20 @@ struct MSLAYOUT DacpHeapSegmentData highAllocMark = heap.alloc_allocated; else highAllocMark = allocated; - } + } return hr; } }; -struct MSLAYOUT DacpOomData : ZeroInit +struct MSLAYOUT DacpOomData { - int reason; - ULONG64 alloc_size; - ULONG64 available_pagefile_mb; - ULONG64 gc_index; - int fgm; - ULONG64 size; - BOOL loh_p; + int reason = 0; + ULONG64 alloc_size = 0; + ULONG64 available_pagefile_mb = 0; + ULONG64 gc_index = 0; + int fgm = 0; + ULONG64 size = 0; + BOOL loh_p = FALSE; HRESULT Request(ISOSDacInterface *sos) { @@ -819,13 +832,13 @@ struct MSLAYOUT DacpOomData : ZeroInit #define DAC_MAX_EXPAND_MECHANISMS_COUNT 6 #define DAC_MAX_GC_MECHANISM_BITS_COUNT 2 #define DAC_MAX_GLOBAL_GC_MECHANISMS_COUNT 6 -struct MSLAYOUT DacpGCInterestingInfoData : ZeroInit +struct MSLAYOUT DacpGCInterestingInfoData { - size_t interestingDataPoints[DAC_NUM_GC_DATA_POINTS]; - size_t compactReasons[DAC_MAX_COMPACT_REASONS_COUNT]; - size_t expandMechanisms[DAC_MAX_EXPAND_MECHANISMS_COUNT]; - size_t bitMechanisms[DAC_MAX_GC_MECHANISM_BITS_COUNT]; - size_t globalMechanisms[DAC_MAX_GLOBAL_GC_MECHANISMS_COUNT]; + size_t interestingDataPoints[DAC_NUM_GC_DATA_POINTS] = {}; + size_t compactReasons[DAC_MAX_COMPACT_REASONS_COUNT] = {}; + size_t expandMechanisms[DAC_MAX_EXPAND_MECHANISMS_COUNT] = {}; + size_t bitMechanisms[DAC_MAX_GC_MECHANISM_BITS_COUNT] = {}; + size_t globalMechanisms[DAC_MAX_GLOBAL_GC_MECHANISMS_COUNT] = {}; HRESULT RequestGlobal(ISOSDacInterface *sos) { @@ -867,18 +880,17 @@ struct MSLAYOUT DacpGCInterestingInfoData : ZeroInit }; struct MSLAYOUT DacpGcHeapAnalyzeData - : ZeroInit { - CLRDATA_ADDRESS heapAddr; // Only filled in in server mode, otherwise NULL + CLRDATA_ADDRESS heapAddr = 0; // Only filled in in server mode, otherwise NULL - CLRDATA_ADDRESS internal_root_array; - ULONG64 internal_root_array_index; - BOOL heap_analyze_success; + CLRDATA_ADDRESS internal_root_array = 0; + ULONG64 internal_root_array_index = 0; + BOOL heap_analyze_success = FALSE; // Use this for workstation mode (DacpGcHeapDat.bServerMode==FALSE). HRESULT Request(ISOSDacInterface *sos) { - return sos->GetHeapAnalyzeStaticData(this); + return sos->GetHeapAnalyzeStaticData(this); } // Use this for Server mode, as there are multiple heaps, @@ -894,25 +906,25 @@ struct MSLAYOUT DacpGcHeapAnalyzeData #define SYNCBLOCKDATA_COMFLAGS_RCW 2 #define SYNCBLOCKDATA_COMFLAGS_CF 4 -struct MSLAYOUT DacpSyncBlockData : ZeroInit -{ - CLRDATA_ADDRESS Object; - BOOL bFree; // if set, no other fields are useful - +struct MSLAYOUT DacpSyncBlockData +{ + CLRDATA_ADDRESS Object = 0; + BOOL bFree = FALSE; // if set, no other fields are useful + // fields below provide data from this, so it's just for display - CLRDATA_ADDRESS SyncBlockPointer; - DWORD COMFlags; - UINT MonitorHeld; - UINT Recursion; - CLRDATA_ADDRESS HoldingThread; - UINT AdditionalThreadCount; - CLRDATA_ADDRESS appDomainPtr; - + CLRDATA_ADDRESS SyncBlockPointer = 0; + DWORD COMFlags = 0; + UINT MonitorHeld = 0; + UINT Recursion = 0; + CLRDATA_ADDRESS HoldingThread = 0; + UINT AdditionalThreadCount = 0; + CLRDATA_ADDRESS appDomainPtr = 0; + // SyncBlockCount will always be filled in with the number of SyncBlocks. // SyncBlocks may be requested from [1,SyncBlockCount] - UINT SyncBlockCount; + UINT SyncBlockCount = 0; - // SyncBlockNumber must be from [1,SyncBlockCount] + // SyncBlockNumber must be from [1,SyncBlockCount] // If there are no SyncBlocks, a call to Request with SyncBlockCount = 1 // will return E_FAIL. HRESULT Request(ISOSDacInterface *sos, UINT SyncBlockNumber) @@ -921,15 +933,15 @@ struct MSLAYOUT DacpSyncBlockData : ZeroInit } }; -struct MSLAYOUT DacpSyncBlockCleanupData : ZeroInit +struct MSLAYOUT DacpSyncBlockCleanupData { - CLRDATA_ADDRESS SyncBlockPointer; - - CLRDATA_ADDRESS nextSyncBlock; - CLRDATA_ADDRESS blockRCW; - CLRDATA_ADDRESS blockClassFactory; - CLRDATA_ADDRESS blockCCW; - + CLRDATA_ADDRESS SyncBlockPointer = 0; + + CLRDATA_ADDRESS nextSyncBlock = 0; + CLRDATA_ADDRESS blockRCW = 0; + CLRDATA_ADDRESS blockClassFactory = 0; + CLRDATA_ADDRESS blockCCW = 0; + // Pass NULL on the first request to start a traversal. HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS psyncBlock) { @@ -940,41 +952,41 @@ struct MSLAYOUT DacpSyncBlockCleanupData : ZeroInit /////////////////////////////////////////////////////////////////////////// enum EHClauseType {EHFault, EHFinally, EHFilter, EHTyped, EHUnknown}; - -struct MSLAYOUT DACEHInfo : ZeroInit + +struct MSLAYOUT DACEHInfo { - EHClauseType clauseType; - CLRDATA_ADDRESS tryStartOffset; - CLRDATA_ADDRESS tryEndOffset; - CLRDATA_ADDRESS handlerStartOffset; - CLRDATA_ADDRESS handlerEndOffset; - BOOL isDuplicateClause; - CLRDATA_ADDRESS filterOffset; // valid when clauseType is EHFilter - BOOL isCatchAllHandler; // valid when clauseType is EHTyped - CLRDATA_ADDRESS moduleAddr; // when == 0 mtCatch contains a MethodTable, when != 0 tokCatch contains a type token - CLRDATA_ADDRESS mtCatch; // the method table of the TYPED clause type - mdToken tokCatch; // the type token of the TYPED clause type + EHClauseType clauseType = EHClauseType::EHFault; + CLRDATA_ADDRESS tryStartOffset = 0; + CLRDATA_ADDRESS tryEndOffset = 0; + CLRDATA_ADDRESS handlerStartOffset = 0; + CLRDATA_ADDRESS handlerEndOffset = 0; + BOOL isDuplicateClause = FALSE; + CLRDATA_ADDRESS filterOffset = 0; // valid when clauseType is EHFilter + BOOL isCatchAllHandler = FALSE; // valid when clauseType is EHTyped + CLRDATA_ADDRESS moduleAddr = 0; // when == 0 mtCatch contains a MethodTable, when != 0 tokCatch contains a type token + CLRDATA_ADDRESS mtCatch = 0; // the method table of the TYPED clause type + mdToken tokCatch = 0; // the type token of the TYPED clause type }; -struct MSLAYOUT DacpGetModuleAddress : ZeroInit +struct MSLAYOUT DacpGetModuleAddress { - CLRDATA_ADDRESS ModulePtr; + CLRDATA_ADDRESS ModulePtr = 0; HRESULT Request(IXCLRDataModule* pDataModule) { return pDataModule->Request(DACDATAMODULEPRIV_REQUEST_GET_MODULEPTR, 0, NULL, sizeof(*this), (PBYTE) this); } }; -struct MSLAYOUT DacpGetModuleData : ZeroInit +struct MSLAYOUT DacpGetModuleData { - BOOL IsDynamic; - BOOL IsInMemory; - BOOL IsFileLayout; - CLRDATA_ADDRESS PEFile; - CLRDATA_ADDRESS LoadedPEAddress; - ULONG64 LoadedPESize; - CLRDATA_ADDRESS InMemoryPdbAddress; - ULONG64 InMemoryPdbSize; + BOOL IsDynamic = FALSE; + BOOL IsInMemory = FALSE; + BOOL IsFileLayout = FALSE; + CLRDATA_ADDRESS PEFile = 0; + CLRDATA_ADDRESS LoadedPEAddress = 0; + ULONG64 LoadedPESize = 0; + CLRDATA_ADDRESS InMemoryPdbAddress = 0; + ULONG64 InMemoryPdbSize = 0; HRESULT Request(IXCLRDataModule* pDataModule) { @@ -982,9 +994,9 @@ struct MSLAYOUT DacpGetModuleData : ZeroInit } }; -struct MSLAYOUT DacpFrameData : ZeroInit +struct MSLAYOUT DacpFrameData { - CLRDATA_ADDRESS frameAddr; + CLRDATA_ADDRESS frameAddr = 0; // Could also be implemented for IXCLRDataFrame if desired. HRESULT Request(IXCLRDataStackWalk* dac) @@ -995,26 +1007,26 @@ struct MSLAYOUT DacpFrameData : ZeroInit } }; -struct MSLAYOUT DacpJitManagerInfo : ZeroInit +struct MSLAYOUT DacpJitManagerInfo { - CLRDATA_ADDRESS managerAddr; - DWORD codeType; // for union below - CLRDATA_ADDRESS ptrHeapList; // A HeapList * if IsMiIL(codeType) + CLRDATA_ADDRESS managerAddr = 0; + DWORD codeType = 0; // for union below + CLRDATA_ADDRESS ptrHeapList = 0; // A HeapList * if IsMiIL(codeType) }; enum CodeHeapType {CODEHEAP_LOADER=0,CODEHEAP_HOST,CODEHEAP_UNKNOWN}; -struct MSLAYOUT DacpJitCodeHeapInfo : ZeroInit +struct MSLAYOUT DacpJitCodeHeapInfo { - DWORD codeHeapType; // for union below + DWORD codeHeapType = 0; // for union below union { - CLRDATA_ADDRESS LoaderHeap; // if CODEHEAP_LOADER + CLRDATA_ADDRESS LoaderHeap = 0; // if CODEHEAP_LOADER struct MSLAYOUT { - CLRDATA_ADDRESS baseAddr; // if CODEHEAP_HOST - CLRDATA_ADDRESS currentAddr; + CLRDATA_ADDRESS baseAddr = 0; // if CODEHEAP_HOST + CLRDATA_ADDRESS currentAddr = 0; } HostData; }; }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/dacvars.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/dacvars.h index 78b1c10..dea6fa6 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/dacvars.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/dacvars.h @@ -4,21 +4,21 @@ // This file contains the globals and statics that are visible to DAC. // It is used for the following: // 1. in daccess.h to build the table of DAC globals -// 2. in enummem.cpp to dump out the related memory of static and globals +// 2. in enummem.cpp to dump out the related memory of static and globals // in a mini dump or heap dump // 3. in DacUpdateDll and toolbox\DacTablenGen\main.cs // -// To use this functionality for other tools or purposes, define the -// DEFINE_DACVAR macro & include dacvars.h like so (see enummem.cpp and/or +// To use this functionality for other tools or purposes, define the +// DEFINE_DACVAR macro & include dacvars.h like so (see enummem.cpp and/or // daccess.h for examples): // // #define DEFINE_DACVAR(type, size, id, var) type id; //this defn. discards // //the size // #include "dacvars.h" // -// @dbgtodo: -// Ideally we may be able to build a tool that generates this automatically. -// At the least, we should automatically verify that the contents of this file +// @dbgtodo: +// Ideally we may be able to build a tool that generates this automatically. +// At the least, we should automatically verify that the contents of this file // are consistent with the uses of all the macros like SVAL_DECL and GARY_DECL. // //================================================= @@ -26,45 +26,45 @@ //================================================= // You need to add a global or static declared with DAC macros, such as SPTR_* // GPTR_*, SVAL_*, GVAL_*, or GARY_*, only if the global or static is actually used -// in a DACized code path. If you have declared a static or global that way just -// because you were pattern-matching or because you anticipate that the variable +// in a DACized code path. If you have declared a static or global that way just +// because you were pattern-matching or because you anticipate that the variable // may eventually be used in a DACized code path, you don't need to add it here, // although in that case, you should not really use the DAC macro when you declare -// the global or static. +// the global or static. // * * * // The FIRST ARGUMENT should always be specified as ULONG. This is the type of -// the offsets for the corresponding id in the _DacGlobals table. -// @dbgtodo: +// the offsets for the corresponding id in the _DacGlobals table. +// @dbgtodo: // We should get rid of the ULONG argument since it's always the same. We would // also need to modify DacTablenGen\main.cs. // * * * -// The SECOND ARGUMENT, "true_type," is used to calculate the true size of the -// static/global variable. It is currently used only in enummem.cpp to write out +// The SECOND ARGUMENT, "true_type," is used to calculate the true size of the +// static/global variable. It is currently used only in enummem.cpp to write out // theproper size of memory for dumps. // * * * // The THIRD ARGUMENT should be a qualified name. If the variable is a static data -// member, the name should be __. If the variable is a +// member, the name should be __. If the variable is a // global, the name should be __. // * * * -// The FOURTH ARGUMENT should be the actual name of the static/global variable. If +// The FOURTH ARGUMENT should be the actual name of the static/global variable. If // static data the should be [::]::. If global, // it should look like . // * * * -// If you need to add an entry to this file, your type may not be visible when +// If you need to add an entry to this file, your type may not be visible when // this file is compiled. In that case, you need to do one of two things: -// - If the type is a pointer type, you can simply use UNKNOWN_POINTER_TYPE as the -// "true type." It may be useful to specify the non-visible type in a comment. -// - If the type is a composite/user-defined type, you must #include the header +// - If the type is a pointer type, you can simply use UNKNOWN_POINTER_TYPE as the +// "true type." It may be useful to specify the non-visible type in a comment. +// - If the type is a composite/user-defined type, you must #include the header // file that defines the type in enummem.cpp. Do NOT #include it in daccess.h -// Array types may be dumped via an explicit call to enumMem, so they should -// be declared with DEFINE_DACVAR_NO_DUMP. The size in this case is immaterial, since -// nothing will be dumped. +// Array types may be dumped via an explicit call to enumMem, so they should +// be declared with DEFINE_DACVAR_NO_DUMP. The size in this case is immaterial, since +// nothing will be dumped. #ifndef DEFINE_DACVAR #define DEFINE_DACVAR(type, true_type, id, var) #endif -// Use this macro to define a static var that is known to DAC, but not captured in a dump. +// Use this macro to define a static var that is known to DAC, but not captured in a dump. #ifndef DEFINE_DACVAR_NO_DUMP #define DEFINE_DACVAR_NO_DUMP(type, true_type, id, var) #endif @@ -95,6 +95,7 @@ DEFINE_DACVAR(ULONG, PTR_JumpStubStubManager, JumpStubStubManager__g_pManager, J DEFINE_DACVAR(ULONG, PTR_RangeSectionStubManager, RangeSectionStubManager__g_pManager, RangeSectionStubManager::g_pManager) DEFINE_DACVAR(ULONG, PTR_DelegateInvokeStubManager, DelegateInvokeStubManager__g_pManager, DelegateInvokeStubManager::g_pManager) DEFINE_DACVAR(ULONG, PTR_VirtualCallStubManagerManager, VirtualCallStubManagerManager__g_pManager, VirtualCallStubManagerManager::g_pManager) +DEFINE_DACVAR(ULONG, PTR_CallCountingStubManager, CallCountingStubManager__g_pManager, CallCountingStubManager::g_pManager) DEFINE_DACVAR(ULONG, PTR_ThreadStore, ThreadStore__s_pThreadStore, ThreadStore::s_pThreadStore) @@ -103,7 +104,7 @@ DEFINE_DACVAR(ULONG, ThreadpoolMgr::ThreadCounter, ThreadpoolMgr__WorkerCounter, DEFINE_DACVAR(ULONG, int, ThreadpoolMgr__MinLimitTotalWorkerThreads, ThreadpoolMgr::MinLimitTotalWorkerThreads) DEFINE_DACVAR(ULONG, DWORD, ThreadpoolMgr__MaxLimitTotalWorkerThreads, ThreadpoolMgr::MaxLimitTotalWorkerThreads) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE /*PTR_WorkRequest*/, ThreadpoolMgr__WorkRequestHead, ThreadpoolMgr::WorkRequestHead) // PTR_WorkRequest is not defined. So use a pointer type -DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE /*PTR_WorkRequest*/, ThreadpoolMgr__WorkRequestTail, ThreadpoolMgr::WorkRequestTail) // +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE /*PTR_WorkRequest*/, ThreadpoolMgr__WorkRequestTail, ThreadpoolMgr::WorkRequestTail) // DEFINE_DACVAR(ULONG, ThreadpoolMgr::ThreadCounter, ThreadpoolMgr__CPThreadCounter, ThreadpoolMgr::CPThreadCounter) DEFINE_DACVAR(ULONG, LONG, ThreadpoolMgr__MaxFreeCPThreads, ThreadpoolMgr::MaxFreeCPThreads) DEFINE_DACVAR(ULONG, LONG, ThreadpoolMgr__MaxLimitTotalCPThreads, ThreadpoolMgr::MaxLimitTotalCPThreads) @@ -160,7 +161,7 @@ DEFINE_DACVAR(ULONG, PTR_BYTE, dac__g_highest_address, ::g_highest_address) DEFINE_DACVAR(ULONG, IGCHeap, dac__g_pGCHeap, ::g_pGCHeap) -DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pThinLockThreadIdDispenser, ::g_pThinLockThreadIdDispenser) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pThinLockThreadIdDispenser, ::g_pThinLockThreadIdDispenser) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pModuleIndexDispenser, ::g_pModuleIndexDispenser) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pObjectClass, ::g_pObjectClass) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pRuntimeTypeClass, ::g_pRuntimeTypeClass) @@ -187,7 +188,6 @@ DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pEnumClass, ::g_pEnumClass) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pThreadClass, ::g_pThreadClass) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pPredefinedArrayTypes, ::g_pPredefinedArrayTypes) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_TypedReferenceMT, ::g_TypedReferenceMT) -DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pByteArrayMT, ::g_pByteArrayMT) #ifdef FEATURE_COMINTEROP DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pBaseCOMObject, ::g_pBaseCOMObject) @@ -198,13 +198,10 @@ DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pBaseRuntimeClass, ::g_pBaseRu DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pICastableInterface, ::g_pICastableInterface) #endif // FEATURE_ICASTABLE -DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pExecuteBackoutCodeHelperMethod, ::g_pExecuteBackoutCodeHelperMethod) - DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pObjectFinalizerMD, ::g_pObjectFinalizerMD) DEFINE_DACVAR(ULONG, bool, dac__g_fProcessDetach, ::g_fProcessDetach) DEFINE_DACVAR(ULONG, DWORD, dac__g_fEEShutDown, ::g_fEEShutDown) -DEFINE_DACVAR(ULONG, DWORD, dac__g_fHostConfig, ::g_fHostConfig) DEFINE_DACVAR(ULONG, ULONG, dac__g_CORDebuggerControlFlags, ::g_CORDebuggerControlFlags) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pDebugger, ::g_pDebugger) @@ -228,10 +225,10 @@ DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pRCWCleanupList, ::g_pRCWClean DEFINE_DACVAR(ULONG, BOOL, RCWWalker__s_bIsGlobalPeggingOn, RCWWalker::s_bIsGlobalPeggingOn) #endif // FEATURE_COMINTEROP -#ifndef FEATURE_PAL +#ifndef TARGET_UNIX DEFINE_DACVAR(ULONG, SIZE_T, dac__g_runtimeLoadedBaseAddress, ::g_runtimeLoadedBaseAddress) DEFINE_DACVAR(ULONG, SIZE_T, dac__g_runtimeVirtualSize, ::g_runtimeVirtualSize) -#endif // !FEATURE_PAL +#endif // !TARGET_UNIX DEFINE_DACVAR(ULONG, SyncBlockCache *, SyncBlockCache__s_pSyncBlockCache, SyncBlockCache::s_pSyncBlockCache) @@ -241,9 +238,9 @@ DEFINE_DACVAR(ULONG, SIZE_T, dac__s_gsCookie, ::s_gsCookie) DEFINE_DACVAR_NO_DUMP(ULONG, SIZE_T, dac__g_FCDynamicallyAssignedImplementations, ::g_FCDynamicallyAssignedImplementations) -#ifndef FEATURE_PAL +#ifndef TARGET_UNIX DEFINE_DACVAR(ULONG, HANDLE, dac__g_hContinueStartupEvent, ::g_hContinueStartupEvent) -#endif // !FEATURE_PAL +#endif // !TARGET_UNIX DEFINE_DACVAR(ULONG, DWORD, CorHost2__m_dwStartupFlags, CorHost2::m_dwStartupFlags) DEFINE_DACVAR(ULONG, HRESULT, dac__g_hrFatalError, ::g_hrFatalError) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/dbgenginemetrics.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/dbgenginemetrics.h index 1748885..954d3b5 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/dbgenginemetrics.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/dbgenginemetrics.h @@ -5,7 +5,7 @@ // DbgEngineMetrics.h // // This file contains the defintion of CLR_ENGINE_METRICS. This struct is used for Silverlight debugging. -// +// // ====================================================================================== @@ -16,7 +16,7 @@ //--------------------------------------------------------------------------------------- // // This struct contains information necessary for Silverlight debugging. coreclr.dll has a static struct -// of this type. It is read by dbgshim.dll to help synchronize the debugger and coreclr.dll in launch +// of this type. It is read by dbgshim.dll to help synchronize the debugger and coreclr.dll in launch // and early attach scenarios. // diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/debugmacros.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/debugmacros.h index 540be99..4fb4fb8 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/debugmacros.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/debugmacros.h @@ -40,7 +40,7 @@ extern int _DbgBreakCount; #define PRE_ASSERTE /* if you need to change modes before doing asserts override */ #define POST_ASSERTE /* put it back */ -#if !defined(_ASSERTE_MSG) +#if !defined(_ASSERTE_MSG) #define _ASSERTE_MSG(expr, msg) \ do { \ if (!(expr)) { \ @@ -100,13 +100,13 @@ void DECLSPEC_NORETURN __FreeBuildAssertFail(const char *szFile, int iLine, cons return FALSE; \ } \ } - - + + #ifdef _DEBUG_IMPL // A macro to execute a statement only in _DEBUG_IMPL. #define DEBUG_IMPL_STMT(stmt) stmt - + #define _ASSERTE_IMPL(expr) _ASSERTE((expr)) #if defined(_M_IX86) @@ -201,7 +201,7 @@ do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); goto LA #define _ASSERT _ASSERTE -#if defined(_DEBUG) && !defined(FEATURE_PAL) +#if defined(_DEBUG) && defined(HOST_WINDOWS) // This function returns the EXE time stamp (effectively a random number) // Under retail it always returns 0. This is meant to be used in the @@ -214,7 +214,7 @@ unsigned DbgGetEXETimeStamp(); // will not be coorelated with each other (9973 is prime). Returns false on a retail build #define DbgRandomOnHashAndExe(hash, fractionOn) \ (((DbgGetEXETimeStamp() * __LINE__ * ((hash) ? (hash) : 1)) % 9973) < \ - unsigned(fractionOn * 9973)) + unsigned((fractionOn) * 9973)) #define DbgRandomOnExe(fractionOn) DbgRandomOnHashAndExe(0, fractionOn) #define DbgRandomOnStringAndExe(string, fractionOn) DbgRandomOnHashAndExe(HashStringA(string), fractionOn) @@ -227,43 +227,4 @@ unsigned DbgGetEXETimeStamp(); #endif // _DEBUG && !FEATUREPAL -#ifdef _DEBUG -namespace clr -{ - namespace dbg - { - // In debug builds, this can be used to write known bad values into - // memory. One example is in ComUtil::IUnknownCommon::~IUnknownCommon, - // which overwrites its instance memory with a known bad value after - // completing its destructor. - template < typename T > - void PoisonMem(T &val) - { - ZeroMemory((void*)&val, sizeof(T)); - } - - template < typename T > - void PoisonMem(T* ptr, size_t len) - { - ZeroMemory((void*)ptr, sizeof(T)* len); - } - } -} -#else - -// Empty versions of the functions in retail that will be inlined -// and completely elided. -namespace clr -{ - namespace dbg - { - template < typename T > - inline void PoisonMem(T &) {} - - template < typename T > - void PoisonMem(T* ptr, size_t len){} - } -} #endif - -#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/debugreturn.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/debugreturn.h index 73edd01..b353169 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/debugreturn.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/debugreturn.h @@ -11,7 +11,7 @@ // #ifdef _PREFAST_ -// Use prefast to detect gotos out of no-return blocks. The gotos out of no-return blocks +// Use prefast to detect gotos out of no-return blocks. The gotos out of no-return blocks // should be reported as memory leaks by prefast. The (nothrow) is because PREfix sees the // throw from the new statement, and doesn't like these macros used in a destructor (and // the NULL returned by failure works just fine in delete[]) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/delayloadhelpers.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/delayloadhelpers.h index 2a62a8d..808172a 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/delayloadhelpers.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/delayloadhelpers.h @@ -1,12 +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. -// +// -// +// // Contains convenience functionality for lazily loading modules // and getting entrypoints within them. -// +// #ifndef DelayLoadHelpers_h #define DelayLoadHelpers_h diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/dlwrap.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/dlwrap.h index 853bc58..9cf926c 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/dlwrap.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/dlwrap.h @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. -// +// #ifndef _DLWRAP_H #define _DLWRAP_H @@ -13,7 +13,7 @@ //nothrow implementations #if defined(VER_H) && !defined (GetFileVersionInfoSizeW_NoThrow) -DWORD +DWORD GetFileVersionInfoSizeW_NoThrow( LPCWSTR lptstrFilename, /* Filename of version stamped file */ LPDWORD lpdwHandle @@ -41,8 +41,8 @@ VerQueryValueW_NoThrow( #endif #if defined(_WININET_) && !defined (CreateUrlCacheEntryW_NoThrow) -__success(return) -BOOL +__success(return) +BOOL CreateUrlCacheEntryW_NoThrow( IN LPCWSTR lpszUrlName, IN DWORD dwExpectedFileSize, @@ -53,7 +53,7 @@ CreateUrlCacheEntryW_NoThrow( #endif #if defined(_WININET_) && !defined (CommitUrlCacheEntryW_NoThrow) -BOOL +BOOL CommitUrlCacheEntryW_NoThrow( IN LPCWSTR lpszUrlName, IN LPCWSTR lpszLocalFileName, @@ -68,7 +68,7 @@ CommitUrlCacheEntryW_NoThrow( #endif #if defined(_WININET_) && !defined (InternetTimeToSystemTimeA_NoThrow) -BOOL +BOOL InternetTimeToSystemTimeA_NoThrow( IN LPCSTR lpszTime, // NULL terminated string OUT SYSTEMTIME *pst, // output in GMT time @@ -77,16 +77,16 @@ InternetTimeToSystemTimeA_NoThrow( #endif #if defined(__urlmon_h__) && !defined(CoInternetCreateSecurityManager_NoThrow) -HRESULT +HRESULT CoInternetCreateSecurityManager_NoThrow( IServiceProvider *pSP, - IInternetSecurityManager **ppSM, + IInternetSecurityManager **ppSM, DWORD dwReserved ); #endif #if defined(__urlmon_h__) && !defined(URLDownloadToCacheFileW_NoThrow) -HRESULT +HRESULT URLDownloadToCacheFileW_NoThrow( LPUNKNOWN lpUnkcaller, LPCWSTR szURL, @@ -98,7 +98,7 @@ URLDownloadToCacheFileW_NoThrow( #endif #if defined(__urlmon_h__) && !defined(CoInternetGetSession_NoThrow) -HRESULT +HRESULT CoInternetGetSession_NoThrow( WORD dwSessionMode, IInternetSession **ppIInternetSession, @@ -107,8 +107,8 @@ CoInternetGetSession_NoThrow( #endif #if defined(__urlmon_h__) && !defined(CopyBindInfo_NoThrow) -HRESULT -CopyBindInfo_NoThrow( +HRESULT +CopyBindInfo_NoThrow( const BINDINFO * pcbiSrc, BINDINFO * pbiDest ); #endif @@ -116,42 +116,42 @@ CopyBindInfo_NoThrow( //overrides -#undef InternetTimeToSystemTimeA -#undef CommitUrlCacheEntryW -#undef HttpQueryInfoA -#undef InternetCloseHandle -#undef HttpSendRequestA -#undef HttpOpenRequestA -#undef InternetConnectA -#undef InternetOpenA -#undef InternetReadFile -#undef CreateUrlCacheEntryW -#undef CoInternetGetSession -#undef CopyBindInfo -#undef CoInternetCreateSecurityManager -#undef URLDownloadToCacheFileW -#undef FDICreate -#undef FDIIsCabinet -#undef FDICopy -#undef FDIDestroy -#undef VerQueryValueW -#undef GetFileVersionInfoW -#undef GetFileVersionInfoSizeW -#undef VerQueryValueA -#undef GetFileVersionInfoA -#undef GetFileVersionInfoSizeA +#undef InternetTimeToSystemTimeA +#undef CommitUrlCacheEntryW +#undef HttpQueryInfoA +#undef InternetCloseHandle +#undef HttpSendRequestA +#undef HttpOpenRequestA +#undef InternetConnectA +#undef InternetOpenA +#undef InternetReadFile +#undef CreateUrlCacheEntryW +#undef CoInternetGetSession +#undef CopyBindInfo +#undef CoInternetCreateSecurityManager +#undef URLDownloadToCacheFileW +#undef FDICreate +#undef FDIIsCabinet +#undef FDICopy +#undef FDIDestroy +#undef VerQueryValueW +#undef GetFileVersionInfoW +#undef GetFileVersionInfoSizeW +#undef VerQueryValueA +#undef GetFileVersionInfoA +#undef GetFileVersionInfoSizeA -#define InternetTimeToSystemTimeA InternetTimeToSystemTimeA_NoThrow -#define CommitUrlCacheEntryW CommitUrlCacheEntryW_NoThrow -#define CreateUrlCacheEntryW CreateUrlCacheEntryW_NoThrow -#define CoInternetGetSession CoInternetGetSession_NoThrow -#define CopyBindInfo CopyBindInfo_NoThrow -#define CoInternetCreateSecurityManager CoInternetCreateSecurityManager_NoThrow -#define URLDownloadToCacheFileW URLDownloadToCacheFileW_NoThrow -#define VerQueryValueW VerQueryValueW_NoThrow -#define GetFileVersionInfoW GetFileVersionInfoW_NoThrow -#define GetFileVersionInfoSizeW GetFileVersionInfoSizeW_NoThrow +#define InternetTimeToSystemTimeA InternetTimeToSystemTimeA_NoThrow +#define CommitUrlCacheEntryW CommitUrlCacheEntryW_NoThrow +#define CreateUrlCacheEntryW CreateUrlCacheEntryW_NoThrow +#define CoInternetGetSession CoInternetGetSession_NoThrow +#define CopyBindInfo CopyBindInfo_NoThrow +#define CoInternetCreateSecurityManager CoInternetCreateSecurityManager_NoThrow +#define URLDownloadToCacheFileW URLDownloadToCacheFileW_NoThrow +#define VerQueryValueW VerQueryValueW_NoThrow +#define GetFileVersionInfoW GetFileVersionInfoW_NoThrow +#define GetFileVersionInfoSizeW GetFileVersionInfoSizeW_NoThrow #define VerQueryValueA Use_VerQueryValueW #define GetFileVersionInfoA Use_GetFileVersionInfoW #define GetFileVersionInfoSizeA Use_GetFileVersionInfoSizeW diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/ecmakey.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/ecmakey.h new file mode 100644 index 0000000..ecff950 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/ecmakey.h @@ -0,0 +1,9 @@ +// 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. +#pragma once + +// The byte values of the ECMA pseudo public key and its token. +const BYTE g_rbNeutralPublicKey[] = { 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0 }; +const BYTE g_rbNeutralPublicKeyToken[] = { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }; + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/eetwain.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/eetwain.h index 9597e30..e53f4a6 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/eetwain.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/eetwain.h @@ -32,11 +32,11 @@ #include "bitvector.h" #include "gcinfotypes.h" -#if !defined(_TARGET_X86_) +#if !defined(TARGET_X86) #define USE_GC_INFO_DECODER #endif -#if (defined(_TARGET_X86_) && !defined(FEATURE_PAL)) || defined(_TARGET_AMD64_) +#if (defined(TARGET_X86) && !defined(TARGET_UNIX)) || defined(TARGET_AMD64) #define HAS_QUICKUNWIND #endif @@ -52,7 +52,7 @@ typedef struct _DAC_SLOT_LOCATION int reg; int regOffset; bool targetPtr; - + _DAC_SLOT_LOCATION(int _reg, int _regOffset, bool _targetPtr) : reg(_reg), regOffset(_regOffset), targetPtr(_targetPtr) { @@ -160,7 +160,7 @@ enum }; #ifndef DACCESS_COMPILE -#ifndef WIN64EXCEPTIONS +#ifndef FEATURE_EH_FUNCLETS virtual void FixContext(ContextType ctxType, EHContext *ctx, EECodeInfo *pCodeInfo, @@ -170,10 +170,10 @@ virtual void FixContext(ContextType ctxType, CodeManState *pState, size_t ** ppShadowSP, // OUT size_t ** ppEndRegion) = 0; // OUT -#endif // !WIN64EXCEPTIONS +#endif // !FEATURE_EH_FUNCLETS #endif // #ifndef DACCESS_COMPILE -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 /* Gets the ambient stack pointer value at the given nesting level within the method. @@ -183,7 +183,7 @@ virtual TADDR GetAmbientSP(PREGDISPLAY pContext, DWORD dwRelOffset, DWORD nestingLevel, CodeManState *pState) = 0; -#endif // _TARGET_X86_ +#endif // TARGET_X86 /* Get the number of bytes used for stack parameters. @@ -214,11 +214,11 @@ virtual bool UnwindStackFrame(PREGDISPLAY pContext, virtual bool IsGcSafe(EECodeInfo *pCodeInfo, DWORD dwRelOffset) = 0; -#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) +#if defined(TARGET_ARM) || defined(TARGET_ARM64) virtual bool HasTailCalls(EECodeInfo *pCodeInfo) = 0; -#endif // _TARGET_ARM_ || _TARGET_ARM64_ +#endif // TARGET_ARM || TARGET_ARM64 -#if defined(_TARGET_AMD64_) && defined(_DEBUG) +#if defined(TARGET_AMD64) && defined(_DEBUG) /* Locates the end of the last interruptible region in the given code range. Returns 0 if the entire range is uninterruptible. Returns the end point @@ -227,7 +227,7 @@ virtual bool HasTailCalls(EECodeInfo *pCodeInfo) = 0; virtual unsigned FindEndOfLastInterruptibleRegion(unsigned curOffset, unsigned endOffset, GCInfoToken gcInfoToken) = 0; -#endif // _TARGET_AMD64_ && _DEBUG +#endif // TARGET_AMD64 && _DEBUG #ifndef CROSSGEN_COMPILE /* @@ -245,23 +245,15 @@ virtual bool EnumGcRefs(PREGDISPLAY pContext, DWORD relOffsetOverride = NO_OVERRIDE_OFFSET) = 0; #endif // !CROSSGEN_COMPILE -#if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) -/* - Return the address of the local security object reference - (if available). -*/ -virtual OBJECTREF* GetAddrOfSecurityObject(CrawlFrame *pCF) = 0; -#endif // !DACCESS_COMPILE && !CROSSGEN_COMPILE - #ifndef CROSSGEN_COMPILE /* For a non-static method, "this" pointer is passed in as argument 0. - However, if there is a "ldarga 0" or "starg 0" in the IL, + However, if there is a "ldarga 0" or "starg 0" in the IL, JIT will create a copy of arg0 and redirect all "ldarg(a) 0" and "starg 0" to this copy. (See Compiler::lvaArg0Var for more details.) - + The following method returns the original "this" argument, i.e. the one that is passed in, - if it is a non-static method AND the object is still alive. + if it is a non-static method AND the object is still alive. Returns NULL in all other cases. */ virtual OBJECTREF GetInstance(PREGDISPLAY pContext, @@ -316,10 +308,12 @@ virtual bool IsInSynchronizedRegion( virtual size_t GetFunctionSize(GCInfoToken gcInfoToken) = 0; /* -Returns the ReturnKind of a given function as reported in the GC info. +* Get information necessary for return address hijacking of the method represented by the gcInfoToken. +* If it can be hijacked, it sets the returnKind output parameter to the kind of the return value and +* returns true. +* If hijacking is not possible for some reason, it return false. */ - -virtual ReturnKind GetReturnKind(GCInfoToken gcInfotoken) = 0; +virtual bool GetReturnAddressHijackInfo(GCInfoToken gcInfoToken, ReturnKind * returnKind) = 0; #ifndef USE_GC_INFO_DECODER /* @@ -332,7 +326,7 @@ virtual unsigned int GetFrameSize(GCInfoToken gcInfoToken) = 0; /* Debugger API */ -#ifndef WIN64EXCEPTIONS +#ifndef FEATURE_EH_FUNCLETS virtual const BYTE* GetFinallyReturnAddr(PREGDISPLAY pReg)=0; virtual BOOL IsInFilter(GCInfoToken gcInfoToken, @@ -347,7 +341,7 @@ virtual BOOL LeaveFinally(GCInfoToken gcInfoToken, virtual void LeaveCatch(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx)=0; -#endif // WIN64EXCEPTIONS +#endif // FEATURE_EH_FUNCLETS #ifdef EnC_SUPPORTED @@ -391,7 +385,7 @@ public: #ifndef DACCESS_COMPILE -#ifndef WIN64EXCEPTIONS +#ifndef FEATURE_EH_FUNCLETS /* Last chance for the runtime support to do fixups in the context before execution continues inside a filter, catch handler, or finally @@ -406,10 +400,10 @@ void FixContext(ContextType ctxType, CodeManState *pState, size_t ** ppShadowSP, // OUT size_t ** ppEndRegion); // OUT -#endif // !WIN64EXCEPTIONS +#endif // !FEATURE_EH_FUNCLETS #endif // #ifndef DACCESS_COMPILE -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 /* Gets the ambient stack pointer value at the given nesting level within the method. @@ -420,13 +414,13 @@ TADDR GetAmbientSP(PREGDISPLAY pContext, DWORD dwRelOffset, DWORD nestingLevel, CodeManState *pState); -#endif // _TARGET_X86_ +#endif // TARGET_X86 /* Get the number of bytes used for stack parameters. This is currently only used on x86. */ -virtual +virtual ULONG32 GetStackParameterSize(EECodeInfo* pCodeInfo); #ifndef CROSSGEN_COMPILE @@ -474,12 +468,12 @@ virtual bool IsGcSafe( EECodeInfo *pCodeInfo, DWORD dwRelOffset); -#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) +#if defined(TARGET_ARM) || defined(TARGET_ARM64) virtual bool HasTailCalls(EECodeInfo *pCodeInfo); -#endif // _TARGET_ARM_ || _TARGET_ARM64_ +#endif // TARGET_ARM || TARGET_ARM64 -#if defined(_TARGET_AMD64_) && defined(_DEBUG) +#if defined(TARGET_AMD64) && defined(_DEBUG) /* Locates the end of the last interruptible region in the given code range. Returns 0 if the entire range is uninterruptible. Returns the end point @@ -489,7 +483,7 @@ virtual unsigned FindEndOfLastInterruptibleRegion(unsigned curOffset, unsigned endOffset, GCInfoToken gcInfoToken); -#endif // _TARGET_AMD64_ && _DEBUG +#endif // TARGET_AMD64 && _DEBUG #ifndef CROSSGEN_COMPILE /* @@ -518,22 +512,6 @@ bool EnumGcRefsConservative(PREGDISPLAY pRD, LPVOID hCallBack); #endif // FEATURE_CONSERVATIVE_GC -#ifdef _TARGET_X86_ -/* - Return the address of the local security object reference - using data that was previously cached before in UnwindStackFrame - using StackwalkCacheUnwindInfo -*/ -static OBJECTREF* GetAddrOfSecurityObjectFromCachedInfo( - PREGDISPLAY pRD, - StackwalkCacheUnwindInfo * stackwalkCacheUnwindInfo); -#endif // _TARGET_X86_ - -#if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) -virtual -OBJECTREF* GetAddrOfSecurityObject(CrawlFrame *pCF) DAC_UNEXPECTED(); -#endif // !DACCESS_COMPILE && !CROSSGEN_COMPILE - #ifndef CROSSGEN_COMPILE virtual OBJECTREF GetInstance( @@ -555,20 +533,20 @@ PTR_VOID GetParamTypeArg(PREGDISPLAY pContext, virtual GenericParamContextType GetParamContextType(PREGDISPLAY pContext, EECodeInfo * pCodeInfo); -#if defined(WIN64EXCEPTIONS) && defined(USE_GC_INFO_DECODER) && !defined(CROSSGEN_COMPILE) +#if defined(FEATURE_EH_FUNCLETS) && defined(USE_GC_INFO_DECODER) && !defined(CROSSGEN_COMPILE) /* Returns the generics token. This is used by GetInstance() and GetParamTypeArg() on WIN64. */ -static +static PTR_VOID GetExactGenericsToken(PREGDISPLAY pContext, EECodeInfo * pCodeInfo); -static +static PTR_VOID GetExactGenericsToken(SIZE_T baseStackSlot, EECodeInfo * pCodeInfo); -#endif // WIN64EXCEPTIONS && USE_GC_INFO_DECODER && !CROSSGEN_COMPILE +#endif // FEATURE_EH_FUNCLETS && USE_GC_INFO_DECODER && !CROSSGEN_COMPILE #ifndef CROSSGEN_COMPILE /* @@ -609,9 +587,12 @@ virtual size_t GetFunctionSize(GCInfoToken gcInfoToken); /* -Returns the ReturnKind of a given function. +* Get information necessary for return address hijacking of the method represented by the gcInfoToken. +* If it can be hijacked, it sets the returnKind output parameter to the kind of the return value and +* returns true. +* If hijacking is not possible for some reason, it return false. */ -virtual ReturnKind GetReturnKind(GCInfoToken gcInfotoken); +virtual bool GetReturnAddressHijackInfo(GCInfoToken gcInfoToken, ReturnKind * returnKind); #ifndef USE_GC_INFO_DECODER /* @@ -623,7 +604,7 @@ unsigned int GetFrameSize(GCInfoToken gcInfoToken); #ifndef DACCESS_COMPILE -#ifndef WIN64EXCEPTIONS +#ifndef FEATURE_EH_FUNCLETS virtual const BYTE* GetFinallyReturnAddr(PREGDISPLAY pReg); virtual BOOL IsInFilter(GCInfoToken gcInfoToken, unsigned offset, @@ -635,7 +616,7 @@ virtual BOOL LeaveFinally(GCInfoToken gcInfoToken, virtual void LeaveCatch(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx); -#endif // WIN64EXCEPTIONS +#endif // FEATURE_EH_FUNCLETS #ifdef EnC_SUPPORTED /* @@ -654,13 +635,13 @@ HRESULT FixContextForEnC(PCONTEXT pCtx, #endif // #ifndef DACCESS_COMPILE -#ifdef WIN64EXCEPTIONS +#ifdef FEATURE_EH_FUNCLETS static void EnsureCallerContextIsValid( PREGDISPLAY pRD, StackwalkCacheEntry* pCacheEntry, EECodeInfo * pCodeInfo = NULL ); static size_t GetCallerSp( PREGDISPLAY pRD ); -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 static size_t GetResumeSp( PCONTEXT pContext ); -#endif // _TARGET_X86_ -#endif // WIN64EXCEPTIONS +#endif // TARGET_X86 +#endif // FEATURE_EH_FUNCLETS #ifdef DACCESS_COMPILE virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); @@ -668,7 +649,7 @@ HRESULT FixContextForEnC(PCONTEXT pCtx, }; -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 bool UnwindStackFrame(PREGDISPLAY pContext, EECodeInfo *pCodeInfo, unsigned flags, @@ -726,13 +707,13 @@ struct hdrInfo // Size of the epilogs in the method. // For methods which use CEE_JMP, some epilogs may end with a "ret" instruction - // and some may end with a "jmp". The epilogSize reported should be for the + // and some may end with a "jmp". The epilogSize reported should be for the // epilog with the smallest size. unsigned int epilogSize; unsigned char epilogCnt; bool epilogEnd; // is the epilog at the end of the method - + bool ebpFrame; // locals and arguments addressed relative to EBP bool doubleAlign; // is the stack double-aligned? locals addressed relative to ESP, and arguments relative to EBP bool interruptible; // intr. at all times (excluding prolog/epilog), not just call sites @@ -765,7 +746,7 @@ struct hdrInfo unsigned int revPInvokeOffset; // INVALID_REV_PINVOKE_OFFSET if there is no Reverse PInvoke frame enum { NOT_IN_PROLOG = -1, NOT_IN_EPILOG = -1 }; - + int prologOffs; // NOT_IN_PROLOG if not in prolog int epilogOffs; // NOT_IN_EPILOG if not in epilog. It is never 0 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/eexcp.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/eexcp.h index b91522b..d4052e1 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/eexcp.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/eexcp.h @@ -3,9 +3,9 @@ // See the LICENSE file in the project root for more information. // ==++== -// +// -// +// // // @@ -29,34 +29,34 @@ typedef PTR_VOID PTR_EXCEPTION_CLAUSE_TOKEN; struct EE_ILEXCEPTION_CLAUSE { //Flags is not marked as volatile since it is always accessed // from within a critical section - CorExceptionFlag Flags; - DWORD TryStartPC; + CorExceptionFlag Flags; + DWORD TryStartPC; DWORD TryEndPC; - DWORD HandlerStartPC; - DWORD HandlerEndPC; + DWORD HandlerStartPC; + DWORD HandlerEndPC; union { - void* TypeHandle; + void* TypeHandle; mdToken ClassToken; DWORD FilterOffset; - }; + }; }; struct EE_ILEXCEPTION; typedef DPTR(EE_ILEXCEPTION) PTR_EE_ILEXCEPTION; -struct EE_ILEXCEPTION : public COR_ILMETHOD_SECT_FAT +struct EE_ILEXCEPTION : public COR_ILMETHOD_SECT_FAT { EE_ILEXCEPTION_CLAUSE Clauses[1]; // actually variable size - void Init(unsigned ehCount) + void Init(unsigned ehCount) { LIMITED_METHOD_CONTRACT; SetKind(CorILMethod_Sect_FatFormat); - SetDataSize((unsigned)sizeof(EE_ILEXCEPTION_CLAUSE) * ehCount); + SetDataSize((unsigned)sizeof(EE_ILEXCEPTION_CLAUSE) * ehCount); } - unsigned EHCount() const + unsigned EHCount() const { LIMITED_METHOD_CONTRACT; @@ -71,7 +71,7 @@ struct EE_ILEXCEPTION : public COR_ILMETHOD_SECT_FAT return (offsetof(EE_ILEXCEPTION, Clauses) + sizeof(EE_ILEXCEPTION_CLAUSE) * ehCount); } - EE_ILEXCEPTION_CLAUSE *EHClause(unsigned i) + EE_ILEXCEPTION_CLAUSE *EHClause(unsigned i) { LIMITED_METHOD_DAC_CONTRACT; return &(PTR_EE_ILEXCEPTION_CLAUSE(PTR_HOST_MEMBER_TADDR(EE_ILEXCEPTION,this,Clauses))[i]); @@ -128,19 +128,19 @@ inline BOOL IsDuplicateClause(EE_ILEXCEPTION_CLAUSE* pEHClause) return pEHClause->Flags & COR_ILEXCEPTION_CLAUSE_DUPLICATED; } -#if defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) // Finally is the only EH construct that can be part of the execution as being fall-through. // // "Cloned" finally is a contruct that represents a finally block that is used as // fall through for normal try-block execution. Such a "cloned" finally will: -// +// // 1) Have its try-clause's Start and End PC the same as its handler's start PC (i.e. will have // zero length try block), AND // 2) Is marked duplicate // // Because of their fall-through nature, JIT guarantees that only finally constructs can be cloned, // and not catch or fault (since they cannot be fallen through but are invoked as funclets). -// +// // The cloned finally construct is also used to mark "call to finally" thunks that are not within // the EH region protected by the finally, and also not within the enclosing region. This is done // to prevent ThreadAbortException from creating an infinite loop of calling the same finally. @@ -150,7 +150,7 @@ inline BOOL IsClonedFinally(EE_ILEXCEPTION_CLAUSE* pEHClause) (pEHClause->TryStartPC == pEHClause->HandlerStartPC) && IsFinally(pEHClause) && IsDuplicateClause(pEHClause)); } -#endif // defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) +#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) #endif // __eexcp_h__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/eventtrace.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/eventtrace.h index 1564c94..9a4a818 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/eventtrace.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/eventtrace.h @@ -11,7 +11,7 @@ // // -// +// // #EventTracing // Windows // ETW (Event Tracing for Windows) is a high-performance, low overhead and highly scalable @@ -42,7 +42,7 @@ struct ProfilingScanContext : ScanContext BOOL fProfilerPinned; void * pvEtwContext; void *pHeapId; - + ProfilingScanContext(BOOL fProfilerPinnedParam) : ScanContext() { LIMITED_METHOD_CONTRACT; @@ -97,7 +97,7 @@ namespace ETW // The type this TypeLoggingInfo represents TypeHandle th; - + // Smart sampling // These bucket values remember stats of a particular time slice that are used to @@ -148,13 +148,13 @@ namespace ETW // Take lock, and consult hash table to see if this is the first time we've // encountered the type, in which case, log it kTypeLogBehaviorTakeLockAndLogIfFirstTime, - + // Don't take lock, don't consult hash table. Just log the type. (This is // used in cases when checking for dupe type logging isn't worth it, such as // when logging the finalization of an object.) kTypeLogBehaviorAlwaysLog, - // When logging the type for GCSampledObjectAllocation events, + // When logging the type for GCSampledObjectAllocation events, // we already know we need to log the type (since we already // looked it up in the hash). But we would still need to consult the hash // for any type parameters, so kTypeLogBehaviorAlwaysLog isn't appropriate, @@ -193,7 +193,7 @@ namespace ETW // When WPA triggers a GC, it gives us this unique number to append to our // GCStart event so WPA can correlate the CLR's GC with the JScript GC they // triggered at the same time. - // + // // We set this value when the GC is triggered, and then retrieve the value on the // first subsequent FireGcStart() method call for a full, induced GC, assuming // that that's the GC that WPA triggered. This is imperfect, and if we were in @@ -251,9 +251,9 @@ namespace ETW // These values are gotten from the gc_reason // in gcimpl.h - typedef enum _GC_REASON { - GC_ALLOC_SOH = 0, - GC_INDUCED = 1, + typedef enum _GC_REASON { + GC_ALLOC_SOH = 0, + GC_INDUCED = 1, GC_LOWMEMORY = 2, GC_EMPTY = 3, GC_ALLOC_LOH = 4, @@ -265,12 +265,12 @@ namespace ETW GC_INDUCED_COMPACTING = 10, GC_LOWMEMORY_HOST = 11 } GC_REASON; - typedef enum _GC_TYPE { - GC_NGC = 0, - GC_BGC = 1, + typedef enum _GC_TYPE { + GC_NGC = 0, + GC_BGC = 1, GC_FGC = 2 } GC_TYPE; - typedef enum _GC_ROOT_KIND { + typedef enum _GC_ROOT_KIND { GC_ROOT_STACK = 0, GC_ROOT_FQ = 1, GC_ROOT_HANDLES = 2, @@ -291,9 +291,9 @@ namespace ETW struct { ULONG Reason; - // This is only valid when SuspendEE is called by GC (ie, Reason is either + // This is only valid when SuspendEE is called by GC (ie, Reason is either // SUSPEND_FOR_GC or SUSPEND_FOR_GC_PREP. - ULONG GcCount; + ULONG GcCount; } SuspendEE; struct { @@ -301,8 +301,8 @@ namespace ETW } GCMark; struct { - ULONGLONG SegmentSize; - ULONGLONG LargeObjectSegmentSize; + ULONGLONG SegmentSize; + ULONGLONG LargeObjectSegmentSize; BOOL ServerGC; // TRUE means it's server GC; FALSE means it's workstation. } GCSettings; @@ -310,7 +310,7 @@ namespace ETW // The generation that triggered this notification. ULONG Count; // 1 means the notification was due to allocation; 0 means it was due to other factors. - ULONG Alloc; + ULONG Alloc; } GCFullNotify; } ETW_GC_INFO, *PETW_GC_INFO; @@ -343,7 +343,7 @@ namespace ETW static BOOL ShouldWalkStaticsAndCOMForEtw(); static VOID WalkStaticsAndCOMForETW(); static VOID EndHeapDump(ProfilerWalkHeapContext * profilerWalkHeapContext); -#ifdef FEATURE_EVENT_TRACE +#ifdef FEATURE_EVENT_TRACE static VOID BeginMovedReferences(size_t * pProfilingContext); static VOID MovedReference(BYTE * pbMemBlockStart, BYTE * pbMemBlockEnd, ptrdiff_t cbRelocDistance, size_t profilingContext, BOOL fCompacting, BOOL fAllowProfApiNotification = TRUE); static VOID EndMovedReferences(size_t profilingContext, BOOL fAllowProfApiNotification = TRUE); @@ -352,7 +352,7 @@ namespace ETW static VOID BeginMovedReferences(size_t * pProfilingContext) {}; static VOID MovedReference(BYTE * pbMemBlockStart, BYTE * pbMemBlockEnd, ptrdiff_t cbRelocDistance, size_t profilingContext, BOOL fCompacting, BOOL fAllowProfApiNotification = TRUE) {}; static VOID EndMovedReferences(size_t profilingContext, BOOL fAllowProfApiNotification = TRUE) {}; -#endif // FEATURE_EVENT_TRACE +#endif // FEATURE_EVENT_TRACE static VOID SendFinalizeObjectEvent(MethodTable * pMT, Object * pObj); }; }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/eventtracebase.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/eventtracebase.h index 43147f5..a02d8f5 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/eventtracebase.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/eventtracebase.h @@ -46,6 +46,16 @@ enum EtwTypeFlags kEtwTypeFlagsFinalizable = 0x2, kEtwTypeFlagsExternallyImplementedCOMObject = 0x4, kEtwTypeFlagsArray = 0x8, + kEtwTypeFlagsArrayRankBit0 = 0x100, + kEtwTypeFlagsArrayRankBit1 = 0x200, + kEtwTypeFlagsArrayRankBit2 = 0x400, + kEtwTypeFlagsArrayRankBit3 = 0x800, + kEtwTypeFlagsArrayRankBit4 = 0x1000, + kEtwTypeFlagsArrayRankBit5 = 0x2000, + + kEtwTypeFlagsArrayRankMask = 0x3F00, + kEtwTypeFlagsArrayRankShift = 8, + kEtwTypeFlagsArrayRankMax = kEtwTypeFlagsArrayRankMask >> kEtwTypeFlagsArrayRankShift }; enum EtwThreadFlags @@ -65,14 +75,14 @@ enum EtwThreadFlags #define EVENT_PIPE_ENABLED() (FALSE) #endif -#if !defined(FEATURE_PAL) +#if !defined(HOST_UNIX) // // Use this macro at the least before calling the Event Macros // #define ETW_TRACING_INITIALIZED(RegHandle) \ - ((g_pEtwTracer && RegHandle) || EVENT_PIPE_ENABLED()) + ((g_pEtwTracer && (RegHandle)) || EVENT_PIPE_ENABLED()) // // Use this macro to check if an event is enabled @@ -95,7 +105,7 @@ enum EtwThreadFlags ((ProviderSymbol##_Context.IsEnabled) || EVENT_PIPE_ENABLED()) -#else //!defined(FEATURE_PAL) +#else //!defined(HOST_UNIX) #if defined(FEATURE_PERFTRACING) #define ETW_INLINE #define ETWOnStartup(StartEventName, EndEventName) @@ -122,7 +132,7 @@ enum EtwThreadFlags #define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (ETW_CATEGORY_ENABLED(Context, Level, Keyword)) #define ETW_PROVIDER_ENABLED(ProviderSymbol) (XplatEventLogger::IsProviderEnabled(Context)) #endif // defined(FEATURE_PERFTRACING) -#endif // !defined(FEATURE_PAL) +#endif // !defined(HOST_UNIX) #else // FEATURE_EVENT_TRACE @@ -160,7 +170,7 @@ public: #ifdef FEATURE_EVENT_TRACE class Object; -#if !defined(FEATURE_PAL) +#if !defined(HOST_UNIX) /***************************************/ /* Tracing levels supported by CLR ETW */ @@ -204,12 +214,12 @@ struct ProfilingScanContext; #include #include #endif //!FEATURE_REDHAWK -#endif //!defined(FEATURE_PAL) +#endif //!defined(HOST_UNIX) #else // FEATURE_EVENT_TRACE -#include "etmdummy.h" +#include "../gc/env/etmdummy.h" #endif // FEATURE_EVENT_TRACE #ifndef FEATURE_REDHAWK @@ -221,9 +231,19 @@ struct ProfilingScanContext; extern UINT32 g_nClrInstanceId; #define GetClrInstanceId() (static_cast(g_nClrInstanceId)) -#if defined(FEATURE_PAL) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) +#if defined(HOST_UNIX) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) #define KEYWORDZERO 0x0 +#define DEF_LTTNG_KEYWORD_ENABLED 1 +#ifdef FEATURE_EVENT_TRACE +#include "clrproviders.h" +#endif // FEATURE_EVENT_TRACE +#include "clrconfig.h" + +#endif // defined(HOST_UNIX) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) + +#if defined(FEATURE_PERFTRACING) || defined(FEATURE_EVENTSOURCE_XPLAT) + /***************************************/ /* Tracing levels supported by CLR ETW */ /***************************************/ @@ -234,10 +254,6 @@ extern UINT32 g_nClrInstanceId; #define TRACE_LEVEL_INFORMATION 4 // Includes non-error cases such as Entry-Exit #define TRACE_LEVEL_VERBOSE 5 // Detailed traces from intermediate steps -#define DEF_LTTNG_KEYWORD_ENABLED 1 -#include "clrproviders.h" -#include "clrconfig.h" - class XplatEventLoggerConfiguration { public: @@ -271,7 +287,11 @@ public: _enabledKeywords = ParseEnabledKeywordsMask(keywordsComponent); auto levelComponent = GetNextComponentString(keywordsComponent.End + 1); - _level = ParseEnabledKeywordsMask(levelComponent); + _level = ParseLevel(levelComponent); + + auto argumentComponent = GetNextComponentString(levelComponent.End + 1); + _argument = ParseArgument(argumentComponent); + _isValid = true; } @@ -285,16 +305,21 @@ public: return _provider; } - ULONGLONG GetEnabledKeywordsMask() const + uint64_t GetEnabledKeywordsMask() const { return _enabledKeywords; } - UINT GetLevel() const + uint32_t GetLevel() const { return _level; } + LPCWSTR GetArgument() const + { + return _argument; + } + private: struct ComponentSpan { @@ -310,9 +335,8 @@ private: ComponentSpan GetNextComponentString(LPCWSTR start) const { - static WCHAR ComponentDelimiter = W(':'); - - auto end = wcschr(start, ComponentDelimiter); + const WCHAR ComponentDelimiter = W(':'); + const WCHAR * end = wcschr(start, ComponentDelimiter); if (end == nullptr) { end = start + wcslen(start); @@ -321,22 +345,22 @@ private: return ComponentSpan(start, end); } - LPCWSTR ParseProviderName(ComponentSpan const & component) const + NewArrayHolder ParseProviderName(ComponentSpan const & component) const { - auto providerName = (WCHAR*)nullptr; + NewArrayHolder providerName = nullptr; if ((component.End - component.Start) != 0) { auto const length = component.End - component.Start; providerName = new WCHAR[length + 1]; - memset(providerName, '\0', (length + 1) * sizeof(WCHAR)); wcsncpy(providerName, component.Start, length); + providerName[length] = '\0'; } return providerName; } - ULONGLONG ParseEnabledKeywordsMask(ComponentSpan const & component) const + uint64_t ParseEnabledKeywordsMask(ComponentSpan const & component) const { - auto enabledKeywordsMask = (ULONGLONG)(-1); + auto enabledKeywordsMask = (uint64_t)(-1); if ((component.End - component.Start) != 0) { enabledKeywordsMask = _wcstoui64(component.Start, nullptr, 16); @@ -344,9 +368,9 @@ private: return enabledKeywordsMask; } - UINT ParseLevel(ComponentSpan const & component) const + uint32_t ParseLevel(ComponentSpan const & component) const { - auto level = TRACE_LEVEL_VERBOSE; + int level = TRACE_LEVEL_VERBOSE; // Verbose if ((component.End - component.Start) != 0) { level = _wtoi(component.Start); @@ -354,11 +378,28 @@ private: return level; } - LPCWSTR _provider; - ULONGLONG _enabledKeywords; - UINT _level; + NewArrayHolder ParseArgument(ComponentSpan const & component) const + { + NewArrayHolder argument = nullptr; + if ((component.End - component.Start) != 0) + { + auto const length = component.End - component.Start; + argument = new WCHAR[length + 1]; + wcsncpy(argument, component.Start, length); + argument[length] = '\0'; + } + return argument; + } + + NewArrayHolder _provider; + uint64_t _enabledKeywords; + uint32_t _level; + NewArrayHolder _argument; bool _isValid; }; +#endif // defined(FEATURE_PERFTRACING) || defined(FEATURE_EVENTSOURCE_XPLAT) + +#if defined(HOST_UNIX) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) class XplatEventLoggerController { @@ -378,9 +419,10 @@ public: { ActivateAllKeywordsOfAllProviders(); } +#ifdef FEATURE_EVENT_TRACE else { - auto provider = GetProvider(providerName); + LTTNG_TRACE_CONTEXT *provider = GetProvider(providerName); if (provider == nullptr) { return; @@ -389,20 +431,23 @@ public: provider->Level = level; provider->IsEnabled = true; } +#endif } static void ActivateAllKeywordsOfAllProviders() { +#ifdef FEATURE_EVENT_TRACE for (LTTNG_TRACE_CONTEXT * const provider : ALL_LTTNG_PROVIDERS_CONTEXT) { provider->EnabledKeywordsBitmask = (ULONGLONG)(-1); provider->Level = TRACE_LEVEL_VERBOSE; provider->IsEnabled = true; } +#endif } private: - +#ifdef FEATURE_EVENT_TRACE static LTTNG_TRACE_CONTEXT * const GetProvider(LPCWSTR providerName) { auto length = wcslen(providerName); @@ -415,6 +460,7 @@ private: } return nullptr; } +#endif }; class XplatEventLogger @@ -427,6 +473,7 @@ public: return configEventLogging.val(CLRConfig::EXTERNAL_EnableEventLog); } +#ifdef FEATURE_EVENT_TRACE inline static bool IsProviderEnabled(DOTNET_TRACE_CONTEXT providerCtx) { return providerCtx.LttngProvider->IsEnabled; @@ -448,7 +495,7 @@ public: } return false; } - +#endif /* This method is where COMPlus_LTTngConfig environment variable is parsed and is registered with the runtime provider @@ -479,7 +526,7 @@ public: } while (configToParse != nullptr) { - static WCHAR comma = W(','); + const WCHAR comma = W(','); auto end = wcschr(configToParse, comma); configuration.Parse(configToParse); XplatEventLoggerController::UpdateProviderContext(configuration); @@ -493,7 +540,7 @@ public: }; -#endif // defined(FEATURE_PAL) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) +#endif // defined(HOST_UNIX) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) #if defined(FEATURE_EVENT_TRACE) @@ -535,7 +582,7 @@ VOID EventPipeEtwCallbackDotNETRuntimePrivate( _In_opt_ EventFilterDescriptor* FilterData, _Inout_opt_ PVOID CallbackContext); -#ifndef FEATURE_PAL +#ifndef HOST_UNIX // Callback and stack support #if !defined(DONOT_DEFINE_ETW_CALLBACK) && !defined(DACCESS_COMPILE) extern "C" { @@ -558,7 +605,7 @@ extern "C" { // User defined callback // #define MCGEN_PRIVATE_ENABLE_CALLBACK(RequestCode, Context, InOutBufferSize, Buffer) \ - EtwCallback(NULL /* SourceId */, (RequestCode==WMI_ENABLE_EVENTS) ? EVENT_CONTROL_CODE_ENABLE_PROVIDER : EVENT_CONTROL_CODE_DISABLE_PROVIDER, 0 /* Level */, 0 /* MatchAnyKeyword */, 0 /* MatchAllKeyword */, NULL /* FilterData */, Context) + EtwCallback(NULL /* SourceId */, ((RequestCode)==WMI_ENABLE_EVENTS) ? EVENT_CONTROL_CODE_ENABLE_PROVIDER : EVENT_CONTROL_CODE_DISABLE_PROVIDER, 0 /* Level */, 0 /* MatchAnyKeyword */, 0 /* MatchAllKeyword */, NULL /* FilterData */, Context) // // User defined callback2 @@ -585,7 +632,7 @@ extern "C" { EtwCallout(RegHandle, Descriptor, NumberOfArguments, EventData) #endif //!DONOT_DEFINE_ETW_CALLBACK && !DACCESS_COMPILE -#endif //!FEATURE_PAL +#endif //!HOST_UNIX #include "clretwallmain.h" #if defined(FEATURE_PERFTRACING) @@ -643,7 +690,7 @@ class Thread; namespace ETW { // Class to wrap the ETW infrastructure logic -#if !defined(FEATURE_PAL) +#if !defined(HOST_UNIX) class CEtwTracer { #if defined(FEATURE_EVENT_TRACE) @@ -668,7 +715,7 @@ namespace ETW } #endif // FEATURE_EVENT_TRACE }; -#endif // !defined(FEATURE_PAL) +#endif // !defined(HOST_UNIX) class LoaderLog; class MethodLog; @@ -739,7 +786,7 @@ namespace ETW class SamplingLog { -#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) +#if defined(FEATURE_EVENT_TRACE) && !defined(HOST_UNIX) public: typedef enum _EtwStackWalkStatus { @@ -756,7 +803,7 @@ namespace ETW public: static ULONG SendStackTrace(MCGEN_TRACE_CONTEXT TraceContext, PCEVENT_DESCRIPTOR Descriptor, LPCGUID EventGuid); EtwStackWalkStatus GetCurrentThreadsCallStack(UINT32 *frameCount, PVOID **Stack); -#endif // FEATURE_EVENT_TRACE && !defined(FEATURE_PAL) +#endif // FEATURE_EVENT_TRACE && !defined(HOST_UNIX) }; // Class to wrap all Loader logic for ETW @@ -846,6 +893,7 @@ namespace ETW static VOID SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, PCODE pNativeCodeStartAddress, ReJITID ilCodeId); static VOID SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, PCODE pNativeCodeStartAddress = 0, PrepareCodeConfig *pConfig = NULL); static VOID SendHelperEvent(ULONGLONG ullHelperStartAddress, ULONG ulHelperSize, LPCWSTR pHelperName); + static VOID SendMethodDetailsEvent(MethodDesc *pMethodDesc); public: typedef union _MethodStructs { @@ -1193,6 +1241,10 @@ namespace ETW #else static bool IsEnabled() { return false; } static void SendSettings() {} + static void SendPause() {} + static void SendResume(UINT32 newMethodCount) {} + static void SendBackgroundJitStart(UINT32 pendingMethodCount) {} + static void SendBackgroundJitStop(UINT32 pendingMethodCount, UINT32 jittedMethodCount) {} #endif DISABLE_CONSTRUCT_COPY(Runtime); @@ -1235,12 +1287,17 @@ namespace ETW #define ETWLoaderStaticLoad 0 // Static reference load #define ETWLoaderDynamicLoad 1 // Dynamic assembly load -#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) +#if defined(FEATURE_EVENT_TRACE) && !defined(HOST_UNIX) // // The ONE and only ONE global instantiation of this class // extern ETW::CEtwTracer * g_pEtwTracer; +EXTERN_C DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context; +EXTERN_C DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_DOTNET_Context; +EXTERN_C DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context; +EXTERN_C DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_DOTNET_Context; + // // Special Handling of Startup events // @@ -1397,18 +1454,18 @@ typedef struct _MCGEN_TRACE_BUFFER { return Result; }; -#endif // FEATURE_EVENT_TRACE && !defined(FEATURE_PAL) +#endif // FEATURE_EVENT_TRACE && !defined(HOST_UNIX) #ifdef FEATURE_EVENT_TRACE -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 struct CallStackFrame { struct CallStackFrame* m_Next; SIZE_T m_ReturnAddress; }; -#endif // _TARGET_X86_ +#endif // TARGET_X86 #endif // FEATURE_EVENT_TRACE -#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) +#if defined(FEATURE_EVENT_TRACE) && !defined(HOST_UNIX) FORCEINLINE BOOLEAN __stdcall McGenEventProviderEnabled( @@ -1443,7 +1500,7 @@ McGenEventProviderEnabled( } return FALSE; } -#endif // FEATURE_EVENT_TRACE && !defined(FEATURE_PAL) +#endif // FEATURE_EVENT_TRACE && !defined(HOST_UNIX) #endif // !FEATURE_REDHAWK diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/ex.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/ex.h index ac40cba..21ce9d3 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/ex.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/ex.h @@ -6,15 +6,15 @@ #if !defined(_EX_H_) #define _EX_H_ -#ifdef FEATURE_PAL +#ifdef HOST_UNIX #define EX_TRY_HOLDER \ HardwareExceptionHolder \ NativeExceptionHolderCatchAll __exceptionHolder; \ __exceptionHolder.Push(); \ -#else // FEATURE_PAL +#else // HOST_UNIX #define EX_TRY_HOLDER -#endif // FEATURE_PAL +#endif // HOST_UNIX #include "sstring.h" #include "crtwrap.h" @@ -29,7 +29,7 @@ #endif -//=========================================================================================== +//=========================================================================================== // These abstractions hide the difference between legacy desktop CLR's (that don't support // side-by-side-inproc and rely on a fixed SEH code to identify managed exceptions) and // new CLR's that support side-by-side inproc. @@ -39,7 +39,7 @@ // the module handle of the owning CLR is stored in ExceptionRecord.ExceptionInformation[4]. // // (Note: all existing SEH's use either only slot [0] or no slots at all. We are leaving -// slots [1] thru [3] open for future expansion.) +// slots [1] thru [3] open for future expansion.) //=========================================================================================== // Is this exception code one of the special CLR-specific SEH codes that participate in the @@ -76,7 +76,7 @@ DWORD MarkAsThrownByUs(/*out*/ ULONG_PTR exceptionArgs[INSTANCE_TAGGED_SEH_PARAM // *and* whether it was tagged by the calling instance of the CLR. // // If this is a non-tagged-SEH-enabled build, it is blindly assumed to be tagged by the -// calling instance of the CLR. +// calling instance of the CLR. BOOL WasThrownByUs(const EXCEPTION_RECORD *pcER, DWORD dwExceptionCode); @@ -87,8 +87,8 @@ BOOL IsComPlusException(const EXCEPTION_RECORD *pcER); VOID RaiseComPlusException(); -//=========================================================================================== -//=========================================================================================== +//=========================================================================================== +//=========================================================================================== //------------------------------------------------------------------------------------------- @@ -112,7 +112,7 @@ void GenerateTopLevelHRExceptionMessage(HRESULT hresult, SString &result); // We save current ExceptionPointers using VectoredExceptionHandler. The save data is only valid // duing exception handling. GetCurrentExceptionPointers returns the saved data. // --------------------------------------------------------------------------- -void GetCurrentExceptionPointers(PEXCEPTION_POINTERS pExceptionInfo); +void GetCurrentExceptionPointers(PEXCEPTION_POINTERS pExceptionInfo DEBUG_ARG(bool checkExceptionRecordLocation)); // --------------------------------------------------------------------------- // We save current ExceptionPointers using VectoredExceptionHandler. The save data is only valid @@ -254,7 +254,7 @@ class Exception // Preallocated exceptions: If there is a preallocated instance of some // subclass of Exception, override this function and return a correct // value. The default implementation returns constant FALSE - virtual BOOL IsPreallocatedException(); + virtual BOOL IsPreallocatedException(); BOOL IsPreallocatedOOMException(); static void Delete(Exception* pvMemory); @@ -264,16 +264,16 @@ protected: // This virtual method must be implemented by any non abstract Exception // derived class. It must allocate a NEW exception of the identical type and // copy all the relevant fields from the current exception to the new one. - // It is NOT responsible however for copying the inner exception. This + // It is NOT responsible however for copying the inner exception. This // will be handled by the base Exception class. - virtual Exception *CloneHelper(); + virtual Exception *CloneHelper(); // This virtual method must be implemented by Exception subclasses whose - // DomainBoundClone behavior is different than their normal clone behavior. + // DomainBoundClone behavior is different than their normal clone behavior. // It must allocate a NEW exception of the identical type and // copy all the relevant fields from the current exception to the new one. - // It is NOT responsible however for copying the inner exception. This - // will be handled by the base Exception class. + // It is NOT responsible however for copying the inner exception. This + // will be handled by the base Exception class. virtual Exception *DomainBoundCloneHelper() { return CloneHelper(); } }; @@ -295,16 +295,16 @@ typedef ExceptionHolderTemplate ExceptionHolder; // class ExceptionHolder // // This is a very lightweight holder class for use inside the EX_TRY family -// of macros. It is based on the standard Holder classes, but has been +// of macros. It is based on the standard Holder classes, but has been // highly specialized for this one function, so that extra code can be // removed, and the resulting code can be simple enough for all of the // non-exceptional-case code to be inlined. class ExceptionHolder { private: - Exception *m_value; + Exception *m_value; BOOL m_acquired; - + public: FORCEINLINE ExceptionHolder(Exception *pException = NULL, BOOL take = TRUE) : m_value(pException) @@ -321,7 +321,7 @@ public: } Exception* operator->() { return m_value; } - + void operator=(Exception *p) { Release(); @@ -330,11 +330,11 @@ public: } BOOL IsNull() { return m_value == NULL; } - - operator Exception*() { return m_value; } - + + operator Exception*() { return m_value; } + Exception* GetValue() { return m_value; } - + void SuppressRelease() { m_acquired = FALSE; } private: @@ -359,7 +359,7 @@ private: }; -#endif +#endif // --------------------------------------------------------------------------- // HRException class. Implements exception API for exceptions generated from HRESULTs @@ -385,18 +385,18 @@ class HRException : public Exception // Virtual overrides HRESULT GetHR(); - BOOL IsSameInstanceType(Exception *pException) + BOOL IsSameInstanceType(Exception *pException) { - WRAPPER_NO_CONTRACT; + WRAPPER_NO_CONTRACT; return pException->GetInstanceType() == GetType() && pException->GetHR() == m_hr; } - protected: + protected: virtual Exception *CloneHelper() { WRAPPER_NO_CONTRACT; return new HRException(m_hr); - } + } }; // --------------------------------------------------------------------------- @@ -418,12 +418,12 @@ class HRMsgException : public HRException // Virtual overrides void GetMessage(SString &s); - protected: + protected: virtual Exception *CloneHelper() { WRAPPER_NO_CONTRACT; return new HRMsgException(m_hr, m_msg); - } + } }; // --------------------------------------------------------------------------- @@ -447,12 +447,12 @@ class COMException : public HRException IErrorInfo *GetErrorInfo(); void GetMessage(SString &result); - protected: + protected: virtual Exception *CloneHelper() { WRAPPER_NO_CONTRACT; return new COMException(m_hr, m_pErrorInfo); - } + } }; // --------------------------------------------------------------------------- @@ -476,9 +476,9 @@ class SEHException : public Exception virtual int GetInstanceType() { LIMITED_METHOD_CONTRACT; return c_type; } virtual BOOL IsType(int type) { WRAPPER_NO_CONTRACT; return type == c_type || Exception::IsType(type); } - BOOL IsSameInstanceType(Exception *pException) + BOOL IsSameInstanceType(Exception *pException) { - WRAPPER_NO_CONTRACT; + WRAPPER_NO_CONTRACT; return pException->GetInstanceType() == GetType() && pException->GetHR() == GetHR(); } @@ -487,12 +487,12 @@ class SEHException : public Exception IErrorInfo *GetErrorInfo(); void GetMessage(SString &result); - protected: + protected: virtual Exception *CloneHelper() { WRAPPER_NO_CONTRACT; return new SEHException(&m_exception); - } + } }; // --------------------------------------------------------------------------- @@ -520,38 +520,38 @@ class DelegatingException : public Exception virtual int GetInstanceType() { LIMITED_METHOD_CONTRACT; return c_type; } virtual BOOL IsType(int type) { WRAPPER_NO_CONTRACT; return type == c_type || Exception::IsType(type); } - BOOL IsSameInstanceType(Exception *pException) + BOOL IsSameInstanceType(Exception *pException) { - WRAPPER_NO_CONTRACT; + WRAPPER_NO_CONTRACT; return pException->GetInstanceType() == GetType() && pException->GetHR() == GetHR(); } // Virtual overrides - virtual BOOL IsDomainBound() {return Exception::IsDomainBound() ||(m_delegatedException!=NULL && m_delegatedException->IsDomainBound());} ; + virtual BOOL IsDomainBound() {return Exception::IsDomainBound() ||(m_delegatedException!=NULL && m_delegatedException->IsDomainBound());} ; HRESULT GetHR(); IErrorInfo *GetErrorInfo(); void GetMessage(SString &result); virtual Exception *Clone(); - protected: + protected: virtual Exception *CloneHelper() { WRAPPER_NO_CONTRACT; return new DelegatingException(); - } + } }; //------------------------------------------------------------------------------ // class OutOfMemoryException // // While there could be any number of instances of this class, there is one -// special instance, the pre-allocated OOM exception. Storage for that +// special instance, the pre-allocated OOM exception. Storage for that // instance is allocated in the image, so we can always obtain it, even // in low memory situations. // Note that, in fact, there is only one instance. //------------------------------------------------------------------------------ class OutOfMemoryException : public Exception -{ +{ private: static const int c_type = 0x4F4F4D20; // 'OOM ' BOOL bIsPreallocated; @@ -564,10 +564,10 @@ class OutOfMemoryException : public Exception static int GetType() {LIMITED_METHOD_CONTRACT; return c_type; } virtual int GetInstanceType() { LIMITED_METHOD_CONTRACT; return c_type; } BOOL IsType(int type) { WRAPPER_NO_CONTRACT; return type == c_type || Exception::IsType(type); } - - BOOL IsSameInstanceType(Exception *pException) + + BOOL IsSameInstanceType(Exception *pException) { - WRAPPER_NO_CONTRACT; + WRAPPER_NO_CONTRACT; return pException->GetInstanceType() == GetType(); } @@ -575,7 +575,7 @@ class OutOfMemoryException : public Exception void GetMessage(SString &result) { WRAPPER_NO_CONTRACT; result.SetASCII("Out Of Memory"); } virtual Exception *Clone(); - + virtual BOOL IsPreallocatedException() { return bIsPreallocated; } }; @@ -609,9 +609,9 @@ public: #ifdef ENABLE_CONTRACTS_IMPL // Restore the original OkayToThrow value since we're leaving the try block. - + m_pClrDebugState->SetOkToThrow( m_oldOkayToThrowValue ); -#endif // ENABLE_CONTRACTS_IMPL +#endif // ENABLE_CONTRACTS_IMPL } protected: @@ -621,7 +621,7 @@ protected: private: BOOL m_oldOkayToThrowValue; ClrDebugState *m_pClrDebugState; -#endif +#endif }; // --------------------------------------------------------------------------- @@ -649,15 +649,15 @@ private: // 1. They catch all exceptions, both C++ and SEH exceptions. // 2. They catch only C++ exceptions. // -// Which way they are defined depends on what sort of handling of SEH +// Which way they are defined depends on what sort of handling of SEH // exceptions, like AV's, you wish to have in your DLL. In general we // do not typically want to catch and swallow AV's. // // By default, the macros catch all exceptions. This is how they work when // compiled into the primary runtime DLL (clr.dll). This is reasonable for // the CLR becuase it needs to also catch managed exceptions, which are SEH -// exceptions, and because that DLL also includes a vectored exception -// handler that will take down the process on any AV within clr.dll. +// exceptions, and because that DLL also includes a vectored exception +// handler that will take down the process on any AV within clr.dll. // // But for uses of these macros outside of the CLR DLL there are other // possibilities. If a DLL only uses facilities in Utilcode that throw the @@ -733,7 +733,7 @@ private: // 4) RethrowCorruptingExceptionsEx - same as (2) but rethrow of CE can be controlled via a condition. // // By default, if a CE is encountered when one of the above policies are applied, the runtime will -// ensure that the CE propagates up the stack and not get swallowed unless the developer chooses to override the behaviour. +// ensure that the CE propagates up the stack and not get swallowed unless the developer chooses to override the behaviour. // This can be done by using the "Ex" versions above that take a conditional which evaluates to a BOOL. In such a case, // the CE will *only* be rethrown if the conditional evalutes to TRUE. For examples, refer to COMToCLRWorker or // DispatchInfo::InvokeMember implementations. @@ -747,7 +747,7 @@ private: // // We also check the global override flag incase it has been set to force pre-V4 beahviour. "0" implies it has not // been overriden. -#define SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr) (((expr == TRUE) && \ +#define SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr) ((((expr) == TRUE) && \ (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_legacyCorruptedStateExceptionsPolicy) == 0) && \ IsProcessCorruptedStateException(GetCurrentExceptionCode(), FALSE))) @@ -841,8 +841,8 @@ Exception *ExThrowWithInnerHelper(Exception *inner); // This macro will set the m_innerException into the newly created exception // The passed in _type has to be derived from CLRException. You cannot put OOM // as the inner exception. If we are throwing in OOM case, allocate more memory (this macro will clone) -// does not make any sense. -// +// does not make any sense. +// #define EX_THROW_WITH_INNER(_type, _args, _inner) \ { \ FAULT_NOT_FATAL(); \ @@ -893,7 +893,7 @@ Exception *ExThrowWithInnerHelper(Exception *inner); DEBUG_ASSURE_NO_RETURN_BEGIN(EX_TRY) \ EX_TRY_HOLDER \ - + #define EX_CATCH_IMPL_EX(DerivedExceptionClass) \ DEBUG_ASSURE_NO_RETURN_END(EX_TRY) \ } \ @@ -967,11 +967,11 @@ Exception *ExThrowWithInnerHelper(Exception *inner); // Here we finally define the EX_CATCH* macros that will be used throughout the system. -// These can catch C++ and SEH exceptions, or just C++ exceptions. +// These can catch C++ and SEH exceptions, or just C++ exceptions. // See code:NO_HOST_CPP_EH_ONLY for more details. // // Note: we make it illegal to use forms that are redundant with the basic EX_CATCH -// version. I.e., in the C++ & SEH version, EX_CATCH_CPP_AND_SEH is the same as EX_CATCH. +// version. I.e., in the C++ & SEH version, EX_CATCH_CPP_AND_SEH is the same as EX_CATCH. // Likewise, in the C++ only version, EX_CATCH_CPP_ONLY is redundant with EX_CATCH. #ifndef NO_HOST_CPP_EH_ONLY @@ -986,8 +986,8 @@ Exception *ExThrowWithInnerHelper(Exception *inner); #define EX_CATCH_CPP_ONLY Dont_Use_EX_CATCH_CPP_ONLY #define EX_CATCH_CPP_AND_SEH EX_CATCH_IMPL -// Note: at this time we don't have a use case for EX_CATCH_EX, and we do not have -// the C++-only version of the implementation available. Thus we disallow its use at this time. +// Note: at this time we don't have a use case for EX_CATCH_EX, and we do not have +// the C++-only version of the implementation available. Thus we disallow its use at this time. // If a real use case arises then we should go ahead and enable this. #define EX_CATCH_EX Dont_Use_EX_CATCH_EX #endif @@ -1002,7 +1002,7 @@ Exception *ExThrowWithInnerHelper(Exception *inner); } \ -// "terminalexceptionpolicy" must be one of "RethrowTerminalExceptions", +// "terminalexceptionpolicy" must be one of "RethrowTerminalExceptions", // "RethrowTransientExceptions", or "SwallowAllExceptions" #define EX_END_CATCH(terminalexceptionpolicy) \ @@ -1068,7 +1068,7 @@ Exception *ExThrowWithInnerHelper(Exception *inner); } \ EX_END_CATCH(SwallowAllExceptions) - + //=================================================================================== // Macro for catching managed exception object. // @@ -1090,7 +1090,7 @@ Exception *ExThrowWithInnerHelper(Exception *inner); #ifdef FEATURE_COMINTEROP - + //=================================================================================== // Macro for defining external entrypoints such as COM interop boundaries. // The boundary will catch all exceptions (including terminals) and convert @@ -1276,10 +1276,10 @@ inline Exception::HandlerState::HandlerState() #if defined(STACK_GUARDS_DEBUG) && defined(ENABLE_CONTRACTS_IMPL) // If we have a debug state, use its setting for SO tolerance. The default - // is SO-tolerant if we have no debug state. Can't probe w/o debug state and + // is SO-tolerant if we have no debug state. Can't probe w/o debug state and // can't enter SO-interolant mode w/o probing. GetClrDebugState(); -#endif +#endif } inline void Exception::HandlerState::CleanupTry() @@ -1396,7 +1396,7 @@ inline HRESULT IfFailThrow(HRESULT hr) inline HRESULT IfFailThrow(HRESULT hr, SString &msg) { WRAPPER_NO_CONTRACT; - + if (FAILED(hr)) { ThrowHR(hr, msg); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/factory.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/factory.h index ae618fe..36c6c81 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/factory.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/factory.h @@ -19,7 +19,7 @@ class InlineFactory : public Factory { public: InlineFactory() : m_next(NULL), m_cProduct(0) { WRAPPER_NO_CONTRACT; } - ~InlineFactory() { WRAPPER_NO_CONTRACT; if (m_next) delete m_next; } + ~InlineFactory() { WRAPPER_NO_CONTRACT; if (m_next) delete m_next; } PRODUCT* Create(); private: @@ -34,7 +34,7 @@ private: { m_next = new (nothrow) InlineFactory(); } - + return m_next; } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/factory.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/factory.inl index b49b90a..f7d0d88 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/factory.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/factory.inl @@ -12,13 +12,13 @@ PRODUCT* InlineFactory::Create() { WRAPPER_NO_CONTRACT; - if (m_cProduct == MAX_FACTORY_PRODUCT) + if (m_cProduct == MAX_FACTORY_PRODUCT) { InlineFactory* pNext = GetNext(); if (pNext) { return pNext->Create(); - } + } else { return NULL; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/fixuppointer.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/fixuppointer.h index 18886c0..22e02f2 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/fixuppointer.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/fixuppointer.h @@ -16,8 +16,8 @@ //---------------------------------------------------------------------------- // RelativePointer is pointer encoded as relative offset. It is used to reduce size of -// relocation section in NGen images. Conversion from/to RelativePointer needs -// address of the pointer ("this") converted to TADDR passed in from outside. +// relocation section in NGen images. Conversion from/to RelativePointer needs +// address of the pointer ("this") converted to TADDR passed in from outside. // Converting "this" to TADDR is not possible in the DAC transparently because // DAC is based on exact pointers, not ranges. // There are several flavors of conversions from/to RelativePointer: @@ -186,7 +186,7 @@ private: //---------------------------------------------------------------------------- // FixupPointer is pointer with optional indirection. It is used to reduce number -// of private pages in NGen images - cross-module pointers that written to at runtime +// of private pages in NGen images - cross-module pointers that written to at runtime // are packed together and accessed via indirection. // // The direct flavor (lowest bit of m_addr is cleared) is user for intra-module pointers @@ -483,7 +483,7 @@ public: } #endif // !DACCESS_COMPILE - // Returns value of the encoded pointer. Assumes that the pointer is not NULL. + // Returns value of the encoded pointer. Assumes that the pointer is not NULL. // Allows the value to be tagged. FORCEINLINE TADDR GetValueMaybeTagged(TADDR base) const { @@ -657,7 +657,7 @@ public: return m_ptr; } - // Returns value of the encoded pointer. Assumes that the pointer is not NULL. + // Returns value of the encoded pointer. Assumes that the pointer is not NULL. // Allows the value to be tagged. FORCEINLINE TADDR GetValueMaybeTagged(TADDR base) const { @@ -776,7 +776,7 @@ private: //---------------------------------------------------------------------------- // RelativePointer32 is pointer encoded as relative 32-bit offset. It is used -// to reduce both the size of the pointer itself as well as size of relocation +// to reduce both the size of the pointer itself as well as size of relocation // section for pointers that live exlusively in NGen images. template class RelativePointer32 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/formattype.cpp b/CoreCLRProfiler/native/coreclr_headers/src/inc/formattype.cpp index fcbfadf..24da3ae 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/formattype.cpp +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/formattype.cpp @@ -17,13 +17,13 @@ char* asString(CQuickBytes *out) { GC_NOTRIGGER; } CONTRACTL_END; - + SIZE_T oldSize = out->Size(); out->ReSizeThrows(oldSize + 1); - char* cur = &((char*) out->Ptr())[oldSize]; - *cur = 0; + char* cur = &((char*) out->Ptr())[oldSize]; + *cur = 0; out->ReSizeThrows(oldSize); // Don't count the null character - return((char*) out->Ptr()); + return((char*) out->Ptr()); } void appendStr(CQuickBytes *out, const char* str, unsigned len) { @@ -33,13 +33,13 @@ void appendStr(CQuickBytes *out, const char* str, unsigned len) { GC_NOTRIGGER; } CONTRACTL_END; - - if(len == (unsigned)(-1)) len = (unsigned)strlen(str); + + if(len == (unsigned)(-1)) len = (unsigned)strlen(str); SIZE_T oldSize = out->Size(); out->ReSizeThrows(oldSize + len); - char* cur = &((char*) out->Ptr())[oldSize]; - memcpy(cur, str, len); - // Note no trailing null! + char* cur = &((char*) out->Ptr())[oldSize]; + memcpy(cur, str, len); + // Note no trailing null! } void appendChar(CQuickBytes *out, char chr) { @@ -49,11 +49,11 @@ void appendChar(CQuickBytes *out, char chr) { GC_NOTRIGGER; } CONTRACTL_END; - + SIZE_T oldSize = out->Size(); - out->ReSizeThrows(oldSize + 1); - ((char*) out->Ptr())[oldSize] = chr; - // Note no trailing null! + out->ReSizeThrows(oldSize + 1); + ((char*) out->Ptr())[oldSize] = chr; + // Note no trailing null! } void insertStr(CQuickBytes *out, const char* str) { @@ -63,14 +63,14 @@ void insertStr(CQuickBytes *out, const char* str) { GC_NOTRIGGER; } CONTRACTL_END; - - unsigned len = (unsigned)strlen(str); + + unsigned len = (unsigned)strlen(str); SIZE_T oldSize = out->Size(); - out->ReSizeThrows(oldSize + len); + out->ReSizeThrows(oldSize + len); char* cur = &((char*) out->Ptr())[len]; memmove(cur,out->Ptr(),oldSize); - memcpy(out->Ptr(), str, len); - // Note no trailing null! + memcpy(out->Ptr(), str, len); + // Note no trailing null! } static void appendStrNum(CQuickBytes *out, int num) { @@ -80,25 +80,25 @@ static void appendStrNum(CQuickBytes *out, int num) { GC_NOTRIGGER; } CONTRACTL_END; - - char buff[16]; - sprintf_s(buff, COUNTOF(buff), "%d", num); - appendStr(out, buff); + + char buff[16]; + sprintf_s(buff, COUNTOF(buff), "%d", num); + appendStr(out, buff); } PCCOR_SIGNATURE PrettyPrintSignature( - PCCOR_SIGNATURE typePtr, // type to convert, - unsigned typeLen, // the lenght of 'typePtr' - const char* name, // can be "", the name of the method for this sig 0 means local var sig - CQuickBytes *out, // where to put the pretty printed string + PCCOR_SIGNATURE typePtr, // type to convert, + unsigned typeLen, // the lenght of 'typePtr' + const char* name, // can be "", the name of the method for this sig 0 means local var sig + CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig _In_opt_z_ const char* inlabel, // prefix for names (NULL if no names required) BOOL printTyArity=FALSE); PCCOR_SIGNATURE PrettyPrintTypeOrDef( - PCCOR_SIGNATURE typePtr, // type to convert, - CQuickBytes *out, // where to put the pretty printed string + PCCOR_SIGNATURE typePtr, // type to convert, + CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI); // ptr to IMDInternal class with ComSig //***************************************************************************** @@ -139,22 +139,16 @@ ULONG GetLength( // Length or -1 on error. /******************************************************************************/ const char* PrettyPrintSig( - PCCOR_SIGNATURE typePtr, // type to convert, - unsigned typeLen, // the length of 'typePtr' - const char* name, // can be "", the name of the method for this sig 0 means local var sig - CQuickBytes *out, // where to put the pretty printed string + PCCOR_SIGNATURE typePtr, // type to convert, + unsigned typeLen, // the length of 'typePtr' + const char* name, // can be "", the name of the method for this sig 0 means local var sig + CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig const char* inlabel, // prefix for names (NULL if no names required) BOOL printTyArity) { STATIC_CONTRACT_THROWS; - - // This had a _try/__except handler earlier that would swallow exceptions like - // SO and breakpoint. Obviously, swallowing any of them is not the right thing to do. - // - // Thus, we replace it with EX_TRY/EX_CATCH that automatically kicks in with SO - // handling if it sees any SO going past it. Also, C++ catch will not swallow - // the breakpoint exception (which is what we want). + EX_TRY { PrettyPrintSignature(typePtr, @@ -164,31 +158,26 @@ const char* PrettyPrintSig( pIMDI, inlabel, printTyArity); - } + } EX_CATCH { out->Shrink(0); appendStr(out,"ERROR PARSING THE SIGNATURE"); } -#if defined(__ILDASM__) - // Dont allow ildasm to swallow bad SEH exceptions - EX_END_CATCH(RethrowCorruptingExceptions); -#else // __ILDASM__ EX_END_CATCH(SwallowAllExceptions); -#endif // __ILDASM__ - return(asString(out)); + return(asString(out)); } /********************************************************************************/ // Converts a com signature to a printable signature. -// Note that return value is pointing at the CQuickBytes buffer, +// Note that return value is pointing at the CQuickBytes buffer, PCCOR_SIGNATURE PrettyPrintSignature( - PCCOR_SIGNATURE typePtr, // type to convert, - unsigned typeLen, // the lenght of 'typePtr' - const char* name, // can be "", the name of the method for this sig 0 means local var sig - CQuickBytes *out, // where to put the pretty printed string + PCCOR_SIGNATURE typePtr, // type to convert, + unsigned typeLen, // the lenght of 'typePtr' + const char* name, // can be "", the name of the method for this sig 0 means local var sig + CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig const char* inlabel, // prefix for names (NULL if no names required) BOOL printTyArity) @@ -199,7 +188,7 @@ PCCOR_SIGNATURE PrettyPrintSignature( GC_NOTRIGGER; } CONTRACTL_END; - + unsigned numArgs; unsigned numTyArgs = 0; PCCOR_SIGNATURE typeEnd = typePtr + typeLen; @@ -217,38 +206,38 @@ PCCOR_SIGNATURE PrettyPrintSignature( label[strlen(label)-1] = 0; if(label[0] == '@') // it's pointer! { -#ifdef _WIN64 +#ifdef HOST_64BIT pszArgName = (ParamDescriptor*)_atoi64(&label[1]); -#else // !_WIN64 +#else // !HOST_64BIT pszArgName = (ParamDescriptor*)(size_t)atoi(&label[1]); -#endif // _WIN64 +#endif // HOST_64BIT } } - // 0 means a local var sig + // 0 means a local var sig if (name != 0) { - // get the calling convention out - unsigned callConv = CorSigUncompressData(typePtr); + // get the calling convention out + unsigned callConv = CorSigUncompressData(typePtr); // should not be a local var sig _ASSERTE(!isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_LOCAL_SIG)); if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD)) { - typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); - if (*name) - { + typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); + if (*name) + { appendChar(out, ' '); - appendStr(out, name); - } - return(typePtr); + appendStr(out, name); + } + return(typePtr); } - if (callConv & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS) - appendStr(out, KEYWORD("explicit ")); + if (callConv & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS) + appendStr(out, KEYWORD("explicit ")); - if (callConv & IMAGE_CEE_CS_CALLCONV_HASTHIS) + if (callConv & IMAGE_CEE_CS_CALLCONV_HASTHIS) appendStr(out, KEYWORD("instance ")); if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_GENERICINST)) @@ -258,17 +247,17 @@ PCCOR_SIGNATURE PrettyPrintSignature( } else { - static const char* const callConvNames[8] = { - "", - "unmanaged cdecl ", - "unmanaged stdcall ", - "unmanaged thiscall ", - "unmanaged fastcall ", - "vararg ", - " ", - " " - }; - appendStr(out, KEYWORD(callConvNames[callConv & 7])); + static const char* const callConvNames[8] = { + "", + "unmanaged cdecl ", + "unmanaged stdcall ", + "unmanaged thiscall ", + "unmanaged fastcall ", + "vararg ", + " ", + " " + }; + appendStr(out, KEYWORD(callConvNames[callConv & 7])); } if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC) @@ -278,14 +267,14 @@ PCCOR_SIGNATURE PrettyPrintSignature( numArgs = CorSigUncompressData(typePtr); if (!isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_GENERICINST)) { - // do return type + // do return type if(pszArgName) { argname[0] = 0; DumpParamAttr(argname,COUNTOF(argname),pszArgName[ixArg+numArgs].attr); appendStr(out,argname); } - typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); + typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); if(pszArgName) { argname[0] = ' '; argname[1] = 0; @@ -294,8 +283,8 @@ PCCOR_SIGNATURE PrettyPrintSignature( } if(*name != 0) { - appendChar(out, ' '); - appendStr(out, name); + appendChar(out, ' '); + appendStr(out, name); } if((numTyArgs != 0)&&printTyArity) { @@ -307,50 +296,50 @@ PCCOR_SIGNATURE PrettyPrintSignature( } } } - else + else { - // get the calling convention out + // get the calling convention out #ifdef _DEBUG - unsigned callConv = -#endif - CorSigUncompressData(typePtr); + unsigned callConv = +#endif + CorSigUncompressData(typePtr); #ifdef _DEBUG (void)callConv; //prevent "unused variable" warning from GCC // should be a local var sig _ASSERTE(callConv == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG); #endif - numArgs = CorSigUncompressData(typePtr); + numArgs = CorSigUncompressData(typePtr); } - appendStr(out, openpar); + appendStr(out, openpar); bool needComma = false; - while(typePtr < typeEnd) + while(typePtr < typeEnd) { if(name) // printing the arguments { PREFIX_ASSUME(typePtr != NULL); - if (*typePtr == ELEMENT_TYPE_SENTINEL) + if (*typePtr == ELEMENT_TYPE_SENTINEL) { if (needComma) - appendChar(out, ','); - appendStr(out, "..."); + appendChar(out, ','); + appendStr(out, "..."); typePtr++; } - else + else { if (numArgs <= 0) break; if (needComma) - appendChar(out, ','); + appendChar(out, ','); if(pszArgName) { argname[0] = 0; DumpParamAttr(argname,COUNTOF(argname),pszArgName[ixArg].attr); appendStr(out,argname); } - typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); + typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); if(inlabel) { if(pszArgName) @@ -362,7 +351,7 @@ PCCOR_SIGNATURE PrettyPrintSignature( else sprintf_s(argname,COUNTOF(argname)," %s_%d",label,ixArg++); appendStr(out,argname); } - --numArgs; + --numArgs; } } else // printing local vars @@ -374,20 +363,20 @@ PCCOR_SIGNATURE PrettyPrintSignature( if(pszArgName[ixArg].attr == 0xFFFFFFFF) { CQuickBytes fake_out; - typePtr = PrettyPrintTypeOrDef(typePtr, &fake_out, pIMDI); + typePtr = PrettyPrintTypeOrDef(typePtr, &fake_out, pIMDI); ixArg++; numArgs--; continue; } } if (needComma) - appendChar(out, ','); + appendChar(out, ','); if(pszArgName) { sprintf_s(argname,COUNTOF(argname),"[%d] ",pszArgName[ixArg].attr); appendStr(out,argname); } - typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); + typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); if(inlabel) { if(pszArgName) @@ -397,27 +386,27 @@ PCCOR_SIGNATURE PrettyPrintSignature( else sprintf_s(argname,COUNTOF(argname)," %s_%d",label,ixArg++); appendStr(out,argname); } - --numArgs; + --numArgs; } needComma = true; } // Have we finished printing all the arguments? if (numArgs > 0) { - appendStr(out, ERRORMSG(" [SIGNATURE ENDED PREMATURELY]")); + appendStr(out, ERRORMSG(" [SIGNATURE ENDED PREMATURELY]")); } - - appendStr(out, closepar); + + appendStr(out, closepar); return(typePtr); } /******************************************************************************/ -// pretty prints 'type' or its 'typedef' to the buffer 'out' returns a pointer to the next type, -// or 0 on a format failure; outside ILDASM -- simple wrapper for PrettyPrintType +// pretty prints 'type' or its 'typedef' to the buffer 'out' returns a pointer to the next type, +// or 0 on a format failure; outside ILDASM -- simple wrapper for PrettyPrintType PCCOR_SIGNATURE PrettyPrintTypeOrDef( - PCCOR_SIGNATURE typePtr, // type to convert, - CQuickBytes *out, // where to put the pretty printed string + PCCOR_SIGNATURE typePtr, // type to convert, + CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI) // ptr to IMDInternal class with ComSig { CONTRACTL @@ -455,12 +444,12 @@ PCCOR_SIGNATURE PrettyPrintTypeOrDef( } /******************************************************************************/ -// pretty prints 'type' to the buffer 'out' returns a pointer to the next type, -// or 0 on a format failure +// pretty prints 'type' to the buffer 'out' returns a pointer to the next type, +// or 0 on a format failure PCCOR_SIGNATURE PrettyPrintType( - PCCOR_SIGNATURE typePtr, // type to convert, - CQuickBytes *out, // where to put the pretty printed string + PCCOR_SIGNATURE typePtr, // type to convert, + CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI) // ptr to IMDInternal class with ComSig { CONTRACTL @@ -469,9 +458,9 @@ PCCOR_SIGNATURE PrettyPrintType( GC_NOTRIGGER; } CONTRACTL_END; - - mdToken tk; - const char* str; + + mdToken tk; + const char* str; int typ; CQuickBytes tmp; CQuickBytes Appendix; @@ -480,76 +469,76 @@ PCCOR_SIGNATURE PrettyPrintType( do { Reiterate = FALSE; - switch(typ = *typePtr++) { - case ELEMENT_TYPE_VOID : - str = "void"; goto APPEND; - case ELEMENT_TYPE_BOOLEAN : - str = "bool"; goto APPEND; - case ELEMENT_TYPE_CHAR : - str = "char"; goto APPEND; - case ELEMENT_TYPE_I1 : - str = "int8"; goto APPEND; - case ELEMENT_TYPE_U1 : - str = "uint8"; goto APPEND; - case ELEMENT_TYPE_I2 : - str = "int16"; goto APPEND; - case ELEMENT_TYPE_U2 : - str = "uint16"; goto APPEND; - case ELEMENT_TYPE_I4 : - str = "int32"; goto APPEND; - case ELEMENT_TYPE_U4 : - str = "uint32"; goto APPEND; - case ELEMENT_TYPE_I8 : - str = "int64"; goto APPEND; - case ELEMENT_TYPE_U8 : - str = "uint64"; goto APPEND; - case ELEMENT_TYPE_R4 : - str = "float32"; goto APPEND; - case ELEMENT_TYPE_R8 : - str = "float64"; goto APPEND; - case ELEMENT_TYPE_U : - str = "native uint"; goto APPEND; - case ELEMENT_TYPE_I : - str = "native int"; goto APPEND; - case ELEMENT_TYPE_OBJECT : - str = "object"; goto APPEND; - case ELEMENT_TYPE_STRING : - str = "string"; goto APPEND; - case ELEMENT_TYPE_TYPEDBYREF : - str = "typedref"; goto APPEND; - APPEND: - appendStr(out, KEYWORD((char*)str)); - break; + switch(typ = *typePtr++) { + case ELEMENT_TYPE_VOID : + str = "void"; goto APPEND; + case ELEMENT_TYPE_BOOLEAN : + str = "bool"; goto APPEND; + case ELEMENT_TYPE_CHAR : + str = "char"; goto APPEND; + case ELEMENT_TYPE_I1 : + str = "int8"; goto APPEND; + case ELEMENT_TYPE_U1 : + str = "uint8"; goto APPEND; + case ELEMENT_TYPE_I2 : + str = "int16"; goto APPEND; + case ELEMENT_TYPE_U2 : + str = "uint16"; goto APPEND; + case ELEMENT_TYPE_I4 : + str = "int32"; goto APPEND; + case ELEMENT_TYPE_U4 : + str = "uint32"; goto APPEND; + case ELEMENT_TYPE_I8 : + str = "int64"; goto APPEND; + case ELEMENT_TYPE_U8 : + str = "uint64"; goto APPEND; + case ELEMENT_TYPE_R4 : + str = "float32"; goto APPEND; + case ELEMENT_TYPE_R8 : + str = "float64"; goto APPEND; + case ELEMENT_TYPE_U : + str = "native uint"; goto APPEND; + case ELEMENT_TYPE_I : + str = "native int"; goto APPEND; + case ELEMENT_TYPE_OBJECT : + str = "object"; goto APPEND; + case ELEMENT_TYPE_STRING : + str = "string"; goto APPEND; + case ELEMENT_TYPE_TYPEDBYREF : + str = "typedref"; goto APPEND; + APPEND: + appendStr(out, KEYWORD((char*)str)); + break; - case ELEMENT_TYPE_VALUETYPE : - str = "valuetype "; - goto DO_CLASS; - case ELEMENT_TYPE_CLASS : - str = "class "; - goto DO_CLASS; + case ELEMENT_TYPE_VALUETYPE : + str = "valuetype "; + goto DO_CLASS; + case ELEMENT_TYPE_CLASS : + str = "class "; + goto DO_CLASS; DO_CLASS: appendStr(out, KEYWORD((char*)str)); - typePtr += CorSigUncompressToken(typePtr, &tk); + typePtr += CorSigUncompressToken(typePtr, &tk); if(IsNilToken(tk)) { appendStr(out, "[ERROR! NIL TOKEN]"); } else PrettyPrintClass(out, tk, pIMDI); REGISTER_REF(g_tkRefUser,tk) - break; + break; - case ELEMENT_TYPE_SZARRAY : + case ELEMENT_TYPE_SZARRAY : insertStr(&Appendix,"[]"); Reiterate = TRUE; break; - - case ELEMENT_TYPE_ARRAY : - { + + case ELEMENT_TYPE_ARRAY : + { typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); PREFIX_ASSUME(typePtr != NULL); - unsigned rank = CorSigUncompressData(typePtr); - // what is the syntax for the rank 0 case? + unsigned rank = CorSigUncompressData(typePtr); + // what is the syntax for the rank 0 case? if (rank == 0) { appendStr(out, ERRORMSG("[BAD: RANK == 0!]")); } @@ -561,53 +550,53 @@ PCCOR_SIGNATURE PrettyPrintType( #pragma prefast(disable:22009 "Suppress PREFAST warnings about integer overflow") #endif int* lowerBounds = (int*) _alloca(sizeof(int)*2*rank); - int* sizes = &lowerBounds[rank]; - memset(lowerBounds, 0, sizeof(int)*2*rank); - - unsigned numSizes = CorSigUncompressData(typePtr); + int* sizes = &lowerBounds[rank]; + memset(lowerBounds, 0, sizeof(int)*2*rank); + + unsigned numSizes = CorSigUncompressData(typePtr); _ASSERTE(numSizes <= rank); unsigned i; for(i =0; i < numSizes; i++) - sizes[i] = CorSigUncompressData(typePtr); - - unsigned numLowBounds = CorSigUncompressData(typePtr); - _ASSERTE(numLowBounds <= rank); - for(i = 0; i < numLowBounds; i++) - typePtr+=CorSigUncompressSignedInt(typePtr,&lowerBounds[i]); - - appendChar(out, '['); + sizes[i] = CorSigUncompressData(typePtr); + + unsigned numLowBounds = CorSigUncompressData(typePtr); + _ASSERTE(numLowBounds <= rank); + for(i = 0; i < numLowBounds; i++) + typePtr+=CorSigUncompressSignedInt(typePtr,&lowerBounds[i]); + + appendChar(out, '['); if (rank == 1 && numSizes == 0 && numLowBounds == 0) - appendStr(out, "..."); + appendStr(out, "..."); else { - for(i = 0; i < rank; i++) - { - //if (sizes[i] != 0 || lowerBounds[i] != 0) - { - if (lowerBounds[i] == 0 && i < numSizes) - appendStrNum(out, sizes[i]); - else - { + for(i = 0; i < rank; i++) + { + //if (sizes[i] != 0 || lowerBounds[i] != 0) + { + if (lowerBounds[i] == 0 && i < numSizes) + appendStrNum(out, sizes[i]); + else + { if(i < numLowBounds) { - appendStrNum(out, lowerBounds[i]); - appendStr(out, "..."); - if (/*sizes[i] != 0 && */i < numSizes) - appendStrNum(out, lowerBounds[i] + sizes[i] - 1); + appendStrNum(out, lowerBounds[i]); + appendStr(out, "..."); + if (/*sizes[i] != 0 && */i < numSizes) + appendStrNum(out, lowerBounds[i] + sizes[i] - 1); } - } - } - if (i < rank-1) - appendChar(out, ','); - } + } + } + if (i < rank-1) + appendChar(out, ','); + } } - appendChar(out, ']'); + appendChar(out, ']'); #ifdef _PREFAST_ #pragma prefast(pop) #endif } - } break; + } break; - case ELEMENT_TYPE_VAR : + case ELEMENT_TYPE_VAR : appendChar(out, '!'); n = CorSigUncompressData(typePtr); #ifdef __ILDASM__ @@ -616,9 +605,9 @@ PCCOR_SIGNATURE PrettyPrintType( appendStrNum(out, n); break; - case ELEMENT_TYPE_MVAR : - appendChar(out, '!'); - appendChar(out, '!'); + case ELEMENT_TYPE_MVAR : + appendChar(out, '!'); + appendChar(out, '!'); n = CorSigUncompressData(typePtr); #ifdef __ILDASM__ if(!PrettyPrintGP(g_tkMVarOwner,out,n)) @@ -626,31 +615,31 @@ PCCOR_SIGNATURE PrettyPrintType( appendStrNum(out, n); break; - case ELEMENT_TYPE_FNPTR : - appendStr(out, KEYWORD("method ")); + case ELEMENT_TYPE_FNPTR : + appendStr(out, KEYWORD("method ")); typePtr = PrettyPrintSignature(typePtr, 0x7FFF, "*", out, pIMDI, NULL); break; case ELEMENT_TYPE_GENERICINST : { typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); - appendStr(out, LTN()); - unsigned numArgs = CorSigUncompressData(typePtr); + appendStr(out, LTN()); + unsigned numArgs = CorSigUncompressData(typePtr); bool needComma = false; while(numArgs--) { if (needComma) - appendChar(out, ','); - typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); + appendChar(out, ','); + typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); needComma = true; } - appendStr(out, GTN()); + appendStr(out, GTN()); break; } #ifndef __ILDASM__ case ELEMENT_TYPE_INTERNAL : - { + { // ELEMENT_TYPE_INTERNAL _ASSERTE(sizeof(TypeHandle) == sizeof(void *)); TypeHandle typeHandle; @@ -674,12 +663,12 @@ PCCOR_SIGNATURE PrettyPrintType( else { pMT = typeHandle.AsMethodTable(); - if (pMT) - PrettyPrintClass(out, pMT->GetCl(), pMT->GetMDImport()); + if (pMT) + PrettyPrintClass(out, pMT->GetCl(), pMT->GetMDImport()); else appendStr(out, "(null)"); } - + char sz[32]; if(IsCompilationProcess()) { @@ -692,16 +681,16 @@ PCCOR_SIGNATURE PrettyPrintType( appendStr(out, sz); break; } -#endif - - - // Modifiers or depedent types +#endif + + + // Modifiers or depedent types case ELEMENT_TYPE_CMOD_OPT : - str = " modopt("; goto ADDCLASSTOCMOD; + str = " modopt("; goto ADDCLASSTOCMOD; case ELEMENT_TYPE_CMOD_REQD : str = " modreq("; ADDCLASSTOCMOD: - typePtr += CorSigUncompressToken(typePtr, &tk); + typePtr += CorSigUncompressToken(typePtr, &tk); if (IsNilToken(tk)) { Debug_ReportError("Nil token in custom modifier"); @@ -714,18 +703,18 @@ PCCOR_SIGNATURE PrettyPrintType( goto MODIFIER; case ELEMENT_TYPE_PINNED : str = " pinned"; goto MODIFIER; - case ELEMENT_TYPE_PTR : - str = "*"; goto MODIFIER; - case ELEMENT_TYPE_BYREF : - str = AMP(); goto MODIFIER; + case ELEMENT_TYPE_PTR : + str = "*"; goto MODIFIER; + case ELEMENT_TYPE_BYREF : + str = AMP(); goto MODIFIER; MODIFIER: insertStr(&Appendix, str); Reiterate = TRUE; - break; + break; - default: - case ELEMENT_TYPE_SENTINEL : - case ELEMENT_TYPE_END : + default: + case ELEMENT_TYPE_SENTINEL : + case ELEMENT_TYPE_END : //_ASSERTE(!"Unknown Type"); if(typ) { @@ -733,17 +722,17 @@ PCCOR_SIGNATURE PrettyPrintType( sprintf_s(sz,COUNTOF(sz),"/* UNKNOWN TYPE (0x%X)*/",typ); appendStr(out, ERRORMSG(sz)); } - break; + break; } // end switch } while(Reiterate); appendStr(out,asString(&Appendix)); - return(typePtr); + return(typePtr); } /******************************************************************/ const char* PrettyPrintClass( - CQuickBytes *out, // where to put the pretty printed string - mdToken tk, // The class token to look up + CQuickBytes *out, // where to put the pretty printed string + mdToken tk, // The class token to look up IMDInternalImport *pIMDI) // ptr to IMDInternalImport class with ComSig { CONTRACTL @@ -752,7 +741,7 @@ const char* PrettyPrintClass( GC_NOTRIGGER; } CONTRACTL_END; - + if(tk == mdTokenNil) // Zero resolution scope for "somewhere here" TypeRefs { appendStr(out,"[*]"); @@ -782,10 +771,10 @@ const char* PrettyPrintClass( else #endif { - const char *nameSpace = 0; + const char *nameSpace = 0; const char *name = 0; mdToken tkEncloser; - + if (TypeFromToken(tk) == mdtTypeRef) { if (FAILED(pIMDI->GetResolutionScopeOfTypeRef(tk, &tkEncloser))) @@ -797,7 +786,7 @@ const char* PrettyPrintClass( nameSpace = name = "Invalid TypeRef record"; } } - else + else { if (FAILED(pIMDI->GetNestedClassProps(tk,&tkEncloser))) { @@ -814,7 +803,7 @@ const char* PrettyPrintClass( PrettyPrintClass(out,tkEncloser,pIMDI); if (TypeFromToken(tkEncloser) == mdtTypeRef || TypeFromToken(tkEncloser) == mdtTypeDef) { - appendChar(out, '/'); + appendChar(out, '/'); //nameSpace = ""; //don't print namespaces for nested classes! } } @@ -841,8 +830,8 @@ const char* PrettyPrintClass( else { if (nameSpace && *nameSpace) { - appendStr(out, ProperName(nameSpace)); - appendChar(out, '.'); + appendStr(out, ProperName(nameSpace)); + appendChar(out, '.'); } appendStr(out, ProperName(name)); @@ -864,7 +853,7 @@ const char* PrettyPrintClass( { szName = rAsmRefName[RidFromToken(tk)-1]; } - else + else #endif { if (FAILED(pIMDI->GetAssemblyRefProps(tk,NULL,NULL,&szName,NULL,NULL,NULL,NULL))) @@ -882,7 +871,7 @@ const char* PrettyPrintClass( sprintf_s(tmp,COUNTOF(tmp),"/*%08X*/",tk); appendStr(out,COMMENT(tmp)); } - appendChar(out, ']'); + appendChar(out, ']'); } } break; @@ -895,7 +884,7 @@ const char* PrettyPrintClass( } if ((szName != NULL) && ((*szName) != 0)) { - appendChar(out, '['); + appendChar(out, '['); appendStr(out,JUMPPT(ProperName(szName),tk)); if(g_fDumpTokens) { @@ -903,7 +892,7 @@ const char* PrettyPrintClass( sprintf_s(tmp,COUNTOF(tmp),"/* %08X */",tk); appendStr(out,COMMENT(tmp)); } - appendChar(out, ']'); + appendChar(out, ']'); } } break; @@ -916,7 +905,7 @@ const char* PrettyPrintClass( } if ((szName != NULL) && ((*szName) != 0)) { - appendChar(out, '['); + appendChar(out, '['); appendStr(out,KEYWORD(".module ")); appendStr(out,JUMPPT(ProperName(szName),tk)); if(g_fDumpTokens) @@ -925,7 +914,7 @@ const char* PrettyPrintClass( sprintf_s(tmp,COUNTOF(tmp),"/*%08X*/",tk); appendStr(out,COMMENT(tmp)); } - appendChar(out, ']'); + appendChar(out, ']'); } } break; @@ -969,7 +958,7 @@ const char* PrettyPrintClass( case mdtModule: break; - + default: { char str[128]; @@ -981,7 +970,7 @@ const char* PrettyPrintClass( } const char* TrySigUncompressAndDumpSimpleNativeType( - PCCOR_SIGNATURE pData, // [IN] compressed data + PCCOR_SIGNATURE pData, // [IN] compressed data ULONG *pDataOut, // [OUT] the expanded *pData ULONG &cbCur, SString &buf) @@ -1027,7 +1016,7 @@ const char* TrySigUncompressAndDumpSimpleNativeType( case NATIVE_TYPE_ASANY: sz = " as any"; break; case NATIVE_TYPE_LPSTRUCT: sz = " lpstruct"; break; case NATIVE_TYPE_PTR: - case NATIVE_TYPE_SAFEARRAY: + case NATIVE_TYPE_SAFEARRAY: case NATIVE_TYPE_ARRAY: case NATIVE_TYPE_FIXEDSYSSTRING: case NATIVE_TYPE_FIXEDARRAY: @@ -1049,7 +1038,7 @@ const char* TrySigUncompressAndDumpSimpleNativeType( return sz; } -bool TrySigUncompress(PCCOR_SIGNATURE pData, // [IN] compressed data +bool TrySigUncompress(PCCOR_SIGNATURE pData, // [IN] compressed data ULONG *pDataOut, // [OUT] the expanded *pData ULONG &cbCur, SString &buf) @@ -1071,9 +1060,9 @@ bool TrySigUncompress(PCCOR_SIGNATURE pData, // [IN] compressed dat #pragma warning(push) #pragma warning(disable:21000) // Suppress PREFast warning about overly large function #endif -char* DumpMarshaling(IMDInternalImport* pImport, - __inout_ecount(cchszString) char* szString, - DWORD cchszString, +char* DumpMarshaling(IMDInternalImport* pImport, + __inout_ecount(cchszString) char* szString, + DWORD cchszString, mdToken tok) { CONTRACTL @@ -1086,7 +1075,7 @@ char* DumpMarshaling(IMDInternalImport* pImport, PCCOR_SIGNATURE pSigNativeType = NULL; ULONG cbNativeType = 0; SString buf; - if (RidFromToken(tok) && + if (RidFromToken(tok) && SUCCEEDED(pImport->GetFieldMarshal( // return error if no native type associate with the token tok, // [IN] given fielddef &pSigNativeType, // [OUT] the native type signature @@ -1111,7 +1100,7 @@ char* DumpMarshaling(IMDInternalImport* pImport, sz = ""; fAddAsterisk = TRUE; break; - case NATIVE_TYPE_SAFEARRAY: + case NATIVE_TYPE_SAFEARRAY: sz = ""; buf.AppendASCII(KEYWORD(" safearray")); ulData = VT_EMPTY; @@ -1166,7 +1155,7 @@ char* DumpMarshaling(IMDInternalImport* pImport, default: sz=NULL; break; } if(sz) buf.AppendASCII(KEYWORD(sz)); - else + else { // buf.AppendPrintf(ERRORMSG(" [ILLEGAL VARIANT TYPE 0x%X]"),ulData & VT_TYPEMASK); buf.Clear(); @@ -1177,11 +1166,11 @@ char* DumpMarshaling(IMDInternalImport* pImport, { case VT_ARRAY: sz = "[]"; break; case VT_VECTOR: sz = " vector"; break; - case VT_BYREF: sz = "&"; break; - case VT_BYREF|VT_ARRAY: sz = "&[]"; break; - case VT_BYREF|VT_VECTOR: sz = "& vector"; break; - case VT_ARRAY|VT_VECTOR: sz = "[] vector"; break; - case VT_BYREF|VT_ARRAY|VT_VECTOR: sz = "&[] vector"; break; + case VT_BYREF: sz = "&"; break; + case VT_BYREF|VT_ARRAY: sz = "&[]"; break; + case VT_BYREF|VT_VECTOR: sz = "& vector"; break; + case VT_ARRAY|VT_VECTOR: sz = "[] vector"; break; + case VT_BYREF|VT_ARRAY|VT_VECTOR: sz = "&[] vector"; break; } buf.AppendASCII(KEYWORD(sz)); sz=""; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/formattype.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/formattype.h index 31a17e0..16e72ae 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/formattype.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/formattype.h @@ -24,12 +24,12 @@ struct ParamDescriptor DWORD attr; }; -char* DumpMarshaling(IMDInternalImport* pImport, - __inout_ecount(cchszString) char* szString, - DWORD cchszString, +char* DumpMarshaling(IMDInternalImport* pImport, + __inout_ecount(cchszString) char* szString, + DWORD cchszString, mdToken tok); -char* DumpParamAttr(__inout_ecount(cchszString) char* szString, - DWORD cchszString, +char* DumpParamAttr(__inout_ecount(cchszString) char* szString, + DWORD cchszString, DWORD dwAttr); void appendStr(CQuickBytes *out, const char* str, unsigned len=(unsigned)-1); @@ -37,28 +37,28 @@ void insertStr(CQuickBytes *out, const char* str); char* asString(CQuickBytes *out); const char* PrettyPrintSig( - PCCOR_SIGNATURE typePtr, // type to convert, - unsigned typeLen, // the lenght of 'typePtr' - const char* name, // can be "", the name of the method for this sig 0 means local var sig - CQuickBytes *out, // where to put the pretty printed string + PCCOR_SIGNATURE typePtr, // type to convert, + unsigned typeLen, // the lenght of 'typePtr' + const char* name, // can be "", the name of the method for this sig 0 means local var sig + CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig __in_opt const char* inlabel, // prefix for names (NULL if no names required) BOOL printTyArity=FALSE); // flag to print Type Param number (MemberRefs only) PCCOR_SIGNATURE PrettyPrintType( - PCCOR_SIGNATURE typePtr, // type to convert, - CQuickBytes *out, // where to put the pretty printed string + PCCOR_SIGNATURE typePtr, // type to convert, + CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI); // ptr to IMDInternal class with ComSig PCCOR_SIGNATURE PrettyPrintTypeOrDef( // outside ILDASM - simple wrapper of PrettyPrintType - PCCOR_SIGNATURE typePtr, // type to convert, - CQuickBytes *out, // where to put the pretty printed string + PCCOR_SIGNATURE typePtr, // type to convert, + CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI); // ptr to IMDInternal class with ComSig const char* PrettyPrintClass( - CQuickBytes *out, // where to put the pretty printed string - mdToken tk, // The class token to look up + CQuickBytes *out, // where to put the pretty printed string + mdToken tk, // The class token to look up IMDInternalImport *pIMDI); // ptr to IMDInternalImport class with ComSig //================= ILDASM-specific ================================================================== @@ -97,7 +97,7 @@ inline BOOL IsDup(mdToken tk) mdToken tktype = TypeFromToken(tk); if((tktype==mdtTypeDef)||(tktype==mdtMethodDef)||(tktype==mdtFieldDef)) { - for (unsigned i=0; i +#include class CFileStream : public IStream { @@ -25,7 +25,7 @@ class CFileStream : public IStream // ISequentialStream methods: STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead); STDMETHODIMP Write(void const *pv, ULONG cb, ULONG *pcbWritten); - + // IStream methods: STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition); STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize); @@ -43,7 +43,7 @@ class CFileStream : public IStream private: LONG _cRef; HANDLE _hFile; - + }; #endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/fstring.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/fstring.h index 9245885..88377a8 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/fstring.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/fstring.h @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. // --------------------------------------------------------------------------- // FString.h (Fast String) -// +// // --------------------------------------------------------------------------- diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/fusion.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/fusion.idl index 4056d16..742148f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/fusion.idl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/fusion.idl @@ -32,32 +32,10 @@ cpp_quote("#pragma once") cpp_quote("#endif") -interface IAssemblyCache; -interface IAssemblyCacheItem; -interface IAssemblyName; -interface IAssemblyEnum; - - -cpp_quote("#ifndef PEKIND_ENUM_DEFINED") -cpp_quote("#define PEKIND_ENUM_DEFINED") -// This must match the definition of pekind in peinformation.h -typedef enum _tagPEKIND -{ - peNone = 0x00000000, - peMSIL = 0x00000001, - peI386 = 0x00000002, - peIA64 = 0x00000003, - peAMD64 = 0x00000004, - peARM = 0x00000005, - peARM64 = 0x00000006, - peInvalid = 0xffffffff -} PEKIND; -cpp_quote("#endif") - typedef enum _tagAssemblyContentType { - AssemblyContentType_Default = 0x00000000, - AssemblyContentType_WindowsRuntime = 0x00000001, + AssemblyContentType_Default = 0x00000000, + AssemblyContentType_WindowsRuntime = 0x00000001, AssemblyContentType_Invalid = 0xffffffff } AssemblyContentType; @@ -81,14 +59,7 @@ cpp_quote("EXTERN_GUID(IID_IAssemblyName, 0xCD193BC0, 0xB4BC, 0x11d2, 0x98, 0x33 interface IAssemblyName: IUnknown { typedef [unique] IAssemblyName *LPASSEMBLYNAME; - - typedef enum { - CANOF_PARSE_DISPLAY_NAME = 0x1, - CANOF_SET_DEFAULT_VALUES = 0x2, - CANOF_VERIFY_FRIEND_ASSEMBLYNAME = 0x4, - CANOF_PARSE_FRIEND_DISPLAY_NAME = CANOF_PARSE_DISPLAY_NAME | CANOF_VERIFY_FRIEND_ASSEMBLYNAME - } CREATE_ASM_NAME_OBJ_FLAGS; - + typedef enum { ASM_NAME_PUBLIC_KEY = 0, // 0 @@ -122,24 +93,24 @@ interface IAssemblyName: IUnknown ASM_NAME_CONTENT_TYPE, // 28 ... 0x1c ASM_NAME_MAX_PARAMS // 29 ... 0x1d } ASM_NAME; - + typedef enum { - ASM_DISPLAYF_VERSION = 0x1, - ASM_DISPLAYF_CULTURE = 0x2, - ASM_DISPLAYF_PUBLIC_KEY_TOKEN = 0x4, - ASM_DISPLAYF_PUBLIC_KEY = 0x8, - ASM_DISPLAYF_CUSTOM = 0x10, - ASM_DISPLAYF_PROCESSORARCHITECTURE = 0x20, - ASM_DISPLAYF_LANGUAGEID = 0x40, - ASM_DISPLAYF_RETARGET = 0x80, - ASM_DISPLAYF_CONFIG_MASK = 0x100, - ASM_DISPLAYF_MVID = 0x200, - ASM_DISPLAYF_CONTENT_TYPE = 0x400, + ASM_DISPLAYF_VERSION = 0x1, + ASM_DISPLAYF_CULTURE = 0x2, + ASM_DISPLAYF_PUBLIC_KEY_TOKEN = 0x4, + ASM_DISPLAYF_PUBLIC_KEY = 0x8, + ASM_DISPLAYF_CUSTOM = 0x10, + ASM_DISPLAYF_PROCESSORARCHITECTURE = 0x20, + ASM_DISPLAYF_LANGUAGEID = 0x40, + ASM_DISPLAYF_RETARGET = 0x80, + ASM_DISPLAYF_CONFIG_MASK = 0x100, + ASM_DISPLAYF_MVID = 0x200, + ASM_DISPLAYF_CONTENT_TYPE = 0x400, + - // ASM_DISPLAYF_FULL shows the full identity of the assembly. - // It should be used when you are working with APIs taking + // It should be used when you are working with APIs taking // assembly full identity, such as GAC APIs. // // WARNING!!! ASM_DISPLAYF_FULL will change in the future, @@ -153,90 +124,19 @@ interface IAssemblyName: IUnknown | ASM_DISPLAYF_PROCESSORARCHITECTURE | ASM_DISPLAYF_CONTENT_TYPE, } ASM_DISPLAY_FLAGS; - - typedef enum - { - ASM_CMPF_NAME = 0x1, - - ASM_CMPF_MAJOR_VERSION = 0x2, - ASM_CMPF_MINOR_VERSION = 0x4, - ASM_CMPF_BUILD_NUMBER = 0x8, - ASM_CMPF_REVISION_NUMBER = 0x10, - - ASM_CMPF_VERSION = ASM_CMPF_MAJOR_VERSION - |ASM_CMPF_MINOR_VERSION - |ASM_CMPF_BUILD_NUMBER - |ASM_CMPF_REVISION_NUMBER, - - ASM_CMPF_PUBLIC_KEY_TOKEN = 0x20, - ASM_CMPF_CULTURE = 0x40, - ASM_CMPF_CUSTOM = 0x80, - - ASM_CMPF_DEFAULT = 0x100, - - ASM_CMPF_RETARGET = 0x200, - ASM_CMPF_ARCHITECTURE = 0x400, - ASM_CMPF_CONFIG_MASK = 0x800, - ASM_CMPF_MVID = 0x1000, - ASM_CMPF_SIGNATURE = 0x2000, - ASM_CMPF_CONTENT_TYPE = 0x4000, - - ASM_CMPF_IL_ALL = ASM_CMPF_NAME - | ASM_CMPF_VERSION - | ASM_CMPF_PUBLIC_KEY_TOKEN - | ASM_CMPF_CULTURE, - - ASM_CMPF_IL_NO_VERSION = ASM_CMPF_NAME - | ASM_CMPF_PUBLIC_KEY_TOKEN - | ASM_CMPF_CULTURE - } ASM_CMP_FLAGS; HRESULT SetProperty( - [in] DWORD PropertyId, + [in] DWORD PropertyId, [in] void const * pvProperty, [in] DWORD cbProperty); HRESULT GetProperty( - [in] DWORD PropertyId, + [in] DWORD PropertyId, [out] LPVOID pvProperty, [in, out] LPDWORD pcbProperty); - HRESULT Finalize(); - - HRESULT GetDisplayName( - [out, annotation("_Out_writes_opt_(*pccDisplayName)")] - LPOLESTR szDisplayName, - [in, out] LPDWORD pccDisplayName, - [in] DWORD dwDisplayFlags); - - HRESULT Reserved( - [in] REFIID refIID, - [in] IUnknown *pUnkReserved1, - [in] IUnknown *pUnkReserved2, - [in] LPCOLESTR szReserved, - [in] LONGLONG llReserved, - [in] LPVOID pvReserved, - [in] DWORD cbReserved, - [out] LPVOID *ppReserved); - - HRESULT GetName( [in, out, annotation("_Inout_")] LPDWORD lpcwBuffer, [out, annotation("_Out_writes_opt_(*lpcwBuffer)")] WCHAR *pwzName); - - HRESULT GetVersion( - [out] LPDWORD pdwVersionHi, - [out] LPDWORD pdwVersionLow); - - HRESULT IsEqual( - [in] IAssemblyName *pName, - [in] DWORD dwCmpFlags); - - HRESULT Clone( - [out] IAssemblyName **pName); - } - -#pragma midl_echo("STDAPI CreateAssemblyNameObject(LPASSEMBLYNAME *ppAssemblyNameObj, LPCWSTR szAssemblyName, DWORD dwFlags, LPVOID pvReserved); ") - diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcdecoder.cpp b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcdecoder.cpp index ed3f1f3..5b7dc5b 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcdecoder.cpp +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcdecoder.cpp @@ -19,7 +19,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // See: https://github.com/dotnet/diagnostics/blob/master/src/inc/gcdecoder.cpp // ****************************************************************************** -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 /* This file is shared between the VM and JIT/IL and SOS/Strike directories */ @@ -196,7 +196,6 @@ PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, UINT32 version, InfoHdr* header header->syncStartOffset ^= HAS_SYNC_OFFSET; break; case FLIP_REV_PINVOKE_FRAME: - _ASSERTE(GCInfoEncodesRevPInvokeFrame(version)); header->revPInvokeOffset ^= HAS_REV_PINVOKE_FRAME_OFFSET; break; @@ -206,15 +205,8 @@ PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, UINT32 version, InfoHdr* header encoding = nextByte & ADJ_ENCODING_MAX; // encoding here always corresponds to codes in InfoHdrAdjust2 set - if (encoding < SET_RET_KIND_MAX) - { - _ASSERTE(GCInfoEncodesReturnKind(version)); - header->returnKind = (ReturnKind)encoding; - } - else - { - assert(!"Unexpected encoding"); - } + _ASSERTE(encoding < SET_RET_KIND_MAX); + header->returnKind = (ReturnKind)encoding; break; } } @@ -476,7 +468,7 @@ bool InfoHdrSmall::isHeaderMatch(const InfoHdr& target) const _ASSERTE(target.untrackedCnt != HAS_UNTRACKED && target.varPtrTableSize != HAS_VARPTR && target.gsCookieOffset != HAS_GS_COOKIE_OFFSET && - target.syncStartOffset != HAS_SYNC_OFFSET && + target.syncStartOffset != HAS_SYNC_OFFSET && target.revPInvokeOffset != HAS_REV_PINVOKE_FRAME_OFFSET); #endif @@ -490,7 +482,7 @@ bool InfoHdrSmall::isHeaderMatch(const InfoHdr& target) const else if (untrackedCnt != HAS_UNTRACKED) return false; } - + if (varPtrTableSize != target.varPtrTableSize) { if ((varPtrTableSize != 0) != (target.varPtrTableSize != 0)) return false; @@ -530,7 +522,7 @@ const unsigned callCommonDelta[4] = { 6,8,10,12 }; * * Note that ARG_MASK is the mask of pushed args that contain GC pointers * since the first two arguments are always passed in registers it is - * a fairly rare occurance to push a GC pointer as an argument, since it + * a fairly rare occurrence to push a GC pointer as an argument, since it * only occurs for nested calls, when the third or later argument for the * outer call contains a GC ref. * @@ -621,4 +613,4 @@ const unsigned callPatternTable[80] = { // # of occurences 0x07000300, // 1684 }; -#endif // _TARGET_X86_ +#endif // TARGET_X86 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcdump.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcdump.h index 3271ca1..7fada85 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcdump.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcdump.h @@ -5,8 +5,8 @@ /***************************************************************************** * GCDump.h * - * Defines functions to display the GCInfo as defined by the GC-encoding - * spec. The GC information may be either dynamically created by a + * Defines functions to display the GCInfo as defined by the GC-encoding + * spec. The GC information may be either dynamically created by a * Just-In-Time compiler conforming to the standard code-manager spec, * or may be persisted by a managed native code compiler conforming * to the standard code-manager spec. @@ -20,7 +20,7 @@ #include "gcinfotypes.h" // For InfoHdr #ifndef FASTCALL -#ifndef FEATURE_PAL +#ifndef TARGET_UNIX #define FASTCALL __fastcall #else #define FASTCALL @@ -33,11 +33,11 @@ class GCDump public: GCDump (UINT32 gcInfoVersion, - bool encBytes = true, - unsigned maxEncBytes = 5, + bool encBytes = true, + unsigned maxEncBytes = 5, bool dumpCodeOffs = true); -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 /*------------------------------------------------------------------------- * Dumps the InfoHdr to 'stdout' * table : Start of the GC info block @@ -59,7 +59,7 @@ public: */ size_t FASTCALL DumpGCTable (PTR_CBYTE gcInfoBlock, -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 const InfoHdr& header, #endif unsigned methodSize, @@ -78,7 +78,7 @@ public: public: typedef void (*printfFtn)(const char* fmt, ...); - printfFtn gcPrintf; + printfFtn gcPrintf; UINT32 gcInfoVersion; //------------------------------------------------------------------------- protected: diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfo.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfo.h index acdfe65..6d623f2 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfo.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfo.h @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. // ****************************************************************************** -// WARNING!!!: These values are used by SOS in the diagnostics repo. Values should +// WARNING!!!: These values are used by SOS in the diagnostics repo. Values should // added or removed in a backwards and forwards compatible way. // See: https://github.com/dotnet/diagnostics/blob/master/src/inc/gcinfo.h // ****************************************************************************** @@ -31,7 +31,7 @@ const unsigned OFFSET_MASK = 0x3; // mask to access the low 2 bits // const unsigned byref_OFFSET_FLAG = 0x1; // the offset is an interior ptr const unsigned pinned_OFFSET_FLAG = 0x2; // the offset is a pinned ptr -#if !defined(_TARGET_X86_) || !defined(WIN64EXCEPTIONS) +#if !defined(TARGET_X86) || !defined(FEATURE_EH_FUNCLETS) const unsigned this_OFFSET_FLAG = 0x2; // the offset is "this" #endif @@ -41,19 +41,6 @@ const unsigned this_OFFSET_FLAG = 0x2; // the offset is "this" #define GCINFO_VERSION 2 -#define MIN_GCINFO_VERSION_WITH_RETURN_KIND 2 -#define MIN_GCINFO_VERSION_WITH_REV_PINVOKE_FRAME 2 - -inline BOOL GCInfoEncodesReturnKind(UINT32 version=GCINFO_VERSION) -{ - return version >= MIN_GCINFO_VERSION_WITH_RETURN_KIND; -} - -inline BOOL GCInfoEncodesRevPInvokeFrame(UINT32 version=GCINFO_VERSION) -{ - return version >= MIN_GCINFO_VERSION_WITH_REV_PINVOKE_FRAME; -} - //----------------------------------------------------------------------------- // GCInfoToken: A wrapper that contains the GcInfo data and version number. // @@ -65,7 +52,7 @@ inline BOOL GCInfoEncodesRevPInvokeFrame(UINT32 version=GCINFO_VERSION) // 1) The current GCINFO_VERSION for JITted and Ngened images // 2) A function of the Ready - to - run major version stored in READYTORUN_HEADER // for ready - to - run images.ReadyToRunJitManager::JitTokenToGCInfoVersion() -// provides the GcInfo version for any Method. +// provides the GcInfo version for any Method. //----------------------------------------------------------------------------- struct GCInfoToken @@ -73,20 +60,10 @@ struct GCInfoToken PTR_VOID Info; UINT32 Version; - BOOL IsReturnKindAvailable() - { - return GCInfoEncodesReturnKind(Version); - } - BOOL IsReversePInvokeFrameAvailable() - { - return GCInfoEncodesRevPInvokeFrame(Version); - } - static UINT32 ReadyToRunVersionToGcInfoVersion(UINT32 readyToRunMajorVersion) { - // GcInfo version is 1 up to ReadyTorun version 1.x // GcInfo version is current from ReadyToRun version 2.0 - return (readyToRunMajorVersion == 1) ? 1 : GCINFO_VERSION; + return GCINFO_VERSION; } }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfoarraylist.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfoarraylist.h index c19f00d..aa9d856 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfoarraylist.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfoarraylist.h @@ -27,7 +27,7 @@ protected: protected: IteratorBase(GcInfoArrayListBase* list, size_t firstChunkCapacity); ChunkBase* GetNextChunk(size_t& elementCount); - + private: GcInfoArrayListBase* m_list; ChunkBase* m_currentChunk; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfodecoder.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfodecoder.h index dfaa3b1..8f63cf2 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfodecoder.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfodecoder.h @@ -9,7 +9,7 @@ *****************************************************************/ // ****************************************************************************** -// WARNING!!!: These values are used by SOS in the diagnostics repo. Values should +// WARNING!!!: These values are used by SOS in the diagnostics repo. Values should // added or removed in a backwards and forwards compatible way. // See: https://github.com/dotnet/diagnostics/blob/master/src/inc/gcinfodecoder.h // ****************************************************************************** @@ -17,10 +17,10 @@ #ifndef _GC_INFO_DECODER_ #define _GC_INFO_DECODER_ -#define _max(a, b) (((a) > (b)) ? (a) : (b)) +#define _max(a, b) (((a) > (b)) ? (a) : (b)) #define _min(a, b) (((a) < (b)) ? (a) : (b)) -#if !defined(_TARGET_X86_) +#if !defined(TARGET_X86) #define USE_GC_INFO_DECODER #endif @@ -70,24 +70,24 @@ inline void SetIP(T_CONTEXT* context, PCODE rip) inline TADDR GetSP(T_CONTEXT* context) { -#ifdef _TARGET_AMD64_ +#ifdef TARGET_AMD64 return (TADDR)context->Rsp; -#elif defined(_TARGET_ARM_) +#elif defined(TARGET_ARM) return (TADDR)context->Sp; -#elif defined(_TARGET_ARM64_) +#elif defined(TARGET_ARM64) return (TADDR)context->Sp; #else _ASSERTE(!"nyi for platform"); #endif } -inline PCODE GetIP(T_CONTEXT* context) +inline PCODE GetIP(T_CONTEXT* context) { -#ifdef _TARGET_AMD64_ +#ifdef TARGET_AMD64 return (PCODE) context->Rip; -#elif defined(_TARGET_ARM_) +#elif defined(TARGET_ARM) return (PCODE)context->Pc; -#elif defined(_TARGET_ARM64_) +#elif defined(TARGET_ARM64) return (PCODE)context->Pc; #else _ASSERTE(!"nyi for platform"); @@ -121,7 +121,7 @@ typedef SIZE_T TADDR; inline BOOL IS_ALIGNED( size_t val, size_t alignment ) { // alignment must be a power of 2 for this implementation to work (need modulo otherwise) - _ASSERTE( 0 == (alignment & (alignment - 1)) ); + _ASSERTE( 0 == (alignment & (alignment - 1)) ); return 0 == (val & (alignment - 1)); } inline BOOL IS_ALIGNED( void* val, size_t alignment ) @@ -138,12 +138,6 @@ inline BOOL IS_ALIGNED( void* val, size_t alignment ) #endif -// Stuff from check.h: - -#ifndef UNREACHABLE -#define UNREACHABLE() __assume(0) -#endif - // Stuff from eetwain.h: #ifndef _EETWAIN_H @@ -201,7 +195,7 @@ enum GcInfoDecoderFlags DECODE_GC_LIFETIMES = 0x10, DECODE_NO_VALIDATION = 0x20, DECODE_PSP_SYM = 0x40, - DECODE_GENERICS_INST_CONTEXT = 0x80, // stack location of instantiation context for generics + DECODE_GENERICS_INST_CONTEXT = 0x80, // stack location of instantiation context for generics // (this may be either the 'this' ptr or the instantiation secret param) DECODE_GS_COOKIE = 0x100, // stack location of the GS cookie DECODE_FOR_RANGES_CALLBACK = 0x200, @@ -209,9 +203,9 @@ enum GcInfoDecoderFlags DECODE_EDIT_AND_CONTINUE = 0x800, DECODE_REVERSE_PINVOKE_VAR = 0x1000, DECODE_RETURN_KIND = 0x2000, -#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) +#if defined(TARGET_ARM) || defined(TARGET_ARM64) DECODE_HAS_TAILCALLS = 0x4000, -#endif // _TARGET_ARM_ || _TARGET_ARM64_ +#endif // TARGET_ARM || TARGET_ARM64 }; enum GcInfoHeaderFlags @@ -226,11 +220,11 @@ enum GcInfoHeaderFlags GC_INFO_HAS_GENERICS_INST_CONTEXT_MD = 0x20, GC_INFO_HAS_GENERICS_INST_CONTEXT_THIS = 0x30, GC_INFO_HAS_STACK_BASE_REGISTER = 0x40, -#ifdef _TARGET_AMD64_ +#ifdef TARGET_AMD64 GC_INFO_WANTS_REPORT_ONLY_LEAF = 0x80, -#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) +#elif defined(TARGET_ARM) || defined(TARGET_ARM64) GC_INFO_HAS_TAILCALLS = 0x80, -#endif // _TARGET_AMD64_ +#endif // TARGET_AMD64 GC_INFO_HAS_EDIT_AND_CONTINUE_PRESERVED_SLOTS = 0x100, GC_INFO_REVERSE_PINVOKE_FRAME = 0x200, @@ -300,7 +294,7 @@ public: result &= SAFE_SHIFT_LEFT(1, numBits) - 1; return result; } - + // This version reads one bit, returning zero/non-zero (not 0/1) // NOTE: This routine is perf-critical __forceinline size_t ReadOneFast() @@ -315,14 +309,14 @@ public: } return result; } - - + + __forceinline size_t GetCurrentPos() { SUPPORTS_DAC; return (size_t) ((m_pCurrent - m_pBuffer) * BITS_PER_SIZE_T + m_RelPos - m_InitialRelPos); } - + __forceinline void SetCurrentPos( size_t pos ) { size_t adjPos = pos + m_InitialRelPos; @@ -359,7 +353,7 @@ public: return (*ptr) & (((size_t)1) << relPos); } - + //-------------------------------------------------------------------------- // Decode variable length numbers // See the corresponding methods on BitStreamWriter for more information on the format @@ -373,7 +367,7 @@ public: for(int shift=0; ; shift+=base) { _ASSERTE(shift+base <= (int)BITS_PER_SIZE_T); - + size_t currentChunk = Read(base+1); result |= (currentChunk & (numEncodings-1)) << shift; if(!(currentChunk & numEncodings)) @@ -392,7 +386,7 @@ public: for(int shift=0; ; shift+=base) { _ASSERTE(shift+base <= (int)BITS_PER_SIZE_T); - + size_t currentChunk = Read(base+1); result |= (currentChunk & (numEncodings-1)) << shift; if(!(currentChunk & numEncodings)) @@ -426,7 +420,7 @@ struct GcSlotDesc class GcSlotDecoder { public: - GcSlotDecoder() + GcSlotDecoder() {} void DecodeSlotTable(BitStreamReader& reader); @@ -452,14 +446,14 @@ public: } const GcSlotDesc* GetSlotDesc(UINT32 slotIndex); - -private: + +private: GcSlotDesc m_SlotArray[MAX_PREDECODED_SLOTS]; BitStreamReader m_SlotReader; UINT32 m_NumSlots; UINT32 m_NumRegisters; UINT32 m_NumUntracked; - + UINT32 m_NumDecodedSlots; GcSlotDesc* m_pLastSlot; }; @@ -533,9 +527,9 @@ public: bool HasMethodTableGenericsInstContext(); bool GetIsVarArg(); bool WantsReportOnlyLeaf(); -#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) +#if defined(TARGET_ARM) || defined(TARGET_ARM64) bool HasTailCalls(); -#endif // _TARGET_ARM_ || _TARGET_ARM64_ +#endif // TARGET_ARM || TARGET_ARM64 ReturnKind GetReturnKind(); UINT32 GetCodeLength(); UINT32 GetStackBaseRegister(); @@ -556,11 +550,11 @@ private: bool m_IsVarArg; bool m_GenericSecretParamIsMD; bool m_GenericSecretParamIsMT; -#ifdef _TARGET_AMD64_ +#ifdef TARGET_AMD64 bool m_WantsReportOnlyLeaf; -#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) +#elif defined(TARGET_ARM) || defined(TARGET_ARM64) bool m_HasTailCalls; -#endif // _TARGET_AMD64_ +#endif // TARGET_AMD64 INT32 m_SecurityObjectStackSlot; INT32 m_GSCookieStackSlot; INT32 m_ReversePInvokeFrameStackSlot; @@ -596,12 +590,12 @@ private: PREGDISPLAY pRD ); -#ifdef FEATURE_PAL +#ifdef TARGET_UNIX OBJECTREF* GetCapturedRegister( int regNum, PREGDISPLAY pRD ); -#endif // FEATURE_PAL +#endif // TARGET_UNIX OBJECTREF* GetStackSlot( INT32 spOffset, diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfodumper.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfodumper.h index cd939c1..9b8d941 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfodumper.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfodumper.h @@ -44,7 +44,7 @@ public: GcSlotFlags Flags, GcSlotState NewState, PVOID pvData); - + // Returns TRUE to stop decoding. typedef BOOL StackSlotStateChangeProc ( UINT32 CodeOffset, diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfoencoder.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfoencoder.h index 18dfa8c..1df36db 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfoencoder.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfoencoder.h @@ -12,7 +12,7 @@ ENCODING LAYOUT 1. Header - + Slim Header for simple and common cases: - EncodingType[Slim] - ReturnKind (Fat: 2 bits) @@ -21,11 +21,11 @@ Fat Header for other cases: - EncodingType[Fat] - - Flag: isVarArg, - hasSecurityObject, + - Flag: isVarArg, + hasSecurityObject, hasGSCookie, hasPSPSymStackSlot, - hasGenericsInstContextStackSlot, + hasGenericsInstContextStackSlot, hasStackBaseregister, wantsReportOnlyLeaf (AMD64 use only), hasTailCalls (ARM/ARM64 only) @@ -53,17 +53,17 @@ 6. GC state at try clauses (#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED) 7. Chunk pointers 8. Chunk encodings - + STANDALONE_BUILD - The STANDALONE_BUILD switch can be used to build the GcInfoEncoder library + The STANDALONE_BUILD switch can be used to build the GcInfoEncoder library independently by clients outside the CoreClr tree. The GcInfo library uses some custom data-structures (ex: ArrayList, SimplerHashTable) - and includes some utility libraries (ex: UtilCode) which pull in several other - headers with considerable unrelated content. Rather than porting all the - utility code to suite other clients, the STANDALONE_BUILD switch can be used + and includes some utility libraries (ex: UtilCode) which pull in several other + headers with considerable unrelated content. Rather than porting all the + utility code to suite other clients, the STANDALONE_BUILD switch can be used to include only the minimal set of headers specific to GcInfo encodings. Clients of STANDALONE_BUILD will likely use standard library @@ -72,9 +72,9 @@ Rather than spew the GcInfoEnoder code with #ifdef STANDALONE_BUILD ... #else .. #endif blocks, we include a special - header GcInfoUtil.h in STANDALONE_BUILD mode. GcInfoUtil.h is expected to - supply the interface/implementation for the data-structures and utilities - used by GcInfoEncoder. This header should be provided by the clients doing + header GcInfoUtil.h in STANDALONE_BUILD mode. GcInfoUtil.h is expected to + supply the interface/implementation for the data-structures and utilities + used by GcInfoEncoder. This header should be provided by the clients doing the standalone build in their source tree. *****************************************************************/ @@ -86,7 +86,7 @@ #ifdef STANDALONE_BUILD #include #include -#include "GcInfoUtil.h" +#include "GcInfoUtil.h" #include "corjit.h" #else #include @@ -101,7 +101,7 @@ #include "gcinfotypes.h" -// As stated in issue #6008, GcInfoSize should be incorporated into debug builds. +// As stated in issue #6008, GcInfoSize should be incorporated into debug builds. #ifdef _DEBUG #define MEASURE_GCINFO #endif @@ -176,11 +176,11 @@ struct GcSlotDesc BOOL IsPinned() const { return (Flags & GC_SLOT_PINNED); - } + } BOOL IsUntracked() const { return (Flags & GC_SLOT_UNTRACKED); - } + } BOOL IsDeleted() const { return (Flags & GC_SLOT_IS_DELETED); @@ -359,8 +359,8 @@ public: #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED void DefineCallSites(UINT32* pCallSites, BYTE* pCallSiteSizes, UINT32 numCallSites); -#endif - +#endif + //------------------------------------------------------------------------ // Interruptibility //------------------------------------------------------------------------ @@ -436,14 +436,14 @@ public: // Number of slots preserved during EnC remap void SetSizeOfEditAndContinuePreservedArea( UINT32 size ); -#ifdef _TARGET_AMD64_ +#ifdef TARGET_AMD64 // Used to only report a frame once for the leaf function/funclet // instead of once for each live function/funclet on the stack. // Called only by RyuJIT (not JIT64) void SetWantsReportOnlyLeaf(); -#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) +#elif defined(TARGET_ARM) || defined(TARGET_ARM64) void SetHasTailCalls(); -#endif // _TARGET_AMD64_ +#endif // TARGET_AMD64 #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA void SetSizeOfStackOutgoingAndScratchArea( UINT32 size ); @@ -495,11 +495,11 @@ private: GcInfoArrayList m_LifetimeTransitions; bool m_IsVarArg; -#if defined(_TARGET_AMD64_) +#if defined(TARGET_AMD64) bool m_WantsReportOnlyLeaf; -#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) +#elif defined(TARGET_ARM) || defined(TARGET_ARM64) bool m_HasTailCalls; -#endif // _TARGET_AMD64_ +#endif // TARGET_AMD64 INT32 m_SecurityObjectStackSlot; INT32 m_GSCookieStackSlot; UINT32 m_GSCookieValidRangeStart; @@ -513,7 +513,7 @@ private: UINT32 m_SizeOfEditAndContinuePreservedArea; INT32 m_ReversePInvokeFrameSlot; InterruptibleRange* m_pLastInterruptibleRange; - + #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA UINT32 m_SizeOfStackOutgoingAndScratchArea; #endif // FIXED_STACK_PARAMETER_SCRATCH_AREA @@ -547,12 +547,12 @@ private: // Assumes that "*ppTransitions" is has size "numTransitions", is sorted by CodeOffset then by SlotId, // and that "*ppEndTransitions" points one beyond the end of the array. If "*ppTransitions" contains - // any dead/live transitions pairs for the same CodeOffset and SlotID, removes those, by allocating a + // any dead/live transitions pairs for the same CodeOffset and SlotID, removes those, by allocating a // new array, and copying the non-removed elements into it. If it does this, sets "*ppTransitions" to - // point to the new array, "*pNumTransitions" to its shorted length, and "*ppEndTransitions" to - // point one beyond the used portion of this array. + // point to the new array, "*pNumTransitions" to its shorted length, and "*ppEndTransitions" to + // point one beyond the used portion of this array. void EliminateRedundantLiveDeadPairs(LifetimeTransition** ppTransitions, - size_t* pNumTransitions, + size_t* pNumTransitions, LifetimeTransition** ppEndTransitions); #ifdef _DEBUG diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfotypes.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfotypes.h index d45b9a6..91c577c 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfotypes.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcinfotypes.h @@ -25,10 +25,10 @@ //-------------------------------------------------------------------------------- -// It turns out, that ((size_t)x) << y == x, when y is not a literal +// It turns out, that ((size_t)x) << y == x, when y is not a literal // and its value is BITS_PER_SIZE_T // I guess the processor only shifts of the right operand modulo BITS_PER_SIZE_T -// In many cases, we want the above operation to yield 0, +// In many cases, we want the above operation to yield 0, // hence the following macros //-------------------------------------------------------------------------------- __forceinline size_t SAFE_SHIFT_LEFT(size_t x, size_t count) @@ -108,34 +108,34 @@ struct GcStackSlot //-------------------------------------------------------------------------------- // ReturnKind -- encoding return type information in GcInfo -// -// When a method is stopped at a call - site for GC (ex: via return-address +// +// When a method is stopped at a call - site for GC (ex: via return-address // hijacking) the runtime needs to know whether the value is a GC - value // (gc - pointer or gc - pointers stored in an aggregate). -// It needs this information so that mark - phase can preserve the gc-pointers +// It needs this information so that mark - phase can preserve the gc-pointers // being returned. // -// The Runtime doesn't need the precise return-type of a method. +// The Runtime doesn't need the precise return-type of a method. // It only needs to find the GC-pointers in the return value. // The only scenarios currently supported by CoreCLR are: // 1. Object references // 2. ByRef pointers // 3. ARM64/X64 only : Structs returned in two registers -// 4. X86 only : Floating point returns to perform the correct save/restore +// 4. X86 only : Floating point returns to perform the correct save/restore // of the return value around return-hijacking. // -// Based on these cases, the legal set of ReturnKind enumerations are specified -// for each architecture/encoding. +// Based on these cases, the legal set of ReturnKind enumerations are specified +// for each architecture/encoding. // A value of this enumeration is stored in the GcInfo header. // //-------------------------------------------------------------------------------- // RT_Unset: An intermediate step for staged bringup. -// When ReturnKind is RT_Unset, it means that the JIT did not set +// When ReturnKind is RT_Unset, it means that the JIT did not set // the ReturnKind in the GCInfo, and therefore the VM cannot rely on it, -// and must use other mechanisms (similar to GcInfo ver 1) to determine +// and must use other mechanisms (similar to GcInfo ver 1) to determine // the Return type's GC information. -// +// // RT_Unset is only used in the following situations: // X64: Used by JIT64 until updated to use GcInfo v2 API // ARM: Used by JIT32 until updated to use GcInfo v2 API @@ -143,21 +143,21 @@ struct GcStackSlot // RT_Unset should have a valid encoding, whose bits are actually stored in the image. // For X86, there are no free bits, and there's no RT_Unused enumeration. -#if defined(_TARGET_X86_) +#if defined(TARGET_X86) // 00 RT_Scalar // 01 RT_Object // 10 RT_ByRef // 11 RT_Float -#elif defined(_TARGET_ARM_) +#elif defined(TARGET_ARM) // 00 RT_Scalar // 01 RT_Object // 10 RT_ByRef // 11 RT_Unset -#elif defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) +#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) // Slim Header: @@ -183,7 +183,7 @@ struct GcStackSlot #ifdef PORTABILITY_WARNING PORTABILITY_WARNING("Need ReturnKind for new Platform") #endif // PORTABILITY_WARNING -#endif // Target checks +#endif // Target checks enum ReturnKind { @@ -193,29 +193,29 @@ enum ReturnKind { RT_Object = 1, RT_ByRef = 2, -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 RT_Float = 3, // Encoding 3 means RT_Float on X86 #else RT_Unset = 3, // RT_Unset on other platforms -#endif // _TARGET_X86_ +#endif // TARGET_X86 // Cases for Struct Return in two registers // - // We have the following equivalencies, because the VM's behavior is the same + // We have the following equivalencies, because the VM's behavior is the same // for both cases: // RT_Scalar_Scalar == RT_Scalar // RT_Obj_Scalar == RT_Object // RT_ByRef_Scalar == RT_Byref - // The encoding for these equivalencies will play out well because - // RT_Scalar is zero. + // The encoding for these equivalencies will play out well because + // RT_Scalar is zero. // // Naming: RT_firstReg_secondReg - // Encoding: + // Encoding: // // This encoding with exclusive bits for each register is chosen for ease of use, - // and because it doesn't cost any more bits. - // It can be changed (ex: to a linear sequence) if necessary. - // For example, we can encode the GC-information for the two registers in 3 bits (instead of 4) + // and because it doesn't cost any more bits. + // It can be changed (ex: to a linear sequence) if necessary. + // For example, we can encode the GC-information for the two registers in 3 bits (instead of 4) // if we approximate RT_Obj_ByRef and RT_ByRef_Obj as RT_ByRef_ByRef. // RT_Scalar_Scalar = RT_Scalar @@ -230,7 +230,7 @@ enum ReturnKind { RT_ByRef_Obj = RT_Object << 2 | RT_ByRef, RT_ByRef_ByRef = RT_ByRef << 2 | RT_ByRef, - // Illegal or uninitialized value, + // Illegal or uninitialized value, // Not a valid encoding, never written to image. RT_Illegal = 0xFF }; @@ -239,9 +239,9 @@ enum ReturnKind { inline bool IsValidReturnKind(ReturnKind returnKind) { return (returnKind != RT_Illegal) -#ifndef _TARGET_X86_ +#ifndef TARGET_X86 && (returnKind != RT_Unset) -#endif // _TARGET_X86_ +#endif // TARGET_X86 ; } @@ -276,9 +276,9 @@ inline bool IsStructReturnKind(ReturnKind returnKind) inline bool IsScalarReturnKind(ReturnKind returnKind) { return (returnKind == RT_Scalar) -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 || (returnKind == RT_Float) -#endif // _TARGET_X86_ +#endif // TARGET_X86 ; } @@ -310,10 +310,10 @@ inline ReturnKind ExtractRegReturnKind(ReturnKind returnKind, size_t returnRegOr // Return kind of each return register is encoded in two bits at returnRegOrdinal*2 position from LSB ReturnKind regReturnKind = (ReturnKind)((returnKind >> (returnRegOrdinal * 2)) & 3); - - // Check if any other higher ordinal return registers have object references. + + // Check if any other higher ordinal return registers have object references. // ReturnKind of higher ordinal return registers are encoded at (returnRegOrdinal+1)*2) position from LSB - // If all of the remaining bits are 0 then there isn't any more RT_Object or RT_ByRef encoded in returnKind. + // If all of the remaining bits are 0 then there isn't any more RT_Object or RT_ByRef encoded in returnKind. moreRegs = (returnKind >> ((returnRegOrdinal+1) * 2)) != 0; _ASSERTE(IsValidReturnKind(regReturnKind)); @@ -328,11 +328,11 @@ inline const char *ReturnKindToString(ReturnKind returnKind) case RT_Scalar: return "Scalar"; case RT_Object: return "Object"; case RT_ByRef: return "ByRef"; -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 case RT_Float: return "Float"; #else case RT_Unset: return "UNSET"; -#endif // _TARGET_X86_ +#endif // TARGET_X86 case RT_Scalar_Obj: return "{Scalar, Object}"; case RT_Scalar_ByRef: return "{Scalar, ByRef}"; case RT_Obj_Obj: return "{Object, Object}"; @@ -345,7 +345,7 @@ inline const char *ReturnKindToString(ReturnKind returnKind) } } -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 #include // For memcmp() #include "bitvector.h" // for ptrArgTP @@ -368,7 +368,7 @@ enum infoHdrAdjustConstants { SET_RET_KIND_MAX = 4, // 2 bits for ReturnKind ADJ_ENCODING_MAX = 0x7f, // Maximum valid encoding in a byte // Also used to mask off next bit from each encoding byte. - MORE_BYTES_TO_FOLLOW = 0x80 // If the High-bit of a header or adjustment byte + MORE_BYTES_TO_FOLLOW = 0x80 // If the High-bit of a header or adjustment byte // is set, then there are more adjustments to follow. }; @@ -425,7 +425,7 @@ enum infoHdrAdjust2 { #define INVALID_REV_PINVOKE_OFFSET 0 #define HAS_REV_PINVOKE_FRAME_OFFSET ((unsigned int) -1) // 0 is not a valid offset for EBP-frames as all locals are at a negative offset -// For ESP frames, the cookie is above (at a higher address than) the buffers, +// For ESP frames, the cookie is above (at a higher address than) the buffers, // and so cannot be at offset 0. #define INVALID_GS_COOKIE_OFFSET 0 // Temporary value to indicate that the offset needs to be read after the header @@ -463,14 +463,14 @@ struct InfoHdrSmall { unsigned char profCallbacks : 1; // 4 [0] unsigned char genericsContext : 1;//4 [1] function reports a generics context parameter is present unsigned char genericsContextIsMethodDesc : 1;//4[2] - unsigned char returnKind : 2; // 4 [4] Available GcInfo v2 onwards, previously undefined + unsigned char returnKind : 2; // 4 [4] Available GcInfo v2 onwards, previously undefined unsigned short argCount; // 5,6 in bytes unsigned int frameSize; // 7,8,9,10 in bytes unsigned int untrackedCnt; // 11,12,13,14 unsigned int varPtrTableSize; // 15.16,17,18 // Checks whether "this" is compatible with "target". - // It is not an exact bit match as "this" could have some + // It is not an exact bit match as "this" could have some // marker/place-holder values, which will have to be written out // after the header. @@ -484,11 +484,11 @@ struct InfoHdr : public InfoHdrSmall { unsigned int gsCookieOffset; // 19,20,21,22 unsigned int syncStartOffset; // 23,24,25,26 unsigned int syncEndOffset; // 27,28,29,30 - unsigned int revPInvokeOffset; // 31,32,33,34 Available GcInfo v2 onwards, previously undefined + unsigned int revPInvokeOffset; // 31,32,33,34 Available GcInfo v2 onwards, previously undefined // 35 bytes total // Checks whether "this" is compatible with "target". - // It is not an exact bit match as "this" could have some + // It is not an exact bit match as "this" could have some // marker/place-holder values, which will have to be written out // after the header. @@ -499,7 +499,7 @@ struct InfoHdr : public InfoHdrSmall { _ASSERTE(target.untrackedCnt != HAS_UNTRACKED && target.varPtrTableSize != HAS_VARPTR && target.gsCookieOffset != HAS_GS_COOKIE_OFFSET && - target.syncStartOffset != HAS_SYNC_OFFSET && + target.syncStartOffset != HAS_SYNC_OFFSET && target.revPInvokeOffset != HAS_REV_PINVOKE_FRAME_OFFSET); #endif @@ -591,7 +591,7 @@ void FASTCALL decodeCallPattern(int pattern, unsigned * argMask, unsigned * codeDelta); -#endif // _TARGET_86_ +#endif // _TARGET_86_ // Stack offsets must be 8-byte aligned, so we use this unaligned // offset to represent that the method doesn't have a security object @@ -603,7 +603,7 @@ void FASTCALL decodeCallPattern(int pattern, #define NO_REVERSE_PINVOKE_FRAME (-1) #define NO_PSP_SYM (-1) -#if defined(_TARGET_AMD64_) +#if defined(TARGET_AMD64) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target @@ -629,7 +629,7 @@ void FASTCALL decodeCallPattern(int pattern, #define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) #define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define PSP_SYM_STACK_SLOT_ENCBASE 6 +#define PSP_SYM_STACK_SLOT_ENCBASE 6 #define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 #define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 #define GS_COOKIE_STACK_SLOT_ENCBASE 6 @@ -659,7 +659,7 @@ void FASTCALL decodeCallPattern(int pattern, #define LIVESTATE_RLE_RUN_ENCBASE 2 #define LIVESTATE_RLE_SKIP_ENCBASE 4 -#elif defined(_TARGET_ARM_) +#elif defined(TARGET_ARM) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target @@ -676,7 +676,7 @@ void FASTCALL decodeCallPattern(int pattern, #define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>2) #define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<2) #define CODE_OFFSETS_NEED_NORMALIZATION 1 -#define NORMALIZE_CODE_OFFSET(x) (x) // Instructions are 2/4 bytes long in Thumb/ARM states, +#define NORMALIZE_CODE_OFFSET(x) (x) // Instructions are 2/4 bytes long in Thumb/ARM states, #define DENORMALIZE_CODE_OFFSET(x) (x) // but the safe-point offsets are encoded with a -1 adjustment. #define NORMALIZE_REGISTER(x) (x) #define DENORMALIZE_REGISTER(x) (x) @@ -687,7 +687,7 @@ void FASTCALL decodeCallPattern(int pattern, // The choices of these encoding bases only affects space overhead // and performance, not semantics/correctness. -#define PSP_SYM_STACK_SLOT_ENCBASE 5 +#define PSP_SYM_STACK_SLOT_ENCBASE 5 #define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 5 #define SECURITY_OBJECT_STACK_SLOT_ENCBASE 5 #define GS_COOKIE_STACK_SLOT_ENCBASE 5 @@ -717,7 +717,7 @@ void FASTCALL decodeCallPattern(int pattern, #define LIVESTATE_RLE_RUN_ENCBASE 2 #define LIVESTATE_RLE_SKIP_ENCBASE 4 -#elif defined(_TARGET_ARM64_) +#elif defined(TARGET_ARM64) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target @@ -727,7 +727,7 @@ void FASTCALL decodeCallPattern(int pattern, #define NORMALIZE_STACK_SLOT(x) ((x)>>3) // GC Pointers are 8-bytes aligned #define DENORMALIZE_STACK_SLOT(x) ((x)<<3) #define NORMALIZE_CODE_LENGTH(x) ((x)>>2) // All Instructions are 4 bytes long -#define DENORMALIZE_CODE_LENGTH(x) ((x)<<2) +#define DENORMALIZE_CODE_LENGTH(x) ((x)<<2) #define NORMALIZE_STACK_BASE_REGISTER(x) ((x)^29) // Encode Frame pointer X29 as zero #define DENORMALIZE_STACK_BASE_REGISTER(x) ((x)^29) #define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) @@ -742,7 +742,7 @@ void FASTCALL decodeCallPattern(int pattern, #define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) #define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define PSP_SYM_STACK_SLOT_ENCBASE 6 +#define PSP_SYM_STACK_SLOT_ENCBASE 6 #define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 #define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 #define GS_COOKIE_STACK_SLOT_ENCBASE 6 @@ -774,7 +774,7 @@ void FASTCALL decodeCallPattern(int pattern, #else -#ifndef _TARGET_X86_ +#ifndef TARGET_X86 #ifdef PORTABILITY_WARNING PORTABILITY_WARNING("Please specialize these definitions for your platform!") #endif @@ -803,7 +803,7 @@ PORTABILITY_WARNING("Please specialize these definitions for your platform!") #define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) #define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define PSP_SYM_STACK_SLOT_ENCBASE 6 +#define PSP_SYM_STACK_SLOT_ENCBASE 6 #define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 #define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 #define GS_COOKIE_STACK_SLOT_ENCBASE 6 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcrefmap.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcrefmap.h index 0e07074..d2ba660 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/gcrefmap.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/gcrefmap.h @@ -9,15 +9,15 @@ #include "sigbuilder.h" // -// The GCRef map is used to encode GC type of arguments for callsites. Logically, it is sequence where pos is +// The GCRef map is used to encode GC type of arguments for callsites. Logically, it is sequence where pos is // position of the reference in the stack frame and token is type of GC reference (one of GCREFMAP_XXX values). // -// - The encoding always starts at the byte boundary. The high order bit of each byte is used to signal end of the encoding +// - The encoding always starts at the byte boundary. The high order bit of each byte is used to signal end of the encoding // stream. The last byte has the high order bit zero. It means that there are 7 useful bits in each byte. // - "pos" is always encoded as delta from previous pos. -// - The basic encoding unit is two bits. Values 0, 1 and 2 are the common constructs (skip single slot, GC reference, interior -// pointer). Value 3 means that extended encoding follows. -// - The extended information is integer encoded in one or more four bit blocks. The high order bit of the four bit block is +// - The basic encoding unit is two bits. Values 0, 1 and 2 are the common constructs (skip single slot, GC reference, interior +// pointer). Value 3 means that extended encoding follows. +// - The extended information is integer encoded in one or more four bit blocks. The high order bit of the four bit block is // used to signal the end. // - For x86, the encoding starts by size of the callee poped stack. The size is encoded using the same mechanism as above (two bit // basic encoding, with extended encoding for large values). @@ -29,7 +29,7 @@ class GCRefMapBuilder { int m_PendingByte; // Pending value, not yet written out - int m_Bits; // Number of bits in pending byte. Note that the trailing zero bits are not written out, + int m_Bits; // Number of bits in pending byte. Note that the trailing zero bits are not written out, // so this can be more than 7. int m_Pos; // Current position @@ -47,7 +47,7 @@ class GCRefMapBuilder m_PendingByte = 0; m_Bits -= 7; } - + m_PendingByte |= (1 << m_Bits); } @@ -80,7 +80,7 @@ public: { } -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 void WriteStackPop(int stackPop) { if (stackPop < 3) @@ -100,6 +100,8 @@ public: int posDelta = pos - m_Pos; m_Pos = pos + 1; + _ASSERTE(posDelta >= 0); + if (posDelta != 0) { if (posDelta < 4) @@ -205,7 +207,7 @@ public: return m_PendingByte == 0; } -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 UINT ReadStackPop() { int x = GetTwoBit(); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/genheaders.cs b/CoreCLRProfiler/native/coreclr_headers/src/inc/genheaders.cs index 6a55cd8..25b042e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/genheaders.cs +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/genheaders.cs @@ -15,7 +15,7 @@ public class GenerateHeaders { Console.WriteLine("Usage:genheaders XML-file header-file resorce-file"); return; } - + ValidateXML(args[0]); String Message=null; String SymbolicName=null; @@ -30,35 +30,35 @@ public class GenerateHeaders { int SeveritySuccess=0; int SeverityError=1; - int minSR = MakeHresult(SeveritySuccess,FaciltyUrt,0); - int maxSR = MakeHresult(SeveritySuccess,FaciltyUrt,0xffff); - int minHR = MakeHresult(SeverityError,FaciltyUrt,0); - int maxHR = MakeHresult(SeverityError,FaciltyUrt,0xffff); + int minSR = MakeHresult(SeveritySuccess,FaciltyUrt,0); + int maxSR = MakeHresult(SeveritySuccess,FaciltyUrt,0xffff); + int minHR = MakeHresult(SeverityError,FaciltyUrt,0); + int maxHR = MakeHresult(SeverityError,FaciltyUrt,0xffff); PrintLicenseHeader(HSW); - PrintHeader(HSW); + PrintHeader(HSW); PrintLicenseHeader(RSW); PrintResourceHeader(RSW); - + XmlTextReader rdr = new XmlTextReader(args[0]); rdr.WhitespaceHandling = WhitespaceHandling.None; - + while (rdr.Read()) { - - switch (rdr.NodeType) { - + + switch (rdr.NodeType) { + case XmlNodeType.Element: if (rdr.Name.ToString() == "HRESULT") { - NumericValue=rdr.GetAttribute("NumericValue"); + NumericValue=rdr.GetAttribute("NumericValue"); } if (rdr.Name.ToString() == "Message") { Message = rdr.ReadString(); } - if (rdr.Name.ToString() == "SymbolicName") { + if (rdr.Name.ToString() == "SymbolicName") { SymbolicName = rdr.ReadString(); } - + break; case XmlNodeType.EndElement: @@ -69,7 +69,7 @@ public class GenerateHeaders { if ( (NumericValue.StartsWith("0x")) || (NumericValue.StartsWith("0X")) ) { String HexResult = NumericValue.Substring(2); - int num = int.Parse(HexResult, System.Globalization.NumberStyles.HexNumber); + int num = int.Parse(HexResult, System.Globalization.NumberStyles.HexNumber); if ((num>minSR) && (num <= maxSR)) { num = num & 0xffff; @@ -78,19 +78,19 @@ public class GenerateHeaders { num = num & 0xffff; HSW.WriteLine("#define " + SymbolicName + " EMAKEHR(0x" + num.ToString("x") + ")"); } else { - HSW.WriteLine("#define " + SymbolicName + " " + NumericValue ); - } + HSW.WriteLine("#define " + SymbolicName + " " + NumericValue ); + } + - } else { HSW.WriteLine("#define " + SymbolicName + " " + NumericValue ); } - if (Message != null) { + if (Message != null) { RSW.Write("\tMSG_FOR_URT_HR(" + SymbolicName + ") "); RSW.WriteLine(Message); - } + } SymbolicName = null; NumericValue = null; @@ -110,7 +110,7 @@ public class GenerateHeaders { bool AreFilesEqual = false; if (File.Exists(args[1])) { - StreamReader sr1 = new StreamReader(tempheaderfile); + StreamReader sr1 = new StreamReader(tempheaderfile); StreamReader sr2 = new StreamReader(args[1]); AreFilesEqual = CompareFiles(sr1, sr2); sr1.Close(); @@ -119,15 +119,15 @@ public class GenerateHeaders { if (!AreFilesEqual) { File.Copy(tempheaderfile, args[1], true); - File.Copy(temprcfile, args[2], true); + File.Copy(temprcfile, args[2], true); } if (!File.Exists(args[2])) { - File.Copy(temprcfile, args[2], true); + File.Copy(temprcfile, args[2], true); } - File.Delete(tempheaderfile); - File.Delete(temprcfile); + File.Delete(tempheaderfile); + File.Delete(temprcfile); } private static void ValidateXML (String XMLFile) { @@ -139,21 +139,21 @@ public class GenerateHeaders { settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack); - + // Create the XmlReader object. XmlReader reader = XmlReader.Create(XMLFile, settings); - // Parse the file. + // Parse the file. while (reader.Read()) { } - } + } // Display any validation errors. private static void ValidationCallBack(object sender, ValidationEventArgs e) { Console.WriteLine("Validation Error: {0}", e.Message); Environment.Exit(-1); - } + } private static void PrintLicenseHeader(StreamWriter SW) { SW.WriteLine("// Licensed to the .NET Foundation under one or more agreements."); @@ -177,7 +177,7 @@ public class GenerateHeaders { SW.WriteLine("//corerror.xml"); SW.WriteLine("//"); SW.WriteLine(); - SW.WriteLine("#ifndef FACILITY_URT"); + SW.WriteLine("#ifndef FACILITY_URT"); SW.WriteLine("#define FACILITY_URT 0x13"); SW.WriteLine("#endif"); SW.WriteLine("#ifndef EMAKEHR"); @@ -216,14 +216,14 @@ public class GenerateHeaders { if (line1 != line2) { return false; } - - } - } + } - private static int MakeHresult(int sev, int fac, int code) { + } + + private static int MakeHresult(int sev, int fac, int code) { return ((sev<<31) | (fac<<16) | (code)); - } + } } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/genrops.pl b/CoreCLRProfiler/native/coreclr_headers/src/inc/genrops.pl index 415eea7..adb6f1b 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/genrops.pl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/genrops.pl @@ -23,7 +23,7 @@ $count = 0; while (<>) { # Process only OPDEF(....) lines - if (/OPDEF\(\s*/) + if (/OPDEF\(\s*/) { chop; # Strip off trailing CR s/^OPDEF\(\s*//; # Strip off "OP(" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/getproductversionnumber.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/getproductversionnumber.h index 81367fa..de90409 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/getproductversionnumber.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/getproductversionnumber.h @@ -5,7 +5,7 @@ // GetProductVersionNumber.h // // Helper function to retrieve the file version number of a file. -// +// // ====================================================================================== @@ -35,7 +35,7 @@ void inline GetProductVersionNumber(SString &szFullPath, DWORD * pdwVersionMS, DWORD * pdwVersionLS) { WRAPPER_NO_CONTRACT; -#ifndef FEATURE_PAL +#ifndef TARGET_UNIX DWORD dwDummy = 0; DWORD dwFileInfoSize = 0; @@ -48,7 +48,7 @@ void inline GetProductVersionNumber(SString &szFullPath, DWORD * pdwVersionMS, D } // Create the buffer to store the file information. - NewHolder pbFileInfo(new BYTE[dwFileInfoSize]); + NewHolder pbFileInfo(new BYTE[dwFileInfoSize]); // Actually retrieve the file version information. if (!GetFileVersionInfo(szFullPath, NULL, dwFileInfoSize, pbFileInfo)) @@ -71,7 +71,7 @@ void inline GetProductVersionNumber(SString &szFullPath, DWORD * pdwVersionMS, D #else *pdwVersionMS = 0; *pdwVersionLS = 0; -#endif // FEATURE_PAL +#endif // TARGET_UNIX } #endif // __GetProductVersionNumber_h__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/holder.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/holder.h index 204f807..c1f86b1 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/holder.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/holder.h @@ -68,7 +68,7 @@ // The problem is that certain codebases (particulary Fusion) implement key data structures // using a class but refer to it using a holder to an interface type. This combination prevents // autoexp rules from working as desired. -// +// // Example: Take this useful autoexp rule for CAssemblyName. // // CAssemblyName=<_rProp._rProp[3].asStr> @@ -98,7 +98,7 @@ struct AutoExpVisibleValue //----------------------------------------------------------------------------- // Holder is the base class of all holder objects. Any backout object should derive from it. -// (Eventually some additional bookeeping and exception handling code will be placed in this +// (Eventually some additional bookeeping and exception handling code will be placed in this // base class.) // // There are several ways to use this class: @@ -108,15 +108,15 @@ struct AutoExpVisibleValue // 3. Instantiate the Wrapper template with your type and functions. The Wrapper adds some additional // operator overloads to provide "smart pointer" like behavior // 4. Use a prebaked Holder. This is ALWAYS the preferable strategy. It is expected that -// the general design patter is that Holders will be provided as part of a typical data abstraction. +// the general design patter is that Holders will be provided as part of a typical data abstraction. // (See Crst for an example of this.) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -// HolderBase defines the base holder functionality. You can subtype and plug in -// a different base if you need to add more members for access during +// HolderBase defines the base holder functionality. You can subtype and plug in +// a different base if you need to add more members for access during // acquire & release //----------------------------------------------------------------------------- template @@ -124,7 +124,7 @@ class HolderBase { protected: TYPE m_value; - + HolderBase(TYPE value) : m_value(value) { @@ -158,7 +158,7 @@ class HolderBase template BOOL CompareDefault(TYPE value, TYPE defaultValue) { - STATIC_CONTRACT_SUPPORTS_DAC; + STATIC_CONTRACT_SUPPORTS_DAC; return value == defaultValue; } @@ -180,17 +180,17 @@ BOOL NoNull(TYPE value, TYPE defaultValue) } // Used e.g. for retail version of code:SyncAccessHolder -template +template class NoOpBaseHolder { public: - FORCEINLINE NoOpBaseHolder() + FORCEINLINE NoOpBaseHolder() { } - FORCEINLINE NoOpBaseHolder(TYPE value, BOOL take = TRUE) + FORCEINLINE NoOpBaseHolder(TYPE value, BOOL take = TRUE) { } - FORCEINLINE ~NoOpBaseHolder() + FORCEINLINE ~NoOpBaseHolder() { } FORCEINLINE void Assign(TYPE value, BOOL fTake = TRUE) @@ -241,26 +241,26 @@ class BaseHolder : protected BASE "DEFAULTVALUE must be NULL for pointer holders and wrappers."); public: - FORCEINLINE BaseHolder() - : BASE(TYPE(DEFAULTVALUE)), + FORCEINLINE BaseHolder() + : BASE(TYPE(DEFAULTVALUE)), m_acquired(FALSE) { } FORCEINLINE BaseHolder(TYPE value) - : BASE(value), + : BASE(value), m_acquired(FALSE) { if (!IsNull()) Acquire(); } - FORCEINLINE BaseHolder(TYPE value, BOOL takeOwnership) - : BASE(value), + FORCEINLINE BaseHolder(TYPE value, BOOL takeOwnership) + : BASE(value), m_acquired(FALSE) { if (takeOwnership) Acquire(); } - FORCEINLINE ~BaseHolder() + FORCEINLINE ~BaseHolder() { Release(); } @@ -336,14 +336,14 @@ class StateHolder BOOL m_acquired; // Have we acquired the state? public: - FORCEINLINE StateHolder(BOOL take = TRUE) + FORCEINLINE StateHolder(BOOL take = TRUE) : m_acquired(FALSE) { STATIC_CONTRACT_WRAPPER; if (take) Acquire(); } - FORCEINLINE ~StateHolder() + FORCEINLINE ~StateHolder() { STATIC_CONTRACT_WRAPPER; Release(); @@ -397,14 +397,14 @@ class ConditionalStateHolder BOOL m_acquired; // Have we acquired the state? public: - FORCEINLINE ConditionalStateHolder(VALUE value, BOOL take = TRUE) + FORCEINLINE ConditionalStateHolder(VALUE value, BOOL take = TRUE) : m_value(value), m_acquired(FALSE) { STATIC_CONTRACT_WRAPPER; if (take) Acquire(); } - FORCEINLINE ~ConditionalStateHolder() + FORCEINLINE ~ConditionalStateHolder() { STATIC_CONTRACT_WRAPPER; Release(); @@ -417,7 +417,7 @@ class ConditionalStateHolder _ASSERTE(!m_acquired); m_acquired = ACQUIRE(m_value); - + return m_acquired; } FORCEINLINE void Release() @@ -465,7 +465,7 @@ class ConditionalStateHolder //----------------------------------------------------------------------------- // BaseWrapper is just Base like a Holder, but it "transparently" proxies the type it contains, -// using operator overloads. Use this when you want a holder to expose the functionality of +// using operator overloads. Use this when you want a holder to expose the functionality of // the value it contains. //----------------------------------------------------------------------------- template #ifdef __GNUC__ //#pragma GCC visibility push(hidden) #endif // __GNUC__ - // This temporary object takes care of the case where we are initializing - // a holder's contents by passing it as an out parameter. The object is + // This temporary object takes care of the case where we are initializing + // a holder's contents by passing it as an out parameter. The object is // guaranteed to live longer than the call it is passed to, hence we should // properly acquire the object on return friend class AddressInitHolder; @@ -489,8 +489,8 @@ class BaseWrapper : public BaseHolder BaseWrapper &m_holder; public: - FORCEINLINE AddressInitHolder(BaseWrapper &holder) - : m_holder(holder) + FORCEINLINE AddressInitHolder(BaseWrapper &holder) + : m_holder(holder) { // // We must clear the value, to avoid the following scenario: @@ -515,7 +515,7 @@ class BaseWrapper : public BaseHolder m_holder.Acquire(); } - // It's not optimal to have to declare these casting operators. But if we don't, + // It's not optimal to have to declare these casting operators. But if we don't, // people cannot cast the result of &holder to these values. (The C++ compiler won't // automatically use the TYPE * cast as an intermediate value.) So we put them here, // rather than forcing callers to double cast in these common cases. @@ -551,14 +551,14 @@ class BaseWrapper : public BaseHolder return (void *)(&m_holder.m_value); } }; - - // Separate out method with TYPE * cast operator, since it may clash with IUnknown ** or + + // Separate out method with TYPE * cast operator, since it may clash with IUnknown ** or // void ** cast operator. friend class TypedAddressInitHolder; class TypedAddressInitHolder : public AddressInitHolder { public: - FORCEINLINE TypedAddressInitHolder(BaseWrapper & holder) + FORCEINLINE TypedAddressInitHolder(BaseWrapper & holder) : AddressInitHolder(holder) { } @@ -571,7 +571,7 @@ class BaseWrapper : public BaseHolder #ifdef __GNUC__ //#pragma GCC visibility pop #endif // __GNUC__ - + public: FORCEINLINE BaseWrapper() : BaseT(TYPE(DEFAULTVALUE), FALSE) @@ -608,9 +608,9 @@ class BaseWrapper : public BaseHolder { return !!(this->m_value != TYPE(value)); } -#ifdef __GNUC__ - // This handles the NULL value that is an int and clang - // doesn't want to convert int to a pointer + + // This handles the NULL value that is an int and the + // compiler doesn't want to convert int to a pointer. FORCEINLINE bool operator==(int value) const { return !!(this->m_value == TYPE((void*)(SIZE_T)value)); @@ -619,7 +619,7 @@ class BaseWrapper : public BaseHolder { return !!(this->m_value != TYPE((void*)(SIZE_T)value)); } -#endif // __GNUC__ + FORCEINLINE const TYPE &operator->() const { return this->m_value; @@ -635,7 +635,7 @@ class BaseWrapper : public BaseHolder //----------------------------------------------------------------------------- // Generic templates to use to wrap up acquire/release functionality for Holder -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- template FORCEINLINE void DoNothing(TYPE value) @@ -695,7 +695,7 @@ FORCEINLINE void SafeArrayDoNothing(SAFEARRAY* p) //----------------------------------------------------------------------------- -// Holder/Wrapper are the simplest way to define holders - they synthesizes a base class out of +// Holder/Wrapper are the simplest way to define holders - they synthesizes a base class out of // function pointers //----------------------------------------------------------------------------- @@ -725,7 +725,7 @@ template typename TYPE, void (*ACQUIREF)(TYPE), void (*RELEASEF)(TYPE), - UINT_PTR DEFAULTVALUE = 0, + UINT_PTR DEFAULTVALUE = 0, BOOL IS_NULL(TYPE, TYPE) = CompareDefault, // For legacy compat (see EEJitManager::WriterLockHolder), where default ctor // causes ACQUIREF(DEFAULTVALUE), but ACQUIREF ignores the argument and @@ -751,7 +751,7 @@ class Holder : public BaseHolder, STATIC_CONTRACT_WRAPPER; } - FORCEINLINE Holder(TYPE value, BOOL takeOwnership) + FORCEINLINE Holder(TYPE value, BOOL takeOwnership) : BaseT(value, takeOwnership) { STATIC_CONTRACT_WRAPPER; @@ -768,7 +768,7 @@ class Holder : public BaseHolder, }; //--------------------------------------------------------------------------------------- -// +// template < typename TYPE, @@ -800,7 +800,7 @@ class Wrapper : public BaseWrapper, STATIC_CONTRACT_WRAPPER; } - FORCEINLINE Wrapper(TYPE value, BOOL takeOwnership) + FORCEINLINE Wrapper(TYPE value, BOOL takeOwnership) : BaseT(value, takeOwnership) { STATIC_CONTRACT_WRAPPER; @@ -822,10 +822,10 @@ class Wrapper : public BaseWrapper, #define INDEBUG_AND_WINDOWS_FOR_HOLDERS(x) x #else #define INDEBUG_AND_WINDOWS_FOR_HOLDERS(x) -#endif +#endif //--------------------------------------------------------------------------------------- -// +// // New template wrapper type macros. These save some effort when specializing // existing holder templates. (We would rather use a construct like: // @@ -834,7 +834,7 @@ class Wrapper : public BaseWrapper, // // But this construct doesn't exist in C++. These macros ease some of the cruft necessary // to get similar functionality out of class templates. -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- // Dev10 VC++ has some of the new C++0x language extensions. Of particular interest here: // rvalue references, which enables differentiation between named (lvalue) and @@ -915,13 +915,13 @@ class Wrapper : public BaseWrapper, // // { // ReleaseHolder foo; -// hr = FunctionToGetRefOfFoo(&foo); +// hr = FunctionToGetRefOfFoo(&foo); // // Note ComHolder doesn't call AddRef - it assumes you already have a ref (if non-0). // } // foo->Release() on out of scope (WITHOUT RESPECT FOR GC MODE!!) // //----------------------------------------------------------------------------- -template +template FORCEINLINE void DoTheRelease(TYPE *value) { if (value) @@ -967,7 +967,7 @@ NEW_WRAPPER_TEMPLATE1(StubHolder, StubRelease<_TYPE>); // } // delete foo on out of scope //----------------------------------------------------------------------------- -template +template FORCEINLINE void DeleteCoTaskMem(TYPE *value) { if (value) @@ -984,7 +984,7 @@ NEW_WRAPPER_TEMPLATE1(CoTaskMemHolder, DeleteCoTaskMem<_TYPE>); // } // delete foo on out of scope //----------------------------------------------------------------------------- -template +template FORCEINLINE void Delete(TYPE *value) { STATIC_CONTRACT_LEAF; @@ -993,7 +993,7 @@ FORCEINLINE void Delete(TYPE *value) "Must use NewArrayHolder (not NewHolder) for strings."); static_assert(!std::is_same::type, CHAR>::value, "Must use NewArrayHolder (not NewHolder) for strings."); - + delete value; } @@ -1010,7 +1010,7 @@ NEW_WRAPPER_TEMPLATE1(NewHolder, Delete<_TYPE>); template void DeleteExecutable(T *p); NEW_WRAPPER_TEMPLATE1(NewExecutableHolder, DeleteExecutable<_TYPE>); - + //----------------------------------------------------------------------------- // NewArrayHolder : New []'ed pointer holder // { @@ -1018,7 +1018,7 @@ NEW_WRAPPER_TEMPLATE1(NewExecutableHolder, DeleteExecutable<_TYPE>); // } // delete [] foo on out of scope //----------------------------------------------------------------------------- -template +template FORCEINLINE void DeleteArray(TYPE *value) { STATIC_CONTRACT_WRAPPER; @@ -1033,27 +1033,27 @@ typedef NewArrayHolder WStringHolder; //----------------------------------------------------------------------------- // A special array holder that expects its contents are interface pointers, // and will call Release() on them. -// +// // NOTE: You may ONLY use this if you've determined that it is SAFE to call // Release() on the contained interface pointers (e.g., as opposed to SafeRelease) -// +// template class NewInterfaceArrayHolder : public NewArrayHolder { public: NewInterfaceArrayHolder() : NewArrayHolder(), - m_cElements(0) + m_cElements(0) { STATIC_CONTRACT_WRAPPER; } - NewInterfaceArrayHolder& operator=(INTERFACE ** value) - { - STATIC_CONTRACT_WRAPPER; - NewArrayHolder::operator=(value); - return *this; - } + NewInterfaceArrayHolder& operator=(INTERFACE ** value) + { + STATIC_CONTRACT_WRAPPER; + NewArrayHolder::operator=(value); + return *this; + } void SetElementCount(ULONG32 cElements) { @@ -1126,7 +1126,7 @@ FORCEINLINE void VoidCloseFileHandle(HANDLE h) { if (h != ((HANDLE)((LONG_PTR) - FORCEINLINE void VoidFindClose(HANDLE h) { FindClose(h); } FORCEINLINE void VoidUnmapViewOfFile(void *ptr) { UnmapViewOfFile(ptr); } -template +template FORCEINLINE void TypeUnmapViewOfFile(TYPE *ptr) { UnmapViewOfFile(ptr); } // (UINT_PTR) -1 is INVALID_HANDLE_VALUE @@ -1175,10 +1175,10 @@ FORCEINLINE void CounterDecrease(RAW_KEYWORD(volatile) LONG* p) {InterlockedDecr typedef Wrapper> CounterHolder; -#ifndef FEATURE_PAL +#ifdef HOST_WINDOWS FORCEINLINE void RegKeyRelease(HKEY k) {RegCloseKey(k);}; typedef Wrapper RegKeyHolder; -#endif // !FEATURE_PAL +#endif // HOST_WINDOWS class ErrorModeHolder { @@ -1189,14 +1189,14 @@ public: UINT OldMode() {return m_oldMode;}; }; -#ifndef FEATURE_PAL +#ifdef HOST_WINDOWS //----------------------------------------------------------------------------- // HKEYHolder : HKEY holder, Calls RegCloseKey on scope exit. // // { // HKEYHolder hFoo = NULL; // WszRegOpenKeyEx(HKEY_CLASSES_ROOT, L"Interface",0, KEY_READ, hFoo); -// +// // } // close key on out of scope via RegCloseKey. //----------------------------------------------------------------------------- @@ -1244,7 +1244,7 @@ public: private: HKEY m_value; }; -#endif // !FEATURE_PAL +#endif // HOST_WINDOWS //---------------------------------------------------------------------------- // @@ -1270,22 +1270,22 @@ class DacHolder BOOL m_acquired; // Have we acquired the resource? public: - FORCEINLINE DacHolder() - : m_value(TYPE(DEFAULTVALUE)), + FORCEINLINE DacHolder() + : m_value(TYPE(DEFAULTVALUE)), m_acquired(FALSE) { STATIC_CONTRACT_SUPPORTS_DAC; } // construct a new instance of DacHolder - // Arguments: + // Arguments: // input: value - the resource held // take - indicates whether the lock should be taken--the default is true. See Notes: // Note: In DAC builds, the Acquire function does not actually take the lock, instead // it determines whether the lock is held (by the LS). If it is, the locked data // is assumed to be inconsistent and the Acquire function will throw. - FORCEINLINE DacHolder(TYPE value, BOOL take = TRUE) - : m_value(value), + FORCEINLINE DacHolder(TYPE value, BOOL take = TRUE) + : m_value(value), m_acquired(FALSE) { STATIC_CONTRACT_SUPPORTS_DAC; @@ -1293,7 +1293,7 @@ class DacHolder Acquire(); } - FORCEINLINE ~DacHolder() + FORCEINLINE ~DacHolder() { STATIC_CONTRACT_SUPPORTS_DAC; } @@ -1310,7 +1310,7 @@ class DacHolder { m_acquired = TRUE; // because ACQUIRE is a template argument, if the line m_acquired = TRUE is placed after the call - // where it logically belongs, the compiler flags it as "unreachable code." + // where it logically belongs, the compiler flags it as "unreachable code." ACQUIRE(this->m_value); } } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/iallocator.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/iallocator.h index b4c1b71..75b80a5 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/iallocator.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/iallocator.h @@ -11,8 +11,8 @@ // To allow utilcode collection classes to deal with this, they may be // written to do allocation and freeing via an instance of the -// "IAllocator" class defined in this file. -// +// "IAllocator" class defined in this file. +// #ifndef _IALLOCATOR_DEFINED_ #define _IALLOCATOR_DEFINED_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/iceefilegen.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/iceefilegen.h index 65289f4..fe825ba 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/iceefilegen.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/iceefilegen.h @@ -14,27 +14,27 @@ /* This is how this is typically used: - + // Step #1 ... Get CLR hosting API: #include #include ICLRMetaHost * pMetaHost; CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, &pMetaHost); // defined in mscoree.h - + ICLRRuntimeInfo * pCLRRuntimeInfo; pMetaHost->GetRuntime(wszClrVersion, IID_ICLRRuntimeInfo, &pCLRRuntimeInfo); - + // Step #2 ... use mscorpe APIs to create a file generator CreateICeeFileGen(...); // Get a ICeeFileGen - + CreateCeeFile(...); // Get a HCEEFILE (called for every output file needed) SetOutputFileName(...); // Set the name for the output file pEmit = IMetaDataEmit object; // Get a metadata emitter GetSectionBlock(...);, AddSectionReloc(...); ... // Get blocks, write non-metadata information, and add necessary relocation EmitMetaDataEx(pEmit); // Write out the metadata GenerateCeeFile(...); // Write out the file. Implicitly calls LinkCeeFile and FixupCeeFile - + DestroyICeeFileGen(...); // Release the ICeeFileGen object */ @@ -56,14 +56,14 @@ typedef HRESULT (__stdcall * PFN_CreateICeeFileGen)(ICeeFileGen ** ceeFileGen); typedef HRESULT (__stdcall * PFN_DestroyICeeFileGen)(ICeeFileGen ** ceeFileGen); // call this to delete an ICeeFileGen #define ICEE_CREATE_FILE_PE32 0x00000001 // Create a PE (32-bit) -#define ICEE_CREATE_FILE_PE64 0x00000002 // Create a PE+ (64-bit) -#define ICEE_CREATE_FILE_CORMAIN_STUB 0x00000004 // add a mscoree!_Cor___Main call stub +#define ICEE_CREATE_FILE_PE64 0x00000002 // Create a PE+ (64-bit) +#define ICEE_CREATE_FILE_CORMAIN_STUB 0x00000004 // add a mscoree!_Cor___Main call stub #define ICEE_CREATE_FILE_STRIP_RELOCS 0x00000008 // strip the .reloc section #define ICEE_CREATE_FILE_EMIT_FIXUPS 0x00000010 // emit fixups for use by Vulcan #define ICEE_CREATE_MACHINE_MASK 0x0000FF00 // space for up to 256 machine targets (note: most users just do a bit check, not an equality compare after applying the mask) #define ICEE_CREATE_MACHINE_ILLEGAL 0x00000000 // An illegal machine name -#define ICEE_CREATE_MACHINE_I386 0x00000100 // Create a IMAGE_FILE_MACHINE_I386 +#define ICEE_CREATE_MACHINE_I386 0x00000100 // Create a IMAGE_FILE_MACHINE_I386 #define ICEE_CREATE_MACHINE_IA64 0x00000200 // Create a IMAGE_FILE_MACHINE_IA64 #define ICEE_CREATE_MACHINE_AMD64 0x00000400 // Create a IMAGE_FILE_MACHINE_AMD64 #define ICEE_CREATE_MACHINE_ARM 0x00000800 // Create a IMAGE_FILE_MACHINE_ARMNT @@ -84,7 +84,7 @@ class ICeeFileGen { virtual HRESULT EmitMetaData (HCEEFILE ceeFile, IMetaDataEmit *emitter, mdScope scope); virtual HRESULT EmitLibraryName (HCEEFILE ceeFile, IMetaDataEmit *emitter, mdScope scope); virtual HRESULT EmitMethod (); // @FUTURE: remove - virtual HRESULT GetMethodRVA (HCEEFILE ceeFile, ULONG codeOffset, ULONG *codeRVA); + virtual HRESULT GetMethodRVA (HCEEFILE ceeFile, ULONG codeOffset, ULONG *codeRVA); virtual HRESULT EmitSignature (); // @FUTURE: remove virtual HRESULT EmitString (HCEEFILE ceeFile,_In_ LPWSTR strValue, ULONG *strRef); @@ -153,7 +153,7 @@ class ICeeFileGen { // Write out the metadata in "emitter" to the metadata section in "ceeFile" // Use EmitMetaDataAt() for more control - virtual HRESULT EmitMetaDataEx (HCEEFILE ceeFile, IMetaDataEmit *emitter); + virtual HRESULT EmitMetaDataEx (HCEEFILE ceeFile, IMetaDataEmit *emitter); virtual HRESULT EmitLibraryNameEx (HCEEFILE ceeFile, IMetaDataEmit *emitter); virtual HRESULT GetIMapTokenIfaceEx(HCEEFILE ceeFile, IMetaDataEmit *emitter, IUnknown **pIMapToken); @@ -169,22 +169,22 @@ class ICeeFileGen { virtual HRESULT ComputeSectionOffset(HCEESECTION section, _In_ char *ptr, unsigned *offset); - + virtual HRESULT ComputeOffset(HCEEFILE file, _In_ char *ptr, HCEESECTION *pSection, unsigned *offset); - - virtual HRESULT GetCorHeader(HCEEFILE ceeFile, + + virtual HRESULT GetCorHeader(HCEEFILE ceeFile, IMAGE_COR20_HEADER **header); - + // Layout the sections and assign their starting addresses - virtual HRESULT LinkCeeFile (HCEEFILE ceeFile); + virtual HRESULT LinkCeeFile (HCEEFILE ceeFile); // Apply relocations to any pointer data. Also generate PE base relocs virtual HRESULT FixupCeeFile (HCEEFILE ceeFile); // Base RVA assinged to the section. To be called only after LinkCeeFile() virtual HRESULT GetSectionRVA (HCEESECTION section, ULONG *rva); - + _Return_type_success_(return == S_OK) virtual HRESULT ComputeSectionPointer(HCEESECTION section, ULONG offset, _Out_ char **ptr); @@ -200,8 +200,8 @@ class ICeeFileGen { // If 'section != 0, it will put the data in 'buffer'. This // buffer is assumed to be in 'section' at 'offset' and of size 'buffLen' // (should use GetSaveSize to insure that buffer is big enough - virtual HRESULT EmitMetaDataAt (HCEEFILE ceeFile, IMetaDataEmit *emitter, - HCEESECTION section, DWORD offset, + virtual HRESULT EmitMetaDataAt (HCEEFILE ceeFile, IMetaDataEmit *emitter, + HCEESECTION section, DWORD offset, BYTE* buffer, unsigned buffLen); virtual HRESULT GetFileTimeStamp (HCEEFILE ceeFile, DWORD *pTimeStamp); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/il_kywd.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/il_kywd.h index 8269068..b7ea4e5 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/il_kywd.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/il_kywd.h @@ -7,7 +7,7 @@ // // This is the master table used in ILASM (asmparse.y) // and ILDASM (dis.cpp) -// symbols and values are defined in asmparse.y +// symbols and values are defined in asmparse.y // and not used in dis.cpp // @@ -142,13 +142,14 @@ KYWD( ".entrypoint", _ENTRYPOINT, NO_VALUE ) KYWD( ".zeroinit", _ZEROINIT, NO_VALUE ) KYWD( ".data", _DATA, NO_VALUE ) + KYWD( ".param", _PARAM, NO_VALUE ) KYWD( ".event", _EVENT, NO_VALUE ) KYWD( ".addon", _ADDON, NO_VALUE ) KYWD( ".removeon", _REMOVEON, NO_VALUE ) KYWD( ".fire", _FIRE, NO_VALUE ) KYWD( ".other", _OTHER, NO_VALUE ) - + KYWD( ".property", _PROPERTY, NO_VALUE ) KYWD( ".set", _SET, NO_VALUE ) KYWD( ".get", _GET, NO_VALUE ) @@ -172,7 +173,7 @@ KYWD( "noncasdemand", NONCASDEMAND_, NO_VALUE ) KYWD( "noncaslinkdemand",NONCASLINKDEMAND_, NO_VALUE ) KYWD( "noncasinheritance",NONCASINHERITANCE_,NO_VALUE ) - + /* extern debug data specifier */ KYWD( ".line", _LINE, NO_VALUE ) KYWD( ".language", _LANGUAGE, NO_VALUE ) @@ -244,7 +245,6 @@ KYWD( "in", IN_, NO_VALUE ) KYWD( "out", OUT_, NO_VALUE ) KYWD( "opt", OPT_, NO_VALUE ) - KYWD( ".param", PARAM_, NO_VALUE ) /* Method implementations */ KYWD( ".override", _OVERRIDE, NO_VALUE ) KYWD( "with", WITH_, NO_VALUE ) @@ -285,7 +285,7 @@ KYWD( ".template", _TEMPLATE, NO_VALUE ) KYWD( ".typelist", _TYPELIST, NO_VALUE ) KYWD( ".mscorlib", _MSCORLIB, NO_VALUE ) - + /* Compilation control keywords */ KYWD( "#define", P_DEFINE, NO_VALUE ) KYWD( "#undef", P_UNDEF, NO_VALUE ) @@ -295,6 +295,8 @@ KYWD( "#endif", P_ENDIF, NO_VALUE ) KYWD( "#include", P_INCLUDE, NO_VALUE ) + KYWD( "constraint", CONSTRAINT_, NO_VALUE ) + /* Deprecated keywords */ KYWD( ".vtable", _VTABLE, NO_VALUE ) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/ilformatter.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/ilformatter.h index 7593aa6..949f375 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/ilformatter.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/ilformatter.h @@ -22,14 +22,14 @@ class ILFormatter { public: ILFormatter() : start(0), targetStart(0), stackStart(0) {} - ILFormatter(IMetaDataImport* aMeta, const BYTE* aStart, - const BYTE* aLimit, unsigned maxStack, const COR_ILMETHOD_SECT_EH* eh) + ILFormatter(IMetaDataImport* aMeta, const BYTE* aStart, + const BYTE* aLimit, unsigned maxStack, const COR_ILMETHOD_SECT_EH* eh) : targetStart(0), stackStart(0) { init(aMeta, aStart, aLimit, maxStack, eh); } ~ILFormatter() { delete [] stackStart; delete [] targetStart; } - void init(IMetaDataImport* aMeta, const BYTE* aStart, + void init(IMetaDataImport* aMeta, const BYTE* aStart, const BYTE* aLimit, unsigned maxStack, const COR_ILMETHOD_SECT_EH* eh); const BYTE* formatStatement(const BYTE* stmtIL, OutString* out); const BYTE* formatInstr(const BYTE* instrIL, OutString* out); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/internalunknownimpl.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/internalunknownimpl.h index 9b561fa..530b3d1 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/internalunknownimpl.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/internalunknownimpl.h @@ -5,16 +5,16 @@ // // InternalUnknownImpl.h // -// Defines utility class ComUtil::IUnknownCommon, which provides default +// Defines utility class IUnknownCommon, which provides default // implementations for IUnknown's AddRef, Release, and QueryInterface methods. // // Use: a class that implements one or more interfaces should derive from -// ComUtil::IUnknownCommon with a template parameter list consisting of the -// list of implemented interfaces. +// IUnknownCommon with a template parameter list consisting of the +// list of implemented interfaces and their IIDs. // // Example: // class MyInterfacesImpl : -// public IUnknownCommon +// public IUnknownCommon // { ... }; // // IUnknownCommon will provide base AddRef and Release semantics, and will @@ -22,24 +22,6 @@ // arguments against the set of supported interfaces and return the // appropriate result. // -// If you need to specify multiple interfaces where one is a base interface -// of another and implementing all of them would result in a compiler error, -// you can use the NoDerive wrapper to tell IUnknownCommon to not derive from -// this interface but just use it for QueryInterface calls. -// -// Example: -// interface A -// { ... }; -// interface B : public A -// { ... }; -// class MyInterfacesImpl : public IUnknownCommon > -// { ... }; -// -// If a base type also implements IUnknownCommon, then you must override -// QueryInterface with a method that delegates to your type's -// IUnknownCommon::QueryInterface and then to BaseType::QueryInterface. -// - // //***************************************************************************** @@ -52,443 +34,114 @@ #include "contract.h" #include "ex.h" #include "volatile.h" -#include "mpl/type_list" #include "debugmacros.h" -#define COMUTIL_IIDOF(x) __uuidof(x) - -namespace ComUtil +template +class IUnknownCommon : public T { - //--------------------------------------------------------------------------------------------- - template - struct TypeWrapper - { typedef T wrapped_type; }; +protected: + LONG m_cRef; - namespace detail +public: + IUnknownCommon() + : m_cRef(0) { - typedef char (&_Yes)[1]; - typedef char (&_No)[2]; - - static inline _No _IsTypeWrapper(...); - - template - static _Yes _IsTypeWrapper(T *, typename T::wrapped_type * = nullptr); } - //--------------------------------------------------------------------------------------------- - template - struct IsTypeWrapper + // Add a virtual destructor to force derived types to also have virtual destructors. + virtual ~IUnknownCommon() { - static const bool value = std::integral_constant< - bool, - sizeof(detail::_IsTypeWrapper((T*)0)) == sizeof(detail::_Yes)>::value; - }; - - //----------------------------------------------------------------------------------------- - // Utility to remove marker type wrappers. - template ::value> - struct UnwrapOne - { typedef T type; }; - - template - struct UnwrapOne - { typedef typename T::wrapped_type type; }; - - template ::value> - struct Unwrap - { typedef T type; }; - - template - struct Unwrap - { typedef typename Unwrap< typename UnwrapOne::type >::type type; }; - - //--------------------------------------------------------------------------------------------- - // Used as a flag to indicate that an interface should not be used as a base class. - // See DeriveTypeList below. - template - struct NoDerive : public TypeWrapper - { }; - - //--------------------------------------------------------------------------------------------- - // Used to indicate that a base class contributes implemented interfaces. - template - struct ItfBase : public TypeWrapper - { }; - - namespace detail - { - using namespace mpl; - - //----------------------------------------------------------------------------------------- - // Exposes a type that derives every type in the given type list, except for those marked - // with NoDerive. - template - struct DeriveTypeList; - - // Common case. Derive from list head and recursively on list tail. - template - struct DeriveTypeList< type_list > : - public Unwrap::type, - public DeriveTypeList - {}; - - // Non-derived case. Skip this type, continue with tail. - template - struct DeriveTypeList< type_list< NoDerive< HeadT >, TailT> > : - public DeriveTypeList - {}; - - // Termination case. - template <> - struct DeriveTypeList - {}; - - //----------------------------------------------------------------------------------------- - template - struct GetFirstInterface; - - template - struct GetFirstInterface< type_list > - { typedef HeadT type; }; - - template - struct GetFirstInterface< type_list< ItfBase< HeadT >, TailT> > - { typedef typename GetFirstInterface::type type; }; - - template <> - struct GetFirstInterface< null_type > - { typedef IUnknown type; }; - - //----------------------------------------------------------------------------------------- - // Uses type lists to implement the helper. Type lists are implemented - // through templates, and can be best understood if compared to Scheme - // cdr and cons: each list type has a head type and a tail type. The - // head type is typically a concrete type, and the tail type is - // typically another list containing the remainder of the list. Type - // lists are terminated with a head type of null_type. - // - // QueryInterface is implemented using QIHelper, which uses type_lists - // and partial specialization to recursively walk the type list and - // look to see if the requested interface is supported. If not, then - // the termination case is reached and a final test against IUknown - // is made before returning a failure. - //----------------------------------------------------------------------------------------- - template - struct QIHelper; - - template - struct QIHelper< type_list< HeadT, TailT > > - { - template - static inline HRESULT QI( - REFIID riid, - void **ppvObject, - IUnknownCommonT *pThis) - { - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_ENTRY_POINT; - - HRESULT hr = S_OK; - - typedef typename Unwrap::type ItfT; - - // If the interface type matches that of the head of the list, - // then cast to it and return success. - if (riid == COMUTIL_IIDOF(ItfT)) - { - ItfT *pItf = static_cast(pThis); - pItf->AddRef(); - *ppvObject = pItf; - } - // If not, recurse on the tail of the list. - else - hr = QIHelper::QI(riid, ppvObject, pThis); - - return hr; - } - }; - - template - struct QIHelper< type_list< ItfBase< HeadT >, TailT> > - { - template - static inline HRESULT QI( - REFIID riid, - void **ppvObject, - IUnknownCommonT *pThis) - { - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_ENTRY_POINT; - - HRESULT hr = S_OK; - - hr = pThis->HeadT::QueryInterface(riid, ppvObject); - - if (hr == E_NOINTERFACE) - hr = QIHelper::QI(riid, ppvObject, pThis); - - return hr; - } - }; - - // This is the termination case. In this case, we check if the - // requested interface is IUnknown (which is common to all interfaces). - template <> - struct QIHelper< null_type > - { - template - static inline HRESULT QI( - REFIID riid, - void **ppvObject, - IUnknownCommonT *pThis) - { - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_ENTRY_POINT; - - HRESULT hr = S_OK; - - // If the request was for IUnknown, cast and return success. - if (riid == COMUTIL_IIDOF(IUnknown)) - { - typedef typename detail::GetFirstInterface< - typename IUnknownCommonT::InterfaceListT>::type IUnknownCastHelper; - - // Cast to first interface type to then cast to IUnknown unambiguously. - IUnknown *pItf = static_cast( - static_cast(pThis)); - pItf->AddRef(); - *ppvObject = pItf; - } - // Otherwise none of the interfaces match the requested IID, - // so return E_NOINTERFACE. - else - { - *ppvObject = nullptr; - hr = E_NOINTERFACE; - } - - return hr; - } - }; - - //----------------------------------------------------------------------------------------- - // Is used as a virtual base to ensure that there is a single reference count field. - struct IUnknownCommonRef - { - inline - IUnknownCommonRef() - : m_cRef(0) - {} - - Volatile m_cRef; - }; } - //--------------------------------------------------------------------------------------------- - // IUnknownCommon - // - // T0-T9 - the list of interfaces to implement. - template - < - typename T0 = mpl::null_type, - typename T1 = mpl::null_type, - typename T2 = mpl::null_type, - typename T3 = mpl::null_type, - typename T4 = mpl::null_type, - typename T5 = mpl::null_type, - typename T6 = mpl::null_type, - typename T7 = mpl::null_type, - typename T8 = mpl::null_type, - typename T9 = mpl::null_type - > - class IUnknownCommon : - virtual protected detail::IUnknownCommonRef, - public detail::DeriveTypeList< typename mpl::make_type_list< - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type > + STDMETHOD_(ULONG, AddRef()) { - public: - typedef typename mpl::make_type_list< - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type InterfaceListT; + return InterlockedIncrement(&m_cRef); + } - // Add a virtual destructor to force derived types to also have virtual destructors. - virtual ~IUnknownCommon() - { - WRAPPER_NO_CONTRACT; - clr::dbg::PoisonMem(*this); - } - - // Standard AddRef implementation - STDMETHOD_(ULONG, AddRef()) - { - STATIC_CONTRACT_LIMITED_METHOD; - STATIC_CONTRACT_ENTRY_POINT; - - return InterlockedIncrement(&m_cRef); - } - - // Standard Release implementation. - STDMETHOD_(ULONG, Release()) - { - STATIC_CONTRACT_LIMITED_METHOD; - STATIC_CONTRACT_ENTRY_POINT; - - _ASSERTE(m_cRef > 0); - - ULONG cRef = InterlockedDecrement(&m_cRef); - - if (cRef == 0) - delete this; // Relies on virtual dtor to work properly. - - return cRef; - } - - // Uses detail::QIHelper for implementation. - STDMETHOD(QueryInterface(REFIID riid, void **ppvObject)) - { - STATIC_CONTRACT_LIMITED_METHOD; - STATIC_CONTRACT_ENTRY_POINT; - - if (ppvObject == nullptr) - return E_INVALIDARG; - - *ppvObject = nullptr; - - return detail::QIHelper::QI( - riid, ppvObject, this); - } - - template - HRESULT QueryInterface(ItfT **ppItf) - { - return QueryInterface(__uuidof(ItfT), reinterpret_cast(ppItf)); - } - - protected: - // May only be constructed as a base type. - inline IUnknownCommon() : - IUnknownCommonRef() - { WRAPPER_NO_CONTRACT; } - }; - - //--------------------------------------------------------------------------------------------- - // IUnknownCommonExternal - // - // T0-T9 - the list of interfaces to implement. - template - < - typename T0 = mpl::null_type, - typename T1 = mpl::null_type, - typename T2 = mpl::null_type, - typename T3 = mpl::null_type, - typename T4 = mpl::null_type, - typename T5 = mpl::null_type, - typename T6 = mpl::null_type, - typename T7 = mpl::null_type, - typename T8 = mpl::null_type, - typename T9 = mpl::null_type - > - class IUnknownCommonExternal : - virtual protected detail::IUnknownCommonRef, - public detail::DeriveTypeList< typename mpl::make_type_list< - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type > + STDMETHOD_(ULONG, Release()) { - public: - typedef typename mpl::make_type_list< - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type InterfaceListT; + _ASSERTE(m_cRef > 0); - // Standard AddRef implementation - STDMETHOD_(ULONG, AddRef()) + ULONG cRef = InterlockedDecrement(&m_cRef); + + if (cRef == 0) + delete this; // Relies on virtual dtor to work properly. + + return cRef; + } + + STDMETHOD(QueryInterface(REFIID riid, void** ppObj)) + { + if (ppObj == NULL) + return E_INVALIDARG; + + if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_T)) { - STATIC_CONTRACT_LIMITED_METHOD; - STATIC_CONTRACT_ENTRY_POINT; - - return InterlockedIncrement(&m_cRef); + AddRef(); + *ppObj = static_cast(this); + return S_OK; } - // Standard Release implementation. - // Should be called outside VM only - STDMETHOD_(ULONG, Release()) + *ppObj = NULL; + return E_NOINTERFACE; + } +}; + +template +class IUnknownCommon2 : public T, public T2 +{ +protected: + LONG m_cRef; + +public: + IUnknownCommon2() + : m_cRef(0) + { + } + + // Add a virtual destructor to force derived types to also have virtual destructors. + virtual ~IUnknownCommon2() + { + } + + STDMETHOD_(ULONG, AddRef()) + { + return InterlockedIncrement(&m_cRef); + } + + STDMETHOD_(ULONG, Release()) + { + _ASSERTE(m_cRef > 0); + + ULONG cRef = InterlockedDecrement(&m_cRef); + + if (cRef == 0) + delete this; // Relies on virtual dtor to work properly. + + return cRef; + } + + STDMETHOD(QueryInterface(REFIID riid, void** ppObj)) + { + if (ppObj == NULL) + return E_INVALIDARG; + + if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_T)) { - STATIC_CONTRACT_LIMITED_METHOD; - STATIC_CONTRACT_ENTRY_POINT; - - _ASSERTE(m_cRef > 0); - - ULONG cRef = InterlockedDecrement(&m_cRef); - - if (cRef == 0) - { - Cleanup(); // Cleans up the object - delete this; - } - - return cRef; + AddRef(); + *ppObj = static_cast(this); + return S_OK; + } + else if (IsEqualIID(riid, IID_T2)) + { + AddRef(); + *ppObj = static_cast(this); + return S_OK; } - // Internal release - // Should be called inside VM only - STDMETHOD_(ULONG, InternalRelease()) - { - LIMITED_METHOD_CONTRACT; - - _ASSERTE(m_cRef > 0); - - ULONG cRef = InterlockedDecrement(&m_cRef); - - if (cRef == 0) - { - InternalCleanup(); // Cleans up the object, internal version - delete this; - } - - return cRef; - } - - // Uses detail::QIHelper for implementation. - STDMETHOD(QueryInterface(REFIID riid, void **ppvObject)) - { - STATIC_CONTRACT_LIMITED_METHOD; - STATIC_CONTRACT_ENTRY_POINT; - - if (ppvObject == nullptr) - return E_INVALIDARG; - - *ppvObject = nullptr; - - return detail::QIHelper::QI( - riid, ppvObject, this); - } - - template - HRESULT QueryInterface(ItfT **ppItf) - { - return QueryInterface(__uuidof(ItfT), reinterpret_cast(ppItf)); - } - - protected: - // May only be constructed as a base type. - inline IUnknownCommonExternal() : - IUnknownCommonRef() - { WRAPPER_NO_CONTRACT; } - - // Internal version of cleanup - virtual void InternalCleanup() = 0; - - // External version of cleanup - // Not surprisingly, this should call InternalCleanup to avoid duplicate code - // Not implemented here to avoid bringing too much into this header file - virtual void Cleanup() = 0; - }; -} - -#undef COMUTIL_IIDOF - -using ComUtil::NoDerive; -using ComUtil::ItfBase; -using ComUtil::IUnknownCommon; -using ComUtil::IUnknownCommonExternal; + *ppObj = NULL; + return E_NOINTERFACE; + } +}; #endif // __InternalUnknownImpl_h__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/iterator.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/iterator.h index 7616c2c..9026a68 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/iterator.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/iterator.h @@ -33,12 +33,12 @@ // 3. Indexer (STL random access) - skip around arbitrarily // Indexers have all the functionality of scanners, plus: // operator[] : access the element at index from iterator as ref -// operator+= : advance iterator by index +// operator+= : advance iterator by index // operator+ : return new iterator at index from iterator -// operator-= : rewind iterator by index +// operator-= : rewind iterator by index // operator- : return new iterator at index back from iterator // operator <, operator <=, operator >, operator>= : -// range comparison on two indexers +// range comparison on two indexers // // The object being iterated should define the following methods: // Begin() return an iterator starting at the first element @@ -55,7 +55,7 @@ #include "contract.h" namespace HIDDEN { -// These prototypes are not for direct use - they are only here to illustrate the +// These prototypes are not for direct use - they are only here to illustrate the // iterator pattern template @@ -81,7 +81,7 @@ template class EnumeratorPrototype { public: - + typedef EnumeratorPrototype Iterator; ELEMENT &operator*(); @@ -155,18 +155,18 @@ class IndexablePrototype }; // -------------------------------------------------------------------------------- -// EnumeratorBase, ScannerBase, and IndexerBase are abstract classes +// EnumeratorBase, ScannerBase, and IndexerBase are abstract classes // describing basic operations for iterator functionality at the different levels. -// +// // You -// 1. Use the classes as a pattern (don't derive from them), and plug in your own +// 1. Use the classes as a pattern (don't derive from them), and plug in your own // class into the Enumerator/Scanner/Indexer templates below. // 2. Subclass the AbstractEnumerator/AbstractScanner/AbstractIndexer classes // -------------------------------------------------------------------------------- namespace HIDDEN { -// These prototypes are not for direct use - they are only here to illustrate the +// These prototypes are not for direct use - they are only here to illustrate the // pattern of the BASE class for the Iterator templates template @@ -222,7 +222,7 @@ class CheckedIteratorBase #if defined(_DEBUG) && (defined(_MSC_VER) || defined(__llvm__)) __if_exists(CONTAINER::m_revision) { - CHECK_MSG(m_revision == m_container->m_revision, + CHECK_MSG(m_revision == m_container->m_revision, "Use of Iterator after container has been modified"); } #endif @@ -293,13 +293,13 @@ class CheckedIteratorBase // -------------------------------------------------------------------------------- -// Enumerator, Scanner, and Indexer provide a template to produce an iterator +// Enumerator, Scanner, and Indexer provide a template to produce an iterator // on an existing class with a single iteration variable. // // The template takes 3 type parameters: -// CONTAINER - type of object being interated on +// CONTAINER - type of object being interated on // ELEMENT - type of iteration -// BASE - base type of the iteration. This type must follow the pattern described +// BASE - base type of the iteration. This type must follow the pattern described // by the above Prototypes // -------------------------------------------------------------------------------- @@ -377,7 +377,7 @@ class Enumerator }; template -class Scanner +class Scanner { private: const SUBTYPE *This() const @@ -484,7 +484,7 @@ class Indexer { LIMITED_METHOD_DAC_CONTRACT; } - + CHECK CheckIndex() const { #if defined(_DEBUG) @@ -589,7 +589,7 @@ class Indexer WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); PRECONDITION(i.Check()); - + return This()->Subtract(i); } bool operator==(const SUBTYPE &i) const diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/jithelpers.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/jithelpers.h index d7d501f..608398a 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/jithelpers.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/jithelpers.h @@ -11,7 +11,7 @@ // The JIT/EE interface is versioned. By "interface", we mean mean any and all communication between the // JIT and the EE. Any time a change is made to the interface, the JIT/EE interface version identifier // must be updated. See code:JITEEVersionIdentifier for more information. -// +// // THIS FILE IS PART OF THE JIT-EE INTERFACE. // // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE @@ -38,15 +38,15 @@ // CORINFO_HELP_DBL2INT, CORINFO_HELP_DBL2UINT, and CORINFO_HELP_DBL2LONG get // patched for CPUs that support SSE2 (P4 and above). -#ifndef _TARGET_64BIT_ +#ifndef TARGET_64BIT JITHELPER(CORINFO_HELP_LLSH, JIT_LLsh, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_LRSH, JIT_LRsh, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_LRSZ, JIT_LRsz, CORINFO_HELP_SIG_REG_ONLY) -#else // !_TARGET_64BIT_ +#else // !TARGET_64BIT JITHELPER(CORINFO_HELP_LLSH, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) JITHELPER(CORINFO_HELP_LRSH, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) JITHELPER(CORINFO_HELP_LRSZ, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) -#endif // _TARGET_64BIT_ +#endif // TARGET_64BIT JITHELPER(CORINFO_HELP_LMUL, JIT_LMul, CORINFO_HELP_SIG_16_STACK) JITHELPER(CORINFO_HELP_LMUL_OVF, JIT_LMulOvf, CORINFO_HELP_SIG_16_STACK) JITHELPER(CORINFO_HELP_ULMUL_OVF, JIT_ULMulOvf, CORINFO_HELP_SIG_16_STACK) @@ -70,7 +70,6 @@ JITHELPER(CORINFO_HELP_DBLROUND, JIT_DoubleRound, CORINFO_HELP_SIG_16_STACK) // Allocating a new object - JITHELPER(CORINFO_HELP_NEW_CROSSCONTEXT, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) JITHELPER(CORINFO_HELP_NEWFAST, JIT_New, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_NEWSFAST, JIT_New, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_NEWSFAST_FINALIZE, NULL, CORINFO_HELP_SIG_REG_ONLY) @@ -80,7 +79,6 @@ JITHELPER(CORINFO_HELP_NEW_MDARR, JIT_NewMDArr,CORINFO_HELP_SIG_8_VA) JITHELPER(CORINFO_HELP_NEW_MDARR_NONVARARG, JIT_NewMDArrNonVarArg,CORINFO_HELP_SIG_4_STACK) JITHELPER(CORINFO_HELP_NEWARR_1_DIRECT, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_NEWARR_1_R2R_DIRECT, JIT_NewArr1_R2R,CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_OBJ, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_VC, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_ALIGN8, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY) @@ -92,28 +90,25 @@ JITHELPER(CORINFO_HELP_INITCLASS, JIT_InitClass, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_INITINSTCLASS, JIT_InitInstantiatedClass, CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_ISINSTANCEOFINTERFACE,JIT_IsInstanceOfInterface, CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_ISINSTANCEOFARRAY, JIT_IsInstanceOfArray,CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_ISINSTANCEOFCLASS, JIT_IsInstanceOfClass,CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_ISINSTANCEOFANY, JIT_IsInstanceOfAny,CORINFO_HELP_SIG_REG_ONLY) + // Casting helpers + DYNAMICJITHELPER(CORINFO_HELP_ISINSTANCEOFINTERFACE, NULL, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_ISINSTANCEOFARRAY, NULL, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_ISINSTANCEOFCLASS, NULL, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_ISINSTANCEOFANY, NULL, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_CHKCASTINTERFACE, NULL, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_CHKCASTARRAY, NULL, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_CHKCASTCLASS, NULL, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_CHKCASTANY, NULL, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_CHKCASTCLASS_SPECIAL, NULL, CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_CHKCASTINTERFACE, JIT_ChkCastInterface,CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_CHKCASTARRAY, JIT_ChkCastArray, CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_CHKCASTCLASS, JIT_ChkCastClass, CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_CHKCASTANY, JIT_ChkCastAny, CORINFO_HELP_SIG_REG_ONLY) - - JITHELPER(CORINFO_HELP_CHKCASTCLASS_SPECIAL,JIT_ChkCastClassSpecial,CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_BOX, JIT_Box, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_BOX_NULLABLE, JIT_Box, CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_UNBOX, JIT_Unbox, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_UNBOX, NULL, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_UNBOX_NULLABLE, JIT_Unbox_Nullable, CORINFO_HELP_SIG_4_STACK) + JITHELPER(CORINFO_HELP_GETREFANY, JIT_GetRefAny, CORINFO_HELP_SIG_8_STACK) -#if defined(_TARGET_ARM_) - DYNAMICJITHELPER(CORINFO_HELP_ARRADDR_ST, JIT_Stelem_Ref, CORINFO_HELP_SIG_4_STACK) -#else - JITHELPER(CORINFO_HELP_ARRADDR_ST, JIT_Stelem_Ref, CORINFO_HELP_SIG_4_STACK) -#endif // _TARGET_ARM_ - JITHELPER(CORINFO_HELP_LDELEMA_REF, JIT_Ldelema_Ref, CORINFO_HELP_SIG_4_STACK) + DYNAMICJITHELPER(CORINFO_HELP_ARRADDR_ST, NULL, CORINFO_HELP_SIG_4_STACK) + DYNAMICJITHELPER(CORINFO_HELP_LDELEMA_REF, NULL, CORINFO_HELP_SIG_4_STACK) // Exceptions JITHELPER(CORINFO_HELP_THROW, IL_Throw, CORINFO_HELP_SIG_REG_ONLY) @@ -131,7 +126,7 @@ JITHELPER(CORINFO_HELP_FIELD_ACCESS_EXCEPTION,JIT_ThrowFieldAccessException, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_CLASS_ACCESS_EXCEPTION,JIT_ThrowClassAccessException, CORINFO_HELP_SIG_REG_ONLY) -#ifdef WIN64EXCEPTIONS +#ifdef FEATURE_EH_FUNCLETS JITHELPER(CORINFO_HELP_ENDCATCH, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) #else JITHELPER(CORINFO_HELP_ENDCATCH, JIT_EndCatch, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) @@ -145,26 +140,9 @@ JITHELPER(CORINFO_HELP_GETCLASSFROMMETHODPARAM, JIT_GetClassFromMethodParam, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETSYNCFROMCLASSHANDLE, JIT_GetSyncFromClassHandle, CORINFO_HELP_SIG_REG_ONLY) - // Security callout support - JITHELPER(CORINFO_HELP_SECURITY_PROLOG, JIT_Security_Prolog,CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_SECURITY_PROLOG_FRAMED, JIT_Security_Prolog_Framed,CORINFO_HELP_SIG_REG_ONLY) - - JITHELPER(CORINFO_HELP_METHOD_ACCESS_CHECK, JIT_MethodAccessCheck,CORINFO_HELP_SIG_8_STACK) - JITHELPER(CORINFO_HELP_FIELD_ACCESS_CHECK, JIT_FieldAccessCheck,CORINFO_HELP_SIG_4_STACK) - JITHELPER(CORINFO_HELP_CLASS_ACCESS_CHECK, JIT_ClassAccessCheck,CORINFO_HELP_SIG_4_STACK) - - JITHELPER(CORINFO_HELP_DELEGATE_SECURITY_CHECK, JIT_DelegateSecurityCheck,CORINFO_HELP_SIG_REG_ONLY) - - // Verification runtime callout support - JITHELPER(CORINFO_HELP_VERIFICATION_RUNTIME_CHECK, JIT_VerificationRuntimeCheck,CORINFO_HELP_SIG_REG_ONLY) - // GC support DYNAMICJITHELPER(CORINFO_HELP_STOP_FOR_GC, JIT_RareDisableHelper, CORINFO_HELP_SIG_REG_ONLY) -#ifdef ENABLE_FAST_GCPOLL_HELPER - DYNAMICJITHELPER(CORINFO_HELP_POLL_GC, JIT_PollGC, CORINFO_HELP_SIG_REG_ONLY) -#else JITHELPER(CORINFO_HELP_POLL_GC, JIT_PollGC, CORINFO_HELP_SIG_REG_ONLY) -#endif JITHELPER(CORINFO_HELP_STRESS_GC, JIT_StressGC, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_CHECK_OBJ, JIT_CheckObj, CORINFO_HELP_SIG_REG_ONLY) @@ -204,7 +182,7 @@ JITHELPER(CORINFO_HELP_GETGENERICS_GCSTATIC_BASE, JIT_GetGenericsGCStaticBase,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE, JIT_GetGenericsNonGCStaticBase,CORINFO_HELP_SIG_REG_ONLY) -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR, NULL, CORINFO_HELP_SIG_REG_ONLY) @@ -242,18 +220,21 @@ JITHELPER(CORINFO_HELP_PINVOKE_CALLI, GenericPInvokeCalliHelper, CORINFO_HELP_SIG_NO_ALIGN_STUB) +#if defined(TARGET_X86) && !defined(UNIX_X86_ABI) JITHELPER(CORINFO_HELP_TAILCALL, JIT_TailCall, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) +#else + JITHELPER(CORINFO_HELP_TAILCALL, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) +#endif JITHELPER(CORINFO_HELP_GETCURRENTMANAGEDTHREADID, JIT_GetCurrentManagedThreadId, CORINFO_HELP_SIG_REG_ONLY) -#ifdef _WIN64 - // On Windows X64, the last argument is ignored. +#ifdef TARGET_64BIT JITHELPER(CORINFO_HELP_INIT_PINVOKE_FRAME, JIT_InitPInvokeFrame, CORINFO_HELP_SIG_REG_ONLY) #else DYNAMICJITHELPER(CORINFO_HELP_INIT_PINVOKE_FRAME, NULL, CORINFO_HELP_SIG_REG_ONLY) #endif -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 JITHELPER(CORINFO_HELP_MEMSET, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) JITHELPER(CORINFO_HELP_MEMCPY, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) #else @@ -290,7 +271,7 @@ JITHELPER(CORINFO_HELP_EE_PRESTUB, ThePreStub, CORINFO_HELP_SIG_NO_ALIGN_STUB) -#if defined(HAS_FIXUP_PRECODE) +#if defined(HAS_FIXUP_PRECODE) JITHELPER(CORINFO_HELP_EE_PRECODE_FIXUP, PrecodeFixupThunk, CORINFO_HELP_SIG_NO_ALIGN_STUB) #else JITHELPER(CORINFO_HELP_EE_PRECODE_FIXUP, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) @@ -315,15 +296,15 @@ // We do not need this to be saved in ngen images on Mac64 since the exception dispatch // is not done via the OS and thus, there wont be any need to know this information // by anyone. -#ifdef WIN64EXCEPTIONS +#ifdef FEATURE_EH_FUNCLETS JITHELPER(CORINFO_HELP_EE_PERSONALITY_ROUTINE, ProcessCLRException, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_EE_PERSONALITY_ROUTINE_FILTER_FUNCLET, ProcessCLRException,CORINFO_HELP_SIG_UNDEF) -#else // WIN64EXCEPTIONS +#else // FEATURE_EH_FUNCLETS JITHELPER(CORINFO_HELP_EE_PERSONALITY_ROUTINE, NULL, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_EE_PERSONALITY_ROUTINE_FILTER_FUNCLET, NULL, CORINFO_HELP_SIG_UNDEF) -#endif // !WIN64EXCEPTIONS +#endif // !FEATURE_EH_FUNCLETS -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 JITHELPER(CORINFO_HELP_ASSIGN_REF_EAX, JIT_WriteBarrierEAX, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_ASSIGN_REF_EBX, JIT_WriteBarrierEBX, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_ASSIGN_REF_ECX, JIT_WriteBarrierECX, CORINFO_HELP_SIG_NO_ALIGN_STUB) @@ -365,11 +346,19 @@ JITHELPER(CORINFO_HELP_JIT_PINVOKE_BEGIN, JIT_PInvokeBegin, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_JIT_PINVOKE_END, JIT_PInvokeEnd, CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, NULL, CORINFO_HELP_SIG_UNDEF) - JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, NULL, CORINFO_HELP_SIG_UNDEF) + JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, JIT_ReversePInvokeEnter, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, JIT_ReversePInvokeExit, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GVMLOOKUP_FOR_SLOT, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) +#ifndef TARGET_ARM64 + JITHELPER(CORINFO_HELP_STACK_PROBE, JIT_StackProbe, CORINFO_HELP_SIG_REG_ONLY) +#else + JITHELPER(CORINFO_HELP_STACK_PROBE, NULL, CORINFO_HELP_SIG_UNDEF) +#endif + + JITHELPER(CORINFO_HELP_PATCHPOINT, JIT_Patchpoint, CORINFO_HELP_SIG_REG_ONLY) + #undef JITHELPER #undef DYNAMICJITHELPER #undef JITHELPER diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/jitperf.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/jitperf.h deleted file mode 100644 index 022cfd2..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/jitperf.h +++ /dev/null @@ -1,97 +0,0 @@ -// 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. -//----------------------------------------------------------------------------- -// JitPerf.h -// Internal interface for gathering JIT perfmormance stats. These stats are -// logged (or displayed) in two ways. If PERF_COUNTERS are enabled the -// perfmon etc. would display the jit stats. If ENABLE_PERF_LOG is enabled -// and PERF_OUTPUT env var is defined then the jit stats are displayed on the -// stdout. (The jit stats are outputted in a specific format to a file for -// automated perf tests.) -// - -//----------------------------------------------------------------------------- - - -#ifndef __JITPERF_H__ -#define __JITPERF_H__ - -#include "mscoree.h" -#include "clrinternal.h" - -// ENABLE_JIT_PERF tag used to activate JIT specific profiling. -#define ENABLE_JIT_PERF - -#if defined(ENABLE_JIT_PERF) - -extern __int64 g_JitCycles; -extern size_t g_NonJitCycles; -extern CRITSEC_COOKIE g_csJit; -extern __int64 g_tlsJitCycles; -extern int g_fJitPerfOn; - -extern size_t g_dwTlsx86CodeSize; -extern size_t g_TotalILCodeSize; -extern size_t g_Totalx86CodeSize; -extern size_t g_TotalMethodsJitted; - -// Public interface to initialize jit stats data structs -void InitJitPerf(void); -// Public interface to deallocate datastruct and output the stats. -void DoneJitPerfStats(void); - -// Start/StopNonJITPerf macros are used many times. Factor out the payload -// into helper method to reduce code size. -void StartNonJITPerfWorker(LARGE_INTEGER * pCycleStart); -void StopNonJITPerfWorker(LARGE_INTEGER * pCycleStart); - -// Use the callee's stack frame (so START & STOP functions can share variables) -#define START_JIT_PERF() \ - if (g_fJitPerfOn) { \ - ClrFlsSetValue (TlsIdx_JitPerf, (LPVOID)0); \ - g_dwTlsx86CodeSize = 0; \ - ClrFlsSetValue (TlsIdx_JitX86Perf, (LPVOID)g_dwTlsx86CodeSize); \ - } - - -#define STOP_JIT_PERF() \ - if (g_fJitPerfOn) { \ - size_t dwTlsNonJitCycles = (size_t)ClrFlsGetValue (TlsIdx_JitPerf); \ - size_t dwx86CodeSize = (size_t)ClrFlsGetValue (TlsIdx_JitX86Perf); \ - CRITSEC_Holder csh (g_csJit); \ - g_JitCycles += static_cast(CycleStop.QuadPart - CycleStart.QuadPart); \ - g_NonJitCycles += dwTlsNonJitCycles; \ - g_TotalILCodeSize += methodInfo.ILCodeSize; \ - g_Totalx86CodeSize += dwx86CodeSize; \ - g_TotalMethodsJitted ++; \ - } - -#define START_NON_JIT_PERF() \ - LARGE_INTEGER CycleStart; \ - if(g_fJitPerfOn) { \ - StartNonJITPerfWorker(&CycleStart); \ - } - -#define STOP_NON_JIT_PERF() \ - if(g_fJitPerfOn) { \ - StopNonJITPerfWorker(&CycleStart); \ - } - -#define JIT_PERF_UPDATE_X86_CODE_SIZE(size) \ - if(g_fJitPerfOn) { \ - size_t dwx86CodeSize = (size_t)ClrFlsGetValue (TlsIdx_JitX86Perf); \ - dwx86CodeSize += (size); \ - ClrFlsSetValue (TlsIdx_JitX86Perf, (LPVOID)dwx86CodeSize); \ - } - - -#else //ENABLE_JIT_PERF -#define START_JIT_PERF() -#define STOP_JIT_PERF() -#define START_NON_JIT_PERF() -#define STOP_NON_JIT_PERF() -#define JIT_PERF_UPDATE_X86_CODE_SIZE(size) -#endif //ENABLE_JIT_PERF - -#endif //__JITPERF_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/lazycow.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/lazycow.h deleted file mode 100644 index c4605b6..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/lazycow.h +++ /dev/null @@ -1,99 +0,0 @@ -// 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. -// -------------------------------------------------------------------------------- -// LazyCOW.h -// - -// -// Provides support for "lazy copy-on-write" pages. -// -// NGEN images contain a large amount of writable data. At runtime, we typically only actually write to a small portion of this data. -// When we write to a writable page in an image, the OS must create a process-local copy of that page, so that other proceses -// cannot see the written data. To prevent this copy from failing, the OS pre-commits space in the pagefile for all writable -// pages when the image is loaded. Thus we get charged for every writable page, even if we only write to a few of them. -// -// FEATURE_LAZY_COW_PAGES enables "lazy copy-on-write." We mark the pages in the image file as read-only, and thus the OS -// does not pre-commit pagefile for these pages. At runtime, prior to writing to any page, we update it to be writable. -// This may fail, and thus is not appropriate for scenarios where strong reliability guarantees must be met. But for -// devices with small memory this is still worth it. -// -// -------------------------------------------------------------------------------- - -#ifndef LAZY_COW_H -#define LAZY_COW_H - -#ifdef FEATURE_LAZY_COW_PAGES - -#ifdef _WIN64 // due to the way we track pages, we cannot currently support 64-bit. -#error FEATURE_LAZY_COW_PAGES is only supported on 32-bit platforms. -#endif - -class PEDecoder; - -// If hModule is a native image, establishes copy-on-write tracking for the image. -// FreeLazyCOWPages must be called immediately before the module is unloaded. -void AllocateLazyCOWPages(PEDecoder * pImage); - -// If hModule is a native image, disestablishes copy-on-write tracking for the image. -// The image must be immediately unloaded following this call. -void FreeLazyCOWPages(PEDecoder * pImage); - -bool IsInReadOnlyLazyCOWPage(void* p); - - -// Forces the page(s) covered by the given address range to be made writable, -// if they are being tracked as copy-on-write pages. Otherwise does nothing. -// Returns false if we could not allocate the necessary memory. -bool EnsureWritablePagesNoThrow(void* p, size_t len); - -// Version for executable pages -bool EnsureWritableExecutablePagesNoThrow(void* p, size_t len); - -// Throwing version of EnsureWritablePagesNoThrow -void EnsureWritablePages(void* p, size_t len); - -// Version for executable pages -void EnsureWritableExecutablePages(void* p, size_t len); - -#else //FEATURE_LAZY_COW_PAGES - -inline bool EnsureWritablePagesNoThrow(void* p, size_t len) -{ - return true; -} - -inline bool EnsureWritableExecutablePagesNoThrow(void* p, size_t len) -{ - return true; -} - -inline void EnsureWritablePages(void* p, size_t len) -{ -} - -inline void EnsureWritableExecutablePages(void* p, size_t len) -{ -} - -#endif //FEATURE_LAZY_COW_PAGES - -// Typed version of EnsureWritable. Returns p, so this can be inserted in expressions. -// Ignores any failure to allocate. In typical cases this means that the write will AV. -// In the CLR that's OK; we handle the AV, try EnsureWritable(void*,size_t), and -// fail-fast when it fails. -template -inline T* EnsureWritablePages(T* p) -{ - EnsureWritablePages(p, sizeof(T)); - return p; -} - -template -inline T* EnsureWritableExecutablePages(T* p) -{ - EnsureWritableExecutablePages(p, sizeof(T)); - return p; -} - -#endif // LAZY_COW_H diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/livedatatarget.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/livedatatarget.h index 1ffbca7..a2107c0 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/livedatatarget.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/livedatatarget.h @@ -14,12 +14,12 @@ // Does not include IXClrData definitions. #include -#ifndef FEATURE_PAL +#ifndef TARGET_UNIX //--------------------------------------------------------------------------------------- // // Provides a simple legacy data-target implementation for a live, local, process. -// Note that in arrowhead, most debuggers use ICorDebugDataTarget, and we have +// Note that in arrowhead, most debuggers use ICorDebugDataTarget, and we have // implementations of this in MDbg. // class LiveProcDataTarget : public ICLRDataTarget @@ -35,7 +35,7 @@ public: // This class is intended to be kept on the stack // or as a member and does not maintain a refcount. // - + STDMETHOD(QueryInterface)( THIS_ IN REFIID InterfaceId, @@ -51,20 +51,20 @@ public: // // ICLRDataTarget. // - - virtual HRESULT STDMETHODCALLTYPE GetMachineType( + + virtual HRESULT STDMETHODCALLTYPE GetMachineType( /* [out] */ ULONG32 *machine); - virtual HRESULT STDMETHODCALLTYPE GetPointerSize( + virtual HRESULT STDMETHODCALLTYPE GetPointerSize( /* [out] */ ULONG32 *size); - virtual HRESULT STDMETHODCALLTYPE GetImageBase( + virtual HRESULT STDMETHODCALLTYPE GetImageBase( /* [string][in] */ LPCWSTR name, /* [out] */ CLRDATA_ADDRESS *base); - virtual HRESULT STDMETHODCALLTYPE ReadVirtual( + virtual HRESULT STDMETHODCALLTYPE ReadVirtual( /* [in] */ CLRDATA_ADDRESS address, /* [length_is][size_is][out] */ PBYTE buffer, /* [in] */ ULONG32 request, /* [optional][out] */ ULONG32 *done); - virtual HRESULT STDMETHODCALLTYPE WriteVirtual( + virtual HRESULT STDMETHODCALLTYPE WriteVirtual( /* [in] */ CLRDATA_ADDRESS address, /* [size_is][in] */ PBYTE buffer, /* [in] */ ULONG32 request, @@ -88,7 +88,7 @@ public: /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextSize, /* [in, size_is(contextSize)] */ PBYTE context); - virtual HRESULT STDMETHODCALLTYPE Request( + virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, @@ -101,7 +101,7 @@ private: CLRDATA_ADDRESS m_baseAddressOfEngine; }; -#endif // FEATURE_PAL +#endif // TARGET_UNIX #endif // _LIVEPROC_DATATARGET_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/loaderheap.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/loaderheap.h index ee45b74..97d24f6 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/loaderheap.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/loaderheap.h @@ -215,8 +215,6 @@ private: size_t m_dwTotalAlloc; - size_t * m_pPrivatePerfCounter_LoaderBytes; - DWORD m_Options; LoaderHeapFreeBlock *m_pFirstFreeBlock; @@ -286,7 +284,6 @@ protected: DWORD dwCommitBlockSize, const BYTE* dwReservedRegionAddress, SIZE_T dwReservedRegionSize, - size_t *pPrivatePerfCounter_LoaderBytes = NULL, RangeList *pRangeList = NULL, BOOL fMakeExecutable = FALSE); @@ -441,20 +438,18 @@ private: public: LoaderHeap(DWORD dwReserveBlockSize, DWORD dwCommitBlockSize, - size_t *pPrivatePerfCounter_LoaderBytes = NULL, RangeList *pRangeList = NULL, - BOOL fMakeExecutable = FALSE + BOOL fMakeExecutable = FALSE, + BOOL fUnlocked = FALSE ) : UnlockedLoaderHeap(dwReserveBlockSize, dwCommitBlockSize, NULL, 0, - pPrivatePerfCounter_LoaderBytes, pRangeList, - fMakeExecutable) + fMakeExecutable), + m_CriticalSection(fUnlocked ? NULL : CreateLoaderHeapLock()) { WRAPPER_NO_CONTRACT; - m_CriticalSection = NULL; - m_CriticalSection = CreateLoaderHeapLock(); m_fExplicitControl = FALSE; } @@ -463,21 +458,19 @@ public: DWORD dwCommitBlockSize, const BYTE* dwReservedRegionAddress, SIZE_T dwReservedRegionSize, - size_t *pPrivatePerfCounter_LoaderBytes = NULL, RangeList *pRangeList = NULL, - BOOL fMakeExecutable = FALSE + BOOL fMakeExecutable = FALSE, + BOOL fUnlocked = FALSE ) : UnlockedLoaderHeap(dwReserveBlockSize, dwCommitBlockSize, dwReservedRegionAddress, dwReservedRegionSize, - pPrivatePerfCounter_LoaderBytes, pRangeList, - fMakeExecutable) + fMakeExecutable), + m_CriticalSection(fUnlocked ? NULL : CreateLoaderHeapLock()) { WRAPPER_NO_CONTRACT; - m_CriticalSection = NULL; - m_CriticalSection = CreateLoaderHeapLock(); m_fExplicitControl = FALSE; } @@ -547,7 +540,7 @@ public: return RealAllocMemUnsafe_NoThrow(dwSize.Value() COMMA_INDEBUG(szFile) COMMA_INDEBUG(lineNum)); } private: - + TaggedMemAllocPtr RealAllocMemUnsafe(size_t dwSize #ifdef _DEBUG ,__in __in_z const char *szFile @@ -557,7 +550,7 @@ private: { WRAPPER_NO_CONTRACT; - + void *pResult; TaggedMemAllocPtr tmap; @@ -774,12 +767,10 @@ class ExplicitControlLoaderHeap : public UnlockedLoaderHeap { #ifndef DACCESS_COMPILE public: - ExplicitControlLoaderHeap(size_t *pPrivatePerfCounter_LoaderBytes = NULL, - RangeList *pRangeList = NULL, + ExplicitControlLoaderHeap(RangeList *pRangeList = NULL, BOOL fMakeExecutable = FALSE ) : UnlockedLoaderHeap(0, 0, NULL, 0, - pPrivatePerfCounter_LoaderBytes, pRangeList, fMakeExecutable) { diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/log.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/log.h index 37aab45..b2ccce1 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/log.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/log.h @@ -26,7 +26,7 @@ enum { }; -#define LL_EVERYTHING 10 +#define LL_EVERYTHING 10 #define LL_INFO1000000 9 // can be expected to generate 1,000,000 logs per small but not trival run #define LL_INFO100000 8 // can be expected to generate 100,000 logs per small but not trival run #define LL_INFO10000 7 // can be expected to generate 10,000 logs per small but not trival run @@ -52,6 +52,7 @@ enum { #define LOG(x) #define LOG2(x) +#define LOGALWAYS(x) #define InitializeLogging() #define InitLogging() @@ -90,6 +91,8 @@ bool Logging2On(DWORD facility, DWORD level); #define LOG2(x) do { if (LoggingEnabled()) { LogSpew2 x; } } while (0) +#define LOGALWAYS(x) LogSpewAlways x + #endif #ifdef __cplusplus diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/loglf.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/loglf.h index 76a9897..750de53 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/loglf.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/loglf.h @@ -1,7 +1,7 @@ // 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. -// The code in sos.DumpLog depends on the first 32 facility codes +// The code in sos.DumpLog depends on the first 32 facility codes // being bit flags sorted in incresing order. DEFINE_LOG_FACILITY(LF_GC ,0x00000001) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/longfilepathwrappers.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/longfilepathwrappers.h index 3bb9166..23033c2 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/longfilepathwrappers.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/longfilepathwrappers.h @@ -1,6 +1,6 @@ -// 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. +// 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. #ifndef _WIN_PATH_APIS_WRAPPER_ #define _WIN_PATH_APIS_WRAPPER_ @@ -24,12 +24,6 @@ CreateFileWrapper( _In_opt_ HANDLE hTemplateFile ); -BOOL -SetFileAttributesWrapper( - _In_ LPCWSTR lpFileName, - _In_ DWORD dwFileAttributes - ); - DWORD GetFileAttributesWrapper( _In_ LPCWSTR lpFileName @@ -56,14 +50,7 @@ FindFirstFileExWrapper( _In_ DWORD dwAdditionalFlags ); -BOOL -CopyFileWrapper( - _In_ LPCWSTR lpExistingFileName, - _In_ LPCWSTR lpNewFileName, - _In_ BOOL bFailIfExists - ); - -#ifndef FEATURE_PAL +#ifndef TARGET_UNIX BOOL CopyFileExWrapper( _In_ LPCWSTR lpExistingFileName, @@ -74,7 +61,7 @@ CopyFileExWrapper( _Inout_opt_ LPBOOL pbCancel, _In_ DWORD dwCopyFlags ); -#endif //FEATURE_PAL +#endif //TARGET_UNIX BOOL MoveFileExWrapper( @@ -83,24 +70,6 @@ MoveFileExWrapper( _In_ DWORD dwFlags ); -BOOL -CreateDirectoryWrapper( - _In_ LPCWSTR lpPathName, - _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes - ); - -BOOL -RemoveDirectoryWrapper( - _In_ LPCWSTR lpPathName - ); - -BOOL -CreateHardLinkWrapper( - _In_ LPCWSTR lpFileName, - _In_ LPCWSTR lpExistingFileName, - _Reserved_ LPSECURITY_ATTRIBUTES lpSecurityAttributes - ); - DWORD SearchPathWrapper( _In_opt_ LPCWSTR lpPath, @@ -112,18 +81,6 @@ SearchPathWrapper( ); -DWORD -GetShortPathNameWrapper( - _In_ LPCWSTR lpszLongPath, - SString& lpszShortPath - ); - -DWORD -GetLongPathNameWrapper( - _In_ LPCWSTR lpszShortPath, - SString& lpszLongPath - ); - UINT WINAPI GetTempFileNameWrapper( _In_ LPCTSTR lpPathName, _In_ LPCTSTR lpPrefixString, diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/md5.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/md5.h index b368471..dc82523 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/md5.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/md5.h @@ -5,7 +5,7 @@ // md5.h // -// +// // A pretty fast implementation of MD5 // @@ -18,14 +18,14 @@ // Declaration of the central transform function // void __stdcall MD5Transform(ULONG state[4], const ULONG* data); - + ///////////////////////////////////////////////////////////////////////////////////// #include // This structure is used to return the final resulting hash. -// +// struct MD5HASHDATA { union @@ -67,17 +67,17 @@ class MD5 ULONG m_state[4]; struct { - ULONG m_a; // state + ULONG m_a; // state ULONG m_b; // ... variables ULONG m_c; // ... as found in ULONG m_d; // ... RFC1321 } u; }; - + BYTE m_data[64]; // where to accumulate the data as we are passed it ULONGLONG m_cbitHashed; // amount of data that we've hashed ULONG m_cbData; // number of bytes presently in data - + BYTE m_padding[64]; // padding data, used if length data not = 0 mod 64 public: @@ -107,7 +107,7 @@ public: pbData += cbHash; ul.QuadPart -= cbHash; } - + HashMore(pbData, ul.u.LowPart); // Hash whatever is left GetHashValue(phash); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/mdcommon.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/mdcommon.h index 7aeb710..45c6f04 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/mdcommon.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/mdcommon.h @@ -13,7 +13,7 @@ // File types for the database. enum FILETYPE -{ +{ FILETYPE_UNKNOWN, // Unknown or undefined type. FILETYPE_CLB, // Native .clb file format. FILETYPE_CLX, // An obsolete file format. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/mdfileformat.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/mdfileformat.h new file mode 100644 index 0000000..b414b0c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/mdfileformat.h @@ -0,0 +1,272 @@ +// 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. +//***************************************************************************** +// MDFileFormat.h +// + +// +// This file contains a set of helpers to verify and read the file format. +// This code does not handle the paging of the data, or different types of +// I/O. See the StgTiggerStorage and StgIO code for this level of support. +// +//***************************************************************************** +#ifndef __MDFileFormat_h__ +#define __MDFileFormat_h__ + +#include +#include "utilcode.h" + +//***************************************************************************** +// The signature ULONG is the first 4 bytes of the file format. The second +// signature string starts the header containing the stream list. It is used +// for an integrity check when reading the header in lieu of a more complicated +// system. +//***************************************************************************** +#define STORAGE_MAGIC_SIG 0x424A5342 // BSJB + + + +//***************************************************************************** +// These values get written to the signature at the front of the file. Changing +// these values should not be done lightly because all old files will no longer +// be supported. In a future revision if a format change is required, a +// backwards compatible migration path must be provided. +//***************************************************************************** + +#define FILE_VER_MAJOR 1 +#define FILE_VER_MINOR 1 + +// These are the last legitimate 0.x version macros. The file format has +// sinced move up to 1.x (see macros above). After COM+ 1.0/NT 5 RTM's, these +// macros should no longer be required or ever seen. +#define FILE_VER_MAJOR_v0 0 + +#define FILE_VER_MINOR_v0 19 + + +#define MAXSTREAMNAME 32 + +enum +{ + STGHDR_NORMAL = 0x00, // Normal default flags. + STGHDR_EXTRADATA = 0x01, // Additional data exists after header. +}; + + +//***************************************************************************** +// This is the formal signature area at the front of the file. This structure +// is not allowed to change, the shim depends on it staying the same size. +// Use the reserved pointer if it must extended. +//***************************************************************************** +struct STORAGESIGNATURE; +typedef STORAGESIGNATURE UNALIGNED * PSTORAGESIGNATURE; + +#include "pshpack1.h" +struct STORAGESIGNATURE +{ +METADATA_FIELDS_PROTECTION: + ULONG lSignature; // "Magic" signature. + USHORT iMajorVer; // Major file version. + USHORT iMinorVer; // Minor file version. + ULONG iExtraData; // Offset to next structure of information + ULONG iVersionString; // Length of version string +public: + BYTE pVersion[0]; // Version string + ULONG GetSignature() + { + return VAL32(lSignature); + } + void SetSignature(ULONG Signature) + { + lSignature = VAL32(Signature); + } + + USHORT GetMajorVer() + { + return VAL16(iMajorVer); + } + void SetMajorVer(USHORT MajorVer) + { + iMajorVer = VAL16(MajorVer); + } + + USHORT GetMinorVer() + { + return VAL16(iMinorVer); + } + void SetMinorVer(USHORT MinorVer) + { + iMinorVer = VAL16(MinorVer); + } + + ULONG GetExtraDataOffset() + { + return VAL32(iExtraData); + } + void SetExtraDataOffset(ULONG ExtraDataOffset) + { + iExtraData = VAL32(ExtraDataOffset); + } + + ULONG GetVersionStringLength() + { + return VAL32(iVersionString); + } + void SetVersionStringLength(ULONG VersionStringLength) + { + iVersionString = VAL32(VersionStringLength); + } +}; +#include "poppack.h" + + +//***************************************************************************** +// The header of the storage format. +//***************************************************************************** +struct STORAGEHEADER; +typedef STORAGEHEADER UNALIGNED * PSTORAGEHEADER; + +#include "pshpack1.h" +struct STORAGEHEADER +{ +METADATA_FIELDS_PROTECTION: + BYTE fFlags; // STGHDR_xxx flags. + BYTE pad; + USHORT iStreams; // How many streams are there. +public: + BYTE GetFlags() + { + return fFlags; + } + void SetFlags(BYTE flags) + { + fFlags = flags; + } + void AddFlags(BYTE flags) + { + fFlags |= flags; + } + + + USHORT GetiStreams() + { + return VAL16(iStreams); + } + void SetiStreams(USHORT iStreamsCount) + { + iStreams = VAL16(iStreamsCount); + } +}; +#include "poppack.h" + + +//***************************************************************************** +// Each stream is described by this struct, which includes the offset and size +// of the data. The name is stored in ANSI null terminated. +//***************************************************************************** +struct STORAGESTREAM; +typedef STORAGESTREAM UNALIGNED * PSTORAGESTREAM; + +#include "pshpack1.h" +struct STORAGESTREAM +{ +METADATA_FIELDS_PROTECTION: + ULONG iOffset; // Offset in file for this stream. + ULONG iSize; // Size of the file. + char rcName[MAXSTREAMNAME]; // Start of name, null terminated. +public: + // Returns pointer to the next stream. Doesn't validate the structure. + inline PSTORAGESTREAM NextStream() + { + int iLen = (int)(strlen(rcName) + 1); + iLen = ALIGN4BYTE(iLen); + return ((PSTORAGESTREAM) (((BYTE*)this) + (sizeof(ULONG) * 2) + iLen)); + } + // Returns pointer to the next stream. + // Returns NULL if the structure has invalid format. + inline PSTORAGESTREAM NextStream_Verify() + { + // Check existence of null-terminator in the name + if (memchr(rcName, 0, MAXSTREAMNAME) == NULL) + { + return NULL; + } + return NextStream(); + } + + inline ULONG GetStreamSize() + { + return (ULONG)(strlen(rcName) + 1 + (sizeof(STORAGESTREAM) - sizeof(rcName))); + } + + inline char* GetName() + { + return rcName; + } + inline LPCWSTR GetName(__inout_ecount (iMaxSize) LPWSTR szName, int iMaxSize) + { + VERIFY(::WszMultiByteToWideChar(CP_ACP, 0, rcName, -1, szName, iMaxSize)); + return (szName); + } + inline void SetName(LPCWSTR szName) + { + int size; + size = WszWideCharToMultiByte(CP_ACP, 0, szName, -1, rcName, MAXSTREAMNAME, 0, 0); + _ASSERTE(size > 0); + } + + ULONG GetSize() + { + return VAL32(iSize); + } + void SetSize(ULONG Size) + { + iSize = VAL32(Size); + } + + ULONG GetOffset() + { + return VAL32(iOffset); + } + void SetOffset(ULONG Offset) + { + iOffset = VAL32(Offset); + } +}; +#include "poppack.h" + + +class MDFormat +{ +public: +//***************************************************************************** +// Verify the signature at the front of the file to see what type it is. +//***************************************************************************** + static HRESULT VerifySignature( + PSTORAGESIGNATURE pSig, // The signature to check. + ULONG cbData); // Size of metadata. + +//***************************************************************************** +// Skip over the header and find the actual stream data. +// It doesn't perform any checks for buffer overflow - use GetFirstStream_Verify +// instead. +//***************************************************************************** + static PSTORAGESTREAM GetFirstStream(// Return pointer to the first stream. + PSTORAGEHEADER pHeader, // Return copy of header struct. + const void *pvMd); // Pointer to the full file. +//***************************************************************************** +// Skip over the header and find the actual stream data. Secure version of +// GetFirstStream method. +// The header is supposed to be verified by VerifySignature. +// +// Caller has to check available buffer size before using the first stream. +//***************************************************************************** + static PSTORAGESTREAM GetFirstStream_Verify(// Return pointer to the first stream. + PSTORAGEHEADER pHeader, // Return copy of header struct. + const void *pvMd, // Pointer to the full file. + ULONG *pcbMd); // [in, out] Size of pvMd buffer (we don't want to read behind it) + +}; + +#endif // __MDFileFormat_h__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/memorypool.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/memorypool.h index 9ea524f..b398f00 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/memorypool.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/memorypool.h @@ -19,7 +19,7 @@ // // It also has several additional features: // * you can free the entire pool of objects cheaply. -// * you can test an object to see if it's an element of the pool. +// * you can test an object to see if it's an element of the pool. // class MemoryPool @@ -132,7 +132,7 @@ class MemoryPoolElementHolder if (bRelease) Release(); } - + operator void* () { LIMITED_METHOD_CONTRACT; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/memoryrange.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/memoryrange.h index d558d6b..b3d39aa 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/memoryrange.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/memoryrange.h @@ -13,23 +13,23 @@ #include "daccess.h" // MemoryRange is a descriptor of a memory range. This groups (pointer + size). -// +// // Some key qualities: // - simple! // - Not mutable // - blitabble descriptor which can be useful for out-of-process tools like the debugger. -// - no ownership semantics. -// - no manipulation, growing semantics. +// - no ownership semantics. +// - no manipulation, growing semantics. // - no memory marshalling, allocation, copying. etc. -// - can be efficiently passed / copied / returned by value -// +// - can be efficiently passed / copied / returned by value +// // This class has general value as an abstraction to group pointer and size together. It also has significant // value to the debugger. An expected design pattern is that other mutable complex data structures (eg, // code:SBuffer, code:CGrowableStream) will provide an accessor to expose their underlying storage as a -// MemoryRange to debugger. This mirrors the Debugger's code:TargetBuffer data structure, but as a -// general-purpose VM utility versus a debugger right-side data structure. +// MemoryRange to debugger. This mirrors the Debugger's code:TargetBuffer data structure, but as a +// general-purpose VM utility versus a debugger right-side data structure. -// +// class MemoryRange { public: @@ -37,18 +37,18 @@ public: MemoryRange() : m_pStartAddress(NULL), m_cbBytes(0) - { + { SUPPORTS_DAC; } - MemoryRange(PTR_VOID pStartAddress, SIZE_T cbBytes) : + MemoryRange(PTR_VOID pStartAddress, SIZE_T cbBytes) : m_pStartAddress(pStartAddress), m_cbBytes(cbBytes) - { + { SUPPORTS_DAC; } - // Note: use compiler-default copy ctor and assignment operator + // Note: use compiler-default copy ctor and assignment operator @@ -82,7 +82,7 @@ public: return m_cbBytes; } -private: +private: // The start of the memory range. PTR_VOID const m_pStartAddress; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/metadata.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/metadata.h index 8fcf493..662a77e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/metadata.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/metadata.h @@ -3,9 +3,9 @@ // See the LICENSE file in the project root for more information. //**************************************************************************** // File: metadata.h -// +// -// +// // Notes: // Common includes for EE & metadata internal. This file contains // definition of CorMetaDataScope @@ -14,9 +14,11 @@ #ifndef _METADATA_H_ #define _METADATA_H_ -#include "../md/inc/metamodelro.h" -#include "../md/inc/liteweightstgdb.h" +#include "ex.h" +class CorProfileData; +class IMetaModelCommon; +class MDInternalRW; class UTSemReadWrite; inline int IsGlobalMethodParentTk(mdTypeDef td) @@ -67,20 +69,18 @@ enum CorClassIfaceAttr #define HANDLE_UNCOMPRESSED(func) (E_FAIL) #define HANDLE_UNCOMPRESSED_BOOL(func) (false) -class TOKENLIST : public CDynArray +class TOKENLIST : public CDynArray { }; typedef enum tagEnumType { - MDSimpleEnum = 0x0, // simple enumerator that doesn't allocate memory + MDSimpleEnum = 0x0, // simple enumerator that doesn't allocate memory // You could get this kind of enum if you perform a non-simple query (such as EnumMethodWithName). - // + // MDDynamicArrayEnum = 0x2, // dynamic array that holds tokens - - MDCustomEnum = 0x3, // Custom enumerator that doesnt work with the enum functions } EnumType; //***************************************** @@ -90,7 +90,7 @@ struct HENUMInternal { DWORD m_tkKind; // kind of tables that the enum is holding the result ULONG m_ulCount; // count of total entries holding by the enumerator - + EnumType m_EnumType; struct { @@ -139,7 +139,7 @@ struct HENUMInternal // TODO: remove this when we remove m_cursor from the HENUMInternal structure _ASSERTE(IS_ALIGNED(pEnum->m_cursor, sizeof(DWORD))); _ASSERTE((sizeof(HENUMInternal) - offsetof(HENUMInternal, m_cursor)) == (8 * sizeof(DWORD))); - + DWORD* pBuffer = (DWORD*)pEnum->m_cursor; pBuffer[0] = 0; pBuffer[1] = 0; @@ -156,14 +156,14 @@ struct HENUMInternal HENUMInternal *pmdEnum); // create a HENUMInternal. This will allocate the memory - __checkReturn + __checkReturn static HRESULT CreateSimpleEnum( DWORD tkKind, // kind of token that we are iterating ULONG ridStart, // starting rid ULONG ridEnd, // end rid HENUMInternal **ppEnum); // return the created HENUMInternal - __checkReturn + __checkReturn static HRESULT CreateDynamicArrayEnum( DWORD tkKind, // kind of token that we are iterating HENUMInternal **ppEnum); // return the created HENUMInternal @@ -174,15 +174,15 @@ struct HENUMInternal static void DestroyEnumIfEmpty( HENUMInternal **ppEnum); // reset the enumerator pointer to NULL if empty - - __checkReturn + + __checkReturn static HRESULT EnumWithCount( HENUMInternal *pEnum, // enumerator ULONG cMax, // max tokens that caller wants mdToken rTokens[], // output buffer to fill the tokens ULONG *pcTokens); // number of tokens fill to the buffer upon return - __checkReturn + __checkReturn static HRESULT EnumWithCount( HENUMInternal *pEnum, // enumerator ULONG cMax, // max tokens that caller wants @@ -190,26 +190,26 @@ struct HENUMInternal mdToken rTokens2[], // second output buffer to fill the tokens ULONG *pcTokens); // number of tokens fill to the buffer upon return - __checkReturn + __checkReturn static HRESULT AddElementToEnum( HENUMInternal *pEnum, // return the created HENUMInternal mdToken tk); // token to fill //***************************************** // Get next value contained in the enumerator - //***************************************** + //***************************************** static bool EnumNext( - HENUMInternal *phEnum, // [IN] the enumerator to retrieve information + HENUMInternal *phEnum, // [IN] the enumerator to retrieve information mdToken *ptk); // [OUT] token to scope the search - __checkReturn + __checkReturn static HRESULT GetCount( - HENUMInternal *phEnum, // [IN] the enumerator to retrieve information + HENUMInternal *phEnum, // [IN] the enumerator to retrieve information ULONG *pCount); // ]OUT] the index of the desired item - __checkReturn + __checkReturn static HRESULT GetElement( - HENUMInternal *phEnum, // [IN] the enumerator to retrieve information + HENUMInternal *phEnum, // [IN] the enumerator to retrieve information ULONG ix, // ]IN] the index of the desired item mdToken *ptk); // [OUT] token to fill @@ -219,7 +219,7 @@ struct HENUMInternal //***************************************** // Default Value for field, param or property. Returned by GetDefaultValue -//***************************************** +//***************************************** typedef struct _MDDefaultValue { #if BIGENDIAN @@ -236,9 +236,9 @@ typedef struct _MDDefaultValue } #endif - // type of default value + // type of default value BYTE m_bType; // CorElementType for the default value - + // the default value union { @@ -254,10 +254,10 @@ typedef struct _MDDefaultValue FLOAT m_fltValue; // ELEMENT_TYPE_R4 DOUBLE m_dblValue; // ELEMENT_TYPE_R8 LPCWSTR m_wzValue; // ELEMENT_TYPE_STRING - IUnknown *m_unkValue; // ELEMENT_TYPE_CLASS + IUnknown *m_unkValue; // ELEMENT_TYPE_CLASS }; ULONG m_cbSize; // default value size (for blob) - + } MDDefaultValue; @@ -270,7 +270,7 @@ typedef struct mdMethodDef m_memberdef; DWORD m_dwSemantics; } ASSOCIATE_RECORD; - + // // structure use to retrieve class layout informaiton @@ -285,153 +285,155 @@ typedef struct // Structure for describing the Assembly MetaData. typedef struct { - USHORT usMajorVersion; // Major Version. + USHORT usMajorVersion; // Major Version. USHORT usMinorVersion; // Minor Version. USHORT usBuildNumber; // Build Number. USHORT usRevisionNumber; // Revision Number. LPCSTR szLocale; // Locale. - DWORD *rProcessor; // Processor array. - ULONG ulProcessor; // [IN/OUT] Size of the processor array/Actual # of entries filled in. - OSINFO *rOS; // OSINFO array. - ULONG ulOS; // [IN/OUT]Size of the OSINFO array/Actual # of entries filled in. } AssemblyMetaDataInternal; // Callback definition for comparing signatures. -// (*PSIGCOMPARE) (BYTE ScopeSignature[], DWORD ScopeSignatureLength, -// BYTE ExternalSignature[], DWORD ExternalSignatureLength, +// (*PSIGCOMPARE) (BYTE ScopeSignature[], DWORD ScopeSignatureLength, +// BYTE ExternalSignature[], DWORD ExternalSignatureLength, // void* SignatureData); typedef BOOL (*PSIGCOMPARE)(PCCOR_SIGNATURE, DWORD, PCCOR_SIGNATURE, DWORD, void*); - -// {CE0F34ED-BBC6-11d2-941E-0000F8083460} -EXTERN_GUID(IID_IMDInternalImport, 0xce0f34ed, 0xbbc6, 0x11d2, 0x94, 0x1e, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60); +// {1B119F60-C507-4024-BB39-F8223FB3E1FD} +EXTERN_GUID(IID_IMDInternalImport, 0x1b119f60, 0xc507, 0x4024, 0xbb, 0x39, 0xf8, 0x22, 0x3f, 0xb3, 0xe1, 0xfd); #undef INTERFACE #define INTERFACE IMDInternalImport DECLARE_INTERFACE_(IMDInternalImport, IUnknown) { - //---------------------------------------------------------------------------------------- - // !!! READ THIS !!! - // - // New methods have to be added at the end. The order and signatures of the existing methods - // have to be preserved. We need to maintain a backward compatibility for this interface to - // allow ildasm to work on SingleCLR. - // - //---------------------------------------------------------------------------------------- - //***************************************************************************** - // return the count of entries of a given kind in a scope - // For example, pass in mdtMethodDef will tell you how many MethodDef + // return the count of entries of a given kind in a scope + // For example, pass in mdtMethodDef will tell you how many MethodDef // contained in a scope //***************************************************************************** STDMETHOD_(ULONG, GetCountWithTokenKind)(// return hresult - DWORD tkKind) PURE; // [IN] pass in the kind of token. + DWORD tkKind) PURE; // [IN] pass in the kind of token. //***************************************************************************** // enumerator for typedef //***************************************************************************** - __checkReturn + __checkReturn STDMETHOD(EnumTypeDefInit)( // return hresult HENUMInternal *phEnum) PURE; // [OUT] buffer to fill for enumerator data - STDMETHOD_(ULONG, EnumTypeDefGetCount)( - HENUMInternal *phEnum) PURE; // [IN] the enumerator to retrieve information - - STDMETHOD_(void, EnumTypeDefReset)( - HENUMInternal *phEnum) PURE; // [IN] the enumerator to retrieve information - - STDMETHOD_(bool, EnumTypeDefNext)( // return hresult - HENUMInternal *phEnum, // [IN] input enum - mdTypeDef *ptd) PURE; // [OUT] return token - - STDMETHOD_(void, EnumTypeDefClose)( - HENUMInternal *phEnum) PURE; // [IN] the enumerator to retrieve information - //***************************************************************************** // enumerator for MethodImpl //***************************************************************************** - __checkReturn + __checkReturn STDMETHOD(EnumMethodImplInit)( // return hresult mdTypeDef td, // [IN] TypeDef over which to scope the enumeration. HENUMInternal *phEnumBody, // [OUT] buffer to fill for enumerator data for MethodBody tokens. HENUMInternal *phEnumDecl) PURE; // [OUT] buffer to fill for enumerator data for MethodDecl tokens. - - STDMETHOD_(ULONG, EnumMethodImplGetCount)( - HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. - HENUMInternal *phEnumDecl) PURE; // [IN] MethodDecl enumerator. - + + ULONG EnumMethodImplGetCount( + HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. + HENUMInternal *phEnumDecl) // [IN] MethodDecl enumerator. + { + return phEnumBody->m_ulCount; + } + STDMETHOD_(void, EnumMethodImplReset)( HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. HENUMInternal *phEnumDecl) PURE; // [IN] MethodDecl enumerator. - - __checkReturn + + __checkReturn STDMETHOD(EnumMethodImplNext)( // return hresult (S_OK = TRUE, S_FALSE = FALSE or error code) HENUMInternal *phEnumBody, // [IN] input enum for MethodBody HENUMInternal *phEnumDecl, // [IN] input enum for MethodDecl mdToken *ptkBody, // [OUT] return token for MethodBody mdToken *ptkDecl) PURE; // [OUT] return token for MethodDecl - + STDMETHOD_(void, EnumMethodImplClose)( HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. HENUMInternal *phEnumDecl) PURE; // [IN] MethodDecl enumerator. - + //***************************************** // Enumerator helpers for memberdef, memberref, interfaceimp, // event, property, exception, param - //***************************************** + //***************************************** - __checkReturn + __checkReturn STDMETHOD(EnumGlobalFunctionsInit)( // return hresult HENUMInternal *phEnum) PURE; // [OUT] buffer to fill for enumerator data - __checkReturn + __checkReturn STDMETHOD(EnumGlobalFieldsInit)( // return hresult HENUMInternal *phEnum) PURE; // [OUT] buffer to fill for enumerator data - __checkReturn + __checkReturn STDMETHOD(EnumInit)( // return S_FALSE if record not found DWORD tkKind, // [IN] which table to work on mdToken tkParent, // [IN] token to scope the search - HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill + HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill - __checkReturn + __checkReturn STDMETHOD(EnumAllInit)( // return S_FALSE if record not found DWORD tkKind, // [IN] which table to work on - HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill + HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill - STDMETHOD_(bool, EnumNext)( - HENUMInternal *phEnum, // [IN] the enumerator to retrieve information - mdToken *ptk) PURE; // [OUT] token to scope the search + bool EnumNext( + HENUMInternal *phEnum, // [IN] the enumerator to retrieve information + mdToken *ptk) // [OUT] token to scope the search + { + _ASSERTE(phEnum && ptk); + if (phEnum->u.m_ulCur >= phEnum->u.m_ulEnd) + return false; - STDMETHOD_(ULONG, EnumGetCount)( - HENUMInternal *phEnum) PURE; // [IN] the enumerator to retrieve information + if ( phEnum->m_EnumType == MDSimpleEnum ) + { + *ptk = phEnum->u.m_ulCur | phEnum->m_tkKind; + phEnum->u.m_ulCur++; + } + else + { + TOKENLIST *pdalist = (TOKENLIST *)&(phEnum->m_cursor); - STDMETHOD_(void, EnumReset)( - HENUMInternal *phEnum) PURE; // [IN] the enumerator to be reset + _ASSERTE( phEnum->m_EnumType == MDDynamicArrayEnum ); + *ptk = *( pdalist->Get(phEnum->u.m_ulCur++) ); + } + return true; + } - STDMETHOD_(void, EnumClose)( - HENUMInternal *phEnum) PURE; // [IN] the enumerator to be closed + ULONG EnumGetCount( + HENUMInternal *phEnum) // [IN] the enumerator to retrieve information + { + _ASSERTE(phEnum); + return phEnum->m_ulCount; + } - //***************************************** - // Enumerator helpers for declsecurity. - //***************************************** - __checkReturn - STDMETHOD(EnumPermissionSetsInit)( // return S_FALSE if record not found - mdToken tkParent, // [IN] token to scope the search - CorDeclSecurity Action, // [IN] Action to scope the search - HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill + void EnumReset( + HENUMInternal *phEnum) // [IN] the enumerator to be reset + { + _ASSERTE(phEnum); + _ASSERTE( phEnum->m_EnumType == MDSimpleEnum || phEnum->m_EnumType == MDDynamicArrayEnum); + + phEnum->u.m_ulCur = phEnum->u.m_ulStart; + } // MDInternalRW::EnumReset + + void EnumClose( + HENUMInternal *phEnum) // [IN] the enumerator to be closed + { + _ASSERTE( phEnum->m_EnumType == MDSimpleEnum || + phEnum->m_EnumType == MDDynamicArrayEnum); + if (phEnum->m_EnumType == MDDynamicArrayEnum) + HENUMInternal::ClearEnum(phEnum); + } //***************************************** // Enumerator helpers for CustomAttribute //***************************************** - __checkReturn + __checkReturn STDMETHOD(EnumCustomAttributeByNameInit)(// return S_FALSE if record not found mdToken tkParent, // [IN] token to scope the search LPCSTR szName, // [IN] CustomAttribute's name to scope the search - HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill + HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill //***************************************** // Nagivator helper to navigate back to the parent token given a token. @@ -446,43 +448,43 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) // mdProperty mdTypeDef // mdEvent mdTypeDef // - //***************************************** - __checkReturn + //***************************************** + __checkReturn STDMETHOD(GetParentToken)( mdToken tkChild, // [IN] given child token mdToken *ptkParent) PURE; // [OUT] returning parent //***************************************** // Custom value helpers - //***************************************** - __checkReturn + //***************************************** + __checkReturn STDMETHOD(GetCustomAttributeProps)( // S_OK or error. mdCustomAttribute at, // [IN] The attribute. mdToken *ptkType) PURE; // [OUT] Put attribute type here. - - __checkReturn + + __checkReturn STDMETHOD(GetCustomAttributeAsBlob)( mdCustomAttribute cv, // [IN] given custom value token void const **ppBlob, // [OUT] return the pointer to internal blob ULONG *pcbSize) PURE; // [OUT] return the size of the blob - + // returned void in v1.0/v1.1 - __checkReturn + __checkReturn STDMETHOD (GetScopeProps)( LPCSTR *pszName, // [OUT] scope name GUID *pmvid) PURE; // [OUT] version id - - // finding a particular method - __checkReturn + + // finding a particular method + __checkReturn STDMETHOD(FindMethodDef)( mdTypeDef classdef, // [IN] given typedef LPCSTR szName, // [IN] member name PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob mdMethodDef *pmd) PURE; // [OUT] matching memberdef - + // return a iSeq's param given a MethodDef - __checkReturn + __checkReturn STDMETHOD(FindParamOfMethod)( // S_OK or error. mdMethodDef md, // [IN] The owning method of the param. ULONG iSeq, // [IN] The sequence # of the param. @@ -495,56 +497,56 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) //***************************************** // return the name and namespace of typedef - __checkReturn + __checkReturn STDMETHOD(GetNameOfTypeDef)( mdTypeDef classdef, // given classdef LPCSTR *pszname, // return class name(unqualified) LPCSTR *psznamespace) PURE; // return the name space name - - __checkReturn + + __checkReturn STDMETHOD(GetIsDualOfTypeDef)( mdTypeDef classdef, // [IN] given classdef. ULONG *pDual) PURE; // [OUT] return dual flag here. - - __checkReturn + + __checkReturn STDMETHOD(GetIfaceTypeOfTypeDef)( mdTypeDef classdef, // [IN] given classdef. ULONG *pIface) PURE; // [OUT] 0=dual, 1=vtable, 2=dispinterface - + // get the name of either methoddef - __checkReturn + __checkReturn STDMETHOD(GetNameOfMethodDef)( // return the name of the memberdef in UTF8 mdMethodDef md, // given memberdef LPCSTR *pszName) PURE; - - __checkReturn + + __checkReturn STDMETHOD(GetNameAndSigOfMethodDef)( mdMethodDef methoddef, // [IN] given memberdef PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of CLR signature ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob LPCSTR *pszName) PURE; - + // return the name of a FieldDef - __checkReturn + __checkReturn STDMETHOD(GetNameOfFieldDef)( mdFieldDef fd, // given memberdef LPCSTR *pszName) PURE; - + // return the name of typeref - __checkReturn + __checkReturn STDMETHOD(GetNameOfTypeRef)( mdTypeRef classref, // [IN] given typeref LPCSTR *psznamespace, // [OUT] return typeref name LPCSTR *pszname) PURE; // [OUT] return typeref namespace - + // return the resolutionscope of typeref - __checkReturn + __checkReturn STDMETHOD(GetResolutionScopeOfTypeRef)( mdTypeRef classref, // given classref mdToken *ptkResolutionScope) PURE; - + // Find the type token given the name. - __checkReturn + __checkReturn STDMETHOD(FindTypeRefByName)( LPCSTR szNamespace, // [IN] Namespace for the TypeRef. LPCSTR szName, // [IN] Name of the TypeRef. @@ -553,117 +555,117 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) // return the TypeDef properties // returned void in v1.0/v1.1 - __checkReturn - STDMETHOD(GetTypeDefProps)( + __checkReturn + STDMETHOD(GetTypeDefProps)( mdTypeDef classdef, // given classdef DWORD *pdwAttr, // return flags on class, tdPublic, tdAbstract mdToken *ptkExtends) PURE; // [OUT] Put base class TypeDef/TypeRef here // return the item's guid - __checkReturn - STDMETHOD(GetItemGuid)( + __checkReturn + STDMETHOD(GetItemGuid)( mdToken tkObj, // [IN] given item. CLSID *pGuid) PURE; // [out[ put guid here. // Get enclosing class of the NestedClass. - __checkReturn + __checkReturn STDMETHOD(GetNestedClassProps)( // S_OK or error mdTypeDef tkNestedClass, // [IN] NestedClass token. mdTypeDef *ptkEnclosingClass) PURE; // [OUT] EnclosingClass token. - + // Get count of Nested classes given the enclosing class. - __checkReturn + __checkReturn STDMETHOD(GetCountNestedClasses)( // return count of Nested classes. mdTypeDef tkEnclosingClass, // Enclosing class. ULONG *pcNestedClassesCount) PURE; - + // Return array of Nested classes given the enclosing class. - __checkReturn + __checkReturn STDMETHOD(GetNestedClasses)( // Return actual count. mdTypeDef tkEnclosingClass, // [IN] Enclosing class. mdTypeDef *rNestedClasses, // [OUT] Array of nested class tokens. ULONG ulNestedClasses, // [IN] Size of array. ULONG *pcNestedClasses) PURE; - + // return the ModuleRef properties // returned void in v1.0/v1.1 - __checkReturn + __checkReturn STDMETHOD(GetModuleRefProps)( mdModuleRef mur, // [IN] moduleref token LPCSTR *pszName) PURE; // [OUT] buffer to fill with the moduleref name - + //***************************************** // // GetSig* functions // //***************************************** - __checkReturn + __checkReturn STDMETHOD(GetSigOfMethodDef)( mdMethodDef tkMethodDef, // [IN] given MethodDef ULONG * pcbSigBlob, // [OUT] count of bytes in the signature blob PCCOR_SIGNATURE * ppSig) PURE; - - __checkReturn + + __checkReturn STDMETHOD(GetSigOfFieldDef)( mdFieldDef tkFieldDef, // [IN] given FieldDef ULONG * pcbSigBlob, // [OUT] count of bytes in the signature blob PCCOR_SIGNATURE * ppSig) PURE; - - __checkReturn + + __checkReturn STDMETHOD(GetSigFromToken)( mdToken tk, // FieldDef, MethodDef, Signature or TypeSpec token - ULONG * pcbSig, + ULONG * pcbSig, PCCOR_SIGNATURE * ppSig) PURE; - - - + + + //***************************************** // get method property //***************************************** - __checkReturn + __checkReturn STDMETHOD(GetMethodDefProps)( mdMethodDef md, // The method for which to get props. DWORD *pdwFlags) PURE; - + //***************************************** // return method implementation informaiton, like RVA and implflags //***************************************** // returned void in v1.0/v1.1 - __checkReturn + __checkReturn STDMETHOD(GetMethodImplProps)( mdToken tk, // [IN] MethodDef ULONG *pulCodeRVA, // [OUT] CodeRVA DWORD *pdwImplFlags) PURE; // [OUT] Impl. Flags - + //***************************************** // return method implementation informaiton, like RVA and implflags //***************************************** - __checkReturn + __checkReturn STDMETHOD(GetFieldRVA)( - mdFieldDef fd, // [IN] fielddef + mdFieldDef fd, // [IN] fielddef ULONG *pulCodeRVA) PURE; // [OUT] CodeRVA - + //***************************************** // get field property //***************************************** - __checkReturn + __checkReturn STDMETHOD(GetFieldDefProps)( mdFieldDef fd, // [IN] given fielddef DWORD *pdwFlags) PURE; // [OUT] return fdPublic, fdPrive, etc flags - + //***************************************************************************** // return default value of a token(could be paramdef, fielddef, or property //***************************************************************************** - __checkReturn - STDMETHOD(GetDefaultValue)( + __checkReturn + STDMETHOD(GetDefaultValue)( mdToken tk, // [IN] given FieldDef, ParamDef, or Property MDDefaultValue *pDefaultValue) PURE;// [OUT] default value to fill - - + + //***************************************** // get dispid of a MethodDef or a FieldDef //***************************************** - __checkReturn + __checkReturn STDMETHOD(GetDispIdOfMemberDef)( // return hresult mdToken tk, // [IN] given methoddef or fielddef ULONG *pDispid) PURE; // [OUT] Put the dispid here. @@ -671,7 +673,7 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) //***************************************** // return TypeRef/TypeDef given an InterfaceImpl token //***************************************** - __checkReturn + __checkReturn STDMETHOD(GetTypeOfInterfaceImpl)( // return the TypeRef/typedef token for the interfaceimpl mdInterfaceImpl iiImpl, // given a interfaceimpl mdToken *ptkType) PURE; @@ -679,7 +681,7 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) //***************************************** // look up function for TypeDef //***************************************** - __checkReturn + __checkReturn STDMETHOD(FindTypeDef)( LPCSTR szNamespace, // [IN] Namespace for the TypeDef. LPCSTR szName, // [IN] Name of the TypeDef. @@ -689,54 +691,54 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) //***************************************** // return name and sig of a memberref //***************************************** - __checkReturn + __checkReturn STDMETHOD(GetNameAndSigOfMemberRef)( // return name here mdMemberRef memberref, // given memberref PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of CLR signature ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob LPCSTR *pszName) PURE; - + //***************************************************************************** // Given memberref, return the parent. It can be TypeRef, ModuleRef, MethodDef //***************************************************************************** - __checkReturn + __checkReturn STDMETHOD(GetParentOfMemberRef)( mdMemberRef memberref, // given memberref mdToken *ptkParent) PURE; // return the parent token - - __checkReturn + + __checkReturn STDMETHOD(GetParamDefProps)( mdParamDef paramdef, // given a paramdef USHORT *pusSequence, // [OUT] slot number for this parameter DWORD *pdwAttr, // [OUT] flags LPCSTR *pszName) PURE; // [OUT] return the name of the parameter - - __checkReturn + + __checkReturn STDMETHOD(GetPropertyInfoForMethodDef)( // Result. mdMethodDef md, // [IN] memberdef mdProperty *ppd, // [OUT] put property token here LPCSTR *pName, // [OUT] put pointer to name here ULONG *pSemantic) PURE; // [OUT] put semantic here - + //***************************************** // class layout/sequence information //***************************************** - __checkReturn + __checkReturn STDMETHOD(GetClassPackSize)( // return error if class doesn't have packsize mdTypeDef td, // [IN] give typedef ULONG *pdwPackSize) PURE; // [OUT] 1, 2, 4, 8, or 16 - __checkReturn + __checkReturn STDMETHOD(GetClassTotalSize)( // return error if class doesn't have total size info mdTypeDef td, // [IN] give typedef ULONG *pdwClassSize) PURE; // [OUT] return the total size of the class - __checkReturn + __checkReturn STDMETHOD(GetClassLayoutInit)( mdTypeDef td, // [IN] give typedef MD_CLASS_LAYOUT *pLayout) PURE; // [OUT] set up the status of query here - __checkReturn + __checkReturn STDMETHOD(GetClassLayoutNext)( MD_CLASS_LAYOUT *pLayout, // [IN|OUT] set up the status of query here mdFieldDef *pfd, // [OUT] return the fielddef @@ -745,7 +747,7 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) //***************************************** // marshal information of a field //***************************************** - __checkReturn + __checkReturn STDMETHOD(GetFieldMarshal)( // return error if no native type associate with the token mdFieldDef fd, // [IN] given fielddef PCCOR_SIGNATURE *pSigNativeType, // [OUT] the native type signature @@ -756,14 +758,14 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) // property APIs //***************************************** // find a property by name - __checkReturn + __checkReturn STDMETHOD(FindProperty)( mdTypeDef td, // [IN] given a typdef LPCSTR szPropName, // [IN] property name mdProperty *pProp) PURE; // [OUT] return property token // returned void in v1.0/v1.1 - __checkReturn + __checkReturn STDMETHOD(GetPropertyProps)( mdProperty prop, // [IN] property token LPCSTR *szProperty, // [OUT] property name @@ -774,14 +776,14 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) //********************************** // Event APIs //********************************** - __checkReturn + __checkReturn STDMETHOD(FindEvent)( mdTypeDef td, // [IN] given a typdef LPCSTR szEventName, // [IN] event name mdEvent *pEvent) PURE; // [OUT] return event token // returned void in v1.0/v1.1 - __checkReturn + __checkReturn STDMETHOD(GetEventProps)( mdEvent ev, // [IN] event token LPCSTR *pszEvent, // [OUT] Event name @@ -792,20 +794,20 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) //********************************** // find a particular associate of a property or an event //********************************** - __checkReturn + __checkReturn STDMETHOD(FindAssociate)( mdToken evprop, // [IN] given a property or event token DWORD associate, // [IN] given a associate semantics(setter, getter, testdefault, reset, AddOn, RemoveOn, Fire) - mdMethodDef *pmd) PURE; // [OUT] return method def token + mdMethodDef *pmd) PURE; // [OUT] return method def token // Note, void function in v1.0/v1.1 - __checkReturn + __checkReturn STDMETHOD(EnumAssociateInit)( mdToken evprop, // [IN] given a property or an event token HENUMInternal *phEnum) PURE; // [OUT] cursor to hold the query result // returned void in v1.0/v1.1 - __checkReturn + __checkReturn STDMETHOD(GetAllAssociates)( HENUMInternal *phEnum, // [IN] query result form GetPropertyAssociateCounts ASSOCIATE_RECORD *pAssociateRec, // [OUT] struct to fill for output @@ -816,7 +818,7 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) // Get info about a PermissionSet. //********************************** // returned void in v1.0/v1.1 - __checkReturn + __checkReturn STDMETHOD(GetPermissionSetProps)( mdPermission pm, // [IN] the permission token. DWORD *pdwAction, // [OUT] CorDeclSecurity. @@ -827,17 +829,17 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) // Get the String given the String token. // Returns a pointer to the string, or NULL in case of error. //**************************************** - __checkReturn + __checkReturn STDMETHOD(GetUserString)( mdString stk, // [IN] the string token. ULONG *pchString, // [OUT] count of characters in the string. BOOL *pbIs80Plus, // [OUT] specifies where there are extended characters >= 0x80. LPCWSTR *pwszUserString) PURE; - + //***************************************************************************** // p-invoke APIs. //***************************************************************************** - __checkReturn + __checkReturn STDMETHOD(GetPinvokeMap)( mdToken tk, // [IN] FieldDef, MethodDef. DWORD *pdwMappingFlags, // [OUT] Flags used for mapping. @@ -847,7 +849,7 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) //***************************************************************************** // helpers to convert a text signature to a com format //***************************************************************************** - __checkReturn + __checkReturn STDMETHOD(ConvertTextSigToComSig)( // Return hresult. BOOL fCreateTrIfNotFound, // [IN] create typeref if not found LPCSTR pSignature, // [IN] class file format signature @@ -858,7 +860,7 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) // Assembly MetaData APIs. //***************************************************************************** // returned void in v1.0/v1.1 - __checkReturn + __checkReturn STDMETHOD(GetAssemblyProps)( mdAssembly mda, // [IN] The Assembly for which to get the properties. const void **ppbPublicKey, // [OUT] Pointer to the public key. @@ -869,7 +871,7 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) DWORD *pdwAssemblyFlags) PURE;// [OUT] Flags. // returned void in v1.0/v1.1 - __checkReturn + __checkReturn STDMETHOD(GetAssemblyRefProps)( mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties. const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token. @@ -881,7 +883,7 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) DWORD *pdwAssemblyRefFlags) PURE; // [OUT] Flags. // returned void in v1.0/v1.1 - __checkReturn + __checkReturn STDMETHOD(GetFileProps)( mdFile mdf, // [IN] The File for which to get the properties. LPCSTR *pszName, // [OUT] Buffer to fill with name. @@ -890,7 +892,7 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) DWORD *pdwFileFlags) PURE; // [OUT] Flags. // returned void in v1.0/v1.1 - __checkReturn + __checkReturn STDMETHOD(GetExportedTypeProps)( mdExportedType mdct, // [IN] The ExportedType for which to get the properties. LPCSTR *pszNamespace, // [OUT] Namespace. @@ -900,7 +902,7 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) DWORD *pdwExportedTypeFlags) PURE; // [OUT] Flags. // returned void in v1.0/v1.1 - __checkReturn + __checkReturn STDMETHOD(GetManifestResourceProps)( mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties. LPCSTR *pszName, // [OUT] Buffer to fill with name. @@ -908,23 +910,23 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file. DWORD *pdwResourceFlags) PURE;// [OUT] Flags. - __checkReturn + __checkReturn STDMETHOD(FindExportedTypeByName)( // S_OK or error - LPCSTR szNamespace, // [IN] Namespace of the ExportedType. - LPCSTR szName, // [IN] Name of the ExportedType. + LPCSTR szNamespace, // [IN] Namespace of the ExportedType. + LPCSTR szName, // [IN] Name of the ExportedType. mdExportedType tkEnclosingType, // [IN] ExportedType for the enclosing class. mdExportedType *pmct) PURE; // [OUT] Put ExportedType token here. - __checkReturn + __checkReturn STDMETHOD(FindManifestResourceByName)( // S_OK or error - LPCSTR szName, // [IN] Name of the ManifestResource. + LPCSTR szName, // [IN] Name of the ManifestResource. mdManifestResource *pmmr) PURE; // [OUT] Put ManifestResource token here. - __checkReturn + __checkReturn STDMETHOD(GetAssemblyFromScope)( // S_OK or error mdAssembly *ptkAssembly) PURE; // [OUT] Put token here. - __checkReturn + __checkReturn STDMETHOD(GetCustomAttributeByName)( // S_OK or error mdToken tkObj, // [IN] Object with Custom Attribute. LPCUTF8 szName, // [IN] Name of desired Custom Attribute. @@ -932,21 +934,21 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) ULONG *pcbData) PURE; // [OUT] Put size of data here. // Note: The return type of this method was void in v1 - __checkReturn + __checkReturn STDMETHOD(GetTypeSpecFromToken)( // S_OK or error. mdTypeSpec typespec, // [IN] Signature token. PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token. ULONG *pcbSig) PURE; // [OUT] return size of signature. - __checkReturn + __checkReturn STDMETHOD(SetUserContextData)( // S_OK or E_NOTIMPL IUnknown *pIUnk) PURE; // The user context. - __checkReturn + __checkReturn STDMETHOD_(BOOL, IsValidToken)( // True or False. mdToken tk) PURE; // [IN] Given token. - __checkReturn + __checkReturn STDMETHOD(TranslateSigWithScope)( IMDInternalImport *pAssemImport, // [IN] import assembly scope. const void *pbHashValue, // [IN] hash value for the import assembly. @@ -962,11 +964,11 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) ) PURE; STDMETHOD_(IUnknown *, GetCachedPublicInterface)(BOOL fWithLock) PURE; // return the cached public interface - __checkReturn + __checkReturn STDMETHOD(SetCachedPublicInterface)(IUnknown *pUnk) PURE; // no return value STDMETHOD_(UTSemReadWrite*, GetReaderWriterLock)() PURE; // return the reader writer lock - __checkReturn - STDMETHOD(SetReaderWriterLock)(UTSemReadWrite * pSem) PURE; + __checkReturn + STDMETHOD(SetReaderWriterLock)(UTSemReadWrite * pSem) PURE; STDMETHOD_(mdModule, GetModuleFromScope)() PURE; // [OUT] Put mdModule token here. @@ -974,8 +976,8 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) //----------------------------------------------------------------- // Additional custom methods - // finding a particular method - __checkReturn + // finding a particular method + __checkReturn STDMETHOD(FindMethodDefUsingCompare)( mdTypeDef classdef, // [IN] given typedef LPCSTR szName, // [IN] member name @@ -990,25 +992,25 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) //***************************************** // return a field offset for a given field //***************************************** - __checkReturn + __checkReturn STDMETHOD(GetFieldOffset)( - mdFieldDef fd, // [IN] fielddef + mdFieldDef fd, // [IN] fielddef ULONG *pulOffset) PURE; // [OUT] FieldOffset - __checkReturn + __checkReturn STDMETHOD(GetMethodSpecProps)( mdMethodSpec ms, // [IN] The method instantiation mdToken *tkParent, // [OUT] MethodDef or MemberRef - PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data - ULONG *pcbSigBlob) PURE; // [OUT] actual size of signature blob + PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data + ULONG *pcbSigBlob) PURE; // [OUT] actual size of signature blob - __checkReturn + __checkReturn STDMETHOD(GetTableInfoWithIndex)( ULONG index, // [IN] pass in the table index void **pTable, // [OUT] pointer to table at index void **pTableSize) PURE; // [OUT] size of table at index - __checkReturn + __checkReturn STDMETHOD(ApplyEditAndContinue)( void *pDeltaMD, // [IN] the delta metadata ULONG cbDeltaMD, // [IN] length of pData @@ -1017,16 +1019,16 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) //********************************** // Generics APIs //********************************** - __checkReturn + __checkReturn STDMETHOD(GetGenericParamProps)( // S_OK or error. mdGenericParam rd, // [IN] The type parameter ULONG* pulSequence, // [OUT] Parameter sequence number - DWORD* pdwAttr, // [OUT] Type parameter flags (for future use) - mdToken *ptOwner, // [OUT] The owner (TypeDef or MethodDef) + DWORD* pdwAttr, // [OUT] Type parameter flags (for future use) + mdToken *ptOwner, // [OUT] The owner (TypeDef or MethodDef) DWORD *reserved, // [OUT] The kind (TypeDef/Ref/Spec, for future use) LPCSTR *szName) PURE; // [OUT] The name - __checkReturn + __checkReturn STDMETHOD(GetGenericParamConstraintProps)( // S_OK or error. mdGenericParamConstraint rd, // [IN] The constraint token mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained @@ -1037,26 +1039,12 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) // NOTE: if the scope has never been saved, it will not have a built-for // version, and an empty string will be returned. //***************************************************************************** - __checkReturn + __checkReturn STDMETHOD(GetVersionString)( // S_OK or error. LPCSTR *pVer) PURE; // [OUT] Put version string here. - __checkReturn - STDMETHOD(SafeAndSlowEnumCustomAttributeByNameInit)(// return S_FALSE if record not found - mdToken tkParent, // [IN] token to scope the search - LPCSTR szName, // [IN] CustomAttribute's name to scope the search - HENUMInternal *phEnum) PURE; // [OUT] The enumerator - - __checkReturn - STDMETHOD(SafeAndSlowEnumCustomAttributeByNameNext)(// return S_FALSE if record not found - mdToken tkParent, // [IN] token to scope the search - LPCSTR szName, // [IN] CustomAttribute's name to scope the search - HENUMInternal *phEnum, // [IN] The enumerator - mdCustomAttribute *mdAttribute) PURE; // [OUT] The custom attribute that was found - - - __checkReturn + __checkReturn STDMETHOD(GetTypeDefRefTokenInTypeSpec)(// return S_FALSE if enclosing type does not have a token mdTypeSpec tkTypeSpec, // [IN] TypeSpec token to look at mdToken *tkEnclosedToken) PURE; // [OUT] The enclosed type token @@ -1067,7 +1055,7 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) STDMETHOD_(DWORD, GetMetadataStreamVersion)() PURE; //returns DWORD with major version of // MD stream in senior word and minor version--in junior word - __checkReturn + __checkReturn STDMETHOD(GetNameOfCustomAttribute)(// S_OK or error mdCustomAttribute mdAttribute, // [IN] The Custom Attribute LPCUTF8 *pszNamespace, // [OUT] Namespace of Custom Attribute. @@ -1090,13 +1078,13 @@ DECLARE_INTERFACE_(IMDInternalImport, IUnknown) //---------------------------------------------------------------------------------------- // !!! READ THIS !!! - // - // New methods have to be added at the end. The order and signatures of the existing methods + // + // New methods have to be added at the end. The order and signatures of the existing methods // have to be preserved. We need to maintain a backward compatibility for this interface to // allow ildasm to work on SingleCLR. // //---------------------------------------------------------------------------------------- - + }; // IMDInternalImport @@ -1108,7 +1096,7 @@ EXTERN_GUID(IID_IMDInternalImportENC, 0xe03d7730, 0xd7e3, 0x11d2, 0x8c, 0xd, 0x0 DECLARE_INTERFACE_(IMDInternalImportENC, IMDInternalImport) { private: - using IMDInternalImport::ApplyEditAndContinue; + using IMDInternalImport::ApplyEditAndContinue; public: // ENC only methods here. STDMETHOD(ApplyEditAndContinue)( // S_OK or error. @@ -1137,8 +1125,12 @@ DECLARE_INTERFACE_(IMDInternalEmit, IUnknown) #ifdef FEATURE_METADATA_CUSTOM_DATA_SOURCE struct IMDCustomDataSource; - -#include "../md/inc/metamodel.h" +class CMiniMdSchema; +struct CMiniTableDef; +namespace MetaData +{ + class DataBlob; +} // {CC0C8F7A-A00B-493D-80B6-CE0C92491670} EXTERN_GUID(IID_IMDCustomDataSource, 0xcc0c8f7a, 0xa00b, 0x493d, 0x80, 0xb6, 0xce, 0xc, 0x92, 0x49, 0x16, 0x70); @@ -1182,11 +1174,42 @@ struct ICorDebugDataTarget; HRESULT CreateRemoteMDInternalRWSource(TADDR mdInternalRWRemoteAddress, ICorDebugDataTarget* pDataTarget, DWORD defines, DWORD dataStructureVersion, IMDCustomDataSource** ppDataSource); #endif +enum MetaDataReorderingOptions { + NoReordering=0x0, + ReArrangeStringPool=0x1 +}; + +#ifdef FEATURE_PREJIT + +// {0702E333-8D64-4ca7-B564-4AA56B1FCEA3} +EXTERN_GUID(IID_IMetaDataCorProfileData, 0x702e333, 0x8d64, 0x4ca7, 0xb5, 0x64, 0x4a, 0xa5, 0x6b, 0x1f, 0xce, 0xa3 ); + +#undef INTERFACE +#define INTERFACE IMetaDataCorProfileData +DECLARE_INTERFACE_(IMetaDataCorProfileData, IUnknown) +{ + STDMETHOD(SetCorProfileData)( + CorProfileData *pProfileData) PURE; // [IN] Pointer to profile data +}; + +// {2B464817-C0F6-454e-99E7-C352D8384D7B} +EXTERN_GUID(IID_IMDInternalMetadataReorderingOptions, 0x2B464817, 0xC0F6, 0x454e, 0x99, 0xE7, 0xC3, 0x52, 0xD8, 0x38, 0x4D, 0x7B ); + +#undef INTERFACE +#define INTERFACE IMDInternalMetadataReorderingOptions +DECLARE_INTERFACE_(IMDInternalMetadataReorderingOptions, IUnknown) +{ + STDMETHOD(SetMetaDataReorderingOptions)( + MetaDataReorderingOptions options) PURE; // [IN] metadata reordering options +}; + +#endif //FEATURE_PREJIT + #ifdef __HOLDER_H_ void DECLSPEC_NORETURN ThrowHR(HRESULT hr); -// This wrapper class ensures that the HENUMInternal is EnumTypeDefClose'd no matter how the scope is exited. +// This wrapper class ensures that the HENUMInternal is EnumClose'd no matter how the scope is exited. class HENUMTypeDefInternalHolder { public: @@ -1235,7 +1258,7 @@ public: if (m_fAcquired) { - m_pInternalImport->EnumTypeDefClose(&m_hEnum); + m_pInternalImport->EnumClose(&m_hEnum); } } @@ -1274,28 +1297,6 @@ public: m_fAcquired = FALSE; } - FORCEINLINE BOOL EnumPermissionSetsInit(mdToken tkToken, CorDeclSecurity action) - { - CONTRACTL { - THROWS; - } CONTRACTL_END; - - _ASSERTE(!m_fAcquired); - HRESULT hr = m_pInternalImport->EnumPermissionSetsInit(tkToken, action, &m_hEnum); - - if (hr == CLDB_E_RECORD_NOTFOUND) - return FALSE; - - if (FAILED(hr) ) - { - ThrowHR(hr); - } - - m_fAcquired = TRUE; - - return TRUE; - } - FORCEINLINE VOID EnumGlobalFunctionsInit() { CONTRACTL { @@ -1354,7 +1355,7 @@ public: IfFailThrow(m_pInternalImport->EnumAssociateInit(tkParent, &m_hEnum)); m_fAcquired = TRUE; } - + FORCEINLINE VOID EnumInit(DWORD tkKind, // [IN] which table to work on mdToken tkParent // [IN] token to scope the search ) @@ -1370,7 +1371,7 @@ public: } } - __checkReturn + __checkReturn FORCEINLINE HRESULT EnumInitNoThrow(DWORD tkKind, // [IN] which table to work on mdToken tkParent // [IN] token to scope the search ) @@ -1437,26 +1438,26 @@ public: return m_pInternalImport->EnumReset(&m_hEnum); } - + FORCEINLINE ~HENUMInternalHolder() { WRAPPER_NO_CONTRACT; - + if (m_fAcquired) { // Ignore the error (void)m_pInternalImport->EnumClose(&m_hEnum); } } - + FORCEINLINE HENUMInternal* operator& () { LIMITED_METHOD_CONTRACT; - + _ASSERTE(m_fAcquired); return &m_hEnum; } - + private: FORCEINLINE HENUMInternalHolder(const HENUMInternalHolder &) { @@ -1484,14 +1485,14 @@ class HENUMInternalMethodImplHolder : protected HENUMInternalHolder FORCEINLINE ~HENUMInternalMethodImplHolder() { WRAPPER_NO_CONTRACT; - + if (m_fAcquired) { // Ignore the error (void)m_pInternalImport->EnumClose(&m_hEnum2); } } - + FORCEINLINE void EnumMethodImplInit(mdToken tkParent // [IN] token to scope the search ) { @@ -1505,8 +1506,8 @@ class HENUMInternalMethodImplHolder : protected HENUMInternalHolder ThrowHR(hr); } } - - __checkReturn + + __checkReturn FORCEINLINE HRESULT EnumMethodImplInitNoThrow(mdToken tkParent // [IN] token to scope the search ) { @@ -1523,9 +1524,9 @@ class HENUMInternalMethodImplHolder : protected HENUMInternalHolder return hr; } - __checkReturn + __checkReturn FORCEINLINE HRESULT EnumMethodImplNext( - mdToken *ptkImpl, + mdToken *ptkImpl, mdToken *ptkDecl) { CONTRACTL { @@ -1533,7 +1534,7 @@ class HENUMInternalMethodImplHolder : protected HENUMInternalHolder GC_NOTRIGGER; CONSISTENCY_CHECK(m_fAcquired); } CONTRACTL_END; - + return m_pInternalImport->EnumMethodImplNext(&m_hEnum, &m_hEnum2, ptkImpl, ptkDecl); } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/metadataexports.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/metadataexports.h index 159af69..4128347 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/metadataexports.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/metadataexports.h @@ -5,10 +5,10 @@ // MDCommon.h // -// +// // Header for functions exported by metadata. These are consumed 2 ways: // 1. Mscoree provides public exports that plumb to some of these functions to invoke these dynamically. -// 2. Standalone metadata (statically linked) +// 2. Standalone metadata (statically linked) // //***************************************************************************** @@ -25,8 +25,8 @@ STDAPI MetaDataDllGetClassObject(REFCLSID rclsid, REFIID riid, void ** ppv); HRESULT InternalCreateMetaDataDispenser(REFIID riid, void ** pMetaDataDispenserOut); STDAPI GetMDInternalInterface( - LPVOID pData, - ULONG cbData, + LPVOID pData, + ULONG cbData, DWORD flags, // [IN] MDInternal_OpenForRead or MDInternal_OpenForENC REFIID riid, // [in] The interface desired. void **ppIUnk); // [out] Return interface on success. @@ -50,7 +50,7 @@ STDAPI MDReOpenMetaDataWithMemoryEx( void *pImport, // [IN] Given scope. public interfaces LPCVOID pData, // [in] Location of scope data. ULONG cbData, // [in] Size of the data pointed to by pData. - DWORD dwReOpenFlags); // [in] ReOpen flags + DWORD dwReOpenFlags); // [in] ReOpen flags diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/metadatatracker.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/metadatatracker.h index 90db242..8a22bd7 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/metadatatracker.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/metadatatracker.h @@ -48,7 +48,7 @@ class MetaDataTracker SIZE_T m_mdSectionRowSize[NUM_MD_SECTIONS]; BOOL m_bActivated; - static BOOL s_bEnabled; + static BOOL s_bEnabled; static MetaDataTracker *m_MDTrackers; @@ -72,12 +72,12 @@ public: m_ModuleName = NULL; size_t len = wcslen(modName); - m_ModuleName = new wchar_t[len + 1]; - NewArrayHolder moduleNameHolder(m_ModuleName); - wcscpy_s((wchar_t *)m_ModuleName, len + 1, (wchar_t *)modName); + m_ModuleName = new WCHAR[len + 1]; + NewArrayHolder moduleNameHolder(m_ModuleName); + wcscpy_s((WCHAR *)m_ModuleName, len + 1, (WCHAR *)modName); m_MetadataBase = baseAddress; - m_MetadataSize = mdSize; + m_MetadataSize = mdSize; m_next = m_MDTrackers; m_MDTrackers = this; @@ -158,7 +158,7 @@ public: if (!Enabled()) return; - + MetaDataTracker *mdMod = m_MDTrackers; while( mdMod) { @@ -218,7 +218,7 @@ public: if (!Enabled()) return NULL; - + MetaDataTracker *mdMod = m_MDTrackers; while( mdMod) { @@ -296,7 +296,7 @@ public: private: - + // *************************************************************************** // Helper functions // *************************************************************************** @@ -310,7 +310,7 @@ private: if (address < m_MetadataBase || address >= (m_MetadataBase + m_MetadataSize)) return FALSE; - // This address range belongs to us but the tracker is not activated. + // This address range belongs to us but the tracker is not activated. if (!IsActivated()) { // _ASSERTE (!"Metadata Tracker not active but trying to access metadata"); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/metahost.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/metahost.idl index 1ed19b5..6aeef38 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/metahost.idl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/metahost.idl @@ -101,8 +101,8 @@ interface ICLRMetaHost : IUnknown **********************************************************************************/ HRESULT GetVersionFromFile( [in] LPCWSTR pwzFilePath, - [out, size_is(*pcchBuffer), annotation("_Out_writes_all_(*pcchBuffer)")] - LPWSTR pwzBuffer, + [out, size_is(*pcchBuffer), annotation("_Out_writes_all_(*pcchBuffer)")] + LPWSTR pwzBuffer, [in, out] DWORD *pcchBuffer); /********************************************************************************** @@ -386,7 +386,7 @@ interface ICLRDebugging : IUnknown ** interfaces have been released and no thread is currently within a call to ** ** OpenVirtualProcess. ** ** Arguments: ** - ** hModule - A module handle previously provided by the ** + ** hModule - A module handle previously provided by the ** ** ICLRDebuggingLibraryProvider used in OpenVirtualProcess ** ** Returns: ** ** S_OK if the module can be unloaded now ** @@ -422,8 +422,8 @@ interface ICLRRuntimeInfo : IUnknown ** GetCORVersion ** **********************************************************************************/ HRESULT GetVersionString( - [out, size_is(*pcchBuffer), annotation("_Out_writes_all_opt_(*pcchBuffer)")] - LPWSTR pwzBuffer, + [out, size_is(*pcchBuffer), annotation("_Out_writes_all_opt_(*pcchBuffer)")] + LPWSTR pwzBuffer, [in, out] DWORD *pcchBuffer); /********************************************************************************** @@ -431,8 +431,8 @@ interface ICLRRuntimeInfo : IUnknown ** Supersedes: GetCORSystemDirectory ** **********************************************************************************/ HRESULT GetRuntimeDirectory( - [out, size_is(*pcchBuffer), annotation("_Out_writes_all_(*pcchBuffer)")] - LPWSTR pwzBuffer, + [out, size_is(*pcchBuffer), annotation("_Out_writes_all_(*pcchBuffer)")] + LPWSTR pwzBuffer, [in, out] DWORD *pcchBuffer); /********************************************************************************** @@ -451,9 +451,9 @@ interface ICLRRuntimeInfo : IUnknown ** Supersedes: LoadStringRC, LoadStringRCEx ** **********************************************************************************/ HRESULT LoadErrorString( - [in] UINT iResourceID, - [out, size_is(*pcchBuffer), annotation("_Out_writes_all_(*pcchBuffer)")] - LPWSTR pwzBuffer, + [in] UINT iResourceID, + [out, size_is(*pcchBuffer), annotation("_Out_writes_all_(*pcchBuffer)")] + LPWSTR pwzBuffer, [in, out] DWORD *pcchBuffer, [in, lcid] LONG iLocaleID); @@ -462,7 +462,7 @@ interface ICLRRuntimeInfo : IUnknown ** Supersedes: LoadLibraryShim ** **********************************************************************************/ HRESULT LoadLibrary( - [in] LPCWSTR pwzDllName, + [in] LPCWSTR pwzDllName, [out, retval] HMODULE *phndModule); /********************************************************************************** @@ -473,7 +473,7 @@ interface ICLRRuntimeInfo : IUnknown ** Supersedes: GetRealProcAddress ** **********************************************************************************/ HRESULT GetProcAddress( - [in] LPCSTR pszProcName, + [in] LPCSTR pszProcName, [out, retval] LPVOID *ppProc); /********************************************************************************** @@ -522,7 +522,7 @@ interface ICLRRuntimeInfo : IUnknown HRESULT GetDefaultStartupFlags( [out] DWORD *pdwStartupFlags, [out, size_is(*pcchHostConfigFile), annotation("_Out_writes_all_opt_(*pcchHostConfigFile)")] - LPWSTR pwzHostConfigFile, + LPWSTR pwzHostConfigFile, [in, out] DWORD *pcchHostConfigFile); /********************************************************************************** diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/metamodelpub.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/metamodelpub.h index ba68ae0..83cc9c6 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/metamodelpub.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/metamodelpub.h @@ -3,9 +3,9 @@ // See the LICENSE file in the project root for more information. //***************************************************************************** // MetaModelPub.h -- header file for Common Language Runtime metadata. -// +// -// +// //***************************************************************************** #ifndef _METAMODELPUB_H_ @@ -16,13 +16,14 @@ #endif #include -#include +#include "contract.h" + #ifndef lengthof # define lengthof(x) (sizeof(x)/sizeof((x)[0])) #endif -template inline T Align4(T p) +template inline T Align4(T p) { LIMITED_METHOD_CONTRACT; @@ -51,16 +52,16 @@ typedef ULONG RID; // Naming is as follows: // Given some table "Xyz": // class XyzRec { public: -// SOMETYPE m_SomeField; +// SOMETYPE m_SomeField; // // rest of the fixed fields. -// enum { COL_Xyz_SomeOtherField, +// enum { COL_Xyz_SomeOtherField, // // rest of the fields, enumerated. // COL_Xyz_COUNT }; // }; // // The important features are the class name (XyzRec), the enumerations // (COL_Xyz_FieldName), and the enumeration count (COL_Xyz_COUNT). -// +// // THESE NAMING CONVENTIONS ARE CARVED IN STONE! DON'T TRY TO BE CREATIVE! // //***************************************************************************** @@ -455,7 +456,7 @@ public: }; }; -class FieldMarshalRec +class FieldMarshalRec { public: enum { @@ -1414,12 +1415,12 @@ METADATA_FIELDS_PROTECTION: USHORT m_Flags; // index; zero = first var public: enum { - + COL_Number, // index; zero = first var COL_Flags, // flags, for future use COL_Owner, // typeDef/methodDef COL_Name, // Purely descriptive, not used for binding purposes - COL_COUNT, + COL_COUNT, COL_KEY = COL_Owner }; @@ -1450,7 +1451,7 @@ public: } }; -// @todo: this definition is for reading the old (and wrong) GenericParamRec from a +// @todo: this definition is for reading the old (and wrong) GenericParamRec from a // Beta1 assembly. class GenericParamV1_1Rec { @@ -1459,13 +1460,13 @@ METADATA_FIELDS_PROTECTION: USHORT m_Flags; // index; zero = first var public: enum { - + COL_Number, // index; zero = first var COL_Flags, // flags, for future use COL_Owner, // typeDef/methodDef COL_Name, // Purely descriptive, not used for binding purposes COL_Kind, // typeDef/Ref/Spec, reserved for future use - COL_COUNT, + COL_COUNT, COL_KEY = COL_Owner }; @@ -1512,10 +1513,10 @@ class GenericParamConstraintRec { public: enum { - + COL_Owner, // GenericParam COL_Constraint, // typeDef/Ref/Spec - COL_COUNT, + COL_COUNT, COL_KEY = COL_Owner }; }; @@ -1637,7 +1638,7 @@ enum MDPools { MDPoolUSBlobs, // ...the user string pool. MDPoolCount, // Count of pools, for array sizing. -}; // enum MDPools +}; // enum MDPools struct CCodedTokenDef @@ -1661,7 +1662,7 @@ struct CMiniTableDef BYTE m_iKey; // Column which is the key, if any. USHORT m_cbRec; // Size of the records. }; -struct CMiniTableDefEx +struct CMiniTableDefEx { CMiniTableDef m_Def; // Table definition. const char * const *m_pColNames; // Array of column names. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/mpl/type_list b/CoreCLRProfiler/native/coreclr_headers/src/inc/mpl/type_list index 9073c5e..0e1140f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/mpl/type_list +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/mpl/type_list @@ -28,11 +28,11 @@ namespace mpl // 'mpl' => 'meta-programming library' template struct type_at; - + template struct type_at, IDX> { typedef typename type_at::type type; }; - + template struct type_at, 0> { typedef head type; }; @@ -46,7 +46,7 @@ namespace mpl // 'mpl' => 'meta-programming library' typename T10 = null_type, typename T11 = null_type, typename T12 = null_type, typename T13 = null_type, typename T14 = null_type, typename T15 = null_type, typename T16 = null_type, typename T17 = null_type, typename T18 = null_type - > + > struct make_type_list { private: diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/mscorsvc.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/mscorsvc.idl index 33ded42..6cfff8f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/mscorsvc.idl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/mscorsvc.idl @@ -59,8 +59,8 @@ library mscorsvc //***************************************************************************** // ICorSvcWorker contains methods for generating native images and enumerating // their dependencies. - //*****************************************************************************[ - + //*****************************************************************************[ + typedef enum { ScenarioDefault = 0x00000000, // No special scenario flags @@ -70,7 +70,7 @@ library mscorsvc ScenarioTuningDataCollection = 0x00000010, // Used to gather IBC data ScenarioLegacy = 0x00000020, // Follow hard dependencies only - ScenarioNgenLastRetry = 0x00010000, // Ngen failed last time and this a final retry + ScenarioNgenLastRetry = 0x00010000, // Ngen failed last time and this a final retry ScenarioAutoNGen = 0x00100000, // This is an Auto NGen request ScenarioRepositoryOnly = 0x00200000, // Install from repository only, no real NGen } OptimizationScenario; @@ -99,8 +99,8 @@ library mscorsvc ); HRESULT OptimizeAssembly( - [in] BSTR pAssemblyName, - [in] BSTR pApplicationName, + [in] BSTR pAssemblyName, + [in] BSTR pApplicationName, [in] OptimizationScenario scenario, [in] SAFEARRAY(BSTR) loadAlwaysList, [in] SAFEARRAY(BSTR) loadSometimesList, @@ -112,7 +112,7 @@ library mscorsvc [in] BSTR pAssemblyName, [in] BSTR pNativeImage ); - + HRESULT DisplayNativeImages( [in] BSTR pAssemblyName ); @@ -121,7 +121,7 @@ library mscorsvc [in] BSTR pApplicationName, [in] OptimizationScenario scenario, [out] ICorSvcDependencies **pCorSvcDependencies - ); + ); HRESULT Stop( ); @@ -136,13 +136,13 @@ library mscorsvc interface ICorSvcWorker2 : ICorSvcWorker { // Create a PDB for the NGEN image that was generated for pAssemblyName // when compiled with the given appbase and scenario. - HRESULT CreatePdb([in] BSTR pAssemblyName, + HRESULT CreatePdb([in] BSTR pAssemblyName, [in] BSTR pAppBaseOrConfig, [in] OptimizationScenario scenario, [in] BSTR pNativeImagePath, [in] BSTR pPdbPath); }; - + [ object, oleautomation, @@ -153,7 +153,7 @@ library mscorsvc // Create a PDB for the NGEN image that was generated for pAssemblyName // when compiled with the given appbase and scenario. Optionally include // source lines information in the geneated PDB - HRESULT CreatePdb2([in] BSTR pAssemblyName, + HRESULT CreatePdb2([in] BSTR pAssemblyName, [in] BSTR pAppBaseOrConfig, [in] OptimizationScenario scenario, [in] BSTR pNativeImagePath, @@ -166,7 +166,7 @@ library mscorsvc // ICorSvcSetPrivateAttributes sets private attributes that are used just for // the initial compilation //*****************************************************************************[ - + typedef enum { DbgTypePdb = 0x00000001, // Generate a pdb for the NGen image @@ -214,7 +214,7 @@ library mscorsvc interface ICorSvcRepository : IUnknown { HRESULT SetRepository( - [in] BSTR pRepositoryDir, + [in] BSTR pRepositoryDir, [in] RepositoryFlags repositoryFlags ); @@ -241,7 +241,7 @@ library mscorsvc //***************************************************************************** // ICorSvcLogger is used to log various messages to the service process //*****************************************************************************[ - + typedef enum CorSvcLogLevel { LogLevel_Error, @@ -249,7 +249,7 @@ library mscorsvc LogLevel_Success, LogLevel_Info } CorSvcLogLevel; - + [ object, oleautomation, @@ -284,12 +284,12 @@ library mscorsvc ); } - + //***************************************************************************** // ICorSvcBindToWorker is used to bind to a specific runtime version. //*****************************************************************************[ - + [ object, oleautomation, @@ -323,16 +323,16 @@ typedef enum // Haven't seen a better way of doing this. Everybody seems to be duplicating // into IDLs (for example wtypes.idl) -typedef struct _COR_SERVICE_STATUS -{ +typedef struct _COR_SERVICE_STATUS +{ WCHAR sServiceName[64]; - DWORD dwServiceType; - DWORD dwCurrentState; - DWORD dwControlsAccepted; - DWORD dwWin32ExitCode; - DWORD dwServiceSpecificExitCode; - DWORD dwCheckPoint; - DWORD dwWaitHint; + DWORD dwServiceType; + DWORD dwCurrentState; + DWORD dwControlsAccepted; + DWORD dwWin32ExitCode; + DWORD dwServiceSpecificExitCode; + DWORD dwCheckPoint; + DWORD dwWaitHint; } COR_SERVICE_STATUS, *LPCOR_SERVICE_STATUS; /* -------------------------------------------------------------------------- * @@ -369,7 +369,7 @@ interface ICorSvc : IUnknown [in] ControlServiceAction Action, [out] LPCOR_SERVICE_STATUS lpServiceStatus ); - + HRESULT RunService( [in] ServiceOptions options ); @@ -385,7 +385,7 @@ interface ICompileProgressNotification : IUnknown // Notify the installer that compilation has started, and give it an // estimation of how long it will take. HRESULT CompileStarted( - [in] DWORD cAssembliesToCompile, + [in] DWORD cAssembliesToCompile, [in] DWORD cTimeEstimate ); @@ -396,12 +396,12 @@ interface ICompileProgressNotification : IUnknown [in] DWORD cAssembly, [in] BSTR pAssemblyName, [in] BOOL isStartNotification, // if TRUE: we're starting to compile, if FALSE, we finished - [in] HRESULT hrResult, + [in] HRESULT hrResult, [in] BSTR errorExplanation, [in] DWORD cTimeRemainingEstimate ); - + } /* @@ -417,7 +417,7 @@ interface ICompileProgressNotification2 : IUnknown // Notify the installer that compilation has started, and give it an // estimation of how long it will take. HRESULT CompileStarted( - [in] DWORD cAssembliesToCompile, + [in] DWORD cAssembliesToCompile, [in] DWORD cTimeEstimate, [in] DWORD threadID ); @@ -429,13 +429,13 @@ interface ICompileProgressNotification2 : IUnknown [in] DWORD cAssembly, [in] BSTR pAssemblyName, [in] BOOL isStartNotification, // if TRUE: we're starting to compile, if FALSE, we finished - [in] HRESULT hrResult, + [in] HRESULT hrResult, [in] BSTR errorExplanation, [in] DWORD cTimeRemainingEstimate, [in] DWORD threadID ); - + } typedef enum @@ -450,7 +450,7 @@ typedef enum object, uuid(0523feee-eb0e-4857-b2aa-db787521d077), pointer_default(unique), -] +] interface ICorSvcInstaller : IUnknown { HRESULT Install( @@ -458,9 +458,9 @@ interface ICorSvcInstaller : IUnknown ); HRESULT Uninstall( - [in] BSTR path + [in] BSTR path ); - + HRESULT Optimize( [in] ICompileProgressNotification *pCompileProgressNotification, [in] OptimizeFlags optimizeFlags @@ -468,7 +468,7 @@ interface ICorSvcInstaller : IUnknown HRESULT SetLogger( [in] ICorSvcLogger *pCorSvcLogger - ); + ); } typedef enum @@ -605,7 +605,7 @@ typedef enum pointer_default(unique), ] interface ICorSvcManager : IUnknown -{ +{ // Schedule work only for selected priority level HRESULT ScheduleWorkForSinglePriorityLevel( [in] PriorityLevel priorityLevel, @@ -618,22 +618,22 @@ interface ICorSvcManager : IUnknown [in] DWORD dwWorkerPriorityClass, [in] ICompileProgressNotification *pCompileProgressNotification, [in] BSTR pInterruptEventName - ); - + ); + // Notify the service of new work - HRESULT NotifyService(ServiceNotification notification); + HRESULT NotifyService(ServiceNotification notification); HRESULT IsWorkAvailable ([in] PriorityLevel priorityLevel, - [out] BOOL* pWorkAvailable); + [out] BOOL* pWorkAvailable); HRESULT Update( [in] UpdateFlags updateFlags, [in] BSTR pInterruptEventName - ); + ); HRESULT SetSvcLogger( [in] ICorSvcLogger *pCorSvcLogger - ); + ); } [ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/nativevaraccessors.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/nativevaraccessors.h index b3ee7bb..7a3583f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/nativevaraccessors.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/nativevaraccessors.h @@ -26,23 +26,23 @@ struct NativeVarLocation bool contextReg; }; -ULONG NativeVarLocations(const ICorDebugInfo::VarLoc & varLoc, +ULONG NativeVarLocations(const ICorDebugInfo::VarLoc & varLoc, PT_CONTEXT pCtx, ULONG numLocs, NativeVarLocation* locs); -SIZE_T *NativeVarStackAddr(const ICorDebugInfo::VarLoc & varLoc, +SIZE_T *NativeVarStackAddr(const ICorDebugInfo::VarLoc & varLoc, PT_CONTEXT pCtx); - -bool GetNativeVarVal(const ICorDebugInfo::VarLoc & varLoc, + +bool GetNativeVarVal(const ICorDebugInfo::VarLoc & varLoc, PT_CONTEXT pCtx, - SIZE_T * pVal1, + SIZE_T * pVal1, SIZE_T * pVal2 - WIN64_ARG(SIZE_T cbSize)); - -bool SetNativeVarVal(const ICorDebugInfo::VarLoc & varLoc, + BIT64_ARG(SIZE_T cbSize)); + +bool SetNativeVarVal(const ICorDebugInfo::VarLoc & varLoc, PT_CONTEXT pCtx, - SIZE_T val1, + SIZE_T val1, SIZE_T val2 - WIN64_ARG(SIZE_T cbSize)); + BIT64_ARG(SIZE_T cbSize)); #endif // #ifndef _NATIVE_VAR_ACCESSORS_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/ngen.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/ngen.h index fa0b982..7e49349 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/ngen.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/ngen.h @@ -19,7 +19,7 @@ #define DEFAULT_MACHINE_WIDE_LOG_SIZE (1 * 1024 * 1024) // User specific log is yet smaller 200KB #define DEFAULT_USER_WIDE_LOG_SIZE (200 * 1024) -// Log size default of 100 KB. This should be big enough to hold some log info from roughly 100 +// Log size default of 100 KB. This should be big enough to hold some log info from roughly 100 // ngen events. (Roughly 200KB of space including secondary log file.) #define DEFAULT_APPLOCAL_WIDE_LOG_SIZE (100*1024) @@ -42,25 +42,25 @@ enum DebugType // NGening a module invokes the runtime against which the module was built. // Thus this structure needs to be backwards-compatible. // -// If additional options need to be added to this structure, +// If additional options need to be added to this structure, // add them to the end of the structure and make sure you update // logic throughout the runtime to look at a different size in the dwSize // field. This is how we'll 'version' this structure. -// +// // If you are adding a code-generation flag (like debug or prof), use // fInstrument as a template (but be sure to add your new flag as the -// last element in the struct). +// last element in the struct). typedef struct _NGenOptions { DWORD dwSize; // Size of the structure. Used to version the structure - + // V1 - + bool fDebug; // Generate debuggable code and debug information bool fDebugOpt; // Generate debugging information, but optimized code bool fProf; // Generate instrumented code for profiling (call graphs) - + bool fSilent; // Dont spew text output LPCWSTR lpszExecutableFileName; // Name of the module to ngen @@ -108,7 +108,7 @@ typedef struct _NGenOptions // Function pointer types that we use to dynamically bind to the appropriate runtime version extern "C" typedef HRESULT STDAPICALLTYPE NGenCreateZapperAPI( - HANDLE* hZapper, + HANDLE* hZapper, NGenOptions *options); typedef NGenCreateZapperAPI *PNGenCreateZapper; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/nibblemapmacros.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/nibblemapmacros.h index 42ea90a..7153bc6 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/nibblemapmacros.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/nibblemapmacros.h @@ -25,8 +25,8 @@ // nibbles inside a DWORD from the highest bits (28..31). Because // of that we can scan backwards inside the DWORD with right shifts. -#if defined(_WIN64) -// TODO: bump up the windows CODE_ALIGN to 16 and iron out any nibble map bugs that exist. +#if defined(HOST_64BIT) +// TODO: bump up the windows CODE_ALIGN to 16 and iron out any nibble map bugs that exist. // TODO: there is something wrong with USE_INDIRECT_CODEHEADER with CODE_ALIGN=16 # define CODE_ALIGN 4 # define LOG2_CODE_ALIGN 2 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/nibblestream.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/nibblestream.h index 1b92bd0..7921e9f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/nibblestream.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/nibblestream.h @@ -17,14 +17,14 @@ typedef BYTE NIBBLE; //----------------------------------------------------------------------------- // This class allows variable-length compression of DWORDs. // -// A value can be stored using one or more nibbles. 3 bits of a nibble are used -// to store 3 bits of the value, and the top bit indicates if the following nibble +// A value can be stored using one or more nibbles. 3 bits of a nibble are used +// to store 3 bits of the value, and the top bit indicates if the following nibble // contains rest of the value. If the top bit is not set, then this -// nibble is the last part of the value. +// nibble is the last part of the value. // The higher bits of the value are written out first, and the lowest 3 bits // are written out last. // -// In the encoded stream of bytes, the lower nibble of a byte is used before +// In the encoded stream of bytes, the lower nibble of a byte is used before // the high nibble. // // A binary value ABCDEFGHI (where A is the highest bit) is encoded as @@ -52,7 +52,7 @@ public: NibbleWriter() { LIMITED_METHOD_CONTRACT; - + m_fPending = false; } @@ -126,7 +126,7 @@ public: { WriteNibble((NIBBLE) ((dw >> 3) | 8)); } - + WriteNibble((NIBBLE) (dw & 7)); return; } @@ -143,7 +143,7 @@ public: WriteNibble((NIBBLE) ((dw >> i) & 0x7) | 0x8); i -= 3; } - WriteNibble((NIBBLE) dw & 0x7); + WriteNibble((NIBBLE) dw & 0x7); } // Write a signed 32 bit value. @@ -155,7 +155,7 @@ public: GC_NOTRIGGER; } CONTRACTL_END; - + DWORD dw = (x < 0) ? (((-x) << 1) + 1) : (x << 1); WriteEncodedU32(dw); }; @@ -178,7 +178,7 @@ public: LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; _ASSERTE(pBuffer != NULL); - + m_pBuffer = pBuffer; m_cBytes = size; m_cNibble = 0; @@ -204,7 +204,7 @@ public: SUPPORTS_DAC; } CONTRACTL_END; - + NIBBLE i = 0; // Bufer should have been allocated large enough to hold data. if (!(m_cNibble / 2 < m_cBytes)) @@ -213,7 +213,7 @@ public: // We could wind up here if somebody provided us invalid data (maybe by corrupting an ngenned image). EX_THROW(HRException, (E_INVALIDARG)); } - + BYTE p = m_pBuffer[m_cNibble / 2]; if ((m_cNibble & 1) == 0) { @@ -231,7 +231,7 @@ public: } // Read an unsigned int that was encoded via variable length nibble encoding - // from NibbleWriter::WriteEncodedU32. + // from NibbleWriter::WriteEncodedU32. DWORD ReadEncodedU32() { CONTRACTL @@ -241,7 +241,7 @@ public: SUPPORTS_DAC; } CONTRACTL_END; - + DWORD dw =0; #if defined(_DEBUG) || defined(DACCESS_COMPILE) @@ -254,7 +254,7 @@ public: do { #if defined(_DEBUG) || defined(DACCESS_COMPILE) - // If we've already read 11 nibbles (with 3 bits of usable data each), then we + // If we've already read 11 nibbles (with 3 bits of usable data each), then we // should be done reading a 32-bit integer. // Avoid working with corrupted data and potentially long loops by failing if(dwCount > 11) @@ -263,7 +263,7 @@ public: #ifdef DACCESS_COMPILE DacError(CORDBG_E_TARGET_INCONSISTENT); #endif - } + } dwCount++; #endif @@ -283,7 +283,7 @@ public: SUPPORTS_DAC; } CONTRACTL_END; - + DWORD dw = ReadEncodedU32(); int x = dw >> 1; return (dw & 1) ? (-x) : (x); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/nsutilpriv.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/nsutilpriv.h index ede064c..3891bbc 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/nsutilpriv.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/nsutilpriv.h @@ -54,11 +54,11 @@ int IsValidName( // true if valid, false invalid. // | // The ".ctor" is considered one token. //***************************************************************************** -static +static WCHAR *FindSep( // Pointer to separator or null. const WCHAR *szPath); // The path to look in. -static +static LPUTF8 FindSep( // Pointer to separator or null. LPCUTF8 szPath); // The path to look in. @@ -69,11 +69,11 @@ LPUTF8 FindSep( // Pointer to separator or null. // a.b.c // becomes two strings "a.b" and "c" and the return value points to "c". //***************************************************************************** -static +static WCHAR *SplitInline( // Pointer to name portion. __inout __inout_z WCHAR *szPath); // The path to split. -static +static LPUTF8 SplitInline( // Pointer to name portion. __inout __inout_z LPUTF8 szPath); // The path to split. @@ -94,7 +94,7 @@ void SplitInline( // Split the last parsable element from the end of the string as the name, // the first part as the namespace. //***************************************************************************** -static +static int SplitPath( // true ok, false trunction. const WCHAR *szPath, // Path to split. __out_ecount_opt (cchNameSpace) WCHAR *szNameSpace, // Output for namespace value. @@ -102,7 +102,7 @@ int SplitPath( // true ok, false trunction. __out_ecount_opt (cchName) WCHAR *szName, // Output for name. int cchName); // Max chars for output. -static +static int SplitPath( // true ok, false trunction. LPCUTF8 szPath, // Path to split. __out_ecount_opt (cchNameSpace) LPUTF8 szNameSpace, // Output for namespace value. @@ -115,14 +115,14 @@ int SplitPath( // true ok, false trunction. // Take two values and put them together in a fully qualified path using the // correct separator. //***************************************************************************** -static +static int MakePath( // true ok, false truncation. __out_ecount(cchChars) WCHAR *szOut, // output path for name. int cchChars, // max chars for output path. const WCHAR *szNameSpace, // Namespace. const WCHAR *szName); // Name. -static +static int MakePath( // true ok, false truncation. __out_ecount(cchChars) LPUTF8 szOut, // output path for name. int cchChars, // max chars for output path. @@ -163,13 +163,13 @@ void MakePath( // throws on out of memory //***************************************************************************** // Concatinate type names to assembly names //***************************************************************************** -static +static bool MakeAssemblyQualifiedName( // true if ok, false if out of memory CQuickBytes &qb, // location to put result const WCHAR *szTypeName, // Type name const WCHAR *szAssemblyName); // Assembly Name - -static + +static bool MakeAssemblyQualifiedName( // true ok, false truncation __out_ecount (dwBuffer) WCHAR* pBuffer, // Buffer to recieve the results int dwBuffer, // Number of characters total in buffer @@ -178,20 +178,20 @@ bool MakeAssemblyQualifiedName( // true o const WCHAR *szAssemblyName, // Final part of name. int dwAssemblyName); // Number of characters (not including null) -static +static int MakeNestedTypeName( // true ok, false out of memory CQuickBytes &qb, // Where to put results. LPCUTF8 szEnclosingName, // Full name for enclosing type LPCUTF8 szNestedName); // Full name for nested type -static +static int MakeNestedTypeName( // true ok, false truncation. __out_ecount (cchChars) LPUTF8 szOut, // output path for name. int cchChars, // max chars for output path. LPCUTF8 szEnclosingName, // Full name for enclosing type LPCUTF8 szNestedName); // Full name for nested type -static +static void MakeNestedTypeName( // throws on out of memory SString &ssBuf, // output path for name. const SString &ssEnclosingName, // Full name for enclosing type @@ -256,7 +256,7 @@ void MakeNestedTypeName( // throws on out of memory } #ifdef _PREFAST_ -// need to eliminate the expansion of MAKE_FULLY_QUALIFIED_MEMBER_NAME in prefast +// need to eliminate the expansion of MAKE_FULLY_QUALIFIED_MEMBER_NAME in prefast // builds to prevent it complaining about the potential for NULLs to strlen and strcat #undef MAKE_FULLY_QUALIFIED_MEMBER_NAME // need to set ptr=NULL so we don't get a build error because ptr isn't inited in a couple cases diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/openum.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/openum.h index f71e411..e707da4 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/openum.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/openum.h @@ -15,9 +15,9 @@ typedef enum opcode_t } OPCODE; -typedef enum opcode_format_t +typedef enum opcode_format_t { - InlineNone = 0, // no inline args + InlineNone = 0, // no inline args InlineVar = 1, // local variable (U2 (U1 if Short on)) InlineI = 2, // an signed integer (I4 (I1 if Short on)) InlineR = 3, // a real number (R8 (R4 if Short on)) @@ -31,7 +31,7 @@ typedef enum opcode_format_t InlineRVA = 11, // ldptr token (U4) InlineTok = 12, // a meta-data token of unknown type (U4) InlineSwitch = 13, // count (U4), pcrel1 (U4) .... pcrelN (U4) - InlinePhi = 14, // count (U1), var1 (U2) ... varN (U2) + InlinePhi = 14, // count (U1), var1 (U2) ... varN (U2) // WATCH OUT we are close to the limit here, if you add // more enumerations you need to change ShortIline definition below diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/opinfo.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/opinfo.h index d98c006..f19811e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/opinfo.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/opinfo.h @@ -23,10 +23,10 @@ enum OpFlow { FLOW_CALL, // a call instruction FLOW_BRANCH, // unconditional branch, does not fall through FLOW_COND_BRANCH, // may fall through - FLOW_PHI, + FLOW_PHI, FLOW_THROW, FLOW_BREAK, - FLOW_RETURN, + FLOW_RETURN, FLOW_NEXT, // flows into next instruction (none of the above) }; @@ -52,11 +52,11 @@ union OpArgsVal { class OpInfo { public: OpInfo() { data = 0; } - OpInfo(OPCODE opCode) { _ASSERTE(opCode < CEE_COUNT); data = &table[opCode]; } + OpInfo(OPCODE opCode) { _ASSERTE(opCode < CEE_COUNT); data = &table[opCode]; } - // fetch instruction at 'instrPtr, fills in 'args' returns pointer - // to next instruction - const unsigned char* fetch(const unsigned char* instrPtr, OpArgsVal* args); + // fetch instruction at 'instrPtr, fills in 'args' returns pointer + // to next instruction + const unsigned char* fetch(const unsigned char* instrPtr, OpArgsVal* args); const char* getName() { return(data->name); } OPCODE_FORMAT getArgsInfo() { return(OPCODE_FORMAT(data->format & PrimaryMask)); } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/optsmallperfcritical.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/optsmallperfcritical.h index 68c8088..44f7c0f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/optsmallperfcritical.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/optsmallperfcritical.h @@ -15,7 +15,7 @@ #if defined(_MSC_VER) && !defined(_DEBUG) #pragma optimize("t", on) // optimize for speed - #if !defined(_AMD64_) // 'y' isn't an option on amd64 + #if !defined(HOST_AMD64) // 'y' isn't an option on amd64 #pragma optimize("y", on) // omit frame pointer - #endif // !defined(_TARGET_AMD64_) -#endif + #endif // !defined(TARGET_AMD64) +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/ostype.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/ostype.h index b64927c..18ed50a 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/ostype.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/ostype.h @@ -16,15 +16,15 @@ //***************************************************************************** // Enum to track which version of the OS we are running // Note that NT5 (Win2k) is the minimum supported platform. Any code using -// utilcode (which includes the CLR's execution engine) will fail to start +// utilcode (which includes the CLR's execution engine) will fail to start // on a pre-Win2k platform. This is enforced by InitRunningOnVersionStatus. -// +// // Note: The value is used for data mining from links clicked by user in shim dialog - see code:FWLinkTemplateFromTextID // Please do not modify existing values, adding new ones is fine. //***************************************************************************** typedef enum { - RUNNING_ON_STATUS_UNINITED = 0, - RUNNING_ON_WIN7 = 1, + RUNNING_ON_STATUS_UNINITED = 0, + RUNNING_ON_WIN7 = 1, RUNNING_ON_WIN8 = 2 } RunningOnStatusEnum; @@ -52,7 +52,7 @@ void InitWinRTStatus(); inline BOOL RunningOnWin8() { WRAPPER_NO_CONTRACT; -#if (!defined(_X86_) && !defined(_AMD64_)) || defined(CROSSGEN_COMPILE) +#if (!defined(HOST_X86) && !defined(HOST_AMD64)) || defined(CROSSGEN_COMPILE) return TRUE; #else if (gRunningOnStatus == RUNNING_ON_STATUS_UNINITED) @@ -78,7 +78,7 @@ inline BOOL WinRTSupported() STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_CANNOT_TAKE_LOCK; - + #ifdef CROSSGEN_COMPILE return TRUE; #endif @@ -94,7 +94,7 @@ inline BOOL WinRTSupported() #endif // FEATURE_COMINTEROP -#ifdef _WIN64 +#ifdef HOST_64BIT inline BOOL RunningInWow64() { return FALSE; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/outstring.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/outstring.h index 167ef9a..1d66883 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/outstring.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/outstring.h @@ -9,7 +9,7 @@ /* A simple, lightweight, character output stream, with very few external dependancies (like sprintf ... ) */ -/* +/* Date : 2/1/99 */ /*****************************************************************/ @@ -20,36 +20,36 @@ #include // for strlen, strcpy /*****************************************************************/ - // a light weight character 'output' stream + // a light weight character 'output' stream class OutString { public: enum FormatFlags { // used to control printing of numbers none = 0, - put0x = 1, // put leading 0x on hexidecimal + put0x = 1, // put leading 0x on hexidecimal zeroFill = 2, // zero fill (instead of space fill) }; OutString() : start(0), end(0), cur(0) {} - OutString(unsigned initialAlloc) { + OutString(unsigned initialAlloc) { cur = start = new char[initialAlloc+1]; // for null termination end = &start[initialAlloc]; } - + ~OutString() { delete [] start; } - - // shortcut for printing decimal + + // shortcut for printing decimal OutString& operator<<(int i) { return(dec(i)); } OutString& operator<<(double d); - + // FIX make this really unsigned OutString& operator<<(unsigned i) { return(dec(i)); } // prints out the hexidecimal representation OutString& dec(int i, size_t minWidth = 0); - - // prints out the hexidecimal representation + + // prints out the hexidecimal representation OutString& hex(unsigned i, int minWidth = 0, unsigned flags = none); OutString& hex(unsigned __int64 i, int minWidth = 0, unsigned flags = none); @@ -61,10 +61,10 @@ public: OutString& hex(__int64 i, int minWidth = 0, unsigned flags = none) { return hex((unsigned __int64) i, minWidth, flags); } - + // print out 'count' instances of the character 'c' OutString& pad(size_t count, char c); - + OutString& operator<<(char c) { if (cur >= end) Realloc(1); @@ -72,12 +72,12 @@ public: _ASSERTE(start <= cur && cur <= end); return(*this); } - - OutString& operator<<(const wchar_t* str) { + + OutString& operator<<(const WCHAR* str) { size_t len = wcslen(str); if (cur+len > end) Realloc(len); - while(str != 0) + while(str != 0) *cur++ = (char) *str++; _ASSERTE(start <= cur && cur <= end); return(*this); @@ -138,16 +138,16 @@ public: void clear() { cur = start; } size_t length() const { return(cur-start); } - + // return the null terminated string, OutString keeps ownership const char* val() const { *cur = 0; return(start); } - - // grab string (caller must now delete) OutString is cleared + + // grab string (caller must now delete) OutString is cleared char* grab() { char* ret = start; *cur = 0; end = cur = start = 0; return(ret); } - + private: void Realloc(size_t neededSpace); - + char *start; // start of the buffer char *end; // points at the last place null terminator can go char *cur; // points at a null terminator diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/palclr.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/palclr.h index 3b42ac5..5978ea1 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/palclr.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/palclr.h @@ -10,7 +10,7 @@ // =========================================================================== -#if !defined(FEATURE_PAL) +#if defined(HOST_WINDOWS) #ifndef __PALCLR_H__ #define __PALCLR_H__ @@ -19,11 +19,7 @@ // Unix L"" is UTF32, and on windows it's UTF16. Because of built-in assumptions on the size // of string literals, it's important to match behaviour between Unix and Windows. Unix will be defined // as u"" (char16_t) -#ifdef PLATFORM_UNIX -#define W(str) u##str -#else // PLATFORM_UNIX #define W(str) L##str -#endif // PLATFORM_UNIX #include @@ -55,12 +51,18 @@ #define ANALYZER_NORETURN +#ifdef _MSC_VER +#define EMPTY_BASES_DECL __declspec(empty_bases) +#else +#define EMPTY_BASES_DECL +#endif // !_MSC_VER + // // CPP_ASSERT() can be used within a class definition, to perform a // compile-time assertion involving private names within the class. // // MS compiler doesn't allow redefinition of the typedef within a template. -// gcc doesn't allow redefinition of the typedef within a class, though +// gcc doesn't allow redefinition of the typedef within a class, though // it does at file scope. #define CPP_ASSERT(n, e) typedef char __C_ASSERT__##n[(e) ? 1 : -1]; @@ -70,11 +72,11 @@ // usage pattern is: // // int get_scratch_register() { -// #if defined(_TARGET_X86_) +// #if defined(TARGET_X86) // return eax; -// #elif defined(_TARGET_AMD64_) +// #elif defined(TARGET_AMD64) // return rax; -// #elif defined(_TARGET_ARM_) +// #elif defined(TARGET_ARM) // return r0; // #else // PORTABILITY_ASSERT("scratch register"); @@ -91,7 +93,7 @@ // errors. Once they fix all the places that need attention for portability, // they can define PORTABILITY_ASSERT and PORTABILITY_WARNING to cause // compile-time errors to make sure that they haven't missed anything. -// +// // If it is reasonably possible all codepaths containing PORTABILITY_ASSERT // should be compilable (e.g. functions should return NULL or something if // they are expected to return a value). @@ -99,14 +101,14 @@ // The message in these two macros should not contain any keywords like TODO // or NYI. It should be just the brief description of the problem. -#if defined(_TARGET_X86_) +#if defined(TARGET_X86) // Finished ports - compile-time errors #define PORTABILITY_WARNING(message) NEED_TO_PORT_THIS_ONE(NEED_TO_PORT_THIS_ONE) #define PORTABILITY_ASSERT(message) NEED_TO_PORT_THIS_ONE(NEED_TO_PORT_THIS_ONE) #else // Ports in progress - run-time asserts only #define PORTABILITY_WARNING(message) -#define PORTABILITY_ASSERT(message) _ASSERTE(false && message) +#define PORTABILITY_ASSERT(message) _ASSERTE(false && (message)) #endif #define DIRECTORY_SEPARATOR_CHAR_A '\\' @@ -242,7 +244,7 @@ // - It is not possible to directly use the local variables in the filter. // All the local information that the filter has to need to know about should // be passed through pv parameter -// +// // - Do not use goto to jump out of the PAL_TRY block // (jumping out of the try block is not a good idea even on Win32, because of // it causes stack unwind) @@ -270,7 +272,7 @@ // .... // } // PAL_ENDTRY -// +// // // LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) // { @@ -403,7 +405,7 @@ static void Run(__ParamType __paramDef) \ { \ PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(__reason) - + #define PAL_EXCEPT(Disposition) \ PAL_TRY_HANDLER_DBG_END \ } \ @@ -452,7 +454,7 @@ __ParamType __paramDef; __paramDef = __param; \ PAL_TRY_NAKED \ PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(__reason) - + #define PAL_EXCEPT(Disposition) \ PAL_TRY_HANDLER_DBG_END \ PAL_EXCEPT_NAKED(Disposition) @@ -473,7 +475,7 @@ // Executes the handler if the specified exception code matches // the one in the exception. Otherwise, returns EXCEPTION_CONTINUE_SEARCH. -#define PAL_EXCEPT_IF_EXCEPTION_CODE(dwExceptionCode) PAL_EXCEPT((GetExceptionCode() == dwExceptionCode)?EXCEPTION_EXECUTE_HANDLER:EXCEPTION_CONTINUE_SEARCH) +#define PAL_EXCEPT_IF_EXCEPTION_CODE(dwExceptionCode) PAL_EXCEPT((GetExceptionCode() == (dwExceptionCode))?EXCEPTION_EXECUTE_HANDLER:EXCEPTION_CONTINUE_SEARCH) #define PAL_CPP_TRY try #define PAL_CPP_ENDTRY @@ -494,7 +496,7 @@ // SELECTANY declares a variable as extern to give it external linkage // and it provides __declspec(selectany) to instruct the linker to merge // duplicate external const static data copies into one. -// +// #if defined(SOURCE_FORMATTING) #define SELECTANY extern #else @@ -507,17 +509,16 @@ #if defined(SOURCE_FORMATTING) #define __annotation(x) #endif - -#if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(JIT64_BUILD) && !defined(CROSS_COMPILE) && !defined(DISABLE_CONTRACTS) + +#if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(CROSS_COMPILE) && !defined(DISABLE_CONTRACTS) #define PAL_TRY_HANDLER_DBG_BEGIN \ BOOL ___oldOkayToThrowValue = FALSE; \ ClrDebugState *___pState = ::GetClrDebugState(); \ __try \ { \ ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ - ___pState->SetOkToThrow(); \ - PAL_ENTER_THROWS_REGION; + ___pState->SetOkToThrow(); // Special version that avoids touching the debug state after doing work in a DllMain for process or thread detach. #define PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) \ @@ -535,11 +536,9 @@ if ((_reason == DLL_PROCESS_DETACH) || (_reason == DLL_THREAD_DETACH)) \ { \ ___pState = NULL; \ - } \ - PAL_ENTER_THROWS_REGION; + } #define PAL_TRY_HANDLER_DBG_END \ - PAL_LEAVE_THROWS_REGION \ } \ __finally \ { \ @@ -556,8 +555,8 @@ #define PAL_TRY_HANDLER_DBG_BEGIN ANNOTATION_TRY_BEGIN; #define PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) ANNOTATION_TRY_BEGIN; #define PAL_TRY_HANDLER_DBG_END ANNOTATION_TRY_END; -#define PAL_ENDTRY_NAKED_DBG -#endif // defined(ENABLE_CONTRACTS_IMPL) && !defined(JIT64_BUILD) +#define PAL_ENDTRY_NAKED_DBG +#endif // defined(ENABLE_CONTRACTS_IMPL) #if !BIGENDIAN @@ -576,23 +575,23 @@ #define GET_UNALIGNED_32(_pObject) (*(UINT32 UNALIGNED *)(_pObject)) #define GET_UNALIGNED_64(_pObject) (*(UINT64 UNALIGNED *)(_pObject)) -// Set Value on an potentially unaligned object +// Set Value on an potentially unaligned object #define SET_UNALIGNED_16(_pObject, _Value) (*(UNALIGNED UINT16 *)(_pObject)) = (UINT16)(_Value) #define SET_UNALIGNED_32(_pObject, _Value) (*(UNALIGNED UINT32 *)(_pObject)) = (UINT32)(_Value) -#define SET_UNALIGNED_64(_pObject, _Value) (*(UNALIGNED UINT64 *)(_pObject)) = (UINT64)(_Value) +#define SET_UNALIGNED_64(_pObject, _Value) (*(UNALIGNED UINT64 *)(_pObject)) = (UINT64)(_Value) // Get Unaligned values from a potentially unaligned object and swap the value #define GET_UNALIGNED_VAL16(_pObject) VAL16(GET_UNALIGNED_16(_pObject)) #define GET_UNALIGNED_VAL32(_pObject) VAL32(GET_UNALIGNED_32(_pObject)) #define GET_UNALIGNED_VAL64(_pObject) VAL64(GET_UNALIGNED_64(_pObject)) -// Set a swap Value on an potentially unaligned object +// Set a swap Value on an potentially unaligned object #define SET_UNALIGNED_VAL16(_pObject, _Value) SET_UNALIGNED_16(_pObject, VAL16((UINT16)_Value)) #define SET_UNALIGNED_VAL32(_pObject, _Value) SET_UNALIGNED_32(_pObject, VAL32((UINT32)_Value)) #define SET_UNALIGNED_VAL64(_pObject, _Value) SET_UNALIGNED_64(_pObject, VAL64((UINT64)_Value)) #endif -#ifdef _WIN64 +#ifdef HOST_64BIT #define VALPTR(x) VAL64(x) #define GET_UNALIGNED_PTR(x) GET_UNALIGNED_64(x) #define GET_UNALIGNED_VALPTR(x) GET_UNALIGNED_VAL64(x) @@ -628,4 +627,4 @@ #include "palclr_win.h" -#endif // !defined(FEATURE_PAL) +#endif // defined(HOST_WINDOWS) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/palclr_win.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/palclr_win.h index 5050586..4db25f6 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/palclr_win.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/palclr_win.h @@ -24,7 +24,7 @@ // - It is not possible to directly use the local variables in the filter. // All the local information that the filter has to need to know about should // be passed through pv parameter -// +// // - Do not use goto to jump out of the PAL_TRY block // (jumping out of the try block is not a good idea even on Win32, because of // it causes stack unwind) @@ -46,7 +46,7 @@ // .... // } // WIN_PAL_ENDTRY -// +// // // LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) // { @@ -85,7 +85,7 @@ -#if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(JIT64_BUILD) && !defined(_ARM_) // @ARMTODO +#if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(HOST_ARM) // @ARMTODO #define WIN_PAL_TRY_HANDLER_DBG_BEGIN \ BOOL ___oldOkayToThrowValue = FALSE; \ ClrDebugState *___pState = GetClrDebugState(); \ @@ -132,13 +132,13 @@ #define WIN_PAL_TRY_HANDLER_DBG_BEGIN ANNOTATION_TRY_BEGIN; #define WIN_PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) ANNOTATION_TRY_BEGIN; #define WIN_PAL_TRY_HANDLER_DBG_END ANNOTATION_TRY_END; -#define WIN_PAL_ENDTRY_NAKED_DBG -#endif // defined(ENABLE_CONTRACTS_IMPL) && !defined(JIT64_BUILD) +#define WIN_PAL_ENDTRY_NAKED_DBG +#endif // defined(ENABLE_CONTRACTS_IMPL) -#if !defined (FEATURE_PAL) +#if defined(HOST_WINDOWS) // Native system libray handle. // In Windows, NATIVE_LIBRARY_HANDLE is the same as HMODULE. typedef HMODULE NATIVE_LIBRARY_HANDLE; -#endif // !FEATURE_PAL +#endif // HOST_WINDOWS #endif // __PALCLR_WIN_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/patchpointinfo.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/patchpointinfo.h new file mode 100644 index 0000000..135ad01 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/patchpointinfo.h @@ -0,0 +1,145 @@ +// 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. + +// -------------------------------------------------------------------------------- +// patchpointinfo.h +// -------------------------------------------------------------------------------- + +#include + +#ifndef _PATCHPOINTINFO_H_ +#define _PATCHPOINTINFO_H_ + +// -------------------------------------------------------------------------------- +// Describes information needed to make an OSR transition +// - location of Il-visible locals and other important state on the +// original (Tier0) method frame +// - total size of the original frame, and SP-FP delta +// +// Currently the patchpoint info is independent of the IL offset of the patchpoint. +// +// This data is produced when jitting a Tier0 method with OSR enabled, and consumed +// by the Tier1/OSR jit request. +// +struct PatchpointInfo +{ + // Determine how much storage is needed to hold this info + static unsigned ComputeSize(unsigned localCount) + { + unsigned baseSize = sizeof(PatchpointInfo); + unsigned variableSize = localCount * sizeof(int); + unsigned totalSize = baseSize + variableSize; + return totalSize; + } + + // Initialize + void Initialize(unsigned localCount, int fpToSpDelta) + { + m_fpToSpDelta = fpToSpDelta; + m_numberOfLocals = localCount; + m_genericContextArgOffset = -1; + m_keptAliveThisOffset = -1; + m_securityCookieOffset = -1; + } + + // Total size of this patchpoint info record, in bytes + unsigned PatchpointInfoSize() const + { + return ComputeSize(m_numberOfLocals); + } + + // FP to SP delta of the original method + int FpToSpDelta() const + { + return m_fpToSpDelta; + } + + // Number of locals in the original method (including special locals) + unsigned NumberOfLocals() const + { + return m_numberOfLocals; + } + + // Original method caller SP offset for generic context arg + int GenericContextArgOffset() const + { + return m_genericContextArgOffset; + } + + void SetGenericContextArgOffset(int offset) + { + m_genericContextArgOffset = offset; + } + + // Original method FP relative offset for kept-alive this + int KeptAliveThisOffset() const + { + return m_keptAliveThisOffset; + } + + bool HasKeptAliveThis() const + { + return m_keptAliveThisOffset != -1; + } + + void SetKeptAliveThisOffset(int offset) + { + m_keptAliveThisOffset = offset; + } + + // Original method FP relative offset for security cookie + int SecurityCookieOffset() const + { + return m_securityCookieOffset; + } + + bool HasSecurityCookie() const + { + return m_securityCookieOffset != -1; + } + + void SetSecurityCookieOffset(int offset) + { + m_securityCookieOffset = offset; + } + + // True if this local was address exposed in the original method + bool IsExposed(unsigned localNum) const + { + return ((m_offsetAndExposureData[localNum] & EXPOSURE_MASK) != 0); + } + + void SetIsExposed(unsigned localNum) + { + m_offsetAndExposureData[localNum] |= EXPOSURE_MASK; + } + + // FP relative offset of this local in the original method + int Offset(unsigned localNum) const + { + return (m_offsetAndExposureData[localNum] & ~EXPOSURE_MASK); + } + + void SetOffset(unsigned localNum, int offset) + { + m_offsetAndExposureData[localNum] = offset; + } + +private: + enum + { + EXPOSURE_MASK = 0x1 + }; + + unsigned m_numberOfLocals; + int m_fpToSpDelta; + int m_genericContextArgOffset; + int m_keptAliveThisOffset; + int m_securityCookieOffset; + int m_offsetAndExposureData[]; +}; + +typedef DPTR(struct PatchpointInfo) PTR_PatchpointInfo; + +#endif // _PATCHPOINTINFO_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/pedecoder.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/pedecoder.h index 5dff335..ad0e77e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/pedecoder.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/pedecoder.h @@ -41,6 +41,7 @@ #include "corcompile.h" #include "readytorun.h" +typedef DPTR(struct READYTORUN_CORE_HEADER) PTR_READYTORUN_CORE_HEADER; typedef DPTR(struct READYTORUN_HEADER) PTR_READYTORUN_HEADER; typedef DPTR(struct READYTORUN_SECTION) PTR_READYTORUN_SECTION; @@ -73,13 +74,13 @@ inline CHECK CheckOverflow(RVA value1, COUNT_T value2) // IMAGE_FILE_MACHINE_NATIVE // -------------------------------------------------------------------------------- -#if defined(_TARGET_X86_) +#if defined(TARGET_X86) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_I386 -#elif defined(_TARGET_AMD64_) +#elif defined(TARGET_AMD64) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_AMD64 -#elif defined(_TARGET_ARM_) +#elif defined(TARGET_ARM) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_ARMNT -#elif defined(_TARGET_ARM64_) +#elif defined(TARGET_ARM64) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_ARM64 #else #error "port me" @@ -338,6 +339,7 @@ class PEDecoder TADDR GetVirtualSectionsTable(COUNT_T *pSize = NULL) const; #endif // FEATURE_PREJIT + BOOL IsComponentAssembly() const; BOOL HasReadyToRunHeader() const; READYTORUN_HEADER *GetReadyToRunHeader() const; @@ -349,6 +351,9 @@ class PEDecoder BOOL HasNativeEntryPoint() const; void *GetNativeEntryPoint() const; + // Look up a named symbol in the export directory + void *GetExport(LPCSTR exportName) const; + #ifdef _DEBUG // Stress mode for relocations static BOOL GetForceRelocs(); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/pedecoder.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/pedecoder.inl index c17c03a..09bcfd7 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/pedecoder.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/pedecoder.inl @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. // -------------------------------------------------------------------------------- // PEDecoder.inl -// +// // -------------------------------------------------------------------------------- @@ -52,14 +52,14 @@ inline BOOL PEDecoder::IsMapped() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; - + return (m_flags & FLAG_MAPPED) != 0; } inline BOOL PEDecoder::IsRelocated() const { LIMITED_METHOD_CONTRACT; - + return (m_flags & FLAG_RELOCATED) != 0; } @@ -71,7 +71,7 @@ inline void PEDecoder::SetRelocated() inline BOOL PEDecoder::IsFlat() const { LIMITED_METHOD_CONTRACT; - + return HasContents() && !IsMapped(); } @@ -79,7 +79,7 @@ inline BOOL PEDecoder::HasContents() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; - + return (m_flags & FLAG_CONTENTS) != 0; } @@ -157,7 +157,7 @@ inline void PEDecoder::Init(void *flatBase, COUNT_T size) PRECONDITION((size == 0) || CheckPointer(flatBase)); PRECONDITION(!HasContents()); NOTHROW; - GC_NOTRIGGER; + GC_NOTRIGGER; } CONTRACTL_END; @@ -262,7 +262,7 @@ inline const void *PEDecoder::GetHeaders(COUNT_T *pSize) const //even though some data in OptionalHeader is different for 32 and 64, this field is the same if (pSize != NULL) - *pSize = VAL32(FindNTHeaders()->OptionalHeader.SizeOfHeaders); + *pSize = VAL32(FindNTHeaders()->OptionalHeader.SizeOfHeaders); RETURN (const void *) m_base; } @@ -742,7 +742,7 @@ inline COUNT_T PEDecoder::RvaToOffset(RVA rva) const IMAGE_SECTION_HEADER *section = RvaToSection(rva); if (section == NULL) return rva; - + return rva - VAL32(section->VirtualAddress) + VAL32(section->PointerToRawData); } else return 0; @@ -764,7 +764,7 @@ inline RVA PEDecoder::OffsetToRva(COUNT_T fileOffset) const { IMAGE_SECTION_HEADER *section = OffsetToSection(fileOffset); PREFIX_ASSUME (section!=NULL); //TODO: actually it is possible that it si null we need to rethink how we handle this cases and do better there - + return fileOffset - VAL32(section->PointerToRawData) + VAL32(section->VirtualAddress); } else return 0; @@ -873,7 +873,7 @@ inline CHECK PEDecoder::CheckTls() const CHECK(CheckUnderflow(VALPTR(pTlsHeader->EndAddressOfRawData), VALPTR(pTlsHeader->StartAddressOfRawData))); CHECK(VALPTR(pTlsHeader->EndAddressOfRawData) - VALPTR(pTlsHeader->StartAddressOfRawData) <= COUNT_T_MAX); - CHECK(CheckInternalAddress(VALPTR(pTlsHeader->StartAddressOfRawData), + CHECK(CheckInternalAddress(VALPTR(pTlsHeader->StartAddressOfRawData), (COUNT_T) (VALPTR(pTlsHeader->EndAddressOfRawData) - VALPTR(pTlsHeader->StartAddressOfRawData)))); CHECK_OK; @@ -916,7 +916,7 @@ inline UINT32 PEDecoder::GetTlsIndex() const CONTRACTL_END; IMAGE_TLS_DIRECTORY *pTlsHeader = (IMAGE_TLS_DIRECTORY *) GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_TLS); - + return (UINT32)*PTR_UINT32(GetInternalAddressData((SIZE_T)VALPTR(pTlsHeader->AddressOfIndex))); } @@ -1279,8 +1279,8 @@ inline void PEDecoder::GetPEKindAndMachine(DWORD * pdwPEKind, DWORD *pdwMachine) { dwMachine = GetMachine(); - BOOL fIsPE32Plus = !Has32BitNTHeaders(); - + BOOL fIsPE32Plus = !Has32BitNTHeaders(); + if (fIsPE32Plus) dwKind |= (DWORD)pe32Plus; @@ -1294,7 +1294,7 @@ inline void PEDecoder::GetPEKindAndMachine(DWORD * pdwPEKind, DWORD *pdwMachine) if (dwCorFlags & VAL32(COMIMAGE_FLAGS_ILONLY)) { dwKind |= (DWORD)peILonly; -#ifdef _WIN64 +#ifdef HOST_64BIT // compensate for shim promotion of PE32/ILONLY headers to PE32+ on WIN64 if (fIsPE32Plus && (GetMachine() == IMAGE_FILE_MACHINE_I386)) dwKind &= ~((DWORD)pe32Plus); @@ -1323,7 +1323,7 @@ inline void PEDecoder::GetPEKindAndMachine(DWORD * pdwPEKind, DWORD *pdwMachine) dwMachine = IMAGE_FILE_MACHINE_NATIVE; } - if ((GetReadyToRunHeader()->Flags & READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE) != 0) + if ((GetReadyToRunHeader()->CoreHeader.Flags & READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE) != 0) { // Supply the original PEKind/Machine to the assembly binder to make the full assembly name look like the original dwKind = peILonly; @@ -1355,6 +1355,21 @@ inline BOOL PEDecoder::IsPlatformNeutral() return ((dwKind & (peILonly | pe32Plus | pe32BitRequired)) == peILonly) && (dwMachine == IMAGE_FILE_MACHINE_I386); } +inline BOOL PEDecoder::IsComponentAssembly() const +{ + CONTRACTL + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACTL_END; + + return HasReadyToRunHeader() && (m_pReadyToRunHeader->CoreHeader.Flags & READYTORUN_FLAG_COMPONENT) != 0; +} + inline BOOL PEDecoder::HasReadyToRunHeader() const { CONTRACTL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/peinformation.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/peinformation.h index 8b5ac19..80e7f71 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/peinformation.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/peinformation.h @@ -13,7 +13,7 @@ #ifndef PEKIND_ENUM_DEFINED #define PEKIND_ENUM_DEFINED // This must match the definition of pekind in fusion.idl -typedef enum _tagPEKIND +typedef enum _tagPEKIND { peNone = 0x00000000, peMSIL = 0x00000001, @@ -43,19 +43,19 @@ inline bool IsPEMSIL(PEKIND x) return ( (x == peMSIL) ); } -#ifdef _WIN64 +#ifdef HOST_64BIT inline bool IsProcess32() { return false; } #else inline bool IsProcess32() { return true; } #endif -#if defined(_TARGET_X86_) +#if defined(TARGET_X86) inline PEKIND TargetNativePEKIND() { return peI386; } -#elif defined(_TARGET_AMD64_) +#elif defined(TARGET_AMD64) inline PEKIND TargetNativePEKIND() { return peAMD64; } -#elif defined(_TARGET_ARM_) +#elif defined(TARGET_ARM) inline PEKIND TargetNativePEKIND() { return peARM; } -#elif defined(_TARGET_ARM64_) +#elif defined(TARGET_ARM64) inline PEKIND TargetNativePEKIND() { return peARM64; } #else #error Need to define valid TargetNativePEKIND() diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/perflog.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/perflog.h deleted file mode 100644 index 84578d3..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/perflog.h +++ /dev/null @@ -1,142 +0,0 @@ -// 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. -//----------------------------------------------------------------------------- -// PerfLog.h - -// Internal interface for logging perfromance data. Currently, two types of logging -// formats are supported, Pretty print for stdout and perf automation friendly -// format. -// The logging code is compiled in for retail builds but logs are generated only if -// PERF_OUTPUT environment variable is set. (This can be changed to a registry entry -// if we want perf logs on CE or other platforms that don't supprt env vars.)) -//----------------------------------------------------------------------------- - -#include "contract.h" - -#ifndef _PERFLOG_H_ -#define _PERFLOG_H_ - -#if !defined(_WIN64) && !defined(DACCESS_COMPILE) -#define ENABLE_PERF_LOG -#else -#undef ENABLE_PERF_LOG -#endif - -// Also disable Perf logging code if there's a explicite define to do so in SOURCES -// file or another hdr file. This provides one point where all perf log related baggage -// can be avoided in the build. -#if defined(DISABLE_PERF_LOG) -#undef ENABLE_PERF_LOG -#endif - - -//----------------------------------------------------------------------------- -// PERFLOG is the public interface that should be used from EE source to log perf data. -// If -#if !defined (ENABLE_PERF_LOG) -#define PERFLOG(x) -#else -#define PERFLOG(x) do {if (PerfLog::PerfLoggingEnabled()) PerfLog::Log x;} while (0) -#endif - -//============================================================================= -// ALL THE PERF LOG CODE IS COMPILED ONLY IF THE ENABLE_PERF_LOG WAS DEFINED. -#if defined (ENABLE_PERF_LOG) -//============================================================================= -//----------------------------------------------------------------------------- -// Static allocation of logging related memory, avoid dynamic allocation to -// skew perf numbers. -#define PRINT_STR_LEN 256 // Temp work space -#define MAX_CHARS_UNIT 20 -#define MAX_CHARS_DIRECTION 6 - -//----------------------------------------------------------------------------- -// ENUM of units for all kinds of perf data the we might get. Grow this as needed. -// **keep in sync *** with the array of strings defined in PerfLog.cpp -typedef enum -{ - COUNT = 0, - SECONDS, - BYTES, - KBYTES, - KBYTES_PER_SEC, - CYCLES, - MAX_UNITS_OF_MEASURE -} UnitOfMeasure; - -//----------------------------------------------------------------------------- -// Widechar strings representing the above units. *** Keep in sync *** with the -// array defined in PerfLog.cpp -extern const wchar_t * const wszUnitOfMeasureDescr[MAX_UNITS_OF_MEASURE]; - -//----------------------------------------------------------------------------- -// Widechar strings representing the "direction" property of above units. -// *** Keep in sync *** with the array defined in PerfLog.cpp -// "Direction" property is false if an increase in the value of the counter indicates -// a degrade. -// "Direction" property is true if an increase in the value of the counter indicates -// an improvement. -extern const wchar_t * const wszIDirection[MAX_UNITS_OF_MEASURE]; - -//----------------------------------------------------------------------------- -// Namespace for perf log. Don't create perf log objects (private ctor). -class PerfLog -{ -public: - - // Called during EEStartup - static void PerfLogInitialize(); - - // Called during EEShutdown - static void PerfLogDone(); - - // Perf logging is enabled if the env var PERF_LOG is set. - static int PerfLoggingEnabled () { LIMITED_METHOD_CONTRACT; return m_fLogPerfData; } - - // Perf automation format is desired. - static bool PerfAutomationFormat () { LIMITED_METHOD_CONTRACT; return m_perfAutomationFormat; } - - // CSV format is desired. - static bool CommaSeparatedFormat () { LIMITED_METHOD_CONTRACT; return m_commaSeparatedFormat; } - - // Overloaded member functions to print different data types. Grow as needed. - // wszName is the name of thet perf counter, val is the perf counter value, - static void Log(__in_z wchar_t const *wszName, UINT val, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr = 0); - static void Log(__in_z wchar_t const *wszName, UINT64 val, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr = 0); - static void Log(__in_z wchar_t const *wszName, double val, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr = 0); - -private: - PerfLog(); - ~PerfLog(); - - // Helper routine to hide some details of the perf automation - static void OutToPerfFile(__in_z const wchar_t *wszName, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr = 0); - - // Helper routine to hide some details of output to stdout - static void OutToStdout(__in_z const wchar_t *wszName, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr = 0); - - // Perf log initialized ? - static bool m_perfLogInit; - - // Output in perf automation format ? - static bool m_perfAutomationFormat; - - // Output in csv format ? - static bool m_commaSeparatedFormat; - - // Temp storage to convert wide char to multibyte for file IO. - static wchar_t m_wszOutStr_1[PRINT_STR_LEN]; - static DWORD m_dwWriteByte; - - // State of the env var PERF_OUTPUT - static int m_fLogPerfData; - - // Open handle of the file which is used by the perf auotmation. (Currently - // its at C:\PerfData.data - static HANDLE m_hPerfLogFileHandle; -}; - -#endif // ENABLE_PERF_LOG - -#endif //_PERFLOG_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/pesectionman.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/pesectionman.h index f031ca3..184743d 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/pesectionman.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/pesectionman.h @@ -42,21 +42,21 @@ public: HRESULT cloneInstance(PESectionMan *destination); protected: - + // Finds section with given name. returns 0 if not found virtual PESection *getSection(const char *name); - + // Create a new section virtual HRESULT newSection( - const char *name, + const char *name, PESection **section, - unsigned flags = sdNone, - unsigned estSize = 0x10000, + unsigned flags = sdNone, + unsigned estSize = 0x10000, unsigned estRelocs = 1); - - // Keep proctected & no accessors, so that derived class PEWriter + + // Keep proctected & no accessors, so that derived class PEWriter // is the ONLY one with access - + PESection **sectStart; PESection **sectCur; PESection **sectEnd; @@ -72,38 +72,38 @@ protected: * as a flat consecutive piece of memory which can be indexed into * using offsets. */ - + class PESection : public CeeSectionImpl { public: // bytes in this section at present - unsigned dataLen(); + unsigned dataLen(); // Apply all the relocs for in memory conversion HRESULT applyRelocs(CeeGenTokenMapper *pTokenMapper); - + // get a block to write on (use instead of write to avoid copy) char* getBlock(unsigned len, unsigned align=1); // writes 'val' (which is offset into section 'relativeTo') // and adds a relocation fixup for that section - void writeSectReloc(unsigned val, CeeSection& relativeTo, + void writeSectReloc(unsigned val, CeeSection& relativeTo, CeeSectionRelocType reloc = srRelocHighLow, CeeSectionRelocExtra *extra=0); - + // Indicates that the DWORD at 'offset' in the current section should // have the base of section 'relativeTo' added to it - HRESULT addSectReloc(unsigned offset, CeeSection& relativeTo, + HRESULT addSectReloc(unsigned offset, CeeSection& relativeTo, CeeSectionRelocType reloc = srRelocHighLow, CeeSectionRelocExtra *extra=0); // If relativeTo is NULL, it is treated as a base reloc. // ie. the value only needs to be fixed at load time if the module gets rebased. - HRESULT addSectReloc(unsigned offset, PESection *relativeTo, + HRESULT addSectReloc(unsigned offset, PESection *relativeTo, CeeSectionRelocType reloc = srRelocHighLow, CeeSectionRelocExtra *extra=0); // Add a base reloc for the given offset in the current section - HRESULT addBaseReloc(unsigned offset, CeeSectionRelocType reloc = srRelocHighLow, + HRESULT addBaseReloc(unsigned offset, CeeSectionRelocType reloc = srRelocHighLow, CeeSectionRelocExtra *extra = 0); // section name @@ -152,29 +152,29 @@ class PESection : public CeeSectionImpl { virtual ~PESection(); private: - // purposely not defined, - PESection(); + // purposely not defined, + PESection(); // purposely not defined, - PESection(const PESection&); + PESection(const PESection&); // purposely not defined, - PESection& operator=(const PESection& x); + PESection& operator=(const PESection& x); // this dir entry points to this section - int dirEntry; + int dirEntry; protected: friend class PEWriter; friend class PEWriterSection; friend class PESectionMan; - PESection(const char* name, unsigned flags, + PESection(const char* name, unsigned flags, unsigned estSize, unsigned estRelocs); // Blob fetcher handles getBlock() and fetching binary chunks. CBlobFetcher m_blobFetcher; - + PESectionReloc* m_relocStart; PESectionReloc* m_relocCur; PESectionReloc* m_relocEnd; @@ -183,7 +183,7 @@ protected: unsigned m_baseRVA; // RVA into the file of this section. unsigned m_filePos; // Start offset into the file (treated as a data image) unsigned m_filePad; // Padding added to the end of the section for alignment - + char m_name[8+6]; // extra room for digits unsigned m_flags; @@ -193,10 +193,10 @@ protected: /***************************************************************/ /* implementation section */ -inline HRESULT PESection::directoryEntry(unsigned num) { +inline HRESULT PESection::directoryEntry(unsigned num) { WRAPPER_NO_CONTRACT; TESTANDRETURN(num < 16, E_INVALIDARG); - dirEntry = num; + dirEntry = num; return S_OK; } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/posterror.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/posterror.h index 816d14e..3862956 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/posterror.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/posterror.h @@ -35,11 +35,11 @@ HRESULT __cdecl PostErrorVA( // Returned error. //***************************************************************************** // This function formats an error message, but doesn't fill the IErrorInfo. //***************************************************************************** -HRESULT __cdecl FormatRuntimeErrorVa( - __out_ecount(cchMsg) WCHAR *rcMsg, // Buffer into which to format. - ULONG cchMsg, // Size of buffer, characters. - HRESULT hrRpt, // The HR to report. - va_list marker); // Optional args. +HRESULT __cdecl FormatRuntimeErrorVa( + __out_ecount(cchMsg) WCHAR *rcMsg, // Buffer into which to format. + ULONG cchMsg, // Size of buffer, characters. + HRESULT hrRpt, // The HR to report. + va_list marker); // Optional args. HRESULT __cdecl FormatRuntimeError( __out_ecount(cchMsg) WCHAR *rcMsg, // Buffer into which to format. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/predeftlsslot.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/predeftlsslot.h index c2c59f2..eba2dc1 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/predeftlsslot.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/predeftlsslot.h @@ -8,56 +8,16 @@ #define __PREDEFTLSSLOT_H__ // ****************************************************************************** -// WARNING!!!: These enums are used by SOS in the diagnostics repo. Values should +// WARNING!!!: These enums are used by SOS in the diagnostics repo. Values should // added or removed in a backwards and forwards compatible way. // See: https://github.com/dotnet/diagnostics/blob/master/src/inc/predeftlsslot.h // ****************************************************************************** -// And here are the predefined slots for accessing TLS from various DLLs of the CLR. -// Note that we want to support combinations of Debug and Retail DLLs for testing -// purposes, so we burn the slots into the retail EE even if a debug CLR dll needs -// them. +// The historic location of ThreadType slot kept for compatibility with SOS +// TODO: Introduce DAC API to make this hack unnecessary enum PredefinedTlsSlots { - TlsIdx_StrongName, - TlsIdx_JitPerf, - TlsIdx_JitX86Perf, - TlsIdx_JitLogEnv, - TlsIdx_AssertDlgStatus, // Whether the thread is displaying an assert dialog - TlsIdx_StressLog, - TlsIdx_CantStopCount, // Can't-stop counter for any thread - TlsIdx_Check, - TlsIdx_ForbidGCLoaderUseCount, - TlsIdx_ClrDebugState, // Pointer to ClrDebugState* structure - TlsIdx_StressThread, - - // Add more indices here. - TlsIdx_ThreadType, // bit flags to indicate special thread's type - TlsIdx_OwnedCrstsChain, // slot to store the Crsts owned by this thread - TlsIdx_CantAllocCount, //Can't allocate memory on heap in this thread - - // A transient thread value that indicates this thread is currently walking its stack - // or the stack of another thread. This value is useful to help short-circuit - // some problematic checks in the loader, guarantee that types & assemblies - // encountered during the walk must already be loaded, and provide information to control - // assembly loading behavior during stack walks. - // - // This value is set around the main portions of the stack walk (as those portions may - // enter the type & assembly loaders). This is also explicitly cleared while the - // walking thread calls the stackwalker callback or needs to execute managed code, as - // such calls may execute arbitrary code unrelated to the actual stack walking, and - // may never return, in the case of exception stackwalk callbacks. - TlsIdx_StackWalkerWalkingThread, // Thread* that the stack walker is currently walking. - - // Save the last exception info. Sometimes we need this info in our EX_CATCH, such as for SO. - // It will be better if VC can supply this in catch(...) block. - // !!! These data may become stale. Use it only inside exception handling code. - // !!! Please access these fields through GetCurrentExceptionPointers which validates the data to some level. - TlsIdx_EXCEPTION_CODE, - TlsIdx_PEXCEPTION_RECORD, - TlsIdx_PCONTEXT, - - MAX_PREDEFINED_TLS_SLOT + TlsIdx_ThreadType = 11 // bit flags to indicate special thread's type }; enum TlsThreadTypeFlag // flag used for thread type in Tls data @@ -77,10 +37,8 @@ enum TlsThreadTypeFlag // flag used for thread type in Tls data ThreadType_ProfAPI_Attach = 0x00004000, ThreadType_ProfAPI_Detach = 0x00008000, ThreadType_ETWRundownThread = 0x00010000, - ThreadType_GenericInstantiationCompare= 0x00020000, // Used to indicate that the thread is determining if a generic instantiation in an ngen image matches a lookup. + ThreadType_GenericInstantiationCompare= 0x00020000, // Used to indicate that the thread is determining if a generic instantiation in an ngen image matches a lookup. }; -static_assert(TlsIdx_ThreadType == 11, "SOS in diagnostics repo has a dependency on this value."); - #endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/prettyprintsig.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/prettyprintsig.h index adab46e..c5dd917 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/prettyprintsig.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/prettyprintsig.h @@ -78,10 +78,10 @@ struct IMDInternalImport; // of this string. // HRESULT PrettyPrintSigInternalLegacy( // S_OK or error. - PCCOR_SIGNATURE sigPtr, // sig to convert, + PCCOR_SIGNATURE sigPtr, // sig to convert, unsigned sigLen, // length of sig LPCSTR name, // can be "", the name of the method for this sig - CQuickBytes *out, // where to put the pretty printed string + CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI); // Import api to use. // diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/profilepriv.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/profilepriv.h index acec829..8258b05 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/profilepriv.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/profilepriv.h @@ -1,13 +1,13 @@ // 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. -// +// // ProfilePriv.h -// +// // // Structures, etc. used by the Profiling API and throughout the EE -// +// // ====================================================================================== @@ -29,7 +29,7 @@ struct ScanContext; //--------------------------------------------------------------------------------------- // Enumerates the various init states of profiling. -// +// // *** NOTE: The order is important here, as some of the status checks (e.g., // CORProfilerPresentOrInitializing) use ">" with these enum values. *** @@ -60,7 +60,7 @@ public: // Global struct that lets the EE see the load status of the profiler, and provides a // pointer (pProfInterface) through which profiler calls can be made // -// When you are adding new session, please refer to +// When you are adding new session, please refer to // code:ProfControlBlock::ResetPerSessionStatus#ProfileResetSessionStatus for more details. struct ProfControlBlock { @@ -73,7 +73,7 @@ struct ProfControlBlock // code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization VolatilePtr pProfInterface; // **** IMPORTANT!! **** - + DWORD dwEventMask; // Original low event mask bits DWORD dwEventMaskHigh; // New high event mask bits CurrentProfilerStatus curProfStatus; @@ -88,7 +88,7 @@ struct ProfControlBlock // (e.g., stack walking). When this BOOL is TRUE, the JIT will insert calls to the // slow-path profiling API enter/leave/tailcall hooks, which will forward the call to // a profiler if one is loaded (and do nothing otherwise). - // + // // See code:AreCallbackStateFlagsSet#P2CLRRestrictionsOverview for general information // on how the test hooks lift restrictions normally in place for the Info functions. BOOL fTestOnlyForceEnterLeave; @@ -97,19 +97,19 @@ struct ProfControlBlock #ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED_DATA // #TestOnlyObjectAllocated This implements a test-only (and debug-only) hook that allows // a test profiler to ensure ObjectAllocated callback is enabled on startup even though no - // profiler is loaded on startup. This allows an attach profiler to use ObjectAllocated + // profiler is loaded on startup. This allows an attach profiler to use ObjectAllocated // callback for the sole purpose of verifying OTHER GC areas of the profiling API - // (e.g., constructing a object graph). When this BOOL is TRUE, the JIT will use special - // version of new allocators that issue object allocation notifications, which will forward + // (e.g., constructing a object graph). When this BOOL is TRUE, the JIT will use special + // version of new allocators that issue object allocation notifications, which will forward // the notifications to a profiler if one is loaded (and do nothing otherwise). - // + // // See code:AreCallbackStateFlagsSet#P2CLRRestrictionsOverview for general information // on how the test hooks lift restrictions normally in place for the Info functions. BOOL fTestOnlyForceObjectAllocated; -#endif +#endif #ifdef _DEBUG - // Test-only, debug-only code to allow attaching profilers to call ICorProfilerInfo inteface, + // Test-only, debug-only code to allow attaching profilers to call ICorProfilerInfo inteface, // which would otherwise be disallowed for attaching profilers BOOL fTestOnlyEnableICorProfilerInfo; #endif // _DEBUG @@ -120,9 +120,9 @@ struct ProfControlBlock Volatile fProfControlBlockInitialized; Volatile fProfilerRequestedRuntimeSuspend; - + void Init(); - void ResetPerSessionStatus(); + void ResetPerSessionStatus(); }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/profilepriv.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/profilepriv.inl index 5a0513f..1d4d859 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/profilepriv.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/profilepriv.inl @@ -1,15 +1,15 @@ // 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. -// +// // ProfilePriv.inl -// +// -// +// // Inlined functions used by the Profiling API and throughout the EE. Most notably are // the CORProfilerTrack* functions that test whether a profiler is active and responding // to various callbacks -// +// // ====================================================================================== #ifndef _ProfilePriv_inl_ @@ -61,7 +61,7 @@ inline void ProfControlBlock::Init() #ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED fTestOnlyForceObjectAllocated = FALSE; -#endif +#endif #ifdef _DEBUG fTestOnlyEnableICorProfilerInfo = FALSE; @@ -80,7 +80,7 @@ inline void ProfControlBlock::Init() inline void ProfControlBlock::ResetPerSessionStatus() { LIMITED_METHOD_CONTRACT; - + pProfInterface = NULL; dwEventMask = COR_PRF_MONITOR_NONE; dwEventMaskHigh = COR_PRF_HIGH_MONITOR_NONE; @@ -114,9 +114,9 @@ inline BOOL CORProfilerFunctionIDMapperEnabled() } CONTRACTL_END; - return (CORProfilerPresent() && + return (CORProfilerPresent() && ( - ((&g_profControlBlock)->pProfInterface->GetFunctionIDMapper() != NULL) || + ((&g_profControlBlock)->pProfInterface->GetFunctionIDMapper() != NULL) || ((&g_profControlBlock)->pProfInterface->GetFunctionIDMapper2() != NULL) )); } @@ -243,7 +243,7 @@ inline BOOL CORProfilerTrackAllocationsEnabled() } CONTRACTL_END; - return + return ( #ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED (&g_profControlBlock)->fTestOnlyForceObjectAllocated || @@ -311,20 +311,6 @@ inline BOOL CORProfilerTrackExceptions() ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_EXCEPTIONS)); } -inline BOOL CORProfilerTrackCLRExceptions() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; - - return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CLR_EXCEPTIONS)); -} - inline BOOL CORProfilerTrackTransitions() { CONTRACTL @@ -397,7 +383,7 @@ inline BOOL CORProfilerTrackRemotingCookie() CONTRACTL_END; return - (CORProfilerPresent() && + (CORProfilerPresent() && (((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING_COOKIE) == COR_PRF_MONITOR_REMOTING_COOKIE)); } @@ -413,7 +399,7 @@ inline BOOL CORProfilerTrackRemotingAsync() CONTRACTL_END; return - (CORProfilerPresent() && + (CORProfilerPresent() && (((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING_ASYNC) == COR_PRF_MONITOR_REMOTING_ASYNC)); } @@ -493,7 +479,7 @@ inline BOOL CORProfilerUseProfileImages() if (!CORProfilerPresent()) return FALSE; - if (((&g_profControlBlock)->dwEventMask & + if (((&g_profControlBlock)->dwEventMask & COR_PRF_REQUIRE_PROFILE_IMAGE) == 0) return FALSE; @@ -517,7 +503,7 @@ inline BOOL CORProfilerTrackConditionalWeakTableElements() // CORProfilerPresentOrInitializing() returns nonzero iff a CLR Profiler is actively // loaded and ready to receive callbacks OR a CLR Profiler has loaded just enough that it -// is ready to receive (or is currently executing inside) its Initialize() callback. +// is ready to receive (or is currently executing inside) its Initialize() callback. // Typically, you'll want to use code:CORProfilerPresent instead of this. But there is // some internal profiling API code that wants to test for event flags for a profiler // that may still be initializing, and this function is appropriate for that code. @@ -528,7 +514,7 @@ inline BOOL CORProfilerPresentOrInitializing() } // These return whether a CLR Profiler has requested the specified functionality. -// +// // Note that, unlike the above functions, a profiler that's not done loading (and is // still somewhere in the initialization phase) still counts. This is only safe because // these functions are not used to determine whether to issue a callback. These functions @@ -545,7 +531,7 @@ inline BOOL CORProfilerELT3SlowPathEnabled() } CONTRACTL_END; - return (CORProfilerPresentOrInitializing() && + return (CORProfilerPresentOrInitializing() && ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); } @@ -559,7 +545,7 @@ inline BOOL CORProfilerELT3SlowPathEnterEnabled() } CONTRACTL_END; - return (CORProfilerPresentOrInitializing() && + return (CORProfilerPresentOrInitializing() && ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO))); } @@ -573,7 +559,7 @@ inline BOOL CORProfilerELT3SlowPathLeaveEnabled() } CONTRACTL_END; - return (CORProfilerPresentOrInitializing() && + return (CORProfilerPresentOrInitializing() && ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); } @@ -587,7 +573,7 @@ inline BOOL CORProfilerELT3SlowPathTailcallEnabled() } CONTRACTL_END; - return (CORProfilerPresentOrInitializing() && + return (CORProfilerPresentOrInitializing() && ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FRAME_INFO))); } @@ -601,7 +587,7 @@ inline BOOL CORProfilerELT2FastPathEnterEnabled() } CONTRACTL_END; - return (CORProfilerPresentOrInitializing() && + return (CORProfilerPresentOrInitializing() && (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO)))); } @@ -615,7 +601,7 @@ inline BOOL CORProfilerELT2FastPathLeaveEnabled() } CONTRACTL_END; - return (CORProfilerPresentOrInitializing() && + return (CORProfilerPresentOrInitializing() && (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)))); } @@ -629,7 +615,7 @@ inline BOOL CORProfilerELT2FastPathTailcallEnabled() } CONTRACTL_END; - return (CORProfilerPresentOrInitializing() && + return (CORProfilerPresentOrInitializing() && (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FRAME_INFO)))); } @@ -643,7 +629,7 @@ inline BOOL CORProfilerFunctionArgsEnabled() } CONTRACTL_END; - return (CORProfilerPresentOrInitializing() && + return (CORProfilerPresentOrInitializing() && ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FUNCTION_ARGS)); } @@ -657,7 +643,7 @@ inline BOOL CORProfilerFunctionReturnValueEnabled() } CONTRACTL_END; - return (CORProfilerPresentOrInitializing() && + return (CORProfilerPresentOrInitializing() && ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FUNCTION_RETVAL)); } @@ -671,7 +657,7 @@ inline BOOL CORProfilerFrameInfoEnabled() } CONTRACTL_END; - return (CORProfilerPresentOrInitializing() && + return (CORProfilerPresentOrInitializing() && ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FRAME_INFO)); } @@ -685,7 +671,7 @@ inline BOOL CORProfilerStackSnapshotEnabled() } CONTRACTL_END; - return (CORProfilerPresentOrInitializing() && + return (CORProfilerPresentOrInitializing() && ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_STACK_SNAPSHOT)); } @@ -699,7 +685,7 @@ inline BOOL CORProfilerAddsAssemblyReferences() } CONTRACTL_END; - return (CORProfilerPresent() && + return (CORProfilerPresent() && ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES)); } @@ -733,7 +719,7 @@ inline BOOL CORProfilerIsMonitoringDynamicFunctionUnloads() inline BOOL CORProfilerDisableTieredCompilation() { - CONTRACTL + CONTRACTL { NOTHROW; GC_NOTRIGGER; @@ -748,7 +734,7 @@ inline BOOL CORProfilerDisableTieredCompilation() inline BOOL CORProfilerTrackBasicGC() { - CONTRACTL + CONTRACTL { NOTHROW; GC_NOTRIGGER; @@ -762,7 +748,7 @@ inline BOOL CORProfilerTrackBasicGC() inline BOOL CORProfilerTrackGCMovedObjects() { - CONTRACTL + CONTRACTL { NOTHROW; GC_NOTRIGGER; @@ -783,13 +769,13 @@ inline BOOL CORProfilerTrackGCMovedObjects() // the stack to increment the evacuation counter inside the EE Thread. Upon returning to // EE, this EvacuationCounterHolder object when being destroyed decreases the evacuation // counter by one. -// +// // Do not use this object directly. Use BEGIN_PIN_PROFILER / END_PIN_PROFILER defined // below. -// +// // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization. -// -typedef Wrapper> EvacuationCounterHolder; @@ -821,11 +807,11 @@ typedef WrapperpMD->IsQCall())") is only evaluated if the profiler is loaded. That way, we're // not executing extra, unnecessary instructions when no profiler is present. -// +// // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization // for more details about how the synchronization works. #define BEGIN_PIN_PROFILER(condition) \ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/random.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/random.h index cbf2d21..2c2f94a 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/random.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/random.h @@ -3,9 +3,9 @@ // See the LICENSE file in the project root for more information. // // random.h -// +// -// +// // Defines a random number generator, initially from the System.Random code in the BCL. If you notice any problems, // please compare to the implementation in src\mscorlib\src\system\random.cs. // @@ -44,11 +44,11 @@ #endif //!DO_NOT_DISABLE_RAND && !USE_STL -class CLRRandom +class CLRRandom { private: // - // Private Constants + // Private Constants // static const int MBIG = INT_MAX; static const int MSEED = 161803398; @@ -75,7 +75,7 @@ public: initialized = false; } - void Init() + void Init() { LIMITED_METHOD_CONTRACT; LARGE_INTEGER time; @@ -84,7 +84,7 @@ public: Init((int)time.u.LowPart ^ GetCurrentThreadId() ^ GetCurrentProcessId()); } - void Init(int Seed) + void Init(int Seed) { LIMITED_METHOD_CONTRACT; @@ -115,7 +115,7 @@ public: initialized = true; } - bool IsInitialized() + bool IsInitialized() { LIMITED_METHOD_CONTRACT; return initialized; @@ -132,7 +132,7 @@ private: **Arguments: None **Exceptions: None ==============================================================================*/ - double Sample() + double Sample() { LIMITED_METHOD_CONTRACT; @@ -141,7 +141,7 @@ private: return (InternalSample()*(1.0/MBIG)); } - int InternalSample() + int InternalSample() { LIMITED_METHOD_CONTRACT; @@ -154,7 +154,7 @@ private: retVal = SeedArray[locINext]-SeedArray[locINextp]; - if (retVal == MBIG) retVal--; + if (retVal == MBIG) retVal--; if (retVal<0) retVal+=MBIG; SeedArray[locINext]=retVal; @@ -165,11 +165,11 @@ private: return retVal; } - double GetSampleForLargeRange() + double GetSampleForLargeRange() { LIMITED_METHOD_CONTRACT; - // The distribution of double value returned by Sample + // The distribution of double value returned by Sample // is not distributed well enough for a large range. // If we use Sample for a range [Int32.MinValue..Int32.MaxValue) // We will end up getting even numbers only. @@ -182,14 +182,14 @@ private: } double d = result; d += (INT_MAX - 1); // get a number in range [0 .. 2 * Int32MaxValue - 1) - d /= 2*(unsigned int)INT_MAX - 1 ; + d /= 2*(unsigned int)INT_MAX - 1 ; return d; } public: // // Public Instance Methods - // + // /*=====================================Next===================================== @@ -197,7 +197,7 @@ public: **Arguments: None **Exceptions: None. ==============================================================================*/ - int Next() + int Next() { LIMITED_METHOD_CONTRACT; _ASSERTE(initialized); @@ -211,8 +211,8 @@ public: ** maxValue -- One greater than the greatest legal return value. **Exceptions: None. ==============================================================================*/ - int Next(int minValue, int maxValue) - { + int Next(int minValue, int maxValue) + { LIMITED_METHOD_CONTRACT; _ASSERTE(initialized); _ASSERTE(minValue < maxValue); @@ -220,9 +220,9 @@ public: LONGLONG range = (LONGLONG)maxValue-minValue; double result; - if( range <= (LONGLONG)INT_MAX) + if( range <= (LONGLONG)INT_MAX) result = (Sample() * range) + minValue; - else + else result = (GetSampleForLargeRange() * range) + minValue; _ASSERTE(result >= minValue && result < maxValue); @@ -235,7 +235,7 @@ public: **Arguments: maxValue -- One more than the greatest legal return value. **Exceptions: None. ==============================================================================*/ - int Next(int maxValue) + int Next(int maxValue) { LIMITED_METHOD_CONTRACT; _ASSERTE(initialized); @@ -250,7 +250,7 @@ public: **Arguments: None **Exceptions: None ==============================================================================*/ - double NextDouble() + double NextDouble() { LIMITED_METHOD_CONTRACT; _ASSERTE(initialized); @@ -271,7 +271,7 @@ public: LIMITED_METHOD_CONTRACT; _ASSERTE(initialized); for (int i=0; iControlPC); } @@ -65,11 +65,11 @@ inline void SetRegdisplaySP(REGDISPLAY_BASE *pRD, LPVOID sp) { pRD->SP = (TADDR)sp; } -#if defined(_TARGET_X86_) +#if defined(TARGET_X86) struct REGDISPLAY : public REGDISPLAY_BASE { -#ifndef WIN64EXCEPTIONS +#ifndef FEATURE_EH_FUNCLETS // TODO: Unify with pCurrentContext / pCallerContext used on 64-bit PCONTEXT pContextForUnwind; // scratch context for unwinding // used to preserve context saved in the frame that @@ -83,21 +83,25 @@ struct REGDISPLAY : public REGDISPLAY_BASE { DWORD * pEax; DWORD * pEbp; -#endif // !WIN64EXCEPTIONS +#endif // !FEATURE_EH_FUNCLETS -#ifndef WIN64EXCEPTIONS +#ifndef FEATURE_EH_FUNCLETS #define REG_METHODS(reg) \ inline PDWORD Get##reg##Location(void) { return p##reg; } \ inline void Set##reg##Location(PDWORD p##reg) { this->p##reg = p##reg; } -#else // !WIN64EXCEPTIONS +#else // !FEATURE_EH_FUNCLETS #define REG_METHODS(reg) \ inline PDWORD Get##reg##Location(void) { return pCurrentContextPointers->reg; } \ - inline void Set##reg##Location(PDWORD p##reg) { pCurrentContextPointers->reg = p##reg; } + inline void Set##reg##Location(PDWORD p##reg) \ + { \ + pCurrentContextPointers->reg = p##reg; \ + pCurrentContext->reg = *p##reg; \ + } -#endif // WIN64EXCEPTIONS +#endif // FEATURE_EH_FUNCLETS REG_METHODS(Eax) REG_METHODS(Ecx) @@ -115,13 +119,16 @@ struct REGDISPLAY : public REGDISPLAY_BASE { inline TADDR GetRegdisplayFP(REGDISPLAY *display) { LIMITED_METHOD_DAC_CONTRACT; - +#ifdef FEATURE_EH_FUNCLETS + return (TADDR)display->pCurrentContext->Ebp; +#else return (TADDR)*display->GetEbpLocation(); +#endif } inline LPVOID GetRegdisplayFPAddress(REGDISPLAY *display) { LIMITED_METHOD_CONTRACT; - + return (LPVOID)display->GetEbpLocation(); } @@ -130,7 +137,7 @@ inline LPVOID GetRegdisplayFPAddress(REGDISPLAY *display) { inline BOOL IsInCalleesFrames(REGDISPLAY *display, LPVOID stackPointer) { LIMITED_METHOD_CONTRACT; -#ifdef WIN64EXCEPTIONS +#ifdef FEATURE_EH_FUNCLETS return stackPointer < ((LPVOID)(display->SP)); #else return (TADDR)stackPointer < display->PCTAddr; @@ -139,7 +146,7 @@ inline BOOL IsInCalleesFrames(REGDISPLAY *display, LPVOID stackPointer) { inline TADDR GetRegdisplayStackMark(REGDISPLAY *display) { LIMITED_METHOD_DAC_CONTRACT; -#ifdef WIN64EXCEPTIONS +#ifdef FEATURE_EH_FUNCLETS _ASSERTE(GetRegdisplaySP(display) == GetSP(display->pCurrentContext)); return GetRegdisplaySP(display); #else @@ -147,9 +154,9 @@ inline TADDR GetRegdisplayStackMark(REGDISPLAY *display) { #endif } -#elif defined(_TARGET_64BIT_) +#elif defined(TARGET_64BIT) -#if defined(_TARGET_ARM64_) +#if defined(TARGET_ARM64) typedef struct _Arm64VolatileContextPointer { union { @@ -177,9 +184,9 @@ typedef struct _Arm64VolatileContextPointer PDWORD64 X[18]; }; } Arm64VolatileContextPointer; -#endif //_TARGET_ARM64_ +#endif //TARGET_ARM64 struct REGDISPLAY : public REGDISPLAY_BASE { -#ifdef _TARGET_ARM64_ +#ifdef TARGET_ARM64 Arm64VolatileContextPointer volatileCurrContextPointers; #endif @@ -193,12 +200,12 @@ struct REGDISPLAY : public REGDISPLAY_BASE { inline TADDR GetRegdisplayFP(REGDISPLAY *display) { LIMITED_METHOD_CONTRACT; - return NULL; + return NULL; } inline TADDR GetRegdisplayFPAddress(REGDISPLAY *display) { LIMITED_METHOD_CONTRACT; - return NULL; + return NULL; } // This function tells us if the given stack pointer is in one of the frames of the functions called by the given frame @@ -210,32 +217,32 @@ inline BOOL IsInCalleesFrames(REGDISPLAY *display, LPVOID stackPointer) inline TADDR GetRegdisplayStackMark(REGDISPLAY *display) { -#if defined(_TARGET_AMD64_) +#if defined(TARGET_AMD64) // On AMD64, the MemoryStackFp value is the current sp (i.e. the sp value when calling another method). _ASSERTE(GetRegdisplaySP(display) == GetSP(display->pCurrentContext)); return GetRegdisplaySP(display); -#elif defined(_TARGET_ARM64_) +#elif defined(TARGET_ARM64) _ASSERTE(display->IsCallerContextValid); return GetSP(display->pCallerContext); -#else // _TARGET_AMD64_ +#else // TARGET_AMD64 PORTABILITY_ASSERT("GetRegdisplayStackMark NYI for this platform (Regdisp.h)"); return NULL; -#endif // _TARGET_AMD64_ +#endif // TARGET_AMD64 } -#elif defined(_TARGET_ARM_) +#elif defined(TARGET_ARM) // ResumableFrame is pushed on the stack before -// starting the GC. registers r0-r3 in ResumableFrame can +// starting the GC. registers r0-r3 in ResumableFrame can // contain roots which might need to be updated if they are // relocated. On Stack walking the addresses of the registers in the // resumable Frame are passed to GC using pCurrentContextPointers // member in _REGDISPLAY. However On ARM KNONVOLATILE_CONTEXT_POINTERS // does not contain pointers for volatile registers. Therefore creating -// this structure to store pointers to volatile registers and adding an object +// this structure to store pointers to volatile registers and adding an object // as member in _REGDISPLAY typedef struct _ArmVolatileContextPointer { @@ -282,19 +289,19 @@ inline TADDR GetRegdisplayStackMark(REGDISPLAY *display) { #error "RegDisplay functions are not implemented on this platform." #endif -#if defined(_TARGET_64BIT_) || defined(_TARGET_ARM_) || (defined(_TARGET_X86_) && defined(WIN64EXCEPTIONS)) +#if defined(TARGET_64BIT) || defined(TARGET_ARM) || (defined(TARGET_X86) && defined(FEATURE_EH_FUNCLETS)) // This needs to be implemented for platforms that have funclets. inline LPVOID GetRegdisplayReturnValue(REGDISPLAY *display) { LIMITED_METHOD_CONTRACT; -#if defined(_TARGET_AMD64_) +#if defined(TARGET_AMD64) return (LPVOID)display->pCurrentContext->Rax; -#elif defined(_TARGET_ARM64_) +#elif defined(TARGET_ARM64) return (LPVOID)display->pCurrentContext->X0; -#elif defined(_TARGET_ARM_) +#elif defined(TARGET_ARM) return (LPVOID)((TADDR)display->pCurrentContext->R0); -#elif defined(_TARGET_X86_) +#elif defined(TARGET_X86) return (LPVOID)display->pCurrentContext->Eax; #else PORTABILITY_ASSERT("GetRegdisplayReturnValue NYI for this platform (Regdisp.h)"); @@ -306,16 +313,16 @@ inline void SyncRegDisplayToCurrentContext(REGDISPLAY* pRD) { LIMITED_METHOD_CONTRACT; -#if defined(_TARGET_64BIT_) +#if defined(TARGET_64BIT) pRD->SP = (INT_PTR)GetSP(pRD->pCurrentContext); pRD->ControlPC = INT_PTR(GetIP(pRD->pCurrentContext)); -#elif defined(_TARGET_ARM_) +#elif defined(TARGET_ARM) pRD->SP = (DWORD)GetSP(pRD->pCurrentContext); pRD->ControlPC = (DWORD)GetIP(pRD->pCurrentContext); -#elif defined(_TARGET_X86_) +#elif defined(TARGET_X86) pRD->SP = (DWORD)GetSP(pRD->pCurrentContext); pRD->ControlPC = (DWORD)GetIP(pRD->pCurrentContext); -#else // _TARGET_X86_ +#else // TARGET_X86 PORTABILITY_ASSERT("SyncRegDisplayToCurrentContext"); #endif @@ -323,39 +330,39 @@ inline void SyncRegDisplayToCurrentContext(REGDISPLAY* pRD) CheckRegDisplaySP(pRD); #endif // DEBUG_REGDISPLAY } -#endif // _TARGET_64BIT_ || _TARGET_ARM_ || (_TARGET_X86_ && WIN64EXCEPTIONS) +#endif // TARGET_64BIT || TARGET_ARM || (TARGET_X86 && FEATURE_EH_FUNCLETS) typedef REGDISPLAY *PREGDISPLAY; -#ifdef WIN64EXCEPTIONS +#ifdef FEATURE_EH_FUNCLETS inline void FillContextPointers(PT_KNONVOLATILE_CONTEXT_POINTERS pCtxPtrs, PT_CONTEXT pCtx) { -#ifdef _TARGET_AMD64_ +#ifdef TARGET_AMD64 for (int i = 0; i < 16; i++) { *(&pCtxPtrs->Rax + i) = (&pCtx->Rax + i); } -#elif defined(_TARGET_ARM64_) // _TARGET_AMD64_ +#elif defined(TARGET_ARM64) // TARGET_AMD64 for (int i = 0; i < 12; i++) { *(&pCtxPtrs->X19 + i) = (&pCtx->X19 + i); } -#elif defined(_TARGET_ARM_) // _TARGET_ARM64_ +#elif defined(TARGET_ARM) // TARGET_ARM64 // Copy over the nonvolatile integer registers (R4-R11) for (int i = 0; i < 8; i++) { *(&pCtxPtrs->R4 + i) = (&pCtx->R4 + i); } -#elif defined(_TARGET_X86_) // _TARGET_ARM_ +#elif defined(TARGET_X86) // TARGET_ARM for (int i = 0; i < 7; i++) { *(&pCtxPtrs->Edi + i) = (&pCtx->Edi + i); } -#else // _TARGET_X86_ +#else // TARGET_X86 PORTABILITY_ASSERT("FillContextPointers"); #endif // _TARGET_???_ (ELSE) } -#endif // WIN64EXCEPTIONS +#endif // FEATURE_EH_FUNCLETS inline void FillRegDisplay(const PREGDISPLAY pRD, PT_CONTEXT pctx, PT_CONTEXT pCallerCtx = NULL) { @@ -363,8 +370,8 @@ inline void FillRegDisplay(const PREGDISPLAY pRD, PT_CONTEXT pctx, PT_CONTEXT pC SUPPORTS_DAC; -#ifndef WIN64EXCEPTIONS -#ifdef _TARGET_X86_ +#ifndef FEATURE_EH_FUNCLETS +#ifdef TARGET_X86 pRD->pContext = pctx; pRD->pContextForUnwind = NULL; pRD->pEdi = &(pctx->Edi); @@ -377,11 +384,11 @@ inline void FillRegDisplay(const PREGDISPLAY pRD, PT_CONTEXT pctx, PT_CONTEXT pC pRD->SP = pctx->Esp; pRD->ControlPC = (PCODE)(pctx->Eip); pRD->PCTAddr = (UINT_PTR)&(pctx->Eip); -#else // _TARGET_X86_ +#else // TARGET_X86 PORTABILITY_ASSERT("FillRegDisplay"); #endif // _TARGET_???_ (ELSE) -#else // !WIN64EXCEPTIONS +#else // !FEATURE_EH_FUNCLETS pRD->pContext = pctx; // Setup the references @@ -409,7 +416,7 @@ inline void FillRegDisplay(const PREGDISPLAY pRD, PT_CONTEXT pctx, PT_CONTEXT pC FillContextPointers(&pRD->ctxPtrsOne, pctx); -#if defined(_TARGET_ARM_) +#if defined(TARGET_ARM) // Fill volatile context pointers. They can be used by GC in the case of the leaf frame pRD->volatileCurrContextPointers.R0 = &pctx->R0; pRD->volatileCurrContextPointers.R1 = &pctx->R1; @@ -419,11 +426,11 @@ inline void FillRegDisplay(const PREGDISPLAY pRD, PT_CONTEXT pctx, PT_CONTEXT pC pRD->ctxPtrsOne.Lr = &pctx->Lr; pRD->pPC = &pRD->pCurrentContext->Pc; -#elif defined(_TARGET_ARM64_) // _TARGET_ARM_ +#elif defined(TARGET_ARM64) // TARGET_ARM // Fill volatile context pointers. They can be used by GC in the case of the leaf frame for (int i=0; i < 18; i++) pRD->volatileCurrContextPointers.X[i] = &pctx->X[i]; -#endif // _TARGET_ARM64_ +#endif // TARGET_ARM64 #ifdef DEBUG_REGDISPLAY pRD->_pThread = NULL; @@ -431,7 +438,7 @@ inline void FillRegDisplay(const PREGDISPLAY pRD, PT_CONTEXT pctx, PT_CONTEXT pC // This will setup the PC and SP SyncRegDisplayToCurrentContext(pRD); -#endif // !WIN64EXCEPTIONS +#endif // !FEATURE_EH_FUNCLETS } // Initialize a new REGDISPLAY/CONTEXT pair from an existing valid REGDISPLAY. @@ -439,14 +446,14 @@ inline void CopyRegDisplay(const PREGDISPLAY pInRD, PREGDISPLAY pOutRD, T_CONTEX { WRAPPER_NO_CONTRACT; - // The general strategy is to extract the register state from the input REGDISPLAY + // The general strategy is to extract the register state from the input REGDISPLAY // into the new CONTEXT then simply call FillRegDisplay. T_CONTEXT* pOutCallerCtx = NULL; -#ifndef WIN64EXCEPTIONS +#ifndef FEATURE_EH_FUNCLETS -#if defined(_TARGET_X86_) +#if defined(TARGET_X86) if (pInRD->pEdi != NULL) {pOutCtx->Edi = *pInRD->pEdi;} else {pInRD->pEdi = NULL;} if (pInRD->pEsi != NULL) {pOutCtx->Esi = *pInRD->pEsi;} else {pInRD->pEsi = NULL;} if (pInRD->pEbx != NULL) {pOutCtx->Ebx = *pInRD->pEbx;} else {pInRD->pEbx = NULL;} @@ -456,11 +463,11 @@ inline void CopyRegDisplay(const PREGDISPLAY pInRD, PREGDISPLAY pOutRD, T_CONTEX if (pInRD->pEdx != NULL) {pOutCtx->Edx = *pInRD->pEdx;} else {pInRD->pEdx = NULL;} pOutCtx->Esp = pInRD->SP; pOutCtx->Eip = pInRD->ControlPC; -#else // _TARGET_X86_ +#else // TARGET_X86 PORTABILITY_ASSERT("CopyRegDisplay"); #endif // _TARGET_???_ -#else // WIN64EXCEPTIONS +#else // FEATURE_EH_FUNCLETS *pOutCtx = *(pInRD->pCurrentContext); if (pInRD->IsCallerContextValid) @@ -468,17 +475,17 @@ inline void CopyRegDisplay(const PREGDISPLAY pInRD, PREGDISPLAY pOutRD, T_CONTEX pOutCallerCtx = pInRD->pCallerContext; } -#endif // WIN64EXCEPTIONS +#endif // FEATURE_EH_FUNCLETS if (pOutRD) FillRegDisplay(pOutRD, pOutCtx, pOutCallerCtx); } -// Get address of a register in a CONTEXT given the reg number. For X86, +// Get address of a register in a CONTEXT given the reg number. For X86, // the reg number is the R/M number from ModR/M byte or base in SIB byte inline size_t * getRegAddr (unsigned regNum, PTR_CONTEXT regs) { -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 _ASSERTE(regNum < 8); static const SIZE_T OFFSET_OF_REGISTERS[] = @@ -494,13 +501,13 @@ inline size_t * getRegAddr (unsigned regNum, PTR_CONTEXT regs) }; return (PTR_size_t)(PTR_BYTE(regs) + OFFSET_OF_REGISTERS[regNum]); -#elif defined(_TARGET_AMD64_) +#elif defined(TARGET_AMD64) _ASSERTE(regNum < 16); return ®s->Rax + regNum; -#elif defined(_TARGET_ARM_) +#elif defined(TARGET_ARM) _ASSERTE(regNum < 16); return (size_t *)®s->R0 + regNum; -#elif defined(_TARGET_ARM64_) +#elif defined(TARGET_ARM64) _ASSERTE(regNum < 31); return (size_t *)®s->X0 + regNum; #else @@ -521,9 +528,9 @@ inline void UpdateContextFromRegDisp(PREGDISPLAY pRegDisp, PT_CONTEXT pContext) { _ASSERTE((pRegDisp != NULL) && (pContext != NULL)); -#ifndef WIN64EXCEPTIONS +#ifndef FEATURE_EH_FUNCLETS -#if defined(_TARGET_X86_) +#if defined(TARGET_X86) pContext->ContextFlags = (CONTEXT_INTEGER | CONTEXT_CONTROL); pContext->Edi = *pRegDisp->pEdi; pContext->Esi = *pRegDisp->pEsi; @@ -534,15 +541,15 @@ inline void UpdateContextFromRegDisp(PREGDISPLAY pRegDisp, PT_CONTEXT pContext) pContext->Edx = *pRegDisp->pEdx; pContext->Esp = pRegDisp->SP; pContext->Eip = pRegDisp->ControlPC; -#else // _TARGET_X86_ +#else // TARGET_X86 PORTABILITY_ASSERT("UpdateContextFromRegDisp"); #endif // _TARGET_???_ -#else // WIN64EXCEPTIONS +#else // FEATURE_EH_FUNCLETS *pContext = *pRegDisp->pCurrentContext; -#endif // WIN64EXCEPTIONS +#endif // FEATURE_EH_FUNCLETS } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/regex_base.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/regex_base.h index 28097b2..1aaa163 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/regex_base.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/regex_base.h @@ -45,7 +45,7 @@ namespace imp { //=================================================================================================== // Helper for clr::regex::RegExBase. See class definition for clr::regex::RegExBase below for more // information. - + template class RegExBaseHelper : protected ITEM_TRAITS { @@ -66,7 +66,7 @@ namespace imp { // Returns true if the regular expression was successfully matched against the input string; // otherwise false. - RegExBaseHelper(const RegexIterator& regex, + RegExBaseHelper(const RegexIterator& regex, const RegexIterator& regexEnd, const InputIterator& input, const InputIterator& inputEnd, @@ -97,7 +97,7 @@ namespace imp { // The function returns true if a match is found consisting of zero or more items c followed by a // successful match of regex on the remaining input; otherwise false is returned. This is a // conservative match, so it starts with trying to match zero items followed by regex, - // and will then try to match one item followed by regex. + // and will then try to match one item followed by regex. bool DoMatchStar( const Item& c, const RegexIterator& regex, @@ -141,7 +141,7 @@ namespace imp { template RegExBaseHelper::RegExBaseHelper( - const RegexIterator& regex, + const RegexIterator& regex, const RegexIterator& regexEnd, const InputIterator& input, const InputIterator& inputEnd, @@ -458,7 +458,7 @@ public: Iterator End() { WRAPPER_NO_CONTRACT; return m_array.End(); } - // + // COUNT_T Count() const { WRAPPER_NO_CONTRACT; return m_array.GetCount(); } @@ -513,7 +513,7 @@ GroupContainer::CloseGroup( // Reopen a group at the given index, using 'end' to overwrite the current end. template -void +void GroupContainer::ReopenGroup( COUNT_T i, const INPUT_ITERATOR& end) @@ -586,7 +586,7 @@ public: // PLUS // PAREN_OPEN // PAREN_CLOSE -// ItemType may include more values, and may even choose to ignore the above enum types, all of +// ItemType may include more values, and may even choose to ignore the above enum types, all of // which must be recognized by GetItem and MatchItem (see below). // 6. static Item GetItem(const RegexIterator& regex, // const RegexIterator& regexEnd, @@ -635,7 +635,7 @@ public: static const MatchFlags DefaultMatchFlags = ITEM_TRAITS::DefaultMatchFlags; template - static bool Match(RegexIterator regex, + static bool Match(RegexIterator regex, RegexIterator regexEnd, InputIterator input, InputIterator inputEnd, @@ -647,7 +647,7 @@ public: return re.Match(); } - static bool Matches(RegexIterator regex, + static bool Matches(RegexIterator regex, RegexIterator regexEnd, InputIterator input, InputIterator inputEnd, @@ -965,7 +965,7 @@ CHARItemTraits::MatchItem( return c.GetType() == PARENT_TYPE::DOT || MatchCharacter(c.GetValue(), *input, flags); } -} /* namespace regex */ +} /* namespace regex */ } /* namespace clr */ #endif // _DEBUG diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/registrywrapper.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/registrywrapper.h index 0fbeee2..6e0264f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/registrywrapper.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/registrywrapper.h @@ -4,7 +4,7 @@ //***************************************************************************** // File: registrywrapper.h // -// Wrapper around Win32 Registry Functions allowing redirection of .NET +// Wrapper around Win32 Registry Functions allowing redirection of .NET // Framework root registry location // //***************************************************************************** diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/releaseholder.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/releaseholder.h index b2c42e3..672308e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/releaseholder.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/releaseholder.h @@ -18,11 +18,11 @@ public: ReleaseHolder() : m_ptr(NULL) {} - + ReleaseHolder(T* ptr) : m_ptr(ptr) {} - + ~ReleaseHolder() { Release(); @@ -61,7 +61,7 @@ public: m_ptr = NULL; return pT; } - + void Release() { if (m_ptr != NULL) @@ -72,6 +72,6 @@ public: } private: - T* m_ptr; + T* m_ptr; }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/safemath.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/safemath.h index 473e846..7369e24 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/safemath.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/safemath.h @@ -24,9 +24,9 @@ // Otherwise (eg. we're being used from a tool like SOS) there isn't much // we can rely on that is available everywhere. In // several other tools we just take the recourse of disabling asserts, -// we'll do the same here. +// we'll do the same here. // Ideally we'd have a collection of common utilities available evererywhere. -#define _ASSERTE_SAFEMATH(a) +#define _ASSERTE_SAFEMATH(a) #endif #endif @@ -159,12 +159,12 @@ inline bool DoubleFitsInIntType(double val) // http://msdn.microsoft.com/library/en-us/dncode/html/secure01142004.asp // // Modified to track an overflow bit instead of throwing exceptions. In most -// cases the Visual C++ optimizer (Whidbey beta1 - v14.00.40607) is able to +// cases the Visual C++ optimizer (Whidbey beta1 - v14.00.40607) is able to // optimize the bool away completely. // Note that using a sentinal value (IntMax for example) to represent overflow // actually results in poorer code-gen. // -// This has also been simplified significantly to remove functionality we +// This has also been simplified significantly to remove functionality we // don't currently want (division, implicit conversions, many additional operators etc.) // // Example: @@ -177,19 +177,19 @@ inline bool DoubleFitsInIntType(double val) // or: // UINT32 tmp, bufSize; // if( !ClrSafeInt::multiply( elementCount, sizeof(void*), tmp ) || -// !ClrSafeInt::addition( tmp, headerSize, bufSize ) ) +// !ClrSafeInt::addition( tmp, headerSize, bufSize ) ) // { } // else { use bufSize } -// +// //----------------------------------------------------------------------------- // TODO: Any way to prevent unintended instantiations? This is only designed to -// work with unsigned integral types (signed types will work but we probably +// work with unsigned integral types (signed types will work but we probably // don't need signed support). template class ClrSafeInt { public: // Default constructor - 0 value by default - ClrSafeInt() : + ClrSafeInt() : m_value(0), m_overflow(false) COMMA_INDEBUG( m_checkedOverflow( false ) ) @@ -197,7 +197,7 @@ public: } // Value constructor - // This is explicit because otherwise it would be harder to + // This is explicit because otherwise it would be harder to // differentiate between checked and unchecked usage of an operator. // I.e. si + x + y vs. si + ( x + y ) // @@ -207,7 +207,7 @@ public: // be used: // if (val.IsOverflow()) // val = ClrSafeInt(some_value); - explicit ClrSafeInt( T v ) : + explicit ClrSafeInt( T v ) : m_value(v), m_overflow(false) COMMA_INDEBUG( m_checkedOverflow( true ) ) @@ -248,20 +248,20 @@ public: // Note: compiler-generated copy constructor and assignment operator // are correct for our purposes. - - // Note: The MS compiler will sometimes silently perform value-destroying - // conversions when calling the operators below. + + // Note: The MS compiler will sometimes silently perform value-destroying + // conversions when calling the operators below. // Eg. "ClrSafeInt s(0); s += int(-1);" will result in s // having the value 0xffffffff without generating a compile-time warning. // Narrowing conversions are generally level 4 warnings so may or may not // be visible. // - // In the original SafeInt class, all operators have an - // additional overload that takes an arbitrary type U and then safe + // In the original SafeInt class, all operators have an + // additional overload that takes an arbitrary type U and then safe // conversions are performed (resulting in overflow whenever the value // cannot be preserved). - // We could do the same thing, but currently don't because: - // - we don't believe there are common cases where this would result in a + // We could do the same thing, but currently don't because: + // - we don't believe there are common cases where this would result in a // security hole. // - the extra complexity isn't worth the benefits // - it would prevent compiler warnings in the cases we do get warnings for. @@ -277,8 +277,8 @@ public: return m_overflow; } - // Get the value of this integer. - // Must only be called when IsOverflow()==false. If this is called + // Get the value of this integer. + // Must only be called when IsOverflow()==false. If this is called // on overflow we'll assert in Debug and return 0 in release. inline T Value() const { @@ -287,36 +287,36 @@ public: return m_value; } - // force the value into the overflow state. + // force the value into the overflow state. inline void SetOverflow() { INDEBUG( this->m_checkedOverflow = false; ) this->m_overflow = true; // incase someone manages to call Value in release mode - should be optimized out - this->m_value = 0; + this->m_value = 0; } - + // // OPERATORS - // + // // Addition and multiplication. Only permitted when both sides are explicitly - // wrapped inside of a ClrSafeInt and when the types match exactly. + // wrapped inside of a ClrSafeInt and when the types match exactly. // If we permitted a RHS of type 'T', then there would be differences - // in correctness between mathematically equivalent expressions such as + // in correctness between mathematically equivalent expressions such as // "si + x + y" and "si + ( x + y )". Unfortunately, not permitting this // makes expressions involving constants tedius and ugly since the constants - // must be wrapped in ClrSafeInt instances. If we become confident that + // must be wrapped in ClrSafeInt instances. If we become confident that // our tools (PreFast) will catch all integer overflows, then we can probably // safely add this. inline ClrSafeInt operator +(ClrSafeInt rhs) const { ClrSafeInt result; // value is initialized to 0 if( this->m_overflow || - rhs.m_overflow || + rhs.m_overflow || !addition( this->m_value, rhs.m_value, result.m_value ) ) - { + { result.m_overflow = true; } @@ -327,9 +327,9 @@ public: { ClrSafeInt result; // value is initialized to 0 if( this->m_overflow || - rhs.m_overflow || + rhs.m_overflow || !subtraction( this->m_value, rhs.m_value, result.m_value ) ) - { + { result.m_overflow = true; } @@ -340,12 +340,12 @@ public: { ClrSafeInt result; // value is initialized to 0 if( this->m_overflow || - rhs.m_overflow || + rhs.m_overflow || !multiply( this->m_value, rhs.m_value, result.m_value ) ) { result.m_overflow = true; } - + return result; } @@ -355,7 +355,7 @@ public: inline ClrSafeInt& operator +=(ClrSafeInt rhs) { INDEBUG( this->m_checkedOverflow = false; ) - if( this->m_overflow || + if( this->m_overflow || rhs.m_overflow || !ClrSafeInt::addition( this->m_value, rhs.m_value, this->m_value ) ) { @@ -378,7 +378,7 @@ public: inline ClrSafeInt& operator *=(ClrSafeInt rhs) { INDEBUG( this->m_checkedOverflow = false; ) - if( this->m_overflow || + if( this->m_overflow || rhs.m_overflow || !ClrSafeInt::multiply( this->m_value, rhs.m_value, this->m_value ) ) { @@ -401,9 +401,9 @@ public: // // STATIC HELPER METHODS - //these compile down to something as efficient as macros and allow run-time testing + //these compile down to something as efficient as macros and allow run-time testing //of type by the developer - // + // template static bool IsSigned(U) { @@ -455,7 +455,7 @@ public: { _ASSERTE_SAFEMATH( IsPowerOf2( alignment ) ); *this += (alignment - 1); - if( !this->m_overflow ) + if( !this->m_overflow ) { m_value &= ~(alignment - 1); } @@ -465,7 +465,7 @@ public: // Arithmetic implementation functions // - //note - this looks complex, but most of the conditionals + //note - this looks complex, but most of the conditionals //are constant and optimize away //for example, a signed 64-bit check collapses to: /* @@ -524,6 +524,7 @@ public: } #ifdef _MSC_VER +#pragma warning(push) #pragma warning( disable : 4146 ) // unary minus applied to unsigned is still unsigned #endif if(MaxInt()/(-lhs) < (-rhs) ) @@ -532,7 +533,7 @@ public: return false; } #ifdef _MSC_VER -#pragma warning( default : 4146 ) +#pragma warning(pop) #endif } } @@ -540,11 +541,11 @@ public: { //mixed sign - this case is difficult //test case is lhs * rhs < MinInt => overflow - //if lhs < 0 (implies rhs > 0), + //if lhs < 0 (implies rhs > 0), //lhs < MinInt/rhs is the correct test - //else if lhs > 0 + //else if lhs > 0 //rhs < MinInt/lhs is the correct test - //avoid dividing MinInt by a negative number, + //avoid dividing MinInt by a negative number, //because MinInt/-1 is a corner case if(lhs < 0) @@ -591,7 +592,7 @@ public: //upper 33 bits must be the same //most common case is likely that both are positive - test first - if( (tmp & 0xffffffff80000000LL) == 0 || + if( (tmp & 0xffffffff80000000LL) == 0 || (tmp & 0xffffffff80000000LL) == 0xffffffff80000000LL) { //this is OK @@ -601,7 +602,7 @@ public: //overflow return false; - + } else { @@ -683,14 +684,14 @@ public: if(IsSigned()) { //test for +/- combo - if(!IsMixedSign(lhs, rhs)) + if(!IsMixedSign(lhs, rhs)) { //either two negatives, or 2 positives #ifdef __GNUC__ // Workaround for GCC warning: "comparison is always // false due to limited range of data type." if (!(rhs == 0 || rhs > 0)) -#else +#else if(rhs < 0) #endif // __GNUC__ else { @@ -720,7 +721,7 @@ public: if((T)(MaxInt() - lhs) < rhs) { return false; - + } result = lhs + rhs; return true; @@ -765,7 +766,7 @@ public: //or -X < MinInt() + Y //we do not have the same issues because abs(MinInt()) > MaxInt() //tmp should be LTE lhs - + //if(lhs < (T)(MinInt() + rhs)) // old test - leave in for clarity if(tmp > lhs) { @@ -774,7 +775,7 @@ public: //fall through to return value } } - // else + // else //both negative, or both positive //no possible overflow result = tmp; @@ -808,10 +809,10 @@ private: testPow = testPow << 1; // advance to next power of 2 if( testPow <= 0 ) { - return false; // overflow + return false; // overflow } } - + return( testPow == x ); } @@ -825,8 +826,8 @@ private: // True if overflow has been reached. Once this is set, it cannot be cleared. bool m_overflow; - // In debug builds we verify that our caller checked the overflow bit before - // accessing the value. This flag is cleared on initialization, and whenever + // In debug builds we verify that our caller checked the overflow bit before + // accessing the value. This flag is cleared on initialization, and whenever // m_value or m_overflow changes, and set only when IsOverflow // is called. INDEBUG( mutable bool m_checkedOverflow; ) @@ -845,14 +846,14 @@ ClrSafeInt AsClrSafeInt(ClrSafeInt t) return t; } -// Convenience safe-integer types. Currently these are the only types +// Convenience safe-integer types. Currently these are the only types // we are using ClrSafeInt with. We may want to add others. // These type names are based on our standardized names in clrtypes.h typedef ClrSafeInt S_UINT8; typedef ClrSafeInt S_UINT16; //typedef ClrSafeInt S_UINT32; #define S_UINT32 ClrSafeInt -typedef ClrSafeInt S_UINT64; +typedef ClrSafeInt S_UINT64; typedef ClrSafeInt S_SIZE_T; #endif // SAFEMATH_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/safewrap.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/safewrap.h index f489999..84d00e1 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/safewrap.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/safewrap.h @@ -6,7 +6,7 @@ // // -// This file contains wrapper functions for Win32 API's that take SStrings +// This file contains wrapper functions for Win32 API's that take SStrings // and use CLR-safe holders. //***************************************************************************** @@ -18,11 +18,11 @@ consistency's sake. - THROWING: Throw on oom, but return all other failure codes. The rationale here is that SString operations already throw, so to make these APIs - non-throwing would require an extra EX_TRY/EX_CATCH. Most callees will want to throw - on OOM anyways. So making these APIs non-throwing would mean an extra try/catch in + non-throwing would require an extra EX_TRY/EX_CATCH. Most callees will want to throw + on OOM anyways. So making these APIs non-throwing would mean an extra try/catch in the caller + an extra check at the callee. We can eliminate that overhead and just make it throwing. - + Return non-oom failure codes because callees actually freqeuntly expect an API to fail. For example, the callee will have special handling for file-not-found. @@ -32,11 +32,11 @@ consistency's sake. - NAMING: Prefix the name with 'Clr', just like we do for win32 APIs going through hosting. -- DON'T FORGET CONTRACTS: Most of these APIs will likely be Throws/GC_Notrigger. +- DON'T FORGET CONTRACTS: Most of these APIs will likely be Throws/GC_Notrigger. Also use PRECONDITIONs + POSTCONDITIONS when possible. - + - SIGNATURES: Keep the method signture as close the the original win32 API as possible. - - Preserve the return type + value. (except allow it to throw on oom). If the return value + - Preserve the return type + value. (except allow it to throw on oom). If the return value should be a holder, then use that as an out-parameter at the end of the argument list. We don't want to return holders because that will cause the dtors to be called. - For input strings use 'const SString &' instead of 'LPCWSTR'. @@ -49,10 +49,10 @@ consistency's sake. This will also simplify callsites from having to figure out the length of the output string. - USE YOUR BEST JUDGEMENT: The primary goal of these API wrappers is to embrace 'security-safe' practices. - Certainly take any additional steps to that goal. For example, it may make sense to eliminate - corner case inputs for a given API or to break a single confusing API up into several discrete and + Certainly take any additional steps to that goal. For example, it may make sense to eliminate + corner case inputs for a given API or to break a single confusing API up into several discrete and move obvious APIs. - + */ #ifndef _safewrap_h_ #define _safewrap_h_ @@ -63,10 +63,8 @@ class SString; bool ClrGetEnvironmentVariable(LPCSTR szEnvVarName, SString & value); bool ClrGetEnvironmentVariableNoThrow(LPCSTR szEnvVarName, SString & value); void ClrGetModuleFileName(HMODULE hModule, SString & value); -bool ClrGetModuleFileNameNoThrow(HMODULE hModule, SString & value); void ClrGetCurrentDirectory(SString & value); -bool ClrGetCurrentDirectoryNoThrow(SString & value); /* --------------------------------------------------------------------------- * @@ -104,7 +102,7 @@ void ClrRegReadString(HKEY hKey, const SString & szValueName, SString & value); /* --------------------------------------------------------------------------- * * Simple wrapper around RegisterEventSource/ReportEvent/DeregisterEventSource * --------------------------------------------------------------------------- */ -// Returns ERROR_SUCCESS if succeessful in reporting to event log, or +// Returns ERROR_SUCCESS if succeessful in reporting to event log, or // Windows error code to indicate the specific error. DWORD ClrReportEvent( LPCWSTR pEventSource, @@ -130,7 +128,7 @@ DWORD ClrReportEvent( // if the file is >4g and pdwHigh is NULL. Other than that, it acts like // the genuine GetFileSize(). // -// +// //***************************************************************************** DWORD inline SafeGetFileSize(HANDLE hFile, DWORD *pdwHigh) { @@ -159,7 +157,7 @@ DWORD inline SafeGetFileSize(HANDLE hFile, DWORD *pdwHigh) // note that a success return of (hi=0,lo=0xffffffff) will be // treated as an error by the caller. Again, that's part of the // price of being a slacker and not handling the high dword. - // We'll set a lasterror for him to pick up. + // We'll set a lasterror for them to pick up. SetLastError(ERROR_NOT_ENOUGH_MEMORY); } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/sarray.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/sarray.h index ac361cf..1258ad5 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/sarray.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/sarray.h @@ -12,13 +12,13 @@ #include "sbuffer.h" // -------------------------------------------------------------------------------- -// SArray is a typed array wrapper around an SBuffer. It manages individual +// SArray is a typed array wrapper around an SBuffer. It manages individual // constructors and destructors of array elements if avaiable, as well as providing // typed access. // -------------------------------------------------------------------------------- template -class SArray +class SArray { private: @@ -81,7 +81,7 @@ class SArray *Append() = elem; return elem; } - + void Insert(const Iterator &i); void Delete(const Iterator &i); @@ -123,8 +123,8 @@ class SArray public: - class Iterator : public CheckedIteratorBase >, - public Indexer + class EMPTY_BASES_DECL Iterator : public CheckedIteratorBase >, + public Indexer { friend class SArray; friend class Indexer; @@ -132,7 +132,7 @@ class SArray SBuffer::Iterator m_i; public: - + Iterator(SArray *array, SCOUNT_T index) : CheckedIteratorBase >(array) { @@ -180,7 +180,7 @@ class SArray private: //-------------------------------------------------------------------- - // Routines for managing the buffer content. + // Routines for managing the buffer content. //-------------------------------------------------------------------- void ConstructBuffer(const Iterator &i, COUNT_T size); @@ -193,10 +193,10 @@ class SArray // ================================================================================ template -class InlineSArray : public SArray +class EMPTY_BASES_DECL InlineSArray : public SArray { private: -#ifdef _MSC_VER +#ifdef TARGET_WINDOWS #pragma warning(push) #pragma warning(disable:4200) // zero sized array #pragma warning(disable:4324) // don't complain if DECLSPEC_ALIGN actually pads @@ -216,9 +216,9 @@ class InlineSArray : public SArray // ================================================================================ template -class StackSArray : public InlineSArray +class EMPTY_BASES_DECL StackSArray : public InlineSArray { -}; +}; // ================================================================================ // Inline definitions diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/sarray.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/sarray.inl index 102b3c5..65f17ae 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/sarray.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/sarray.inl @@ -16,7 +16,7 @@ inline SArray::SArray() { LIMITED_METHOD_CONTRACT; } - + template inline SArray::SArray(COUNT_T count) : m_buffer(count * sizeof(ELEMENT)) @@ -151,7 +151,7 @@ inline void SArray::SetCount(COUNT_T count) COUNT_T oldCount = GetCount(); if (count > oldCount) ConstructBuffer(Begin() + oldCount, count - oldCount); - + m_buffer.SetSize(count*sizeof(ELEMENT)); if (oldCount > count) @@ -301,7 +301,7 @@ inline void SArray::ConstructBuffer(const Iterator &i, CO GC_NOTRIGGER; } CONTRACTL_END; - + if (!BITWISE_COPY) { ELEMENT *start = GetElements() + (i - Begin()); @@ -351,7 +351,7 @@ inline void SArray::DestructBuffer(const Iterator &i, COU GC_NOTRIGGER; } CONTRACTL_END; - + if (!BITWISE_COPY) { ELEMENT *start = GetElements() + (i - Begin()); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/sbuffer.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/sbuffer.h index e56322a..4ab7d75 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/sbuffer.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/sbuffer.h @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. // -------------------------------------------------------------------------------- // SBuffer.h (Safe Buffer) -// +// // -------------------------------------------------------------------------------- @@ -11,11 +11,11 @@ // SBuffer is a relatively safe way to manipulate a dynamically // allocated data buffer. An SBuffer is conceptually a simple array // of bytes. It maintains both a conceptual size and an actual allocated size. -// -// SBuffer provides safe access to the data buffer by providing rich high -// level functionality (like insertion, deleteion, copying, comparison, and -// iteration) without exposing direct pointers to its buffers. -// +// +// SBuffer provides safe access to the data buffer by providing rich high +// level functionality (like insertion, deleteion, copying, comparison, and +// iteration) without exposing direct pointers to its buffers. +// // For interoperability, SBuffers can expose their buffers - either as readonly // by BYTE * or void * cases, or as writable by the OpenRawBuffer/CloseRawBuffer // entry points. Use of these should be limited wherever possible though; as there @@ -24,7 +24,7 @@ // To mimimize heap allocations, the InlineSBuffer template will preallocate a fixed // size buffer inline with the SBuffer object itself. It will use this buffer unless // it needs a bigger one, in which case it transparently moves on to using the heap. -// The StackSBuffer class instatiates the InlineSBuffer with a standard heuristic +// The StackSBuffer class instatiates the InlineSBuffer with a standard heuristic // stack preallocation size. // // SBuffer is "subclassable" to add content typeing to the buffer. See SArray and @@ -46,7 +46,7 @@ // ================================================================================ #define ALIGNMENT(size) \ - (( (size^(size-1)) >> 1) +1) + (( ((size)^((size)-1)) >> 1) +1) #define ALIGN(size, align) \ (((size)+((align)-1)) & ~((align)-1)) @@ -71,12 +71,12 @@ class SBuffer { Immutable }; - + enum PreallocFlag { Prealloc }; - + //-------------------------------------------------------------------- // Types //-------------------------------------------------------------------- @@ -99,7 +99,7 @@ class SBuffer SBuffer(const BYTE *buffer, COUNT_T size); explicit SBuffer(const SBuffer &buffer); - // Immutable constructor should ONLY be used if buffer will + // Immutable constructor should ONLY be used if buffer will // NEVER BE FREED OR MODIFIED. PERIOD. . SBuffer(ImmutableFlag immutable, const BYTE *buffer, COUNT_T size); @@ -120,7 +120,7 @@ class SBuffer // it also has an internal allocation size which may be larger. //-------------------------------------------------------------------- - // Get and set size of buffer. Note that the actual size of the + // Get and set size of buffer. Note that the actual size of the // internally allocated memory block may be bigger. COUNT_T GetSize() const; void SetSize(COUNT_T count); @@ -139,7 +139,7 @@ class SBuffer // multiple reallocations. Note this does not change the visible // size of the buffer. void Preallocate(COUNT_T allocation) const; - + // Shrink memory usage of buffer to minimal amount. Note that // this does not change the visible size of the buffer. void Trim() const; @@ -153,18 +153,18 @@ class SBuffer void Fill(const Iterator &to, BYTE value, COUNT_T size); // Internal copy. "Copy" leaves from range as is; "Move" - // leaves from range in uninitialized state. - // (This distinction is more important when using from a + // leaves from range in uninitialized state. + // (This distinction is more important when using from a // typed wrapper than in the base SBuffer class.) - // + // // NOTE: Copy vs Move is NOT based on whether ranges overlap // or not. Ranges may overlap in either case. - // + // // Note that both Iterators must be on THIS buffer. void Copy(const Iterator &to, const CIterator &from, COUNT_T size); void Move(const Iterator &to, const CIterator &from, COUNT_T size); - // External copy. + // External copy. void Copy(const Iterator &i, const SBuffer &source); void Copy(const Iterator &i, const void *source, COUNT_T size); void Copy(void *dest, const CIterator &i, COUNT_T size); @@ -213,7 +213,7 @@ class SBuffer // Raw buffer access // // Accessing a raw buffer via pointer is inherently more dangerous than - // other uses of this API, and should be avoided if at all possible. + // other uses of this API, and should be avoided if at all possible. // It is primarily provided for compatibility with existing APIs. // // Note that any buffer pointer returned is not @@ -226,16 +226,16 @@ class SBuffer operator const void *() const; operator const BYTE *() const; - // To write directly to the SString's underlying buffer: - // 1) Call OpenRawBuffer() and pass it the count of bytes + // To write directly to the SString's underlying buffer: + // 1) Call OpenRawBuffer() and pass it the count of bytes // you need. // 2) That returns a pointer to the raw buffer which you can write to. // 3) When you are done writing to the pointer, call CloseBuffer() - // and pass it the count of bytes you actually wrote. - // The pointer from step 1 is now invalid. + // and pass it the count of bytes you actually wrote. + // The pointer from step 1 is now invalid. // example usage: - // void GetInfo(SBuffer &buf) + // void GetInfo(SBuffer &buf) // { // BYTE *p = buf.OpenRawBuffer(3); // OSGetSomeInfo(p, 3); @@ -244,22 +244,22 @@ class SBuffer // You should open the buffer, write the data, and immediately close it. // No sbuffer operations are valid while the buffer is opened. - // + // // In a debug build, Open/Close will do lots of little checks to make sure // you don't buffer overflow while it's opened. In a retail build, this // is a very streamlined action. // Open the raw buffer for writing count bytes BYTE *OpenRawBuffer(COUNT_T maxCount); - + // Call after OpenRawBuffer(). - - // Provide the count of bytes actually used. This will make sure the + + // Provide the count of bytes actually used. This will make sure the // SBuffer's size is correct. void CloseRawBuffer(COUNT_T actualCount); // Close the buffer. Assumes that we completely filled the buffer - // that OpenRawBuffer() gave back. + // that OpenRawBuffer() gave back. void CloseRawBuffer(); //-------------------------------------------------------------------- @@ -349,7 +349,7 @@ class SBuffer CHECK CheckBuffer(const BYTE* buffer, COUNT_T allocation) const; - // Manipulates contents of the buffer via the plugins below, but + // Manipulates contents of the buffer via the plugins below, but // adds some debugging checks. Should always call through here rather // than directly calling the extensibility points. void DebugMoveBuffer(__out_bcount(size) BYTE *to, BYTE *from, COUNT_T size); @@ -358,7 +358,7 @@ class SBuffer void DebugDestructBuffer(BYTE *buffer, COUNT_T size); void DebugStompUnusedBuffer(BYTE *buffer, COUNT_T size); -#ifdef _DEBUG +#ifdef _DEBUG static BOOL EnsureGarbageCharOnly(const BYTE *buffer, COUNT_T size); #endif CHECK CheckUnusedBuffer(const BYTE *buffer, COUNT_T size) const; @@ -374,7 +374,7 @@ public: SUPPORTS_DAC; PTR_VOID p = dac_cast((TADDR) m_buffer); return MemoryRange(p, GetSize()); - } + } protected: @@ -384,10 +384,10 @@ protected: SUPPORTS_DAC; // SBuffers are used in DAC in two ways - buffers in the host, and marshalled buffers from the target. - // This is a problem - we can't reason about the address space of the buffer statically, and instead rely on + // This is a problem - we can't reason about the address space of the buffer statically, and instead rely on // the dynamic usage (i.e. the methods are basically bifurcated into those you can use on host instances, // and those you can use on marshalled copies). - // Ideally we'll have two versions of the SBuffer code - one that's marshalled (normal DACization) and one + // Ideally we'll have two versions of the SBuffer code - one that's marshalled (normal DACization) and one // that isn't (host-only utility). This is the "dual-mode DAC problem". // But this only affects a couple classes, and so for now we'll ignore the problem - causing a bunch of DacCop // violations. @@ -415,7 +415,7 @@ protected: friend class CheckedIteratorBase; - class Index : public CheckedIteratorBase + class EMPTY_BASES_DECL Index : public CheckedIteratorBase { friend class SBuffer; @@ -427,7 +427,7 @@ protected: protected: BYTE* m_ptr; - + Index(); Index(SBuffer *container, SCOUNT_T index); BYTE &GetAt(SCOUNT_T delta) const; @@ -441,7 +441,7 @@ protected: public: - class CIterator : public Index, public Indexer + class EMPTY_BASES_DECL CIterator : public Index, public Indexer { friend class SBuffer; @@ -456,7 +456,7 @@ protected: } }; - class Iterator : public Index, public Indexer + class EMPTY_BASES_DECL Iterator : public Index, public Indexer { friend class SBuffer; @@ -506,12 +506,12 @@ protected: protected: union { BYTE *m_buffer; - wchar_t *m_asStr; // For debugging, view as a unicode string + WCHAR *m_asStr; // For debugging, view as a unicode string }; - + #if _DEBUG protected: - // We will update the "revision" of the buffer every time it is potentially reallocation, + // We will update the "revision" of the buffer every time it is potentially reallocation, // so we can tell when iterators are no longer valid. int m_revision; #endif @@ -524,7 +524,7 @@ protected: #define BUFFER_ALIGNMENT 4 template -class InlineSBuffer : public SBuffer +class EMPTY_BASES_DECL InlineSBuffer : public SBuffer { private: #ifdef _MSC_VER @@ -563,7 +563,7 @@ typedef InlineSBuffer StackSBuffer; // Inline definitions // ================================================================================ -/// a wrapper for templates and such, that use "==". +/// a wrapper for templates and such, that use "==". /// more expensive than a typical "==", though inline BOOL operator == (const SBuffer& b1,const SBuffer& b2) { diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/sbuffer.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/sbuffer.inl index 30c93c8..09c9c53 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/sbuffer.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/sbuffer.inl @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// +// #ifndef _SBUFFER_INL_ #define _SBUFFER_INL_ @@ -24,7 +24,7 @@ inline SBuffer::SBuffer(PreallocFlag flag, void *buffer, COUNT_T size) m_flags(0), m_buffer(NULL) { - CONTRACT_VOID + CONTRACT_VOID { CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(buffer)); @@ -32,7 +32,7 @@ inline SBuffer::SBuffer(PreallocFlag flag, void *buffer, COUNT_T size) NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; - } + } CONTRACT_END; m_buffer = UseBuffer((BYTE *) buffer, &size); @@ -51,14 +51,14 @@ inline SBuffer::SBuffer() m_flags(0), m_buffer(NULL) { - CONTRACT_VOID + CONTRACT_VOID { CONSTRUCTOR_CHECK; NOTHROW; GC_NOTRIGGER; - } + } CONTRACT_END; - + #ifdef _DEBUG m_revision = 0; #endif @@ -72,13 +72,13 @@ inline SBuffer::SBuffer(COUNT_T size) m_flags(0), m_buffer(NULL) { - CONTRACT_VOID + CONTRACT_VOID {; CONSTRUCTOR_CHECK; PRECONDITION(CheckSize(size)); THROWS; GC_NOTRIGGER; - } + } CONTRACT_END; Resize(size); @@ -96,14 +96,14 @@ inline SBuffer::SBuffer(const SBuffer &buffer) m_flags(0), m_buffer(NULL) { - CONTRACT_VOID + CONTRACT_VOID { CONSTRUCTOR_CHECK; PRECONDITION(buffer.Check()); POSTCONDITION(Equals(buffer)); THROWS; GC_NOTRIGGER; - } + } CONTRACT_END; Set(buffer); @@ -121,7 +121,7 @@ inline SBuffer::SBuffer(const BYTE *buffer, COUNT_T size) m_flags(0), m_buffer(NULL) { - CONTRACT_VOID + CONTRACT_VOID { CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(buffer)); @@ -129,7 +129,7 @@ inline SBuffer::SBuffer(const BYTE *buffer, COUNT_T size) POSTCONDITION(Equals(buffer, size)); THROWS; GC_NOTRIGGER; - } + } CONTRACT_END; Set(buffer, size); @@ -148,7 +148,7 @@ inline SBuffer::SBuffer(ImmutableFlag immutable, const BYTE *buffer, COUNT_T siz m_flags(IMMUTABLE), m_buffer(const_cast(buffer)) { - CONTRACT_VOID + CONTRACT_VOID { CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(buffer)); @@ -157,7 +157,7 @@ inline SBuffer::SBuffer(ImmutableFlag immutable, const BYTE *buffer, COUNT_T siz NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; - } + } CONTRACT_END; #ifdef _DEBUG @@ -183,12 +183,16 @@ inline SBuffer::~SBuffer() DeleteBuffer(m_buffer, m_allocation); } +#ifdef _DEBUG + m_revision = 0; +#endif + RETURN; } inline void SBuffer::Set(const SBuffer &buffer) { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(buffer.Check()); @@ -196,14 +200,14 @@ inline void SBuffer::Set(const SBuffer &buffer) THROWS; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; - } + } CONTRACT_END; if (buffer.IsImmutable() && (IsImmutable() || m_allocation < buffer.GetSize())) { // Share immutable block rather than reallocate and copy - // (Note that we prefer to copy to our buffer if we + // (Note that we prefer to copy to our buffer if we // don't have to reallocate it.) if (IsAllocated()) @@ -218,7 +222,7 @@ inline void SBuffer::Set(const SBuffer &buffer) // Increment our revision to invalidate iterators m_revision++; #endif - + } else { @@ -237,7 +241,7 @@ inline void SBuffer::Set(const SBuffer &buffer) inline void SBuffer::Set(const BYTE *buffer, COUNT_T size) { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckPointer(buffer, size == 0 ? NULL_OK : NULL_NOT_OK)); @@ -245,7 +249,7 @@ inline void SBuffer::Set(const BYTE *buffer, COUNT_T size) POSTCONDITION(Equals(buffer, size)); THROWS; GC_NOTRIGGER; - } + } CONTRACT_END; Resize(size); @@ -262,7 +266,7 @@ inline void SBuffer::Set(const BYTE *buffer, COUNT_T size) inline void SBuffer::SetImmutable(const BYTE *buffer, COUNT_T size) { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckPointer(buffer, size == 0 ? NULL_OK : NULL_NOT_OK)); @@ -272,7 +276,7 @@ inline void SBuffer::SetImmutable(const BYTE *buffer, COUNT_T size) GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; - } + } CONTRACT_END; SBuffer temp(Immutable, buffer, size); @@ -296,13 +300,13 @@ inline COUNT_T SBuffer::GetSize() const inline void SBuffer::SetSize(COUNT_T size) { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckSize(size)); THROWS; GC_NOTRIGGER; - } + } CONTRACT_END; Resize(size); @@ -312,12 +316,12 @@ inline void SBuffer::SetSize(COUNT_T size) inline void SBuffer::MaximizeSize() { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; THROWS; GC_NOTRIGGER; - } + } CONTRACT_END; if (!IsImmutable()) @@ -334,7 +338,7 @@ inline COUNT_T SBuffer::GetAllocation() const NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; - } + } CONTRACT_END; RETURN m_allocation; @@ -342,7 +346,7 @@ inline COUNT_T SBuffer::GetAllocation() const inline void SBuffer::Preallocate(COUNT_T allocation) const { - CONTRACT_VOID + CONTRACT_VOID { if (allocation) THROWS; else NOTHROW; INSTANCE_CHECK; @@ -350,7 +354,7 @@ inline void SBuffer::Preallocate(COUNT_T allocation) const THROWS; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; - } + } CONTRACT_END; if (allocation > m_allocation) @@ -361,12 +365,12 @@ inline void SBuffer::Preallocate(COUNT_T allocation) const inline void SBuffer::Trim() const { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; THROWS; GC_NOTRIGGER; - } + } CONTRACT_END; if (!IsImmutable()) @@ -377,12 +381,12 @@ inline void SBuffer::Trim() const inline void SBuffer::Zero() { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; - } + } CONTRACT_END; ZeroMemory(m_buffer, m_size); @@ -392,12 +396,12 @@ inline void SBuffer::Zero() inline void SBuffer::Fill(BYTE value) { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; - } + } CONTRACT_END; memset(m_buffer, value, m_size); @@ -407,13 +411,13 @@ inline void SBuffer::Fill(BYTE value) inline void SBuffer::Fill(const Iterator &i, BYTE value, COUNT_T size) { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i, size)); NOTHROW; GC_NOTRIGGER; - } + } CONTRACT_END; memset(i.m_ptr, value, size); @@ -423,14 +427,14 @@ inline void SBuffer::Fill(const Iterator &i, BYTE value, COUNT_T size) inline void SBuffer::Copy(const Iterator &to, const CIterator &from, COUNT_T size) { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(to, size)); PRECONDITION(CheckIteratorRange(from, size)); NOTHROW; GC_NOTRIGGER; - } + } CONTRACT_END; DebugDestructBuffer(to.m_ptr, size); @@ -439,17 +443,17 @@ inline void SBuffer::Copy(const Iterator &to, const CIterator &from, COUNT_T siz RETURN; } - + inline void SBuffer::Move(const Iterator &to, const CIterator &from, COUNT_T size) { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(to, size)); PRECONDITION(CheckIteratorRange(from, size)); NOTHROW; GC_NOTRIGGER; - } + } CONTRACT_END; DebugDestructBuffer(to.m_ptr, size); @@ -460,17 +464,17 @@ inline void SBuffer::Move(const Iterator &to, const CIterator &from, COUNT_T siz RETURN; } - + inline void SBuffer::Copy(const Iterator &i, const SBuffer &source) { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i, source.GetSize())); PRECONDITION(source.Check()); NOTHROW; GC_NOTRIGGER; - } + } CONTRACT_END; DebugDestructBuffer(i.m_ptr, source.m_size); @@ -482,7 +486,7 @@ inline void SBuffer::Copy(const Iterator &i, const SBuffer &source) inline void SBuffer::Copy(const Iterator &i, const void *source, COUNT_T size) { - CONTRACT_VOID + CONTRACT_VOID { PRECONDITION(CheckPointer(this)); PRECONDITION(CheckSize(size)); @@ -491,7 +495,7 @@ inline void SBuffer::Copy(const Iterator &i, const void *source, COUNT_T size) NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; - } + } CONTRACT_END; DebugDestructBuffer(i.m_ptr, size); @@ -503,15 +507,15 @@ inline void SBuffer::Copy(const Iterator &i, const void *source, COUNT_T size) inline void SBuffer::Copy(void *dest, const CIterator &i, COUNT_T size) { - CONTRACT_VOID + CONTRACT_VOID { PRECONDITION(CheckPointer(this)); PRECONDITION(CheckSize(size)); PRECONDITION(CheckIteratorRange(i, size)); PRECONDITION(CheckPointer(dest, size == 0 ? NULL_OK : NULL_NOT_OK)); - NOTHROW; + NOTHROW; GC_NOTRIGGER; - } + } CONTRACT_END; memcpy(dest, i.m_ptr, size); @@ -521,13 +525,13 @@ inline void SBuffer::Copy(void *dest, const CIterator &i, COUNT_T size) inline void SBuffer::Insert(const Iterator &i, const SBuffer &source) { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; THROWS; PRECONDITION(CheckIteratorRange(i,0)); GC_NOTRIGGER; - } + } CONTRACT_END; Replace(i, 0, source.GetSize()); @@ -538,13 +542,13 @@ inline void SBuffer::Insert(const Iterator &i, const SBuffer &source) inline void SBuffer::Insert(const Iterator &i, COUNT_T size) { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; THROWS; PRECONDITION(CheckIteratorRange(i,0)); GC_NOTRIGGER; - } + } CONTRACT_END; Replace(i, 0, size); @@ -554,12 +558,12 @@ inline void SBuffer::Insert(const Iterator &i, COUNT_T size) inline void SBuffer::Clear() { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; THROWS; GC_NOTRIGGER; - } + } CONTRACT_END; Delete(Begin(), GetSize()); @@ -569,13 +573,13 @@ inline void SBuffer::Clear() inline void SBuffer::Delete(const Iterator &i, COUNT_T size) { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i, size)); THROWS; GC_NOTRIGGER; - } + } CONTRACT_END; Replace(i, size, 0); @@ -585,13 +589,13 @@ inline void SBuffer::Delete(const Iterator &i, COUNT_T size) inline void SBuffer::Replace(const Iterator &i, COUNT_T deleteSize, const SBuffer &insert) { - CONTRACT_VOID + CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i, deleteSize)); THROWS; GC_NOTRIGGER; - } + } CONTRACT_END; Replace(i, deleteSize, insert.GetSize()); @@ -602,14 +606,14 @@ inline void SBuffer::Replace(const Iterator &i, COUNT_T deleteSize, const SBuffe inline int SBuffer::Compare(const SBuffer &compare) const { - CONTRACT(int) + CONTRACT(int) { INSTANCE_CHECK; PRECONDITION(compare.Check()); POSTCONDITION(RETVAL == -1 || RETVAL == 0 || RETVAL == 1); NOTHROW; GC_NOTRIGGER; - } + } CONTRACT_END; RETURN Compare(compare.m_buffer, compare.m_size); @@ -617,7 +621,7 @@ inline int SBuffer::Compare(const SBuffer &compare) const inline int SBuffer::Compare(const BYTE *compare, COUNT_T size) const { - CONTRACT(int) + CONTRACT(int) { INSTANCE_CHECK; PRECONDITION(CheckPointer(compare)); @@ -625,13 +629,13 @@ inline int SBuffer::Compare(const BYTE *compare, COUNT_T size) const POSTCONDITION(RETVAL == -1 || RETVAL == 0 || RETVAL == 1); NOTHROW; GC_NOTRIGGER; - } + } CONTRACT_END; COUNT_T smaller; int equals; int result; - + if (m_size < size) { smaller = m_size; @@ -647,7 +651,7 @@ inline int SBuffer::Compare(const BYTE *compare, COUNT_T size) const smaller = size; equals = 0; } - + result = memcmp(m_buffer, compare, size); if (result == 0) @@ -658,13 +662,13 @@ inline int SBuffer::Compare(const BYTE *compare, COUNT_T size) const inline BOOL SBuffer::Equals(const SBuffer &compare) const { - CONTRACT(int) + CONTRACT(int) { INSTANCE_CHECK; PRECONDITION(compare.Check()); NOTHROW; GC_NOTRIGGER; - } + } CONTRACT_END; RETURN Equals(compare.m_buffer, compare.m_size); @@ -672,14 +676,14 @@ inline BOOL SBuffer::Equals(const SBuffer &compare) const inline BOOL SBuffer::Equals(const BYTE *compare, COUNT_T size) const { - CONTRACT(int) + CONTRACT(int) { INSTANCE_CHECK; PRECONDITION(CheckPointer(compare)); PRECONDITION(CheckSize(size)); NOTHROW; GC_NOTRIGGER; - } + } CONTRACT_END; if (m_size != size) @@ -690,14 +694,14 @@ inline BOOL SBuffer::Equals(const BYTE *compare, COUNT_T size) const inline BOOL SBuffer::Match(const CIterator &i, const SBuffer &match) const { - CONTRACT(int) + CONTRACT(int) { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i)); PRECONDITION(match.Check()); NOTHROW; GC_NOTRIGGER; - } + } CONTRACT_END; RETURN Match(i, match.m_buffer, match.m_size); @@ -705,7 +709,7 @@ inline BOOL SBuffer::Match(const CIterator &i, const SBuffer &match) const inline BOOL SBuffer::Match(const CIterator &i, const BYTE *match, COUNT_T size) const { - CONTRACT(int) + CONTRACT(int) { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i)); @@ -713,11 +717,11 @@ inline BOOL SBuffer::Match(const CIterator &i, const BYTE *match, COUNT_T size) PRECONDITION(CheckSize(size)); NOTHROW; GC_NOTRIGGER; - } + } CONTRACT_END; COUNT_T remaining = (COUNT_T) (m_buffer + m_size - i.m_ptr); - + if (remaining < size) RETURN FALSE; @@ -730,14 +734,14 @@ inline BOOL SBuffer::Match(const CIterator &i, const BYTE *match, COUNT_T size) //---------------------------------------------------------------------------- inline void SBuffer::EnsureMutable() const { - CONTRACT_VOID + CONTRACT_VOID { PRECONDITION(CheckPointer(this)); PRECONDITION(CheckBufferClosed()); THROWS; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; - } + } CONTRACT_END; if (IsImmutable()) @@ -762,7 +766,7 @@ FORCEINLINE void SBuffer::Resize(COUNT_T size, Preserve preserve) if (size > 0) THROWS; else NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; - } + } CONTRACT_END; #ifdef _DEBUG @@ -774,7 +778,7 @@ FORCEINLINE void SBuffer::Resize(COUNT_T size, Preserve preserve) if (delta < 0) DebugDestructBuffer(m_buffer + size, -delta); - + // Only actually allocate if we are growing if (size > m_allocation) ReallocateBuffer(size, preserve); @@ -789,7 +793,7 @@ FORCEINLINE void SBuffer::Resize(COUNT_T size, Preserve preserve) //---------------------------------------------------------------------------- // ResizePadded -// Change the visible size of the buffer; realloc if necessary +// Change the visible size of the buffer; realloc if necessary // add extra space to minimize further growth //---------------------------------------------------------------------------- inline void SBuffer::ResizePadded(COUNT_T size, Preserve preserve) @@ -804,7 +808,7 @@ inline void SBuffer::ResizePadded(COUNT_T size, Preserve preserve) if (size > 0) THROWS; else NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; - } + } CONTRACT_END; #ifdef _DEBUG @@ -816,7 +820,7 @@ inline void SBuffer::ResizePadded(COUNT_T size, Preserve preserve) if (delta < 0) DebugDestructBuffer(m_buffer + size, -delta); - + // Only actually allocate if we are growing if (size > m_allocation) { @@ -850,21 +854,21 @@ inline void SBuffer::TweakSize(COUNT_T size) NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; - } + } CONTRACT_END; #ifdef _DEBUG // Change our revision m_revision++; #endif - + SCOUNT_T delta = size - m_size; if (delta < 0) DebugDestructBuffer(m_buffer + size, -delta); else DebugConstructBuffer(m_buffer + m_size, delta); - + m_size = size; RETURN; @@ -882,10 +886,10 @@ inline void SBuffer::TweakSize(COUNT_T size) #ifdef SBUFFER_CANARY_CHECKS -// The value we place at the start/end of the buffer, +// The value we place at the start/end of the buffer, static const UINT64 SBUFFER_CANARY_VALUE = UI64(0xD00BED00BED00BAA); -// Expose the quantity of padding needed when providing a prealloced +// Expose the quantity of padding needed when providing a prealloced // buffer. This is an unrolled version of the actualAllocation calculated // below for use as a constant value for InlineSString to use. It is // padded with one additional sizeof(SBUFFER_CANARY_VALUE) to account for @@ -913,7 +917,7 @@ static const int SBUFFER_ALIGNMENT = 4; //---------------------------------------------------------------------------- inline BYTE *SBuffer::NewBuffer(COUNT_T allocation) { - CONTRACT(BYTE*) + CONTRACT(BYTE*) { PRECONDITION(CheckSize(allocation)); PRECONDITION(allocation > 0); @@ -921,10 +925,10 @@ inline BYTE *SBuffer::NewBuffer(COUNT_T allocation) THROWS; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; - } + } CONTRACT_END; -#ifdef SBUFFER_CANARY_CHECKS +#ifdef SBUFFER_CANARY_CHECKS COUNT_T alignPadding = AlignmentPad(allocation, sizeof(SBUFFER_CANARY_VALUE)); COUNT_T actualAllocation= sizeof(SBUFFER_CANARY_VALUE) + allocation + alignPadding + sizeof(SBUFFER_CANARY_VALUE); @@ -936,7 +940,7 @@ inline BYTE *SBuffer::NewBuffer(COUNT_T allocation) BYTE *buffer = raw + sizeof(SBUFFER_CANARY_VALUE); #else - + BYTE *buffer = new BYTE [allocation]; #endif @@ -953,7 +957,7 @@ inline BYTE *SBuffer::NewBuffer(COUNT_T allocation) //---------------------------------------------------------------------------- inline BYTE *SBuffer::UseBuffer(BYTE *buffer, COUNT_T *allocation) { - CONTRACT(BYTE*) + CONTRACT(BYTE*) { NOTHROW; GC_NOTRIGGER; @@ -963,7 +967,7 @@ inline BYTE *SBuffer::UseBuffer(BYTE *buffer, COUNT_T *allocation) PRECONDITION(CheckSize(*allocation)); // POSTCONDITION(CheckPointer(RETVAL)); POSTCONDITION(CheckSize(*allocation)); - } + } CONTRACT_END; #ifdef SBUFFER_CANARY_CHECKS @@ -1002,14 +1006,14 @@ inline BYTE *SBuffer::UseBuffer(BYTE *buffer, COUNT_T *allocation) //---------------------------------------------------------------------------- inline void SBuffer::DeleteBuffer(BYTE *buffer, COUNT_T allocation) { - CONTRACT_VOID + CONTRACT_VOID { PRECONDITION(CheckSize(allocation)); POSTCONDITION(CheckPointer(buffer)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; - } + } CONTRACT_END; CONSISTENCY_CHECK(CheckBuffer(buffer, allocation)); @@ -1063,7 +1067,7 @@ inline CHECK SBuffer::CheckBuffer(const BYTE *buffer, COUNT_T allocation) const inline BYTE *SBuffer::OpenRawBuffer(COUNT_T size) { - CONTRACT(BYTE*) + CONTRACT(BYTE*) { #if _DEBUG PRECONDITION_MSG(!IsOpened(), "Can't nest calls to OpenBuffer()"); @@ -1072,7 +1076,7 @@ inline BYTE *SBuffer::OpenRawBuffer(COUNT_T size) POSTCONDITION(GetSize() == size); THROWS; GC_NOTRIGGER; - } + } CONTRACT_END; Resize(size); @@ -1086,19 +1090,19 @@ inline BYTE *SBuffer::OpenRawBuffer(COUNT_T size) } //---------------------------------------------------------------------------- -// Close an open buffer. Assumes that we wrote exactly number of characters +// Close an open buffer. Assumes that we wrote exactly number of characters // we requested in OpenBuffer. //---------------------------------------------------------------------------- inline void SBuffer::CloseRawBuffer() { - CONTRACT_VOID + CONTRACT_VOID { #if _DEBUG PRECONDITION(IsOpened()); #endif THROWS; GC_NOTRIGGER; - } + } CONTRACT_END; CloseRawBuffer(m_size); @@ -1109,12 +1113,12 @@ inline void SBuffer::CloseRawBuffer() //---------------------------------------------------------------------------- // CloseBuffer() tells the SBuffer that we're done using the unsafe buffer. // finalSize is the count of bytes actually used (so we can set m_count). -// This is important if we request a buffer larger than what we actually +// This is important if we request a buffer larger than what we actually // used. //---------------------------------------------------------------------------- inline void SBuffer::CloseRawBuffer(COUNT_T finalSize) { - CONTRACT_VOID + CONTRACT_VOID { #if _DEBUG PRECONDITION_MSG(IsOpened(), "Can only CloseRawBuffer() after a call to OpenRawBuffer()"); @@ -1123,7 +1127,7 @@ inline void SBuffer::CloseRawBuffer(COUNT_T finalSize) PRECONDITION_MSG(finalSize <= GetSize(), "Can't use more characters than requested via OpenRawBuffer()"); THROWS; GC_NOTRIGGER; - } + } CONTRACT_END; #if _DEBUG @@ -1173,7 +1177,7 @@ inline SBuffer::Iterator SBuffer::Begin() THROWS; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; - } + } CONTRACT_END; // This is a bit unfortunate to have to do here, but it's our @@ -1185,12 +1189,12 @@ inline SBuffer::Iterator SBuffer::Begin() inline SBuffer::Iterator SBuffer::End() { - CONTRACT(SBuffer::Iterator) + CONTRACT(SBuffer::Iterator) { INSTANCE_CHECK; THROWS; GC_NOTRIGGER; - } + } CONTRACT_END; // This is a bit unfortunate to have to do here, but it's our @@ -1202,7 +1206,7 @@ inline SBuffer::Iterator SBuffer::End() inline SBuffer::CIterator SBuffer::Begin() const { - CONTRACT(SBuffer::CIterator) + CONTRACT(SBuffer::CIterator) { INSTANCE_CHECK; NOTHROW; @@ -1215,7 +1219,7 @@ inline SBuffer::CIterator SBuffer::Begin() const inline SBuffer::CIterator SBuffer::End() const { - CONTRACT(SBuffer::CIterator) + CONTRACT(SBuffer::CIterator) { INSTANCE_CHECK; NOTHROW; @@ -1345,18 +1349,18 @@ inline int SBuffer::GetRepresentationField() const inline void SBuffer::SetRepresentationField(int value) { - CONTRACT_VOID + CONTRACT_VOID { PRECONDITION((value & ~REPRESENTATION_MASK) == 0); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; - } + } CONTRACT_END; m_flags &= ~REPRESENTATION_MASK; m_flags |= value; - + RETURN; } @@ -1488,7 +1492,7 @@ inline void SBuffer::DebugDestructBuffer(BYTE *buffer, COUNT_T size) static const BYTE GARBAGE_FILL_CHARACTER = '$'; -extern const DWORD g_garbageFillBuffer[]; +extern const DWORD g_garbageFillBuffer[]; inline void SBuffer::DebugStompUnusedBuffer(BYTE *buffer, COUNT_T size) { @@ -1509,7 +1513,7 @@ inline void SBuffer::DebugStompUnusedBuffer(BYTE *buffer, COUNT_T size) if (!IsImmutable() || buffer < m_buffer || buffer > m_buffer + m_allocation) // Allocating a new buffer { - // Whack the memory + // Whack the memory if (size > GARBAGE_FILL_BUFFER_SIZE) size = GARBAGE_FILL_BUFFER_SIZE; memset(buffer, GARBAGE_FILL_CHARACTER, size); } @@ -1640,26 +1644,26 @@ inline SBuffer::Index::Index(SBuffer *container, SCOUNT_T index) } inline BYTE &SBuffer::Index::GetAt(SCOUNT_T delta) const -{ +{ LIMITED_METHOD_DAC_CONTRACT; return m_ptr[delta]; } -inline void SBuffer::Index::Skip(SCOUNT_T delta) -{ +inline void SBuffer::Index::Skip(SCOUNT_T delta) +{ LIMITED_METHOD_CONTRACT; SUPPORTS_DAC_HOST_ONLY; - m_ptr += delta; + m_ptr += delta; } inline SCOUNT_T SBuffer::Index::Subtract(const Index &i) const -{ +{ LIMITED_METHOD_CONTRACT; SUPPORTS_DAC_HOST_ONLY; - return (SCOUNT_T) (m_ptr - i.m_ptr); + return (SCOUNT_T) (m_ptr - i.m_ptr); } inline CHECK SBuffer::Index::DoCheck(SCOUNT_T delta) const diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/securityutil.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/securityutil.h index 2278495..c49acf7 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/securityutil.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/securityutil.h @@ -8,23 +8,23 @@ #include "winnt.h" -// Security utility class. This is currently used by the debugger right-side and dbgshim to figure out the +// Security utility class. This is currently used by the debugger right-side and dbgshim to figure out the // SECURITY_ATTRIBUTES to use on various IPC objects (named events, etc.). // This is pretty debugger specific, and so perhaps doesn't actually belong in utilcode (that's just the most -// convenient way to share it between mscordbi and dbgshim.dll). This is also a pretty big mess. All of +// convenient way to share it between mscordbi and dbgshim.dll). This is also a pretty big mess. All of // this ACL craziness is already gone in Arrowhead, so it's not a high priority to clean this up. class SecurityUtil { public: // - // This will generate ACL containing the current process and + // This will generate ACL containing the current process and // an allowed ACE on the target process of the given pid. // // Host should free returned *ppACL by calling FreeACL // static HRESULT GetACLOfPid(DWORD pid, PACL *ppACL); - + static void FreeACL(PACL pACL); static HRESULT GetMandatoryLabelFromProcess(HANDLE hProcess, LPBYTE * ppbLabel); @@ -33,8 +33,8 @@ public: // instance functions. SecurityUtil is used to minimized memory allocation when converting // pACL to SECURITY_ATTRIBUTES // The needed memory to hold SECURITY_ATTRIBUTES and SECURITY_DESCRIPTOR are embedded - // in the SecurityUtil instance. - // + // in the SecurityUtil instance. + // SecurityUtil(PACL pACL); ~SecurityUtil(); HRESULT Init(); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/securitywrapper.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/securitywrapper.h index 1dad3a6..9688220 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/securitywrapper.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/securitywrapper.h @@ -12,7 +12,7 @@ #ifndef _SECURITY_WRAPPER_H #define _SECURITY_WRAPPER_H -#ifdef FEATURE_PAL +#ifdef TARGET_UNIX #error This file should not be included on non-Windows platforms. #endif @@ -27,13 +27,13 @@ public: Sid(PSID pSid); static bool Equals(const Sid & a, const Sid & b) { return Equals(a.m_pSid, b.m_pSid); } static bool Equals(const Sid & a, PSID b) { return Equals(a.m_pSid, b); } - static bool Equals(PSID a, const Sid & b) { return Equals(a, b.m_pSid); } + static bool Equals(PSID a, const Sid & b) { return Equals(a, b.m_pSid); } static bool Equals(PSID a, PSID b); PSID RawSid() { return m_pSid; } protected: // Pointer to Sid buffer. We don't owner the data. - PSID m_pSid; + PSID m_pSid; }; //----------------------------------------------------------------------------- @@ -70,7 +70,7 @@ class Dacl public: Dacl(PACL pAcl); - SIZE_T GetAceCount(); + SIZE_T GetAceCount(); ACE_HEADER * GetAce(SIZE_T dwAceIndex); protected: PACL m_acl; @@ -78,7 +78,7 @@ protected: //----------------------------------------------------------------------------- // Represent a win32 SECURITY_DESCRIPTOR object. -// (Note there's a "SecurityDescriptor" class in the VM for managed goo, +// (Note there's a "SecurityDescriptor" class in the VM for managed goo, // so we prefix this with "Win32" to avoid a naming collision.) //----------------------------------------------------------------------------- class Win32SecurityDescriptor diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/sha1.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/sha1.h new file mode 100644 index 0000000..6b32d1e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/sha1.h @@ -0,0 +1,50 @@ +// 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. +// + +#ifndef SHA1_H_ +#define SHA1_H_ + +// Hasher class, performs no allocation and therefore does not throw or return +// errors. Usage is as follows: +// Create an instance (this initializes the hash). +// Add one or more blocks of input data using AddData(). +// Retrieve the hash using GetHash(). This can be done as many times as desired +// until the object is destructed. Once a hash is asked for, further AddData +// calls will be ignored. There is no way to reset object state (simply +// destroy the object and create another instead). + +#define SHA1_HASH_SIZE 20 // Number of bytes output by SHA-1 + +typedef struct { + DWORD magic_sha1; // Magic value for A_SHA_CTX + DWORD awaiting_data[16]; + // Data awaiting full 512-bit block. + // Length (nbit_total[0] % 512) bits. + // Unused part of buffer (at end) is zero + DWORD partial_hash[5]; + // Hash through last full block + DWORD nbit_total[2]; + // Total length of message so far + // (bits, mod 2^64) +} SHA1_CTX; + +class SHA1Hash +{ +private: + SHA1_CTX m_Context; + BYTE m_Value[SHA1_HASH_SIZE]; + BOOL m_fFinalized; + + void SHA1Init(SHA1_CTX*); + void SHA1Update(SHA1_CTX*, const BYTE*, const DWORD); + void SHA1Final(SHA1_CTX*, BYTE* digest); + +public: + SHA1Hash(); + void AddData(BYTE *pbData, DWORD cbData); + BYTE *GetHash(); +}; + +#endif // SHA1_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/shash.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/shash.h index 05a8a9d..58d08d4 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/shash.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/shash.h @@ -18,9 +18,9 @@ // Synchronization requirements depend on use. There are several properties to take into account: // // - Lookups may be asynchronous with each other -// - Lookups must be exclusive with Add operations +// - Lookups must be exclusive with Add operations // (@todo: this can be remedied by delaying destruction of old tables during reallocation, e.g. during GC) -// - Remove operations may be asynchronous with Lookup/Add, unless elements are also deallocated. (In which +// - Remove operations may be asynchronous with Lookup/Add, unless elements are also deallocated. (In which // case full synchronization is required) // Common "gotchas": @@ -36,22 +36,22 @@ // The required traits are: // // element_t Type of elements in the hash table. These elements are stored -// by value in the hash table. Elements must look more or less -// like primitives - they must support assignment relatively -// efficiently. There are 2 required sentinel values: -// Null and Deleted (described below). (Note that element_t is -// very commonly a pointer type.) +// by value in the hash table. Elements must look more or less +// like primitives - they must support assignment relatively +// efficiently. There are 2 required sentinel values: +// Null and Deleted (described below). (Note that element_t is +// very commonly a pointer type.) // // The key must be derivable from the element; if your // table's keys are independent of the stored values, element_t // should be a key/value pair. -// -// key_t Type of the lookup key. The key is used for identity -// comparison between elements, and also as a key for lookup. -// This is also used by value and should support +// +// key_t Type of the lookup key. The key is used for identity +// comparison between elements, and also as a key for lookup. +// This is also used by value and should support // efficient assignment. // -// count_t integral type for counts. Typically inherited by default +// count_t integral type for counts. Typically inherited by default // Traits (COUNT_T). // // static key_t GetKey(const element_t &e) Get key from element. Should be stable for a given e. @@ -59,12 +59,12 @@ // static count_t Hash(key_t k) Compute hash from a key. For efficient operation, the hashes // for a set of elements should have random uniform distribution. // -// static const bool s_NoThrow TRUE if GetKey, Equals, and hash are NOTHROW functions. +// static const bool s_NoThrow TRUE if GetKey, Equals, and hash are NOTHROW functions. // Affects the THROWS clauses of several SHash functions. -// (Note that the Null- and Deleted-related functions below +// (Note that the Null- and Deleted-related functions below // are not affected by this and must always be NOTHROW.) // -// static element_t Null() Return the Null sentinal value. May be inherited from +// static element_t Null() Return the Null sentinal value. May be inherited from // default traits if it can be assigned from 0. // static element_t Deleted() Return the Deleted sentinal value. May be inherited from the // default traits if it can be assigned from -1. @@ -77,27 +77,27 @@ // s_DestructPerEntryCleanupAction must be set to true if implemented. // // s_growth_factor_numerator -// s_growth_factor_denominator Factor to grow allocation (numerator/denominator). +// s_growth_factor_denominator Factor to grow allocation (numerator/denominator). // Typically inherited from default traits (3/2) // -// s_density_factor_numerator -// s_density_factor_denominator Maxium occupied density of table before growth +// s_density_factor_numerator +// s_density_factor_denominator Maxium occupied density of table before growth // occurs (num/denom). Typically inherited (3/4). // -// s_minimum_allocation Minimum table allocation count (size on first growth.) It is +// s_minimum_allocation Minimum table allocation count (size on first growth.) It is // probably preferable to call Reallocate on initialization rather // than override his from the default traits. (7) // -// s_supports_remove Set to false for a slightly faster implementation that does not -// support deletes. There is a downside to the s_supports_remove flag, -// in that there may be more copies of the template instantiated through +// s_supports_remove Set to false for a slightly faster implementation that does not +// support deletes. There is a downside to the s_supports_remove flag, +// in that there may be more copies of the template instantiated through // the system as different variants are used. // // s_DestructPerEntryCleanupAction Set to true if OnDestructPerEntryCleanupAction has non-empty implementation. // -// DefaultHashTraits provides defaults for seldomly customized values in traits classes. +// DefaultHashTraits provides defaults for seldomly customized values in traits classes. -template < typename ELEMENT > +template < typename ELEMENT > class DefaultSHashTraits { public: @@ -117,10 +117,10 @@ class DefaultSHashTraits static const bool s_supports_remove = true; - static ELEMENT Null() { return (const ELEMENT) 0; } - static ELEMENT Deleted() { return (const ELEMENT) -1; } - static bool IsNull(const ELEMENT &e) { return e == (const ELEMENT) 0; } - static bool IsDeleted(const ELEMENT &e) { return e == (const ELEMENT) -1; } + static ELEMENT Null() { return (ELEMENT)(TADDR)0; } + static ELEMENT Deleted() { return (ELEMENT)(TADDR)-1; } + static bool IsNull(const ELEMENT &e) { return e == (ELEMENT)(TADDR)0; } + static bool IsDeleted(const ELEMENT &e) { return e == (ELEMENT)(TADDR)-1; } static inline void OnDestructPerEntryCleanupAction(const ELEMENT& e) { /* Do nothing */ } static const bool s_DestructPerEntryCleanupAction = false; @@ -128,7 +128,7 @@ class DefaultSHashTraits static const bool s_NoThrow = true; // No defaults - must specify: - // + // // typedef key_t; // static key_t GetKey(const element_t &i); // static BOOL Equals(key_t k1, key_t k2); @@ -138,13 +138,13 @@ class DefaultSHashTraits // Hash table class definition template -class SHash : public TRAITS - , private noncopyable +class EMPTY_BASES_DECL SHash : public TRAITS + , private noncopyable { friend class VerifyLayoutsMD; // verifies class layout doesn't accidentally change public: - // explicitly declare local typedefs for these traits types, otherwise + // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused typedef typename TRAITS::element_t element_t; typedef typename TRAITS::PTR_element_t PTR_element_t; @@ -168,7 +168,7 @@ class SHash : public TRAITS ~SHash(); // Lookup an element in the table by key. Returns NULL if no element in the table - // has the given key. Note that multiple entries for the same key may be stored - + // has the given key. Note that multiple entries for the same key may be stored - // this will return the first element added. Use KeyIterator to find all elements // with a given key. @@ -183,12 +183,12 @@ class SHash : public TRAITS void Add(const element_t &element); - // Add a new element to the hash table, if no element with the same key is already + // Add a new element to the hash table, if no element with the same key is already // there. Otherwise, it will replace the existing element. This has the effect of - // updating an element rather than adding a duplicate. + // updating an element rather than adding a duplicate. void AddOrReplace(const element_t & element); - // Remove the first element matching the key from the hash table. + // Remove the first element matching the key from the hash table. void Remove(key_t key); @@ -205,7 +205,7 @@ class SHash : public TRAITS void RemoveAll(); - // Begin and End pointers for iteration over entire table. + // Begin and End pointers for iteration over entire table. Iterator Begin() const; Iterator End() const; @@ -217,7 +217,11 @@ class SHash : public TRAITS // Return the number of elements currently stored in the table - count_t GetCount() const; + count_t GetCount() const; + + // Return the number of elements allocated in the table + + count_t GetCapacity() const; // Resizes a hash table for growth. The new size is computed based // on the current population, growth factor, and maximum density factor. @@ -225,7 +229,7 @@ class SHash : public TRAITS void Grow(); // Reallocates a hash table to a specific size. The size must be big enough - // to hold all elements in the table appropriately. + // to hold all elements in the table appropriately. // // Note that the actual table size must always be a prime number; the number // passed in will be upward adjusted if necessary. @@ -248,36 +252,36 @@ class SHash : public TRAITS // See if it is OK to grow the hash table by one element. If not, reallocate // the hash table. BOOL CheckGrowth(); - - // See if it is OK to grow the hash table by one element. If not, allocate new + + // See if it is OK to grow the hash table by one element. If not, allocate new // hash table and return it together with its size *pcNewSize (used by code:AddPhases). // Returns NULL if there already is space for one element. element_t * CheckGrowth_OnlyAllocateNewTable(count_t * pcNewSize); - + // Allocates new resized hash table for growth. Does not update the hash table on the object. // The new size is computed based on the current population, growth factor, and maximum density factor. element_t * Grow_OnlyAllocateNewTable(count_t * pcNewSize); - - // Utility function to allocate new table (does not copy the values into it yet). Returns the size of new table in + + // Utility function to allocate new table (does not copy the values into it yet). Returns the size of new table in // *pcNewTableSize (finds next prime). // Phase 1 of code:Reallocate - it is split to support code:AddPhases. element_t * AllocateNewTable(count_t requestedSize, count_t * pcNewTableSize); - - // Utility function to replace old table with newly allocated table (as allocated by + + // Utility function to replace old table with newly allocated table (as allocated by // code:AllocateNewTable). Copies all 'old' values into the new table first. // Returns the old table. Caller is expected to delete it (via code:DeleteOldTable). // Phase 2 of code:Reallocate - it is split to support code:AddPhases. element_t * ReplaceTable(element_t * newTable, count_t newTableSize); - + // Utility function to delete old table (as returned by code:ReplaceTable). // Phase 3 of code:Reallocate - it is split to support code:AddPhases. void DeleteOldTable(element_t * oldTable); - + // Utility function that does not call code:CheckGrowth. - // Add an element to the hash table. This will never replace an element; multiple + // Add an element to the hash table. This will never replace an element; multiple // elements may be stored with the same key. void Add_GrowthChecked(const element_t & element); - + // Utility function to add a new element to the hash table. Note that // it is perfectly fine for the element to be a duplicate - if so it // is added an additional time. Returns TRUE if a new empty spot was used; @@ -286,10 +290,10 @@ class SHash : public TRAITS // Utility function to add a new element to the hash table, if no element with the same key // is already there. Otherwise, it will replace the existing element. This has the effect of - // updating an element rather than adding a duplicate. + // updating an element rather than adding a duplicate. void AddOrReplace(element_t *table, count_t tableSize, const element_t &element); - - // Utility function to find the first element with the given key in + + // Utility function to find the first element with the given key in // the hash table. static const element_t* Lookup(PTR_element_t table, count_t tableSize, key_t key); @@ -307,13 +311,8 @@ class SHash : public TRAITS public: - class Index -#ifdef _DEBUG - // CheckedIteratorBase is a no-op in RET builds. having it as an empty base-class - // causes differences in the sizeof(SHash::Iterator) in DAC vs. non-DAC builds. - // avoid the issue by not specifying it as a base class in RET builds + class EMPTY_BASES_DECL Index : public CheckedIteratorBase< SHash > -#endif { friend class SHash; friend class Iterator; @@ -358,7 +357,7 @@ class SHash : public TRAITS if (m_index >= m_tableSize) return; - + for (;;) { m_index++; @@ -370,10 +369,10 @@ class SHash : public TRAITS } bool Equal(const Index &i) const - { + { LIMITED_METHOD_CONTRACT; - return i.m_index == m_index; + return i.m_index == m_index; } CHECK DoCheck() const @@ -382,7 +381,7 @@ class SHash : public TRAITS } }; - class Iterator : public Index, public Enumerator + class EMPTY_BASES_DECL Iterator : public Index, public Enumerator { friend class SHash; @@ -393,13 +392,13 @@ class SHash : public TRAITS } }; - // Index for iterating elements with a given key. + // Index for iterating elements with a given key. // // Note that the m_index field // is artificially bumped to m_tableSize when the end of iteration is reached. // This allows a canonical End iterator to be used. - class KeyIndex : public Index + class EMPTY_BASES_DECL KeyIndex : public Index { friend class SHash; friend class KeyIterator; @@ -464,7 +463,7 @@ class SHash : public TRAITS } }; - class KeyIterator : public KeyIndex, public Enumerator + class EMPTY_BASES_DECL KeyIterator : public KeyIndex, public Enumerator { friend class SHash; @@ -486,7 +485,7 @@ class SHash : public TRAITS } }; - // Wrapper and holder for adding an element to the hash table. Useful for Add operations that have to happen + // Wrapper and holder for adding an element to the hash table. Useful for Add operations that have to happen // under a rare lock that does not allow call out into host. // There are 3 phases: // 1. code:PreallocateForAdd ... Can allocate memory (calls into host). @@ -519,35 +518,35 @@ class SHash : public TRAITS public: AddPhases(); ~AddPhases(); - - // Prepares object for one call to code:Add. Pre-allocates new table memory if needed, does not publish + + // Prepares object for one call to code:Add. Pre-allocates new table memory if needed, does not publish // the table yet (it is kept ready only in this holder for call to code:Add). // Calls out into host. void PreallocateForAdd(SHash * pHash); - - // Add an element to the hash table. This will never replace an element; multiple elements may be stored + + // Add an element to the hash table. This will never replace an element; multiple elements may be stored // with the same key. // Will use/publish pre-allocated memory from code:PreallocateForAdd. // Does not call out into host. // Only one Add* method can be called once per object! (Create a new object for each call) void Add(const element_t & element); - + // Element will not be added to the hash table. // Will use/publish pre-allocated memory from code:PreallocateForAdd. // Does not call out into host. // Only one Add* method can be called once per object! (Create a new object for each call) void AddNothing_PublishPreallocatedTable(); - + // Deletes old table if it was replaced by call to code:Add or code:AddNothing_PublishPreallocatedTable. // Calls out into host. void DeleteOldTable(); - + private: SHash * m_pHash; element_t * m_newTable; count_t m_newTableSize; element_t * m_oldTable; - + #ifdef _DEBUG PTR_element_t dbg_m_table; count_t dbg_m_tableSize; @@ -572,13 +571,13 @@ class SHash : public TRAITS LockT & lock, AddLockT & addLock, IUnknown * addRefObject = nullptr); - + private: - + // Test for prime number. static BOOL IsPrime(COUNT_T number); - // Find the next prime number >= the given value. + // Find the next prime number >= the given value. static COUNT_T NextPrime(COUNT_T number); @@ -593,7 +592,7 @@ class SHash : public TRAITS // disables support for DAC marshaling. Useful for defining right-side only SHashes template -class NonDacAwareSHashTraits : public PARENT +class EMPTY_BASES_DECL NonDacAwareSHashTraits : public PARENT { public: typedef typename PARENT::element_t element_t; @@ -603,10 +602,10 @@ public: // disables support for removing elements - produces slightly faster implementation template -class NoRemoveSHashTraits : public PARENT +class EMPTY_BASES_DECL NoRemoveSHashTraits : public PARENT { public: - // explicitly declare local typedefs for these traits types, otherwise + // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused typedef typename PARENT::element_t element_t; typedef typename PARENT::count_t count_t; @@ -619,12 +618,12 @@ public: // PtrHashTraits is a template to provides useful defaults for pointer hash tables // It relies on methods GetKey and Hash defined on ELEMENT -template -class PtrSHashTraits : public DefaultSHashTraits +template +class EMPTY_BASES_DECL PtrSHashTraits : public DefaultSHashTraits { public: - // explicitly declare local typedefs for these traits types, otherwise + // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused typedef DefaultSHashTraits PARENT; typedef typename PARENT::element_t element_t; @@ -632,29 +631,29 @@ class PtrSHashTraits : public DefaultSHashTraits typedef KEY key_t; - static key_t GetKey(const element_t &e) - { + static key_t GetKey(const element_t &e) + { WRAPPER_NO_CONTRACT; - return e->GetKey(); + return e->GetKey(); } - static BOOL Equals(key_t k1, key_t k2) - { + static BOOL Equals(key_t k1, key_t k2) + { LIMITED_METHOD_CONTRACT; - return k1 == k2; + return k1 == k2; } static count_t Hash(key_t k) - { + { WRAPPER_NO_CONTRACT; return ELEMENT::Hash(k); } }; template -class PtrSHash : public SHash< PtrSHashTraits > +class EMPTY_BASES_DECL PtrSHash : public SHash< PtrSHashTraits > { }; -template +template class PtrSHashWithCleanupTraits : public PtrSHashTraits { @@ -669,7 +668,7 @@ public: // a class that automatically deletes data referenced by the pointers (so effectively it takes ownership of the data) // since I was too lazy to implement Remove() APIs properly, removing entries is disallowed template -class PtrSHashWithCleanup : public SHash< NoRemoveSHashTraits< PtrSHashWithCleanupTraits > > +class EMPTY_BASES_DECL PtrSHashWithCleanup : public SHash< NoRemoveSHashTraits< PtrSHashWithCleanupTraits > > { }; @@ -695,7 +694,7 @@ private: { return HashStringA(str); } - + static size_t _hash(WCHAR const *str) { return HashString(str); @@ -740,7 +739,7 @@ private: { return HashiStringA(str); } - + static size_t _hash(WCHAR const *str) { return HashiString(str); @@ -769,37 +768,37 @@ public: }; // StringSHashTraits is a traits class useful for string-keyed -// pointer hash tables. +// pointer hash tables. template > -class StringSHashTraits : public PtrSHashTraits +class EMPTY_BASES_DECL StringSHashTraits : public PtrSHashTraits { public: - // explicitly declare local typedefs for these traits types, otherwise + // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused typedef PtrSHashTraits PARENT; typedef typename PARENT::element_t element_t; typedef typename PARENT::key_t key_t; typedef typename PARENT::count_t count_t; - static BOOL Equals(key_t k1, key_t k2) - { + static BOOL Equals(key_t k1, key_t k2) + { LIMITED_METHOD_CONTRACT; if (k1 == NULL && k2 == NULL) return TRUE; if (k1 == NULL || k2 == NULL) return FALSE; - return ComparerT::compare(k1, k2) == 0; + return ComparerT::compare(k1, k2) == 0; } - static count_t Hash(key_t k) - { + static count_t Hash(key_t k) + { LIMITED_METHOD_CONTRACT; if (k == NULL) return 0; else - return (count_t)ComparerT::hash(k); + return (count_t)ComparerT::hash(k); } }; @@ -816,7 +815,7 @@ struct StringHashElement }; template > -class StringHashWithCleanupTraits : public StringSHashTraits, CharT, ComparerT> +class EMPTY_BASES_DECL StringHashWithCleanupTraits : public StringSHashTraits, CharT, ComparerT> { public: void OnDestructPerEntryCleanupAction(StringHashElement * e) @@ -825,7 +824,7 @@ public: { delete[] e->String; } - + if (e->Object != NULL) { e->Object->Release(); @@ -835,22 +834,22 @@ public: }; template > -class StringSHashWithCleanup : public SHash< StringHashWithCleanupTraits > +class EMPTY_BASES_DECL StringSHashWithCleanup : public SHash< StringHashWithCleanupTraits > { }; template -class StringSHash : public SHash< StringSHashTraits > +class EMPTY_BASES_DECL StringSHash : public SHash< StringSHashTraits > { }; template -class WStringSHash : public SHash< StringSHashTraits > +class EMPTY_BASES_DECL WStringSHash : public SHash< StringSHashTraits > { }; -template -class SStringSHashTraits : public PtrSHashTraits +template +class EMPTY_BASES_DECL SStringSHashTraits : public PtrSHashTraits { public: typedef PtrSHashTraits PARENT; @@ -860,28 +859,28 @@ class SStringSHashTraits : public PtrSHashTraits static const bool s_NoThrow = false; - static BOOL Equals(const key_t &k1, const key_t &k2) - { + static BOOL Equals(const key_t &k1, const key_t &k2) + { WRAPPER_NO_CONTRACT; return k1.Equals(k2); } - static count_t Hash(const key_t &k) - { + static count_t Hash(const key_t &k) + { WRAPPER_NO_CONTRACT; return k.Hash(); } }; template -class SStringSHash : public SHash< SStringSHashTraits > +class EMPTY_BASES_DECL SStringSHash : public SHash< SStringSHashTraits > { }; template -class SetSHashTraits : public DefaultSHashTraits +class EMPTY_BASES_DECL SetSHashTraits : public DefaultSHashTraits { public: - // explicitly declare local typedefs for these traits types, otherwise + // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused typedef typename DefaultSHashTraits::element_t element_t; typedef typename DefaultSHashTraits::count_t count_t; @@ -906,7 +905,7 @@ public: }; template > > -class SetSHash : public SHash< TRAITS > +class EMPTY_BASES_DECL SetSHash : public SHash< TRAITS > { typedef SHash PARENT; @@ -917,27 +916,27 @@ public: } }; -template -class PtrSetSHashTraits : public SetSHashTraits +template +class EMPTY_BASES_DECL PtrSetSHashTraits : public SetSHashTraits { public: - // explicitly declare local typedefs for these traits types, otherwise + // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused typedef SetSHashTraits PARENT; typedef typename PARENT::element_t element_t; typedef typename PARENT::key_t key_t; typedef typename PARENT::count_t count_t; - static count_t Hash(key_t k) - { + static count_t Hash(key_t k) + { WRAPPER_NO_CONTRACT; return (count_t)(size_t)k >> 2; } }; template -class DeleteElementsOnDestructSHashTraits : public PARENT_TRAITS +class EMPTY_BASES_DECL DeleteElementsOnDestructSHashTraits : public PARENT_TRAITS { public: static inline void OnDestructPerEntryCleanupAction(typename PARENT_TRAITS::element_t e) @@ -978,10 +977,10 @@ public: }; template -class MapSHashTraits : public DefaultSHashTraits< KeyValuePair > +class EMPTY_BASES_DECL MapSHashTraits : public DefaultSHashTraits< KeyValuePair > { public: - // explicitly declare local typedefs for these traits types, otherwise + // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused typedef typename DefaultSHashTraits< KeyValuePair >::element_t element_t; typedef typename DefaultSHashTraits< KeyValuePair >::count_t count_t; @@ -1011,7 +1010,7 @@ public: }; template > > -class MapSHash : public SHash< TRAITS > +class EMPTY_BASES_DECL MapSHash : public SHash< TRAITS > { typedef SHash< TRAITS > PARENT; @@ -1049,7 +1048,7 @@ public: }; template -class MapSHashWithRemove : public SHash< MapSHashTraits > +class EMPTY_BASES_DECL MapSHashWithRemove : public SHash< MapSHashTraits > { typedef SHash< MapSHashTraits > PARENT; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/shash.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/shash.inl index c43e91f..d0d6e1a 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/shash.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/shash.inl @@ -44,13 +44,21 @@ SHash::~SHash() } template -typename SHash::count_t SHash::GetCount() const +typename SHash::count_t SHash::GetCount() const { LIMITED_METHOD_CONTRACT; return m_tableCount; } +template +typename SHash::count_t SHash::GetCapacity() const +{ + LIMITED_METHOD_CONTRACT; + + return m_tableMax; +} + template typename SHash::element_t SHash::Lookup(key_t key) const { @@ -94,11 +102,11 @@ void SHash::Add(const element_t & element) POSTCONDITION(TRAITS::Equals(TRAITS::GetKey(element), TRAITS::GetKey(*LookupPtr(TRAITS::GetKey(element))))); } CONTRACT_END; - + CheckGrowth(); - + Add_GrowthChecked(element); - + RETURN; } @@ -113,11 +121,11 @@ void SHash::Add_GrowthChecked(const element_t & element) POSTCONDITION(TRAITS::Equals(TRAITS::GetKey(element), TRAITS::GetKey(*LookupPtr(TRAITS::GetKey(element))))); } CONTRACT_END; - + if (Add(m_table, m_tableSize, element)) m_tableOccupied++; m_tableCount++; - + RETURN; } @@ -298,12 +306,12 @@ BOOL SHash::CheckGrowth() Grow(); RETURN TRUE; } - + RETURN FALSE; } template -typename SHash::element_t * +typename SHash::element_t * SHash::CheckGrowth_OnlyAllocateNewTable(count_t * pcNewSize) { CONTRACT(element_t *) @@ -313,12 +321,12 @@ SHash::CheckGrowth_OnlyAllocateNewTable(count_t * pcNewSize) INSTANCE_CHECK; } CONTRACT_END; - + if (m_tableOccupied == m_tableMax) { RETURN Grow_OnlyAllocateNewTable(pcNewSize); } - + RETURN NULL; } @@ -332,17 +340,17 @@ void SHash::Grow() INSTANCE_CHECK; } CONTRACT_END; - + count_t newSize; element_t * newTable = Grow_OnlyAllocateNewTable(&newSize); element_t * oldTable = ReplaceTable(newTable, newSize); DeleteOldTable(oldTable); - + RETURN; } template -typename SHash::element_t * +typename SHash::element_t * SHash::Grow_OnlyAllocateNewTable(count_t * pcNewSize) { CONTRACT(element_t *) @@ -352,17 +360,17 @@ SHash::Grow_OnlyAllocateNewTable(count_t * pcNewSize) INSTANCE_CHECK; } CONTRACT_END; - - count_t newSize = (count_t) (m_tableCount + + count_t newSize = (count_t) (m_tableCount * TRAITS::s_growth_factor_numerator / TRAITS::s_growth_factor_denominator * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator); if (newSize < TRAITS::s_minimum_allocation) newSize = TRAITS::s_minimum_allocation; - + // handle potential overflow if (newSize < m_tableCount) ThrowOutOfMemory(); - + RETURN AllocateNewTable(newSize, pcNewSize); } @@ -376,12 +384,12 @@ void SHash::Reallocate(count_t requestedSize) INSTANCE_CHECK; } CONTRACT_END; - + count_t newTableSize; element_t * newTable = AllocateNewTable(requestedSize, &newTableSize); element_t * oldTable = ReplaceTable(newTable, newTableSize); DeleteOldTable(oldTable); - + RETURN; } @@ -402,7 +410,7 @@ void SHash::ForEach(Functor &functor) } template -typename SHash::element_t * +typename SHash::element_t * SHash::AllocateNewTable(count_t requestedSize, count_t * pcNewTableSize) { CONTRACT(element_t *) @@ -410,7 +418,7 @@ SHash::AllocateNewTable(count_t requestedSize, count_t * pcNewTableSize) THROWS; GC_NOTRIGGER; INSTANCE_CHECK; - PRECONDITION(requestedSize >= + PRECONDITION(requestedSize >= (count_t) (GetCount() * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator)); } CONTRACT_END; @@ -428,12 +436,12 @@ SHash::AllocateNewTable(count_t requestedSize, count_t * pcNewTableSize) *p = TRAITS::Null(); p++; } - + RETURN newTable; } template -typename SHash::element_t * +typename SHash::element_t * SHash::ReplaceTable(element_t * newTable, count_t newTableSize) { CONTRACT(element_t *) @@ -441,13 +449,13 @@ SHash::ReplaceTable(element_t * newTable, count_t newTableSize) NOTHROW_UNLESS_TRAITS_THROWS; GC_NOTRIGGER; INSTANCE_CHECK; - PRECONDITION(newTableSize >= + PRECONDITION(newTableSize >= (count_t) (GetCount() * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator)); } CONTRACT_END; - + element_t * oldTable = m_table; - + // Move all entries over to new table. for (Iterator i = Begin(), end = End(); i != end; i++) { @@ -455,7 +463,7 @@ SHash::ReplaceTable(element_t * newTable, count_t newTableSize) if (!TRAITS::IsNull(cur) && !TRAITS::IsDeleted(cur)) Add(newTable, newTableSize, cur); } - + m_table = PTR_element_t(newTable); m_tableSize = newTableSize; m_tableMax = (count_t) (newTableSize * TRAITS::s_density_factor_numerator / TRAITS::s_density_factor_denominator); @@ -465,7 +473,7 @@ SHash::ReplaceTable(element_t * newTable, count_t newTableSize) } template -void +void SHash::DeleteOldTable(element_t * oldTable) { CONTRACT_VOID @@ -474,12 +482,12 @@ SHash::DeleteOldTable(element_t * oldTable) GC_NOTRIGGER; } CONTRACT_END; - + // @todo: // We might want to try to delay this cleanup to allow asynchronous readers if (oldTable != NULL) delete [] oldTable; - + RETURN; } @@ -499,13 +507,13 @@ const typename SHash::element_t * SHash::Lookup(PTR_element_t ta RETURN NULL; count_t hash = TRAITS::Hash(key); - count_t index = hash % tableSize; + count_t index = hash % tableSize; count_t increment = 0; // delay computation while (TRUE) { element_t& current = table[index]; - + if (TRAITS::IsNull(current)) RETURN NULL; @@ -516,7 +524,7 @@ const typename SHash::element_t * SHash::Lookup(PTR_element_t ta } if (increment == 0) - increment = (hash % (tableSize-1)) + 1; + increment = (hash % (tableSize-1)) + 1; index += increment; if (index >= tableSize) @@ -538,28 +546,28 @@ BOOL SHash::Add(element_t * table, count_t tableSize, const element_t & key_t key = TRAITS::GetKey(element); count_t hash = TRAITS::Hash(key); - count_t index = hash % tableSize; + count_t index = hash % tableSize; count_t increment = 0; // delay computation while (TRUE) { element_t & current = table[index]; - + if (TRAITS::IsNull(current)) { table[index] = element; RETURN TRUE; } - + if (TRAITS::IsDeleted(current)) { table[index] = element; RETURN FALSE; } - + if (increment == 0) - increment = (hash % (tableSize-1)) + 1; - + increment = (hash % (tableSize-1)) + 1; + index += increment; if (index >= tableSize) index -= tableSize; @@ -581,14 +589,14 @@ void SHash::AddOrReplace(element_t *table, count_t tableSize, const elem key_t key = TRAITS::GetKey(element); count_t hash = TRAITS::Hash(key); - count_t index = hash % tableSize; + count_t index = hash % tableSize; count_t increment = 0; // delay computation while (TRUE) { element_t& current = table[index]; - _ASSERTE(!TRAITS::IsDeleted(current)); - + _ASSERTE(!TRAITS::IsDeleted(current)); + if (TRAITS::IsNull(current)) { table[index] = element; @@ -603,7 +611,7 @@ void SHash::AddOrReplace(element_t *table, count_t tableSize, const elem } if (increment == 0) - increment = (hash % (tableSize-1)) + 1; + increment = (hash % (tableSize-1)) + 1; index += increment; if (index >= tableSize) @@ -624,13 +632,13 @@ void SHash::Remove(element_t *table, count_t tableSize, key_t key) CONTRACT_END; count_t hash = TRAITS::Hash(key); - count_t index = hash % tableSize; + count_t index = hash % tableSize; count_t increment = 0; // delay computation while (TRUE) { element_t& current = table[index]; - + if (TRAITS::IsNull(current)) RETURN; @@ -643,7 +651,7 @@ void SHash::Remove(element_t *table, count_t tableSize, key_t key) } if (increment == 0) - increment = (hash % (tableSize-1)) + 1; + increment = (hash % (tableSize-1)) + 1; index += increment; if (index >= tableSize) @@ -679,7 +687,7 @@ BOOL SHash::IsPrime(COUNT_T number) } CONTRACT_END; - // This is a very low-tech check for primality, which doesn't scale very well. + // This is a very low-tech check for primality, which doesn't scale very well. // There are more efficient tests if this proves to be burdensome for larger // tables. @@ -706,9 +714,9 @@ namespace const COUNT_T g_shash_primes[] = { 11,17,23,29,37,47,59,71,89,107,131,163,197,239,293,353,431,521,631,761,919, 1103,1327,1597,1931,2333,2801,3371,4049,4861,5839,7013,8419,10103,12143,14591, - 17519,21023,25229,30293,36353,43627,52361,62851,75431,90523, 108631, 130363, + 17519,21023,25229,30293,36353,43627,52361,62851,75431,90523, 108631, 130363, 156437, 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, - 968897, 1162687, 1395263, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, + 968897, 1162687, 1395263, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369 }; } @@ -747,12 +755,12 @@ template SHash::AddPhases::AddPhases() { LIMITED_METHOD_CONTRACT; - + m_pHash = NULL; m_newTable = NULL; m_newTableSize = 0; m_oldTable = NULL; - + INDEBUG(dbg_m_fAddCalled = FALSE;) } @@ -760,11 +768,11 @@ template SHash::AddPhases::~AddPhases() { LIMITED_METHOD_CONTRACT; - + if (m_newTable != NULL) { // The new table was not applied to the hash yet _ASSERTE((m_pHash != NULL) && (m_newTableSize != 0) && (m_oldTable == NULL)); - + delete [] m_newTable; } DeleteOldTable(); @@ -779,13 +787,13 @@ void SHash::AddPhases::PreallocateForAdd(SHash * pHash) GC_NOTRIGGER; } CONTRACT_END; - + _ASSERTE((m_pHash == NULL) && (m_newTable == NULL) && (m_newTableSize == 0) && (m_oldTable == NULL)); - + m_pHash = pHash; // May return NULL if the allocation was not needed m_newTable = m_pHash->CheckGrowth_OnlyAllocateNewTable(&m_newTableSize); - + #ifdef _DEBUG dbg_m_table = pHash->m_table; dbg_m_tableSize = pHash->m_tableSize; @@ -793,7 +801,7 @@ void SHash::AddPhases::PreallocateForAdd(SHash * pHash) dbg_m_tableOccupied = pHash->m_tableOccupied; dbg_m_tableMax = pHash->m_tableMax; #endif //_DEBUG - + RETURN; } @@ -806,33 +814,33 @@ void SHash::AddPhases::Add(const element_t & element) GC_NOTRIGGER; } CONTRACT_END; - + _ASSERTE((m_pHash != NULL) && (m_oldTable == NULL)); // Add can be called only once on this object _ASSERTE(!dbg_m_fAddCalled); - + // Check that the hash table didn't change since call to code:PreallocateForAdd _ASSERTE(dbg_m_table == m_pHash->m_table); _ASSERTE(dbg_m_tableSize == m_pHash->m_tableSize); _ASSERTE(dbg_m_tableCount >= m_pHash->m_tableCount); // Remove operation might have removed elements _ASSERTE(dbg_m_tableOccupied == m_pHash->m_tableOccupied); _ASSERTE(dbg_m_tableMax == m_pHash->m_tableMax); - + if (m_newTable != NULL) { // We have pre-allocated table from code:PreallocateForAdd, use it. _ASSERTE(m_newTableSize != 0); - + // May return NULL if there was not table allocated yet m_oldTable = m_pHash->ReplaceTable(m_newTable, m_newTableSize); - + m_newTable = NULL; m_newTableSize = 0; } // We know that we have enough space, direcly add the element m_pHash->Add_GrowthChecked(element); - + INDEBUG(dbg_m_fAddCalled = TRUE;) - + RETURN; } @@ -845,31 +853,31 @@ void SHash::AddPhases::AddNothing_PublishPreallocatedTable() GC_NOTRIGGER; } CONTRACT_END; - + _ASSERTE((m_pHash != NULL) && (m_oldTable == NULL)); // Add can be called only once on this object _ASSERTE(!dbg_m_fAddCalled); - + // Check that the hash table didn't change since call to code:PreallocateForAdd _ASSERTE(dbg_m_table == m_pHash->m_table); _ASSERTE(dbg_m_tableSize == m_pHash->m_tableSize); _ASSERTE(dbg_m_tableCount >= m_pHash->m_tableCount); // Remove operation might have removed elements _ASSERTE(dbg_m_tableOccupied == m_pHash->m_tableOccupied); _ASSERTE(dbg_m_tableMax == m_pHash->m_tableMax); - + if (m_newTable != NULL) { // We have pre-allocated table from code:PreallocateForAdd, use it. _ASSERTE(m_newTableSize != 0); - + // May return NULL if there was not table allocated yet m_oldTable = m_pHash->ReplaceTable(m_newTable, m_newTableSize); - + m_newTable = NULL; m_newTableSize = 0; } - + INDEBUG(dbg_m_fAddCalled = TRUE;) - + RETURN; } @@ -877,11 +885,11 @@ template void SHash::AddPhases::DeleteOldTable() { LIMITED_METHOD_CONTRACT; - + if (m_oldTable != NULL) { _ASSERTE((m_pHash != NULL) && (m_newTable == NULL) && (m_newTableSize == 0)); - + delete [] m_oldTable; m_oldTable = NULL; } @@ -931,7 +939,7 @@ bool SHash::CheckAddInPhases( { clr::SafeAddRef(addRefObject); } - + return true; } } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/locationinfo.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/locationinfo.h index d6a1b6d..de05e3e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/locationinfo.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/locationinfo.h @@ -5,7 +5,7 @@ // locationinfo.h // // Enum describing different types of locations for coreCLR -// +// // Note: must be platform independent // // ====================================================================================== @@ -32,7 +32,7 @@ enum LocationInfo // Input: // locations to compare // -// Output: +// Output: // the preferred location inline LocationInfo BetterLocation(LocationInfo l1, LocationInfo l2) { diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/runtimeselector.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/runtimeselector.h index 168aee9..e4cce87 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/runtimeselector.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/runtimeselector.h @@ -44,7 +44,7 @@ public: // has any useful data bool HasUsefulRuntimeInfo(); - + // is 1st better than 2nd static bool IsBetter(const RuntimeInfo& ri1, const RuntimeInfo& ri2); }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/runtimeselector.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/runtimeselector.inl index 5b73a69..2156306 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/runtimeselector.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/runtimeselector.inl @@ -5,7 +5,7 @@ // runtimeselector.inl // // implementation that select the best runtime -// +// // Note: must be platform independent // // ====================================================================================== @@ -33,9 +33,9 @@ inline void RuntimeSelector::SetRequestedVersion(const VersionInfo& version) // Input: // runtimeInfo - the runtime info // -// Output: +// Output: // return value - true: can be used, false: cannot be used -inline bool RuntimeSelector::IsAcceptable(const RuntimeInfo& runtimeInfo) const +inline bool RuntimeSelector::IsAcceptable(const RuntimeInfo& runtimeInfo) const { return ( m_RequestedVersion.Major() == runtimeInfo.Version().Major() && m_RequestedVersion.Minor() == runtimeInfo.Version().Minor()); @@ -47,7 +47,7 @@ inline bool RuntimeSelector::IsAcceptable(const RuntimeInfo& runtimeInfo) cons // Input: // runtimeInfo - the runtime info // -// Output: +// Output: // return value - S_OK added, S_FALSE not added (not a failure) or a failure code inline HRESULT RuntimeSelector::Add(const RuntimeInfo& runtimeInfo) { @@ -58,7 +58,7 @@ inline HRESULT RuntimeSelector::Add(const RuntimeInfo& runtimeInfo) if(!m_bHasSomething || IsBetter(runtimeInfo,m_Best)) { m_Best=runtimeInfo; - hr=S_OK; + hr=S_OK; } m_bHasSomething=true; @@ -67,7 +67,7 @@ inline HRESULT RuntimeSelector::Add(const RuntimeInfo& runtimeInfo) // Returns add the best runtime of the options given (see Add) // -// Output: +// Output: // return value - the best option inline RuntimeInfo RuntimeSelector::GetBest() { @@ -76,8 +76,8 @@ inline RuntimeInfo RuntimeSelector::GetBest() // Returns whether we have any usable choices // -// Output: -// return value - true if the has something usable +// Output: +// return value - true if the has something usable inline bool RuntimeSelector::HasUsefulRuntimeInfo() { return m_bHasSomething; @@ -85,12 +85,12 @@ inline bool RuntimeSelector::HasUsefulRuntimeInfo() // Compares two given options // -// Input: +// Input: // ri1, ri2 - runtimes to compare // -// Output: +// Output: // return value - true if ri1 is better than ri2 -inline bool RuntimeSelector::IsBetter(const RuntimeInfo& ri1, const RuntimeInfo& ri2) +inline bool RuntimeSelector::IsBetter(const RuntimeInfo& ri1, const RuntimeInfo& ri2) { switch(ri1.Version().Compare(ri2.Version())) { diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/shimselector.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/shimselector.inl index 2fd3b14..565a471 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/shimselector.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/shimselector.inl @@ -5,7 +5,7 @@ // shimselector.inl // // implementation that select the best shim -// +// // Note: must be platform independent // // ====================================================================================== @@ -34,9 +34,9 @@ inline void ShimSelector::SetBaseline(const VersionInfo& version) // Input: // shimInfo - the shim info // -// Output: +// Output: // return value - true: better, false: worse or the same -inline bool ShimSelector::IsAcceptable(const ShimInfo& shimInfo) const +inline bool ShimSelector::IsAcceptable(const ShimInfo& shimInfo) const { return ( m_Baseline.Compare(shimInfo.Version()) < 0 ); } @@ -46,7 +46,7 @@ inline bool ShimSelector::IsAcceptable(const ShimInfo& shimInfo) const // Input: // shimInfo - the shim info // -// Output: +// Output: // return value - S_OK added, S_FALSE not added (not a failure) or a failure code inline HRESULT ShimSelector::Add(const ShimInfo& shimInfo) { @@ -66,7 +66,7 @@ inline HRESULT ShimSelector::Add(const ShimInfo& shimInfo) // Returns add the best shim of the options given (see Add) // -// Output: +// Output: // return value - the best option inline ShimInfo ShimSelector::GetBest() { @@ -75,8 +75,8 @@ inline ShimInfo ShimSelector::GetBest() // Returns whether we have any usable choices // -// Output: -// return value - true if the has something usable +// Output: +// return value - true if the has something usable inline bool ShimSelector::HasUsefulShimInfo() { return m_bHasSomething; @@ -84,12 +84,12 @@ inline bool ShimSelector::HasUsefulShimInfo() // Compares two given options // -// Input: +// Input: // si1, si2 - shims to compare // -// Output: +// Output: // return value - true if si1 is better than si2 -inline bool ShimSelector::IsBetter(const ShimInfo& si1, const ShimInfo& si2) +inline bool ShimSelector::IsBetter(const ShimInfo& si1, const ShimInfo& si2) { switch(si1.Version().Compare(si2.Version())) { diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versionandlocationinfo.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versionandlocationinfo.h index 38be7f2..feb4e31 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versionandlocationinfo.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versionandlocationinfo.h @@ -5,7 +5,7 @@ // versionandlocationinfo.h // // a simple struct encapsulating version# and location code -// +// // Note: must be platform independent // // ====================================================================================== diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versionandlocationinfo.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versionandlocationinfo.inl index 37c0d98..91261bb 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versionandlocationinfo.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versionandlocationinfo.inl @@ -5,30 +5,30 @@ // versionandlocationinfo.inl // // simple accessors for the struct encapsulating version# and location code -// +// // Note: must be platform independent // // ====================================================================================== -inline VersionAndLocationInfo::VersionAndLocationInfo(): +inline VersionAndLocationInfo::VersionAndLocationInfo(): m_Version(0,0,0,0), m_Location(Loc_Undefined) { }; -inline VersionAndLocationInfo::VersionAndLocationInfo(const VersionInfo& version, const LocationInfo location): +inline VersionAndLocationInfo::VersionAndLocationInfo(const VersionInfo& version, const LocationInfo location): m_Version(version), m_Location(location) { }; -inline VersionInfo VersionAndLocationInfo::Version() const +inline VersionInfo VersionAndLocationInfo::Version() const { return m_Version; }; -inline LocationInfo VersionAndLocationInfo::Location() const +inline LocationInfo VersionAndLocationInfo::Location() const { return m_Location; }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versioninfo.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versioninfo.h index f3f3b8a..0a99180 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versioninfo.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versioninfo.h @@ -5,7 +5,7 @@ // versioninfo.h // // representation of version# -// +// // Note: must be platform independent // // ====================================================================================== @@ -33,14 +33,14 @@ public: unsigned short Build() const; unsigned short Revision() const; - // 1 if "this" is bigger, -1 if "this' is smaller + // 1 if "this" is bigger, -1 if "this' is smaller int Compare(const VersionInfo& version) const; // on success returns count of numbers read (<=4), otherwise -1 - static int Parse( LPCTSTR szString, + static int Parse( LPCTSTR szString, VersionInfo* result); }; #include "versioninfo.inl" -#endif +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versioninfo.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versioninfo.inl index f2f6b11..c572227 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versioninfo.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/shim/versioninfo.inl @@ -5,7 +5,7 @@ // versioninfo.inl // // representation of version# -// +// // Note: must be platform independent // // ====================================================================================== @@ -34,27 +34,27 @@ inline VersionInfo::VersionInfo( unsigned short major, } // field accessor -inline unsigned short VersionInfo::Major() const +inline unsigned short VersionInfo::Major() const { - return m_wMajor; + return m_wMajor; }; // field accessor -inline unsigned short VersionInfo::Minor() const +inline unsigned short VersionInfo::Minor() const { - return m_wMinor; + return m_wMinor; }; // field accessor -inline unsigned short VersionInfo::Build() const +inline unsigned short VersionInfo::Build() const { - return m_wBuild; + return m_wBuild; }; // field accessor -inline unsigned short VersionInfo::Revision() const +inline unsigned short VersionInfo::Revision() const { - return m_wRevision; + return m_wRevision; }; // Compares against the given version @@ -62,12 +62,12 @@ inline unsigned short VersionInfo::Revision() const // Input: // version - the version info // -// Output: +// Output: // return value: // -1 given version is newer // 1 given version is older // 0 given version is the same -inline int VersionInfo::Compare(const VersionInfo& version) const +inline int VersionInfo::Compare(const VersionInfo& version) const { if (Major() > version.Major()) return 1; @@ -92,20 +92,20 @@ inline int VersionInfo::Compare(const VersionInfo& version) const // Parses the given string into VersionInfo // // Input: -// szString - the string to parse, "x.x.x.x" +// szString - the string to parse, "x.x.x.x" // -// Output: +// Output: // return value: count of fields parsed (<=4) or -1 if an error inline int VersionInfo::Parse(LPCTSTR szString, VersionInfo* result) { // sscanf is nice but we need an exact format match and no 0s size_t iLen = _tcslen(szString); - + unsigned short wVersion[4] = {0}; int iVerIdx = 0; unsigned int dwCurrentValue = 0; bool bFirstChar = true; - + for (size_t i=0; i<= iLen; i++) { if(szString[i] == _T('\0')) @@ -119,7 +119,7 @@ inline int VersionInfo::Parse(LPCTSTR szString, VersionInfo* result) { if(bFirstChar) return -1; - + // fill in wVersion[iVerIdx++] = (unsigned short)(dwCurrentValue & 0xffff); @@ -131,8 +131,8 @@ inline int VersionInfo::Parse(LPCTSTR szString, VersionInfo* result) else return -1; } - - //reset + + //reset dwCurrentValue=0; bFirstChar=true; continue; @@ -146,9 +146,9 @@ inline int VersionInfo::Parse(LPCTSTR szString, VersionInfo* result) if (szString[i] > _T('9')) { return -1; - } + } else - if (szString[i] == _T('0') && bFirstChar && szString[i+1]!= _T('.') && szString[i+1]!= _T('\0') ) + if (szString[i] == _T('0') && bFirstChar && szString[i+1]!= _T('.') && szString[i+1]!= _T('\0') ) { return -1; } @@ -159,12 +159,12 @@ inline int VersionInfo::Parse(LPCTSTR szString, VersionInfo* result) return -1; bFirstChar=false; - + } //successfully parsed *result = VersionInfo(wVersion[0], wVersion[1], wVersion[2], wVersion[3]); return iVerIdx; - + } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/shimload.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/shimload.h index a2651d1..576274b 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/shimload.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/shimload.h @@ -6,7 +6,7 @@ ** ** Header: ShimLoad.hpp ** -** Purpose: Delay load hook used to images to bind to +** Purpose: Delay load hook used to images to bind to ** dll's shim shipped with the EE ** ** @@ -17,7 +17,7 @@ //***************************************************************************** // Sets/Gets the directory based on the location of the module. This routine -// is called at COR setup time. Set is called during EEStartup and by the +// is called at COR setup time. Set is called during EEStartup and by the // MetaData dispenser. //***************************************************************************** HRESULT SetInternalSystemDirectory(); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/sigbuilder.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/sigbuilder.h index 6d7cbf2..c1ad67a 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/sigbuilder.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/sigbuilder.h @@ -39,9 +39,9 @@ public: } ~SigBuilder(); - + SigBuilder(DWORD cbPreallocationSize); - + PVOID GetSignature(DWORD * pdwLength) { LIMITED_METHOD_CONTRACT; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/sigparser.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/sigparser.h index 2c8cf8b..eb7a635 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/sigparser.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/sigparser.h @@ -22,7 +22,7 @@ // These macros tell us whether the arguments we see as we proceed with the signature walk are mapped // to increasing or decreasing stack addresses. This is valid only for arguments that go on the stack. //--------------------------------------------------------------------------------------- -#if defined(_TARGET_X86_) +#if defined(TARGET_X86) #define STACK_GROWS_DOWN_ON_ARGS_WALK #else #define STACK_GROWS_UP_ON_ARGS_WALK @@ -33,10 +33,10 @@ // Encapsulates how compressed integers and typeref tokens are encoded into // a bytestream. // -// As you use this class please understand the implicit normalizations +// As you use this class please understand the implicit normalizations // on the CorElementType's returned by the various methods, especially // for variable types (e.g. !0 in generic signatures), string types -// (i.e. E_T_STRING), object types (E_T_OBJECT), constructed types +// (i.e. E_T_STRING), object types (E_T_OBJECT), constructed types // (e.g. List) and enums. //------------------------------------------------------------------------ class SigParser @@ -72,7 +72,7 @@ class SigParser SigParser(const SigParser &sig); //------------------------------------------------------------------------ - // Initialize + // Initialize //------------------------------------------------------------------------ FORCEINLINE SigParser(PCCOR_SIGNATURE ptr) { @@ -94,7 +94,7 @@ class SigParser inline void SetSig(PCCOR_SIGNATURE ptr) { LIMITED_METHOD_CONTRACT; - + m_ptr = ptr; // We don't know the size of the signature, so we'll say it's "big enough" m_dwLen = 0xffffffff; @@ -103,7 +103,7 @@ class SigParser inline void SetSig(PCCOR_SIGNATURE ptr, DWORD len) { LIMITED_METHOD_CONTRACT; - + m_ptr = ptr; m_dwLen = len; } @@ -117,9 +117,9 @@ class SigParser } // Returns represented signature as pointer and size. - void + void GetSignature( - PCCOR_SIGNATURE * pSig, + PCCOR_SIGNATURE * pSig, DWORD * pcbSigSize) { *pSig = m_ptr; @@ -132,7 +132,7 @@ class SigParser // apart from custom modifiers which for historical reasons tend to get eaten. // // DO NOT USE THESE METHODS UNLESS YOU'RE TOTALLY SURE YOU WANT - // THE RAW signature. You nearly always want GetElemTypeClosed() or + // THE RAW signature. You nearly always want GetElemTypeClosed() or // PeekElemTypeClosed() or one of the MetaSig functions. See the notes above. // These functions will return E_T_INTERNAL, E_T_VAR, E_T_MVAR and such // so the caller must be able to deal with those @@ -142,7 +142,7 @@ class SigParser // Remove one compressed integer (using CorSigUncompressData) from // the head of the stream and return it. //------------------------------------------------------------------------ - __checkReturn + __checkReturn FORCEINLINE HRESULT GetData(ULONG* data) { WRAPPER_NO_CONTRACT; @@ -153,14 +153,14 @@ class SigParser if (data == NULL) data = &tempData; - + HRESULT hr = CorSigUncompressData(m_ptr, m_dwLen, data, &sizeOfData); if (SUCCEEDED(hr)) { SkipBytes(sizeOfData); } - + return hr; } @@ -168,7 +168,7 @@ class SigParser //------------------------------------------------------------------------- // Remove one byte and return it. //------------------------------------------------------------------------- - __checkReturn + __checkReturn FORCEINLINE HRESULT GetByte(BYTE *data) { LIMITED_METHOD_CONTRACT; @@ -179,7 +179,7 @@ class SigParser *data = *m_ptr; SkipBytes(1); - + return S_OK; } @@ -191,7 +191,7 @@ class SigParser //------------------------------------------------------------------------- // Peek at value of one byte and return it. //------------------------------------------------------------------------- - __checkReturn + __checkReturn FORCEINLINE HRESULT PeekByte(BYTE *data) { LIMITED_METHOD_CONTRACT; @@ -213,7 +213,7 @@ class SigParser // The element type as defined in CorElementType. No normalization for // generics (E_T_VAR, E_T_MVAR,..) or dynamic methods (E_T_INTERNAL occurs) //------------------------------------------------------------------------- - __checkReturn + __checkReturn HRESULT GetElemTypeSlow(CorElementType * etype) { WRAPPER_NO_CONTRACT; @@ -233,21 +233,21 @@ class SigParser BYTE bElemType = 0; hr = sigTemp.GetByte(&bElemType); *etype = (CorElementType)bElemType; - + if (SUCCEEDED(hr)) { *this = sigTemp; return S_OK; } } - + *etype = ELEMENT_TYPE_END; - + return META_E_BAD_SIGNATURE; } // Inlined version - __checkReturn + __checkReturn FORCEINLINE HRESULT GetElemType(CorElementType * etype) { WRAPPER_NO_CONTRACT; @@ -275,8 +275,8 @@ class SigParser } // Note: Calling convention is always one byte, not four bytes - __checkReturn - HRESULT GetCallingConvInfo(ULONG * data) + __checkReturn + HRESULT GetCallingConvInfo(ULONG * data) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; @@ -285,7 +285,7 @@ class SigParser if (data == NULL) data = &tmpData; - + HRESULT hr = CorSigUncompressCallingConv(m_ptr, m_dwLen, data); if (SUCCEEDED(hr)) { @@ -293,11 +293,11 @@ class SigParser } return hr; - } + } - __checkReturn + __checkReturn HRESULT GetCallingConv(ULONG* data) // @REVISIT_TODO: Calling convention is one byte, not four. - { + { WRAPPER_NO_CONTRACT; ULONG info; HRESULT hr = GetCallingConvInfo(&info); @@ -307,13 +307,13 @@ class SigParser *data = IMAGE_CEE_CS_CALLCONV_MASK & info; } - return hr; - } + return hr; + } //------------------------------------------------------------------------ // Non-destructive read of compressed integer. //------------------------------------------------------------------------ - __checkReturn + __checkReturn HRESULT PeekData(ULONG *data) const { WRAPPER_NO_CONTRACT; @@ -332,10 +332,10 @@ class SigParser // rather than the ELEMENT_TYPE_STRING. This is partially to avoid // rewriting client code which depended on this behavior previously. // But it also seems like the right thing to do generally. - // No normalization for generics (E_T_VAR, E_T_MVAR,..) or + // No normalization for generics (E_T_VAR, E_T_MVAR,..) or // dynamic methods (E_T_INTERNAL occurs) //------------------------------------------------------------------------ - __checkReturn + __checkReturn HRESULT PeekElemTypeSlow(CorElementType *etype) const { WRAPPER_NO_CONTRACT; @@ -352,7 +352,7 @@ class SigParser } // inline version - __checkReturn + __checkReturn FORCEINLINE HRESULT PeekElemType(CorElementType *etype) const { WRAPPER_NO_CONTRACT; @@ -386,14 +386,14 @@ class SigParser // Returns the raw size of the type next in the signature, or returns // E_INVALIDARG for base types that have variables sizes. //------------------------------------------------------------------------- - __checkReturn + __checkReturn HRESULT PeekElemTypeSize(ULONG *pSize) { WRAPPER_NO_CONTRACT; HRESULT hr = S_OK; DWORD dwSize = 0; - + if (pSize == NULL) { pSize = &dwSize; @@ -423,7 +423,7 @@ class SigParser case ELEMENT_TYPE_I8: case ELEMENT_TYPE_U8: case ELEMENT_TYPE_R8: - #ifdef _WIN64 + #ifdef HOST_64BIT case ELEMENT_TYPE_I: case ELEMENT_TYPE_U: #endif // WIN64 @@ -434,10 +434,10 @@ class SigParser case ELEMENT_TYPE_I4: case ELEMENT_TYPE_U4: case ELEMENT_TYPE_R4: - #ifndef _WIN64 + #ifndef HOST_64BIT case ELEMENT_TYPE_I: case ELEMENT_TYPE_U: - #endif // _WIN64 + #endif // HOST_64BIT *pSize = 4; break; @@ -490,7 +490,7 @@ class SigParser //------------------------------------------------------------------------ // Is this at the Sentinal (the ... in a varargs signature) that marks - // the begining of varguments that are not decared at the target + // the beginning of varguments that are not decared at the target bool AtSentinel() const { @@ -506,8 +506,8 @@ class SigParser // broken in that case. Make sure you call this function if // you are absolutely sure E_T_INTERNAL was not in the sig //------------------------------------------------------------------------ - __checkReturn - FORCEINLINE + __checkReturn + FORCEINLINE HRESULT GetToken(mdToken * token) { WRAPPER_NO_CONTRACT; @@ -516,7 +516,7 @@ class SigParser if (token == NULL) token = &tempToken; - + HRESULT hr = CorSigUncompressToken(m_ptr, m_dwLen, token, &dwLen); if (SUCCEEDED(hr)) @@ -529,8 +529,8 @@ class SigParser //------------------------------------------------------------------------ // Removes a pointer value and returns it. Used for ELEMENT_TYPE_INTERNAL. - __checkReturn - FORCEINLINE + __checkReturn + FORCEINLINE HRESULT GetPointer(void ** pPtr) { WRAPPER_NO_CONTRACT; @@ -562,7 +562,7 @@ class SigParser return m_ptr == sp.m_ptr; } - __checkReturn + __checkReturn HRESULT SkipCustomModifiers() { WRAPPER_NO_CONTRACT; @@ -585,7 +585,7 @@ class SigParser if (FAILED(hr)) return hr; - while ((ELEMENT_TYPE_CMOD_REQD == bElementType) || + while ((ELEMENT_TYPE_CMOD_REQD == bElementType) || (ELEMENT_TYPE_CMOD_OPT == bElementType)) { sigTemp.SkipBytes(1); @@ -609,7 +609,6 @@ class SigParser switch (bElementType) { case ELEMENT_TYPE_VAR_ZAPSIG: - case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG: case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG: case ELEMENT_TYPE_CANON_ZAPSIG: case ELEMENT_TYPE_MODULE_ZAPSIG: @@ -624,7 +623,7 @@ class SigParser return hr; }// SkipCustomModifiers - __checkReturn + __checkReturn HRESULT SkipFunkyAndCustomModifiers() { WRAPPER_NO_CONTRACT; @@ -645,7 +644,7 @@ class SigParser if (FAILED(hr)) return hr; - while (ELEMENT_TYPE_CMOD_REQD == bElementType || + while (ELEMENT_TYPE_CMOD_REQD == bElementType || ELEMENT_TYPE_CMOD_OPT == bElementType || ELEMENT_TYPE_MODIFIER == bElementType || ELEMENT_TYPE_PINNED == bElementType) @@ -670,7 +669,6 @@ class SigParser { switch (bElementType) { - case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG: case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG: case ELEMENT_TYPE_CANON_ZAPSIG: case ELEMENT_TYPE_MODULE_ZAPSIG: @@ -686,7 +684,7 @@ class SigParser }// SkipFunkyAndCustomModifiers - __checkReturn + __checkReturn HRESULT SkipAnyVASentinel() { WRAPPER_NO_CONTRACT; @@ -709,22 +707,22 @@ class SigParser //------------------------------------------------------------------------ // Assumes that the SigParser points to the start of an element type // (i.e. function parameter, function return type or field type.) - // Advances the pointer to the first data after the element type. + // Advances the pointer to the first data after the element type. //------------------------------------------------------------------------ - __checkReturn + __checkReturn HRESULT SkipExactlyOne(); //------------------------------------------------------------------------ - // Skip only the method header of the signature, not the signature of + // Skip only the method header of the signature, not the signature of // the arguments. //------------------------------------------------------------------------ - __checkReturn + __checkReturn HRESULT SkipMethodHeaderSignature(ULONG *pcArgs); //------------------------------------------------------------------------ // Skip a sub signature (as immediately follows an ELEMENT_TYPE_FNPTR). //------------------------------------------------------------------------ - __checkReturn + __checkReturn HRESULT SkipSignature(); public: @@ -732,15 +730,15 @@ public: //------------------------------------------------------------------------ // Return pointer // PLEASE DON'T USE THIS. - // + // // Return the internal pointer. It's hard to resist, but please try // not to use this. Certainly don't use it if there's any chance of the // signature containing generic type variables. - // - // It's currently only used for working on the + // + // It's currently only used for working on the // signatures stored in TypeSpec tokens (we should add a new abstraction, // i.e. on MetaSig for this) and a couple of places to do with COM - // and native interop signature parsing. + // and native interop signature parsing. // We should try to get rid of these uses as well. //------------------------------------------------------------------------ PCCOR_SIGNATURE GetPtr() const @@ -752,7 +750,7 @@ public: }; // class SigParser //------------------------------------------------------------------------ -FORCEINLINE +FORCEINLINE SigParser::SigParser( const SigParser &sig) : m_ptr(sig.m_ptr), m_dwLen(sig.m_dwLen) @@ -781,7 +779,7 @@ protected: unsigned isGenVar : 1; // 1 more byte here to use for 32-bit }; - + protected: FORCEINLINE static const CorTypeInfoEntry &GetTypeInfo(CorElementType type) { @@ -795,7 +793,7 @@ protected: #endif } CONTRACTL_END; - + if (type >= (CorElementType)_countof(info)) { ThrowHR(COR_E_BADIMAGEFORMAT); @@ -805,143 +803,143 @@ protected: FORCEINLINE static const CorTypeInfoEntry &GetTypeInfo_NoThrow(CorElementType type) { LIMITED_METHOD_DAC_CONTRACT; - + if (type >= (CorElementType)_countof(info)) { return info[ELEMENT_TYPE_END]; } return info[type]; } - + public: - + FORCEINLINE static LPCUTF8 GetName(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo(type).className; } - + FORCEINLINE static LPCUTF8 GetNamespace(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo(type).nameSpace; } - + static void CheckConsistency() { LIMITED_METHOD_CONTRACT; - + for (int i = 0; i < (int)_countof(info); i++) { _ASSERTE(info[i].type == i); } } - + FORCEINLINE static CorInfoGCType GetGCType(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo(type).gcType; } FORCEINLINE static CorInfoGCType GetGCType_NoThrow(CorElementType type) { LIMITED_METHOD_DAC_CONTRACT; - + return GetTypeInfo_NoThrow(type).gcType; } - + static BOOL IsObjRef(CorElementType type) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - + return (GetGCType(type) == TYPE_GC_REF); } static BOOL IsObjRef_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - + return (GetGCType_NoThrow(type) == TYPE_GC_REF); } - + FORCEINLINE static BOOL IsGenericVariable(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo(type).isGenVar; } FORCEINLINE static BOOL IsGenericVariable_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo_NoThrow(type).isGenVar; } - + FORCEINLINE static BOOL IsArray(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo(type).isArray; } FORCEINLINE static BOOL IsArray_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo_NoThrow(type).isArray; } - + FORCEINLINE static BOOL IsFloat(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo(type).isFloat; } FORCEINLINE static BOOL IsFloat_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo_NoThrow(type).isFloat; } - + FORCEINLINE static BOOL IsModifier(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo(type).isModifier; } FORCEINLINE static BOOL IsModifier_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo_NoThrow(type).isModifier; } - + FORCEINLINE static BOOL IsPrimitiveType(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo(type).isPrim; } FORCEINLINE static BOOL IsPrimitiveType_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo_NoThrow(type).isPrim; } - + FORCEINLINE static unsigned Size(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo(type).size; } FORCEINLINE static unsigned Size_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; - + return GetTypeInfo_NoThrow(type).size; } @@ -949,7 +947,7 @@ public: protected: static const CorTypeInfoEntry info[ELEMENT_TYPE_MAX]; - + }; // class CorTypeInfo @@ -968,7 +966,7 @@ inline void* StackElemEndianessFixup(void* pStackElem, UINT cbSize) { case 2: pRetVal += sizeof(void*)-2; break; -#ifdef _WIN64 +#ifdef HOST_64BIT case 4: pRetVal += sizeof(void*)-4; break; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/simplerhash.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/simplerhash.h index eb0f80d..ec43d93 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/simplerhash.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/simplerhash.h @@ -27,18 +27,18 @@ // implementor of a candidate Key class K understands this convention, // these static methods can be implemented by K, so that K can be used // as the actual arguments for the both Key and KeyTrait classes. -// +// // The "Behavior" argument provides the following static members: // // s_growth_factor_numerator -// s_growth_factor_denominator Factor to grow allocation (numerator/denominator). +// s_growth_factor_denominator Factor to grow allocation (numerator/denominator). // Typically inherited from default traits (3/2) // -// s_density_factor_numerator -// s_density_factor_denominator Maxium occupied density of table before growth +// s_density_factor_numerator +// s_density_factor_denominator Maxium occupied density of table before growth // occurs (num/denom). Typically inherited (3/4). // -// s_minimum_allocation Minimum table allocation count (size on first growth.) It is +// s_minimum_allocation Minimum table allocation count (size on first growth.) It is // probably preferable to call Reallocate on initialization rather // than override his from the default traits. (7) // @@ -118,12 +118,12 @@ public: // Remove all mappings in the table. void RemoveAll(); - // Begin and End pointers for iteration over entire table. + // Begin and End pointers for iteration over entire table. KeyIterator Begin() const; KeyIterator End() const; // Return the number of elements currently stored in the table - unsigned GetCount() const; + unsigned GetCount() const; private: // Forward declaration of the linked-list node class. @@ -145,7 +145,7 @@ private: public: // Reallocates a hash table to a specific size. The size must be big enough - // to hold all elements in the table appropriately. + // to hold all elements in the table appropriately. // // Note that the actual table size must always be a prime number; the number // passed in will be upward adjusted if necessary. @@ -250,8 +250,8 @@ public: } bool Equal(const KeyIterator &i) const - { - return i.m_node == m_node; + { + return i.m_node == m_node; } void operator++() { @@ -270,9 +270,9 @@ public: { public: // this is really the getter for the array. - operator Value() + operator Value() { - + Value result; table->Lookup(key, &result); return result; @@ -286,8 +286,8 @@ public: friend class SimplerHashTable; protected: - HashTableRef(SimplerHashTable *t, Key k) - { + HashTableRef(SimplerHashTable *t, Key k) + { table = t; key = k; } @@ -304,7 +304,7 @@ public: } private: - // Find the next prime number >= the given value. + // Find the next prime number >= the given value. static PrimeInfo NextPrime(unsigned number); // Instance members @@ -380,7 +380,7 @@ struct LargePrimitiveKeyFuncs: public KeyFuncsDefEquals // So we cast the address of val to a pointer to an equivalent sized unsigned int // This allows us to read the actual bit representation of a float type // - // We can't read beyond the end of val, so we use sizeof(T) to determine + // We can't read beyond the end of val, so we use sizeof(T) to determine // exactly how many bytes to read // if (sizeof(T) == 8) @@ -401,7 +401,7 @@ struct LargePrimitiveKeyFuncs: public KeyFuncsDefEquals // cast &val to (UINT32 *) then deref to get the bits UINT32 asUINT32 = *(reinterpret_cast(&val)); - // Just return the 32-bit value + // Just return the 32-bit value return static_cast(asUINT32); } else if ((sizeof(T) == 2) || (sizeof(T) == 1)) @@ -412,7 +412,7 @@ struct LargePrimitiveKeyFuncs: public KeyFuncsDefEquals return static_cast(val); } else - { + { // Only support Hashing for types that are 8,4,2 or 1 bytes in size assert(!"Unsupported size"); return static_cast(val); // compile-time error here when we have a illegal size diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/simplerhash.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/simplerhash.inl index dc72acb..e207ba6 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/simplerhash.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/simplerhash.inl @@ -74,7 +74,7 @@ void SimplerHashTable::operator delete[](void * p, } template -unsigned SimplerHashTable::GetCount() const +unsigned SimplerHashTable::GetCount() const { return m_tableCount; } @@ -136,7 +136,7 @@ template unsigned SimplerHashTable::GetIndexForKey(Key k) const { unsigned hash = KeyFuncs::GetHashCode(k); - + unsigned index = magicNumberRem(hash, m_tableSizeInfo); return index; @@ -242,7 +242,7 @@ void SimplerHashTable::CheckGrowth() template void SimplerHashTable::Grow() { - unsigned newSize = (unsigned) (m_tableCount + unsigned newSize = (unsigned) (m_tableCount * Behavior::s_growth_factor_numerator / Behavior::s_growth_factor_denominator * Behavior::s_density_factor_denominator / Behavior::s_density_factor_numerator); if (newSize < Behavior::s_minimum_allocation) @@ -279,11 +279,11 @@ void SimplerHashTable::Reallocate(unsigned newTable while (pN != NULL) { Node* pNext = pN->m_next; - + unsigned newIndex = magicNumberRem(KeyFuncs::GetHashCode(pN->m_key), newPrime); pN->m_next = newTable[newIndex]; newTable[newIndex] = pN; - + pN = pNext; } } @@ -301,10 +301,10 @@ void SimplerHashTable::Reallocate(unsigned newTable // Table of primes and their magic-number-divide constant. // For more info see the book "Hacker's Delight" chapter 10.9 "Unsigned Division by Divisors >= 1" // These were selected by looking for primes, each roughly twice as big as the next, having -// 32-bit magic numbers, (because the algorithm for using 33-bit magic numbers is slightly slower). +// 32-bit magic numbers, (because the algorithm for using 33-bit magic numbers is slightly slower). // -SELECTANY const PrimeInfo primeInfo[] = +SELECTANY const PrimeInfo primeInfo[] = { PrimeInfo(9, 0x38e38e39, 1), PrimeInfo(23, 0xb21642c9, 4), @@ -317,9 +317,9 @@ SELECTANY const PrimeInfo primeInfo[] = PrimeInfo(2473, 0x6a009f01, 10), PrimeInfo(4327, 0xf2555049, 12), PrimeInfo(7499, 0x45ea155f, 11), - PrimeInfo(12973, 0x1434f6d3, 10), - PrimeInfo(22433, 0x2ebe18db, 12), - PrimeInfo(46559, 0xb42bebd5, 15), + PrimeInfo(12973, 0x1434f6d3, 10), + PrimeInfo(22433, 0x2ebe18db, 12), + PrimeInfo(46559, 0xb42bebd5, 15), PrimeInfo(96581, 0xadb61b1b, 16), PrimeInfo(200341, 0x29df2461, 15), PrimeInfo(415517, 0xa181c46d, 18), @@ -327,10 +327,10 @@ SELECTANY const PrimeInfo primeInfo[] = PrimeInfo(1787021, 0x9636c46f, 20), PrimeInfo(3705617, 0x4870adc1, 20), PrimeInfo(7684087, 0x8bbc5b83, 22), - PrimeInfo(15933877, 0x86c65361, 23), - PrimeInfo(33040633, 0x40fec79b, 23), - PrimeInfo(68513161, 0x7d605cd1, 25), - PrimeInfo(142069021, 0xf1da390b, 27), + PrimeInfo(15933877, 0x86c65361, 23), + PrimeInfo(33040633, 0x40fec79b, 23), + PrimeInfo(68513161, 0x7d605cd1, 25), + PrimeInfo(142069021, 0xf1da390b, 27), PrimeInfo(294594427, 0x74a2507d, 27), PrimeInfo(733045421, 0x5dbec447, 28), }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/slist.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/slist.h index f05d763..87dec1d 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/slist.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/slist.h @@ -7,14 +7,14 @@ // // @commn: Bunch of utility classes -// +// // HISTORY: // 02/03/98: created helper classes // SLink, link node for singly linked list, every class that is intrusively // linked should have a data member of this type -// SList, template linked list class, contains only inline +// SList, template linked list class, contains only inline // methods for fast list operations, with proper type checking -// +// // see below for futher info. on how to use these template classes // //----------------------------------------------------------------------------- @@ -28,7 +28,7 @@ #define _H_SLIST_ //------------------------------------------------------------------ -// struct SLink, to use a singly linked list +// struct SLink, to use a singly linked list // have a data member m_Link of type SLink in your class // and instantiate the template SList class //-------------------------------------------------------------------- @@ -39,7 +39,7 @@ typedef DPTR(struct SLink) PTR_SLink; struct SLink { PTR_SLink m_pNext; - SLink() + SLink() { LIMITED_METHOD_CONTRACT; @@ -81,7 +81,7 @@ struct SLink } pHead = pHead->m_pNext; } - + return pFreeLink; } }; @@ -96,7 +96,7 @@ struct SLink // 'SList' // // SList has two different behaviours depending on boolean -// fHead variable, +// fHead variable, // // if fHead is true, then the list allows only InsertHead operations // if fHead is false, then the list allows only InsertTail operations @@ -110,11 +110,11 @@ class SList { public: // typedef used by the Queue class below - typedef T ENTRY_TYPE; + typedef T ENTRY_TYPE; protected: - // used as sentinel + // used as sentinel SLink m_link; // slink.m_pNext == Null PTR_SLink m_pHead; PTR_SLink m_pTail; @@ -125,7 +125,7 @@ protected: LIMITED_METHOD_DAC_CONTRACT; return &(pLink->*LinkPtr); } - + // move to the beginning of the object given the pointer within the object static T* GetObject (SLink* pLink) { @@ -160,13 +160,13 @@ public: void Init() { LIMITED_METHOD_CONTRACT; - m_pHead = &m_link; - // NOTE :: fHead variable is template argument + m_pHead = PTR_SLink(&m_link); + // NOTE :: fHead variable is template argument // the following code is a compiled in, only if the fHead flag // is set to false, if (!fHead) { - m_pTail = &m_link; + m_pTail = PTR_SLink(&m_link); } } @@ -190,12 +190,12 @@ public: m_pTail->m_pNext = pLink; m_pTail = pLink; } - else + else {// you instantiated this class asking only for InsertHead operations _ASSERTE(0); } } - + void InsertHead(T *pObj) { LIMITED_METHOD_CONTRACT; @@ -204,7 +204,7 @@ public: { _ASSERTE(pObj != NULL); SLink *pLink = GetLink(pObj); - + pLink->m_pNext = m_pHead->m_pNext; m_pHead->m_pNext = pLink; } @@ -234,7 +234,7 @@ public: return GetObject(pLink); } - + #endif // !DACCESS_COMPILE T* GetHead() @@ -242,7 +242,7 @@ public: WRAPPER_NO_CONTRACT; return GetObject(m_pHead->m_pNext); } - + T* GetTail() { WRAPPER_NO_CONTRACT; @@ -269,13 +269,13 @@ public: WRAPPER_NO_CONTRACT; _ASSERTE(pObj != NULL); - + SLink *prior; SLink *ret = SLink::FindAndRemove(m_pHead, GetLink(pObj), &prior); - + if (ret == m_pTail) - m_pTail = prior; - + m_pTail = PTR_SLink(prior); + return GetObject(ret); } @@ -301,10 +301,10 @@ public: T & operator*() { _ASSERTE(m_cur != NULL); return *m_cur; } - + T * operator->() const { return m_cur; } - + private: Iterator(SList * pList) : m_cur(pList->GetHead()) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/sospriv.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/sospriv.idl index 5896426..d0b9262 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/sospriv.idl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/sospriv.idl @@ -44,15 +44,15 @@ typedef unsigned int size_t; typedef int ModuleMapType; typedef int VCSHeapType; cpp_quote("#endif") - -cpp_quote("typedef enum ModuleMapType { TYPEDEFTOMETHODTABLE, TYPEREFTOMETHODTABLE };") -cpp_quote("typedef enum VCSHeapType {IndcellHeap, LookupHeap, ResolveHeap, DispatchHeap, CacheEntryHeap};") + +cpp_quote("typedef enum { TYPEDEFTOMETHODTABLE, TYPEREFTOMETHODTABLE } ModuleMapType;") +cpp_quote("typedef enum {IndcellHeap, LookupHeap, ResolveHeap, DispatchHeap, CacheEntryHeap} VCSHeapType;") typedef void (*MODULEMAPTRAVERSE)(UINT index, CLRDATA_ADDRESS methodTable,LPVOID token); typedef void (*VISITHEAP)(CLRDATA_ADDRESS blockData,size_t blockSize,BOOL blockIsCurrentBlock); -typedef BOOL (*VISITRCWFORCLEANUP)(CLRDATA_ADDRESS RCW,CLRDATA_ADDRESS Context,CLRDATA_ADDRESS Thread, +typedef BOOL (*VISITRCWFORCLEANUP)(CLRDATA_ADDRESS RCW,CLRDATA_ADDRESS Context,CLRDATA_ADDRESS Thread, BOOL bIsFreeThreaded, LPVOID token); typedef BOOL (*DUMPEHINFO)(UINT clauseIndex,UINT totalClauses, struct DACEHInfo *pEHInfo,LPVOID token); @@ -66,7 +66,7 @@ typedef struct _SOSHandleData CLRDATA_ADDRESS Secondary; unsigned int Type; BOOL StrongReference; - + // For RefCounted Handles unsigned int RefCount; unsigned int JupiterRefCount; @@ -123,7 +123,7 @@ typedef struct _SOS_StackRefData CLRDATA_ADDRESS Address; CLRDATA_ADDRESS Object; unsigned int Flags; - + SOSStackSourceType SourceType; CLRDATA_ADDRESS Source; CLRDATA_ADDRESS StackPointer; @@ -163,8 +163,8 @@ interface ISOSStackRefEnum : ISOSEnum HRESULT Next([in] unsigned int count, [out, size_is(count), length_is(*pFetched)] SOSStackRefData ref[], [out] unsigned int *pFetched); - - + + /* Reports all frames which we could not enumerate gc references for. */ HRESULT EnumerateErrors([out] ISOSStackRefErrorEnum **ppEnum); @@ -180,31 +180,31 @@ interface ISOSDacInterface : IUnknown { // ThreadStore HRESULT GetThreadStoreData(struct DacpThreadStoreData *data); - + // AppDomains HRESULT GetAppDomainStoreData(struct DacpAppDomainStoreData *data); HRESULT GetAppDomainList(unsigned int count, CLRDATA_ADDRESS values[], unsigned int *pNeeded); HRESULT GetAppDomainData(CLRDATA_ADDRESS addr, struct DacpAppDomainData *data); HRESULT GetAppDomainName(CLRDATA_ADDRESS addr, unsigned int count, WCHAR *name, unsigned int *pNeeded); HRESULT GetDomainFromContext(CLRDATA_ADDRESS context, CLRDATA_ADDRESS *domain); - + // Assemblies HRESULT GetAssemblyList(CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[], int *pNeeded); HRESULT GetAssemblyData(CLRDATA_ADDRESS baseDomainPtr, CLRDATA_ADDRESS assembly, struct DacpAssemblyData *data); HRESULT GetAssemblyName(CLRDATA_ADDRESS assembly, unsigned int count, WCHAR *name, unsigned int *pNeeded); - + // Modules HRESULT GetModule(CLRDATA_ADDRESS addr, IXCLRDataModule **mod); HRESULT GetModuleData(CLRDATA_ADDRESS moduleAddr, struct DacpModuleData *data); HRESULT TraverseModuleMap(ModuleMapType mmt, CLRDATA_ADDRESS moduleAddr, MODULEMAPTRAVERSE pCallback, LPVOID token); HRESULT GetAssemblyModuleList(CLRDATA_ADDRESS assembly, unsigned int count, CLRDATA_ADDRESS modules[], unsigned int *pNeeded); HRESULT GetILForModule(CLRDATA_ADDRESS moduleAddr, DWORD rva, CLRDATA_ADDRESS *il); - + // Threads HRESULT GetThreadData(CLRDATA_ADDRESS thread, struct DacpThreadData *data); HRESULT GetThreadFromThinlockID(UINT thinLockId, CLRDATA_ADDRESS *pThread); HRESULT GetStackLimits(CLRDATA_ADDRESS threadPtr, CLRDATA_ADDRESS *lower, CLRDATA_ADDRESS *upper, CLRDATA_ADDRESS *fp); - + // MethodDescs HRESULT GetMethodDescData(CLRDATA_ADDRESS methodDesc, CLRDATA_ADDRESS ip, struct DacpMethodDescData *data, ULONG cRevertedRejitVersions, struct DacpReJitData * rgRevertedRejitData, ULONG * pcNeededRevertedRejitData); HRESULT GetMethodDescPtrFromIP(CLRDATA_ADDRESS ip, CLRDATA_ADDRESS * ppMD); @@ -228,7 +228,7 @@ interface ISOSDacInterface : IUnknown HRESULT GetObjectData(CLRDATA_ADDRESS objAddr, struct DacpObjectData *data); HRESULT GetObjectStringData(CLRDATA_ADDRESS obj, unsigned int count, WCHAR *stringData, unsigned int *pNeeded); HRESULT GetObjectClassName(CLRDATA_ADDRESS obj, unsigned int count, WCHAR *className, unsigned int *pNeeded); - + // MethodTable HRESULT GetMethodTableName(CLRDATA_ADDRESS mt, unsigned int count, WCHAR *mtName, unsigned int *pNeeded); HRESULT GetMethodTableData(CLRDATA_ADDRESS mt, struct DacpMethodTableData *data); @@ -238,7 +238,7 @@ interface ISOSDacInterface : IUnknown // EEClass HRESULT GetMethodTableForEEClass(CLRDATA_ADDRESS eeClass, CLRDATA_ADDRESS *value); - + // FieldDesc HRESULT GetFieldDescData(CLRDATA_ADDRESS fieldDesc, struct DacpFieldDescData *data); @@ -260,7 +260,7 @@ interface ISOSDacInterface : IUnknown HRESULT GetOOMStaticData(struct DacpOomData *data); HRESULT GetHeapAnalyzeData(CLRDATA_ADDRESS addr, struct DacpGcHeapAnalyzeData *data); HRESULT GetHeapAnalyzeStaticData(struct DacpGcHeapAnalyzeData *data); - + // DomainLocal HRESULT GetDomainLocalModuleData(CLRDATA_ADDRESS addr, struct DacpDomainLocalModuleData *data); HRESULT GetDomainLocalModuleDataFromAppDomain(CLRDATA_ADDRESS appDomainAddr, int moduleID, struct DacpDomainLocalModuleData *data); @@ -281,7 +281,7 @@ interface ISOSDacInterface : IUnknown // EH HRESULT TraverseEHInfo(CLRDATA_ADDRESS ip, DUMPEHINFO pCallback, LPVOID token); HRESULT GetNestedExceptionData(CLRDATA_ADDRESS exception, CLRDATA_ADDRESS *exceptionObject, CLRDATA_ADDRESS *nextNestedException); - + // StressLog HRESULT GetStressLogAddress(CLRDATA_ADDRESS *stressLog); @@ -302,9 +302,9 @@ interface ISOSDacInterface : IUnknown HRESULT GetCCWData(CLRDATA_ADDRESS ccw, struct DacpCCWData *data); HRESULT GetCCWInterfaces(CLRDATA_ADDRESS ccw, unsigned int count, struct DacpCOMInterfacePointerData *interfaces, unsigned int *pNeeded); HRESULT TraverseRCWCleanupList(CLRDATA_ADDRESS cleanupListPtr, VISITRCWFORCLEANUP pCallback, LPVOID token); - + // GC Reference Functions - + /* GetStackReferences * Enumerates all references on a given callstack. */ @@ -313,7 +313,7 @@ interface ISOSDacInterface : IUnknown HRESULT GetThreadAllocData(CLRDATA_ADDRESS thread, struct DacpAllocData *data); HRESULT GetHeapAllocData(unsigned int count, struct DacpGenerationAllocData *data, unsigned int *pNeeded); - + // For BindingDisplay plugin HRESULT GetFailedAssemblyList(CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[], unsigned int *pNeeded); HRESULT GetPrivateBinPaths(CLRDATA_ADDRESS appDomain, int count, WCHAR *paths, unsigned int *pNeeded); @@ -375,5 +375,18 @@ interface ISOSDacInterface5 : IUnknown ] interface ISOSDacInterface6 : IUnknown { - HRESULT GetMethodTableFieldData(CLRDATA_ADDRESS mt, struct DacpMethodTableFieldData *data); + HRESULT GetMethodTableCollectibleData(CLRDATA_ADDRESS mt, struct DacpMethodTableCollectibleData *data); +}; + +[ + object, + local, + uuid(c1020dde-fe98-4536-a53b-f35a74c327eb) +] +interface ISOSDacInterface7 : IUnknown +{ + HRESULT GetPendingReJITID(CLRDATA_ADDRESS methodDesc, int *pRejitId); + HRESULT GetReJITInformation(CLRDATA_ADDRESS methodDesc, int rejitId, struct DacpReJitData2 *pRejitData); + HRESULT GetProfilerModifiedILInformation(CLRDATA_ADDRESS methodDesc, struct DacpProfilerILData *pILData); + HRESULT GetMethodsWithProfilerModifiedIL(CLRDATA_ADDRESS mod, CLRDATA_ADDRESS *methodDescs, int cMethodDescs, int *pcMethodDescs); }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/sstring.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/sstring.h index a37070d..ec2eb0c 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/sstring.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/sstring.h @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. // --------------------------------------------------------------------------- // SString.h (Safe String) -// +// // --------------------------------------------------------------------------- @@ -45,6 +45,7 @@ #include "utilcode.h" #include "sbuffer.h" +#include "debugmacros.h" // ========================================================================================== // Documentational typedefs: use these to indicate specific representations of 8 bit strings: @@ -70,7 +71,7 @@ typedef const UTF8 *LPCUTF8; typedef DPTR(class SString) PTR_SString; -class SString : private SBuffer +class EMPTY_BASES_DECL SString : private SBuffer { friend struct _DacGlobals; @@ -208,22 +209,22 @@ private: COUNT_T GetCount() const; BOOL IsEmpty() const; - // Return whether a single byte string has all characters which fit in the ASCII set. - // (Note that this will return FALSE if the string has been converted to unicode for any + // Return whether a single byte string has all characters which fit in the ASCII set. + // (Note that this will return FALSE if the string has been converted to unicode for any // reason.) BOOL IsASCII() const; - // !!!!!!!!!!!!!! WARNING about case insensitive operations !!!!!!!!!!!!!!! + // !!!!!!!!!!!!!! WARNING about case insensitive operations !!!!!!!!!!!!!!! // - // THIS IS NOT SUPPORTED FULLY ON WIN9x - // SString case-insensitive comparison is based off LCMapString, + // THIS IS NOT SUPPORTED FULLY ON WIN9x + // SString case-insensitive comparison is based off LCMapString, // which does not work on characters outside the current OS code page. // - // Case insensitive code in SString is primarily targeted at - // supporting path comparisons, which is supported correctly on 9x, + // Case insensitive code in SString is primarily targeted at + // supporting path comparisons, which is supported correctly on 9x, // since file system names are limited to the OS code page. - // - // !!!!!!!!!!!!!! WARNING about case insensitive operations !!!!!!!!!!!!!!! + // + // !!!!!!!!!!!!!! WARNING about case insensitive operations !!!!!!!!!!!!!!! // Compute a content-based hash value ULONG Hash() const; @@ -320,13 +321,13 @@ private: // Iterators: // ------------------------------------------------------------------ - // SString splits iterators into two categories. + // SString splits iterators into two categories. // // CIterator and Iterator are cheap to create, but allow only read-only - // access to the string. + // access to the string. // // UIterator forces a unicode conversion, but allows - // assignment to individual string characters. They are also a bit more + // assignment to individual string characters. They are also a bit more // efficient once created. // ------------------------------------------------------------------ @@ -335,7 +336,7 @@ private: protected: - class UIndex : public SBuffer::Index + class EMPTY_BASES_DECL UIndex : public SBuffer::Index { friend class SString; friend class Indexer; @@ -354,7 +355,7 @@ private: public: - class UIterator : public UIndex, public Indexer + class EMPTY_BASES_DECL UIterator : public UIndex, public Indexer { friend class SString; @@ -389,7 +390,7 @@ private: protected: - class Index : public SBuffer::Index + class EMPTY_BASES_DECL Index : public SBuffer::Index { friend class SString; @@ -421,7 +422,7 @@ private: public: - class CIterator : public Index, public Indexer + class EMPTY_BASES_DECL CIterator : public Index, public Indexer { friend class SString; @@ -461,7 +462,7 @@ private: WCHAR operator[](int index) const { return Index::operator[](index); } }; - class Iterator : public Index, public Indexer + class EMPTY_BASES_DECL Iterator : public Index, public Indexer { friend class SString; @@ -523,10 +524,10 @@ private: void LowerCase(); void UpperCase(); - + // Helper function to convert string in-place to lower-case (no allocation overhead for SString instance) static void LowerCase(__inout_z LPWSTR wszString); - + // These routines will use the given scratch string if necessary // to perform a conversion to the desired representation @@ -626,7 +627,7 @@ private: // Instantiate a copy of the raw buffer in the host and return a pointer to it void * DacGetRawContent() const; - // Instantiate a copy of the raw buffer in the host. Requires that the underlying + // Instantiate a copy of the raw buffer in the host. Requires that the underlying // representation is already unicode. const WCHAR * DacGetRawUnicode() const; @@ -737,7 +738,7 @@ private: private: static int CaseCompareHelperA(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount); static int CaseCompareHelper(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount); - + // Internal helpers: static const BYTE s_EmptyBuffer[2]; @@ -786,13 +787,13 @@ private: void ConvertASCIIToUnicode(SString &dest) const; void ConvertToUnicode() const; void ConvertToUnicode(const CIterator &i) const; - + const SString &GetCompatibleString(const SString &s, SString &scratch) const; const SString &GetCompatibleString(const SString &s, SString &scratch, const CIterator &i) const; BOOL ScanASCII() const; void NullTerminate(); - void Resize(COUNT_T count, Representation representation, + void Resize(COUNT_T count, Representation representation, Preserve preserve = DONT_PRESERVE); void OpenBuffer(Representation representation, COUNT_T countChars); @@ -805,7 +806,7 @@ private: // =========================================================================== template -class InlineSString : public SString +class EMPTY_BASES_DECL InlineSString : public SString { private: BYTE m_inline[SBUFFER_PADDED_SIZE(MEMSIZE)]; @@ -978,7 +979,7 @@ typedef InlineSString<2 * 260> LongPathString; // ScratchBuffer classes are used by the GetXXX() routines to allocate scratch space in. // ================================================================================ -class SString::AbstractScratchBuffer : private SString +class EMPTY_BASES_DECL SString::AbstractScratchBuffer : private SString { protected: // Do not use this class directly - use @@ -987,7 +988,7 @@ class SString::AbstractScratchBuffer : private SString }; template -class ScratchBuffer : public SString::AbstractScratchBuffer +class EMPTY_BASES_DECL ScratchBuffer : public SString::AbstractScratchBuffer { private: BYTE m_inline[MEMSIZE]; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/sstring.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/sstring.inl index 3bf8444..459226b 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/sstring.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/sstring.inl @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// +// #ifndef _SSTRING_INL_ #define _SSTRING_INL_ @@ -646,9 +646,6 @@ inline const WCHAR *SString::GetUnicode() const SUPPORTS_DAC; } SS_CONTRACT_END; - - if (this == NULL) - SS_RETURN NULL; ConvertToUnicode(); @@ -686,7 +683,7 @@ inline const WCHAR *SString::GetUnicode(const CIterator &i) const SS_CONTRACT_END; PRECONDITION(CheckPointer(this)); - + ConvertToUnicode(i); SS_RETURN i.GetUnicode(); @@ -711,7 +708,7 @@ inline void SString::Append(const SString &s) } inline void SString::Append(const WCHAR *string) -{ +{ SS_CONTRACT_VOID { GC_NOTRIGGER; @@ -875,7 +872,7 @@ inline BOOL SString::Match(const CIterator &i, WCHAR c) const NOTHROW; } SS_CONTRACT_END; - + // End() will not throw here CONTRACT_VIOLATION(ThrowsViolation); SS_RETURN (i < End() && i[0] == c); @@ -924,7 +921,7 @@ inline BOOL SString::Skip(CIterator &i, WCHAR c) const // Find string within this string. Return TRUE and update iterator if found inline BOOL SString::Find(CIterator &i, const WCHAR *string) const -{ +{ SS_CONTRACT(BOOL) { GC_NOTRIGGER; @@ -941,7 +938,7 @@ inline BOOL SString::Find(CIterator &i, const WCHAR *string) const } inline BOOL SString::FindASCII(CIterator &i, const CHAR *string) const -{ +{ SS_CONTRACT(BOOL) { GC_NOTRIGGER; @@ -958,7 +955,7 @@ inline BOOL SString::FindASCII(CIterator &i, const CHAR *string) const } inline BOOL SString::FindUTF8(CIterator &i, const CHAR *string) const -{ +{ SS_CONTRACT(BOOL) { GC_NOTRIGGER; @@ -975,7 +972,7 @@ inline BOOL SString::FindUTF8(CIterator &i, const CHAR *string) const } inline BOOL SString::FindBack(CIterator &i, const WCHAR *string) const -{ +{ SS_CONTRACT(BOOL) { GC_NOTRIGGER; @@ -992,7 +989,7 @@ inline BOOL SString::FindBack(CIterator &i, const WCHAR *string) const } inline BOOL SString::FindBackASCII(CIterator &i, const CHAR *string) const -{ +{ SS_CONTRACT(BOOL) { GC_NOTRIGGER; @@ -1009,7 +1006,7 @@ inline BOOL SString::FindBackASCII(CIterator &i, const CHAR *string) const } inline BOOL SString::FindBackUTF8(CIterator &i, const CHAR *string) const -{ +{ SS_CONTRACT(BOOL) { GC_NOTRIGGER; @@ -1143,7 +1140,7 @@ inline void SString::Trim() const // RETURN true if the string is empty. inline BOOL SString::IsEmpty() const -{ +{ SS_CONTRACT(BOOL) { GC_NOTRIGGER; @@ -1158,7 +1155,7 @@ inline BOOL SString::IsEmpty() const // RETURN true if the string rep is ASCII. inline BOOL SString::IsASCII() const -{ +{ SS_CONTRACT(BOOL) { GC_NOTRIGGER; @@ -1172,7 +1169,7 @@ inline BOOL SString::IsASCII() const // Get the number of characters in the string (excluding the terminating NULL) inline COUNT_T SString::GetCount() const -{ +{ SS_CONTRACT(COUNT_T) { GC_NOTRIGGER; @@ -1231,8 +1228,8 @@ inline WCHAR *SString::GetRawUnicode() const // Private helper: // get the representation (ansi, unicode, utf8) -inline SString::Representation SString::GetRepresentation() const -{ +inline SString::Representation SString::GetRepresentation() const +{ WRAPPER_NO_CONTRACT; return (Representation) SBuffer::GetRepresentationField(); @@ -1241,7 +1238,7 @@ inline SString::Representation SString::GetRepresentation() const // Private helper. // Set the representation. inline void SString::SetRepresentation(SString::Representation representation) -{ +{ #ifdef SSTRING_EXTRA_CHECKS CONTRACT_VOID { @@ -1265,8 +1262,8 @@ inline void SString::SetRepresentation(SString::Representation representation) // Private helper: // Get the amount to shift the byte size to get a character count -inline int SString::GetCharacterSizeShift() const -{ +inline int SString::GetCharacterSizeShift() const +{ WRAPPER_NO_CONTRACT; // Note that the flag is backwards; we want the default @@ -1312,9 +1309,9 @@ FORCEINLINE void SString::NullTerminate() //---------------------------------------------------------------------------- // private helper // Return true if the string is a literal. -// A literal string has immutable memory. +// A literal string has immutable memory. //---------------------------------------------------------------------------- -inline BOOL SString::IsLiteral() const +inline BOOL SString::IsLiteral() const { WRAPPER_NO_CONTRACT; @@ -1324,7 +1321,7 @@ inline BOOL SString::IsLiteral() const //---------------------------------------------------------------------------- // private helper: // RETURN true if the string allocated (and should delete) its buffer. -// IsAllocated() will RETURN false for Literal strings and +// IsAllocated() will RETURN false for Literal strings and // stack-based strings (the buffer is on the stack) //---------------------------------------------------------------------------- inline BOOL SString::IsAllocated() const @@ -1338,7 +1335,7 @@ inline BOOL SString::IsAllocated() const // Return true after we call OpenBuffer(), but before we close it. // All SString operations are illegal while the buffer is open. //---------------------------------------------------------------------------- -#if _DEBUG +#if _DEBUG inline BOOL SString::IsBufferOpen() const { WRAPPER_NO_CONTRACT; @@ -1351,7 +1348,7 @@ inline BOOL SString::IsBufferOpen() const // Return true if we've scanned the string to see if it is in the ASCII subset. //---------------------------------------------------------------------------- inline BOOL SString::IsASCIIScanned() const -{ +{ WRAPPER_NO_CONTRACT; SUPPORTS_DAC; @@ -1362,7 +1359,7 @@ inline BOOL SString::IsASCIIScanned() const // Set that we've scanned the string to see if it is in the ASCII subset. //---------------------------------------------------------------------------- inline void SString::SetASCIIScanned() const -{ +{ WRAPPER_NO_CONTRACT; SUPPORTS_DAC_HOST_ONLY; @@ -1373,7 +1370,7 @@ inline void SString::SetASCIIScanned() const // Return true if we've normalized the string to unicode //---------------------------------------------------------------------------- inline BOOL SString::IsNormalized() const -{ +{ WRAPPER_NO_CONTRACT; SUPPORTS_DAC; @@ -1384,7 +1381,7 @@ inline BOOL SString::IsNormalized() const // Set that we've normalized the string to unicode //---------------------------------------------------------------------------- inline void SString::SetNormalized() const -{ +{ WRAPPER_NO_CONTRACT; const_cast(this)->SBuffer::SetFlag3(); @@ -1394,7 +1391,7 @@ inline void SString::SetNormalized() const // Clear normalization //---------------------------------------------------------------------------- inline void SString::ClearNormalized() const -{ +{ WRAPPER_NO_CONTRACT; SUPPORTS_DAC_HOST_ONLY; @@ -1439,10 +1436,10 @@ inline BOOL SString::IsIteratable() const STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_SUPPORTS_DAC; - // Note that in many cases ANSI may be fixed width. However we + // Note that in many cases ANSI may be fixed width. However we // currently still do not allow iterating on them, because we would have to // do character-by-character conversion on a character dereference (which must - // go to unicode) . We may want to adjust this going forward to + // go to unicode) . We may want to adjust this going forward to // depending on perf in the non-ASCII but fixed width ANSI case. return ((GetRepresentation()&REPRESENTATION_VARIABLE_MASK) == 0); @@ -1455,7 +1452,7 @@ inline BOOL SString::IsIteratable() const // count does not include the null-terminator, but the RETURN value does. //---------------------------------------------------------------------------- inline COUNT_T SString::CountToSize(COUNT_T count) const -{ +{ SS_CONTRACT(COUNT_T) { GC_NOTRIGGER; @@ -1471,7 +1468,7 @@ inline COUNT_T SString::CountToSize(COUNT_T count) const //---------------------------------------------------------------------------- // Private helper. -// Return the maxmimum count of characters that could fit in a buffer of +// Return the maxmimum count of characters that could fit in a buffer of // 'size' bytes in the given representation. // 'size' includes the null terminator, but the RETURN value does not. //---------------------------------------------------------------------------- @@ -1493,7 +1490,7 @@ inline COUNT_T SString::SizeToCount(COUNT_T size) const //---------------------------------------------------------------------------- // Private helper. // Return the maxmimum count of characters that could fit in the current -// buffer including NULL terminator. +// buffer including NULL terminator. //---------------------------------------------------------------------------- inline COUNT_T SString::GetBufferSizeInCharIncludeNullChar() const { @@ -1505,7 +1502,7 @@ inline COUNT_T SString::GetBufferSizeInCharIncludeNullChar() const } - + //---------------------------------------------------------------------------- // Assert helper // Asser that the iterator is within the given string. @@ -1543,7 +1540,7 @@ inline CHECK SString::CheckEmpty() const //---------------------------------------------------------------------------- // Check the range of a count //---------------------------------------------------------------------------- -inline CHECK SString::CheckCount(COUNT_T count) +inline CHECK SString::CheckCount(COUNT_T count) { CANNOT_HAVE_CONTRACT; CHECK(CheckSize(count*sizeof(WCHAR))); @@ -1568,7 +1565,7 @@ inline CHECK SString::CheckRepresentation(int representation) #if CHECK_INVARIANTS //---------------------------------------------------------------------------- -// Assert helper. Check that the string only uses the ASCII subset of +// Assert helper. Check that the string only uses the ASCII subset of // codes. //---------------------------------------------------------------------------- inline CHECK SString::CheckASCIIString(const CHAR *string) @@ -1625,7 +1622,7 @@ inline CHECK SString::InternalInvariant() const //---------------------------------------------------------------------------- // Return a writeable buffer that can store 'countChars'+1 unicode characters. // Call CloseBuffer when done. -//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- inline WCHAR *SString::OpenUnicodeBuffer(COUNT_T countChars) { SS_CONTRACT(WCHAR*) @@ -1665,7 +1662,7 @@ inline WCHAR *SString::GetCopyOfUnicodeString() buffer = new WCHAR[GetCount() +1]; wcscpy_s(buffer, GetCount() + 1, GetUnicode()); - + SS_RETURN buffer.Extract(); } @@ -1721,9 +1718,9 @@ inline UTF8 *SString::OpenUTF8Buffer(COUNT_T countBytes) //---------------------------------------------------------------------------- // Private helper to open a raw buffer. -// Called by public functions to open the buffer in the specific +// Called by public functions to open the buffer in the specific // representation. -// While the buffer is opened, all other operations are illegal. Call +// While the buffer is opened, all other operations are illegal. Call // CloseBuffer() when done. //---------------------------------------------------------------------------- inline void SString::OpenBuffer(SString::Representation representation, COUNT_T countChars) @@ -1757,7 +1754,7 @@ inline void SString::OpenBuffer(SString::Representation representation, COUNT_T } //---------------------------------------------------------------------------- -// Get the max size that can be passed to OpenUnicodeBuffer without causing +// Get the max size that can be passed to OpenUnicodeBuffer without causing // allocations. //---------------------------------------------------------------------------- inline COUNT_T SString::GetUnicodeAllocation() @@ -1767,16 +1764,16 @@ inline COUNT_T SString::GetUnicodeAllocation() INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; - } + } CONTRACTL_END; COUNT_T allocation = GetAllocation(); - return ( (allocation > sizeof(WCHAR)) + return ( (allocation > sizeof(WCHAR)) ? (allocation - sizeof(WCHAR)) / sizeof(WCHAR) : 0 ); } //---------------------------------------------------------------------------- -// Close an open buffer. Assumes that we wrote exactly number of characters +// Close an open buffer. Assumes that we wrote exactly number of characters // we requested in OpenBuffer. //---------------------------------------------------------------------------- inline void SString::CloseBuffer() @@ -1801,7 +1798,7 @@ inline void SString::CloseBuffer() //---------------------------------------------------------------------------- // CloseBuffer() tells the SString that we're done using the unsafe buffer. // countChars is the count of characters actually used (so we can set m_count). -// This is important if we request a buffer larger than what we actually +// This is important if we request a buffer larger than what we actually // used. //---------------------------------------------------------------------------- inline void SString::CloseBuffer(COUNT_T finalCount) @@ -1852,7 +1849,7 @@ inline void SString::EnsureWritable() const } //----------------------------------------------------------------------------- -// Convert the internal representation to be a fixed size +// Convert the internal representation to be a fixed size //----------------------------------------------------------------------------- inline void SString::ConvertToFixed() const { @@ -1881,7 +1878,7 @@ inline void SString::ConvertToFixed() const } //----------------------------------------------------------------------------- -// Convert the internal representation to be an iteratable one (current +// Convert the internal representation to be an iteratable one (current // requirements here are that it be trivially convertable to unicode chars.) //----------------------------------------------------------------------------- inline void SString::ConvertToIteratable() const @@ -1930,7 +1927,7 @@ inline SString::UIterator SString::BeginUnicode() SS_RETURN UIterator(this, 0); } - + inline SString::UIterator SString::EndUnicode() { SS_CONTRACT(SString::UIterator) @@ -1967,7 +1964,7 @@ FORCEINLINE SString::CIterator SString::Begin() const SS_RETURN CIterator(this, 0); } - + FORCEINLINE SString::CIterator SString::End() const { SS_CONTRACT(SString::CIterator) @@ -1988,7 +1985,7 @@ FORCEINLINE SString::CIterator SString::End() const // Create Iterators on the string. //----------------------------------------------------------------------------- -FORCEINLINE SString::Iterator SString::Begin() +FORCEINLINE SString::Iterator SString::Begin() { SS_CONTRACT(SString::Iterator) { @@ -2005,8 +2002,8 @@ FORCEINLINE SString::Iterator SString::Begin() SS_RETURN Iterator(this, 0); } - -FORCEINLINE SString::Iterator SString::End() + +FORCEINLINE SString::Iterator SString::End() { SS_CONTRACT(SString::Iterator) { @@ -2049,7 +2046,7 @@ inline SString::Index::Index(SString *string, SCOUNT_T index) SUPPORTS_DAC; } SS_CONTRACT_END; - + m_characterSizeShift = string->GetCharacterSizeShift(); SS_RETURN; @@ -2125,7 +2122,7 @@ inline WCHAR SString::Index::operator*() const } inline void SString::Index::operator->() const -{ +{ LIMITED_METHOD_CONTRACT; } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/stack.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/stack.h index 589f8f7..fd9af58 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/stack.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/stack.h @@ -1,9 +1,9 @@ // 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. -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- // This is a generic growable stack of T. #ifndef GENERIC_STACK_H @@ -75,7 +75,7 @@ class Stack return m_elems[m_elemsCount-1]; } - // Caller should take care to only side-effect the return reference if he/she is *sure* + // Caller should take care to only side-effect the return reference if they are *sure* // that the stack will not be popped in the interim! T& PeekRef() { diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/stackframe.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/stackframe.h index 940951d..43ca110 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/stackframe.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/stackframe.h @@ -86,19 +86,19 @@ struct StackFrame //--------------------------------------------------------------------------------------- // -// On WIN64, all the stack range tracking done by the Exception Handling (EH) subsystem is based on the +// On WIN64, all the stack range tracking done by the Exception Handling (EH) subsystem is based on the // establisher frame given by the OS. On IA64, the establisher frame is the caller SP and the current BSP. // On X64, it is the initial SP before any dynamic stack allocation, i.e. it is the SP when a function exits // the prolog. The EH subsystem uses the same format. // -// The stackwalker needs to get information from the EH subsystem in order to skip funclets. Unfortunately, -// stackwalking is based on the current SP, i.e. the SP when the control flow leaves a function via a -// function call. Thus, for stack frames with dynamic stack allocations on X64, the SP values used by the -// stackwalker and the EH subsystem don't match. +// The stackwalker needs to get information from the EH subsystem in order to skip funclets. Unfortunately, +// stackwalking is based on the current SP, i.e. the SP when the control flow leaves a function via a +// function call. Thus, for stack frames with dynamic stack allocations on X64, the SP values used by the +// stackwalker and the EH subsystem don't match. // // To work around this problem, we need to somehow bridge the different SP values. We do so by using the -// caller SP instead of the current SP for comparisons during a stackwalk on X64. Creating a new type -// explicitly spells out the important distinction that this is NOT in the same format as the +// caller SP instead of the current SP for comparisons during a stackwalk on X64. Creating a new type +// explicitly spells out the important distinction that this is NOT in the same format as the // OS establisher frame. // // Notes: @@ -115,13 +115,13 @@ struct CallerStackFrame : StackFrame { } -#ifdef WIN64EXCEPTIONS +#ifdef FEATURE_EH_FUNCLETS static inline CallerStackFrame FromRegDisplay(REGDISPLAY* pRD) { _ASSERTE(pRD->IsCallerSPValid || pRD->IsCallerContextValid); return CallerStackFrame(GetSP(pRD->pCallerContext)); } -#endif // WIN64EXCEPTIONS +#endif // FEATURE_EH_FUNCLETS }; #endif // __STACKFRAME_H diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/stacktrace.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/stacktrace.h index 9152116..ef37dd9 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/stacktrace.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/stacktrace.h @@ -1,9 +1,9 @@ // 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. -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- #ifndef __STACK_TRACE_H__ #define __STACK_TRACE_H__ @@ -22,13 +22,13 @@ HINSTANCE LoadDbgHelp(); #define cfrMaxAssertStackLevels 20 #define cchMaxAssertExprLen 257 -#ifdef _WIN64 +#ifdef HOST_64BIT #define cchMaxAssertStackLevelStringLen \ ((3 * 8) + cchMaxAssertModuleLen + cchMaxAssertSymbolLen + 13) // 3 addresses of at most 8 char, module, symbol, and the extra chars: // 0x
: ! + 0x\n - //FMT_ADDR_BARE is defined as "%08x`%08x" on Win64, and as + //FMT_ADDR_BARE is defined as "%08x`%08x" on Win64, and as //"%08x" on 32 bit platforms. Hence the difference in the definitions. #else @@ -47,7 +47,7 @@ HINSTANCE LoadDbgHelp(); /**************************************************************************** * MagicDeinit * *-------------* -* Description: +* Description: * Cleans up for the symbol loading code. Should be called before * exiting in order to free the dynamically loaded imagehlp.dll ******************************************************************** robch */ @@ -56,7 +56,7 @@ void MagicDeinit(void); /**************************************************************************** * GetStringFromStackLevels * *--------------------------* -* Description: +* Description: * Retrieves a string from the stack frame. If more than one frame, they * are separated by newlines. Each fram appears in this format: * @@ -67,25 +67,25 @@ void GetStringFromStackLevels(UINT ifrStart, UINT cfrTotal, __out_ecount(cchMaxA /**************************************************************************** * GetStringFromAddr * *-------------------* -* Description: +* Description: * Builds a string from an address in the format: * * 0x
: ! + 0x ******************************************************************** robch */ void GetStringFromAddr(DWORD_PTR dwAddr, __out_ecount(cchMaxAssertStackLevelStringLen) LPSTR szString); -#if defined(_TARGET_X86_) && !defined(FEATURE_PAL) +#if defined(TARGET_X86) && !defined(TARGET_UNIX) /**************************************************************************** * ClrCaptureContext * *-------------------* -* Description: +* Description: * Exactly the contents of RtlCaptureContext for Win7 - Win2K doesn't * support this, so we need it for CoreCLR 4, if we require Win2K support ****************************************************************************/ extern "C" void __stdcall ClrCaptureContext(__out PCONTEXT ctx); -#else // _TARGET_X86_ && !FEATURE_PAL +#else // TARGET_X86 && !TARGET_UNIX #define ClrCaptureContext RtlCaptureContext -#endif // _TARGET_X86_ && !FEATURE_PAL +#endif // TARGET_X86 && !TARGET_UNIX #endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/static_assert.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/static_assert.h index e635d70..e5b542d 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/static_assert.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/static_assert.h @@ -9,7 +9,7 @@ //-------------------------------------------------------------------------------- // static_assert represents a check which should be made at compile time. It -// can only be done on a constant expression. +// can only be done on a constant expression. //-------------------------------------------------------------------------------- #ifndef __STATIC_ASSERT_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/staticcontract.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/staticcontract.h index 4cf7f4a..3fe749d 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/staticcontract.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/staticcontract.h @@ -28,7 +28,7 @@ // from Contract.h to allow their inclusion in any part of the system. // -#if defined(_DEBUG) && defined(_TARGET_X86_) +#if defined(_DEBUG) && defined(TARGET_X86) #define METHOD_CANNOT_BE_FOLDED_DEBUG \ static int _noFold = 0; \ _noFold++; @@ -36,7 +36,7 @@ #define METHOD_CANNOT_BE_FOLDED_DEBUG #endif -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 // // currently, only x86 has a static contract analysis tool, so let's not @@ -68,7 +68,7 @@ // here is the plan: // -// a special holder which implements a violation +// a special holder which implements a violation // #define ANNOTATION_FN_SPECIAL_HOLDER_BEGIN __annotation(W("SPECIAL_HOLDER_BEGIN ") SCAN_WIDEN(__FUNCTION__)) @@ -97,7 +97,7 @@ #define ANNOTATION_FN_HOST_NOCALLS __annotation(W("HOST_NOCALLS ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_HOST_CALLS __annotation(W("HOST_CALLS ") SCAN_WIDEN(__FUNCTION__)) -#define ANNOTATION_ENTRY_POINT __annotation(W("SO_EP ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_ENTRY_POINT __annotation(W("SO_EP ") SCAN_WIDEN(__FUNCTION__)) // for DacCop @@ -111,7 +111,7 @@ #endif -#else // _TARGET_X86_ +#else // TARGET_X86 #define ANNOTATION_TRY_BEGIN { } #define ANNOTATION_TRY_END { } @@ -170,7 +170,7 @@ #define ANNOTATION_DEBUG_ONLY { } #endif -#endif // _TARGET_X86_ +#endif // TARGET_X86 #define STATIC_CONTRACT_THROWS ANNOTATION_FN_THROWS #define STATIC_CONTRACT_NOTHROW ANNOTATION_FN_NOTHROW @@ -181,7 +181,7 @@ #define STATIC_CONTRACT_GC_TRIGGERS ANNOTATION_FN_GC_TRIGGERS #define STATIC_CONTRACT_GC_NOTRIGGER ANNOTATION_FN_GC_NOTRIGGER #define STATIC_CONTRACT_HOST_NOCALLS ANNOTATION_FN_HOST_NOCALLS -#define STATIC_CONTRACT_HOST_CALLS ANNOTATION_FN_HOST_CALLS +#define STATIC_CONTRACT_HOST_CALLS ANNOTATION_FN_HOST_CALLS #define STATIC_CONTRACT_SUPPORTS_DAC ANNOTATION_SUPPORTS_DAC #define STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY ANNOTATION_SUPPORTS_DAC_HOST_ONLY @@ -201,7 +201,7 @@ STATIC_CONTRACT_CANNOT_TAKE_LOCK; \ ANNOTATION_VIOLATION(TakesLockViolation); #else -#define STATIC_CONTRACT_DEBUG_ONLY +#define STATIC_CONTRACT_DEBUG_ONLY #endif #define STATIC_CONTRACT_VIOLATION(mask) \ @@ -285,7 +285,7 @@ typedef StaticContract::ScanThrowMarkerStandard ScanThrowMarker; // we use BlockMarker's only for SCAN -#if defined(_DEBUG) && defined(_TARGET_X86_) && !defined(DACCESS_COMPILE) +#if defined(_DEBUG) && defined(TARGET_X86) && !defined(DACCESS_COMPILE) template class BlockMarker diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/stdmacros.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/stdmacros.h index 6a7f286..bd556a5 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/stdmacros.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/stdmacros.h @@ -29,14 +29,14 @@ #define DEBUG_ARG(x) , x #define DEBUG_ARG1(x) x #else -#define DEBUG_ARG(x) +#define DEBUG_ARG(x) #define DEBUG_ARG1(x) #endif #ifdef DACCESS_COMPILE #define DAC_ARG(x) , x #else -#define DAC_ARG(x) +#define DAC_ARG(x) #endif @@ -44,7 +44,7 @@ /* Portability macros */ /********************************************/ -#ifdef _TARGET_AMD64_ +#ifdef TARGET_AMD64 #define AMD64_FIRST_ARG(x) x , #define AMD64_ARG(x) , x #define AMD64_ONLY(x) x @@ -58,7 +58,7 @@ #define NOT_AMD64_ARG(x) , x #endif -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 #define X86_FIRST_ARG(x) x , #define X86_ARG(x) , x #define X86_ONLY(x) x @@ -72,19 +72,19 @@ #define NOT_X86_ARG(x) , x #endif -#ifdef _WIN64 -#define WIN64_ARG(x) , x -#define WIN64_ONLY(x) x -#define NOT_WIN64(x) -#define NOT_WIN64_ARG(x) +#ifdef HOST_64BIT +#define BIT64_ARG(x) , x +#define BIT64_ONLY(x) x +#define NOT_BIT64(x) +#define NOT_BIT64_ARG(x) #else -#define WIN64_ARG(x) -#define WIN64_ONLY(x) -#define NOT_WIN64(x) x -#define NOT_WIN64_ARG(x) , x -#endif // _WIN64 +#define BIT64_ARG(x) +#define BIT64_ONLY(x) +#define NOT_BIT64(x) x +#define NOT_BIT64_ARG(x) , x +#endif // HOST_64BIT -#ifdef _TARGET_ARM_ +#ifdef TARGET_ARM #define ARM_FIRST_ARG(x) x , #define ARM_ARG(x) , x #define ARM_ONLY(x) x @@ -98,7 +98,7 @@ #define NOT_ARM_ARG(x) , x #endif -#ifdef _TARGET_ARM64_ +#ifdef TARGET_ARM64 #define ARM64_FIRST_ARG(x) x , #define ARM64_ARG(x) , x #define ARM64_ONLY(x) x @@ -112,27 +112,27 @@ #define NOT_ARM64_ARG(x) , x #endif -#ifdef _TARGET_64BIT_ +#ifdef TARGET_64BIT #define LOG2_PTRSIZE 3 #else #define LOG2_PTRSIZE 2 #endif -#ifdef _WIN64 +#ifdef HOST_64BIT #define INVALID_POINTER_CC 0xcccccccccccccccc #define INVALID_POINTER_CD 0xcdcdcdcdcdcdcdcd #define FMT_ADDR " %08x`%08x " #define LFMT_ADDR W(" %08x`%08x ") - #define DBG_ADDR(ptr) (((UINT_PTR) (ptr)) >> 32), (((UINT_PTR) (ptr)) & 0xffffffff) -#else // _WIN64 + #define DBG_ADDR(ptr) (DWORD)(((UINT_PTR) (ptr)) >> 32), (DWORD)(((UINT_PTR) (ptr)) & 0xffffffff) +#else // HOST_64BIT #define INVALID_POINTER_CC 0xcccccccc #define INVALID_POINTER_CD 0xcdcdcdcd #define FMT_ADDR " %08x " #define LFMT_ADDR W(" %08x ") - #define DBG_ADDR(ptr) ((UINT_PTR)(ptr)) -#endif // _WIN64 + #define DBG_ADDR(ptr) (DWORD)((UINT_PTR)(ptr)) +#endif // HOST_64BIT -#ifdef _TARGET_ARM_ +#ifdef TARGET_ARM #define ALIGN_ACCESS ((1<= val ); // check for overflow return result; @@ -189,20 +189,20 @@ inline size_t ALIGN_UP( size_t val, size_t alignment ) inline void* ALIGN_UP( void* val, size_t alignment ) { WRAPPER_NO_CONTRACT; - + return (void*) ALIGN_UP( (size_t)val, alignment ); } inline uint8_t* ALIGN_UP( uint8_t* val, size_t alignment ) { WRAPPER_NO_CONTRACT; - + return (uint8_t*) ALIGN_UP( (size_t)val, alignment ); } inline size_t ALIGN_DOWN( size_t val, size_t alignment ) { LIMITED_METHOD_CONTRACT; - + // alignment must be a power of 2 for this implementation to work (need modulo otherwise) _ASSERTE( 0 == (alignment & (alignment - 1)) ); size_t result = val & ~(alignment - 1); @@ -223,9 +223,9 @@ inline BOOL IS_ALIGNED( size_t val, size_t alignment ) { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; - + // alignment must be a power of 2 for this implementation to work (need modulo otherwise) - _ASSERTE( 0 == (alignment & (alignment - 1)) ); + _ASSERTE( 0 == (alignment & (alignment - 1)) ); return 0 == (val & (alignment - 1)); } inline BOOL IS_ALIGNED( const void* val, size_t alignment ) @@ -235,7 +235,7 @@ inline BOOL IS_ALIGNED( const void* val, size_t alignment ) } // Rounds a ULONG up to the nearest power of two number. -inline ULONG RoundUpToPower2(ULONG x) +inline ULONG RoundUpToPower2(ULONG x) { if (x == 0) return 1; @@ -284,13 +284,13 @@ inline ULONG RoundUpToPower2(ULONG x) (((pMT) == NULL) ? NULL : (pMT)->GetClass()->GetDebugClassName()) #define DBG_CLASS_NAME_MT(pMT) \ - (DBG_GET_CLASS_NAME(pMT) == NULL) ? "" : DBG_GET_CLASS_NAME(pMT) + (DBG_GET_CLASS_NAME(pMT) == NULL) ? "" : DBG_GET_CLASS_NAME(pMT) #define DBG_GET_MT_FROM_OBJ(obj) \ - (MethodTable*)((size_t)((Object*) (obj))->GetGCSafeMethodTable()) + (MethodTable*)((size_t)((Object*) (obj))->GetGCSafeMethodTable()) #define DBG_CLASS_NAME_OBJ(obj) \ - ((obj) == NULL) ? "null" : DBG_CLASS_NAME_MT(DBG_GET_MT_FROM_OBJ(obj)) + ((obj) == NULL) ? "null" : DBG_CLASS_NAME_MT(DBG_GET_MT_FROM_OBJ(obj)) #define DBG_CLASS_NAME_IPTR2(obj,iptr) \ ((iptr) != 0) ? "" : DBG_CLASS_NAME_MT(DBG_GET_MT_FROM_OBJ(obj)) @@ -344,7 +344,7 @@ inline ULONG RoundUpToPower2(ULONG x) #endif -// This is temporary. LKG should provide these macros and we should then +// This is temporary. LKG should provide these macros and we should then // remove STRUNCATE and _TRUNCATE from here. /* error codes */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/stgpool.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/stgpool.h index 67d78b2..d9a84c3 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/stgpool.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/stgpool.h @@ -5,7 +5,7 @@ // StgPool.h // -// +// // Pools are used to reduce the amount of data actually required in the database. // This allows for duplicate string and binary values to be folded into one // copy shared by the rest of the database. Strings are tracked in a hash @@ -30,8 +30,6 @@ #include "memoryrange.h" #include "../md/hotdata/hotheap.h" -#include "../md/debug_metadata.h" - //***************************************************************************** // NOTE: // One limitation with the pools, we have no way to removing strings from @@ -59,24 +57,24 @@ class CorProfileData; class RIDBinarySearch : public CBinarySearch { public: - RIDBinarySearch(const UINT32 *pBase, int iCount) : CBinarySearch(pBase, iCount) + RIDBinarySearch(const UINT32 *pBase, int iCount) : CBinarySearch(pBase, iCount) { LIMITED_METHOD_CONTRACT; } // RIDBinarySearch::RIDBinarySearch - + int Compare(UINT32 const *pFirst, UINT32 const *pSecond) { LIMITED_METHOD_CONTRACT; - + if (*pFirst < *pSecond) return -1; - + if (*pFirst > *pSecond) return 1; - + return 0; } // RIDBinarySearch::Compare - + }; // class RIDBinarySearch //***************************************************************************** @@ -88,19 +86,19 @@ class StgPoolSeg { friend class VerifyLayoutsMD; public: - StgPoolSeg() : - m_pSegData((BYTE*)m_zeros), - m_pNextSeg(NULL), - m_cbSegSize(0), - m_cbSegNext(0) + StgPoolSeg() : + m_pSegData((BYTE*)m_zeros), + m_pNextSeg(NULL), + m_cbSegSize(0), + m_cbSegNext(0) {LIMITED_METHOD_CONTRACT; } - ~StgPoolSeg() + ~StgPoolSeg() { LIMITED_METHOD_CONTRACT; _ASSERTE(m_pSegData == m_zeros);_ASSERTE(m_pNextSeg == NULL); } protected: BYTE *m_pSegData; // Pointer to the data. StgPoolSeg *m_pNextSeg; // Pointer to next segment, or NULL. - // Size of the segment buffer. If this is last segment (code:m_pNextSeg is NULL), then it's the - // allocation size. If this is not the last segment, then this is shrinked to segment data size + // Size of the segment buffer. If this is last segment (code:m_pNextSeg is NULL), then it's the + // allocation size. If this is not the last segment, then this is shrinked to segment data size // (code:m_cbSegNext). ULONG m_cbSegSize; ULONG m_cbSegNext; // Offset of next available byte in segment. @@ -115,14 +113,14 @@ protected: public: const BYTE *GetSegData() const { LIMITED_METHOD_CONTRACT; return m_pSegData; } const StgPoolSeg* GetNextSeg() const { LIMITED_METHOD_CONTRACT; return m_pNextSeg; } - // Returns size of the segment. It can be bigger than the size of represented data by this segment if + // Returns size of the segment. It can be bigger than the size of represented data by this segment if // this is the last segment. ULONG GetSegSize() const { LIMITED_METHOD_CONTRACT; return m_cbSegSize; } // Returns size of represented data in this segment. ULONG GetDataSize() const { LIMITED_METHOD_CONTRACT; return m_cbSegNext; } static const BYTE m_zeros[64]; // array of zeros for "0" indices. - // The size should be at least maximum of all MD table record sizes + // The size should be at least maximum of all MD table record sizes // (MD\Runtime\MDColumnDescriptors.cpp) which is currently 28 B. }; // class StgPoolSeg @@ -138,7 +136,7 @@ namespace MetaData // // StgPoolReadOnly // -// +// //***************************************************************************** // This is the read only StgPool class //***************************************************************************** @@ -156,11 +154,11 @@ public: ~StgPoolReadOnly(); - + //***************************************************************************** // Init the pool from existing data. //***************************************************************************** - __checkReturn + __checkReturn HRESULT InitOnMemReadOnly( // Return code. void *pData, // Predefined data. ULONG iSize); // Size of data. @@ -192,7 +190,7 @@ public: //***************************************************************************** virtual int IsValidCookie(UINT32 nCookie) { WRAPPER_NO_CONTRACT; return (IsValidOffset(nCookie)); } - + #ifdef _PREFAST_ #pragma warning(push) @@ -203,22 +201,22 @@ public: // Return a pointer to a null terminated string given an offset previously // handed out by AddString or FindString. //***************************************************************************** - __checkReturn + __checkReturn inline HRESULT GetString( - UINT32 nIndex, + UINT32 nIndex, __deref_out LPCSTR *pszString) { HRESULT hr; - - // Size of the data in the heap will be ignored, because we have verified during creation of the string - // heap (code:Initialize) and when adding new strings (e.g. code:AddString, - // code:AddTemporaryStringBuffer), that the heap is null-terminated, therefore we don't have to check it + + // Size of the data in the heap will be ignored, because we have verified during creation of the string + // heap (code:Initialize) and when adding new strings (e.g. code:AddString, + // code:AddTemporaryStringBuffer), that the heap is null-terminated, therefore we don't have to check it // for each string in the heap MetaData::DataBlob stringData; - + // Get data from the heap (clears stringData on error) IfFailGo(GetData( - nIndex, + nIndex, &stringData)); _ASSERTE(hr == S_OK); // Raw data are always at least 1 byte long, otherwise it would be invalid offset and hr != S_OK @@ -226,12 +224,12 @@ public: // Fills output string *pszString = reinterpret_cast(stringData.GetDataPointer()); //_ASSERTE(stringData.GetSize() > strlen(*pszString)); - + return hr; ErrExit: // Clears output string on error *pszString = NULL; - + return hr; } @@ -239,22 +237,22 @@ public: // Return a pointer to a null terminated string given an offset previously // handed out by AddString or FindString. Only valid for use if the Storage pool is actuall ReadOnly, and not derived //***************************************************************************** - __checkReturn + __checkReturn inline HRESULT GetStringReadOnly( - UINT32 nIndex, + UINT32 nIndex, __deref_out LPCSTR *pszString) { HRESULT hr; - - // Size of the data in the heap will be ignored, because we have verified during creation of the string - // heap (code:Initialize) and when adding new strings (e.g. code:AddString, - // code:AddTemporaryStringBuffer), that the heap is null-terminated, therefore we don't have to check it + + // Size of the data in the heap will be ignored, because we have verified during creation of the string + // heap (code:Initialize) and when adding new strings (e.g. code:AddString, + // code:AddTemporaryStringBuffer), that the heap is null-terminated, therefore we don't have to check it // for each string in the heap MetaData::DataBlob stringData; - + // Get data from the heap (clears stringData on error) IfFailGo(GetDataReadOnly( - nIndex, + nIndex, &stringData)); _ASSERTE(hr == S_OK); // Raw data are always at least 1 byte long, otherwise it would be invalid offset and hr != S_OK @@ -262,47 +260,47 @@ public: // Fills output string *pszString = reinterpret_cast(stringData.GetDataPointer()); //_ASSERTE(stringData.GetSize() > strlen(*pszString)); - + return hr; ErrExit: // Clears output string on error *pszString = NULL; - + return hr; } #ifdef _PREFAST_ #pragma warning(pop) #endif - + //***************************************************************************** // Convert a string to UNICODE into the caller's buffer. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT GetStringW( // Return code. ULONG iOffset, // Offset of string in pool. __out_ecount(cchBuffer) LPWSTR szOut, // Output buffer for string. int cchBuffer); // Size of output buffer. - + //***************************************************************************** // Copy a GUID into the caller's buffer. //***************************************************************************** - __checkReturn + __checkReturn HRESULT GetGuid( UINT32 nIndex, // 1-based index of Guid in pool. GUID UNALIGNED **ppGuid) // Output buffer for Guid. { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; - + HRESULT hr; MetaData::DataBlob heapData; - + if (nIndex == 0) { *ppGuid = (GUID *)m_zeros; return S_OK; } - + S_UINT32 nOffset = S_UINT32(nIndex - 1) * S_UINT32(sizeof(GUID)); if (nOffset.IsOverflow() || !IsValidOffset(nOffset.Value())) { @@ -320,27 +318,27 @@ public: IfFailGo(CLDB_E_INTERNALERROR); } _ASSERTE(heapData.GetSize() >= sizeof(GUID)); - + *ppGuid = (GUID UNALIGNED *)heapData.GetDataPointer(); return S_OK; - + ErrExit: *ppGuid = (GUID *)m_zeros; return hr; } // StgPoolReadOnly::GetGuid - + //***************************************************************************** // Return a pointer to a null terminated blob given an offset previously // handed out by Addblob or Findblob. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT GetBlob( UINT32 nOffset, // Offset of blob in pool. MetaData::DataBlob *pData); - + #ifdef FEATURE_PREJIT // Initialize hot data structures. - // Method can be called multiple time, e.g. to disable usage of hot data structures in certain scenarios + // Method can be called multiple time, e.g. to disable usage of hot data structures in certain scenarios // (see code:CMiniMd::DisableHotDataUsage). void InitHotData(MetaData::HotHeap hotHeap) { @@ -361,17 +359,17 @@ protected: //***************************************************************************** virtual int IsValidOffset(UINT32 nOffset) {LIMITED_METHOD_CONTRACT; return (nOffset == 0) || ((m_pSegData != m_zeros) && (nOffset < m_cbSegSize)); } - + //***************************************************************************** // Get a pointer to an offset within the heap. Inline for base segment, // helper for extension segments. //***************************************************************************** - __checkReturn + __checkReturn FORCEINLINE HRESULT GetDataReadOnly(UINT32 nOffset, __inout MetaData::DataBlob *pData) { LIMITED_METHOD_CONTRACT; _ASSERTE(IsReadOnly()); - + // If off the end of the heap, return the 'nul' item from the beginning. if (nOffset >= m_cbSegSize) { @@ -395,38 +393,38 @@ protected: #endif //FEATURE_PREJIT #endif //!(defined(FEATURE_UTILCODE_NO_DEPENDENCIES)) - + pData->Init(m_pSegData + nOffset, m_cbSegSize - nOffset); - + METADATATRACKER_ONLY(MetaDataTracker::NoteAccess((void *)pData->GetDataPointer())); - + return S_OK; } // StgPoolReadOnly::GetDataReadOnly - + //***************************************************************************** // Get a pointer to an offset within the heap. Inline for base segment, // helper for extension segments. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT GetData(UINT32 nOffset, __inout MetaData::DataBlob *pData) { WRAPPER_NO_CONTRACT; return GetDataReadOnly(nOffset, pData); } // StgPoolReadOnly::GetData - + private: #if !defined(FEATURE_UTILCODE_NO_DEPENDENCIES) // hot pool data MetaData::HotHeap m_HotHeap; #endif //!(defined(FEATURE_UTILCODE_NO_DEPENDENCIES)) - + }; // class StgPoolReadOnly // // // StgBlobPoolReadOnly // -// +// //***************************************************************************** // This is the read only StgBlobPool class //***************************************************************************** @@ -436,7 +434,7 @@ public: //***************************************************************************** // Return a pointer to a null terminated blob given an offset //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT GetBlob( UINT32 nOffset, // Offset of blob in pool. MetaData::DataBlob *pData); @@ -450,7 +448,7 @@ protected: { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; - + MetaData::DataBlob data; return (StgBlobPoolReadOnly::GetBlob(nOffset, &data) == S_OK); } @@ -493,7 +491,7 @@ protected: HRESULT Align(UINT32 nValue, UINT32 *pnAlignedValue) const { LIMITED_METHOD_CONTRACT; - + *pnAlignedValue = (nValue + m_nVariableAlignmentMask) & ~m_nVariableAlignmentMask; if (*pnAlignedValue < nValue) { @@ -501,12 +499,12 @@ protected: } return S_OK; } - + public: //***************************************************************************** // Init the pool for use. This is called for the create empty case. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT InitNew( // Return code. ULONG cbSize=0, // Estimated size. ULONG cItems=0); // Estimated item count. @@ -514,7 +512,7 @@ public: //***************************************************************************** // Init the pool from existing data. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT InitOnMem( // Return code. void *pData, // Predefined data. ULONG iSize, // Size of data. @@ -523,7 +521,7 @@ public: //***************************************************************************** // Called when the pool must stop accessing memory passed to InitOnMem(). //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT TakeOwnershipOfInitMem(); //***************************************************************************** @@ -534,13 +532,13 @@ public: //***************************************************************************** // Called to copy the pool to writable memory, reset the r/o bit. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT ConvertToRW(); //***************************************************************************** // Turn hashing off or on. Implemented as required in subclass. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT SetHash(int bHash); //***************************************************************************** @@ -553,7 +551,7 @@ public: //***************************************************************************** // Add a segment to the chain of segments. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT AddSegment( // S_OK or error. const void *pData, // The data. ULONG cbData, // Size of the data. @@ -569,17 +567,17 @@ public: // PersistToStream were the next call, the amount of bytes written to pIStream // has to be same as the return value from this function. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT GetSaveSize( UINT32 *pcbSaveSize) const { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; - + _ASSERTE(pcbSaveSize != NULL); // Size is offset of last seg + size of last seg. UINT32 cbSize = m_pCurSeg->m_cbSegNext + m_cbCurSegOffset; - + if (FAILED(Align(cbSize, pcbSaveSize))) { *pcbSaveSize = 0; @@ -588,24 +586,24 @@ public: } return S_OK; } - + //***************************************************************************** // Return the size in bytes of the edits contained in the persistent version of this pool. //***************************************************************************** - __checkReturn + __checkReturn HRESULT GetEditSaveSize( UINT32 *pcbSaveSize) const // Return save size of this pool. { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; - + _ASSERTE(pcbSaveSize != NULL); UINT32 cbSize = 0; - + if (HaveEdits()) { // Size is offset of last seg + size of last seg. - + // An offset of zero in the pool will give us a zero length blob. The first // "real" user string is at offset 1. Wherever this delta gets applied, it will // already have this zero length blob. Let's make sure we don't sent it another one. @@ -617,13 +615,13 @@ public: _ASSERTE(*(debug_data.GetDataPointer()) == 0); #endif //_DEBUG UINT32 nOffsetOfEdit = GetOffsetOfEdit(); - + if (nOffsetOfEdit == 0) - nOffsetOfEdit = 1; - + nOffsetOfEdit = 1; + cbSize = m_pCurSeg->m_cbSegNext + m_cbCurSegOffset - nOffsetOfEdit; } - + if (FAILED(Align(cbSize, pcbSaveSize))) { *pcbSaveSize = 0; @@ -632,12 +630,12 @@ public: } return S_OK; } // StgPool::GetEditSaveSize - + //***************************************************************************** // The entire pool is written to the given stream. The stream is aligned // to a 4 byte boundary. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT PersistToStream( // Return code. IStream *pIStream) // The stream to write to. DAC_UNEXPECTED(); @@ -645,7 +643,7 @@ public: //***************************************************************************** // A portion of the pool is written to the stream. Must not be optimized. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT PersistPartialToStream( // Return code. IStream *pIStream, // The stream to write to. ULONG iOffset); // Starting byte. @@ -689,7 +687,7 @@ public: // Get a pointer to an offset within the heap. Inline for base segment, // helper for extension segments. //***************************************************************************** - __checkReturn + __checkReturn FORCEINLINE HRESULT GetData(UINT32 nOffset, MetaData::DataBlob *pData) { WRAPPER_NO_CONTRACT; @@ -703,43 +701,43 @@ public: return GetData_i(nOffset, pData); } } // StgPool::GetData - + // Copies data from pSourcePool starting at index nStartSourceIndex. - __checkReturn + __checkReturn HRESULT CopyPool( - UINT32 nStartSourceIndex, + UINT32 nStartSourceIndex, const StgPool *pSourcePool); - + //***************************************************************************** // Copies data from the pool into a buffer. It will correctly walk the different // segments for the copy //***************************************************************************** private: - __checkReturn + __checkReturn HRESULT CopyData( - UINT32 nOffset, - BYTE *pBuffer, - UINT32 cbBuffer, + UINT32 nOffset, + BYTE *pBuffer, + UINT32 cbBuffer, UINT32 *pcbWritten) const; - + public: //***************************************************************************** -// Helpers for dump utilities. +// Helpers for dump utilities. //***************************************************************************** UINT32 GetRawSize() const { LIMITED_METHOD_CONTRACT; - + // Size is offset of last seg + size of last seg. return m_pCurSeg->m_cbSegNext + m_cbCurSegOffset; } - + BOOL HaveEdits() const {LIMITED_METHOD_CONTRACT; return m_fValidOffsetOfEdit;} UINT32 GetOffsetOfEdit() const {LIMITED_METHOD_CONTRACT; return m_cbStartOffsetOfEdit;} void ResetOffsetOfEdit() {LIMITED_METHOD_CONTRACT; m_fValidOffsetOfEdit=FALSE;} - + protected: - + //***************************************************************************** // Check whether a given offset is valid in the pool. //***************************************************************************** @@ -749,9 +747,9 @@ protected: // Following virtual because a) this header included outside the project, and // non-virtual function call (in non-expanded inline function!!) generates // an external def, which causes linkage errors. - __checkReturn + __checkReturn virtual HRESULT GetData_i(UINT32 nOffset, MetaData::DataBlob *pData); - + // Get pointer to next location to which to write. BYTE *GetNextLocation() {LIMITED_METHOD_CONTRACT; return (m_pCurSeg->m_pSegData + m_pCurSeg->m_cbSegNext); } @@ -780,7 +778,7 @@ protected: m_pCurSeg->m_cbSegNext += cb; }// SegAllocate - + ULONG m_ulGrowInc; // How many bytes at a time. StgPoolSeg *m_pCurSeg; // Current seg for append -- end of chain. @@ -828,7 +826,7 @@ public: //***************************************************************************** // Create a new, empty string pool. //***************************************************************************** - __checkReturn + __checkReturn HRESULT InitNew( // Return code. ULONG cbSize=0, // Estimated size. ULONG cItems=0); // Estimated item count. @@ -838,7 +836,7 @@ public: // (so that it may be updated), then a new hash table is generated which can // be used to elminate duplicates with new strings. //***************************************************************************** - __checkReturn + __checkReturn HRESULT InitOnMem( // Return code. void *pData, // Predefined data. ULONG iSize, // Size of data. @@ -853,32 +851,32 @@ public: // Turn hashing off or on. If you turn hashing on, then any existing data is // thrown away and all data is rehashed during this call. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT SetHash(int bHash); //***************************************************************************** // The string will be added to the pool. The offset of the string in the pool // is returned in *piOffset. If the string is already in the pool, then the // offset will be to the existing copy of the string. -// +// // The first version essentially adds a zero-terminated sequence of bytes // to the pool. MBCS pairs will not be converted to the appropriate UTF8 // sequence. The second version converts from Unicode. //***************************************************************************** - __checkReturn + __checkReturn HRESULT AddString( LPCSTR szString, // The string to add to pool. UINT32 *pnOffset); // Return offset of string here. - - __checkReturn + + __checkReturn HRESULT AddStringW( LPCWSTR szString, // The string to add to pool. UINT32 *pnOffset); // Return offset of string here. - + //***************************************************************************** // Look for the string and return its offset if found. //***************************************************************************** - __checkReturn + __checkReturn HRESULT FindString( // S_OK, S_FALSE. LPCSTR szString, // The string to find in pool. ULONG *piOffset) // Return offset of string here. @@ -910,7 +908,7 @@ public: { WRAPPER_NO_CONTRACT; - return (GetNextOffset() <= 1); + return (GetNextOffset() <= 1); } //***************************************************************************** @@ -918,19 +916,19 @@ public: // PersistToStream were the next call, the amount of bytes written to pIStream // has to be same as the return value from this function. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT GetSaveSize( UINT32 *pcbSaveSize) const { LIMITED_METHOD_CONTRACT; - + _ASSERTE(pcbSaveSize != NULL); - + // Size is offset of last seg + size of last seg. S_UINT32 cbSize = S_UINT32(m_pCurSeg->m_cbSegNext + m_cbCurSegOffset); - + cbSize.AlignUp(4); - + if (cbSize.IsOverflow()) { *pcbSaveSize = 0; @@ -950,9 +948,9 @@ public: LIMITED_METHOD_CONTRACT; return ULONG( strlen( reinterpret_cast< LPCSTR >( data ) ) + 1 ); // using strlen since the string is UTF8 } - + private: - __checkReturn + __checkReturn HRESULT RehashStrings(); private: @@ -985,7 +983,7 @@ public: //***************************************************************************** // Init the pool for use. This is called for the create empty case. //***************************************************************************** - __checkReturn + __checkReturn HRESULT InitNew( // Return code. ULONG cbSize=0, // Estimated size. ULONG cItems=0); // Estimated item count. @@ -995,7 +993,7 @@ public: // (so that it may be updated), then a new hash table is generated which can // be used to elminate duplicates with new Guids. //***************************************************************************** - __checkReturn + __checkReturn HRESULT InitOnMem( // Return code. void *pData, // Predefined data. ULONG iSize, // Size of data. @@ -1009,7 +1007,7 @@ public: //***************************************************************************** // Add a segment to the chain of segments. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT AddSegment( // S_OK or error. const void *pData, // The data. ULONG cbData, // Size of the data. @@ -1019,7 +1017,7 @@ public: // Turn hashing off or on. If you turn hashing on, then any existing data is // thrown away and all data is rehashed during this call. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT SetHash(int bHash); //***************************************************************************** @@ -1027,11 +1025,11 @@ public: // is returned in *piIndex. If the Guid is already in the pool, then the // index will be to the existing copy of the Guid. //***************************************************************************** - __checkReturn + __checkReturn HRESULT AddGuid( const GUID *pGuid, // The Guid to add to pool. UINT32 *pnIndex); // Return index of Guid here. - + //***************************************************************************** // Get the size of the GUID obtained from the pool. // Needed for generic persisting of data blocks. @@ -1055,15 +1053,15 @@ public: //***************************************************************************** // Indicate if heap is empty. This has to be based on the size of the data // we are keeping. If you open in r/o mode on memory, there is no hash -// table. +// table. //***************************************************************************** virtual int IsEmpty() // true if empty. { WRAPPER_NO_CONTRACT; - + return (GetNextOffset() == 0); } - + //***************************************************************************** // Is the index valid for the GUID? //***************************************************************************** @@ -1081,30 +1079,31 @@ public: // PersistToStream were the next call, the amount of bytes written to pIStream // has to be same as the return value from this function. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT GetSaveSize( UINT32 *pcbSaveSize) const { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; - + _ASSERTE(pcbSaveSize != NULL); - + // Size is offset of last seg + size of last seg. *pcbSaveSize = m_pCurSeg->m_cbSegNext + m_cbCurSegOffset; - + // Should be aligned. _ASSERTE(*pcbSaveSize == ALIGN4BYTE(*pcbSaveSize)); return S_OK; } - + private: - - __checkReturn + + __checkReturn HRESULT RehashGuids(); private: + DAC_ALIGNAS(StgPool) // Align first member to alignment of base class CGuidPoolHash m_Hash; // Hash table for lookups. int m_bHash; // true to keep hash table. }; // class StgGuidPool @@ -1129,7 +1128,7 @@ class StgBlobPool : public StgPool using StgPool::InitNew; using StgPool::InitOnMem; - + public: StgBlobPool(ULONG ulGrowInc=DFT_BLOB_HEAP_SIZE) : StgPool(ulGrowInc), @@ -1139,7 +1138,7 @@ public: //***************************************************************************** // Init the pool for use. This is called for the create empty case. //***************************************************************************** - __checkReturn + __checkReturn HRESULT InitNew( // Return code. ULONG cbSize=0, // Estimated size. ULONG cItems=0, // Estimated item count. @@ -1150,7 +1149,7 @@ public: // If there is existing data and bCopyData is true, then the data is rehashed // to eliminate dupes in future adds. //***************************************************************************** - __checkReturn + __checkReturn HRESULT InitOnMem( // Return code. void *pData, // Predefined data. ULONG iSize, // Size of data. @@ -1166,30 +1165,30 @@ public: // is returned in *piOffset. If the blob is already in the pool, then the // offset will be to the existing copy of the blob. //***************************************************************************** - __checkReturn + __checkReturn HRESULT AddBlob( - const MetaData::DataBlob *pData, + const MetaData::DataBlob *pData, UINT32 *pnOffset); - + //***************************************************************************** // Return a pointer to a null terminated blob given an offset previously // handed out by Addblob or Findblob. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT GetBlob( UINT32 nOffset, // Offset of blob in pool. MetaData::DataBlob *pData); - - __checkReturn + + __checkReturn HRESULT GetBlobWithSizePrefix( UINT32 nOffset, // Offset of blob in pool. MetaData::DataBlob *pData); - + //***************************************************************************** // Turn hashing off or on. If you turn hashing on, then any existing data is // thrown away and all data is rehashed during this call. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT SetHash(int bHash); //***************************************************************************** @@ -1199,7 +1198,7 @@ public: virtual ULONG GetSizeOfData( void const * data ) { WRAPPER_NO_CONTRACT; - + void const * blobdata = 0; ULONG blobsize = CPackedLen::GetLength( data, & blobdata ); // the size is encoded at the beginning of the block return blobsize + static_cast< ULONG >( reinterpret_cast< BYTE const * >( blobdata ) - reinterpret_cast< BYTE const * >( data ) ); @@ -1221,7 +1220,7 @@ public: STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; - return (GetNextOffset() <= 1); + return (GetNextOffset() <= 1); } //***************************************************************************** @@ -1229,16 +1228,16 @@ public: // PersistToStream were the next call, the amount of bytes written to pIStream // has to be same as the return value from this function. //***************************************************************************** - __checkReturn + __checkReturn virtual HRESULT GetSaveSize( UINT32 *pcbSaveSize) const { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; - + return StgPool::GetSaveSize(pcbSaveSize); } - + protected: //***************************************************************************** @@ -1248,15 +1247,16 @@ protected: { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; - + MetaData::DataBlob data; return (StgBlobPool::GetBlob(nOffset, &data) == S_OK); } - + private: - __checkReturn + __checkReturn HRESULT RehashBlobs(); + DAC_ALIGNAS(StgPool) // Align first member to alignment of base class CBlobPoolHash m_Hash; // Hash table for lookups. }; // class StgBlobPool @@ -1304,19 +1304,19 @@ public: ULONG STDMETHODCALLTYPE Release(); - __checkReturn + __checkReturn HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, PVOID *ppOut); - __checkReturn + __checkReturn HRESULT STDMETHODCALLTYPE Read(void *pv, ULONG cb, ULONG *pcbRead); - __checkReturn + __checkReturn HRESULT STDMETHODCALLTYPE Write(const void *pv, ULONG cb, ULONG *pcbWritten); - __checkReturn + __checkReturn HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition); - __checkReturn + __checkReturn HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize) { STATIC_CONTRACT_NOTHROW; @@ -1325,14 +1325,14 @@ public: return (BadError(E_NOTIMPL)); } - __checkReturn + __checkReturn HRESULT STDMETHODCALLTYPE CopyTo( IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten); - __checkReturn + __checkReturn HRESULT STDMETHODCALLTYPE Commit( DWORD grfCommitFlags) { @@ -1342,7 +1342,7 @@ public: return (BadError(E_NOTIMPL)); } - __checkReturn + __checkReturn HRESULT STDMETHODCALLTYPE Revert() { STATIC_CONTRACT_NOTHROW; @@ -1351,7 +1351,7 @@ public: return (BadError(E_NOTIMPL)); } - __checkReturn + __checkReturn HRESULT STDMETHODCALLTYPE LockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, @@ -1363,7 +1363,7 @@ public: return (BadError(E_NOTIMPL)); } - __checkReturn + __checkReturn HRESULT STDMETHODCALLTYPE UnlockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, @@ -1375,7 +1375,7 @@ public: return (BadError(E_NOTIMPL)); } - __checkReturn + __checkReturn HRESULT STDMETHODCALLTYPE Stat( STATSTG *pstatstg, DWORD grfStatFlag) @@ -1387,7 +1387,7 @@ public: return (S_OK); } - __checkReturn + __checkReturn HRESULT STDMETHODCALLTYPE Clone( IStream **ppstm) { @@ -1397,15 +1397,15 @@ public: return (BadError(E_NOTIMPL)); } - __checkReturn + __checkReturn static HRESULT CreateStreamOnMemory( // Return code. void *pMem, // Memory to create stream on. ULONG cbSize, // Size of data. IStream **ppIStream, // Return stream object here. BOOL fDeleteMemoryOnRelease = FALSE - ); + ); - __checkReturn + __checkReturn static HRESULT CreateStreamOnMemoryCopy( void *pMem, ULONG cbSize, @@ -1442,14 +1442,14 @@ public: // increased memory usage. CGrowableStream(float multiplicativeGrowthRate = 2.0, DWORD additiveGrowthRate = 4096); -#ifndef DACCESS_COMPILE +#ifndef DACCESS_COMPILE virtual ~CGrowableStream(); #endif // Expose the total raw buffer. // This can be used by DAC to get the raw contents. // This becomes potentiallyinvalid on the next call on the class, because the underlying storage can be - // reallocated. + // reallocated. MemoryRange GetRawBuffer() const { SUPPORTS_DAC; @@ -1461,14 +1461,14 @@ private: // Raw pointer to buffer. This may change as the buffer grows and gets reallocated. PTR_BYTE m_swBuffer; - // Total size of the buffer in bytes. + // Total size of the buffer in bytes. DWORD m_dwBufferSize; // Current index in the buffer. This can be moved around by Seek. DWORD m_dwBufferIndex; // Logical length of the stream - DWORD m_dwStreamLength; + DWORD m_dwStreamLength; // Reference count LONG m_cRef; @@ -1484,7 +1484,7 @@ private: // IStream methods public: -#ifndef DACCESS_COMPILE +#ifndef DACCESS_COMPILE ULONG STDMETHODCALLTYPE AddRef() { LIMITED_METHOD_CONTRACT; return InterlockedIncrement(&m_cRef); @@ -1493,7 +1493,7 @@ public: ULONG STDMETHODCALLTYPE Release(); - __checkReturn + __checkReturn HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, PVOID *ppOut); STDMETHOD(Read)( diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/stgpooli.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/stgpooli.h index a29fa01..db4c049 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/stgpooli.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/stgpooli.h @@ -3,9 +3,9 @@ // See the LICENSE file in the project root for more information. //***************************************************************************** // StgPooli.h -// +// -// +// // This is helper code for the string and blob pools. It is here because it is // secondary to the pooling interface and reduces clutter in the main file. // @@ -136,27 +136,27 @@ class CStringPoolHash : public CChainedHash { friend class VerifyLayoutsMD; public: - CStringPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) + CStringPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) { LIMITED_METHOD_CONTRACT; } virtual bool InUse(STRINGHASH *pItem) - { + { LIMITED_METHOD_CONTRACT; - return (pItem->iOffset != 0xffffffff); + return (pItem->iOffset != 0xffffffff); } virtual void SetFree(STRINGHASH *pItem) - { + { LIMITED_METHOD_CONTRACT; - pItem->iOffset = 0xffffffff; + pItem->iOffset = 0xffffffff; } virtual ULONG Hash(const void *pData) - { + { WRAPPER_NO_CONTRACT; - return (HashStringA(reinterpret_cast(pData))); + return (HashStringA(reinterpret_cast(pData))); } virtual int Cmp(const void *pData, void *pItem); @@ -176,21 +176,21 @@ class CBlobPoolHash : public CChainedHash { friend class VerifyLayoutsMD; public: - CBlobPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) + CBlobPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) { LIMITED_METHOD_CONTRACT; } virtual bool InUse(BLOBHASH *pItem) - { + { LIMITED_METHOD_CONTRACT; - return (pItem->iOffset != 0xffffffff); + return (pItem->iOffset != 0xffffffff); } virtual void SetFree(BLOBHASH *pItem) - { + { LIMITED_METHOD_CONTRACT; - pItem->iOffset = 0xffffffff; + pItem->iOffset = 0xffffffff; } virtual ULONG Hash(const void *pData) @@ -223,27 +223,27 @@ class CGuidPoolHash : public CChainedHash { friend class VerifyLayoutsMD; public: - CGuidPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) - { - LIMITED_METHOD_CONTRACT; + CGuidPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) + { + LIMITED_METHOD_CONTRACT; } virtual bool InUse(GUIDHASH *pItem) { - LIMITED_METHOD_CONTRACT; - return (pItem->iIndex != 0xffffffff); + LIMITED_METHOD_CONTRACT; + return (pItem->iIndex != 0xffffffff); } virtual void SetFree(GUIDHASH *pItem) { - LIMITED_METHOD_CONTRACT; - pItem->iIndex = 0xffffffff; + LIMITED_METHOD_CONTRACT; + pItem->iIndex = 0xffffffff; } virtual ULONG Hash(const void *pData) - { + { WRAPPER_NO_CONTRACT; - return (HashBytes(reinterpret_cast(pData), sizeof(GUID))); + return (HashBytes(reinterpret_cast(pData), sizeof(GUID))); } virtual int Cmp(const void *pData, void *pItem); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/stresslog.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/stresslog.h index 8e509e5..244cf74 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/stresslog.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/stresslog.h @@ -7,18 +7,18 @@ /* StressLog.h */ /*************************************************************************************/ -/* StressLog is a binary, memory based circular queue of logging messages. It is +/* StressLog is a binary, memory based circular queue of logging messages. It is intended to be used in retail builds during stress runs (activated - by registry key), so to help find bugs that only turn up during stress runs. + by registry key), so to help find bugs that only turn up during stress runs. It is meant to have very low overhead and can not cause deadlocks, etc. It is however thread safe */ -/* The log has a very simple structure, and it meant to be dumped from a NTSD +/* The log has a very simple structure, and it meant to be dumped from a NTSD extention (eg. strike). There is no memory allocation system calls etc to purtub things */ // ****************************************************************************** -// WARNING!!!: These classes are used by SOS in the diagnostics repo. Values should +// WARNING!!!: These classes are used by SOS in the diagnostics repo. Values should // added or removed in a backwards and forwards compatible way. // See: https://github.com/dotnet/diagnostics/blob/master/src/inc/stresslog.h // Parser: https://github.com/dotnet/diagnostics/blob/master/src/SOS/Strike/stressLogDump.cpp @@ -26,7 +26,7 @@ /*************************************************************************************/ -#ifndef StressLog_h +#ifndef StressLog_h #define StressLog_h 1 #include "log.h" @@ -47,7 +47,7 @@ #endif /* The STRESS_LOG* macros work like printf. In fact the use printf in their implementation - so all printf format specifications work. In addition the Stress log dumper knows + so all printf format specifications work. In addition the Stress log dumper knows about certain suffixes for the %p format specification (normally used to print a pointer) %pM // The pointer is a MethodDesc @@ -56,16 +56,16 @@ %pK // The pointer is a code address (used for stack track) */ -/* STRESS_LOG_VA was added to allow sendign GC trace output to the stress log. msg must be enclosed - in ()'s and contain a format string followed by 0 - 4 arguments. The arguments must be numbers or - string literals. LogMsgOL is overloaded so that all of the possible sets of parameters are covered. - This was done becasue GC Trace uses dprintf which dosen't contain info on how many arguments are +/* STRESS_LOG_VA was added to allow sendign GC trace output to the stress log. msg must be enclosed + in ()'s and contain a format string followed by 0 - 4 arguments. The arguments must be numbers or + string literals. LogMsgOL is overloaded so that all of the possible sets of parameters are covered. + This was done becasue GC Trace uses dprintf which dosen't contain info on how many arguments are getting passed in and using va_args would require parsing the format string during the GC */ #define STRESS_LOG_VA(msg) do { \ if (StressLog::LogOn(LF_GC, LL_ALWAYS)) \ StressLog::LogMsgOL msg; \ - LogSpewAlways msg; \ + LOGALWAYS(msg); \ } while(0) #define STRESS_LOG0(facility, level, msg) do { \ @@ -250,8 +250,8 @@ StressLog::LogCallStack ("GC"); \ } \ } while(0) - -#else //!_DEBUG + +#else //!_DEBUG #define STRESS_LOG_OOM_STACK(size) #define STRESS_LOG_GC_STACK #endif //_DEBUG @@ -260,13 +260,13 @@ class ThreadStressLog; /*************************************************************************************/ /* a log is a circular queue of messages */ - + class StressLog { public: - static void Initialize(unsigned facilities, unsigned level, unsigned maxBytesPerThread, + static void Initialize(unsigned facilities, unsigned level, unsigned maxBytesPerThread, unsigned maxBytesTotal, HMODULE hMod); static void Terminate(BOOL fProcessDetach=FALSE); - static void ThreadDetach(ThreadStressLog *msgs); // call at DllMain THREAD_DETACH if you want to recycle thread logs + static void ThreadDetach(); // call at DllMain THREAD_DETACH if you want to recycle thread logs static int NewChunk () { return InterlockedIncrement (&theLog.totalChunk); @@ -276,7 +276,7 @@ public: return InterlockedDecrement (&theLog.totalChunk); } - //the result is not 100% accurate. If multiple threads call this funciton at the same time, + //the result is not 100% accurate. If multiple threads call this funciton at the same time, //we could allow the total size be bigger than required. But the memory won't grow forever //and this is not critical so we don't try to fix the race static BOOL AllowNewChunk (LONG numChunksInCurThread); @@ -287,9 +287,9 @@ public: static BOOL ReserveStressLogChunks (unsigned chunksToReserve); // used by out of process debugger to dump the stress log to 'fileName' - // IDebugDataSpaces is the NTSD execution callback for getting process memory. + // IDebugDataSpaces is the NTSD execution callback for getting process memory. // This function is defined in the tools\strike\stressLogDump.cpp file - static HRESULT Dump(ULONG64 logAddr, const char* fileName, struct IDebugDataSpaces* memCallBack); + static HRESULT Dump(ULONG64 logAddr, const char* fileName, struct IDebugDataSpaces* memCallBack); static BOOL StressLogOn(unsigned facility, unsigned level); static BOOL ETWLogOn(unsigned facility, unsigned level); @@ -302,7 +302,7 @@ public: unsigned MaxSizeTotal; //maximum memory allowed for stress log Volatile totalChunk; //current number of total chunks allocated Volatile logs; // the list of logs for every thread. - Volatile TLSslot; // Each thread gets a log this is used to fetch each threads log + unsigned padding; // Preserve the layout for SOS Volatile deadCount; // count of dead threads in the log CRITSEC_COOKIE lock; // lock unsigned __int64 tickFrequency; // number of ticks per second @@ -310,6 +310,8 @@ public: FILETIME startTime; // time the application started SIZE_T moduleOffset; // Used to compute format strings. + static thread_local ThreadStressLog* t_pCurrentThreadLog; + // private: static void Enter(CRITSEC_COOKIE dummy = NULL); static void Leave(CRITSEC_COOKIE dummy = NULL); @@ -334,50 +336,50 @@ public: template < typename T1 > static void LogMsgOL(const char* format, T1 data1) { - static_assert_no_msg(sizeof(T1) <= sizeof(void*)); + static_assert_no_msg(sizeof(T1) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 1, format, (void*)(size_t)data1); } template < typename T1, typename T2 > static void LogMsgOL(const char* format, T1 data1, T2 data2) { - static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*)); + static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 2, format, (void*)(size_t)data1, (void*)(size_t)data2); } template < typename T1, typename T2, typename T3 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3) - { - static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*)); + { + static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 3, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3); } template < typename T1, typename T2, typename T3, typename T4 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4) - { - static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*)); + { + static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 4, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4); } template < typename T1, typename T2, typename T3, typename T4, typename T5 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5) - { - static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*)); + { + static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 5, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5); } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6) - { - static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*)); + { + static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 6, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5, (void*)(size_t)data6); } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6, T7 data7) - { - static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*)); - LogMsg(LL_ALWAYS, LF_GC, 7, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5, (void*)(size_t)data6, (void*)(size_t)data7); + { + static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*)); + LogMsg(LL_ALWAYS, LF_GC, 7, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5, (void*)(size_t)data6, (void*)(size_t)data7); } #ifdef _MSC_VER @@ -423,7 +425,7 @@ inline BOOL StressLog::LogOn(unsigned facility, unsigned level) #endif // The order of fields is important. Keep the prefix length as the first field. -// And make sure the timeStamp field is naturally alligned, so we don't waste +// And make sure the timeStamp field is naturally alligned, so we don't waste // space on 32-bit platforms struct StressMsg { union { @@ -439,17 +441,17 @@ struct StressMsg { static const size_t maxArgCnt = 7; static const size_t maxOffset = 0x20000000; - static size_t maxMsgSize () + static size_t maxMsgSize () { return sizeof(StressMsg) + maxArgCnt*sizeof(void*); } friend class ThreadStressLog; friend class StressLog; }; -#ifdef _WIN64 +#ifdef HOST_64BIT #define STRESSLOG_CHUNK_SIZE (32 * 1024) -#else //_WIN64 +#else //HOST_64BIT #define STRESSLOG_CHUNK_SIZE (16 * 1024) -#endif //_WIN64 +#endif //HOST_64BIT #define GC_STRESSLOG_MULTIPLY 5 // a chunk of memory for stress log @@ -459,33 +461,50 @@ struct StressLogChunk StressLogChunk * next; char buf[STRESSLOG_CHUNK_SIZE]; DWORD dwSig1; - DWORD dwSig2; + DWORD dwSig2; #if !defined(STRESS_LOG_READONLY) - static HANDLE s_LogChunkHeap; +#ifdef HOST_WINDOWS + static HANDLE s_LogChunkHeap; - void * operator new (size_t) throw() + void * operator new (size_t size) throw() { if (IsInCantAllocStressLogRegion ()) { return NULL; } - + _ASSERTE (s_LogChunkHeap != NULL); //no need to zero memory because we could handle garbage contents - return ClrHeapAlloc (s_LogChunkHeap, 0, S_SIZE_T(sizeof (StressLogChunk))); + return HeapAlloc (s_LogChunkHeap, 0, size); } void operator delete (void * chunk) { _ASSERTE (s_LogChunkHeap != NULL); - ClrHeapFree (s_LogChunkHeap, 0, chunk); + HeapFree (s_LogChunkHeap, 0, chunk); } +#else + void* operator new (size_t size) throw() + { + if (IsInCantAllocStressLogRegion()) + { + return NULL; + } + + return malloc(size); + } + + void operator delete (void* chunk) + { + free(chunk); + } +#endif #endif //!STRESS_LOG_READONLY StressLogChunk (StressLogChunk * p = NULL, StressLogChunk * n = NULL) - :prev (p), next (n), dwSig1 (0xCFCFCFCF), dwSig2 (0xCFCFCFCF) - {} + :prev (p), next (n), dwSig1 (0xCFCFCFCF), dwSig2 (0xCFCFCFCF) + {} char * StartPtr () { @@ -512,13 +531,13 @@ struct StressLogChunk // .readPtr points to the next log message to be dumped // .hasWrapped is TRUE while dumping the log, if we had wrapped // past the endPtr marker, back to startPtr -// The AdvanceRead/AdvanceWrite operations simply update the -// readPtr / curPtr fields. thecaller is responsible for reading/writing +// The AdvanceRead/AdvanceWrite operations simply update the +// readPtr / curPtr fields. thecaller is responsible for reading/writing // to the corresponding field class ThreadStressLog { ThreadStressLog* next; // we keep a linked list of these uint64_t threadId; // the id for the thread using this buffer - uint8_t isDead; // Is this thread dead + uint8_t isDead; // Is this thread dead uint8_t readHasWrapped; // set when read ptr has passed chunListTail uint8_t writeHasWrapped; // set when write ptr has passed chunListHead StressMsg* curPtr; // where packets are being put on the queue @@ -570,30 +589,30 @@ class ThreadStressLog { public: #ifndef STRESS_LOG_READONLY ThreadStressLog () - { + { chunkListHead = chunkListTail = curWriteChunk = NULL; - StressLogChunk * newChunk =new StressLogChunk; + StressLogChunk * newChunk =new StressLogChunk; //OOM or in cantalloc region if (newChunk == NULL) { return; - } + } StressLog::NewChunk (); newChunk->prev = newChunk; newChunk->next = newChunk; - + chunkListHead = chunkListTail = newChunk; next = NULL; threadId = 0; isDead = TRUE; curPtr = NULL; - readPtr = NULL; - writeHasWrapped = FALSE; + readPtr = NULL; + writeHasWrapped = FALSE; curReadChunk = NULL; curWriteChunk = NULL; - chunkListLength = 1; + chunkListLength = 1; } #endif //!STRESS_LOG_READONLY @@ -604,17 +623,17 @@ public: { return; } -#ifndef STRESS_LOG_READONLY +#ifndef STRESS_LOG_READONLY _ASSERTE (chunkListLength >= 1 && chunkListLength <= StressLog::theLog.totalChunk); -#endif //!STRESS_LOG_READONLY - StressLogChunk * chunk = chunkListHead; - +#endif //!STRESS_LOG_READONLY + StressLogChunk * chunk = chunkListHead; + do { StressLogChunk * tmp = chunk; chunk = chunk->next; delete tmp; -#ifndef STRESS_LOG_READONLY +#ifndef STRESS_LOG_READONLY StressLog::ChunkDeleted (); #endif //!STRESS_LOG_READONLY } while (chunk != chunkListHead); @@ -624,8 +643,8 @@ public: { #ifndef STRESS_LOG_READONLY //there is no need to zero buffers because we could handle garbage contents - threadId = GetCurrentThreadId (); - isDead = FALSE; + threadId = GetCurrentThreadId (); + isDead = FALSE; curWriteChunk = chunkListTail; curPtr = (StressMsg *)curWriteChunk->EndPtr (); writeHasWrapped = FALSE; @@ -635,7 +654,7 @@ public: readHasWrapped = FALSE; // the last written log, if it wrapped around may have partially overwritten // a previous record. Update curPtr to reflect the last safe beginning of a record, - // but curPtr shouldn't wrap around, otherwise it'll break our assumptions about stress + // but curPtr shouldn't wrap around, otherwise it'll break our assumptions about stress // log curPtr = (StressMsg*)((char*)curPtr - StressMsg::maxMsgSize()); if (curPtr < (StressMsg*)curWriteChunk->StartPtr()) @@ -648,21 +667,21 @@ public: AdvReadPastBoundary(); } #endif //!STRESS_LOG_READONLY - } + } BOOL IsValid () const { return chunkListHead != NULL && (!curWriteChunk || curWriteChunk->IsValid ()); } - -#ifdef STRESS_LOG_READONLY + +#ifdef STRESS_LOG_READONLY // Called while dumping. Returns true after all messages in log were dumped FORCEINLINE BOOL CompletedDump () { - return readPtr->timeStamp == 0 + return readPtr->timeStamp == 0 //if read has passed end of list but write has not passed head of list yet, we are done //if write has also wrapped, we are at the end if read pointer passed write pointer - || (readHasWrapped && + || (readHasWrapped && (!writeHasWrapped || (curReadChunk == curWriteChunk && readPtr >= curPtr))); } #endif //STRESS_LOG_READONLY @@ -678,7 +697,7 @@ public: STATIC_CONTRACT_LEAF; return "========== ENDGC %d (gen = %lu, collect_classes = %lu) ===========}\n"; } - + static const char* gcRootMsg() { STATIC_CONTRACT_LEAF; @@ -695,7 +714,7 @@ public: { STATIC_CONTRACT_LEAF; return "GC_HEAP RELOCATING Objects in heap within range [%p %p) by -0x%x bytes\n"; - } + } static const char* TaskSwitchMsg() { @@ -714,7 +733,7 @@ public: #ifdef STRESS_LOG_READONLY static size_t OffsetOfNext () {return offsetof (ThreadStressLog, next);} static size_t OffsetOfListHead () {return offsetof (ThreadStressLog, chunkListHead);} -#endif //STRESS_LOG_READONLY +#endif //STRESS_LOG_READONLY }; #ifdef STRESS_LOG_READONLY @@ -735,7 +754,7 @@ inline StressMsg* ThreadStressLog::AdvanceRead() { } // It's the factored-out slow codepath for AdvanceRead() and -// is only called by AdvanceRead(). +// is only called by AdvanceRead(). // Updates readPtr to and returns the first stress message >= startPtr inline StressMsg* ThreadStressLog::AdvReadPastBoundary() { STATIC_CONTRACT_LEAF; @@ -743,7 +762,7 @@ inline StressMsg* ThreadStressLog::AdvReadPastBoundary() { if (curReadChunk == chunkListTail) { readHasWrapped = TRUE; - //If write has not wrapped, we know the contents from list head to + //If write has not wrapped, we know the contents from list head to //cur pointer is garbage, we don't need to read them if (!writeHasWrapped) { @@ -770,7 +789,7 @@ inline StressMsg* ThreadStressLog::AdvReadPastBoundary() { // Called at runtime when writing the log (by StressLog::LogMsg()) // Updates curPtr to point to the next spot in the log where we can write // a stress message with cArgs arguments -// For convenience it returns a pointer to the empty slot where we can +// For convenience it returns a pointer to the empty slot where we can // write the next stress message. // cArgs is the number of arguments in the message to be written. inline StressMsg* ThreadStressLog::AdvanceWrite(int cArgs) { @@ -789,26 +808,26 @@ inline StressMsg* ThreadStressLog::AdvanceWrite(int cArgs) { { curPtr = p; } - + return curPtr; } // It's the factored-out slow codepath for AdvanceWrite() and -// is only called by AdvanceWrite(). +// is only called by AdvanceWrite(). // Returns the stress message flushed against endPtr // In addition it writes NULLs b/w the startPtr and curPtr inline StressMsg* ThreadStressLog::AdvWritePastBoundary(int cArgs) { STATIC_CONTRACT_WRAPPER; -#ifndef STRESS_LOG_READONLY +#ifndef STRESS_LOG_READONLY //zeroed out remaining buffer memset (curWriteChunk->StartPtr (), 0, (BYTE *)curPtr - (BYTE *)curWriteChunk->StartPtr ()); - + //if we are already at head of the list, try to grow the list if (curWriteChunk == chunkListHead) { - GrowChunkList (); + GrowChunkList (); } -#endif //!STRESS_LOG_READONLY +#endif //!STRESS_LOG_READONLY curWriteChunk = curWriteChunk->prev; #ifndef STRESS_LOG_READONLY @@ -817,7 +836,7 @@ inline StressMsg* ThreadStressLog::AdvWritePastBoundary(int cArgs) { writeHasWrapped = TRUE; } #endif //STRESS_LOG_READONLY - curPtr = (StressMsg*)((char*)curWriteChunk->EndPtr () - sizeof(StressMsg) - cArgs * sizeof(void*)); + curPtr = (StressMsg*)((char*)curWriteChunk->EndPtr () - sizeof(StressMsg) - cArgs * sizeof(void*)); return curPtr; } @@ -843,4 +862,4 @@ inline StressMsg* ThreadStressLog::AdvWritePastBoundary(int cArgs) { #define STRESS_LOG_RESERVE_MEM(numChunks) do {} while (0) #endif // STRESS_LOG -#endif // StressLog_h +#endif // StressLog_h diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/stringarraylist.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/stringarraylist.h index 10401ac..248d41e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/stringarraylist.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/stringarraylist.h @@ -17,9 +17,9 @@ class StringArrayList ArrayList m_Elements; public: DWORD GetCount() const; - SString& operator[] (DWORD idx) const; - SString& Get (DWORD idx) const; -#ifndef DACCESS_COMPILE + SString& operator[] (DWORD idx) const; + SString& Get (DWORD idx) const; +#ifndef DACCESS_COMPILE void Append(const SString& string); void AppendIfNotThere(const SString& string); #endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/stringarraylist.inl b/CoreCLRProfiler/native/coreclr_headers/src/inc/stringarraylist.inl index 73ca405..9e19636 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/stringarraylist.inl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/stringarraylist.inl @@ -8,14 +8,14 @@ inline SString& StringArrayList::operator[] (DWORD idx) const { WRAPPER_NO_CONTRACT; return Get(idx); -} +} inline SString& StringArrayList::Get (DWORD idx) const { WRAPPER_NO_CONTRACT; PTR_SString ppRet=(PTR_SString)m_Elements.Get(idx); return *ppRet; -} +} inline DWORD StringArrayList::GetCount() const { @@ -31,7 +31,7 @@ inline void StringArrayList::Append(const SString& string) THROWS; GC_NOTRIGGER; } - CONTRACTL_END; + CONTRACTL_END; NewHolder pAdd=new SString(string); pAdd->Normalize(); IfFailThrow(m_Elements.Append(pAdd)); @@ -45,7 +45,7 @@ inline void StringArrayList::AppendIfNotThere(const SString& string) THROWS; GC_NOTRIGGER; } - CONTRACTL_END; + CONTRACTL_END; for (DWORD i=0;i +#include + +// +// Holder classes for types returned from and used in strong name APIs +// + +// Holder for any memory allocated by the strong name APIs +template +void VoidStrongNameFreeBuffer(__in T *pBuffer) +{ + StrongNameFreeBuffer(reinterpret_cast(pBuffer)); +} +NEW_WRAPPER_TEMPLATE1(StrongNameBufferHolder, VoidStrongNameFreeBuffer<_TYPE>); + +#endif // !__STRONGNAME_HOLDERS_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/strongnameinternal.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/strongnameinternal.h new file mode 100644 index 0000000..a340c76 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/strongnameinternal.h @@ -0,0 +1,36 @@ +// 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. +// +// Strong name APIs which are not exposed publicly, but are built into StrongName.lib +// + +#ifndef _STRONGNAME_INTERNAL_H +#define _STRONGNAME_INTERNAL_H + +// Public key blob binary format. +typedef struct { + unsigned int SigAlgID; // (ALG_ID) signature algorithm used to create the signature + unsigned int HashAlgID; // (ALG_ID) hash algorithm used to create the signature + ULONG cbPublicKey; // length of the key in bytes + BYTE PublicKey[1]; // variable length byte array containing the key value in format output by CryptoAPI +} PublicKeyBlob; + +// Determine the number of bytes in a public key +DWORD StrongNameSizeOfPublicKey(const PublicKeyBlob &keyPublicKey); + +bool StrongNameIsValidPublicKey(__in_ecount(cbPublicKeyBlob) const BYTE *pbPublicKeyBlob, DWORD cbPublicKeyBlob); +bool StrongNameIsValidPublicKey(const PublicKeyBlob &keyPublicKey); + +// Determine if a public key is the ECMA key +bool StrongNameIsEcmaKey(__in_ecount(cbKey) const BYTE *pbKey, DWORD cbKey); +bool StrongNameIsEcmaKey(const PublicKeyBlob &keyPublicKey); + +HRESULT StrongNameTokenFromPublicKey(BYTE* pbPublicKeyBlob, // [in] public key blob + ULONG cbPublicKeyBlob, + BYTE** ppbStrongNameToken, // [out] strong name token + ULONG* pcbStrongNameToken); + +VOID StrongNameFreeBuffer(BYTE* pbMemory); + +#endif // !_STRONGNAME_INTERNAL_H diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/switches.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/switches.h index 6003460..eaf1c57 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/switches.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/switches.h @@ -15,7 +15,7 @@ #define GC_CONFIG_DRIVEN -// define this to test data safety for the DAC. See code:DataTest::TestDataSafety. +// define this to test data safety for the DAC. See code:DataTest::TestDataSafety. #define TEST_DATA_CONSISTENCY #if !defined(STRESS_LOG) && !defined(FEATURE_UTILCODE_NO_DEPENDENCIES) @@ -34,13 +34,9 @@ #define LOGGING #endif -#if !defined(_TARGET_X86_) || defined(FEATURE_PAL) -#define WIN64EXCEPTIONS -#endif - #if !defined(FEATURE_UTILCODE_NO_DEPENDENCIES) // Failpoint support -#if defined(_DEBUG) && !defined(DACCESS_COMPILE) && !defined(FEATURE_PAL) +#if defined(_DEBUG) && !defined(DACCESS_COMPILE) && !defined(TARGET_UNIX) #define FAILPOINTS_ENABLED #endif #endif //!defined(FEATURE_UTILCODE_NO_DEPENDENCIES) @@ -57,26 +53,26 @@ #define GC_STATS #endif -#if defined(_TARGET_X86_) || defined(_TARGET_ARM_) +#if defined(TARGET_X86) || defined(TARGET_ARM) #define USE_UPPER_ADDRESS 0 -#elif defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) +#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) #define UPPER_ADDRESS_MAPPING_FACTOR 2 #define CLR_UPPER_ADDRESS_MIN 0x64400000000 #define CODEHEAP_START_ADDRESS 0x64480000000 #define CLR_UPPER_ADDRESS_MAX 0x644FC000000 -#if !defined(FEATURE_PAL) +#if !defined(HOST_UNIX) #define USE_UPPER_ADDRESS 1 #else #define USE_UPPER_ADDRESS 0 -#endif // !FEATURE_PAL +#endif // !HOST_UNIX #else #error Please add a new #elif clause and define all portability macros for the new platform #endif -#if defined(_WIN64) +#if defined(HOST_64BIT) #define JIT_IS_ALIGNED #endif @@ -89,18 +85,13 @@ //master switch for gc suspension not based on hijacking #define FEATURE_ENABLE_GCPOLL -#if defined(_TARGET_X86_) -//this enables a fast version of the GC Poll helper instead of the default portable one. -#define ENABLE_FAST_GCPOLL_HELPER -#endif // defined(FEATURE_ENABLE_GCPOLL) && defined(_TARGET_X86_) - -#if !defined(FEATURE_PAL) -// PLATFORM_SUPPORTS_THREADSUSPEND is defined for platforms where it is safe to call -// SuspendThread. This API is dangerous on non-Windows platforms, as it can lead to -// deadlocks, due to low level OS resources that the PAL is not aware of, or due to +#if !defined(TARGET_UNIX) +// PLATFORM_SUPPORTS_THREADSUSPEND is defined for platforms where it is safe to call +// SuspendThread. This API is dangerous on non-Windows platforms, as it can lead to +// deadlocks, due to low level OS resources that the PAL is not aware of, or due to // the fact that PAL-unaware code in the process may hold onto some OS resources. #define PLATFORM_SUPPORTS_SAFE_THREADSUSPEND -#endif // !FEATURE_PAL +#endif // !TARGET_UNIX #if defined(STRESS_HEAP) && defined(_DEBUG) && defined(FEATURE_HIJACK) @@ -109,7 +100,7 @@ // Some platforms may see spurious AVs when GcCoverage is enabled because of races. // Enable further processing to see if they recur. -#if defined(HAVE_GCCOVER) && (defined(_TARGET_X86_) || defined(_TARGET_AMD64_)) && !defined(FEATURE_PAL) +#if defined(HAVE_GCCOVER) && (defined(TARGET_X86) || defined(TARGET_AMD64)) && !defined(TARGET_UNIX) #define GCCOVER_TOLERATE_SPURIOUS_AV #endif @@ -160,25 +151,25 @@ #endif // Enables a mode in which GC is completely conservative in stacks and registers: all stack slots and registers -// are treated as potential pinned interior pointers. When enabled, the runtime flag COMPLUS_GCCONSERVATIVE +// are treated as potential pinned interior pointers. When enabled, the runtime flag COMPLUS_GCCONSERVATIVE // determines dynamically whether GC is conservative. Note that appdomain unload, LCG and unloadable assemblies // do not work reliably with conservative GC. #define FEATURE_CONSERVATIVE_GC 1 -#if (defined(_TARGET_ARM_) && !defined(ARM_SOFTFP)) || defined(_TARGET_ARM64_) +#if (defined(TARGET_ARM) && !defined(ARM_SOFTFP)) || defined(TARGET_ARM64) #define FEATURE_HFA #endif // ARM requires that 64-bit primitive types are aligned at 64-bit boundaries for interlocked-like operations. // Additionally the platform ABI requires these types and composite type containing them to be similarly // aligned when passed as arguments. -#ifdef _TARGET_ARM_ +#ifdef TARGET_ARM #define FEATURE_64BIT_ALIGNMENT #endif -// Prefer double alignment for structs and arrays with doubles. Put arrays of doubles more agressively -// into large object heap for performance because large object heap is 8 byte aligned -#if !defined(FEATURE_64BIT_ALIGNMENT) && !defined(_WIN64) +// Prefer double alignment for structs and arrays with doubles. Put arrays of doubles more agressively +// into large object heap for performance because large object heap is 8 byte aligned +#if !defined(FEATURE_64BIT_ALIGNMENT) && !defined(HOST_64BIT) #define FEATURE_DOUBLE_ALIGNMENT_HINT #endif @@ -189,7 +180,7 @@ // If defined, support interpretation. #if !defined(CROSSGEN_COMPILE) -#if !defined(FEATURE_PAL) +#if !defined(TARGET_UNIX) #define FEATURE_STACK_SAMPLING #endif // defined (ALLOW_SXS_JIT) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/thekey.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/thekey.h new file mode 100644 index 0000000..dba313c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/thekey.h @@ -0,0 +1,54 @@ +// 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. +#pragma once +// This file allows customization of the strongname key used to replace the ECMA key + +static const BYTE g_rbTheKey[] = +{ +0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, +0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, +0x07,0xd1,0xfa,0x57,0xc4,0xae,0xd9,0xf0,0xa3,0x2e,0x84,0xaa,0x0f,0xae,0xfd,0x0d, +0xe9,0xe8,0xfd,0x6a,0xec,0x8f,0x87,0xfb,0x03,0x76,0x6c,0x83,0x4c,0x99,0x92,0x1e, +0xb2,0x3b,0xe7,0x9a,0xd9,0xd5,0xdc,0xc1,0xdd,0x9a,0xd2,0x36,0x13,0x21,0x02,0x90, +0x0b,0x72,0x3c,0xf9,0x80,0x95,0x7f,0xc4,0xe1,0x77,0x10,0x8f,0xc6,0x07,0x77,0x4f, +0x29,0xe8,0x32,0x0e,0x92,0xea,0x05,0xec,0xe4,0xe8,0x21,0xc0,0xa5,0xef,0xe8,0xf1, +0x64,0x5c,0x4c,0x0c,0x93,0xc1,0xab,0x99,0x28,0x5d,0x62,0x2c,0xaa,0x65,0x2c,0x1d, +0xfa,0xd6,0x3d,0x74,0x5d,0x6f,0x2d,0xe5,0xf1,0x7e,0x5e,0xaf,0x0f,0xc4,0x96,0x3d, +0x26,0x1c,0x8a,0x12,0x43,0x65,0x18,0x20,0x6d,0xc0,0x93,0x34,0x4d,0x5a,0xd2,0x93 +}; + +static const BYTE g_rbTheKeyToken[] = {0xb0,0x3f,0x5f,0x7f,0x11,0xd5,0x0a,0x3a}; + + +static const BYTE g_rbTheSilverlightPlatformKey[] = +{ +0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, +0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, +0x8d,0x56,0xc7,0x6f,0x9e,0x86,0x49,0x38,0x30,0x49,0xf3,0x83,0xc4,0x4b,0xe0,0xec, +0x20,0x41,0x81,0x82,0x2a,0x6c,0x31,0xcf,0x5e,0xb7,0xef,0x48,0x69,0x44,0xd0,0x32, +0x18,0x8e,0xa1,0xd3,0x92,0x07,0x63,0x71,0x2c,0xcb,0x12,0xd7,0x5f,0xb7,0x7e,0x98, +0x11,0x14,0x9e,0x61,0x48,0xe5,0xd3,0x2f,0xba,0xab,0x37,0x61,0x1c,0x18,0x78,0xdd, +0xc1,0x9e,0x20,0xef,0x13,0x5d,0x0c,0xb2,0xcf,0xf2,0xbf,0xec,0x3d,0x11,0x58,0x10, +0xc3,0xd9,0x06,0x96,0x38,0xfe,0x4b,0xe2,0x15,0xdb,0xf7,0x95,0x86,0x19,0x20,0xe5, +0xab,0x6f,0x7d,0xb2,0xe2,0xce,0xef,0x13,0x6a,0xc2,0x3d,0x5d,0xd2,0xbf,0x03,0x17, +0x00,0xae,0xc2,0x32,0xf6,0xc6,0xb1,0xc7,0x85,0xb4,0x30,0x5c,0x12,0x3b,0x37,0xab +}; + +static const BYTE g_rbTheSilverlightPlatformKeyToken[] = {0x7c,0xec,0x85,0xd7,0xbe,0xa7,0x79,0x8e}; + +static const BYTE g_rbTheSilverlightKey[] = +{ +0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, +0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, +0xb5,0xfc,0x90,0xe7,0x02,0x7f,0x67,0x87,0x1e,0x77,0x3a,0x8f,0xde,0x89,0x38,0xc8, +0x1d,0xd4,0x02,0xba,0x65,0xb9,0x20,0x1d,0x60,0x59,0x3e,0x96,0xc4,0x92,0x65,0x1e, +0x88,0x9c,0xc1,0x3f,0x14,0x15,0xeb,0xb5,0x3f,0xac,0x11,0x31,0xae,0x0b,0xd3,0x33, +0xc5,0xee,0x60,0x21,0x67,0x2d,0x97,0x18,0xea,0x31,0xa8,0xae,0xbd,0x0d,0xa0,0x07, +0x2f,0x25,0xd8,0x7d,0xba,0x6f,0xc9,0x0f,0xfd,0x59,0x8e,0xd4,0xda,0x35,0xe4,0x4c, +0x39,0x8c,0x45,0x43,0x07,0xe8,0xe3,0x3b,0x84,0x26,0x14,0x3d,0xae,0xc9,0xf5,0x96, +0x83,0x6f,0x97,0xc8,0xf7,0x47,0x50,0xe5,0x97,0x5c,0x64,0xe2,0x18,0x9f,0x45,0xde, +0xf4,0x6b,0x2a,0x2b,0x12,0x47,0xad,0xc3,0x65,0x2b,0xf5,0xc3,0x08,0x05,0x5d,0xa9 +}; + +static const BYTE g_rbTheSilverlightKeyToken[] = {0x31,0xBF,0x38,0x56,0xAD,0x36,0x4E,0x35}; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/tls.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/tls.h index e359a99..fb880ba 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/tls.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/tls.h @@ -5,7 +5,7 @@ // // -// Encapsulates TLS access for maximum performance. +// Encapsulates TLS access for maximum performance. // // ************************************************************************************** @@ -19,7 +19,7 @@ #define OFFSETOF__TLS__tls_CurrentThread (0x0) #define OFFSETOF__TLS__tls_EETlsData (2*sizeof(void*)) -#ifdef DBG_TARGET_WIN64 +#ifdef TARGET_64BIT #define WINNT_OFFSETOF__TEB__ThreadLocalStoragePointer 0x58 #else #define WINNT_OFFSETOF__TEB__ThreadLocalStoragePointer 0x2c diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/unreachable.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/unreachable.h new file mode 100644 index 0000000..0e2ae87 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/unreachable.h @@ -0,0 +1,26 @@ +// 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. +// --------------------------------------------------------------------------- +// unreachable.h +// --------------------------------------------------------------------------- + + +#ifndef __UNREACHABLE_H__ +#define __UNREACHABLE_H__ + +#if defined(_MSC_VER) || defined(_PREFIX_) +#if defined(TARGET_AMD64) +// Empty methods that consist of UNREACHABLE() result in a zero-sized declspec(noreturn) method +// which causes the pdb file to make the next method declspec(noreturn) as well, thus breaking BBT +// Remove when we get a VC compiler that fixes VSW 449170 +# define __UNREACHABLE() do { DebugBreak(); __assume(0); } while (0) +#else +# define __UNREACHABLE() __assume(0) +#endif +#else +#define __UNREACHABLE() __builtin_unreachable() +#endif + +#endif // __UNREACHABLE_H__ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/utilcode.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/utilcode.h index 5b8107c..1721db0 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/utilcode.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/utilcode.h @@ -66,7 +66,7 @@ class StringArrayList; #define _DEBUG_IMPL 1 #endif -#ifdef _TARGET_ARM_ +#ifdef TARGET_ARM // Under ARM we generate code only with Thumb encoding. In order to ensure we execute such code in the correct // mode we must ensure the low-order bit is set in any code address we'll call as a sub-routine. In C++ this @@ -102,13 +102,13 @@ inline ResultType ThumbCodeToDataPointer(SourceType pCode) return (ResultType)(((UINT_PTR)pCode) & ~THUMB_CODE); } -#endif // _TARGET_ARM_ +#endif // TARGET_ARM // Convert from a PCODE to the corresponding PINSTR. On many architectures this will be the identity function; // on ARM, this will mask off the THUMB bit. inline TADDR PCODEToPINSTR(PCODE pc) { -#ifdef _TARGET_ARM_ +#ifdef TARGET_ARM return ThumbCodeToDataPointer(pc); #else return dac_cast(pc); @@ -119,7 +119,7 @@ inline TADDR PCODEToPINSTR(PCODE pc) // on ARM, this will raise the THUMB bit. inline PCODE PINSTRToPCODE(TADDR addr) { -#ifdef _TARGET_ARM_ +#ifdef TARGET_ARM return DataPointerToThumbCode(addr); #else return dac_cast(addr); @@ -163,14 +163,14 @@ typedef LPSTR LPUTF8; #endif -#define IS_DIGIT(ch) ((ch >= W('0')) && (ch <= W('9'))) -#define DIGIT_TO_INT(ch) (ch - W('0')) -#define INT_TO_DIGIT(i) ((WCHAR)(W('0') + i)) +#define IS_DIGIT(ch) (((ch) >= W('0')) && ((ch) <= W('9'))) +#define DIGIT_TO_INT(ch) ((ch) - W('0')) +#define INT_TO_DIGIT(i) ((WCHAR)(W('0') + (i))) -#define IS_HEXDIGIT(ch) (((ch >= W('a')) && (ch <= W('f'))) || \ - ((ch >= W('A')) && (ch <= W('F')))) +#define IS_HEXDIGIT(ch) ((((ch) >= W('a')) && ((ch) <= W('f'))) || \ + (((ch) >= W('A')) && ((ch) <= W('F')))) #define HEXDIGIT_TO_INT(ch) ((towlower(ch) - W('a')) + 10) -#define INT_TO_HEXDIGIT(i) ((WCHAR)(W('a') + (i - 10))) +#define INT_TO_HEXDIGIT(i) ((WCHAR)(W('a') + ((i) - 10))) // Helper will 4 byte align a value, rounding up. @@ -489,15 +489,8 @@ inline void *__cdecl operator new(size_t, void *_P) /********************************************************************************/ /* portability helpers */ -#ifdef _WIN64 -#define IN_WIN64(x) x -#define IN_WIN32(x) -#else -#define IN_WIN64(x) -#define IN_WIN32(x) x -#endif -#ifdef _TARGET_64BIT_ +#ifdef TARGET_64BIT #define IN_TARGET_64BIT(x) x #define IN_TARGET_32BIT(x) #else @@ -574,16 +567,8 @@ void GetResourceCultureCallbacks( FPGETTHREADUICULTUREID* fpGetThreadUICultureId ); -#if !defined(DACCESS_COMPILE) -// Get the MUI ID, on downlevel platforms where MUI is not supported it -// returns the default system ID. -extern int GetMUILanguageID(LocaleIDValue* pResult); -extern HRESULT GetMUILanguageNames(__inout StringArrayList* pCultureNames); - -#endif // !defined(DACCESS_COMPILE) - //***************************************************************************** -// Use this class by privately deriving from noncopyable to disallow copying of +// Use this class by privately deriving from noncopyable to disallow copying of // your class. //***************************************************************************** class noncopyable @@ -611,7 +596,7 @@ class CCulturedHInstance LocaleIDValue m_LangId; HRESOURCEDLL m_hInst; BOOL m_fMissing; - + public: CCulturedHInstance() { @@ -619,7 +604,7 @@ public: m_hInst = NULL; m_fMissing = FALSE; } - + BOOL HasID(LocaleID id) { _ASSERTE(m_hInst != NULL || m_fMissing); @@ -628,12 +613,12 @@ public: return wcscmp(id, m_LangId) == 0; } - + HRESOURCEDLL GetLibraryHandle() { return m_hInst; } - + BOOL IsSet() { return m_hInst != NULL; @@ -650,7 +635,7 @@ public: SetId(id); m_fMissing = TRUE; } - + void Set(LocaleID id, HRESOURCEDLL hInst) { _ASSERTE(m_hInst == NULL); @@ -688,18 +673,18 @@ public: enum ResourceCategory { // must be present - Required, - + Required, + // present in Desktop CLR and Core CLR + debug pack, an error // If missing, get a generic error message instead - Error, - + Error, + // present in Desktop CLR and Core CLR + debug pack, normal operation (e.g tracing) // if missing, get a generic "resource not found" message instead - Debugging, + Debugging, // present in Desktop CLR, optional for CoreCLR - DesktopCLR, + DesktopCLR, // might not be present, non essential Optional @@ -709,34 +694,19 @@ public: { // This constructor will be fired up on startup. Make sure it doesn't // do anything besides zero-out out values. - m_bUseFallback = FALSE; - m_fpGetThreadUICultureId = NULL; m_fpGetThreadUICultureNames = NULL; - m_pHash = NULL; m_nHashSize = 0; m_csMap = NULL; m_pResourceFile = NULL; -#ifdef FEATURE_PAL - m_pResourceDomain = NULL; -#endif // FEATURE_PAL - }// CCompRC - HRESULT Init(LPCWSTR pResourceFile, BOOL bUseFallback = FALSE); + HRESULT Init(LPCWSTR pResourceFile); void Destroy(); - BOOL ShouldUseFallback() - { - LIMITED_METHOD_CONTRACT; - return m_bUseFallback; - }; - - static void SetIsMscoree() {s_bIsMscoree = TRUE;} - - HRESULT LoadString(ResourceCategory eCategory, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax , int *pcwchUsed=NULL); + HRESULT LoadString(ResourceCategory eCategory, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax , int *pcwchUsed=NULL); HRESULT LoadString(ResourceCategory eCategory, LocaleID langId, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int *pcwchUsed); void SetResourceCultureCallbacks( @@ -749,13 +719,9 @@ public: FPGETTHREADUICULTUREID* fpGetThreadUICultureId ); - HRESULT LoadMUILibrary(HRESOURCEDLL * pHInst); - - // Get the default resource location (mscorrc.dll for desktop, mscorrc.debug.dll for CoreCLR) + // Get the default resource location (mscorrc.dll) static CCompRC* GetDefaultResourceDll(); - // Get the generic messages dll (Silverlight only, mscorrc.dll) - static CCompRC* GetFallbackResourceDll(); - static void ShutdownDefaultResourceDll(); + static void GetDefaultCallbacks( FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames, FPGETTHREADUICULTUREID* fpGetThreadUICultureId) @@ -778,29 +744,8 @@ public: m_DefaultResourceDll.SetResourceCultureCallbacks( fpGetThreadUICultureNames, fpGetThreadUICultureId); - - m_FallbackResourceDll.SetResourceCultureCallbacks( - fpGetThreadUICultureNames, - fpGetThreadUICultureId); - } -#ifdef USE_FORMATMESSAGE_WRAPPER - -DWORD -PALAPI -static -FormatMessage( - IN DWORD dwFlags, - IN LPCVOID lpSource, - IN DWORD dwMessageId, - IN DWORD dwLanguageId, - OUT LPWSTR lpBuffer, - IN DWORD nSize, - IN va_list *Arguments); -#endif // USE_FORMATMESSAGE_WRAPPER - - private: HRESULT GetLibrary(LocaleID langId, HRESOURCEDLL* phInst); #ifndef DACCESS_COMPILE @@ -816,11 +761,6 @@ private: static CCompRC m_DefaultResourceDll; static LPCWSTR m_pDefaultResource; - // fallback resources if debug pack is not installed - static LONG m_dwFallbackInitialized; - static CCompRC m_FallbackResourceDll; - static LPCWSTR m_pFallbackResource; - // We must map between a thread's int and a dll instance. // Since we only expect 1 language almost all of the time, we'll special case // that and then use a variable size map for everything else. @@ -831,12 +771,6 @@ private: CRITSEC_COOKIE m_csMap; LPCWSTR m_pResourceFile; -#ifdef FEATURE_PAL - // Resource domain is an ANSI string identifying a native resources file - static LPCSTR m_pDefaultResourceDomain; - static LPCSTR m_pFallbackResourceDomain; - LPCSTR m_pResourceDomain; -#endif // FEATURE_PAL // Main accessors for hash HRESOURCEDLL LookupNode(LocaleID langId, BOOL &fMissing); @@ -844,9 +778,6 @@ private: FPGETTHREADUICULTUREID m_fpGetThreadUICultureId; FPGETTHREADUICULTURENAMES m_fpGetThreadUICultureNames; - - BOOL m_bUseFallback; - static BOOL s_bIsMscoree; }; HRESULT UtilLoadResourceString(CCompRC::ResourceCategory eCategory, UINT iResouceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax); @@ -857,7 +788,7 @@ int UtilMessageBox( UINT uText, // Resource Identifier for Text message UINT uCaption, // Resource Identifier for Caption UINT uType, // Style of MessageBox - BOOL displayForNonInteractive, // Display even if the process is running non interactive + BOOL displayForNonInteractive, // Display even if the process is running non interactive BOOL ShowFileNameInTitle, // Flag to show FileName in Caption ...); // Additional Arguments @@ -866,7 +797,7 @@ int UtilMessageBoxNonLocalized( LPCWSTR lpText, // Resource Identifier for Text message LPCWSTR lpTitle, // Resource Identifier for Caption UINT uType, // Style of MessageBox - BOOL displayForNonInteractive, // Display even if the process is running non interactive + BOOL displayForNonInteractive, // Display even if the process is running non interactive BOOL ShowFileNameInTitle, // Flag to show FileName in Caption ...); // Additional Arguments @@ -875,7 +806,7 @@ int UtilMessageBoxVA( UINT uText, // Resource Identifier for Text message UINT uCaption, // Resource Identifier for Caption UINT uType, // Style of MessageBox - BOOL displayForNonInteractive, // Display even if the process is running non interactive + BOOL displayForNonInteractive, // Display even if the process is running non interactive BOOL ShowFileNameInTitle, // Flag to show FileName in Caption va_list args); // Additional Arguments @@ -884,7 +815,7 @@ int UtilMessageBoxNonLocalizedVA( LPCWSTR lpText, // Text message LPCWSTR lpCaption, // Caption UINT uType, // Style of MessageBox - BOOL displayForNonInteractive, // Display even if the process is running non interactive + BOOL displayForNonInteractive, // Display even if the process is running non interactive BOOL ShowFileNameInTitle, // Flag to show FileName in Caption BOOL * pInputFromUser, // To distinguish between user pressing abort vs. assuming abort. va_list args); // Additional Arguments @@ -895,7 +826,7 @@ int UtilMessageBoxNonLocalizedVA( LPCWSTR lpCaption, // Caption LPCWSTR lpDetails, // Details that may be shown in a collapsed extended area of the dialog (Vista or higher). UINT uType, // Style of MessageBox - BOOL displayForNonInteractive, // Display even if the process is running non interactive + BOOL displayForNonInteractive, // Display even if the process is running non interactive BOOL ShowFileNameInTitle, // Flag to show FileName in Caption BOOL * pInputFromUser, // To distinguish between user pressing abort vs. assuming abort. va_list args); // Additional Arguments @@ -972,10 +903,10 @@ inline HRESULT BadError(HRESULT hr) } #define TESTANDRETURNPOINTER(pointer) \ - TESTANDRETURN(pointer!=NULL, E_POINTER) + TESTANDRETURN((pointer)!=NULL, E_POINTER) #define TESTANDRETURNMEMORY(pointer) \ - TESTANDRETURN(pointer!=NULL, E_OUTOFMEMORY) + TESTANDRETURN((pointer)!=NULL, E_OUTOFMEMORY) #define TESTANDRETURNHR(hr) \ TESTANDRETURN(SUCCEEDED(hr), hr) @@ -1096,16 +1027,15 @@ public: COR_CONFIG_ENV = 0x01, COR_CONFIG_USER = 0x02, COR_CONFIG_MACHINE = 0x04, - COR_CONFIG_FUSION = 0x08, - COR_CONFIG_REGISTRY = (COR_CONFIG_USER|COR_CONFIG_MACHINE|COR_CONFIG_FUSION), + COR_CONFIG_REGISTRY = (COR_CONFIG_USER|COR_CONFIG_MACHINE), COR_CONFIG_ALL = (COR_CONFIG_ENV|COR_CONFIG_USER|COR_CONFIG_MACHINE), }; // - // NOTE: The following function is deprecated; use the CLRConfig class instead. + // NOTE: The following function is deprecated; use the CLRConfig class instead. // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. - // + // static DWORD GetConfigDWORD_DontUse_( LPCWSTR name, DWORD defValue, @@ -1113,16 +1043,16 @@ public: BOOL fPrependCOMPLUS = TRUE); // - // NOTE: The following function is deprecated; use the CLRConfig class instead. + // NOTE: The following function is deprecated; use the CLRConfig class instead. // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. - // + // static HRESULT GetConfigDWORD_DontUse_( LPCWSTR name, DWORD defValue, __out DWORD * result, CORConfigLevel level = COR_CONFIG_ALL, BOOL fPrependCOMPLUS = TRUE); - + static ULONGLONG GetConfigULONGLONG_DontUse_( LPCWSTR name, ULONGLONG defValue, @@ -1130,18 +1060,18 @@ public: BOOL fPrependCOMPLUS = TRUE); // - // NOTE: The following function is deprecated; use the CLRConfig class instead. + // NOTE: The following function is deprecated; use the CLRConfig class instead. // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. - // + // static DWORD GetConfigFlag_DontUse_( LPCWSTR name, DWORD bitToSet, BOOL defValue = FALSE); // - // NOTE: The following function is deprecated; use the CLRConfig class instead. + // NOTE: The following function is deprecated; use the CLRConfig class instead. // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. - // + // static LPWSTR GetConfigString_DontUse_( LPCWSTR name, BOOL fPrependCOMPLUS = TRUE, @@ -1152,15 +1082,12 @@ public: private: static LPWSTR EnvGetString(LPCWSTR name, BOOL fPrependCOMPLUS); -public: - - static BOOL UseRegistry(); private: //***************************************************************************** // Get either a DWORD or ULONGLONG. Always puts the result in a ULONGLONG that // you can safely cast to a DWORD if fGetDWORD is TRUE. -//***************************************************************************** +//***************************************************************************** static HRESULT GetConfigInteger( LPCWSTR name, ULONGLONG defValue, @@ -1200,15 +1127,13 @@ private: // always returns TRUE. static BOOL s_fUseEnvCache; // Enable env cache. - static BOOL s_fUseRegistry; // Allow lookups in the registry - // Open the .NetFramework keys once and cache the handles static HKEY s_hMachineFrameworkKey; static HKEY s_hUserFrameworkKey; }; // need this here because CLRConfig depends on REGUTIL, and ConfigStringHolder depends on CLRConfig -#include "clrconfig.h" +#include "clrconfig.h" //----------------------------------------------------------------------------- // Wrapper for configuration strings. @@ -1223,9 +1148,9 @@ public: } // - // NOTE: The following function is deprecated; use the CLRConfig class instead. + // NOTE: The following function is deprecated; use the CLRConfig class instead. // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. - // + // void Init_DontUse_(LPCWSTR wszName) { Clear(); @@ -1283,7 +1208,7 @@ BOOL IsPreferredExecutableRange(void * p); // Handles the special requirements that we have on 64-bit platforms // where we want the executable memory to be located near mscorwks // -BYTE * ClrVirtualAllocExecutable(SIZE_T dwSize, +BYTE * ClrVirtualAllocExecutable(SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); @@ -1293,16 +1218,16 @@ BYTE * ClrVirtualAllocExecutable(SIZE_T dwSize, // BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, const BYTE *pMaxAddr, - SIZE_T dwSize, + SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); // -// Allocate free memory with specific alignment +// Allocate free memory with specific alignment // LPVOID ClrVirtualAllocAligned(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, SIZE_T alignment); -class NumaNodeInfo +class NumaNodeInfo { private: static BOOL m_enableGCNumaAware; @@ -1318,18 +1243,18 @@ public: // functions static LPVOID VirtualAllocExNuma(HANDLE hProc, LPVOID lpAddr, SIZE_T size, DWORD allocType, DWORD prot, DWORD node); -#ifndef FEATURE_PAL +#ifdef HOST_WINDOWS static BOOL GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, PUSHORT node_no); static bool GetNumaInfo(PUSHORT total_nodes, DWORD* max_procs_per_node); -#else // !FEATURE_PAL +#else // HOST_WINDOWS static BOOL GetNumaProcessorNodeEx(USHORT proc_no, PUSHORT node_no); -#endif // !FEATURE_PAL +#endif // HOST_WINDOWS #endif }; -#ifndef FEATURE_PAL +#ifdef HOST_WINDOWS -struct CPU_Group_Info +struct CPU_Group_Info { WORD nr_active; // at most 64 WORD reserved[1]; @@ -1362,7 +1287,7 @@ public: static BOOL CanEnableGCCPUGroups(); static BOOL CanEnableThreadUseAllCpuGroups(); static WORD GetNumActiveProcessors(); - static void GetGroupForProcessor(WORD processor_number, + static void GetGroupForProcessor(WORD processor_number, WORD *group_number, WORD *group_processor_number); static DWORD CalculateCurrentProcessorNumber(); static bool GetCPUGroupInfo(PUSHORT total_groups, DWORD* max_procs_per_group); @@ -1371,9 +1296,9 @@ public: #if !defined(FEATURE_REDHAWK) public: static BOOL GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP relationship, - SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *slpiex, PDWORD count); + SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *slpiex, PDWORD count); static BOOL SetThreadGroupAffinity(HANDLE h, - GROUP_AFFINITY *groupAffinity, GROUP_AFFINITY *previousGroupAffinity); + const GROUP_AFFINITY *groupAffinity, GROUP_AFFINITY *previousGroupAffinity); static BOOL GetThreadGroupAffinity(HANDLE h, GROUP_AFFINITY *groupAffinity); static BOOL GetSystemTimes(FILETIME *idleTime, FILETIME *kernelTime, FILETIME *userTime); static void ChooseCPUGroupAffinity(GROUP_AFFINITY *gf); @@ -1391,7 +1316,7 @@ public: DWORD_PTR GetCurrentProcessCpuMask(); -#endif // !FEATURE_PAL +#endif // HOST_WINDOWS //****************************************************************************** // Returns the number of processors that a process has been configured to run on @@ -2160,24 +2085,24 @@ private: WRAPPER_NO_CONTRACT; SSIZE_T iLast; SSIZE_T i; // loop variable. - + for (;;) { // if less than two elements you're done. if (iLeft >= iRight) return; - + // ASSERT that we now have valid indicies. This is statically provable // since this private function is only called with valid indicies, // and iLeft and iRight only converge towards eachother. However, // PreFast can't detect this because it doesn't know about our callers. COMPILER_ASSUME(iLeft >= 0 && iLeft < m_iCount); COMPILER_ASSUME(iRight >= 0 && iRight < m_iCount); - + // The mid-element is the pivot, move it to the left. Swap(iLeft, (iLeft + iRight) / 2); iLast = iLeft; - + // move everything that is smaller than the pivot to the left. for (i = iLeft + 1; i <= iRight; i++) { @@ -2186,10 +2111,10 @@ private: Swap(i, ++iLast); } } - + // Put the pivot to the point where it is in between smaller and larger elements. Swap(iLeft, iLast); - + // Sort each partition. SSIZE_T iLeftLast = iLast - 1; SSIZE_T iRightFirst = iLast + 1; @@ -2228,7 +2153,7 @@ const T * BinarySearch(const T * pBase, int iCount, const T & find) while (iLast - iFirst > 10) { int iMid = (iLast + iFirst) / 2; - + if (find < pBase[iMid]) iLast = iMid - 1; else @@ -2860,7 +2785,7 @@ int CHashTableAndData::Grow() // 1 if successful, 0 if not. { _ASSERTE( !"CHashTableAndData overflow!" ); return (0); - } + } iCurSize = MemMgr::RoundSize( iTotEntrySize.Value() ); iEntries = (iCurSize + MemMgr::GrowSize(iCurSize)) / m_iEntrySize; @@ -2907,8 +2832,8 @@ inline DWORD HashThreeToOne(DWORD a, DWORD b, DWORD c) lookup3.c, by Bob Jenkins, May 2006, Public Domain. These are functions for producing 32-bit hashes for hash table lookup. - hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() - are externally useful functions. Routines to test the hash are included + hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() + are externally useful functions. Routines to test the hash are included if SELF_TEST is defined. You can use this free for any purpose. It's in the public domain. It has no warranty. */ @@ -2918,7 +2843,7 @@ inline DWORD HashThreeToOne(DWORD a, DWORD b, DWORD c) a ^= c; a -= rot32(c,11); b ^= a; b -= rot32(a,25); c ^= b; c -= rot32(b,16); - a ^= c; a -= rot32(c,4); + a ^= c; a -= rot32(c,4); b ^= a; b -= rot32(a,14); c ^= b; c -= rot32(b,24); @@ -2975,7 +2900,7 @@ inline ULONG HashStringN(LPCWSTR szStr, SIZE_T cchStr) // hash the string two characters at a time ULONG *ptr = (ULONG *)szStr; - + // we assume that szStr is null-terminated _ASSERTE(cchStr <= wcslen(szStr)); SIZE_T cDwordCount = (cchStr + 1) / 2; @@ -3875,9 +3800,9 @@ class ConfigDWORD { public: // - // NOTE: The following function is deprecated; use the CLRConfig class instead. + // NOTE: The following function is deprecated; use the CLRConfig class instead. // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. - // + // inline DWORD val_DontUse_(__in __in_z LPCWSTR keyName, DWORD defaultVal=0) { WRAPPER_NO_CONTRACT; @@ -4017,16 +3942,16 @@ class RangeList { return this->AddRangeWorker(start, end, id); } - + void RemoveRanges(void *id, const BYTE *start = NULL, const BYTE *end = NULL) { return this->RemoveRangesWorker(id, start, end); } - + BOOL IsInRange(TADDR address, TADDR *pID = NULL) { SUPPORTS_DAC; - + return this->IsInRangeWorker(address, pID); } @@ -4057,7 +3982,7 @@ class RangeList RANGE_COUNT = 10 }; - + private: struct Range { @@ -4243,7 +4168,7 @@ INT32 GetThumb2BlRel24(UINT16 * p); void PutThumb2BlRel24(UINT16 * p, INT32 imm24); //***************************************************************************** -// Extract the PC-Relative offset from a b or bl instruction +// Extract the PC-Relative offset from a b or bl instruction //***************************************************************************** INT32 GetArm64Rel28(UINT32 * pCode); @@ -4258,7 +4183,7 @@ INT32 GetArm64Rel21(UINT32 * pCode); INT32 GetArm64Rel12(UINT32 * pCode); //***************************************************************************** -// Deposit the PC-Relative offset 'imm28' into a b or bl instruction +// Deposit the PC-Relative offset 'imm28' into a b or bl instruction //***************************************************************************** void PutArm64Rel28(UINT32 * pCode, INT32 imm28); @@ -4334,13 +4259,13 @@ LPWSTR *SegmentCommandLine(LPCWSTR lpCmdLine, DWORD *pNumArgs); class ClrTeb { public: -#if defined(FEATURE_PAL) +#if defined(HOST_UNIX) // returns pointer that uniquely identifies the fiber static void* GetFiberPtrId() { LIMITED_METHOD_CONTRACT; - // not fiber for FEATURE_PAL - use the regular thread ID + // not fiber for HOST_UNIX - use the regular thread ID return (void *)(size_t)GetCurrentThreadId(); } @@ -4359,7 +4284,7 @@ public: return PAL_GetStackLimit(); } -#else // !FEATURE_PAL +#else // HOST_UNIX // returns pointer that uniquely identifies the fiber static void* GetFiberPtrId() @@ -4408,11 +4333,13 @@ public: { return (void*) 1; } -#endif // !FEATURE_PAL +#endif // HOST_UNIX }; #if !defined(DACCESS_COMPILE) +extern thread_local size_t t_ThreadType; + // check if current thread is a GC thread (concurrent or server) inline BOOL IsGCSpecialThread () { @@ -4421,7 +4348,7 @@ inline BOOL IsGCSpecialThread () STATIC_CONTRACT_MODE_ANY; STATIC_CONTRACT_CANNOT_TAKE_LOCK; - return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_GC); + return !!(t_ThreadType & ThreadType_GC); } // check if current thread is a Gate thread @@ -4431,7 +4358,7 @@ inline BOOL IsGateSpecialThread () STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; - return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Gate); + return !!(t_ThreadType & ThreadType_Gate); } // check if current thread is a Timer thread @@ -4441,7 +4368,7 @@ inline BOOL IsTimerSpecialThread () STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; - return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Timer); + return !!(t_ThreadType & ThreadType_Timer); } // check if current thread is a debugger helper thread @@ -4451,7 +4378,7 @@ inline BOOL IsDbgHelperSpecialThread () STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; - return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_DbgHelper); + return !!(t_ThreadType & ThreadType_DbgHelper); } // check if current thread is a debugger helper thread @@ -4461,7 +4388,7 @@ inline BOOL IsETWRundownSpecialThread () STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; - return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ETWRundownThread); + return !!(t_ThreadType & ThreadType_ETWRundownThread); } // check if current thread is a generic instantiation lookup compare thread @@ -4471,7 +4398,7 @@ inline BOOL IsGenericInstantiationLookupCompareThread () STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; - return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_GenericInstantiationCompare); + return !!(t_ThreadType & ThreadType_GenericInstantiationCompare); } // check if current thread is a thread which is performing shutdown @@ -4481,7 +4408,7 @@ inline BOOL IsShutdownSpecialThread () STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; - return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Shutdown); + return !!(t_ThreadType & ThreadType_Shutdown); } inline BOOL IsThreadPoolIOCompletionSpecialThread () @@ -4490,7 +4417,7 @@ inline BOOL IsThreadPoolIOCompletionSpecialThread () STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; - return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Threadpool_IOCompletion); + return !!(t_ThreadType & ThreadType_Threadpool_IOCompletion); } inline BOOL IsThreadPoolWorkerSpecialThread () @@ -4499,7 +4426,7 @@ inline BOOL IsThreadPoolWorkerSpecialThread () STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; - return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Threadpool_Worker); + return !!(t_ThreadType & ThreadType_Threadpool_Worker); } inline BOOL IsWaitSpecialThread () @@ -4508,7 +4435,7 @@ inline BOOL IsWaitSpecialThread () STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; - return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Wait); + return !!(t_ThreadType & ThreadType_Wait); } // check if current thread is a thread which is performing shutdown @@ -4518,7 +4445,7 @@ inline BOOL IsSuspendEEThread () STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; - return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_DynamicSuspendEE); + return !!(t_ThreadType & ThreadType_DynamicSuspendEE); } inline BOOL IsFinalizerThread () @@ -4527,7 +4454,7 @@ inline BOOL IsFinalizerThread () STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; - return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Finalizer); + return !!(t_ThreadType & ThreadType_Finalizer); } inline BOOL IsShutdownHelperThread () @@ -4536,7 +4463,7 @@ inline BOOL IsShutdownHelperThread () STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; - return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ShutdownHelper); + return !!(t_ThreadType & ThreadType_ShutdownHelper); } inline BOOL IsProfilerAttachThread () @@ -4545,55 +4472,17 @@ inline BOOL IsProfilerAttachThread () STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; - return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ProfAPI_Attach); + return !!(t_ThreadType & ThreadType_ProfAPI_Attach); } -// set specical type for current thread -inline void ClrFlsSetThreadType (TlsThreadTypeFlag flag) -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_MODE_ANY; - - ClrFlsSetValue (TlsIdx_ThreadType, (LPVOID)(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) |flag)); -} - -// clear specical type for current thread -inline void ClrFlsClearThreadType (TlsThreadTypeFlag flag) -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_MODE_ANY; - - ClrFlsSetValue (TlsIdx_ThreadType, (LPVOID)(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ~flag)); -} +// set special type for current thread +void ClrFlsSetThreadType(TlsThreadTypeFlag flag); +void ClrFlsClearThreadType(TlsThreadTypeFlag flag); #endif //!DACCESS_COMPILE -#ifdef DACCESS_COMPILE -#define SET_THREAD_TYPE_STACKWALKER(pThread) -#define CLEAR_THREAD_TYPE_STACKWALKER() -#else // DACCESS_COMPILE -#define SET_THREAD_TYPE_STACKWALKER(pThread) ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, pThread) -#define CLEAR_THREAD_TYPE_STACKWALKER() ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, NULL) -#endif // DACCESS_COMPILE - HRESULT SetThreadName(HANDLE hThread, PCWSTR lpThreadDescription); -inline BOOL IsStackWalkerThread() -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_MODE_ANY; - STATIC_CONTRACT_CANNOT_TAKE_LOCK; - -#if defined(DACCESS_COMPILE) - return FALSE; -#else - return ClrFlsGetValue (TlsIdx_StackWalkerWalkingThread) != NULL; -#endif -} - inline BOOL IsGCThread () { STATIC_CONTRACT_NOTHROW; @@ -4619,12 +4508,12 @@ public: #ifndef DACCESS_COMPILE m_flag = flag; - m_fPreviouslySet = (((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & flag); + m_fPreviouslySet = (t_ThreadType & flag); // In debug builds, remember the full group of flags that were set at the time // the constructor was called. This will be used in ASSERTs in the destructor - INDEBUG(m_nPreviousFlagGroup = (size_t)ClrFlsGetValue (TlsIdx_ThreadType)); - + INDEBUG(m_nPreviousFlagGroup = t_ThreadType); + if (!m_fPreviouslySet) { ClrFlsSetThreadType(flag); @@ -4644,11 +4533,11 @@ public: // instantiated, then this holder still restores only the flag it knows about. To // prevent confusion, assert if some other flag was modified, so the user doesn't // expect the holder to restore the entire original set of flags. - // + // // The expression below says that the only difference between the previous flag // group and the current flag group should be m_flag (or no difference at all, if // m_flag's state didn't actually change). - _ASSERTE(((m_nPreviousFlagGroup ^ (size_t) ClrFlsGetValue(TlsIdx_ThreadType)) | (size_t) m_flag) == (size_t) m_flag); + _ASSERTE(((m_nPreviousFlagGroup ^ t_ThreadType) | (size_t) m_flag) == (size_t) m_flag); if (m_fPreviouslySet) { @@ -4667,81 +4556,6 @@ private: INDEBUG(size_t m_nPreviousFlagGroup); }; -class ClrFlsValueSwitch -{ -public: - ClrFlsValueSwitch (PredefinedTlsSlots slot, PVOID value) - { - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_MODE_ANY; - -#ifndef DACCESS_COMPILE - m_slot = slot; - m_PreviousValue = ClrFlsGetValue(slot); - ClrFlsSetValue(slot, value); -#endif // DACCESS_COMPILE - } - - ~ClrFlsValueSwitch () - { - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_MODE_ANY; - -#ifndef DACCESS_COMPILE - ClrFlsSetValue(m_slot, m_PreviousValue); -#endif // DACCESS_COMPILE - } - -private: - PVOID m_PreviousValue; - PredefinedTlsSlots m_slot; -}; - -//********************************************************************************* - -// When we're hosted, operations called by the host (such as Thread::YieldTask) -// may not cause calls back into the host, as the host needs not be reentrant. -// Use the following holder for code in which calls into the host are forbidden. -// (If a call into the host is attempted nevertheless, an assert will fire.) - -class ForbidCallsIntoHostOnThisThread -{ -private: - static Volatile s_pvOwningFiber; - - FORCEINLINE static BOOL Enter(BOOL) - { - WRAPPER_NO_CONTRACT; - return InterlockedCompareExchangePointer( - &s_pvOwningFiber, ClrTeb::GetFiberPtrId(), NULL) == NULL; - } - - FORCEINLINE static void Leave(BOOL) - { - LIMITED_METHOD_CONTRACT; - s_pvOwningFiber = NULL; - } - -public: - typedef ConditionalStateHolder Holder; - - FORCEINLINE static BOOL CanThisThreadCallIntoHost() - { - WRAPPER_NO_CONTRACT; - return s_pvOwningFiber != ClrTeb::GetFiberPtrId(); - } -}; - -typedef ForbidCallsIntoHostOnThisThread::Holder ForbidCallsIntoHostOnThisThreadHolder; - -FORCEINLINE BOOL CanThisThreadCallIntoHost() -{ - WRAPPER_NO_CONTRACT; - return ForbidCallsIntoHostOnThisThread::CanThisThreadCallIntoHost(); -} - //********************************************************************************* #include "contract.inl" @@ -4749,8 +4563,8 @@ FORCEINLINE BOOL CanThisThreadCallIntoHost() namespace util { // compare adapters - // - + // + template < typename T > struct less { @@ -4768,7 +4582,7 @@ namespace util return first > second; } }; - + // sort adapters // @@ -4785,7 +4599,7 @@ namespace util : CQuickSort< T >( begin, end - begin ) , m_pred( pred ) {} - + virtual int Compare( T * first, T * second ) { return m_pred( *first, *second ) ? -1 @@ -4798,7 +4612,7 @@ namespace util sort_helper sort_obj( begin, end, pred ); sort_obj.Sort(); } - + template < typename Iter > void sort( Iter begin, Iter end ); @@ -4809,7 +4623,7 @@ namespace util util::sort( begin, end, util::less< T >() ); } - + // binary search adapters // @@ -4847,7 +4661,7 @@ namespace util * Overloaded operators for the executable heap * ------------------------------------------------------------------------ */ -#ifndef FEATURE_PAL +#ifdef HOST_WINDOWS struct CExecutable { int x; }; extern const CExecutable executable; @@ -4867,11 +4681,11 @@ template void DeleteExecutable(T *p) { p->T::~T(); - ClrHeapFree(ClrGetProcessExecutableHeap(), 0, p); + HeapFree(ClrGetProcessExecutableHeap(), 0, p); } } -#endif // FEATURE_PAL +#endif // HOST_WINDOWS INDEBUG(BOOL DbgIsExecutable(LPVOID lpMem, SIZE_T length);) @@ -4880,16 +4694,6 @@ BOOL NoGuiOnAssert(); VOID TerminateOnAssert(); #endif // _DEBUG -class HighCharHelper { -public: - static inline BOOL IsHighChar(int c) { - return (BOOL)HighCharTable[c]; - } - -private: - static const BYTE HighCharTable[]; -}; - BOOL ThreadWillCreateGuardPage(SIZE_T sizeReservedStack, SIZE_T sizeCommitedStack); @@ -4899,7 +4703,7 @@ typedef Wrapper BSTRHolder; // HMODULE_TGT represents a handle to a module in the target process. In non-DAC builds this is identical // to HMODULE (HINSTANCE), which is the base address of the module. In DAC builds this must be a target address, -// and so is represented by TADDR. +// and so is represented by TADDR. #ifdef DACCESS_COMPILE typedef TADDR HMODULE_TGT; @@ -4909,50 +4713,7 @@ typedef HMODULE HMODULE_TGT; BOOL IsIPInModule(HMODULE_TGT hModule, PCODE ip); -//---------------------------------------------------------------------------------------- -// The runtime invokes InitUtilcode() in its dllmain and passes along all of the critical -// callback pointers. For the desktop CLR, all DLLs loaded by the runtime must also call -// InitUtilcode with the same callbacks as the runtime used. To achieve this, the runtime -// calls a special initialization routine exposed by the loaded module with the callbacks, -// which in turn calls InitUtilcode. -// -// This structure collects all of the critical callback info passed in InitUtilcode(). -//---------------------------------------------------------------------------------------- -struct CoreClrCallbacks -{ - typedef IExecutionEngine* (* pfnIEE_t)(); - typedef HRESULT (* pfnGetCORSystemDirectory_t)(SString& pbuffer); - - HINSTANCE m_hmodCoreCLR; - pfnIEE_t m_pfnIEE; - pfnGetCORSystemDirectory_t m_pfnGetCORSystemDirectory; -}; - - -// For DAC, we include this functionality only when EH SxS is enabled. - -//---------------------------------------------------------------------------------------- -// CoreCLR must invoke this before CRT initialization to ensure utilcode has all the callback -// pointers it needs. -//---------------------------------------------------------------------------------------- -VOID InitUtilcode(const CoreClrCallbacks &cccallbacks); -CoreClrCallbacks const & GetClrCallbacks(); - -//---------------------------------------------------------------------------------------- -// Stuff below is for utilcode.lib eyes only. -//---------------------------------------------------------------------------------------- - -// Stores callback pointers provided by InitUtilcode(). -extern CoreClrCallbacks g_CoreClrCallbacks; - -// Throws up a helpful dialog if InitUtilcode() wasn't called. -#ifdef _DEBUG -void OnUninitializedCoreClrCallbacks(); -#define VALIDATECORECLRCALLBACKS() if (g_CoreClrCallbacks.m_hmodCoreCLR == NULL) OnUninitializedCoreClrCallbacks() -#else //_DEBUG -#define VALIDATECORECLRCALLBACKS() -#endif //_DEBUG - +extern HINSTANCE g_hmodCoreCLR; #ifdef FEATURE_CORRUPTING_EXCEPTIONS @@ -4966,7 +4727,7 @@ namespace UtilCode // These are type-safe versions of Interlocked[Compare]Exchange // They avoid invoking struct cast operations via reinterpreting // the struct's address as a LONG* or LONGLONG* and dereferencing it. - // + // // If we had a global ::operator & (unary), we would love to use that // to ensure we were not also accidentally getting a structs's provided // operator &. TODO: probe with a static_assert? @@ -5001,7 +4762,7 @@ namespace UtilCode return *reinterpret_cast(&res); } }; - + template struct InterlockedCompareExchangeHelper { @@ -5030,7 +4791,7 @@ namespace UtilCode } }; } - + template inline T InterlockedExchangeT( T volatile * target, @@ -5075,41 +4836,10 @@ inline T* InterlockedCompareExchangeT( typedef typename std::remove_const::type * non_const_ptr_t; return reinterpret_cast(InterlockedCompareExchangePointer( reinterpret_cast(const_cast(destination)), - reinterpret_cast(const_cast(exchange)), + reinterpret_cast(const_cast(exchange)), reinterpret_cast(const_cast(comparand)))); } -// NULL pointer variants of the above to avoid having to cast NULL -// to the appropriate pointer type. -template -inline T* InterlockedExchangeT( - T* volatile * target, - int value) // When NULL is provided as argument. -{ - //STATIC_ASSERT(value == 0); - return InterlockedExchangeT(target, reinterpret_cast(value)); -} - -template -inline T* InterlockedCompareExchangeT( - T* volatile * destination, - int exchange, // When NULL is provided as argument. - T* comparand) -{ - //STATIC_ASSERT(exchange == 0); - return InterlockedCompareExchangeT(destination, reinterpret_cast(exchange), comparand); -} - -template -inline T* InterlockedCompareExchangeT( - T* volatile * destination, - T* exchange, - int comparand) // When NULL is provided as argument. -{ - //STATIC_ASSERT(comparand == 0); - return InterlockedCompareExchangeT(destination, exchange, reinterpret_cast(comparand)); -} - // NULL pointer variants of the above to avoid having to cast NULL // to the appropriate pointer type. template @@ -5141,6 +4871,37 @@ inline T* InterlockedCompareExchangeT( return InterlockedCompareExchangeT(destination, exchange, static_cast(comparand)); } +// NULL pointer variants of the above to avoid having to cast NULL +// to the appropriate pointer type. +template +inline T* InterlockedExchangeT( + T* volatile * target, + int value) // When NULL is provided as argument. +{ + //STATIC_ASSERT(value == 0); + return InterlockedExchangeT(target, nullptr); +} + +template +inline T* InterlockedCompareExchangeT( + T* volatile * destination, + int exchange, // When NULL is provided as argument. + T* comparand) +{ + //STATIC_ASSERT(exchange == 0); + return InterlockedCompareExchangeT(destination, nullptr, comparand); +} + +template +inline T* InterlockedCompareExchangeT( + T* volatile * destination, + T* exchange, + int comparand) // When NULL is provided as argument. +{ + //STATIC_ASSERT(comparand == 0); + return InterlockedCompareExchangeT(destination, exchange, nullptr); +} + #undef InterlockedExchangePointer #define InterlockedExchangePointer Use_InterlockedExchangeT #undef InterlockedCompareExchangePointer @@ -5157,27 +4918,8 @@ typedef void* (__cdecl *LocalizedFileHandler)(LPCWSTR); void* FindLocalizedFile(_In_z_ LPCWSTR wzResourceDllName, LocalizedFileHandler lfh, _In_opt_z_ LPCWSTR modulePath=NULL); - -// Helper to support termination due to heap corruption -// It's not supported on Win2K, so we have to manually delay load it -void EnableTerminationOnHeapCorruption(); - - - namespace Clr { namespace Util { - // This api returns a pointer to a null-terminated string that contains the local appdata directory - // or it returns NULL in the case that the directory could not be found. The return value from this function - // is not actually checked for existence. - HRESULT GetLocalAppDataDirectory(LPCWSTR *ppwzLocalAppDataDirectory); - HRESULT SetLocalAppDataDirectory(LPCWSTR pwzLocalAppDataDirectory); - -namespace Reg -{ - HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, SString & ssValue); - __success(return == S_OK) - HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, __deref_out __deref_out_z LPWSTR* pwszValue); -} #ifdef FEATURE_COMINTEROP namespace Com @@ -5186,29 +4928,6 @@ namespace Com } #endif // FEATURE_COMINTEROP -namespace Win32 -{ - static const WCHAR LONG_FILENAME_PREFIX_W[] = W("\\\\?\\"); - static const CHAR LONG_FILENAME_PREFIX_A[] = "\\\\?\\"; - - void GetModuleFileName( - HMODULE hModule, - SString & ssFileName, - bool fAllowLongFileNames = false); - - __success(return == S_OK) - HRESULT GetModuleFileName( - HMODULE hModule, - __deref_out_z LPWSTR * pwszFileName, - bool fAllowLongFileNames = false); - - void GetFullPathName( - SString const & ssFileName, - SString & ssPathName, - DWORD * pdwFilePartIdx, - bool fAllowLongFileNames = false); -} - }} #if defined(FEATURE_APPX) && !defined(DACCESS_COMPILE) @@ -5239,7 +4958,7 @@ namespace clr { //================================================================================================================= template - static inline + static inline typename std::enable_if< std::is_pointer::value, ItfT >::type SafeAddRef(ItfT pItf) { @@ -5286,7 +5005,7 @@ namespace clr { //================================================================================================================= template - static inline + static inline typename std::enable_if< std::is_pointer::value, PtrT >::type SafeDelete(PtrT & ptr) { diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/utsem.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/utsem.h index 91036db..0cacfcd 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/utsem.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/utsem.h @@ -32,32 +32,23 @@ class UTSemReadWrite public: UTSemReadWrite(); // Constructor ~UTSemReadWrite(); // Destructor - + HRESULT Init(); - + HRESULT LockRead(); // Lock the object for reading HRESULT LockWrite(); // Lock the object for writing void UnlockRead(); // Unlock the object for reading void UnlockWrite(); // Unlock the object for writing - + #ifdef _DEBUG BOOL Debug_IsLockedForRead(); BOOL Debug_IsLockedForWrite(); #endif //_DEBUG - + private: - Semaphore * GetReadWaiterSemaphore() - { - return m_pReadWaiterSemaphore; - } - Event * GetWriteWaiterEvent() - { - return m_pWriteWaiterEvent; - } - Volatile m_dwFlag; // internal state, see implementation - Semaphore * m_pReadWaiterSemaphore; // semaphore for awakening read waiters - Event * m_pWriteWaiterEvent; // event for awakening write waiters + HANDLE m_hReadWaiterSemaphore; // semaphore for awakening read waiters + HANDLE m_hWriteWaiterEvent; // event for awakening write waiters }; // class UTSemReadWrite #endif // __UTSEM_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/vererror.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/vererror.h deleted file mode 100644 index 2299b8e..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/vererror.h +++ /dev/null @@ -1,137 +0,0 @@ -// 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. - -/************************************************************************************** - ** ** - ** Vererror.h - definitions of data structures, needed to report verifier errors. ** - ** ** - **************************************************************************************/ - -#ifndef __VERERROR_h__ -#define __VERERROR_h__ - -#ifndef _VER_RAW_STRUCT_FOR_IDL_ -#ifndef _JIT64_PEV_ -#include "corhdr.h" -#include "openum.h" -#include "corerror.h" -#endif // !_JIT64_PEV_ - -// Set these flags if the error info fields are valid. - -#define VER_ERR_FATAL 0x80000000L // Cannot Continue -#define VER_ERR_OFFSET 0x00000001L -#define VER_ERR_OPCODE 0x00000002L -#define VER_ERR_OPERAND 0x00000004L -#define VER_ERR_TOKEN 0x00000008L -#define VER_ERR_EXCEP_NUM_1 0x00000010L -#define VER_ERR_EXCEP_NUM_2 0x00000020L -#define VER_ERR_STACK_SLOT 0x00000040L -#define VER_ERR_ITEM_1 0x00000080L -#define VER_ERR_ITEM_2 0x00000100L -#define VER_ERR_ITEM_F 0x00000200L -#define VER_ERR_ITEM_E 0x00000400L -#define VER_ERR_TYPE_1 0x00000800L -#define VER_ERR_TYPE_2 0x00001000L -#define VER_ERR_TYPE_F 0x00002000L -#define VER_ERR_TYPE_E 0x00004000L -#define VER_ERR_ADDL_MSG 0x00008000L - -#define VER_ERR_SIG_MASK 0x07000000L // Enum -#define VER_ERR_METHOD_SIG 0x01000000L -#define VER_ERR_LOCAL_SIG 0x02000000L -#define VER_ERR_FIELD_SIG 0x03000000L -#define VER_ERR_CALL_SIG 0x04000000L - -#define VER_ERR_OPCODE_OFFSET (VER_ERR_OPCODE|VER_ERR_OFFSET) - -#define VER_ERR_LOCAL_VAR VER_ERR_LOCAL_SIG -#define VER_ERR_ARGUMENT VER_ERR_METHOD_SIG - -#define VER_ERR_ARG_RET 0xFFFFFFFEL // The Argument # is return -#define VER_ERR_NO_ARG 0xFFFFFFFFL // Argument # is not valid -#define VER_ERR_NO_LOC VER_ERR_NO_ARG // Local # is not valid - -typedef struct -{ - DWORD dwFlags; // BYREF / BOXED etc.. see veritem.hpp - void* pv; // TypeHandle / MethodDesc * etc. -} _VerItem; - -// This structure is used to fully define a verification error. -// Verification error codes are found in CorError.h -// The error resource strings are found in src/dlls/mscorrc/mscor.rc - -typedef struct VerErrorStruct -{ - DWORD dwFlags; // VER_ERR_XXX - - union { -#ifndef _JIT64_PEV_ - OPCODE opcode; -#endif // !_JIT64_PEV_ - unsigned long padding1; // to match with idl generated struct size - }; - - union { - DWORD dwOffset; // #of bytes from start of method - long uOffset; // for backward compat with Metadata validator - }; - - union { - mdToken token; - mdToken Token; // for backward compat with metadata validator - BYTE bCallConv; - CorElementType elem; - DWORD dwStackSlot; // positon in the Stack - unsigned long padding2; // to match with idl generated struct size - }; - - union { - _VerItem sItem1; - _VerItem sItemFound; - WCHAR* wszType1; - WCHAR* wszTypeFound; - DWORD dwException1; // Exception Record # - DWORD dwVarNumber; // Variable # - DWORD dwArgNumber; // Argument # - DWORD dwOperand; // Operand for the opcode - WCHAR* wszAdditionalMessage; // message from getlasterror - }; - - union { - _VerItem sItem2; - _VerItem sItemExpected; - WCHAR* wszType2; - WCHAR* wszTypeExpected; - DWORD dwException2; // Exception Record # - }; - -} VerError; - -#else - -// Assert that sizeof(_VerError) == sizeof(VerError) in Verifier.cpp -typedef struct tag_VerError -{ - unsigned long flags; // DWORD - unsigned long opcode; // OPCODE, padded to ulong - unsigned long uOffset; // DWORD - unsigned long Token; // mdToken - unsigned long item1_flags; // _VerItem.DWORD - int *item1_data; // _VerItem.PVOID - unsigned long item2_flags; // _VerItem.DWORD - int *item2_data; // _VerItem.PVOID -} _VerError; -#endif - -#endif // __VERERROR_h__ - - - - - - - - diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/volatile.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/volatile.h index fa756ef..6c73dc4 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/volatile.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/volatile.h @@ -3,55 +3,55 @@ // See the LICENSE file in the project root for more information. // // Volatile.h -// +// -// +// // Defines the Volatile type, which provides uniform volatile-ness on // Visual C++ and GNU C++. -// +// // Visual C++ treats accesses to volatile variables as follows: no read or write // can be removed by the compiler, no global memory access can be moved backwards past // a volatile read, and no global memory access can be moved forward past a volatile // write. -// -// The GCC volatile semantic is straight out of the C standard: the compiler is not -// allowed to remove accesses to volatile variables, and it is not allowed to reorder -// volatile accesses relative to other volatile accesses. It is allowed to freely +// +// The GCC volatile semantic is straight out of the C standard: the compiler is not +// allowed to remove accesses to volatile variables, and it is not allowed to reorder +// volatile accesses relative to other volatile accesses. It is allowed to freely // reorder non-volatile accesses relative to volatile accesses. // -// We have lots of code that assumes that ordering of non-volatile accesses will be -// constrained relative to volatile accesses. For example, this pattern appears all +// We have lots of code that assumes that ordering of non-volatile accesses will be +// constrained relative to volatile accesses. For example, this pattern appears all // over the place: // // static volatile int lock = 0; // -// while (InterlockedCompareExchange(&lock, 0, 1)) +// while (InterlockedCompareExchange(&lock, 0, 1)) // { // //spin // } -// +// // //read and write variables protected by the lock // // lock = 0; // -// This depends on the reads and writes in the critical section not moving past the -// final statement, which releases the lock. If this should happen, then you have an +// This depends on the reads and writes in the critical section not moving past the +// final statement, which releases the lock. If this should happen, then you have an // unintended race. -// +// // The solution is to ban the use of the "volatile" keyword, and instead define our // own type Volatile, which acts like a variable of type T except that accesses to // the variable are always given VC++'s volatile semantics. -// -// (NOTE: The code above is not intended to be an example of how a spinlock should be -// implemented; it has many flaws, and should not be used. This code is intended only +// +// (NOTE: The code above is not intended to be an example of how a spinlock should be +// implemented; it has many flaws, and should not be used. This code is intended only // to illustrate where we might get into trouble with GCC's volatile semantics.) -// -// @TODO: many of the variables marked volatile in the CLR do not actually need to be +// +// @TODO: many of the variables marked volatile in the CLR do not actually need to be // volatile. For example, if a variable is just always passed to Interlocked functions -// (such as a refcount variable), there is no need for it to be volatile. A future +// (such as a refcount variable), there is no need for it to be volatile. A future // cleanup task should be to examine each volatile variable and make them non-volatile // if possible. -// +// // @TODO: link to a "Memory Models for CLR Devs" doc here (this doc does not yet exist). // @@ -61,37 +61,37 @@ #include "staticcontract.h" // -// This code is extremely compiler- and CPU-specific, and will need to be altered to +// This code is extremely compiler- and CPU-specific, and will need to be altered to // support new compilers and/or CPUs. Here we enforce that we can only compile using // VC++, or GCC on x86 or AMD64. -// +// #if !defined(_MSC_VER) && !defined(__GNUC__) #error The Volatile type is currently only defined for Visual C++ and GNU C++ #endif -#if defined(__GNUC__) && !defined(_X86_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) +#if defined(__GNUC__) && !defined(HOST_X86) && !defined(HOST_AMD64) && !defined(HOST_ARM) && !defined(HOST_ARM64) #error The Volatile type is currently only defined for GCC when targeting x86, AMD64, ARM or ARM64 CPUs #endif #if defined(__GNUC__) -#if defined(_ARM_) || defined(_ARM64_) +#if defined(HOST_ARM) || defined(HOST_ARM64) // This is functionally equivalent to the MemoryBarrier() macro used on ARM on Windows. #define VOLATILE_MEMORY_BARRIER() asm volatile ("dmb ish" : : : "memory") #else // // For GCC, we prevent reordering by the compiler by inserting the following after a volatile -// load (to prevent subsequent operations from moving before the read), and before a volatile +// load (to prevent subsequent operations from moving before the read), and before a volatile // write (to prevent prior operations from moving past the write). We don't need to do anything // special to prevent CPU reorderings, because the x86 and AMD64 architectures are already // sufficiently constrained for our purposes. If we ever need to run on weaker CPU architectures // (such as PowerPC), then we will need to do more work. -// +// // Please do not use this macro outside of this file. It is subject to change or removal without // notice. // #define VOLATILE_MEMORY_BARRIER() asm volatile ("" : : : "memory") -#endif // _ARM_ || _ARM64_ -#elif (defined(_ARM_) || defined(_ARM64_)) && _ISO_VOLATILE +#endif // HOST_ARM || HOST_ARM64 +#elif (defined(HOST_ARM) || defined(HOST_ARM64)) && _ISO_VOLATILE // ARM & ARM64 have a very weak memory model and very few tools to control that model. We're forced to perform a full // memory barrier to preserve the volatile semantics. Technically this is only necessary on MP systems but we // currently don't have a cheap way to determine the number of CPUs from this header file. Revisit this if it @@ -99,7 +99,7 @@ #define VOLATILE_MEMORY_BARRIER() MemoryBarrier() #else // -// On VC++, reorderings at the compiler and machine level are prevented by the use of the +// On VC++, reorderings at the compiler and machine level are prevented by the use of the // "volatile" keyword in VolatileLoad and VolatileStore. This should work on any CPU architecture // targeted by VC++ with /iso_volatile-. // @@ -129,6 +129,9 @@ struct RemoveVolatile // Starting at version 3.8, clang errors out on initializing of type int * to volatile int *. To fix this, we add two templates to cast away volatility // Helper structures for casting away volatileness +#if defined(HOST_ARM64) && defined(_MSC_VER) +#include +#endif template inline @@ -137,7 +140,7 @@ T VolatileLoad(T const * pt) STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; #ifndef DACCESS_COMPILE -#if defined(_ARM64_) && defined(__GNUC__) +#if defined(HOST_ARM64) && defined(__GNUC__) T val; static const unsigned lockFreeAtomicSizeMask = (1 << 1) | (1 << 2) | (1 << 4) | (1 << 8); if((1 << sizeof(T)) & lockFreeAtomicSizeMask) @@ -149,6 +152,33 @@ T VolatileLoad(T const * pt) val = *(T volatile const *)pt; asm volatile ("dmb ishld" : : : "memory"); } +#elif defined(HOST_ARM64) && defined(_MSC_VER) +// silence warnings on casts in branches that are not taken. +#pragma warning(push) +#pragma warning(disable : 4302) +#pragma warning(disable : 4311) +#pragma warning(disable : 4312) + T val; + T* pv = &val; + switch (sizeof(T)) + { + case 1: + *(unsigned __int8* )pv = __ldar8 ((unsigned __int8 volatile*)pt); + break; + case 2: + *(unsigned __int16*)pv = __ldar16((unsigned __int16 volatile*)pt); + break; + case 4: + *(unsigned __int32*)pv = __ldar32((unsigned __int32 volatile*)pt); + break; + case 8: + *(unsigned __int64*)pv = __ldar64((unsigned __int64 volatile*)pt); + break; + default: + val = *(T volatile const*)pt; + __dmb(_ARM64_BARRIER_ISHLD); + } +#pragma warning(pop) #else T val = *(T volatile const *)pt; VOLATILE_MEMORY_BARRIER(); @@ -197,7 +227,7 @@ void VolatileStore(T* pt, T val) STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; #ifndef DACCESS_COMPILE -#if defined(_ARM64_) && defined(__GNUC__) +#if defined(HOST_ARM64) && defined(__GNUC__) static const unsigned lockFreeAtomicSizeMask = (1 << 1) | (1 << 2) | (1 << 4) | (1 << 8); if((1 << sizeof(T)) & lockFreeAtomicSizeMask) { @@ -208,6 +238,32 @@ void VolatileStore(T* pt, T val) VOLATILE_MEMORY_BARRIER(); *(T volatile *)pt = val; } +#elif defined(HOST_ARM64) && defined(_MSC_VER) +// silence warnings on casts in branches that are not taken. +#pragma warning(push) +#pragma warning(disable : 4302) +#pragma warning(disable : 4311) +#pragma warning(disable : 4312) + T* pv = &val; + switch (sizeof(T)) + { + case 1: + __stlr8 ((unsigned __int8 volatile*)pt, *(unsigned __int8* )pv); + break; + case 2: + __stlr16((unsigned __int16 volatile*)pt, *(unsigned __int16*)pv); + break; + case 4: + __stlr32((unsigned __int32 volatile*)pt, *(unsigned __int32*)pv); + break; + case 8: + __stlr64((unsigned __int64 volatile*)pt, *(unsigned __int64*)pv); + break; + default: + __dmb(_ARM64_BARRIER_ISH); + *(T volatile *)pt = val; + } +#pragma warning(pop) #else VOLATILE_MEMORY_BARRIER(); *(T volatile *)pt = val; @@ -230,17 +286,38 @@ void VolatileStoreWithoutBarrier(T* pt, T val) #endif } +// +// Memory ordering barrier that waits for loads in progress to complete. +// Any effects of loads or stores that appear after, in program order, will "happen after" relative to this. +// Other operations such as computation or instruction prefetch are not affected. +// +// Architectural mapping: +// arm64 : dmb ishld +// arm : dmb ish +// x86/64 : compiler fence +inline +void VolatileLoadBarrier() +{ +#if defined(HOST_ARM64) && defined(__GNUC__) + asm volatile ("dmb ishld" : : : "memory"); +#elif defined(HOST_ARM64) && defined(_MSC_VER) + __dmb(_ARM64_BARRIER_ISHLD); +#else + VOLATILE_MEMORY_BARRIER(); +#endif +} + // // Volatile implements accesses with our volatile semantics over a variable of type T. -// Wherever you would have used a "volatile Foo" or, equivalently, "Foo volatile", use Volatile +// Wherever you would have used a "volatile Foo" or, equivalently, "Foo volatile", use Volatile // instead. If Foo is a pointer type, use VolatilePtr. -// +// // Note that there are still some things that don't work with a Volatile, // that would have worked with a "volatile T". For example, you can't cast a Volatile to a float. // You must instead cast to an int, then to a float. Or you can call Load on the Volatile, and -// cast the result to a float. In general, calling Load or Store explicitly will work around +// cast the result to a float. In general, calling Load or Store explicitly will work around // any problems that can't be solved by operator overloading. -// +// // @TODO: it's not clear that we actually *want* any operator overloading here. It's in here primarily // to ease the task of converting all of the old uses of the volatile keyword, but in the long // run it's probably better if users of this class are forced to call Load() and Store() explicitly. @@ -260,7 +337,7 @@ public: // // Default constructor. Results in an unitialized value! // - inline Volatile() + inline Volatile() { STATIC_CONTRACT_SUPPORTS_DAC; } @@ -268,7 +345,7 @@ public: // // Allow initialization of Volatile from a T // - inline Volatile(const T& val) + inline Volatile(const T& val) { STATIC_CONTRACT_SUPPORTS_DAC; ((volatile T &)m_val) = val; @@ -305,7 +382,7 @@ public: // Stores a new value to the volatile variable. See code:VolatileStore for the semantics of this // operation. // - inline void Store(const T& val) + inline void Store(const T& val) { STATIC_CONTRACT_SUPPORTS_DAC; VolatileStore(&m_val, val); @@ -340,7 +417,7 @@ public: // Allow casts from Volatile to T. Note that this allows implicit casts, so you can // pass a Volatile directly to a method that expects a T. // - inline operator T() const + inline operator T() const { STATIC_CONTRACT_SUPPORTS_DAC; return this->Load(); @@ -352,10 +429,10 @@ public: inline Volatile& operator=(T val) {Store(val); return *this;} // - // Get the address of the volatile variable. This is dangerous, as it allows the value of the + // Get the address of the volatile variable. This is dangerous, as it allows the value of the // volatile variable to be accessed directly, without going through Load and Store, but it is // necessary for passing Volatile to APIs like InterlockedIncrement. Note that we are returning - // a pointer to a volatile T here, so we cannot accidentally pass this pointer to an API that + // a pointer to a volatile T here, so we cannot accidentally pass this pointer to an API that // expects a normal pointer. // inline T volatile * operator&() {return this->GetPointer();} @@ -403,7 +480,7 @@ public: // // A VolatilePtr builds on Volatile by adding operators appropriate to pointers. // Wherever you would have used "Foo * volatile", use "VolatilePtr" instead. -// +// // VolatilePtr also allows the substution of other types for the underlying pointer. This // allows you to wrap a VolatilePtr around a custom type that looks like a pointer. For example, // if what you want is a "volatile DPTR", use "VolatilePtr>". @@ -415,7 +492,7 @@ public: // // Default constructor. Results in an uninitialized pointer! // - inline VolatilePtr() + inline VolatilePtr() { STATIC_CONTRACT_SUPPORTS_DAC; } @@ -423,7 +500,7 @@ public: // // Allow assignment from the pointer type. // - inline VolatilePtr(P val) : Volatile

(val) + inline VolatilePtr(P val) : Volatile

(val) { STATIC_CONTRACT_SUPPORTS_DAC; } @@ -431,7 +508,7 @@ public: // // Copy constructor // - inline VolatilePtr(const VolatilePtr& other) : Volatile

(other) + inline VolatilePtr(const VolatilePtr& other) : Volatile

(other) { STATIC_CONTRACT_SUPPORTS_DAC; } @@ -439,7 +516,7 @@ public: // // Cast to the pointer type // - inline operator P() const + inline operator P() const { STATIC_CONTRACT_SUPPORTS_DAC; return (P)this->Load(); @@ -448,7 +525,7 @@ public: // // Member access // - inline P operator->() const + inline P operator->() const { STATIC_CONTRACT_SUPPORTS_DAC; return (P)this->Load(); @@ -457,7 +534,7 @@ public: // // Dereference the pointer // - inline T& operator*() const + inline T& operator*() const { STATIC_CONTRACT_SUPPORTS_DAC; return *(P)this->Load(); @@ -467,7 +544,7 @@ public: // Access the pointer as an array // template - inline T& operator[](TIndex index) + inline T& operator[](TIndex index) { STATIC_CONTRACT_SUPPORTS_DAC; return ((P)this->Load())[index]; @@ -497,7 +574,7 @@ public: #else // Disable use of Volatile for GC/HandleTable code except on platforms where it's absolutely necessary. -#if defined(_MSC_VER) && !defined(_ARM_) && !defined(_ARM64_) +#if defined(_MSC_VER) && !defined(HOST_ARM) && !defined(HOST_ARM64) #define VOLATILE(T) T RAW_KEYWORD(volatile) #else #define VOLATILE(T) Volatile diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/vptr_list.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/vptr_list.h index 0476533..f53bbac 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/vptr_list.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/vptr_list.h @@ -5,11 +5,9 @@ // Any class with a vtable that needs to be instantiated // during debugging data access must be listed here. -VPTR_CLASS(Thread) - VPTR_CLASS(EEJitManager) -#ifdef FEATURE_PREJIT +#ifdef FEATURE_PREJIT VPTR_CLASS(NativeImageJitManager) #endif // FEATURE_PREJIT #ifdef FEATURE_READYTORUN @@ -20,7 +18,7 @@ VPTR_CLASS(EECodeManager) VPTR_CLASS(RangeList) VPTR_CLASS(LockedRangeList) -#ifdef EnC_SUPPORTED +#ifdef EnC_SUPPORTED VPTR_CLASS(EditAndContinueModule) #endif VPTR_CLASS(Module) @@ -41,18 +39,21 @@ VPTR_CLASS(RangeSectionStubManager) VPTR_CLASS(ILStubManager) VPTR_CLASS(InteropDispatchStubManager) VPTR_CLASS(DelegateInvokeStubManager) +#if defined(TARGET_X86) && !defined(UNIX_X86_ABI) VPTR_CLASS(TailCallStubManager) +#endif +VPTR_CLASS(CallCountingStubManager) VPTR_CLASS(PEFile) VPTR_CLASS(PEAssembly) VPTR_CLASS(PEImageLayout) VPTR_CLASS(RawImageLayout) VPTR_CLASS(ConvertedImageLayout) VPTR_CLASS(MappedImageLayout) -#if !defined(CROSSGEN_COMPILE) && !defined(FEATURE_PAL) +#if !defined(CROSSGEN_COMPILE) && !defined(TARGET_UNIX) VPTR_CLASS(LoadedImageLayout) -#endif // !CROSSGEN_COMPILE && !FEATURE_PAL +#endif // !CROSSGEN_COMPILE && !TARGET_UNIX VPTR_CLASS(FlatImageLayout) -#ifdef FEATURE_COMINTEROP +#ifdef FEATURE_COMINTEROP VPTR_CLASS(ComMethodFrame) VPTR_CLASS(ComPlusMethodFrame) VPTR_CLASS(ComPrestubMethodFrame) @@ -67,7 +68,6 @@ VPTR_CLASS(DebuggerExitFrame) VPTR_CLASS(DebuggerU2MCatchHandlerFrame) VPTR_CLASS(FaultingExceptionFrame) VPTR_CLASS(FuncEvalFrame) -VPTR_CLASS(GCFrame) VPTR_CLASS(HelperMethodFrame) VPTR_CLASS(HelperMethodFrame_1OBJ) VPTR_CLASS(HelperMethodFrame_2OBJ) @@ -77,7 +77,6 @@ VPTR_CLASS(HelperMethodFrame_PROTECTOBJ) VPTR_CLASS(HijackFrame) #endif VPTR_CLASS(InlinedCallFrame) -VPTR_CLASS(SecureDelegateFrame) VPTR_CLASS(MulticastFrame) VPTR_CLASS(PInvokeCalliFrame) VPTR_CLASS(PrestubMethodFrame) @@ -88,24 +87,24 @@ VPTR_CLASS(ResumableFrame) VPTR_CLASS(RedirectedThreadFrame) #endif VPTR_CLASS(StubDispatchFrame) +VPTR_CLASS(CallCountingHelperFrame) VPTR_CLASS(ExternalMethodFrame) #ifdef FEATURE_READYTORUN VPTR_CLASS(DynamicHelperFrame) #endif -#if !defined(_TARGET_X86_) -VPTR_CLASS(StubHelperFrame) -#endif -#if defined(_TARGET_X86_) +#if defined(TARGET_X86) VPTR_CLASS(UMThkCallFrame) #endif +#if defined(TARGET_X86) && !defined(UNIX_X86_ABI) VPTR_CLASS(TailCallFrame) +#endif VPTR_CLASS(ExceptionFilterFrame) #ifdef _DEBUG VPTR_CLASS(AssumeByrefFromJITStack) -#endif +#endif -#ifdef DEBUGGING_SUPPORTED +#ifdef DEBUGGING_SUPPORTED VPTR_CLASS(Debugger) VPTR_CLASS(EEDbgInterfaceImpl) #endif // DEBUGGING_SUPPORTED diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/warningcontrol.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/warningcontrol.h deleted file mode 100644 index e3b6f07..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/warningcontrol.h +++ /dev/null @@ -1,48 +0,0 @@ -// 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. -// -// warningcontrol.h -// -// Header file to globally control the warning settings for the entire Viper build. -// You do not need to explicitly include this file; rather, it gets included -// on the command line with a /FI (force include) directive. This is controlled -// in sources.vip. -// -// KEEP THIS LIST SORTED! -// - -#if defined(_MSC_VER) -#pragma warning(error :4007) // 'main' : must be __cdecl -#pragma warning(error :4013) // 'function' undefined - assuming extern returning int -#pragma warning(3 :4092) // sizeof returns 'unsigned long' -#pragma warning(error :4102) // "'%$S' : unreferenced label" -#pragma warning(3 :4121) // structure is sensitive to alignment -#pragma warning(3 :4125) // decimal digit in octal sequence -#pragma warning(3 :4130) // logical operation on address of string constant -#pragma warning(3 :4132) // const object should be initialized -#pragma warning(4 :4177) // pragma data_seg s/b at global scope -#pragma warning(3 :4212) // function declaration used ellipsis -#pragma warning(disable :4291) // delete not defined for new, c++ exception may cause leak -#pragma warning(disable :4302) // truncation from '%$S' to '%$S' -#pragma warning(disable :4311) // pointer truncation from '%$S' to '%$S' -#pragma warning(disable :4312) // '' : conversion from '%$S' to '%$S' of greater size -#pragma warning(disable :4477) // format string '%$S' requires an argument of type '%$S', but variadic argument %d has type '%$S' -#pragma warning(3 :4530) // C++ exception handler used, but unwind semantics are not enabled. Specify -GX -#pragma warning(error :4551) // Function call missing argument list - -#pragma warning(error :4700) // Local used w/o being initialized -#pragma warning(error :4806) // unsafe operation involving type 'bool' - -#if defined(_DEBUG) && (!defined(_MSC_FULL_VER) || (_MSC_FULL_VER <= 181040116)) -// The CLR header file check.h, macro CHECK_MSG_EX, can create unreachable code if the LEAVE_DEBUG_ONLY_CODE -// macro is not empty (such as it is defined in contract.h) and the _RESULT macro expands to "return". -// Checked-in compilers used by the TFS-based desktop build (e.g., version 18.10.40116.8) started reporting -// unreachable code warnings when debugholder.h was changed to no longer #define "return" to something relatively -// complex. However, newer compilers, such as Visual Studio 2015, used to build the CLR from the open source -// GitHub repo, still do not report this warning. We don't want to disable this warning for open source build, -// which will use a newer compiler. Hence, only disable it for older compilers. -#pragma warning(disable :4702) // unreachable code -#endif - -#endif // defined(_MSC_VER) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/win64unwind.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/win64unwind.h index e4cea02..d9477a9 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/win64unwind.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/win64unwind.h @@ -24,7 +24,7 @@ typedef enum _UNWIND_OP_CODES { UWOP_SAVE_XMM128_FAR, UWOP_PUSH_MACHFRAME, -#ifdef PLATFORM_UNIX +#ifdef TARGET_UNIX // UWOP_SET_FPREG_LARGE is a CLR Unix-only extension to the Windows AMD64 unwind codes. // It is not part of the standard Windows AMD64 unwind codes specification. // UWOP_SET_FPREG allows for a maximum of a 240 byte offset between RSP and the @@ -39,7 +39,7 @@ typedef enum _UNWIND_OP_CODES { // is established. Either UWOP_SET_FPREG or UWOP_SET_FPREG_LARGE can be used, but not both. UWOP_SET_FPREG_LARGE, -#endif // PLATFORM_UNIX +#endif // TARGET_UNIX } UNWIND_OP_CODES, *PUNWIND_OP_CODES; static const UCHAR UnwindOpExtraSlotTable[] = { @@ -55,9 +55,9 @@ static const UCHAR UnwindOpExtraSlotTable[] = { 2, // UWOP_SAVE_XMM128_FAR 0, // UWOP_PUSH_MACHFRAME -#ifdef PLATFORM_UNIX +#ifdef TARGET_UNIX 2, // UWOP_SET_FPREG_LARGE -#endif // PLATFORM_UNIX +#endif // TARGET_UNIX }; // @@ -89,13 +89,13 @@ typedef union _UNWIND_CODE { #define UNW_FLAG_UHANDLER 0x2 #define UNW_FLAG_CHAININFO 0x4 -#ifdef _TARGET_X86_ +#ifdef TARGET_X86 typedef struct _UNWIND_INFO { ULONG FunctionLength; } UNWIND_INFO, *PUNWIND_INFO; -#else // _TARGET_X86_ +#else // TARGET_X86 typedef struct _UNWIND_INFO { UCHAR Version : 3; @@ -122,5 +122,5 @@ typedef struct _UNWIND_INFO { } UNWIND_INFO, *PUNWIND_INFO; -#endif // _TARGET_X86_ +#endif // TARGET_X86 #endif // _WIN64UNWIND_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/winrt/ntassert.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/winrt/ntassert.h index 33a90a1..d6a2fd1 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/winrt/ntassert.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/winrt/ntassert.h @@ -45,7 +45,7 @@ DbgRaiseAssertionFailure ( #endif -#if defined(_AMD64_) +#if defined(HOST_AMD64) #if defined(_M_AMD64) @@ -64,7 +64,7 @@ __int2c ( #endif // defined(_M_AMD64) -#elif defined(_X86_) +#elif defined(HOST_X86) #if defined(_M_IX86) @@ -131,7 +131,7 @@ __break( #endif // defined(_M_IA64) -#elif defined(_ARM_) +#elif defined(HOST_ARM) #if defined(_M_ARM) @@ -150,7 +150,7 @@ __emit( #endif // defined(_M_ARM) -#endif // _AMD64_, _X86_, _IA64_, _ARM_ +#endif // HOST_AMD64, HOST_X86, _IA64_, HOST_ARM #endif // !defined(_DBGRAISEASSERTIONFAILURE_) && !defined(RC_INVOKED) && !defined(MIDL_PASS) #ifdef __cplusplus diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/winrt/paraminstanceapi.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/winrt/paraminstanceapi.h index ad3fd17..9f65aff 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/winrt/paraminstanceapi.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/winrt/paraminstanceapi.h @@ -7,14 +7,14 @@ * * Portions of this header fall under the following * copyrights and/or licenses: -* +* * rfc4122 and supporting functions * * Algorithm from RFC 4122 - A Universally Unique IDentifier (UUID) URN Namespace * * By Paul J. Leach, Michael Mealling and Rich Sals, July 2005. -* * +* * * * This function is adapted from the routines in the document * * uuid_create_sha1_from_name and format_uuid_v3or5 -* * +* * * * * * Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. * * Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & @@ -46,8 +46,8 @@ #ifdef _MSC_VER #pragma warning( push ) -#pragma warning( disable : 4180 ) // qualifier applied to function type has no meaning; ignored -#endif +#pragma warning( disable : 4180 ) // qualifier applied to function type has no meaning; ignored +#endif #include #include @@ -74,10 +74,10 @@ namespace Ro { namespace detail { - // - // Debugging aide. Set breakpoint on _FailedHR + // + // Debugging aide. Set breakpoint on _FailedHR // to see HRESULT propagation. - // + // #ifdef DEBUG inline HRESULT NOINLINE _FailedHR(HRESULT hr) { static HRESULT _hr = hr; return hr; } #else @@ -86,32 +86,32 @@ namespace Ro { namespace detail { }} #undef CHKHR -// +// // Call HRESULT returning code and propagate any errors. // Note: only use in code that is exception-safe / uses RAII. -// +// #define CHKHR(expr) \ { HRESULT _zzhr; \ _zzhr = expr; \ if (FAILED(_zzhr)) return Ro::detail::_FailedHR(_zzhr); } #undef CHKNT -// +// // Call NTSTATUS returning code and propagate any errors, as HRESULTs. -// Note: +// Note: // - only use in code that is exception-safe / uses RAII / RRID. -// - HRESULT_FROM_NT does safely convert STATUS_SUCCESS into +// - HRESULT_FROM_NT does safely convert STATUS_SUCCESS into // a SUCCEEDED hr. -// +// #define CHKNT(expr) \ CHKHR( HRESULT_FROM_NT( expr ) ) namespace Ro { namespace detail { - - // + + // // Runtime check for an invariant. This check executes in release builds. - // - + // + inline HRESULT Verify(bool invariant, HRESULT defaultHr = E_UNEXPECTED) { if (!invariant) @@ -130,7 +130,7 @@ extern "C" { // create hash instance HRESULT _RoSha1Create( - __out void** handle); + __out void** handle); // sha1 adaptor @@ -163,18 +163,18 @@ struct IRoMetaDataLocator; // The 'detail' namespace includes implementation details that // are subject to change without notice. namespace Ro { namespace detail -{ +{ struct SimpleMetaDataBuffer; }} // -// Purpose: -// Given a parameterized type instance name and metadata, +// Purpose: +// Given a parameterized type instance name and metadata, // computes the IID for that instance. -// +// // Parameters: -// +// // nameElementCount // number of elements in nameElements // nameElements @@ -182,38 +182,38 @@ namespace Ro { namespace detail // Eg: ["W.F.C.IVector`1", "N1.N2.IFoo"] // metaDataLocator // A callback to use for resolving metadata. -// +// // An implementation could, for example, forward all calls -// to RoGetMetaData, then passing the results to +// to RoGetMetaData, then passing the results to // RoWriteImporterToPushSimpleMetaData. As RoGetMetadata does // not cache results, such an implementation would be inefficient. // A better implementation will cache the results to RoGetMetaData, // as appropriate. // -// The Locator helper function can be used to wrap a lambda +// The Locator helper function can be used to wrap a lambda // expression, or function pointer. eg: // RoGetParameterizedTypeInstanceIID( -// ..., +// ..., // Locate([&](PCWSTR* name, IRoSimpleMetaDataBuilder& push){...}), // ...); // iid -// out param. Returns the iid for the parameterized type specified +// out param. Returns the iid for the parameterized type specified // by nameElements -// extra +// extra // out param. returns a handle that holds extra information about the // IID result, for diagnostic purposes. If this handle is not desired, // provide nullptr instead. -// +// // Notes: // - This function is stateless. IRoMetaDataLocator will not be preserved // between calls. -// - This function does not perform deep semantic analysis. For instance, +// - This function does not perform deep semantic analysis. For instance, // if IRoSimpleMetaDataBuilder specifies that a struct contains an interface pointer, // this API will return success, even though such metadata is semantically -// invalid. The value of the IID returned is unspecified in such cases. +// invalid. The value of the IID returned is unspecified in such cases. // - This function does introduce reentrancy. Its implementation // of IRoSimpleMetaDataBuilder may make reentrant calls to IRoMetaDataLocator. -// - If a call to IRoSimpleMetaDataBuilder fails, this function will return that +// - If a call to IRoSimpleMetaDataBuilder fails, this function will return that // failure code. // @@ -221,13 +221,13 @@ namespace Ro { namespace detail DECLARE_HANDLE(ROPARAMIIDHANDLE); inline HRESULT RoGetParameterizedTypeInstanceIID( - UINT32 nameElementCount, - __in_ecount(nameElementCount) PCWSTR* nameElements, - __in const IRoMetaDataLocator& metaDataLocator, + UINT32 nameElementCount, + __in_ecount(nameElementCount) PCWSTR* nameElements, + __in const IRoMetaDataLocator& metaDataLocator, __out GUID* iid, __deref_opt_out ROPARAMIIDHANDLE* pExtra = nullptr); -// Frees the 'extra' handle allocated +// Frees the 'extra' handle allocated // by RoGetParameterizedTypeInstanceIID inline void RoFreeParameterizedTypeExtra(__in ROPARAMIIDHANDLE extra); @@ -237,71 +237,71 @@ inline void RoFreeParameterizedTypeExtra(__in ROPARAMIIDHANDLE extra); // until RoFreeParameterizedTypeExtra is called on the extra pointer. inline PCSTR RoParameterizedTypeExtraGetTypeSignature(__in ROPARAMIIDHANDLE extra); -namespace Ro { namespace detail +namespace Ro { namespace detail { - - // private type used in helper function - + + // private type used in helper function + template struct _Locator; }} // namespace Ro::detail -namespace Ro +namespace Ro { - + // helper function to create IRoMetaDataLocator from lambda expression - + template Ro::detail::_Locator Locator(const Fn& fn); } // namespace Ro -// +// // Purpose: // Destination for IRoMetaDataLocator::Locate to write parsed metadata to. // 'Locate' should set the appropriate Windows Runtime metadata information gleaned // from Windows Runtime metadata file, or other appropriate source. -// +// // Notes: // - Methods for base types and COM interfaces (eg, Int32 and IInspectable -// respectively) are not needed -- RoGetParameterizedTypeInstanceIID already -// knows the WinRT base type names, so will not invoke IMetDataLocator -// to discover them. +// respectively) are not needed -- RoGetParameterizedTypeInstanceIID already +// knows the WinRT base type names, so will not invoke IMetDataLocator +// to discover them. // - This is not a COM interface. It does not derive from IUnknown. // struct IRoSimpleMetaDataBuilder { - - // Notes: + + // Notes: // IInspectable and other non-WinRT interfaces are not permissible. // Not for use with parameterized type instances. See SetParameterizedInterface - + STDMETHOD(SetWinRtInterface)( GUID iid) = 0; - - // Notes: + + // Notes: // Not for use with parameterized type instances. See SetParameterizedDelegate - + STDMETHOD(SetDelegate)( GUID iid) = 0; - + // Notes: - // Call this method when an interface group has a default interface + // Call this method when an interface group has a default interface // that is a non-parametric type. - + STDMETHOD(SetInterfaceGroupSimpleDefault)( PCWSTR name, PCWSTR defaultInterfaceName, __in_opt const GUID* defaultInterfaceIID) = 0; - + // Notes: - // Call this method when an interface group has a parameterized + // Call this method when an interface group has a parameterized // interface as its default interface. - + STDMETHOD(SetInterfaceGroupParameterizedDefault)( PCWSTR name, UINT32 elementCount, @@ -319,19 +319,19 @@ struct IRoSimpleMetaDataBuilder STDMETHOD(SetStruct)( PCWSTR name, - UINT32 numFields, + UINT32 numFields, __in_ecount(numFields) PCWSTR* fieldTypeNames) = 0; STDMETHOD(SetEnum)( PCWSTR name, PCWSTR baseType) = 0; - - - // Notes: - // This is only for the 'non-instantiated' parameterized interface itself - - // instances are handled by RoGetParameterizedTypeInstanceIID, and the + + + // Notes: + // This is only for the 'non-instantiated' parameterized interface itself - + // instances are handled by RoGetParameterizedTypeInstanceIID, and the // caller need not parse them. - + STDMETHOD(SetParameterizedInterface)( GUID piid, UINT32 numArgs) = 0; @@ -343,23 +343,23 @@ struct IRoSimpleMetaDataBuilder // -// Purpose: +// Purpose: // Callback for resolving metadata. -// +// struct IRoMetaDataLocator { - - // + + // // Parameters: // nameElement - // a metadata typeref name to resolve. + // a metadata typeref name to resolve. // Eg: "N1.N2.IFoo", or "W.F.C.IVector`1". // pushMetaData - // data sink for providing information about the + // data sink for providing information about the // type information for nameElement - // - + // + STDMETHOD(Locate)( PCWSTR nameElement, __in IRoSimpleMetaDataBuilder& metaDataDestination @@ -368,30 +368,30 @@ struct IRoMetaDataLocator namespace Ro { namespace detail { - - // + + // // helper function, moves range of elements - // - + // + template void _VecMoveRange( __in_ecount(size) T* dst, - __in_ecount(size) T* src, + __in_ecount(size) T* src, size_t size) { - for (size_t i = 0; i != size; ++i) + for (size_t i = 0; i != size; ++i) { dst[i] = static_cast(src[i]); } } - - // + + // // specializations to move strings more efficiently - // - + // + inline void _VecMoveRange( __in_ecount(size) char* dst, - __in_ecount(size) char* src, + __in_ecount(size) char* src, size_t size) { errno_t err = memcpy_s(dst, size*sizeof(*dst), src, size*sizeof(*dst)); @@ -400,7 +400,7 @@ namespace Ro { namespace detail { } inline void _VecMoveRange( __in_ecount(size) wchar_t* dst, - __in_ecount(size) wchar_t* src, + __in_ecount(size) wchar_t* src, size_t size) { errno_t err = memcpy_s(dst, size*sizeof(*dst), src, size*sizeof(*dst)); @@ -408,30 +408,30 @@ namespace Ro { namespace detail { (void)err; } - - // + + // // helper function, moves range of elements - // - + // + template void _VecCopyRange( __in_ecount(size) T* dst, - __in_ecount(size) const T* src, + __in_ecount(size) const T* src, size_t size) { - for (size_t i = 0; i != size; ++i) + for (size_t i = 0; i != size; ++i) { dst[i] = src[i]; } } - - // + + // // specializations to move strings more efficiently - // - + // + inline void _VecCopyRange( __in_ecount(size) char* dst, - __in_ecount(size) const char* src, + __in_ecount(size) const char* src, size_t size) { errno_t err = memcpy_s(dst, size*sizeof(*dst), const_cast(src), size*sizeof(*dst)); @@ -440,18 +440,18 @@ namespace Ro { namespace detail { } inline void _VecCopyRange( __in_ecount(size) wchar_t* dst, - __in_ecount(size) const wchar_t* src, + __in_ecount(size) const wchar_t* src, size_t size) { errno_t err = memcpy_s(dst, size*sizeof(*dst), const_cast(src), size*sizeof(*dst)); NT_ASSERT(!err); (void)err; } - - // + + // // Single-owner smart pointer for arrays - // - + // + template struct ArrayHolder { @@ -459,11 +459,11 @@ namespace Ro { namespace detail { { } T* Value() const - { + { return _value; } T*& Value() - { + { return _value; } T* Detach() @@ -480,11 +480,11 @@ namespace Ro { namespace detail { private: T* _value; }; - - // + + // // Single-owner smart pointer for object pointer - // - + // + template struct ElementHolder { @@ -496,11 +496,11 @@ namespace Ro { namespace detail { return _value; } T* Value() const - { + { return _value; } T*& Value() - { + { return _value; } T* Detach() @@ -519,43 +519,43 @@ namespace Ro { namespace detail { }; - - // + + // // simple vector, with small vector optimization // T - must be default constructable and movable. // const input overload of AppendN requires copyable. - // FixedBufSize - number of bytes to use for small array - // optimization, to avoid heap allocation in case of - // small vectors. Defaults to at least one element, - // otherwise the largest value such that <= 64 bytes + // FixedBufSize - number of bytes to use for small array + // optimization, to avoid heap allocation in case of + // small vectors. Defaults to at least one element, + // otherwise the largest value such that <= 64 bytes // are used. - // - + // + template < - typename T, + typename T, size_t FixedBufSize = 0 > class Vec { private: - static const size_t _fixedBufSize = - FixedBufSize/sizeof(T) + static const size_t _fixedBufSize = + FixedBufSize/sizeof(T) ? FixedBufSize/sizeof(T) - : (((64/sizeof(T)) > 0) ? (64/sizeof(T)) + : (((64/sizeof(T)) > 0) ? (64/sizeof(T)) : 1); public: - Vec() : - _size(0), - _cap(_countof(_fixedBuf)), + Vec() : + _size(0), + _cap(_countof(_fixedBuf)), _buf(_fixedBuf) { } - - // Appends an element, or a default value if one - // it not specified. If called with an rvalue, + + // Appends an element, or a default value if one + // it not specified. If called with an rvalue, // it uses move assignment instead of copy. - + HRESULT Append(T value = T()) { if (_cap - _size < 1) @@ -567,9 +567,9 @@ namespace Ro { namespace detail { return S_OK; } - + // Moves elements (move assignment) into array. - + HRESULT MoveN(__in_ecount(n) T* values, size_t n) { if (_cap - _size < n) @@ -581,10 +581,10 @@ namespace Ro { namespace detail { return S_OK; } - - + + // Appends elements. Does not invoke move assignment. - + HRESULT AppendN(__in_ecount(n) const T* values, size_t n) { if (_cap - _size < n) @@ -632,18 +632,18 @@ namespace Ro { namespace detail { ~Vec() { - if (_buf != _fixedBuf) + if (_buf != _fixedBuf) { delete[] _buf; } } private: - - // + + // // growth factor (does not check for overflow) -- returns amount to grow by - // - + // + static size_t _GrowthIncrement(size_t n) { return n / 2; @@ -657,21 +657,21 @@ namespace Ro { namespace detail { increase = byAtLeast; } size_t newCap = _cap + increase; - if (newCap <= _cap) + if (newCap <= _cap) { CHKHR(E_OUTOFMEMORY); } ArrayHolder newBuf; void* p = (newBuf.Value() = new (std::nothrow) T[newCap]); - if (!p) + if (!p) { CHKHR(E_OUTOFMEMORY); } _VecMoveRange( newBuf.Value(), _buf, _size ); - if (_buf != _fixedBuf) + if (_buf != _fixedBuf) { delete _buf; } @@ -690,7 +690,7 @@ namespace Ro { namespace detail { struct SimpleMetaDataBuilder : IRoSimpleMetaDataBuilder { public: - SimpleMetaDataBuilder(SimpleMetaDataBuffer& buffer, const IRoMetaDataLocator& locator) + SimpleMetaDataBuilder(SimpleMetaDataBuffer& buffer, const IRoMetaDataLocator& locator) : _buffer(&buffer), _locator(&locator), _invoked(false) { } @@ -705,42 +705,42 @@ namespace Ro { namespace detail { IFACEMETHOD(SetParameterizedInterface)(GUID piid, UINT32 numArgs); IFACEMETHOD(SetParameterizedDelegate)(GUID piid, UINT32 numArgs); - - // Runs the locating process for a parameterized type. + + // Runs the locating process for a parameterized type. // Notes: - // _buffer->_nestingLevel is used to determine the number of - // arguments left to consume for nested parameterized types. - + // _buffer->_nestingLevel is used to determine the number of + // arguments left to consume for nested parameterized types. + HRESULT SendArguments(UINT32 nameElementCount, __in_ecount(nameElementCount) PCWSTR *nameElements); private: - + // Writes the type signature for the type 'name' // Notes: // - If a builtin type, writes the type directly. - // - Otherwise, uses the IRoMetaDataLocator to + // - Otherwise, uses the IRoMetaDataLocator to // write the type signature into _buffer - // - As the sole function to call + // - As the sole function to call // IRoMetaDataLocator, it also performs the check // on recursion depth bounds. - + HRESULT _WriteType(PCWSTR name); - - // The tail portion of IG and RC formats is the same. This + + // The tail portion of IG and RC formats is the same. This // function implements the shared portion of that format. - + HRESULT _CommonInterfaceGroupSimple(PCWSTR name, PCWSTR defaultInterfaceName, __in_opt const GUID *defaultInterfaceIID); - - // Called at the beginning of every 'Set' method. Set must only be called once. - + + // Called at the beginning of every 'Set' method. Set must only be called once. + HRESULT _OnSet(); - - // Called at the end of every 'Set' method, only if successful. - + + // Called at the end of every 'Set' method, only if successful. + void _Completed(); static char _AsciiLower(char ch) @@ -755,9 +755,9 @@ namespace Ro { namespace detail { } } - + // Writes a guid into the type signature being built, in lower case. - + HRESULT _WriteGuid(const GUID& iid); HRESULT _WriteString(PCSTR str); HRESULT _WriteChar(char c); @@ -772,17 +772,17 @@ namespace Ro { namespace detail { bool _invoked; }; - - // If the type string describes a built-in type, modifies + + // If the type string describes a built-in type, modifies // this instance to use builtin type table entry instead of name. - + inline bool _IsBuiltin(__in PCWSTR name, __out PCSTR * typeSignature) { *typeSignature = nullptr; struct BuiltinEntry { PCWSTR name; PCSTR typeSignature; }; static const BuiltinEntry entries[] = { - + { L"UInt8", "u1" }, { L"Int16", "i2" }, { L"UInt16", "u2" }, @@ -808,24 +808,24 @@ namespace Ro { namespace detail { return true; } } - + // if not found, assume is a normal type name - + return false; } - + // Linked list (stack allocated) of type resolution calls, // used to detect if an InterfaceGroup/RuntimeClass type // signature depends on itself. In that case, we use "*" // in the type signature instead of recurring further. - + struct ResolutionPathEntry { ResolutionPathEntry* _next; PCWSTR _typeName; - ResolutionPathEntry(PCWSTR typeName) + ResolutionPathEntry(PCWSTR typeName) : _next(nullptr) , _typeName(typeName) { @@ -847,11 +847,11 @@ namespace Ro { namespace detail { return S_OK; } - + // Holds metadata state that is shared between RoGetParamInstanceIID and SimpleMetaDataBuilder - - struct SimpleMetaDataBuffer - { + + struct SimpleMetaDataBuffer + { SimpleMetaDataBuffer() { Clear(); @@ -868,18 +868,18 @@ namespace Ro { namespace detail { static const size_t _maxTypeName = 256; - - // Estimate of 'reasonable' level of Interface Group / Runtime + + // Estimate of 'reasonable' level of Interface Group / Runtime // Class / Parameterized Type nesting. - + static const size_t _maxRecursionDepth = 64; Vec _outputStream; ResolutionPathEntry* _resolutionPath; - + // RAII object, places an item on the resolution path, and pops it on destruction - + class ResolutionPathGuard { private: @@ -901,9 +901,9 @@ namespace Ro { namespace detail { } }; - + // Searches the resolution path for 'name' returning true if exists - + bool ExistsCycle(PCWSTR typeName) { for (auto pTip = _resolutionPath; pTip; pTip = pTip->_next) @@ -916,12 +916,12 @@ namespace Ro { namespace detail { return false; } - + // Indicates the nesting level of compound types, used // to properly balance parenthesis on parameterized types, // and used to bound recursion depth. - // - // - Pinterfaces + // + // - Pinterfaces // : push 'numArgs' on to _nestingLevel // - A compound type that doesn't know number of arguments // eg, RoGetParameterizedInstanceIID arguments, or @@ -929,37 +929,37 @@ namespace Ro { namespace detail { // : will 0) note nesting level // 1) iterate calling Locate on the compound arguments. // 2) the above should cause exactly one push of _nestingLevel - // 3) reduce nesting level back to original nesting level, + // 3) reduce nesting level back to original nesting level, // inserting the difference in closing parens // - Compound types that do know number of arguments (eg SetStruct) // : will 1) increase nesting level by 1 // 2) iterate calling Locate on arguments // 3) decrease nesting level again - // - // - + // + // + Vec _nestedArgs; - + // topLevelTypes should be incremented once, by the initial // parameterized type, then never again. - + size_t _topLevelTypes; size_t _recursionDepth; }; }} // namespace Ro::detail -namespace Ro { namespace detail +namespace Ro { namespace detail { template struct _Locator : IRoMetaDataLocator { Fn _fn; - _Locator(const Fn& fn) + _Locator(const Fn& fn) : _fn(fn) { } - + IFACEMETHOD(Locate)( PCWSTR name, IRoSimpleMetaDataBuilder& pushMetaData) const @@ -980,9 +980,9 @@ namespace Ro namespace Ro { namespace detail { - + // Figure out if we're compiling for a big- or little-endian machine. - + inline bool BigEndian() { unsigned long n = 0xff000000L; @@ -990,9 +990,9 @@ namespace Ro { namespace detail return 0 != *reinterpret_cast(&n); } - + // HostToNetworkLong converts a 32-bit long to network byte order - + inline ULONG HostToNetworkLong(ULONG hostlong) { if (BigEndian()) @@ -1004,9 +1004,9 @@ namespace Ro { namespace detail ( (hostlong << 24) & 0xFF000000L); } - + // HostToNetworkLong converts a 16-bit short to network byte order - + inline USHORT HostToNetworkShort(USHORT hostshort) { if (BigEndian()) @@ -1015,9 +1015,9 @@ namespace Ro { namespace detail return ((hostshort >> 8) & 0x00FF) | ((hostshort << 8) & 0xFF00); } - + // NetworkToHostLong converts a 32-bit long to local host byte order - + inline ULONG NetworkToHostLong(ULONG netlong) { if (BigEndian()) @@ -1029,9 +1029,9 @@ namespace Ro { namespace detail ( (netlong << 24) & 0xFF000000L); } - + // NetworkToHostShort converts a 16-bit short to local host byte order - + inline USHORT NetworkToHostShort(USHORT netshort) { if (BigEndian()) @@ -1040,9 +1040,9 @@ namespace Ro { namespace detail return ((netshort >> 8) & 0x00FF) | ((netshort << 8) & 0xFF00); } - + // smart pointer for Sha1 handle - + struct Sha1Holder { Sha1Holder() : _handle(nullptr) @@ -1063,17 +1063,17 @@ namespace Ro { namespace detail void* _handle; }; - - - // + + + // // Computes the rfc4122 v5 UUID from GUID,name pair. - // + // // Notes: // - see copyright at beginning of file. - // - + // + inline HRESULT - GuidFromName( + GuidFromName( __in const GUID& guidNamespace, __in_bcount(dwcbSize) const void* pbName, __in DWORD dwcbSize, @@ -1084,10 +1084,10 @@ namespace Ro { namespace detail CHKHR( _RoSha1Create(&sha1.Value()) ); { GUID networkOrderGuidNamespace = guidNamespace; - + // Put name space ID in network byte order so it hashes the same // no matter what endian machine we're on - + if (!BigEndian()) { networkOrderGuidNamespace.Data1 = HostToNetworkLong (networkOrderGuidNamespace.Data1); @@ -1101,13 +1101,13 @@ namespace Ro { namespace detail { BYTE sha1Result[20]; CHKHR( _RoSha1Finish(sha1.Value(), &sha1Result) ); - + errno_t err = memcpy_s(pGuid, sizeof(GUID), &sha1Result[0], sizeof(GUID)); CHKHR(Verify( 0 == err )); - + // Restore the byte order - + if (!BigEndian()) { pGuid->Data1 = NetworkToHostLong (pGuid->Data1); @@ -1115,28 +1115,28 @@ namespace Ro { namespace detail pGuid->Data3 = NetworkToHostShort(pGuid->Data3); } - - // set version number + + // set version number // 1: clear version number nibble // 2: set version 5 = name-based SHA1 - + pGuid->Data3 &= 0x0FFF; - pGuid->Data3 |= (5 << 12); - - + pGuid->Data3 |= (5 << 12); + + // set variant field by clearing variant bits. - - pGuid->Data4[0] &= 0x3F; - pGuid->Data4[0] |= 0x80; + + pGuid->Data4[0] &= 0x3F; + pGuid->Data4[0] |= 0x80; } return S_OK; } }} // namespace Ro::detail inline HRESULT RoGetParameterizedTypeInstanceIID( - UINT32 nameElementCount, - __in_ecount(nameElementCount) PCWSTR* nameElements, - __in const IRoMetaDataLocator& metaDataLocator, + UINT32 nameElementCount, + __in_ecount(nameElementCount) PCWSTR* nameElements, + __in const IRoMetaDataLocator& metaDataLocator, __out GUID* iid, __deref_opt_out ROPARAMIIDHANDLE* pExtra) { @@ -1146,7 +1146,7 @@ inline HRESULT RoGetParameterizedTypeInstanceIID( SimpleMetaDataBuffer reserveBuffer; SimpleMetaDataBuffer *pBuffer = &reserveBuffer; - // if user wishes to hold on to the result value, + // if user wishes to hold on to the result value, // dynamically allocate this buffer. if (pExtra) { @@ -1155,17 +1155,17 @@ inline HRESULT RoGetParameterizedTypeInstanceIID( } SimpleMetaDataBuffer& buffer = *pBuffer; SimpleMetaDataBuilder builder(*pBuffer, metaDataLocator); - + // send initial arguments CHKHR(builder.SendArguments(nameElementCount, nameElements)); // verify that precisely one type was resolved, to completion. - CHKHR(Verify(buffer._topLevelTypes == 1 + CHKHR(Verify(buffer._topLevelTypes == 1 && buffer._nestedArgs.Size() == 0, E_INVALIDARG)); // compute type signature hash - static const GUID guidPinterfaceNamespace + static const GUID guidPinterfaceNamespace = { 0x11f47ad5, 0x7b73, 0x42c0, { 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16, 0xad, 0xee }}; CHKHR(Ro::detail::Verify( buffer._outputStream.Size() <= DWORD(-1) )); @@ -1173,19 +1173,19 @@ inline HRESULT RoGetParameterizedTypeInstanceIID( // null terminate CHKHR( buffer._outputStream.Append('\0') ); - - // + + // // Unit test logging, to verify proper signatures - // + // #ifdef UNITTEST_TRACE { CHKHR( UNITTEST_TRACE("type signature", &buffer._outputStream[0]) ); } #endif - - CHKHR( GuidFromName(guidPinterfaceNamespace, - &buffer._outputStream[0], + + CHKHR( GuidFromName(guidPinterfaceNamespace, + &buffer._outputStream[0], DWORD(buffer._outputStream.Size() - 1), // does not include terminator iid) ); return S_OK; @@ -1203,8 +1203,8 @@ inline PCSTR RoParameterizedTypeExtraGetTypeSignature(__in ROPARAMIIDHANDLE extr return &pBuffer->_outputStream[0]; } - -namespace Ro { namespace detail + +namespace Ro { namespace detail { inline HRESULT SimpleMetaDataBuilder::_WriteType(PCWSTR name) @@ -1218,25 +1218,25 @@ namespace Ro { namespace detail CHKHR(builder._WriteString(builtInName)); builder._Completed(); } - else + else { size_t newDepth = ++_buffer->_recursionDepth; size_t pinterfaceNesting = _buffer->_nestedArgs.Size(); if (newDepth + pinterfaceNesting > _buffer->_maxRecursionDepth) { - + // Terminate recursion; bounds call stack consumption - + CHKHR(E_UNEXPECTED); } CHKHR(_locator->Locate(name, builder)); - + // Note, buffers aren't reusable, so it's fine that we don't // unwind this value on return. Also note, we do not unwind - // this value if the user provides inconsistent data either + // this value if the user provides inconsistent data either // (eg, if they provide only 1 argument to a 2 parameter // parameterized type). - + --_buffer->_recursionDepth; } return S_OK; @@ -1250,22 +1250,22 @@ namespace Ro { namespace detail } _invoked = true; - + // Reduce the number of arguments left for this compound type. - + if(_buffer->_nestedArgs.Size() > 0) { --(_buffer->_nestedArgs.Last()); } else { - + // Increase number of top level types in signature // string. (should never exceed one) - + ++_buffer->_topLevelTypes; } - + return S_OK; } @@ -1283,28 +1283,28 @@ namespace Ro { namespace detail { CHKHR(_WriteType(nameElements[i])); - + // Close any nested parameterized types that are complete - + while (_buffer->_nestedArgs.Size() > previousLevel && _buffer->_nestedArgs.Last() == 0) { CHKHR(_buffer->_nestedArgs.Pop()); CHKHR(_WriteChar(')')); } - + // insert separator between parameterized type arguments - + CHKHR(_WriteChar(';')); } - + // remove final separator - + CHKHR(_buffer->_outputStream.Pop()); - + // Verify that all the arguments were consumed. - + CHKHR(Verify(_buffer->_nestedArgs.Size() == previousLevel, E_INVALIDARG)); return S_OK; @@ -1320,13 +1320,13 @@ namespace Ro { namespace detail NT_ASSERT( numWritten == guidStringLength + 1 ); size_t offset = _buffer->_outputStream.Size(); - CHKHR(Verify( offset + guidStringLength > offset )) + CHKHR(Verify( offset + guidStringLength > offset )) CHKHR( _buffer->_outputStream.Resize(offset + guidStringLength) ); char* writePtr = &_buffer->_outputStream[offset]; - + // All characters are ascii. Just truncate. - + for(size_t i = 0; i < guidStringLength; ++i) { writePtr[i] = _AsciiLower(char(tmpString[i])); @@ -1349,9 +1349,9 @@ namespace Ro { namespace detail size_t offset = _buffer->_outputStream.Size(); int written; - + // provision enough space for conversion to take place - + size_t provision = len + 1; for(;;) { @@ -1378,7 +1378,7 @@ namespace Ro { namespace detail } else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - CHKHR(HRESULT_FROM_WIN32(GetLastError())); + CHKHR(HRESULT_FROM_WIN32(GetLastError())); } else { @@ -1386,13 +1386,13 @@ namespace Ro { namespace detail CHKHR(Verify( offset + provision > offset )); } } - - // reduce size to reflect number of characters actually written. - // Note that since we specified string length, no null terminator + + // reduce size to reflect number of characters actually written. + // Note that since we specified string length, no null terminator // was injected, so we don't have to remove it. - + CHKHR( _buffer->_outputStream.Resize(offset+written) ); - + return S_OK; } @@ -1415,22 +1415,22 @@ namespace Ro { namespace detail CHKHR(_WriteString("delegate(")); CHKHR(_WriteGuid(iid)); CHKHR(_WriteChar(')')); - + _Completed(); return S_OK; } - + inline HRESULT SimpleMetaDataBuilder::_CommonInterfaceGroupSimple( - PCWSTR name, - PCWSTR defaultInterfaceName, + PCWSTR name, + PCWSTR defaultInterfaceName, __in_opt const GUID * defaultInterfaceIID) { CHKHR(_WriteWideString(name)); CHKHR(_WriteChar(';')); - + // InterfaceGroups and RuntimeClasses take one nested argument - + CHKHR(_buffer->_nestedArgs.Append(1)); if (!defaultInterfaceIID) { @@ -1438,10 +1438,10 @@ namespace Ro { namespace detail } else { - - // complete the type signature immediately; no nested + + // complete the type signature immediately; no nested // call needed to resolve the interface. - + SimpleMetaDataBuilder builder(*_buffer, *_locator); CHKHR(builder.SetWinRtInterface(*defaultInterfaceIID)) } @@ -1449,7 +1449,7 @@ namespace Ro { namespace detail CHKHR(_buffer->_nestedArgs.Pop()); return S_OK; } - + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetInterfaceGroupSimpleDefault( PCWSTR name, PCWSTR defaultInterfaceName, @@ -1459,12 +1459,12 @@ namespace Ro { namespace detail CHKHR(_WriteString("ig(")); CHKHR(_CommonInterfaceGroupSimple(name, defaultInterfaceName, defaultInterfaceIID)); - + _Completed(); return S_OK; } - + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetInterfaceGroupParameterizedDefault( PCWSTR name, UINT32 elementCount, @@ -1472,12 +1472,12 @@ namespace Ro { namespace detail { CHKHR(_OnSet()); - - // If an interface group or runtime class has a compound type as its default, and that + + // If an interface group or runtime class has a compound type as its default, and that // type directly or indirectly refers to itself, the second occurrence instead used '*' // to signal that the default interface has already been specified earlier up the call // stack. This prevents unbounded recursion. - + if (_buffer->ExistsCycle(name)) { CHKHR( _WriteString("ig(") ); @@ -1492,9 +1492,9 @@ namespace Ro { namespace detail CHKHR( _WriteWideString(name) ); CHKHR( _WriteChar(';') ); - + // InterfaceGroups and RuntimeClasses take one nested argument - + CHKHR( _buffer->_nestedArgs.Append(1) ); CHKHR( SendArguments(elementCount, defaultInterfaceNameElements) ); CHKHR( _buffer->_nestedArgs.Pop() ); @@ -1504,7 +1504,7 @@ namespace Ro { namespace detail _Completed(); return S_OK; } - + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetRuntimeClassSimpleDefault( PCWSTR name, PCWSTR defaultInterfaceName, @@ -1519,7 +1519,7 @@ namespace Ro { namespace detail return S_OK; } - + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetRuntimeClassParameterizedDefault( PCWSTR name, UINT32 elementCount, @@ -1541,22 +1541,22 @@ namespace Ro { namespace detail CHKHR(_WriteWideString(name)); CHKHR(_WriteChar(';')); - + // InterfaceGroups and RuntimeClasses take one nested argument - + CHKHR(_buffer->_nestedArgs.Append(1)); CHKHR(SendArguments(elementCount, defaultInterfaceNameElements)); CHKHR(_buffer->_nestedArgs.Pop()); CHKHR(_WriteChar(')')); - } + } _Completed(); return S_OK; } - + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetStruct( PCWSTR name, - UINT32 numFields, + UINT32 numFields, __in_ecount(numFields) PCWSTR* fieldTypeNames) { CHKHR(_OnSet()); @@ -1573,7 +1573,7 @@ namespace Ro { namespace detail _Completed(); return S_OK; } - + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetEnum( PCWSTR name, PCWSTR baseType) @@ -1587,11 +1587,11 @@ namespace Ro { namespace detail CHKHR(_WriteType(baseType)); CHKHR(_buffer->_nestedArgs.Pop()); CHKHR(_WriteChar(')')); - + _Completed(); return S_OK; } - + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetParameterizedInterface( GUID piid, UINT32 numArgs) @@ -1601,24 +1601,24 @@ namespace Ro { namespace detail CHKHR(_WriteString("pinterface(")); CHKHR(_WriteGuid(piid)); - + // Note the number of arguments. The SendArguments - // function will append the ')' after that number of + // function will append the ')' after that number of // arguments are consumed. - + CHKHR(_buffer->_nestedArgs.Append(numArgs)); _Completed(); return S_OK; } - + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetParameterizedDelegate( GUID piid, UINT32 numArgs) { - + // Parameterized interfaces and parameterized delegates use the same signature scheme. - + return SetParameterizedInterface(piid, numArgs); } @@ -1670,9 +1670,9 @@ namespace Ro { namespace detail { } HRESULT GetResult(__out BYTE (*hashValue)[20]) { - + // Sha1 hash result is fixed size, at 20 bytes. - + CHKNT(BCryptFinishHash(_hHash, reinterpret_cast(&hashValue[0]), _countof(*hashValue), 0)); return S_OK; } @@ -1695,7 +1695,7 @@ namespace Ro { namespace detail { }; }} // namespace Ro::detail -extern "C" +extern "C" { inline HRESULT _RoSha1Create( diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/winrt/windowsstring.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/winrt/windowsstring.h index aa18eb6..f63fcdd 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/winrt/windowsstring.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/winrt/windowsstring.h @@ -71,24 +71,24 @@ namespace clr { STATIC_CONTRACT_LIMITED_METHOD; HRESULT hr = S_OK; - + if (nullptr == str) { // HSTRING functions promote null string pointers to the empty string, so we should too. str = L""; } - + size_t length = 0; if (SUCCEEDED(hr)) { hr = StringCchLengthW(str, STRSAFE_MAX_CCH, &length); } - + HSTRING local = nullptr; if (SUCCEEDED(hr)) { hr = WindowsCreateString(str, static_cast(length), &local); } - + return FreeAndAssignOnSuccess(hr, local, &_hstring); } @@ -158,14 +158,14 @@ namespace clr STATIC_CONTRACT_LIMITED_METHOD; return _hstring; } - + // Retrieve the address of the held hstring HSTRING* Address() { STATIC_CONTRACT_LIMITED_METHOD; return &_hstring; } - + // Return the address of the internal HSTRING so that the caller can overwrite it, // trusting that the caller will not leak the previously held value HSTRING* GetAddressOf() @@ -427,7 +427,7 @@ namespace clr { STATIC_CONTRACT_LIMITED_METHOD; HRESULT hr = WindowsCreateStringReference(stringRef, length, &_header, &_hstring); - + // Failfast if internal developers try to create a reference to a non-NUL terminated string if (FAILED(hr)) { @@ -486,7 +486,7 @@ namespace clr STATIC_CONTRACT_LIMITED_METHOD; return _hstring; } - + // CompareOrdinal INT32 CompareOrdinal(const String& other) const throw() { @@ -600,7 +600,7 @@ namespace clr STATIC_CONTRACT_LIMITED_METHOD; return reinterpret_cast(_hstring); } - + HSTRING _hstring; HSTRING_HEADER _header; }; @@ -677,7 +677,7 @@ HRESULT StringCchLength( return StringCchLengthW(wz == nullptr ? L"" : wz, size_t(STRSAFE_MAX_CCH), pcch); } -#ifdef _WIN64 +#ifdef HOST_64BIT // A UINT32-specific overload with built-in overflow check. inline HRESULT StringCchLength( @@ -686,15 +686,15 @@ HRESULT StringCchLength( { if (pcch == nullptr) return E_INVALIDARG; - + size_t cch; HRESULT hr = StringCchLength(wz, &cch); if (FAILED(hr)) return hr; - + return SizeTToUInt32(cch, pcch); } -#endif // _WIN64 +#endif // HOST_64BIT #ifndef DACCESS_COMPILE //===================================================================================================================== @@ -705,7 +705,7 @@ HRESULT StringCchLength( CoTaskMemHSTRINGArrayHolder() { LIMITED_METHOD_CONTRACT; - + m_cValues = 0; m_rgValues = nullptr; } @@ -714,39 +714,39 @@ HRESULT StringCchLength( LIMITED_METHOD_CONTRACT; Destroy(); } - + // Destroys current array and holds new array rgValues of size cValues. void Init(HSTRING * rgValues, DWORD cValues) { LIMITED_METHOD_CONTRACT; - + Destroy(); _ASSERTE(m_cValues == 0); - - _ASSERTE(((cValues == 0) && (rgValues == nullptr)) || + + _ASSERTE(((cValues == 0) && (rgValues == nullptr)) || ((cValues > 0) && (rgValues != nullptr))); - + m_rgValues = rgValues; m_cValues = cValues; } - + HSTRING GetAt(DWORD index) const { LIMITED_METHOD_CONTRACT; return m_rgValues[index]; } - + DWORD GetCount() { LIMITED_METHOD_CONTRACT; return m_cValues; } - + private: void Destroy() { LIMITED_METHOD_CONTRACT; - + for (DWORD i = 0; i < m_cValues; i++) { if (m_rgValues[i] != nullptr) @@ -755,14 +755,14 @@ HRESULT StringCchLength( } } m_cValues = 0; - + if (m_rgValues != nullptr) { CoTaskMemFree(m_rgValues); m_rgValues = nullptr; } } - + private: DWORD m_cValues; HSTRING * m_rgValues; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/winrtprojectedtypes.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/winrtprojectedtypes.h index 503e030..226aa44 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/winrtprojectedtypes.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/winrtprojectedtypes.h @@ -12,7 +12,7 @@ // * An ASCII string representing the name in winmd of the type being projected from // * An ASCII string representing the namespace in .NET which contains the type being projected to // * An ASCII string representing the name in .NET of the type being projected to -// * A symbol which is used to represent the assembly the .NET type is defined in +// * A symbol which is used to represent the assembly the .NET type is defined in // * A symbol which is used to represent the contract assembly the .NET type is defined in // * A symbol which is used to represent the WinRT type // * A symbol which is used to represent the .NET type @@ -22,7 +22,7 @@ // Optionally, the DEFINE_PROJECTED_RUNTIMECLASS, DEFINE_PROJECTED_STRUCT, DEFINE_PROJECTED_ENUM, DEFINE_PROJECTED_PINTERFACE, // DEFINE_PROJECTED_INTERFACE, and DEFINE_PROJECTED_ATTRIBUTE macros can be defined by the consumer of this header file, in // order to get extra information about the projected types. -// +// // Note that the input to these macros is in terms of the original winmd - so HResult is a DEFINE_PROJECTED_STRUCT even though it // projects to the class Exception. If you are adding a projection where the WinRT and CLR views differ upon if the type is a // value type or not, you'll need to update the signature rewriting code in md\winmd\adapter.cpp as well as the export code in @@ -62,7 +62,7 @@ #endif // !DEFINE_PROJECTED_JUPITER_STRUCT #ifndef STRUCT_FIELDS -#define STRUCT_FIELDS(...) __VA_ARGS__ +#define STRUCT_FIELDS(...) __VA_ARGS__ #endif // !STRUCT_FIELDS // DEFINE_PROJECTED_ENUM adds the following parameters: @@ -265,7 +265,7 @@ DEFINE_HIDDEN_WINRT_TYPE("Windows.Foundation", "IReferenceArray`1") #undef JUPITER_PROJECTION_NS #undef JUPITER_PROJECTION_CONTROLS_PRIMITIVES_NS -#undef JUPITER_PROJECTION_MEDIA_NS -#undef JUPITER_PROJECTION_MEDIA_ANIMATION_NS -#undef JUPITER_PROJECTION_MEDIA_3D_NS -#undef JUPITER_FOUNDATION_PROJECTION_NS +#undef JUPITER_PROJECTION_MEDIA_NS +#undef JUPITER_PROJECTION_MEDIA_ANIMATION_NS +#undef JUPITER_PROJECTION_MEDIA_3D_NS +#undef JUPITER_FOUNDATION_PROJECTION_NS diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/winwrap.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/winwrap.h index 1986e1d..e692ac7 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/winwrap.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/winwrap.h @@ -57,7 +57,6 @@ // winbase.h #undef GetBinaryType #undef GetShortPathName -#undef GetLongPathName #undef GetEnvironmentStrings #undef FreeEnvironmentStrings #undef FormatMessage @@ -94,20 +93,15 @@ #undef GetSystemDirectory #undef GetTempPath #undef GetTempFileName -#undef SetCurrentDirectory #undef GetCurrentDirectory -#undef CreateDirectory -#undef RemoveDirectory #undef GetFullPathName #undef CreateFile -#undef SetFileAttributes #undef GetFileAttributes #undef GetFileAttributesEx #undef DeleteFile #undef FindFirstFileEx #undef FindFirstFile #undef FindNextFile -#undef SearchPath #undef CopyFile #undef CopyFileEx #undef MoveFile @@ -125,7 +119,6 @@ #undef SendMessage #undef CharLower -#undef CharNext #undef MessageBox #undef GetClassName #undef LoadString @@ -144,11 +137,7 @@ // winbase.h #define WszGetEnvironmentStrings GetEnvironmentStringsW #define WszFreeEnvironmentStrings FreeEnvironmentStringsW -#ifndef USE_FORMATMESSAGE_WRAPPER #define WszFormatMessage FormatMessageW -#else -#define WszFormatMessage CCompRC::FormatMessage -#endif #define Wszlstrcmp lstrcmpW #define Wszlstrcmpi lstrcmpiW #define WszCreateMutex CreateMutexW @@ -181,7 +170,6 @@ #define WszGetMessage GetMessageW #define WszSendMessage SendMessageW #define WszCharLower CharLowerW -#define WszCharNext CharNextW #define WszMessageBox LateboundMessageBoxW #define WszGetClassName GetClassNameW #define WszLoadString LoadStringW @@ -228,21 +216,14 @@ #define WszLoadLibrary LoadLibraryExWrapper #define WszLoadLibraryEx LoadLibraryExWrapper #define WszCreateFile CreateFileWrapper -#define WszSetFileAttributes SetFileAttributesWrapper #define WszGetFileAttributes GetFileAttributesWrapper #define WszGetFileAttributesEx GetFileAttributesExWrapper #define WszDeleteFile DeleteFileWrapper #define WszFindFirstFileEx FindFirstFileExWrapper #define WszFindNextFile FindNextFileW -#define WszCopyFile CopyFileWrapper -#define WszCopyFileEx CopyFileExWrapper #define WszMoveFileEx MoveFileExWrapper -#define WszMoveFile(lpExistingFileName, lpNewFileName) WszMoveFileEx(lpExistingFileName, lpNewFileName, 0) -#define WszCreateDirectory CreateDirectoryWrapper -#define WszRemoveDirectory RemoveDirectoryWrapper -#define WszCreateHardLink CreateHardLinkWrapper -//Can not use extended syntax +//Can not use extended syntax #define WszGetFullPathName GetFullPathNameW //Long Files will not work on these till redstone @@ -253,21 +234,18 @@ //APIS which have a buffer as an out parameter #define WszGetEnvironmentVariable GetEnvironmentVariableWrapper #define WszSearchPath SearchPathWrapper -#define WszGetShortPathName GetShortPathNameWrapper -#define WszGetLongPathName GetLongPathNameWrapper #define WszGetModuleFileName GetModuleFileNameWrapper //NOTE: IF the following API's are enabled ensure that they can work with LongFile Names //See the usage and implementation of above API's // -//#define WszSetCurrentDirectory SetCurrentDirectoryW //#define WszGetBinaryType GetBinaryTypeWrapper //Coresys does not seem to have this API -#if FEATURE_PAL +#if HOST_UNIX #define WszFindFirstFile FindFirstFileW #else #define WszFindFirstFile(_lpFileName_, _lpFindData_) FindFirstFileExWrapper(_lpFileName_, FindExInfoStandard, _lpFindData_, FindExSearchNameMatch, NULL, 0) -#endif //FEATURE_PAL +#endif // HOST_UNIX //***************************************************************************** // Prototypes for API's. //***************************************************************************** @@ -280,21 +258,21 @@ inline DWORD GetMaxDBCSCharByteSize() { // contract.h not visible here __annotation(W("WRAPPER ") W("GetMaxDBCSCharByteSize")); -#ifndef FEATURE_PAL +#ifndef HOST_UNIX EnsureCharSetInfoInitialized(); _ASSERTE(g_dwMaxDBCSCharByteSize != 0); return (g_dwMaxDBCSCharByteSize); -#else // FEATURE_PAL +#else // HOST_UNIX return 3; -#endif // FEATURE_PAL +#endif // HOST_UNIX } -#ifndef FEATURE_PAL +#ifndef TARGET_UNIX BOOL RunningInteractive(); -#else // !FEATURE_PAL +#else // !TARGET_UNIX #define RunningInteractive() FALSE -#endif // !FEATURE_PAL +#endif // !TARGET_UNIX #ifndef Wsz_mbstowcs #define Wsz_mbstowcs(szOut, szIn, iSize) WszMultiByteToWideChar(CP_ACP, 0, szIn, -1, szOut, iSize) @@ -320,7 +298,7 @@ WszCreateProcess( LPPROCESS_INFORMATION lpProcessInformation ); -#if defined(_X86_) && defined(_MSC_VER) +#if defined(HOST_X86) && defined(_MSC_VER) // // Windows SDK does not use intrinsics on x86. Redefine the interlocked operations to use intrinsics. @@ -358,9 +336,9 @@ InterlockedCompareExchangePointer ( return((PVOID)(LONG_PTR)_InterlockedCompareExchange((LONG volatile *)Destination, (LONG)(LONG_PTR)ExChange, (LONG)(LONG_PTR)Comperand)); } -#endif // _X86_ && _MSC_VER +#endif // HOST_X86 && _MSC_VER -#if defined(_ARM_) & !defined(FEATURE_PAL) +#if defined(HOST_ARM) & !defined(HOST_UNIX) // // InterlockedCompareExchangeAcquire/InterlockedCompareExchangeRelease is not mapped in SDK to the correct intrinsics. Remove once // the SDK definition is fixed (OS Bug #516255) @@ -371,7 +349,7 @@ InterlockedCompareExchangePointer ( #define InterlockedCompareExchangeRelease _InterlockedCompareExchange_rel #endif -#if defined(_X86_) & !defined(InterlockedIncrement64) +#if defined(HOST_X86) & !defined(InterlockedIncrement64) // Interlockedxxx64 that do not have intrinsics are only supported on Windows Server 2003 // or higher for X86 so define our own portable implementation @@ -437,7 +415,7 @@ __forceinline LONGLONG __InterlockedExchangeAdd64(LONGLONG volatile * Addend, LO return Old; } -#endif // _X86_ +#endif // HOST_X86 // Output printf-style formatted text to the debugger if it's present or stdout otherwise. inline void DbgWPrintf(const LPCWSTR wszFormat, ...) @@ -472,7 +450,7 @@ inline int LateboundMessageBoxW(HWND hWnd, LPCWSTR lpCaption, UINT uType) { -#ifndef FEATURE_PAL +#ifndef HOST_UNIX // User32 should exist on all systems where displaying a message box makes sense. HMODULE hGuiExtModule = WszLoadLibrary(W("user32")); if (hGuiExtModule) @@ -485,7 +463,7 @@ inline int LateboundMessageBoxW(HWND hWnd, FreeLibrary(hGuiExtModule); return result; } -#endif // !FEATURE_PAL +#endif // !HOST_UNIX // No luck. Output the caption and text to the debugger if present or stdout otherwise. if (lpText == NULL) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/xclrdata.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/xclrdata.idl index fb3f19a..7054c7f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/xclrdata.idl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/xclrdata.idl @@ -135,7 +135,7 @@ typedef enum typedef enum { CLRDATA_FIELD_DEFAULT = 0x00000000, - + // Identify particular kinds of types. These flags // are shared between type, field and value. CLRDATA_FIELD_IS_PRIMITIVE = CLRDATA_TYPE_IS_PRIMITIVE, @@ -374,10 +374,10 @@ interface IXCLRLibrarySupport : IUnknown }; interface IXCLRDisassemblySupport; -typedef SIZE_T (__stdcall *CDSTranslateAddrCB)(IXCLRDisassemblySupport *, CLRDATA_ADDRESS, wchar_t *, SIZE_T, DWORDLONG *); -typedef SIZE_T (__stdcall *CDSTranslateFixupCB)(IXCLRDisassemblySupport *, CLRDATA_ADDRESS, SIZE_T, wchar_t *, SIZE_T, DWORDLONG *); -typedef SIZE_T (__stdcall *CDSTranslateConstCB)(IXCLRDisassemblySupport *, DWORD, wchar_t *, SIZE_T); -typedef SIZE_T (__stdcall *CDSTranslateRegrelCB)(IXCLRDisassemblySupport *, unsigned rega, CLRDATA_ADDRESS, wchar_t *, SIZE_T, DWORD *); +typedef SIZE_T (__stdcall *CDSTranslateAddrCB)(IXCLRDisassemblySupport *, CLRDATA_ADDRESS, WCHAR *, SIZE_T, DWORDLONG *); +typedef SIZE_T (__stdcall *CDSTranslateFixupCB)(IXCLRDisassemblySupport *, CLRDATA_ADDRESS, SIZE_T, WCHAR *, SIZE_T, DWORDLONG *); +typedef SIZE_T (__stdcall *CDSTranslateConstCB)(IXCLRDisassemblySupport *, DWORD, WCHAR *, SIZE_T); +typedef SIZE_T (__stdcall *CDSTranslateRegrelCB)(IXCLRDisassemblySupport *, unsigned rega, CLRDATA_ADDRESS, WCHAR *, SIZE_T, DWORD *); [ object, @@ -392,7 +392,7 @@ interface IXCLRDisassemblySupport : IUnknown SIZE_T CbDisassemble(CLRDATA_ADDRESS, const void *, SIZE_T); SIZE_T Cinstruction(); BOOL FSelectInstruction(SIZE_T); - SIZE_T CchFormatInstr(wchar_t *, SIZE_T); + SIZE_T CchFormatInstr(WCHAR *, SIZE_T); void *PvClient(); HRESULT SetTranslateFixupCallback([in]CDSTranslateFixupCB cb); HRESULT SetTranslateConstCallback([in]CDSTranslateConstCB cb); @@ -407,7 +407,7 @@ interface IXCLRDisassemblySupport : IUnknown [ object, local, - uuid(A3C1704A-4559-4a67-8D28-E8F4FE3B3F62) + uuid(A3C1704A-4559-4a67-8D28-E8F4FE3B3F62) ] interface IXCLRDataDisplay : IUnknown { @@ -454,9 +454,9 @@ interface IXCLRDataDisplay : IUnknown const WCHAR * const annotation ); //produces HRESULT WriteElementAddress(const char * const element, SIZE_T base, SIZE_T size); - HRESULT WriteElementAddressNamed(const char * const element, const char * const name, + HRESULT WriteElementAddressNamed(const char * const element, const char * const name, SIZE_T base, SIZE_T size); - HRESULT WriteElementAddressNamedW(const char * const element, const WCHAR * const name, + HRESULT WriteElementAddressNamedW(const char * const element, const WCHAR * const name, SIZE_T base, SIZE_T size); HRESULT WriteElementString(const char * const element, const char * const data); HRESULT WriteElementStringW(const char * const element, const WCHAR * const data); @@ -615,19 +615,19 @@ interface IXCLRDataProcess : IUnknown * the same target state. */ HRESULT IsSameObject([in] IXCLRDataProcess* process); - + /* * Get the managed object representing the process. */ HRESULT GetManagedObject([out] IXCLRDataValue** value); - + /* * Mark the process so that it attempts to reach the * desired execution state the next time it executes. */ HRESULT GetDesiredExecutionState([out] ULONG32* state); HRESULT SetDesiredExecutionState([in] ULONG32 state); - + /* * Return an indicator of the type of data referred * to by the given address. @@ -640,7 +640,7 @@ interface IXCLRDataProcess : IUnknown * the address refers to non-managed-method information. * Method names can be retrieved by using GetMethodInstanceByAddress * and GetName on the method instance. - * + * * Returns S_FALSE if the buffer is not large enough for the name, * and sets nameLen to be the buffer length needed. */ @@ -686,7 +686,7 @@ interface IXCLRDataProcess : IUnknown */ HRESULT GetModuleByAddress([in] CLRDATA_ADDRESS address, [out] IXCLRDataModule** mod); - + /* * Look up method instances by native code address. */ @@ -748,7 +748,7 @@ interface IXCLRDataProcess : IUnknown ULONG32 flags); HRESULT SetAllCodeNotifications(IXCLRDataModule* mod, ULONG32 flags); - + /* * Request notification when a type is * loaded or unloaded. @@ -770,7 +770,7 @@ interface IXCLRDataProcess : IUnknown [in, size_is(numTokens)] mdTypeDef tokens[], [in, size_is(numTokens)] ULONG32 flags[], [in] ULONG32 singleFlags); - + /* * Request notification when code is generated or * discarded for a method. @@ -799,7 +799,7 @@ interface IXCLRDataProcess : IUnknown */ HRESULT GetOtherNotificationFlags([out] ULONG32* flags); HRESULT SetOtherNotificationFlags([in] ULONG32 flags); - + /* * Look up method definitions by IL code address. */ @@ -842,7 +842,7 @@ interface IXCLRDataProcess : IUnknown /* * Types used in IXCLRDataProcess2 and IXCLRDataExceptionNotification3 */ - + typedef enum { GC_MARK_END = 1, @@ -871,7 +871,7 @@ interface IXCLRDataProcess2 : IXCLRDataProcess { /* * Request notification when a GC is triggered. - * GcEvtArgs specifies exactly which GC events + * GcEvtArgs specifies exactly which GC events * are of interest. */ /* @@ -909,7 +909,7 @@ interface IXCLRDataAppDomain : IUnknown [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR name[]); - /* + /* * Get a unique, stable identifier for this object. */ HRESULT GetUniqueID([out] ULONG64* id); @@ -918,13 +918,13 @@ interface IXCLRDataAppDomain : IUnknown * Get state flags, defined in CLRDataAppDomainFlag. */ HRESULT GetFlags([out] ULONG32* flags); - + /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataAppDomain* appDomain); - + /* * Get the managed object representing the app domain. */ @@ -979,13 +979,13 @@ interface IXCLRDataAssembly : IUnknown * Get state flags, defined in CLRDataAssemblyFlag. */ HRESULT GetFlags([out] ULONG32* flags); - + /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataAssembly* assembly); - + HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, @@ -1048,9 +1048,9 @@ typedef enum #pragma warning(push) #pragma warning(disable:28718) -/* +/* * Represents a loaded module. - * + * * Can be QI'd for a metadata interface or a symbol-store interface. */ [ @@ -1107,7 +1107,7 @@ interface IXCLRDataModule : IUnknown */ HRESULT GetTypeDefinitionByToken([in] mdTypeDef token, [out] IXCLRDataTypeDefinition** typeDefinition); - + /* * Look up methods by name. */ @@ -1117,7 +1117,7 @@ interface IXCLRDataModule : IUnknown HRESULT EnumMethodDefinitionByName([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataMethodDefinition** method); HRESULT EndEnumMethodDefinitionsByName([in] CLRDATA_ENUM handle); - + HRESULT StartEnumMethodInstancesByName([in] LPCWSTR name, [in] ULONG32 flags, [in] IXCLRDataAppDomain* appDomain, @@ -1125,7 +1125,7 @@ interface IXCLRDataModule : IUnknown HRESULT EnumMethodInstanceByName([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataMethodInstance** method); HRESULT EndEnumMethodInstancesByName([in] CLRDATA_ENUM handle); - + /* * Get a method definition by metadata token. */ @@ -1143,7 +1143,7 @@ interface IXCLRDataModule : IUnknown HRESULT EnumDataByName([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataValue** value); HRESULT EndEnumDataByName([in] CLRDATA_ENUM handle); - + /* * Get the module's base name. */ @@ -1163,13 +1163,13 @@ interface IXCLRDataModule : IUnknown * Get state flags, defined in CLRDataModuleFlag. */ HRESULT GetFlags([out] ULONG32* flags); - + /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataModule* mod); - + /* * Get the memory regions associated with this module. */ @@ -1201,9 +1201,9 @@ interface IXCLRDataModule : IUnknown #pragma warning(pop) -/* +/* * Represents additional APIs for a loaded module. - * + * */ [ object, @@ -1257,7 +1257,7 @@ interface IXCLRDataTypeDefinition : IUnknown */ HRESULT GetMethodDefinitionByToken([in] mdMethodDef token, [out] IXCLRDataMethodDefinition** methodDefinition); - + /* * Enumerate instances of this definition. */ @@ -1285,18 +1285,18 @@ interface IXCLRDataTypeDefinition : IUnknown * Get standard element type. */ HRESULT GetCorElementType([out] CorElementType* type); - + /* * Get state flags, defined in CLRDataTypeFlag. */ HRESULT GetFlags([out] ULONG32* flags); - + /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataTypeDefinition* type); - + HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, @@ -1354,7 +1354,7 @@ interface IXCLRDataTypeDefinition : IUnknown [out, size_is(nameBufLen)] WCHAR nameBuf[], [out] IXCLRDataTypeDefinition** type, [out] ULONG32* flags); - + /* * Request notification when the given type is * loaded or unloaded. @@ -1411,7 +1411,7 @@ interface IXCLRDataTypeInstance : IUnknown HRESULT EnumMethodInstanceByName([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataMethodInstance** method); HRESULT EndEnumMethodInstancesByName([in] CLRDATA_ENUM handle); - + /* * Get the number of static fields in the type. * OBSOLETE: Use GetNumStaticFields2. @@ -1475,13 +1475,13 @@ interface IXCLRDataTypeInstance : IUnknown * Get state flags, defined in CLRDataTypeFlag. */ HRESULT GetFlags([out] ULONG32* flags); - + /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataTypeInstance* type); - + HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, @@ -1640,12 +1640,12 @@ interface IXCLRDataMethodDefinition : IUnknown * the same target state. */ HRESULT IsSameObject([in] IXCLRDataMethodDefinition* method); - + /* * Get the latest EnC version of this method. */ HRESULT GetLatestEnCVersion([out] ULONG32* version); - + /* * Get the IL code regions associated with this method. */ @@ -1653,14 +1653,14 @@ interface IXCLRDataMethodDefinition : IUnknown HRESULT EnumExtent([in, out] CLRDATA_ENUM* handle, [out] CLRDATA_METHDEF_EXTENT* extent); HRESULT EndEnumExtents([in] CLRDATA_ENUM handle); - + /* * Request notification when code is generated or * discarded for the method. */ HRESULT GetCodeNotification([out] ULONG32* flags); HRESULT SetCodeNotification([in] ULONG32 flags); - + HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, @@ -1717,18 +1717,18 @@ interface IXCLRDataMethodInstance : IUnknown * Get state flags, defined in CLRDataMethodFlag. */ HRESULT GetFlags([out] ULONG32* flags); - + /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataMethodInstance* method); - + /* * Get the EnC version of this instance. */ HRESULT GetEnCVersion([out] ULONG32* version); - + /* * Enumerate this method's parameterization. */ @@ -1742,12 +1742,12 @@ interface IXCLRDataMethodInstance : IUnknown HRESULT GetILOffsetsByAddress([in] CLRDATA_ADDRESS address, [in] ULONG32 offsetsLen, [out] ULONG32 *offsetsNeeded, - [out, size_is(offsetsLen)] + [out, size_is(offsetsLen)] ULONG32 ilOffsets[]); HRESULT GetAddressRangesByILOffset([in] ULONG32 ilOffset, [in] ULONG32 rangesLen, [out] ULONG32 *rangesNeeded, - [out, size_is(rangesLen)] + [out, size_is(rangesLen)] CLRDATA_ADDRESS_RANGE addressRanges[]); HRESULT GetILAddressMap([in] ULONG32 mapLen, [out] ULONG32 *mapNeeded, @@ -1761,7 +1761,7 @@ interface IXCLRDataMethodInstance : IUnknown HRESULT EnumExtent([in, out] CLRDATA_ENUM* handle, [out] CLRDATA_ADDRESS_RANGE* extent); HRESULT EndEnumExtents([in] CLRDATA_ENUM handle); - + HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, @@ -1797,8 +1797,8 @@ typedef enum ] interface IXCLRDataTask : IUnknown { - /* - * Get the process for this task. + /* + * Get the process for this task. */ HRESULT GetProcess([out] IXCLRDataProcess** process); @@ -1808,7 +1808,7 @@ interface IXCLRDataTask : IUnknown */ HRESULT GetCurrentAppDomain([out] IXCLRDataAppDomain **appDomain); - /* + /* * Get a unique, stable identifier for this task. */ HRESULT GetUniqueID([out] ULONG64* id); @@ -1823,19 +1823,19 @@ interface IXCLRDataTask : IUnknown * the same target state. */ HRESULT IsSameObject([in] IXCLRDataTask* task); - + /* * Get the managed object representing the task. */ HRESULT GetManagedObject([out] IXCLRDataValue** value); - + /* * Mark the task so that it attempts to reach the * given execution state the next time it executes. */ HRESULT GetDesiredExecutionState([out] ULONG32* state); HRESULT SetDesiredExecutionState([in] ULONG32 state); - + /* * Create a stack walker to walk this task's stack. The * flags parameter takes a bitfield of values from the @@ -1844,13 +1844,13 @@ interface IXCLRDataTask : IUnknown HRESULT CreateStackWalk([in] ULONG32 flags, [out] IXCLRDataStackWalk** stackWalk); - /* + /* * Get the current OS thread ID for this task. If this task is on a fiber, - * the ID may change over time. + * the ID may change over time. */ HRESULT GetOSThreadID([out] ULONG32* id); - /* + /* * Get the current context for this task, controlled by the given flags. * Returns S_FALSE if the size is not large enough. */ @@ -1859,7 +1859,7 @@ interface IXCLRDataTask : IUnknown [out] ULONG32* contextSize, [out, size_is(contextBufSize)] BYTE contextBuf[]); - /* + /* * Destructively set the current context for this task. */ HRESULT SetContext([in] ULONG32 contextSize, @@ -1901,10 +1901,10 @@ interface IXCLRDataTask : IUnknown typedef enum { /* Frame not recognized */ - CLRDATA_SIMPFRAME_UNRECOGNIZED = 0x1, + CLRDATA_SIMPFRAME_UNRECOGNIZED = 0x1, /* Frame corresponds to a managed method */ - CLRDATA_SIMPFRAME_MANAGED_METHOD = 0x2, + CLRDATA_SIMPFRAME_MANAGED_METHOD = 0x2, /* Frame corresponds to runtime-controlled managed code */ CLRDATA_SIMPFRAME_RUNTIME_MANAGED_CODE = 0x4, @@ -1923,7 +1923,7 @@ typedef enum CLRDATA_DETFRAME_EXCEPTION_FILTER, CLRDATA_DETFRAME_SECURITY, CLRDATA_DETFRAME_CONTEXT_POLICY, - CLRDATA_DETFRAME_INTERCEPTION, + CLRDATA_DETFRAME_INTERCEPTION, CLRDATA_DETFRAME_PROCESS_START, CLRDATA_DETFRAME_THREAD_START, CLRDATA_DETFRAME_TRANSITION_TO_MANAGED, @@ -1967,7 +1967,7 @@ typedef enum ] interface IXCLRDataStackWalk : IUnknown { - /* + /* * Get the current context of this stack walk. * This is the original context with any unwinding * applied to it. As unwinding may only restore @@ -1980,7 +1980,7 @@ interface IXCLRDataStackWalk : IUnknown [out] ULONG32* contextSize, [out, size_is(contextBufSize)] BYTE contextBuf[]); - /* + /* * Change the current context of this stack walk, allowing the * debugger to move it to an arbitrary context. Does not actually * alter the current context of the thread whose stack is being walked. @@ -2013,7 +2013,7 @@ interface IXCLRDataStackWalk : IUnknown */ HRESULT GetStackSizeSkipped([out] ULONG64* stackSizeSkipped); - /* + /* * Return information about the type of the current frame */ HRESULT GetFrameType([out] CLRDataSimpleFrameType* simpleType, @@ -2030,7 +2030,7 @@ interface IXCLRDataStackWalk : IUnknown [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); - /* + /* * Change the current context of this stack walk, allowing the * debugger to move it to an arbitrary context. Does not actually * alter the current context of the thread whose stack is being walked. @@ -2049,13 +2049,13 @@ interface IXCLRDataStackWalk : IUnknown ] interface IXCLRDataFrame : IUnknown { - /* + /* * Return information about the type of this frame. */ HRESULT GetFrameType([out] CLRDataSimpleFrameType* simpleType, [out] CLRDataDetailedFrameType* detailedType); - /* + /* * Get the stack walk context as of this frame. * This is the original context with any unwinding * applied to it. As unwinding may only restore @@ -2125,7 +2125,7 @@ interface IXCLRDataFrame : IUnknown [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); - + /* * Enumerate the full parameterization of the frame's * type and method. @@ -2143,7 +2143,7 @@ interface IXCLRDataFrame : IUnknown ] interface IXCLRDataFrame2 : IUnknown { - /* + /* * Retun generic token if available. */ HRESULT GetExactGenericArgsToken([out] IXCLRDataValue** genericToken); @@ -2189,7 +2189,7 @@ interface IXCLRDataExceptionState : IUnknown * Get state flags, defined in CLRDataExceptionStateFlag. */ HRESULT GetFlags([out] ULONG32* flags); - + /* * For nested exceptions, get the exception that * was being handled when this exception occurred. @@ -2200,7 +2200,7 @@ interface IXCLRDataExceptionState : IUnknown * Get the managed object representing the exception. */ HRESULT GetManagedObject([out] IXCLRDataValue** value); - + /* * Get the standard base type of the exception. */ @@ -2213,7 +2213,7 @@ interface IXCLRDataExceptionState : IUnknown HRESULT GetString([in] ULONG32 bufLen, [out] ULONG32 *strLen, [out, size_is(bufLen)] WCHAR str[]); - + HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, @@ -2270,7 +2270,7 @@ interface IXCLRDataValue : IUnknown * Get state flags, defined in CLRDataValueFlag. */ HRESULT GetFlags([out] ULONG32* flags); - + /* * Get the address of the object. * Fails unless the object is a single contiguous @@ -2301,13 +2301,13 @@ interface IXCLRDataValue : IUnknown */ HRESULT GetType([out] IXCLRDataTypeInstance **typeInstance); - /* + /* * Get the number of fields in the object. * OBSOLETE: Use GetNumFields2. */ HRESULT GetNumFields([out] ULONG32 *numFields); - /* + /* * Gets one field of the object. * * Because field ordering is not fixed, can also return name @@ -2390,12 +2390,12 @@ interface IXCLRDataValue : IUnknown * For other values there is no associated type. */ HRESULT GetAssociatedType([out] IXCLRDataTypeInstance** assocType); - + /* * String methods that only work for string data values. */ - /* + /* * Return the length and contents of the string. */ HRESULT GetString([in] ULONG32 bufLen, @@ -2518,7 +2518,7 @@ interface IXCLRDataExceptionNotification2 : IXCLRDataExceptionNotification interface IXCLRDataExceptionNotification3 : IXCLRDataExceptionNotification2 { /* - * The specified GC event was triggered. The GC event is passed in an + * The specified GC event was triggered. The GC event is passed in an * opaque structure, whose structure is given by buffSize */ HRESULT OnGcEvent([in] GcEvtArgs gcEvtArgs); @@ -2545,8 +2545,8 @@ interface IXCLRDataExceptionNotification4 : IXCLRDataExceptionNotification3 interface IXCLRDataExceptionNotification5 : IXCLRDataExceptionNotification4 { /* - * New code was generated for a method. The given address is the start address of + * New code was generated for a method. The given address is the start address of * the native newly jitted code. */ HRESULT OnCodeGenerated2([in] IXCLRDataMethodInstance* method, [in] CLRDATA_ADDRESS nativeCodeLocation); -} \ No newline at end of file +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/xcordebug.idl b/CoreCLRProfiler/native/coreclr_headers/src/inc/xcordebug.idl index ef9128b..8f4b5bb 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/xcordebug.idl +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/xcordebug.idl @@ -17,12 +17,12 @@ import "cordebug.idl"; -// @dbgtodo : proper API docs here. +// @dbgtodo : proper API docs here. // - include failure semantics of Filter. What does failure mean? -// +// /* Comments to add to ICorDebugDataTarget docs: * Whenever the target process changes, the debugger client must - * call ICorDebugProcess4::ProcessStateChanged before issuing any other + * call ICorDebugProcess4::ProcessStateChanged before issuing any other * ICorDebug API calls. */ [ @@ -34,20 +34,20 @@ import "cordebug.idl"; interface ICorDebugProcess4 : IUnknown { /* - * Process native debug events. + * Process native debug events. */ HRESULT Filter( [in, length_is(countBytes), size_is(countBytes)] const BYTE pRecord[], [in] DWORD countBytes, [in] CorDebugRecordFormat format, - [in] DWORD dwFlags, - [in] DWORD dwThreadId, + [in] DWORD dwFlags, + [in] DWORD dwThreadId, [in] ICorDebugManagedCallback * pCallback, [in, out] CORDB_CONTINUE_STATUS * pContinueStatus); /* * Debugger calls this to notify ICorDebug that the process is running. - * + * * Notes: * ProcessStateChanged(PROCESS_RUNNING) has similar semantics to ICorDebugProcess::Continue(); */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/inc/zapper.h b/CoreCLRProfiler/native/coreclr_headers/src/inc/zapper.h index 29fc4fb..159f5fe 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/inc/zapper.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/inc/zapper.h @@ -71,7 +71,7 @@ class Zapper ICorJitCompiler *m_pJitCompiler; IMetaDataDispenserEx *m_pMetaDataDispenser; HMODULE m_hJitLib; -#ifdef _TARGET_AMD64_ +#ifdef TARGET_AMD64 HMODULE m_hJitLegacy; #endif @@ -304,8 +304,8 @@ class Zapper void DefineOutputAssembly(SString& strAssemblyName, ULONG * pHashAlgId); HRESULT Compile(LPCWSTR path, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig = NULL); - void DontUseProfileData(); - bool HasProfileData(); + void DontUseProfileData(); + bool HasProfileData(); void CompileAssembly(CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig); ZapImage * CompileModule(CORINFO_MODULE_HANDLE hModule, @@ -331,11 +331,11 @@ class Zapper BOOL *pfHitMismatchedVersion, BOOL *pfHitMismatchedDependencies, BOOL useHardLink = FALSE); - void CopyAndInstallFromRepository(LPCWSTR lpszNativeImageDir, - LPCWSTR lpszNativeImageName, + void CopyAndInstallFromRepository(LPCWSTR lpszNativeImageDir, + LPCWSTR lpszNativeImageName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig, BOOL useHardLink = FALSE); - void InstallFromRepository(LPCWSTR lpszNativeImage, + void InstallFromRepository(LPCWSTR lpszNativeImage, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig); void CopyDirectory(LPCWSTR srcPath, LPCWSTR dstPath); @@ -425,7 +425,7 @@ class ZapperOptions bool m_ignoreProfileData; // Don't use profile data bool m_noProcedureSplitting; // Don't do procedure splitting - bool m_fHasAnyProfileData; // true if we successfully loaded and used + bool m_fHasAnyProfileData; // true if we successfully loaded and used // any profile data when compiling this assembly bool m_fPartialNGen; // Generate partial NGen images using IBC data diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/CMakeLists.txt new file mode 100644 index 0000000..ca4a35d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/CMakeLists.txt @@ -0,0 +1,17 @@ +project(COREPAL) + +include(../../clrfeatures.cmake) + +include_directories(${COREPAL_SOURCE_DIR}/inc) +include_directories(${COREPAL_SOURCE_DIR}/src) +include_directories(${COREPAL_SOURCE_DIR}/../inc) + +add_compile_options(-fexceptions) +add_definitions(-DUSE_STL) + +add_subdirectory(src) + +if(CLR_CMAKE_BUILD_TESTS) + add_subdirectory(tests) +endif(CLR_CMAKE_BUILD_TESTS) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/mbusafecrt.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/mbusafecrt.h index abc2dca..663d032 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/mbusafecrt.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/mbusafecrt.h @@ -28,7 +28,7 @@ typedef int errno_t; /* errno value that specific to SafeCRT */ #define STRUNCATE 80 -// define the return value for success +// define the return value for success #define SAFECRT_SUCCESS 0 #ifndef THROW_DECL @@ -76,12 +76,8 @@ extern errno_t _ltow_s( long inValue, WCHAR* outBuffer, size_t inDestBufferSize, extern errno_t _ultoa_s( unsigned long inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); extern errno_t _ultow_s( unsigned long inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); -extern errno_t _i64toa_s( long long inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); extern errno_t _i64tow_s( long long inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); -extern errno_t _ui64toa_s( unsigned long long inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); -extern errno_t _ui64tow_s( unsigned long long inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); - extern errno_t _makepath_s( char* outDest, size_t inDestBufferSize, const char* inDrive, const char* inDirectory, const char* inFilename, const char* inExtension ); extern errno_t _wmakepath_s( WCHAR* outDest, size_t inDestBufferSize, const WCHAR* inDrive, const WCHAR* inDirectory, const WCHAR* inFilename, const WCHAR* inExtension ); @@ -103,9 +99,6 @@ extern int _vsnwprintf_s( WCHAR* string, size_t sizeInWords, size_t count, const extern int sscanf_s( const char *string, const char *format, ... ); extern int swscanf_s( const WCHAR *string, const WCHAR *format, ... ); -extern int _snscanf_s( const char *string, size_t count, const char *format, ... ); -extern int _snwscanf_s( const WCHAR *string, size_t count, const WCHAR *format, ... ); - extern errno_t memcpy_s( void * dst, size_t sizeInBytes, const void * src, size_t count ) THROW_DECL; extern errno_t memmove_s( void * dst, size_t sizeInBytes, const void * src, size_t count ); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal.h index 08a35c8..861a10f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal.h @@ -37,6 +37,7 @@ Abstract: #define __PAL_H__ #ifdef PAL_STDCPP_COMPAT +#include #include #include #include @@ -66,13 +67,11 @@ extern "C" { #define QUOTE_MACRO_u_HELPER(x) u###x #define QUOTE_MACRO_u(x) QUOTE_MACRO_u_HELPER(x) -#include #include #include // Native system libray handle. // On Unix systems, NATIVE_LIBRARY_HANDLE type represents a library handle not registered with the PAL. -// To get a HMODULE on Unix, call PAL_RegisterLibraryDirect() on a NATIVE_LIBRARY_HANDLE. typedef PVOID NATIVE_LIBRARY_HANDLE; /******************* Processor-specific glue *****************************/ @@ -95,26 +94,20 @@ typedef PVOID NATIVE_LIBRARY_HANDLE; #define _M_ARM64 1 #endif -#if defined(_M_IX86) && !defined(_X86_) -#define _X86_ -#elif defined(_M_AMD64) && !defined(_AMD64_) -#define _AMD64_ -#elif defined(_M_ARM) && !defined(_ARM_) -#define _ARM_ -#elif defined(_M_ARM64) && !defined(_ARM64_) -#define _ARM64_ +#if defined(_M_IX86) && !defined(HOST_X86) +#define HOST_X86 +#elif defined(_M_AMD64) && !defined(HOST_AMD64) +#define HOST_AMD64 +#elif defined(_M_ARM) && !defined(HOST_ARM) +#define HOST_ARM +#elif defined(_M_ARM64) && !defined(HOST_ARM64) +#define HOST_ARM64 #endif #endif // !_MSC_VER /******************* ABI-specific glue *******************************/ -#ifdef __APPLE__ -// Both PowerPC, i386 and x86_64 on Mac OS X use 16-byte alignment. -#define STACK_ALIGN_BITS 4 -#define STACK_ALIGN_REQ (1 << STACK_ALIGN_BITS) -#endif - #define MAX_PATH 260 #define _MAX_PATH 260 #define _MAX_DRIVE 3 /* max. length of drive component */ @@ -137,30 +130,17 @@ typedef PVOID NATIVE_LIBRARY_HANDLE; // Note that the named locale APIs (eg CompareStringExEx) are recommended. // -#define LANG_CHINESE 0x04 #define LANG_ENGLISH 0x09 -#define LANG_JAPANESE 0x11 -#define LANG_KOREAN 0x12 -#define LANG_THAI 0x1e /******************* Compiler-specific glue *******************************/ #ifndef THROW_DECL -#if defined(_MSC_VER) || defined(__llvm__) || !defined(__cplusplus) +#if defined(_MSC_VER) || !defined(__cplusplus) #define THROW_DECL #else #define THROW_DECL throw() #endif // !_MSC_VER #endif // !THROW_DECL -#ifndef _MSC_VER -#if defined(CORECLR) -// Define this if the underlying platform supports true 2-pass EH. -// At the same time, this enables running several PAL instances -// side-by-side. -#define FEATURE_PAL_SXS 1 -#endif // CORECLR -#endif // !_MSC_VER - #if defined(_MSC_VER) #define DECLSPEC_ALIGN(x) __declspec(align(x)) #else @@ -175,6 +155,9 @@ typedef PVOID NATIVE_LIBRARY_HANDLE; #define ANALYZER_NORETURN #endif +#define EMPTY_BASES_DECL + + #if !defined(_MSC_VER) || defined(SOURCE_FORMATTING) #define __assume(x) (void)0 #define __annotation(x) @@ -271,9 +254,10 @@ typedef char * va_list; #define INT_MAX 2147483647 #define UINT_MAX 0xffffffff -#define LONG_MIN (-2147483647L - 1) -#define LONG_MAX 2147483647L -#define ULONG_MAX 0xffffffffUL +// LONG_MIN, LONG_MAX, ULONG_MAX -- use INT32_MIN etc. instead. + +#define FLT_MAX 3.402823466e+38F +#define DBL_MAX 1.7976931348623157e+308 #endif // !PAL_STDCPP_COMPAT @@ -284,10 +268,7 @@ typedef char * va_list; PALIMPORT BOOL PALAPI -PAL_IsDebuggerPresent(VOID); - -#define FLT_MAX 3.402823466e+38F -#define DBL_MAX 1.7976931348623157e+308 +PAL_IsDebuggerPresent(); /* minimum signed 64 bit value */ #define _I64_MIN (I64(-9223372036854775807) - 1) @@ -323,7 +304,7 @@ PAL_IsDebuggerPresent(VOID); #ifndef PAL_STDCPP_COMPAT -#if _WIN64 || _MSC_VER >= 1400 +#if HOST_64BIT || _MSC_VER >= 1400 typedef __int64 time_t; #else typedef long time_t; @@ -381,8 +362,7 @@ PAL_InitializeWithFlags( PALIMPORT int PALAPI -PAL_InitializeDLL( - VOID); +PAL_InitializeDLL(); PALIMPORT void @@ -396,13 +376,6 @@ PALAPI PAL_InitializeCoreCLR( const char *szExePath); -PALIMPORT -DWORD_PTR -PALAPI -PAL_EntryPoint( - IN LPTHREAD_START_ROUTINE lpStartAddress, - IN LPVOID lpParameter); - ///

/// This function shuts down PAL WITHOUT exiting the current process. /// @@ -471,7 +444,7 @@ PAL_UnregisterForRuntimeStartup( PALIMPORT BOOL PALAPI -PAL_NotifyRuntimeStarted(VOID); +PAL_NotifyRuntimeStarted(); #ifdef __APPLE__ PALIMPORT @@ -502,12 +475,6 @@ PAL_GetTransportPipeName( IN const char *applicationGroupId, IN const char *suffix); -PALIMPORT -void -PALAPI -PAL_InitializeDebug( - void); - PALIMPORT void PALAPI @@ -552,26 +519,25 @@ PAL_ProbeMemory( DWORD cbBuffer, BOOL fWriteAccess); +PALIMPORT +int +PALAPI +// Start the jitdump file +PAL_PerfJitDump_Start(const char* path); + +PALIMPORT +int +PALAPI +// Log a method to the jitdump file. +PAL_PerfJitDump_LogMethod(void* pCode, size_t codeSize, const char* symbol, void* debugInfo, void* unwindInfo); + +PALIMPORT +int +PALAPI +// Finish the jitdump file +PAL_PerfJitDump_Finish(); + /******************* winuser.h Entrypoints *******************************/ -PALIMPORT -LPSTR -PALAPI -CharNextA( - IN LPCSTR lpsz); - -PALIMPORT -LPSTR -PALAPI -CharNextExA( - IN WORD CodePage, - IN LPCSTR lpCurrentChar, - IN DWORD dwFlags); - -#ifndef UNICODE -#define CharNext CharNextA -#define CharNextEx CharNextExA -#endif - #define MB_OK 0x00000000L #define MB_OKCANCEL 0x00000001L @@ -774,31 +740,6 @@ MoveFileExW( #define MoveFileEx MoveFileExA #endif -PALIMPORT -BOOL -PALAPI -CreateDirectoryW( - IN LPCWSTR lpPathName, - IN LPSECURITY_ATTRIBUTES lpSecurityAttributes); - -#ifdef UNICODE -#define CreateDirectory CreateDirectoryW -#else -#define CreateDirectory CreateDirectoryA -#endif - -PALIMPORT -BOOL -PALAPI -RemoveDirectoryW( - IN LPCWSTR lpPathName); - -#ifdef UNICODE -#define RemoveDirectory RemoveDirectoryW -#else -#define RemoveDirectory RemoveDirectoryA -#endif - typedef struct _BY_HANDLE_FILE_INFORMATION { DWORD dwFileAttributes; FILETIME ftCreationTime; @@ -930,19 +871,6 @@ GetFileAttributesExW( #define GetFileAttributesEx GetFileAttributesExW #endif -PALIMPORT -BOOL -PALAPI -SetFileAttributesW( - IN LPCWSTR lpFileName, - IN DWORD dwFileAttributes); - -#ifdef UNICODE -#define SetFileAttributes SetFileAttributesW -#else -#define SetFileAttributes SetFileAttributesA -#endif - typedef struct _OVERLAPPED { ULONG_PTR Internal; ULONG_PTR InternalHigh; @@ -1018,20 +946,6 @@ PALAPI GetFileSizeEx( IN HANDLE hFile, OUT PLARGE_INTEGER lpFileSize); -PALIMPORT -BOOL -PALAPI -GetFileInformationByHandle( - IN HANDLE hFile, - OUT BY_HANDLE_FILE_INFORMATION* lpFileInformation); - -PALIMPORT -LONG -PALAPI -CompareFileTime( - IN CONST FILETIME *lpFileTime1, - IN CONST FILETIME *lpFileTime2); - PALIMPORT VOID PALAPI @@ -1073,8 +987,7 @@ FlushFileBuffers( PALIMPORT UINT PALAPI -GetConsoleOutputCP( - VOID); +GetConsoleOutputCP(); PALIMPORT DWORD @@ -1091,31 +1004,6 @@ GetFullPathNameW( #define GetFullPathName GetFullPathNameA #endif -PALIMPORT -DWORD -PALAPI -GetLongPathNameW( - IN LPCWSTR lpszShortPath, - OUT LPWSTR lpszLongPath, - IN DWORD cchBuffer); - -#ifdef UNICODE -#define GetLongPathName GetLongPathNameW -#endif - -PALIMPORT -DWORD -PALAPI -GetShortPathNameW( - IN LPCWSTR lpszLongPath, - OUT LPWSTR lpszShortPath, - IN DWORD cchBuffer); - -#ifdef UNICODE -#define GetShortPathName GetShortPathNameW -#endif - - PALIMPORT UINT PALAPI @@ -1165,19 +1053,6 @@ GetCurrentDirectoryW( #define GetCurrentDirectory GetCurrentDirectoryA #endif -PALIMPORT -BOOL -PALAPI -SetCurrentDirectoryW( - IN LPCWSTR lpPathName); - - -#ifdef UNICODE -#define SetCurrentDirectory SetCurrentDirectoryW -#else -#define SetCurrentDirectory SetCurrentDirectoryA -#endif - PALIMPORT HANDLE PALAPI @@ -1324,40 +1199,34 @@ ReleaseMutex( PALIMPORT DWORD PALAPI -GetCurrentProcessId( - VOID); +GetCurrentProcessId(); PALIMPORT DWORD PALAPI -GetCurrentSessionId( - VOID); +GetCurrentSessionId(); PALIMPORT HANDLE PALAPI -GetCurrentProcess( - VOID); +GetCurrentProcess(); PALIMPORT DWORD PALAPI -GetCurrentThreadId( - VOID); +GetCurrentThreadId(); PALIMPORT size_t PALAPI -PAL_GetCurrentOSThreadId( - VOID); +PAL_GetCurrentOSThreadId(); // To work around multiply-defined symbols in the Carbon framework. #define GetCurrentThread PAL_GetCurrentThread PALIMPORT HANDLE PALAPI -GetCurrentThread( - VOID); +GetCurrentThread(); #define STARTF_USESTDHANDLES 0x00000100 @@ -1565,8 +1434,7 @@ SleepEx( PALIMPORT BOOL PALAPI -SwitchToThread( - VOID); +SwitchToThread(); #define DEBUG_PROCESS 0x00000001 #define DEBUG_ONLY_THIS_PROCESS 0x00000002 @@ -1618,7 +1486,7 @@ QueueUserAPC( IN HANDLE hThread, IN ULONG_PTR dwData); -#ifdef _X86_ +#ifdef HOST_X86 // // *********************************************************************************** @@ -1744,7 +1612,7 @@ typedef struct _KNONVOLATILE_CONTEXT_POINTERS { } KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; -#elif defined(_AMD64_) +#elif defined(HOST_AMD64) // copied from winnt.h #define CONTEXT_AMD64 0x100000 @@ -1995,7 +1863,7 @@ typedef struct _KNONVOLATILE_CONTEXT_POINTERS { } KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; -#elif defined(_ARM_) +#elif defined(HOST_ARM) #define CONTEXT_ARM 0x00200000L @@ -2175,7 +2043,7 @@ typedef struct _IMAGE_ARM_RUNTIME_FUNCTION_ENTRY { }; } IMAGE_ARM_RUNTIME_FUNCTION_ENTRY, * PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY; -#elif defined(_ARM64_) +#elif defined(HOST_ARM64) #define CONTEXT_ARM64 0x00400000L @@ -2415,57 +2283,40 @@ GetThreadTimes( OUT LPFILETIME lpKernelTime, OUT LPFILETIME lpUserTime); +PALIMPORT +HRESULT +PALAPI +SetThreadDescription( + IN HANDLE hThread, + IN PCWSTR lpThreadDescription +); + #define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF) PALIMPORT -DWORD +PVOID PALAPI -TlsAlloc( - VOID); - -PALIMPORT -LPVOID -PALAPI -TlsGetValue( - IN DWORD dwTlsIndex); - -PALIMPORT -BOOL -PALAPI -TlsSetValue( - IN DWORD dwTlsIndex, - IN LPVOID lpTlsValue); - -PALIMPORT -BOOL -PALAPI -TlsFree( - IN DWORD dwTlsIndex); +PAL_GetStackBase(); PALIMPORT PVOID PALAPI -PAL_GetStackBase(VOID); - -PALIMPORT -PVOID -PALAPI -PAL_GetStackLimit(VOID); +PAL_GetStackLimit(); PALIMPORT DWORD PALAPI -PAL_GetLogicalCpuCountFromOS(VOID); +PAL_GetLogicalCpuCountFromOS(); PALIMPORT DWORD PALAPI -PAL_GetTotalCpuCount(VOID); +PAL_GetTotalCpuCount(); PALIMPORT size_t PALAPI -PAL_GetRestrictedPhysicalMemoryLimit(VOID); +PAL_GetRestrictedPhysicalMemoryLimit(); PALIMPORT BOOL @@ -2480,7 +2331,7 @@ PAL_GetCpuLimit(UINT* val); PALIMPORT size_t PALAPI -PAL_GetLogicalProcessorCacheSizeFromOS(VOID); +PAL_GetLogicalProcessorCacheSizeFromOS(); typedef BOOL(*UnwindReadMemoryCallback)(PVOID address, PVOID buffer, SIZE_T size); @@ -2496,13 +2347,13 @@ PALIMPORT BOOL PALAPI PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_ #define PAL_CS_NATIVE_DATA_SIZE 76 #elif defined(__APPLE__) && defined(__x86_64__) #define PAL_CS_NATIVE_DATA_SIZE 120 -#elif defined(__FreeBSD__) && defined(_X86_) +#elif defined(__FreeBSD__) && defined(HOST_X86) #define PAL_CS_NATIVE_DATA_SIZE 12 #elif defined(__FreeBSD__) && defined(__x86_64__) #define PAL_CS_NATIVE_DATA_SIZE 24 -#elif defined(__linux__) && defined(_ARM_) +#elif defined(__linux__) && defined(HOST_ARM) #define PAL_CS_NATIVE_DATA_SIZE 80 -#elif defined(__linux__) && defined(_ARM64_) +#elif defined(__linux__) && defined(HOST_ARM64) #define PAL_CS_NATIVE_DATA_SIZE 116 #elif defined(__linux__) && defined(__i386__) #define PAL_CS_NATIVE_DATA_SIZE 76 @@ -2514,6 +2365,8 @@ PALIMPORT BOOL PALAPI PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_ #define PAL_CS_NATIVE_DATA_SIZE 56 #elif defined(__NetBSD__) && defined(__i386__) #define PAL_CS_NATIVE_DATA_SIZE 56 +#elif defined(__sun) && defined(__x86_64__) +#define PAL_CS_NATIVE_DATA_SIZE 48 #else #warning #error PAL_CS_NATIVE_DATA_SIZE is not defined for this architecture @@ -2525,11 +2378,13 @@ typedef struct _CRITICAL_SECTION { LONG LockCount; LONG RecursionCount; HANDLE OwningThread; - HANDLE LockSemaphore; ULONG_PTR SpinCount; +#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA BOOL bInternal; +#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA volatile DWORD dwInitState; + union CSNativeDataStorage { BYTE rgNativeDataStorage[PAL_CS_NATIVE_DATA_SIZE]; @@ -2715,6 +2570,22 @@ BOOL PALAPI PAL_LOADUnloadPEFile(PVOID ptr); +/*++ + PAL_LOADMarkSectionAsNotNeeded + + Mark a section as NotNeeded that was loaded by PAL_LOADLoadPEFile(). + +Parameters: + IN ptr - the section address mapped by PAL_LOADLoadPEFile() + +Return value: + TRUE - success + FALSE - failure (incorrect ptr, etc.) +--*/ +BOOL +PALAPI +PAL_LOADMarkSectionAsNotNeeded(void * ptr); + #ifdef UNICODE #define LoadLibrary LoadLibraryW #define LoadLibraryEx LoadLibraryExW @@ -2864,62 +2735,6 @@ VirtualQuery( #define FillMemory(Destination,Length,Fill) memset((Destination),(Fill),(Length)) #define ZeroMemory(Destination,Length) memset((Destination),0,(Length)) -PALIMPORT -HANDLE -PALAPI -GetProcessHeap( - VOID); - -#define HEAP_ZERO_MEMORY 0x00000008 - -PALIMPORT -HANDLE -PALAPI -HeapCreate( - IN DWORD flOptions, - IN SIZE_T dwInitialSize, - IN SIZE_T dwMaximumSize); - -PALIMPORT -LPVOID -PALAPI -HeapAlloc( - IN HANDLE hHeap, - IN DWORD dwFlags, - IN SIZE_T dwBytes); - -PALIMPORT -LPVOID -PALAPI -HeapReAlloc( - IN HANDLE hHeap, - IN DWORD dwFlags, - IN LPVOID lpMem, - IN SIZE_T dwBytes - ); - -PALIMPORT -BOOL -PALAPI -HeapFree( - IN HANDLE hHeap, - IN DWORD dwFlags, - IN LPVOID lpMem); - -typedef enum _HEAP_INFORMATION_CLASS { - HeapCompatibilityInformation, - HeapEnableTerminationOnCorruption -} HEAP_INFORMATION_CLASS; - -PALIMPORT -BOOL -PALAPI -HeapSetInformation( - IN OPTIONAL HANDLE HeapHandle, - IN HEAP_INFORMATION_CLASS HeapInformationClass, - IN PVOID HeapInformation, - IN SIZE_T HeapInformationLength); - #define LMEM_FIXED 0x0000 #define LMEM_MOVEABLE 0x0002 #define LMEM_ZEROINIT 0x0040 @@ -2988,13 +2803,6 @@ PALAPI IsDBCSLeadByte( IN BYTE TestChar); -PALIMPORT -BOOL -PALAPI -IsValidCodePage( - IN UINT CodePage); - - #define MB_PRECOMPOSED 0x00000001 #define MB_ERR_INVALID_CHARS 0x00000008 @@ -3024,25 +2832,9 @@ WideCharToMultiByte( IN LPCSTR lpDefaultChar, OUT LPBOOL lpUsedDefaultChar); -PALIMPORT -int -PALAPI -PAL_GetResourceString( - IN LPCSTR lpDomain, - IN LPCSTR lpResourceStr, - OUT LPWSTR lpWideCharStr, - IN int cchWideChar); - -PALIMPORT -BOOL -PALAPI -PAL_BindResources(IN LPCSTR lpDomain); - #define EXCEPTION_NONCONTINUABLE 0x1 #define EXCEPTION_UNWINDING 0x2 -#ifdef FEATURE_PAL_SXS - #define EXCEPTION_EXIT_UNWIND 0x4 // Exit unwind is in progress (not used by PAL SEH) #define EXCEPTION_NESTED_CALL 0x10 // Nested exception handler call #define EXCEPTION_TARGET_UNWIND 0x20 // Target unwind in progress @@ -3056,8 +2848,6 @@ PAL_BindResources(IN LPCSTR lpDomain); #define IS_UNWINDING(Flag) ((Flag & EXCEPTION_UNWIND) != 0) #define IS_TARGET_UNWIND(Flag) (Flag & EXCEPTION_TARGET_UNWIND) -#endif // FEATURE_PAL_SXS - #define EXCEPTION_IS_SIGNAL 0x100 #define EXCEPTION_MAXIMUM_PARAMETERS 15 @@ -3081,8 +2871,6 @@ typedef struct _EXCEPTION_POINTERS { PCONTEXT ContextRecord; } EXCEPTION_POINTERS, *PEXCEPTION_POINTERS, *LPEXCEPTION_POINTERS; -#ifdef FEATURE_PAL_SXS - typedef LONG EXCEPTION_DISPOSITION; enum { @@ -3092,14 +2880,12 @@ enum { ExceptionCollidedUnwind, }; -#endif // FEATURE_PAL_SXS - // // A function table entry is generated for each frame function. // typedef struct _RUNTIME_FUNCTION { DWORD BeginAddress; -#ifdef _TARGET_AMD64_ +#ifdef TARGET_AMD64 DWORD EndAddress; #endif DWORD UnwindData; @@ -3175,8 +2961,7 @@ OutputDebugStringW( PALIMPORT VOID PALAPI -DebugBreak( - VOID); +DebugBreak(); PALIMPORT DWORD @@ -3208,8 +2993,7 @@ SetEnvironmentVariableW( PALIMPORT LPWSTR PALAPI -GetEnvironmentStringsW( - VOID); +GetEnvironmentStringsW(); #ifdef UNICODE #define GetEnvironmentStrings GetEnvironmentStringsW @@ -3255,13 +3039,12 @@ RaiseFailFastException( PALIMPORT DWORD PALAPI -GetTickCount( - VOID); +GetTickCount(); PALIMPORT ULONGLONG PALAPI -GetTickCount64(VOID); +GetTickCount64(); PALIMPORT BOOL @@ -3290,25 +3073,9 @@ PALAPI PAL_nanosleep( IN long timeInNs); -#ifndef FEATURE_PAL_SXS - -typedef LONG (PALAPI_NOEXPORT *PTOP_LEVEL_EXCEPTION_FILTER)( - struct _EXCEPTION_POINTERS *ExceptionInfo); -typedef PTOP_LEVEL_EXCEPTION_FILTER LPTOP_LEVEL_EXCEPTION_FILTER; - -PALIMPORT -LPTOP_LEVEL_EXCEPTION_FILTER -PALAPI -SetUnhandledExceptionFilter( - IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter); - -#else // FEATURE_PAL_SXS - typedef EXCEPTION_DISPOSITION (PALAPI_NOEXPORT *PVECTORED_EXCEPTION_HANDLER)( struct _EXCEPTION_POINTERS *ExceptionPointers); -#endif // FEATURE_PAL_SXS - // Define BitScanForward64 and BitScanForward // Per MSDN, BitScanForward64 will search the mask data from LSB to MSB for a set bit. // If one is found, its bit position is stored in the out PDWORD argument and 1 is returned; @@ -3403,7 +3170,7 @@ BitScanReverse64( FORCEINLINE void PAL_ArmInterlockedOperationBarrier() { -#ifdef _ARM64_ +#ifdef HOST_ARM64 // On arm64, most of the __sync* functions generate a code sequence like: // loop: // ldaxr (load acquire exclusive) @@ -3416,7 +3183,7 @@ FORCEINLINE void PAL_ArmInterlockedOperationBarrier() // require the load to occur after the store. This memory barrier should be used following a call to a __sync* function to // prevent that reordering. Code generated for arm32 includes a 'dmb' after 'cbnz', so no issue there at the moment. __sync_synchronize(); -#endif // _ARM64_ +#endif // HOST_ARM64 } /*++ @@ -3723,7 +3490,7 @@ InterlockedBitTestAndSet( return (InterlockedOr(Base, (1 << Bit)) & (1 << Bit)) != 0; } -#if defined(BIT64) +#if defined(HOST_64BIT) #define InterlockedExchangePointer(Target, Value) \ ((PVOID)InterlockedExchange64((PLONG64)(Target), (LONGLONG)(Value))) @@ -3749,8 +3516,7 @@ PALIMPORT inline VOID PALAPI -MemoryBarrier( - VOID) +MemoryBarrier() { __sync_synchronize(); } @@ -3760,14 +3526,13 @@ PALIMPORT inline VOID PALAPI -YieldProcessor( - VOID) +YieldProcessor() { -#if defined(_X86_) || defined(_AMD64_) +#if defined(HOST_X86) || defined(HOST_AMD64) __asm__ __volatile__( "rep\n" "nop"); -#elif defined(_ARM64_) +#elif defined(HOST_ARM64) __asm__ __volatile__( "yield"); #else return; @@ -3777,7 +3542,7 @@ YieldProcessor( PALIMPORT DWORD PALAPI -GetCurrentProcessorNumber(VOID); +GetCurrentProcessorNumber(); /*++ Function: @@ -3789,7 +3554,7 @@ Checks if GetCurrentProcessorNumber is available in the current environment PALIMPORT BOOL PALAPI -PAL_HasGetCurrentProcessorNumber(VOID); +PAL_HasGetCurrentProcessorNumber(); #define FORMAT_MESSAGE_ALLOCATE_BUFFER 0x00000100 #define FORMAT_MESSAGE_IGNORE_INSERTS 0x00000200 @@ -3818,8 +3583,7 @@ FormatMessageW( PALIMPORT DWORD PALAPI -GetLastError( - VOID); +GetLastError(); PALIMPORT VOID @@ -3830,8 +3594,7 @@ SetLastError( PALIMPORT LPWSTR PALAPI -GetCommandLineW( - VOID); +GetCommandLineW(); #ifdef UNICODE #define GetCommandLine GetCommandLineW @@ -3852,30 +3615,10 @@ RtlCaptureContext( OUT PCONTEXT ContextRecord ); -PALIMPORT -UINT -PALAPI -GetWriteWatch( - IN DWORD dwFlags, - IN PVOID lpBaseAddress, - IN SIZE_T dwRegionSize, - OUT PVOID *lpAddresses, - IN OUT PULONG_PTR lpdwCount, - OUT PULONG lpdwGranularity -); - -PALIMPORT -UINT -PALAPI -ResetWriteWatch( - IN LPVOID lpBaseAddress, - IN SIZE_T dwRegionSize -); - PALIMPORT VOID PALAPI -FlushProcessWriteBuffers(VOID); +FlushProcessWriteBuffers(); typedef void (*PAL_ActivationFunction)(CONTEXT *context); typedef BOOL (*PAL_SafeActivationCheckFunction)(SIZE_T ip, BOOL checkingCurrentThread); @@ -4056,13 +3799,10 @@ PAL_GetCurrentThreadAffinitySet(SIZE_T size, UINT_PTR* data); defines */ #ifndef PAL_STDCPP_COMPAT #define exit PAL_exit -#define atexit PAL_atexit #define printf PAL_printf #define vprintf PAL_vprintf #define wprintf PAL_wprintf -#define wcsspn PAL_wcsspn #define wcstod PAL_wcstod -#define wcstol PAL_wcstol #define wcstoul PAL_wcstoul #define wcscat PAL_wcscat #define wcscpy PAL_wcscpy @@ -4074,7 +3814,6 @@ PAL_GetCurrentThreadAffinitySet(SIZE_T size, UINT_PTR* data); #define swscanf PAL_swscanf #define wcspbrk PAL_wcspbrk #define wcscmp PAL_wcscmp -#define wcsncat PAL_wcsncat #define wcsncpy PAL_wcsncpy #define wcstok PAL_wcstok #define wcscspn PAL_wcscspn @@ -4086,36 +3825,23 @@ PAL_GetCurrentThreadAffinitySet(SIZE_T size, UINT_PTR* data); #define fwprintf PAL_fwprintf #define vfprintf PAL_vfprintf #define vfwprintf PAL_vfwprintf -#define ctime PAL_ctime -#define localtime PAL_localtime -#define mktime PAL_mktime #define rand PAL_rand #define time PAL_time #define getenv PAL_getenv #define fgets PAL_fgets -#define fgetws PAL_fgetws -#define fputc PAL_fputc -#define putchar PAL_putchar #define qsort PAL_qsort #define bsearch PAL_bsearch #define ferror PAL_ferror #define fread PAL_fread #define fwrite PAL_fwrite -#define feof PAL_feof #define ftell PAL_ftell #define fclose PAL_fclose -#define setbuf PAL_setbuf #define fflush PAL_fflush #define fputs PAL_fputs #define fseek PAL_fseek #define fgetpos PAL_fgetpos #define fsetpos PAL_fsetpos -#define getc PAL_getc -#define fgetc PAL_getc // not a typo -#define ungetc PAL_ungetc #define setvbuf PAL_setvbuf -#define atol PAL_atol -#define labs PAL_labs #define acos PAL_acos #define acosh PAL_acosh #define asin PAL_asin @@ -4144,10 +3870,7 @@ PAL_GetCurrentThreadAffinitySet(SIZE_T size, UINT_PTR* data); #define scalbnf PAL_scalbnf #define malloc PAL_malloc #define free PAL_free -#define mkstemp PAL_mkstemp -#define rename PAL_rename #define _strdup PAL__strdup -#define _getcwd PAL__getcwd #define _open PAL__open #define _pread PAL__pread #define _close PAL__close @@ -4156,10 +3879,10 @@ PAL_GetCurrentThreadAffinitySet(SIZE_T size, UINT_PTR* data); #define strnlen PAL_strnlen #define wcsnlen PAL_wcsnlen -#ifdef _AMD64_ +#ifdef HOST_AMD64 #define _mm_getcsr PAL__mm_getcsr #define _mm_setcsr PAL__mm_setcsr -#endif // _AMD64_ +#endif // HOST_AMD64 #endif // !PAL_STDCPP_COMPAT @@ -4187,13 +3910,6 @@ typedef unsigned int wint_t; #ifndef PAL_STDCPP_COMPAT -typedef struct { - int quot; - int rem; -} div_t; - -PALIMPORT div_t div(int numer, int denom); - #if defined(_DEBUG) /*++ @@ -4221,7 +3937,11 @@ PALIMPORT int __cdecl memcmp(const void *, const void *, size_t); PALIMPORT void * __cdecl memset(void *, int, size_t); PALIMPORT void * __cdecl memmove(void *, const void *, size_t); PALIMPORT void * __cdecl memchr(const void *, int, size_t); -PALIMPORT long long int __cdecl atoll(const char *) THROW_DECL; +PALIMPORT long long int __cdecl atoll(const char *) +#ifndef __sun +THROW_DECL +#endif +; PALIMPORT size_t __cdecl strlen(const char *); PALIMPORT int __cdecl strcmp(const char*, const char *); PALIMPORT int __cdecl strncmp(const char*, const char *, size_t); @@ -4238,7 +3958,6 @@ PALIMPORT char * __cdecl strtok(char *, const char *); PALIMPORT size_t __cdecl strspn(const char *, const char *); PALIMPORT size_t __cdecl strcspn(const char *, const char *); PALIMPORT int __cdecl atoi(const char *); -PALIMPORT LONG __cdecl atol(const char *); PALIMPORT ULONG __cdecl strtoul(const char *, char **, int); PALIMPORT double __cdecl atof(const char *); PALIMPORT double __cdecl strtod(const char *, char **); @@ -4269,7 +3988,6 @@ PALIMPORT wint_t __cdecl towlower(wint_t); PALIMPORT DLLEXPORT errno_t __cdecl memcpy_s(void *, size_t, const void *, size_t) THROW_DECL; PALIMPORT errno_t __cdecl memmove_s(void *, size_t, const void *, size_t); -PALIMPORT char * __cdecl _strlwr(char *); PALIMPORT DLLEXPORT int __cdecl _stricmp(const char *, const char *); PALIMPORT DLLEXPORT int __cdecl vsprintf_s(char *, size_t, const char *, va_list); PALIMPORT char * __cdecl _gcvt_s(char *, int, double, int); @@ -4295,7 +4013,6 @@ PALIMPORT DLLEXPORT size_t __cdecl PAL_wcslen(const WCHAR *); PALIMPORT DLLEXPORT int __cdecl PAL_wcscmp(const WCHAR*, const WCHAR*); PALIMPORT DLLEXPORT int __cdecl PAL_wcsncmp(const WCHAR *, const WCHAR *, size_t); PALIMPORT DLLEXPORT WCHAR * __cdecl PAL_wcscat(WCHAR *, const WCHAR *); -PALIMPORT WCHAR * __cdecl PAL_wcsncat(WCHAR *, const WCHAR *, size_t); PALIMPORT WCHAR * __cdecl PAL_wcscpy(WCHAR *, const WCHAR *); PALIMPORT WCHAR * __cdecl PAL_wcsncpy(WCHAR *, const WCHAR *, size_t); PALIMPORT DLLEXPORT const WCHAR * __cdecl PAL_wcschr(const WCHAR *, WCHAR); @@ -4307,9 +4024,7 @@ PALIMPORT DLLEXPORT size_t __cdecl PAL_wcscspn(const WCHAR *, const WCHAR *); PALIMPORT int __cdecl PAL_swprintf(WCHAR *, const WCHAR *, ...); PALIMPORT int __cdecl PAL_vswprintf(WCHAR *, const WCHAR *, va_list); PALIMPORT int __cdecl PAL_swscanf(const WCHAR *, const WCHAR *, ...); -PALIMPORT LONG __cdecl PAL_wcstol(const WCHAR *, WCHAR **, int); PALIMPORT DLLEXPORT ULONG __cdecl PAL_wcstoul(const WCHAR *, WCHAR **, int); -PALIMPORT size_t __cdecl PAL_wcsspn (const WCHAR *, const WCHAR *); PALIMPORT double __cdecl PAL_wcstod(const WCHAR *, WCHAR **); PALIMPORT WCHAR * __cdecl _wcslwr(WCHAR *); @@ -4319,14 +4034,14 @@ PALIMPORT int __cdecl _wtoi(const WCHAR *); #ifdef __cplusplus extern "C++" { -inline WCHAR *PAL_wcschr(WCHAR *_S, WCHAR _C) - {return ((WCHAR *)PAL_wcschr((const WCHAR *)_S, _C)); } -inline WCHAR *PAL_wcsrchr(WCHAR *_S, WCHAR _C) - {return ((WCHAR *)PAL_wcsrchr((const WCHAR *)_S, _C)); } -inline WCHAR *PAL_wcspbrk(WCHAR *_S, const WCHAR *_P) - {return ((WCHAR *)PAL_wcspbrk((const WCHAR *)_S, _P)); } -inline WCHAR *PAL_wcsstr(WCHAR *_S, const WCHAR *_P) - {return ((WCHAR *)PAL_wcsstr((const WCHAR *)_S, _P)); } +inline WCHAR *PAL_wcschr(WCHAR* S, WCHAR C) + {return ((WCHAR *)PAL_wcschr((const WCHAR *)S, C)); } +inline WCHAR *PAL_wcsrchr(WCHAR* S, WCHAR C) + {return ((WCHAR *)PAL_wcsrchr((const WCHAR *)S, C)); } +inline WCHAR *PAL_wcspbrk(WCHAR* S, const WCHAR* P) + {return ((WCHAR *)PAL_wcspbrk((const WCHAR *)S, P)); } +inline WCHAR *PAL_wcsstr(WCHAR* S, const WCHAR* P) + {return ((WCHAR *)PAL_wcsstr((const WCHAR *)S, P)); } } #endif @@ -4359,9 +4074,9 @@ unsigned int __cdecl _rotl(unsigned int value, int shift) #endif // !HAS_ROTL // On 64 bit unix, make the long an int. -#ifdef BIT64 +#ifdef HOST_64BIT #define _lrotl _rotl -#endif // BIT64 +#endif // HOST_64BIT #if !HAS_ROTR @@ -4389,9 +4104,7 @@ PALIMPORT int __cdecl abs(int); // clang complains if this is declared with __int64 PALIMPORT long long __cdecl llabs(long long); #ifndef PAL_STDCPP_COMPAT -PALIMPORT LONG __cdecl labs(LONG); -PALIMPORT int __cdecl _signbit(double); PALIMPORT int __cdecl _finite(double); PALIMPORT int __cdecl _isnan(double); PALIMPORT double __cdecl _copysign(double, double); @@ -4400,9 +4113,17 @@ PALIMPORT double __cdecl acosh(double); PALIMPORT double __cdecl asin(double); PALIMPORT double __cdecl asinh(double); PALIMPORT double __cdecl atan(double) THROW_DECL; -PALIMPORT double __cdecl atanh(double) THROW_DECL; +PALIMPORT double __cdecl atanh(double) +#ifndef __sun +THROW_DECL +#endif +; PALIMPORT double __cdecl atan2(double, double); -PALIMPORT double __cdecl cbrt(double) THROW_DECL; +PALIMPORT double __cdecl cbrt(double) +#ifndef __sun +THROW_DECL +#endif +; PALIMPORT double __cdecl ceil(double); PALIMPORT double __cdecl cos(double); PALIMPORT double __cdecl cosh(double); @@ -4424,7 +4145,6 @@ PALIMPORT double __cdecl sqrt(double); PALIMPORT double __cdecl tan(double); PALIMPORT double __cdecl tanh(double); -PALIMPORT int __cdecl _signbitf(float); PALIMPORT int __cdecl _finitef(float); PALIMPORT int __cdecl _isnanf(float); PALIMPORT float __cdecl _copysignf(float, float); @@ -4432,10 +4152,22 @@ PALIMPORT float __cdecl acosf(float); PALIMPORT float __cdecl acoshf(float); PALIMPORT float __cdecl asinf(float); PALIMPORT float __cdecl asinhf(float); -PALIMPORT float __cdecl atanf(float) THROW_DECL; -PALIMPORT float __cdecl atanhf(float) THROW_DECL; +PALIMPORT float __cdecl atanf(float) +#ifndef __sun +THROW_DECL +#endif +; +PALIMPORT float __cdecl atanhf(float) +#ifndef __sun +THROW_DECL +#endif +; PALIMPORT float __cdecl atan2f(float, float); -PALIMPORT float __cdecl cbrtf(float) THROW_DECL; +PALIMPORT float __cdecl cbrtf(float) +#ifndef __sun +THROW_DECL +#endif +; PALIMPORT float __cdecl ceilf(float); PALIMPORT float __cdecl cosf(float); PALIMPORT float __cdecl coshf(float); @@ -4489,9 +4221,6 @@ PALIMPORT char * __cdecl _strdup(const char *); #endif // !PAL_STDCPP_COMPAT PALIMPORT PAL_NORETURN void __cdecl exit(int); -int __cdecl atexit(void (__cdecl *function)(void)); - -PALIMPORT char * __cdecl _fullpath(char *, const char *, size_t); #ifndef PAL_STDCPP_COMPAT @@ -4501,24 +4230,8 @@ PALIMPORT DLLEXPORT void * __cdecl bsearch(const void *, const void *, size_t, s PALIMPORT time_t __cdecl time(time_t *); -struct tm { - int tm_sec; /* seconds after the minute - [0,59] */ - int tm_min; /* minutes after the hour - [0,59] */ - int tm_hour; /* hours since midnight - [0,23] */ - int tm_mday; /* day of the month - [1,31] */ - int tm_mon; /* months since January - [0,11] */ - int tm_year; /* years since 1900 */ - int tm_wday; /* days since Sunday - [0,6] */ - int tm_yday; /* days since January 1 - [0,365] */ - int tm_isdst; /* daylight savings time flag */ - }; - -PALIMPORT struct tm * __cdecl localtime(const time_t *); -PALIMPORT time_t __cdecl mktime(struct tm *); -PALIMPORT char * __cdecl ctime(const time_t *); #endif // !PAL_STDCPP_COMPAT -PALIMPORT int __cdecl _open_osfhandle(INT_PTR, int); PALIMPORT DLLEXPORT int __cdecl _open(const char *szPath, int nFlags, ...); PALIMPORT DLLEXPORT size_t __cdecl _pread(int fd, void *buf, size_t nbytes, ULONG64 offset); PALIMPORT DLLEXPORT int __cdecl _close(int); @@ -4554,26 +4267,18 @@ typedef struct _FILE PAL_FILE; #endif // PAL_STDCPP_COMPAT PALIMPORT int __cdecl PAL_fclose(PAL_FILE *); -PALIMPORT void __cdecl PAL_setbuf(PAL_FILE *, char*); PALIMPORT DLLEXPORT int __cdecl PAL_fflush(PAL_FILE *); PALIMPORT size_t __cdecl PAL_fwrite(const void *, size_t, size_t, PAL_FILE *); PALIMPORT size_t __cdecl PAL_fread(void *, size_t, size_t, PAL_FILE *); PALIMPORT char * __cdecl PAL_fgets(char *, int, PAL_FILE *); PALIMPORT int __cdecl PAL_fputs(const char *, PAL_FILE *); -PALIMPORT int __cdecl PAL_fputc(int c, PAL_FILE *stream); -PALIMPORT int __cdecl PAL_putchar(int c); PALIMPORT DLLEXPORT int __cdecl PAL_fprintf(PAL_FILE *, const char *, ...); PALIMPORT int __cdecl PAL_vfprintf(PAL_FILE *, const char *, va_list); PALIMPORT int __cdecl PAL_fseek(PAL_FILE *, LONG, int); PALIMPORT LONG __cdecl PAL_ftell(PAL_FILE *); -PALIMPORT int __cdecl PAL_feof(PAL_FILE *); PALIMPORT int __cdecl PAL_ferror(PAL_FILE *); PALIMPORT PAL_FILE * __cdecl PAL_fopen(const char *, const char *); -PALIMPORT int __cdecl PAL_getc(PAL_FILE *stream); -PALIMPORT int __cdecl PAL_fgetc(PAL_FILE *stream); -PALIMPORT int __cdecl PAL_ungetc(int c, PAL_FILE *stream); PALIMPORT int __cdecl PAL_setvbuf(PAL_FILE *stream, char *, int, size_t); -PALIMPORT WCHAR * __cdecl PAL_fgetws(WCHAR *, int, PAL_FILE *); PALIMPORT DLLEXPORT int __cdecl PAL_fwprintf(PAL_FILE *, const WCHAR *, ...); PALIMPORT int __cdecl PAL_vfwprintf(PAL_FILE *, const WCHAR *, va_list); PALIMPORT int __cdecl PAL_wprintf(const WCHAR*, ...); @@ -4582,7 +4287,6 @@ PALIMPORT int __cdecl _getw(PAL_FILE *); PALIMPORT int __cdecl _putw(int, PAL_FILE *); PALIMPORT PAL_FILE * __cdecl _fdopen(int, const char *); PALIMPORT PAL_FILE * __cdecl _wfopen(const WCHAR *, const WCHAR *); -PALIMPORT PAL_FILE * __cdecl _wfsopen(const WCHAR *, const WCHAR *, int); /* Maximum value that can be returned by the rand function. */ @@ -4649,22 +4353,22 @@ PAL_GetCPUBusyTime( PALIMPORT VOID PALAPI -PAL_EnableProcessProfile(VOID); +PAL_EnableProcessProfile(); PALIMPORT VOID PALAPI -PAL_DisableProcessProfile(VOID); +PAL_DisableProcessProfile(); PALIMPORT BOOL PALAPI -PAL_IsProcessProfileEnabled(VOID); +PAL_IsProcessProfileEnabled(); PALIMPORT INT64 PALAPI -PAL_GetCpuTickCount(VOID); +PAL_GetCpuTickCount(); #endif // PAL_PERF /******************* PAL functions for SIMD extensions *****************/ @@ -4688,183 +4392,7 @@ PAL_GetJitCpuCapabilityFlags(CORJIT_FLAGS *flags); #endif -/******************* PAL side-by-side support ************************/ - -#ifdef FEATURE_PAL_SXS -// -// Some versions of the PAL support several PALs side-by-side -// in the process. To avoid those PALs interfering with one -// another, they need to be told by clients when they are active -// and when they are not. -// - -// To avoid performance problems incurred by swapping thread -// exception ports every time we leave the PAL, there's also -// the concept of entering/leaving the PAL at its top boundary -// (entering down/leaving up) or at the bottom boundary -// (leaving down/entering up). - -typedef enum _PAL_Boundary { - PAL_BoundaryTop, // closer to main() - PAL_BoundaryBottom, // closer to execution - PAL_BoundaryEH, // out-of-band during EH - - PAL_BoundaryMax = PAL_BoundaryEH -} PAL_Boundary; - -// This function needs to be called on a thread when it enters -// a region of code that depends on this instance of the PAL -// in the process, and the current thread may or may not be -// known to the PAL. This function can fail (for something else -// than an internal error) if this is the first time that the -// current thread entered this PAL. Note that PAL_Initialize -// implies a call to this function. Does not modify LastError. -PALIMPORT -DWORD -PALAPI -PAL_Enter(PAL_Boundary boundary); - -// Returns TRUE if we this thread has already entered the PAL, -// returns FALSE if we have not entered the PAL. -PALIMPORT -BOOL -PALAPI -PAL_HasEntered(VOID); - -// Equivalent to PAL_Enter(PAL_BoundaryTop) and is for stub -// code generation use. -PALIMPORT -DWORD -PALAPI -PAL_EnterTop(VOID); - -// This function needs to be called on a thread when it enters -// a region of code that depends on this instance of the PAL -// in the process, and the current thread is already known to -// the PAL. Does not modify LastError. -PALIMPORT -VOID -PALAPI -PAL_Reenter(PAL_Boundary boundary); - -// This function needs to be called on a thread when it enters -// a region of code that depends on this instance of the PAL -// in the process, and it is unknown whether the current thread -// is already running in the PAL. Returns TRUE if and only if -// the thread was not running in the PAL previously. Does not -// modify LastError. -PALIMPORT -BOOL -PALAPI -PAL_ReenterForEH(VOID); - -// This function needs to be called on a thread when it leaves -// a region of code that depends on this instance of the PAL -// in the process. Does not modify LastError. -PALIMPORT -VOID -PALAPI -PAL_Leave(PAL_Boundary boundary); - -// This function is equivalent to PAL_Leave(PAL_BoundaryBottom) -// and is available to limit the creation of stub code. -PALIMPORT -VOID -PALAPI -PAL_LeaveBottom(VOID); - -// This function is equivalent to PAL_Leave(PAL_BoundaryTop) -// and is available to limit the creation of stub code. -PALIMPORT -VOID -PALAPI -PAL_LeaveTop(VOID); - -#ifdef __cplusplus -// -// A holder to enter the PAL for a specific region of code. -// Previously, we must have been executing outside the PAL -// (unless fEnter is set to FALSE). -// -class PAL_EnterHolder -{ -private: - BOOL m_fEntered; - DWORD m_palError; -public: - PAL_EnterHolder(BOOL fEnter = TRUE) : m_palError(ERROR_SUCCESS) - { - if (fEnter) - { - m_palError = PAL_Enter(PAL_BoundaryTop); - m_fEntered = m_palError == ERROR_SUCCESS; - } - else - { - m_fEntered = FALSE; - } - } - - ~PAL_EnterHolder() - { - if (m_fEntered) - { - PAL_Leave(PAL_BoundaryTop); - } - } - - DWORD GetError() - { - return m_palError; - } - - void SuppressRelease() - { - // Used to avoid calling PAL_Leave() when - // another code path will explicitly do so. - m_fEntered = FALSE; - } -}; - -class PAL_LeaveHolder -{ -public: - PAL_LeaveHolder() - { - PAL_Leave(PAL_BoundaryBottom); - } - - ~PAL_LeaveHolder() - { - PAL_Reenter(PAL_BoundaryBottom); - } -}; -#endif // __cplusplus - -#else // FEATURE_PAL_SXS - -#define PAL_Enter(boundary) ERROR_SUCCESS -#define PAL_Reenter(boundary) -#define PAL_Leave(boundary) - #ifdef __cplusplus -class PAL_EnterHolder { -public: - // using constructor to suppress the "unused variable" warnings - PAL_EnterHolder() {} -}; -class PAL_LeaveHolder { -public: - // using constructor to suppress the "unused variable" warnings - PAL_LeaveHolder() {} -}; -#endif // __cplusplus - -#endif // FEATURE_PAL_SXS - -#ifdef __cplusplus - -#include "pal_unwind.h" PALIMPORT VOID @@ -5044,8 +4572,6 @@ public: #define HardwareExceptionHolder #endif // FEATURE_ENABLE_HARDWARE_EXCEPTIONS -#ifdef FEATURE_PAL_SXS - class NativeExceptionHolderBase; PALIMPORT @@ -5256,16 +4782,13 @@ public: } // extern "C++" -#endif // FEATURE_PAL_SXS - #define PAL_CPP_THROW(type, obj) { throw obj; } #define PAL_CPP_RETHROW { throw; } #define PAL_CPP_TRY try { HardwareExceptionHolder -#define PAL_CPP_CATCH_EXCEPTION(ident) } catch (Exception *ident) { PAL_Reenter(PAL_BoundaryBottom); -#define PAL_CPP_CATCH_EXCEPTION_NOARG } catch (Exception *) { PAL_Reenter(PAL_BoundaryBottom); -#define PAL_CPP_CATCH_DERIVED(type, ident) } catch (type *ident) { PAL_Reenter(PAL_BoundaryBottom); +#define PAL_CPP_CATCH_EXCEPTION(ident) } catch (Exception *ident) { +#define PAL_CPP_CATCH_EXCEPTION_NOARG } catch (Exception *) { +#define PAL_CPP_CATCH_DERIVED(type, ident) } catch (type *ident) { #define PAL_CPP_CATCH_ALL } catch (...) { \ - PAL_Reenter(PAL_BoundaryBottom); \ try { throw; } \ catch (PAL_SEHException& ex) { ex.SecondPassDone(); } \ catch (...) {} @@ -5276,32 +4799,8 @@ public: #pragma warning(disable:4611) // interaction between '_setjmp' and C++ object destruction is non-portable #endif -#ifdef FEATURE_PAL_SXS - #define PAL_TRY_FOR_DLLMAIN(ParamType, paramDef, paramRef, _reason) PAL_TRY(ParamType, paramDef, paramRef) -#else // FEATURE_PAL_SXS - -#define PAL_TRY(ParamType, paramDef, paramRef) \ - { \ - ParamType __param = paramRef; \ - ParamType paramDef; paramDef = __param; \ - try { \ - HardwareExceptionHolder - -#define PAL_TRY_FOR_DLLMAIN(ParamType, paramDef, paramRef, _reason) \ - { \ - ParamType __param = paramRef; \ - ParamType paramDef; paramDef = __param; \ - try { \ - HardwareExceptionHolder - -#define PAL_ENDTRY \ - } \ - } - -#endif // FEATURE_PAL_SXS - #endif // __cplusplus // Platform-specific library naming @@ -5397,12 +4896,58 @@ public: #define CONTROL_C_EXIT STATUS_CONTROL_C_EXIT -/* These are from the file in windows. - They are needed for _open_osfhandle.*/ -#define _O_RDONLY 0x0000 -#define _O_APPEND 0x0008 -#define _O_TEXT 0x4000 -#define _O_BINARY 0x8000 +/******************* HRESULT types ****************************************/ + +#define FACILITY_WINDOWS 8 +#define FACILITY_URT 19 +#define FACILITY_UMI 22 +#define FACILITY_SXS 23 +#define FACILITY_STORAGE 3 +#define FACILITY_SSPI 9 +#define FACILITY_SCARD 16 +#define FACILITY_SETUPAPI 15 +#define FACILITY_SECURITY 9 +#define FACILITY_RPC 1 +#define FACILITY_WIN32 7 +#define FACILITY_CONTROL 10 +#define FACILITY_NULL 0 +#define FACILITY_MSMQ 14 +#define FACILITY_MEDIASERVER 13 +#define FACILITY_INTERNET 12 +#define FACILITY_ITF 4 +#define FACILITY_DPLAY 21 +#define FACILITY_DISPATCH 2 +#define FACILITY_COMPLUS 17 +#define FACILITY_CERT 11 +#define FACILITY_ACS 20 +#define FACILITY_AAF 18 + +#define NO_ERROR 0L + +#define SEVERITY_SUCCESS 0 +#define SEVERITY_ERROR 1 + +#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0) +#define FAILED(Status) ((HRESULT)(Status)<0) +#define IS_ERROR(Status) ((ULONG)(Status) >> 31 == SEVERITY_ERROR) // diff from win32 +#define HRESULT_CODE(hr) ((hr) & 0xFFFF) +#define SCODE_CODE(sc) ((sc) & 0xFFFF) +#define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff) +#define SCODE_FACILITY(sc) (((sc) >> 16) & 0x1fff) +#define HRESULT_SEVERITY(hr) (((hr) >> 31) & 0x1) +#define SCODE_SEVERITY(sc) (((sc) >> 31) & 0x1) + +// both macros diff from Win32 +#define MAKE_HRESULT(sev,fac,code) \ + ((HRESULT) (((ULONG)(sev)<<31) | ((ULONG)(fac)<<16) | ((ULONG)(code))) ) +#define MAKE_SCODE(sev,fac,code) \ + ((SCODE) (((ULONG)(sev)<<31) | ((ULONG)(fac)<<16) | ((LONG)(code))) ) + +#define FACILITY_NT_BIT 0x10000000 +#define HRESULT_FROM_WIN32(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000))) +#define __HRESULT_FROM_WIN32(x) HRESULT_FROM_WIN32(x) + +#define HRESULT_FROM_NT(x) ((HRESULT) ((x) | FACILITY_NT_BIT)) #ifdef __cplusplus } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal_char16.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal_char16.h deleted file mode 100644 index 0697b23..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal_char16.h +++ /dev/null @@ -1,55 +0,0 @@ -// 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: - - pal_char16.h - -Abstract: - -This file is used to define the wchar_t type as a 16-bit type on Unix. - - - ---*/ - -// The unix compilers use a 32-bit wchar_t, so we must make a 16 bit wchar_t. -// The windows compilers, gcc and MSVC, both define a 16 bit wchar_t. - -// Note : wchar_t is a built-in type in C++, gcc/llvm ignores any attempts to -// typedef it. Using the preprocessor here, we make sure gcc sees -// __wchar_16_cpp__ instead of wchar_t. This is apparently not necessary under -// vc++, for whom wchar_t is already a typedef instead of a built-in. - -#ifndef PAL_STDCPP_COMPAT -#undef wchar_t -#undef __WCHAR_TYPE__ -#define __WCHAR_TYPE__ __wchar_16_cpp__ -#define wchar_t __wchar_16_cpp__ - -// Set up the wchar_t type (which got preprocessed to __wchar_16_cpp__). -// In C++11, the standard gives us char16_t, which is what we want (and matches types with u"") -// In C, this doesn't exist, so use unsigned short. -// **** WARNING: Linking C and C++ objects will break with -fstrict-aliasing with GCC/Clang -// due to conditional typedef -#if !defined(_WCHAR_T_DEFINED) || !defined(_MSC_VER) -#if defined(__cplusplus) -#undef __WCHAR_TYPE__ -#define __WCHAR_TYPE__ char16_t -typedef char16_t wchar_t; -#else -#undef __WCHAR_TYPE__ -#define __WCHAR_TYPE__ unsigned short -typedef unsigned short wchar_t; -#endif // __cplusplus - -#ifndef _WCHAR_T_DEFINED -#define _WCHAR_T_DEFINED -#endif // !_WCHAR_T_DEFINED -#endif // !_WCHAR_T_DEFINED || !_MSC_VER -#endif // !PAL_STDCPP_COMPAT diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal_endian.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal_endian.h index 50b9e76..92cef33 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal_endian.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal_endian.h @@ -44,7 +44,7 @@ inline UINT32 VAL32(UINT32 x) return SWAP32(x); } -inline UINT64 VAL64(UINT64 x) +inline UINT64 VAL64(UINT64 x) { return ((UINT64)VAL32(x) << 32) | VAL32(x >> 32); } @@ -67,8 +67,8 @@ inline void SwapStringLength(WCHAR *szString, ULONG StringLength) } } -inline void SwapGuid(GUID *pGuid) -{ +inline void SwapGuid(GUID *pGuid) +{ pGuid->Data1 = VAL32(pGuid->Data1); pGuid->Data2 = VAL16(pGuid->Data2); pGuid->Data3 = VAL16(pGuid->Data3); @@ -92,13 +92,13 @@ inline void SwapGuid(GUID *pGuid) #endif // !BIGENDIAN -#ifdef BIT64 +#ifdef HOST_64BIT #define VALPTR(x) VAL64(x) #else #define VALPTR(x) VAL32(x) #endif -#ifdef _ARM_ +#ifdef HOST_ARM #define LOG2_PTRSIZE 2 #define ALIGN_ACCESS ((1< longs = 32 bits, long long = 64 bits) // // To handle this difference, we #define long to be int (and thus 32 bits) when -// compiling those files. (See the bottom of this file or search for -// #define long to see where we do this.) +// compiling those files. (See the bottom of this file or search for +// #define long to see where we do this.) // -// But this fix is more complicated than it seems, because we also use the +// But this fix is more complicated than it seems, because we also use the // preprocessor to #define __int64 to long for LP64 architectures (__int64 -// isn't a builtin in gcc). We don't want __int64 to be an int (by cascading -// macro rules). So we play this little trick below where we add -// __cppmungestrip before "long", which is what we're really #defining __int64 -// to. The preprocessor sees __cppmungestriplong as something different than -// long, so it doesn't replace it with int. The during the cppmunge phase, we +// isn't a builtin in gcc). We don't want __int64 to be an int (by cascading +// macro rules). So we play this little trick below where we add +// __cppmungestrip before "long", which is what we're really #defining __int64 +// to. The preprocessor sees __cppmungestriplong as something different than +// long, so it doesn't replace it with int. The during the cppmunge phase, we // remove the __cppmungestrip part, leaving long for the compiler to see. // -// Note that we can't just use a typedef to define __int64 as long before -// #defining long because typedefed types can't be signedness-agnostic (i.e. -// they must be either signed or unsigned) and we want to be able to use +// Note that we can't just use a typedef to define __int64 as long before +// #defining long because typedefed types can't be signedness-agnostic (i.e. +// they must be either signed or unsigned) and we want to be able to use // __int64 as though it were intrinsic -#ifdef BIT64 +#ifdef HOST_64BIT #define __int64 long -#else // BIT64 +#else // HOST_64BIT #define __int64 long long -#endif // BIT64 +#endif // HOST_64BIT #define __int32 int #define __int16 short int @@ -213,8 +213,6 @@ extern "C" { // includes are not included, so we need to define them. #ifndef PAL_IMPLEMENTATION -// OS X already defines these types in 64 bit -#if !defined(_TARGET_MAC64) typedef __int64 int64_t; typedef unsigned __int64 uint64_t; typedef __int32 int32_t; @@ -223,13 +221,12 @@ typedef __int16 int16_t; typedef unsigned __int16 uint16_t; typedef __int8 int8_t; typedef unsigned __int8 uint8_t; -#endif #endif // PAL_IMPLEMENTATION #ifndef _MSC_VER -#if _WIN64 +#if HOST_64BIT typedef long double LONG_DOUBLE; #endif @@ -302,13 +299,13 @@ typedef signed __int32 LONG32, *PLONG32; typedef unsigned __int64 ULONG64; typedef signed __int64 LONG64; -#if defined(_X86_) && _MSC_VER >= 1300 +#if defined(HOST_X86) && _MSC_VER >= 1300 #define _W64 __w64 #else #define _W64 #endif -#ifdef BIT64 +#ifdef HOST_64BIT #define _atoi64 (__int64)atoll @@ -329,7 +326,7 @@ typedef unsigned __int64 DWORD_PTR, *PDWORD_PTR; #define __int3264 __int64 -#if !defined(BIT64) +#if !defined(HOST_64BIT) __inline unsigned long HandleToULong( @@ -482,7 +479,7 @@ UShortToPtr( return( (void *)(UINT_PTR)us ); } -#else // !defined(BIT64) +#else // !defined(HOST_64BIT) #define HandleToULong( h ) ((ULONG)(ULONG_PTR)(h) ) #define HandleToLong( h ) ((LONG)(LONG_PTR) (h) ) #define ULongToHandle( ul ) ((HANDLE)(ULONG_PTR) (ul) ) @@ -499,7 +496,7 @@ UShortToPtr( #define ULongToPtr( ul ) ((VOID *)(ULONG_PTR)((unsigned long)(ul))) #define ShortToPtr( s ) ((VOID *)(INT_PTR)((short)(s))) #define UShortToPtr( us ) ((VOID *)(UINT_PTR)((unsigned short)(s))) -#endif // !defined(BIT64) +#endif // !defined(HOST_64BIT) @@ -564,13 +561,13 @@ typedef LONG_PTR SSIZE_T, *PSSIZE_T; #ifndef PAL_STDCPP_COMPAT #if defined(__APPLE_CC__) || defined(__linux__) -#ifdef BIT64 +#ifdef HOST_64BIT typedef unsigned long size_t; typedef long ptrdiff_t; -#else // !BIT64 +#else // !HOST_64BIT typedef unsigned int size_t; typedef int ptrdiff_t; -#endif // !BIT64 +#endif // !HOST_64BIT #else typedef ULONG_PTR size_t; typedef LONG_PTR ptrdiff_t; @@ -587,21 +584,18 @@ typedef LONG_PTR LPARAM; #define _PTRDIFF_T #endif -#ifdef PAL_STDCPP_COMPAT - typedef char16_t WCHAR; -#else // PAL_STDCPP_COMPAT +#ifndef PAL_STDCPP_COMPAT -typedef wchar_t WCHAR; -#if defined(__linux__) -#ifdef BIT64 +#if defined(__linux__) +#ifdef HOST_64BIT typedef long int intptr_t; typedef unsigned long int uintptr_t; -#else // !BIT64 +#else // !HOST_64BIT typedef int intptr_t; typedef unsigned int uintptr_t; -#endif // !BIT64 +#endif // !HOST_64BIT #else typedef INT_PTR intptr_t; typedef UINT_PTR uintptr_t; @@ -700,13 +694,6 @@ typedef struct _FILETIME { /* Code Page Default Values */ #define CP_ACP 0 /* default to ANSI code page */ -#define CP_OEMCP 1 /* default to OEM code page */ -#define CP_MACCP 2 /* default to MAC code page */ -#define CP_THREAD_ACP 3 /* current thread's ANSI code page */ -#define CP_WINUNICODE 1200 -#define CP_UNICODE 1200 /* Unicode */ -#define CP_UNICODESWAP 1201 /* Unicode Big-Endian */ -#define CP_UTF7 65000 /* UTF-7 translation */ #define CP_UTF8 65001 /* UTF-8 translation */ typedef PVOID PSID; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal_unwind.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal_unwind.h deleted file mode 100644 index 2931488..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/pal_unwind.h +++ /dev/null @@ -1,91 +0,0 @@ -// 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. - -// -// Definition of the Unwind API functions. -// Taken from the ABI documentation. -// - - - -#ifndef __PAL_UNWIND_H__ -#define __PAL_UNWIND_H__ - -#if FEATURE_PAL_SXS - -#ifdef __cplusplus -extern "C" -{ -#endif // __cplusplus - - // - // Exception Handling ABI Level I: Base ABI - // - - typedef enum - { - _URC_NO_REASON = 0, - _URC_FOREIGN_EXCEPTION_CAUGHT = 1, - _URC_FATAL_PHASE2_ERROR = 2, - _URC_FATAL_PHASE1_ERROR = 3, - _URC_NORMAL_STOP = 4, - _URC_END_OF_STACK = 5, - _URC_HANDLER_FOUND = 6, - _URC_INSTALL_CONTEXT = 7, - _URC_CONTINUE_UNWIND = 8, - } _Unwind_Reason_Code; - - typedef enum - { - _UA_SEARCH_PHASE = 1, - _UA_CLEANUP_PHASE = 2, - _UA_HANDLER_FRAME = 4, - _UA_FORCE_UNWIND = 8, - } _Unwind_Action; - #define _UA_PHASE_MASK (_UA_SEARCH_PHASE|_UA_CLEANUP_PHASE) - - struct _Unwind_Context; - - void *_Unwind_GetIP(struct _Unwind_Context *context); - void _Unwind_SetIP(struct _Unwind_Context *context, void *new_value); - void *_Unwind_GetCFA(struct _Unwind_Context *context); - void *_Unwind_GetGR(struct _Unwind_Context *context, int index); - void _Unwind_SetGR(struct _Unwind_Context *context, int index, void *new_value); - - struct _Unwind_Exception; - - typedef void (*_Unwind_Exception_Cleanup_Fn)( - _Unwind_Reason_Code urc, - struct _Unwind_Exception *exception_object); - - struct _Unwind_Exception - { - ULONG64 exception_class; - _Unwind_Exception_Cleanup_Fn exception_cleanup; - UINT_PTR private_1; - UINT_PTR private_2; - } __attribute__((aligned)); - - void _Unwind_DeleteException(struct _Unwind_Exception *exception_object); - - typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *context, void *pvParam); - _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn pfnTrace, void *pvParam); - - _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exception_object); - __attribute__((noreturn)) void _Unwind_Resume(struct _Unwind_Exception *exception_object); - - // - // Exception Handling ABI Level II: C++ ABI - // - - void *__cxa_begin_catch(void *exceptionObject); - void __cxa_end_catch(); - -#ifdef __cplusplus -}; -#endif // __cplusplus - -#endif // FEATURE_PAL_SXS - -#endif // __PAL_UNWIND_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/palprivate.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/palprivate.h index b9c9d08..a9d8624 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/palprivate.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/palprivate.h @@ -31,18 +31,6 @@ CreateFileA( IN DWORD dwFlagsAndAttributes, IN HANDLE hTemplateFile); -PALIMPORT -DWORD -PALAPI -SearchPathA( - IN LPCSTR lpPath, - IN LPCSTR lpFileName, - IN LPCSTR lpExtension, - IN DWORD nBufferLength, - OUT LPSTR lpBuffer, - OUT LPSTR *lpFilePart - ); - PALIMPORT BOOL PALAPI @@ -73,6 +61,13 @@ CreateDirectoryA( IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes); +PALIMPORT +BOOL +PALAPI +CreateDirectoryW( + IN LPCWSTR lpPathName, + IN LPSECURITY_ATTRIBUTES lpSecurityAttributes); + PALIMPORT HANDLE PALAPI @@ -100,6 +95,13 @@ SetFileAttributesA( IN LPCSTR lpFileName, IN DWORD dwFileAttributes); +PALIMPORT +BOOL +PALAPI +SetFileAttributesW( + IN LPCWSTR lpFileName, + IN DWORD dwFileAttributes); + PALIMPORT DWORD PALAPI @@ -132,6 +134,12 @@ GetCurrentDirectoryA( IN DWORD nBufferLength, OUT LPSTR lpBuffer); +PALIMPORT +BOOL +PALAPI +SetCurrentDirectoryW( + IN LPCWSTR lpPathName); + PALIMPORT BOOL PALAPI @@ -243,8 +251,7 @@ GetModuleFileNameA( PALIMPORT LPSTR PALAPI -GetEnvironmentStringsA( - VOID); +GetEnvironmentStringsA(); PALIMPORT BOOL @@ -273,6 +280,12 @@ PALAPI RemoveDirectoryA( IN LPCSTR lpPathName); +PALIMPORT +BOOL +PALAPI +RemoveDirectoryW( + IN LPCWSTR lpPathName); + PALIMPORT BOOL PALAPI @@ -280,6 +293,24 @@ PAL_GetPALDirectoryA( OUT LPSTR lpDirectoryName, IN UINT* cchDirectoryName); +PALIMPORT +LONG +PALAPI +CompareFileTime( + IN CONST FILETIME *lpFileTime1, + IN CONST FILETIME *lpFileTime2); + +PALIMPORT char * __cdecl _fullpath(char *, const char *, size_t); + +/* These are from the file in windows. + They are needed for _open_osfhandle.*/ +#define _O_RDONLY 0x0000 +#define _O_APPEND 0x0008 +#define _O_TEXT 0x4000 +#define _O_BINARY 0x8000 + +PALIMPORT int __cdecl _open_osfhandle(INT_PTR, int); + #ifdef __cplusplus } #endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/accctrl.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/accctrl.h index 6670eac..c2491f2 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/accctrl.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/accctrl.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: accctl.h -// +// // =========================================================================== // dummy accctl.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/aclapi.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/aclapi.h index 3cad8e4..2494a36 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/aclapi.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/aclapi.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: aclapi.h -// +// // =========================================================================== // dummy aclapi.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/atl.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/atl.h deleted file mode 100644 index 9f95fc7..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/atl.h +++ /dev/null @@ -1,557 +0,0 @@ -// 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. -// - -// -// =========================================================================== -// File: atl.h -// -// =========================================================================== - -#ifndef __ATL_H__ -#define __ATL_H__ - -#include "ole2.h" -///////////////////////////////////////////////////////////////////////////// -// COM Smart pointers - -template -class _NoAddRefReleaseOnCComPtr : public T -{ - private: - STDMETHOD_(ULONG, AddRef)()=0; - STDMETHOD_(ULONG, Release)()=0; -}; - -//CComPtrBase provides the basis for all other smart pointers -//The other smartpointers add their own constructors and operators -template -class CComPtrBase -{ -protected: - CComPtrBase() - { - p = NULL; - } - CComPtrBase(int nNull) - { - (void)nNull; - p = NULL; - } - CComPtrBase(T* lp) - { - p = lp; - if (p != NULL) - p->AddRef(); - } -public: - typedef T _PtrClass; - ~CComPtrBase() - { - if (p) - p->Release(); - } - operator T*() const - { - return p; - } - T& operator*() const - { - return *p; - } - T** operator&() - { - return &p; - } - _NoAddRefReleaseOnCComPtr* operator->() const - { - return (_NoAddRefReleaseOnCComPtr*)p; - } - bool operator!() const - { - return (p == NULL); - } - bool operator<(T* pT) const - { - return p < pT; - } - bool operator==(T* pT) const - { - return p == pT; - } - - // Release the interface and set to NULL - void Release() - { - T* pTemp = p; - if (pTemp) - { - p = NULL; - pTemp->Release(); - } - } - // Attach to an existing interface (does not AddRef) - void Attach(T* p2) - { - if (p) - p->Release(); - p = p2; - } - // Detach the interface (does not Release) - T* Detach() - { - T* pt = p; - p = NULL; - return pt; - } - HRESULT CopyTo(T** ppT) - { - if (ppT == NULL) - return E_POINTER; - *ppT = p; - if (p) - p->AddRef(); - return S_OK; - } - - T* p; -}; - -template -class CComPtr : public CComPtrBase -{ -public: - CComPtr() - { - } - CComPtr(int nNull) : - CComPtrBase(nNull) - { - } - CComPtr(T* lp) : - CComPtrBase(lp) - - { - } - CComPtr(const CComPtr& lp) : - CComPtrBase(lp.p) - { - } - T* operator=(T* lp) - { - return static_cast(AtlComPtrAssign((IUnknown**)&this->p, lp)); - } - T* operator=(const CComPtr& lp) - { - return static_cast(AtlComPtrAssign((IUnknown**)&this->p, lp)); - } -}; - -#define IUNKNOWN_METHODS \ -private: ULONG m_dwRef; \ -public: \ - virtual ULONG STDMETHODCALLTYPE AddRef( void) { \ - return (ULONG)InterlockedIncrement((LONG*)&m_dwRef); } \ - virtual ULONG STDMETHODCALLTYPE Release( void) { \ - ULONG new_ref = (ULONG)InterlockedDecrement((LONG*)&m_dwRef); \ - if (new_ref == 0) { delete this; return 0; } return new_ref; } \ - - -#define BEGIN_COM_MAP(t) \ - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) \ - { \ - if (ppvObject == NULL) \ - { \ - return E_POINTER; \ - } - -#define COM_INTERFACE_ENTRY(i) \ - if (riid == IID_##i) \ - { \ - *ppvObject = (i*)this; \ - this->AddRef(); \ - return S_OK; \ - } - -#define END_COM_MAP() \ - return E_NOINTERFACE; \ - } \ - virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0; \ - virtual ULONG STDMETHODCALLTYPE Release( void) = 0; - - - -template -class ISupportErrorInfoImpl : public ISupportErrorInfo -{ -public: - STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid) - { - return (riid == *piid) ? S_OK : S_FALSE; - } -}; - -inline IUnknown* AtlComPtrAssign(IUnknown** pp, IUnknown* lp) -{ - if (lp != NULL) - lp->AddRef(); - if (*pp) - (*pp)->Release(); - *pp = lp; - return lp; -} - -inline IUnknown* AtlComQIPtrAssign(IUnknown** pp, IUnknown* lp, REFIID riid) -{ - IUnknown* pTemp = *pp; - *pp = NULL; - if (lp != NULL) - lp->QueryInterface(riid, (void**)pp); - if (pTemp) - pTemp->Release(); - return *pp; -} - - -class CComMultiThreadModelNoCS -{ -public: - static ULONG WINAPI Increment(LONG *p) {return InterlockedIncrement(p);} - static ULONG WINAPI Decrement(LONG *p) {return InterlockedDecrement(p);} -}; - -//Base is the user's class that derives from CComObjectRoot and whatever -//interfaces the user wants to support on the object -template -class CComObject : public Base -{ -public: - typedef Base _BaseClass; - - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - ~CComObject() - { - this->m_dwRef = -(LONG_MAX/2); - } - //If InternalAddRef or InternalRelease is undefined then your class - //doesn't derive from CComObjectRoot - STDMETHOD_(ULONG, AddRef)() {return this->InternalAddRef();} - STDMETHOD_(ULONG, Release)() - { - ULONG l = this->InternalRelease(); - if (l == 0) - delete this; - return l; - } - - static HRESULT WINAPI CreateInstance(CComObject** pp); -}; - -template -HRESULT WINAPI CComObject::CreateInstance(CComObject** pp) -{ - ATLASSERT(pp != NULL); - if (pp == NULL) - return E_POINTER; - *pp = NULL; - - HRESULT hRes = E_OUTOFMEMORY; - CComObject* p = NULL; - p = new CComObject(); - if (p != NULL) - { - hRes = NOERROR; - } - *pp = p; - return hRes; -} - - -// the functions in this class don't need to be virtual because -// they are called from CComObject -class CComObjectRootBase -{ -public: - CComObjectRootBase() - { - m_dwRef = 0L; - } -public: - LONG m_dwRef; -}; // CComObjectRootBase - -template -class CComObjectRootEx : public CComObjectRootBase -{ -public: - typedef ThreadModel _ThreadModel; - - ULONG InternalAddRef() - { - ATLASSERT(m_dwRef != -1L); - return _ThreadModel::Increment(&m_dwRef); - } - ULONG InternalRelease() - { -#ifdef _DEBUG - LONG nRef = _ThreadModel::Decrement(&m_dwRef); - if (nRef < -(LONG_MAX / 2)) - { - ATLASSERT(0); - } - return nRef; -#else - return _ThreadModel::Decrement(&m_dwRef); -#endif - } -}; // CComObjectRootEx - -typedef CComMultiThreadModelNoCS CComObjectThreadModel; - -typedef CComObjectRootEx CComObjectRoot; - -// dummy definitions for the ATL COM goo -#define DECLARE_NO_REGISTRY() - -#define BEGIN_OBJECT_MAP(x) static const int x = 0; -#define OBJECT_ENTRY(clsid, class) -#define END_OBJECT_MAP() - -template -class CComCoClass { -}; - -class CComModule { -public: - HINSTANCE m_hInst; - HINSTANCE m_hInstResource; - - HRESULT Init(int objmap, HINSTANCE h) - { - m_hInst = h; - return S_OK; - } - - void Term() - { - m_hInst = NULL; - m_hInstResource = NULL; - } - - HINSTANCE GetModuleInstance() - { - return m_hInst; - } - - HINSTANCE GetResourceInstance() - { - return m_hInstResource; - } -}; - -template -class CAtlArray -{ -private: - E * m_pData; // Elements of the array. - size_t m_nSize; // Number of valid elements in the array. - size_t m_nMaxSize; // Total number of elements m_pData buffer can hold. - - // Call the constructors for the nElements elements starting from pBeggingElement - void CallConstructors( E* pBeginningElement, size_t nElements ) - { - for( size_t iElement = 0; iElement < nElements; iElement++ ) - { - ::new( this->pElements+iElement ) E; - } - } - - // Call the destructor for the nElements elements starting from pBeggingElement - void CallDestructors( E* pBeginningElement, size_t nElements ) - { - ATLASSERT(nElements == 0 || - pBeginningElement + (nElements-1) < m_pData + m_nSize // Should not go beyond the valid element range. - ); - - for( size_t iElement = 0; iElement < nElements; iElement++ ) - { - pBeginningElement[iElement].~E(); -#ifdef DEBUG - // Put some garbage there. - // It would be 0xcccccccc if the element is a pointer. For easy debugging. - memset(&pBeginningElement[iElement], 0xcc, sizeof(E)); -#endif - } - } - - -public: - CAtlArray() : m_pData(NULL), m_nSize(0), m_nMaxSize(0) {} - ~CAtlArray() { RemoveAll(); } - - size_t GetCount() const - { - return m_nSize; - } - - bool IsEmpty() - { - return m_nSize == 0; - } - - void RemoveAll() - { - if (m_pData) - { - CallDestructors( m_pData, m_nSize ); - free( m_pData ); - m_pData = NULL; - m_nSize = 0; - m_nMaxSize = 0; - } - - ATLASSERT(m_pData == NULL); - ATLASSERT(m_nSize == 0); - ATLASSERT(m_nMaxSize == 0); - } - - E& GetAt( size_t iElement ) - { - ATLASSERT(iElement < m_nSize); - if (iElement >= m_nSize) - AtlThrow(E_INVALIDARG); - return (m_pData[iElement]); - } - - E& operator[]( size_t iElement ) - { - return GetAt(iElement); - } - - E* GetData() - { - return (m_pData); - } - - void SetCount( size_t nNewSize ) - { - if ( nNewSize == 0 ) - { - RemoveAll(); - } - else - if ( nNewSize <= m_nSize ) - { - CallDestructors( m_pData+nNewSize, m_nSize-nNewSize ); - m_nSize = nNewSize; - } - else - if ( nNewSize > m_nSize ) - { - bool bSuccess = GrowBuffer( nNewSize ); - if( !bSuccess ) - { - AtlThrow( E_OUTOFMEMORY ); - } - - CallDestructors( m_pData+m_nSize, nNewSize-m_nSize ); - m_nSize = nNewSize; - } - } - - bool GrowBuffer( size_t nNewMaxSize ) - { - if( nNewMaxSize > m_nMaxSize ) - { - E* pNewData = static_cast< E* >( malloc( nNewMaxSize*sizeof( E ) ) ); - if( pNewData == NULL ) - { - return false; - } - - // Ok, allocation succeeded. - - if (m_pData == NULL) - { - // First time allocation. Simply return the newly allocated buffer. - goto DoneNewBuffer; - - } - - // copy new data from old - memmove( pNewData, m_pData, m_nSize*sizeof( E )); - - // get rid of old stuff - // (note: no need to call the destructors, because the elements are still alive - // in the new array.) - free( m_pData ); - -DoneNewBuffer: - m_pData = pNewData; - m_nMaxSize = nNewMaxSize; - } - - return true; - } - - size_t Add( E element ) - { - size_t iElement = m_nSize; - - if( iElement >= m_nMaxSize ) - { - size_t nNewMaxSize = m_nMaxSize * 2; - nNewMaxSize = (nNewMaxSize >= 16)?nNewMaxSize:16; // Let's allocate at least 16 elements. - if (nNewMaxSize < m_nMaxSize) - AtlThrow( E_OUTOFMEMORY ); // Integer overflow - - if (iElement >= nNewMaxSize) - { - nNewMaxSize = iElement + 1; - if (nNewMaxSize m_nSize ) - AtlThrow(E_INVALIDARG); - - // just remove a range - size_t nMoveCount = m_nSize-(iElement+nElements); - CallDestructors( m_pData+iElement, nElements ); - if( nMoveCount > 0 ) - { - memmove_s( m_pData+iElement, - nMoveCount * sizeof( E ), - m_pData+(iElement+nElements), - nMoveCount * sizeof( E ) - ); - } - m_nSize -= nElements; - } - -}; // CAtlArray - -#endif // __ATL_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/atlcom.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/atlcom.h deleted file mode 100644 index f7d96a1..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/atlcom.h +++ /dev/null @@ -1,13 +0,0 @@ -// 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. -// - -// -// =========================================================================== -// File: atlcom.h -// -// =========================================================================== -// dummy atlcom.h for PAL - -#include "atl.h" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/atlwin.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/atlwin.h deleted file mode 100644 index 0d63430..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/atlwin.h +++ /dev/null @@ -1,13 +0,0 @@ -// 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. -// - -// -// =========================================================================== -// File: atlwin.h -// -// =========================================================================== -// dummy atlwin.h for PAL - -#include "atlwin.h" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/commctrl.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/commctrl.h index f7065dc..d56ff80 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/commctrl.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/commctrl.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: commctrl.h -// +// // =========================================================================== // dummy commctrl.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/commdlg.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/commdlg.h index 0ef590d..be5fdfe 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/commdlg.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/commdlg.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: commdlg.h -// +// // =========================================================================== // dummy commdlg.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/conio.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/conio.h index 955a929..4cc3e4b 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/conio.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/conio.h @@ -6,8 +6,8 @@ // // =========================================================================== // File: conio.h -// -// =========================================================================== +// +// =========================================================================== // dummy conio.h for PAL #include "palrt.h" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/assert.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/assert.h index b0c8ecd..3f86104 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/assert.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/assert.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: assert.h -// +// // =========================================================================== // dummy assert.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/cstdlib b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/cstdlib index 74d9989..ee8f59a 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/cstdlib +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/cstdlib @@ -7,7 +7,7 @@ // // =========================================================================== // File: cstdlib -// +// // =========================================================================== // dummy cstdlib for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/ctype.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/ctype.h index 2cd9456..12a0e69 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/ctype.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/ctype.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: ctype.h -// +// // =========================================================================== // dummy ctype.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/emmintrin.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/emmintrin.h index cd633a3..89e1492 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/emmintrin.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/emmintrin.h @@ -40,7 +40,7 @@ typedef char __v16qi __attribute__((__vector_size__(16))); /* Define the default attribute for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, NODEBUG_ATTRIBUTE, __target__("sse2"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, NODEBUG_ATTRIBUTE)) /// \brief Performs a bitwise OR of two 128-bit integer vectors. /// diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/fcntl.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/fcntl.h index 4acf456..47b948a 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/fcntl.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/fcntl.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: fcntl.h -// +// // =========================================================================== // dummy fcntl.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/float.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/float.h index 87705ee..c7c2ca2 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/float.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/float.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: float.h -// +// // =========================================================================== // dummy float.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/io.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/io.h index d742d1c..a80d9a4 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/io.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/io.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: io.h -// +// // =========================================================================== // dummy io.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/limits.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/limits.h index 21b6d47..6c0ee61 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/limits.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/limits.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: limits.h -// +// // =========================================================================== // dummy limits.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/malloc.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/malloc.h index a9ecc1a..a8324bb 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/malloc.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/malloc.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: malloc.h -// +// // =========================================================================== // dummy malloc.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/math.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/math.h index 07dbfa3..9f70610 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/math.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/math.h @@ -5,8 +5,8 @@ // // =========================================================================== -// File: math.h -// +// File: math.h +// // =========================================================================== // dummy math.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/memory.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/memory.h index 8257d71..09f74a1 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/memory.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/memory.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: memory.h -// +// // =========================================================================== // dummy memory.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stdarg.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stdarg.h index 22517d0..dfbe495 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stdarg.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stdarg.h @@ -6,8 +6,8 @@ // // =========================================================================== // File: stdarg.h -// -// =========================================================================== +// +// =========================================================================== // dummy stdarg.h for PAL #include "palrt.h" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stddef.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stddef.h index 1725893..c4bfff3 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stddef.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stddef.h @@ -5,9 +5,9 @@ // // =========================================================================== -// File: stddef.h -// -// =========================================================================== +// File: stddef.h +// +// =========================================================================== // dummy stddef.h for PAL #include "palrt.h" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stdio.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stdio.h index 35ed761..1d00ca3 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stdio.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stdio.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: stdio.h -// +// // =========================================================================== // dummy stdio.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stdlib.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stdlib.h index 68e0a40..6a89f45 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stdlib.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/stdlib.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: stdlib.h -// +// // =========================================================================== // dummy stdlib.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/string.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/string.h index 8045132..cfc81cc 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/string.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/string.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: string.h -// +// // =========================================================================== // dummy string.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/time.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/time.h index d6f487e..127083b 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/time.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/time.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: time.h -// +// // =========================================================================== // dummy time.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/wchar.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/wchar.h index af00ca0..569a021 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/wchar.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/cpp/wchar.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: wchar.h -// +// // =========================================================================== // dummy wchar.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/crtdbg.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/crtdbg.h index e94bb32..456b471 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/crtdbg.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/crtdbg.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: crtdbg.h -// +// // =========================================================================== // dummy crtdbg.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/guiddef.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/guiddef.h index 392df60..db742c6 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/guiddef.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/guiddef.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: guiddef.h -// +// // =========================================================================== // simplified guiddef.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/htmlhelp.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/htmlhelp.h index 6ae044a..b554033 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/htmlhelp.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/htmlhelp.h @@ -6,8 +6,8 @@ // // =========================================================================== // File: htmlhelp.h -// -// =========================================================================== +// +// =========================================================================== // dummy htmlhelp.h for PAL #include "palrt.h" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/intsafe.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/intsafe.h index 6e28175..1d18f91 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/intsafe.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/intsafe.h @@ -50,11 +50,6 @@ #endif -#define INT_MAX 2147483647 -#define LONG_MAX 2147483647L -#define USHRT_MAX 0xffff -#define UINT_MAX 0xffffffff -#define ULONG_MAX 0xffffffffUL #define DWORD_MAX 0xffffffffUL // @@ -72,7 +67,7 @@ #define ULONGLONG_ERROR (0xffffffffffffffffULL) #define HIDWORD_MASK (0xffffffff00000000ULL) #endif // _MSC_VER -#ifdef _WIN64 +#ifdef HOST_64BIT #define SIZET_ERROR ULONGLONG_ERROR #else #define SIZET_ERROR ULONG_ERROR @@ -350,7 +345,7 @@ UIntToLong( IN UINT Operand, OUT LONG* Result) { - if (Operand <= LONG_MAX) + if (Operand <= _I32_MAX) { *Result = (LONG)Operand; return S_OK; @@ -372,7 +367,7 @@ UIntToULong( OUT ULONG* pulResult) { *pulResult = (ULONG)uOperand; - + return S_OK; } @@ -490,7 +485,7 @@ ULongToUInt( OUT UINT* puResult) { *puResult = (UINT)ulOperand; - + return S_OK; } @@ -503,7 +498,7 @@ ULongToLong( IN ULONG Operand, OUT LONG* Result) { - if (Operand <= LONG_MAX) + if (Operand <= _I32_MAX) { *Result = (LONG)Operand; return S_OK; @@ -545,7 +540,7 @@ ULongLongToLong( IN ULONGLONG Operand, OUT LONG* Result) { - if (Operand <= LONG_MAX) + if (Operand <= _I32_MAX) { *Result = (LONG)Operand; return S_OK; @@ -611,13 +606,13 @@ ULongLongToULong( { HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; *pulResult = ULONG_ERROR; - - if (ullOperand <= ULONG_MAX) + + if (ullOperand <= _UI32_MAX) { *pulResult = (ULONG)ullOperand; hr = S_OK; } - + return hr; } @@ -625,7 +620,7 @@ ULongLongToULong( // UINT_PTR -> ULONG conversion // ULONG_PTR -> ULONG conversion // -#ifdef _WIN64 +#ifdef HOST_64BIT #define UIntPtrToULong ULongLongToULong #define ULongPtrToULong ULongLongToULong @@ -665,13 +660,13 @@ ULongLongToUInt( { HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; *puResult = UINT_ERROR; - + if (ullOperand <= UINT_MAX) { *puResult = (UINT)ullOperand; hr = S_OK; } - + return hr; } @@ -679,7 +674,7 @@ ULongLongToUInt( // UINT_PTR -> UINT conversion // ULONG_PTR -> UINT conversion // -#ifdef _WIN64 +#ifdef HOST_64BIT #define UIntPtrToUInt ULongLongToUInt #define ULongPtrToUInt ULongLongToUInt @@ -780,7 +775,7 @@ ULongPtrToUInt( // // * -> UINT_PTR conversion (UINT_PTR is UINT on Win32, ULONGLONG on Win64) // -#ifdef _WIN64 +#ifdef HOST_64BIT #define CharToUIntPtr CharToULongLong #define SignedCharToUIntPtr SignedCharToULongLong #define ShortToUIntPtr ShortToULongLong @@ -816,7 +811,7 @@ ULongLongToUIntPtr( IN ULONGLONG ullOperand, OUT UINT_PTR* puResult) { -#ifdef _WIN64 +#ifdef HOST_64BIT *puResult = ullOperand; return S_OK; #else @@ -828,7 +823,7 @@ ULongLongToUIntPtr( // // UINT_PTR -> * conversion (UINT_PTR is UINT on Win32, ULONGLONG on Win64) // -#ifdef _WIN64 +#ifdef HOST_64BIT #define UIntPtrToUShort ULongLongToUShort #define UIntPtrToInt ULongLongToInt #define UIntPtrToLong ULongLongToLong @@ -873,7 +868,7 @@ UIntPtrToLong( // // * -> ULONG_PTR conversion (ULONG_PTR is ULONG on Win32, ULONGLONG on Win64) // -#ifdef _WIN64 +#ifdef HOST_64BIT #define CharToULongPtr CharToULongLong #define SignedCharToULongPtr SignedCharToULongLong #define ShortToULongPtr ShortToULongLong @@ -909,7 +904,7 @@ ULongLongToULongPtr( IN ULONGLONG ullOperand, OUT ULONG_PTR* pulResult) { -#ifdef _WIN64 +#ifdef HOST_64BIT *pulResult = ullOperand; return S_OK; #else @@ -921,7 +916,7 @@ ULongLongToULongPtr( // // ULONG_PTR -> * conversion (ULONG_PTR is ULONG on Win32, ULONGLONG on Win64) // -#ifdef _WIN64 +#ifdef HOST_64BIT #define ULongPtrToUShort ULongLongToUShort #define ULongPtrToInt ULongLongToInt #define ULongPtrToLong ULongLongToLong @@ -1058,7 +1053,7 @@ UShortAdd( *pusResult = (usAugend + usAddend); hr = S_OK; } - + return hr; } @@ -1085,7 +1080,7 @@ UIntAdd( *puResult = (uAugend + uAddend); hr = S_OK; } - + return hr; } @@ -1112,14 +1107,14 @@ ULongAdd( *pulResult = (ulAugend + ulAddend); hr = S_OK; } - + return hr; } // // ULONG_PTR addition // -#ifdef _WIN64 +#ifdef HOST_64BIT #define ULongPtrAdd ULongLongAdd #else __inline @@ -1131,7 +1126,7 @@ ULongPtrAdd( { return ULongAdd((ULONG)ulAugend, (ULONG)ulAddend, (ULONG*)pulResult); } -#endif // _WIN64 +#endif // HOST_64BIT // // DWORD addition @@ -1161,7 +1156,7 @@ SizeTAdd( *pResult = (Augend + Addend); hr = S_OK; } - + return hr; } @@ -1188,7 +1183,7 @@ ULongLongAdd( *pullResult = (ullAugend + ullAddend); hr = S_OK; } - + return hr; } @@ -1210,7 +1205,7 @@ UShortSub( *pusResult = (usMinuend - usSubtrahend); hr = S_OK; } - + return hr; } @@ -1238,7 +1233,7 @@ UIntSub( *puResult = (uMinuend - uSubtrahend); hr = S_OK; } - + return hr; } @@ -1265,14 +1260,14 @@ ULongSub( *pulResult = (ulMinuend - ulSubtrahend); hr = S_OK; } - + return hr; } // // ULONG_PTR subtraction // -#ifdef _WIN64 +#ifdef HOST_64BIT #define ULongPtrSub ULongLongSub #else __inline @@ -1284,7 +1279,7 @@ ULongPtrSub( { return ULongSub((ULONG)ulMinuend, (ULONG)ulSubtrahend, (ULONG*)pulResult); } -#endif // _WIN64 +#endif // HOST_64BIT // @@ -1315,7 +1310,7 @@ SizeTSub( *pResult = (Minuend - Subtrahend); hr = S_OK; } - + return hr; } @@ -1342,7 +1337,7 @@ ULongLongSub( *pullResult = (ullMinuend - ullSubtrahend); hr = S_OK; } - + return hr; } @@ -1357,7 +1352,7 @@ UShortMult( OUT USHORT* pusResult) { ULONG ulResult = ((ULONG)usMultiplicand) * (ULONG)usMultiplier; - + return ULongToUShort(ulResult, pusResult); } @@ -1392,7 +1387,7 @@ ULongMult( OUT ULONG* pulResult) { ULONGLONG ull64Result = UInt32x32To64(ulMultiplicand, ulMultiplier); - + return ULongLongToULong(ull64Result, pulResult); } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/mbstring.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/mbstring.h index bf9ceb6..0813ae6 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/mbstring.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/mbstring.h @@ -5,8 +5,8 @@ // // =========================================================================== -// File: mbstring.h -// +// File: mbstring.h +// // =========================================================================== // dummy mbstring.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/new.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/new.h index b9932d7..740a18c 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/new.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/new.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: new.h -// +// // =========================================================================== // dummy new.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/no_sal2.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/no_sal2.h index d2a97a4..aa6c6db 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/no_sal2.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/no_sal2.h @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - + /*** * no_sal2.h - renders the SAL annotations for documenting APIs harmless. * diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/ntimage.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/ntimage.h index 8e03cb4..10686ef 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/ntimage.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/ntimage.h @@ -5,8 +5,8 @@ // // =========================================================================== -// File: ntimage.h -// +// File: ntimage.h +// // =========================================================================== // @@ -16,7 +16,7 @@ // //Author: // -// +// // //Revision History: // @@ -30,7 +30,7 @@ #endif // -// Define the linker version number. +// Define the linker version number. #define IMAGE_MAJOR_LINKER_VERSION 2 @@ -357,7 +357,7 @@ typedef struct _IMAGE_OPTIONAL_HEADER64 { #define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b #define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 -#ifdef _WIN64 +#ifdef HOST_64BIT typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER; typedef PIMAGE_OPTIONAL_HEADER64 PIMAGE_OPTIONAL_HEADER; #define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL64_HEADER @@ -386,7 +386,7 @@ typedef struct _IMAGE_ROM_HEADERS { IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; } IMAGE_ROM_HEADERS, *PIMAGE_ROM_HEADERS; -#ifdef _WIN64 +#ifdef HOST_64BIT typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS; typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS; #else @@ -1006,7 +1006,7 @@ typedef IMAGE_RELOCATION UNALIGNED *PIMAGE_RELOCATION; #define IMAGE_REL_IA64_SECREL22 0x000C #define IMAGE_REL_IA64_SECREL64I 0x000D #define IMAGE_REL_IA64_SECREL32 0x000E -// +// #define IMAGE_REL_IA64_DIR32NB 0x0010 #define IMAGE_REL_IA64_SREL14 0x0011 #define IMAGE_REL_IA64_SREL22 0x0012 @@ -1288,7 +1288,7 @@ typedef struct _IMAGE_TLS_DIRECTORY32 { } IMAGE_TLS_DIRECTORY32; typedef IMAGE_TLS_DIRECTORY32 * PIMAGE_TLS_DIRECTORY32; -#ifdef _WIN64 +#ifdef HOST_64BIT #define IMAGE_ORDINAL_FLAG IMAGE_ORDINAL_FLAG64 #define IMAGE_ORDINAL(Ordinal) IMAGE_ORDINAL64(Ordinal) typedef IMAGE_THUNK_DATA64 IMAGE_THUNK_DATA; @@ -1485,7 +1485,7 @@ typedef struct { ULONG Reserved[ 2 ]; } IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64; -#ifdef _WIN64 +#ifdef HOST_64BIT typedef IMAGE_LOAD_CONFIG_DIRECTORY64 IMAGE_LOAD_CONFIG_DIRECTORY; typedef PIMAGE_LOAD_CONFIG_DIRECTORY64 PIMAGE_LOAD_CONFIG_DIRECTORY; #else @@ -1584,7 +1584,7 @@ typedef struct _IMAGE_DEBUG_DIRECTORY { // end_winnt -// +// // begin_winnt diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/oaidl.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/oaidl.h index f5c9aa1..8e16d4f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/oaidl.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/oaidl.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: oaidl.h -// +// // =========================================================================== #ifndef __OAIDL_H__ @@ -38,23 +38,23 @@ EXTERN_C const IID IID_IErrorInfo; IErrorInfo : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetGUID( + virtual HRESULT STDMETHODCALLTYPE GetGUID( /* [out] */ GUID *pGUID) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSource( + + virtual HRESULT STDMETHODCALLTYPE GetSource( /* [out] */ BSTR *pBstrSource) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDescription( + + virtual HRESULT STDMETHODCALLTYPE GetDescription( /* [out] */ BSTR *pBstrDescription) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetHelpFile( + + virtual HRESULT STDMETHODCALLTYPE GetHelpFile( /* [out] */ BSTR *pBstrHelpFile) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetHelpContext( + + virtual HRESULT STDMETHODCALLTYPE GetHelpContext( /* [out] */ DWORD *pdwHelpContext) = 0; - + }; - + typedef interface ICreateErrorInfo ICreateErrorInfo; EXTERN_C const IID IID_ICreateErrorInfo; @@ -65,23 +65,23 @@ typedef /* [unique] */ ICreateErrorInfo *LPCREATEERRORINFO; ICreateErrorInfo : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE SetGUID( + virtual HRESULT STDMETHODCALLTYPE SetGUID( /* [in] */ REFGUID rguid) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetSource( + + virtual HRESULT STDMETHODCALLTYPE SetSource( /* [in] */ LPOLESTR szSource) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetDescription( + + virtual HRESULT STDMETHODCALLTYPE SetDescription( /* [in] */ LPOLESTR szDescription) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetHelpFile( + + virtual HRESULT STDMETHODCALLTYPE SetHelpFile( /* [in] */ LPOLESTR szHelpFile) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetHelpContext( + + virtual HRESULT STDMETHODCALLTYPE SetHelpContext( /* [in] */ DWORD dwHelpContext) = 0; - + }; - + STDAPI SetErrorInfo(ULONG dwReserved, IErrorInfo FAR* perrinfo); @@ -98,14 +98,14 @@ typedef /* [unique] */ ISupportErrorInfo *LPSUPPORTERRORINFO; EXTERN_C const IID IID_ISupportErrorInfo; - + interface ISupportErrorInfo : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE InterfaceSupportsErrorInfo( + virtual HRESULT STDMETHODCALLTYPE InterfaceSupportsErrorInfo( /* [in] */ REFIID riid) = 0; - + }; #endif //__OAIDL_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/objidl.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/objidl.h index 4586a55..0872542 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/objidl.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/objidl.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: objidl.h -// +// // =========================================================================== // simplified objidl.h for PAL @@ -24,22 +24,22 @@ EXTERN_C const IID IID_IEnumUnknown; interface IEnumUnknown : public IUnknown { public: - virtual /* [local] */ HRESULT STDMETHODCALLTYPE Next( - /* [annotation][in] */ + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Next( + /* [annotation][in] */ _In_ ULONG celt, - /* [annotation][out] */ + /* [annotation][out] */ _Out_writes_to_(celt,*pceltFetched) IUnknown **rgelt, - /* [annotation][out] */ + /* [annotation][out] */ _Out_opt_ ULONG *pceltFetched) = 0; - - virtual HRESULT STDMETHODCALLTYPE Skip( + + virtual HRESULT STDMETHODCALLTYPE Skip( /* [in] */ ULONG celt) = 0; - + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE Clone( + + virtual HRESULT STDMETHODCALLTYPE Clone( /* [out] */ __RPC__deref_out_opt IEnumUnknown **ppenum) = 0; - + }; #endif /* __IEnumUnknown_INTERFACE_DEFINED__ */ @@ -53,16 +53,16 @@ EXTERN_C const IID IID_ISequentialStream; interface ISequentialStream : public IUnknown { public: - virtual /* [local] */ HRESULT STDMETHODCALLTYPE Read( + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Read( /* [length_is][size_is][out] */ void *pv, /* [in] */ ULONG cb, /* [out] */ ULONG *pcbRead) = 0; - - virtual /* [local] */ HRESULT STDMETHODCALLTYPE Write( + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Write( /* [size_is][in] */ const void *pv, /* [in] */ ULONG cb, /* [out] */ ULONG *pcbWritten) = 0; - + }; #endif // __ISequentialStream_INTERFACE_DEFINED__ @@ -86,7 +86,7 @@ typedef struct tagSTATSTG DWORD reserved; } STATSTG; -typedef +typedef enum tagSTGTY { STGTY_STORAGE = 1, STGTY_STREAM = 2, @@ -94,21 +94,14 @@ enum tagSTGTY STGTY_PROPERTY = 4 } STGTY; -typedef +typedef enum tagSTREAM_SEEK { STREAM_SEEK_SET = 0, STREAM_SEEK_CUR = 1, STREAM_SEEK_END = 2 } STREAM_SEEK; -typedef -enum tagLOCKTYPE - { LOCK_WRITE = 1, - LOCK_EXCLUSIVE = 2, - LOCK_ONLYONCE = 4 - } LOCKTYPE; - -typedef +typedef enum tagSTATFLAG { STATFLAG_DEFAULT = 0, STATFLAG_NONAME = 1, @@ -122,44 +115,44 @@ interface DECLSPEC_UUID("0000000c-0000-0000-C000-000000000046") IStream : public ISequentialStream { public: - virtual /* [local] */ HRESULT STDMETHODCALLTYPE Seek( + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Seek( /* [in] */ LARGE_INTEGER dlibMove, /* [in] */ DWORD dwOrigin, /* [out] */ ULARGE_INTEGER *plibNewPosition) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetSize( + + virtual HRESULT STDMETHODCALLTYPE SetSize( /* [in] */ ULARGE_INTEGER libNewSize) = 0; - - virtual /* [local] */ HRESULT STDMETHODCALLTYPE CopyTo( + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE CopyTo( /* [unique][in] */ IStream *pstm, /* [in] */ ULARGE_INTEGER cb, /* [out] */ ULARGE_INTEGER *pcbRead, /* [out] */ ULARGE_INTEGER *pcbWritten) = 0; - - virtual HRESULT STDMETHODCALLTYPE Commit( + + virtual HRESULT STDMETHODCALLTYPE Commit( /* [in] */ DWORD grfCommitFlags) = 0; - + virtual HRESULT STDMETHODCALLTYPE Revert( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE LockRegion( + + virtual HRESULT STDMETHODCALLTYPE LockRegion( /* [in] */ ULARGE_INTEGER libOffset, /* [in] */ ULARGE_INTEGER cb, /* [in] */ DWORD dwLockType) = 0; - - virtual HRESULT STDMETHODCALLTYPE UnlockRegion( + + virtual HRESULT STDMETHODCALLTYPE UnlockRegion( /* [in] */ ULARGE_INTEGER libOffset, /* [in] */ ULARGE_INTEGER cb, /* [in] */ DWORD dwLockType) = 0; - - virtual HRESULT STDMETHODCALLTYPE Stat( + + virtual HRESULT STDMETHODCALLTYPE Stat( /* [out] */ STATSTG *pstatstg, /* [in] */ DWORD grfStatFlag) = 0; - - virtual HRESULT STDMETHODCALLTYPE Clone( + + virtual HRESULT STDMETHODCALLTYPE Clone( /* [out] */ IStream **ppstm) = 0; - + }; - + #endif // __IStream_INTERFACE_DEFINED__ @@ -175,82 +168,82 @@ interface IEnumSTATSTG; interface IStorage : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CreateStream( + virtual HRESULT STDMETHODCALLTYPE CreateStream( /* [string][in] */ const OLECHAR *pwcsName, /* [in] */ DWORD grfMode, /* [in] */ DWORD reserved1, /* [in] */ DWORD reserved2, /* [out] */ IStream **ppstm) = 0; - - virtual /* [local] */ HRESULT STDMETHODCALLTYPE OpenStream( + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE OpenStream( /* [string][in] */ const OLECHAR *pwcsName, /* [unique][in] */ void *reserved1, /* [in] */ DWORD grfMode, /* [in] */ DWORD reserved2, /* [out] */ IStream **ppstm) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateStorage( + + virtual HRESULT STDMETHODCALLTYPE CreateStorage( /* [string][in] */ const OLECHAR *pwcsName, /* [in] */ DWORD grfMode, /* [in] */ DWORD reserved1, /* [in] */ DWORD reserved2, /* [out] */ IStorage **ppstg) = 0; - - virtual HRESULT STDMETHODCALLTYPE OpenStorage( + + virtual HRESULT STDMETHODCALLTYPE OpenStorage( /* [string][unique][in] */ const OLECHAR *pwcsName, /* [unique][in] */ IStorage *pstgPriority, /* [in] */ DWORD grfMode, /* [unique][in] */ SNB snbExclude, /* [in] */ DWORD reserved, /* [out] */ IStorage **ppstg) = 0; - - virtual HRESULT STDMETHODCALLTYPE CopyTo( + + virtual HRESULT STDMETHODCALLTYPE CopyTo( /* [in] */ DWORD ciidExclude, /* [size_is][unique][in] */ const IID *rgiidExclude, /* [unique][in] */ SNB snbExclude, /* [unique][in] */ IStorage *pstgDest) = 0; - - virtual HRESULT STDMETHODCALLTYPE MoveElementTo( + + virtual HRESULT STDMETHODCALLTYPE MoveElementTo( /* [string][in] */ const OLECHAR *pwcsName, /* [unique][in] */ IStorage *pstgDest, /* [string][in] */ const OLECHAR *pwcsNewName, /* [in] */ DWORD grfFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE Commit( + + virtual HRESULT STDMETHODCALLTYPE Commit( /* [in] */ DWORD grfCommitFlags) = 0; - + virtual HRESULT STDMETHODCALLTYPE Revert( void) = 0; - - virtual /* [local] */ HRESULT STDMETHODCALLTYPE EnumElements( + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE EnumElements( /* [in] */ DWORD reserved1, /* [size_is][unique][in] */ void *reserved2, /* [in] */ DWORD reserved3, /* [out] */ IEnumSTATSTG **ppenum) = 0; - - virtual HRESULT STDMETHODCALLTYPE DestroyElement( + + virtual HRESULT STDMETHODCALLTYPE DestroyElement( /* [string][in] */ const OLECHAR *pwcsName) = 0; - - virtual HRESULT STDMETHODCALLTYPE RenameElement( + + virtual HRESULT STDMETHODCALLTYPE RenameElement( /* [string][in] */ const OLECHAR *pwcsOldName, /* [string][in] */ const OLECHAR *pwcsNewName) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetElementTimes( + + virtual HRESULT STDMETHODCALLTYPE SetElementTimes( /* [string][unique][in] */ const OLECHAR *pwcsName, /* [unique][in] */ const FILETIME *pctime, /* [unique][in] */ const FILETIME *patime, /* [unique][in] */ const FILETIME *pmtime) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetClass( + + virtual HRESULT STDMETHODCALLTYPE SetClass( /* [in] */ REFCLSID clsid) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetStateBits( + + virtual HRESULT STDMETHODCALLTYPE SetStateBits( /* [in] */ DWORD grfStateBits, /* [in] */ DWORD grfMask) = 0; - - virtual HRESULT STDMETHODCALLTYPE Stat( + + virtual HRESULT STDMETHODCALLTYPE Stat( /* [out] */ STATSTG *pstatstg, /* [in] */ DWORD grfStatFlag) = 0; - + }; #endif // __IStorage_INTERFACE_DEFINED__ @@ -268,24 +261,24 @@ EXTERN_C const IID IID_IMalloc; interface IMalloc : public IUnknown { public: - virtual void *STDMETHODCALLTYPE Alloc( + virtual void *STDMETHODCALLTYPE Alloc( /* [in] */ SIZE_T cb) = 0; - - virtual void *STDMETHODCALLTYPE Realloc( + + virtual void *STDMETHODCALLTYPE Realloc( /* [in] */ void *pv, /* [in] */ SIZE_T cb) = 0; - - virtual void STDMETHODCALLTYPE Free( + + virtual void STDMETHODCALLTYPE Free( /* [in] */ void *pv) = 0; - - virtual SIZE_T STDMETHODCALLTYPE GetSize( + + virtual SIZE_T STDMETHODCALLTYPE GetSize( /* [in] */ void *pv) = 0; - - virtual int STDMETHODCALLTYPE DidAlloc( + + virtual int STDMETHODCALLTYPE DidAlloc( void *pv) = 0; - + virtual void STDMETHODCALLTYPE HeapMinimize( void) = 0; - + }; typedef /* [unique] */ IMalloc *LPMALLOC; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/ocidl.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/ocidl.h index ab6272e..ab9201e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/ocidl.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/ocidl.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: ocidl.h -// +// // =========================================================================== // dummy ocidl.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/oleauto.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/oleauto.h index 958476f..aa80290 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/oleauto.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/oleauto.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: oleauto.h -// +// // =========================================================================== // simplified oleauto.h for PAL @@ -76,7 +76,7 @@ typedef struct { #endif // Compare results for VarDecCmp. These are returned as a SUCCESS HResult. -// Subtracting one gives the usual values of -1 for Less Than, +// Subtracting one gives the usual values of -1 for Less Than, // 0 for Equal To, +1 for Greater Than. // #define VARCMP_LT 0 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/olectl.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/olectl.h index 94b093f..fddc2e4 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/olectl.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/olectl.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: olectl.h -// +// // =========================================================================== // dummy olectl.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/oleidl.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/oleidl.h index 301692e..9293d1f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/oleidl.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/oleidl.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: oleidl.h -// +// // =========================================================================== // simplified oleidl.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/palrt.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/palrt.h index 6502cf5..0de8be1 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/palrt.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/palrt.h @@ -6,8 +6,8 @@ // // =========================================================================== // File: palrt.h -// -// =========================================================================== +// +// =========================================================================== /*++ @@ -20,7 +20,7 @@ Abstract: Author: - + Revision History: @@ -180,7 +180,7 @@ inline void *__cdecl operator new(size_t, void *_P) #define ARGUMENT_PRESENT(ArgumentPointer) (\ (CHAR *)(ArgumentPointer) != (CHAR *)(NULL) ) -#if defined(_WIN64) +#if defined(HOST_64BIT) #define MAX_NATURAL_ALIGNMENT sizeof(ULONGLONG) #else #define MAX_NATURAL_ALIGNMENT sizeof(ULONG) @@ -223,24 +223,8 @@ inline void *__cdecl operator new(size_t, void *_P) #define THIS_ #define THIS void -#ifndef _DECLSPEC_DEFINED_ -#define _DECLSPEC_DEFINED_ - -#if defined(_MSC_VER) -#define DECLSPEC_NOVTABLE __declspec(novtable) -#define DECLSPEC_IMPORT __declspec(dllimport) -#define DECLSPEC_SELECTANY __declspec(selectany) -#elif defined(__GNUC__) #define DECLSPEC_NOVTABLE -#define DECLSPEC_IMPORT #define DECLSPEC_SELECTANY __attribute__((weak)) -#else -#define DECLSPEC_NOVTABLE -#define DECLSPEC_IMPORT -#define DECLSPEC_SELECTANY -#endif - -#endif // !_DECLSPEC_DEFINED_ #define DECLARE_INTERFACE(iface) interface DECLSPEC_NOVTABLE iface #define DECLARE_INTERFACE_(iface, baseiface) interface DECLSPEC_NOVTABLE iface : public baseiface @@ -310,7 +294,7 @@ typedef union _ULARGE_INTEGER { DWORD LowPart; DWORD HighPart; #endif - } + } #ifndef PAL_STDCPP_COMPAT u #endif // PAL_STDCPP_COMPAT @@ -318,59 +302,6 @@ typedef union _ULARGE_INTEGER { ULONGLONG QuadPart; } ULARGE_INTEGER, *PULARGE_INTEGER; -/******************* HRESULT types ****************************************/ - -#define FACILITY_WINDOWS 8 -#define FACILITY_URT 19 -#define FACILITY_UMI 22 -#define FACILITY_SXS 23 -#define FACILITY_STORAGE 3 -#define FACILITY_SSPI 9 -#define FACILITY_SCARD 16 -#define FACILITY_SETUPAPI 15 -#define FACILITY_SECURITY 9 -#define FACILITY_RPC 1 -#define FACILITY_WIN32 7 -#define FACILITY_CONTROL 10 -#define FACILITY_NULL 0 -#define FACILITY_MSMQ 14 -#define FACILITY_MEDIASERVER 13 -#define FACILITY_INTERNET 12 -#define FACILITY_ITF 4 -#define FACILITY_DPLAY 21 -#define FACILITY_DISPATCH 2 -#define FACILITY_COMPLUS 17 -#define FACILITY_CERT 11 -#define FACILITY_ACS 20 -#define FACILITY_AAF 18 - -#define NO_ERROR 0L - -#define SEVERITY_SUCCESS 0 -#define SEVERITY_ERROR 1 - -#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0) -#define FAILED(Status) ((HRESULT)(Status)<0) -#define IS_ERROR(Status) ((ULONG)(Status) >> 31 == SEVERITY_ERROR) // diff from win32 -#define HRESULT_CODE(hr) ((hr) & 0xFFFF) -#define SCODE_CODE(sc) ((sc) & 0xFFFF) -#define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff) -#define SCODE_FACILITY(sc) (((sc) >> 16) & 0x1fff) -#define HRESULT_SEVERITY(hr) (((hr) >> 31) & 0x1) -#define SCODE_SEVERITY(sc) (((sc) >> 31) & 0x1) - -// both macros diff from Win32 -#define MAKE_HRESULT(sev,fac,code) \ - ((HRESULT) (((ULONG)(sev)<<31) | ((ULONG)(fac)<<16) | ((ULONG)(code))) ) -#define MAKE_SCODE(sev,fac,code) \ - ((SCODE) (((ULONG)(sev)<<31) | ((ULONG)(fac)<<16) | ((LONG)(code))) ) - -#define FACILITY_NT_BIT 0x10000000 -#define HRESULT_FROM_WIN32(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000))) -#define __HRESULT_FROM_WIN32(x) HRESULT_FROM_WIN32(x) - -#define HRESULT_FROM_NT(x) ((HRESULT) ((x) | FACILITY_NT_BIT)) - /******************* OLE, BSTR, VARIANT *************************/ STDAPI_VIS(DLLEXPORT, LPVOID) CoTaskMemAlloc(SIZE_T cb); @@ -501,7 +432,7 @@ enum VARENUM { VT_LPWSTR = 31, VT_RECORD = 36, VT_INT_PTR = 37, - VT_UINT_PTR = 38, + VT_UINT_PTR = 38, VT_FILETIME = 64, VT_BLOB = 65, @@ -629,7 +560,7 @@ STDAPI_(HRESULT) VariantClear(VARIANT * pvarg); #define V_UINTREF(X) V_UNION(X, puintVal) #define V_ARRAY(X) V_UNION(X, parray) -#ifdef _WIN64 +#ifdef HOST_64BIT #define V_INT_PTR(X) V_UNION(X, llVal) #define V_UINT_PTR(X) V_UNION(X, ullVal) #define V_INT_PTRREF(X) V_UNION(X, pllVal) @@ -684,7 +615,7 @@ STDAPI CreateStreamOnHGlobal(PVOID hGlobal, BOOL fDeleteOnRelease, interface ISt #define STGM_NOSNAPSHOT 0x00200000L STDAPI IIDFromString(LPOLESTR lpsz, IID* lpiid); -STDAPI_(int) StringFromGUID2(REFGUID rguid, LPOLESTR lpsz, int cchMax); +STDAPI_(int) StringFromGUID2(REFGUID rguid, LPOLESTR lpsz, int cchMax); /******************* CRYPT **************************************/ @@ -714,34 +645,8 @@ typedef unsigned int ALG_ID; /******************* NLS ****************************************/ -typedef -enum tagMIMECONTF { - MIMECONTF_MAILNEWS = 0x1, - MIMECONTF_BROWSER = 0x2, - MIMECONTF_MINIMAL = 0x4, - MIMECONTF_IMPORT = 0x8, - MIMECONTF_SAVABLE_MAILNEWS = 0x100, - MIMECONTF_SAVABLE_BROWSER = 0x200, - MIMECONTF_EXPORT = 0x400, - MIMECONTF_PRIVCONVERTER = 0x10000, - MIMECONTF_VALID = 0x20000, - MIMECONTF_VALID_NLS = 0x40000, - MIMECONTF_MIME_IE4 = 0x10000000, - MIMECONTF_MIME_LATEST = 0x20000000, - MIMECONTF_MIME_REGISTRY = 0x40000000 - } MIMECONTF; - #define LCMAP_LOWERCASE 0x00000100 #define LCMAP_UPPERCASE 0x00000200 -#define LCMAP_SORTKEY 0x00000400 -#define LCMAP_BYTEREV 0x00000800 - -#define LCMAP_HIRAGANA 0x00100000 -#define LCMAP_KATAKANA 0x00200000 -#define LCMAP_HALFWIDTH 0x00400000 -#define LCMAP_FULLWIDTH 0x00800000 - -#define LCMAP_LINGUISTIC_CASING 0x01000000 // 8 characters for language // 8 characters for region @@ -751,23 +656,10 @@ enum tagMIMECONTF { // 1 null termination #define LOCALE_NAME_MAX_LENGTH 85 -#define LOCALE_SCOUNTRY 0x00000006 -#define LOCALE_SENGCOUNTRY 0x00001002 - -#define LOCALE_SLANGUAGE 0x00000002 -#define LOCALE_SENGLANGUAGE 0x00001001 - -#define LOCALE_SDATE 0x0000001D -#define LOCALE_STIME 0x0000001E - #define CSTR_LESS_THAN 1 #define CSTR_EQUAL 2 #define CSTR_GREATER_THAN 3 -#define NORM_IGNORENONSPACE 0x00000002 - -#define WC_COMPOSITECHECK 0x00000000 // NOTE: diff from winnls.h - /******************* shlwapi ************************************/ // note: diff in NULL handing and calling convetion @@ -836,8 +728,6 @@ Remember to fix the errcode defintion in safecrt.h. #define _wfopen_s _wfopen_unsafe #define fopen_s _fopen_unsafe -#define _strlwr_s _strlwr_unsafe - #define _vscprintf _vscprintf_unsafe extern "C++" { @@ -862,25 +752,7 @@ inline errno_t __cdecl _wcslwr_unsafe(WCHAR *str, size_t sz) _wcslwr(copy); wcscpy_s(str, sz, copy); free(copy); - - return 0; -} -inline errno_t __cdecl _strlwr_unsafe(char *str, size_t sz) -{ - char *copy = (char *)malloc(sz); - if(copy == nullptr) - return 1; - errno_t retCode = strcpy_s(copy, sz, str); - if(retCode) { - free(copy); - return 1; - } - - _strlwr(copy); - strcpy_s(str, sz, copy); - free(copy); - return 0; } @@ -974,7 +846,7 @@ STDAPI_(void) PathStripPathW (LPWSTR pszPath); /******************* misc ***************************************/ #ifdef __cplusplus -namespace std +namespace std { typedef decltype(nullptr) nullptr_t; } @@ -1020,11 +892,11 @@ typedef VOID (NTAPI *WAITORTIMERCALLBACK)(PVOID, BOOLEAN); // usage pattern is: // // int get_scratch_register() { -// #if defined(_TARGET_X86_) +// #if defined(TARGET_X86) // return eax; -// #elif defined(_TARGET_AMD64_) +// #elif defined(TARGET_AMD64) // return rax; -// #elif defined(_TARGET_ARM_) +// #elif defined(TARGET_ARM) // return r0; // #else // PORTABILITY_ASSERT("scratch register"); @@ -1041,7 +913,7 @@ typedef VOID (NTAPI *WAITORTIMERCALLBACK)(PVOID, BOOLEAN); // errors. Once they fix all the places that need attention for portability, // they can define PORTABILITY_ASSERT and PORTABILITY_WARNING to cause // compile-time errors to make sure that they haven't missed anything. -// +// // If it is reasonably possible all codepaths containing PORTABILITY_ASSERT // should be compilable (e.g. functions should return NULL or something if // they are expected to return a value). @@ -1061,7 +933,7 @@ typedef VOID (NTAPI *WAITORTIMERCALLBACK)(PVOID, BOOLEAN); #define UNREFERENCED_PARAMETER(P) (void)(P) -#ifdef BIT64 +#ifdef HOST_64BIT #define VALPTR(x) VAL64(x) #define GET_UNALIGNED_PTR(x) GET_UNALIGNED_64(x) #define GET_UNALIGNED_VALPTR(x) GET_UNALIGNED_VAL64(x) @@ -1075,7 +947,7 @@ typedef VOID (NTAPI *WAITORTIMERCALLBACK)(PVOID, BOOLEAN); #define SET_UNALIGNED_VALPTR(p,x) SET_UNALIGNED_VAL32(p,x) #endif -#ifdef _TARGET_AMD64_ +#ifdef TARGET_AMD64 #define RUNTIME_FUNCTION_INDIRECT 0x1 #endif @@ -1185,7 +1057,7 @@ interface ITypeInfo; interface ITypeLib; interface IMoniker; -typedef VOID (WINAPI *LPOVERLAPPED_COMPLETION_ROUTINE)( +typedef VOID (WINAPI *LPOVERLAPPED_COMPLETION_ROUTINE)( DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped); @@ -1289,7 +1161,7 @@ GET_RUNTIME_FUNCTION_CALLBACK ( typedef GET_RUNTIME_FUNCTION_CALLBACK *PGET_RUNTIME_FUNCTION_CALLBACK; typedef -DWORD +DWORD OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK ( HANDLE Process, PVOID TableAddress, @@ -1301,39 +1173,6 @@ typedef OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK *POUT_OF_PROCESS_FUNCTION_TABLE_C #define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME \ "OutOfProcessFunctionTableCallback" -#if defined(FEATURE_PAL_SXS) - -// #if !defined(_TARGET_MAC64) -// typedef LONG (*PEXCEPTION_ROUTINE)( - // IN PEXCEPTION_POINTERS pExceptionPointers, - // IN LPVOID lpvParam); - -// #define DISPATCHER_CONTEXT LPVOID - -// #else // defined(_TARGET_MAC64) - -// -// Define unwind history table structure. -// - -#define UNWIND_HISTORY_TABLE_SIZE 12 - -typedef struct _UNWIND_HISTORY_TABLE_ENTRY { - DWORD64 ImageBase; - PRUNTIME_FUNCTION FunctionEntry; -} UNWIND_HISTORY_TABLE_ENTRY, *PUNWIND_HISTORY_TABLE_ENTRY; - -typedef struct _UNWIND_HISTORY_TABLE { - DWORD Count; - BYTE LocalHint; - BYTE GlobalHint; - BYTE Search; - BYTE Once; - DWORD64 LowAddress; - DWORD64 HighAddress; - UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE]; -} UNWIND_HISTORY_TABLE, *PUNWIND_HISTORY_TABLE; - typedef EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE) ( @@ -1343,7 +1182,7 @@ EXCEPTION_DISPOSITION PVOID DispatcherContext ); -#if defined(_ARM_) +#if defined(HOST_ARM) typedef struct _DISPATCHER_CONTEXT { DWORD ControlPc; @@ -1354,14 +1193,14 @@ typedef struct _DISPATCHER_CONTEXT { PCONTEXT ContextRecord; PEXCEPTION_ROUTINE LanguageHandler; PVOID HandlerData; - PUNWIND_HISTORY_TABLE HistoryTable; + PVOID HistoryTable; DWORD ScopeIndex; BOOLEAN ControlPcIsUnwound; PBYTE NonVolatileRegisters; DWORD Reserved; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; -#elif defined(_ARM64_) +#elif defined(HOST_ARM64) typedef struct _DISPATCHER_CONTEXT { ULONG64 ControlPc; @@ -1372,14 +1211,14 @@ typedef struct _DISPATCHER_CONTEXT { PCONTEXT ContextRecord; PEXCEPTION_ROUTINE LanguageHandler; PVOID HandlerData; - PUNWIND_HISTORY_TABLE HistoryTable; + PVOID HistoryTable; ULONG64 ScopeIndex; BOOLEAN ControlPcIsUnwound; PBYTE NonVolatileRegisters; ULONG64 Reserved; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; -#elif defined(_AMD64_) +#elif defined(HOST_AMD64) typedef struct _DISPATCHER_CONTEXT { ULONG64 ControlPc; @@ -1390,10 +1229,10 @@ typedef struct _DISPATCHER_CONTEXT { PCONTEXT ContextRecord; PEXCEPTION_ROUTINE LanguageHandler; PVOID HandlerData; - PUNWIND_HISTORY_TABLE HistoryTable; + PVOID HistoryTable; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; -#elif defined(_X86_) +#elif defined(HOST_X86) typedef struct _DISPATCHER_CONTEXT { DWORD ControlPc; @@ -1405,7 +1244,7 @@ typedef struct _DISPATCHER_CONTEXT { PCONTEXT ContextRecord; PEXCEPTION_ROUTINE LanguageHandler; PVOID HandlerData; - PUNWIND_HISTORY_TABLE HistoryTable; + PVOID HistoryTable; BOOLEAN ControlPcIsUnwound; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; @@ -1415,7 +1254,7 @@ typedef struct _DISPATCHER_CONTEXT { #endif -// #endif // !defined(_TARGET_MAC64) +// #endif // !defined(TARGET_OSX) typedef DISPATCHER_CONTEXT *PDISPATCHER_CONTEXT; @@ -1423,8 +1262,6 @@ typedef DISPATCHER_CONTEXT *PDISPATCHER_CONTEXT; #define ExceptionStackUnwind EXCEPTION_EXECUTE_HANDLER #define ExceptionContinueExecution EXCEPTION_CONTINUE_EXECUTION -#endif // FEATURE_PAL_SXS - typedef struct _EXCEPTION_REGISTRATION_RECORD EXCEPTION_REGISTRATION_RECORD; typedef EXCEPTION_REGISTRATION_RECORD *PEXCEPTION_REGISTRATION_RECORD; @@ -1488,7 +1325,7 @@ EXTERN_C HRESULT PALAPI PAL_CoCreateInstance(REFCLSID rclsid, REFIID riid, void **ppv); -// So we can have CoCreateInstance in most of the code base, +// So we can have CoCreateInstance in most of the code base, // instead of spreading around of if'def FEATURE_PALs for PAL_CoCreateInstance. #define CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv) PAL_CoCreateInstance(rclsid, riid, ppv) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/poppack.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/poppack.h index ef4e86b..4d5264c 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/poppack.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/poppack.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: poppack.h -// +// // =========================================================================== /* Abstract: diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/process.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/process.h index 4dcfbe8..901c4e5 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/process.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/process.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: process.h -// +// // =========================================================================== // dummy process.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack1.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack1.h index f53472d..568a609 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack1.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack1.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: pshpack1.h -// +// // =========================================================================== /*++ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack2.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack2.h index bbeffac..d92bac0 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack2.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack2.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: pshpack2.h -// +// // =========================================================================== /*++ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack4.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack4.h index 4431c9d..96ab354 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack4.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack4.h @@ -6,8 +6,8 @@ // // =========================================================================== // File: pshpack4.h -// -// =========================================================================== +// +// =========================================================================== /*++ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack8.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack8.h index b1377d3..35a48dd 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack8.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpack8.h @@ -6,8 +6,8 @@ // // =========================================================================== // File: pshpack8.h -// -// =========================================================================== +// +// =========================================================================== /*++ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpck16.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpck16.h index bb4a0e1..19807f2 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpck16.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/pshpck16.h @@ -6,8 +6,8 @@ // // =========================================================================== // File: pshpck16.h -// -// =========================================================================== +// +// =========================================================================== /*++ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/richedit.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/richedit.h index c3c5849..6c41a08 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/richedit.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/richedit.h @@ -6,8 +6,8 @@ // // =========================================================================== // File: richedit.h -// -// =========================================================================== +// +// =========================================================================== // dummy richedit.h for PAL #include "palrt.h" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/rpc.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/rpc.h index e63e617..5e44c2b 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/rpc.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/rpc.h @@ -6,8 +6,8 @@ // // =========================================================================== // File: rpc.h -// -// =========================================================================== +// +// =========================================================================== // dummy rpc.h for PAL #ifndef __RPC_H__ @@ -19,7 +19,10 @@ #define __RPC_USER #define __RPC_FAR -#define DECLSPEC_UUID(x) __declspec(uuid(x)) +#define __uuidof(type) IID_##type + +#define DECLSPEC_UUID(x) + #define MIDL_INTERFACE(x) struct DECLSPEC_UUID(x) DECLSPEC_NOVTABLE #define EXTERN_GUID(itf,l1,s1,s2,c1,c2,c3,c4,c5,c6,c7,c8) \ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/rpcndr.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/rpcndr.h index bf67d4c..35e4c18 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/rpcndr.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/rpcndr.h @@ -6,8 +6,8 @@ // // =========================================================================== // File: rpcndr.h -// -// =========================================================================== +// +// =========================================================================== // dummy rpcndr.h for PAL #ifndef __RPCNDR_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/safecrt.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/safecrt.h index 9f9e15c..1f5e826 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/safecrt.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/safecrt.h @@ -96,38 +96,18 @@ #endif #endif -/* WCHAR */ -#if defined (SAFECRT_INCLUDE_REDEFINES) -#if !defined(_WCHAR_T_DEFINED) -typedef unsigned short WCHAR; -#define _WCHAR_T_DEFINED -#endif -#endif - /* _W64 */ #if !defined(_W64) -#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +#if !defined(__midl) && (defined(HOST_X86) || defined(_M_IX86)) && _MSC_VER >= 1300 #define _W64 __w64 #else #define _W64 #endif #endif -/* size_t */ -#if defined (SAFECRT_INCLUDE_REDEFINES) -#if !defined(_SIZE_T_DEFINED) -#if defined(_WIN64) -typedef unsigned __int64 size_t; -#else -typedef _W64 unsigned int size_t; -#endif -#define _SIZE_T_DEFINED -#endif -#endif - /* uintptr_t */ #if !defined(_UINTPTR_T_DEFINED) -#if defined(_WIN64) +#if defined(HOST_64BIT) typedef unsigned __int64 uintptr_t; #else typedef _W64 unsigned int uintptr_t; @@ -318,7 +298,7 @@ typedef int errno_t; /* standard */ #endif #endif -/* put a null terminator at the beginning of the string and then calls _SAFECRT__FILL_STRING; +/* put a null terminator at the beginning of the string and then calls _SAFECRT__FILL_STRING; * assume that the string has been validated with _SAFECRT__VALIDATE_STRING */ #if !defined(_SAFECRT__RESET_STRING) @@ -370,9 +350,6 @@ void __cdecl _invalid_parameter(const WCHAR *_Message, const WCHAR *_FunctionNam #if (_SAFECRT_USE_INLINES || _SAFECRT_IMPL) && !defined(_SAFECRT_DO_NOT_DEFINE_INVALID_PARAMETER) #ifndef STATUS_INVALID_PARAMETER -#if defined (SAFECRT_INCLUDE_REDEFINES) -typedef LONG NTSTATUS; -#endif #define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL) #endif @@ -413,7 +390,6 @@ void __cdecl _invalid_parameter(const WCHAR *_Message, const WCHAR *_FunctionNam #define _vsntprintf_s _vsnprintf_s #define _tscanf_s scanf_s #define _tsscanf_s sscanf_s -#define _tsnscanf_s _snscanf_s #elif defined(_UNICODE) || defined(UNICODE) @@ -430,7 +406,6 @@ void __cdecl _invalid_parameter(const WCHAR *_Message, const WCHAR *_FunctionNam #define _vsntprintf_s _vsnwprintf_s #define _tscanf_s wscanf_s #define _tsscanf_s swscanf_s -#define _tsnscanf_s _swnscanf_s #elif defined(_MBCS) @@ -447,7 +422,6 @@ void __cdecl _invalid_parameter(const WCHAR *_Message, const WCHAR *_FunctionNam #define _sntprintf_s _snprintf_s #define _tscanf_s scanf_s #define _tsscanf_s sscanf_s -#define _tsnscanf_s _snscanf_s #else @@ -458,7 +432,7 @@ void __cdecl _invalid_parameter(const WCHAR *_Message, const WCHAR *_FunctionNam #endif /* _SAFECRT_DEFINE_TCS_MACROS */ /* strcpy_s */ -/* +/* * strcpy_s, wcscpy_s copy string _Src into _Dst; * will call _SAFECRT_INVALID_PARAMETER if string _Src does not fit into _Dst */ @@ -479,18 +453,18 @@ errno_t __cdecl strcpy_s(char (&_Dst)[_SizeInBytes], const char *_Src) #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl strcpy_s(char *_Dst, size_t _SizeInBytes, const char *_Src) { char *p; size_t available; - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); - + p = _Dst; available = _SizeInBytes; while ((*p++ = *_Src++) != 0 && --available > 0) @@ -502,11 +476,11 @@ errno_t __cdecl strcpy_s(char *_Dst, size_t _SizeInBytes, const char *_Src) _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); } - + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); return 0; } - + #endif /* wcscpy_s */ @@ -523,23 +497,23 @@ errno_t __cdecl wcscpy_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Src) #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl wcscpy_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src) { WCHAR *p; size_t available; - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInWords); - + p = _Dst; available = _SizeInWords; while ((*p++ = *_Src++) != 0 && --available > 0) { } - + if (available == 0) { _SAFECRT__RESET_STRING(_Dst, _SizeInWords); @@ -548,7 +522,7 @@ errno_t __cdecl wcscpy_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src) _SAFECRT__FILL_STRING(_Dst, _SizeInWords, _SizeInWords - available + 1); return 0; } - + #endif /* _mbscpy_s */ @@ -567,23 +541,23 @@ errno_t __cdecl _mbscpy_s(unsigned char (&_Dst)[_SizeInBytes], const unsigned ch #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _mbscpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src) { unsigned char *p; size_t available; - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); - + p = _Dst; available = _SizeInBytes; while ((*p++ = *_Src++) != 0 && --available > 0) { } - + if (available == 0) { if (*_Src == 0 && _SAFECRT__ISMBBLEAD(p[-1])) @@ -604,17 +578,17 @@ errno_t __cdecl _mbscpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsign _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); return 0; } - + #endif #endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ /* strncpy_s */ -/* +/* * strncpy_s, wcsncpy_s copy at max _Count characters from string _Src into _Dst; * string _Dst will always be null-terminated; * will call _SAFECRT_INVALID_PARAMETER if there is not enough space in _Dst; - * if _Count == _TRUNCATE, we will copy as many characters as we can from _Src into _Dst, and + * if _Count == _TRUNCATE, we will copy as many characters as we can from _Src into _Dst, and * return STRUNCATE if _Src does not entirely fit into _Dst (we will not call _SAFECRT_INVALID_PARAMETER); * if _Count == 0, then (_Dst == nullptr && _SizeInBytes == 0) is allowed */ @@ -631,19 +605,19 @@ errno_t __cdecl strncpy_s(char (&_Dst)[_SizeInBytes], const char *_Src, size_t _ #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl strncpy_s(char *_Dst, size_t _SizeInBytes, const char *_Src, size_t _Count) { char *p; size_t available; - + if (_Count == 0 && _Dst == nullptr && _SizeInBytes == 0) { /* this case is allowed; nothing to do */ return 0; } - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); if (_Count == 0) @@ -653,7 +627,7 @@ errno_t __cdecl strncpy_s(char *_Dst, size_t _SizeInBytes, const char *_Src, siz return 0; } _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); - + p = _Dst; available = _SizeInBytes; if (_Count == _TRUNCATE) @@ -672,7 +646,7 @@ errno_t __cdecl strncpy_s(char *_Dst, size_t _SizeInBytes, const char *_Src, siz *p = 0; } } - + if (available == 0) { if (_Count == _TRUNCATE) @@ -686,7 +660,7 @@ errno_t __cdecl strncpy_s(char *_Dst, size_t _SizeInBytes, const char *_Src, siz _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); return 0; } - + #endif /* wcsncpy_s */ @@ -703,19 +677,19 @@ errno_t __cdecl wcsncpy_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Src, size_t #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl wcsncpy_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src, size_t _Count) { WCHAR *p; size_t available; - + if (_Count == 0 && _Dst == nullptr && _SizeInWords == 0) { /* this case is allowed; nothing to do */ return 0; } - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); if (_Count == 0) @@ -725,7 +699,7 @@ errno_t __cdecl wcsncpy_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src, s return 0; } _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInWords); - + p = _Dst; available = _SizeInWords; if (_Count == _TRUNCATE) @@ -744,7 +718,7 @@ errno_t __cdecl wcsncpy_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src, s *p = 0; } } - + if (available == 0) { if (_Count == _TRUNCATE) @@ -758,7 +732,7 @@ errno_t __cdecl wcsncpy_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src, s _SAFECRT__FILL_STRING(_Dst, _SizeInWords, _SizeInWords - available + 1); return 0; } - + #endif /* _mbsnbcpy_s */ @@ -777,19 +751,19 @@ errno_t __cdecl _mbsnbcpy_s(unsigned char (&_Dst)[_SizeInBytes], const unsigned #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _mbsnbcpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, size_t _CountInBytes) { unsigned char *p; size_t available; - + if (_CountInBytes == 0 && _Dst == nullptr && _SizeInBytes == 0) { /* this case is allowed; nothing to do */ return 0; } - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); if (_CountInBytes == 0) @@ -799,7 +773,7 @@ errno_t __cdecl _mbsnbcpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsi return 0; } _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); - + p = _Dst; available = _SizeInBytes; if (_CountInBytes == _TRUNCATE) @@ -818,7 +792,7 @@ errno_t __cdecl _mbsnbcpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsi *p++ = 0; } } - + if (available == 0) { if ((*_Src == 0 || _CountInBytes == 1) && _SAFECRT__ISMBBLEAD(p[-1])) @@ -852,7 +826,7 @@ errno_t __cdecl _mbsnbcpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsi _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); return 0; } - + #endif #endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ @@ -873,19 +847,19 @@ errno_t __cdecl _mbsncpy_s(unsigned char (&_Dst)[_SizeInBytes], const unsigned c #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _mbsncpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, size_t _CountInChars) { unsigned char *p; size_t available; - + if (_CountInChars == 0 && _Dst == nullptr && _SizeInBytes == 0) { /* this case is allowed; nothing to do */ return 0; } - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); if (_CountInChars == 0) @@ -895,7 +869,7 @@ errno_t __cdecl _mbsncpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsig return 0; } _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); - + p = _Dst; available = _SizeInBytes; if (_CountInChars == _TRUNCATE) @@ -940,7 +914,7 @@ errno_t __cdecl _mbsncpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsig *p++ = 0; } } - + if (available == 0) { if (_CountInChars == _TRUNCATE) @@ -962,13 +936,13 @@ errno_t __cdecl _mbsncpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsig _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); return 0; } - + #endif #endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ /* strcat_s */ -/* +/* * strcat_s, wcscat_s append string _Src to _Dst; * will call _SAFECRT_INVALID_PARAMETER if there is not enough space in _Dst */ @@ -985,17 +959,17 @@ errno_t __cdecl strcat_s(char (&_Dst)[_SizeInBytes], const char *_Src) #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl strcat_s(char *_Dst, size_t _SizeInBytes, const char *_Src) { char *p; size_t available; - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); - + p = _Dst; available = _SizeInBytes; while (available > 0 && *p != 0) @@ -1003,17 +977,17 @@ errno_t __cdecl strcat_s(char *_Dst, size_t _SizeInBytes, const char *_Src) p++; available--; } - + if (available == 0) { _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInBytes); } - + while ((*p++ = *_Src++) != 0 && --available > 0) { } - + if (available == 0) { _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); @@ -1022,7 +996,7 @@ errno_t __cdecl strcat_s(char *_Dst, size_t _SizeInBytes, const char *_Src) _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); return 0; } - + #endif /* wcscat_s */ @@ -1039,17 +1013,17 @@ errno_t __cdecl wcscat_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Src) #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl wcscat_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src) { WCHAR *p; size_t available; - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInWords); - + p = _Dst; available = _SizeInWords; while (available > 0 && *p != 0) @@ -1057,17 +1031,17 @@ errno_t __cdecl wcscat_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src) p++; available--; } - + if (available == 0) { _SAFECRT__RESET_STRING(_Dst, _SizeInWords); _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInWords); } - + while ((*p++ = *_Src++) != 0 && --available > 0) { } - + if (available == 0) { _SAFECRT__RESET_STRING(_Dst, _SizeInWords); @@ -1076,7 +1050,7 @@ errno_t __cdecl wcscat_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src) _SAFECRT__FILL_STRING(_Dst, _SizeInWords, _SizeInWords - available + 1); return 0; } - + #endif /* _mbscat_s */ @@ -1095,17 +1069,17 @@ errno_t __cdecl _mbscat_s(unsigned char (&_Dst)[_SizeInBytes], const unsigned ch #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _mbscat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src) { unsigned char *p; size_t available; - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); - + p = _Dst; available = _SizeInBytes; while (available > 0 && *p != 0) @@ -1113,7 +1087,7 @@ errno_t __cdecl _mbscat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsign p++; available--; } - + if (available == 0) { if (*p == 0 && _SAFECRT__ISMBBLEAD(p[-1])) @@ -1136,11 +1110,11 @@ errno_t __cdecl _mbscat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsign *p = 0; available++; } - + while ((*p++ = *_Src++) != 0 && --available > 0) { } - + if (available == 0) { if (*_Src == 0 && _SAFECRT__ISMBBLEAD(p[-1])) @@ -1161,17 +1135,17 @@ errno_t __cdecl _mbscat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsign _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); return 0; } - + #endif #endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ /* strncat_s */ -/* +/* * strncat_s, wcsncat_s append at max _Count characters from string _Src to _Dst; * string _Dst will always be null-terminated; * will call _SAFECRT_INVALID_PARAMETER if there is not enough space in _Dst; - * if _Count == _TRUNCATE, we will append as many characters as we can from _Src to _Dst, and + * if _Count == _TRUNCATE, we will append as many characters as we can from _Src to _Dst, and * return STRUNCATE if _Src does not entirely fit into _Dst (we will not call _SAFECRT_INVALID_PARAMETER); * if _Count == 0, then (_Dst == nullptr && _SizeInBytes == 0) is allowed */ @@ -1188,7 +1162,7 @@ errno_t __cdecl strncat_s(char (&_Dst)[_SizeInBytes], const char *_Src, size_t _ #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl strncat_s(char *_Dst, size_t _SizeInBytes, const char *_Src, size_t _Count) { @@ -1205,7 +1179,7 @@ errno_t __cdecl strncat_s(char *_Dst, size_t _SizeInBytes, const char *_Src, siz { _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); } - + p = _Dst; available = _SizeInBytes; while (available > 0 && *p != 0) @@ -1213,13 +1187,13 @@ errno_t __cdecl strncat_s(char *_Dst, size_t _SizeInBytes, const char *_Src, siz p++; available--; } - + if (available == 0) { _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInBytes); } - + if (_Count == _TRUNCATE) { while ((*p++ = *_Src++) != 0 && --available > 0) @@ -1237,7 +1211,7 @@ errno_t __cdecl strncat_s(char *_Dst, size_t _SizeInBytes, const char *_Src, siz *p = 0; } } - + if (available == 0) { if (_Count == _TRUNCATE) @@ -1251,7 +1225,7 @@ errno_t __cdecl strncat_s(char *_Dst, size_t _SizeInBytes, const char *_Src, siz _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); return 0; } - + #endif /* wcsncat_s */ @@ -1268,7 +1242,7 @@ errno_t __cdecl wcsncat_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Src, size_t #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl wcsncat_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src, size_t _Count) { @@ -1285,7 +1259,7 @@ errno_t __cdecl wcsncat_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src, s { _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInWords); } - + p = _Dst; available = _SizeInWords; while (available > 0 && *p != 0) @@ -1293,13 +1267,13 @@ errno_t __cdecl wcsncat_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src, s p++; available--; } - + if (available == 0) { _SAFECRT__RESET_STRING(_Dst, _SizeInWords); _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInWords); } - + if (_Count == _TRUNCATE) { while ((*p++ = *_Src++) != 0 && --available > 0) @@ -1317,7 +1291,7 @@ errno_t __cdecl wcsncat_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src, s *p = 0; } } - + if (available == 0) { if (_Count == _TRUNCATE) @@ -1331,7 +1305,7 @@ errno_t __cdecl wcsncat_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src, s _SAFECRT__FILL_STRING(_Dst, _SizeInWords, _SizeInWords - available + 1); return 0; } - + #endif /* _mbsnbcat_s */ @@ -1350,7 +1324,7 @@ errno_t __cdecl _mbsnbcat_s(unsigned char (&_Dst)[_SizeInBytes], const unsigned #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _mbsnbcat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, size_t _CountInBytes) { @@ -1367,7 +1341,7 @@ errno_t __cdecl _mbsnbcat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsi { _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); } - + p = _Dst; available = _SizeInBytes; while (available > 0 && *p != 0) @@ -1375,7 +1349,7 @@ errno_t __cdecl _mbsnbcat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsi p++; available--; } - + if (available == 0) { if (*p == 0 && _SAFECRT__ISMBBLEAD(p[-1])) @@ -1398,7 +1372,7 @@ errno_t __cdecl _mbsnbcat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsi *p = 0; available++; } - + if (_CountInBytes == _TRUNCATE) { while ((*p++ = *_Src++) != 0 && --available > 0) @@ -1416,7 +1390,7 @@ errno_t __cdecl _mbsnbcat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsi *p++ = 0; } } - + if (available == 0) { if ((*_Src == 0 || _CountInBytes == 1) && _SAFECRT__ISMBBLEAD(p[-1])) @@ -1450,7 +1424,7 @@ errno_t __cdecl _mbsnbcat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsi _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); return 0; } - + #endif #endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ @@ -1471,7 +1445,7 @@ errno_t __cdecl _mbsncat_s(unsigned char (&_Dst)[_SizeInBytes], const unsigned c #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _mbsncat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, size_t _CountInChars) { @@ -1488,7 +1462,7 @@ errno_t __cdecl _mbsncat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsig { _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); } - + p = _Dst; available = _SizeInBytes; while (available > 0 && *p != 0) @@ -1496,7 +1470,7 @@ errno_t __cdecl _mbsncat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsig p++; available--; } - + if (available == 0) { if (*p == 0 && _SAFECRT__ISMBBLEAD(p[-1])) @@ -1519,7 +1493,7 @@ errno_t __cdecl _mbsncat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsig *p = 0; available++; } - + if (_CountInChars == _TRUNCATE) { while ((*p++ = *_Src++) != 0 && --available > 0) @@ -1562,7 +1536,7 @@ errno_t __cdecl _mbsncat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsig *p++ = 0; } } - + if (available == 0) { if (_CountInChars == _TRUNCATE) @@ -1584,13 +1558,13 @@ errno_t __cdecl _mbsncat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsig _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); return 0; } - + #endif #endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ /* _strset_s */ -/* +/* * _strset_s, _wcsset_s ; * will call _SAFECRT_INVALID_PARAMETER if _Dst is not null terminated. */ @@ -1607,23 +1581,23 @@ errno_t __cdecl _strset_s(char (&_Dst)[_SizeInBytes], int _Value) #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _strset_s(char *_Dst, size_t _SizeInBytes, int _Value) { char *p; size_t available; - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); - + p = _Dst; available = _SizeInBytes; while (*p != 0 && --available > 0) { *p++ = (char)_Value; } - + if (available == 0) { _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); @@ -1632,7 +1606,7 @@ errno_t __cdecl _strset_s(char *_Dst, size_t _SizeInBytes, int _Value) _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); return 0; } - + #endif /* _wcsset_s */ @@ -1649,23 +1623,23 @@ errno_t __cdecl _wcsset_s(WCHAR (&_Dst)[_SizeInWords], WCHAR _Value) #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _wcsset_s(WCHAR *_Dst, size_t _SizeInWords, WCHAR _Value) { WCHAR *p; size_t available; - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); - + p = _Dst; available = _SizeInWords; while (*p != 0 && --available > 0) { *p++ = (WCHAR)_Value; } - + if (available == 0) { _SAFECRT__RESET_STRING(_Dst, _SizeInWords); @@ -1674,7 +1648,7 @@ errno_t __cdecl _wcsset_s(WCHAR *_Dst, size_t _SizeInWords, WCHAR _Value) _SAFECRT__FILL_STRING(_Dst, _SizeInWords, _SizeInWords - available + 1); return 0; } - + #endif /* _mbsset_s */ @@ -1693,7 +1667,7 @@ errno_t __cdecl _mbsset_s(unsigned char (&_Dst)[_SizeInBytes], unsigned int _Val #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _mbsset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned int _Value) { @@ -1701,10 +1675,10 @@ errno_t __cdecl _mbsset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned int unsigned char *p; size_t available; unsigned char highval, lowval; - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); - + p = _Dst; available = _SizeInBytes; highval = (unsigned char)(_Value >> 8); @@ -1751,7 +1725,7 @@ errno_t __cdecl _mbsset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned int *p++ = lowval; } } - + if (available == 0) { _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); @@ -1767,13 +1741,13 @@ errno_t __cdecl _mbsset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned int return 0; } } - + #endif #endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ /* _strnset_s */ -/* +/* * _strnset_s, _wcsnset_s ; * will call _SAFECRT_INVALID_PARAMETER if _Dst is not null terminated. */ @@ -1790,13 +1764,13 @@ errno_t __cdecl _strnset_s(char (&_Dst)[_SizeInBytes], int _Value, size_t _Count #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _strnset_s(char *_Dst, size_t _SizeInBytes, int _Value, size_t _Count) { char *p; size_t available; - + /* validation section */ if (_Count == 0 && _Dst == nullptr && _SizeInBytes == 0) { @@ -1804,7 +1778,7 @@ errno_t __cdecl _strnset_s(char *_Dst, size_t _SizeInBytes, int _Value, size_t _ return 0; } _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); - + p = _Dst; available = _SizeInBytes; while (*p != 0 && _Count > 0 && --available > 0) @@ -1812,7 +1786,7 @@ errno_t __cdecl _strnset_s(char *_Dst, size_t _SizeInBytes, int _Value, size_t _ *p++ = (char)_Value; --_Count; } - + if (available == 0) { _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); @@ -1825,7 +1799,7 @@ errno_t __cdecl _strnset_s(char *_Dst, size_t _SizeInBytes, int _Value, size_t _ _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); return 0; } - + #endif /* _wcsnset_s */ @@ -1842,13 +1816,13 @@ errno_t __cdecl _wcsnset_s(WCHAR (&_Dst)[_SizeInWords], WCHAR _Value, size_t _Co #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _wcsnset_s(WCHAR *_Dst, size_t _SizeInWords, WCHAR _Value, size_t _Count) { WCHAR *p; size_t available; - + /* validation section */ if (_Count == 0 && _Dst == nullptr && _SizeInWords == 0) { @@ -1856,7 +1830,7 @@ errno_t __cdecl _wcsnset_s(WCHAR *_Dst, size_t _SizeInWords, WCHAR _Value, size_ return 0; } _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); - + p = _Dst; available = _SizeInWords; while (*p != 0 && _Count > 0 && --available > 0) @@ -1864,7 +1838,7 @@ errno_t __cdecl _wcsnset_s(WCHAR *_Dst, size_t _SizeInWords, WCHAR _Value, size_ *p++ = (WCHAR)_Value; --_Count; } - + if (available == 0) { _SAFECRT__RESET_STRING(_Dst, _SizeInWords); @@ -1877,7 +1851,7 @@ errno_t __cdecl _wcsnset_s(WCHAR *_Dst, size_t _SizeInWords, WCHAR _Value, size_ _SAFECRT__FILL_STRING(_Dst, _SizeInWords, _SizeInWords - available + 1); return 0; } - + #endif /* _mbsnbset_s */ @@ -1896,7 +1870,7 @@ errno_t __cdecl _mbsnbset_s(unsigned char (&_Dst)[_SizeInBytes], unsigned int _V #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _mbsnbset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned int _Value, size_t _CountInBytes) { @@ -1904,7 +1878,7 @@ errno_t __cdecl _mbsnbset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned i unsigned char *p; size_t available; unsigned char highval, lowval; - + /* validation section */ if (_CountInBytes == 0 && _Dst == nullptr && _SizeInBytes == 0) { @@ -1912,7 +1886,7 @@ errno_t __cdecl _mbsnbset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned i return 0; } _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); - + p = _Dst; available = _SizeInBytes; highval = (unsigned char)(_Value >> 8); @@ -1982,7 +1956,7 @@ errno_t __cdecl _mbsnbset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned i return 0; } } - + #endif #endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ @@ -2003,7 +1977,7 @@ errno_t __cdecl _mbsnset_s(unsigned char (&_Dst)[_SizeInBytes], unsigned int _Va #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _mbsnset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned int _Value, size_t _CountInChars) { @@ -2011,7 +1985,7 @@ errno_t __cdecl _mbsnset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned in unsigned char *p; size_t available; unsigned char highval, lowval; - + /* validation section */ if (_CountInChars == 0 && _Dst == nullptr && _SizeInBytes == 0) { @@ -2019,7 +1993,7 @@ errno_t __cdecl _mbsnset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned in return 0; } _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); - + p = _Dst; available = _SizeInBytes; highval = (unsigned char)(_Value >> 8); @@ -2088,7 +2062,7 @@ errno_t __cdecl _mbsnset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned in return 0; } } - + #endif #endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ @@ -2109,7 +2083,7 @@ errno_t __cdecl _mbccpy_s(unsigned char (&_Dst)[_SizeInBytes], int *_PCopied, co #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _mbccpy_s(unsigned char *_Dst, size_t _SizeInBytes, int *_PCopied, const unsigned char *_Src) { @@ -2121,7 +2095,7 @@ errno_t __cdecl _mbccpy_s(unsigned char *_Dst, size_t _SizeInBytes, int *_PCopie *_Dst = '\0'; _SAFECRT__RETURN_EINVAL; } - + /* copy */ if (_SAFECRT__ISMBBLEAD(*_Src)) { @@ -2148,7 +2122,7 @@ errno_t __cdecl _mbccpy_s(unsigned char *_Dst, size_t _SizeInBytes, int *_PCopie *_Dst = *_Src; if (_PCopied != nullptr) { *_PCopied = 1; }; } - + return 0; } #endif @@ -2156,7 +2130,7 @@ errno_t __cdecl _mbccpy_s(unsigned char *_Dst, size_t _SizeInBytes, int *_PCopie #endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ /* strtok_s */ -/* +/* * strtok_s, wcstok_s ; * uses _Context to keep track of the position in the string. */ @@ -2164,7 +2138,7 @@ _SAFECRT__EXTERN_C char * __cdecl strtok_s(char *_String, const char *_Control, char **_Context); #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE char * __cdecl strtok_s(char *_String, const char *_Control, char **_Context) { @@ -2172,23 +2146,23 @@ char * __cdecl strtok_s(char *_String, const char *_Control, char **_Context) const unsigned char *ctl = (const unsigned char *)_Control; unsigned char map[32]; int count; - + /* validation section */ _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Context, EINVAL, nullptr); _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Control, EINVAL, nullptr); _SAFECRT__VALIDATE_CONDITION_ERROR_RETURN(_String != nullptr || *_Context != nullptr, EINVAL, nullptr); - + /* Clear control map */ for (count = 0; count < 32; count++) { map[count] = 0; } - + /* Set bits in delimiter table */ do { map[*ctl >> 3] |= (1 << (*ctl & 7)); } while (*ctl++); - + /* If string is nullptr, set str to the saved * pointer (i.e., continue breaking tokens out of the string * from the last strtok call) */ @@ -2200,7 +2174,7 @@ char * __cdecl strtok_s(char *_String, const char *_Control, char **_Context) { str = (unsigned char *)*_Context; } - + /* Find beginning of token (skip over leading delimiters). Note that * there is no token iff this loop sets str to point to the terminal * null (*str == 0) */ @@ -2208,9 +2182,9 @@ char * __cdecl strtok_s(char *_String, const char *_Control, char **_Context) { str++; } - + _String = (char *)str; - + /* Find the end of the token. If it is not the end of the string, * put a null there. */ for ( ; *str != 0 ; str++ ) @@ -2221,10 +2195,10 @@ char * __cdecl strtok_s(char *_String, const char *_Control, char **_Context) break; } } - + /* Update context */ *_Context = (char *)str; - + /* Determine if a token has been found. */ if (_String == (char *)str) { @@ -2242,24 +2216,24 @@ _SAFECRT__EXTERN_C WCHAR * __cdecl wcstok_s(WCHAR *_String, const WCHAR *_Control, WCHAR **_Context); #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE WCHAR * __cdecl wcstok_s(WCHAR *_String, const WCHAR *_Control, WCHAR **_Context) { WCHAR *token; const WCHAR *ctl; - + /* validation section */ _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Context, EINVAL, nullptr); _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Control, EINVAL, nullptr); _SAFECRT__VALIDATE_CONDITION_ERROR_RETURN(_String != nullptr || *_Context != nullptr, EINVAL, nullptr); - + /* If string==nullptr, continue with previous string */ if (!_String) { _String = *_Context; } - + /* Find beginning of token (skip over leading delimiters). Note that * there is no token iff this loop sets string to point to the terminal null. */ for ( ; *_String != 0 ; _String++) @@ -2271,9 +2245,9 @@ WCHAR * __cdecl wcstok_s(WCHAR *_String, const WCHAR *_Control, WCHAR **_Context break; } } - + token = _String; - + /* Find the end of the token. If it is not the end of the string, * put a null there. */ for ( ; *_String != 0 ; _String++) @@ -2286,10 +2260,10 @@ WCHAR * __cdecl wcstok_s(WCHAR *_String, const WCHAR *_Control, WCHAR **_Context break; } } - + /* Update the context */ *_Context = _String; - + /* Determine if a token has been found. */ if (token == _String) { @@ -2309,25 +2283,25 @@ _SAFECRT__EXTERN_C unsigned char * __cdecl _mbstok_s(unsigned char *_String, const unsigned char *_Control, unsigned char **_Context); #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE unsigned char * __cdecl _mbstok_s(unsigned char *_String, const unsigned char *_Control, unsigned char **_Context) { unsigned char *token; const unsigned char *ctl; int dbc; - + /* validation section */ _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Context, EINVAL, nullptr); _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Control, EINVAL, nullptr); _SAFECRT__VALIDATE_CONDITION_ERROR_RETURN(_String != nullptr || *_Context != nullptr, EINVAL, nullptr); - + /* If string==nullptr, continue with previous string */ if (!_String) { _String = *_Context; } - + /* Find beginning of token (skip over leading delimiters). Note that * there is no token iff this loop sets string to point to the terminal null. */ for ( ; *_String != 0; _String++) @@ -2363,9 +2337,9 @@ unsigned char * __cdecl _mbstok_s(unsigned char *_String, const unsigned char *_ } } } - + token = _String; - + /* Find the end of the token. If it is not the end of the string, * put a null there. */ for ( ; *_String != 0; _String++) @@ -2407,10 +2381,10 @@ unsigned char * __cdecl _mbstok_s(unsigned char *_String, const unsigned char *_ } } } - + /* Update the context */ *_Context = _String; - + /* Determine if a token has been found. */ if (token == _String) { @@ -2478,7 +2452,7 @@ size_t __cdecl wcsnlen(const WCHAR *inString, size_t inMaxSize) #endif // PAL_STDCPP_COMPAT /* _makepath_s */ -/* +/* * _makepath_s, _wmakepath_s build up a path starting from the specified components; * will call _SAFECRT_INVALID_PARAMETER if there is not enough space in _Dst; * any of _Drive, _Dir, _Filename and _Ext can be nullptr @@ -2496,17 +2470,17 @@ errno_t __cdecl _makepath_s(char (&_Dst)[_SizeInBytes], const char *_Drive, cons #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _makepath_s(char *_Dst, size_t _SizeInBytes, const char *_Drive, const char *_Dir, const char *_Filename, const char *_Ext) { size_t written; const char *p; char *d; - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); - + /* copy drive */ written = 0; d = _Dst; @@ -2520,7 +2494,7 @@ errno_t __cdecl _makepath_s(char *_Dst, size_t _SizeInBytes, const char *_Drive, *d++ = *_Drive; *d++ = ':'; } - + /* copy dir */ p = _Dir; if (p != nullptr && *p != 0) @@ -2532,7 +2506,7 @@ errno_t __cdecl _makepath_s(char *_Dst, size_t _SizeInBytes, const char *_Drive, } *d++ = *p++; } while (*p != 0); - + p = (const char *)_SAFECRT__MBSDEC((const unsigned char *)_Dir, (const unsigned char *)p); if (*p != '/' && *p != '\\') { @@ -2543,12 +2517,12 @@ errno_t __cdecl _makepath_s(char *_Dst, size_t _SizeInBytes, const char *_Drive, *d++ = '\\'; } } - + /* copy fname */ p = _Filename; if (p != nullptr) { - while (*p != 0) + while (*p != 0) { if(++written >= _SizeInBytes) { @@ -2557,7 +2531,7 @@ errno_t __cdecl _makepath_s(char *_Dst, size_t _SizeInBytes, const char *_Drive, *d++ = *p++; } } - + /* copy extension; check to see if a '.' needs to be inserted */ p = _Ext; if (p != nullptr) @@ -2579,7 +2553,7 @@ errno_t __cdecl _makepath_s(char *_Dst, size_t _SizeInBytes, const char *_Drive, *d++ = *p++; } } - + if(++written > _SizeInBytes) { goto error_return; @@ -2587,7 +2561,7 @@ errno_t __cdecl _makepath_s(char *_Dst, size_t _SizeInBytes, const char *_Drive, *d = 0; _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, written); return 0; - + error_return: _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); @@ -2610,17 +2584,17 @@ errno_t __cdecl _wmakepath_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Drive, c #endif #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _wmakepath_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Drive, const WCHAR *_Dir, const WCHAR *_Filename, const WCHAR *_Ext) { size_t written; const WCHAR *p; WCHAR *d; - + /* validation section */ _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); - + /* copy drive */ written = 0; d = _Dst; @@ -2634,7 +2608,7 @@ errno_t __cdecl _wmakepath_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Dri *d++ = *_Drive; *d++ = L':'; } - + /* copy dir */ p = _Dir; if (p != nullptr && *p != 0) @@ -2646,7 +2620,7 @@ errno_t __cdecl _wmakepath_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Dri } *d++ = *p++; } while (*p != 0); - + p = p - 1; if (*p != L'/' && *p != L'\\') { @@ -2657,12 +2631,12 @@ errno_t __cdecl _wmakepath_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Dri *d++ = L'\\'; } } - + /* copy fname */ p = _Filename; if (p != nullptr) { - while (*p != 0) + while (*p != 0) { if(++written >= _SizeInWords) { @@ -2671,7 +2645,7 @@ errno_t __cdecl _wmakepath_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Dri *d++ = *p++; } } - + /* copy extension; check to see if a '.' needs to be inserted */ p = _Ext; if (p != nullptr) @@ -2693,7 +2667,7 @@ errno_t __cdecl _wmakepath_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Dri *d++ = *p++; } } - + if(++written > _SizeInWords) { goto error_return; @@ -2701,7 +2675,7 @@ errno_t __cdecl _wmakepath_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Dri *d = 0; _SAFECRT__FILL_STRING(_Dst, _SizeInWords, written); return 0; - + error_return: _SAFECRT__RESET_STRING(_Dst, _SizeInWords); _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInWords); @@ -2711,7 +2685,7 @@ error_return: #endif /* _splitpath_s */ -/* +/* * _splitpath_s, _wsplitpath_s decompose a path into the specified components; * will call _SAFECRT_INVALID_PARAMETER if there is not enough space in * any of _Drive, _Dir, _Filename and _Ext; @@ -2731,7 +2705,7 @@ errno_t __cdecl _splitpath_s( /* no C++ overload for _splitpath_s */ #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _splitpath_s( const char *_Path, @@ -2747,7 +2721,7 @@ errno_t __cdecl _splitpath_s( int drive_set = 0; size_t length = 0; int bEinval = 0; - + /* validation section */ _SAFECRT__VALIDATE_POINTER(_Path); if ((_Drive == nullptr && _DriveSize != 0) || (_Drive != nullptr && _DriveSize == 0)) @@ -2766,13 +2740,13 @@ errno_t __cdecl _splitpath_s( { goto error_einval; } - + /* check if _Path begins with the longpath prefix */ if (_Path[0] == '\\' && _Path[1] == '\\' && _Path[2] == '?' && _Path[3] == '\\') { _Path += 4; } - + /* extract drive letter and ':', if any */ if (!drive_set) { @@ -2803,7 +2777,7 @@ errno_t __cdecl _splitpath_s( } } } - + /* extract path string, if any. _Path now points to the first character * of the path, if any, or the filename or extension, if no path was * specified. Scan ahead for the last occurence, if any, of a '/' or @@ -2827,7 +2801,7 @@ errno_t __cdecl _splitpath_s( { tmp++; } - else + else { if (*tmp == '/' || *tmp == '\\') { @@ -2840,8 +2814,8 @@ errno_t __cdecl _splitpath_s( } } } - - if (last_slash != nullptr) + + if (last_slash != nullptr) { /* found a path - copy up through last_slash or max characters * allowed, whichever is smaller @@ -2864,7 +2838,7 @@ errno_t __cdecl _splitpath_s( _SAFECRT__RESET_STRING(_Dir, _DirSize); } } - + /* extract file name and extension, if any. Path now points to the * first character of the file name, if any, or the extension if no * file name was given. Dot points to the '.' beginning the extension, @@ -2914,12 +2888,12 @@ errno_t __cdecl _splitpath_s( _SAFECRT__RESET_STRING(_Ext, _ExtSize); } } - + return 0; - + error_einval: bEinval = 1; - + error_erange: if (_Drive != nullptr && _DriveSize > 0) { @@ -2937,12 +2911,12 @@ error_erange: { _SAFECRT__RESET_STRING(_Ext, _ExtSize); } - + if (bEinval) { _SAFECRT__RETURN_EINVAL; } - + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Strings, _StringSizes); /* should never happen, but compiler can't tell */ return EINVAL; @@ -2962,7 +2936,7 @@ errno_t __cdecl _wsplitpath_s( /* no C++ overload for _wsplitpath_s */ #if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - + _SAFECRT__INLINE errno_t __cdecl _wsplitpath_s( const WCHAR *_Path, @@ -2978,7 +2952,7 @@ errno_t __cdecl _wsplitpath_s( int drive_set = 0; size_t length = 0; int bEinval = 0; - + /* validation section */ _SAFECRT__VALIDATE_POINTER(_Path); if ((_Drive == nullptr && _DriveSize != 0) || (_Drive != nullptr && _DriveSize == 0)) @@ -2997,13 +2971,13 @@ errno_t __cdecl _wsplitpath_s( { goto error_einval; } - + /* check if _Path begins with the longpath prefix */ if (_Path[0] == L'\\' && _Path[1] == L'\\' && _Path[2] == L'?' && _Path[3] == L'\\') { _Path += 4; } - + /* extract drive letter and ':', if any */ if (!drive_set) { @@ -3034,7 +3008,7 @@ errno_t __cdecl _wsplitpath_s( } } } - + /* extract path string, if any. _Path now points to the first character * of the path, if any, or the filename or extension, if no path was * specified. Scan ahead for the last occurence, if any, of a '/' or @@ -3059,8 +3033,8 @@ errno_t __cdecl _wsplitpath_s( } } } - - if (last_slash != nullptr) + + if (last_slash != nullptr) { /* found a path - copy up through last_slash or max characters * allowed, whichever is smaller @@ -3083,7 +3057,7 @@ errno_t __cdecl _wsplitpath_s( _SAFECRT__RESET_STRING(_Dir, _DirSize); } } - + /* extract file name and extension, if any. Path now points to the * first character of the file name, if any, or the extension if no * file name was given. Dot points to the '.' beginning the extension, @@ -3133,12 +3107,12 @@ errno_t __cdecl _wsplitpath_s( _SAFECRT__RESET_STRING(_Ext, _ExtSize); } } - + return 0; - + error_einval: bEinval = 1; - + error_erange: if (_Drive != nullptr && _DriveSize > 0) { @@ -3156,12 +3130,12 @@ error_erange: { _SAFECRT__RESET_STRING(_Ext, _ExtSize); } - + if (bEinval) { _SAFECRT__RETURN_EINVAL; } - + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Strings, _StringSizes); /* should never happen, but compiler can't tell */ return EINVAL; @@ -3169,7 +3143,7 @@ error_erange: #endif /* sprintf_s, vsprintf_s */ -/* +/* * sprintf_s, swprintf_s, vsprintf_s, vswprintf_s format a string and copy it into _Dst; * need safecrt.lib and msvcrt.dll; * will call _SAFECRT_INVALID_PARAMETER if there is not enough space in _Dst; @@ -3238,7 +3212,7 @@ int __cdecl vswprintf_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Format, va_li /* no inline version of swprintf_s, vswprintf_s */ /* _snprintf_s, _vsnprintf_s */ -/* +/* * _snprintf_s, _snwprintf_s, _vsnprintf_s, _vsnwprintf_s format a string and copy at max _Count characters into _Dst; * need safecrt.lib and msvcrt.dll; * string _Dst will always be null-terminated; @@ -3249,7 +3223,7 @@ int __cdecl vswprintf_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Format, va_li * return a negative number if something goes wrong with mbcs conversions (we will not call _SAFECRT_INVALID_PARAMETER); * _SizeInBytes/_SizeInWords must be <= (INT_MAX / sizeof(char/WCHAR)); * cannot be used without safecrt.lib; - * if _Count == _TRUNCATE, we will copy into _Dst as many characters as we can, and + * if _Count == _TRUNCATE, we will copy into _Dst as many characters as we can, and * return -1 if the formatted string does not entirely fit into _Dst (we will not call _SAFECRT_INVALID_PARAMETER); * if _Count == 0, then (_Dst == nullptr && _SizeInBytes == 0) is allowed */ @@ -3349,14 +3323,6 @@ int __cdecl swscanf_s(const WCHAR *_String, const WCHAR *_Format, ...); /* no inline version of swscanf_s */ -/* _snscanf_s */ -_SAFECRT__EXTERN_C -int __cdecl _snscanf_s(const char *_String, size_t _Count, const char *_Format, ...); - -/* no C++ overload for snscanf_s */ - -/* no inline version of snscanf_s */ - /* _swnscanf_s */ _SAFECRT__EXTERN_C int __cdecl _swnscanf_s(const WCHAR *_String, size_t _Count, const WCHAR *_Format, ...); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/sal.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/sal.h index 9a8c2a4..d42c724 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/sal.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/sal.h @@ -183,7 +183,7 @@ #else -// Disable expansion of SAL macros in non-Prefast mode to +// Disable expansion of SAL macros in non-Prefast mode to // improve compiler throughput. #ifndef _USE_DECLSPECS_FOR_SAL // [ #define _USE_DECLSPECS_FOR_SAL 0 @@ -428,7 +428,7 @@ enum __SAL_YesNo {_SAL_notpresent, _SAL_no, _SAL_maybe, _SAL_yes, _SAL_default}; #define _Outptr_result_maybenull_z_ _SAL2_Source_(_Outptr_result_maybenull_z_, (), _Out_impl_ _Deref_post_opt_z_) #define _Outptr_opt_result_maybenull_z_ _SAL2_Source_(_Outptr_opt_result_maybenull_z_, (), _Out_opt_impl_ _Deref_post_opt_z_) -// Annotations for _Outptr_ parameters where the output pointer is set to NULL if the function fails. +// Annotations for _Outptr_ parameters where the output pointer is set to NULL if the function fails. #define _Outptr_result_nullonfailure_ _SAL2_Source_(_Outptr_result_nullonfailure_, (), _Outptr_ _On_failure_(_Deref_post_null_)) #define _Outptr_opt_result_nullonfailure_ _SAL2_Source_(_Outptr_opt_result_nullonfailure_, (), _Outptr_opt_ _On_failure_(_Deref_post_null_)) @@ -779,10 +779,10 @@ enum __SAL_YesNo {_SAL_notpresent, _SAL_no, _SAL_maybe, _SAL_yes, _SAL_default}; with _Out_. The default unit is elements. Use 'bytecap' if the size is given in bytes 'count' describes the readable size of the buffer and is typically used with _In_. The default unit is elements. Use 'bytecount' if the size is given in bytes. - + Argument syntax for cap_, bytecap_, count_, bytecount_: (|return)[+n] e.g. cch, return, cb+2 - + If the buffer size is a constant expression use the c_ postfix. E.g. cap_c_(20), count_c_(MAX_PATH), bytecount_c_(16) @@ -903,7 +903,7 @@ enum __SAL_YesNo {_SAL_notpresent, _SAL_no, _SAL_maybe, _SAL_yes, _SAL_default}; #define _Out_z_bytecap_post_bytecount_(cap,count) _SAL1_1_Source_(_Out_z_bytecap_post_bytecount_, (cap,count), _Pre_bytecap_(cap) _Post_valid_impl_ _Post_z_bytecount_(count)) #define _Out_opt_z_bytecap_post_bytecount_(cap,count) _SAL1_1_Source_(_Out_opt_z_bytecap_post_bytecount_, (cap,count), _Pre_opt_bytecap_(cap) _Post_valid_impl_ _Post_z_bytecount_(count)) -// only use with dereferenced arguments e.g. '*pcch' +// only use with dereferenced arguments e.g. '*pcch' #define _Out_capcount_(capcount) _SAL1_1_Source_(_Out_capcount_, (capcount), _Pre_cap_(capcount) _Post_valid_impl_ _Post_count_(capcount)) #define _Out_opt_capcount_(capcount) _SAL1_1_Source_(_Out_opt_capcount_, (capcount), _Pre_opt_cap_(capcount) _Post_valid_impl_ _Post_count_(capcount)) #define _Out_bytecapcount_(capcount) _SAL1_1_Source_(_Out_bytecapcount_, (capcount), _Pre_bytecap_(capcount) _Post_valid_impl_ _Post_bytecount_(capcount)) @@ -1072,7 +1072,7 @@ enum __SAL_YesNo {_SAL_notpresent, _SAL_no, _SAL_maybe, _SAL_yes, _SAL_default}; #define _Deref_pre_valid_bytecap_x_(size) _SAL1_1_Source_(_Deref_pre_valid_bytecap_x_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__bytecap_x_impl(size)) _Pre_valid_impl_) #define _Deref_pre_opt_valid_bytecap_x_(size) _SAL1_1_Source_(_Deref_pre_opt_valid_bytecap_x_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__bytecap_x_impl(size)) _Pre_valid_impl_) -// e.g. void SaveMatrix( _In_count_(n) _Deref_pre_count_(n) const Elem** matrix, size_t n ); +// e.g. void SaveMatrix( _In_count_(n) _Deref_pre_count_(n) const Elem** matrix, size_t n ); // valid buffer extent is described by another parameter #define _Deref_pre_count_(size) _SAL1_1_Source_(_Deref_pre_count_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__count_impl(size)) _Pre_valid_impl_) #define _Deref_pre_opt_count_(size) _SAL1_1_Source_(_Deref_pre_opt_count_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__count_impl(size)) _Pre_valid_impl_) @@ -1153,12 +1153,12 @@ enum __SAL_YesNo {_SAL_notpresent, _SAL_no, _SAL_maybe, _SAL_yes, _SAL_default}; #define _Deref_post_opt_valid_cap_(size) _SAL1_1_Source_(_Deref_post_opt_valid_cap_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__cap_impl(size)) _Post_valid_impl_) #define _Deref_post_valid_bytecap_(size) _SAL1_1_Source_(_Deref_post_valid_bytecap_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__bytecap_impl(size)) _Post_valid_impl_) #define _Deref_post_opt_valid_bytecap_(size) _SAL1_1_Source_(_Deref_post_opt_valid_bytecap_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__bytecap_impl(size)) _Post_valid_impl_) - + #define _Deref_post_valid_cap_c_(size) _SAL1_1_Source_(_Deref_post_valid_cap_c_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__cap_c_impl(size)) _Post_valid_impl_) #define _Deref_post_opt_valid_cap_c_(size) _SAL1_1_Source_(_Deref_post_opt_valid_cap_c_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__cap_c_impl(size)) _Post_valid_impl_) #define _Deref_post_valid_bytecap_c_(size) _SAL1_1_Source_(_Deref_post_valid_bytecap_c_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__bytecap_c_impl(size)) _Post_valid_impl_) #define _Deref_post_opt_valid_bytecap_c_(size) _SAL1_1_Source_(_Deref_post_opt_valid_bytecap_c_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__bytecap_c_impl(size)) _Post_valid_impl_) - + #define _Deref_post_valid_cap_x_(size) _SAL1_1_Source_(_Deref_post_valid_cap_x_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__cap_x_impl(size)) _Post_valid_impl_) #define _Deref_post_opt_valid_cap_x_(size) _SAL1_1_Source_(_Deref_post_opt_valid_cap_x_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__cap_x_impl(size)) _Post_valid_impl_) #define _Deref_post_valid_bytecap_x_(size) _SAL1_1_Source_(_Deref_post_valid_bytecap_x_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__bytecap_x_impl(size)) _Post_valid_impl_) @@ -1481,7 +1481,7 @@ enum __SAL_YesNo {_SAL_notpresent, _SAL_no, _SAL_maybe, _SAL_yes, _SAL_default}; // not required to be a legal standalone annotation, and in the case // of attribute annotations, usually is not. (In the case of some declspec // annotations, it might be, but it should not be assumed so.) Those -// symols will be used in the _PreN..., _PostN... and _RetN... annotations +// symols will be used in the _PreN..., _PostN... and _RetN... annotations // to build up more complete annotations. // A symbol ending in _impl_ is reserved to the implementation as well, @@ -1595,7 +1595,7 @@ enum __SAL_YesNo {_SAL_notpresent, _SAL_no, _SAL_maybe, _SAL_yes, _SAL_default}; // Done this way so that they don't appear in the regular compiler's // namespace. #define __ANNOTATION(fun) _SA_annotes0(SAL_annotation) void __SA_##fun - + #define __PRIMOP(type, fun) _SA_annotes0(SAL_primop) type __SA_##fun #define __QUALIFIER(fun) _SA_annotes0(SAL_qualifier) void __SA_##fun; @@ -1611,9 +1611,9 @@ enum __SAL_YesNo {_SAL_notpresent, _SAL_no, _SAL_maybe, _SAL_yes, _SAL_default}; #define _SA_annotes2(n,pp1,pp2) #define _SA_annotes3(n,pp1,pp2,pp3) -#define __ANNOTATION(fun) -#define __PRIMOP(type, fun) -#define __QUALIFIER(type, fun) +#define __ANNOTATION(fun) +#define __PRIMOP(type, fun) +#define __QUALIFIER(type, fun) #endif // ] @@ -2116,15 +2116,15 @@ typedef struct __F_ __F_; #define _Pre3_impl_(p1,p2,p3) #define _Post_impl_ -#define _Post1_impl_(p1) +#define _Post1_impl_(p1) #define _Post2_impl_(p1,p2) #define _Post3_impl_(p1,p2,p3) -#define _Ret1_impl_(p1) +#define _Ret1_impl_(p1) #define _Ret2_impl_(p1,p2) #define _Ret3_impl_(p1,p2,p3) -#define _Deref_pre1_impl_(p1) +#define _Deref_pre1_impl_(p1) #define _Deref_pre2_impl_(p1,p2) #define _Deref_pre3_impl_(p1,p2,p3) @@ -2156,7 +2156,7 @@ typedef struct __F_ __F_; // This section contains the deprecated annotations -/* +/* ------------------------------------------------------------------------------- Introduction @@ -2347,7 +2347,7 @@ typedef struct __F_ __F_; ------------------------------------------------------------------------------- Advanced Annotation Examples - __success(return != FALSE) LWSTDAPI_(BOOL) + __success(return != FALSE) LWSTDAPI_(BOOL) PathCanonicalizeA(__out_ecount(MAX_PATH) LPSTR pszBuf, LPCSTR pszPath) : pszBuf is only guaranteed to be NULL-terminated when TRUE is returned. @@ -2383,8 +2383,8 @@ extern "C" { */ /* - The helper annotations are only understood by the compiler version used by - various defect detection tools. When the regular compiler is running, they + The helper annotations are only understood by the compiler version used by + various defect detection tools. When the regular compiler is running, they are defined into nothing, and do not affect the compiled code. */ @@ -2403,7 +2403,7 @@ extern "C" { __null p __notnull p __maybenull p - + Annotates a pointer p. States that pointer p is null. Commonly used in the negated form __notnull or the possibly null form __maybenull. */ @@ -2418,7 +2418,7 @@ extern "C" { __readonly l __notreadonly l __mabyereadonly l - + Annotates a location l. States that location l is not modified after this point. If the annotation is placed on the precondition state of a function, the restriction only applies until the postcondition state @@ -2435,7 +2435,7 @@ extern "C" { __valid v __notvalid v __maybevalid v - + Annotates any value v. States that the value satisfies all properties of valid values of its type. For example, for a string buffer, valid means that the buffer pointer is either NULL or points to a NULL-terminated string. @@ -2447,7 +2447,7 @@ extern "C" { /* __readableTo(extent) p - + Annotates a buffer pointer p. If the buffer can be read, extent describes how much of the buffer is readable. For a reader of the buffer, this is an explicit permission to read up to that amount, rather than a restriction to @@ -2457,24 +2457,24 @@ extern "C" { #define __readableTo(extent) _SA_annotes1(SAL_readableTo, extent) /* - + __elem_readableTo(size) - + Annotates a buffer pointer p as being readable to size elements. */ #define __elem_readableTo(size) _SA_annotes1(SAL_readableTo, elementCount( size )) - + /* __byte_readableTo(size) - + Annotates a buffer pointer p as being readable to size bytes. */ #define __byte_readableTo(size) _SA_annotes1(SAL_readableTo, byteCount(size)) - + /* __writableTo(extent) p - + Annotates a buffer pointer p. If the buffer can be modified, extent describes how much of the buffer is writable (usually the allocation size). For a writer of the buffer, this is an explicit permission to @@ -2484,45 +2484,45 @@ extern "C" { /* __elem_writableTo(size) - + Annotates a buffer pointer p as being writable to size elements. */ #define __elem_writableTo(size) _SA_annotes1(SAL_writableTo, elementCount( size )) - + /* __byte_writableTo(size) - + Annotates a buffer pointer p as being writable to size bytes. */ #define __byte_writableTo(size) _SA_annotes1(SAL_writableTo, byteCount( size)) /* __deref p - + Annotates a pointer p. The next annotation applies one dereference down in the type. If readableTo(p, size) then the next annotation applies to all elements *(p+i) for which i satisfies the size. If p is a pointer to a struct, the next annotation applies to all fields of the struct. */ #define __deref _Deref_impl_ - + /* __pre __next_annotation - + The next annotation applies in the precondition state */ #define __pre _Pre_impl_ - + /* __post __next_annotation - + The next annotation applies in the postcondition state */ #define __post _Post_impl_ - + /* __precond() - + When is true, the next annotation applies in the precondition state (currently not enabled) */ @@ -2530,7 +2530,7 @@ extern "C" { /* __postcond() - + When is true, the next annotation applies in the postcondition state (currently not enabled) */ @@ -2538,26 +2538,26 @@ extern "C" { /* __exceptthat - + Given a set of annotations Q containing __exceptthat maybeP, the effect of the except clause is to erase any P or notP annotations (explicit or implied) within Q at the same level of dereferencing that the except clause appears, and to replace it with maybeP. - + Example 1: __valid __pre_except_maybenull on a pointer p means that the pointer may be null, and is otherwise valid, thus overriding the implicit notnull annotation implied by __valid on pointers. - + Example 2: __valid __deref __pre_except_maybenull on an int **p means that p is not null (implied by valid), but the elements - pointed to by p could be null, and are otherwise valid. + pointed to by p could be null, and are otherwise valid. */ #define __exceptthat __inner_exceptthat - + /* _refparam - + Added to all out parameter macros to indicate that they are all reference parameters. */ @@ -2565,16 +2565,16 @@ extern "C" { /* __inner_* - + Helper macros that directly correspond to certain high-level annotations. - + */ /* Macros to classify the entrypoints and indicate their category. - + Pre-defined control point categories include: RPC, LPC, DeviceDriver, UserToKernel, ISAPI, COM. - + */ #define __inner_control_entrypoint(category) _SA_annotes2(SAL_entrypoint, controlEntry, category) @@ -2643,7 +2643,7 @@ extern "C" { #endif /* #if !defined(__midl) && defined(_PREFAST_) */ // ] -/* +/* ------------------------------------------------------------------------------- Buffer Annotation Definitions @@ -2872,7 +2872,7 @@ of each annotation, see the advanced annotations section. #define __data_entrypoint(category) __inner_data_entrypoint(category) #define __useHeader _Use_decl_anno_impl_ #define __on_failure(annotes) _On_failure_impl_(annotes _SAL_nop_impl_) - + #ifndef __fallthrough // [ __inner_fallthrough_dec #define __fallthrough __inner_fallthrough @@ -2882,7 +2882,7 @@ of each annotation, see the advanced annotations section. #ifdef _PREFAST_ // [ #define __analysis_assume(expr) __assume(expr) #else // ][ -#define __analysis_assume(expr) +#define __analysis_assume(expr) #endif // ] #endif // ] @@ -2890,14 +2890,14 @@ of each annotation, see the advanced annotations section. #ifdef _PREFAST_ // [ #define _Analysis_assume_(expr) __assume(expr) #else // ][ -#define _Analysis_assume_(expr) +#define _Analysis_assume_(expr) #endif // ] #endif // ] #define _Analysis_noreturn_ _SAL2_Source_(_Analysis_noreturn_, (), _SA_annotes0(SAL_terminates)) #ifdef _PREFAST_ // [ -__inline __nothrow +__inline __nothrow void __AnalysisAssumeNullterminated(_Post_ __nullterminated void *p); #define _Analysis_assume_nullterminated_(x) __AnalysisAssumeNullterminated(x) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/servprov.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/servprov.h index 4dfffb1..0153cef 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/servprov.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/servprov.h @@ -6,8 +6,8 @@ // // =========================================================================== // File: servprov.h -// -// =========================================================================== +// +// =========================================================================== // simplified servprov.h for PAL #include "rpc.h" @@ -23,10 +23,10 @@ EXTERN_C const IID IID_IServiceProvider; interface IServiceProvider : public IUnknown { - virtual /* [local] */ HRESULT STDMETHODCALLTYPE QueryService( + virtual /* [local] */ HRESULT STDMETHODCALLTYPE QueryService( /* [in] */ REFGUID guidService, /* [in] */ REFIID riid, - /* [out] */ void **ppvObject) = 0; + /* [out] */ void **ppvObject) = 0; }; #endif // __IServiceProvider_INTERFACE_DEFINED__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/shellapi.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/shellapi.h index 5c20f4f..28e43f5 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/shellapi.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/shellapi.h @@ -6,8 +6,8 @@ // // =========================================================================== // File: shellapi.h -// -// =========================================================================== +// +// =========================================================================== // dummy shellapi.h for PAL #include "palrt.h" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/shlobj.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/shlobj.h index ba60876..3743143 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/shlobj.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/shlobj.h @@ -6,8 +6,8 @@ // // =========================================================================== // File: shlobj.h -// -// =========================================================================== +// +// =========================================================================== // dummy shlobj.h for PAL #include "palrt.h" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/shlwapi.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/shlwapi.h index d284fd6..deec281 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/shlwapi.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/shlwapi.h @@ -6,8 +6,8 @@ // // =========================================================================== // File: shlwapi.h -// -// =========================================================================== +// +// =========================================================================== // dummy shlwapi.h for PAL #include "palrt.h" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings.h index 12feab9..0a6397e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings.h @@ -310,8 +310,8 @@ __ANNOTATION(SAL_failureDefault(enum __SAL_failureKind)); __byte_readableTo((expr) ? (size) : (size) * 2) #define __post_invalid _Post_ __notvalid /* integer related macros */ -#define __allocator __inner_allocator #ifndef PAL_STDCPP_COMPAT +#define __allocator __inner_allocator #define __deallocate(kind) _Pre_ __notnull __post_invalid #define __deallocate_opt(kind) _Pre_ __maybenull __post_invalid #endif @@ -421,7 +421,7 @@ __inner_analysis_assume_nullterminated_dec // A common pattern is to pass an "_Inout_ PCHAR* ppBuf" of size "_Inout_ DWORD* pSize" // to a function that writes to **pBuf, incrementing *ppBuf to point to one // past the last written byte. Thus the length of the write is -// (*ppBuf - Old(*ppBuf)). The size of the remaining unwritten capacity +// (*ppBuf - Old(*ppBuf)). The size of the remaining unwritten capacity // is written to *pSize. // // This pattern is frequently used when progressively filling a @@ -463,7 +463,7 @@ __inner_analysis_assume_nullterminated_dec // completely accurate approximation, but reasonable. // #define _Post_equals_last_error_ _Post_satisfies_(_Curr_ != 0) - + #ifdef __cplusplus } #endif @@ -522,7 +522,7 @@ void __pfx_assume(int, const char *); as VS11 is the minimum required for SAL 2 support. If we are in a downlevel environment, we can go ahead and include no_sal2.h - to make all of SAL 2 no-ops to ensure no build failures. + to make all of SAL 2 no-ops to ensure no build failures. */ #if (!defined(_Outptr_) || _MSC_VER <= 1600) && !( defined( MIDL_PASS ) || defined(__midl) || defined(RC_INVOKED) ) && !( defined( _SDV_ ) ) /*IFSTRIP=IGN*/ #include diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings_adt.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings_adt.h index b3b9492..4737719 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings_adt.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings_adt.h @@ -7,7 +7,7 @@ // #pragma once /************************************************************************* -* DEFINITIONS OF NEW TYPES +* DEFINITIONS OF NEW TYPES *************************************************************************/ #if !defined(__midl) #define __$compname_props \ @@ -51,7 +51,7 @@ void __inline __nothrow __SAL_ValidCompNameW(__out_has_type_adt_props(ValidCompN #define __assume_ValidCompNameA(expr) __SAL_ValidCompNameA(expr) #define __assume_ValidCompNameW(expr) __SAL_ValidCompNameW(expr) #else -#define __assume_ValidCompNameA(expr) +#define __assume_ValidCompNameA(expr) #define __assume_ValidCompNameW(expr) #endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings_strict.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings_strict.h index 08d323c..2cf3512 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings_strict.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings_strict.h @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -/************************************************************************* +/************************************************************************* * This file documents all the macros approved for use in windows source * code. It includes some experimental macros which should only be used by * experts. @@ -17,12 +17,12 @@ * There are several levels of strictness, each level includes the behavior of * all previous levels. * -* 0 - Disable strict checking -* 1 - Break on unapproved macros and misuse of statement +* 0 - Disable strict checking +* 1 - Break on unapproved macros and misuse of statement * macros such as __fallthrough (default) * 2 - Deprecated some old macros that should not be used -* 3 - Use VS 2005 Source Annotation to make sure every macro -* is used in the right context. For example placing __in on a return +* 3 - Use VS 2005 Source Annotation to make sure every macro +* is used in the right context. For example placing __in on a return * parameter will result in an error. * @@ -37,32 +37,32 @@ * specstrings.h provides a set of annotations to describe how a function uses * its parameters - the assumptions it makes about them, and the guarantees it * makes upon finishing. -* +* * Annotations must be placed before a function parameter's type or its return * type. There are two basic classes of common annotations buffer annotations * and advanced annotations. Buffer annotations describe how functions use * their pointer parameters, and advanced annotations either describe * complex/unusual buffer behavior, or provide additional information about a * parameter that is not otherwise expressible. -* +* * Buffer Annotations -* +* * The most important annotations in SpecStrings.h provide a consistent way to * annotate buffer parameters or return values for a function. Each of these * annotations describes a single buffer (which could be a string, a * fixed-length or variable-length array, or just a pointer) that the function * interacts with: where it is, how large it is, how much is initialized, and * what the function does with it. -* +* * The appropriate macro for a given buffer can be constructed using the table * below. Just pick the appropriate values from each category, and combine * them together with a leading underscore. Some combinations of values do not * make sense as buffer annotations. Only meaningful annotations can be added * to your code; for a list of these, see the buffer annotation definitions * section. -* +* * Only a single buffer annotation should be used for each parameter. -* +* * |------------|------------|---------|--------|----------|---------------| * | Level | Usage | Size | Output | Optional | Parameters | * |------------|------------|---------|--------|----------|---------------| @@ -74,17 +74,17 @@ * |------------|------------|---------|--------|----------|---------------| * * Note: "<>" represents the empty string. -* +* * Level: Describes the buffer pointer's level of indirection from the * parameter or return value 'p'. -* +* * <> : p is the buffer pointer. * _deref : *p is the buffer pointer. p must not be NULL. -* _deref_opt : *p may be the buffer pointer. p may be NULL, in which case the +* _deref_opt : *p may be the buffer pointer. p may be NULL, in which case the * rest of the annotation is ignored. -* +* * Usage: Describes how the function uses the buffer. -* +* * <> : The buffer is not accessed. If used on the return value or with * _deref, the function will provide the buffer, and it will be uninitialized * at exit. Otherwise, the caller must provide the buffer. This should only @@ -105,7 +105,7 @@ * Size: Describes the total size of the buffer. This may be less than the * space actually allocated for the buffer, in which case it describes the * accessible amount. -* +* * <> : No buffer size is given. If the type specifies the buffer size (such * as with LPSTR and LPWSTR), that amount is used. Otherwise, the buffer is * one element long. Must be used with _in, _out, or _inout. @@ -113,12 +113,12 @@ * _ecount : The buffer size is an explicit element count. * * _bcount : The buffer size is an explicit byte count. -* +* * Output: Describes how much of the buffer will be initialized by the * function. For _inout buffers, this also describes how much is initialized * at entry. Omit this category for _in buffers; they must be fully * initialized by the caller. -* +* * <> : The type specifies how much is initialized. For instance, a function * initializing an LPWSTR must NULL-terminate the string. * @@ -126,16 +126,16 @@ * * _part : The function initializes part of the buffer, and explicitly * indicates how much. -* +* * Optional: Describes if the buffer itself is optional. -* +* * <> : The pointer to the buffer must not be NULL. * * _opt : The pointer to the buffer might be NULL. It will be checked before * being dereferenced. -* +* * Parameters: Gives explicit counts for the size and length of the buffer. -* +* * <> : There is no explicit count. Use when neither _ecount nor _bcount is * used. * @@ -144,47 +144,47 @@ * * (size,length) : The buffer's total size and initialized length are * given. Use with _ecount_part and _bcount_part. -* +* * ---------------------------------------------------------------------------- * Buffer Annotation Examples -* +* * LWSTDAPI_(BOOL) StrToIntExA( * LPCSTR pszString, // No annotation required, const implies __in. * DWORD dwFlags, * __out int *piRet // A pointer whose dereference will be filled in. * ); -* +* * void MyPaintingFunction( * __in HWND hwndControl, // An initialized read-only parameter. -* __in_opt HDC hdcOptional, // An initialized read-only parameter that +* __in_opt HDC hdcOptional, // An initialized read-only parameter that * // might be NULL. -* __inout IPropertyStore *ppsStore // An initialized parameter that +* __inout IPropertyStore *ppsStore // An initialized parameter that * // may be freely used and modified. * ); -* +* * LWSTDAPI_(BOOL) PathCompactPathExA( * __out_ecount(cchMax) LPSTR pszOut, // A string buffer with cch elements -* // that will be '\0' terminated +* // that will be '\0' terminated * // on exit. -* LPCSTR pszSrc, // No annotation required, +* LPCSTR pszSrc, // No annotation required, * // const implies __in. -* UINT cchMax, +* UINT cchMax, * DWORD dwFlags * ); -* +* * HRESULT SHLocalAllocBytes( * size_t cb, * __deref_bcount(cb) T **ppv // A pointer whose dereference will be set * // to an uninitialized buffer with cb bytes. * ); -* +* * __inout_bcount_full(cb) : A buffer with cb elements that is fully * initialized at entry and exit, and may be written to by this function. -* +* * __out_ecount_part(count, *countOut) : A buffer with count elements that * will be partially initialized by this function. The function indicates how * much it initialized by setting *countOut. -* +* ************************************************************************/ #if (_MSC_VER >= 1400) && !defined(__midl) && !defined(_PREFAST_) && (__SPECSTRINGS_STRICT_LEVEL > 0) @@ -375,7 +375,7 @@ #define __deref_opt_out_xcount_part_opt(size,len) __allowed(on_parameter) #define __deref_opt_out_ecount_full_opt(size) __allowed(on_parameter) #define __deref_opt_out_bcount_full_opt(size) __allowed(on_parameter) -#define __deref_opt_out_xcount_full_opt(size) __allowed(on_parameter) +#define __deref_opt_out_xcount_full_opt(size) __allowed(on_parameter) #define __deref_opt_out_z_opt __allowed(on_parameter) #define __deref_opt_out_ecount_z_opt(size) __allowed(on_parameter) #define __deref_opt_out_bcount_z_opt(size) __allowed(on_parameter) @@ -383,7 +383,7 @@ #define __deref_opt_inout_ecount_opt(size) __allowed(on_parameter) #define __deref_opt_inout_bcount_opt(size) __allowed(on_parameter) #define __deref_opt_inout_xcount_opt(size) __allowed(on_parameter) -#define __deref_opt_inout_ecount_part_opt(size,len) __allowed(on_parameter) +#define __deref_opt_inout_ecount_part_opt(size,len) __allowed(on_parameter) #define __deref_opt_inout_bcount_part_opt(size,len) __allowed(on_parameter) #define __deref_opt_inout_xcount_part_opt(size,len) __allowed(on_parameter) #define __deref_opt_inout_ecount_full_opt(size) __allowed(on_parameter) @@ -466,12 +466,12 @@ /************************************************************************ * Advanced Annotations -* +* * Advanced annotations describe behavior that is not expressible with the * regular buffer macros. These may be used either to annotate buffer * parameters that involve complex or conditional behavior, or to enrich * existing annotations with additional information. -* +* * _At_(expr, annotes) : annotation list annotes applies to target 'expr' * * _When_(expr, annotes) : annotation list annotes applies when 'expr' is true @@ -483,57 +483,57 @@ * the function must always satisfy its guarantees. Added automatically to * functions that indicate success in standard ways, such as by returning an * HRESULT. -* +* * __out_awcount(expr, size) T *p : Pointer p is a buffer whose size may be * given in either bytes or elements. If is true, this acts like * __out_bcount. If is false, this acts like __out_ecount. This * should only be used to annotate old APIs. -* +* * __in_awcount(expr, size) T* p : Pointer p is a buffer whose size may be given * in either bytes or elements. If is true, this acts like * __in_bcount. If is false, this acts like __in_ecount. This should * only be used to annotate old APIs. -* +* * __nullterminated T* p : Pointer p is a buffer that may be read or written * up to and including the first '\0' character or pointer. May be used on * typedefs, which marks valid (properly initialized) instances of that type * as being null-terminated. -* +* * __nullnullterminated T* p : Pointer p is a buffer that may be read or * written up to and including the first sequence of two '\0' characters or * pointers. May be used on typedefs, which marks valid instances of that * type as being double-null terminated. -* +* * __reserved T v : Value v must be 0/NULL, reserved for future use. -* +* * __checkReturn T f(); : Return value of f must not be ignored by callers * of this function. -* +* * __typefix(ctype) T v : Value v should be treated as an instance of ctype, * rather than its declared type when considering validity. -* +* * __override T f(); : Specify C#-style 'override' behaviour for overriding * virtual methods. -* +* * __callback T f(); : Function f can be used as a function pointer. -* +* * __format_string T p : Pointer p is a string that contains % markers in * the style of printf. -* +* * __blocksOn(resource) f(); : Function f blocks on the resource 'resource'. -* +* * __fallthrough : Annotates switch statement labels where fall-through is * desired, to distinguish from forgotten break statements. -* +* * __range(low_bnd, up_bnd) int f(): The return from the function "f" must * be in the inclusive numeric range [low_bnd, up_bnd]. * * __in_range(low_bnd, up_bnd) int i : Precondition that integer i must be * in the inclusive numeric range [low_bnd, up_bnd]. -* +* * __out_range(low_bnd, up_bnd) int i : Postcondition that integer i must be * in the inclusive numeric range [low_bnd, up_bnd]. -* +* * __deref_in_range(low_bnd, up_bnd) int* pi : Precondition that integer *pi * must be in the inclusive numeric range [low_bnd, up_bnd]. * @@ -545,16 +545,16 @@ * * The first argument of a range macro may also be a C relational operator * (<,>,!=, ==, <=, >=). -* +* * __range(rel_op, j) int f(): Postcondition that "f() rel_op j" must be * true. Note that j may be a expression known only at runtime. * * __in_range(rel_op, j) int i : Precondition that "i rel_op j" must be * true. Note that j may be a expression known only at runtime. -* +* * __out_range(rel_op, j) int i : Postcondition that integer "i rel_op j" * must be true. Note that j may be a expression known only at runtime. -* +* * __deref_in_range(rel_op, j) int *pi : Precondition that "*pi rel_op j" * must be true. Note that j may be a expression known only at runtime. * @@ -577,11 +577,11 @@ * __out_bound int i : Postcondition that integer i must be bound, but the * exact range can't be specified at compile time. __out_range should be * used if the range can be explicitly stated. -* +* * __deref_out_bound int pi : Postcondition that integer *pi must be bound, * but the exact range can't be specified at compile time. * __deref_out_range should be used if the range can be explicitly stated. -* +* * __assume_bound(expr); : Assume that the expression is bound to some known * range. This can be used to suppress integer overflow warnings on integral * expressions that are known to be bound due to reasons not explicit in the @@ -590,8 +590,8 @@ * __analysis_assume_nulltermianted(expr); : Assume that the expression is * a null terminated buffer. Use this to suppress tool noise specific to * nulltermination warnings, and capture deeper invariants tools can not -* discover. -* +* discover. +* * __allocator void f(): Function allocates memory using an integral size * argument * @@ -601,69 +601,69 @@ * void myfree(__deallocate_opt(Mem) void *p) : Memory is freed, no longer * usable upon return, and p may be null. * -* void free(__post_invalid void* x): Mark memory as untouchable when +* void free(__post_invalid void* x): Mark memory as unusable when * function returns. * * ---------------------------------------------------------------------------- * Advanced Annotation Examples -* -* __success(return == TRUE) LWSTDAPI_(BOOL) +* +* __success(return == TRUE) LWSTDAPI_(BOOL) * PathCanonicalizeA(__out_ecount(MAX_PATH) LPSTR pszBuf, LPCSTR pszPath); * // pszBuf is only guaranteed to be null-terminated when TRUE is returned. -* +* * // Initialized LPWSTRs are null-terminated strings. * typedef __nullterminated WCHAR* LPWSTR; -* +* * __out_ecount(cch) __typefix(LPWSTR) void *psz; -* // psz is a buffer parameter which will be a null-terminated WCHAR string +* // psz is a buffer parameter which will be a null-terminated WCHAR string * // at exit, and which initially contains cch WCHARs. -* +* ************************************************************************/ #define _At_(expr, annotes) __allowed(on_parameter_or_return) #define _When_(expr, annotes) __allowed(on_parameter_or_return) #define __success(expr) _SAL_VERSION_CHECK(__success) -#define __out_awcount(expr,size) __allowed(on_parameter) -#define __in_awcount(expr,size) __allowed(on_parameter) +#define __out_awcount(expr,size) __allowed(on_parameter) +#define __in_awcount(expr,size) __allowed(on_parameter) #define __nullterminated _SAL_VERSION_CHECK(__nullterminated) #define __nullnullterminated _SAL_VERSION_CHECK(__nullnullterminated) #define __clr_reserved _SAL_VERSION_CHECK(__reserved) #define __checkReturn _SAL_VERSION_CHECK(__checkReturn) -#define __typefix(ctype) __allowed(on_parameter_or_return) -#define __override __allowed(on_function) -#define __callback __allowed(on_function) -#define __format_string __allowed(on_parameter_or_return) -#define __blocksOn(resource) __allowed(on_function) +#define __typefix(ctype) __allowed(on_parameter_or_return) +#define __override __allowed(on_function) +#define __callback __allowed(on_function) +#define __format_string __allowed(on_parameter_or_return) +#define __blocksOn(resource) __allowed(on_function) #define __fallthrough __allowed(as_statement) -#define __range(lb,ub) __allowed(on_return) +#define __range(lb,ub) __allowed(on_return) #define __in_range(lb,ub) _SAL_VERSION_CHECK(__in_range) #define __out_range(lb,ub) _SAL_VERSION_CHECK(__out_range) -#define __deref_in_range(lb,ub) __allowed(on_parameter) +#define __deref_in_range(lb,ub) __allowed(on_parameter) #define __deref_out_range(lb,ub) _SAL_VERSION_CHECK(__deref_out_range) -#define __deref_inout_range(lb,ub) __allowed(on_parameter) +#define __deref_inout_range(lb,ub) __allowed(on_parameter) #define __field_range(lb,ub) _SAL_VERSION_CHECK(__field_range) -#define __range_max(a,b) __allowed(on_return) -#define __range_min(a,b) __allowed(on_return) -#define __bound __allowed(on_return) -#define __in_bound __allowed(on_parameter) -#define __out_bound __allowed(on_parameter) -#define __deref_out_bound __allowed(on_parameter) +#define __range_max(a,b) __allowed(on_return) +#define __range_min(a,b) __allowed(on_return) +#define __bound __allowed(on_return) +#define __in_bound __allowed(on_parameter) +#define __out_bound __allowed(on_parameter) +#define __deref_out_bound __allowed(on_parameter) #define __assume_bound(i) __allowed(as_statement_with_arg(i)) #define __analysis_assume_nullterminated(x) \ __allowed(as_statement_with_arg(x)) -#define __allocator __allowed(on_function) -#define __deallocate(kind) __allowed(on_parameter) -#define __deallocate_opt(kind) __allowed(on_parameter) -#define __post_invalid __allowed(on_parameter_or_return) +#define __allocator __allowed(on_function) +#define __deallocate(kind) __allowed(on_parameter) +#define __deallocate_opt(kind) __allowed(on_parameter) +#define __post_invalid __allowed(on_parameter_or_return) #define __post_nullnullterminated \ __allowed(on_parameter_or_return) -/*************************************************************************** +/*************************************************************************** * Expert Macros ***************************************************************************/ #define __null __allowed(on_typedecl) #define __notnull __allowed(on_typedecl) #define __maybenull __allowed(on_typedecl) #define __exceptthat __allowed(on_typedecl) -/*************************************************************************** +/*************************************************************************** * Macros to classify fields of structures. * Structure Annotations * @@ -764,54 +764,54 @@ * The pointer to the block of memory is may be * NULL * -* -* // Basic Usage of Struct Annotations -* #include -* #include -* struct buf_s { -* int sz; -* __field_bcount_full(sz) -* char *buf; -* }; -* void InitBuf(__out struct *buf_s b,int sz) { -* b->buf = calloc(sz,sizeof(char)); -* b->sz = sz; -* } -* void WriteBuf(__in FILE *fp,__in struct *buf_s b) { -* fwrite(b->buf,b->sz,sizeof(char),fp); -* } -* void ReadBuf(__in FILE *fp,__inout struct *buf_s b) { -* fread(b->buf,b->sz,sizeof(char),fp); -* } -* -* -* -* // Inline Allocated Buffer -* struct buf_s { -* int sz; -* __field_bcount(sz) -* char buf[1]; -* }; -* void WriteBuf(__in FILE *fp,__in struct *buf_s b) { -* fwrite(&(b->buf),b->sz,sizeof(char),fp); -* } -* void ReadBuf(__in FILE *fp,__inout struct *buf_s b) { -* fread(&(b->buf),b->sz,sizeof(char),fp); -* } -* -* -* -* // Embedded Header Structure -* __struct_bcount(sz) -* struct buf_s { -* int sz; -* }; -* void WriteBuf(__in FILE *fp,__in struct *buf_s b) { -* fwrite(&b,b->sz,sizeof(char),fp); -* } -* void ReadBuf(__in FILE *fp,__inout struct *buf_s b) { -* fread(&b,b->sz,sizeof(char),fp); -* } +* +* // Basic Usage of Struct Annotations +* #include +* #include +* struct buf_s { +* int sz; +* __field_bcount_full(sz) +* char *buf; +* }; +* void InitBuf(__out struct *buf_s b,int sz) { +* b->buf = calloc(sz,sizeof(char)); +* b->sz = sz; +* } +* void WriteBuf(__in FILE *fp,__in struct *buf_s b) { +* fwrite(b->buf,b->sz,sizeof(char),fp); +* } +* void ReadBuf(__in FILE *fp,__inout struct *buf_s b) { +* fread(b->buf,b->sz,sizeof(char),fp); +* } +* +* +* +* // Inline Allocated Buffer +* struct buf_s { +* int sz; +* __field_bcount(sz) +* char buf[1]; +* }; +* void WriteBuf(__in FILE *fp,__in struct *buf_s b) { +* fwrite(&(b->buf),b->sz,sizeof(char),fp); +* } +* void ReadBuf(__in FILE *fp,__inout struct *buf_s b) { +* fread(&(b->buf),b->sz,sizeof(char),fp); +* } +* +* +* +* // Embedded Header Structure +* __struct_bcount(sz) +* struct buf_s { +* int sz; +* }; +* void WriteBuf(__in FILE *fp,__in struct *buf_s b) { +* fwrite(&b,b->sz,sizeof(char),fp); +* } +* void ReadBuf(__in FILE *fp,__inout struct *buf_s b) { +* fread(&b,b->sz,sizeof(char),fp); +* } * * ****************************************************************************/ @@ -831,13 +831,13 @@ #define __field_bcount_full(size) __allowed(on_field) #define __field_xcount_full(size) __allowed(on_field) #define __field_ecount_full_opt(size) __allowed(on_field) -#define __field_bcount_full_opt(size) __allowed(on_field) +#define __field_bcount_full_opt(size) __allowed(on_field) #define __field_xcount_full_opt(size) __allowed(on_field) #define __field_nullterminated __allowed(on_field) -#define __struct_bcount(size) __allowed(on_struct) -#define __struct_xcount(size) __allowed(on_struct) +#define __struct_bcount(size) __allowed(on_struct) +#define __struct_xcount(size) __allowed(on_struct) -/*************************************************************************** +/*************************************************************************** * Macros to classify the entrypoints and indicate their category. * * Pre-defined control point categories include: RPC, KERNEL, GDI. @@ -845,12 +845,12 @@ * Pre-defined control point macros include: * __rpc_entry, __kernel_entry, __gdi_entry. ***************************************************************************/ -#define __control_entrypoint(category) __allowed(on_function) -#define __rpc_entry __allowed(on_function) -#define __kernel_entry __allowed(on_function) -#define __gdi_entry __allowed(on_function) +#define __control_entrypoint(category) __allowed(on_function) +#define __rpc_entry __allowed(on_function) +#define __kernel_entry __allowed(on_function) +#define __gdi_entry __allowed(on_function) -/*************************************************************************** +/*************************************************************************** * Macros to track untrusted data and their validation. The list of untrusted * sources include: * @@ -859,15 +859,15 @@ * INTERNET - WinInet and WinHttp readers * USER_REGISTRY - HKCU portions of the registry * USER_MODE - Parameters to kernel entry points -* RPC - Parameters to RPC entry points -* DRIVER - Device driver +* RPC - Parameters to RPC entry points +* DRIVER - Device driver ***************************************************************************/ -#define __in_data_source(src_sym) __allowed(on_parameter) -#define __out_data_source(src_sym) __allowed(on_parameter) +#define __in_data_source(src_sym) __allowed(on_parameter) +#define __out_data_source(src_sym) __allowed(on_parameter) #define __field_data_source(src_sym) __allowed(on_field) #define __this_out_data_source(src_syn) __allowed(on_function) -/************************************************************************** +/************************************************************************** * Macros to tag file parsing code. Predefined formats include: * PNG - Portable Network Graphics * JPEG - Joint Photographic Experts Group @@ -887,40 +887,40 @@ * AVI - Audio Visual Interchange * ACM - Audio Compression Manager **************************************************************************/ -#define __out_validated(filetype_sym) __allowed(on_parameter) -#define __this_out_validated(filetype_sym) __allowed(on_function) -#define __file_parser(filetype_sym) __allowed(on_function) -#define __file_parser_class(filetype_sym) __allowed(on_struct) -#define __file_parser_library(filetype_sym) __allowed(as_global_decl) +#define __out_validated(filetype_sym) __allowed(on_parameter) +#define __this_out_validated(filetype_sym) __allowed(on_function) +#define __file_parser(filetype_sym) __allowed(on_function) +#define __file_parser_class(filetype_sym) __allowed(on_struct) +#define __file_parser_library(filetype_sym) __allowed(as_global_decl) -/*************************************************************************** +/*************************************************************************** * Macros to track the code content in the file. The type of code * contents currently tracked: * -* NDIS_DRIVER - NDIS Device driver +* NDIS_DRIVER - NDIS Device driver ***************************************************************************/ -#define __source_code_content(codetype_sym) __allowed(as_global_decl) +#define __source_code_content(codetype_sym) __allowed(as_global_decl) -/*************************************************************************** +/*************************************************************************** * Macros to track the code content in the class. The type of code * contents currently tracked: * * DCOM - Class implementing DCOM ***************************************************************************/ -#define __class_code_content(codetype_sym) __allowed(on_struct) +#define __class_code_content(codetype_sym) __allowed(on_struct) /************************************************************************* * Macros to tag encoded function pointers **************************************************************************/ -#define __encoded_pointer -#define __encoded_array +#define __encoded_pointer +#define __encoded_array #define __field_encoded_pointer __allowed(on_field) #define __field_encoded_array __allowed(on_field) -#define __transfer(formal) __allowed(on_parameter_or_return) +#define __transfer(formal) __allowed(on_parameter_or_return) #define __assume_validated(exp) __allowed(as_statement_with_arg(exp)) -/************************************************************************* +/************************************************************************* * __analysis_assume(expr) : Expert macro use only when directed. Use this to * tell static analysis tools like PREfix and PREfast about a non-coded * assumption that you wish the tools to assume. The assumption will be @@ -937,7 +937,7 @@ #define __analysis_assume(expr) __allowed(as_statement_with_arg(expr)) #define __analysis_assert(expr) __allowed(as_statement_with_arg(expr)) -/************************************************************************* +/************************************************************************* * __analysis_hint(hint_sym) : Expert macro use only when * directed. Use this to influence certain analysis heuristics * used by the tools. These hints do not describe the semantics @@ -947,13 +947,13 @@ * Current hints that are supported are: * * INLINE - inline this function during analysis overrides any -* default heuristics -* NOINLINE - do not inline this function during analysis overrides +* default heuristics +* NOINLINE - do not inline this function during analysis overrides * and default heuristics *************************************************************************/ #define __analysis_hint(hint) __allowed(on_function) -/************************************************************************* +/************************************************************************* * Macros to encode abstract properties of values. Used by SALadt.h *************************************************************************/ #define __type_has_adt_prop(adt,prop) __allowed(on_typdecl) @@ -962,9 +962,9 @@ #define __out_transfer_adt_prop(arg) __allowed(on_parameter) #define __out_has_type_adt_props(typ) __allowed(on_parameter) -/************************************************************************* -* Macros used by Prefast for Drivers -* +/************************************************************************* +* Macros used by Prefast for Drivers +* * __possibly_notnullterminated : * * Used for return values of parameters or functions that do not @@ -973,18 +973,18 @@ *************************************************************************/ #define __possibly_notnullterminated __allowed(on_parameter_or_return) -/************************************************************************* +/************************************************************************* * Advanced macros -* -* __volatile +* +* __volatile * The __volatile annotation identifies a global variable or -* structure field that: -* 1) is not declared volatile; +* structure field that: +* 1) is not declared volatile; * 2) is accessed concurrently by multiple threads. * * The __deref_volatile annotation identifies a global variable * or structure field that stores a pointer to some data that: -* 1) is not declared volatile; +* 1) is not declared volatile; * 2) is accessed concurrently by multiple threads. * * Prefast uses these annotations to find patterns of code that @@ -1004,7 +1004,7 @@ #define __nonvolatile __allowed(on_global_or_field) #define __deref_nonvolatile __allowed(on_global_or_field) -/************************************************************************* +/************************************************************************* * Macros deprecated with strict level greater then 1. **************************************************************************/ #if (__SPECSTRINGS_STRICT_LEVEL > 1) @@ -1019,33 +1019,33 @@ #pragma deprecated(__inout_nz) #pragma deprecated(__inout_ecount_nz) #pragma deprecated(__inout_bcount_nz) -#pragma deprecated(__in_nz_opt) +#pragma deprecated(__in_nz_opt) #pragma deprecated(__in_ecount_nz_opt) #pragma deprecated(__in_bcount_nz_opt) #pragma deprecated(__out_ecount_nz_opt) #pragma deprecated(__out_bcount_nz_opt) -#pragma deprecated(__inout_nz_opt) +#pragma deprecated(__inout_nz_opt) #pragma deprecated(__inout_ecount_nz_opt) #pragma deprecated(__inout_bcount_nz_opt) -#pragma deprecated(__deref_out_nz) +#pragma deprecated(__deref_out_nz) #pragma deprecated(__deref_out_ecount_nz) #pragma deprecated(__deref_out_bcount_nz) -#pragma deprecated(__deref_inout_nz) +#pragma deprecated(__deref_inout_nz) #pragma deprecated(__deref_inout_ecount_nz) #pragma deprecated(__deref_inout_bcount_nz) -#pragma deprecated(__deref_out_nz_opt) +#pragma deprecated(__deref_out_nz_opt) #pragma deprecated(__deref_out_ecount_nz_opt) #pragma deprecated(__deref_out_bcount_nz_opt) -#pragma deprecated(__deref_inout_nz_opt) +#pragma deprecated(__deref_inout_nz_opt) #pragma deprecated(__deref_inout_ecount_nz_opt) #pragma deprecated(__deref_inout_bcount_nz_opt) -#pragma deprecated(__deref_opt_inout_nz) +#pragma deprecated(__deref_opt_inout_nz) #pragma deprecated(__deref_opt_inout_ecount_nz) #pragma deprecated(__deref_opt_inout_bcount_nz) -#pragma deprecated(__deref_opt_out_nz_opt) +#pragma deprecated(__deref_opt_out_nz_opt) #pragma deprecated(__deref_opt_out_ecount_nz_opt) #pragma deprecated(__deref_opt_out_bcount_nz_opt) -#pragma deprecated(__deref_opt_inout_nz_opt) +#pragma deprecated(__deref_opt_inout_nz_opt) #pragma deprecated(__deref_opt_inout_ecount_nz_opt) #pragma deprecated(__deref_opt_inout_bcount_nz_opt) #pragma deprecated(__deref) @@ -1067,52 +1067,52 @@ #pragma deprecated(__precond) #endif /* Define soon to be deprecated macros to nops. */ -#define __in_nz -#define __in_ecount_nz(size) -#define __in_bcount_nz(size) -#define __out_nz -#define __out_nz_opt -#define __out_ecount_nz(size) -#define __out_bcount_nz(size) -#define __inout_nz -#define __inout_ecount_nz(size) -#define __inout_bcount_nz(size) -#define __in_nz_opt -#define __in_ecount_nz_opt(size) -#define __in_bcount_nz_opt(size) -#define __out_ecount_nz_opt(size) -#define __out_bcount_nz_opt(size) -#define __inout_nz_opt -#define __inout_ecount_nz_opt(size) -#define __inout_bcount_nz_opt(size) -#define __deref_out_nz -#define __deref_out_ecount_nz(size) -#define __deref_out_bcount_nz(size) -#define __deref_inout_nz -#define __deref_inout_ecount_nz(size) -#define __deref_inout_bcount_nz(size) -#define __deref_out_nz_opt -#define __deref_out_ecount_nz_opt(size) -#define __deref_out_bcount_nz_opt(size) -#define __deref_inout_nz_opt -#define __deref_inout_ecount_nz_opt(size) -#define __deref_inout_bcount_nz_opt(size) -#define __deref_opt_inout_nz -#define __deref_opt_inout_ecount_nz(size) -#define __deref_opt_inout_bcount_nz(size) -#define __deref_opt_out_nz_opt -#define __deref_opt_out_ecount_nz_opt(size) -#define __deref_opt_out_bcount_nz_opt(size) -#define __deref_opt_inout_nz_opt -#define __deref_opt_inout_ecount_nz_opt(size) -#define __deref_opt_inout_bcount_nz_opt(size) -#define __deref -#define __pre -#define __post -#define __readableTo(count) -#define __writableTo(count) -#define __maybevalid -#define __inexpressible_readableTo(string) +#define __in_nz +#define __in_ecount_nz(size) +#define __in_bcount_nz(size) +#define __out_nz +#define __out_nz_opt +#define __out_ecount_nz(size) +#define __out_bcount_nz(size) +#define __inout_nz +#define __inout_ecount_nz(size) +#define __inout_bcount_nz(size) +#define __in_nz_opt +#define __in_ecount_nz_opt(size) +#define __in_bcount_nz_opt(size) +#define __out_ecount_nz_opt(size) +#define __out_bcount_nz_opt(size) +#define __inout_nz_opt +#define __inout_ecount_nz_opt(size) +#define __inout_bcount_nz_opt(size) +#define __deref_out_nz +#define __deref_out_ecount_nz(size) +#define __deref_out_bcount_nz(size) +#define __deref_inout_nz +#define __deref_inout_ecount_nz(size) +#define __deref_inout_bcount_nz(size) +#define __deref_out_nz_opt +#define __deref_out_ecount_nz_opt(size) +#define __deref_out_bcount_nz_opt(size) +#define __deref_inout_nz_opt +#define __deref_inout_ecount_nz_opt(size) +#define __deref_inout_bcount_nz_opt(size) +#define __deref_opt_inout_nz +#define __deref_opt_inout_ecount_nz(size) +#define __deref_opt_inout_bcount_nz(size) +#define __deref_opt_out_nz_opt +#define __deref_opt_out_ecount_nz_opt(size) +#define __deref_opt_out_bcount_nz_opt(size) +#define __deref_opt_inout_nz_opt +#define __deref_opt_inout_ecount_nz_opt(size) +#define __deref_opt_inout_bcount_nz_opt(size) +#define __deref +#define __pre +#define __post +#define __readableTo(count) +#define __writableTo(count) +#define __maybevalid +#define __inexpressible_readableTo(string) #define __data_entrypoint(category) #define __readonly #define __byte_writableTo(count) @@ -1124,7 +1124,7 @@ #define __refparam #define __precond(condition) -/************************************************************************* +/************************************************************************* * Definitions to force a compile error when macros are used improperly. * Relies on VS 2005 source annotations. *************************************************************************/ @@ -1160,7 +1160,7 @@ #define __$allowed_on_function [method: OnFunctionOnly] #define __$allowed_on_struct [OnStructOnly] #define __$allowed_on_field [OnFieldOnly] -#define __$allowed_on_parameter_or_return [OnParameterOrReturnOnly] +#define __$allowed_on_parameter_or_return [OnParameterOrReturnOnly] #define __$allowed_on_global_or_field /* empty */ #pragma push_macro( "DECL_SA" ) #pragma push_macro( "SA" ) @@ -1169,7 +1169,7 @@ #define DECL_SA(name,loc) \ [repeatable] \ [source_annotation_attribute( loc )] \ - struct name##Attribute { name##Attribute(); const char* ignored; }; + struct name##Attribute { name##Attribute(); const char* ignored; }; #else #define SA(x) SA_##x #define DECL_SA(name,loc) \ @@ -1185,6 +1185,6 @@ DECL_SA(OnFieldOnly,SA(Field)); DECL_SA(OnParameterOrReturnOnly,SA(Parameter) | SA(ReturnValue)); #pragma pop_macro( "SA" ) #pragma pop_macro( "DECL_SA" ) -#endif -#endif +#endif +#endif #endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings_undef.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings_undef.h index 69fc01c..d240ae1 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings_undef.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/specstrings_undef.h @@ -323,7 +323,7 @@ #undef __inner_adt_transfer_prop #undef __inner_adt_type_props #undef __inner_analysis_assume_nulltermianted_dec -#undef __inner_analysis_assume_nullterminated +#undef __inner_analysis_assume_nullterminated #undef __inner_assume_bound #undef __inner_assume_bound_dec #undef __inner_assume_validated diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/symcrypt.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/symcrypt.h index 33c24b2..0e71e2c 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/symcrypt.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/symcrypt.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: symcrypt.h -// +// // =========================================================================== // dummy symcrypt.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/tlhelp32.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/tlhelp32.h index 721590d..b052d0c 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/tlhelp32.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/tlhelp32.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: tlhelp32.h -// +// // =========================================================================== // dummy tlhelp32.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/unknwn.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/unknwn.h index 1397cdb..b2efa8f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/unknwn.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/unknwn.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: unknwn.h -// +// // =========================================================================== // simplified unknwn.h for PAL @@ -26,21 +26,13 @@ EXTERN_C const IID IID_IUnknown; MIDL_INTERFACE("00000000-0000-0000-C000-000000000046") IUnknown { - virtual HRESULT STDMETHODCALLTYPE QueryInterface( + virtual HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void **ppvObject) = 0; - - virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0; - - virtual ULONG STDMETHODCALLTYPE Release( void) = 0; - template - HRESULT - STDMETHODCALLTYPE - QueryInterface(Q** pp) - { - return QueryInterface(__uuidof(Q), (void **)pp); - } + virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0; + + virtual ULONG STDMETHODCALLTYPE Release( void) = 0; }; #endif // __IUnknown_INTERFACE_DEFINED__ @@ -50,16 +42,16 @@ IUnknown // 00000001-0000-0000-C000-000000000046 EXTERN_C const IID IID_IClassFactory; - + MIDL_INTERFACE("00000001-0000-0000-C000-000000000046") IClassFactory : public IUnknown { - virtual HRESULT STDMETHODCALLTYPE CreateInstance( + virtual HRESULT STDMETHODCALLTYPE CreateInstance( IUnknown *pUnkOuter, REFIID riid, void **ppvObject) = 0; - - virtual HRESULT STDMETHODCALLTYPE LockServer( + + virtual HRESULT STDMETHODCALLTYPE LockServer( BOOL fLock) = 0; }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/urlmon.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/urlmon.h index 827ad0d..80320f7 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/urlmon.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/urlmon.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: urlmon.h -// +// // =========================================================================== // dummy urlmon.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/verrsrc.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/verrsrc.h index 78a53cf..cd80202 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/verrsrc.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/verrsrc.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: verrsrc.h -// +// // =========================================================================== // dummy verrsrc.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/vsassert.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/vsassert.h deleted file mode 100644 index 3c50e59..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/vsassert.h +++ /dev/null @@ -1,93 +0,0 @@ -// 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. -// - -// - -// This is a simple implementation of what's in vsassert.h in vscommon, since -// we don't want to pull in the entire vsassert library. - -#ifndef __VSASSERT_H__ -#define __VSASSERT_H__ - -#define VSASSERT(e, szMsg) \ -do { \ - if (!(e)) { \ - PAL_fprintf (stderr, \ - "ASSERT FAILED:\n" \ - "\tExpression: %s\n" \ - "\tLocation: line %d in %s\n" \ - "\tFunction: %s\n" \ - "\tMessage: %s\n", \ - #e, __LINE__, __FILE__, __FUNCTION__, szMsg); \ - DebugBreak(); \ - } \ -} while (0) - -#define VSFAIL(szMsg) VSASSERT(0, szMsg) -#define VSIMPLIES(fHypothesis, fConclusion, szMsg) VSASSERT(!(fHypothesis) || (fConclusion), szMsg) -#define VSVERIFY(fTest, szMsg) VSASSERT((fTest), (szMsg)) - -#undef VSAlloc -#undef VSAllocZero -#undef VSRealloc -#undef VSReallocZero -#undef VSFree -#undef VSSize -#undef VsDebAlloc -#undef VsDebRealloc -#undef VsDebSafeRealloc -#undef VsDebFree -#undef VsDebHeapSize - -#undef VsDebHeapCreate -#undef VsDebHeapDestroy - -#undef VsDebugInitialize -#undef VsDebugTerminate - -// NOTE: These have changed to use the HeapAlloc family (as opposed to -// LocalAlloc family) because of HeapReAlloc's behavior (a block may move to -// satisfy a realloc request, as opposed to LocalReAlloc's behavior of simply -// failing). - -#define VSAlloc(cb) HeapAlloc(GetProcessHeap(), 0, cb) -#define VSAllocZero(cb) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb) -#define VSRealloc(pv, cb) HeapReAlloc(GetProcessHeap(), 0, pv, cb) -#define VSReallocZero(pv,cb) CoreCLR_pal_doesnt_have_vsrealloczero -#define VSFree(pv) HeapFree(GetProcessHeap(), 0, pv) -#define VSSize(pv) CoreCLR_pal_doesnt_have_heapsize - -#define VsDebAlloc(flags,cb) VSAlloc(cb) -#define VsDebRealloc(pv,flags,cb) VSRealloc(pv,cb) -#define VsDebSafeRealloc(pv,flags,cb) CoreCLR_pal_doenst_have_saferealloc -#define VsDebFree(pv) VSFree(pv) -#define VsDebHeapSize(heap, pv) VSSize(pv) - -#define VsDebHeapCreate(flags, name) CoreCLR_doesnt_have_heapcreate -#define VsDebHeapDestroy(heap, fLeakCheck) CoreCLR_doesnt_have_heapdestroy - -#define VsDebugAllocInternal(hheap,dwFlags,cb,pszFile,uLine,dwInst,pszExtra) \ - HeapAlloc(GetProcessHeap(), dwFlags, cb) - -#define DEFAULT_HEAP 0 -#define INSTANCE_GLOBAL 0 - -#define VsDebugInitialize() do {} while (0) -#define VsDebugTerminate() do {} while (0) - - -// Debug switches -// -#define DEFINE_SWITCH(NAME, PACKAGE, DESC) VSDEFINE_SWITCH(NAME, PACKAGE, DESC) -#define EXTERN_SWITCH(NAME) VSEXTERN_SWITCH(NAME) -#define FSWITCH(NAME) VSFSWITCH(NAME) - -#define VSDEFINE_SWITCH(NAME, PACKAGE, DESC) -#define VSEXTERN_SWITCH(NAME) -#define VSFSWITCH(NAME) FALSE - -#define VsIgnoreAllocs(f) - -#endif // __VSASSERT_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winapifamily.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winapifamily.h index 234a07b..3f3781d 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winapifamily.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winapifamily.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: windows.h -// +// // =========================================================================== // dummy winapifamily.h for PAL @@ -14,19 +14,19 @@ #define _INC_WINAPIFAMILY // -// Windows APIs can be placed in a partition represented by one of the below bits. The +// Windows APIs can be placed in a partition represented by one of the below bits. The // WINAPI_FAMILY value determines which partitions are available to the client code. // #define WINAPI_PARTITION_DESKTOP 0x00000001 -#define WINAPI_PARTITION_APP 0x00000002 +#define WINAPI_PARTITION_APP 0x00000002 // A family may be defined as the union of multiple families. WINAPI_FAMILY should be set // to one of these values. #define WINAPI_FAMILY_APP WINAPI_PARTITION_APP -#define WINAPI_FAMILY_DESKTOP_APP (WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_APP) +#define WINAPI_FAMILY_DESKTOP_APP (WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_APP) -// Provide a default for WINAPI_FAMILY if needed. +// Provide a default for WINAPI_FAMILY if needed. #ifndef WINAPI_FAMILY #define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP #endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winbase.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winbase.h index af9de7c..9b5dbdd 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winbase.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winbase.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: winbase.h -// +// // =========================================================================== // dummy winbase.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/wincrypt.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/wincrypt.h index 71caa7d..ce6b478 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/wincrypt.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/wincrypt.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: wincrypt.h -// +// // =========================================================================== // dummy wincrypt.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/windef.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/windef.h index 2ab50f2..e289a7c 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/windef.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/windef.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: windef.h -// +// // =========================================================================== // dummy windef.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/windows.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/windows.h index 802fde1..f793214 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/windows.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/windows.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: windows.h -// +// // =========================================================================== // dummy windows.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winerror.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winerror.h index e8eeed9..fd119d8 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winerror.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winerror.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: winerror.h -// +// // =========================================================================== // dummy winerror.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/wininet.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/wininet.h index e41482f..b11106b 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/wininet.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/wininet.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: wininet.h -// +// // =========================================================================== // dummy wininet.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winnls.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winnls.h index 57bb241..dd0d2fb 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winnls.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winnls.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: winnls.h -// +// // =========================================================================== // dummy winnls.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winnt.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winnt.h index 600338c..68184c4 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winnt.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winnt.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: winnt.h -// +// // =========================================================================== // dummy winnt.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winresrc.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winresrc.h index b8d9270..3f66f4e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winresrc.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winresrc.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: winresrc.h -// +// // =========================================================================== // winresrc.h for PAL // Included in .rc files. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winternl.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winternl.h index 476e40d..ba1c64b 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winternl.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winternl.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: winternl.h -// +// // =========================================================================== // dummy winternl.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winuser.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winuser.h index fc19f9a..1dcef15 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winuser.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winuser.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: winuser.h -// +// // =========================================================================== // dummy winuser.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winver.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winver.h index b315280..a3ab78a 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winver.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/winver.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: winver.h -// +// // =========================================================================== // winver.h for PAL // Included in .rc files. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/wtsapi32.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/wtsapi32.h index 0e41b15..b68f5c4 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/wtsapi32.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/rt/wtsapi32.h @@ -6,7 +6,7 @@ // // =========================================================================== // File: wtsapi32.h -// +// // =========================================================================== // dummy wtsapi32.h for PAL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/strsafe.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/strsafe.h index f32f5e6..b618a3b 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/strsafe.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/strsafe.h @@ -29,20 +29,14 @@ #include // for va_start, etc. #ifndef _SIZE_T_DEFINED -#ifdef _WIN64 +#ifdef HOST_64BIT typedef unsigned __int64 size_t; #else typedef __w64 unsigned int size_t; -#endif // !_WIN64 +#endif // !HOST_64BIT #define _SIZE_T_DEFINED #endif // !_SIZE_T_DEFINED -#if !defined(_WCHAR_T_DEFINED) && !defined(_NATIVE_WCHAR_T_DEFINED) -#error Unexpected define. -typedef char16_t WCHAR; -#define _WCHAR_T_DEFINED -#endif - #ifndef SUCCEEDED #define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) #endif @@ -151,7 +145,7 @@ Routine Description: This routine is not a replacement for strncpy. That function will pad the destination string with extra null termination characters if the count is - greater than the length of the source string, and it will fail to null + greater than the length of the source string, and it will fail to null terminate the destination string if the source string length is greater than or equal to the count. You can not blindly use this instead of strncpy: it is common for code to use it to "patch" strings and you would introduce @@ -172,9 +166,9 @@ Arguments: pszSrc - source string which must be null terminated -Notes: +Notes: Behavior is undefined if source and destination strings overlap. - + pszDest and pszSrc should not be NULL. See StringCchCopyEx if you require the handling of NULL values. @@ -186,7 +180,7 @@ Return Value: failure - you can use the macro HRESULT_CODE() to get a win32 error code for all hresult falure cases - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that the copy operation failed due to insufficient space. When this error occurs, @@ -242,123 +236,6 @@ STRSAFEAPI StringCchCopyW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc) #endif // STRSAFE_INLINE #endif // !STRSAFE_NO_CCH_FUNCTIONS - -#ifndef STRSAFE_NO_CB_FUNCTIONS -/*++ - -STDAPI StringCbCopy(LPTSTR pszDest, - size_t cbDest, - LPCTSTR pszSrc); - -Routine Description: - - This routine is a safer version of the C built-in function 'strcpy'. - The size of the destination buffer (in bytes) is a parameter and this - function will not write past the end of this buffer and it will ALWAYS - null terminate the destination buffer (unless it is zero length). - - This routine is not a replacement for strncpy. That function will pad the - destination string with extra null termination characters if the count is - greater than the length of the source string, and it will fail to null - terminate the destination string if the source string length is greater - than or equal to the count. You can not blindly use this instead of strncpy: - it is common for code to use it to "patch" strings and you would introduce - errors if the code started null terminating in the middle of the string. - - This function returns a hresult, and not a pointer. It returns a S_OK - if the string was copied without truncation and null terminated, otherwise - it will return a failure code. In failure cases as much of pszSrc will be - copied to pszDest as possible, and pszDest will be null terminated. - -Arguments: - - pszDest - destination string - - cbDest - size of destination buffer in bytes. - length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to - hold all of the source including the null terminator - - pszSrc - source string which must be null terminated - -Notes: - Behavior is undefined if source and destination strings overlap. - - pszDest and pszSrc should not be NULL. See StringCbCopyEx if you require - the handling of NULL values. - -Return Value: - - S_OK - if there was source data and it was all copied and the - resultant dest string was null terminated - - failure - you can use the macro HRESULT_CODE() to get a win32 error - code for all hresult falure cases - - STRSAFE_E_INSUFFICIENT_BUFFER / - HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - - this return value is an indication that the copy operation - failed due to insufficient space. When this error occurs, - the destination buffer is modified to contain a truncated - version of the ideal result and is null terminated. This - is useful for situations where truncation is ok - - It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the - return value of this function. - ---*/ - -STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc); -STRSAFEAPI StringCbCopyW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc); -#ifdef UNICODE -#define StringCbCopy StringCbCopyW -#else -#define StringCbCopy StringCbCopyA -#endif // !UNICODE - -#ifdef STRSAFE_INLINE -STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc) -{ - HRESULT hr; - size_t cchDest; - - // convert to count of characters - cchDest = cbDest / sizeof(char); - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringCopyWorkerA(pszDest, cchDest, pszSrc); - } - - return hr; -} - -STRSAFEAPI StringCbCopyW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc) -{ - HRESULT hr; - size_t cchDest; - - // convert to count of characters - cchDest = cbDest / sizeof(WCHAR); - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringCopyWorkerW(pszDest, cchDest, pszSrc); - } - - return hr; -} -#endif // STRSAFE_INLINE -#endif // !STRSAFE_NO_CB_FUNCTIONS - - #ifndef STRSAFE_NO_CCH_FUNCTIONS /*++ @@ -410,7 +287,7 @@ Arguments: STRSAFE_FILL_ON_FAILURE if the function fails, the low byte of dwFlags will be used to fill all of the destination buffer, and it will - be null terminated. This will overwrite any truncated + be null terminated. This will overwrite any truncated string returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER @@ -436,7 +313,7 @@ Return Value: failure - you can use the macro HRESULT_CODE() to get a win32 error code for all falure cases - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that the copy operation failed due to insufficient space. When this error occurs, @@ -482,7 +359,7 @@ STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, c STRSAFEAPI StringCchCopyExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) { HRESULT hr; - + if (cchDest > STRSAFE_MAX_CCH) { hr = STRSAFE_E_INVALID_PARAMETER; @@ -502,167 +379,6 @@ STRSAFEAPI StringCchCopyExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, #endif // STRSAFE_INLINE #endif // !STRSAFE_NO_CCH_FUNCTIONS - -#ifndef STRSAFE_NO_CB_FUNCTIONS -/*++ - -STDAPI StringCbCopyEx(TCHAR pszDest, - size_t cbDest, - LPCTSTR pszSrc, - LPTSTR* ppszDestEnd, - size_t* pcbRemaining, - DWORD dwFlags); - -Routine Description: - - This routine is a safer version of the C built-in function 'strcpy' with - some additional parameters. In addition to functionality provided by - StringCbCopy, this routine also returns a pointer to the end of the - destination string and the number of bytes left in the destination string - including the null terminator. The flags parameter allows additional controls. - -Arguments: - - pszDest - destination string - - cbDest - size of destination buffer in bytes. - length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to - hold all of the source including the null terminator - - pszSrc - source string which must be null terminated - - ppszDestEnd - if ppszDestEnd is non-null, the function will return a - pointer to the end of the destination string. If the - function copied any data, the result will point to the - null termination character - - pcbRemaining - pcbRemaining is non-null,the function will return the - number of bytes left in the destination string, - including the null terminator - - dwFlags - controls some details of the string copy: - - STRSAFE_FILL_BEHIND_NULL - if the function succeeds, the low byte of dwFlags will be - used to fill the uninitialize part of destination buffer - behind the null terminator - - STRSAFE_IGNORE_NULLS - treat NULL string pointers like empty strings (TEXT("")). - this flag is useful for emulating functions like lstrcpy - - STRSAFE_FILL_ON_FAILURE - if the function fails, the low byte of dwFlags will be - used to fill all of the destination buffer, and it will - be null terminated. This will overwrite any truncated - string returned when the failure is - STRSAFE_E_INSUFFICIENT_BUFFER - - STRSAFE_NO_TRUNCATION / - STRSAFE_NULL_ON_FAILURE - if the function fails, the destination buffer will be set - to the empty string. This will overwrite any truncated string - returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. - -Notes: - Behavior is undefined if source and destination strings overlap. - - pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag - is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc - may be NULL. An error may still be returned even though NULLS are ignored - due to insufficient space. - -Return Value: - - S_OK - if there was source data and it was all copied and the - resultant dest string was null terminated - - failure - you can use the macro HRESULT_CODE() to get a win32 error - code for all falure cases - - STRSAFE_E_INSUFFICIENT_BUFFER / - HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - - this return value is an indication that the copy operation - failed due to insufficient space. When this error occurs, - the destination buffer is modified to contain a truncated - version of the ideal result and is null terminated. This - is useful for situations where truncation is ok. - - It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the - return value of this function - ---*/ - -STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); -STRSAFEAPI StringCbCopyExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); -#ifdef UNICODE -#define StringCbCopyEx StringCbCopyExW -#else -#define StringCbCopyEx StringCbCopyExA -#endif // !UNICODE - -#ifdef STRSAFE_INLINE -STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) -{ - HRESULT hr; - size_t cchDest; - size_t cchRemaining = 0; - - cchDest = cbDest / sizeof(char); - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringCopyExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags); - } - - if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) - { - if (pcbRemaining) - { - // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 - *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); - } - } - - return hr; -} - -STRSAFEAPI StringCbCopyExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) -{ - HRESULT hr; - size_t cchDest; - size_t cchRemaining = 0; - - cchDest = cbDest / sizeof(WCHAR); - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags); - } - - if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) - { - if (pcbRemaining) - { - // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 - *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)); - } - } - - return hr; -} -#endif // STRSAFE_INLINE -#endif // !STRSAFE_NO_CB_FUNCTIONS - - #ifndef STRSAFE_NO_CCH_FUNCTIONS /*++ @@ -700,9 +416,9 @@ Arguments: cchSrc - maximum number of characters to copy from source string -Notes: +Notes: Behavior is undefined if source and destination strings overlap. - + pszDest and pszSrc should not be NULL. See StringCchCopyNEx if you require the handling of NULL values. @@ -714,7 +430,7 @@ Return Value: failure - you can use the macro HRESULT_CODE() to get a win32 error code for all hresult falure cases - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that the copy operation failed due to insufficient space. When this error occurs, @@ -757,128 +473,6 @@ STRSAFEAPI StringCchCopyNW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, { HRESULT hr; - if ((cchDest > STRSAFE_MAX_CCH) || - (cchSrc > STRSAFE_MAX_CCH)) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringCopyNWorkerW(pszDest, cchDest, pszSrc, cchSrc); - } - - return hr; -} -#endif // STRSAFE_INLINE -#endif // !STRSAFE_NO_CCH_FUNCTIONS - - -#ifndef STRSAFE_NO_CB_FUNCTIONS -/*++ - -STDAPI StringCbCopyN(LPTSTR pszDest, - size_t cbDest, - LPCTSTR pszSrc, - size_t cbSrc); - -Routine Description: - - This routine is a safer version of the C built-in function 'strncpy'. - The size of the destination buffer (in bytes) is a parameter and this - function will not write past the end of this buffer and it will ALWAYS - null terminate the destination buffer (unless it is zero length). - - This routine is meant as a replacement for strncpy, but it does behave - differently. This function will not pad the destination buffer with extra - null termination characters if cbSrc is greater than the size of pszSrc. - - This function returns a hresult, and not a pointer. It returns a S_OK - if the entire string or the first cbSrc characters were copied without - truncation and the resultant destination string was null terminated, otherwise - it will return a failure code. In failure cases as much of pszSrc will be - copied to pszDest as possible, and pszDest will be null terminated. - -Arguments: - - pszDest - destination string - - cbDest - size of destination buffer in bytes. - length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to - hold all of the source including the null terminator - - pszSrc - source string - - cbSrc - maximum number of bytes to copy from source string - -Notes: - Behavior is undefined if source and destination strings overlap. - - pszDest and pszSrc should not be NULL. See StringCbCopyEx if you require - the handling of NULL values. - -Return Value: - - S_OK - if there was source data and it was all copied and the - resultant dest string was null terminated - - failure - you can use the macro HRESULT_CODE() to get a win32 error - code for all hresult falure cases - - STRSAFE_E_INSUFFICIENT_BUFFER / - HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - - this return value is an indication that the copy operation - failed due to insufficient space. When this error occurs, - the destination buffer is modified to contain a truncated - version of the ideal result and is null terminated. This - is useful for situations where truncation is ok - - It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the - return value of this function. - ---*/ - -STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc); -STRSAFEAPI StringCbCopyNW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbSrc); -#ifdef UNICODE -#define StringCbCopyN StringCbCopyNW -#else -#define StringCbCopyN StringCbCopyNA -#endif // !UNICODE - -#ifdef STRSAFE_INLINE -STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc) -{ - HRESULT hr; - size_t cchDest; - size_t cchSrc; - - // convert to count of characters - cchDest = cbDest / sizeof(char); - cchSrc = cbSrc / sizeof(char); - - if ((cchDest > STRSAFE_MAX_CCH) || - (cchSrc > STRSAFE_MAX_CCH)) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc); - } - - return hr; -} - -STRSAFEAPI StringCbCopyNW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbSrc) -{ - HRESULT hr; - size_t cchDest; - size_t cchSrc; - - // convert to count of characters - cchDest = cbDest / sizeof(WCHAR); - cchSrc = cbSrc / sizeof(WCHAR); - if ((cchDest > STRSAFE_MAX_CCH) || (cchSrc > STRSAFE_MAX_CCH)) { @@ -892,8 +486,7 @@ STRSAFEAPI StringCbCopyNW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, si return hr; } #endif // STRSAFE_INLINE -#endif // !STRSAFE_NO_CB_FUNCTIONS - +#endif // !STRSAFE_NO_CCH_FUNCTIONS #ifndef STRSAFE_NO_CCH_FUNCTIONS /*++ @@ -955,7 +548,7 @@ Arguments: STRSAFE_FILL_ON_FAILURE if the function fails, the low byte of dwFlags will be used to fill all of the destination buffer, and it will - be null terminated. This will overwrite any truncated + be null terminated. This will overwrite any truncated string returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER @@ -981,7 +574,7 @@ Return Value: failure - you can use the macro HRESULT_CODE() to get a win32 error code for all falure cases - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that the copy operation failed due to insufficient space. When this error occurs, @@ -1028,7 +621,7 @@ STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, STRSAFEAPI StringCchCopyNExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) { HRESULT hr; - + if ((cchDest > STRSAFE_MAX_CCH) || (cchSrc > STRSAFE_MAX_CCH)) { @@ -1050,180 +643,6 @@ STRSAFEAPI StringCchCopyNExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc #endif // !STRSAFE_NO_CCH_FUNCTIONS -#ifndef STRSAFE_NO_CB_FUNCTIONS -/*++ - -STDAPI StringCbCopyNEx(TCHAR pszDest, - size_t cbDest, - LPCTSTR pszSrc, - size_t cbSrc, - LPTSTR* ppszDestEnd, - size_t* pcbRemaining, - DWORD dwFlags); - -Routine Description: - - This routine is a safer version of the C built-in function 'strncpy' with - some additional parameters. In addition to functionality provided by - StringCbCopyN, this routine also returns a pointer to the end of the - destination string and the number of bytes left in the destination string - including the null terminator. The flags parameter allows additional controls. - - This routine is meant as a replacement for strncpy, but it does behave - differently. This function will not pad the destination buffer with extra - null termination characters if cbSrc is greater than the size of pszSrc. - -Arguments: - - pszDest - destination string - - cbDest - size of destination buffer in bytes. - length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to - hold all of the source including the null terminator - - pszSrc - source string - - cbSrc - maximum number of bytes to copy from source string - - ppszDestEnd - if ppszDestEnd is non-null, the function will return a - pointer to the end of the destination string. If the - function copied any data, the result will point to the - null termination character - - pcbRemaining - pcbRemaining is non-null,the function will return the - number of bytes left in the destination string, - including the null terminator - - dwFlags - controls some details of the string copy: - - STRSAFE_FILL_BEHIND_NULL - if the function succeeds, the low byte of dwFlags will be - used to fill the uninitialize part of destination buffer - behind the null terminator - - STRSAFE_IGNORE_NULLS - treat NULL string pointers like empty strings (TEXT("")). - this flag is useful for emulating functions like lstrcpy - - STRSAFE_FILL_ON_FAILURE - if the function fails, the low byte of dwFlags will be - used to fill all of the destination buffer, and it will - be null terminated. This will overwrite any truncated - string returned when the failure is - STRSAFE_E_INSUFFICIENT_BUFFER - - STRSAFE_NO_TRUNCATION / - STRSAFE_NULL_ON_FAILURE - if the function fails, the destination buffer will be set - to the empty string. This will overwrite any truncated string - returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. - -Notes: - Behavior is undefined if source and destination strings overlap. - - pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag - is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc - may be NULL. An error may still be returned even though NULLS are ignored - due to insufficient space. - -Return Value: - - S_OK - if there was source data and it was all copied and the - resultant dest string was null terminated - - failure - you can use the macro HRESULT_CODE() to get a win32 error - code for all falure cases - - STRSAFE_E_INSUFFICIENT_BUFFER / - HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - - this return value is an indication that the copy operation - failed due to insufficient space. When this error occurs, - the destination buffer is modified to contain a truncated - version of the ideal result and is null terminated. This - is useful for situations where truncation is ok. - - It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the - return value of this function - ---*/ - -STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); -STRSAFEAPI StringCbCopyNExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); -#ifdef UNICODE -#define StringCbCopyNEx StringCbCopyNExW -#else -#define StringCbCopyNEx StringCbCopyNExA -#endif // !UNICODE - - -#ifdef STRSAFE_INLINE -STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) -{ - HRESULT hr; - size_t cchDest; - size_t cchSrc; - size_t cchRemaining = 0; - - cchDest = cbDest / sizeof(char); - cchSrc = cbSrc / sizeof(char); - - if ((cchDest > STRSAFE_MAX_CCH) || - (cchSrc > STRSAFE_MAX_CCH)) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags); - } - - if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) - { - if (pcbRemaining) - { - // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 - *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); - } - } - - return hr; -} - -STRSAFEAPI StringCbCopyNExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) -{ - HRESULT hr; - size_t cchDest; - size_t cchSrc; - size_t cchRemaining = 0; - - cchDest = cbDest / sizeof(WCHAR); - cchSrc = cbSrc / sizeof(WCHAR); - - if ((cchDest > STRSAFE_MAX_CCH) || - (cchSrc > STRSAFE_MAX_CCH)) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags); - } - - if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) - { - if (pcbRemaining) - { - // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 - *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)); - } - } - - return hr; -} -#endif // STRSAFE_INLINE -#endif // !STRSAFE_NO_CB_FUNCTIONS - - #ifndef STRSAFE_NO_CCH_FUNCTIONS /*++ @@ -1249,14 +668,14 @@ Arguments: cchDest - size of destination buffer in characters. length must be = (_tcslen(pszDest) + _tcslen(pszSrc) + 1) - to hold all of the combine string plus the null + to hold all of the combine string plus the null terminator pszSrc - source string which must be null terminated -Notes: +Notes: Behavior is undefined if source and destination strings overlap. - + pszDest and pszSrc should not be NULL. See StringCchCatEx if you require the handling of NULL values. @@ -1268,7 +687,7 @@ Return Value: failure - you can use the macro HRESULT_CODE() to get a win32 error code for all falure cases - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that the operation failed due to insufficient space. When this error occurs, @@ -1350,14 +769,14 @@ Arguments: cbDest - size of destination buffer in bytes. length must be = ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR) - to hold all of the combine string plus the null + to hold all of the combine string plus the null terminator pszSrc - source string which must be null terminated -Notes: +Notes: Behavior is undefined if source and destination strings overlap. - + pszDest and pszSrc should not be NULL. See StringCbCatEx if you require the handling of NULL values. @@ -1369,7 +788,7 @@ Return Value: failure - you can use the macro HRESULT_CODE() to get a win32 error code for all falure cases - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that the operation failed due to insufficient space. When this error occurs, @@ -1395,7 +814,7 @@ STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* pszSrc) { HRESULT hr; size_t cchDest; - + cchDest = cbDest / sizeof(char); if (cchDest > STRSAFE_MAX_CCH) @@ -1414,7 +833,7 @@ STRSAFEAPI StringCbCatW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc) { HRESULT hr; size_t cchDest; - + cchDest = cbDest / sizeof(WCHAR); if (cchDest > STRSAFE_MAX_CCH) @@ -1443,10 +862,10 @@ STDAPI StringCchCatEx(LPTSTR pszDest, DWORD dwFlags); Routine Description: - + This routine is a safer version of the C built-in function 'strcat' with some additional parameters. In addition to functionality provided by - StringCchCat, this routine also returns a pointer to the end of the + StringCchCat, this routine also returns a pointer to the end of the destination string and the number of characters left in the destination string including the null terminator. The flags parameter allows additional controls. @@ -1512,7 +931,7 @@ Return Value: failure - you can use the macro HRESULT_CODE() to get a win32 error code for all falure cases - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that the operation failed due to insufficient space. When this error occurs, @@ -1558,7 +977,7 @@ STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, ch STRSAFEAPI StringCchCatExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) { HRESULT hr; - + if (cchDest > STRSAFE_MAX_CCH) { hr = STRSAFE_E_INVALID_PARAMETER; @@ -1593,7 +1012,7 @@ Routine Description: This routine is a safer version of the C built-in function 'strcat' with some additional parameters. In addition to functionality provided by - StringCbCat, this routine also returns a pointer to the end of the + StringCbCat, this routine also returns a pointer to the end of the destination string and the number of bytes left in the destination string including the null terminator. The flags parameter allows additional controls. @@ -1602,7 +1021,7 @@ Arguments: pszDest - destination string which must be null terminated cbDest - size of destination buffer in bytes. - length must be ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR) + length must be ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR) to hold all of the combine string plus the null terminator. @@ -1613,7 +1032,7 @@ Arguments: function appended any data, the result will point to the null termination character - pcbRemaining - if pcbRemaining is non-null, the function will return + pcbRemaining - if pcbRemaining is non-null, the function will return the number of bytes left in the destination string, including the null terminator @@ -1659,7 +1078,7 @@ Return Value: failure - you can use the macro HRESULT_CODE() to get a win32 error code for all falure cases - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that the operation failed due to insufficient space. When this error occurs, @@ -1785,14 +1204,14 @@ Notes: Return Value: - S_OK - if all of pszSrc or the first cchMaxAppend characters were + S_OK - if all of pszSrc or the first cchMaxAppend characters were concatenated to pszDest and the resultant dest string was null terminated failure - you can use the macro HRESULT_CODE() to get a win32 error code for all falure cases - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that the operation failed due to insufficient space. When this error occurs, @@ -1833,7 +1252,7 @@ STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, siz STRSAFEAPI StringCchCatNW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend) { HRESULT hr; - + if (cchDest > STRSAFE_MAX_CCH) { hr = STRSAFE_E_INVALID_PARAMETER; @@ -1876,7 +1295,7 @@ Arguments: pszDest - destination string which must be null terminated cbDest - size of destination buffer in bytes. - length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR) + length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR) to hold all of the combine string plus the null terminator. @@ -1892,14 +1311,14 @@ Notes: Return Value: - S_OK - if all of pszSrc or the first cbMaxAppend bytes were + S_OK - if all of pszSrc or the first cbMaxAppend bytes were concatenated to pszDest and the resultant dest string was null terminated failure - you can use the macro HRESULT_CODE() to get a win32 error code for all falure cases - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that the operation failed due to insufficient space. When this error occurs, @@ -1935,7 +1354,7 @@ STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_ else { size_t cchMaxAppend; - + cchMaxAppend = cbMaxAppend / sizeof(char); hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend); @@ -1982,10 +1401,10 @@ STDAPI StringCchCatNEx(LPTSTR pszDest, DWORD dwFlags); Routine Description: - - This routine is a safer version of the C built-in function 'strncat', with + + This routine is a safer version of the C built-in function 'strncat', with some additional parameters. In addition to functionality provided by - StringCchCatN, this routine also returns a pointer to the end of the + StringCchCatN, this routine also returns a pointer to the end of the destination string and the number of characters left in the destination string including the null terminator. The flags parameter allows additional controls. @@ -2046,14 +1465,14 @@ Notes: Return Value: - S_OK - if all of pszSrc or the first cchMaxAppend characters were + S_OK - if all of pszSrc or the first cchMaxAppend characters were concatenated to pszDest and the resultant dest string was null terminated failure - you can use the macro HRESULT_CODE() to get a win32 error code for all falure cases - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that the operation failed due to insufficient space. When this error occurs, @@ -2099,7 +1518,7 @@ STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, s STRSAFEAPI StringCchCatNExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) { HRESULT hr; - + if (cchDest > STRSAFE_MAX_CCH) { hr = STRSAFE_E_INVALID_PARAMETER; @@ -2132,10 +1551,10 @@ STDAPI StringCbCatNEx(LPTSTR pszDest, DWORD dwFlags); Routine Description: - - This routine is a safer version of the C built-in function 'strncat', with + + This routine is a safer version of the C built-in function 'strncat', with some additional parameters. In addition to functionality provided by - StringCbCatN, this routine also returns a pointer to the end of the + StringCbCatN, this routine also returns a pointer to the end of the destination string and the number of bytes left in the destination string including the null terminator. The flags parameter allows additional controls. @@ -2144,7 +1563,7 @@ Arguments: pszDest - destination string which must be null terminated cbDest - size of destination buffer in bytes. - length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR) + length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR) to hold all of the combine string plus the null terminator. @@ -2196,14 +1615,14 @@ Notes: Return Value: - S_OK - if all of pszSrc or the first cbMaxAppend bytes were + S_OK - if all of pszSrc or the first cbMaxAppend bytes were concatenated to pszDest and the resultant dest string was null terminated failure - you can use the macro HRESULT_CODE() to get a win32 error code for all falure cases - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that the operation failed due to insufficient space. When this error occurs, @@ -2240,7 +1659,7 @@ STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, siz else { size_t cchMaxAppend; - + cchMaxAppend = cbMaxAppend / sizeof(char); hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags); @@ -2273,7 +1692,7 @@ STRSAFEAPI StringCbCatNExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, s else { size_t cchMaxAppend; - + cchMaxAppend = cbMaxAppend / sizeof(WCHAR); hr = StringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags); @@ -2320,8 +1739,8 @@ Arguments: cchDest - size of destination buffer in characters. -Notes: - pszDest should not be NULL. See StringCchGetsEx if you require the handling +Notes: + pszDest should not be NULL. See StringCchGetsEx if you require the handling of NULL values. cchDest must be > 1 for this function to succeed. @@ -2338,7 +1757,7 @@ Return Value: - this return value indicates an error or end-of-file condition, use feof or ferror to determine which one has occurred. - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that there was insufficient space in the destination buffer to copy any data @@ -2376,8 +1795,8 @@ Arguments: cbDest - size of destination buffer in bytes. -Notes: - pszDest should not be NULL. See StringCbGetsEx if you require the handling +Notes: + pszDest should not be NULL. See StringCbGetsEx if you require the handling of NULL values. cbDest must be > sizeof(TCHAR) for this function to succeed. @@ -2394,7 +1813,7 @@ Return Value: - this return value indicates an error or end-of-file condition, use feof or ferror to determine which one has occurred. - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that there was insufficient space in the destination buffer to copy any data @@ -2428,7 +1847,7 @@ Arguments: pszDest - destination string cchDest - size of destination buffer in characters. - + ppszDestEnd - if ppszDestEnd is non-null, the function will return a pointer to the end of the destination string. If the function copied any data, the result will point to the @@ -2456,11 +1875,11 @@ Arguments: STRSAFE_NO_TRUNCATION / STRSAFE_NULL_ON_FAILURE if the function fails, the destination buffer will be set - to the empty string. - + to the empty string. + Notes: pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified. - If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be + If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be returned even though NULLS are ignored cchDest must be > 1 for this function to succeed. @@ -2477,7 +1896,7 @@ Return Value: - this return value indicates an error or end-of-file condition, use feof or ferror to determine which one has occurred. - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that there was insufficient space in the destination buffer to copy any data @@ -2511,7 +1930,7 @@ Arguments: pszDest - destination string cbDest - size of destination buffer in bytes. - + ppszDestEnd - if ppszDestEnd is non-null, the function will return a pointer to the end of the destination string. If the function copied any data, the result will point to the @@ -2539,11 +1958,11 @@ Arguments: STRSAFE_NO_TRUNCATION / STRSAFE_NULL_ON_FAILURE if the function fails, the destination buffer will be set - to the empty string. - + to the empty string. + Notes: pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified. - If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be + If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be returned even though NULLS are ignored cbDest must be > sizeof(TCHAR) for this function to succeed @@ -2560,7 +1979,7 @@ Return Value: - this return value indicates an error or end-of-file condition, use feof or ferror to determine which one has occurred. - STRSAFE_E_INSUFFICIENT_BUFFER / + STRSAFE_E_INSUFFICIENT_BUFFER / HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - this return value is an indication that there was insufficient space in the destination buffer to copy any data @@ -2601,7 +2020,7 @@ Arguments: in characters of psz excluding the null terminator will be returned. This out parameter is equivalent to the return value of strlen(psz) -Notes: +Notes: psz can be null but the function will fail cchMax should be greater than zero or the function will fail @@ -2631,7 +2050,7 @@ STRSAFEAPI StringCchLengthW(const WCHAR* psz, size_t cchMax, size_t* pcch); STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch) { HRESULT hr; - + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) { hr = STRSAFE_E_INVALID_PARAMETER; @@ -2674,7 +2093,7 @@ Routine Description: This routine is a safer version of the C built-in function 'strlen'. It is used to make sure a string is not larger than a given length, and - it optionally returns the current length in bytes not including + it optionally returns the current length in bytes not including the null terminator. This function returns a hresult, and not a pointer. It returns a S_OK @@ -2692,7 +2111,7 @@ Arguments: in bytes of psz excluding the null terminator will be returned. This out parameter is equivalent to the return value of strlen(psz) * sizeof(TCHAR) -Notes: +Notes: psz can be null but the function will fail cbMax should be greater than or equal to sizeof(TCHAR) or the function will fail @@ -2844,7 +2263,7 @@ STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, con // ASSERT(cbDest == (cchDest * sizeof(char)) || // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); - + // only accept valid flags if (dwFlags & (~STRSAFE_VALID_FLAGS)) { @@ -2899,7 +2318,7 @@ STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, con *pszDestEnd++= *pszSrc++; cchRemaining--; } - + if (cchRemaining > 0) { if (dwFlags & STRSAFE_FILL_BEHIND_NULL) @@ -2928,7 +2347,7 @@ STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, con if (dwFlags & STRSAFE_FILL_ON_FAILURE) { memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); - + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) { pszDestEnd = pszDest; @@ -2960,7 +2379,7 @@ STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, con if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) { - if (ppszDestEnd) + if (ppszDestEnd) { *ppszDestEnd = pszDestEnd; } @@ -2982,7 +2401,7 @@ STRSAFEAPI StringCopyExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, co // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) || // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); - + // only accept valid flags if (dwFlags & (~STRSAFE_VALID_FLAGS)) { @@ -3037,7 +2456,7 @@ STRSAFEAPI StringCopyExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, co *pszDestEnd++= *pszSrc++; cchRemaining--; } - + if (cchRemaining > 0) { if (dwFlags & STRSAFE_FILL_BEHIND_NULL) @@ -3066,7 +2485,7 @@ STRSAFEAPI StringCopyExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, co if (dwFlags & STRSAFE_FILL_ON_FAILURE) { memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); - + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) { pszDestEnd = pszDest; @@ -3098,7 +2517,7 @@ STRSAFEAPI StringCopyExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, co if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) { - if (ppszDestEnd) + if (ppszDestEnd) { *ppszDestEnd = pszDestEnd; } @@ -3182,7 +2601,7 @@ STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, co // ASSERT(cbDest == (cchDest * sizeof(char)) || // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); - + // only accept valid flags if (dwFlags & (~STRSAFE_VALID_FLAGS)) { @@ -3238,7 +2657,7 @@ STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, co cchRemaining--; cchSrc--; } - + if (cchRemaining > 0) { if (dwFlags & STRSAFE_FILL_BEHIND_NULL) @@ -3267,7 +2686,7 @@ STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, co if (dwFlags & STRSAFE_FILL_ON_FAILURE) { memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); - + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) { pszDestEnd = pszDest; @@ -3299,7 +2718,7 @@ STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, co if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) { - if (ppszDestEnd) + if (ppszDestEnd) { *ppszDestEnd = pszDestEnd; } @@ -3321,7 +2740,7 @@ STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, c // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) || // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); - + // only accept valid flags if (dwFlags & (~STRSAFE_VALID_FLAGS)) { @@ -3377,7 +2796,7 @@ STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, c cchRemaining--; cchSrc--; } - + if (cchRemaining > 0) { if (dwFlags & STRSAFE_FILL_BEHIND_NULL) @@ -3406,7 +2825,7 @@ STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, c if (dwFlags & STRSAFE_FILL_ON_FAILURE) { memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); - + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) { pszDestEnd = pszDest; @@ -3438,7 +2857,7 @@ STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, c if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) { - if (ppszDestEnd) + if (ppszDestEnd) { *ppszDestEnd = pszDestEnd; } @@ -3576,7 +2995,7 @@ STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, cons } } } - + if (FAILED(hr)) { if (pszDest) @@ -3619,7 +3038,7 @@ STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, cons if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) { - if (ppszDestEnd) + if (ppszDestEnd) { *ppszDestEnd = pszDestEnd; } @@ -3719,7 +3138,7 @@ STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, con pszSrc, &pszDestEnd, &cchRemaining, - dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); } } } @@ -3733,7 +3152,7 @@ STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, con if (dwFlags & STRSAFE_FILL_ON_FAILURE) { memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); - + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) { pszDestEnd = pszDest; @@ -3765,7 +3184,7 @@ STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, con if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) { - if (ppszDestEnd) + if (ppszDestEnd) { *ppszDestEnd = pszDestEnd; } @@ -3792,7 +3211,7 @@ STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, cchDest - cchDestCurrent, pszSrc, cchMaxAppend); - } + } return hr; } diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacros.inc b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacros.inc index f553840..18ed49e 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacros.inc +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacros.inc @@ -10,7 +10,7 @@ #define LOCAL_LABEL(name) L##name #else #define C_FUNC(name) name -#if defined(_AMD64_) || defined(_X86_) +#if defined(HOST_AMD64) || defined(HOST_X86) #define EXTERNAL_C_FUNC(name) C_FUNC(name)@plt #else #define EXTERNAL_C_FUNC(name) C_FUNC(name) @@ -20,6 +20,8 @@ #if defined(__APPLE__) #define C_PLTFUNC(name) _##name +#elif defined(HOST_ARM64) +#define C_PLTFUNC(name) name #else #define C_PLTFUNC(name) name@PLT #endif @@ -32,12 +34,12 @@ .equiv \New, \Old .endm -#if defined(_X86_) +#if defined(HOST_X86) #include "unixasmmacrosx86.inc" -#elif defined(_AMD64_) +#elif defined(HOST_AMD64) #include "unixasmmacrosamd64.inc" -#elif defined(_ARM_) +#elif defined(HOST_ARM) #include "unixasmmacrosarm.inc" -#elif defined(_ARM64_) +#elif defined(HOST_ARM64) #include "unixasmmacrosarm64.inc" #endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosamd64.inc b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosamd64.inc index 040ade1..e1b4a95 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosamd64.inc +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosamd64.inc @@ -133,16 +133,16 @@ C_FUNC(\Name\()_End): .macro save_xmm128_postrsp Reg, Offset __Offset = \Offset movdqa xmmword ptr [rsp + __Offset], \Reg - // NOTE: We cannot use ".cfi_rel_offset \Reg, __Offset" here, + // NOTE: We cannot use ".cfi_rel_offset \Reg, __Offset" here, // the xmm registers are not supported by the libunwind .endm .macro restore_xmm128 Reg, ofs __Offset = \ofs movdqa \Reg, xmmword ptr [rsp + __Offset] - // NOTE: We cannot use ".cfi_restore \Reg" here, + // NOTE: We cannot use ".cfi_restore \Reg" here, // the xmm registers are not supported by the libunwind - + .endm .macro PUSH_CALLEE_SAVED_REGISTERS @@ -273,7 +273,7 @@ C_FUNC(\Name\()_End): .macro PROLOG_WITH_TRANSITION_BLOCK extraLocals = 0, stackAllocOnEntry = 0, stackAllocSpill1, stackAllocSpill2, stackAllocSpill3 set_cfa_register rsp, 8 - + __PWTB_FloatArgumentRegisters = \extraLocals .if ((__PWTB_FloatArgumentRegisters % 16) != 0) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosarm.inc b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosarm.inc index e4a3658..fcf9069 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosarm.inc +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosarm.inc @@ -170,7 +170,7 @@ C_FUNC(\Name\()_End): .endif CHECK_STACK_ALIGNMENT - + END_PROLOGUE .endm diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosarm64.inc b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosarm64.inc index 6db1f24..f13bb7a 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosarm64.inc +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosarm64.inc @@ -83,7 +83,7 @@ C_FUNC(\Name\()_End): .macro EPILOG_RESTORE_REG reg, ofs ldr \reg, [sp, \ofs] - .cfi_restore \reg1 + .cfi_restore \reg .endm .macro EPILOG_RESTORE_REG_PAIR reg1, reg2, ofs diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosx86.inc b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosx86.inc index 7730505..ae4ad14 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosx86.inc +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/inc/unixasmmacrosx86.inc @@ -110,7 +110,7 @@ C_FUNC(\Name\()_End): .macro CHECK_STACK_ALIGNMENT #ifdef _DEBUG - test esp, 0Fh + test esp, 0x0F je 0f int3 0: diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/corerror/makecorerror.bat b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/corerror/makecorerror.bat new file mode 100644 index 0000000..7e5d6e8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/corerror/makecorerror.bat @@ -0,0 +1,11 @@ +@if "%_echo%"=="" echo off +REM Licensed to the .NET Foundation under one or more agreements. +REM The .NET Foundation licenses this file to you under the MIT license. +REM See the LICENSE file in the project root for more information. +setlocal + +csc ..\..\..\inc\genheaders.cs + +genheaders.exe ..\..\..\inc\corerror.xml ..\inc\corerror.h mscorurt.rc + +del genheaders.exe diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/corerror/mscorurt.rc b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/corerror/mscorurt.rc new file mode 100644 index 0000000..d4a3a39 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/corerror/mscorurt.rc @@ -0,0 +1,333 @@ +// 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. + +STRINGTABLE DISCARDABLE +BEGIN + MSG_FOR_URT_HR(CORDBG_S_AT_END_OF_STACK) "The stack walk has reached the end of the stack. There are no more frames to walk." + MSG_FOR_URT_HR(CEE_E_CVTRES_NOT_FOUND) "cvtres.exe not found." + MSG_FOR_URT_HR(COR_E_TYPEUNLOADED) "Type has been unloaded." + MSG_FOR_URT_HR(COR_E_APPDOMAINUNLOADED) "Attempted to access an unloaded appdomain." + MSG_FOR_URT_HR(COR_E_CANNOTUNLOADAPPDOMAIN) "Error while unloading appdomain." + MSG_FOR_URT_HR(MSEE_E_ASSEMBLYLOADINPROGRESS) "Assembly is still being loaded." + MSG_FOR_URT_HR(COR_E_ASSEMBLYEXPECTED) "The module was expected to contain an assembly manifest." + MSG_FOR_URT_HR(COR_E_FIXUPSINEXE) "Attempt to load an unverifiable executable with fixups (IAT with more than 2 sections or a TLS section.)" + MSG_FOR_URT_HR(COR_E_NEWER_RUNTIME) "This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded." + MSG_FOR_URT_HR(COR_E_MULTIMODULEASSEMBLIESDIALLOWED) "The module cannot be loaded because only single file assemblies are supported." + MSG_FOR_URT_HR(HOST_E_DEADLOCK) "Host detected a deadlock on a blocking operation." + MSG_FOR_URT_HR(HOST_E_INVALIDOPERATION) "Invalid operation." + MSG_FOR_URT_HR(HOST_E_CLRNOTAVAILABLE) "CLR has been disabled due to unrecoverable error." + MSG_FOR_URT_HR(HOST_E_EXITPROCESS_THREADABORT) "Process exited due to ThreadAbort escalation." + MSG_FOR_URT_HR(HOST_E_EXITPROCESS_ADUNLOAD) "Process exited due to AD Unload escalation." + MSG_FOR_URT_HR(HOST_E_EXITPROCESS_TIMEOUT) "Process exited due to Timeout escalation." + MSG_FOR_URT_HR(HOST_E_EXITPROCESS_OUTOFMEMORY) "Process exited due to OutOfMemory escalation." + MSG_FOR_URT_HR(COR_E_MODULE_HASH_CHECK_FAILED) "The check of the module's hash failed." + MSG_FOR_URT_HR(FUSION_E_REF_DEF_MISMATCH) "The located assembly's manifest definition does not match the assembly reference." + MSG_FOR_URT_HR(FUSION_E_INVALID_PRIVATE_ASM_LOCATION) "The private assembly was located outside the appbase directory." + MSG_FOR_URT_HR(FUSION_E_ASM_MODULE_MISSING) "A module specified in the manifest was not found." + MSG_FOR_URT_HR(FUSION_E_PRIVATE_ASM_DISALLOWED) "A strongly-named assembly is required." + MSG_FOR_URT_HR(FUSION_E_SIGNATURE_CHECK_FAILED) "Strong name signature could not be verified. The assembly may have been tampered with, or it was delay signed but not fully signed with the correct private key." + MSG_FOR_URT_HR(FUSION_E_INVALID_NAME) "The given assembly name or codebase was invalid." + MSG_FOR_URT_HR(FUSION_E_CODE_DOWNLOAD_DISABLED) "HTTP download of assemblies has been disabled for this appdomain." + MSG_FOR_URT_HR(FUSION_E_HOST_GAC_ASM_MISMATCH) "Assembly in host store has a different signature than assembly in GAC." + MSG_FOR_URT_HR(FUSION_E_LOADFROM_BLOCKED) "LoadFrom(), LoadFile(), Load(byte[]) and LoadModule() have been disabled by the host." + MSG_FOR_URT_HR(FUSION_E_CACHEFILE_FAILED) "Failed to add file to AppDomain cache." + MSG_FOR_URT_HR(FUSION_E_APP_DOMAIN_LOCKED) "The requested assembly version conflicts with what is already bound in the app domain or specified in the manifest." + MSG_FOR_URT_HR(FUSION_E_CONFIGURATION_ERROR) "The requested assembly name was neither found in the GAC nor in the manifest or the manifest's specified location is wrong." + MSG_FOR_URT_HR(FUSION_E_MANIFEST_PARSE_ERROR) "Unexpected error while parsing the specified manifest." + MSG_FOR_URT_HR(COR_E_LOADING_REFERENCE_ASSEMBLY) "Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context." + MSG_FOR_URT_HR(COR_E_NI_AND_RUNTIME_VERSION_MISMATCH) "The native image could not be loaded, because it was generated for use by a different version of the runtime." + MSG_FOR_URT_HR(COR_E_LOADING_WINMD_REFERENCE_ASSEMBLY) "Contract Windows Runtime assemblies cannot be loaded for execution. Make sure your application only contains non-contract Windows Runtime assemblies." + MSG_FOR_URT_HR(COR_E_AMBIGUOUSIMPLEMENTATION) "Ambiguous implementation found." + MSG_FOR_URT_HR(CLDB_E_FILE_BADREAD) "Error occurred during a read." + MSG_FOR_URT_HR(CLDB_E_FILE_BADWRITE) "Error occurred during a write." + MSG_FOR_URT_HR(CLDB_E_FILE_OLDVER) "Old version error." + MSG_FOR_URT_HR(CLDB_E_SMDUPLICATE) "Create of shared memory failed. A memory mapping of the same name already exists." + MSG_FOR_URT_HR(CLDB_E_NO_DATA) "No .CLB data in the memory or stream." + MSG_FOR_URT_HR(CLDB_E_INCOMPATIBLE) "Importing scope is not compatible with the emitting scope." + MSG_FOR_URT_HR(CLDB_E_FILE_CORRUPT) "File is corrupt." + MSG_FOR_URT_HR(CLDB_E_BADUPDATEMODE) "Cannot open a incrementally build scope for full update." + MSG_FOR_URT_HR(CLDB_E_INDEX_NOTFOUND) "Index not found." + MSG_FOR_URT_HR(CLDB_E_RECORD_NOTFOUND) "Record not found on lookup." + MSG_FOR_URT_HR(CLDB_E_RECORD_OUTOFORDER) "Record is emitted out of order." + MSG_FOR_URT_HR(CLDB_E_TOO_BIG) "A blob or string was too big." + MSG_FOR_URT_HR(META_E_INVALID_TOKEN_TYPE) "A token of the wrong type passed to a metadata function." + MSG_FOR_URT_HR(TLBX_E_LIBNOTREGISTERED) "Typelib export: Type library is not registered." + MSG_FOR_URT_HR(META_E_BADMETADATA) "Merge: Inconsistency in meta data import scope." + MSG_FOR_URT_HR(META_E_BAD_SIGNATURE) "Bad binary signature." + MSG_FOR_URT_HR(META_E_BAD_INPUT_PARAMETER) "Bad input parameters." + MSG_FOR_URT_HR(META_E_CANNOTRESOLVETYPEREF) "Cannot resolve typeref." + MSG_FOR_URT_HR(META_E_STRINGSPACE_FULL) "No logical space left to create more user strings." + MSG_FOR_URT_HR(META_E_HAS_UNMARKALL) "Unmark all has been called already." + MSG_FOR_URT_HR(META_E_MUST_CALL_UNMARKALL) "Must call UnmarkAll first before marking." + MSG_FOR_URT_HR(META_E_CA_INVALID_TARGET) "Known custom attribute on invalid target." + MSG_FOR_URT_HR(META_E_CA_INVALID_VALUE) "Known custom attribute had invalid value." + MSG_FOR_URT_HR(META_E_CA_INVALID_BLOB) "Known custom attribute blob has bad format." + MSG_FOR_URT_HR(META_E_CA_REPEATED_ARG) "Known custom attribute blob has repeated named argument." + MSG_FOR_URT_HR(META_E_CA_UNKNOWN_ARGUMENT) "Known custom attribute named argument not recognized." + MSG_FOR_URT_HR(META_E_CA_UNEXPECTED_TYPE) "Known attribute parser found unexpected type." + MSG_FOR_URT_HR(META_E_CA_INVALID_ARGTYPE) "Known attribute parser only handles fields, not properties." + MSG_FOR_URT_HR(META_E_CA_INVALID_ARG_FOR_TYPE) "Known attribute parser found an argument that is invalid for the object it is applied to." + MSG_FOR_URT_HR(META_E_CA_INVALID_UUID) "The format of the UUID was invalid." + MSG_FOR_URT_HR(META_E_CA_INVALID_MARSHALAS_FIELDS) "The MarshalAs attribute has fields set that are not valid for the specified unmanaged type." + MSG_FOR_URT_HR(META_E_CA_NT_FIELDONLY) "The specified unmanaged type is only valid on fields." + MSG_FOR_URT_HR(META_E_CA_NEGATIVE_PARAMINDEX) "The parameter index cannot be negative." + MSG_FOR_URT_HR(META_E_CA_NEGATIVE_CONSTSIZE) "The constant size cannot be negative." + MSG_FOR_URT_HR(META_E_CA_FIXEDSTR_SIZE_REQUIRED) "A fixed string requires a size." + MSG_FOR_URT_HR(META_E_CA_CUSTMARSH_TYPE_REQUIRED) "A custom marshaler requires the custom marshaler type." + MSG_FOR_URT_HR(META_E_NOT_IN_ENC_MODE) "SaveDelta was called without being in EnC mode." + MSG_FOR_URT_HR(META_E_CA_BAD_FRIENDS_ARGS) "InternalsVisibleTo can't have a version, culture, or processor architecture." + MSG_FOR_URT_HR(VLDTR_E_RID_OUTOFRANGE) "Rid is out of range." + MSG_FOR_URT_HR(VLDTR_E_STRING_INVALID) "String offset is invalid." + MSG_FOR_URT_HR(VLDTR_E_GUID_INVALID) "GUID offset is invalid." + MSG_FOR_URT_HR(VLDTR_E_BLOB_INVALID) "Blob offset if invalid." + MSG_FOR_URT_HR(VLDTR_E_MR_BADCALLINGCONV) "MemberRef has invalid calling convention." + MSG_FOR_URT_HR(VLDTR_E_SIGNULL) "Signature specified is zero-sized." + MSG_FOR_URT_HR(VLDTR_E_MD_BADCALLINGCONV) "Method signature has invalid calling convention." + MSG_FOR_URT_HR(VLDTR_E_MD_THISSTATIC) "Method is marked static but has HASTHIS/EXPLICITTHIS set on the calling convention." + MSG_FOR_URT_HR(VLDTR_E_MD_NOTTHISNOTSTATIC) "Method is not marked static but is not HASTHIS or EXPLICITTHIS." + MSG_FOR_URT_HR(VLDTR_E_MD_NOARGCNT) "Method signature is missing the argument count." + MSG_FOR_URT_HR(VLDTR_E_SIG_MISSELTYPE) "Signature missing element type." + MSG_FOR_URT_HR(VLDTR_E_SIG_MISSTKN) "Signature missing token." + MSG_FOR_URT_HR(VLDTR_E_SIG_TKNBAD) "Signature has bad token." + MSG_FOR_URT_HR(VLDTR_E_SIG_MISSFPTR) "Signature is missing function pointer." + MSG_FOR_URT_HR(VLDTR_E_SIG_MISSFPTRARGCNT) "Signature has function pointer missing argument count." + MSG_FOR_URT_HR(VLDTR_E_SIG_MISSRANK) "Signature is missing rank specification." + MSG_FOR_URT_HR(VLDTR_E_SIG_MISSNSIZE) "Signature is missing count of sized dimensions." + MSG_FOR_URT_HR(VLDTR_E_SIG_MISSSIZE) "Signature is missing size of dimension." + MSG_FOR_URT_HR(VLDTR_E_SIG_MISSNLBND) "Signature is missing count of lower bounds." + MSG_FOR_URT_HR(VLDTR_E_SIG_MISSLBND) "Signature is missing a lower bound." + MSG_FOR_URT_HR(VLDTR_E_SIG_BADELTYPE) "Signature has bad element type." + MSG_FOR_URT_HR(VLDTR_E_TD_ENCLNOTNESTED) "TypeDef not nested has encloser." + MSG_FOR_URT_HR(VLDTR_E_FMD_PINVOKENOTSTATIC) "Field or method is PInvoke but is not marked Static." + MSG_FOR_URT_HR(VLDTR_E_SIG_SENTINMETHODDEF) "E_T_SENTINEL in MethodDef signature." + MSG_FOR_URT_HR(VLDTR_E_SIG_SENTMUSTVARARG) "E_T_SENTINEL <=> VARARG." + MSG_FOR_URT_HR(VLDTR_E_SIG_MULTSENTINELS) "Multiple E_T_SENTINELs." + MSG_FOR_URT_HR(VLDTR_E_SIG_MISSARG) "Signature missing argument." + MSG_FOR_URT_HR(VLDTR_E_SIG_BYREFINFIELD) "Field of ByRef type." + MSG_FOR_URT_HR(CORDBG_E_UNRECOVERABLE_ERROR) "Unrecoverable API error." + MSG_FOR_URT_HR(CORDBG_E_PROCESS_TERMINATED) "Process was terminated." + MSG_FOR_URT_HR(CORDBG_E_PROCESS_NOT_SYNCHRONIZED) "Process not synchronized." + MSG_FOR_URT_HR(CORDBG_E_CLASS_NOT_LOADED) "A class is not loaded." + MSG_FOR_URT_HR(CORDBG_E_IL_VAR_NOT_AVAILABLE) "An IL variable is not available at the current native IP." + MSG_FOR_URT_HR(CORDBG_E_BAD_REFERENCE_VALUE) "A reference value was found to be bad during dereferencing." + MSG_FOR_URT_HR(CORDBG_E_FIELD_NOT_AVAILABLE) "A field in a class is not available, because the runtime optimized it away." + MSG_FOR_URT_HR(CORDBG_E_NON_NATIVE_FRAME) "'Native-frame-only' operation on non-native frame." + MSG_FOR_URT_HR(CORDBG_E_CODE_NOT_AVAILABLE) "The code is currently unavailable." + MSG_FOR_URT_HR(CORDBG_E_FUNCTION_NOT_IL) "Attempt to get a ICorDebugFunction for a function that is not IL." + MSG_FOR_URT_HR(CORDBG_E_CANT_SET_IP_INTO_FINALLY) "SetIP is not possible because SetIP would move EIP from outside of an exception handling finally clause to a point inside of one." + MSG_FOR_URT_HR(CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY) "SetIP is not possible because it would move EIP from within an exception handling finally clause to a point outside of one." + MSG_FOR_URT_HR(CORDBG_E_CANT_SET_IP_INTO_CATCH) "SetIP is not possible, because SetIP would move EIP from outside of an exception handling catch clause to a point inside of one." + MSG_FOR_URT_HR(CORDBG_E_SET_IP_NOT_ALLOWED_ON_NONLEAF_FRAME) "SetIP cannot be done on any frame except the leaf frame." + MSG_FOR_URT_HR(CORDBG_E_SET_IP_IMPOSSIBLE) "SetIP is not allowed." + MSG_FOR_URT_HR(CORDBG_E_FUNC_EVAL_BAD_START_POINT) "Func eval cannot work. Bad starting point." + MSG_FOR_URT_HR(CORDBG_E_INVALID_OBJECT) "This object value is no longer valid." + MSG_FOR_URT_HR(CORDBG_E_FUNC_EVAL_NOT_COMPLETE) "CordbEval::GetResult called before func eval has finished." + MSG_FOR_URT_HR(CORDBG_E_STATIC_VAR_NOT_AVAILABLE) "A static variable is not available because it has not been initialized yet." + MSG_FOR_URT_HR(CORDBG_E_CANT_SETIP_INTO_OR_OUT_OF_FILTER) "SetIP cannot leave or enter a filter." + MSG_FOR_URT_HR(CORDBG_E_CANT_CHANGE_JIT_SETTING_FOR_ZAP_MODULE) "JIT settings for ZAP modules cannot be changed." + MSG_FOR_URT_HR(CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY_ON_WIN64) "SetIP is not possible because it would move EIP from within a finally clause to a point outside of one on this platforms." + MSG_FOR_URT_HR(CORDBG_E_CANT_SET_IP_OUT_OF_CATCH_ON_WIN64) "SetIP is not possible because it would move EIP from within a catch clause to a point outside of one on this platforms." + MSG_FOR_URT_HR(CORDBG_E_CANT_SET_TO_JMC) "Cannot use JMC on this code (likely wrong JIT settings)." + MSG_FOR_URT_HR(CORDBG_E_NO_CONTEXT_FOR_INTERNAL_FRAME) "Internal frame markers have no associated context." + MSG_FOR_URT_HR(CORDBG_E_NOT_CHILD_FRAME) "The current frame is not a child frame." + MSG_FOR_URT_HR(CORDBG_E_NON_MATCHING_CONTEXT) "The provided CONTEXT does not match the specified thread." + MSG_FOR_URT_HR(CORDBG_E_PAST_END_OF_STACK) "The stackwalker is now past the end of stack. No information is available." + MSG_FOR_URT_HR(CORDBG_E_FUNC_EVAL_CANNOT_UPDATE_REGISTER_IN_NONLEAF_FRAME) "Func eval cannot update a variable stored in a register on a non-leaf frame. The most likely cause is that such a variable is passed as a ref/out argument." + MSG_FOR_URT_HR(CORDBG_E_BAD_THREAD_STATE) "The state of the thread is invalid." + MSG_FOR_URT_HR(CORDBG_E_DEBUGGER_ALREADY_ATTACHED) "This process has already been attached." + MSG_FOR_URT_HR(CORDBG_E_SUPERFLOUS_CONTINUE) "Returned from a call to Continue that was not matched with a stopping event." + MSG_FOR_URT_HR(CORDBG_E_SET_VALUE_NOT_ALLOWED_ON_NONLEAF_FRAME) "Cannot perfrom SetValue on non-leaf frames." + MSG_FOR_URT_HR(CORDBG_E_ENC_MODULE_NOT_ENC_ENABLED) "Tried to do Edit and Continue on a module that was not started in Edit and Continue mode." + MSG_FOR_URT_HR(CORDBG_E_SET_IP_NOT_ALLOWED_ON_EXCEPTION) "SetIP cannot be done on any exception." + MSG_FOR_URT_HR(CORDBG_E_VARIABLE_IS_ACTUALLY_LITERAL) "The 'variable' does not exist because it is a literal optimized away by the compiler." + MSG_FOR_URT_HR(CORDBG_E_PROCESS_DETACHED) "Process has been detached." + MSG_FOR_URT_HR(CORDBG_E_ENC_CANT_ADD_FIELD_TO_VALUE_OR_LAYOUT_CLASS) "Adding a field to a value or layout class is prohibited." + MSG_FOR_URT_HR(CORDBG_E_FIELD_NOT_STATIC) "GetStaticFieldValue called on a non-static field." + MSG_FOR_URT_HR(CORDBG_E_FIELD_NOT_INSTANCE) "Returned if someone tries to call GetStaticFieldValue on a non-instance field." + MSG_FOR_URT_HR(CORDBG_E_ENC_JIT_CANT_UPDATE) "The JIT is unable to update the method." + MSG_FOR_URT_HR(CORDBG_E_ENC_INTERNAL_ERROR) "Internal Runtime Error while doing Edit-and-Continue." + MSG_FOR_URT_HR(CORDBG_E_ENC_HANGING_FIELD) "The field was added via Edit and Continue after the class was loaded." + MSG_FOR_URT_HR(CORDBG_E_MODULE_NOT_LOADED) "Module not loaded." + MSG_FOR_URT_HR(CORDBG_E_UNABLE_TO_SET_BREAKPOINT) "Cannot set a breakpoint here." + MSG_FOR_URT_HR(CORDBG_E_DEBUGGING_NOT_POSSIBLE) "Debugging is not possible due to an incompatibility within the CLR implementation." + MSG_FOR_URT_HR(CORDBG_E_KERNEL_DEBUGGER_ENABLED) "A kernel debugger is enabled on the system. User-mode debugging will trap to the kernel debugger." + MSG_FOR_URT_HR(CORDBG_E_KERNEL_DEBUGGER_PRESENT) "A kernel debugger is present on the system. User-mode debugging will trap to the kernel debugger." + MSG_FOR_URT_HR(CORDBG_E_INCOMPATIBLE_PROTOCOL) "The debugger's protocol is incompatible with the debuggee." + MSG_FOR_URT_HR(CORDBG_E_TOO_MANY_PROCESSES) "The debugger can only handle a finite number of debuggees." + MSG_FOR_URT_HR(CORDBG_E_INTEROP_NOT_SUPPORTED) "Interop debugging is not supported." + MSG_FOR_URT_HR(CORDBG_E_NO_REMAP_BREAKPIONT) "Cannot call RemapFunction until have received RemapBreakpoint." + MSG_FOR_URT_HR(CORDBG_E_OBJECT_NEUTERED) "Object is in a zombie state." + MSG_FOR_URT_HR(CORPROF_E_FUNCTION_NOT_COMPILED) "Function not yet compiled." + MSG_FOR_URT_HR(CORPROF_E_DATAINCOMPLETE) "The ID is not fully loaded/defined yet." + MSG_FOR_URT_HR(CORPROF_E_FUNCTION_NOT_IL) "The Method has no associated IL." + MSG_FOR_URT_HR(CORPROF_E_NOT_MANAGED_THREAD) "The thread has never run managed code before." + MSG_FOR_URT_HR(CORPROF_E_CALL_ONLY_FROM_INIT) "The function may only be called during profiler initialization." + MSG_FOR_URT_HR(CORPROF_E_NOT_YET_AVAILABLE) "Requested information is not yet available." + MSG_FOR_URT_HR(CORPROF_E_TYPE_IS_PARAMETERIZED) "The given type is a generic and cannot be used with this method." + MSG_FOR_URT_HR(CORPROF_E_FUNCTION_IS_PARAMETERIZED) "The given function is a generic and cannot be used with this method." + MSG_FOR_URT_HR(SECURITY_E_INCOMPATIBLE_SHARE) "Loading this assembly would produce a different grant set from other instances." + MSG_FOR_URT_HR(SECURITY_E_UNVERIFIABLE) "Unverifiable code failed policy check." + MSG_FOR_URT_HR(SECURITY_E_INCOMPATIBLE_EVIDENCE) "Assembly already loaded without additional security evidence." + MSG_FOR_URT_HR(CORSEC_E_POLICY_EXCEPTION) "PolicyException thrown." + MSG_FOR_URT_HR(CORSEC_E_MIN_GRANT_FAIL) "Failed to grant minimum permission requests." + MSG_FOR_URT_HR(CORSEC_E_NO_EXEC_PERM) "Failed to grant permission to execute." + MSG_FOR_URT_HR(CORSEC_E_XMLSYNTAX) "XML Syntax error." + MSG_FOR_URT_HR(CORSEC_E_INVALID_STRONGNAME) "Strong name validation failed." + MSG_FOR_URT_HR(CORSEC_E_MISSING_STRONGNAME) "Assembly is not strong named." + MSG_FOR_URT_HR(CORSEC_E_INVALID_IMAGE_FORMAT) "Invalid assembly file format." + MSG_FOR_URT_HR(CORSEC_E_INVALID_PUBLICKEY) "Invalid assembly public key." + MSG_FOR_URT_HR(CORSEC_E_SIGNATURE_MISMATCH) "Signature size mismatch." + MSG_FOR_URT_HR(CORSEC_E_CRYPTO) "Failure during Cryptographic operation." + MSG_FOR_URT_HR(CORSEC_E_CRYPTO_UNEX_OPER) "Unexpected Cryptographic operation." + MSG_FOR_URT_HR(CORSECATTR_E_BAD_ACTION) "Invalid security action code." + MSG_FOR_URT_HR(COR_E_EXCEPTION) "General Exception" + MSG_FOR_URT_HR(COR_E_SYSTEM) "System.Exception" + MSG_FOR_URT_HR(COR_E_ARGUMENTOUTOFRANGE) "An argument was out of its legal range." + MSG_FOR_URT_HR(COR_E_ARRAYTYPEMISMATCH) "Attempted to store an object of the wrong type in an array." + MSG_FOR_URT_HR(COR_E_CONTEXTMARSHAL) "Attempted to marshal an object across a context boundary." + MSG_FOR_URT_HR(COR_E_TIMEOUT) "Operation timed out." + MSG_FOR_URT_HR(COR_E_EXECUTIONENGINE) "Internal CLR error." + MSG_FOR_URT_HR(COR_E_FIELDACCESS) "Access to this field is denied." + MSG_FOR_URT_HR(COR_E_INDEXOUTOFRANGE) "Array subscript out of range." + MSG_FOR_URT_HR(COR_E_INVALIDOPERATION) "An operation is not legal in the current state." + MSG_FOR_URT_HR(COR_E_SECURITY) "An error relating to security occurred." + MSG_FOR_URT_HR(COR_E_SERIALIZATION) "An error relating to serialization occurred." + MSG_FOR_URT_HR(COR_E_VERIFICATION) "A verification failure has occurred." + MSG_FOR_URT_HR(COR_E_METHODACCESS) "Access to this method is denied." + MSG_FOR_URT_HR(COR_E_MISSINGFIELD) "Field does not exist." + MSG_FOR_URT_HR(COR_E_MISSINGMEMBER) "Member does not exist." + MSG_FOR_URT_HR(COR_E_MISSINGMETHOD) "Method does not exist." + MSG_FOR_URT_HR(COR_E_MULTICASTNOTSUPPORTED) "Attempt to combine delegates that are not multicast." + MSG_FOR_URT_HR(COR_E_NOTSUPPORTED) "Operation is not supported." + MSG_FOR_URT_HR(COR_E_OVERFLOW) "Arithmetic, casting or conversion operation overflowed or underflowed." + MSG_FOR_URT_HR(COR_E_RANK) "An array has the wrong number of dimensions for a particular operation." + MSG_FOR_URT_HR(COR_E_SYNCHRONIZATIONLOCK) "This operation must be called from a synchronized block." + MSG_FOR_URT_HR(COR_E_THREADINTERRUPTED) "Thread was interrupted from a waiting state." + MSG_FOR_URT_HR(COR_E_MEMBERACCESS) "Access to this member is denied." + MSG_FOR_URT_HR(COR_E_THREADSTATE) "Thread is in an invalid state for this operation." + MSG_FOR_URT_HR(COR_E_THREADSTOP) "Thread is stopping." + MSG_FOR_URT_HR(COR_E_TYPELOAD) "Could not find or load a type." + MSG_FOR_URT_HR(COR_E_ENTRYPOINTNOTFOUND) "Could not find the specified DllImport entrypoint." + MSG_FOR_URT_HR(COR_E_DLLNOTFOUND) "Could not find the specified DllImport Dll." + MSG_FOR_URT_HR(COR_E_INVALIDCOMOBJECT) "An invalid __ComObject has been used." + MSG_FOR_URT_HR(COR_E_NOTFINITENUMBER) "Not a Number." + MSG_FOR_URT_HR(COR_E_DUPLICATEWAITOBJECT) "An object appears more than once in the wait objects array." + MSG_FOR_URT_HR(COR_E_SEMAPHOREFULL) "Reached maximum count for semaphore." + MSG_FOR_URT_HR(COR_E_WAITHANDLECANNOTBEOPENED) "No semaphore of the given name exists." + MSG_FOR_URT_HR(COR_E_ABANDONEDMUTEX) "The wait completed due to an abandoned mutex." + MSG_FOR_URT_HR(COR_E_THREADABORTED) "Thread has aborted." + MSG_FOR_URT_HR(COR_E_INVALIDOLEVARIANTTYPE) "OLE Variant has an invalid type." + MSG_FOR_URT_HR(COR_E_MISSINGMANIFESTRESOURCE) "An expected resource in the assembly manifest was missing." + MSG_FOR_URT_HR(COR_E_SAFEARRAYTYPEMISMATCH) "A mismatch has occurred between the runtime type of the array and the sub type recorded in the metadata." + MSG_FOR_URT_HR(COR_E_TYPEINITIALIZATION) "Uncaught exception during type initialization." + MSG_FOR_URT_HR(COR_E_MARSHALDIRECTIVE) "Invalid marshaling directives." + MSG_FOR_URT_HR(COR_E_MISSINGSATELLITEASSEMBLY) "An expected satellite assembly containing the ultimate fallback resources for a given culture was not found or could not be loaded." + MSG_FOR_URT_HR(COR_E_FORMAT) "The format of one argument does not meet the contract of the method." + MSG_FOR_URT_HR(COR_E_SAFEARRAYRANKMISMATCH) "A mismatch has occurred between the runtime rank of the array and the rank recorded in the metadata." + MSG_FOR_URT_HR(COR_E_PLATFORMNOTSUPPORTED) "Operation is not supported on this platform." + MSG_FOR_URT_HR(COR_E_INVALIDPROGRAM) "Invalid IL or CLR metadata." + MSG_FOR_URT_HR(COR_E_OPERATIONCANCELED) "The operation was cancelled." + MSG_FOR_URT_HR(COR_E_DATAMISALIGNED) "A datatype misalignment was detected in a load or store instruction." + MSG_FOR_URT_HR(COR_E_CODECONTRACTFAILED) "A managed code contract (ie, precondition, postcondition, invariant, or assert) failed." + MSG_FOR_URT_HR(COR_E_TYPEACCESS) "Access to this type is denied." + MSG_FOR_URT_HR(COR_E_ACCESSING_CCW) "Fail to access a CCW because the corresponding managed object is already collected." + MSG_FOR_URT_HR(COR_E_KEYNOTFOUND) "The given key was not present in the dictionary." + MSG_FOR_URT_HR(COR_E_INSUFFICIENTEXECUTIONSTACK) "Insufficient stack to continue executing the program safely. This can happen from having too many functions on the call stack or function on the stack using too much stack space." + MSG_FOR_URT_HR(COR_E_APPLICATION) "Application exception" + MSG_FOR_URT_HR(COR_E_INVALIDFILTERCRITERIA) "The given filter criteria does not match the filter content." + MSG_FOR_URT_HR(COR_E_REFLECTIONTYPELOAD) "Could not find or load a specific class that was requested through Reflection." + MSG_FOR_URT_HR(COR_E_TARGET) "Attempt to invoke non-static method with a null Object." + MSG_FOR_URT_HR(COR_E_TARGETINVOCATION) "Uncaught exception thrown by method called through Reflection." + MSG_FOR_URT_HR(COR_E_CUSTOMATTRIBUTEFORMAT) "Custom attribute has invalid format." + MSG_FOR_URT_HR(COR_E_IO) "Error during managed I/O." + MSG_FOR_URT_HR(COR_E_FILELOAD) "Could not find or load a specific file." + MSG_FOR_URT_HR(COR_E_OBJECTDISPOSED) "The object has already been disposed." + MSG_FOR_URT_HR(COR_E_FAILFAST) "Runtime operation halted by call to System.Environment.FailFast()." + MSG_FOR_URT_HR(COR_E_HOSTPROTECTION) "The host has forbidden this operation." + MSG_FOR_URT_HR(COR_E_ILLEGAL_REENTRANCY) "Attempted to call into managed code when executing inside a low level extensibility point." + MSG_FOR_URT_HR(CLR_E_SHIM_RUNTIMELOAD) "Failed to load the runtime." + MSG_FOR_URT_HR(CLR_E_SHIM_LEGACYRUNTIMEALREADYBOUND) "A runtime has already been bound for legacy activation policy use." + MSG_FOR_URT_HR(VER_E_FIELD_SIG) "[field sig]" + MSG_FOR_URT_HR(VER_E_CIRCULAR_VAR_CONSTRAINTS) "Method parent has circular class type parameter constraints." + MSG_FOR_URT_HR(VER_E_CIRCULAR_MVAR_CONSTRAINTS) "Method has circular method type parameter constraints." + MSG_FOR_URT_HR(VLDTR_E_SIG_BADVOID) "Illegal 'void' in signature." + MSG_FOR_URT_HR(VLDTR_E_GP_ILLEGAL_VARIANT_MVAR) "GenericParam is a method type parameter and must be non-variant." + MSG_FOR_URT_HR(CORDBG_E_THREAD_NOT_SCHEDULED) "Thread is not scheduled. Thus we may not have OSThreadId, handle, or context." + MSG_FOR_URT_HR(CORDBG_E_HANDLE_HAS_BEEN_DISPOSED) "Handle has been disposed." + MSG_FOR_URT_HR(CORDBG_E_NONINTERCEPTABLE_EXCEPTION) "Cannot intercept this exception." + MSG_FOR_URT_HR(CORDBG_E_INTERCEPT_FRAME_ALREADY_SET) "The intercept frame for this exception has already been set." + MSG_FOR_URT_HR(CORDBG_E_NO_NATIVE_PATCH_AT_ADDR) "There is no native patch at the given address." + MSG_FOR_URT_HR(CORDBG_E_MUST_BE_INTEROP_DEBUGGING) "This API is only allowed when interop debugging." + MSG_FOR_URT_HR(CORDBG_E_NATIVE_PATCH_ALREADY_AT_ADDR) "There is already a native patch at the address." + MSG_FOR_URT_HR(CORDBG_E_TIMEOUT) "A wait timed out, likely an indication of deadlock." + MSG_FOR_URT_HR(CORDBG_E_CANT_CALL_ON_THIS_THREAD) "Cannot use the API on this thread." + MSG_FOR_URT_HR(CORDBG_E_ENC_INFOLESS_METHOD) "Method was not JIT'd in EnC mode." + MSG_FOR_URT_HR(CORDBG_E_ENC_IN_FUNCLET) "Method is in a callable handler/filter. Cannot increase stack." + MSG_FOR_URT_HR(CORDBG_E_ENC_EDIT_NOT_SUPPORTED) "Attempt to perform unsupported edit." + MSG_FOR_URT_HR(CORDBG_E_NOTREADY) "The LS is not in a good spot to perform the requested operation." + MSG_FOR_URT_HR(CORDBG_E_CANNOT_RESOLVE_ASSEMBLY) "We failed to resolve assembly given an AssemblyRef token. Assembly may be not loaded yet or not a valid token." + MSG_FOR_URT_HR(CORDBG_E_MUST_BE_IN_LOAD_MODULE) "Must be in context of LoadModule callback to perform requested operation." + MSG_FOR_URT_HR(CORDBG_E_CANNOT_BE_ON_ATTACH) "Requested operation cannot be performed during an attach operation." + MSG_FOR_URT_HR(CORDBG_E_NGEN_NOT_SUPPORTED) "NGEN must be supported to perform the requested operation." + MSG_FOR_URT_HR(CORDBG_E_ILLEGAL_SHUTDOWN_ORDER) "Trying to shutdown out of order." + MSG_FOR_URT_HR(CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS) "Debugging fiber mode managed process is not supported." + MSG_FOR_URT_HR(CORDBG_E_MUST_BE_IN_CREATE_PROCESS) "Must be in context of CreateProcess callback to perform requested operation." + MSG_FOR_URT_HR(CORDBG_E_DETACH_FAILED_OUTSTANDING_EVALS) "All outstanding func-evals have not completed, detaching is not allowed at this time." + MSG_FOR_URT_HR(CORDBG_E_DETACH_FAILED_OUTSTANDING_STEPPERS) "All outstanding steppers have not been closed, detaching is not allowed at this time." + MSG_FOR_URT_HR(CORDBG_E_CANT_INTEROP_STEP_OUT) "Cannot have an ICorDebugStepper do a native step-out." + MSG_FOR_URT_HR(CORDBG_E_DETACH_FAILED_OUTSTANDING_BREAKPOINTS) "All outstanding breakpoints have not been closed, detaching is not allowed at this time." + MSG_FOR_URT_HR(CORDBG_E_ILLEGAL_IN_STACK_OVERFLOW) "The operation is illegal because of a stack overflow." + MSG_FOR_URT_HR(CORDBG_E_ILLEGAL_AT_GC_UNSAFE_POINT) "The operation failed because it is a GC unsafe point." + MSG_FOR_URT_HR(CORDBG_E_ILLEGAL_IN_PROLOG) "The operation failed because the thread is in the prolog." + MSG_FOR_URT_HR(CORDBG_E_ILLEGAL_IN_NATIVE_CODE) "The operation failed because the thread is in native code." + MSG_FOR_URT_HR(CORDBG_E_ILLEGAL_IN_OPTIMIZED_CODE) "The operation failed because the thread is in optimized code." + MSG_FOR_URT_HR(CORDBG_E_APPDOMAIN_MISMATCH) "A supplied object or type belongs to the wrong AppDomain." + MSG_FOR_URT_HR(CORDBG_E_CONTEXT_UNVAILABLE) "The thread's context is not available." + MSG_FOR_URT_HR(CORDBG_E_UNCOMPATIBLE_PLATFORMS) "The operation failed because debuggee and debugger are on incompatible platforms." + MSG_FOR_URT_HR(CORDBG_E_DEBUGGING_DISABLED) "The operation failed because the debugging has been disabled" + MSG_FOR_URT_HR(CORDBG_E_DETACH_FAILED_ON_ENC) "Detach is illegal after an Edit and Continue on a module." + MSG_FOR_URT_HR(CORDBG_E_CURRENT_EXCEPTION_IS_OUTSIDE_CURRENT_EXECUTION_SCOPE) "Cannot intercept the current exception at the specified frame." + MSG_FOR_URT_HR(CORDBG_E_HELPER_MAY_DEADLOCK) "The debugger helper thread cannot obtain the locks it needs to perform this operation." + MSG_FOR_URT_HR(CORDBG_E_MISSING_METADATA) "The operation failed because the debugger could not get the metadata." + MSG_FOR_URT_HR(CORDBG_E_TARGET_INCONSISTENT) "The debuggee is in a corrupt state." + MSG_FOR_URT_HR(CORDBG_E_DETACH_FAILED_OUTSTANDING_TARGET_RESOURCES) "Detach failed because there are outstanding resources in the target." + MSG_FOR_URT_HR(CORDBG_E_TARGET_READONLY) "The debuggee is read-only." + MSG_FOR_URT_HR(CORDBG_E_MISMATCHED_CORWKS_AND_DACWKS_DLLS) "The version of clr.dll in the target does not match the one mscordacwks.dll was built for." + MSG_FOR_URT_HR(CORDBG_E_MODULE_LOADED_FROM_DISK) "Symbols are not supplied for modules loaded from disk." + MSG_FOR_URT_HR(CORDBG_E_SYMBOLS_NOT_AVAILABLE) "The application did not supply symbols when it loaded or created this module, or they are not yet available." + MSG_FOR_URT_HR(CORDBG_E_DEBUG_COMPONENT_MISSING) "A debug component is not installed." + MSG_FOR_URT_HR(CORDBG_E_LIBRARY_PROVIDER_ERROR) "The ICLRDebuggingLibraryProvider callback returned an error or did not provide a valid handle." + MSG_FOR_URT_HR(CORDBG_E_NOT_CLR) "The module at the base address indicated was not recognized as a CLR" + MSG_FOR_URT_HR(CORDBG_E_MISSING_DATA_TARGET_INTERFACE) "The provided data target does not implement the required interfaces for this version of the runtime" + MSG_FOR_URT_HR(CORDBG_E_UNSUPPORTED_DEBUGGING_MODEL) "This debugging model is unsupported by the specified runtime" + MSG_FOR_URT_HR(CORDBG_E_UNSUPPORTED_FORWARD_COMPAT) "The debugger is not designed to support the version of the CLR the debuggee is using." + MSG_FOR_URT_HR(CORDBG_E_UNSUPPORTED_VERSION_STRUCT) "The version struct has an unrecognized value for wStructVersion" + MSG_FOR_URT_HR(CORDBG_E_READVIRTUAL_FAILURE) "A call into a ReadVirtual implementation returned failure" + MSG_FOR_URT_HR(CORDBG_E_VALUE_POINTS_TO_FUNCTION) "The Debugging API doesn't support dereferencing function pointers." + MSG_FOR_URT_HR(CORDBG_E_CORRUPT_OBJECT) "The address provided does not point to a valid managed object." + MSG_FOR_URT_HR(CORDBG_E_GC_STRUCTURES_INVALID) "The GC heap structures are not in a valid state for traversal." + MSG_FOR_URT_HR(CORDBG_E_INVALID_OPCODE) "The specified IL offset or opcode is not supported for this operation." + MSG_FOR_URT_HR(CORDBG_E_UNSUPPORTED) "The specified action is unsupported by this version of the runtime." + MSG_FOR_URT_HR(CORDBG_E_MISSING_DEBUGGER_EXPORTS) "The debuggee memory space does not have the expected debugging export table." + MSG_FOR_URT_HR(CORDBG_E_DATA_TARGET_ERROR) "Failure when calling a data target method." + MSG_FOR_URT_HR(CORDBG_E_NO_IMAGE_AVAILABLE) "Couldn't find a native image." + MSG_FOR_URT_HR(CORDBG_E_UNSUPPORTED_DELEGATE) "The delegate contains a delegate currently not supported by the API." + MSG_FOR_URT_HR(PEFMT_E_64BIT) "File is PE32+." + MSG_FOR_URT_HR(PEFMT_E_32BIT) "File is PE32" + MSG_FOR_URT_HR(NGEN_E_SYS_ASM_NI_MISSING) "NGen cannot proceed because Mscorlib.dll does not have a native image" + MSG_FOR_URT_HR(CLR_E_BIND_ASSEMBLY_VERSION_TOO_LOW) "The bound assembly has a version that is lower than that of the request." + MSG_FOR_URT_HR(CLR_E_BIND_ASSEMBLY_PUBLIC_KEY_MISMATCH) "The assembly version has a public key token that does not match that of the request." + MSG_FOR_URT_HR(CLR_E_BIND_IMAGE_UNAVAILABLE) "The requested image was not found or is unavailable." + MSG_FOR_URT_HR(CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT) "The provided identity format is not recognized." + MSG_FOR_URT_HR(CLR_E_BIND_ASSEMBLY_NOT_FOUND) "A binding for the specified assembly name was not found." + MSG_FOR_URT_HR(CLR_E_BIND_TYPE_NOT_FOUND) "A binding for the specified type name was not found." + MSG_FOR_URT_HR(CLR_E_BIND_SYS_ASM_NI_MISSING) "Could not use native image because Mscorlib.dll is missing a native image" + MSG_FOR_URT_HR(CLR_E_BIND_NI_SECURITY_FAILURE) "Native image was generated in a different trust level than present at runtime" + MSG_FOR_URT_HR(CLR_E_BIND_NI_DEP_IDENTITY_MISMATCH) "Native image identity mismatch with respect to its dependencies" + MSG_FOR_URT_HR(CLR_E_GC_OOM) "Failfast due to an OOM during a GC" + MSG_FOR_URT_HR(CLR_E_GC_BAD_AFFINITY_CONFIG) "GCHeapAffinitizeMask or GCHeapAffinitizeRanges didn't specify any CPUs the current process is affinitized to." + MSG_FOR_URT_HR(CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT) "GCHeapAffinitizeRanges configuration string has invalid format." + MSG_FOR_URT_HR(CLR_E_CROSSGEN_NO_IBC_DATA_FOUND) "Cannot compile using the PartialNgen flag because no IBC data was found." + MSG_FOR_URT_HR(COR_E_BADIMAGEFORMAT) "The format of a DLL or executable being loaded is invalid." +END diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/corerror/readme.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/corerror/readme.txt new file mode 100644 index 0000000..a21a724 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/corerror/readme.txt @@ -0,0 +1,7 @@ +Steps to generate corerror.h for the Unix: + +Open Razzle window +tf edit ..\inc\corerror.h +tf edit mscorurt.rc +makecorerror.bat +tf undo any files that didn't get modified \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrdata_i.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrdata_i.cpp new file mode 100644 index 0000000..f0f6742 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrdata_i.cpp @@ -0,0 +1,102 @@ +// 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. + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.01.0622 */ +/* at Mon Jan 18 19:14:07 2038 + */ +/* Compiler settings for C:/ssd/runtime/src/coreclr/src/inc/clrdata.idl: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + EXTERN_C __declspec(selectany) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif // !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, IID_ICLRDataTarget,0x3E11CCEE,0xD08B,0x43e5,0xAF,0x01,0x32,0x71,0x7A,0x64,0xDA,0x03); + + +MIDL_DEFINE_GUID(IID, IID_ICLRDataTarget2,0x6d05fae3,0x189c,0x4630,0xa6,0xdc,0x1c,0x25,0x1e,0x1c,0x01,0xab); + + +MIDL_DEFINE_GUID(IID, IID_ICLRDataTarget3,0xa5664f95,0x0af4,0x4a1b,0x96,0x0e,0x2f,0x33,0x46,0xb4,0x21,0x4c); + + +MIDL_DEFINE_GUID(IID, IID_ICLRRuntimeLocator,0xb760bf44,0x9377,0x4597,0x8b,0xe7,0x58,0x08,0x3b,0xdc,0x51,0x46); + + +MIDL_DEFINE_GUID(IID, IID_ICLRMetadataLocator,0xaa8fa804,0xbc05,0x4642,0xb2,0xc5,0xc3,0x53,0xed,0x22,0xfc,0x63); + + +MIDL_DEFINE_GUID(IID, IID_ICLRDataEnumMemoryRegionsCallback,0xBCDD6908,0xBA2D,0x4ec5,0x96,0xCF,0xDF,0x4D,0x5C,0xDC,0xB4,0xA4); + + +MIDL_DEFINE_GUID(IID, IID_ICLRDataEnumMemoryRegionsCallback2,0x3721A26F,0x8B91,0x4D98,0xA3,0x88,0xDB,0x17,0xB3,0x56,0xFA,0xDB); + + +MIDL_DEFINE_GUID(IID, IID_ICLRDataEnumMemoryRegions,0x471c35b4,0x7c2f,0x4ef0,0xa9,0x45,0x00,0xf8,0xc3,0x80,0x56,0xf1); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrinternal_i.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrinternal_i.cpp new file mode 100644 index 0000000..7cfb798 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrinternal_i.cpp @@ -0,0 +1,73 @@ +// 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. + + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + EXTERN_C __declspec(selectany) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif // !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, IID_IPrivateManagedExceptionReporting,0xAD76A023,0x332D,0x4298,0x80,0x01,0x07,0xAA,0x93,0x50,0xDC,0xA4); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrprivappxhosting_i.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrprivappxhosting_i.cpp new file mode 100644 index 0000000..c46d033 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrprivappxhosting_i.cpp @@ -0,0 +1,76 @@ +// 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. + + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, IID_ICLRPrivAppXRuntime,0x6D2DF5A4,0xFA3A,0x4481,0x8B,0xA0,0x04,0x22,0xFD,0x21,0x72,0x0F); + + +MIDL_DEFINE_GUID(IID, IID_ICLRPrivAppXDomain,0x6633398E,0x823D,0x4361,0xB3,0x0E,0x82,0x40,0x43,0xBD,0x46,0x86); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrprivbinding_i.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrprivbinding_i.cpp new file mode 100644 index 0000000..3aead62 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/clrprivbinding_i.cpp @@ -0,0 +1,91 @@ +// 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. + + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + EXTERN_C __declspec(selectany) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif // !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, IID_ICLRPrivBinder,0x2601F621,0xE462,0x404C,0xB2,0x99,0x3E,0x1D,0xE7,0x2F,0x85,0x42); + + +MIDL_DEFINE_GUID(IID, IID_ICLRPrivAssembly,0x2601F621,0xE462,0x404C,0xB2,0x99,0x3E,0x1D,0xE7,0x2F,0x85,0x43); + + +MIDL_DEFINE_GUID(IID, IID_ICLRPrivResource,0x2601F621,0xE462,0x404C,0xB2,0x99,0x3E,0x1D,0xE7,0x2F,0x85,0x47); + + +MIDL_DEFINE_GUID(IID, IID_ICLRPrivResourcePath,0x2601F621,0xE462,0x404C,0xB2,0x99,0x3E,0x1D,0xE7,0x2F,0x85,0x44); + + +MIDL_DEFINE_GUID(IID, IID_ICLRPrivResourceAssembly,0x8d2d3cc9,0x1249,0x4ad4,0x97,0x7d,0xb7,0x72,0xbd,0x4e,0x8a,0x94); + + +MIDL_DEFINE_GUID(IID, IID_ICLRPrivAssemblyInfo,0x5653946E,0x800B,0x48B7,0x8B,0x09,0xB1,0xB8,0x79,0xB5,0x4F,0x68); + + +MIDL_DEFINE_GUID(IID, IID_ICLRPrivAssemblyID_WinRT,0x4372D277,0x9906,0x4FED,0xBF,0x53,0x30,0xC0,0xB4,0x01,0x08,0x96); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/cordebug_i.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/cordebug_i.cpp new file mode 100644 index 0000000..d04c21a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/cordebug_i.cpp @@ -0,0 +1,469 @@ +// 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. + + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.01.0622 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + EXTERN_C __declspec(selectany) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif // !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, IID_ICorDebugDataTarget,0xFE06DC28,0x49FB,0x4636,0xA4,0xA3,0xE8,0x0D,0xB4,0xAE,0x11,0x6C); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugStaticFieldSymbol,0xCBF9DA63,0xF68D,0x4BBB,0xA2,0x1C,0x15,0xA4,0x5E,0xAA,0xDF,0x5B); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugInstanceFieldSymbol,0xA074096B,0x3ADC,0x4485,0x81,0xDA,0x68,0xC7,0xA4,0xEA,0x52,0xDB); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugVariableSymbol,0x707E8932,0x1163,0x48D9,0x8A,0x93,0xF5,0xB1,0xF4,0x80,0xFB,0xB7); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugMemoryBuffer,0x677888B3,0xD160,0x4B8C,0xA7,0x3B,0xD7,0x9E,0x6A,0xAA,0x1D,0x13); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugMergedAssemblyRecord,0xFAA8637B,0x3BBE,0x4671,0x8E,0x26,0x3B,0x59,0x87,0x5B,0x92,0x2A); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugSymbolProvider,0x3948A999,0xFD8A,0x4C38,0xA7,0x08,0x8A,0x71,0xE9,0xB0,0x4D,0xBB); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugSymbolProvider2,0xF9801807,0x4764,0x4330,0x9E,0x67,0x4F,0x68,0x50,0x94,0x16,0x5E); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugVirtualUnwinder,0xF69126B7,0xC787,0x4F6B,0xAE,0x96,0xA5,0x69,0x78,0x6F,0xC6,0x70); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugDataTarget2,0x2eb364da,0x605b,0x4e8d,0xb3,0x33,0x33,0x94,0xc4,0x82,0x8d,0x41); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugLoadedModule,0x817F343A,0x6630,0x4578,0x96,0xC5,0xD1,0x1B,0xC0,0xEC,0x5E,0xE2); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugDataTarget3,0xD05E60C3,0x848C,0x4E7D,0x89,0x4E,0x62,0x33,0x20,0xFF,0x6A,0xFA); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugDataTarget4,0xE799DC06,0xE099,0x4713,0xBD,0xD9,0x90,0x6D,0x3C,0xC0,0x2C,0xF2); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugMutableDataTarget,0xA1B8A756,0x3CB6,0x4CCB,0x97,0x9F,0x3D,0xF9,0x99,0x67,0x3A,0x59); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugMetaDataLocator,0x7cef8ba9,0x2ef7,0x42bf,0x97,0x3f,0x41,0x71,0x47,0x4f,0x87,0xd9); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugManagedCallback,0x3d6f5f60,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugManagedCallback3,0x264EA0FC,0x2591,0x49AA,0x86,0x8E,0x83,0x5E,0x65,0x15,0x32,0x3F); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugManagedCallback4,0x322911AE,0x16A5,0x49BA,0x84,0xA3,0xED,0x69,0x67,0x81,0x38,0xA3); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugManagedCallback2,0x250E5EEA,0xDB5C,0x4C76,0xB6,0xF3,0x8C,0x46,0xF1,0x2E,0x32,0x03); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugUnmanagedCallback,0x5263E909,0x8CB5,0x11d3,0xBD,0x2F,0x00,0x00,0xF8,0x08,0x49,0xBD); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebug,0x3d6f5f61,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugRemoteTarget,0xC3ED8383,0x5A49,0x4cf5,0xB4,0xB7,0x01,0x86,0x4D,0x9E,0x58,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugRemote,0xD5EBB8E2,0x7BBE,0x4c1d,0x98,0xA6,0xA3,0xC0,0x4C,0xBD,0xEF,0x64); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebug2,0xECCCCF2E,0xB286,0x4b3e,0xA9,0x83,0x86,0x0A,0x87,0x93,0xD1,0x05); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugController,0x3d6f5f62,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomain,0x3d6f5f63,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomain2,0x096E81D5,0xECDA,0x4202,0x83,0xF5,0xC6,0x59,0x80,0xA9,0xEF,0x75); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugEnum,0xCC7BCB01,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugGuidToTypeEnum,0x6164D242,0x1015,0x4BD6,0x8C,0xBE,0xD0,0xDB,0xD4,0xB8,0x27,0x5A); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomain3,0x8CB96A16,0xB588,0x42E2,0xB7,0x1C,0xDD,0x84,0x9F,0xC2,0xEC,0xCC); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomain4,0xFB99CC40,0x83BE,0x4724,0xAB,0x3B,0x76,0x8E,0x79,0x6E,0xBA,0xC2); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAssembly,0xdf59507c,0xd47a,0x459e,0xbc,0xe2,0x64,0x27,0xea,0xc8,0xfd,0x06); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAssembly2,0x426d1f9e,0x6dd4,0x44c8,0xae,0xc7,0x26,0xcd,0xba,0xf4,0xe3,0x98); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAssembly3,0x76361AB2,0x8C86,0x4FE9,0x96,0xF2,0xF7,0x3D,0x88,0x43,0x57,0x0A); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapEnum,0x76D7DAB8,0xD044,0x11DF,0x9A,0x15,0x7E,0x29,0xDF,0xD7,0x20,0x85); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapSegmentEnum,0xA2FA0F8E,0xD045,0x11DF,0xAC,0x8E,0xCE,0x2A,0xDF,0xD7,0x20,0x85); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugGCReferenceEnum,0x7F3C24D3,0x7E1D,0x4245,0xAC,0x3A,0xF7,0x2F,0x88,0x59,0xC8,0x0C); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess,0x3d6f5f64,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess2,0xAD1B3588,0x0EF0,0x4744,0xA4,0x96,0xAA,0x09,0xA9,0xF8,0x03,0x71); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess3,0x2EE06488,0xC0D4,0x42B1,0xB2,0x6D,0xF3,0x79,0x5E,0xF6,0x06,0xFB); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess5,0x21e9d9c0,0xfcb8,0x11df,0x8c,0xff,0x08,0x00,0x20,0x0c,0x9a,0x66); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugDebugEvent,0x41BD395D,0xDE99,0x48F1,0xBF,0x7A,0xCC,0x0F,0x44,0xA6,0xD2,0x81); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess6,0x11588775,0x7205,0x4CEB,0xA4,0x1A,0x93,0x75,0x3C,0x31,0x53,0xE9); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess7,0x9B2C54E4,0x119F,0x4D6F,0xB4,0x02,0x52,0x76,0x03,0x26,0x6D,0x69); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess8,0x2E6F28C1,0x85EB,0x4141,0x80,0xAD,0x0A,0x90,0x94,0x4B,0x96,0x39); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess10,0x8F378F6F,0x1017,0x4461,0x98,0x90,0xEC,0xF6,0x4C,0x54,0x07,0x9F); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugModuleDebugEvent,0x51A15E8D,0x9FFF,0x4864,0x9B,0x87,0xF4,0xFB,0xDE,0xA7,0x47,0xA2); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugExceptionDebugEvent,0xAF79EC94,0x4752,0x419C,0xA6,0x26,0x5F,0xB1,0xCC,0x1A,0x5A,0xB7); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugBreakpoint,0xCC7BCAE8,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugFunctionBreakpoint,0xCC7BCAE9,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugModuleBreakpoint,0xCC7BCAEA,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugValueBreakpoint,0xCC7BCAEB,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugStepper,0xCC7BCAEC,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugStepper2,0xC5B6E9C3,0xE7D1,0x4a8e,0x87,0x3B,0x7F,0x04,0x7F,0x07,0x06,0xF7); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugRegisterSet,0xCC7BCB0B,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugRegisterSet2,0x6DC7BA3F,0x89BA,0x4459,0x9E,0xC1,0x9D,0x60,0x93,0x7B,0x46,0x8D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugThread,0x938c6d66,0x7fb6,0x4f69,0xb3,0x89,0x42,0x5b,0x89,0x87,0x32,0x9b); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugThread2,0x2BD956D9,0x7B07,0x4bef,0x8A,0x98,0x12,0xAA,0x86,0x24,0x17,0xC5); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugThread3,0xF8544EC3,0x5E4E,0x46c7,0x8D,0x3E,0xA5,0x2B,0x84,0x05,0xB1,0xF5); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugThread4,0x1A1F204B,0x1C66,0x4637,0x82,0x3F,0x3E,0xE6,0xC7,0x44,0xA6,0x9C); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugStackWalk,0xA0647DE9,0x55DE,0x4816,0x92,0x9C,0x38,0x52,0x71,0xC6,0x4C,0xF7); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugChain,0xCC7BCAEE,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugFrame,0xCC7BCAEF,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugInternalFrame,0xB92CC7F7,0x9D2D,0x45c4,0xBC,0x2B,0x62,0x1F,0xCC,0x9D,0xFB,0xF4); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugInternalFrame2,0xC0815BDC,0xCFAB,0x447e,0xA7,0x79,0xC1,0x16,0xB4,0x54,0xEB,0x5B); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugILFrame,0x03E26311,0x4F76,0x11d3,0x88,0xC6,0x00,0x60,0x97,0x94,0x54,0x18); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugILFrame2,0x5D88A994,0x6C30,0x479b,0x89,0x0F,0xBC,0xEF,0x88,0xB1,0x29,0xA5); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugILFrame3,0x9A9E2ED6,0x04DF,0x4FE0,0xBB,0x50,0xCA,0xB6,0x41,0x26,0xAD,0x24); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugILFrame4,0xAD914A30,0xC6D1,0x4AC5,0x9C,0x5E,0x57,0x7F,0x3B,0xAA,0x8A,0x45); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugNativeFrame,0x03E26314,0x4F76,0x11d3,0x88,0xC6,0x00,0x60,0x97,0x94,0x54,0x18); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugNativeFrame2,0x35389FF1,0x3684,0x4c55,0xA2,0xEE,0x21,0x0F,0x26,0xC6,0x0E,0x5E); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugModule3,0x86F012BF,0xFF15,0x4372,0xBD,0x30,0xB6,0xF1,0x1C,0xAA,0xE1,0xDD); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugRuntimeUnwindableFrame,0x879CAC0A,0x4A53,0x4668,0xB8,0xE3,0xCB,0x84,0x73,0xCB,0x18,0x7F); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugModule,0xdba2d8c1,0xe5c5,0x4069,0x8c,0x13,0x10,0xa7,0xc6,0xab,0xf4,0x3d); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugModule2,0x7FCC5FB5,0x49C0,0x41de,0x99,0x38,0x3B,0x88,0xB5,0xB9,0xAD,0xD7); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugFunction,0xCC7BCAF3,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugFunction2,0xEF0C490B,0x94C3,0x4e4d,0xB6,0x29,0xDD,0xC1,0x34,0xC5,0x32,0xD8); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugFunction3,0x09B70F28,0xE465,0x482D,0x99,0xE0,0x81,0xA1,0x65,0xEB,0x05,0x32); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugFunction4,0x72965963,0x34fd,0x46e9,0x94,0x34,0xb8,0x17,0xfe,0x6e,0x7f,0x43); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugCode,0xCC7BCAF4,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugCode2,0x5F696509,0x452F,0x4436,0xA3,0xFE,0x4D,0x11,0xFE,0x7E,0x23,0x47); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugCode3,0xD13D3E88,0xE1F2,0x4020,0xAA,0x1D,0x3D,0x16,0x2D,0xCB,0xE9,0x66); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugCode4,0x18221fa4,0x20cb,0x40fa,0xb1,0x9d,0x9f,0x91,0xc4,0xfa,0x8c,0x14); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugILCode,0x598D46C2,0xC877,0x42A7,0x89,0xD2,0x3D,0x0C,0x7F,0x1C,0x12,0x64); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugILCode2,0x46586093,0xD3F5,0x4DB6,0xAC,0xDB,0x95,0x5B,0xCE,0x22,0x8C,0x15); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugClass,0xCC7BCAF5,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugClass2,0xB008EA8D,0x7AB1,0x43f7,0xBB,0x20,0xFB,0xB5,0xA0,0x40,0x38,0xAE); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugEval,0xCC7BCAF6,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugEval2,0xFB0D9CE7,0xBE66,0x4683,0x9D,0x32,0xA4,0x2A,0x04,0xE2,0xFD,0x91); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugValue,0xCC7BCAF7,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugValue2,0x5E0B54E7,0xD88A,0x4626,0x94,0x20,0xA6,0x91,0xE0,0xA7,0x8B,0x49); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugValue3,0x565005FC,0x0F8A,0x4F3E,0x9E,0xDB,0x83,0x10,0x2B,0x15,0x65,0x95); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugGenericValue,0xCC7BCAF8,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugReferenceValue,0xCC7BCAF9,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapValue,0xCC7BCAFA,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapValue2,0xE3AC4D6C,0x9CB7,0x43e6,0x96,0xCC,0xB2,0x15,0x40,0xE5,0x08,0x3C); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapValue3,0xA69ACAD8,0x2374,0x46e9,0x9F,0xF8,0xB1,0xF1,0x41,0x20,0xD2,0x96); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugObjectValue,0x18AD3D6E,0xB7D2,0x11d2,0xBD,0x04,0x00,0x00,0xF8,0x08,0x49,0xBD); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugObjectValue2,0x49E4A320,0x4A9B,0x4eca,0xB1,0x05,0x22,0x9F,0xB7,0xD5,0x00,0x9F); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugDelegateObjectValue,0x3AF70CC7,0x6047,0x47F6,0xA5,0xC5,0x09,0x0A,0x1A,0x62,0x26,0x38); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugBoxValue,0xCC7BCAFC,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugStringValue,0xCC7BCAFD,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugArrayValue,0x0405B0DF,0xA660,0x11d2,0xBD,0x02,0x00,0x00,0xF8,0x08,0x49,0xBD); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugVariableHome,0x50847b8d,0xf43f,0x41b0,0x92,0x4c,0x63,0x83,0xa5,0xf2,0x27,0x8b); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugHandleValue,0x029596E8,0x276B,0x46a1,0x98,0x21,0x73,0x2E,0x96,0xBB,0xB0,0x0B); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugContext,0xCC7BCB00,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugComObjectValue,0x5F69C5E5,0x3E12,0x42DF,0xB3,0x71,0xF9,0xD7,0x61,0xD6,0xEE,0x24); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugObjectEnum,0xCC7BCB02,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugBreakpointEnum,0xCC7BCB03,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugStepperEnum,0xCC7BCB04,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcessEnum,0xCC7BCB05,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugThreadEnum,0xCC7BCB06,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugFrameEnum,0xCC7BCB07,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugChainEnum,0xCC7BCB08,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugModuleEnum,0xCC7BCB09,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugValueEnum,0xCC7BCB0A,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugVariableHomeEnum,0xe76b7a57,0x4f7a,0x4309,0x85,0xa7,0x5d,0x91,0x8c,0x3d,0xea,0xf7); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugCodeEnum,0x55E96461,0x9645,0x45e4,0xA2,0xFF,0x03,0x67,0x87,0x7A,0xBC,0xDE); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugTypeEnum,0x10F27499,0x9DF2,0x43ce,0x83,0x33,0xA3,0x21,0xD7,0xC9,0x9C,0xB4); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugType,0xD613F0BB,0xACE1,0x4c19,0xBD,0x72,0xE4,0xC0,0x8D,0x5D,0xA7,0xF5); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugType2,0xe6e91d79,0x693d,0x48bc,0xb4,0x17,0x82,0x84,0xb4,0xf1,0x0f,0xb5); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugErrorInfoEnum,0xF0E18809,0x72B5,0x11d2,0x97,0x6F,0x00,0xA0,0xC9,0xB4,0xD5,0x0C); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomainEnum,0x63ca1b24,0x4359,0x4883,0xbd,0x57,0x13,0xf8,0x15,0xf5,0x87,0x44); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAssemblyEnum,0x4a2a1ec9,0x85ec,0x4bfb,0x9f,0x15,0xa8,0x9f,0xdf,0xe0,0xfe,0x83); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugBlockingObjectEnum,0x976A6278,0x134A,0x4a81,0x81,0xA3,0x8F,0x27,0x79,0x43,0xF4,0xC3); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugMDA,0xCC726F2F,0x1DB7,0x459b,0xB0,0xEC,0x05,0xF0,0x1D,0x84,0x1B,0x42); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugEditAndContinueErrorInfo,0x8D600D41,0xF4F6,0x4cb3,0xB7,0xEC,0x7B,0xD1,0x64,0x94,0x40,0x36); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugEditAndContinueSnapshot,0x6DC3FA01,0xD7CB,0x11d2,0x8A,0x95,0x00,0x80,0xC7,0x92,0xE5,0xD8); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugExceptionObjectCallStackEnum,0xED775530,0x4DC4,0x41F7,0x86,0xD0,0x9E,0x2D,0xEF,0x7D,0xFC,0x66); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugExceptionObjectValue,0xAE4CA65D,0x59DD,0x42A2,0x83,0xA5,0x57,0xE8,0xA0,0x8D,0x87,0x19); + + +MIDL_DEFINE_GUID(IID, LIBID_CORDBLib,0x53D13620,0xF417,0x11d1,0x97,0x62,0xA6,0x38,0x26,0xA4,0xF2,0x55); + + +MIDL_DEFINE_GUID(CLSID, CLSID_CorDebug,0x6fef44d0,0x39e7,0x4c77,0xbe,0x8e,0xc9,0xf8,0xcf,0x98,0x86,0x30); + + +MIDL_DEFINE_GUID(CLSID, CLSID_EmbeddedCLRCorDebug,0x211f1254,0xbc7e,0x4af5,0xb9,0xaa,0x06,0x73,0x08,0xd8,0x3d,0xd1); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/corprof_i.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/corprof_i.cpp new file mode 100644 index 0000000..0bf4607 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/corprof_i.cpp @@ -0,0 +1,157 @@ +// 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. + + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.01.0622 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + +#define EXTERN_C extern "C" + + +#ifdef __cplusplus +extern "C"{ +#endif + + + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + EXTERN_C __declspec(selectany) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif // !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback,0x176FBED1,0xA55C,0x4796,0x98,0xCA,0xA9,0xDA,0x0E,0xF8,0x83,0xE7); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback2,0x8A8CC829,0xCCF2,0x49fe,0xBB,0xAE,0x0F,0x02,0x22,0x28,0x07,0x1A); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback3,0x4FD2ED52,0x7731,0x4b8d,0x94,0x69,0x03,0xD2,0xCC,0x30,0x86,0xC5); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback4,0x7B63B2E3,0x107D,0x4d48,0xB2,0xF6,0xF6,0x1E,0x22,0x94,0x70,0xD2); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback5,0x8DFBA405,0x8C9F,0x45F8,0xBF,0xFA,0x83,0xB1,0x4C,0xEF,0x78,0xB5); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback6,0xFC13DF4B,0x4448,0x4F4F,0x95,0x0C,0xBA,0x8D,0x19,0xD0,0x0C,0x36); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback7,0xF76A2DBA,0x1D52,0x4539,0x86,0x6C,0x2A,0xA5,0x18,0xF9,0xEF,0xC3); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback8,0x5BED9B15,0xC079,0x4D47,0xBF,0xE2,0x21,0x5A,0x14,0x0C,0x07,0xE0); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback9,0x27583EC3,0xC8F5,0x482F,0x80,0x52,0x19,0x4B,0x8C,0xE4,0x70,0x5A); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo,0x28B5557D,0x3F3F,0x48b4,0x90,0xB2,0x5F,0x9E,0xEA,0x2F,0x6C,0x48); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo2,0xCC0935CD,0xA518,0x487d,0xB0,0xBB,0xA9,0x32,0x14,0xE6,0x54,0x78); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo3,0xB555ED4F,0x452A,0x4E54,0x8B,0x39,0xB5,0x36,0x0B,0xAD,0x32,0xA0); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerObjectEnum,0x2C6269BD,0x2D13,0x4321,0xAE,0x12,0x66,0x86,0x36,0x5F,0xD6,0xAF); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerFunctionEnum,0xFF71301A,0xB994,0x429D,0xA1,0x0B,0xB3,0x45,0xA6,0x52,0x80,0xEF); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerModuleEnum,0xb0266d75,0x2081,0x4493,0xaf,0x7f,0x02,0x8b,0xa3,0x4d,0xb8,0x91); + + +MIDL_DEFINE_GUID(IID, IID_IMethodMalloc,0xA0EFB28B,0x6EE2,0x4d7b,0xB9,0x83,0xA7,0x5E,0xF7,0xBE,0xED,0xB8); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerFunctionControl,0xF0963021,0xE1EA,0x4732,0x85,0x81,0xE0,0x1B,0x0B,0xD3,0xC0,0xC6); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo4,0x0d8fdcaa,0x6257,0x47bf,0xb1,0xbf,0x94,0xda,0xc8,0x84,0x66,0xee); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo5,0x07602928,0xCE38,0x4B83,0x81,0xE7,0x74,0xAD,0xAF,0x78,0x12,0x14); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo6,0xF30A070D,0xBFFB,0x46A7,0xB1,0xD8,0x87,0x81,0xEF,0x7B,0x69,0x8A); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo7,0x9AEECC0D,0x63E0,0x4187,0x8C,0x00,0xE3,0x12,0xF5,0x03,0xF6,0x63); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo8,0xC5AC80A6,0x782E,0x4716,0x80,0x44,0x39,0x59,0x8C,0x60,0xCF,0xBF); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo9,0x008170DB,0xF8CC,0x4796,0x9A,0x51,0xDC,0x8A,0xA0,0xB4,0x70,0x12); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo10,0x2F1B5152,0xC869,0x40C9,0xAA,0x5F,0x3A,0xBE,0x02,0x6B,0xD7,0x20); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo11,0x06398876,0x8987,0x4154,0xB6,0x21,0x40,0xA0,0x0D,0x6E,0x4D,0x04); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo12,0x27b24ccd,0x1cb1,0x47c5,0x96,0xee,0x98,0x19,0x0d,0xc3,0x09,0x59); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerMethodEnum,0xFCCEE788,0x0088,0x454B,0xA8,0x11,0xC9,0x9F,0x29,0x8D,0x19,0x42); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerThreadEnum,0x571194f7,0x25ed,0x419f,0xaa,0x8b,0x70,0x16,0xb3,0x15,0x97,0x01); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerAssemblyReferenceProvider,0x66A78C24,0x2EEF,0x4F65,0xB4,0x5F,0xDD,0x1D,0x80,0x38,0xBF,0x3C); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/corpub_i.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/corpub_i.cpp new file mode 100644 index 0000000..0be473f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/corpub_i.cpp @@ -0,0 +1,94 @@ +// 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. + + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + EXTERN_C __declspec(selectany) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif // !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, LIBID_CorpubProcessLib,0xe97ca460,0x657d,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); + + +MIDL_DEFINE_GUID(CLSID, CLSID_CorpubPublish,0x047a9a40,0x657e,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); + + +MIDL_DEFINE_GUID(IID, IID_ICorPublish,0x9613A0E7,0x5A68,0x11d3,0x8F,0x84,0x00,0xA0,0xC9,0xB4,0xD5,0x0C); + + +MIDL_DEFINE_GUID(IID, IID_ICorPublishEnum,0xC0B22967,0x5A69,0x11d3,0x8F,0x84,0x00,0xA0,0xC9,0xB4,0xD5,0x0C); + + +MIDL_DEFINE_GUID(IID, IID_ICorPublishProcess,0x18D87AF1,0x5A6A,0x11d3,0x8F,0x84,0x00,0xA0,0xC9,0xB4,0xD5,0x0C); + + +MIDL_DEFINE_GUID(IID, IID_ICorPublishAppDomain,0xD6315C8F,0x5A6A,0x11d3,0x8F,0x84,0x00,0xA0,0xC9,0xB4,0xD5,0x0C); + + +MIDL_DEFINE_GUID(IID, IID_ICorPublishProcessEnum,0xA37FBD41,0x5A69,0x11d3,0x8F,0x84,0x00,0xA0,0xC9,0xB4,0xD5,0x0C); + + +MIDL_DEFINE_GUID(IID, IID_ICorPublishAppDomainEnum,0x9F0C98F5,0x5A6A,0x11d3,0x8F,0x84,0x00,0xA0,0xC9,0xB4,0xD5,0x0C); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/corsym_i.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/corsym_i.cpp new file mode 100644 index 0000000..eba38ce --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/corsym_i.cpp @@ -0,0 +1,175 @@ +// 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. + + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + EXTERN_C __declspec(selectany) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif // !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, LIBID_CorSymLib,0x7E348441,0x7E1F,0x380E,0xA0,0xF6,0x22,0x66,0x8F,0x0F,0x9E,0x4B); + + +MIDL_DEFINE_GUID(CLSID, CLSID_CorSymWriter_deprecated,0x108296C1,0x281E,0x11d3,0xBD,0x22,0x00,0x00,0xF8,0x08,0x49,0xBD); + + +MIDL_DEFINE_GUID(CLSID, CLSID_CorSymReader_deprecated,0x108296C2,0x281E,0x11d3,0xBD,0x22,0x00,0x00,0xF8,0x08,0x49,0xBD); + + +MIDL_DEFINE_GUID(CLSID, CLSID_CorSymBinder_deprecated,0xAA544D41,0x28CB,0x11d3,0xBD,0x22,0x00,0x00,0xF8,0x08,0x49,0xBD); + + +MIDL_DEFINE_GUID(CLSID, CLSID_CorSymWriter_SxS,0x0AE2DEB0,0xF901,0x478b,0xBB,0x9F,0x88,0x1E,0xE8,0x06,0x67,0x88); + + +MIDL_DEFINE_GUID(CLSID, CLSID_CorSymReader_SxS,0x0A3976C5,0x4529,0x4ef8,0xB0,0xB0,0x42,0xEE,0xD3,0x70,0x82,0xCD); + + +MIDL_DEFINE_GUID(CLSID, CLSID_CorSymBinder_SxS,0x0A29FF9E,0x7F9C,0x4437,0x8B,0x11,0xF4,0x24,0x49,0x1E,0x39,0x31); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedBinder,0xAA544D42,0x28CB,0x11d3,0xBD,0x22,0x00,0x00,0xF8,0x08,0x49,0xBD); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedBinder2,0xACCEE350,0x89AF,0x4ccb,0x8B,0x40,0x1C,0x2C,0x4C,0x6F,0x94,0x34); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedBinder3,0x28AD3D43,0xB601,0x4d26,0x8A,0x1B,0x25,0xF9,0x16,0x5A,0xF9,0xD7); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedDispose,0x969708D2,0x05E5,0x4861,0xA3,0xB0,0x96,0xE4,0x73,0xCD,0xF6,0x3F); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedDocument,0x40DE4037,0x7C81,0x3E1E,0xB0,0x22,0xAE,0x1A,0xBF,0xF2,0xCA,0x08); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedDocumentWriter,0xB01FAFEB,0xC450,0x3A4D,0xBE,0xEC,0xB4,0xCE,0xEC,0x01,0xE0,0x06); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedMethod,0xB62B923C,0xB500,0x3158,0xA5,0x43,0x24,0xF3,0x07,0xA8,0xB7,0xE1); + + +MIDL_DEFINE_GUID(IID, IID_ISymENCUnmanagedMethod,0x85E891DA,0xA631,0x4c76,0xAC,0xA2,0xA4,0x4A,0x39,0xC4,0x6B,0x8C); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedNamespace,0x0DFF7289,0x54F8,0x11d3,0xBD,0x28,0x00,0x00,0xF8,0x08,0x49,0xBD); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedReader,0xB4CE6286,0x2A6B,0x3712,0xA3,0xB7,0x1E,0xE1,0xDA,0xD4,0x67,0xB5); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedSourceServerModule,0x997DD0CC,0xA76F,0x4c82,0x8D,0x79,0xEA,0x87,0x55,0x9D,0x27,0xAD); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedENCUpdate,0xE502D2DD,0x8671,0x4338,0x8F,0x2A,0xFC,0x08,0x22,0x96,0x28,0xC4); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedReaderSymbolSearchInfo,0x20D9645D,0x03CD,0x4e34,0x9C,0x11,0x98,0x48,0xA5,0xB0,0x84,0xF1); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedScope,0x68005D0F,0xB8E0,0x3B01,0x84,0xD5,0xA1,0x1A,0x94,0x15,0x49,0x42); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedConstant,0x48B25ED8,0x5BAD,0x41bc,0x9C,0xEE,0xCD,0x62,0xFA,0xBC,0x74,0xE9); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedScope2,0xAE932FBA,0x3FD8,0x4dba,0x82,0x32,0x30,0xA2,0x30,0x9B,0x02,0xDB); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedVariable,0x9F60EEBE,0x2D9A,0x3F7C,0xBF,0x58,0x80,0xBC,0x99,0x1C,0x60,0xBB); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedSymbolSearchInfo,0xF8B3534A,0xA46B,0x4980,0xB5,0x20,0xBE,0xC4,0xAC,0xEA,0xBA,0x8F); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedWriter,0xED14AA72,0x78E2,0x4884,0x84,0xE2,0x33,0x42,0x93,0xAE,0x52,0x14); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedWriter2,0x0B97726E,0x9E6D,0x4f05,0x9A,0x26,0x42,0x40,0x22,0x09,0x3C,0xAA); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedWriter3,0x12F1E02C,0x1E05,0x4B0E,0x94,0x68,0xEB,0xC9,0xD1,0xBB,0x04,0x0F); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedWriter4,0xBC7E3F53,0xF458,0x4C23,0x9D,0xBD,0xA1,0x89,0xE6,0xE9,0x65,0x94); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedWriter5,0xDCF7780D,0xBDE9,0x45DF,0xAC,0xFE,0x21,0x73,0x1A,0x32,0x00,0x0C); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedReader2,0xA09E53B2,0x2A57,0x4cca,0x8F,0x63,0xB8,0x4F,0x7C,0x35,0xD4,0xAA); + + +MIDL_DEFINE_GUID(IID, IID_ISymNGenWriter,0xd682fd12,0x43de,0x411c,0x81,0x1b,0xbe,0x84,0x04,0xce,0xa1,0x26); + + +MIDL_DEFINE_GUID(IID, IID_ISymNGenWriter2,0xB029E51B,0x4C55,0x4fe2,0xB9,0x93,0x9F,0x7B,0xC1,0xF1,0x0D,0xB4); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedAsyncMethodPropertiesWriter,0xFC073774,0x1739,0x4232,0xBD,0x56,0xA0,0x27,0x29,0x4B,0xEC,0x15); + + +MIDL_DEFINE_GUID(IID, IID_ISymUnmanagedAsyncMethod,0xB20D55B3,0x532E,0x4906,0x87,0xE7,0x25,0xBD,0x57,0x34,0xAB,0xD2); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/mscorsvc_i.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/mscorsvc_i.cpp new file mode 100644 index 0000000..1391745 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/mscorsvc_i.cpp @@ -0,0 +1,142 @@ +// 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. + + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + EXTERN_C __declspec(selectany) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif // !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, LIBID_mscorsvc,0xd69cca64,0x16f7,0x485c,0x8c,0xf1,0x67,0x06,0x3e,0x44,0xf0,0xc3); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcDependencies,0xddb34005,0x9ba3,0x4025,0x95,0x54,0xf0,0x0a,0x2d,0xf5,0xdb,0xf5); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcWorker,0xd1047bc2,0x67c0,0x400c,0xa9,0x4c,0xe6,0x44,0x46,0xa6,0x7f,0xbe); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcWorker2,0xf3358a7d,0x0061,0x4776,0x88,0x0e,0xa2,0xf2,0x1b,0x9e,0xf9,0x3e); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcWorker3,0xDC516615,0x47BE,0x477e,0x8B,0x55,0xC5,0xAB,0xE0,0xD7,0x6B,0x8F); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcSetPrivateAttributes,0xb18e0b40,0xc089,0x4350,0x83,0x28,0x06,0x6c,0x66,0x8b,0xcc,0xc2); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcRepository,0xd5346658,0xb5fd,0x4353,0x96,0x47,0x07,0xad,0x47,0x83,0xd5,0xa0); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcAppX,0x5c814791,0x559e,0x4f7f,0x83,0xce,0x18,0x4a,0x4c,0xcb,0xae,0x24); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcLogger,0xd189ff1a,0xe266,0x4f13,0x96,0x37,0x4b,0x95,0x22,0x27,0x9f,0xfc); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcPooledWorker,0x0631e7e2,0x6046,0x4fde,0x8b,0x6d,0xa0,0x9b,0x64,0xfd,0xa6,0xf3); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcBindToWorker,0x5c6fb596,0x4828,0x4ed5,0xb9,0xdd,0x29,0x3d,0xad,0x73,0x6f,0xb5); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvc,0x3eef5ff0,0x3680,0x4f20,0x8a,0x8f,0x90,0x51,0xac,0xa6,0x6b,0x22); + + +MIDL_DEFINE_GUID(IID, IID_ICompileProgressNotification,0x01c10030,0x6c81,0x4671,0xbd,0x51,0x14,0xb1,0x84,0xc6,0x73,0xb2); + + +MIDL_DEFINE_GUID(IID, IID_ICompileProgressNotification2,0x98E5BDE2,0xE9A0,0x4ADE,0x9C,0xB2,0x6C,0xD0,0x6F,0xDB,0x1A,0x85); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcInstaller,0x0523feee,0xeb0e,0x4857,0xb2,0xaa,0xdb,0x78,0x75,0x21,0xd0,0x77); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcAdvancedInstaller,0x0871fb80,0x3ea0,0x47cc,0x9b,0x51,0xd9,0x2e,0x2a,0xee,0x75,0xdb); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcOptimizer,0x94af0ec4,0xc10d,0x45d4,0xa6,0x25,0xd6,0x8d,0x1b,0x02,0xa3,0x96); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcOptimizer2,0xee3b09c2,0x0110,0x4b6e,0xa7,0x3f,0xa3,0xd6,0x56,0x2f,0x98,0xab); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcOptimizer3,0x6EED164F,0x61EE,0x4a07,0xAB,0xE8,0x67,0x0F,0x92,0xB4,0xB7,0xA9); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcManager,0x8f416a48,0xd663,0x4a7e,0x97,0x32,0xfb,0xca,0x3f,0xc4,0x6e,0xa8); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcManager2,0x29626056,0x8031,0x441b,0xaf,0xfa,0x7a,0x82,0x48,0x00,0x58,0xb3); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcSetLegacyServiceBehavior,0x35e5d609,0xec3d,0x4fc2,0x9b,0xa2,0x5f,0x99,0xe4,0x2f,0xf4,0x2f); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcSetTaskBootTriggerState,0x115466A4,0x7005,0x4CA3,0x97,0x1F,0x01,0xF0,0xA2,0xC8,0xEF,0x09); + + +MIDL_DEFINE_GUID(IID, IID_ICorSvcSetTaskDelayStartTriggerState,0x261DD1E3,0xF07E,0x4B8D,0xB5,0x4E,0xF2,0x68,0x89,0x41,0x36,0x26); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/sospriv_i.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/sospriv_i.cpp new file mode 100644 index 0000000..792fdfb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/sospriv_i.cpp @@ -0,0 +1,103 @@ +// 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. + + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.00.0613 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + EXTERN_C __declspec(selectany) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif // !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, IID_ISOSEnum,0x286CA186,0xE763,0x4F61,0x97,0x60,0x48,0x7D,0x43,0xAE,0x43,0x41); + + +MIDL_DEFINE_GUID(IID, IID_ISOSHandleEnum,0x3E269830,0x4A2B,0x4301,0x8E,0xE2,0xD6,0x80,0x5B,0x29,0xB2,0xFA); + + +MIDL_DEFINE_GUID(IID, IID_ISOSStackRefErrorEnum,0x774F4E1B,0xFB7B,0x491B,0x97,0x6D,0xA8,0x13,0x0F,0xE3,0x55,0xE9); + + +MIDL_DEFINE_GUID(IID, IID_ISOSStackRefEnum,0x8FA642BD,0x9F10,0x4799,0x9A,0xA3,0x51,0x2A,0xE7,0x8C,0x77,0xEE); + + +MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface,0x436f00f2,0xb42a,0x4b9f,0x87,0x0c,0xe7,0x3d,0xb6,0x6a,0xe9,0x30); + + +MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface2,0xA16026EC,0x96F4,0x40BA,0x87,0xFB,0x55,0x75,0x98,0x6F,0xB7,0xAF); + + +MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface3,0xB08C5CDC,0xFD8A,0x49C5,0xAB,0x38,0x5F,0xEE,0xF3,0x52,0x35,0xB4); + + +MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface4,0x74B9D34C,0xA612,0x4B07,0x93,0xDD,0x54,0x62,0x17,0x8F,0xCE,0x11); + + +MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface5,0x127d6abe,0x6c86,0x4e48,0x8e,0x7b,0x22,0x07,0x81,0xc5,0x81,0x01); + + +MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface6,0x11206399,0x4B66,0x4EDB,0x98,0xEA,0x85,0x65,0x4E,0x59,0xAD,0x45); + + +MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface7,0xc1020dde,0xfe98,0x4536,0xa5,0x3b,0xf3,0x5a,0x74,0xc3,0x27,0xeb); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/xclrdata_i.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/xclrdata_i.cpp new file mode 100644 index 0000000..140082d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/xclrdata_i.cpp @@ -0,0 +1,145 @@ +// 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. + + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + EXTERN_C __declspec(selectany) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif // !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataTarget3,0x59d9b5e1,0x4a6f,0x4531,0x84,0xc3,0x51,0xd1,0x2d,0xa2,0x2f,0xd4); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRLibrarySupport,0xE5F3039D,0x2C0C,0x4230,0xA6,0x9E,0x12,0xAF,0x1C,0x3E,0x56,0x3C); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDisassemblySupport,0x1F0F7134,0xD3F3,0x47DE,0x8E,0x9B,0xC2,0xFD,0x35,0x8A,0x29,0x36); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataDisplay,0xA3C1704A,0x4559,0x4a67,0x8D,0x28,0xE8,0xF4,0xFE,0x3B,0x3F,0x62); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataProcess,0x5c552ab6,0xfc09,0x4cb3,0x8e,0x36,0x22,0xfa,0x03,0xc7,0x98,0xb7); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataProcess2,0x5c552ab6,0xfc09,0x4cb3,0x8e,0x36,0x22,0xfa,0x03,0xc7,0x98,0xb8); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataAppDomain,0x7CA04601,0xC702,0x4670,0xA6,0x3C,0xFA,0x44,0xF7,0xDA,0x7B,0xD5); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataAssembly,0x2FA17588,0x43C2,0x46ab,0x9B,0x51,0xC8,0xF0,0x1E,0x39,0xC9,0xAC); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataModule,0x88E32849,0x0A0A,0x4cb0,0x90,0x22,0x7C,0xD2,0xE9,0xE1,0x39,0xE2); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataModule2,0x34625881,0x7EB3,0x4524,0x81,0x7B,0x8D,0xB9,0xD0,0x64,0xC7,0x60); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataTypeDefinition,0x4675666C,0xC275,0x45b8,0x9F,0x6C,0xAB,0x16,0x5D,0x5C,0x1E,0x09); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataTypeInstance,0x4D078D91,0x9CB3,0x4b0d,0x97,0xAC,0x28,0xC8,0xA5,0xA8,0x25,0x97); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataMethodDefinition,0xAAF60008,0xFB2C,0x420b,0x8F,0xB1,0x42,0xD2,0x44,0xA5,0x4A,0x97); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataMethodInstance,0xECD73800,0x22CA,0x4b0d,0xAB,0x55,0xE9,0xBA,0x7E,0x63,0x18,0xA5); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataTask,0xA5B0BEEA,0xEC62,0x4618,0x80,0x12,0xA2,0x4F,0xFC,0x23,0x93,0x4C); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataStackWalk,0xE59D8D22,0xADA7,0x49a2,0x89,0xB5,0xA4,0x15,0xAF,0xCF,0xC9,0x5F); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataFrame,0x271498C2,0x4085,0x4766,0xBC,0x3A,0x7F,0x8E,0xD1,0x88,0xA1,0x73); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataFrame2,0x1C4D9A4B,0x702D,0x4CF6,0xB2,0x90,0x1D,0xB6,0xF4,0x30,0x50,0xD0); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataExceptionState,0x75DA9E4C,0xBD33,0x43C8,0x8F,0x5C,0x96,0xE8,0xA5,0x24,0x1F,0x57); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataValue,0x96EC93C7,0x1000,0x4e93,0x89,0x91,0x98,0xD8,0x76,0x6E,0x66,0x66); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataExceptionNotification,0x2D95A079,0x42A1,0x4837,0x81,0x8F,0x0B,0x97,0xD7,0x04,0x8E,0x0E); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataExceptionNotification2,0x31201a94,0x4337,0x49b7,0xae,0xf7,0x0c,0x75,0x50,0x54,0x09,0x1f); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataExceptionNotification3,0x31201a94,0x4337,0x49b7,0xae,0xf7,0x0c,0x75,0x50,0x54,0x09,0x20); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataExceptionNotification4,0xC25E926E,0x5F09,0x4AA2,0xBB,0xAD,0xB7,0xFC,0x7F,0x10,0xCF,0xD7); + + +MIDL_DEFINE_GUID(IID, IID_IXCLRDataExceptionNotification5,0xe77a39ea,0x3548,0x44d9,0xb1,0x71,0x85,0x69,0xed,0x1a,0x94,0x23); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/xcordebug_i.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/xcordebug_i.cpp new file mode 100644 index 0000000..32bb754 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/idl/xcordebug_i.cpp @@ -0,0 +1,73 @@ +// 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. + + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.01.0622 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + EXTERN_C __declspec(selectany) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif // !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess4,0xE930C679,0x78AF,0x4953,0x8A,0xB7,0xB0,0xAA,0xBF,0x0F,0x9F,0x80); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/CMakeLists.txt index ae9892b..79f8e54 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/CMakeLists.txt +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/CMakeLists.txt @@ -1,5 +1,3 @@ -cmake_minimum_required(VERSION 2.8.12.2) - project(COREPAL) _install (FILES corerror.h corprof.h DESTINATION inc) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/asm_version.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/asm_version.h deleted file mode 100644 index 44e09c0..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/asm_version.h +++ /dev/null @@ -1,22 +0,0 @@ -// 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. -#if defined(SILVERLIGHT) -#if defined(FEATURE_CORESYSTEM) -#define asm_rmj 4 -#define asm_rmm 0 -#define asm_rup 0 -#define asm_rpt 0 -#else -#define asm_rmj 5 -#define asm_rmm 0 -#define asm_rup 5 -#define asm_rpt 0 -#endif -#else -#define asm_rmj 4 -#define asm_rmm 0 -#define asm_rup 0 -#define asm_rpt 0 -#endif - diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/buildnumber.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/buildnumber.h deleted file mode 100644 index 5aee76a..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/buildnumber.h +++ /dev/null @@ -1,23 +0,0 @@ -// 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. - -#define BuildNumberMajor 30319 -#define BuildNumberMinor 0 -#define BuildNumberMajor_A "30319" -#define BuildNumberMinor_A "00" -#define BuildNumbers_A "30319.00" -#define BuildNumbers_T TEXT("30319.00") - -#define NDPBuildNumberMajor 30319 -#define NDPBuildNumberMinor 0 -#define NDPBuildNumbers_A "30319.00" -#define NDPBuildNumbers_T TEXT("30319.00") - -#define NDPFileVersionMinor 5 -#define NDPFileVersionBuild 30319 -#define NDPFileVersionRevision 0 - -#define NDPFileVersionMinor_A "5" -#define NDPFileVersionBuild_A "30319" -#define NDPFileVersionRevision_A "00" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrdata.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrdata.h index 5d3a764..6d67005 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrdata.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrdata.h @@ -2,12 +2,20 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - - /* this ALWAYS GENERATED file contains the definitions for the interfaces */ - /* File created by MIDL compiler version 8.00.0603 */ + /* File created by MIDL compiler version 8.01.0622 */ +/* at Mon Jan 18 19:14:07 2038 + */ +/* Compiler settings for C:/ssd/runtime/src/coreclr/src/inc/clrdata.idl: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ @@ -23,7 +31,7 @@ #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of -#endif // __RPCNDR_H_VERSION__ +#endif /* __RPCNDR_H_VERSION__ */ #ifndef COM_NO_WINDOWS_H #include "windows.h" @@ -60,6 +68,13 @@ typedef interface ICLRDataTarget3 ICLRDataTarget3; #endif /* __ICLRDataTarget3_FWD_DEFINED__ */ +#ifndef __ICLRRuntimeLocator_FWD_DEFINED__ +#define __ICLRRuntimeLocator_FWD_DEFINED__ +typedef interface ICLRRuntimeLocator ICLRRuntimeLocator; + +#endif /* __ICLRRuntimeLocator_FWD_DEFINED__ */ + + #ifndef __ICLRMetadataLocator_FWD_DEFINED__ #define __ICLRMetadataLocator_FWD_DEFINED__ typedef interface ICLRMetadataLocator ICLRMetadataLocator; @@ -761,6 +776,86 @@ EXTERN_C const IID IID_ICLRDataTarget3; #endif /* __ICLRDataTarget3_INTERFACE_DEFINED__ */ +#ifndef __ICLRRuntimeLocator_INTERFACE_DEFINED__ +#define __ICLRRuntimeLocator_INTERFACE_DEFINED__ + +/* interface ICLRRuntimeLocator */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICLRRuntimeLocator; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("b760bf44-9377-4597-8be7-58083bdc5146") + ICLRRuntimeLocator : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetRuntimeBase( + /* [out] */ CLRDATA_ADDRESS *baseAddress) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRRuntimeLocatorVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRRuntimeLocator * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRRuntimeLocator * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRRuntimeLocator * This); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeBase )( + ICLRRuntimeLocator * This, + /* [out] */ CLRDATA_ADDRESS *baseAddress); + + END_INTERFACE + } ICLRRuntimeLocatorVtbl; + + interface ICLRRuntimeLocator + { + CONST_VTBL struct ICLRRuntimeLocatorVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRRuntimeLocator_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRRuntimeLocator_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRRuntimeLocator_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRRuntimeLocator_GetRuntimeBase(This,baseAddress) \ + ( (This)->lpVtbl -> GetRuntimeBase(This,baseAddress) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRRuntimeLocator_INTERFACE_DEFINED__ */ + + #ifndef __ICLRMetadataLocator_INTERFACE_DEFINED__ #define __ICLRMetadataLocator_INTERFACE_DEFINED__ @@ -1032,7 +1127,7 @@ EXTERN_C const IID IID_ICLRDataEnumMemoryRegionsCallback2; #endif /* __ICLRDataEnumMemoryRegionsCallback2_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_clrdata_0000_0006 */ +/* interface __MIDL_itf_clrdata_0000_0007 */ /* [local] */ typedef @@ -1046,8 +1141,8 @@ enum CLRDataEnumMemoryFlags -extern RPC_IF_HANDLE __MIDL_itf_clrdata_0000_0006_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_clrdata_0000_0006_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_clrdata_0000_0007_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_clrdata_0000_0007_v0_0_s_ifspec; #ifndef __ICLRDataEnumMemoryRegions_INTERFACE_DEFINED__ #define __ICLRDataEnumMemoryRegions_INTERFACE_DEFINED__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrinternal.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrinternal.h index 647b899..e3625a7 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrinternal.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrinternal.h @@ -39,20 +39,6 @@ /* Forward Declarations */ -#ifndef __IExecutionEngine_FWD_DEFINED__ -#define __IExecutionEngine_FWD_DEFINED__ -typedef interface IExecutionEngine IExecutionEngine; - -#endif /* __IExecutionEngine_FWD_DEFINED__ */ - - -#ifndef __IEEMemoryManager_FWD_DEFINED__ -#define __IEEMemoryManager_FWD_DEFINED__ -typedef interface IEEMemoryManager IEEMemoryManager; - -#endif /* __IEEMemoryManager_FWD_DEFINED__ */ - - #ifndef __IPrivateManagedExceptionReporting_FWD_DEFINED__ #define __IPrivateManagedExceptionReporting_FWD_DEFINED__ typedef interface IPrivateManagedExceptionReporting IPrivateManagedExceptionReporting; @@ -72,48 +58,6 @@ extern "C"{ /* interface __MIDL_itf_clrinternal_0000_0000 */ /* [local] */ -#if 0 -typedef struct _OSVERSIONINFOA - { - DWORD dwOSVersionInfoSize; - DWORD dwMajorVersion; - DWORD dwMinorVersion; - DWORD dwBuildNumber; - DWORD dwPlatformId; - CHAR szCSDVersion[ 128 ]; - } OSVERSIONINFOA; - -typedef struct _OSVERSIONINFOA *POSVERSIONINFOA; - -typedef struct _OSVERSIONINFOA *LPOSVERSIONINFOA; - -typedef struct _OSVERSIONINFOW - { - DWORD dwOSVersionInfoSize; - DWORD dwMajorVersion; - DWORD dwMinorVersion; - DWORD dwBuildNumber; - DWORD dwPlatformId; - WCHAR szCSDVersion[ 128 ]; - } OSVERSIONINFOW; - -typedef struct _OSVERSIONINFOW *POSVERSIONINFOW; - -typedef struct _OSVERSIONINFOW *LPOSVERSIONINFOW; - -typedef struct _OSVERSIONINFOW RTL_OSVERSIONINFOW; - -typedef struct _OSVERSIONINFOW *PRTL_OSVERSIONINFOW; - -typedef OSVERSIONINFOA OSVERSIONINFO; - -typedef POSVERSIONINFOA POSVERSIONINFO; - -typedef LPOSVERSIONINFOA LPOSVERSIONINFO; - -#endif -EXTERN_GUID(IID_IExecutionEngine, 0x7AF02DAC, 0x2A33, 0x494b, 0xA0, 0x9F, 0x25, 0xE0, 0x0A, 0x93, 0xC6, 0xF8); -EXTERN_GUID(IID_IEEMemoryManager, 0x17713b61, 0xb59f, 0x4e13, 0xba, 0xaf, 0x91, 0x62, 0x3d, 0xc8, 0xad, 0xc0); EXTERN_GUID(CLR_ID_V4_DESKTOP, 0x267f3989, 0xd786, 0x4b9a, 0x9a, 0xf6, 0xd1, 0x9e, 0x42, 0xd5, 0x57, 0xec); EXTERN_GUID(CLR_ID_CORECLR, 0x8CB8E075, 0x0A91, 0x408E, 0x92, 0x28, 0xD6, 0x6E, 0x00, 0xA3, 0xBF, 0xF6 ); EXTERN_GUID(CLR_ID_PHONE_CLR, 0xE7237E9C, 0x31C0, 0x488C, 0xAD, 0x48, 0x32, 0x4D, 0x3E, 0x7E, 0xD9, 0x2A); @@ -121,13 +65,7 @@ EXTERN_GUID(CLR_ID_ONECORE_CLR, 0xb1ee760d, 0x6c4a, 0x4533, 0xba, 0x41, 0x6f, 0x EXTERN_GUID(IID_IPrivateManagedExceptionReporting, 0xad76a023, 0x332d, 0x4298, 0x80, 0x01, 0x07, 0xaa, 0x93, 0x50, 0xdc, 0xa4); typedef void *CRITSEC_COOKIE; -typedef void *EVENT_COOKIE; - -typedef void *SEMAPHORE_COOKIE; - -typedef void *MUTEX_COOKIE; - -typedef /* [public][public] */ +typedef /* [public] */ enum __MIDL___MIDL_itf_clrinternal_0000_0000_0001 { CRST_DEFAULT = 0, @@ -142,618 +80,11 @@ enum __MIDL___MIDL_itf_clrinternal_0000_0000_0001 CRST_DEBUG_ONLY_CHECK_FORBID_SUSPEND_THREAD = 0x200 } CrstFlags; -typedef VOID ( WINAPI *PTLS_CALLBACK_FUNCTION )( - PVOID __MIDL____MIDL_itf_clrinternal_0000_00000000); - extern RPC_IF_HANDLE __MIDL_itf_clrinternal_0000_0000_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_clrinternal_0000_0000_v0_0_s_ifspec; -#ifndef __IExecutionEngine_INTERFACE_DEFINED__ -#define __IExecutionEngine_INTERFACE_DEFINED__ - -/* interface IExecutionEngine */ -/* [object][local][unique][helpstring][uuid] */ - - -EXTERN_C const IID IID_IExecutionEngine; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("7AF02DAC-2A33-494b-A09F-25E00A93C6F8") - IExecutionEngine : public IUnknown - { - public: - virtual void STDMETHODCALLTYPE TLS_AssociateCallback( - /* [in] */ DWORD slot, - /* [in] */ PTLS_CALLBACK_FUNCTION callback) = 0; - - virtual PVOID *STDMETHODCALLTYPE TLS_GetDataBlock( void) = 0; - - virtual PVOID STDMETHODCALLTYPE TLS_GetValue( - /* [in] */ DWORD slot) = 0; - - virtual BOOL STDMETHODCALLTYPE TLS_CheckValue( - /* [in] */ DWORD slot, - /* [out] */ PVOID *pValue) = 0; - - virtual void STDMETHODCALLTYPE TLS_SetValue( - /* [in] */ DWORD slot, - /* [in] */ PVOID pData) = 0; - - virtual void STDMETHODCALLTYPE TLS_ThreadDetaching( void) = 0; - - virtual CRITSEC_COOKIE STDMETHODCALLTYPE CreateLock( - /* [in] */ LPCSTR szTag, - /* [in] */ LPCSTR level, - /* [in] */ CrstFlags flags) = 0; - - virtual void STDMETHODCALLTYPE DestroyLock( - /* [in] */ CRITSEC_COOKIE lock) = 0; - - virtual void STDMETHODCALLTYPE AcquireLock( - /* [in] */ CRITSEC_COOKIE lock) = 0; - - virtual void STDMETHODCALLTYPE ReleaseLock( - /* [in] */ CRITSEC_COOKIE lock) = 0; - - virtual EVENT_COOKIE STDMETHODCALLTYPE CreateAutoEvent( - /* [in] */ BOOL bInitialState) = 0; - - virtual EVENT_COOKIE STDMETHODCALLTYPE CreateManualEvent( - /* [in] */ BOOL bInitialState) = 0; - - virtual void STDMETHODCALLTYPE CloseEvent( - /* [in] */ EVENT_COOKIE event) = 0; - - virtual BOOL STDMETHODCALLTYPE ClrSetEvent( - /* [in] */ EVENT_COOKIE event) = 0; - - virtual BOOL STDMETHODCALLTYPE ClrResetEvent( - /* [in] */ EVENT_COOKIE event) = 0; - - virtual DWORD STDMETHODCALLTYPE WaitForEvent( - /* [in] */ EVENT_COOKIE event, - /* [in] */ DWORD dwMilliseconds, - /* [in] */ BOOL bAlertable) = 0; - - virtual DWORD STDMETHODCALLTYPE WaitForSingleObject( - /* [in] */ HANDLE handle, - /* [in] */ DWORD dwMilliseconds) = 0; - - virtual SEMAPHORE_COOKIE STDMETHODCALLTYPE ClrCreateSemaphore( - /* [in] */ DWORD dwInitial, - /* [in] */ DWORD dwMax) = 0; - - virtual void STDMETHODCALLTYPE ClrCloseSemaphore( - /* [in] */ SEMAPHORE_COOKIE semaphore) = 0; - - virtual DWORD STDMETHODCALLTYPE ClrWaitForSemaphore( - /* [in] */ SEMAPHORE_COOKIE semaphore, - /* [in] */ DWORD dwMilliseconds, - /* [in] */ BOOL bAlertable) = 0; - - virtual BOOL STDMETHODCALLTYPE ClrReleaseSemaphore( - /* [in] */ SEMAPHORE_COOKIE semaphore, - /* [in] */ LONG lReleaseCount, - /* [in] */ LONG *lpPreviousCount) = 0; - - virtual MUTEX_COOKIE STDMETHODCALLTYPE ClrCreateMutex( - /* [in] */ LPSECURITY_ATTRIBUTES lpMutexAttributes, - /* [in] */ BOOL bInitialOwner, - /* [in] */ LPCTSTR lpName) = 0; - - virtual DWORD STDMETHODCALLTYPE ClrWaitForMutex( - /* [in] */ MUTEX_COOKIE mutex, - /* [in] */ DWORD dwMilliseconds, - /* [in] */ BOOL bAlertable) = 0; - - virtual BOOL STDMETHODCALLTYPE ClrReleaseMutex( - /* [in] */ MUTEX_COOKIE mutex) = 0; - - virtual void STDMETHODCALLTYPE ClrCloseMutex( - /* [in] */ MUTEX_COOKIE mutex) = 0; - - virtual DWORD STDMETHODCALLTYPE ClrSleepEx( - /* [in] */ DWORD dwMilliseconds, - /* [in] */ BOOL bAlertable) = 0; - - virtual BOOL STDMETHODCALLTYPE ClrAllocationDisallowed( void) = 0; - - virtual void STDMETHODCALLTYPE GetLastThrownObjectExceptionFromThread( - /* [out] */ void **ppvException) = 0; - - }; - - -#else /* C style interface */ - - typedef struct IExecutionEngineVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IExecutionEngine * This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IExecutionEngine * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IExecutionEngine * This); - - void ( STDMETHODCALLTYPE *TLS_AssociateCallback )( - IExecutionEngine * This, - /* [in] */ DWORD slot, - /* [in] */ PTLS_CALLBACK_FUNCTION callback); - - PVOID *( STDMETHODCALLTYPE *TLS_GetDataBlock )( - IExecutionEngine * This); - - PVOID ( STDMETHODCALLTYPE *TLS_GetValue )( - IExecutionEngine * This, - /* [in] */ DWORD slot); - - BOOL ( STDMETHODCALLTYPE *TLS_CheckValue )( - IExecutionEngine * This, - /* [in] */ DWORD slot, - /* [out] */ PVOID *pValue); - - void ( STDMETHODCALLTYPE *TLS_SetValue )( - IExecutionEngine * This, - /* [in] */ DWORD slot, - /* [in] */ PVOID pData); - - void ( STDMETHODCALLTYPE *TLS_ThreadDetaching )( - IExecutionEngine * This); - - CRITSEC_COOKIE ( STDMETHODCALLTYPE *CreateLock )( - IExecutionEngine * This, - /* [in] */ LPCSTR szTag, - /* [in] */ LPCSTR level, - /* [in] */ CrstFlags flags); - - void ( STDMETHODCALLTYPE *DestroyLock )( - IExecutionEngine * This, - /* [in] */ CRITSEC_COOKIE lock); - - void ( STDMETHODCALLTYPE *AcquireLock )( - IExecutionEngine * This, - /* [in] */ CRITSEC_COOKIE lock); - - void ( STDMETHODCALLTYPE *ReleaseLock )( - IExecutionEngine * This, - /* [in] */ CRITSEC_COOKIE lock); - - EVENT_COOKIE ( STDMETHODCALLTYPE *CreateAutoEvent )( - IExecutionEngine * This, - /* [in] */ BOOL bInitialState); - - EVENT_COOKIE ( STDMETHODCALLTYPE *CreateManualEvent )( - IExecutionEngine * This, - /* [in] */ BOOL bInitialState); - - void ( STDMETHODCALLTYPE *CloseEvent )( - IExecutionEngine * This, - /* [in] */ EVENT_COOKIE event); - - BOOL ( STDMETHODCALLTYPE *ClrSetEvent )( - IExecutionEngine * This, - /* [in] */ EVENT_COOKIE event); - - BOOL ( STDMETHODCALLTYPE *ClrResetEvent )( - IExecutionEngine * This, - /* [in] */ EVENT_COOKIE event); - - DWORD ( STDMETHODCALLTYPE *WaitForEvent )( - IExecutionEngine * This, - /* [in] */ EVENT_COOKIE event, - /* [in] */ DWORD dwMilliseconds, - /* [in] */ BOOL bAlertable); - - DWORD ( STDMETHODCALLTYPE *WaitForSingleObject )( - IExecutionEngine * This, - /* [in] */ HANDLE handle, - /* [in] */ DWORD dwMilliseconds); - - SEMAPHORE_COOKIE ( STDMETHODCALLTYPE *ClrCreateSemaphore )( - IExecutionEngine * This, - /* [in] */ DWORD dwInitial, - /* [in] */ DWORD dwMax); - - void ( STDMETHODCALLTYPE *ClrCloseSemaphore )( - IExecutionEngine * This, - /* [in] */ SEMAPHORE_COOKIE semaphore); - - DWORD ( STDMETHODCALLTYPE *ClrWaitForSemaphore )( - IExecutionEngine * This, - /* [in] */ SEMAPHORE_COOKIE semaphore, - /* [in] */ DWORD dwMilliseconds, - /* [in] */ BOOL bAlertable); - - BOOL ( STDMETHODCALLTYPE *ClrReleaseSemaphore )( - IExecutionEngine * This, - /* [in] */ SEMAPHORE_COOKIE semaphore, - /* [in] */ LONG lReleaseCount, - /* [in] */ LONG *lpPreviousCount); - - MUTEX_COOKIE ( STDMETHODCALLTYPE *ClrCreateMutex )( - IExecutionEngine * This, - /* [in] */ LPSECURITY_ATTRIBUTES lpMutexAttributes, - /* [in] */ BOOL bInitialOwner, - /* [in] */ LPCTSTR lpName); - - DWORD ( STDMETHODCALLTYPE *ClrWaitForMutex )( - IExecutionEngine * This, - /* [in] */ MUTEX_COOKIE mutex, - /* [in] */ DWORD dwMilliseconds, - /* [in] */ BOOL bAlertable); - - BOOL ( STDMETHODCALLTYPE *ClrReleaseMutex )( - IExecutionEngine * This, - /* [in] */ MUTEX_COOKIE mutex); - - void ( STDMETHODCALLTYPE *ClrCloseMutex )( - IExecutionEngine * This, - /* [in] */ MUTEX_COOKIE mutex); - - DWORD ( STDMETHODCALLTYPE *ClrSleepEx )( - IExecutionEngine * This, - /* [in] */ DWORD dwMilliseconds, - /* [in] */ BOOL bAlertable); - - BOOL ( STDMETHODCALLTYPE *ClrAllocationDisallowed )( - IExecutionEngine * This); - - void ( STDMETHODCALLTYPE *GetLastThrownObjectExceptionFromThread )( - IExecutionEngine * This, - /* [out] */ void **ppvException); - - END_INTERFACE - } IExecutionEngineVtbl; - - interface IExecutionEngine - { - CONST_VTBL struct IExecutionEngineVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IExecutionEngine_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) - -#define IExecutionEngine_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) - -#define IExecutionEngine_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) - - -#define IExecutionEngine_TLS_AssociateCallback(This,slot,callback) \ - ( (This)->lpVtbl -> TLS_AssociateCallback(This,slot,callback) ) - -#define IExecutionEngine_TLS_GetDataBlock(This) \ - ( (This)->lpVtbl -> TLS_GetDataBlock(This) ) - -#define IExecutionEngine_TLS_GetValue(This,slot) \ - ( (This)->lpVtbl -> TLS_GetValue(This,slot) ) - -#define IExecutionEngine_TLS_CheckValue(This,slot,pValue) \ - ( (This)->lpVtbl -> TLS_CheckValue(This,slot,pValue) ) - -#define IExecutionEngine_TLS_SetValue(This,slot,pData) \ - ( (This)->lpVtbl -> TLS_SetValue(This,slot,pData) ) - -#define IExecutionEngine_TLS_ThreadDetaching(This) \ - ( (This)->lpVtbl -> TLS_ThreadDetaching(This) ) - -#define IExecutionEngine_CreateLock(This,szTag,level,flags) \ - ( (This)->lpVtbl -> CreateLock(This,szTag,level,flags) ) - -#define IExecutionEngine_DestroyLock(This,lock) \ - ( (This)->lpVtbl -> DestroyLock(This,lock) ) - -#define IExecutionEngine_AcquireLock(This,lock) \ - ( (This)->lpVtbl -> AcquireLock(This,lock) ) - -#define IExecutionEngine_ReleaseLock(This,lock) \ - ( (This)->lpVtbl -> ReleaseLock(This,lock) ) - -#define IExecutionEngine_CreateAutoEvent(This,bInitialState) \ - ( (This)->lpVtbl -> CreateAutoEvent(This,bInitialState) ) - -#define IExecutionEngine_CreateManualEvent(This,bInitialState) \ - ( (This)->lpVtbl -> CreateManualEvent(This,bInitialState) ) - -#define IExecutionEngine_CloseEvent(This,event) \ - ( (This)->lpVtbl -> CloseEvent(This,event) ) - -#define IExecutionEngine_ClrSetEvent(This,event) \ - ( (This)->lpVtbl -> ClrSetEvent(This,event) ) - -#define IExecutionEngine_ClrResetEvent(This,event) \ - ( (This)->lpVtbl -> ClrResetEvent(This,event) ) - -#define IExecutionEngine_WaitForEvent(This,event,dwMilliseconds,bAlertable) \ - ( (This)->lpVtbl -> WaitForEvent(This,event,dwMilliseconds,bAlertable) ) - -#define IExecutionEngine_WaitForSingleObject(This,handle,dwMilliseconds) \ - ( (This)->lpVtbl -> WaitForSingleObject(This,handle,dwMilliseconds) ) - -#define IExecutionEngine_ClrCreateSemaphore(This,dwInitial,dwMax) \ - ( (This)->lpVtbl -> ClrCreateSemaphore(This,dwInitial,dwMax) ) - -#define IExecutionEngine_ClrCloseSemaphore(This,semaphore) \ - ( (This)->lpVtbl -> ClrCloseSemaphore(This,semaphore) ) - -#define IExecutionEngine_ClrWaitForSemaphore(This,semaphore,dwMilliseconds,bAlertable) \ - ( (This)->lpVtbl -> ClrWaitForSemaphore(This,semaphore,dwMilliseconds,bAlertable) ) - -#define IExecutionEngine_ClrReleaseSemaphore(This,semaphore,lReleaseCount,lpPreviousCount) \ - ( (This)->lpVtbl -> ClrReleaseSemaphore(This,semaphore,lReleaseCount,lpPreviousCount) ) - -#define IExecutionEngine_ClrCreateMutex(This,lpMutexAttributes,bInitialOwner,lpName) \ - ( (This)->lpVtbl -> ClrCreateMutex(This,lpMutexAttributes,bInitialOwner,lpName) ) - -#define IExecutionEngine_ClrWaitForMutex(This,mutex,dwMilliseconds,bAlertable) \ - ( (This)->lpVtbl -> ClrWaitForMutex(This,mutex,dwMilliseconds,bAlertable) ) - -#define IExecutionEngine_ClrReleaseMutex(This,mutex) \ - ( (This)->lpVtbl -> ClrReleaseMutex(This,mutex) ) - -#define IExecutionEngine_ClrCloseMutex(This,mutex) \ - ( (This)->lpVtbl -> ClrCloseMutex(This,mutex) ) - -#define IExecutionEngine_ClrSleepEx(This,dwMilliseconds,bAlertable) \ - ( (This)->lpVtbl -> ClrSleepEx(This,dwMilliseconds,bAlertable) ) - -#define IExecutionEngine_ClrAllocationDisallowed(This) \ - ( (This)->lpVtbl -> ClrAllocationDisallowed(This) ) - -#define IExecutionEngine_GetLastThrownObjectExceptionFromThread(This,ppvException) \ - ( (This)->lpVtbl -> GetLastThrownObjectExceptionFromThread(This,ppvException) ) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - - -#endif /* __IExecutionEngine_INTERFACE_DEFINED__ */ - - -/* interface __MIDL_itf_clrinternal_0000_0001 */ -/* [local] */ - -#if !defined(_WINNT_) && !defined(_NTMMAPI_) -typedef void *PMEMORY_BASIC_INFORMATION; - -#endif - - -extern RPC_IF_HANDLE __MIDL_itf_clrinternal_0000_0001_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_clrinternal_0000_0001_v0_0_s_ifspec; - -#ifndef __IEEMemoryManager_INTERFACE_DEFINED__ -#define __IEEMemoryManager_INTERFACE_DEFINED__ - -/* interface IEEMemoryManager */ -/* [object][local][unique][helpstring][uuid] */ - - -EXTERN_C const IID IID_IEEMemoryManager; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("17713B61-B59F-4e13-BAAF-91623DC8ADC0") - IEEMemoryManager : public IUnknown - { - public: - virtual LPVOID STDMETHODCALLTYPE ClrVirtualAlloc( - /* [in] */ LPVOID lpAddress, - /* [in] */ SIZE_T dwSize, - /* [in] */ DWORD flAllocationType, - /* [in] */ DWORD flProtect) = 0; - - virtual BOOL STDMETHODCALLTYPE ClrVirtualFree( - /* [in] */ LPVOID lpAddress, - /* [in] */ SIZE_T dwSize, - /* [in] */ DWORD dwFreeType) = 0; - - virtual SIZE_T STDMETHODCALLTYPE ClrVirtualQuery( - /* [in] */ const void *lpAddress, - /* [in] */ PMEMORY_BASIC_INFORMATION lpBuffer, - /* [in] */ SIZE_T dwLength) = 0; - - virtual BOOL STDMETHODCALLTYPE ClrVirtualProtect( - /* [in] */ LPVOID lpAddress, - /* [in] */ SIZE_T dwSize, - /* [in] */ DWORD flNewProtect, - /* [in] */ DWORD *lpflOldProtect) = 0; - - virtual HANDLE STDMETHODCALLTYPE ClrGetProcessHeap( void) = 0; - - virtual HANDLE STDMETHODCALLTYPE ClrHeapCreate( - /* [in] */ DWORD flOptions, - /* [in] */ SIZE_T dwInitialSize, - /* [in] */ SIZE_T dwMaximumSize) = 0; - - virtual BOOL STDMETHODCALLTYPE ClrHeapDestroy( - /* [in] */ HANDLE hHeap) = 0; - - virtual LPVOID STDMETHODCALLTYPE ClrHeapAlloc( - /* [in] */ HANDLE hHeap, - /* [in] */ DWORD dwFlags, - /* [in] */ SIZE_T dwBytes) = 0; - - virtual BOOL STDMETHODCALLTYPE ClrHeapFree( - /* [in] */ HANDLE hHeap, - /* [in] */ DWORD dwFlags, - /* [in] */ LPVOID lpMem) = 0; - - virtual BOOL STDMETHODCALLTYPE ClrHeapValidate( - /* [in] */ HANDLE hHeap, - /* [in] */ DWORD dwFlags, - /* [in] */ const void *lpMem) = 0; - - virtual HANDLE STDMETHODCALLTYPE ClrGetProcessExecutableHeap( void) = 0; - - }; - - -#else /* C style interface */ - - typedef struct IEEMemoryManagerVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IEEMemoryManager * This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IEEMemoryManager * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IEEMemoryManager * This); - - LPVOID ( STDMETHODCALLTYPE *ClrVirtualAlloc )( - IEEMemoryManager * This, - /* [in] */ LPVOID lpAddress, - /* [in] */ SIZE_T dwSize, - /* [in] */ DWORD flAllocationType, - /* [in] */ DWORD flProtect); - - BOOL ( STDMETHODCALLTYPE *ClrVirtualFree )( - IEEMemoryManager * This, - /* [in] */ LPVOID lpAddress, - /* [in] */ SIZE_T dwSize, - /* [in] */ DWORD dwFreeType); - - SIZE_T ( STDMETHODCALLTYPE *ClrVirtualQuery )( - IEEMemoryManager * This, - /* [in] */ const void *lpAddress, - /* [in] */ PMEMORY_BASIC_INFORMATION lpBuffer, - /* [in] */ SIZE_T dwLength); - - BOOL ( STDMETHODCALLTYPE *ClrVirtualProtect )( - IEEMemoryManager * This, - /* [in] */ LPVOID lpAddress, - /* [in] */ SIZE_T dwSize, - /* [in] */ DWORD flNewProtect, - /* [in] */ DWORD *lpflOldProtect); - - HANDLE ( STDMETHODCALLTYPE *ClrGetProcessHeap )( - IEEMemoryManager * This); - - HANDLE ( STDMETHODCALLTYPE *ClrHeapCreate )( - IEEMemoryManager * This, - /* [in] */ DWORD flOptions, - /* [in] */ SIZE_T dwInitialSize, - /* [in] */ SIZE_T dwMaximumSize); - - BOOL ( STDMETHODCALLTYPE *ClrHeapDestroy )( - IEEMemoryManager * This, - /* [in] */ HANDLE hHeap); - - LPVOID ( STDMETHODCALLTYPE *ClrHeapAlloc )( - IEEMemoryManager * This, - /* [in] */ HANDLE hHeap, - /* [in] */ DWORD dwFlags, - /* [in] */ SIZE_T dwBytes); - - BOOL ( STDMETHODCALLTYPE *ClrHeapFree )( - IEEMemoryManager * This, - /* [in] */ HANDLE hHeap, - /* [in] */ DWORD dwFlags, - /* [in] */ LPVOID lpMem); - - BOOL ( STDMETHODCALLTYPE *ClrHeapValidate )( - IEEMemoryManager * This, - /* [in] */ HANDLE hHeap, - /* [in] */ DWORD dwFlags, - /* [in] */ const void *lpMem); - - HANDLE ( STDMETHODCALLTYPE *ClrGetProcessExecutableHeap )( - IEEMemoryManager * This); - - END_INTERFACE - } IEEMemoryManagerVtbl; - - interface IEEMemoryManager - { - CONST_VTBL struct IEEMemoryManagerVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IEEMemoryManager_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) - -#define IEEMemoryManager_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) - -#define IEEMemoryManager_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) - - -#define IEEMemoryManager_ClrVirtualAlloc(This,lpAddress,dwSize,flAllocationType,flProtect) \ - ( (This)->lpVtbl -> ClrVirtualAlloc(This,lpAddress,dwSize,flAllocationType,flProtect) ) - -#define IEEMemoryManager_ClrVirtualFree(This,lpAddress,dwSize,dwFreeType) \ - ( (This)->lpVtbl -> ClrVirtualFree(This,lpAddress,dwSize,dwFreeType) ) - -#define IEEMemoryManager_ClrVirtualQuery(This,lpAddress,lpBuffer,dwLength) \ - ( (This)->lpVtbl -> ClrVirtualQuery(This,lpAddress,lpBuffer,dwLength) ) - -#define IEEMemoryManager_ClrVirtualProtect(This,lpAddress,dwSize,flNewProtect,lpflOldProtect) \ - ( (This)->lpVtbl -> ClrVirtualProtect(This,lpAddress,dwSize,flNewProtect,lpflOldProtect) ) - -#define IEEMemoryManager_ClrGetProcessHeap(This) \ - ( (This)->lpVtbl -> ClrGetProcessHeap(This) ) - -#define IEEMemoryManager_ClrHeapCreate(This,flOptions,dwInitialSize,dwMaximumSize) \ - ( (This)->lpVtbl -> ClrHeapCreate(This,flOptions,dwInitialSize,dwMaximumSize) ) - -#define IEEMemoryManager_ClrHeapDestroy(This,hHeap) \ - ( (This)->lpVtbl -> ClrHeapDestroy(This,hHeap) ) - -#define IEEMemoryManager_ClrHeapAlloc(This,hHeap,dwFlags,dwBytes) \ - ( (This)->lpVtbl -> ClrHeapAlloc(This,hHeap,dwFlags,dwBytes) ) - -#define IEEMemoryManager_ClrHeapFree(This,hHeap,dwFlags,lpMem) \ - ( (This)->lpVtbl -> ClrHeapFree(This,hHeap,dwFlags,lpMem) ) - -#define IEEMemoryManager_ClrHeapValidate(This,hHeap,dwFlags,lpMem) \ - ( (This)->lpVtbl -> ClrHeapValidate(This,hHeap,dwFlags,lpMem) ) - -#define IEEMemoryManager_ClrGetProcessExecutableHeap(This) \ - ( (This)->lpVtbl -> ClrGetProcessExecutableHeap(This) ) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - - -#endif /* __IEEMemoryManager_INTERFACE_DEFINED__ */ - - #ifndef __IPrivateManagedExceptionReporting_INTERFACE_DEFINED__ #define __IPrivateManagedExceptionReporting_INTERFACE_DEFINED__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrprivbinding.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrprivbinding.h index ceb11fe..61094d1 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrprivbinding.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrprivbinding.h @@ -23,15 +23,15 @@ #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of -#endif // __RPCNDR_H_VERSION__ +#endif /* __RPCNDR_H_VERSION__ */ #ifndef COM_NO_WINDOWS_H #include "windows.h" #include "ole2.h" #endif /*COM_NO_WINDOWS_H*/ -#ifndef __CLRPrivBinding_h__ -#define __CLRPrivBinding_h__ +#ifndef __clrprivbinding_h__ +#define __clrprivbinding_h__ #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once @@ -67,20 +67,6 @@ typedef interface ICLRPrivResourcePath ICLRPrivResourcePath; #endif /* __ICLRPrivResourcePath_FWD_DEFINED__ */ -#ifndef __ICLRPrivResourceStream_FWD_DEFINED__ -#define __ICLRPrivResourceStream_FWD_DEFINED__ -typedef interface ICLRPrivResourceStream ICLRPrivResourceStream; - -#endif /* __ICLRPrivResourceStream_FWD_DEFINED__ */ - - -#ifndef __ICLRPrivResourceHMODULE_FWD_DEFINED__ -#define __ICLRPrivResourceHMODULE_FWD_DEFINED__ -typedef interface ICLRPrivResourceHMODULE ICLRPrivResourceHMODULE; - -#endif /* __ICLRPrivResourceHMODULE_FWD_DEFINED__ */ - - #ifndef __ICLRPrivResourceAssembly_FWD_DEFINED__ #define __ICLRPrivResourceAssembly_FWD_DEFINED__ typedef interface ICLRPrivResourceAssembly ICLRPrivResourceAssembly; @@ -102,13 +88,6 @@ typedef interface ICLRPrivAssemblyID_WinRT ICLRPrivAssemblyID_WinRT; #endif /* __ICLRPrivAssemblyID_WinRT_FWD_DEFINED__ */ -#ifndef __ICLRPrivWinRtTypeBinder_FWD_DEFINED__ -#define __ICLRPrivWinRtTypeBinder_FWD_DEFINED__ -typedef interface ICLRPrivWinRtTypeBinder ICLRPrivWinRtTypeBinder; - -#endif /* __ICLRPrivWinRtTypeBinder_FWD_DEFINED__ */ - - /* header files for imported files */ #include "unknwn.h" #include "objidl.h" @@ -119,7 +98,7 @@ extern "C"{ #endif -/* interface __MIDL_itf_CLRPrivBinding_0000_0000 */ +/* interface __MIDL_itf_clrprivbinding_0000_0000 */ /* [local] */ @@ -127,14 +106,12 @@ extern "C"{ - - typedef LPCSTR LPCUTF8; -extern RPC_IF_HANDLE __MIDL_itf_CLRPrivBinding_0000_0000_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_CLRPrivBinding_0000_0000_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_clrprivbinding_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_clrprivbinding_0000_0000_v0_0_s_ifspec; #ifndef __ICLRPrivBinder_INTERFACE_DEFINED__ #define __ICLRPrivBinder_INTERFACE_DEFINED__ @@ -158,8 +135,9 @@ EXTERN_C const IID IID_ICLRPrivBinder; virtual HRESULT STDMETHODCALLTYPE GetBinderID( /* [retval][out] */ UINT_PTR *pBinderId) = 0; - virtual HRESULT STDMETHODCALLTYPE GetLoaderAllocator( - /* [retval][out] */ LPVOID* pLoaderAllocator) = 0; + virtual HRESULT STDMETHODCALLTYPE GetLoaderAllocator( + /* [retval][out] */ LPVOID *pLoaderAllocator) = 0; + }; @@ -190,10 +168,10 @@ EXTERN_C const IID IID_ICLRPrivBinder; ICLRPrivBinder * This, /* [retval][out] */ UINT_PTR *pBinderId); - HRESULT(STDMETHODCALLTYPE *GetLoaderAllocator)( + HRESULT ( STDMETHODCALLTYPE *GetLoaderAllocator )( ICLRPrivBinder * This, - /* [retval][out] */ LPVOID *pLoaderAllocator) = 0; - + /* [retval][out] */ LPVOID *pLoaderAllocator); + END_INTERFACE } ICLRPrivBinderVtbl; @@ -223,6 +201,9 @@ EXTERN_C const IID IID_ICLRPrivBinder; #define ICLRPrivBinder_GetBinderID(This,pBinderId) \ ( (This)->lpVtbl -> GetBinderID(This,pBinderId) ) +#define ICLRPrivBinder_GetLoaderAllocator(This,pLoaderAllocator) \ + ( (This)->lpVtbl -> GetLoaderAllocator(This,pLoaderAllocator) ) + #endif /* COBJMACROS */ @@ -234,7 +215,7 @@ EXTERN_C const IID IID_ICLRPrivBinder; #endif /* __ICLRPrivBinder_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_CLRPrivBinding_0000_0001 */ +/* interface __MIDL_itf_clrprivbinding_0000_0001 */ /* [local] */ @@ -247,8 +228,8 @@ enum ASSEMBLY_IMAGE_TYPES } ; -extern RPC_IF_HANDLE __MIDL_itf_CLRPrivBinding_0000_0001_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_CLRPrivBinding_0000_0001_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_clrprivbinding_0000_0001_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_clrprivbinding_0000_0001_v0_0_s_ifspec; #ifndef __ICLRPrivAssembly_INTERFACE_DEFINED__ #define __ICLRPrivAssembly_INTERFACE_DEFINED__ @@ -265,9 +246,6 @@ EXTERN_C const IID IID_ICLRPrivAssembly; ICLRPrivAssembly : public ICLRPrivBinder { public: - virtual HRESULT STDMETHODCALLTYPE IsShareable( - /* [retval][out] */ BOOL *pbIsShareable) = 0; - virtual HRESULT STDMETHODCALLTYPE GetAvailableImageTypes( /* [retval][out] */ LPDWORD pdwImageTypes) = 0; @@ -306,9 +284,9 @@ EXTERN_C const IID IID_ICLRPrivAssembly; ICLRPrivAssembly * This, /* [retval][out] */ UINT_PTR *pBinderId); - HRESULT ( STDMETHODCALLTYPE *IsShareable )( + HRESULT ( STDMETHODCALLTYPE *GetLoaderAllocator )( ICLRPrivAssembly * This, - /* [retval][out] */ BOOL *pbIsShareable); + /* [retval][out] */ LPVOID *pLoaderAllocator); HRESULT ( STDMETHODCALLTYPE *GetAvailableImageTypes )( ICLRPrivAssembly * This, @@ -349,9 +327,9 @@ EXTERN_C const IID IID_ICLRPrivAssembly; #define ICLRPrivAssembly_GetBinderID(This,pBinderId) \ ( (This)->lpVtbl -> GetBinderID(This,pBinderId) ) +#define ICLRPrivAssembly_GetLoaderAllocator(This,pLoaderAllocator) \ + ( (This)->lpVtbl -> GetLoaderAllocator(This,pLoaderAllocator) ) -#define ICLRPrivAssembly_IsShareable(This,pbIsShareable) \ - ( (This)->lpVtbl -> IsShareable(This,pbIsShareable) ) #define ICLRPrivAssembly_GetAvailableImageTypes(This,pdwImageTypes) \ ( (This)->lpVtbl -> GetAvailableImageTypes(This,pdwImageTypes) ) @@ -534,168 +512,6 @@ EXTERN_C const IID IID_ICLRPrivResourcePath; #endif /* __ICLRPrivResourcePath_INTERFACE_DEFINED__ */ -#ifndef __ICLRPrivResourceStream_INTERFACE_DEFINED__ -#define __ICLRPrivResourceStream_INTERFACE_DEFINED__ - -/* interface ICLRPrivResourceStream */ -/* [object][local][version][uuid] */ - - -EXTERN_C const IID IID_ICLRPrivResourceStream; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("2601F621-E462-404C-B299-3E1DE72F8545") - ICLRPrivResourceStream : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE GetStream( - /* [in] */ REFIID riid, - /* [retval][iid_is][out] */ LPVOID *ppvStream) = 0; - - }; - - -#else /* C style interface */ - - typedef struct ICLRPrivResourceStreamVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICLRPrivResourceStream * This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - ICLRPrivResourceStream * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - ICLRPrivResourceStream * This); - - HRESULT ( STDMETHODCALLTYPE *GetStream )( - ICLRPrivResourceStream * This, - /* [in] */ REFIID riid, - /* [retval][iid_is][out] */ LPVOID *ppvStream); - - END_INTERFACE - } ICLRPrivResourceStreamVtbl; - - interface ICLRPrivResourceStream - { - CONST_VTBL struct ICLRPrivResourceStreamVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define ICLRPrivResourceStream_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) - -#define ICLRPrivResourceStream_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) - -#define ICLRPrivResourceStream_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) - - -#define ICLRPrivResourceStream_GetStream(This,riid,ppvStream) \ - ( (This)->lpVtbl -> GetStream(This,riid,ppvStream) ) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - - -#endif /* __ICLRPrivResourceStream_INTERFACE_DEFINED__ */ - - -#ifndef __ICLRPrivResourceHMODULE_INTERFACE_DEFINED__ -#define __ICLRPrivResourceHMODULE_INTERFACE_DEFINED__ - -/* interface ICLRPrivResourceHMODULE */ -/* [object][local][version][uuid] */ - - -EXTERN_C const IID IID_ICLRPrivResourceHMODULE; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("2601F621-E462-404C-B299-3E1DE72F8546") - ICLRPrivResourceHMODULE : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE GetHMODULE( - /* [retval][out] */ HMODULE *phModule) = 0; - - }; - - -#else /* C style interface */ - - typedef struct ICLRPrivResourceHMODULEVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICLRPrivResourceHMODULE * This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - ICLRPrivResourceHMODULE * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - ICLRPrivResourceHMODULE * This); - - HRESULT ( STDMETHODCALLTYPE *GetHMODULE )( - ICLRPrivResourceHMODULE * This, - /* [retval][out] */ HMODULE *phModule); - - END_INTERFACE - } ICLRPrivResourceHMODULEVtbl; - - interface ICLRPrivResourceHMODULE - { - CONST_VTBL struct ICLRPrivResourceHMODULEVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define ICLRPrivResourceHMODULE_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) - -#define ICLRPrivResourceHMODULE_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) - -#define ICLRPrivResourceHMODULE_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) - - -#define ICLRPrivResourceHMODULE_GetHMODULE(This,phModule) \ - ( (This)->lpVtbl -> GetHMODULE(This,phModule) ) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - - -#endif /* __ICLRPrivResourceHMODULE_INTERFACE_DEFINED__ */ - - #ifndef __ICLRPrivResourceAssembly_INTERFACE_DEFINED__ #define __ICLRPrivResourceAssembly_INTERFACE_DEFINED__ @@ -960,90 +776,6 @@ EXTERN_C const IID IID_ICLRPrivAssemblyID_WinRT; #endif /* __ICLRPrivAssemblyID_WinRT_INTERFACE_DEFINED__ */ -#ifndef __ICLRPrivWinRtTypeBinder_INTERFACE_DEFINED__ -#define __ICLRPrivWinRtTypeBinder_INTERFACE_DEFINED__ - -/* interface ICLRPrivWinRtTypeBinder */ -/* [object][local][version][uuid] */ - - -EXTERN_C const IID IID_ICLRPrivWinRtTypeBinder; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("6DE2A085-EFF4-4078-9F60-B9D366736398") - ICLRPrivWinRtTypeBinder : public IUnknown - { - public: - virtual void *STDMETHODCALLTYPE FindAssemblyForWinRtTypeIfLoaded( - void *pAppDomain, - LPCUTF8 szNamespace, - LPCUTF8 szClassName) = 0; - - }; - - -#else /* C style interface */ - - typedef struct ICLRPrivWinRtTypeBinderVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICLRPrivWinRtTypeBinder * This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - ICLRPrivWinRtTypeBinder * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - ICLRPrivWinRtTypeBinder * This); - - void *( STDMETHODCALLTYPE *FindAssemblyForWinRtTypeIfLoaded )( - ICLRPrivWinRtTypeBinder * This, - void *pAppDomain, - LPCUTF8 szNamespace, - LPCUTF8 szClassName); - - END_INTERFACE - } ICLRPrivWinRtTypeBinderVtbl; - - interface ICLRPrivWinRtTypeBinder - { - CONST_VTBL struct ICLRPrivWinRtTypeBinderVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define ICLRPrivWinRtTypeBinder_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) - -#define ICLRPrivWinRtTypeBinder_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) - -#define ICLRPrivWinRtTypeBinder_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) - - -#define ICLRPrivWinRtTypeBinder_FindAssemblyForWinRtTypeIfLoaded(This,pAppDomain,szNamespace,szClassName) \ - ( (This)->lpVtbl -> FindAssemblyForWinRtTypeIfLoaded(This,pAppDomain,szNamespace,szClassName) ) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - - -#endif /* __ICLRPrivWinRtTypeBinder_INTERFACE_DEFINED__ */ - - /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrprivhosting.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrprivhosting.h deleted file mode 100644 index c0c3fd3..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrprivhosting.h +++ /dev/null @@ -1,236 +0,0 @@ -// 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. - - - -/* this ALWAYS GENERATED file contains the definitions for the interfaces */ - - - /* File created by MIDL compiler version 8.00.0603 */ -/* @@MIDL_FILE_HEADING( ) */ - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ - - -/* verify that the version is high enough to compile this file*/ -#ifndef __REQUIRED_RPCNDR_H_VERSION__ -#define __REQUIRED_RPCNDR_H_VERSION__ 475 -#endif - -#include "rpc.h" -#include "rpcndr.h" - -#ifndef __RPCNDR_H_VERSION__ -#error this stub requires an updated version of -#endif // __RPCNDR_H_VERSION__ - -#ifndef COM_NO_WINDOWS_H -#include "windows.h" -#include "ole2.h" -#endif /*COM_NO_WINDOWS_H*/ - -#ifndef __CLRPrivHosting_h__ -#define __CLRPrivHosting_h__ - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -#pragma once -#endif - -/* Forward Declarations */ - -#ifndef __CLRPrivRuntime_FWD_DEFINED__ -#define __CLRPrivRuntime_FWD_DEFINED__ - -#ifdef __cplusplus -typedef class CLRPrivRuntime CLRPrivRuntime; -#else -typedef struct CLRPrivRuntime CLRPrivRuntime; -#endif /* __cplusplus */ - -#endif /* __CLRPrivRuntime_FWD_DEFINED__ */ - - -#ifndef __ICLRPrivRuntime_FWD_DEFINED__ -#define __ICLRPrivRuntime_FWD_DEFINED__ -typedef interface ICLRPrivRuntime ICLRPrivRuntime; - -#endif /* __ICLRPrivRuntime_FWD_DEFINED__ */ - - -/* header files for imported files */ -#include "unknwn.h" -#include "clrprivbinding.h" - -#ifdef __cplusplus -extern "C"{ -#endif - - -/* interface __MIDL_itf_CLRPrivHosting_0000_0000 */ -/* [local] */ - - - - -extern RPC_IF_HANDLE __MIDL_itf_CLRPrivHosting_0000_0000_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_CLRPrivHosting_0000_0000_v0_0_s_ifspec; - - -#ifndef __CLRPrivHosting_LIBRARY_DEFINED__ -#define __CLRPrivHosting_LIBRARY_DEFINED__ - -/* library CLRPrivHosting */ -/* [uuid] */ - - -EXTERN_C const IID LIBID_CLRPrivHosting; - -EXTERN_C const CLSID CLSID_CLRPrivRuntime; - -#ifdef __cplusplus - -class DECLSPEC_UUID("BC1B53A8-DCBC-43B2-BB17-1E4061447AE8") -CLRPrivRuntime; -#endif -#endif /* __CLRPrivHosting_LIBRARY_DEFINED__ */ - -#ifndef __ICLRPrivRuntime_INTERFACE_DEFINED__ -#define __ICLRPrivRuntime_INTERFACE_DEFINED__ - -/* interface ICLRPrivRuntime */ -/* [object][local][version][uuid] */ - - -EXTERN_C const IID IID_ICLRPrivRuntime; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("BC1B53A8-DCBC-43B2-BB17-1E4061447AE9") - ICLRPrivRuntime : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE GetInterface( - /* [in] */ REFCLSID rclsid, - /* [in] */ REFIID riid, - /* [retval][iid_is][out] */ LPVOID *ppUnk) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateAppDomain( - /* [string][in] */ LPCWSTR pwzFriendlyName, - /* [in] */ ICLRPrivBinder *pBinder, - /* [retval][out] */ LPDWORD pdwAppDomainId) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateDelegate( - /* [in] */ DWORD appDomainID, - /* [string][in] */ LPCWSTR wszAssemblyName, - /* [string][in] */ LPCWSTR wszClassName, - /* [string][in] */ LPCWSTR wszMethodName, - /* [retval][out] */ LPVOID *ppvDelegate) = 0; - - virtual HRESULT STDMETHODCALLTYPE ExecuteMain( - /* [in] */ ICLRPrivBinder *pBinder, - /* [retval][out] */ int *pRetVal) = 0; - - }; - - -#else /* C style interface */ - - typedef struct ICLRPrivRuntimeVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICLRPrivRuntime * This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - ICLRPrivRuntime * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - ICLRPrivRuntime * This); - - HRESULT ( STDMETHODCALLTYPE *GetInterface )( - ICLRPrivRuntime * This, - /* [in] */ REFCLSID rclsid, - /* [in] */ REFIID riid, - /* [retval][iid_is][out] */ LPVOID *ppUnk); - - HRESULT ( STDMETHODCALLTYPE *CreateAppDomain )( - ICLRPrivRuntime * This, - /* [string][in] */ LPCWSTR pwzFriendlyName, - /* [in] */ ICLRPrivBinder *pBinder, - /* [retval][out] */ LPDWORD pdwAppDomainId); - - HRESULT ( STDMETHODCALLTYPE *CreateDelegate )( - ICLRPrivRuntime * This, - /* [in] */ DWORD appDomainID, - /* [string][in] */ LPCWSTR wszAssemblyName, - /* [string][in] */ LPCWSTR wszClassName, - /* [string][in] */ LPCWSTR wszMethodName, - /* [retval][out] */ LPVOID *ppvDelegate); - - HRESULT ( STDMETHODCALLTYPE *ExecuteMain )( - ICLRPrivRuntime * This, - /* [in] */ ICLRPrivBinder *pBinder, - /* [retval][out] */ int *pRetVal); - - END_INTERFACE - } ICLRPrivRuntimeVtbl; - - interface ICLRPrivRuntime - { - CONST_VTBL struct ICLRPrivRuntimeVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define ICLRPrivRuntime_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) - -#define ICLRPrivRuntime_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) - -#define ICLRPrivRuntime_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) - - -#define ICLRPrivRuntime_GetInterface(This,rclsid,riid,ppUnk) \ - ( (This)->lpVtbl -> GetInterface(This,rclsid,riid,ppUnk) ) - -#define ICLRPrivRuntime_CreateAppDomain(This,pwzFriendlyName,pBinder,pdwAppDomainId) \ - ( (This)->lpVtbl -> CreateAppDomain(This,pwzFriendlyName,pBinder,pdwAppDomainId) ) - -#define ICLRPrivRuntime_CreateDelegate(This,appDomainID,wszAssemblyName,wszClassName,wszMethodName,ppvDelegate) \ - ( (This)->lpVtbl -> CreateDelegate(This,appDomainID,wszAssemblyName,wszClassName,wszMethodName,ppvDelegate) ) - -#define ICLRPrivRuntime_ExecuteMain(This,pBinder,pRetVal) \ - ( (This)->lpVtbl -> ExecuteMain(This,pBinder,pRetVal) ) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - - -#endif /* __ICLRPrivRuntime_INTERFACE_DEFINED__ */ - - -/* Additional Prototypes for ALL interfaces */ - -/* end of Additional Prototypes */ - -#ifdef __cplusplus -} -#endif - -#endif - - diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrprivruntimebinders.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrprivruntimebinders.h deleted file mode 100644 index dc4324a..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/clrprivruntimebinders.h +++ /dev/null @@ -1,107 +0,0 @@ -// 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. - - - -/* this ALWAYS GENERATED file contains the definitions for the interfaces */ - - - /* File created by MIDL compiler version 8.00.0603 */ -/* @@MIDL_FILE_HEADING( ) */ - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ - - -/* verify that the version is high enough to compile this file*/ -#ifndef __REQUIRED_RPCNDR_H_VERSION__ -#define __REQUIRED_RPCNDR_H_VERSION__ 475 -#endif - -#include "rpc.h" -#include "rpcndr.h" - -#ifndef __RPCNDR_H_VERSION__ -#error this stub requires an updated version of -#endif // __RPCNDR_H_VERSION__ - - -#ifndef __CLRPrivRuntimeBinders_h__ -#define __CLRPrivRuntimeBinders_h__ - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -#pragma once -#endif - -/* Forward Declarations */ - -#ifndef __CLRPrivAppXBinder_FWD_DEFINED__ -#define __CLRPrivAppXBinder_FWD_DEFINED__ - -#ifdef __cplusplus -typedef class CLRPrivAppXBinder CLRPrivAppXBinder; -#else -typedef struct CLRPrivAppXBinder CLRPrivAppXBinder; -#endif /* __cplusplus */ - -#endif /* __CLRPrivAppXBinder_FWD_DEFINED__ */ - - -#ifndef __CLRPrivFusionBinder_FWD_DEFINED__ -#define __CLRPrivFusionBinder_FWD_DEFINED__ - -#ifdef __cplusplus -typedef class CLRPrivFusionBinder CLRPrivFusionBinder; -#else -typedef struct CLRPrivFusionBinder CLRPrivFusionBinder; -#endif /* __cplusplus */ - -#endif /* __CLRPrivFusionBinder_FWD_DEFINED__ */ - - -/* header files for imported files */ -#include "clrprivbinding.h" - -#ifdef __cplusplus -extern "C"{ -#endif - - - -#ifndef __CLRPrivRuntimeBinders_LIBRARY_DEFINED__ -#define __CLRPrivRuntimeBinders_LIBRARY_DEFINED__ - -/* library CLRPrivRuntimeBinders */ -/* [uuid] */ - - -EXTERN_C const IID LIBID_CLRPrivRuntimeBinders; - -EXTERN_C const CLSID CLSID_CLRPrivAppXBinder; - -#ifdef __cplusplus - -class DECLSPEC_UUID("E990F732-2D0A-48AC-87FC-EF12B618981A") -CLRPrivAppXBinder; -#endif - -EXTERN_C const CLSID CLSID_CLRPrivFusionBinder; - -#ifdef __cplusplus - -class DECLSPEC_UUID("E990F732-2D0A-48AC-87FC-EF12B618981C") -CLRPrivFusionBinder; -#endif -#endif /* __CLRPrivRuntimeBinders_LIBRARY_DEFINED__ */ - -/* Additional Prototypes for ALL interfaces */ - -/* end of Additional Prototypes */ - -#ifdef __cplusplus -} -#endif - -#endif - - diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/corprof.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/corprof.h index 2717067..4a2444f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/corprof.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/corprof.h @@ -6,7 +6,7 @@ /* File created by MIDL compiler version 8.01.0622 */ /* at Mon Jan 18 19:14:07 2038 */ -/* Compiler settings for C:/git/coreclr/src/inc/corprof.idl: +/* Compiler settings for C:/git/runtime/src/coreclr/src/inc/corprof.idl: Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data @@ -213,6 +213,20 @@ typedef interface ICorProfilerInfo10 ICorProfilerInfo10; #endif /* __ICorProfilerInfo10_FWD_DEFINED__ */ +#ifndef __ICorProfilerInfo11_FWD_DEFINED__ +#define __ICorProfilerInfo11_FWD_DEFINED__ +typedef interface ICorProfilerInfo11 ICorProfilerInfo11; + +#endif /* __ICorProfilerInfo11_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerInfo12_FWD_DEFINED__ +#define __ICorProfilerInfo12_FWD_DEFINED__ +typedef interface ICorProfilerInfo12 ICorProfilerInfo12; + +#endif /* __ICorProfilerInfo12_FWD_DEFINED__ */ + + #ifndef __ICorProfilerMethodEnum_FWD_DEFINED__ #define __ICorProfilerMethodEnum_FWD_DEFINED__ typedef interface ICorProfilerMethodEnum ICorProfilerMethodEnum; @@ -582,7 +596,8 @@ enum __MIDL___MIDL_itf_corprof_0000_0000_0010 COR_PRF_SUSPEND_FOR_SHUTDOWN = 4, COR_PRF_SUSPEND_FOR_INPROC_DEBUGGER = 6, COR_PRF_SUSPEND_FOR_GC_PREP = 7, - COR_PRF_SUSPEND_FOR_REJIT = 8 + COR_PRF_SUSPEND_FOR_REJIT = 8, + COR_PRF_SUSPEND_FOR_PROFILER = 9 } COR_PRF_SUSPEND_REASON; typedef /* [public][public] */ @@ -599,6 +614,55 @@ enum __MIDL___MIDL_itf_corprof_0000_0000_0012 COR_PRF_REJIT_INLINING_CALLBACKS = 0x2 } COR_PRF_REJIT_FLAGS; +typedef UINT_PTR EVENTPIPE_PROVIDER; + +typedef UINT_PTR EVENTPIPE_EVENT; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_corprof_0000_0000_0013 + { + COR_PRF_EVENTPIPE_BOOLEAN = 3, + COR_PRF_EVENTPIPE_CHAR = 4, + COR_PRF_EVENTPIPE_SBYTE = 5, + COR_PRF_EVENTPIPE_BYTE = 6, + COR_PRF_EVENTPIPE_INT16 = 7, + COR_PRF_EVENTPIPE_UINT16 = 8, + COR_PRF_EVENTPIPE_INT32 = 9, + COR_PRF_EVENTPIPE_UINT32 = 10, + COR_PRF_EVENTPIPE_INT64 = 11, + COR_PRF_EVENTPIPE_UINT64 = 12, + COR_PRF_EVENTPIPE_SINGLE = 13, + COR_PRF_EVENTPIPE_DOUBLE = 14, + COR_PRF_EVENTPIPE_DECIMAL = 15, + COR_PRF_EVENTPIPE_DATETIME = 16, + COR_PRF_EVENTPIPE_GUID = 17, + COR_PRF_EVENTPIPE_STRING = 18 + } COR_PRF_EVENTPIPE_PARAM_TYPE; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_corprof_0000_0000_0014 + { + COR_PRF_EVENTPIPE_LOGALWAYS = 0, + COR_PRF_EVENTPIPE_CRITICAL = 1, + COR_PRF_EVENTPIPE_ERROR = 2, + COR_PRF_EVENTPIPE_WARNING = 3, + COR_PRF_EVENTPIPE_INFORMATIONAL = 4, + COR_PRF_EVENTPIPE_VERBOSE = 5 + } COR_PRF_EVENTPIPE_LEVEL; + +typedef /* [public][public] */ struct __MIDL___MIDL_itf_corprof_0000_0000_0015 + { + UINT32 type; + const WCHAR *name; + } COR_PRF_EVENTPIPE_PARAM_DESC; + +typedef /* [public][public] */ struct __MIDL___MIDL_itf_corprof_0000_0000_0016 + { + UINT64 ptr; + UINT32 size; + UINT32 reserved; + } COR_PRF_EVENT_DATA; + @@ -1459,7 +1523,8 @@ enum __MIDL___MIDL_itf_corprof_0000_0001_0004 COR_PRF_GC_GEN_0 = 0, COR_PRF_GC_GEN_1 = 1, COR_PRF_GC_GEN_2 = 2, - COR_PRF_GC_LARGE_OBJECT_HEAP = 3 + COR_PRF_GC_LARGE_OBJECT_HEAP = 3, + COR_PRF_GC_PINNED_OBJECT_HEAP = 4 } COR_PRF_GC_GENERATION; typedef struct COR_PRF_GC_GENERATION_RANGE @@ -16156,6 +16221,2034 @@ EXTERN_C const IID IID_ICorProfilerInfo10; #endif /* __ICorProfilerInfo10_INTERFACE_DEFINED__ */ +#ifndef __ICorProfilerInfo11_INTERFACE_DEFINED__ +#define __ICorProfilerInfo11_INTERFACE_DEFINED__ + +/* interface ICorProfilerInfo11 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerInfo11; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("06398876-8987-4154-B621-40A00D6E4D04") + ICorProfilerInfo11 : public ICorProfilerInfo10 + { + public: + virtual HRESULT STDMETHODCALLTYPE GetEnvironmentVariable( + /* [string][in] */ const WCHAR *szName, + /* [in] */ ULONG cchValue, + /* [out] */ ULONG *pcchValue, + /* [annotation][out] */ + _Out_writes_to_(cchValue, *pcchValue) WCHAR szValue[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetEnvironmentVariable( + /* [string][in] */ const WCHAR *szName, + /* [string][in] */ const WCHAR *szValue) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerInfo11Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerInfo11 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerInfo11 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerInfo11 * This); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( + ICorProfilerInfo11 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask )( + ICorProfilerInfo11 * This, + /* [out] */ DWORD *pdwEvents); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( + ICorProfilerInfo11 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( + ICorProfilerInfo11 * This, + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorProfilerInfo11 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( + ICorProfilerInfo11 * This, + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank); + + HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( + ICorProfilerInfo11 * This, + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICorProfilerInfo11 * This, + /* [out] */ ThreadID *pThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( + ICorProfilerInfo11 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask )( + ICorProfilerInfo11 * This, + /* [in] */ DWORD dwEvents); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionIDMapper *pFunc); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId); + + HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( + ICorProfilerInfo11 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( + ICorProfilerInfo11 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ForceGC )( + ICorProfilerInfo11 * This); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( + ICorProfilerInfo11 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( + ICorProfilerInfo11 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorProfilerInfo11 * This, + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId); + + HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( + ICorProfilerInfo11 * This, + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( + ICorProfilerInfo11 * This, + /* [in] */ DWORD dwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( + ICorProfilerInfo11 * This, + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( + ICorProfilerInfo11 * This, + /* [out] */ ULONG *pBufferLengthOffset, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( + ICorProfilerInfo11 * This, + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( + ICorProfilerInfo11 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID); + + HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( + ICorProfilerInfo11 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData); + + HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( + ICorProfilerInfo11 * This, + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( + ICorProfilerInfo11 * This, + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( + ICorProfilerInfo11 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( + ICorProfilerInfo11 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( + ICorProfilerInfo11 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( + ICorProfilerInfo11 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( + ICorProfilerInfo11 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); + + HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( + ICorProfilerInfo11 * This, + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( + ICorProfilerInfo11 * This, + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); + + HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( + ICorProfilerInfo11 * This, + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( + ICorProfilerInfo11 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( + ICorProfilerInfo11 * This, + /* [in] */ DWORD dwExpectedCompletionMilliseconds); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionIDMapper2 *pFunc, + /* [in] */ void *clientData); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( + ICorProfilerInfo11 * This, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionEnter3 *pFuncEnter3, + /* [in] */ FunctionLeave3 *pFuncLeave3, + /* [in] */ FunctionTailcall3 *pFuncTailcall3); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, + /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out][in] */ ULONG *pcbArgumentInfo, + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); + + HRESULT ( STDMETHODCALLTYPE *EnumModules )( + ICorProfilerInfo11 * This, + /* [out] */ ICorProfilerModuleEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( + ICorProfilerInfo11 * This, + /* [out] */ USHORT *pClrInstanceId, + /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, + /* [out] */ USHORT *pMajorVersion, + /* [out] */ USHORT *pMinorVersion, + /* [out] */ USHORT *pBuildNumber, + /* [out] */ USHORT *pQFEVersion, + /* [in] */ ULONG cchVersionString, + /* [out] */ ULONG *pcchVersionString, + /* [annotation][out] */ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( + ICorProfilerInfo11 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ ULONG32 cAppDomainIds, + /* [out] */ ULONG32 *pcAppDomainIds, + /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId, + /* [out] */ DWORD *pdwModuleFlags); + + HRESULT ( STDMETHODCALLTYPE *EnumThreads )( + ICorProfilerInfo11 * This, + /* [out] */ ICorProfilerThreadEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( + ICorProfilerInfo11 * This); + + HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( + ICorProfilerInfo11 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RequestRevert )( + ICorProfilerInfo11 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ], + /* [size_is][out] */ HRESULT status[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( + ICorProfilerInfo11 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG cReJitIds, + /* [out] */ ULONG *pcReJitIds, + /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( + ICorProfilerInfo11 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( + ICorProfilerInfo11 * This, + /* [in] */ ObjectID objectId, + /* [out] */ SIZE_T *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( + ICorProfilerInfo11 * This, + /* [out] */ DWORD *pdwEventsLow, + /* [out] */ DWORD *pdwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( + ICorProfilerInfo11 * This, + /* [in] */ DWORD dwEventsLow, + /* [in] */ DWORD dwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID inlinersModuleId, + /* [in] */ ModuleID inlineeModuleId, + /* [in] */ mdMethodDef inlineeMethodId, + /* [out] */ BOOL *incompleteData, + /* [out] */ ICorProfilerMethodEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ DWORD *pCountSymbolBytes); + + HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( + ICorProfilerInfo11 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD symbolsReadOffset, + /* [out] */ BYTE *pSymbolBytes, + /* [in] */ DWORD countSymbolBytes, + /* [out] */ DWORD *pCountSymbolBytesRead); + + HRESULT ( STDMETHODCALLTYPE *IsFunctionDynamic )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *isDynamic); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP3 )( + ICorProfilerInfo11 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *functionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetDynamicFunctionInfo )( + ICorProfilerInfo11 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ModuleID *moduleId, + /* [out] */ PCCOR_SIGNATURE *ppvSig, + /* [out] */ ULONG *pbSig, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [out] */ WCHAR wszName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetNativeCodeStartAddresses )( + ICorProfilerInfo11 * This, + FunctionID functionID, + ReJITID reJitId, + ULONG32 cCodeStartAddresses, + ULONG32 *pcCodeStartAddresses, + UINT_PTR codeStartAddresses[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping3 )( + ICorProfilerInfo11 * This, + UINT_PTR pNativeCodeStartAddress, + ULONG32 cMap, + ULONG32 *pcMap, + COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo4 )( + ICorProfilerInfo11 * This, + UINT_PTR pNativeCodeStartAddress, + ULONG32 cCodeInfos, + ULONG32 *pcCodeInfos, + COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *EnumerateObjectReferences )( + ICorProfilerInfo11 * This, + ObjectID objectId, + ObjectReferenceCallback callback, + void *clientData); + + HRESULT ( STDMETHODCALLTYPE *IsFrozenObject )( + ICorProfilerInfo11 * This, + ObjectID objectId, + BOOL *pbFrozen); + + HRESULT ( STDMETHODCALLTYPE *GetLOHObjectSizeThreshold )( + ICorProfilerInfo11 * This, + DWORD *pThreshold); + + HRESULT ( STDMETHODCALLTYPE *RequestReJITWithInliners )( + ICorProfilerInfo11 * This, + /* [in] */ DWORD dwRejitFlags, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *SuspendRuntime )( + ICorProfilerInfo11 * This); + + HRESULT ( STDMETHODCALLTYPE *ResumeRuntime )( + ICorProfilerInfo11 * This); + + HRESULT ( STDMETHODCALLTYPE *GetEnvironmentVariable )( + ICorProfilerInfo11 * This, + /* [string][in] */ const WCHAR *szName, + /* [in] */ ULONG cchValue, + /* [out] */ ULONG *pcchValue, + /* [annotation][out] */ + _Out_writes_to_(cchValue, *pcchValue) WCHAR szValue[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetEnvironmentVariable )( + ICorProfilerInfo11 * This, + /* [string][in] */ const WCHAR *szName, + /* [string][in] */ const WCHAR *szValue); + + END_INTERFACE + } ICorProfilerInfo11Vtbl; + + interface ICorProfilerInfo11 + { + CONST_VTBL struct ICorProfilerInfo11Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerInfo11_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerInfo11_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerInfo11_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerInfo11_GetClassFromObject(This,objectId,pClassId) \ + ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) + +#define ICorProfilerInfo11_GetClassFromToken(This,moduleId,typeDef,pClassId) \ + ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) + +#define ICorProfilerInfo11_GetCodeInfo(This,functionId,pStart,pcSize) \ + ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) + +#define ICorProfilerInfo11_GetEventMask(This,pdwEvents) \ + ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) + +#define ICorProfilerInfo11_GetFunctionFromIP(This,ip,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) + +#define ICorProfilerInfo11_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) + +#define ICorProfilerInfo11_GetHandleFromThread(This,threadId,phThread) \ + ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) + +#define ICorProfilerInfo11_GetObjectSize(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) + +#define ICorProfilerInfo11_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ + ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) + +#define ICorProfilerInfo11_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ + ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) + +#define ICorProfilerInfo11_GetCurrentThreadID(This,pThreadId) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) + +#define ICorProfilerInfo11_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ + ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) + +#define ICorProfilerInfo11_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ + ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) + +#define ICorProfilerInfo11_SetEventMask(This,dwEvents) \ + ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) + +#define ICorProfilerInfo11_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo11_SetFunctionIDMapper(This,pFunc) \ + ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) + +#define ICorProfilerInfo11_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ + ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) + +#define ICorProfilerInfo11_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ + ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) + +#define ICorProfilerInfo11_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ + ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) + +#define ICorProfilerInfo11_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ + ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) + +#define ICorProfilerInfo11_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ + ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) + +#define ICorProfilerInfo11_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) + +#define ICorProfilerInfo11_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ + ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) + +#define ICorProfilerInfo11_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ + ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) + +#define ICorProfilerInfo11_SetFunctionReJIT(This,functionId) \ + ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) + +#define ICorProfilerInfo11_ForceGC(This) \ + ( (This)->lpVtbl -> ForceGC(This) ) + +#define ICorProfilerInfo11_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) + +#define ICorProfilerInfo11_GetInprocInspectionInterface(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) + +#define ICorProfilerInfo11_GetInprocInspectionIThisThread(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) + +#define ICorProfilerInfo11_GetThreadContext(This,threadId,pContextId) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) + +#define ICorProfilerInfo11_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ + ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) + +#define ICorProfilerInfo11_EndInprocDebugging(This,dwProfilerContext) \ + ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) + +#define ICorProfilerInfo11_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) + + +#define ICorProfilerInfo11_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ + ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) + +#define ICorProfilerInfo11_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo11_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) + +#define ICorProfilerInfo11_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo11_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ + ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) + +#define ICorProfilerInfo11_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) + +#define ICorProfilerInfo11_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo11_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ + ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) + +#define ICorProfilerInfo11_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ + ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) + +#define ICorProfilerInfo11_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ + ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) + +#define ICorProfilerInfo11_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ + ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) + +#define ICorProfilerInfo11_GetBoxClassLayout(This,classId,pBufferOffset) \ + ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) + +#define ICorProfilerInfo11_GetThreadAppDomain(This,threadId,pAppDomainId) \ + ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) + +#define ICorProfilerInfo11_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ + ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) + +#define ICorProfilerInfo11_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ + ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) + +#define ICorProfilerInfo11_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) + +#define ICorProfilerInfo11_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ + ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) + +#define ICorProfilerInfo11_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ + ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) + +#define ICorProfilerInfo11_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ + ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) + +#define ICorProfilerInfo11_GetObjectGeneration(This,objectId,range) \ + ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) + +#define ICorProfilerInfo11_GetNotifiedExceptionClauseInfo(This,pinfo) \ + ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) + + +#define ICorProfilerInfo11_EnumJITedFunctions(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) + +#define ICorProfilerInfo11_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ + ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) + +#define ICorProfilerInfo11_SetFunctionIDMapper2(This,pFunc,clientData) \ + ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) + +#define ICorProfilerInfo11_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo11_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) + +#define ICorProfilerInfo11_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) + +#define ICorProfilerInfo11_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ + ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) + +#define ICorProfilerInfo11_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ + ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) + +#define ICorProfilerInfo11_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ + ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) + +#define ICorProfilerInfo11_EnumModules(This,ppEnum) \ + ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) + +#define ICorProfilerInfo11_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ + ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) + +#define ICorProfilerInfo11_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) + +#define ICorProfilerInfo11_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ + ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) + +#define ICorProfilerInfo11_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ + ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) + + +#define ICorProfilerInfo11_EnumThreads(This,ppEnum) \ + ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) + +#define ICorProfilerInfo11_InitializeCurrentThread(This) \ + ( (This)->lpVtbl -> InitializeCurrentThread(This) ) + +#define ICorProfilerInfo11_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ + ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) + +#define ICorProfilerInfo11_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ + ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) + +#define ICorProfilerInfo11_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo11_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) + +#define ICorProfilerInfo11_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ + ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) + +#define ICorProfilerInfo11_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) + +#define ICorProfilerInfo11_EnumJITedFunctions2(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) + +#define ICorProfilerInfo11_GetObjectSize2(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) + + +#define ICorProfilerInfo11_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ + ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) + +#define ICorProfilerInfo11_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ + ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) + + +#define ICorProfilerInfo11_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ + ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) + + +#define ICorProfilerInfo11_ApplyMetaData(This,moduleId) \ + ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) + +#define ICorProfilerInfo11_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ + ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) + +#define ICorProfilerInfo11_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ + ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) + + +#define ICorProfilerInfo11_IsFunctionDynamic(This,functionId,isDynamic) \ + ( (This)->lpVtbl -> IsFunctionDynamic(This,functionId,isDynamic) ) + +#define ICorProfilerInfo11_GetFunctionFromIP3(This,ip,functionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP3(This,ip,functionId,pReJitId) ) + +#define ICorProfilerInfo11_GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) \ + ( (This)->lpVtbl -> GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) ) + + +#define ICorProfilerInfo11_GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) \ + ( (This)->lpVtbl -> GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) ) + +#define ICorProfilerInfo11_GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) ) + +#define ICorProfilerInfo11_GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) ) + + +#define ICorProfilerInfo11_EnumerateObjectReferences(This,objectId,callback,clientData) \ + ( (This)->lpVtbl -> EnumerateObjectReferences(This,objectId,callback,clientData) ) + +#define ICorProfilerInfo11_IsFrozenObject(This,objectId,pbFrozen) \ + ( (This)->lpVtbl -> IsFrozenObject(This,objectId,pbFrozen) ) + +#define ICorProfilerInfo11_GetLOHObjectSizeThreshold(This,pThreshold) \ + ( (This)->lpVtbl -> GetLOHObjectSizeThreshold(This,pThreshold) ) + +#define ICorProfilerInfo11_RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) \ + ( (This)->lpVtbl -> RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) ) + +#define ICorProfilerInfo11_SuspendRuntime(This) \ + ( (This)->lpVtbl -> SuspendRuntime(This) ) + +#define ICorProfilerInfo11_ResumeRuntime(This) \ + ( (This)->lpVtbl -> ResumeRuntime(This) ) + + +#define ICorProfilerInfo11_GetEnvironmentVariable(This,szName,cchValue,pcchValue,szValue) \ + ( (This)->lpVtbl -> GetEnvironmentVariable(This,szName,cchValue,pcchValue,szValue) ) + +#define ICorProfilerInfo11_SetEnvironmentVariable(This,szName,szValue) \ + ( (This)->lpVtbl -> SetEnvironmentVariable(This,szName,szValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerInfo11_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerInfo12_INTERFACE_DEFINED__ +#define __ICorProfilerInfo12_INTERFACE_DEFINED__ + +/* interface ICorProfilerInfo12 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerInfo12; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("27b24ccd-1cb1-47c5-96ee-98190dc30959") + ICorProfilerInfo12 : public ICorProfilerInfo11 + { + public: + virtual HRESULT STDMETHODCALLTYPE EventPipeCreateProvider( + /* [string][in] */ const WCHAR *szName, + /* [out] */ EVENTPIPE_PROVIDER *pProviderHandle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EventPipeDefineEvent( + /* [in] */ EVENTPIPE_PROVIDER provHandle, + /* [string][in] */ const WCHAR *szName, + /* [in] */ UINT32 eventID, + /* [in] */ UINT64 keywords, + /* [in] */ UINT32 eventVersion, + /* [in] */ UINT32 level, + /* [in] */ BOOL needStack, + /* [in] */ UINT32 cParamDescs, + /* [size_is][in] */ COR_PRF_EVENTPIPE_PARAM_DESC pParamDescs[ ], + /* [out] */ EVENTPIPE_EVENT *pEventHandle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EventPipeWriteEvent( + /* [in] */ EVENTPIPE_EVENT eventHandle, + /* [size_is][in] */ COR_PRF_EVENT_DATA data[ ], + /* [in] */ UINT32 cData, + /* [in] */ LPCGUID pActivityId, + /* [in] */ LPCGUID pRelatedActivityId) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerInfo12Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerInfo12 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerInfo12 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerInfo12 * This); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( + ICorProfilerInfo12 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask )( + ICorProfilerInfo12 * This, + /* [out] */ DWORD *pdwEvents); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( + ICorProfilerInfo12 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( + ICorProfilerInfo12 * This, + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorProfilerInfo12 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( + ICorProfilerInfo12 * This, + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank); + + HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( + ICorProfilerInfo12 * This, + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICorProfilerInfo12 * This, + /* [out] */ ThreadID *pThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( + ICorProfilerInfo12 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask )( + ICorProfilerInfo12 * This, + /* [in] */ DWORD dwEvents); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionIDMapper *pFunc); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId); + + HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( + ICorProfilerInfo12 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( + ICorProfilerInfo12 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ForceGC )( + ICorProfilerInfo12 * This); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( + ICorProfilerInfo12 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( + ICorProfilerInfo12 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorProfilerInfo12 * This, + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId); + + HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( + ICorProfilerInfo12 * This, + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( + ICorProfilerInfo12 * This, + /* [in] */ DWORD dwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( + ICorProfilerInfo12 * This, + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( + ICorProfilerInfo12 * This, + /* [out] */ ULONG *pBufferLengthOffset, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( + ICorProfilerInfo12 * This, + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( + ICorProfilerInfo12 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID); + + HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( + ICorProfilerInfo12 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData); + + HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( + ICorProfilerInfo12 * This, + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( + ICorProfilerInfo12 * This, + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( + ICorProfilerInfo12 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( + ICorProfilerInfo12 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( + ICorProfilerInfo12 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( + ICorProfilerInfo12 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( + ICorProfilerInfo12 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); + + HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( + ICorProfilerInfo12 * This, + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( + ICorProfilerInfo12 * This, + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); + + HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( + ICorProfilerInfo12 * This, + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( + ICorProfilerInfo12 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( + ICorProfilerInfo12 * This, + /* [in] */ DWORD dwExpectedCompletionMilliseconds); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionIDMapper2 *pFunc, + /* [in] */ void *clientData); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( + ICorProfilerInfo12 * This, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionEnter3 *pFuncEnter3, + /* [in] */ FunctionLeave3 *pFuncLeave3, + /* [in] */ FunctionTailcall3 *pFuncTailcall3); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, + /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out][in] */ ULONG *pcbArgumentInfo, + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); + + HRESULT ( STDMETHODCALLTYPE *EnumModules )( + ICorProfilerInfo12 * This, + /* [out] */ ICorProfilerModuleEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( + ICorProfilerInfo12 * This, + /* [out] */ USHORT *pClrInstanceId, + /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, + /* [out] */ USHORT *pMajorVersion, + /* [out] */ USHORT *pMinorVersion, + /* [out] */ USHORT *pBuildNumber, + /* [out] */ USHORT *pQFEVersion, + /* [in] */ ULONG cchVersionString, + /* [out] */ ULONG *pcchVersionString, + /* [annotation][out] */ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( + ICorProfilerInfo12 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ ULONG32 cAppDomainIds, + /* [out] */ ULONG32 *pcAppDomainIds, + /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId, + /* [out] */ DWORD *pdwModuleFlags); + + HRESULT ( STDMETHODCALLTYPE *EnumThreads )( + ICorProfilerInfo12 * This, + /* [out] */ ICorProfilerThreadEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( + ICorProfilerInfo12 * This); + + HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( + ICorProfilerInfo12 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RequestRevert )( + ICorProfilerInfo12 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ], + /* [size_is][out] */ HRESULT status[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( + ICorProfilerInfo12 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG cReJitIds, + /* [out] */ ULONG *pcReJitIds, + /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( + ICorProfilerInfo12 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( + ICorProfilerInfo12 * This, + /* [in] */ ObjectID objectId, + /* [out] */ SIZE_T *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( + ICorProfilerInfo12 * This, + /* [out] */ DWORD *pdwEventsLow, + /* [out] */ DWORD *pdwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( + ICorProfilerInfo12 * This, + /* [in] */ DWORD dwEventsLow, + /* [in] */ DWORD dwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID inlinersModuleId, + /* [in] */ ModuleID inlineeModuleId, + /* [in] */ mdMethodDef inlineeMethodId, + /* [out] */ BOOL *incompleteData, + /* [out] */ ICorProfilerMethodEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ DWORD *pCountSymbolBytes); + + HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( + ICorProfilerInfo12 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD symbolsReadOffset, + /* [out] */ BYTE *pSymbolBytes, + /* [in] */ DWORD countSymbolBytes, + /* [out] */ DWORD *pCountSymbolBytesRead); + + HRESULT ( STDMETHODCALLTYPE *IsFunctionDynamic )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *isDynamic); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP3 )( + ICorProfilerInfo12 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *functionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetDynamicFunctionInfo )( + ICorProfilerInfo12 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ModuleID *moduleId, + /* [out] */ PCCOR_SIGNATURE *ppvSig, + /* [out] */ ULONG *pbSig, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [out] */ WCHAR wszName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetNativeCodeStartAddresses )( + ICorProfilerInfo12 * This, + FunctionID functionID, + ReJITID reJitId, + ULONG32 cCodeStartAddresses, + ULONG32 *pcCodeStartAddresses, + UINT_PTR codeStartAddresses[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping3 )( + ICorProfilerInfo12 * This, + UINT_PTR pNativeCodeStartAddress, + ULONG32 cMap, + ULONG32 *pcMap, + COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo4 )( + ICorProfilerInfo12 * This, + UINT_PTR pNativeCodeStartAddress, + ULONG32 cCodeInfos, + ULONG32 *pcCodeInfos, + COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *EnumerateObjectReferences )( + ICorProfilerInfo12 * This, + ObjectID objectId, + ObjectReferenceCallback callback, + void *clientData); + + HRESULT ( STDMETHODCALLTYPE *IsFrozenObject )( + ICorProfilerInfo12 * This, + ObjectID objectId, + BOOL *pbFrozen); + + HRESULT ( STDMETHODCALLTYPE *GetLOHObjectSizeThreshold )( + ICorProfilerInfo12 * This, + DWORD *pThreshold); + + HRESULT ( STDMETHODCALLTYPE *RequestReJITWithInliners )( + ICorProfilerInfo12 * This, + /* [in] */ DWORD dwRejitFlags, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *SuspendRuntime )( + ICorProfilerInfo12 * This); + + HRESULT ( STDMETHODCALLTYPE *ResumeRuntime )( + ICorProfilerInfo12 * This); + + HRESULT ( STDMETHODCALLTYPE *GetEnvironmentVariable )( + ICorProfilerInfo12 * This, + /* [string][in] */ const WCHAR *szName, + /* [in] */ ULONG cchValue, + /* [out] */ ULONG *pcchValue, + /* [annotation][out] */ + _Out_writes_to_(cchValue, *pcchValue) WCHAR szValue[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetEnvironmentVariable )( + ICorProfilerInfo12 * This, + /* [string][in] */ const WCHAR *szName, + /* [string][in] */ const WCHAR *szValue); + + HRESULT ( STDMETHODCALLTYPE *EventPipeCreateProvider )( + ICorProfilerInfo12 * This, + /* [string][in] */ const WCHAR *szName, + /* [out] */ EVENTPIPE_PROVIDER *pProviderHandle); + + HRESULT ( STDMETHODCALLTYPE *EventPipeDefineEvent )( + ICorProfilerInfo12 * This, + /* [in] */ EVENTPIPE_PROVIDER provHandle, + /* [string][in] */ const WCHAR *szName, + /* [in] */ UINT32 eventID, + /* [in] */ UINT64 keywords, + /* [in] */ UINT32 eventVersion, + /* [in] */ UINT32 level, + /* [in] */ BOOL needStack, + /* [in] */ UINT32 cParamDescs, + /* [size_is][in] */ COR_PRF_EVENTPIPE_PARAM_DESC pParamDescs[ ], + /* [out] */ EVENTPIPE_EVENT *pEventHandle); + + HRESULT ( STDMETHODCALLTYPE *EventPipeWriteEvent )( + ICorProfilerInfo12 * This, + /* [in] */ EVENTPIPE_EVENT eventHandle, + /* [size_is][in] */ COR_PRF_EVENT_DATA data[ ], + /* [in] */ UINT32 cData, + /* [in] */ LPCGUID pActivityId, + /* [in] */ LPCGUID pRelatedActivityId); + + END_INTERFACE + } ICorProfilerInfo12Vtbl; + + interface ICorProfilerInfo12 + { + CONST_VTBL struct ICorProfilerInfo12Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerInfo12_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerInfo12_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerInfo12_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerInfo12_GetClassFromObject(This,objectId,pClassId) \ + ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) + +#define ICorProfilerInfo12_GetClassFromToken(This,moduleId,typeDef,pClassId) \ + ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) + +#define ICorProfilerInfo12_GetCodeInfo(This,functionId,pStart,pcSize) \ + ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) + +#define ICorProfilerInfo12_GetEventMask(This,pdwEvents) \ + ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) + +#define ICorProfilerInfo12_GetFunctionFromIP(This,ip,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) + +#define ICorProfilerInfo12_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) + +#define ICorProfilerInfo12_GetHandleFromThread(This,threadId,phThread) \ + ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) + +#define ICorProfilerInfo12_GetObjectSize(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) + +#define ICorProfilerInfo12_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ + ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) + +#define ICorProfilerInfo12_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ + ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) + +#define ICorProfilerInfo12_GetCurrentThreadID(This,pThreadId) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) + +#define ICorProfilerInfo12_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ + ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) + +#define ICorProfilerInfo12_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ + ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) + +#define ICorProfilerInfo12_SetEventMask(This,dwEvents) \ + ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) + +#define ICorProfilerInfo12_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo12_SetFunctionIDMapper(This,pFunc) \ + ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) + +#define ICorProfilerInfo12_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ + ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) + +#define ICorProfilerInfo12_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ + ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) + +#define ICorProfilerInfo12_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ + ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) + +#define ICorProfilerInfo12_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ + ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) + +#define ICorProfilerInfo12_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ + ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) + +#define ICorProfilerInfo12_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) + +#define ICorProfilerInfo12_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ + ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) + +#define ICorProfilerInfo12_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ + ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) + +#define ICorProfilerInfo12_SetFunctionReJIT(This,functionId) \ + ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) + +#define ICorProfilerInfo12_ForceGC(This) \ + ( (This)->lpVtbl -> ForceGC(This) ) + +#define ICorProfilerInfo12_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) + +#define ICorProfilerInfo12_GetInprocInspectionInterface(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) + +#define ICorProfilerInfo12_GetInprocInspectionIThisThread(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) + +#define ICorProfilerInfo12_GetThreadContext(This,threadId,pContextId) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) + +#define ICorProfilerInfo12_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ + ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) + +#define ICorProfilerInfo12_EndInprocDebugging(This,dwProfilerContext) \ + ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) + +#define ICorProfilerInfo12_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) + + +#define ICorProfilerInfo12_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ + ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) + +#define ICorProfilerInfo12_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo12_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) + +#define ICorProfilerInfo12_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo12_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ + ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) + +#define ICorProfilerInfo12_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) + +#define ICorProfilerInfo12_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo12_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ + ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) + +#define ICorProfilerInfo12_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ + ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) + +#define ICorProfilerInfo12_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ + ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) + +#define ICorProfilerInfo12_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ + ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) + +#define ICorProfilerInfo12_GetBoxClassLayout(This,classId,pBufferOffset) \ + ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) + +#define ICorProfilerInfo12_GetThreadAppDomain(This,threadId,pAppDomainId) \ + ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) + +#define ICorProfilerInfo12_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ + ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) + +#define ICorProfilerInfo12_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ + ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) + +#define ICorProfilerInfo12_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) + +#define ICorProfilerInfo12_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ + ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) + +#define ICorProfilerInfo12_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ + ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) + +#define ICorProfilerInfo12_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ + ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) + +#define ICorProfilerInfo12_GetObjectGeneration(This,objectId,range) \ + ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) + +#define ICorProfilerInfo12_GetNotifiedExceptionClauseInfo(This,pinfo) \ + ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) + + +#define ICorProfilerInfo12_EnumJITedFunctions(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) + +#define ICorProfilerInfo12_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ + ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) + +#define ICorProfilerInfo12_SetFunctionIDMapper2(This,pFunc,clientData) \ + ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) + +#define ICorProfilerInfo12_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo12_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) + +#define ICorProfilerInfo12_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) + +#define ICorProfilerInfo12_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ + ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) + +#define ICorProfilerInfo12_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ + ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) + +#define ICorProfilerInfo12_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ + ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) + +#define ICorProfilerInfo12_EnumModules(This,ppEnum) \ + ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) + +#define ICorProfilerInfo12_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ + ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) + +#define ICorProfilerInfo12_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) + +#define ICorProfilerInfo12_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ + ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) + +#define ICorProfilerInfo12_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ + ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) + + +#define ICorProfilerInfo12_EnumThreads(This,ppEnum) \ + ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) + +#define ICorProfilerInfo12_InitializeCurrentThread(This) \ + ( (This)->lpVtbl -> InitializeCurrentThread(This) ) + +#define ICorProfilerInfo12_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ + ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) + +#define ICorProfilerInfo12_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ + ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) + +#define ICorProfilerInfo12_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo12_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) + +#define ICorProfilerInfo12_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ + ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) + +#define ICorProfilerInfo12_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) + +#define ICorProfilerInfo12_EnumJITedFunctions2(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) + +#define ICorProfilerInfo12_GetObjectSize2(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) + + +#define ICorProfilerInfo12_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ + ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) + +#define ICorProfilerInfo12_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ + ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) + + +#define ICorProfilerInfo12_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ + ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) + + +#define ICorProfilerInfo12_ApplyMetaData(This,moduleId) \ + ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) + +#define ICorProfilerInfo12_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ + ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) + +#define ICorProfilerInfo12_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ + ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) + + +#define ICorProfilerInfo12_IsFunctionDynamic(This,functionId,isDynamic) \ + ( (This)->lpVtbl -> IsFunctionDynamic(This,functionId,isDynamic) ) + +#define ICorProfilerInfo12_GetFunctionFromIP3(This,ip,functionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP3(This,ip,functionId,pReJitId) ) + +#define ICorProfilerInfo12_GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) \ + ( (This)->lpVtbl -> GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) ) + + +#define ICorProfilerInfo12_GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) \ + ( (This)->lpVtbl -> GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) ) + +#define ICorProfilerInfo12_GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) ) + +#define ICorProfilerInfo12_GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) ) + + +#define ICorProfilerInfo12_EnumerateObjectReferences(This,objectId,callback,clientData) \ + ( (This)->lpVtbl -> EnumerateObjectReferences(This,objectId,callback,clientData) ) + +#define ICorProfilerInfo12_IsFrozenObject(This,objectId,pbFrozen) \ + ( (This)->lpVtbl -> IsFrozenObject(This,objectId,pbFrozen) ) + +#define ICorProfilerInfo12_GetLOHObjectSizeThreshold(This,pThreshold) \ + ( (This)->lpVtbl -> GetLOHObjectSizeThreshold(This,pThreshold) ) + +#define ICorProfilerInfo12_RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) \ + ( (This)->lpVtbl -> RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) ) + +#define ICorProfilerInfo12_SuspendRuntime(This) \ + ( (This)->lpVtbl -> SuspendRuntime(This) ) + +#define ICorProfilerInfo12_ResumeRuntime(This) \ + ( (This)->lpVtbl -> ResumeRuntime(This) ) + + +#define ICorProfilerInfo12_GetEnvironmentVariable(This,szName,cchValue,pcchValue,szValue) \ + ( (This)->lpVtbl -> GetEnvironmentVariable(This,szName,cchValue,pcchValue,szValue) ) + +#define ICorProfilerInfo12_SetEnvironmentVariable(This,szName,szValue) \ + ( (This)->lpVtbl -> SetEnvironmentVariable(This,szName,szValue) ) + + +#define ICorProfilerInfo12_EventPipeCreateProvider(This,szName,pProviderHandle) \ + ( (This)->lpVtbl -> EventPipeCreateProvider(This,szName,pProviderHandle) ) + +#define ICorProfilerInfo12_EventPipeDefineEvent(This,provHandle,szName,eventID,keywords,eventVersion,level,needStack,cParamDescs,pParamDescs,pEventHandle) \ + ( (This)->lpVtbl -> EventPipeDefineEvent(This,provHandle,szName,eventID,keywords,eventVersion,level,needStack,cParamDescs,pParamDescs,pEventHandle) ) + +#define ICorProfilerInfo12_EventPipeWriteEvent(This,eventHandle,data,cData,pActivityId,pRelatedActivityId) \ + ( (This)->lpVtbl -> EventPipeWriteEvent(This,eventHandle,data,cData,pActivityId,pRelatedActivityId) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerInfo12_INTERFACE_DEFINED__ */ + + #ifndef __ICorProfilerMethodEnum_INTERFACE_DEFINED__ #define __ICorProfilerMethodEnum_INTERFACE_DEFINED__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/corsym.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/corsym.h index dd80eae..4602539 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/corsym.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/corsym.h @@ -5293,8 +5293,8 @@ EXTERN_C const IID IID_ISymNGenWriter2; { public: virtual HRESULT STDMETHODCALLTYPE OpenModW( - /* [in] */ const wchar_t *wszModule, - /* [in] */ const wchar_t *wszObjFile, + /* [in] */ LPCWSTR wszModule, + /* [in] */ LPCWSTR wszObjFile, /* [out] */ BYTE **ppmod) = 0; virtual HRESULT STDMETHODCALLTYPE CloseMod( @@ -5315,7 +5315,7 @@ EXTERN_C const IID IID_ISymNGenWriter2; /* [in] */ DWORD dwRelocCrc) = 0; virtual HRESULT STDMETHODCALLTYPE QueryPDBNameExW( - /* [size_is][out] */ wchar_t wszPDB[ ], + /* [size_is][out] */ WCHAR wszPDB[ ], /* [in] */ SIZE_T cchMax) = 0; }; @@ -5354,8 +5354,8 @@ EXTERN_C const IID IID_ISymNGenWriter2; HRESULT ( STDMETHODCALLTYPE *OpenModW )( ISymNGenWriter2 * This, - /* [in] */ const wchar_t *wszModule, - /* [in] */ const wchar_t *wszObjFile, + /* [in] */ const WCHAR *wszModule, + /* [in] */ const WCHAR *wszObjFile, /* [out] */ BYTE **ppmod); HRESULT ( STDMETHODCALLTYPE *CloseMod )( @@ -5380,7 +5380,7 @@ EXTERN_C const IID IID_ISymNGenWriter2; HRESULT ( STDMETHODCALLTYPE *QueryPDBNameExW )( ISymNGenWriter2 * This, - /* [size_is][out] */ wchar_t wszPDB[ ], + /* [size_is][out] */ WCHAR wszPDB[ ], /* [in] */ SIZE_T cchMax); END_INTERFACE diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fusion.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fusion.h index b7a5770..b8d17a3 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fusion.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fusion.h @@ -7,7 +7,7 @@ /* this ALWAYS GENERATED file contains the definitions for the interfaces */ - /* File created by MIDL compiler version 8.00.0603 */ + /* File created by MIDL compiler version 8.01.0622 */ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ @@ -23,7 +23,7 @@ #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of -#endif // __RPCNDR_H_VERSION__ +#endif /* __RPCNDR_H_VERSION__ */ #ifndef COM_NO_WINDOWS_H #include "windows.h" @@ -68,26 +68,6 @@ extern "C"{ #ifdef _MSC_VER #pragma once #endif - - - - -#ifndef PEKIND_ENUM_DEFINED -#define PEKIND_ENUM_DEFINED -typedef -enum _tagPEKIND - { - peNone = 0, - peMSIL = 0x1, - peI386 = 0x2, - peIA64 = 0x3, - peAMD64 = 0x4, - peARM = 0x5, - peARM64 = 0x6, - peInvalid = 0xffffffff - } PEKIND; - -#endif typedef enum _tagAssemblyContentType { @@ -113,15 +93,6 @@ typedef /* [unique] */ IAssemblyName *LPASSEMBLYNAME; typedef /* [public] */ enum __MIDL_IAssemblyName_0001 - { - CANOF_PARSE_DISPLAY_NAME = 0x1, - CANOF_SET_DEFAULT_VALUES = 0x2, - CANOF_VERIFY_FRIEND_ASSEMBLYNAME = 0x4, - CANOF_PARSE_FRIEND_DISPLAY_NAME = ( CANOF_PARSE_DISPLAY_NAME | CANOF_VERIFY_FRIEND_ASSEMBLYNAME ) - } CREATE_ASM_NAME_OBJ_FLAGS; - -typedef /* [public] */ -enum __MIDL_IAssemblyName_0002 { ASM_NAME_PUBLIC_KEY = 0, ASM_NAME_PUBLIC_KEY_TOKEN = ( ASM_NAME_PUBLIC_KEY + 1 ) , @@ -156,7 +127,7 @@ enum __MIDL_IAssemblyName_0002 } ASM_NAME; typedef /* [public] */ -enum __MIDL_IAssemblyName_0003 +enum __MIDL_IAssemblyName_0002 { ASM_DISPLAYF_VERSION = 0x1, ASM_DISPLAYF_CULTURE = 0x2, @@ -172,29 +143,6 @@ enum __MIDL_IAssemblyName_0003 ASM_DISPLAYF_FULL = ( ( ( ( ( ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE ) | ASM_DISPLAYF_PUBLIC_KEY_TOKEN ) | ASM_DISPLAYF_RETARGET ) | ASM_DISPLAYF_PROCESSORARCHITECTURE ) | ASM_DISPLAYF_CONTENT_TYPE ) } ASM_DISPLAY_FLAGS; -typedef /* [public] */ -enum __MIDL_IAssemblyName_0004 - { - ASM_CMPF_NAME = 0x1, - ASM_CMPF_MAJOR_VERSION = 0x2, - ASM_CMPF_MINOR_VERSION = 0x4, - ASM_CMPF_BUILD_NUMBER = 0x8, - ASM_CMPF_REVISION_NUMBER = 0x10, - ASM_CMPF_VERSION = ( ( ( ASM_CMPF_MAJOR_VERSION | ASM_CMPF_MINOR_VERSION ) | ASM_CMPF_BUILD_NUMBER ) | ASM_CMPF_REVISION_NUMBER ) , - ASM_CMPF_PUBLIC_KEY_TOKEN = 0x20, - ASM_CMPF_CULTURE = 0x40, - ASM_CMPF_CUSTOM = 0x80, - ASM_CMPF_DEFAULT = 0x100, - ASM_CMPF_RETARGET = 0x200, - ASM_CMPF_ARCHITECTURE = 0x400, - ASM_CMPF_CONFIG_MASK = 0x800, - ASM_CMPF_MVID = 0x1000, - ASM_CMPF_SIGNATURE = 0x2000, - ASM_CMPF_CONTENT_TYPE = 0x4000, - ASM_CMPF_IL_ALL = ( ( ( ASM_CMPF_NAME | ASM_CMPF_VERSION ) | ASM_CMPF_PUBLIC_KEY_TOKEN ) | ASM_CMPF_CULTURE ) , - ASM_CMPF_IL_NO_VERSION = ( ( ASM_CMPF_NAME | ASM_CMPF_PUBLIC_KEY_TOKEN ) | ASM_CMPF_CULTURE ) - } ASM_CMP_FLAGS; - EXTERN_C const IID IID_IAssemblyName; @@ -214,41 +162,12 @@ EXTERN_C const IID IID_IAssemblyName; /* [out] */ LPVOID pvProperty, /* [out][in] */ LPDWORD pcbProperty) = 0; - virtual HRESULT STDMETHODCALLTYPE Finalize( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDisplayName( - /* [annotation][out] */ - _Out_writes_opt_(*pccDisplayName) LPOLESTR szDisplayName, - /* [out][in] */ LPDWORD pccDisplayName, - /* [in] */ DWORD dwDisplayFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE Reserved( - /* [in] */ REFIID refIID, - /* [in] */ IUnknown *pUnkReserved1, - /* [in] */ IUnknown *pUnkReserved2, - /* [in] */ LPCOLESTR szReserved, - /* [in] */ LONGLONG llReserved, - /* [in] */ LPVOID pvReserved, - /* [in] */ DWORD cbReserved, - /* [out] */ LPVOID *ppReserved) = 0; - virtual HRESULT STDMETHODCALLTYPE GetName( /* [annotation][out][in] */ _Inout_ LPDWORD lpcwBuffer, /* [annotation][out] */ _Out_writes_opt_(*lpcwBuffer) WCHAR *pwzName) = 0; - virtual HRESULT STDMETHODCALLTYPE GetVersion( - /* [out] */ LPDWORD pdwVersionHi, - /* [out] */ LPDWORD pdwVersionLow) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsEqual( - /* [in] */ IAssemblyName *pName, - /* [in] */ DWORD dwCmpFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE Clone( - /* [out] */ IAssemblyName **pName) = 0; - }; @@ -282,27 +201,6 @@ EXTERN_C const IID IID_IAssemblyName; /* [out] */ LPVOID pvProperty, /* [out][in] */ LPDWORD pcbProperty); - HRESULT ( STDMETHODCALLTYPE *Finalize )( - IAssemblyName * This); - - HRESULT ( STDMETHODCALLTYPE *GetDisplayName )( - IAssemblyName * This, - /* [annotation][out] */ - _Out_writes_opt_(*pccDisplayName) LPOLESTR szDisplayName, - /* [out][in] */ LPDWORD pccDisplayName, - /* [in] */ DWORD dwDisplayFlags); - - HRESULT ( STDMETHODCALLTYPE *Reserved )( - IAssemblyName * This, - /* [in] */ REFIID refIID, - /* [in] */ IUnknown *pUnkReserved1, - /* [in] */ IUnknown *pUnkReserved2, - /* [in] */ LPCOLESTR szReserved, - /* [in] */ LONGLONG llReserved, - /* [in] */ LPVOID pvReserved, - /* [in] */ DWORD cbReserved, - /* [out] */ LPVOID *ppReserved); - HRESULT ( STDMETHODCALLTYPE *GetName )( IAssemblyName * This, /* [annotation][out][in] */ @@ -310,20 +208,6 @@ EXTERN_C const IID IID_IAssemblyName; /* [annotation][out] */ _Out_writes_opt_(*lpcwBuffer) WCHAR *pwzName); - HRESULT ( STDMETHODCALLTYPE *GetVersion )( - IAssemblyName * This, - /* [out] */ LPDWORD pdwVersionHi, - /* [out] */ LPDWORD pdwVersionLow); - - HRESULT ( STDMETHODCALLTYPE *IsEqual )( - IAssemblyName * This, - /* [in] */ IAssemblyName *pName, - /* [in] */ DWORD dwCmpFlags); - - HRESULT ( STDMETHODCALLTYPE *Clone )( - IAssemblyName * This, - /* [out] */ IAssemblyName **pName); - END_INTERFACE } IAssemblyNameVtbl; @@ -353,27 +237,9 @@ EXTERN_C const IID IID_IAssemblyName; #define IAssemblyName_GetProperty(This,PropertyId,pvProperty,pcbProperty) \ ( (This)->lpVtbl -> GetProperty(This,PropertyId,pvProperty,pcbProperty) ) -#define IAssemblyName_Finalize(This) \ - ( (This)->lpVtbl -> Finalize(This) ) - -#define IAssemblyName_GetDisplayName(This,szDisplayName,pccDisplayName,dwDisplayFlags) \ - ( (This)->lpVtbl -> GetDisplayName(This,szDisplayName,pccDisplayName,dwDisplayFlags) ) - -#define IAssemblyName_Reserved(This,refIID,pUnkReserved1,pUnkReserved2,szReserved,llReserved,pvReserved,cbReserved,ppReserved) \ - ( (This)->lpVtbl -> Reserved(This,refIID,pUnkReserved1,pUnkReserved2,szReserved,llReserved,pvReserved,cbReserved,ppReserved) ) - #define IAssemblyName_GetName(This,lpcwBuffer,pwzName) \ ( (This)->lpVtbl -> GetName(This,lpcwBuffer,pwzName) ) -#define IAssemblyName_GetVersion(This,pdwVersionHi,pdwVersionLow) \ - ( (This)->lpVtbl -> GetVersion(This,pdwVersionHi,pdwVersionLow) ) - -#define IAssemblyName_IsEqual(This,pName,dwCmpFlags) \ - ( (This)->lpVtbl -> IsEqual(This,pName,dwCmpFlags) ) - -#define IAssemblyName_Clone(This,pName) \ - ( (This)->lpVtbl -> Clone(This,pName) ) - #endif /* COBJMACROS */ @@ -385,15 +251,6 @@ EXTERN_C const IID IID_IAssemblyName; #endif /* __IAssemblyName_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_fusion_0000_0001 */ -/* [local] */ - -STDAPI CreateAssemblyNameObject(LPASSEMBLYNAME *ppAssemblyNameObj, LPCWSTR szAssemblyName, DWORD dwFlags, LPVOID pvReserved); - - -extern RPC_IF_HANDLE __MIDL_itf_fusion_0000_0001_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_fusion_0000_0001_v0_0_s_ifspec; - /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fxver.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fxver.h index 95ccbc6..7e2a322 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fxver.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fxver.h @@ -2,202 +2,28 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// -// Insert just the #defines in winver.h, so that the -// C# compiler can include this file after macro preprocessing. -// - -#ifdef __cplusplus -#ifndef FXVER_H_ -#define FXVER_H_ -#define INCLUDE_FXVER_H -#endif -#else -#define RC_INVOKED 1 -#define INCLUDE_FXVER_H -#endif - -#ifdef INCLUDE_FXVER_H -#undef INCLUDE_FXVER_H - -#ifndef RC_INVOKED -#define FXVER_H_RC_INVOKED_ENABLED -#define RC_INVOKED 1 -#endif - #include -#ifdef FXVER_H_RC_INVOKED_ENABLED -#undef RC_INVOKED -#undef FXVER_H_RC_INVOKED_ENABLED -#endif +#define QUOTE_MACRO_HELPER(x) #x +#define QUOTE_MACRO(x) QUOTE_MACRO_HELPER(x) -// -// Include the definitions for rmj, rmm, rup, rpt -// +#define VER_PRODUCTNAME_STR L"Microsoft\256 .NET" -#include - -/* - * Product version, name and copyright - */ - -#include "fxverstrings.h" - -/* - * File version, names, description. - */ - -// FX_VER_INTERNALNAME_STR is passed in by the build environment. -#ifndef FX_VER_INTERNALNAME_STR -#define FX_VER_INTERNALNAME_STR UNKNOWN_FILE -#endif #define VER_INTERNALNAME_STR QUOTE_MACRO(FX_VER_INTERNALNAME_STR) #define VER_ORIGINALFILENAME_STR QUOTE_MACRO(FX_VER_INTERNALNAME_STR) -// FX_VER_FILEDESCRIPTION_STR is defined in RC files that include fxver.h - -#ifndef FX_VER_FILEDESCRIPTION_STR -#define FX_VER_FILEDESCRIPTION_STR QUOTE_MACRO(FX_VER_INTERNALNAME_STR) -#endif - #define VER_FILEDESCRIPTION_STR FX_VER_FILEDESCRIPTION_STR -#ifndef FX_VER_FILEVERSION_STR -#define FX_VER_FILEVERSION_STR FX_FILEVERSION_STR -#endif - -#define VER_FILEVERSION_STR FX_VER_FILEVERSION_STR -#define VER_FILEVERSION_STR_L VER_PRODUCTVERSION_STR_L - -#ifndef FX_VER_FILEVERSION -#define FX_VER_FILEVERSION VER_DOTFILEVERSION -#endif - -#define VER_FILEVERSION FX_VER_FILEVERSION - -//URT_VFT passed in by the build environment. -#ifndef FX_VFT -#define FX_VFT VFT_UNKNOWN -#endif - -#define VER_FILETYPE FX_VFT -#define VER_FILESUBTYPE VFT2_UNKNOWN - -/* default is nodebug */ -#if DBG -#define VER_DEBUG VS_FF_DEBUG -#else -#define VER_DEBUG 0 -#endif - -#define VER_PRERELEASE 0 - -#define EXPORT_TAG - -// Not setting the private build flag until -// official builds can be detected from native projects -//#if OFFICIAL_BUILD -#define VER_PRIVATE 0 -//#else -//#define VER_PRIVATE VS_FF_PRIVATEBUILD -//#endif - -#define VER_SPECIALBUILD 0 +#define VER_COMMENTS_STR "Flavor=" QUOTE_MACRO(URTBLDENV_FRIENDLY) #define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#define VER_FILEFLAGS (VER_PRERELEASE|VER_DEBUG|VER_PRIVATE|VER_SPECIALBUILD) +#define VER_FILEFLAGS VER_DEBUG #define VER_FILEOS VOS__WINDOWS32 -#define VER_COMPANYNAME_STR "Microsoft Corporation" +#define VER_FILETYPE VFT_UNKNOWN +#define VER_FILESUBTYPE VFT2_UNKNOWN -#ifdef VER_LANGNEUTRAL -#define VER_VERSION_UNICODE_LANG "000004B0" /* LANG_NEUTRAL/SUBLANG_NEUTRAL, Unicode CP */ -#define VER_VERSION_ANSI_LANG "000004E4" /* LANG_NEUTRAL/SUBLANG_NEUTRAL, Ansi CP */ -#define VER_VERSION_TRANSLATION 0x0000, 0x04B0 -#else #define VER_VERSION_UNICODE_LANG "040904B0" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */ #define VER_VERSION_ANSI_LANG "040904E4" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Ansi CP */ #define VER_VERSION_TRANSLATION 0x0409, 0x04B0 -#endif - -#if defined(CSC_INVOKED) -#define VER_COMMENTS_STR "Flavor=" + QUOTE_MACRO(URTBLDENV_FRIENDLY) -#else -#define VER_COMMENTS_STR "Flavor=" QUOTE_MACRO(URTBLDENV_FRIENDLY) -#endif - -#if defined(__BUILDMACHINE__) -#if defined(__BUILDDATE__) -#define B2(x,y) " (" #x "." #y ")" -#define B1(x,y) B2(x, y) -#define BUILD_MACHINE_TAG B1(__BUILDMACHINE__, __BUILDDATE__) -#else -#define B2(x) " built by: " #x -#define B1(x) B2(x) -#define BUILD_MACHINE_TAG B1(__BUILDMACHINE__) -#endif -#if defined(__BUILDMACHINE_LEN__) -#if __BUILDMACHINE_LEN__ >= 25 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG -#elif __BUILDMACHINE_LEN__ == 24 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 23 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 22 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 21 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 20 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 19 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 18 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 17 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 16 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 15 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 14 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 13 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 12 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 11 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 10 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 9 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 8 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 7 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 6 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 5 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 4 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 3 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 2 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#elif __BUILDMACHINE_LEN__ == 1 -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " -#else -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG -#endif -#else -#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG -#endif -#else -#define BUILD_MACHINE_TAG -#define BUILD_MACHINE_TAG_PADDED -#endif - -#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fxver.rc b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fxver.rc index ab037e7..8f8637f 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fxver.rc +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fxver.rc @@ -2,35 +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. -/*---------------------------------------------------------------*/ -/* */ -/* The following section actually creates the version structure. */ -/* They are ignored if we are not being invoked by RC. */ -/* */ -/* ntverp.H must be included before including this file */ -/* */ -/* If VER_LEGALCOPYRIGHT_STR is not defined, it will be */ -/* constructed using VER_LEGALCOPYRIGHT_YEARS, so at least one */ -/* these macros must be defined before including this file. */ -/* */ -/* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR, and */ -/* VER_INTERNALNAME_STR must be defined before including this */ -/* file. */ -/* */ -/* If VER_FILEVERSION is not defined, VER_PRODUCTVERSION will be */ -/* used instead. If VER_FILEVERSION_STR is not defined, */ -/* VER_PRODUCTVERSION_STR will be used instead. */ -/* */ -/* If VER_ORIGINALFILENAME_STR is not defined, it is set to */ -/* the value in VER_INTERNALNAME_STR. */ -/* */ -/* If INTL is defined, then this is assumed to be an */ -/* an international build; two string blocks will be created, */ -/* (since all version resources must have English), and the */ -/* second one can be localized */ -/* */ -/*---------------------------------------------------------------*/ - #ifdef _WIN32 #include <_version.h> #endif //_WIN32 @@ -51,44 +22,15 @@ BEGIN BLOCK VER_VERSION_UNICODE_LANG BEGIN VALUE "CompanyName", VER_COMPANYNAME_STR - VALUE "FileDescription", VER_FILEDESCRIPTION_STR EXPORT_TAG - VALUE "FileVersion", VER_FILEVERSION_STR BUILD_MACHINE_TAG_PADDED - VALUE "InternalName", VER_INTERNALNAME_STR - VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR - VALUE "OriginalFilename",VER_ORIGINALFILENAME_STR - VALUE "ProductName", VER_PRODUCTNAME_STR - VALUE "ProductVersion", VER_FILEVERSION_STR -#ifdef VER_OLESELFREGISTER - VALUE "OleSelfRegister", "\0" -#endif - VALUE "Comments", VER_COMMENTS_STR -#ifdef VER_EXTRA_VALUES - VER_EXTRA_VALUES -#endif - - END - - -#ifdef VER_ANSICP /* Some apps are hard coded to look for ANSI CP. */ - BLOCK VER_VERSION_ANSI_LANG - BEGIN - VALUE "CompanyName", VER_COMPANYNAME_STR - VALUE "FileDescription", VER_FILEDESCRIPTION_STR EXPORT_TAG + VALUE "FileDescription", VER_FILEDESCRIPTION_STR VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", VER_INTERNALNAME_STR VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR VALUE "OriginalFilename",VER_ORIGINALFILENAME_STR VALUE "ProductName", VER_PRODUCTNAME_STR VALUE "ProductVersion", VER_FILEVERSION_STR -#ifdef VER_OLESELFREGISTER - VALUE "OleSelfRegister", "\0" -#endif VALUE "Comments", VER_COMMENTS_STR -#ifdef VER_EXTRA_VALUES - VER_EXTRA_VALUES -#endif END -#endif END BLOCK "VarFileInfo" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fxverstrings.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fxverstrings.h deleted file mode 100644 index cafcbad..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/fxverstrings.h +++ /dev/null @@ -1,17 +0,0 @@ -// 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. - -#ifndef VER_PRODUCTNAME_STR - #define VER_PRODUCTNAME_STR L"Microsoft\256 .NET Core" -#endif - -#ifndef VER_LEGALCOPYRIGHT_STR - #define VER_LEGALCOPYRIGHT_STR "\251 Microsoft Corporation. All rights reserved." - #define VER_LEGALCOPYRIGHT_STR_L L"\251 Microsoft Corporation. All rights reserved." -#endif - -#ifndef VER_LEGALCOPYRIGHT_LOGO_STR - #define VER_LEGALCOPYRIGHT_LOGO_STR "Copyright (c) Microsoft Corporation. All rights reserved." - #define VER_LEGALCOPYRIGHT_LOGO_STR_L L"Copyright (c) Microsoft Corporation. All rights reserved." -#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/mscoree.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/mscoree.h index ab7bbb0..4f5c5b8 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/mscoree.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/mscoree.h @@ -70,16 +70,12 @@ extern "C"{ /* interface __MIDL_itf_mscoree_0000_0000 */ /* [local] */ -#define DECLARE_DEPRECATED -#define DEPRECATED_CLR_STDAPI STDAPI - struct IActivationFactory; struct IHostControl; struct ICLRControl; -EXTERN_GUID(CLSID_ComCallUnmarshalV4, 0x45fb4600,0xe6e8,0x4928,0xb2,0x5e,0x50,0x47,0x6f,0xf7,0x94,0x25); EXTERN_GUID(IID_ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02); EXTERN_GUID(IID_ICLRRuntimeHost2, 0x712AB73F, 0x2C22, 0x4807, 0xAD, 0x7E, 0xF5, 0x01, 0xD7, 0xb7, 0x2C, 0x2D); EXTERN_GUID(IID_ICLRRuntimeHost4, 0x64F6D366, 0xD7C2, 0x4F1F, 0xB4, 0xB2, 0xE8, 0x16, 0x0C, 0xAC, 0x43, 0xAF); @@ -133,22 +129,6 @@ enum __MIDL___MIDL_itf_mscoree_0000_0000_0003 WAIT_NOTINDEADLOCK = 0x4 } WAIT_OPTION; -typedef -enum ETaskType - { - TT_DEBUGGERHELPER = 0x1, - TT_GC = 0x2, - TT_FINALIZER = 0x4, - TT_THREADPOOL_TIMER = 0x8, - TT_THREADPOOL_GATE = 0x10, - TT_THREADPOOL_WORKER = 0x20, - TT_THREADPOOL_IOCOMPLETION = 0x40, - TT_ADUNLOAD = 0x80, - TT_USER = 0x100, - TT_THREADPOOL_WAIT = 0x200, - TT_UNKNOWN = 0x80000000 - } ETaskType; - typedef /* [public] */ enum __MIDL___MIDL_itf_mscoree_0000_0000_0004 { @@ -184,56 +164,6 @@ typedef struct _BucketParameters WCHAR pszParams[ 10 ][ 255 ]; } BucketParameters; -typedef /* [public] */ -enum __MIDL___MIDL_itf_mscoree_0000_0000_0006 - { - OPR_ThreadAbort = 0, - OPR_ThreadRudeAbortInNonCriticalRegion = ( OPR_ThreadAbort + 1 ) , - OPR_ThreadRudeAbortInCriticalRegion = ( OPR_ThreadRudeAbortInNonCriticalRegion + 1 ) , - OPR_AppDomainUnload = ( OPR_ThreadRudeAbortInCriticalRegion + 1 ) , - OPR_AppDomainRudeUnload = ( OPR_AppDomainUnload + 1 ) , - OPR_ProcessExit = ( OPR_AppDomainRudeUnload + 1 ) , - OPR_FinalizerRun = ( OPR_ProcessExit + 1 ) , - MaxClrOperation = ( OPR_FinalizerRun + 1 ) - } EClrOperation; - -typedef /* [public] */ -enum __MIDL___MIDL_itf_mscoree_0000_0000_0007 - { - FAIL_NonCriticalResource = 0, - FAIL_CriticalResource = ( FAIL_NonCriticalResource + 1 ) , - FAIL_FatalRuntime = ( FAIL_CriticalResource + 1 ) , - FAIL_OrphanedLock = ( FAIL_FatalRuntime + 1 ) , - FAIL_StackOverflow = ( FAIL_OrphanedLock + 1 ) , - FAIL_AccessViolation = ( FAIL_StackOverflow + 1 ) , - FAIL_CodeContract = ( FAIL_AccessViolation + 1 ) , - MaxClrFailure = ( FAIL_CodeContract + 1 ) - } EClrFailure; - -typedef /* [public] */ -enum __MIDL___MIDL_itf_mscoree_0000_0000_0008 - { - eRuntimeDeterminedPolicy = 0, - eHostDeterminedPolicy = ( eRuntimeDeterminedPolicy + 1 ) - } EClrUnhandledException; - -typedef /* [public] */ -enum __MIDL___MIDL_itf_mscoree_0000_0000_0009 - { - eNoAction = 0, - eThrowException = ( eNoAction + 1 ) , - eAbortThread = ( eThrowException + 1 ) , - eRudeAbortThread = ( eAbortThread + 1 ) , - eUnloadAppDomain = ( eRudeAbortThread + 1 ) , - eRudeUnloadAppDomain = ( eUnloadAppDomain + 1 ) , - eExitProcess = ( eRudeUnloadAppDomain + 1 ) , - eFastExitProcess = ( eExitProcess + 1 ) , - eRudeExitProcess = ( eFastExitProcess + 1 ) , - MaxPolicyAction = (eRudeExitProcess + 1 ) - } EPolicyAction; - - - extern RPC_IF_HANDLE __MIDL_itf_mscoree_0000_0000_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_mscoree_0000_0000_v0_0_s_ifspec; @@ -890,10 +820,6 @@ EXTERN_C const IID IID_ICLRRuntimeHost4; /* interface __MIDL_itf_mscoree_0000_0003 */ /* [local] */ -#undef DEPRECATED_CLR_STDAPI -#undef DECLARE_DEPRECATED -#undef DEPRECATED_CLR_API_MESG - extern RPC_IF_HANDLE __MIDL_itf_mscoree_0000_0003_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_mscoree_0000_0003_v0_0_s_ifspec; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/ndpversion_generated.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/ndpversion_generated.h deleted file mode 100644 index 563e316..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/ndpversion_generated.h +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -#if 0 -/**** Generated Based on d:\ProjectK\src\InternalApis\Version\buildnumber.settings.targets -One can't put comments in this file (without the #if) -because this header is preprocessed in non-C++ context (xml, perl, etc.). *****/ -#endif -#define NDPVersionNumberMajor 4 -#define NDPVersionNumberMinor 0 -#define NDPVersionNumberMajor_A "4" -#define NDPVersionNumberMinor_A "00" -#define NDPVersionNumbers_A "4.00" -#include "buildnumber.h" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/product_version.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/product_version.h deleted file mode 100644 index a21ee68..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/product_version.h +++ /dev/null @@ -1,113 +0,0 @@ - -#if 0 - Version strings for product keys... no comments can be allowed in this - file due to some usage of this in the build process. - // 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. -#endif - -#include -#ifdef USE_CLR20_VERSION -#include -#else -#include -#endif - -#ifdef CLR_MAJOR_VERSION -#undef CLR_MAJOR_VERSION -#endif - -#ifdef CLR_MINOR_VERSION -#undef CLR_MINOR_VERSION -#endif - -#ifdef CLR_BUILD_VERSION -#undef CLR_BUILD_VERSION -#endif - -#ifdef CLR_BUILD_VERSION_QFE -#undef CLR_BUILD_VERSION_QFE -#endif - -#ifdef VER_FILEVERSIONMINOR -#undef VER_FILEVERSIONMINOR -#endif - -#ifdef VER_FILEVERSIONBUILD -#undef VER_FILEVERSIONBUILD -#endif - -#ifdef VER_FILEVERSIONREVISION -#undef VER_FILEVERSIONREVISION -#endif - -#define CLR_MAJOR_VERSION rmj -#define CLR_MINOR_VERSION rmm -#define CLR_BUILD_VERSION rup -#define CLR_BUILD_VERSION_QFE rpt - -#define VER_FILEVERSIONMINOR fvn -#define VER_FILEVERSIONBUILD fvb -#define VER_FILEVERSIONREVISION fvr - -#define VER_ASSEMBLYMAJORVERSION asm_rmj -#define VER_ASSEMBLYMINORVERSION asm_rmm -#define VER_ASSEMBLYBUILD asm_rup -#define VER_ASSEMBLYBUILD_QFE asm_rpt - -#define QUOTE_MACRO_HELPER(x) #x -#define QUOTE_MACRO(x) QUOTE_MACRO_HELPER(x) - -#ifndef QUOTE_MACRO_L -#define QUOTE_MACRO_L_HELPER(x) L###x -#define QUOTE_MACRO_L(x) QUOTE_MACRO_L_HELPER(x) -#endif - -#define CONCAT_MACRO_HELPER(x, y) x ## y -#define CONCAT_MACRO(x, y) CONCAT_MACRO_HELPER(x, y) - -#define VER_PRODUCTVERSION CLR_MAJOR_VERSION,CLR_MINOR_VERSION,CLR_BUILD_VERSION,CLR_BUILD_VERSION_QFE -#define VER_DOTFILEVERSION CLR_MAJOR_VERSION,VER_FILEVERSIONMINOR,VER_FILEVERSIONBUILD,VER_FILEVERSIONREVISION -#define VER_MANAGED_DOTFILEVERSION CLR_MAJOR_VERSION.VER_FILEVERSIONMINOR.VER_FILEVERSIONBUILD.VER_FILEVERSIONREVISION - -#define VER_DOTPRODUCTVERSION CLR_MAJOR_VERSION.CLR_MINOR_VERSION.CLR_BUILD_VERSION.CLR_BUILD_VERSION_QFE -#define VER_DOTPRODUCTMAJORMINOR CLR_MAJOR_VERSION.CLR_MINOR_VERSION -#define VER_DOTPRODUCTVERSIONNOQFE CLR_MAJOR_VERSION.CLR_MINOR_VERSION.CLR_BUILD_VERSION -#define VER_DOTPRODUCTVERSIONZEROQFE CLR_MAJOR_VERSION.CLR_MINOR_VERSION.CLR_BUILD_VERSION.0 -#define VER_DOTASSEMBLYVERSION VER_ASSEMBLYMAJORVERSION.VER_ASSEMBLYMINORVERSION.VER_ASSEMBLYBUILD.VER_ASSEMBLYBUILD_QFE -#define VER_DOTASSEMBLYVERSION3PART VER_ASSEMBLYMAJORVERSION.VER_ASSEMBLYMINORVERSION.VER_ASSEMBLYBUILD - -#define VER_UNDERSCORE_PRODUCTVERSION_STR3 CONCAT_MACRO(_, CLR_BUILD_VERSION) -#define VER_UNDERSCORE_PRODUCTVERSION_STR2 CONCAT_MACRO(CLR_MINOR_VERSION, VER_UNDERSCORE_PRODUCTVERSION_STR3) -#define VER_UNDERSCORE_PRODUCTVERSION_STR1 CONCAT_MACRO(_, VER_UNDERSCORE_PRODUCTVERSION_STR2) -#define VER_UNDERSCORE_PRODUCTVERSION CONCAT_MACRO(CLR_MAJOR_VERSION, VER_UNDERSCORE_PRODUCTVERSION_STR1) - -#define VER_UNDERSCORE_PRODUCTVERSION_STR QUOTE_MACRO(VER_UNDERSCORE_PRODUCTVERSION) -#define VER_UNDERSCORE_PRODUCTVERSION_STR_L QUOTE_MACRO_L(VER_UNDERSCORE_PRODUCTVERSION) - -#define FX_FILEVERSION_STR QUOTE_MACRO(VER_MANAGED_DOTFILEVERSION) -#define VER_PRODUCTVERSION_STR QUOTE_MACRO(VER_DOTPRODUCTVERSION) -#define VER_PRODUCTVERSION_STR_L QUOTE_MACRO_L(VER_DOTPRODUCTVERSION) - -#define VER_PRODUCTMAJORMINOR_STR QUOTE_MACRO(VER_DOTPRODUCTMAJORMINOR) -#define VER_PRODUCTMAJORMINOR_STR_L QUOTE_MACRO_L(VER_DOTPRODUCTMAJORMINOR) - -#define VER_PRODUCTVERSION_NO_QFE_STR QUOTE_MACRO(VER_DOTPRODUCTVERSIONNOQFE) -#define VER_PRODUCTVERSION_NO_QFE_STR_L QUOTE_MACRO_L(VER_DOTPRODUCTVERSIONNOQFE) - -#define VER_PRODUCTVERSION_ZERO_QFE_STR QUOTE_MACRO(VER_DOTPRODUCTVERSIONZEROQFE) -#define VER_PRODUCTVERSION_ZERO_QFE_STR_L QUOTE_MACRO_L(VER_DOTPRODUCTVERSIONZEROQFE) - -#define VER_PRODUCTVERSION_NO_QFE_STR QUOTE_MACRO(VER_DOTPRODUCTVERSIONNOQFE) -#define VER_PRODUCTVERSION_NO_QFE_STR_L QUOTE_MACRO_L(VER_DOTPRODUCTVERSIONNOQFE) - -#define VER_ASSEMBLYVERSION_STR QUOTE_MACRO(VER_DOTASSEMBLYVERSION) -#define VER_ASSEMBLYVERSION_STR_L QUOTE_MACRO_L(VER_DOTASSEMBLYVERSION) - -#define VER_ASSEMBLYVERSION3PART_STR QUOTE_MACRO(VER_DOTASSEMBLYVERSION3PART) -#define VER_ASSEMBLYVERSION3PART_STR_L QUOTE_MACRO_L(VER_DOTASSEMBLYVERSION3PART) - -#define VER_ECMA_PUBLICKEY b77a5c561934e089 -#define ECMA_PUBLICKEY_STR QUOTE_MACRO(VER_ECMA_PUBLICKEY) -#define ECMA_PUBLICKEY_STR_L QUOTE_MACRO_L(VER_ECMA_PUBLICKEY) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/sospriv.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/sospriv.h index 8896720..2f03eb0 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/sospriv.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/sospriv.h @@ -3,11 +3,11 @@ /* this ALWAYS GENERATED file contains the definitions for the interfaces */ - /* File created by MIDL compiler version 8.00.0613 */ + /* File created by MIDL compiler version 8.01.0622 */ /* at Mon Jan 18 19:14:07 2038 */ -/* Compiler settings for C:/ssd/coreclr/src/inc/sospriv.idl: - Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.00.0613 +/* Compiler settings for C:/git/diagnostics/src/inc/sospriv.idl: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data VC __declspec() decoration level: @@ -49,56 +49,77 @@ #define __ISOSEnum_FWD_DEFINED__ typedef interface ISOSEnum ISOSEnum; -#endif /* __ISOSEnum_FWD_DEFINED__ */ +#endif /* __ISOSEnum_FWD_DEFINED__ */ #ifndef __ISOSHandleEnum_FWD_DEFINED__ #define __ISOSHandleEnum_FWD_DEFINED__ typedef interface ISOSHandleEnum ISOSHandleEnum; -#endif /* __ISOSHandleEnum_FWD_DEFINED__ */ +#endif /* __ISOSHandleEnum_FWD_DEFINED__ */ #ifndef __ISOSStackRefErrorEnum_FWD_DEFINED__ #define __ISOSStackRefErrorEnum_FWD_DEFINED__ typedef interface ISOSStackRefErrorEnum ISOSStackRefErrorEnum; -#endif /* __ISOSStackRefErrorEnum_FWD_DEFINED__ */ +#endif /* __ISOSStackRefErrorEnum_FWD_DEFINED__ */ #ifndef __ISOSStackRefEnum_FWD_DEFINED__ #define __ISOSStackRefEnum_FWD_DEFINED__ typedef interface ISOSStackRefEnum ISOSStackRefEnum; -#endif /* __ISOSStackRefEnum_FWD_DEFINED__ */ +#endif /* __ISOSStackRefEnum_FWD_DEFINED__ */ #ifndef __ISOSDacInterface_FWD_DEFINED__ #define __ISOSDacInterface_FWD_DEFINED__ typedef interface ISOSDacInterface ISOSDacInterface; -#endif /* __ISOSDacInterface_FWD_DEFINED__ */ +#endif /* __ISOSDacInterface_FWD_DEFINED__ */ #ifndef __ISOSDacInterface2_FWD_DEFINED__ #define __ISOSDacInterface2_FWD_DEFINED__ typedef interface ISOSDacInterface2 ISOSDacInterface2; -#endif /* __ISOSDacInterface2_FWD_DEFINED__ */ +#endif /* __ISOSDacInterface2_FWD_DEFINED__ */ #ifndef __ISOSDacInterface3_FWD_DEFINED__ #define __ISOSDacInterface3_FWD_DEFINED__ typedef interface ISOSDacInterface3 ISOSDacInterface3; -#endif /* __ISOSDacInterface3_FWD_DEFINED__ */ +#endif /* __ISOSDacInterface3_FWD_DEFINED__ */ #ifndef __ISOSDacInterface4_FWD_DEFINED__ #define __ISOSDacInterface4_FWD_DEFINED__ typedef interface ISOSDacInterface4 ISOSDacInterface4; -#endif /* __ISOSDacInterface4_FWD_DEFINED__ */ +#endif /* __ISOSDacInterface4_FWD_DEFINED__ */ + + +#ifndef __ISOSDacInterface5_FWD_DEFINED__ +#define __ISOSDacInterface5_FWD_DEFINED__ +typedef interface ISOSDacInterface5 ISOSDacInterface5; + +#endif /* __ISOSDacInterface5_FWD_DEFINED__ */ + + +#ifndef __ISOSDacInterface6_FWD_DEFINED__ +#define __ISOSDacInterface6_FWD_DEFINED__ +typedef interface ISOSDacInterface6 ISOSDacInterface6; + +#endif /* __ISOSDacInterface6_FWD_DEFINED__ */ + + +#ifndef __ISOSDacInterface7_FWD_DEFINED__ +#define __ISOSDacInterface7_FWD_DEFINED__ +typedef interface ISOSDacInterface7 ISOSDacInterface7; + +#endif /* __ISOSDacInterface7_FWD_DEFINED__ */ /* header files for imported files */ @@ -153,8 +174,8 @@ typedef int ModuleMapType; typedef int VCSHeapType; #endif -enum ModuleMapType { TYPEDEFTOMETHODTABLE, TYPEREFTOMETHODTABLE }; -enum VCSHeapType {IndcellHeap, LookupHeap, ResolveHeap, DispatchHeap, CacheEntryHeap}; +typedef enum { TYPEDEFTOMETHODTABLE, TYPEREFTOMETHODTABLE } ModuleMapType; +typedef enum {IndcellHeap, LookupHeap, ResolveHeap, DispatchHeap, CacheEntryHeap} VCSHeapType; typedef void ( *MODULEMAPTRAVERSE )( UINT index, CLRDATA_ADDRESS methodTable, @@ -190,7 +211,7 @@ typedef struct _SOSHandleData unsigned int RefCount; unsigned int JupiterRefCount; BOOL IsPegged; - } SOSHandleData; + } SOSHandleData; #endif //HandleData @@ -224,7 +245,7 @@ EXTERN_C const IID IID_ISOSEnum; }; -#else /* C style interface */ +#else /* C style interface */ typedef struct ISOSEnumVtbl { @@ -266,34 +287,34 @@ EXTERN_C const IID IID_ISOSEnum; #ifdef COBJMACROS -#define ISOSEnum_QueryInterface(This,riid,ppvObject) \ +#define ISOSEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ISOSEnum_AddRef(This) \ +#define ISOSEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ISOSEnum_Release(This) \ +#define ISOSEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ISOSEnum_Skip(This,count) \ +#define ISOSEnum_Skip(This,count) \ ( (This)->lpVtbl -> Skip(This,count) ) -#define ISOSEnum_Reset(This) \ +#define ISOSEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) -#define ISOSEnum_GetCount(This,pCount) \ +#define ISOSEnum_GetCount(This,pCount) \ ( (This)->lpVtbl -> GetCount(This,pCount) ) #endif /* COBJMACROS */ -#endif /* C style interface */ +#endif /* C style interface */ -#endif /* __ISOSEnum_INTERFACE_DEFINED__ */ +#endif /* __ISOSEnum_INTERFACE_DEFINED__ */ #ifndef __ISOSHandleEnum_INTERFACE_DEFINED__ @@ -319,7 +340,7 @@ EXTERN_C const IID IID_ISOSHandleEnum; }; -#else /* C style interface */ +#else /* C style interface */ typedef struct ISOSHandleEnumVtbl { @@ -367,38 +388,38 @@ EXTERN_C const IID IID_ISOSHandleEnum; #ifdef COBJMACROS -#define ISOSHandleEnum_QueryInterface(This,riid,ppvObject) \ +#define ISOSHandleEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ISOSHandleEnum_AddRef(This) \ +#define ISOSHandleEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ISOSHandleEnum_Release(This) \ +#define ISOSHandleEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ISOSHandleEnum_Skip(This,count) \ +#define ISOSHandleEnum_Skip(This,count) \ ( (This)->lpVtbl -> Skip(This,count) ) -#define ISOSHandleEnum_Reset(This) \ +#define ISOSHandleEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) -#define ISOSHandleEnum_GetCount(This,pCount) \ +#define ISOSHandleEnum_GetCount(This,pCount) \ ( (This)->lpVtbl -> GetCount(This,pCount) ) -#define ISOSHandleEnum_Next(This,count,handles,pNeeded) \ +#define ISOSHandleEnum_Next(This,count,handles,pNeeded) \ ( (This)->lpVtbl -> Next(This,count,handles,pNeeded) ) #endif /* COBJMACROS */ -#endif /* C style interface */ +#endif /* C style interface */ -#endif /* __ISOSHandleEnum_INTERFACE_DEFINED__ */ +#endif /* __ISOSHandleEnum_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_sospriv_0000_0002 */ @@ -409,16 +430,16 @@ EXTERN_C const IID IID_ISOSHandleEnum; typedef enum SOSStackSourceType { - SOS_StackSourceIP = 0, - SOS_StackSourceFrame = ( SOS_StackSourceIP + 1 ) - } SOSStackSourceType; + SOS_StackSourceIP = 0, + SOS_StackSourceFrame = ( SOS_StackSourceIP + 1 ) + } SOSStackSourceType; typedef enum SOSRefFlags { - SOSRefInterior = 1, - SOSRefPinned = 2 - } SOSRefFlags; + SOSRefInterior = 1, + SOSRefPinned = 2 + } SOSRefFlags; typedef struct _SOS_StackRefData { @@ -431,14 +452,14 @@ typedef struct _SOS_StackRefData SOSStackSourceType SourceType; CLRDATA_ADDRESS Source; CLRDATA_ADDRESS StackPointer; - } SOSStackRefData; + } SOSStackRefData; typedef struct _SOS_StackRefError { SOSStackSourceType SourceType; CLRDATA_ADDRESS Source; CLRDATA_ADDRESS StackPointer; - } SOSStackRefError; + } SOSStackRefError; #endif // _SOS_StackReference_ @@ -469,7 +490,7 @@ EXTERN_C const IID IID_ISOSStackRefErrorEnum; }; -#else /* C style interface */ +#else /* C style interface */ typedef struct ISOSStackRefErrorEnumVtbl { @@ -517,38 +538,38 @@ EXTERN_C const IID IID_ISOSStackRefErrorEnum; #ifdef COBJMACROS -#define ISOSStackRefErrorEnum_QueryInterface(This,riid,ppvObject) \ +#define ISOSStackRefErrorEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ISOSStackRefErrorEnum_AddRef(This) \ +#define ISOSStackRefErrorEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ISOSStackRefErrorEnum_Release(This) \ +#define ISOSStackRefErrorEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ISOSStackRefErrorEnum_Skip(This,count) \ +#define ISOSStackRefErrorEnum_Skip(This,count) \ ( (This)->lpVtbl -> Skip(This,count) ) -#define ISOSStackRefErrorEnum_Reset(This) \ +#define ISOSStackRefErrorEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) -#define ISOSStackRefErrorEnum_GetCount(This,pCount) \ +#define ISOSStackRefErrorEnum_GetCount(This,pCount) \ ( (This)->lpVtbl -> GetCount(This,pCount) ) -#define ISOSStackRefErrorEnum_Next(This,count,ref,pFetched) \ +#define ISOSStackRefErrorEnum_Next(This,count,ref,pFetched) \ ( (This)->lpVtbl -> Next(This,count,ref,pFetched) ) #endif /* COBJMACROS */ -#endif /* C style interface */ +#endif /* C style interface */ -#endif /* __ISOSStackRefErrorEnum_INTERFACE_DEFINED__ */ +#endif /* __ISOSStackRefErrorEnum_INTERFACE_DEFINED__ */ #ifndef __ISOSStackRefEnum_INTERFACE_DEFINED__ @@ -577,7 +598,7 @@ EXTERN_C const IID IID_ISOSStackRefEnum; }; -#else /* C style interface */ +#else /* C style interface */ typedef struct ISOSStackRefEnumVtbl { @@ -629,41 +650,41 @@ EXTERN_C const IID IID_ISOSStackRefEnum; #ifdef COBJMACROS -#define ISOSStackRefEnum_QueryInterface(This,riid,ppvObject) \ +#define ISOSStackRefEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ISOSStackRefEnum_AddRef(This) \ +#define ISOSStackRefEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ISOSStackRefEnum_Release(This) \ +#define ISOSStackRefEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ISOSStackRefEnum_Skip(This,count) \ +#define ISOSStackRefEnum_Skip(This,count) \ ( (This)->lpVtbl -> Skip(This,count) ) -#define ISOSStackRefEnum_Reset(This) \ +#define ISOSStackRefEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) -#define ISOSStackRefEnum_GetCount(This,pCount) \ +#define ISOSStackRefEnum_GetCount(This,pCount) \ ( (This)->lpVtbl -> GetCount(This,pCount) ) -#define ISOSStackRefEnum_Next(This,count,ref,pFetched) \ +#define ISOSStackRefEnum_Next(This,count,ref,pFetched) \ ( (This)->lpVtbl -> Next(This,count,ref,pFetched) ) -#define ISOSStackRefEnum_EnumerateErrors(This,ppEnum) \ +#define ISOSStackRefEnum_EnumerateErrors(This,ppEnum) \ ( (This)->lpVtbl -> EnumerateErrors(This,ppEnum) ) #endif /* COBJMACROS */ -#endif /* C style interface */ +#endif /* C style interface */ -#endif /* __ISOSStackRefEnum_INTERFACE_DEFINED__ */ +#endif /* __ISOSStackRefEnum_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface_INTERFACE_DEFINED__ @@ -1093,7 +1114,7 @@ EXTERN_C const IID IID_ISOSDacInterface; }; -#else /* C style interface */ +#else /* C style interface */ typedef struct ISOSDacInterfaceVtbl { @@ -1621,289 +1642,289 @@ EXTERN_C const IID IID_ISOSDacInterface; #ifdef COBJMACROS -#define ISOSDacInterface_QueryInterface(This,riid,ppvObject) \ +#define ISOSDacInterface_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ISOSDacInterface_AddRef(This) \ +#define ISOSDacInterface_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ISOSDacInterface_Release(This) \ +#define ISOSDacInterface_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ISOSDacInterface_GetThreadStoreData(This,data) \ +#define ISOSDacInterface_GetThreadStoreData(This,data) \ ( (This)->lpVtbl -> GetThreadStoreData(This,data) ) -#define ISOSDacInterface_GetAppDomainStoreData(This,data) \ +#define ISOSDacInterface_GetAppDomainStoreData(This,data) \ ( (This)->lpVtbl -> GetAppDomainStoreData(This,data) ) -#define ISOSDacInterface_GetAppDomainList(This,count,values,pNeeded) \ +#define ISOSDacInterface_GetAppDomainList(This,count,values,pNeeded) \ ( (This)->lpVtbl -> GetAppDomainList(This,count,values,pNeeded) ) -#define ISOSDacInterface_GetAppDomainData(This,addr,data) \ +#define ISOSDacInterface_GetAppDomainData(This,addr,data) \ ( (This)->lpVtbl -> GetAppDomainData(This,addr,data) ) -#define ISOSDacInterface_GetAppDomainName(This,addr,count,name,pNeeded) \ +#define ISOSDacInterface_GetAppDomainName(This,addr,count,name,pNeeded) \ ( (This)->lpVtbl -> GetAppDomainName(This,addr,count,name,pNeeded) ) -#define ISOSDacInterface_GetDomainFromContext(This,context,domain) \ +#define ISOSDacInterface_GetDomainFromContext(This,context,domain) \ ( (This)->lpVtbl -> GetDomainFromContext(This,context,domain) ) -#define ISOSDacInterface_GetAssemblyList(This,appDomain,count,values,pNeeded) \ +#define ISOSDacInterface_GetAssemblyList(This,appDomain,count,values,pNeeded) \ ( (This)->lpVtbl -> GetAssemblyList(This,appDomain,count,values,pNeeded) ) -#define ISOSDacInterface_GetAssemblyData(This,baseDomainPtr,assembly,data) \ +#define ISOSDacInterface_GetAssemblyData(This,baseDomainPtr,assembly,data) \ ( (This)->lpVtbl -> GetAssemblyData(This,baseDomainPtr,assembly,data) ) -#define ISOSDacInterface_GetAssemblyName(This,assembly,count,name,pNeeded) \ +#define ISOSDacInterface_GetAssemblyName(This,assembly,count,name,pNeeded) \ ( (This)->lpVtbl -> GetAssemblyName(This,assembly,count,name,pNeeded) ) -#define ISOSDacInterface_GetModule(This,addr,mod) \ +#define ISOSDacInterface_GetModule(This,addr,mod) \ ( (This)->lpVtbl -> GetModule(This,addr,mod) ) -#define ISOSDacInterface_GetModuleData(This,moduleAddr,data) \ +#define ISOSDacInterface_GetModuleData(This,moduleAddr,data) \ ( (This)->lpVtbl -> GetModuleData(This,moduleAddr,data) ) -#define ISOSDacInterface_TraverseModuleMap(This,mmt,moduleAddr,pCallback,token) \ +#define ISOSDacInterface_TraverseModuleMap(This,mmt,moduleAddr,pCallback,token) \ ( (This)->lpVtbl -> TraverseModuleMap(This,mmt,moduleAddr,pCallback,token) ) -#define ISOSDacInterface_GetAssemblyModuleList(This,assembly,count,modules,pNeeded) \ +#define ISOSDacInterface_GetAssemblyModuleList(This,assembly,count,modules,pNeeded) \ ( (This)->lpVtbl -> GetAssemblyModuleList(This,assembly,count,modules,pNeeded) ) -#define ISOSDacInterface_GetILForModule(This,moduleAddr,rva,il) \ +#define ISOSDacInterface_GetILForModule(This,moduleAddr,rva,il) \ ( (This)->lpVtbl -> GetILForModule(This,moduleAddr,rva,il) ) -#define ISOSDacInterface_GetThreadData(This,thread,data) \ +#define ISOSDacInterface_GetThreadData(This,thread,data) \ ( (This)->lpVtbl -> GetThreadData(This,thread,data) ) -#define ISOSDacInterface_GetThreadFromThinlockID(This,thinLockId,pThread) \ +#define ISOSDacInterface_GetThreadFromThinlockID(This,thinLockId,pThread) \ ( (This)->lpVtbl -> GetThreadFromThinlockID(This,thinLockId,pThread) ) -#define ISOSDacInterface_GetStackLimits(This,threadPtr,lower,upper,fp) \ +#define ISOSDacInterface_GetStackLimits(This,threadPtr,lower,upper,fp) \ ( (This)->lpVtbl -> GetStackLimits(This,threadPtr,lower,upper,fp) ) -#define ISOSDacInterface_GetMethodDescData(This,methodDesc,ip,data,cRevertedRejitVersions,rgRevertedRejitData,pcNeededRevertedRejitData) \ +#define ISOSDacInterface_GetMethodDescData(This,methodDesc,ip,data,cRevertedRejitVersions,rgRevertedRejitData,pcNeededRevertedRejitData) \ ( (This)->lpVtbl -> GetMethodDescData(This,methodDesc,ip,data,cRevertedRejitVersions,rgRevertedRejitData,pcNeededRevertedRejitData) ) -#define ISOSDacInterface_GetMethodDescPtrFromIP(This,ip,ppMD) \ +#define ISOSDacInterface_GetMethodDescPtrFromIP(This,ip,ppMD) \ ( (This)->lpVtbl -> GetMethodDescPtrFromIP(This,ip,ppMD) ) -#define ISOSDacInterface_GetMethodDescName(This,methodDesc,count,name,pNeeded) \ +#define ISOSDacInterface_GetMethodDescName(This,methodDesc,count,name,pNeeded) \ ( (This)->lpVtbl -> GetMethodDescName(This,methodDesc,count,name,pNeeded) ) -#define ISOSDacInterface_GetMethodDescPtrFromFrame(This,frameAddr,ppMD) \ +#define ISOSDacInterface_GetMethodDescPtrFromFrame(This,frameAddr,ppMD) \ ( (This)->lpVtbl -> GetMethodDescPtrFromFrame(This,frameAddr,ppMD) ) -#define ISOSDacInterface_GetMethodDescFromToken(This,moduleAddr,token,methodDesc) \ +#define ISOSDacInterface_GetMethodDescFromToken(This,moduleAddr,token,methodDesc) \ ( (This)->lpVtbl -> GetMethodDescFromToken(This,moduleAddr,token,methodDesc) ) -#define ISOSDacInterface_GetMethodDescTransparencyData(This,methodDesc,data) \ +#define ISOSDacInterface_GetMethodDescTransparencyData(This,methodDesc,data) \ ( (This)->lpVtbl -> GetMethodDescTransparencyData(This,methodDesc,data) ) -#define ISOSDacInterface_GetCodeHeaderData(This,ip,data) \ +#define ISOSDacInterface_GetCodeHeaderData(This,ip,data) \ ( (This)->lpVtbl -> GetCodeHeaderData(This,ip,data) ) -#define ISOSDacInterface_GetJitManagerList(This,count,managers,pNeeded) \ +#define ISOSDacInterface_GetJitManagerList(This,count,managers,pNeeded) \ ( (This)->lpVtbl -> GetJitManagerList(This,count,managers,pNeeded) ) -#define ISOSDacInterface_GetJitHelperFunctionName(This,ip,count,name,pNeeded) \ +#define ISOSDacInterface_GetJitHelperFunctionName(This,ip,count,name,pNeeded) \ ( (This)->lpVtbl -> GetJitHelperFunctionName(This,ip,count,name,pNeeded) ) -#define ISOSDacInterface_GetJumpThunkTarget(This,ctx,targetIP,targetMD) \ +#define ISOSDacInterface_GetJumpThunkTarget(This,ctx,targetIP,targetMD) \ ( (This)->lpVtbl -> GetJumpThunkTarget(This,ctx,targetIP,targetMD) ) -#define ISOSDacInterface_GetThreadpoolData(This,data) \ +#define ISOSDacInterface_GetThreadpoolData(This,data) \ ( (This)->lpVtbl -> GetThreadpoolData(This,data) ) -#define ISOSDacInterface_GetWorkRequestData(This,addrWorkRequest,data) \ +#define ISOSDacInterface_GetWorkRequestData(This,addrWorkRequest,data) \ ( (This)->lpVtbl -> GetWorkRequestData(This,addrWorkRequest,data) ) -#define ISOSDacInterface_GetHillClimbingLogEntry(This,addr,data) \ +#define ISOSDacInterface_GetHillClimbingLogEntry(This,addr,data) \ ( (This)->lpVtbl -> GetHillClimbingLogEntry(This,addr,data) ) -#define ISOSDacInterface_GetObjectData(This,objAddr,data) \ +#define ISOSDacInterface_GetObjectData(This,objAddr,data) \ ( (This)->lpVtbl -> GetObjectData(This,objAddr,data) ) -#define ISOSDacInterface_GetObjectStringData(This,obj,count,stringData,pNeeded) \ +#define ISOSDacInterface_GetObjectStringData(This,obj,count,stringData,pNeeded) \ ( (This)->lpVtbl -> GetObjectStringData(This,obj,count,stringData,pNeeded) ) -#define ISOSDacInterface_GetObjectClassName(This,obj,count,className,pNeeded) \ +#define ISOSDacInterface_GetObjectClassName(This,obj,count,className,pNeeded) \ ( (This)->lpVtbl -> GetObjectClassName(This,obj,count,className,pNeeded) ) -#define ISOSDacInterface_GetMethodTableName(This,mt,count,mtName,pNeeded) \ +#define ISOSDacInterface_GetMethodTableName(This,mt,count,mtName,pNeeded) \ ( (This)->lpVtbl -> GetMethodTableName(This,mt,count,mtName,pNeeded) ) -#define ISOSDacInterface_GetMethodTableData(This,mt,data) \ +#define ISOSDacInterface_GetMethodTableData(This,mt,data) \ ( (This)->lpVtbl -> GetMethodTableData(This,mt,data) ) -#define ISOSDacInterface_GetMethodTableSlot(This,mt,slot,value) \ +#define ISOSDacInterface_GetMethodTableSlot(This,mt,slot,value) \ ( (This)->lpVtbl -> GetMethodTableSlot(This,mt,slot,value) ) -#define ISOSDacInterface_GetMethodTableFieldData(This,mt,data) \ +#define ISOSDacInterface_GetMethodTableFieldData(This,mt,data) \ ( (This)->lpVtbl -> GetMethodTableFieldData(This,mt,data) ) -#define ISOSDacInterface_GetMethodTableTransparencyData(This,mt,data) \ +#define ISOSDacInterface_GetMethodTableTransparencyData(This,mt,data) \ ( (This)->lpVtbl -> GetMethodTableTransparencyData(This,mt,data) ) -#define ISOSDacInterface_GetMethodTableForEEClass(This,eeClass,value) \ +#define ISOSDacInterface_GetMethodTableForEEClass(This,eeClass,value) \ ( (This)->lpVtbl -> GetMethodTableForEEClass(This,eeClass,value) ) -#define ISOSDacInterface_GetFieldDescData(This,fieldDesc,data) \ +#define ISOSDacInterface_GetFieldDescData(This,fieldDesc,data) \ ( (This)->lpVtbl -> GetFieldDescData(This,fieldDesc,data) ) -#define ISOSDacInterface_GetFrameName(This,vtable,count,frameName,pNeeded) \ +#define ISOSDacInterface_GetFrameName(This,vtable,count,frameName,pNeeded) \ ( (This)->lpVtbl -> GetFrameName(This,vtable,count,frameName,pNeeded) ) -#define ISOSDacInterface_GetPEFileBase(This,addr,base) \ +#define ISOSDacInterface_GetPEFileBase(This,addr,base) \ ( (This)->lpVtbl -> GetPEFileBase(This,addr,base) ) -#define ISOSDacInterface_GetPEFileName(This,addr,count,fileName,pNeeded) \ +#define ISOSDacInterface_GetPEFileName(This,addr,count,fileName,pNeeded) \ ( (This)->lpVtbl -> GetPEFileName(This,addr,count,fileName,pNeeded) ) -#define ISOSDacInterface_GetGCHeapData(This,data) \ +#define ISOSDacInterface_GetGCHeapData(This,data) \ ( (This)->lpVtbl -> GetGCHeapData(This,data) ) -#define ISOSDacInterface_GetGCHeapList(This,count,heaps,pNeeded) \ +#define ISOSDacInterface_GetGCHeapList(This,count,heaps,pNeeded) \ ( (This)->lpVtbl -> GetGCHeapList(This,count,heaps,pNeeded) ) -#define ISOSDacInterface_GetGCHeapDetails(This,heap,details) \ +#define ISOSDacInterface_GetGCHeapDetails(This,heap,details) \ ( (This)->lpVtbl -> GetGCHeapDetails(This,heap,details) ) -#define ISOSDacInterface_GetGCHeapStaticData(This,data) \ +#define ISOSDacInterface_GetGCHeapStaticData(This,data) \ ( (This)->lpVtbl -> GetGCHeapStaticData(This,data) ) -#define ISOSDacInterface_GetHeapSegmentData(This,seg,data) \ +#define ISOSDacInterface_GetHeapSegmentData(This,seg,data) \ ( (This)->lpVtbl -> GetHeapSegmentData(This,seg,data) ) -#define ISOSDacInterface_GetOOMData(This,oomAddr,data) \ +#define ISOSDacInterface_GetOOMData(This,oomAddr,data) \ ( (This)->lpVtbl -> GetOOMData(This,oomAddr,data) ) -#define ISOSDacInterface_GetOOMStaticData(This,data) \ +#define ISOSDacInterface_GetOOMStaticData(This,data) \ ( (This)->lpVtbl -> GetOOMStaticData(This,data) ) -#define ISOSDacInterface_GetHeapAnalyzeData(This,addr,data) \ +#define ISOSDacInterface_GetHeapAnalyzeData(This,addr,data) \ ( (This)->lpVtbl -> GetHeapAnalyzeData(This,addr,data) ) -#define ISOSDacInterface_GetHeapAnalyzeStaticData(This,data) \ +#define ISOSDacInterface_GetHeapAnalyzeStaticData(This,data) \ ( (This)->lpVtbl -> GetHeapAnalyzeStaticData(This,data) ) -#define ISOSDacInterface_GetDomainLocalModuleData(This,addr,data) \ +#define ISOSDacInterface_GetDomainLocalModuleData(This,addr,data) \ ( (This)->lpVtbl -> GetDomainLocalModuleData(This,addr,data) ) -#define ISOSDacInterface_GetDomainLocalModuleDataFromAppDomain(This,appDomainAddr,moduleID,data) \ +#define ISOSDacInterface_GetDomainLocalModuleDataFromAppDomain(This,appDomainAddr,moduleID,data) \ ( (This)->lpVtbl -> GetDomainLocalModuleDataFromAppDomain(This,appDomainAddr,moduleID,data) ) -#define ISOSDacInterface_GetDomainLocalModuleDataFromModule(This,moduleAddr,data) \ +#define ISOSDacInterface_GetDomainLocalModuleDataFromModule(This,moduleAddr,data) \ ( (This)->lpVtbl -> GetDomainLocalModuleDataFromModule(This,moduleAddr,data) ) -#define ISOSDacInterface_GetThreadLocalModuleData(This,thread,index,data) \ +#define ISOSDacInterface_GetThreadLocalModuleData(This,thread,index,data) \ ( (This)->lpVtbl -> GetThreadLocalModuleData(This,thread,index,data) ) -#define ISOSDacInterface_GetSyncBlockData(This,number,data) \ +#define ISOSDacInterface_GetSyncBlockData(This,number,data) \ ( (This)->lpVtbl -> GetSyncBlockData(This,number,data) ) -#define ISOSDacInterface_GetSyncBlockCleanupData(This,addr,data) \ +#define ISOSDacInterface_GetSyncBlockCleanupData(This,addr,data) \ ( (This)->lpVtbl -> GetSyncBlockCleanupData(This,addr,data) ) -#define ISOSDacInterface_GetHandleEnum(This,ppHandleEnum) \ +#define ISOSDacInterface_GetHandleEnum(This,ppHandleEnum) \ ( (This)->lpVtbl -> GetHandleEnum(This,ppHandleEnum) ) -#define ISOSDacInterface_GetHandleEnumForTypes(This,types,count,ppHandleEnum) \ +#define ISOSDacInterface_GetHandleEnumForTypes(This,types,count,ppHandleEnum) \ ( (This)->lpVtbl -> GetHandleEnumForTypes(This,types,count,ppHandleEnum) ) -#define ISOSDacInterface_GetHandleEnumForGC(This,gen,ppHandleEnum) \ +#define ISOSDacInterface_GetHandleEnumForGC(This,gen,ppHandleEnum) \ ( (This)->lpVtbl -> GetHandleEnumForGC(This,gen,ppHandleEnum) ) -#define ISOSDacInterface_TraverseEHInfo(This,ip,pCallback,token) \ +#define ISOSDacInterface_TraverseEHInfo(This,ip,pCallback,token) \ ( (This)->lpVtbl -> TraverseEHInfo(This,ip,pCallback,token) ) -#define ISOSDacInterface_GetNestedExceptionData(This,exception,exceptionObject,nextNestedException) \ +#define ISOSDacInterface_GetNestedExceptionData(This,exception,exceptionObject,nextNestedException) \ ( (This)->lpVtbl -> GetNestedExceptionData(This,exception,exceptionObject,nextNestedException) ) -#define ISOSDacInterface_GetStressLogAddress(This,stressLog) \ +#define ISOSDacInterface_GetStressLogAddress(This,stressLog) \ ( (This)->lpVtbl -> GetStressLogAddress(This,stressLog) ) -#define ISOSDacInterface_TraverseLoaderHeap(This,loaderHeapAddr,pCallback) \ +#define ISOSDacInterface_TraverseLoaderHeap(This,loaderHeapAddr,pCallback) \ ( (This)->lpVtbl -> TraverseLoaderHeap(This,loaderHeapAddr,pCallback) ) -#define ISOSDacInterface_GetCodeHeapList(This,jitManager,count,codeHeaps,pNeeded) \ +#define ISOSDacInterface_GetCodeHeapList(This,jitManager,count,codeHeaps,pNeeded) \ ( (This)->lpVtbl -> GetCodeHeapList(This,jitManager,count,codeHeaps,pNeeded) ) -#define ISOSDacInterface_TraverseVirtCallStubHeap(This,pAppDomain,heaptype,pCallback) \ +#define ISOSDacInterface_TraverseVirtCallStubHeap(This,pAppDomain,heaptype,pCallback) \ ( (This)->lpVtbl -> TraverseVirtCallStubHeap(This,pAppDomain,heaptype,pCallback) ) -#define ISOSDacInterface_GetUsefulGlobals(This,data) \ +#define ISOSDacInterface_GetUsefulGlobals(This,data) \ ( (This)->lpVtbl -> GetUsefulGlobals(This,data) ) -#define ISOSDacInterface_GetClrWatsonBuckets(This,thread,pGenericModeBlock) \ +#define ISOSDacInterface_GetClrWatsonBuckets(This,thread,pGenericModeBlock) \ ( (This)->lpVtbl -> GetClrWatsonBuckets(This,thread,pGenericModeBlock) ) -#define ISOSDacInterface_GetTLSIndex(This,pIndex) \ +#define ISOSDacInterface_GetTLSIndex(This,pIndex) \ ( (This)->lpVtbl -> GetTLSIndex(This,pIndex) ) -#define ISOSDacInterface_GetDacModuleHandle(This,phModule) \ +#define ISOSDacInterface_GetDacModuleHandle(This,phModule) \ ( (This)->lpVtbl -> GetDacModuleHandle(This,phModule) ) -#define ISOSDacInterface_GetRCWData(This,addr,data) \ +#define ISOSDacInterface_GetRCWData(This,addr,data) \ ( (This)->lpVtbl -> GetRCWData(This,addr,data) ) -#define ISOSDacInterface_GetRCWInterfaces(This,rcw,count,interfaces,pNeeded) \ +#define ISOSDacInterface_GetRCWInterfaces(This,rcw,count,interfaces,pNeeded) \ ( (This)->lpVtbl -> GetRCWInterfaces(This,rcw,count,interfaces,pNeeded) ) -#define ISOSDacInterface_GetCCWData(This,ccw,data) \ +#define ISOSDacInterface_GetCCWData(This,ccw,data) \ ( (This)->lpVtbl -> GetCCWData(This,ccw,data) ) -#define ISOSDacInterface_GetCCWInterfaces(This,ccw,count,interfaces,pNeeded) \ +#define ISOSDacInterface_GetCCWInterfaces(This,ccw,count,interfaces,pNeeded) \ ( (This)->lpVtbl -> GetCCWInterfaces(This,ccw,count,interfaces,pNeeded) ) -#define ISOSDacInterface_TraverseRCWCleanupList(This,cleanupListPtr,pCallback,token) \ +#define ISOSDacInterface_TraverseRCWCleanupList(This,cleanupListPtr,pCallback,token) \ ( (This)->lpVtbl -> TraverseRCWCleanupList(This,cleanupListPtr,pCallback,token) ) -#define ISOSDacInterface_GetStackReferences(This,osThreadID,ppEnum) \ +#define ISOSDacInterface_GetStackReferences(This,osThreadID,ppEnum) \ ( (This)->lpVtbl -> GetStackReferences(This,osThreadID,ppEnum) ) -#define ISOSDacInterface_GetRegisterName(This,regName,count,buffer,pNeeded) \ +#define ISOSDacInterface_GetRegisterName(This,regName,count,buffer,pNeeded) \ ( (This)->lpVtbl -> GetRegisterName(This,regName,count,buffer,pNeeded) ) -#define ISOSDacInterface_GetThreadAllocData(This,thread,data) \ +#define ISOSDacInterface_GetThreadAllocData(This,thread,data) \ ( (This)->lpVtbl -> GetThreadAllocData(This,thread,data) ) -#define ISOSDacInterface_GetHeapAllocData(This,count,data,pNeeded) \ +#define ISOSDacInterface_GetHeapAllocData(This,count,data,pNeeded) \ ( (This)->lpVtbl -> GetHeapAllocData(This,count,data,pNeeded) ) -#define ISOSDacInterface_GetFailedAssemblyList(This,appDomain,count,values,pNeeded) \ +#define ISOSDacInterface_GetFailedAssemblyList(This,appDomain,count,values,pNeeded) \ ( (This)->lpVtbl -> GetFailedAssemblyList(This,appDomain,count,values,pNeeded) ) -#define ISOSDacInterface_GetPrivateBinPaths(This,appDomain,count,paths,pNeeded) \ +#define ISOSDacInterface_GetPrivateBinPaths(This,appDomain,count,paths,pNeeded) \ ( (This)->lpVtbl -> GetPrivateBinPaths(This,appDomain,count,paths,pNeeded) ) -#define ISOSDacInterface_GetAssemblyLocation(This,assembly,count,location,pNeeded) \ +#define ISOSDacInterface_GetAssemblyLocation(This,assembly,count,location,pNeeded) \ ( (This)->lpVtbl -> GetAssemblyLocation(This,assembly,count,location,pNeeded) ) -#define ISOSDacInterface_GetAppDomainConfigFile(This,appDomain,count,configFile,pNeeded) \ +#define ISOSDacInterface_GetAppDomainConfigFile(This,appDomain,count,configFile,pNeeded) \ ( (This)->lpVtbl -> GetAppDomainConfigFile(This,appDomain,count,configFile,pNeeded) ) -#define ISOSDacInterface_GetApplicationBase(This,appDomain,count,base,pNeeded) \ +#define ISOSDacInterface_GetApplicationBase(This,appDomain,count,base,pNeeded) \ ( (This)->lpVtbl -> GetApplicationBase(This,appDomain,count,base,pNeeded) ) -#define ISOSDacInterface_GetFailedAssemblyData(This,assembly,pContext,pResult) \ +#define ISOSDacInterface_GetFailedAssemblyData(This,assembly,pContext,pResult) \ ( (This)->lpVtbl -> GetFailedAssemblyData(This,assembly,pContext,pResult) ) -#define ISOSDacInterface_GetFailedAssemblyLocation(This,assesmbly,count,location,pNeeded) \ +#define ISOSDacInterface_GetFailedAssemblyLocation(This,assesmbly,count,location,pNeeded) \ ( (This)->lpVtbl -> GetFailedAssemblyLocation(This,assesmbly,count,location,pNeeded) ) -#define ISOSDacInterface_GetFailedAssemblyDisplayName(This,assembly,count,name,pNeeded) \ +#define ISOSDacInterface_GetFailedAssemblyDisplayName(This,assembly,count,name,pNeeded) \ ( (This)->lpVtbl -> GetFailedAssemblyDisplayName(This,assembly,count,name,pNeeded) ) #endif /* COBJMACROS */ -#endif /* C style interface */ +#endif /* C style interface */ -#endif /* __ISOSDacInterface_INTERFACE_DEFINED__ */ +#endif /* __ISOSDacInterface_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface2_INTERFACE_DEFINED__ @@ -1932,7 +1953,7 @@ EXTERN_C const IID IID_ISOSDacInterface2; }; -#else /* C style interface */ +#else /* C style interface */ typedef struct ISOSDacInterface2Vtbl { @@ -1973,31 +1994,31 @@ EXTERN_C const IID IID_ISOSDacInterface2; #ifdef COBJMACROS -#define ISOSDacInterface2_QueryInterface(This,riid,ppvObject) \ +#define ISOSDacInterface2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ISOSDacInterface2_AddRef(This) \ +#define ISOSDacInterface2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ISOSDacInterface2_Release(This) \ +#define ISOSDacInterface2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ISOSDacInterface2_GetObjectExceptionData(This,objAddr,data) \ +#define ISOSDacInterface2_GetObjectExceptionData(This,objAddr,data) \ ( (This)->lpVtbl -> GetObjectExceptionData(This,objAddr,data) ) -#define ISOSDacInterface2_IsRCWDCOMProxy(This,rcwAddr,isDCOMProxy) \ +#define ISOSDacInterface2_IsRCWDCOMProxy(This,rcwAddr,isDCOMProxy) \ ( (This)->lpVtbl -> IsRCWDCOMProxy(This,rcwAddr,isDCOMProxy) ) #endif /* COBJMACROS */ -#endif /* C style interface */ +#endif /* C style interface */ -#endif /* __ISOSDacInterface2_INTERFACE_DEFINED__ */ +#endif /* __ISOSDacInterface2_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface3_INTERFACE_DEFINED__ @@ -2028,7 +2049,7 @@ EXTERN_C const IID IID_ISOSDacInterface3; }; -#else /* C style interface */ +#else /* C style interface */ typedef struct ISOSDacInterface3Vtbl { @@ -2072,34 +2093,34 @@ EXTERN_C const IID IID_ISOSDacInterface3; #ifdef COBJMACROS -#define ISOSDacInterface3_QueryInterface(This,riid,ppvObject) \ +#define ISOSDacInterface3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ISOSDacInterface3_AddRef(This) \ +#define ISOSDacInterface3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ISOSDacInterface3_Release(This) \ +#define ISOSDacInterface3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ISOSDacInterface3_GetGCInterestingInfoData(This,interestingInfoAddr,data) \ +#define ISOSDacInterface3_GetGCInterestingInfoData(This,interestingInfoAddr,data) \ ( (This)->lpVtbl -> GetGCInterestingInfoData(This,interestingInfoAddr,data) ) -#define ISOSDacInterface3_GetGCInterestingInfoStaticData(This,data) \ +#define ISOSDacInterface3_GetGCInterestingInfoStaticData(This,data) \ ( (This)->lpVtbl -> GetGCInterestingInfoStaticData(This,data) ) -#define ISOSDacInterface3_GetGCGlobalMechanisms(This,globalMechanisms) \ +#define ISOSDacInterface3_GetGCGlobalMechanisms(This,globalMechanisms) \ ( (This)->lpVtbl -> GetGCGlobalMechanisms(This,globalMechanisms) ) #endif /* COBJMACROS */ -#endif /* C style interface */ +#endif /* C style interface */ -#endif /* __ISOSDacInterface3_INTERFACE_DEFINED__ */ +#endif /* __ISOSDacInterface3_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface4_INTERFACE_DEFINED__ @@ -2125,7 +2146,7 @@ EXTERN_C const IID IID_ISOSDacInterface4; }; -#else /* C style interface */ +#else /* C style interface */ typedef struct ISOSDacInterface4Vtbl { @@ -2162,28 +2183,28 @@ EXTERN_C const IID IID_ISOSDacInterface4; #ifdef COBJMACROS -#define ISOSDacInterface4_QueryInterface(This,riid,ppvObject) \ +#define ISOSDacInterface4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ISOSDacInterface4_AddRef(This) \ +#define ISOSDacInterface4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ISOSDacInterface4_Release(This) \ +#define ISOSDacInterface4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ISOSDacInterface4_GetClrNotification(This,arguments,count,pNeeded) \ +#define ISOSDacInterface4_GetClrNotification(This,arguments,count,pNeeded) \ ( (This)->lpVtbl -> GetClrNotification(This,arguments,count,pNeeded) ) #endif /* COBJMACROS */ -#endif /* C style interface */ +#endif /* C style interface */ -#endif /* __ISOSDacInterface4_INTERFACE_DEFINED__ */ +#endif /* __ISOSDacInterface4_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface5_INTERFACE_DEFINED__ @@ -2211,7 +2232,7 @@ EXTERN_C const IID IID_ISOSDacInterface5; }; -#else /* C style interface */ +#else /* C style interface */ typedef struct ISOSDacInterface5Vtbl { @@ -2233,8 +2254,9 @@ EXTERN_C const IID IID_ISOSDacInterface5; ISOSDacInterface5 * This, CLRDATA_ADDRESS methodDesc, int rejitId, - CLRDATA_ADDRESS *nativeCodeAddrs, - int cNativeCodeAddrs); + struct DacpTieredVersionData *nativeCodeAddrs, + int cNativeCodeAddrs, + int *pcNativeCodeAddrs); END_INTERFACE } ISOSDacInterface5Vtbl; @@ -2249,73 +2271,75 @@ EXTERN_C const IID IID_ISOSDacInterface5; #ifdef COBJMACROS -#define ISOSDacInterface5_QueryInterface(This,riid,ppvObject) \ +#define ISOSDacInterface5_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ISOSDacInterface5_AddRef(This) \ +#define ISOSDacInterface5_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ISOSDacInterface5_Release(This) \ +#define ISOSDacInterface5_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ISOSDacInterface5_GetTieredVersions(This,methodDesc,rejitId,nativeCodeAddrs,cNativeCodeAddrs) \ - ( (This)->lpVtbl -> GetTieredVersions(This,methodDesc,rejitId,nativeCodeAddrs,cNativeCodeAddrs) ) +#define ISOSDacInterface5_GetTieredVersions(This,methodDesc,rejitId,nativeCodeAddrs,cNativeCodeAddrs,pcNativeCodeAddrs) \ + ( (This)->lpVtbl -> GetTieredVersions(This,methodDesc,rejitId,nativeCodeAddrs,cNativeCodeAddrs,pcNativeCodeAddrs) ) #endif /* COBJMACROS */ -#endif /* C style interface */ +#endif /* C style interface */ -#endif /* __ISOSDacInterface5_INTERFACE_DEFINED__ */ +#endif /* __ISOSDacInterface5_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface6_INTERFACE_DEFINED__ #define __ISOSDacInterface6_INTERFACE_DEFINED__ - /* interface ISOSDacInterface6 */ - /* [uuid][local][object] */ +/* interface ISOSDacInterface6 */ +/* [uuid][local][object] */ - EXTERN_C const IID IID_ISOSDacInterface6; +EXTERN_C const IID IID_ISOSDacInterface6; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("11206399-4B66-4EDB-98EA-85654E59AD45") ISOSDacInterface6 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetMethodTableCollectibleData( - CLRDATA_ADDRESS mt, + virtual HRESULT STDMETHODCALLTYPE GetMethodTableCollectibleData( + CLRDATA_ADDRESS mt, struct DacpMethodTableCollectibleData *data) = 0; + }; - - -#else /* C style interface */ + + +#else /* C style interface */ typedef struct ISOSDacInterface6Vtbl { BEGIN_INTERFACE - - HRESULT(STDMETHODCALLTYPE *QueryInterface)( - ISOSDacInterface5 * This, + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSDacInterface6 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG(STDMETHODCALLTYPE *AddRef)( - ISOSDacInterface5 * This); - - ULONG(STDMETHODCALLTYPE *Release)( - ISOSDacInterface5 * This); - - HRESULT(STDMETHODCALLTYPE *GetMethodTableCollectibleData)( - CLRDATA_ADDRESS mt, + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSDacInterface6 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSDacInterface6 * This); + + HRESULT ( STDMETHODCALLTYPE *GetMethodTableCollectibleData )( + ISOSDacInterface6 * This, + CLRDATA_ADDRESS mt, struct DacpMethodTableCollectibleData *data); - + END_INTERFACE } ISOSDacInterface6Vtbl; @@ -2324,33 +2348,158 @@ EXTERN_C const IID IID_ISOSDacInterface5; CONST_VTBL struct ISOSDacInterface6Vtbl *lpVtbl; }; - + #ifdef COBJMACROS -#define ISOSDacInterface6_QueryInterface(This,riid,ppvObject) \ +#define ISOSDacInterface6_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ISOSDacInterface6_AddRef(This) \ +#define ISOSDacInterface6_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ISOSDacInterface6_Release(This) \ +#define ISOSDacInterface6_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ISOSDacInterface6_GetMethodTableCollectibleData(This,mt,data) \ +#define ISOSDacInterface6_GetMethodTableCollectibleData(This,mt,data) \ ( (This)->lpVtbl -> GetMethodTableCollectibleData(This,mt,data) ) #endif /* COBJMACROS */ -#endif /* C style interface */ +#endif /* C style interface */ -#endif /* __ISOSDacInterface6_INTERFACE_DEFINED__ */ +#endif /* __ISOSDacInterface6_INTERFACE_DEFINED__ */ + + +#ifndef __ISOSDacInterface7_INTERFACE_DEFINED__ +#define __ISOSDacInterface7_INTERFACE_DEFINED__ + +/* interface ISOSDacInterface7 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSDacInterface7; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("c1020dde-fe98-4536-a53b-f35a74c327eb") + ISOSDacInterface7 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetPendingReJITID( + CLRDATA_ADDRESS methodDesc, + int *pRejitId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetReJITInformation( + CLRDATA_ADDRESS methodDesc, + int rejitId, + struct DacpReJitData2 *pRejitData) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetProfilerModifiedILInformation( + CLRDATA_ADDRESS methodDesc, + struct DacpProfilerILData *pILData) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodsWithProfilerModifiedIL( + CLRDATA_ADDRESS mod, + CLRDATA_ADDRESS *methodDescs, + int cMethodDescs, + int *pcMethodDescs) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSDacInterface7Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSDacInterface7 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSDacInterface7 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSDacInterface7 * This); + + HRESULT ( STDMETHODCALLTYPE *GetPendingReJITID )( + ISOSDacInterface7 * This, + CLRDATA_ADDRESS methodDesc, + int *pRejitId); + + HRESULT ( STDMETHODCALLTYPE *GetReJITInformation )( + ISOSDacInterface7 * This, + CLRDATA_ADDRESS methodDesc, + int rejitId, + struct DacpReJitData2 *pRejitData); + + HRESULT ( STDMETHODCALLTYPE *GetProfilerModifiedILInformation )( + ISOSDacInterface7 * This, + CLRDATA_ADDRESS methodDesc, + struct DacpProfilerILData *pILData); + + HRESULT ( STDMETHODCALLTYPE *GetMethodsWithProfilerModifiedIL )( + ISOSDacInterface7 * This, + CLRDATA_ADDRESS mod, + CLRDATA_ADDRESS *methodDescs, + int cMethodDescs, + int *pcMethodDescs); + + END_INTERFACE + } ISOSDacInterface7Vtbl; + + interface ISOSDacInterface7 + { + CONST_VTBL struct ISOSDacInterface7Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISOSDacInterface7_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISOSDacInterface7_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISOSDacInterface7_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISOSDacInterface7_GetPendingReJITID(This,methodDesc,pRejitId) \ + ( (This)->lpVtbl -> GetPendingReJITID(This,methodDesc,pRejitId) ) + +#define ISOSDacInterface7_GetReJITInformation(This,methodDesc,rejitId,pRejitData) \ + ( (This)->lpVtbl -> GetReJITInformation(This,methodDesc,rejitId,pRejitData) ) + +#define ISOSDacInterface7_GetProfilerModifiedILInformation(This,methodDesc,pILData) \ + ( (This)->lpVtbl -> GetProfilerModifiedILInformation(This,methodDesc,pILData) ) + +#define ISOSDacInterface7_GetMethodsWithProfilerModifiedIL(This,mod,methodDescs,cMethodDescs,pcMethodDescs) \ + ( (This)->lpVtbl -> GetMethodsWithProfilerModifiedIL(This,mod,methodDescs,cMethodDescs,pcMethodDescs) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISOSDacInterface7_INTERFACE_DEFINED__ */ + /* Additional Prototypes for ALL interfaces */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/version.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/version.h deleted file mode 100644 index a6de92c..0000000 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/version.h +++ /dev/null @@ -1,17 +0,0 @@ -// 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. - -#include - -#define rmj NDPVersionNumberMajor -#define rmm NDPVersionNumberMinor -#define rup NDPBuildNumberMajor -#define rpt NDPBuildNumberMinor - -#define fvn NDPFileVersionMinor -#define fvb NDPFileVersionBuild -#define fvr NDPFileVersionRevision - -#define szVerName "" -#define szVerUser "" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/xclrdata.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/xclrdata.h index 3ce477e..ea97929 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/xclrdata.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/xclrdata.h @@ -791,7 +791,7 @@ EXTERN_C const IID IID_IXCLRLibrarySupport; typedef SIZE_T ( __stdcall *CDSTranslateAddrCB )( IXCLRDisassemblySupport *__MIDL____MIDL_itf_xclrdata_0000_00020000, CLRDATA_ADDRESS __MIDL____MIDL_itf_xclrdata_0000_00020001, - wchar_t *__MIDL____MIDL_itf_xclrdata_0000_00020002, + WCHAR *__MIDL____MIDL_itf_xclrdata_0000_00020002, SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020003, DWORDLONG *__MIDL____MIDL_itf_xclrdata_0000_00020004); @@ -799,21 +799,21 @@ typedef SIZE_T ( __stdcall *CDSTranslateFixupCB )( IXCLRDisassemblySupport *__MIDL____MIDL_itf_xclrdata_0000_00020006, CLRDATA_ADDRESS __MIDL____MIDL_itf_xclrdata_0000_00020007, SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020008, - wchar_t *__MIDL____MIDL_itf_xclrdata_0000_00020009, + WCHAR *__MIDL____MIDL_itf_xclrdata_0000_00020009, SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020010, DWORDLONG *__MIDL____MIDL_itf_xclrdata_0000_00020011); typedef SIZE_T ( __stdcall *CDSTranslateConstCB )( IXCLRDisassemblySupport *__MIDL____MIDL_itf_xclrdata_0000_00020013, DWORD __MIDL____MIDL_itf_xclrdata_0000_00020014, - wchar_t *__MIDL____MIDL_itf_xclrdata_0000_00020015, + WCHAR *__MIDL____MIDL_itf_xclrdata_0000_00020015, SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020016); typedef SIZE_T ( __stdcall *CDSTranslateRegrelCB )( IXCLRDisassemblySupport *__MIDL____MIDL_itf_xclrdata_0000_00020018, unsigned int rega, CLRDATA_ADDRESS __MIDL____MIDL_itf_xclrdata_0000_00020019, - wchar_t *__MIDL____MIDL_itf_xclrdata_0000_00020020, + WCHAR *__MIDL____MIDL_itf_xclrdata_0000_00020020, SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020021, DWORD *__MIDL____MIDL_itf_xclrdata_0000_00020022); @@ -854,7 +854,7 @@ EXTERN_C const IID IID_IXCLRDisassemblySupport; SIZE_T __MIDL__IXCLRDisassemblySupport0003) = 0; virtual SIZE_T STDMETHODCALLTYPE CchFormatInstr( - wchar_t *__MIDL__IXCLRDisassemblySupport0004, + WCHAR *__MIDL__IXCLRDisassemblySupport0004, SIZE_T __MIDL__IXCLRDisassemblySupport0005) = 0; virtual void *STDMETHODCALLTYPE PvClient( void) = 0; @@ -914,7 +914,7 @@ EXTERN_C const IID IID_IXCLRDisassemblySupport; SIZE_T ( STDMETHODCALLTYPE *CchFormatInstr )( IXCLRDisassemblySupport * This, - wchar_t *__MIDL__IXCLRDisassemblySupport0004, + WCHAR *__MIDL__IXCLRDisassemblySupport0004, SIZE_T __MIDL__IXCLRDisassemblySupport0005); void *( STDMETHODCALLTYPE *PvClient )( diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/xcordebug.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/xcordebug.h index 4160fe5..f19f965 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/xcordebug.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/xcordebug.h @@ -52,13 +52,6 @@ typedef interface ICorDebugProcess4 ICorDebugProcess4; #endif /* __ICorDebugProcess4_FWD_DEFINED__ */ -#ifndef __ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_FWD_DEFINED__ -#define __ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_FWD_DEFINED__ -typedef interface ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly; - -#endif /* __ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_FWD_DEFINED__ */ - - /* header files for imported files */ #include "cordebug.h" @@ -169,92 +162,6 @@ EXTERN_C const IID IID_ICorDebugProcess4; #endif /* __ICorDebugProcess4_INTERFACE_DEFINED__ */ -#ifndef __ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_INTERFACE_DEFINED__ -#define __ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_INTERFACE_DEFINED__ - -/* interface ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly */ -/* [unique][uuid][local][object] */ - - -EXTERN_C const IID IID_ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("34B27FB0-A318-450D-A0DD-11B70B21F41D") - ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE InvokePauseCallback( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE InvokeResumeCallback( void) = 0; - - }; - - -#else /* C style interface */ - - typedef struct ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnlyVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly * This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly * This); - - HRESULT ( STDMETHODCALLTYPE *InvokePauseCallback )( - ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly * This); - - HRESULT ( STDMETHODCALLTYPE *InvokeResumeCallback )( - ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly * This); - - END_INTERFACE - } ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnlyVtbl; - - interface ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly - { - CONST_VTBL struct ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnlyVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) - -#define ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) - -#define ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) - - -#define ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_InvokePauseCallback(This) \ - ( (This)->lpVtbl -> InvokePauseCallback(This) ) - -#define ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_InvokeResumeCallback(This) \ - ( (This)->lpVtbl -> InvokeResumeCallback(This) ) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - - -#endif /* __ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_INTERFACE_DEFINED__ */ - - /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/.tpattributes b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/.tpattributes new file mode 100644 index 0000000..ca534f0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/.tpattributes @@ -0,0 +1 @@ +configure:x diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/CMakeLists.txt new file mode 100644 index 0000000..1a39363 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/CMakeLists.txt @@ -0,0 +1,341 @@ +if(CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_FREEBSD) + # On OSX and *BSD, we use the libunwind that's part of the OS + set(CLR_CMAKE_USE_SYSTEM_LIBUNWIND 1) +endif(CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_FREEBSD) + +if(NOT DEFINED ENV{ROOTFS_DIR}) + include_directories(SYSTEM /usr/local/include) +elseif (CLR_CMAKE_TARGET_FREEBSD) + include_directories(SYSTEM $ENV{ROOTFS_DIR}/usr/local/include) +endif() + +if(NOT CLR_CMAKE_USE_SYSTEM_LIBUNWIND) + include_directories(libunwind/include) + include_directories(libunwind/include/tdep) + include_directories(${CMAKE_CURRENT_BINARY_DIR}/libunwind/include) + include_directories(${CMAKE_CURRENT_BINARY_DIR}/libunwind/include/tdep) + + add_subdirectory(libunwind) +elseif(NOT CLR_CMAKE_TARGET_OSX) + if(CLR_CMAKE_HOST_ARCH_ARM) + find_library(UNWIND_ARCH NAMES unwind-arm) + endif() + + if(CLR_CMAKE_HOST_ARCH_ARM64) + find_library(UNWIND_ARCH NAMES unwind-aarch64) + endif() + + if(CLR_CMAKE_HOST_ARCH_AMD64) + find_library(UNWIND_ARCH NAMES unwind-x86_64) + endif() + + if(NOT UNWIND_ARCH STREQUAL UNWIND_ARCH-NOTFOUND) + set(UNWIND_LIBS ${UNWIND_ARCH}) + endif() + + find_library(UNWIND_GENERIC NAMES unwind-generic) + + if(NOT UNWIND_GENERIC STREQUAL UNWIND_GENERIC-NOTFOUND) + set(UNWIND_LIBS ${UNWIND_LIBS} ${UNWIND_GENERIC}) + endif() + + find_library(UNWIND NAMES unwind) + + if(UNWIND STREQUAL UNWIND-NOTFOUND) + message(FATAL_ERROR "Cannot find libunwind. Try installing libunwind8-dev or libunwind-devel.") + endif() + + set(UNWIND_LIBS ${UNWIND_LIBS} ${UNWIND}) +endif(NOT CLR_CMAKE_USE_SYSTEM_LIBUNWIND) +include(configure.cmake) + +project(coreclrpal) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +if(CORECLR_SET_RPATH) + # Enable @rpath support for shared libraries. + set(MACOSX_RPATH ON) +endif(CORECLR_SET_RPATH) + +cmake_policy(SET CMP0042 NEW) + +# Include directories + +include_directories(include) + +# Compile options + +if(CLR_CMAKE_TARGET_OSX) + add_definitions(-DTARGET_OSX) + add_definitions(-DXSTATE_SUPPORTED) + set(PLATFORM_SOURCES + arch/amd64/activationhandlerwrapper.S + arch/amd64/context.S + arch/amd64/dispatchexceptionwrapper.S + exception/machexception.cpp + exception/machmessage.cpp + ) +endif(CLR_CMAKE_TARGET_OSX) + +if (FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION) + add_definitions(-DFEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION) +endif(FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION) +add_definitions(-DLP64COMPATIBLE) +add_definitions(-DCORECLR) +add_definitions(-DPIC) +add_definitions(-D_FILE_OFFSET_BITS=64) +if(CLR_CMAKE_HOST_ARCH_AMD64) + set(PAL_ARCH_SOURCES_DIR amd64) +elseif(CLR_CMAKE_HOST_ARCH_ARM) + set(PAL_ARCH_SOURCES_DIR arm) +elseif(CLR_CMAKE_HOST_ARCH_ARM64) + set(PAL_ARCH_SOURCES_DIR arm64) +elseif(CLR_CMAKE_HOST_ARCH_I386) + set(PAL_ARCH_SOURCES_DIR i386) +endif() + +if(CLR_CMAKE_HOST_ARCH_AMD64 AND CLR_CMAKE_TARGET_LINUX AND NOT CLR_CMAKE_HOST_ALPINE_LINUX) + # Currently the _xstate is not available on Alpine Linux + add_definitions(-DXSTATE_SUPPORTED) +endif(CLR_CMAKE_HOST_ARCH_AMD64 AND CLR_CMAKE_TARGET_LINUX AND NOT CLR_CMAKE_HOST_ALPINE_LINUX) + +if(CLR_CMAKE_HOST_ALPINE_LINUX) + # Setting RLIMIT_NOFILE breaks debugging of coreclr on Alpine Linux for some reason + add_definitions(-DDONT_SET_RLIMIT_NOFILE) + # On Alpine Linux, we need to ensure that the reported stack range for the primary thread is + # larger than the initial committed stack size. + add_definitions(-DENSURE_PRIMARY_STACK_SIZE) +endif(CLR_CMAKE_HOST_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") + +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + add_compile_options(-Wno-unused-result) +endif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + +set(ARCH_SOURCES + arch/${PAL_ARCH_SOURCES_DIR}/context2.S + arch/${PAL_ARCH_SOURCES_DIR}/debugbreak.S + arch/${PAL_ARCH_SOURCES_DIR}/exceptionhelper.S + arch/${PAL_ARCH_SOURCES_DIR}/processor.cpp +) + +if(NOT CLR_CMAKE_TARGET_OSX) + list(APPEND PLATFORM_SOURCES + arch/${PAL_ARCH_SOURCES_DIR}/callsignalhandlerwrapper.S + arch/${PAL_ARCH_SOURCES_DIR}/signalhandlerhelper.cpp + ) +endif(NOT CLR_CMAKE_TARGET_OSX) + +if(CLR_CMAKE_HOST_ARCH_ARM) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set_source_files_properties(exception/seh.cpp PROPERTIES COMPILE_FLAGS -Wno-error=inline-asm) + endif() +endif(CLR_CMAKE_HOST_ARCH_ARM) + +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + add_compile_options(-Wa,--divide) +endif() + +set(SOURCES + cruntime/file.cpp + cruntime/filecrt.cpp + cruntime/malloc.cpp + cruntime/math.cpp + cruntime/mbstring.cpp + cruntime/misc.cpp + cruntime/path.cpp + cruntime/printf.cpp + cruntime/printfcpp.cpp + cruntime/silent_printf.cpp + cruntime/string.cpp + cruntime/stringtls.cpp + cruntime/thread.cpp + cruntime/wchar.cpp + cruntime/wchartls.cpp + debug/debug.cpp + exception/seh.cpp + exception/signal.cpp + exception/remote-unwind.cpp + file/directory.cpp + file/file.cpp + file/filetime.cpp + file/find.cpp + file/path.cpp + handlemgr/handleapi.cpp + handlemgr/handlemgr.cpp + init/pal.cpp + init/sxs.cpp + loader/module.cpp + loader/modulename.cpp + locale/unicode.cpp + locale/unicodedata.cpp + locale/utf8.cpp + map/common.cpp + map/map.cpp + map/virtual.cpp + memory/local.cpp + misc/cgroup.cpp + misc/dbgmsg.cpp + misc/environ.cpp + misc/error.cpp + misc/errorstrings.cpp + misc/fmtmessage.cpp + misc/jitsupport.cpp + misc/miscpalapi.cpp + misc/msgbox.cpp + misc/perfjitdump.cpp + misc/strutil.cpp + misc/sysinfo.cpp + misc/time.cpp + misc/utils.cpp + numa/numa.cpp + objmgr/palobjbase.cpp + objmgr/shmobject.cpp + objmgr/shmobjectmanager.cpp + 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 + synchobj/event.cpp + synchobj/semaphore.cpp + synchobj/mutex.cpp + synchmgr/synchcontrollers.cpp + synchmgr/synchmanager.cpp + synchmgr/wait.cpp + thread/context.cpp + thread/process.cpp + thread/thread.cpp + thread/threadsusp.cpp +) + +if(NOT CLR_CMAKE_USE_SYSTEM_LIBUNWIND) + set(LIBUNWIND_OBJECTS $) +endif(NOT CLR_CMAKE_USE_SYSTEM_LIBUNWIND) + +add_library(coreclrpal + STATIC + ${SOURCES} + ${ARCH_SOURCES} + ${PLATFORM_SOURCES} + ${LIBUNWIND_OBJECTS} +) + +# There is only one function exported in 'tracepointprovider.cpp' namely 'PAL_InitializeTracing', +# which is guarded with '#if defined(__linux__)'. On macOS, Xcode issues the following warning: +# +# > warning: /Applications/Xcode-9.4.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib: +# > warning for library: libtracepointprovider.a the table of contents is empty (no object file members in the library define global symbols) +# +if(CLR_CMAKE_TARGET_LINUX) + add_library(tracepointprovider + STATIC + misc/tracepointprovider.cpp + ) +endif(CLR_CMAKE_TARGET_LINUX) + +if(CLR_CMAKE_TARGET_OSX) + find_library(COREFOUNDATION CoreFoundation) + find_library(CORESERVICES CoreServices) + find_library(SECURITY Security) + find_library(SYSTEM System) + target_link_libraries(coreclrpal + ${COREFOUNDATION} + ${CORESERVICES} + ${SECURITY} + ${SYSTEM} + ) +endif(CLR_CMAKE_TARGET_OSX) + +if(CLR_CMAKE_TARGET_FREEBSD) + target_link_libraries(coreclrpal + pthread + rt + ${UNWIND_LIBS} + ) +endif(CLR_CMAKE_TARGET_FREEBSD) + +if(CLR_CMAKE_TARGET_LINUX) + # On Android, we don't need to link with gcc_s, pthread and rt + if(NOT CLR_CMAKE_TARGET_ANDROID) + target_link_libraries(coreclrpal + gcc_s + pthread + rt + ) + else(NOT CLR_CMAKE_TARGET_ANDROID) + target_link_libraries(coreclrpal + ${ANDROID_GLOB} + ${LZMA}) + endif(NOT CLR_CMAKE_TARGET_ANDROID) + + target_link_libraries(coreclrpal + dl + ) + + if(CLR_CMAKE_USE_SYSTEM_LIBUNWIND) + target_link_libraries(coreclrpal ${UNWIND_LIBS}) + endif(CLR_CMAKE_USE_SYSTEM_LIBUNWIND) + +endif(CLR_CMAKE_TARGET_LINUX) + +if(CLR_CMAKE_TARGET_NETBSD) + if (CLR_CMAKE_USE_SYSTEM_LIBUNWIND) + find_library(UNWIND unwind) + endif() + add_definitions(-D_KMEMUSER) + find_library(KVM kvm) + target_link_libraries(coreclrpal + pthread + rt + ${UNWIND} + ${KVM} + ) +endif(CLR_CMAKE_TARGET_NETBSD) + +if(CLR_CMAKE_TARGET_SUNOS) + target_link_libraries(coreclrpal + pthread + rt + ) +endif(CLR_CMAKE_TARGET_SUNOS) + +if(FEATURE_EVENT_TRACE) + add_subdirectory(eventprovider) +endif(FEATURE_EVENT_TRACE) + + +# Install the static PAL library for VS +_install (TARGETS coreclrpal DESTINATION lib) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/activationhandlerwrapper.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/activationhandlerwrapper.S new file mode 100644 index 0000000..0ac73fc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/activationhandlerwrapper.S @@ -0,0 +1,30 @@ +// 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" + +#ifdef HOST_64BIT +// Offset of the return address from the ActivationHandler in the ActivationHandlerWrapper +.globl C_FUNC(ActivationHandlerReturnOffset) +C_FUNC(ActivationHandlerReturnOffset): + .int LOCAL_LABEL(ActivationHandlerReturn)-C_FUNC(ActivationHandlerWrapper) + +NESTED_ENTRY ActivationHandlerWrapper, _TEXT, NoHandler + push_nonvol_reg rbp + mov rbp, rsp + alloc_stack (CONTEXT_Size) + set_cfa_register rbp, (2*8) + mov rdi, rsp + int3 + call C_FUNC(ActivationHandler) +LOCAL_LABEL(ActivationHandlerReturn): + int3 + free_stack (CONTEXT_Size) + pop_nonvol_reg rbp + ret +NESTED_END ActivationHandlerWrapper, _TEXT + +#endif // HOST_64BIT diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/asmconstants.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/asmconstants.h new file mode 100644 index 0000000..71b584a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/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 HOST_64BIT + +#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 // HOST_64BIT + +#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 // HOST_64BIT diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/callsignalhandlerwrapper.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/callsignalhandlerwrapper.S new file mode 100644 index 0000000..8260591 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/callsignalhandlerwrapper.S @@ -0,0 +1,31 @@ +// 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" + +.macro CALL_SIGNAL_HANDLER_WRAPPER Alignment + +.globl C_FUNC(SignalHandlerWorkerReturnOffset\Alignment) +C_FUNC(SignalHandlerWorkerReturnOffset\Alignment): + .int LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment)-C_FUNC(CallSignalHandlerWrapper\Alignment) + +// This function is never called, only a fake stack frame will be setup to have a return +// address set to SignalHandlerWorkerReturn during SIGSEGV handling. +// It enables the unwinder to unwind stack from the handling code to the actual failure site. +NESTED_ENTRY CallSignalHandlerWrapper\Alignment, _TEXT, NoHandler + .cfi_def_cfa_offset (128 + 8 + \Alignment) // red zone + return address + alignment + .cfi_offset rip, -(128 + 8 + \Alignment) + push_nonvol_reg rbp + call EXTERNAL_C_FUNC(signal_handler_worker) +LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment): + pop rbp + ret +NESTED_END CallSignalHandlerWrapper\Alignment, _TEXT + +.endm + +CALL_SIGNAL_HANDLER_WRAPPER 0 +CALL_SIGNAL_HANDLER_WRAPPER 8 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/context.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/context.S new file mode 100644 index 0000000..f8a2dca --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/context.S @@ -0,0 +1,21 @@ +// 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. + +#if defined(_DEBUG) + .text + .globl _DBG_CheckStackAlignment + +_DBG_CheckStackAlignment: + // Prolog - at this point we are at aligned - 8 (for the call) + pushq %rbp // aligned -16 + movq %rsp, %rbp + + testl $0xf,%esp // can get away with esp even on AMD64. + jz .+3 + int3 + + // Epilog + popq %rbp + ret +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/context2.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/context2.S new file mode 100644 index 0000000..b2a2391 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/context2.S @@ -0,0 +1,238 @@ +// 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 HOST_64BIT + +#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): + + 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) + +#ifdef HAS_ASAN + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_CONTROL + je LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT) + + push_nonvol_reg rdi + push_nonvol_reg rsi + call EXTERNAL_C_FUNC(__asan_handle_no_return) + pop_nonvol_reg rsi + pop_nonvol_reg rdi +LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT): +#endif + 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/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/debugbreak.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/debugbreak.S new file mode 100644 index 0000000..3065e40 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/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/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/dispatchexceptionwrapper.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/dispatchexceptionwrapper.S new file mode 100644 index 0000000..e9baaec --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/dispatchexceptionwrapper.S @@ -0,0 +1,51 @@ +// 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 the PAL_DispatchExceptionWrapper that is +// interposed between a function that caused a hardware fault +// and PAL_DispatchException that throws an SEH exception for +// the fault, to make the stack unwindable. +// + +.intel_syntax noprefix +#include "unixasmmacros.inc" + +// Offset of the return address from the PAL_DispatchException in the PAL_DispatchExceptionWrapper +.globl C_FUNC(PAL_DispatchExceptionReturnOffset) +C_FUNC(PAL_DispatchExceptionReturnOffset): + .int LOCAL_LABEL(PAL_DispatchExceptionReturn) - C_FUNC(PAL_DispatchExceptionWrapper) + +// +// PAL_DispatchExceptionWrapper will never be called; it only serves +// to be referenced from a stack frame on the faulting thread. Its +// unwinding behavior is equivalent to any standard function having +// an ebp frame. It is analogous to the following source file. +// +// extern "C" void PAL_DispatchException(CONTEXT *pContext, EXCEPTION_RECORD *pExceptionRecord, MachExceptionInfo *pMachExceptionInfo); +// +// extern "C" void PAL_DispatchExceptionWrapper() +// { +// CONTEXT Context; +// EXCEPTION_RECORD ExceptionRecord; +// MachExceptionInfo MachExceptionInfo; +// PAL_DispatchException(&Context, &ExceptionRecord, &MachExceptionInfo); +// } +// + +NESTED_ENTRY PAL_DispatchExceptionWrapper, _TEXT, NoHandler + push_nonvol_reg rbp + mov rbp, rsp + set_cfa_register rbp, (2*8) + int3 + call C_FUNC(PAL_DispatchException) +LOCAL_LABEL(PAL_DispatchExceptionReturn): + int3 + pop_nonvol_reg rbp + ret +NESTED_END PAL_DispatchExceptionWrapper, _TEXT diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/exceptionhelper.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/exceptionhelper.S new file mode 100644 index 0000000..2072583 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/exceptionhelper.S @@ -0,0 +1,52 @@ +// 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 +#ifdef HAS_ASAN + // Need to call __asan_handle_no_return explicitly here because we re-intialize RSP before + // throwing exception in ThrowExceptionHelper + push_nonvol_reg rdi + push_nonvol_reg rsi + call EXTERNAL_C_FUNC(__asan_handle_no_return) + pop_nonvol_reg rsi + pop_nonvol_reg rdi +#endif + + // 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/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/processor.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/processor.cpp new file mode 100644 index 0000000..a520111 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/processor.cpp @@ -0,0 +1,51 @@ +// 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: +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(" mov $1, %%eax\n" \ + " cpuid\n" \ + " xor %%eax, %%eax\n" \ + " and $0x18000000, %%ecx\n" /* check for xsave feature set and that it is enabled by the OS */ \ + " cmp $0x18000000, %%ecx\n" \ + " jne end\n" \ + " xor %%ecx, %%ecx\n" \ + " xgetbv\n" \ + "end:\n" \ + : "=a"(eax) /* output in eax */ \ + : /* no inputs */ \ + : "ebx", "ecx", "edx" /* registers that are clobbered */ + ); + // Check OS has enabled both XMM and YMM state support + return ((eax & 0x06) == 0x06) ? 1 : 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/signalhandlerhelper.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/signalhandlerhelper.cpp new file mode 100644 index 0000000..61eba90 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/amd64/signalhandlerhelper.cpp @@ -0,0 +1,76 @@ +// 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. + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do this first + +#include "pal/palinternal.h" +#include "pal/context.h" +#include "pal/signal.hpp" +#include "pal/utils.h" +#include + +/*++ +Function : + ExecuteHandlerOnCustomStack + + Execute signal handler on a custom stack, the current stack pointer is specified by the customSp + If the customSp is 0, then the handler is executed on the original stack where the signal was fired. + It installs a fake stack frame to enable stack unwinding to the signal source location. + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + returnPoint - context to which the function returns if the common_signal_handler returns + + (no return value) +--*/ +void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t customSp, SignalHandlerWorkerReturnPoint* returnPoint) +{ + ucontext_t *ucontext = (ucontext_t *)context; + size_t faultSp = (size_t)MCREG_Rsp(ucontext->uc_mcontext); + + _ASSERTE(IS_ALIGNED(faultSp, 8)); + + if (customSp == 0) + { + // preserve 128 bytes long red zone and align stack pointer + customSp = ALIGN_DOWN(faultSp - 128, 16); + } + + size_t fakeFrameReturnAddress; + + if (IS_ALIGNED(faultSp, 16)) + { + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset0 + (size_t)CallSignalHandlerWrapper0; + } + else + { + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset8 + (size_t)CallSignalHandlerWrapper8; + } + + size_t* sp = (size_t*)customSp; + + // Build fake stack frame to enable the stack unwinder to unwind from signal_handler_worker to the faulting instruction + *--sp = (size_t)MCREG_Rip(ucontext->uc_mcontext); + *--sp = (size_t)MCREG_Rbp(ucontext->uc_mcontext); + size_t fp = (size_t)sp; + *--sp = fakeFrameReturnAddress; + + // Switch the current context to the signal_handler_worker and the custom stack + CONTEXT context2; + RtlCaptureContext(&context2); + + // We don't care about the other registers state since the stack unwinding restores + // them for the target frame directly from the signal context. + context2.Rsp = (size_t)sp; + context2.Rbx = (size_t)faultSp; + context2.Rbp = (size_t)fp; + context2.Rip = (size_t)signal_handler_worker; + context2.Rdi = code; + context2.Rsi = (size_t)siginfo; + context2.Rdx = (size_t)context; + context2.Rcx = (size_t)returnPoint; + + RtlRestoreContext(&context2, NULL); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/asmconstants.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/asmconstants.h new file mode 100644 index 0000000..ae4b01b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/asmconstants.h @@ -0,0 +1,61 @@ +// 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. + +#ifndef __PAL_ARM_ASMCONSTANTS_H__ +#define __PAL_ARM_ASMCONSTANTS_H__ + +#define CONTEXT_ContextFlags 0 +#define CONTEXT_R0 CONTEXT_ContextFlags+4 +#define CONTEXT_R1 CONTEXT_R0+4 +#define CONTEXT_R2 CONTEXT_R1+4 +#define CONTEXT_R3 CONTEXT_R2+4 +#define CONTEXT_R4 CONTEXT_R3+4 +#define CONTEXT_R5 CONTEXT_R4+4 +#define CONTEXT_R6 CONTEXT_R5+4 +#define CONTEXT_R7 CONTEXT_R6+4 +#define CONTEXT_R8 CONTEXT_R7+4 +#define CONTEXT_R9 CONTEXT_R8+4 +#define CONTEXT_R10 CONTEXT_R9+4 +#define CONTEXT_R11 CONTEXT_R10+4 +#define CONTEXT_R12 CONTEXT_R11+4 +#define CONTEXT_Sp CONTEXT_R12+4 +#define CONTEXT_Lr CONTEXT_Sp+4 +#define CONTEXT_Pc CONTEXT_Lr+4 +#define CONTEXT_Cpsr CONTEXT_Pc+4 +#define CONTEXT_Fpscr CONTEXT_Cpsr+4 +#define CONTEXT_Padding CONTEXT_Fpscr+4 +#define CONTEXT_D0 CONTEXT_Padding+4 +#define CONTEXT_D1 CONTEXT_D0+8 +#define CONTEXT_D2 CONTEXT_D1+8 +#define CONTEXT_D3 CONTEXT_D2+8 +#define CONTEXT_D4 CONTEXT_D3+8 +#define CONTEXT_D5 CONTEXT_D4+8 +#define CONTEXT_D6 CONTEXT_D5+8 +#define CONTEXT_D7 CONTEXT_D6+8 +#define CONTEXT_D8 CONTEXT_D7+8 +#define CONTEXT_D9 CONTEXT_D8+8 +#define CONTEXT_D10 CONTEXT_D9+8 +#define CONTEXT_D11 CONTEXT_D10+8 +#define CONTEXT_D12 CONTEXT_D11+8 +#define CONTEXT_D13 CONTEXT_D12+8 +#define CONTEXT_D14 CONTEXT_D13+8 +#define CONTEXT_D15 CONTEXT_D14+8 +#define CONTEXT_D16 CONTEXT_D15+8 +#define CONTEXT_D17 CONTEXT_D16+8 +#define CONTEXT_D18 CONTEXT_D17+8 +#define CONTEXT_D19 CONTEXT_D18+8 +#define CONTEXT_D20 CONTEXT_D19+8 +#define CONTEXT_D21 CONTEXT_D20+8 +#define CONTEXT_D22 CONTEXT_D21+8 +#define CONTEXT_D23 CONTEXT_D22+8 +#define CONTEXT_D24 CONTEXT_D23+8 +#define CONTEXT_D25 CONTEXT_D24+8 +#define CONTEXT_D26 CONTEXT_D25+8 +#define CONTEXT_D27 CONTEXT_D26+8 +#define CONTEXT_D28 CONTEXT_D27+8 +#define CONTEXT_D29 CONTEXT_D28+8 +#define CONTEXT_D30 CONTEXT_D29+8 +#define CONTEXT_D31 CONTEXT_D30+8 + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/callsignalhandlerwrapper.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/callsignalhandlerwrapper.S new file mode 100644 index 0000000..b9398d6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/callsignalhandlerwrapper.S @@ -0,0 +1,47 @@ +// 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. + +#include "unixasmmacros.inc" +#include "asmconstants.h" + +.syntax unified +.thumb + +.macro CALL_SIGNAL_HANDLER_WRAPPER Alignment + +.globl C_FUNC(SignalHandlerWorkerReturnOffset\Alignment) +C_FUNC(SignalHandlerWorkerReturnOffset\Alignment): + .int LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment)-C_FUNC(CallSignalHandlerWrapper\Alignment) + +// This function is never called, only a fake stack frame will be setup to have a return +// address set to SignalHandlerWorkerReturn during SIGSEGV handling. +// It enables the unwinder to unwind stack from the handling code to the actual failure site. +NESTED_ENTRY CallSignalHandlerWrapper\Alignment, _TEXT, NoHandler +#ifndef __linux__ +__StackAllocationSize = (8 + 4 + \Alignment) // red zone + alignment + alloc_stack __StackAllocationSize + PROLOG_PUSH "{r7, r11, lr}" + bl EXTERNAL_C_FUNC(signal_handler_worker) +LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment): + EPILOG_POP "{r7, r11, lr}" + free_stack __StackAllocationSize + bx lr +#else + // This unwind information is needed for lldb gdb doesn't use it and tries + // to read all registers from $sp + 12 + .save {r0-r15} + .pad #12 + bl EXTERNAL_C_FUNC(signal_handler_worker) +LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment): + // Following instruction are needed to say gdb that this frame is SIGTRAMP_FRAME + // and it can restore all registers from stack + mov.w r7, #119 + svc 0 +#endif +NESTED_END CallSignalHandlerWrapper\Alignment, _TEXT + +.endm + +CALL_SIGNAL_HANDLER_WRAPPER 0 +CALL_SIGNAL_HANDLER_WRAPPER 4 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/context2.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/context2.S new file mode 100644 index 0000000..6ea8aba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/context2.S @@ -0,0 +1,193 @@ +// 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 ARM platform. +// This function is processor dependent. It is used by exception handling, +// and is always apply to the current thread. +// + +#include "unixasmmacros.inc" +#include "asmconstants.h" + +.syntax unified +.thumb + +#define CONTEXT_ARM 0x00200000 + +#define CONTEXT_CONTROL 1 // Sp, Lr, Pc, Cpsr +#define CONTEXT_INTEGER 2 // R0-R12 +#define CONTEXT_SEGMENTS 4 // +#define CONTEXT_FLOATING_POINT 8 +#define CONTEXT_DEBUG_REGISTERS 16 // + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + + +// Incoming: +// r0: Context* +// +LEAF_ENTRY CONTEXT_CaptureContext, _TEXT + // Ensure we save these registers + push {r4-r11} + // Save processor flags before calling any of the following 'test' instructions + // because they will modify state of some flags + push {r1} + mrs r1, apsr // Get APSR - equivalent to eflags + push {r1} // Save APSR + END_PROLOGUE + + push {r2} + ldr r2, [r0, #(CONTEXT_ContextFlags)] + tst r2, #(CONTEXT_INTEGER) + pop {r2} + + // Add 4 to stack so we point at R1, pop, then sub 8 to point at APSR + add sp, sp, #4 + pop {r1} + sub sp, sp, #8 + + itttt ne + strne r0, [r0, #(CONTEXT_R0)] + addne r0, CONTEXT_R1 + stmiane r0, {r1-r12} + subne r0, CONTEXT_R1 + + ldr r2, [r0, #(CONTEXT_ContextFlags)] + tst r2, #(CONTEXT_CONTROL) + + ittt ne + addne sp, sp, #(10*4) // This needs to put the stack in the same state as it started + strne sp, [r0, #(CONTEXT_Sp)] + subne sp, sp, #(10*4) + + itt ne + strne lr, [r0, #(CONTEXT_Lr)] + strne lr, [r0, #(CONTEXT_Pc)] + + // Get the APSR pushed onto the stack at the start + pop {r1} + it ne + strne r1, [r0, #(CONTEXT_Cpsr)] + + ldr r2, [r0, #(CONTEXT_ContextFlags)] + tst r2, #(CONTEXT_FLOATING_POINT) + + itt ne + vmrsne r3, fpscr + strne r3, [r0, #(CONTEXT_Fpscr)] + + itttt ne + addne r0, CONTEXT_D0 + vstmiane r0!, {d0-d15} +#if CLR_ARM_FPU_CAPABILITY & 0x4 + vstmiane r0!, {d16-d31} +#else + addne r0, r0, #128 +#endif + subne r0, CONTEXT_D31 + + // Make sure sp is restored + add sp, sp, #4 + + // Restore callee saved registers + pop {r4-r11} + bx lr +LEAF_END CONTEXT_CaptureContext, _TEXT + +// Incoming: +// R0: Context* +// +LEAF_ENTRY RtlCaptureContext, _TEXT + push {r1} + mov r1, #0 + orr r1, r1, #CONTEXT_ARM + orr r1, r1, #CONTEXT_INTEGER + orr r1, r1, #CONTEXT_CONTROL + orr r1, r1, #CONTEXT_FLOATING_POINT + str r1, [r0, #(CONTEXT_ContextFlags)] + pop {r1} + b C_FUNC(CONTEXT_CaptureContext) +LEAF_END RtlCaptureContext, _TEXT + +// Incoming: +// r0: Context* +// r1: Exception* +// +LEAF_ENTRY RtlRestoreContext, _TEXT + END_PROLOGUE + +#ifdef HAS_ASAN + ldr r2, [r0, #(CONTEXT_ContextFlags)] + tst r2, #(CONTEXT_CONTROL) + beq LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT) + + push {r0, r1} + bl EXTERNAL_C_FUNC(__asan_handle_no_return) + pop {r0, r1} + +LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT): +#endif + ldr r2, [r0, #(CONTEXT_ContextFlags)] + tst r2, #(CONTEXT_FLOATING_POINT) + + itttt ne + addne r0, CONTEXT_D0 + vldmiane r0!, {d0-d15} +#if CLR_ARM_FPU_CAPABILITY & 0x4 + vldmiane r0, {d16-d31} +#else + nopne +#endif + subne r0, CONTEXT_D16 + + itt ne + ldrne r3, [r0, #(CONTEXT_Fpscr)] + vmrsne r3, FPSCR + + ldr r2, [r0, #(CONTEXT_ContextFlags)] + tst r2, #(CONTEXT_CONTROL) + + it eq + beq LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) + + ldr r2, [r0, #(CONTEXT_ContextFlags)] + tst r2, #(CONTEXT_INTEGER) + + it eq + beq LOCAL_LABEL(No_Restore_CONTEXT_INTEGER) + + ldr R2, [r0, #(CONTEXT_Cpsr)] + msr APSR, r2 + + // Ideally, we would like to use `ldmia r0, {r0-r12, sp, lr, pc}` here, + // but clang 3.6 and later, as per ARM recommendation, disallows using + // Sp in the register list, and Pc and Lr simultaneously. + // So we are going to use the IPC register r12 to copy Sp, Lr and Pc + // which should be ok -- TODO: Is this really ok? + add r12, r0, CONTEXT_R0 + ldm r12, {r0-r11} + ldr sp, [r12, #(CONTEXT_Sp - (CONTEXT_R0))] + ldr lr, [r12, #(CONTEXT_Lr - (CONTEXT_R0))] + ldr pc, [r12, #(CONTEXT_Pc - (CONTEXT_R0))] + +LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): + + ldr r2, [r0, #(CONTEXT_Cpsr)] + msr APSR, r2 + + ldr sp, [r0, #(CONTEXT_Sp)] + ldr lr, [r0, #(CONTEXT_Lr)] + ldr pc, [r0, #(CONTEXT_Pc)] + +LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): + ldr r2, [r0, #(CONTEXT_ContextFlags)] + tst r2, #(CONTEXT_INTEGER) + + itt ne + addne r0, CONTEXT_R0 + ldmiane r0, {r0-r12} + + sub sp, sp, #4 + bx lr +LEAF_END RtlRestoreContext, _TEXT diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/debugbreak.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/debugbreak.S new file mode 100644 index 0000000..863d7cf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/debugbreak.S @@ -0,0 +1,14 @@ +// 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. + +#include "unixasmmacros.inc" + +.syntax unified +.thumb + +LEAF_ENTRY DBG_DebugBreak, _TEXT + EMIT_BREAKPOINT + bx lr +LEAF_END_MARKED DBG_DebugBreak, _TEXT + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/exceptionhelper.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/exceptionhelper.S new file mode 100644 index 0000000..1234305 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/exceptionhelper.S @@ -0,0 +1,47 @@ +// 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. + +#include "unixasmmacros.inc" +#include "asmconstants.h" + +.syntax unified +.thumb + +// EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); +LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT + // Ported from src/pal/src/arch/amd64/exceptionhelper.S +#ifdef HAS_ASAN + // Need to call __asan_handle_no_return explicitly here because we re-intialize SP before + // throwing exception in ThrowExceptionHelper + push_nonvol_reg "{r0, r1}" + bl EXTERNAL_C_FUNC(__asan_handle_no_return) + pop_nonvol_reg "{r0, r1}" +#endif + + push_nonvol_reg {r7} /* FP. x64-RBP */ + + ldr r4, [r0, #(CONTEXT_R4)] + ldr r5, [r0, #(CONTEXT_R5)] + ldr r6, [r0, #(CONTEXT_R6)] + ldr r7, [r0, #(CONTEXT_R7)] + ldr r8, [r0, #(CONTEXT_R8)] + ldr r9, [r0, #(CONTEXT_R9)] + ldr r10, [r0, #(CONTEXT_R10)] + ldr r11, [r0, #(CONTEXT_R11)] + ldr sp, [r0, #(CONTEXT_Sp)] + ldr lr, [r0, #(CONTEXT_Pc)] + + vldr d8, [r0, #(CONTEXT_D8)] + vldr d9, [r0, #(CONTEXT_D9)] + vldr d10, [r0, #(CONTEXT_D10)] + vldr d11, [r0, #(CONTEXT_D11)] + vldr d12, [r0, #(CONTEXT_D12)] + vldr d13, [r0, #(CONTEXT_D13)] + vldr d14, [r0, #(CONTEXT_D14)] + vldr d15, [r0, #(CONTEXT_D15)] + + // The PAL_SEHException pointer + mov r0, r1 + b EXTERNAL_C_FUNC(ThrowExceptionHelper) +LEAF_END ThrowExceptionFromContextInternal, _TEXT diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/processor.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/processor.cpp new file mode 100644 index 0000000..7993212 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/processor.cpp @@ -0,0 +1,22 @@ +// 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 ARM + platform. These functions are processor dependent. + + + +--*/ + +#include "pal/palinternal.h" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/signalhandlerhelper.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/signalhandlerhelper.cpp new file mode 100644 index 0000000..9c6dda1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm/signalhandlerhelper.cpp @@ -0,0 +1,87 @@ +// 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. + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do this first + +#include "pal/palinternal.h" +#include "pal/context.h" +#include "pal/signal.hpp" +#include "pal/utils.h" +#include + +/*++ +Function : + ExecuteHandlerOnCustomStack + + Execute signal handler on a custom stack, the current stack pointer is specified by the customSp + If the customSp is 0, then the handler is executed on the original stack where the signal was fired. + It installs a fake stack frame to enable stack unwinding to the signal source location. + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + returnPoint - context to which the function returns if the common_signal_handler returns + + (no return value) +--*/ +void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t customSp, SignalHandlerWorkerReturnPoint* returnPoint) +{ + ucontext_t *ucontext = (ucontext_t *)context; + size_t faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext); + + _ASSERTE(IS_ALIGNED(faultSp, 4)); + + if (customSp == 0) + { + // preserve 8 bytes long red zone and align stack pointer + customSp = ALIGN_DOWN(faultSp - 8, 8); + } + + size_t fakeFrameReturnAddress; + + if (IS_ALIGNED(faultSp, 8)) + { + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset0 + (size_t)CallSignalHandlerWrapper0; + } + else + { + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset4 + (size_t)CallSignalHandlerWrapper4; + } + + size_t* sp = (size_t*)customSp; + +#ifndef __linux__ + size_t cpsr = (size_t)MCREG_Cpsr(ucontext->uc_mcontext); + + // Build fake stack frame to enable the stack unwinder to unwind from signal_handler_worker to the faulting instruction + // align + --sp; + // pushed LR with correct mode bit + *--sp = (size_t)MCREG_Pc(ucontext->uc_mcontext) | ((cpsr & (1 << 5)) >> 5); + // pushed frame pointer + *--sp = (size_t)MCREG_R11(ucontext->uc_mcontext); + *--sp = (size_t)MCREG_R7(ucontext->uc_mcontext); +#else + size_t size = ALIGN_UP(sizeof(ucontext->uc_mcontext), 8); + sp -= size / sizeof(size_t); + *(mcontext_t *)sp = ucontext->uc_mcontext; +#endif + + // Switch the current context to the signal_handler_worker and the original stack + CONTEXT context2; + RtlCaptureContext(&context2); + + // We don't care about the other registers state since the stack unwinding restores + // them for the target frame directly from the signal context. + context2.Sp = (size_t)sp; + context2.R7 = (size_t)sp; // Fp and Sp are the same + context2.Lr = fakeFrameReturnAddress; + context2.Pc = (size_t)signal_handler_worker; + context2.R0 = code; + context2.R1 = (size_t)siginfo; + context2.R2 = (size_t)context; + context2.R3 = (size_t)returnPoint; + + RtlRestoreContext(&context2, NULL); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/asmconstants.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/asmconstants.h new file mode 100644 index 0000000..08502ed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/asmconstants.h @@ -0,0 +1,95 @@ +// 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. + +#ifndef __PAL_ARM64_ASMCONSTANTS_H__ +#define __PAL_ARM64_ASMCONSTANTS_H__ + +#define CONTEXT_ARM64 0x00400000L + +#define CONTEXT_CONTROL_BIT (0) +#define CONTEXT_INTEGER_BIT (1) +#define CONTEXT_FLOATING_POINT_BIT (2) +#define CONTEXT_DEBUG_REGISTERS_BIT (3) + +#define CONTEXT_CONTROL (CONTEXT_ARM64 | (1L << CONTEXT_CONTROL_BIT)) +#define CONTEXT_INTEGER (CONTEXT_ARM64 | (1 << CONTEXT_INTEGER_BIT)) +#define CONTEXT_FLOATING_POINT (CONTEXT_ARM64 | (1 << CONTEXT_FLOATING_POINT_BIT)) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARM64 | (1 << CONTEXT_DEBUG_REGISTERS_BIT)) + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + + +#define CONTEXT_ContextFlags 0 +#define CONTEXT_Cpsr CONTEXT_ContextFlags+4 +#define CONTEXT_X0 CONTEXT_Cpsr+4 +#define CONTEXT_X1 CONTEXT_X0+8 +#define CONTEXT_X2 CONTEXT_X1+8 +#define CONTEXT_X3 CONTEXT_X2+8 +#define CONTEXT_X4 CONTEXT_X3+8 +#define CONTEXT_X5 CONTEXT_X4+8 +#define CONTEXT_X6 CONTEXT_X5+8 +#define CONTEXT_X7 CONTEXT_X6+8 +#define CONTEXT_X8 CONTEXT_X7+8 +#define CONTEXT_X9 CONTEXT_X8+8 +#define CONTEXT_X10 CONTEXT_X9+8 +#define CONTEXT_X11 CONTEXT_X10+8 +#define CONTEXT_X12 CONTEXT_X11+8 +#define CONTEXT_X13 CONTEXT_X12+8 +#define CONTEXT_X14 CONTEXT_X13+8 +#define CONTEXT_X15 CONTEXT_X14+8 +#define CONTEXT_X16 CONTEXT_X15+8 +#define CONTEXT_X17 CONTEXT_X16+8 +#define CONTEXT_X18 CONTEXT_X17+8 +#define CONTEXT_X19 CONTEXT_X18+8 +#define CONTEXT_X20 CONTEXT_X19+8 +#define CONTEXT_X21 CONTEXT_X20+8 +#define CONTEXT_X22 CONTEXT_X21+8 +#define CONTEXT_X23 CONTEXT_X22+8 +#define CONTEXT_X24 CONTEXT_X23+8 +#define CONTEXT_X25 CONTEXT_X24+8 +#define CONTEXT_X26 CONTEXT_X25+8 +#define CONTEXT_X27 CONTEXT_X26+8 +#define CONTEXT_X28 CONTEXT_X27+8 +#define CONTEXT_Fp CONTEXT_X28+8 +#define CONTEXT_Lr CONTEXT_Fp+8 +#define CONTEXT_Sp CONTEXT_Lr+8 +#define CONTEXT_Pc CONTEXT_Sp+8 +#define CONTEXT_NEON_OFFSET CONTEXT_Pc+8 +#define CONTEXT_V0 0 +#define CONTEXT_V1 CONTEXT_V0+16 +#define CONTEXT_V2 CONTEXT_V1+16 +#define CONTEXT_V3 CONTEXT_V2+16 +#define CONTEXT_V4 CONTEXT_V3+16 +#define CONTEXT_V5 CONTEXT_V4+16 +#define CONTEXT_V6 CONTEXT_V5+16 +#define CONTEXT_V7 CONTEXT_V6+16 +#define CONTEXT_V8 CONTEXT_V7+16 +#define CONTEXT_V9 CONTEXT_V8+16 +#define CONTEXT_V10 CONTEXT_V9+16 +#define CONTEXT_V11 CONTEXT_V10+16 +#define CONTEXT_V12 CONTEXT_V11+16 +#define CONTEXT_V13 CONTEXT_V12+16 +#define CONTEXT_V14 CONTEXT_V13+16 +#define CONTEXT_V15 CONTEXT_V14+16 +#define CONTEXT_V16 CONTEXT_V15+16 +#define CONTEXT_V17 CONTEXT_V16+16 +#define CONTEXT_V18 CONTEXT_V17+16 +#define CONTEXT_V19 CONTEXT_V18+16 +#define CONTEXT_V20 CONTEXT_V19+16 +#define CONTEXT_V21 CONTEXT_V20+16 +#define CONTEXT_V22 CONTEXT_V21+16 +#define CONTEXT_V23 CONTEXT_V22+16 +#define CONTEXT_V24 CONTEXT_V23+16 +#define CONTEXT_V25 CONTEXT_V24+16 +#define CONTEXT_V26 CONTEXT_V25+16 +#define CONTEXT_V27 CONTEXT_V26+16 +#define CONTEXT_V28 CONTEXT_V27+16 +#define CONTEXT_V29 CONTEXT_V28+16 +#define CONTEXT_V30 CONTEXT_V29+16 +#define CONTEXT_V31 CONTEXT_V30+16 +#define CONTEXT_FLOAT_CONTROL_OFFSET CONTEXT_V31+16 +#define CONTEXT_Fpcr 0 +#define CONTEXT_Fpsr CONTEXT_Fpcr+8 + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/callsignalhandlerwrapper.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/callsignalhandlerwrapper.S new file mode 100644 index 0000000..a74932e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/callsignalhandlerwrapper.S @@ -0,0 +1,32 @@ +// 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. + +#include "unixasmmacros.inc" +#include "asmconstants.h" + +.macro CALL_SIGNAL_HANDLER_WRAPPER Alignment + +.globl C_FUNC(SignalHandlerWorkerReturnOffset\Alignment) +C_FUNC(SignalHandlerWorkerReturnOffset\Alignment): + .int LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment)-C_FUNC(CallSignalHandlerWrapper\Alignment) + +// This function is never called, only a fake stack frame will be setup to have a return +// address set to SignalHandlerWorkerReturn during SIGSEGV handling. +// It enables the unwinder to unwind stack from the handling code to the actual failure site. +NESTED_ENTRY CallSignalHandlerWrapper\Alignment, _TEXT, NoHandler +__StackAllocationSize = (128 + 8 + 8 + \Alignment) // red zone + fp + lr + alignment + PROLOG_STACK_ALLOC __StackAllocationSize + .cfi_adjust_cfa_offset __StackAllocationSize + PROLOG_SAVE_REG_PAIR fp, lr, 0 + bl EXTERNAL_C_FUNC(signal_handler_worker) +LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment): + EPILOG_RESTORE_REG_PAIR fp, lr, 0 + EPILOG_STACK_FREE __StackAllocationSize + ret +NESTED_END CallSignalHandlerWrapper\Alignment, _TEXT + +.endm + +CALL_SIGNAL_HANDLER_WRAPPER 0 +CALL_SIGNAL_HANDLER_WRAPPER 8 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/context2.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/context2.S new file mode 100644 index 0000000..2c8e4f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/context2.S @@ -0,0 +1,213 @@ +// 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 ARM platform. +// This function is processor dependent. It is used by exception handling, +// and is always apply to the current thread. +// + +#include "unixasmmacros.inc" +#include "asmconstants.h" + +// Incoming: +// x0: Context* +// +LEAF_ENTRY CONTEXT_CaptureContext, _TEXT + sub sp, sp, #32 + // save x1, x2 and x3 on stack so we can use them as scratch + stp x1, x2, [sp] + str x3, [sp, 16] + // save the current flags on the stack + mrs x1, nzcv + str x1, [sp, 24] + + ldr w1, [x0, CONTEXT_ContextFlags] + // clangs assembler doesn't seem to support the mov Wx, imm32 yet + movz w2, #0x40, lsl #16 + movk w2, #0x1 + mov w3, w2 + and w2, w1, w2 + cmp w2, w3 + b.ne LOCAL_LABEL(Done_CONTEXT_CONTROL) + + // save the cpsr + ldr x2, [sp, 24] + str w2, [x0, CONTEXT_Cpsr] + stp fp, lr, [x0, CONTEXT_Fp] + add x2, sp, #32 + stp x2, lr, [x0, CONTEXT_Sp] + +LOCAL_LABEL(Done_CONTEXT_CONTROL): + // we dont clobber x1 in the CONTEXT_CONTROL case + // ldr w1, [x0, CONTEXT_ContextFlags] + // clangs assembler doesn't seem to support the mov Wx, imm32 yet + movz w2, #0x40, lsl #16 + movk w2, #0x2 + mov w3, w2 + and w2, w1, w2 + cmp w2, w3 + b.ne LOCAL_LABEL(Done_CONTEXT_INTEGER) + + ldp x1, x2, [sp] + ldr x3, [sp, 16] + + stp x0, x1, [x0, CONTEXT_X0] + stp x2, x3, [x0, CONTEXT_X2] + stp x4, x5, [x0, CONTEXT_X4] + stp x6, x7, [x0, CONTEXT_X6] + stp x8, x9, [x0, CONTEXT_X8] + stp x10, x11, [x0, CONTEXT_X10] + stp x12, x13, [x0, CONTEXT_X12] + stp x14, x15, [x0, CONTEXT_X14] + stp x16, x17, [x0, CONTEXT_X16] + stp x18, x19, [x0, CONTEXT_X18] + stp x20, x21, [x0, CONTEXT_X20] + stp x22, x23, [x0, CONTEXT_X22] + stp x24, x25, [x0, CONTEXT_X24] + stp x26, x27, [x0, CONTEXT_X26] + str x28, [x0, CONTEXT_X28] + + +LOCAL_LABEL(Done_CONTEXT_INTEGER): + ldr w1, [x0, CONTEXT_ContextFlags] + // clangs assembler doesn't seem to support the mov Wx, imm32 yet + movz w2, #0x40, lsl #16 + movk w2, #0x4 + mov w3, w2 + and w2, w1, w2 + cmp w2, w3 + b.ne LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT) + + add x0, x0, CONTEXT_NEON_OFFSET + stp q0, q1, [x0, CONTEXT_V0] + stp q2, q3, [x0, CONTEXT_V2] + stp q4, q5, [x0, CONTEXT_V4] + stp q6, q7, [x0, CONTEXT_V6] + stp q8, q9, [x0, CONTEXT_V8] + stp q10, q11, [x0, CONTEXT_V10] + stp q12, q13, [x0, CONTEXT_V12] + stp q14, q15, [x0, CONTEXT_V14] + stp q16, q17, [x0, CONTEXT_V16] + stp q18, q19, [x0, CONTEXT_V18] + stp q20, q21, [x0, CONTEXT_V20] + stp q22, q23, [x0, CONTEXT_V22] + stp q24, q25, [x0, CONTEXT_V24] + stp q26, q27, [x0, CONTEXT_V26] + stp q28, q29, [x0, CONTEXT_V28] + stp q30, q31, [x0, CONTEXT_V30] + add x0, x0, CONTEXT_FLOAT_CONTROL_OFFSET + mrs x1, fpcr + mrs x2, fpsr + stp x1, x2, [x0, CONTEXT_Fpcr] + sub x0, x0, CONTEXT_FLOAT_CONTROL_OFFSET + CONTEXT_NEON_OFFSET + +LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT): + + add sp, sp, #32 + ret +LEAF_END CONTEXT_CaptureContext, _TEXT + +// Incoming: +// x0: Context* + +LEAF_ENTRY RtlCaptureContext, _TEXT + sub sp, sp, #16 + str x1, [sp] + // same as above, clang doesn't like mov with #imm32 + // keep this in sync if CONTEXT_FULL changes + movz w1, #0x40, lsl #16 + orr w1, w1, #0x1 + orr w1, w1, #0x2 + orr w1, w1, #0x4 + orr w1, w1, #0x8 + str w1, [x0, CONTEXT_ContextFlags] + ldr x1, [sp] + add sp, sp, #16 + b C_FUNC(CONTEXT_CaptureContext) +LEAF_END RtlCaptureContext, _TEXT + +// Incoming: +// x0: Context* +// x1: Exception* +// +LEAF_ENTRY RtlRestoreContext, _TEXT + +#ifdef HAS_ASAN + ldr w17, [x0, #(CONTEXT_ContextFlags)] + tbz w17, #CONTEXT_CONTROL_BIT, LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT) + + stp x0, x1, [sp, -16]! + bl EXTERNAL_C_FUNC(__asan_handle_no_return) + ldp x0, x1, [sp], 16 + +LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT): +#endif + // aarch64 specifies: + // IP0 and IP1, the Intra-Procedure Call temporary registers, + // are available for use by e.g. veneers or branch islands during a procedure call. + // They are otherwise corruptible. + // Since we cannot control $pc directly, we're going to corrupt x16 and x17 + // so that we can restore control + // since we potentially clobber x0 below, we'll bank it in x16 + mov x16, x0 + + ldr w17, [x16, CONTEXT_ContextFlags] + tbz w17, #CONTEXT_FLOATING_POINT_BIT, LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT) + + add x16, x16, CONTEXT_NEON_OFFSET + ldp q0, q1, [x16, CONTEXT_V0] + ldp q2, q3, [x16, CONTEXT_V2] + ldp q4, q5, [x16, CONTEXT_V4] + ldp q6, q7, [x16, CONTEXT_V6] + ldp q8, q9, [x16, CONTEXT_V8] + ldp q10, q11, [x16, CONTEXT_V10] + ldp q12, q13, [x16, CONTEXT_V12] + ldp q14, q15, [x16, CONTEXT_V14] + ldp q16, q17, [x16, CONTEXT_V16] + ldp q18, q19, [x16, CONTEXT_V18] + ldp q20, q21, [x16, CONTEXT_V20] + ldp q22, q23, [x16, CONTEXT_V22] + ldp q24, q25, [x16, CONTEXT_V24] + ldp q26, q27, [x16, CONTEXT_V26] + ldp q28, q29, [x16, CONTEXT_V28] + ldp q30, q31, [x16, CONTEXT_V30] + add x16, x16, CONTEXT_FLOAT_CONTROL_OFFSET + ldp x1, x2, [x16, CONTEXT_Fpcr] + msr fpcr, x1 + msr fpsr, x2 + sub x16, x16, CONTEXT_FLOAT_CONTROL_OFFSET + CONTEXT_NEON_OFFSET + +LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT): + tbz w17, #CONTEXT_INTEGER_BIT, LOCAL_LABEL(No_Restore_CONTEXT_INTEGER) + + ldp x0, x1, [x16, CONTEXT_X0] + ldp x2, x3, [x16, CONTEXT_X2] + ldp x4, x5, [x16, CONTEXT_X4] + ldp x6, x7, [x16, CONTEXT_X6] + ldp x8, x9, [x16, CONTEXT_X8] + ldp x10, x11, [x16, CONTEXT_X10] + ldp x12, x13, [x16, CONTEXT_X12] + ldp x14, x15, [x16, CONTEXT_X14] + ldp x18, x19, [x16, CONTEXT_X18] + ldp x20, x21, [x16, CONTEXT_X20] + ldp x22, x23, [x16, CONTEXT_X22] + ldp x24, x25, [x16, CONTEXT_X24] + ldp x26, x27, [x16, CONTEXT_X26] + ldr x28, [x16, CONTEXT_X28] + +LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): + tbz w17, #CONTEXT_CONTROL_BIT, LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) + + ldr w17, [x16, CONTEXT_Cpsr] + msr nzcv, x17 + ldp fp, lr, [x16, CONTEXT_Fp] + ldr x17, [x16, CONTEXT_Sp] + mov sp, x17 + ldr x17, [x16, CONTEXT_Pc] + br x17 + +LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): + ret + +LEAF_END RtlRestoreContext, _TEXT diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/debugbreak.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/debugbreak.S new file mode 100644 index 0000000..0dc5bb6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/debugbreak.S @@ -0,0 +1,11 @@ +// 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. + +#include "unixasmmacros.inc" + +LEAF_ENTRY DBG_DebugBreak, _TEXT + EMIT_BREAKPOINT + ret +LEAF_END_MARKED DBG_DebugBreak, _TEXT + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/exceptionhelper.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/exceptionhelper.S new file mode 100644 index 0000000..93c9af1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/exceptionhelper.S @@ -0,0 +1,52 @@ +// 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. + +#include "unixasmmacros.inc" +#include "asmconstants.h" + +////////////////////////////////////////////////////////////////////////// +// +// This function creates a stack frame right below the target frame, restores all callee +// saved registers, SP, and LR from the passed in context. +// 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 +#ifdef HAS_ASAN + // Need to call __asan_handle_no_return explicitly here because we re-intialize SP before + // throwing exception in ThrowExceptionHelper + stp x0, x1, [sp, -16]! + bl EXTERNAL_C_FUNC(__asan_handle_no_return) + ldp x0, x1, [sp], 16 +#endif + + // Save the FP & LR to the stack so that the unwind can work at the instruction after + // loading the FP from the context, but before loading the SP from the context. + stp fp, lr, [sp, -16]! + + ldp x19,x20, [x0, #(CONTEXT_X19)] + ldp x21,x22, [x0, #(CONTEXT_X21)] + ldp x23,x24, [x0, #(CONTEXT_X23)] + ldp x24,x25, [x0, #(CONTEXT_X24)] + ldp x26,x27, [x0, #(CONTEXT_X26)] + ldp x28,fp, [x0, #(CONTEXT_X28)] + ldr lr, [x0, #(CONTEXT_Pc)] + + // Restore the lower 64 bits of v8-v15 + add x2, x0, CONTEXT_NEON_OFFSET + ldr d8, [x2, #(CONTEXT_V8 )] + ldr d9, [x2, #(CONTEXT_V9 )] + ldr d10, [x2, #(CONTEXT_V10)] + ldr d11, [x2, #(CONTEXT_V11)] + ldr d12, [x2, #(CONTEXT_V12)] + ldr d13, [x2, #(CONTEXT_V13)] + ldr d14, [x2, #(CONTEXT_V14)] + ldr d15, [x2, #(CONTEXT_V15)] + + ldr x2, [x0, #(CONTEXT_Sp)] + mov sp, x2 + + // The PAL_SEHException pointer + mov x0, x1 + b EXTERNAL_C_FUNC(ThrowExceptionHelper) +LEAF_END ThrowExceptionFromContextInternal, _TEXT diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/processor.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/processor.cpp new file mode 100644 index 0000000..4c47210 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/processor.cpp @@ -0,0 +1,22 @@ +// 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 ARM64 + platform. These functions are processor dependent. + + + +--*/ + +#include "pal/palinternal.h" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/signalhandlerhelper.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/signalhandlerhelper.cpp new file mode 100644 index 0000000..524bd11 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/arm64/signalhandlerhelper.cpp @@ -0,0 +1,74 @@ +// 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. + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do this first + +#include "pal/palinternal.h" +#include "pal/context.h" +#include "pal/signal.hpp" +#include "pal/utils.h" +#include + +/*++ +Function : + ExecuteHandlerOnCustomStack + + Execute signal handler on a custom stack, the current stack pointer is specified by the customSp + If the customSp is 0, then the handler is executed on the original stack where the signal was fired. + It installs a fake stack frame to enable stack unwinding to the signal source location. + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + returnPoint - context to which the function returns if the common_signal_handler returns + + (no return value) +--*/ +void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t customSp, SignalHandlerWorkerReturnPoint* returnPoint) +{ + ucontext_t *ucontext = (ucontext_t *)context; + size_t faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext); + _ASSERTE(IS_ALIGNED(faultSp, 8)); + + if (customSp == 0) + { + // preserve 128 bytes long red zone and align stack pointer + customSp = ALIGN_DOWN(faultSp - 128, 16); + } + + size_t fakeFrameReturnAddress; + + if (IS_ALIGNED(faultSp, 16)) + { + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset0 + (size_t)CallSignalHandlerWrapper0; + } + else + { + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset8 + (size_t)CallSignalHandlerWrapper8; + } + + // preserve 128 bytes long red zone and align stack pointer + size_t* sp = (size_t*)customSp; + + // Build fake stack frame to enable the stack unwinder to unwind from signal_handler_worker to the faulting instruction + // pushed LR + *--sp = (size_t)MCREG_Pc(ucontext->uc_mcontext); + // pushed frame pointer + *--sp = (size_t)MCREG_Fp(ucontext->uc_mcontext); + + // Switch the current context to the signal_handler_worker and the original stack + CONTEXT context2; + RtlCaptureContext(&context2); + + context2.Sp = (size_t)sp; + context2.Fp = (size_t)sp; + context2.Lr = fakeFrameReturnAddress; + context2.Pc = (size_t)signal_handler_worker; + context2.X0 = code; + context2.X1 = (size_t)siginfo; + context2.X2 = (size_t)context; + context2.X3 = (size_t)returnPoint; + + RtlRestoreContext(&context2, NULL); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/asmconstants.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/asmconstants.h new file mode 100644 index 0000000..ff763ef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/asmconstants.h @@ -0,0 +1,30 @@ +// 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. + +#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 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/callsignalhandlerwrapper.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/callsignalhandlerwrapper.S new file mode 100644 index 0000000..26f06d9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/callsignalhandlerwrapper.S @@ -0,0 +1,47 @@ +// 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" + +.macro CALL_SIGNAL_HANDLER_WRAPPER Alignment + +.globl C_FUNC(SignalHandlerWorkerReturnOffset\Alignment) +C_FUNC(SignalHandlerWorkerReturnOffset\Alignment): + .int LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment)-C_FUNC(CallSignalHandlerWrapper\Alignment) + +// This function is never called, only a fake stack frame will be setup to have a return +// address set to SignalHandlerWorkerReturn during SIGSEGV handling. +// It enables the unwinder to unwind stack from the handling code to the actual failure site. +NESTED_ENTRY CallSignalHandlerWrapper\Alignment, _TEXT, NoHandler + + .cfi_def_cfa_offset (4 + \Alignment) // return address + stack alignment + .cfi_offset eip, -(4 + \Alignment) + push ebp + .cfi_adjust_cfa_offset 4 + .cfi_rel_offset ebp, 0 + mov ebp, esp + .cfi_def_cfa_register ebp + // Align stack + sub esp, 8 + // Simulate arguments pushing + push eax + push eax + push eax + push eax + call EXTERNAL_C_FUNC(signal_handler_worker) +LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment): + add esp, 4 * 4 + 8 + pop ebp + ret + +NESTED_END CallSignalHandlerWrapper\Alignment, _TEXT + +.endm + +CALL_SIGNAL_HANDLER_WRAPPER 0 +CALL_SIGNAL_HANDLER_WRAPPER 4 +CALL_SIGNAL_HANDLER_WRAPPER 8 +CALL_SIGNAL_HANDLER_WRAPPER 12 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/context2.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/context2.S new file mode 100644 index 0000000..8c5db20 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/context2.S @@ -0,0 +1,137 @@ +// 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" + +// +// 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 + // 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 + + pushf + xor ebx, ebx + pop bx + mov [eax + CONTEXT_EFlags], ebx + + test BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT + je LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT) + // Capture FPU status + fnsave [eax + CONTEXT_FloatSave] + frstor [eax + CONTEXT_FloatSave] +LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT): + + 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 +LEAF_END CONTEXT_CaptureContext, _TEXT + +LEAF_ENTRY RtlCaptureContext, _TEXT + 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 + +#ifdef HAS_ASAN + call EXTERNAL_C_FUNC(__asan_handle_no_return) +#endif + mov eax, [esp + 4] + test BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT + je LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT) + frstor [eax + CONTEXT_FloatSave] +LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT): + + 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 Stack + mov esp, [eax + CONTEXT_Esp] + + // Create a minimal frame + push DWORD PTR [eax + CONTEXT_Eip] + + // Restore register(s) + mov ebp, [eax + CONTEXT_Ebp] + mov edi, [eax + CONTEXT_Edi] + mov esi, [eax + CONTEXT_Esi] + mov edx, [eax + CONTEXT_Edx] + mov ecx, [eax + CONTEXT_Ecx] + mov ebx, [eax + CONTEXT_Ebx] + mov eax, [eax + CONTEXT_Eax] + + // Resume + ret +LEAF_END RtlRestoreContext, _TEXT + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/debugbreak.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/debugbreak.S new file mode 100644 index 0000000..3065e40 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/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/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/exceptionhelper.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/exceptionhelper.S new file mode 100644 index 0000000..609efcf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/exceptionhelper.S @@ -0,0 +1,50 @@ +// 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" + +////////////////////////////////////////////////////////////////////////// +// +// 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 +#ifdef HAS_ASAN + // Need to call __asan_handle_no_return explicitly here because we re-intialize ESP before + // throwing exception in ThrowExceptionHelper + call EXTERNAL_C_FUNC(__asan_handle_no_return) +#endif + + push ebp + mov ecx, [esp + 12] // ecx: PAL_SEHException * (first argument for ThrowExceptionHelper) + mov eax, [esp + 8] // ebx: CONTEXT * + + mov ebp, [eax + CONTEXT_Ebp] + mov esp, [eax + CONTEXT_Esp] + mov ebx, [eax + CONTEXT_Ebx] + mov esi, [eax + CONTEXT_Esi] + mov edi, [eax + CONTEXT_Edi] + + // 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 EBP is no longer saved in the current stack frame. + .cfi_restore ebp + + // Store return address to the stack + mov eax, [eax + CONTEXT_Eip] + push eax + jmp EXTERNAL_C_FUNC(ThrowExceptionHelper) + +LEAF_END ThrowExceptionFromContextInternal, _TEXT diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/processor.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/processor.cpp new file mode 100644 index 0000000..e1c8de1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/processor.cpp @@ -0,0 +1,22 @@ +// 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" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/signalhandlerhelper.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/signalhandlerhelper.cpp new file mode 100644 index 0000000..16e527a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/arch/i386/signalhandlerhelper.cpp @@ -0,0 +1,83 @@ +// 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. + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do this first + +#include "pal/palinternal.h" +#include "pal/context.h" +#include "pal/signal.hpp" +#include "pal/utils.h" +#include + +/*++ +Function : + ExecuteHandlerOnCustomStack + + Execute signal handler on a custom stack, the current stack pointer is specified by the customSp + If the customSp is 0, then the handler is executed on the original stack where the signal was fired. + It installs a fake stack frame to enable stack unwinding to the signal source location. + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + returnPoint - context to which the function returns if the common_signal_handler returns + + (no return value) +--*/ +void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t customSp, SignalHandlerWorkerReturnPoint* returnPoint) +{ + ucontext_t *ucontext = (ucontext_t *)context; + size_t faultSp = (size_t)MCREG_Esp(ucontext->uc_mcontext); + + _ASSERTE(IS_ALIGNED(faultSp, 4)); + + if (customSp == 0) + { + customSp = ALIGN_DOWN(faultSp, 16); + } + + size_t fakeFrameReturnAddress; + + switch (faultSp & 0xc) + { + case 0x0: + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset0 + (size_t)CallSignalHandlerWrapper0; + break; + case 0x4: + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset4 + (size_t)CallSignalHandlerWrapper4; + break; + case 0x8: + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset8 + (size_t)CallSignalHandlerWrapper8; + break; + case 0xc: + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset12 + (size_t)CallSignalHandlerWrapper12; + break; + } + + size_t* sp = (size_t*)customSp; + + // Build fake stack frame to enable the stack unwinder to unwind from signal_handler_worker to the faulting instruction + *--sp = (size_t)MCREG_Eip(ucontext->uc_mcontext); + *--sp = (size_t)MCREG_Ebp(ucontext->uc_mcontext); + size_t fp = (size_t)sp; + // Align stack + sp -= 2; + *--sp = (size_t)returnPoint; + *--sp = (size_t)context; + *--sp = (size_t)siginfo; + *--sp = code; + *--sp = fakeFrameReturnAddress; + + // Switch the current context to the signal_handler_worker and the original stack + CONTEXT context2; + RtlCaptureContext(&context2); + + // We don't care about the other registers state since the stack unwinding restores + // them for the target frame directly from the signal context. + context2.Esp = (size_t)sp; + context2.Ebp = (size_t)fp; + context2.Eip = (size_t)signal_handler_worker; + + RtlRestoreContext(&context2, NULL); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/build_tools/mdtool_dummy b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/build_tools/mdtool_dummy new file mode 100644 index 0000000..1005a34 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/build_tools/mdtool_dummy @@ -0,0 +1,7 @@ +#!/bin/sh + +# 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. + +echo mdtool_dummy : not generating any dependencies diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/build_tools/mdtool_gcc.in b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/build_tools/mdtool_gcc.in new file mode 100644 index 0000000..233b58a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/build_tools/mdtool_gcc.in @@ -0,0 +1,43 @@ +#!/bin/sh + +# 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. +# +# mdtool_gcc +# +#Abstract: +# Generates dependencies for a makefile +# (for gcc compilers) +# + +str=`grep -n '#mdtool output goes here>' obj${BUILD_ALT_DIR}/${_BUILDARCH}/makefile` +if [ "$str" = "" ] ; then +#didn't find our placeholder string : don't change file + echo mdtool_gcc : makefile not setup for mdtool : ignoring + exit 0 +fi + +#truncate makefile to remove old dependencies +sed /'#mdtool output goes here>'/q obj${BUILD_ALT_DIR}/${_BUILDARCH}/makefile > obj${BUILD_ALT_DIR}/${_BUILDARCH}/makefile.final + +echo '#dependencies generated by mdtool_gcc :' >> obj${BUILD_ALT_DIR}/${_BUILDARCH}/makefile.final +echo >> obj${BUILD_ALT_DIR}/${_BUILDARCH}/makefile.final +# gcc -M generates make-friendly dependencies; +# -MM ignores system includes (#include ) +@CC@ @MDTOOL_CFLAGS@ $@ >> obj${BUILD_ALT_DIR}/${_BUILDARCH}/makefile.depfromgcc +#Prepend ../.. to the source's filename +#with some sed magic, since gcc doesn't do it for us. +sed 's#: \(.*\)$#: ../../\1#g' obj${BUILD_ALT_DIR}/${_BUILDARCH}/makefile.depfromgcc > obj${BUILD_ALT_DIR}/${_BUILDARCH}/makefile.aftersed +cat obj${BUILD_ALT_DIR}/${_BUILDARCH}/makefile.aftersed >> obj${BUILD_ALT_DIR}/${_BUILDARCH}/makefile.final + +if [ "$?" = "0" ] ; then + echo mdtool_gcc : dependencies generated + # replace old makefile by new one. + mv -f obj${BUILD_ALT_DIR}/${_BUILDARCH}/makefile.final obj${BUILD_ALT_DIR}/${_BUILDARCH}/makefile + rm -f obj${BUILD_ALT_DIR}/${_BUILDARCH}/makefile.aftersed + rm -f obj${BUILD_ALT_DIR}/${_BUILDARCH}/makefile.depfromgcc + exit 0 +fi +exit 1 + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/config.h.in b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/config.h.in new file mode 100644 index 0000000..8e7e692 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/config.h.in @@ -0,0 +1,172 @@ +#ifndef _PAL_CONFIG_H_INCLUDED +#define _PAL_CONFIG_H_INCLUDED 1 + +#cmakedefine01 HAVE_VM_FLAGS_SUPERPAGE_SIZE_ANY +#cmakedefine01 HAVE_MAP_HUGETLB +#cmakedefine01 HAVE_IEEEFP_H +#cmakedefine01 HAVE_SYS_VMPARAM_H +#cmakedefine01 HAVE_MACH_VM_TYPES_H +#cmakedefine01 HAVE_MACH_VM_PARAM_H +#cmakedefine01 HAVE_MACHINE_NPX_H +#cmakedefine01 HAVE_MACHINE_REG_H +#cmakedefine01 HAVE_MACHINE_VMPARAM_H +#cmakedefine01 HAVE_PROCFS_H +#cmakedefine01 HAVE_CRT_EXTERNS_H +#cmakedefine01 HAVE_SYS_TIME_H +#cmakedefine01 HAVE_PTHREAD_NP_H +#cmakedefine01 HAVE_SYS_LWP_H +#cmakedefine01 HAVE_LWP_H +#cmakedefine01 HAVE_RUNETYPE_H +#cmakedefine01 HAVE_SYS_SYSCTL_H +#cmakedefine01 HAVE_GNU_LIBNAMES_H +#cmakedefine01 HAVE_PRCTL_H +#cmakedefine01 HAVE_NUMA_H +#cmakedefine01 HAVE_PTHREAD_NP_H +#cmakedefine01 HAVE_AUXV_HWCAP_H +#cmakedefine01 HAVE_SYS_PTRACE_H + +#cmakedefine01 HAVE_KQUEUE +#cmakedefine01 HAVE_PTHREAD_SUSPEND +#cmakedefine01 HAVE_PTHREAD_SUSPEND_NP +#cmakedefine01 HAVE_PTHREAD_CONTINUE +#cmakedefine01 HAVE_PTHREAD_RESUME_NP +#cmakedefine01 HAVE_PTHREAD_CONTINUE_NP +#cmakedefine01 HAVE_PTHREAD_ATTR_GET_NP +#cmakedefine01 HAVE_PTHREAD_GETATTR_NP +#cmakedefine01 HAVE_PTHREAD_GETCPUCLOCKID +#cmakedefine01 HAVE_PTHREAD_SIGQUEUE +#cmakedefine01 HAVE_PTHREAD_GETAFFINITY_NP +#cmakedefine01 HAVE_PTHREAD_ATTR_SETAFFINITY_NP +#cmakedefine01 HAVE_CPUSET_T +#cmakedefine01 HAVE_SIGRETURN +#cmakedefine01 HAVE__THREAD_SYS_SIGRETURN +#cmakedefine01 HAVE_COPYSIGN +#cmakedefine01 HAVE_FSYNC +#cmakedefine01 HAVE_FUTIMES +#cmakedefine01 HAVE_UTIMES +#cmakedefine01 HAVE_SYSCTL +#cmakedefine01 HAVE_SYSCTLBYNAME +#cmakedefine01 HAVE_SYSCONF +#cmakedefine01 HAVE_SYSINFO +#cmakedefine01 HAVE_GMTIME_R +#cmakedefine01 HAVE_TIMEGM +#cmakedefine01 HAVE_POLL +#cmakedefine01 HAVE_STATVFS +#cmakedefine01 HAVE_NON_LEGACY_STATFS +#cmakedefine01 HAVE_THREAD_SELF +#cmakedefine01 HAVE__LWP_SELF +#cmakedefine01 HAVE_MACH_THREADS +#cmakedefine01 HAVE_MACH_EXCEPTIONS +#cmakedefine01 HAVE_VM_ALLOCATE +#cmakedefine01 HAVE_VM_READ +#cmakedefine01 HAVE_DIRECTIO +#cmakedefine01 HAVE_SEMAPHORE_H +#cmakedefine01 HAS_SYSV_SEMAPHORES +#cmakedefine01 HAS_PTHREAD_MUTEXES +#cmakedefine01 HAVE_TTRACE +#cmakedefine01 HAVE_PIPE2 +#cmakedefine01 HAVE_SCHED_GETAFFINITY +#cmakedefine HAVE_UNW_GET_SAVE_LOC +#cmakedefine HAVE_UNW_GET_ACCESSORS +#cmakedefine01 HAVE_XSWDEV +#cmakedefine01 HAVE_XSW_USAGE +#cmakedefine01 HAVE_PUBLIC_XSTATE_STRUCT +#cmakedefine01 HAVE__FPX_SW_BYTES_WITH_XSTATE_BV +#cmakedefine01 HAVE_PR_SET_PTRACER +#cmakedefine01 HAVE_SWAPCTL + +#cmakedefine01 HAVE_STAT_TIMESPEC +#cmakedefine01 HAVE_STAT_TIM +#cmakedefine01 HAVE_STAT_NSEC +#cmakedefine01 HAVE_TM_GMTOFF + +#cmakedefine01 HAVE_BSD_REGS_T +#cmakedefine01 HAVE_PT_REGS +#cmakedefine01 HAVE_GREGSET_T +#cmakedefine01 HAVE___GREGSET_T +#cmakedefine01 HAVE_FPSTATE_GLIBC_RESERVED1 +#cmakedefine01 HAVE_UCONTEXT_T +#cmakedefine01 HAVE_PTHREAD_RWLOCK_T +#cmakedefine01 HAVE_PRWATCH_T +#cmakedefine SIZEOF_OFF_T @SIZEOF_OFF_T@ +#cmakedefine01 HAVE_DIRENT_D_TYPE +#cmakedefine01 HAVE_FPREGS_WITH_CW + +#cmakedefine01 HAVE_YIELD_SYSCALL +#cmakedefine01 HAVE_INFTIM +#cmakedefine01 HAVE_CHAR_BIT +#cmakedefine01 USER_H_DEFINES_DEBUG +#cmakedefine01 HAVE__SC_PHYS_PAGES +#cmakedefine01 HAVE__SC_AVPHYS_PAGES + +#cmakedefine01 REALPATH_SUPPORTS_NONEXISTENT_FILES +#cmakedefine01 SSCANF_CANNOT_HANDLE_MISSING_EXPONENT +#cmakedefine01 SSCANF_SUPPORT_ll +#cmakedefine01 HAVE_LARGE_SNPRINTF_SUPPORT +#cmakedefine01 HAVE_BROKEN_FIFO_SELECT +#cmakedefine01 HAVE_BROKEN_FIFO_KEVENT +#cmakedefine01 HAS_FTRUNCATE_LENGTH_ISSUE +#cmakedefine01 UNWIND_CONTEXT_IS_UCONTEXT_T +#cmakedefine01 HAVE_SCHED_GET_PRIORITY +#cmakedefine01 HAVE_SCHED_GETCPU +#cmakedefine01 HAVE_WORKING_GETTIMEOFDAY +#cmakedefine01 HAVE_WORKING_CLOCK_GETTIME +#cmakedefine01 HAVE_CLOCK_MONOTONIC +#cmakedefine01 HAVE_CLOCK_MONOTONIC_COARSE +#cmakedefine01 HAVE_MACH_ABSOLUTE_TIME +#cmakedefine01 HAVE_CLOCK_THREAD_CPUTIME +#cmakedefine01 HAVE_PTHREAD_CONDATTR_SETCLOCK +#cmakedefine01 HAVE_MMAP_DEV_ZERO +#cmakedefine01 MMAP_ANON_IGNORES_PROTECTION +#cmakedefine01 ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS +#cmakedefine01 PTHREAD_CREATE_MODIFIES_ERRNO +#cmakedefine01 SEM_INIT_MODIFIES_ERRNO +#cmakedefine01 HAVE_PROCFS_CTL +#cmakedefine01 HAVE_PROCFS_MAPS +#cmakedefine01 HAVE_PROCFS_STAT +#cmakedefine01 HAVE_PROCFS_STATUS +#cmakedefine01 HAVE_COMPATIBLE_ACOS +#cmakedefine01 HAVE_COMPATIBLE_ASIN +#cmakedefine01 HAVE_COMPATIBLE_POW +#cmakedefine01 HAVE_VALID_NEGATIVE_INF_POW +#cmakedefine01 HAVE_VALID_POSITIVE_INF_POW +#cmakedefine01 HAVE_COMPATIBLE_ATAN2 +#cmakedefine01 HAVE_COMPATIBLE_EXP +#cmakedefine01 HAVE_COMPATIBLE_ILOGB0 +#cmakedefine01 HAVE_COMPATIBLE_ILOGBNAN +#cmakedefine01 HAVE_COMPATIBLE_LOG +#cmakedefine01 HAVE_COMPATIBLE_LOG10 +#cmakedefine01 UNGETC_NOT_RETURN_EOF +#cmakedefine01 HAS_POSIX_SEMAPHORES +#cmakedefine01 GETPWUID_R_SETS_ERRNO +#cmakedefine01 FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL + +#define PAL_THREAD_PRIORITY_MIN 0 +#define PAL_THREAD_PRIORITY_MAX 0 + +#cmakedefine01 HAVE__NSGETENVIRON +#cmakedefine01 DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX +#cmakedefine PAL_PTRACE(cmd, pid, addr, data) @PAL_PTRACE@ +#cmakedefine PAL_PT_ATTACH @PAL_PT_ATTACH@ +#cmakedefine PAL_PT_DETACH @PAL_PT_DETACH@ +#cmakedefine PAL_PT_READ_D @PAL_PT_READ_D@ +#cmakedefine PAL_PT_WRITE_D @PAL_PT_WRITE_D@ +#cmakedefine01 SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING +#cmakedefine01 ERROR_FUNC_FOR_GLOB_HAS_FIXED_PARAMS +#cmakedefine01 HAS_FTRUNCATE_LENGTH_ISSUE +#cmakedefine01 HAVE_FULLY_FEATURED_PTHREAD_MUTEXES +#cmakedefine01 HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES +#cmakedefine BSD_REGS_STYLE(reg, RR, rr) @BSD_REGS_STYLE@ +#cmakedefine01 HAVE_SCHED_OTHER_ASSIGNABLE + +#define CHECK_TRACE_SPECIFIERS 0 +#define HAVE_GETHRTIME 0 +#define HAVE_READ_REAL_TIME 0 +#define OPEN64_IS_USED_INSTEAD_OF_OPEN 0 +#define PAL_IGNORE_NORMAL_THREAD_PRIORITY 0 +#define SELF_SUSPEND_FAILS_WITH_NATIVE_SUSPENSION 0 +#define SET_SCHEDPARAM_NEEDS_PRIVS 0 +#define SIGWAIT_FAILS_WHEN_PASSED_FULL_SIGSET 0 +#define WRITE_0_BYTES_HANGS_TTY 0 +#define HAVE_FTRUNCATE_LARGE_LENGTH_SUPPORT 1 +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/configure.cmake b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/configure.cmake new file mode 100644 index 0000000..b67637b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/configure.cmake @@ -0,0 +1,1442 @@ +include(CheckCXXSourceCompiles) +include(CheckCXXSourceRuns) +include(CheckCXXSymbolExists) +include(CheckFunctionExists) +include(CheckPrototypeDefinition) +include(CheckIncludeFiles) +include(CheckStructHasMember) +include(CheckTypeSize) +include(CheckLibraryExists) + +if(CLR_CMAKE_TARGET_FREEBSD) + set(CMAKE_REQUIRED_INCLUDES ${CROSS_ROOTFS}/usr/local/include) +elseif(CLR_CMAKE_TARGET_SUNOS) + set(CMAKE_REQUIRED_INCLUDES /opt/local/include) +endif() +if(NOT CLR_CMAKE_TARGET_OSX AND NOT CLR_CMAKE_TARGET_FREEBSD AND NOT CLR_CMAKE_TARGET_NETBSD) + set(CMAKE_REQUIRED_DEFINITIONS "-D_BSD_SOURCE -D_SVID_SOURCE -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L") +endif() + +if(CLR_CMAKE_TARGET_LINUX AND NOT CLR_CMAKE_TARGET_ANDROID) + set(CMAKE_RT_LIBS rt) +elseif(CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD) + set(CMAKE_RT_LIBS rt) +else() + set(CMAKE_RT_LIBS "") +endif() + +list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_FILE_OFFSET_BITS=64) + +check_include_files(ieeefp.h HAVE_IEEEFP_H) +check_include_files(sys/vmparam.h HAVE_SYS_VMPARAM_H) +check_include_files(mach/vm_types.h HAVE_MACH_VM_TYPES_H) +check_include_files(mach/vm_param.h HAVE_MACH_VM_PARAM_H) +check_include_files("sys/param.h;sys/types.h;machine/npx.h" HAVE_MACHINE_NPX_H) +check_include_files("sys/param.h;sys/cdefs.h;machine/reg.h" HAVE_MACHINE_REG_H) +check_include_files(machine/vmparam.h HAVE_MACHINE_VMPARAM_H) +check_include_files(procfs.h HAVE_PROCFS_H) +check_include_files(crt_externs.h HAVE_CRT_EXTERNS_H) +check_include_files(sys/time.h HAVE_SYS_TIME_H) +check_include_files(pthread_np.h HAVE_PTHREAD_NP_H) +check_include_files(sys/lwp.h HAVE_SYS_LWP_H) +check_include_files(lwp.h HAVE_LWP_H) +check_include_files(runetype.h HAVE_RUNETYPE_H) +check_include_files(semaphore.h HAVE_SEMAPHORE_H) +check_include_files(sys/prctl.h HAVE_PRCTL_H) +check_include_files(numa.h HAVE_NUMA_H) +check_include_files(pthread_np.h HAVE_PTHREAD_NP_H) +check_include_files("sys/auxv.h;asm/hwcap.h" HAVE_AUXV_HWCAP_H) +check_include_files("sys/ptrace.h" HAVE_SYS_PTRACE_H) + +set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_DL_LIBS}) + +check_cxx_source_compiles(" +#include +int main() +{ + return VM_FLAGS_SUPERPAGE_SIZE_ANY; +} +" HAVE_VM_FLAGS_SUPERPAGE_SIZE_ANY) + +check_cxx_source_compiles(" +#include +int main() +{ + return MAP_HUGETLB; +} +" HAVE_MAP_HUGETLB) + +check_cxx_source_compiles(" +#include +int main(int argc, char **argv) { + return 0; +}" HAVE_LTTNG_TRACEPOINT_H) + +set(CMAKE_REQUIRED_LIBRARIES) + +check_include_files(sys/sysctl.h HAVE_SYS_SYSCTL_H) +check_function_exists(sysctlbyname HAVE_SYSCTLBYNAME) +check_include_files(gnu/lib-names.h HAVE_GNU_LIBNAMES_H) + +check_function_exists(kqueue HAVE_KQUEUE) + +check_library_exists(c sched_getaffinity "" HAVE_SCHED_GETAFFINITY) +check_library_exists(pthread pthread_create "" HAVE_LIBPTHREAD) +check_library_exists(c pthread_create "" HAVE_PTHREAD_IN_LIBC) + +if (HAVE_LIBPTHREAD) + set(PTHREAD_LIBRARY pthread) +elseif (HAVE_PTHREAD_IN_LIBC) + set(PTHREAD_LIBRARY c) +endif() + +check_library_exists(${PTHREAD_LIBRARY} pthread_suspend "" HAVE_PTHREAD_SUSPEND) +check_library_exists(${PTHREAD_LIBRARY} pthread_suspend_np "" HAVE_PTHREAD_SUSPEND_NP) +check_library_exists(${PTHREAD_LIBRARY} pthread_continue "" HAVE_PTHREAD_CONTINUE) +check_library_exists(${PTHREAD_LIBRARY} pthread_continue_np "" HAVE_PTHREAD_CONTINUE_NP) +check_library_exists(${PTHREAD_LIBRARY} pthread_resume_np "" HAVE_PTHREAD_RESUME_NP) +check_library_exists(${PTHREAD_LIBRARY} pthread_attr_get_np "" HAVE_PTHREAD_ATTR_GET_NP) +check_library_exists(${PTHREAD_LIBRARY} pthread_getattr_np "" HAVE_PTHREAD_GETATTR_NP) +check_library_exists(${PTHREAD_LIBRARY} pthread_getcpuclockid "" HAVE_PTHREAD_GETCPUCLOCKID) +check_library_exists(${PTHREAD_LIBRARY} pthread_sigqueue "" HAVE_PTHREAD_SIGQUEUE) +check_library_exists(${PTHREAD_LIBRARY} pthread_getaffinity_np "" HAVE_PTHREAD_GETAFFINITY_NP) +check_library_exists(${PTHREAD_LIBRARY} pthread_attr_setaffinity_np "" HAVE_PTHREAD_ATTR_SETAFFINITY_NP) + +check_function_exists(sigreturn HAVE_SIGRETURN) +check_function_exists(_thread_sys_sigreturn HAVE__THREAD_SYS_SIGRETURN) +set(CMAKE_REQUIRED_LIBRARIES m) +check_function_exists(copysign HAVE_COPYSIGN) +set(CMAKE_REQUIRED_LIBRARIES) +check_function_exists(fsync HAVE_FSYNC) +check_function_exists(futimes HAVE_FUTIMES) +check_function_exists(utimes HAVE_UTIMES) +check_function_exists(sysctl HAVE_SYSCTL) +check_function_exists(sysinfo HAVE_SYSINFO) +check_function_exists(sysconf HAVE_SYSCONF) +check_function_exists(gmtime_r HAVE_GMTIME_R) +check_function_exists(timegm HAVE_TIMEGM) +check_function_exists(poll HAVE_POLL) +check_function_exists(statvfs HAVE_STATVFS) +check_function_exists(thread_self HAVE_THREAD_SELF) +check_function_exists(_lwp_self HAVE__LWP_SELF) +check_function_exists(pthread_mach_thread_np HAVE_MACH_THREADS) +check_function_exists(thread_set_exception_ports HAVE_MACH_EXCEPTIONS) +check_function_exists(vm_allocate HAVE_VM_ALLOCATE) +check_function_exists(vm_read HAVE_VM_READ) +check_function_exists(directio HAVE_DIRECTIO) +check_function_exists(semget HAS_SYSV_SEMAPHORES) +check_function_exists(pthread_mutex_init HAS_PTHREAD_MUTEXES) +check_function_exists(ttrace HAVE_TTRACE) +check_function_exists(pipe2 HAVE_PIPE2) + +check_cxx_source_compiles(" +#include +int main(int argc, char **argv) { + cpuset_t cpuSet; + + return 0; +}" HAVE_CPUSET_T) + +check_struct_has_member ("struct stat" st_atimespec "sys/types.h;sys/stat.h" HAVE_STAT_TIMESPEC) +check_struct_has_member ("struct stat" st_atim "sys/types.h;sys/stat.h" HAVE_STAT_TIM) +check_struct_has_member ("struct stat" st_atimensec "sys/types.h;sys/stat.h" HAVE_STAT_NSEC) +check_struct_has_member ("struct tm" tm_gmtoff time.h HAVE_TM_GMTOFF) +check_struct_has_member ("ucontext_t" uc_mcontext.gregs[0] ucontext.h HAVE_GREGSET_T) +check_struct_has_member ("ucontext_t" uc_mcontext.__gregs[0] ucontext.h HAVE___GREGSET_T) +check_struct_has_member ("ucontext_t" uc_mcontext.fpregs->__glibc_reserved1[0] ucontext.h HAVE_FPSTATE_GLIBC_RESERVED1) +check_struct_has_member ("struct sysinfo" mem_unit "sys/sysinfo.h" HAVE_SYSINFO_WITH_MEM_UNIT) +check_struct_has_member ("struct dirent" d_type dirent.h HAVE_DIRENT_D_TYPE) +check_struct_has_member ("struct _fpchip_state" cw sys/ucontext.h HAVE_FPREGS_WITH_CW) + +set(CMAKE_EXTRA_INCLUDE_FILES machine/reg.h) +check_type_size("struct reg" BSD_REGS_T) +set(CMAKE_EXTRA_INCLUDE_FILES) +set(CMAKE_EXTRA_INCLUDE_FILES asm/ptrace.h) +check_type_size("struct pt_regs" PT_REGS) +set(CMAKE_EXTRA_INCLUDE_FILES) +set(CMAKE_EXTRA_INCLUDE_FILES signal.h) +set(CMAKE_EXTRA_INCLUDE_FILES) +set(CMAKE_EXTRA_INCLUDE_FILES ucontext.h) +check_type_size(ucontext_t UCONTEXT_T) +set(CMAKE_EXTRA_INCLUDE_FILES) +set(CMAKE_EXTRA_INCLUDE_FILES pthread.h) +check_type_size(pthread_rwlock_t PTHREAD_RWLOCK_T) +set(CMAKE_EXTRA_INCLUDE_FILES) +set(CMAKE_EXTRA_INCLUDE_FILE procfs.h) +check_type_size(prwatch_t PRWATCH_T) +set(CMAKE_EXTRA_INCLUDE_FILE) +check_type_size(off_t SIZEOF_OFF_T) + +check_cxx_symbol_exists(SYS_yield sys/syscall.h HAVE_YIELD_SYSCALL) +check_cxx_symbol_exists(INFTIM poll.h HAVE_INFTIM) +check_cxx_symbol_exists(CHAR_BIT limits.h HAVE_CHAR_BIT) +check_cxx_symbol_exists(_DEBUG sys/user.h USER_H_DEFINES_DEBUG) +check_cxx_symbol_exists(_SC_PHYS_PAGES unistd.h HAVE__SC_PHYS_PAGES) +check_cxx_symbol_exists(_SC_AVPHYS_PAGES unistd.h HAVE__SC_AVPHYS_PAGES) +check_cxx_symbol_exists(swapctl sys/swap.h HAVE_SWAPCTL) + +check_cxx_source_runs(" +#include +#include + +int main(void) { + char *path; +#ifdef PATH_MAX + char resolvedPath[PATH_MAX]; +#elif defined(MAXPATHLEN) + char resolvedPath[MAXPATHLEN]; +#else + char resolvedPath[1024]; +#endif + path = realpath(\"a_nonexistent_file\", resolvedPath); + if (path == NULL) { + exit(1); + } + exit(0); +}" REALPATH_SUPPORTS_NONEXISTENT_FILES) +check_cxx_source_runs(" +#include +#include +int main(void) +{ + long long n = 0; + sscanf(\"5000000000\", \"%qu\", &n); + exit (n != 5000000000); + }" SSCANF_SUPPORT_ll) +check_cxx_source_runs(" +#include +#include + +int main() +{ + int ret; + float f = 0; + char * strin = \"12.34e\"; + + ret = sscanf (strin, \"%e\", &f); + if (ret <= 0) + exit (0); + exit(1); +}" SSCANF_CANNOT_HANDLE_MISSING_EXPONENT) +check_cxx_source_runs(" +#include +#include + +int main(void) { + char buf[256] = { 0 }; + snprintf(buf, 0x7fffffff, \"%#x\", 0x12345678); + if (buf[0] == 0x0) { + exit(1); + } + exit(0); +}" HAVE_LARGE_SNPRINTF_SUPPORT) +check_cxx_source_runs(" +#include +#include +#include +#include +#include +#include +#include +#include + +int main(void) { + int fd, numFDs; + fd_set readFDs, writeFDs, exceptFDs; + struct timeval time = { 0 }; + char * filename = NULL; + + filename = (char *)malloc(L_tmpnam * sizeof(char)); /* ok to leak this at exit */ + if (NULL == filename) { + exit(0); + } + + /* On some platforms (e.g. HP-UX) the multithreading c-runtime does not + support the tmpnam(NULL) semantics, and it returns NULL. Therefore + we need to use the tmpnam(pbuffer) version. + */ + if (NULL == tmpnam(filename)) { + exit(0); + } + if (mkfifo(filename, S_IRWXU) != 0) { + if (unlink(filename) != 0) { + exit(0); + } + if (mkfifo(filename, S_IRWXU) != 0) { + exit(0); + } + } + fd = open(filename, O_RDWR | O_NONBLOCK); + if (fd == -1) { + exit(0); + } + + FD_ZERO(&readFDs); + FD_ZERO(&writeFDs); + FD_ZERO(&exceptFDs); + FD_SET(fd, &readFDs); + numFDs = select(fd + 1, &readFDs, &writeFDs, &exceptFDs, &time); + + close(fd); + unlink(filename); + + /* numFDs is zero if select() works correctly */ + exit(numFD==0); +}" HAVE_BROKEN_FIFO_SELECT) +check_cxx_source_runs(" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(void) +{ + int ikq; + int iRet; + int fd; + struct kevent ke, keChangeList; + struct timespec ts = { 0, 0 }; + + char * filename = NULL; + + filename = (char *)malloc(L_tmpnam * sizeof(char)); /* ok to leak this at exit */ + if (NULL == filename) + { + exit(1); + } + + /* On some platforms (e.g. HP-UX) the multithreading c-runtime does not + support the tmpnam(NULL) semantics, and it returns NULL. Therefore + we need to use the tmpnam(pbuffer) version. + */ + if (NULL == tmpnam(filename)) { + exit(0); + } + if (mkfifo(filename, S_IRWXU) != 0) { + if (unlink(filename) != 0) { + exit(0); + } + if (mkfifo(filename, S_IRWXU) != 0) { + exit(0); + } + } + fd = open(filename, O_RDWR | O_NONBLOCK); + if (fd == -1) { + exit(0); + } + + EV_SET(&keChangeList, fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, NULL); + ikq = kqueue(); + iRet = kevent(ikq, &keChangeList, 1, &ke, 1, &ts); + + close(fd); + unlink(filename); + + /* iRet is zero is kevent() works correctly */ + return(iRet==0); +}" HAVE_BROKEN_FIFO_KEVENT) +set(CMAKE_REQUIRED_LIBRARIES pthread) +check_cxx_source_runs(" +#include +#include +#include +#include + +int main(void) +{ + int policy; + struct sched_param schedParam; + int max_priority; + int min_priority; + + if (0 != pthread_getschedparam(pthread_self(), &policy, &schedParam)) + { + exit(1); + } + + max_priority = sched_get_priority_max(policy); + min_priority = sched_get_priority_min(policy); + + exit(-1 == max_priority || -1 == min_priority); +}" HAVE_SCHED_GET_PRIORITY) +set(CMAKE_REQUIRED_LIBRARIES pthread) +check_cxx_source_runs(" +#include +#include + +int main(void) +{ + if (sched_getcpu() >= 0) + { + exit(0); + } + exit(1); +}" HAVE_SCHED_GETCPU) +set(CMAKE_REQUIRED_LIBRARIES) +check_cxx_source_runs(" +#include +#include +#include + +int main() +{ + int ret; + struct timeval tv; + ret = gettimeofday(&tv, NULL); + + exit(ret); +}" HAVE_WORKING_GETTIMEOFDAY) + +set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_RT_LIBS}) +check_cxx_source_runs(" +#include +#include +#include + +int main() +{ + int ret; + struct timespec ts; + ret = clock_gettime(CLOCK_REALTIME, &ts); + + exit(ret); +}" HAVE_WORKING_CLOCK_GETTIME) +set(CMAKE_REQUIRED_LIBRARIES) + +set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_RT_LIBS}) +check_cxx_source_runs(" +#include +#include +#include + +int main() +{ + int ret; + struct timespec ts; + ret = clock_gettime(CLOCK_MONOTONIC, &ts); + + exit(ret); +}" HAVE_CLOCK_MONOTONIC) +set(CMAKE_REQUIRED_LIBRARIES) + +check_library_exists(${PTHREAD_LIBRARY} pthread_condattr_setclock "" HAVE_PTHREAD_CONDATTR_SETCLOCK) + +set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_RT_LIBS}) +check_cxx_source_runs(" +#include +#include +#include + +int main() +{ + int ret; + struct timespec ts; + ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); + + exit(ret); +}" HAVE_CLOCK_MONOTONIC_COARSE) +set(CMAKE_REQUIRED_LIBRARIES) + +check_cxx_source_runs(" +#include +#include + +int main() +{ + int ret; + mach_timebase_info_data_t timebaseInfo; + ret = mach_timebase_info(&timebaseInfo); + mach_absolute_time(); + exit(ret); +}" HAVE_MACH_ABSOLUTE_TIME) + +set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_RT_LIBS}) +check_cxx_source_runs(" +#include +#include +#include + +int main() +{ + int ret; + struct timespec ts; + ret = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); + + exit(ret); +}" HAVE_CLOCK_THREAD_CPUTIME) +set(CMAKE_REQUIRED_LIBRARIES) + +check_cxx_source_runs(" +#include +#include +#include +#include + +int main(void) { + int devzero; + void *retval; + + devzero = open(\"/dev/zero\", O_RDWR); + if (-1 == devzero) { + exit(1); + } + retval = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, devzero, 0); + if (retval == (void *)-1) { + exit(1); + } + exit(0); +}" HAVE_MMAP_DEV_ZERO) +check_cxx_source_runs(" +#include +#include +#include +#include +#include + +#ifndef MAP_ANON +#define MAP_ANON MAP_ANONYMOUS +#endif + +void *handle_signal(int signal) { + /* If we reach this, we've crashed due to mmap honoring + PROT_NONE. */ + _exit(1); +} + +int main(void) { + int *ptr; + struct sigaction action; + + ptr = (int *) mmap(NULL, getpagesize(), PROT_NONE, + MAP_ANON | MAP_PRIVATE, -1, 0); + if (ptr == (int *) MAP_FAILED) { + exit(0); + } + action.sa_handler = &handle_signal; + action.sa_flags = 0; + sigemptyset(&action.sa_mask); + if (sigaction(SIGBUS, &action, NULL) != 0) { + exit(0); + } + if (sigaction(SIGSEGV, &action, NULL) != 0) { + exit(0); + } + /* This will drop us into the signal handler if PROT_NONE + is honored. */ + *ptr = 123; + exit(0); +}" MMAP_ANON_IGNORES_PROTECTION) +check_cxx_source_runs(" +#include +#include +#include +#include +#include +#include +#include + +#define MEM_SIZE 1024 +#define TEMP_FILE_TEMPLATE \"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/multiplemaptestXXXXXX\" +int main(void) +{ + char * fname; + int fd; + int ret; + void * pAddr0, * pAddr1; + + fname = (char *)malloc(std::max((size_t)MEM_SIZE, sizeof(TEMP_FILE_TEMPLATE))); + if (!fname) + exit(1); + strcpy(fname, TEMP_FILE_TEMPLATE); + + fd = mkstemp(fname); + if (fd < 0) + exit(1); + + ret = write (fd, (void *)fname, MEM_SIZE); + if (ret < 0) + exit(1); + + pAddr0 = mmap(0, MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + pAddr1 = mmap(0, MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + /* In theory we should look for (pAddr1 == MAP_FAILED) && (pAddr1 != MAP_FAILED) + but in case the first test also failed, i.e. we failed to run the test, + let's assume that the system might not allow multiple shared mapping of the + same file region in the same process. The code enabled in this case is + only a fall-back code path. In case the double mmap actually works, virtually + nothing will change and the normal code path will be executed */ + if (pAddr1 == MAP_FAILED) + ret = 1; + else + ret = 0; + + if (pAddr0) + munmap (pAddr0, MEM_SIZE); + if (pAddr1) + munmap (pAddr1, MEM_SIZE); + close(fd); + unlink(fname); + free(fname); + + exit(ret != 1); +}" ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS) +set(CMAKE_REQUIRED_LIBRARIES pthread) +check_cxx_source_runs(" +#include +#include +#include + +void *start_routine(void *param) { return NULL; } + +int main() { + int result; + pthread_t tid; + + errno = 0; + result = pthread_create(&tid, NULL, start_routine, NULL); + if (result != 0) { + exit(1); + } + if (errno != 0) { + exit(0); + } + exit(1); +}" PTHREAD_CREATE_MODIFIES_ERRNO) +set(CMAKE_REQUIRED_LIBRARIES) +set(CMAKE_REQUIRED_LIBRARIES pthread) +check_cxx_source_runs(" +#include +#include +#include + +int main() { + int result; + sem_t sema; + + errno = 50; + result = sem_init(&sema, 0, 0); + if (result != 0) + { + exit(1); + } + if (errno != 50) + { + exit(0); + } + exit(1); +}" SEM_INIT_MODIFIES_ERRNO) +set(CMAKE_REQUIRED_LIBRARIES) +check_cxx_source_runs(" +#include +#include +#include +#include + +int main(void) { + int fd; +#ifdef PATH_MAX + char path[PATH_MAX]; +#elif defined(MAXPATHLEN) + char path[MAXPATHLEN]; +#else + char path[1024]; +#endif + + sprintf(path, \"/proc/%u/ctl\", getpid()); + fd = open(path, O_WRONLY); + if (fd == -1) { + exit(1); + } + exit(0); +}" HAVE_PROCFS_CTL) +set(CMAKE_REQUIRED_LIBRARIES) +check_cxx_source_runs(" +#include +#include +#include +#include + +int main(void) { + int fd; +#ifdef PATH_MAX + char path[PATH_MAX]; +#elif defined(MAXPATHLEN) + char path[MAXPATHLEN]; +#else + char path[1024]; +#endif + + sprintf(path, \"/proc/%u/maps\", getpid()); + fd = open(path, O_RDONLY); + if (fd == -1) { + exit(1); + } + exit(0); +}" HAVE_PROCFS_MAPS) +set(CMAKE_REQUIRED_LIBRARIES) +check_cxx_source_runs(" +#include +#include +#include +#include + +int main(void) { + int fd; +#ifdef PATH_MAX + char path[PATH_MAX]; +#elif defined(MAXPATHLEN) + char path[MAXPATHLEN]; +#else + char path[1024]; +#endif + + sprintf(path, \"/proc/%u/stat\", getpid()); + fd = open(path, O_RDONLY); + if (fd == -1) { + exit(1); + } + exit(0); +}" HAVE_PROCFS_STAT) +set(CMAKE_REQUIRED_LIBRARIES) +check_cxx_source_runs(" +#include +#include +#include +#include + +int main(void) { + int fd; +#ifdef PATH_MAX + char path[PATH_MAX]; +#elif defined(MAXPATHLEN) + char path[MAXPATHLEN]; +#else + char path[1024]; +#endif + + sprintf(path, \"/proc/%u/status\", getpid()); + fd = open(path, O_RDONLY); + if (fd == -1) { + exit(1); + } + exit(0); +}" HAVE_PROCFS_STATUS) +set(CMAKE_REQUIRED_LIBRARIES m) +check_cxx_source_runs(" +#include +#include + +int main(void) { + volatile double x = 10; + if (!isnan(acos(x))) { + exit(1); + } + exit(0); +}" HAVE_COMPATIBLE_ACOS) +set(CMAKE_REQUIRED_LIBRARIES) +set(CMAKE_REQUIRED_LIBRARIES m) +check_cxx_source_runs(" +#include +#include + +int main(void) { + volatile double arg = 10; + if (!isnan(asin(arg))) { + exit(1); + } + exit(0); +}" HAVE_COMPATIBLE_ASIN) +set(CMAKE_REQUIRED_LIBRARIES) +set(CMAKE_REQUIRED_LIBRARIES m) +check_cxx_source_runs(" +#include +#include + +int main(void) { + volatile double base = 1.0; + volatile double infinity = 1.0 / 0.0; + if (pow(base, infinity) != 1.0 || pow(base, -infinity) != 1.0) { + exit(1); + } + if (pow(-base, infinity) != 1.0 || pow(-base, -infinity) != 1.0) { + exit(1); + } + + base = 0.0; + if (pow(base, infinity) != 0.0) { + exit(1); + } + if (pow(base, -infinity) != infinity) { + exit(1); + } + + base = 1.1; + if (pow(-base, infinity) != infinity || pow(base, infinity) != infinity) { + exit(1); + } + if (pow(-base, -infinity) != 0.0 || pow(base, -infinity) != 0.0) { + exit(1); + } + + base = 0.0; + volatile int iexp = 1; + if (pow(-base, -iexp) != -infinity) { + exit(1); + } + if (pow(base, -iexp) != infinity) { + exit(1); + } + exit(0); +}" HAVE_COMPATIBLE_POW) +set(CMAKE_REQUIRED_LIBRARIES) +set(CMAKE_REQUIRED_LIBRARIES m) +check_cxx_source_runs(" +#include +#include + +int main(int argc, char **argv) { + double result; + volatile double base = 3.2e-10; + volatile double exp = 1 - 5e14; + + result = pow(-base, exp); + if (result != -1.0 / 0.0) { + exit(1); + } + exit(0); +}" HAVE_VALID_NEGATIVE_INF_POW) +set(CMAKE_REQUIRED_LIBRARIES) +set(CMAKE_REQUIRED_LIBRARIES m) +check_cxx_source_runs(" +#include +#include + +int main(int argc, char **argv) { + double result; + volatile double base = 3.5; + volatile double exp = 3e100; + + result = pow(-base, exp); + if (result != 1.0 / 0.0) { + exit(1); + } + exit(0); +}" HAVE_VALID_POSITIVE_INF_POW) +set(CMAKE_REQUIRED_LIBRARIES) +set(CMAKE_REQUIRED_LIBRARIES m) +check_cxx_source_runs(" +#include +#include + +int main(void) { + double pi = 3.14159265358979323846; + double result; + volatile double y = 0.0; + volatile double x = 0.0; + + result = atan2(y, -x); + if (fabs(pi - result) > 0.0000001) { + exit(1); + } + + result = atan2(-y, -x); + if (fabs(-pi - result) > 0.0000001) { + exit(1); + } + + result = atan2 (-y, x); + if (result != 0.0 || copysign (1.0, result) > 0) { + exit(1); + } + + result = atan2 (y, x); + if (result != 0.0 || copysign (1.0, result) < 0) { + exit(1); + } + + exit (0); +}" HAVE_COMPATIBLE_ATAN2) +set(CMAKE_REQUIRED_LIBRARIES) +set(CMAKE_REQUIRED_LIBRARIES m) +check_cxx_source_runs(" +#include +#include + +int main(void) { + double d = exp(1.0), e = M_E; + + /* Used memcmp rather than == to test that the doubles are equal to + prevent gcc's optimizer from using its 80 bit internal long + doubles. If you use ==, then on BSD you get a false negative since + exp(1.0) == M_E to 64 bits, but not 80. + */ + + if (memcmp (&d, &e, sizeof (double)) == 0) { + exit(0); + } + exit(1); +}" HAVE_COMPATIBLE_EXP) +set(CMAKE_REQUIRED_LIBRARIES) +set(CMAKE_REQUIRED_LIBRARIES m) +check_cxx_source_runs(" +#include +#include + +int main(void) { + if (FP_ILOGB0 != -2147483648) { + exit(1); + } + + exit(0); +}" HAVE_COMPATIBLE_ILOGB0) +set(CMAKE_REQUIRED_LIBRARIES) +set(CMAKE_REQUIRED_LIBRARIES m) +check_cxx_source_runs(" +#include +#include + +int main(void) { + if (FP_ILOGBNAN != 2147483647) { + exit(1); + } + + exit(0); +}" HAVE_COMPATIBLE_ILOGBNAN) +set(CMAKE_REQUIRED_LIBRARIES) +set(CMAKE_REQUIRED_LIBRARIES m) +check_cxx_source_runs(" +#include +#include + +int main(void) { + volatile int arg = 10000; + if (!isnan(log(-arg))) { + exit(1); + } + exit(0); +}" HAVE_COMPATIBLE_LOG) +set(CMAKE_REQUIRED_LIBRARIES) +set(CMAKE_REQUIRED_LIBRARIES m) +check_cxx_source_runs(" +#include +#include + +int main(void) { + volatile int arg = 10000; + if (!isnan(log10(-arg))) { + exit(1); + } + exit(0); +}" HAVE_COMPATIBLE_LOG10) +set(CMAKE_REQUIRED_LIBRARIES) +check_cxx_source_runs(" +#include +#include +#include + +int main(void) +{ + char* szFileName; + FILE* pFile = NULL; + int ret = 1; + + szFileName = tempnam(\".\", \"tmp\"); + + /* open the file write-only */ + pFile = fopen(szFileName, \"a\"); + if (pFile == NULL) + { + exit(0); + } + if (ungetc('A', pFile) != EOF) + { + ret = 0; + } + unlink(szFileName); + exit(ret); +}" UNGETC_NOT_RETURN_EOF) + +set(CMAKE_REQUIRED_LIBRARIES ${PTHREAD_LIBRARY}) +check_cxx_source_runs(" +#include +#include +#include + +int main() { + sem_t sema; + if (sem_init(&sema, 0, 0) == -1){ + exit(1); + } + exit(0); +}" HAS_POSIX_SEMAPHORES) +set(CMAKE_REQUIRED_LIBRARIES) +check_cxx_source_runs(" +#include +#include +#include +#include +#include + +int main(void) +{ + struct passwd sPasswd; + struct passwd *pPasswd; + char buf[1]; + int bufLen = sizeof(buf)/sizeof(buf[0]); + int euid = geteuid(); + int ret = 0; + + errno = 0; // clear errno + ret = getpwuid_r(euid, &sPasswd, buf, bufLen, &pPasswd); + if (0 != ret) + { + if (ERANGE == errno) + { + return 0; + } + } + + return 1; // assume errno is NOT set for all other cases +}" GETPWUID_R_SETS_ERRNO) +check_cxx_source_runs(" +#include +#include + +int main() +{ + FILE *fp = NULL; + char *fileName = \"/dev/zero\"; + char buf[10]; + + /* + * Open the file in append mode and try to read some text. + * And, make sure ferror() is set. + */ + fp = fopen (fileName, \"a\"); + if ( (NULL == fp) || + (fread (buf, sizeof(buf), 1, fp) > 0) || + (!ferror(fp)) + ) + { + return 0; + } + + /* + * Now that ferror() is set, try to close the file. + * If we get an error, we can conclude that this + * fgets() depended on the previous ferror(). + */ + if ( fclose(fp) != 0 ) + { + return 0; + } + + return 1; +}" FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL) + +set(SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING 1) +set(ERROR_FUNC_FOR_GLOB_HAS_FIXED_PARAMS 1) + +if(NOT CLR_CMAKE_USE_SYSTEM_LIBUNWIND) + list(INSERT CMAKE_REQUIRED_INCLUDES 0 ${CMAKE_CURRENT_SOURCE_DIR}/libunwind/include ${CMAKE_CURRENT_BINARY_DIR}/libunwind/include) +endif() + +set(CMAKE_REQUIRED_FLAGS "-c -Werror=implicit-function-declaration") + +check_c_source_compiles(" +#include +#include +int main(int argc, char **argv) +{ + unw_context_t libUnwindContext; + ucontext_t uContext; + libUnwindContext = uContext; + return 0; +}" UNWIND_CONTEXT_IS_UCONTEXT_T) + +check_c_source_compiles(" +#include + +int main(int argc, char **argv) { + unw_cursor_t cursor; + unw_save_loc_t saveLoc; + int reg = UNW_REG_IP; + unw_get_save_loc(&cursor, reg, &saveLoc); + + return 0; +}" HAVE_UNW_GET_SAVE_LOC) + +check_c_source_compiles(" +#include + +int main(int argc, char **argv) { + unw_addr_space_t as; + unw_get_accessors(as); + + return 0; +}" HAVE_UNW_GET_ACCESSORS) + +set(CMAKE_REQUIRED_FLAGS) +if(NOT CLR_CMAKE_USE_SYSTEM_LIBUNWIND) + list(REMOVE_AT CMAKE_REQUIRED_INCLUDES 0 1) +endif() + +check_cxx_source_compiles(" +#include +#include +#include + +int main(int argc, char **argv) +{ + struct xswdev xsw; + + return 0; +}" HAVE_XSWDEV) + +check_cxx_source_compiles(" +#include +#include + +int main(int argc, char **argv) +{ + struct xsw_usage xsu; + + return 0; +}" HAVE_XSW_USAGE) + +check_cxx_source_compiles(" +#include + +int main(int argc, char **argv) +{ + struct _xstate xstate; + struct _fpx_sw_bytes bytes; + return 0; +}" HAVE_PUBLIC_XSTATE_STRUCT) + +if(HAVE_PUBLIC_XSTATE_STRUCT) + check_struct_has_member ("struct _fpx_sw_bytes" xstate_bv "signal.h" HAVE__FPX_SW_BYTES_WITH_XSTATE_BV) +endif() + +check_cxx_source_compiles(" +#include + +int main(int argc, char **argv) +{ + int flag = (int)PR_SET_PTRACER; + return 0; +}" HAVE_PR_SET_PTRACER) + +set(CMAKE_REQUIRED_LIBRARIES pthread) +check_cxx_source_compiles(" +#include +#include +#include + +int main() +{ + pthread_mutexattr_t mutexAttributes; + pthread_mutexattr_init(&mutexAttributes); + pthread_mutexattr_setpshared(&mutexAttributes, PTHREAD_PROCESS_SHARED); + pthread_mutexattr_settype(&mutexAttributes, PTHREAD_MUTEX_RECURSIVE); + pthread_mutexattr_setrobust(&mutexAttributes, PTHREAD_MUTEX_ROBUST); + + pthread_mutex_t mutex; + pthread_mutex_init(&mutex, &mutexAttributes); + + pthread_mutexattr_destroy(&mutexAttributes); + + struct timespec timeoutTime; + timeoutTime.tv_sec = 1; // not the right way to specify absolute time, but just checking availability of timed lock + timeoutTime.tv_nsec = 0; + pthread_mutex_timedlock(&mutex, &timeoutTime); + pthread_mutex_consistent(&mutex); + + pthread_mutex_destroy(&mutex); + + int error = EOWNERDEAD; + error = ENOTRECOVERABLE; + error = ETIMEDOUT; + error = 0; + return error; +}" HAVE_FULLY_FEATURED_PTHREAD_MUTEXES) +set(CMAKE_REQUIRED_LIBRARIES) + +if(NOT CLR_CMAKE_HOST_ARCH_ARM AND NOT CLR_CMAKE_HOST_ARCH_ARM64) + set(CMAKE_REQUIRED_LIBRARIES pthread) + check_cxx_source_runs(" + // This test case verifies the pthread process-shared robust mutex's cross-process abandon detection. The parent process starts + // a child process that locks the mutex, the process process then waits to acquire the lock, and the child process abandons the + // mutex by exiting the process while holding the lock. The parent process should then be released from its wait, be assigned + // ownership of the lock, and be notified that the mutex was abandoned. + + #include + #include + + #include + #include + #include + #include + + #include + using namespace std; + + struct Shm + { + pthread_mutex_t syncMutex; + pthread_cond_t syncCondition; + pthread_mutex_t robustMutex; + int conditionValue; + + Shm() : conditionValue(0) + { + } + } *shm; + + int GetFailTimeoutTime(struct timespec *timeoutTimeRef) + { + int getTimeResult = clock_gettime(CLOCK_REALTIME, timeoutTimeRef); + if (getTimeResult != 0) + { + struct timeval tv; + getTimeResult = gettimeofday(&tv, NULL); + if (getTimeResult != 0) + return 1; + timeoutTimeRef->tv_sec = tv.tv_sec; + timeoutTimeRef->tv_nsec = tv.tv_usec * 1000; + } + timeoutTimeRef->tv_sec += 30; + return 0; + } + + int WaitForConditionValue(int desiredConditionValue) + { + struct timespec timeoutTime; + if (GetFailTimeoutTime(&timeoutTime) != 0) + return 1; + if (pthread_mutex_timedlock(&shm->syncMutex, &timeoutTime) != 0) + return 1; + + if (shm->conditionValue != desiredConditionValue) + { + if (GetFailTimeoutTime(&timeoutTime) != 0) + return 1; + if (pthread_cond_timedwait(&shm->syncCondition, &shm->syncMutex, &timeoutTime) != 0) + return 1; + if (shm->conditionValue != desiredConditionValue) + return 1; + } + + if (pthread_mutex_unlock(&shm->syncMutex) != 0) + return 1; + return 0; + } + + int SetConditionValue(int newConditionValue) + { + struct timespec timeoutTime; + if (GetFailTimeoutTime(&timeoutTime) != 0) + return 1; + if (pthread_mutex_timedlock(&shm->syncMutex, &timeoutTime) != 0) + return 1; + + shm->conditionValue = newConditionValue; + if (pthread_cond_signal(&shm->syncCondition) != 0) + return 1; + + if (pthread_mutex_unlock(&shm->syncMutex) != 0) + return 1; + return 0; + } + + void DoTest_Child(); + + int DoTest() + { + // Map some shared memory + void *shmBuffer = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); + if (shmBuffer == MAP_FAILED) + return 1; + shm = new(shmBuffer) Shm; + + // Create sync mutex + pthread_mutexattr_t syncMutexAttributes; + if (pthread_mutexattr_init(&syncMutexAttributes) != 0) + return 1; + if (pthread_mutexattr_setpshared(&syncMutexAttributes, PTHREAD_PROCESS_SHARED) != 0) + return 1; + if (pthread_mutex_init(&shm->syncMutex, &syncMutexAttributes) != 0) + return 1; + if (pthread_mutexattr_destroy(&syncMutexAttributes) != 0) + return 1; + + // Create sync condition + pthread_condattr_t syncConditionAttributes; + if (pthread_condattr_init(&syncConditionAttributes) != 0) + return 1; + if (pthread_condattr_setpshared(&syncConditionAttributes, PTHREAD_PROCESS_SHARED) != 0) + return 1; + if (pthread_cond_init(&shm->syncCondition, &syncConditionAttributes) != 0) + return 1; + if (pthread_condattr_destroy(&syncConditionAttributes) != 0) + return 1; + + // Create the robust mutex that will be tested + pthread_mutexattr_t robustMutexAttributes; + if (pthread_mutexattr_init(&robustMutexAttributes) != 0) + return 1; + if (pthread_mutexattr_setpshared(&robustMutexAttributes, PTHREAD_PROCESS_SHARED) != 0) + return 1; + if (pthread_mutexattr_setrobust(&robustMutexAttributes, PTHREAD_MUTEX_ROBUST) != 0) + return 1; + if (pthread_mutex_init(&shm->robustMutex, &robustMutexAttributes) != 0) + return 1; + if (pthread_mutexattr_destroy(&robustMutexAttributes) != 0) + return 1; + + // Start child test process + int error = fork(); + if (error == -1) + return 1; + if (error == 0) + { + DoTest_Child(); + return -1; + } + + // Wait for child to take a lock + WaitForConditionValue(1); + + // Wait to try to take a lock. Meanwhile, child abandons the robust mutex. + struct timespec timeoutTime; + if (GetFailTimeoutTime(&timeoutTime) != 0) + return 1; + error = pthread_mutex_timedlock(&shm->robustMutex, &timeoutTime); + if (error != EOWNERDEAD) // expect to be notified that the robust mutex was abandoned + return 1; + if (pthread_mutex_consistent(&shm->robustMutex) != 0) + return 1; + + if (pthread_mutex_unlock(&shm->robustMutex) != 0) + return 1; + if (pthread_mutex_destroy(&shm->robustMutex) != 0) + return 1; + return 0; + } + + void DoTest_Child() + { + // Lock the robust mutex + struct timespec timeoutTime; + if (GetFailTimeoutTime(&timeoutTime) != 0) + return; + if (pthread_mutex_timedlock(&shm->robustMutex, &timeoutTime) != 0) + return; + + // Notify parent that robust mutex is locked + if (SetConditionValue(1) != 0) + return; + + // Wait a short period to let the parent block on waiting for a lock + sleep(1); + + // Abandon the mutex by exiting the process while holding the lock. Parent's wait should be released by EOWNERDEAD. + } + + int main() + { + int result = DoTest(); + return result >= 0 ? result : 0; + }" HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES) + set(CMAKE_REQUIRED_LIBRARIES) +endif() + +if(CLR_CMAKE_TARGET_OSX) + set(HAVE__NSGETENVIRON 1) + set(DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX 1) + set(PAL_PTRACE "ptrace((cmd), (pid), (caddr_t)(addr), (data))") + set(PAL_PT_ATTACH PT_ATTACH) + set(PAL_PT_DETACH PT_DETACH) + set(PAL_PT_READ_D PT_READ_D) + set(PAL_PT_WRITE_D PT_WRITE_D) + set(HAS_FTRUNCATE_LENGTH_ISSUE 1) + set(HAVE_SCHED_OTHER_ASSIGNABLE 1) + +elseif(CLR_CMAKE_TARGET_FREEBSD) + set(DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX 0) + set(PAL_PTRACE "ptrace((cmd), (pid), (caddr_t)(addr), (data))") + set(PAL_PT_ATTACH PT_ATTACH) + set(PAL_PT_DETACH PT_DETACH) + set(PAL_PT_READ_D PT_READ_D) + set(PAL_PT_WRITE_D PT_WRITE_D) + set(HAS_FTRUNCATE_LENGTH_ISSUE 0) + set(BSD_REGS_STYLE "((reg).r_##rr)") + set(HAVE_SCHED_OTHER_ASSIGNABLE 1) +elseif(CLR_CMAKE_TARGET_NETBSD) + set(DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX 0) + set(PAL_PTRACE "ptrace((cmd), (pid), (void*)(addr), (data))") + set(PAL_PT_ATTACH PT_ATTACH) + set(PAL_PT_DETACH PT_DETACH) + set(PAL_PT_READ_D PT_READ_D) + set(PAL_PT_WRITE_D PT_WRITE_D) + set(HAS_FTRUNCATE_LENGTH_ISSUE 0) + set(BSD_REGS_STYLE "((reg).regs[_REG_##RR])") + set(HAVE_SCHED_OTHER_ASSIGNABLE 0) + +elseif(CLR_CMAKE_TARGET_SUNOS) + set(DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX 0) + set(PAL_PTRACE "ptrace((cmd), (pid), (caddr_t)(addr), (data))") + set(PAL_PT_ATTACH PT_ATTACH) + set(PAL_PT_DETACH PT_DETACH) + set(PAL_PT_READ_D PT_READ_D) + set(PAL_PT_WRITE_D PT_WRITE_D) + set(HAS_FTRUNCATE_LENGTH_ISSUE 0) +else() # Anything else is Linux + if(NOT HAVE_LTTNG_TRACEPOINT_H AND FEATURE_EVENT_TRACE) + unset(HAVE_LTTNG_TRACEPOINT_H CACHE) + message(FATAL_ERROR "Cannot find liblttng-ust-dev. Try installing liblttng-ust-dev (or the appropriate packages for your platform)") + endif() + set(DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX 0) + set(PAL_PTRACE "ptrace((cmd), (pid), (void*)(addr), (data))") + set(PAL_PT_ATTACH PTRACE_ATTACH) + set(PAL_PT_DETACH PTRACE_DETACH) + set(PAL_PT_READ_D PTRACE_PEEKDATA) + set(PAL_PT_WRITE_D PTRACE_POKEDATA) + set(HAS_FTRUNCATE_LENGTH_ISSUE 0) + set(HAVE_SCHED_OTHER_ASSIGNABLE 1) +endif(CLR_CMAKE_TARGET_OSX) + +check_struct_has_member( + "struct statfs" + f_fstypename + "sys/mount.h" + HAVE_STATFS_FSTYPENAME) + +check_struct_has_member( + "struct statvfs" + f_fstypename + "sys/mount.h" + HAVE_STATVFS_FSTYPENAME) + +# statfs: Find whether this struct exists +if (HAVE_STATFS_FSTYPENAME OR HAVE_STATVFS_FSTYPENAME) + set (STATFS_INCLUDES sys/mount.h) +else () + set (STATFS_INCLUDES sys/statfs.h) +endif () + +check_prototype_definition( + statfs + "int statfs(const char *path, struct statfs *buf)" + 0 + ${STATFS_INCLUDES} + HAVE_NON_LEGACY_STATFS) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/file.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/file.cpp new file mode 100644 index 0000000..e481d43 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/file.cpp @@ -0,0 +1,725 @@ +// 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: + + file.c + +Abstract: + + Implementation of the file functions in the C runtime library that + are Windows specific. + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/file.h" +#include "pal/cruntime.h" + +#include "pal/thread.hpp" +#include "pal/threadsusp.hpp" + +#include +#include +#include +#include + +#if FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL + #define CLEARERR(f) clearerr((f)->bsdFilePtr) +#else + #define CLEARERR(f) +#endif + +SET_DEFAULT_DEBUG_CHANNEL(CRT); + +/* Global variables storing the std streams.*/ +PAL_FILE PAL_Stdout; +PAL_FILE PAL_Stdin; +PAL_FILE PAL_Stderr; + +/*++ + +Function: + + CRTInitStdStreams. + + Initilizes the standard streams. + Returns TRUE on success, FALSE otherwise. +--*/ +BOOL CRTInitStdStreams() +{ + /* stdout */ + PAL_Stdout.bsdFilePtr = stdout; + PAL_Stdout.PALferrorCode = PAL_FILE_NOERROR; + PAL_Stdout.bTextMode = TRUE; + + /* stdin */ + PAL_Stdin.bsdFilePtr = stdin; + PAL_Stdin.PALferrorCode = PAL_FILE_NOERROR; + PAL_Stdin.bTextMode = TRUE; + + /* stderr */ + PAL_Stderr.bsdFilePtr = stderr; + PAL_Stderr.PALferrorCode = PAL_FILE_NOERROR; + PAL_Stderr.bTextMode = TRUE; + return TRUE; +} + +/*++ +Function : + + MapFileOpenModes + + Maps Windows file open modes to Unix fopen modes and validates. + +--*/ +static LPSTR MapFileOpenModes(LPSTR str , BOOL * bTextMode) +{ + LPSTR retval = NULL; + LPSTR temp = NULL; + + if (NULL == bTextMode) + { + ASSERT("MapFileOpenModes called with a NULL parameter for bTextMode.\n"); + return NULL; + } + + *bTextMode = TRUE; + + if (NULL == str) + { + ASSERT("MapFileOpenModes called with a NULL parameter for str.\n"); + return NULL; + } + + /* The PAL behaves differently for some Windows file open modes: + + c, n, S, R, and T: these are all hints to the system that aren't supported + by the PAL. Since the user cannot depend on this behavior, it's safe to + simply ignore these modes. + + D: specifies a file as temporary. This file is expected to be deleted when + the last file descriptor is closed. The PAL does not support this behavior + and asserts when this mode is used. + + t: represents opening in text mode. Calls to fdopen on Unix don't accept + 't' so it is silently stripped out. However, the PAL supports the mode by + having the PAL wrappers do the translation of CR-LF to LF and vice versa. + + t vs. b: To get binary mode, you must explicitly use 'b'. If neither mode + is specified on Windows, the default mode is defined by the global + variable _fmode. The PAL simply defaults to text mode. After examining + CLR usage patterns, the PAL behavior seems acceptable. */ + + /* Check if the mode specifies deleting the temporary file + automatically when the last file descriptor is closed. + The PAL does not support this behavior. */ + if (NULL != strchr(str,'D')) + { + ASSERT("The PAL doesn't support the 'D' flag for _fdopen and fopen.\n"); + return NULL; + } + + /* Check if the mode specifies opening in binary. + If so, set the bTextMode to false. */ + if(NULL != strchr(str,'b')) + { + *bTextMode = FALSE; + } + + retval = (LPSTR)PAL_malloc( ( strlen( str ) + 1 ) * sizeof( CHAR ) ); + if (NULL == retval) + { + ERROR("Unable to allocate memory.\n"); + return NULL; + } + + temp = retval; + while ( *str ) + { + if ( *str == 'r' || *str == 'w' || *str == 'a' ) + { + *temp = *str; + temp++; + if ( ( ++str != NULL ) && *str == '+' ) + { + *temp = *str; + temp++; + str++; + } + } + else + { + str++; + } + } + *temp = '\0'; + return retval; +} + +#if UNGETC_NOT_RETURN_EOF +/*++ +Function : + + WriteOnlyMode + + Returns TRUE to if a file is opened in write-only mode, + Otherwise FALSE. + +--*/ +static BOOL WriteOnlyMode(FILE* pFile) +{ + INT fd, flags; + + if (pFile != NULL) + { + fd = fileno(pFile); + if ((flags = fcntl(fd, F_GETFL)) >= 0) + { + if ((flags & O_ACCMODE) == O_WRONLY) + { + return TRUE; + } + } + } + return FALSE; +} +#endif //UNGETC_NOT_RETURN_EOF + +/*++ +Function: + _fdopen + +see MSDN + +--*/ +PAL_FILE * +__cdecl +_fdopen( + int handle, + const char *mode) +{ + PAL_FILE *f = NULL; + LPSTR supported = NULL; + BOOL bTextMode = TRUE; + + PERF_ENTRY(_fdopen); + ENTRY("_fdopen (handle=%d mode=%p (%s))\n", handle, mode, mode); + + _ASSERTE(mode != NULL); + + f = (PAL_FILE*)PAL_malloc( sizeof( PAL_FILE ) ); + if ( f ) + { + supported = MapFileOpenModes( (char*)mode , &bTextMode); + if ( !supported ) + { + PAL_free(f); + f = NULL; + goto EXIT; + } + + f->bsdFilePtr = (FILE *)fdopen( handle, supported ); + f->PALferrorCode = PAL_FILE_NOERROR; + /* Make sure fdopen did not fail. */ + if ( !f->bsdFilePtr ) + { + PAL_free( f ); + f = NULL; + } + + PAL_free( supported ); + supported = NULL; + } + else + { + ERROR( "Unable to allocate memory for the PAL_FILE wrapper!\n" ); + } + +EXIT: + LOGEXIT( "_fdopen returns FILE* %p\n", f ); + PERF_EXIT(_fdopen); + return f; +} + + +/*++ + +Function : + fopen + +see MSDN doc. + +--*/ +PAL_FILE * +__cdecl +PAL_fopen(const char * fileName, const char * mode) +{ + PAL_FILE *f = NULL; + LPSTR supported = NULL; + LPSTR UnixFileName = NULL; + struct stat stat_data; + BOOL bTextMode = TRUE; + + PERF_ENTRY(fopen); + ENTRY("fopen ( fileName=%p (%s) mode=%p (%s))\n", fileName, fileName, mode , mode ); + + _ASSERTE(fileName != NULL); + _ASSERTE(mode != NULL); + + if ( *mode == 'r' || *mode == 'w' || *mode == 'a' ) + { + supported = MapFileOpenModes( (char*)mode,&bTextMode); + + if ( !supported ) + { + goto done; + } + + UnixFileName = PAL__strdup(fileName); + if (UnixFileName == NULL ) + { + ERROR("PAL__strdup() failed\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + + FILEDosToUnixPathA( UnixFileName ); + + /*I am not checking for the case where stat fails + *as fopen will handle the error more gracefully in case + *UnixFileName is invalid*/ + if ((stat(UnixFileName, &stat_data) == 0 ) && + ((stat_data.st_mode & S_IFMT) == S_IFDIR)) + { + goto done; + } + + f = (PAL_FILE*)PAL_malloc( sizeof( PAL_FILE ) ); + if ( f ) + { + f->bsdFilePtr = (FILE*)fopen( UnixFileName, supported ); + f->PALferrorCode = PAL_FILE_NOERROR; + f->bTextMode = bTextMode; + if ( !f->bsdFilePtr ) + { + /* Failed */ + PAL_free( f ); + f = NULL; + } +#if UNGETC_NOT_RETURN_EOF + else + { + f->bWriteOnlyMode = WriteOnlyMode(f->bsdFilePtr); + } +#endif //UNGETC_NOT_RETURN_EOF + } + else + { + ERROR( "Unable to allocate memory to the PAL_FILE wrapper\n" ); + } + } + else + { + ERROR( "The mode flags must start with either an a, w, or r.\n" ); + } + +done: + PAL_free( supported ); + supported = NULL; + PAL_free( UnixFileName ); + + LOGEXIT( "fopen returns FILE* %p\n", f ); + PERF_EXIT(fopen); + return f; +} + +/*++ +Function: + _wfopen + +see MSDN doc. + +--*/ +PAL_FILE * +__cdecl +_wfopen( + const wchar_16 *fileName, + const wchar_16 *mode) +{ + CHAR mbFileName[ _MAX_PATH ]; + CHAR mbMode[ 10 ]; + PAL_FILE * filePtr = NULL; + + PERF_ENTRY(_wfopen); + ENTRY("_wfopen(fileName:%p (%S), mode:%p (%S))\n", fileName, fileName, mode, mode); + + _ASSERTE(fileName != NULL); + _ASSERTE(mode != NULL); + + /* Convert the parameters to ASCII and defer to PAL_fopen */ + if ( WideCharToMultiByte( CP_ACP, 0, fileName, -1, mbFileName, + sizeof mbFileName, NULL, NULL ) != 0 ) + { + if ( WideCharToMultiByte( CP_ACP, 0, mode, -1, mbMode, + sizeof mbMode, NULL, NULL ) != 0 ) + { + filePtr = PAL_fopen(mbFileName, mbMode); + } + else + { + ERROR( "An error occurred while converting mode to ANSI.\n" ); + } + } + else + { + ERROR( "An error occurred while converting" + " fileName to ANSI string.\n" ); + } + LOGEXIT("_wfopen returning FILE* %p\n", filePtr); + PERF_EXIT(_wfopen); + return filePtr; +} + +/*++ +Function + PAL_get_stdout. + + Returns the stdout stream. +--*/ +PAL_FILE * __cdecl PAL_get_stdout(int caller) +{ + PERF_ENTRY(get_stdout); + ENTRY("PAL_get_stdout\n"); + LOGEXIT("PAL_get_stdout returns PAL_FILE * %p\n", &PAL_Stdout ); + PERF_EXIT(get_stdout); + return &PAL_Stdout; +} + +/*++ +Function + PAL_get_stdin. + + Returns the stdin stream. +--*/ +PAL_FILE * __cdecl PAL_get_stdin(int caller) +{ + PERF_ENTRY(get_stdin); + ENTRY("PAL_get_stdin\n"); + LOGEXIT("PAL_get_stdin returns PAL_FILE * %p\n", &PAL_Stdin ); + PERF_EXIT(get_stdin); + return &PAL_Stdin; +} + +/*++ +Function + PAL_get_stderr. + + Returns the stderr stream. +--*/ +PAL_FILE * __cdecl PAL_get_stderr(int caller) +{ + PERF_ENTRY(get_stderr); + ENTRY("PAL_get_stderr\n"); + LOGEXIT("PAL_get_stderr returns PAL_FILE * %p\n", &PAL_Stderr ); + PERF_EXIT(get_stderr); + return &PAL_Stderr; +} + +/*++ + +Function: + + PAL_pread + +See msdn for more details. +--*/ +size_t __cdecl PAL__pread(int fd, void *buf, size_t nbytes, ULONG64 offset) +{ + return pread(fd, buf, nbytes, offset); +} + +/*++ + +Function: + + _close + +See msdn for more details. +--*/ +int __cdecl PAL__close(int handle) +{ + INT nRetVal = 0; + + PERF_ENTRY(_close); + ENTRY( "_close( handle=%d )\n", handle ); + + nRetVal = close( handle ); + + LOGEXIT( "_close returning %d.\n", nRetVal ); + PERF_EXIT(_close); + return nRetVal; +} + +int __cdecl PAL__flushall() +{ + return fflush(NULL); +} + +int __cdecl PAL_getc(PAL_FILE *stream); + +/*++ +Function : + + fread + + See MSDN for more details. +--*/ + +size_t +__cdecl +PAL_fread(void * buffer, size_t size, size_t count, PAL_FILE * f) +{ + size_t nReadBytes = 0; + + PERF_ENTRY(fread); + ENTRY( "fread( buffer=%p, size=%d, count=%d, f=%p )\n", + buffer, size, count, f ); + + _ASSERTE(f != NULL); + + CLEARERR(f); + + if(f->bTextMode != TRUE) + { + nReadBytes = fread( buffer, size, count, f->bsdFilePtr ); + } + else + { + size_t i=0; + if(size > 0) + { + size_t j=0; + LPSTR temp = (LPSTR)buffer; + int nChar = 0; + int nCount =0; + + for(i=0; i< count; i++) + { + for(j=0; j< size; j++) + { + if((nChar = PAL_getc(f)) == EOF) + { + nReadBytes = i; + goto done; + } + else + { + temp[nCount++]=nChar; + } + } + } + } + nReadBytes = i; + } + +done: + LOGEXIT( "fread returning size_t %d\n", nReadBytes ); + PERF_EXIT(fread); + return nReadBytes; +} + + +/*++ +Function : + + ferror + + See MSDN for more details. +--*/ +int +_cdecl +PAL_ferror(PAL_FILE * f) +{ + INT nErrorCode = PAL_FILE_NOERROR; + + PERF_ENTRY(ferror); + ENTRY( "ferror( f=%p )\n", f ); + + _ASSERTE(f != NULL); + + nErrorCode = ferror( f->bsdFilePtr ); + if ( 0 == nErrorCode ) + { + /* See if the PAL file error code is set. */ + nErrorCode = f->PALferrorCode; + } + + LOGEXIT( "ferror returns %d\n", nErrorCode ); + PERF_EXIT(ferror); + return nErrorCode; +} + + +/*++ +Function : + + fclose + + See MSDN for more details. +--*/ +int +_cdecl +PAL_fclose(PAL_FILE * f) +{ + INT nRetVal = 0; + + PERF_ENTRY(fclose); + ENTRY( "fclose( f=%p )\n", f ); + + _ASSERTE(f != NULL); + + CLEARERR(f); + + nRetVal = fclose( f->bsdFilePtr ); + PAL_free( f ); + + LOGEXIT( "fclose returning %d\n", nRetVal ); + PERF_EXIT(fclose); + return nRetVal; +} + +/*++ +Function : + + fputs + + See MSDN for more details. +--*/ +int +_cdecl +PAL_fputs(const char * str, PAL_FILE * f) +{ + INT nRetVal = 0; + + PERF_ENTRY(fputs); + ENTRY( "fputs( %p (%s), %p )\n", str, str, f); + + _ASSERTE(str != NULL); + _ASSERTE(f != NULL); + + CLEARERR(f); + + nRetVal = fputs( str, f->bsdFilePtr ); + + LOGEXIT( "fputs returning %d\n", nRetVal ); + PERF_EXIT(fputs); + return nRetVal; +} + +/*++ +Function : + + ftell + + See MSDN for more details. +--*/ +LONG +_cdecl +PAL_ftell(PAL_FILE * f) +{ + long lRetVal = 0; + + PERF_ENTRY(ftell); + ENTRY( "ftell( %p )\n", f ); + + _ASSERTE(f != NULL); + lRetVal = ftell( f->bsdFilePtr ); + +#ifdef HOST_64BIT + /* Windows does not set an error if the file pointer's position + is greater than _I32_MAX. It just returns -1. */ + if (lRetVal > _I32_MAX) + { + lRetVal = -1; + } +#endif + + LOGEXIT( "ftell returning %ld\n", lRetVal ); + PERF_EXIT(ftell); + /* This explicit cast to LONG is used to silence any potential warnings + due to implicitly casting the native long lRetVal to LONG when returning. */ + return (LONG)lRetVal; +} + +/*++ +Function : + getc + + See MSDN for more details. +--*/ +int +_cdecl +PAL_getc(PAL_FILE * f) +{ + INT nRetVal = 0; + INT temp =0; + + PERF_ENTRY(getc); + ENTRY( "getc( %p )\n", f ); + + _ASSERTE(f != NULL); + + CLEARERR(f); + + nRetVal = getc( f->bsdFilePtr ); + + if ( (f->bTextMode) && (nRetVal == '\r') ) + { + if ((temp = getc( f->bsdFilePtr ))== '\n') + { + nRetVal ='\n'; + } + else if (EOF == ungetc( temp, f->bsdFilePtr )) + { + ERROR("ungetc operation failed\n"); + } + } + + LOGEXIT( "getc returning %d\n", nRetVal ); + PERF_EXIT(getc); + return nRetVal; +} + +/*++ +Function : + + setvbuf + + See MSDN for more details. +--*/ +int +_cdecl +PAL_setvbuf(PAL_FILE *f, char *buf, int type, size_t size) +{ + INT nRetVal = 0; + + PERF_ENTRY(setvbuf); + ENTRY( "setvbuf( %p, %p, %d, %ul )\n", f, buf, type, size); + + _ASSERTE(f != NULL); + + nRetVal = setvbuf(f->bsdFilePtr, buf, type, size); + + LOGEXIT( "setvbuf returning %d\n", nRetVal ); + PERF_EXIT(setvbuf); + return nRetVal; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/filecrt.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/filecrt.cpp new file mode 100644 index 0000000..3875a08 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/filecrt.cpp @@ -0,0 +1,475 @@ +// 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: + + filecrt.cpp + +Abstract: + + Implementation of the file functions in the C runtime library that + are Windows specific. + + + +--*/ + +#include "pal/thread.hpp" +#include "pal/file.hpp" + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/file.h" +#include "pal/cruntime.h" + +#include +#include +#include + +#ifdef __APPLE__ +#include +#endif // __APPLE__ + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(CRT); + +/*++ +Function: + _open_osfhandle + +See MSDN doc. +--*/ +int +__cdecl +_open_osfhandle( INT_PTR osfhandle, int flags ) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pthrCurrent = NULL; + IPalObject *pobjFile = NULL; + CFileProcessLocalData *pLocalData = NULL; + IDataLock *pDataLock = NULL; + INT nRetVal = -1; + INT openFlags = 0; + + PERF_ENTRY(_open_osfhandle); + ENTRY( "_open_osfhandle (osfhandle=%#x, flags=%#x)\n", osfhandle, flags ); + + pthrCurrent = InternalGetCurrentThread(); + + if (flags != _O_RDONLY) + { + ASSERT("flag(%#x) not supported\n", flags); + goto EXIT; + } + + openFlags |= O_RDONLY; + + palError = g_pObjectManager->ReferenceObjectByHandle( + pthrCurrent, + reinterpret_cast(osfhandle), + &aotFile, + &pobjFile + ); + + if (NO_ERROR != palError) + { + ERROR("Error dereferencing file handle\n"); + goto EXIT; + } + + palError = pobjFile->GetProcessLocalData( + pthrCurrent, + ReadLock, + &pDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR == palError) + { + if (NULL != pLocalData->unix_filename) + { + nRetVal = InternalOpen(pLocalData->unix_filename, openFlags); + } + else /* the only file object with no unix_filename is a pipe */ + { + /* check if the file pipe descrptor is for read or write */ + if (pLocalData->open_flags == O_WRONLY) + { + ERROR( "Couldn't open a write pipe on read mode\n"); + goto EXIT; + } + + nRetVal = pLocalData->unix_fd; + } + + if ( nRetVal == -1 ) + { + ERROR( "Error: %s.\n", strerror( errno ) ); + } + } + else + { + ASSERT("Unable to access file data"); + } + +EXIT: + + if (NULL != pDataLock) + { + pDataLock->ReleaseLock(pthrCurrent, FALSE); + } + + if (NULL != pobjFile) + { + pobjFile->ReleaseReference(pthrCurrent); + } + + LOGEXIT( "_open_osfhandle return nRetVal:%d\n", nRetVal); + PERF_EXIT(_open_osfhandle); + return nRetVal; +} + + +/*++ +Function: + PAL_fflush + +See MSDN for more details. +--*/ +int +_cdecl +PAL_fflush( PAL_FILE *stream ) +{ + int nRetVal = 0; + + PERF_ENTRY(fflush); + ENTRY( "fflush( %p )\n", stream ); + + nRetVal = fflush(stream ? stream->bsdFilePtr : NULL); + + LOGEXIT( "fflush returning %d\n", nRetVal ); + PERF_EXIT(fflush); + return nRetVal; +} + + +/*++ +PAL__open + +Wrapper function for InternalOpen. + +Input parameters: + +szPath = pointer to a pathname of a file to be opened +nFlags = arguments that control how the file should be accessed +mode = file permission settings that are used only when a file is created + +Return value: + File descriptor on success, -1 on failure +--*/ +int +__cdecl +PAL__open( + const char *szPath, + int nFlags, + ... + ) +{ + int nRet = -1; + int mode = 0; + va_list ap; + + // If nFlags does not contain O_CREAT, the mode parameter will be ignored. + if (nFlags & O_CREAT) + { + va_start(ap, nFlags); + mode = va_arg(ap, int); + va_end(ap); + } + + nRet = InternalOpen(szPath, nFlags, mode); + return nRet; +} + +/*++ +InternalOpen + +Wrapper for open. + +Input parameters: + +szPath = pointer to a pathname of a file to be opened +nFlags = arguments that control how the file should be accessed +mode = file permission settings that are used only when a file is created + +Return value: + File descriptor on success, -1 on failure +--*/ +int +CorUnix::InternalOpen( + const char *szPath, + int nFlags, + ... + ) +{ + int nRet = -1; + int mode = 0; + va_list ap; + + // If nFlags does not contain O_CREAT, the mode parameter will be ignored. + if (nFlags & O_CREAT) + { + va_start(ap, nFlags); + mode = va_arg(ap, int); + va_end(ap); + } + +#if OPEN64_IS_USED_INSTEAD_OF_OPEN + nRet = open64(szPath, nFlags, mode); +#else + nRet = open(szPath, nFlags, mode); +#endif + return nRet; +} + + +/*++ +PAL_fgets + +Wrapper function for InternalFgets. + +Input parameters: + +sz = stores characters read from the given file stream +nSize = number of characters to be read +pf = stream to read characters from + +Return value: + Returns a pointer to the string storing the characters on success + and NULL on failure. +--*/ +char * +__cdecl +PAL_fgets( + char *sz, + int nSize, + PAL_FILE *pf + ) +{ + char * szBuf; + + PERF_ENTRY(fgets); + ENTRY( "fgets(sz=%p (%s) nSize=%d pf=%p)\n", sz, sz, nSize, pf); + + if (pf != NULL) + { + szBuf = InternalFgets(sz, nSize, pf->bsdFilePtr, pf->bTextMode); + } + else + { + szBuf = NULL; + } + + LOGEXIT("fgets() returns %p\n", szBuf); + PERF_EXIT(fgets); + + return szBuf; +} + +/*++ +InternalFgets + +Wrapper for fgets. + +Input parameters: + +sz = stores characters read from the given file stream +nSize = number of characters to be read +f = stream to read characters from +fTextMode = flag that indicates if file contents are text or binary + +Return value: + Returns a pointer to the string storing the characters on success + and NULL on failure. + +Notes: +In Unix systems, fgets() can return an error if it gets interrupted by a +signal before reading anything, and errno is set to EINTR. When this +happens, it is SOP to call fgets again. +--*/ +char * +CorUnix::InternalFgets( + char *sz, + int nSize, + FILE *f, + bool fTextMode + ) +{ + char *retval = NULL; + + _ASSERTE(sz != NULL); + _ASSERTE(f != NULL); + +#if FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL + clearerr(f); +#endif + + do + { + retval = fgets(sz, nSize, f); + if (NULL==retval) + { + if (feof(f)) + { + TRACE("Reached EOF\n"); + break; + } + /* The man page suggests using ferror and feof to distinguish + between error and EOF, but feof and errno is sufficient. + Not all cases that set errno also flag ferror, so just + checking errno is the best solution. */ + if (EINTR != errno) + { + WARN("got error; errno is %d (%s)\n",errno, strerror(errno)); + break; + } + /* we ignored a EINTR error, reset the stream's error state */ + clearerr(f); + TRACE("call got interrupted (EINTR), trying again\n"); + } + if (fTextMode) + { + int len = strlen(sz); + if ((len>=2) && (sz[len-1]=='\n') && (sz[len-2]=='\r')) + { + sz[len-2]='\n'; + sz[len-1]='\0'; + } + } + } while(NULL == retval); + + return retval; +} + +/*++ +PAL_fwrite + +Wrapper function for InternalFwrite. + +Input parameters: + +pvBuffer = array of objects to write to the given file stream +nSize = size of a object in bytes +nCount = number of objects to write +pf = stream to write characters to + +Return value: + Returns the number of objects written. +--*/ +size_t +__cdecl +PAL_fwrite( + const void *pvBuffer, + size_t nSize, + size_t nCount, + PAL_FILE *pf + ) +{ + size_t nWrittenBytes = 0; + + PERF_ENTRY(fwrite); + ENTRY( "fwrite( pvBuffer=%p, nSize=%d, nCount=%d, pf=%p )\n", + pvBuffer, nSize, nCount, pf); + _ASSERTE(pf != NULL); + + nWrittenBytes = InternalFwrite(pvBuffer, nSize, nCount, pf->bsdFilePtr, &pf->PALferrorCode); + + LOGEXIT( "fwrite returning size_t %d\n", nWrittenBytes ); + PERF_EXIT(fwrite); + return nWrittenBytes; +} + +/*++ +InternalFwrite + +Wrapper for fwrite. + +Input parameters: + +pvBuffer = array of objects to write to the given file stream +nSize = size of a object in bytes +nCount = number of objects to write +f = stream to write characters to +pnErrorCode = reference to a PAL_FILE's fwrite error code field + +Return value: + Returns the number of objects written. +--*/ +size_t +CorUnix::InternalFwrite( + const void *pvBuffer, + size_t nSize, + size_t nCount, + FILE *f, + INT *pnErrorCode + ) +{ + size_t nWrittenBytes = 0; + _ASSERTE(f != NULL); + +#if FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL + clearerr(f); +#endif + + nWrittenBytes = fwrite(pvBuffer, nSize, nCount, f); + + // Make sure no error ocurred. + if ( nWrittenBytes < nCount ) + { + // Set the FILE* error code + *pnErrorCode = PAL_FILE_ERROR; + } + + return nWrittenBytes; +} + + +/*++ +PAL_fseek + +Wrapper function for fseek. + +Input parameters: + +pf = a given file stream +lOffset = distance from position to set file-position indicator +nWhence = method used to determine the file_position indicator location relative to lOffset + +Return value: + 0 on success, -1 on failure. +--*/ +int +_cdecl +PAL_fseek( + PAL_FILE * pf, + LONG lOffset, + int nWhence + ) +{ + int nRet = 0; + + PERF_ENTRY(fseek); + ENTRY( "fseek( %p, %ld, %d )\n", pf, lOffset, nWhence ); + + nRet = fseek(pf ? pf->bsdFilePtr : NULL, lOffset, nWhence); + + LOGEXIT("fseek returning %d\n", nRet); + PERF_EXIT(fseek); + return nRet; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/malloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/malloc.cpp new file mode 100644 index 0000000..4f0979d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/malloc.cpp @@ -0,0 +1,116 @@ +// 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: + + malloc.cpp + +Abstract: + + Implementation of suspension safe memory allocation functions. + +Revision History: + + + +--*/ + +#include "pal/corunix.hpp" +#include "pal/thread.hpp" +#include "pal/malloc.hpp" +#include "pal/dbgmsg.h" + +#include + +SET_DEFAULT_DEBUG_CHANNEL(CRT); + +using namespace CorUnix; + +void * +__cdecl +PAL_realloc( + void* pvMemblock, + size_t szSize + ) +{ + return InternalRealloc(pvMemblock, szSize); +} + +void * +CorUnix::InternalRealloc( + void* pvMemblock, + size_t szSize + ) +{ + void *pvMem; + + PERF_ENTRY(InternalRealloc); + ENTRY("realloc (memblock:%p size=%d)\n", pvMemblock, szSize); + + if (szSize == 0) + { + // If pvMemblock is NULL, there's no reason to call free. + if (pvMemblock != NULL) + { + free(pvMemblock); + } + pvMem = NULL; + } + else + { + pvMem = realloc(pvMemblock, szSize); + } + + LOGEXIT("realloc returns void * %p\n", pvMem); + PERF_EXIT(InternalRealloc); + return pvMem; +} + +void +__cdecl +PAL_free( + void *pvMem + ) +{ + free(pvMem); +} + +void * +__cdecl +PAL_malloc( + size_t szSize + ) +{ + return InternalMalloc(szSize); +} + +void * +CorUnix::InternalMalloc( + size_t szSize + ) +{ + void *pvMem; + + if (szSize == 0) + { + // malloc may return null for a requested size of zero bytes. Force a nonzero size to get a valid pointer. + szSize = 1; + } + + pvMem = (void*)malloc(szSize); + return pvMem; +} + +char * +__cdecl +PAL__strdup( + const char *c_szStr + ) +{ + return strdup(c_szStr); +} \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/math.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/math.cpp new file mode 100644 index 0000000..aa6c024 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/math.cpp @@ -0,0 +1,1009 @@ +// 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: + + math.cpp + +Abstract: + + Implementation of math family functions. + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" + +#include + +#if HAVE_IEEEFP_H +#include +#endif // HAVE_IEEEFP_H + +#include + +#define PAL_NAN_DBL sqrt(-1.0) +#define PAL_POSINF_DBL -log(0.0) +#define PAL_NEGINF_DBL log(0.0) + +#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); + +/*++ +Function: + _finite + +Determines whether given double-precision floating point value is finite. + +Return Value + +_finite 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 Double-precision floating-point value + +--*/ +int __cdecl _finite(double x) +{ + int ret; + PERF_ENTRY(_finite); + ENTRY("_finite (x=%f)\n", x); + + ret = isfinite(x); + + LOGEXIT("_finite returns int %d\n", ret); + PERF_EXIT(_finite); + return ret; +} + +/*++ +Function: + _isnan + +See MSDN doc +--*/ +int __cdecl _isnan(double x) +{ + int ret; + PERF_ENTRY(_isnan); + ENTRY("_isnan (x=%f)\n", x); + + ret = isnan(x); + + LOGEXIT("_isnan returns int %d\n", ret); + PERF_EXIT(_isnan); + return ret; +} + +/*++ +Function: + _copysign + +See MSDN doc +--*/ +double __cdecl _copysign(double x, double y) +{ + double ret; + PERF_ENTRY(_copysign); + ENTRY("_copysign (x=%f, y=%f)\n", x, y); + + ret = copysign(x, y); + + LOGEXIT("_copysign returns double %f\n", ret); + PERF_EXIT(_copysign); + return ret; +} + +/*++ +Function: + acos + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_acos(double x) +{ + double ret; + PERF_ENTRY(acos); + ENTRY("acos (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_ACOS + errno = 0; +#endif // HAVE_COMPATIBLE_ACOS + + ret = acos(x); + +#if !HAVE_COMPATIBLE_ACOS + if (errno == EDOM) + { + ret = PAL_NAN_DBL; // NaN + } +#endif // HAVE_COMPATIBLE_ACOS + + LOGEXIT("acos returns double %f\n", ret); + PERF_EXIT(acos); + return ret; +} + +/*++ +Function: + acosh + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_acosh(double x) +{ + double ret; + PERF_ENTRY(acosh); + ENTRY("acosh (x=%f)\n", x); + + ret = acosh(x); + + LOGEXIT("acosh returns double %f\n", ret); + PERF_EXIT(acosh); + return ret; +} + +/*++ +Function: + asin + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_asin(double x) +{ + double ret; + PERF_ENTRY(asin); + ENTRY("asin (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_ASIN + errno = 0; +#endif // HAVE_COMPATIBLE_ASIN + + ret = asin(x); + +#if !HAVE_COMPATIBLE_ASIN + if (errno == EDOM) + { + ret = PAL_NAN_DBL; // NaN + } +#endif // HAVE_COMPATIBLE_ASIN + + LOGEXIT("asin returns double %f\n", ret); + PERF_EXIT(asin); + return ret; +} + +/*++ +Function: + asinh + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_asinh(double x) +{ + double ret; + PERF_ENTRY(asinh); + ENTRY("asinh (x=%f)\n", x); + + ret = asinh(x); + + LOGEXIT("asinh returns double %f\n", ret); + PERF_EXIT(asinh); + return ret; +} + +/*++ +Function: + atan2 + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_atan2(double y, double x) +{ + double ret; + PERF_ENTRY(atan2); + ENTRY("atan2 (y=%f, x=%f)\n", y, x); + +#if !HAVE_COMPATIBLE_ATAN2 + errno = 0; +#endif // !HAVE_COMPATIBLE_ATAN2 + + ret = atan2(y, x); + +#if !HAVE_COMPATIBLE_ATAN2 + if ((errno == EDOM) && (x == 0.0) && (y == 0.0)) + { + const double sign_x = copysign(1.0, x); + const double sign_y = copysign(1.0, y); + + if (sign_x > 0) + { + ret = copysign(0.0, sign_y); + } + else + { + ret = copysign(atan2(0.0, -1.0), sign_y); + } + } +#endif // !HAVE_COMPATIBLE_ATAN2 + + LOGEXIT("atan2 returns double %f\n", ret); + PERF_EXIT(atan2); + return ret; +} + +/*++ +Function: + exp + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_exp(double x) +{ + double ret; + PERF_ENTRY(exp); + ENTRY("exp (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_EXP + if (x == 1.0) + { + ret = M_E; + } + else + { +#endif // HAVE_COMPATIBLE_EXP + + ret = exp(x); + +#if !HAVE_COMPATIBLE_EXP + } +#endif // HAVE_COMPATIBLE_EXP + + LOGEXIT("exp returns double %f\n", ret); + PERF_EXIT(exp); + return ret; +} + +/*++ +Function: + fma + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_fma(double x, double y, double z) +{ + double ret; + PERF_ENTRY(fma); + ENTRY("fma (x=%f, y=%f, z=%f)\n", x, y, z); + + ret = fma(x, y, z); + + LOGEXIT("fma returns double %f\n", ret); + PERF_EXIT(fma); + return ret; +} + +/*++ +Function: + ilogb + +See MSDN. +--*/ +PALIMPORT int __cdecl PAL_ilogb(double x) +{ + int ret; + PERF_ENTRY(ilogb); + ENTRY("ilogb (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_ILOGB0 + if (x == 0.0) + { + ret = -2147483648; + } + else +#endif // !HAVE_COMPATIBLE_ILOGB0 + +#if !HAVE_COMPATIBLE_ILOGBNAN + if (isnan(x)) + { + ret = 2147483647; + } + else +#endif // !HAVE_COMPATIBLE_ILOGBNAN + + { + ret = ilogb(x); + } + + LOGEXIT("ilogb returns int %d\n", ret); + PERF_EXIT(ilogb); + return ret; +} + +/*++ +Function: + log + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_log(double x) +{ + double ret; + PERF_ENTRY(log); + ENTRY("log (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_LOG + errno = 0; +#endif // !HAVE_COMPATIBLE_LOG + + ret = log(x); + +#if !HAVE_COMPATIBLE_LOG + if ((errno == EDOM) && (x < 0)) + { + ret = PAL_NAN_DBL; // NaN + } +#endif // !HAVE_COMPATIBLE_LOG + + LOGEXIT("log returns double %f\n", ret); + PERF_EXIT(log); + return ret; +} + +/*++ +Function: + log2 + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_log2(double x) +{ + double ret; + PERF_ENTRY(log2); + ENTRY("log2 (x=%f)\n", x); + + ret = log2(x); + + LOGEXIT("log2 returns double %f\n", ret); + PERF_EXIT(log2); + return ret; +} + +/*++ +Function: + log10 + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_log10(double x) +{ + double ret; + PERF_ENTRY(log10); + ENTRY("log10 (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_LOG10 + errno = 0; +#endif // !HAVE_COMPATIBLE_LOG10 + + ret = log10(x); + +#if !HAVE_COMPATIBLE_LOG10 + if ((errno == EDOM) && (x < 0)) + { + ret = PAL_NAN_DBL; // NaN + } +#endif // !HAVE_COMPATIBLE_LOG10 + + LOGEXIT("log10 returns double %f\n", ret); + PERF_EXIT(log10); + return ret; +} + +/*++ +Function: + pow + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_pow(double x, double y) +{ + double ret; + PERF_ENTRY(pow); + ENTRY("pow (x=%f, y=%f)\n", x, y); + +#if !HAVE_COMPATIBLE_POW + if ((y == PAL_POSINF_DBL) && !isnan(x)) // +Inf + { + if (x == 1.0) + { + ret = x; + } + else if (x == -1.0) + { + ret = 1.0; + } + else if ((x > -1.0) && (x < 1.0)) + { + ret = 0.0; + } + else + { + ret = PAL_POSINF_DBL; // +Inf + } + } + else if ((y == PAL_NEGINF_DBL) && !isnan(x)) // -Inf + { + if (x == 1.0) + { + ret = x; + } + else if (x == -1.0) + { + ret = 1.0; + } + else if ((x > -1.0) && (x < 1.0)) + { + ret = PAL_POSINF_DBL; // +Inf + } + else + { + ret = 0.0; + } + } + else if (IS_DBL_NEGZERO(x) && (y == -1.0)) + { + ret = PAL_NEGINF_DBL; // -Inf + } + else if ((x == 0.0) && (y < 0.0)) + { + ret = PAL_POSINF_DBL; // +Inf + } + else +#endif // !HAVE_COMPATIBLE_POW + + ret = pow(x, y); + +#if !HAVE_VALID_NEGATIVE_INF_POW + if ((ret == PAL_POSINF_DBL) && (x < 0) && isfinite(x) && (ceil(y / 2) != floor(y / 2))) + { + ret = PAL_NEGINF_DBL; // -Inf + } +#endif // !HAVE_VALID_NEGATIVE_INF_POW + +#if !HAVE_VALID_POSITIVE_INF_POW + /* + * The even/odd test in the if (this one and the one above) used to be ((long long) y % 2 == 0) + * on SPARC (long long) y for large y (>2**63) is always 0x7fffffff7fffffff, which + * is an odd number, so the test ((long long) y % 2 == 0) will always fail for + * large y. Since large double numbers are always even (e.g., the representation of + * 1E20+1 is the same as that of 1E20, the last .+1. is too insignificant to be part + * of the representation), this test will always return the wrong result for large y. + * + * The (ceil(y/2) == floor(y/2)) test is slower, but more robust. + */ + if ((ret == PAL_NEGINF_DBL) && (x < 0) && isfinite(x) && (ceil(y / 2) == floor(y / 2))) + { + ret = PAL_POSINF_DBL; // +Inf + } +#endif // !HAVE_VALID_POSITIVE_INF_POW + + LOGEXIT("pow returns double %f\n", ret); + PERF_EXIT(pow); + return ret; +} + +/*++ +Function: + scalbn + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_scalbn(double x, int n) +{ + double ret; + PERF_ENTRY(scalbn); + ENTRY("scalbn (x=%f, n=%d)\n", x, n); + + ret = scalbn(x, n); + + LOGEXIT("scalbn returns double %f\n", ret); + PERF_EXIT(scalbn); + 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); + + ret = isfinite(x); + + 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: + acoshf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_acoshf(float x) +{ + float ret; + PERF_ENTRY(acoshf); + ENTRY("acoshf (x=%f)\n", x); + + ret = acoshf(x); + + LOGEXIT("acoshf returns float %f\n", ret); + PERF_EXIT(acoshf); + 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: + asinhf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_asinhf(float x) +{ + float ret; + PERF_ENTRY(asinhf); + ENTRY("asinhf (x=%f)\n", x); + + ret = asinhf(x); + + LOGEXIT("asinhf returns float %f\n", ret); + PERF_EXIT(asinhf); + 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: + fmaf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_fmaf(float x, float y, float z) +{ + float ret; + PERF_ENTRY(fmaf); + ENTRY("fmaf (x=%f, y=%f, z=%f)\n", x, y, z); + + ret = fmaf(x, y, z); + + LOGEXIT("fma returns float %f\n", ret); + PERF_EXIT(fmaf); + return ret; +} + +/*++ +Function: + ilogbf + +See MSDN. +--*/ +PALIMPORT int __cdecl PAL_ilogbf(float x) +{ + int ret; + PERF_ENTRY(ilogbf); + ENTRY("ilogbf (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_ILOGB0 + if (x == 0.0f) + { + ret = -2147483648; + } + else +#endif // !HAVE_COMPATIBLE_ILOGB0 + +#if !HAVE_COMPATIBLE_ILOGBNAN + if (isnan(x)) + { + ret = 2147483647; + } + else +#endif // !HAVE_COMPATIBLE_ILOGBNAN + + { + ret = ilogbf(x); + } + + LOGEXIT("ilogbf returns int %d\n", ret); + PERF_EXIT(ilogbf); + 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: + log2f + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_log2f(float x) +{ + float ret; + PERF_ENTRY(log2f); + ENTRY("log2f (x=%f)\n", x); + + ret = log2f(x); + + LOGEXIT("log2f returns float %f\n", ret); + PERF_EXIT(log2f); + 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 = 1.0f; + } + 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 = 1.0f; + } + 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 + + 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; +} + +/*++ +Function: + scalbnf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_scalbnf(float x, int n) +{ + float ret; + PERF_ENTRY(scalbnf); + ENTRY("scalbnf (x=%f, n=%d)\n", x, n); + + ret = scalbnf(x, n); + + LOGEXIT("scalbnf returns double %f\n", ret); + PERF_EXIT(scalbnf); + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/mbstring.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/mbstring.cpp new file mode 100644 index 0000000..e929b9a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/mbstring.cpp @@ -0,0 +1,204 @@ +// 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: + + mbstring.c + +Abstract: + + Implementation of the multi-byte string functions in the C runtime library that + are Windows specific. + +Implementation Notes: + + Assuming it is not possible to change multi-byte code page using + the PAL (_setmbcp does not seem to be required), these functions + should have a trivial implementation (treat as single-byte). If it + is possible, then support for multi-byte code pages will have to + be implemented before these functions can behave correctly for + multi-byte strings. + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" + +#include + +SET_DEFAULT_DEBUG_CHANNEL(CRT); + + +/*++ +Function: + _mbsinc + +Return Value + +Returns a pointer to the character that immediately follows string. + +Parameter + +string Character pointer + +Remarks + +The _mbsinc function returns a pointer to the first byte of the +multibyte character that immediately follows string. + +--*/ +unsigned char * +__cdecl +_mbsinc( + const unsigned char *string) +{ + unsigned char *ret; + + PERF_ENTRY(_mbsinc); + ENTRY("_mbsinc (string=%p)\n", string); + + if (string == NULL) + { + ret = NULL; + } + else + { + ret = (unsigned char *) string; + if (IsDBCSLeadByteEx(CP_ACP, *ret)) + { + ++ret; + } + ++ret; + } + + LOGEXIT("_mbsinc returning unsigned char* %p (%s)\n", ret, ret); + PERF_EXIT(_mbsinc); + return ret; +} + + +/*++ +Function: + _mbsninc + +Return Value + +Returns a pointer to string after string has been incremented by count +characters, or NULL if the supplied pointer is NULL. If count is +greater than or equal to the number of characters in string, the +result is undefined. + +Parameters + +string Source string +count Number of characters to increment string pointer + +Remarks + +The _mbsninc function increments string by count multibyte +characters. _mbsninc recognizes multibyte-character sequences +according to the multibyte code page currently in use. + +--*/ +unsigned char * +__cdecl +_mbsninc( + const unsigned char *string, size_t count) +{ + unsigned char *ret; + CPINFO cpinfo; + + PERF_ENTRY(_mbsninc); + ENTRY("_mbsninc (string=%p, count=%lu)\n", string, count); + if (string == NULL) + { + ret = NULL; + } + else + { + ret = (unsigned char *) string; + if (GetCPInfo(CP_ACP, &cpinfo) && cpinfo.MaxCharSize == 1) + { + ret += std::min(count, strlen((const char*)string)); + } + else + { + while (count-- && (*ret != 0)) + { + if (IsDBCSLeadByteEx(CP_ACP, *ret)) + { + ++ret; + } + ++ret; + } + } + } + LOGEXIT("_mbsninc returning unsigned char* %p (%s)\n", ret, ret); + PERF_EXIT(_mbsninc); + return ret; +} + +/*++ +Function: + _mbsdec + +Return Value + +_mbsdec returns a pointer to the character that immediately precedes +current; _mbsdec returns NULL if the value of start is greater than or +equal to that of current. + +Parameters + +start Pointer to first byte of any multibyte character in the source + string; start must precede current in the source string + +current Pointer to first byte of any multibyte character in the source + string; current must follow start in the source string + +--*/ +unsigned char * +__cdecl +_mbsdec( + const unsigned char *start, + const unsigned char *current) +{ + unsigned char *ret; + unsigned char *strPtr; + CPINFO cpinfo; + + PERF_ENTRY(_mbsdec); + ENTRY("_mbsdec (start=%p, current=%p)\n", start, current); + + if (current <= start) + { + ret = NULL; + } + else if (GetCPInfo(CP_ACP, &cpinfo) && cpinfo.MaxCharSize == 1) + { + ret = (unsigned char *) current - 1; + } + else + { + ret = strPtr = (unsigned char *) start; + while (strPtr < current) + { + ret = strPtr; + if (IsDBCSLeadByteEx(CP_ACP, *strPtr)) + { + ++strPtr; + } + ++strPtr; + } + } + LOGEXIT("_mbsdec returning unsigned int %p (%s)\n", ret, ret); + PERF_EXIT(_mbsdec); + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/misc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/misc.cpp new file mode 100644 index 0000000..2a569a6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/misc.cpp @@ -0,0 +1,278 @@ +// 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: + + cruntime/misc.cpp + +Abstract: + + Implementation of C runtime functions that don't fit anywhere else. + + + +--*/ + +#include "pal/thread.hpp" +#include "pal/threadsusp.hpp" +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/misc.h" + +#include +/* needs to be included after "palinternal.h" to avoid name + collision for va_start and va_end */ +#include +#include +#include + +#if defined(HOST_AMD64) || defined(_x86_) +#include +#endif // defined(HOST_AMD64) || defined(_x86_) +#if defined(_DEBUG) +#include +#endif //defined(_DEBUG) + +SET_DEFAULT_DEBUG_CHANNEL(CRT); + +using namespace CorUnix; + +/*++ +Function: + _gcvt_s + +See MSDN doc. +--*/ +char * +__cdecl +_gcvt_s( char * buffer, int iSize, double value, int digits ) +{ + PERF_ENTRY(_gcvt); + ENTRY( "_gcvt( value:%f digits=%d, buffer=%p )\n", value, digits, buffer ); + + if ( !buffer ) + { + ERROR( "buffer was an invalid pointer.\n" ); + } + + switch ( digits ) + { + case 7 : + /* Fall through */ + case 8 : + /* Fall through */ + case 15 : + /* Fall through */ + case 17 : + + sprintf_s( buffer, iSize, "%.*g", digits, value ); + break; + + default : + ASSERT( "Only the digits 7, 8, 15, and 17 are valid.\n" ); + *buffer = '\0'; + } + + LOGEXIT( "_gcvt returns %p (%s)\n", buffer , buffer ); + PERF_EXIT(_gcvt); + return buffer; +} + + +/*++ +Function : + + __iscsym + +See MSDN for more details. +--*/ +int +__cdecl +__iscsym( int c ) +{ + PERF_ENTRY(__iscsym); + ENTRY( "__iscsym( c=%d )\n", c ); + + if ( isalnum( c ) || c == '_' ) + { + LOGEXIT( "__iscsym returning 1\n" ); + PERF_EXIT(__iscsym); + return 1; + } + + LOGEXIT( "__iscsym returning 0\n" ); + PERF_EXIT(__iscsym); + return 0; +} + + +/*++ + +Function : + + PAL_errno + + Returns the address of the errno. + +--*/ +int * __cdecl PAL_errno( int caller ) +{ + int *retval; + PERF_ENTRY(errno); + ENTRY( "PAL_errno( void )\n" ); + retval = (INT*)(&errno); + LOGEXIT("PAL_errno returns %p\n",retval); + PERF_EXIT(errno); + return retval; +} + + +/*++ +Function: + + rand + + The RAND_MAX value can vary by platform. + +See MSDN for more details. +--*/ +int +__cdecl +PAL_rand(void) +{ + int ret; + PERF_ENTRY(rand); + ENTRY("rand(void)\n"); + + ret = (rand() % (PAL_RAND_MAX + 1)); + + LOGEXIT("rand() returning %d\n", ret); + PERF_EXIT(rand); + return ret; +} + + +/*++ +Function: + + time + +See MSDN for more details. +--*/ +PAL_time_t +__cdecl +PAL_time(PAL_time_t *tloc) +{ + time_t result; + + PERF_ENTRY(time); + ENTRY( "time( tloc=%p )\n",tloc ); + + result = time(tloc); + + LOGEXIT( "time returning %#lx\n",result ); + PERF_EXIT(time); + return result; +} + +PALIMPORT +void __cdecl +PAL_qsort(void *base, size_t nmemb, size_t size, + int (__cdecl *compar )(const void *, const void *)) +{ + PERF_ENTRY(qsort); + ENTRY("qsort(base=%p, nmemb=%lu, size=%lu, compar=%p\n", + base,(unsigned long) nmemb,(unsigned long) size, compar); + +/* reset ENTRY nesting level back to zero, qsort will invoke app-defined + callbacks and we want their entry traces... */ +#if _ENABLE_DEBUG_MESSAGES_ +{ + int old_level; + old_level = DBG_change_entrylevel(0); +#endif /* _ENABLE_DEBUG_MESSAGES_ */ + + qsort(base,nmemb,size,compar); + +/* ...and set nesting level back to what it was */ +#if _ENABLE_DEBUG_MESSAGES_ + DBG_change_entrylevel(old_level); +} +#endif /* _ENABLE_DEBUG_MESSAGES_ */ + + LOGEXIT("qsort returns\n"); + PERF_EXIT(qsort); +} + +PALIMPORT +void * __cdecl +PAL_bsearch(const void *key, const void *base, size_t nmemb, size_t size, + int (__cdecl *compar)(const void *, const void *)) +{ + void *retval; + + PERF_ENTRY(bsearch); + ENTRY("bsearch(key=%p, base=%p, nmemb=%lu, size=%lu, compar=%p\n", + key, base, (unsigned long) nmemb, (unsigned long) size, compar); + +/* reset ENTRY nesting level back to zero, bsearch will invoke app-defined + callbacks and we want their entry traces... */ +#if _ENABLE_DEBUG_MESSAGES_ +{ + int old_level; + old_level = DBG_change_entrylevel(0); +#endif /* _ENABLE_DEBUG_MESSAGES_ */ + + retval = bsearch(key,base,nmemb,size,compar); + +/* ...and set nesting level back to what it was */ +#if _ENABLE_DEBUG_MESSAGES_ + DBG_change_entrylevel(old_level); +} +#endif /* _ENABLE_DEBUG_MESSAGES_ */ + + LOGEXIT("bsearch returns %p\n",retval); + PERF_EXIT(bsearch); + return retval; +} + +#ifdef HOST_AMD64 + +PALIMPORT +unsigned int PAL__mm_getcsr(void) +{ + return _mm_getcsr(); +} + +PALIMPORT +void PAL__mm_setcsr(unsigned int i) +{ + _mm_setcsr(i); +} + +#endif // HOST_AMD64 + +/*++ +Function: +PAL_memcpy + +Overlapping buffer-safe version of memcpy. +See MSDN doc for memcpy +--*/ +EXTERN_C +PALIMPORT +void *PAL_memcpy (void *dest, const void *src, size_t count) +{ + UINT_PTR x = (UINT_PTR)dest, y = (UINT_PTR)src; + _ASSERTE((x + count <= y) || (y + count <= x)); + + void *ret; + #undef memcpy + ret = memcpy(dest, src, count); + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/path.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/path.cpp new file mode 100644 index 0000000..add20b3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/path.cpp @@ -0,0 +1,114 @@ +// 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: + + path.c + +Abstract: + + Implementation of path functions part of Windows runtime library. + +Revision History: + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/file.h" +#include "pal/printfcpp.hpp" + +#include +#include +#include +#include +#include + +SET_DEFAULT_DEBUG_CHANNEL(CRT); + +/*++ +Function: + _fullpath + +See MSDN doc. + +--*/ +char * +__cdecl +_fullpath( + char *absPath, + const char *relPath, + size_t maxLength) +{ + char realpath_buf[PATH_MAX+1]; + char path_copy[PATH_MAX+1]; + char *retval = NULL; + DWORD cPathCopy = sizeof(path_copy)/sizeof(path_copy[0]); + size_t min_length; + BOOL fBufAllocated = FALSE; + + PERF_ENTRY(_fullpath); + ENTRY("_fullpath (absPath=%p, relPath=%p (%s), maxLength = %lu)\n", + absPath, relPath ? relPath:"NULL", relPath ? relPath:"NULL", maxLength); + + if (strncpy_s(path_copy, sizeof(path_copy), relPath ? relPath : ".", cPathCopy) != SAFECRT_SUCCESS) + { + TRACE("_fullpath: strncpy_s failed!\n"); + goto fullpathExit; + } + + FILEDosToUnixPathA(path_copy); + + if(NULL == realpath(path_copy, realpath_buf)) + { + ERROR("realpath() failed; problem path is '%s'. errno is %d (%s)\n", + realpath_buf, errno, strerror(errno)); + goto fullpathExit; + } + + TRACE("real path is %s\n", realpath_buf); + min_length = strlen(realpath_buf)+1; // +1 for the NULL terminator + + if(NULL == absPath) + { + absPath = static_cast( + PAL_malloc(_MAX_PATH * sizeof(char))); + if (!absPath) + { + ERROR("PAL_malloc failed with error %d\n", errno); + goto fullpathExit; + } + maxLength = _MAX_PATH; + fBufAllocated = TRUE; + } + + if(min_length > maxLength) + { + ERROR("maxLength is %lu, we need at least %lu\n", + maxLength, min_length); + if (fBufAllocated) + { + PAL_free(absPath); + fBufAllocated = FALSE; + } + goto fullpathExit; + } + + strcpy_s(absPath, maxLength, realpath_buf); + retval = absPath; + +fullpathExit: + LOGEXIT("_fullpath returns char * %p\n", retval); + PERF_EXIT(_fullpath); + return retval; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/printf.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/printf.cpp new file mode 100644 index 0000000..f0d5b1c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/printf.cpp @@ -0,0 +1,1222 @@ +// 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: + + printf.c + +Abstract: + + Implementation of the printf family functions. + +Revision History: + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/cruntime.h" +#include "pal/thread.hpp" +#include "pal/threadsusp.hpp" +#include "pal/printfcpp.hpp" + +/* needs to be included after "palinternal.h" to avoid name + collision for va_start and va_end */ +#include +#include + +SET_DEFAULT_DEBUG_CHANNEL(CRT); + +#if SSCANF_SUPPORT_ll +const static char *scanf_longlongfmt = "ll"; +#else +const static char *scanf_longlongfmt = "q"; +#endif + +#if SSCANF_CANNOT_HANDLE_MISSING_EXPONENT +static int SscanfFloatCheckExponent(LPCSTR buff, LPCSTR floatFmt, + void * voidPtr, int * pn); +#endif // SSCANF_CANNOT_HANDLE_MISSING_EXPONENT + +/******************************************************************************* +Function: + PAL_printf_arg_remover + +Parameters: + ap + - pointer to the va_list from which to remove arguments + Width + - the width of the current format operation + Precision + - the precision of the current format option + Type + - the type of the argument for the current format option + Prefix + - the prefix for the current format option +*******************************************************************************/ +void PAL_printf_arg_remover(va_list *ap, INT Width, INT Precision, INT Type, INT Prefix) +{ + /* remove arg and precision if needed */ + if (PRECISION_STAR == Precision || + PRECISION_INVALID == Precision) + { + (void)va_arg(*ap, int); + } + if (WIDTH_STAR == Width || + WIDTH_INVALID == Width) + { + (void)va_arg(*ap, int); + } + if (Type == PFF_TYPE_FLOAT) + { + (void)va_arg(*ap, double); + } + else if (Type == PFF_TYPE_INT && Prefix == PFF_PREFIX_LONGLONG) + { + (void)va_arg(*ap, INT64); + } + else if (Type == PFF_TYPE_INT || Type == PFF_TYPE_CHAR) + { + (void)va_arg(*ap, int); + } + else + { + (void)va_arg(*ap, void *); + } +} + +/*++ +Function: + PAL_printf + +See MSDN doc. +--*/ +int +__cdecl +PAL_printf( + const char *format, + ...) +{ + LONG Length; + va_list ap; + + PERF_ENTRY(printf); + ENTRY("PAL_printf (format=%p (%s))\n", format, format); + + va_start(ap, format); + Length = PAL_vprintf(format, ap); + va_end(ap); + + LOGEXIT("PAL_printf returns int %d\n", Length); + PERF_EXIT(printf); + return Length; +} + +/*++ +Function: + PAL_fprintf + +See MSDN doc. +--*/ +int +__cdecl +PAL_fprintf(PAL_FILE *stream,const char *format,...) +{ + LONG Length = 0; + va_list ap; + + PERF_ENTRY(fprintf); + ENTRY("PAL_fprintf(stream=%p,format=%p (%s))\n",stream, format, format); + + va_start(ap, format); + Length = PAL_vfprintf( stream, format, ap); + va_end(ap); + + LOGEXIT("PAL_fprintf returns int %d\n", Length); + PERF_EXIT(fprintf); + return Length; +} + +/*++ +Function: + PAL_wprintf + +See MSDN doc. +--*/ +int +__cdecl +PAL_wprintf( + const wchar_16 *format, + ...) +{ + LONG Length; + va_list ap; + + PERF_ENTRY(wprintf); + ENTRY("PAL_wprintf (format=%p (%S))\n", format, format); + + va_start(ap, format); + Length = PAL_vfwprintf( PAL_get_stdout(PAL_get_caller), format, ap); + va_end(ap); + + LOGEXIT("PAL_wprintf returns int %d\n", Length); + PERF_EXIT(wprintf); + return Length; +} + + + +/*++ +Function: + PAL_vprintf + +See MSDN doc. +--*/ +int +__cdecl +PAL_vprintf( + const char *format, + va_list ap) +{ + LONG Length; + + PERF_ENTRY(vprintf); + ENTRY("PAL_vprintf (format=%p (%s))\n", format, format); + + Length = PAL_vfprintf( PAL_get_stdout(PAL_get_caller), format, ap); + + LOGEXIT("PAL_vprintf returns int %d\n", Length); + PERF_EXIT(vprintf); + return Length; +} + + +/*++ +Function: + fwprintf + +See MSDN doc. +--*/ +int +__cdecl +PAL_fwprintf( + PAL_FILE *stream, + const wchar_16 *format, + ...) +{ + LONG Length; + va_list ap; + + PERF_ENTRY(fwprintf); + ENTRY("PAL_fwprintf (stream=%p, format=%p (%S))\n", stream, format, format); + + va_start(ap, format); + Length = PAL_vfwprintf( stream, format, ap); + va_end(ap); + + LOGEXIT("PAL_fwprintf returns int %d\n", Length); + PERF_EXIT(fwprintf); + return Length; +} + +/******************************************************************************* +Function: + Internal_ScanfExtractFormatA + +Paramaters: + Fmt + - format string to parse + - first character must be a '%' + - paramater gets updated to point to the character after + the % format string + Out + - buffer will contain the % format string + Store + - boolean value representing whether to store the type to be parsed + - '*' flag + Width + - will contain the width specified by the format string + - -1 if none given + Prefix + - an enumeration of the type prefix + Type + - an enumeration of the value type to be parsed + +Notes: + - I'm also handling the undocumented %ws, %wc, %w... +*******************************************************************************/ + +#define CHECK_OUT_IN_ITS_RANGE(Out,BeginOut,EndOut) \ + if ((Out)<(BeginOut) || (Out)>=(EndOut)) \ + { \ + SetLastError(ERROR_INSUFFICIENT_BUFFER); \ + ERROR("Pointer Out wanted to access 0x%p. However the range of buffer is [0x%p,0x%p).",\ + (Out), (BeginOut), (EndOut)); \ + return false; \ + } + +static BOOL Internal_ScanfExtractFormatA(LPCSTR *Fmt, LPSTR Out, int iOutSize, LPBOOL Store, + LPINT Width, LPINT Prefix, LPINT Type) +{ + BOOL Result = FALSE; + LPSTR TempStr; + LPSTR TempStrPtr; + LPSTR BaseOut = Out; + LPSTR EndOut = Out + iOutSize; + + *Width = -1; + *Store = TRUE; + *Prefix = -1; + *Type = -1; + + if (*Fmt && **Fmt == '%') + { + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = *(*Fmt)++; + } + else + { + return Result; + } + + /* we'll never need a temp string longer than the original */ + TempStrPtr = TempStr = (LPSTR) PAL_malloc(strlen(*Fmt)+1); + if (!TempStr) + { + ERROR("PAL_malloc failed\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return Result; + } + + /* parse '*' flag which means don't store */ + if (**Fmt == '*') + { + *Store = FALSE; + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = *(*Fmt)++; + } + + /* grab width specifier */ + if (isdigit((unsigned char) **Fmt)) + { + TempStrPtr = TempStr; + while (isdigit((unsigned char) **Fmt)) + { + *TempStrPtr++ = **Fmt; + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = *(*Fmt)++; + } + *TempStrPtr = 0; /* end string */ + *Width = atoi(TempStr); + if (*Width < 0) + { + ERROR("atoi returned a negative value indicative of an overflow.\n"); + SetLastError(ERROR_INTERNAL_ERROR); + return Result; + } + } + +#ifdef HOST_64BIT + if (**Fmt == 'p') + { + *Prefix = SCANF_PREFIX_LONGLONG; + } +#endif + /* grab prefix of 'I64' for __int64 */ + if ((*Fmt)[0] == 'I' && (*Fmt)[1] == '6' && (*Fmt)[2] == '4') + { + /* convert to 'q'/'ll' so Unix sscanf can handle it */ + *Fmt += 3; + *Prefix = SCANF_PREFIX_LONGLONG; + } + /* grab a prefix of 'h' */ + else if (**Fmt == 'h') + { + *Prefix = SCANF_PREFIX_SHORT; + ++(*Fmt); + } + /* grab prefix of 'l' or the undocumented 'w' (at least in MSDN) */ + else if (**Fmt == 'l' || **Fmt == 'w') + { + ++(*Fmt); +#ifdef HOST_64BIT + // Only want to change the prefix on 64 bit when inputing characters. + if (**Fmt == 'c' || **Fmt == 's') +#endif + { + *Prefix = SCANF_PREFIX_LONG; /* give it a wide prefix */ + } + if (**Fmt == 'l') + { + *Prefix = SCANF_PREFIX_LONGLONG; + ++(*Fmt); + } + } + else if (**Fmt == 'L') + { + /* a prefix of 'L' seems to be ignored */ + ++(*Fmt); + } + + /* grab type 'c' */ + if (**Fmt == 'c' || **Fmt == 'C') + { + *Type = SCANF_TYPE_CHAR; + if (*Prefix != SCANF_PREFIX_SHORT && **Fmt == 'C') + { + *Prefix = SCANF_PREFIX_LONG; /* give it a wide prefix */ + } + if (*Prefix == SCANF_PREFIX_LONG) + { + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = 'l'; + } + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = 'c'; + ++(*Fmt); + Result = TRUE; + } + /* grab type 's' */ + else if (**Fmt == 's' || **Fmt == 'S') + { + *Type = SCANF_TYPE_STRING; + if (*Prefix != SCANF_PREFIX_SHORT && **Fmt == 'S') + { + *Prefix = SCANF_PREFIX_LONG; /* give it a wide prefix */ + } + if (*Prefix == SCANF_PREFIX_LONG) + { + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = 'l'; + } + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = 's'; + ++(*Fmt); + Result = TRUE; + } + /* grab int types */ + else if (**Fmt == 'd' || **Fmt == 'i' || **Fmt == 'o' || + **Fmt == 'u' || **Fmt == 'x' || **Fmt == 'X' || + **Fmt == 'p') + { + *Type = SCANF_TYPE_INT; + if (*Prefix == SCANF_PREFIX_SHORT) + { + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = 'h'; + } + else if (*Prefix == SCANF_PREFIX_LONG) + { + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = 'l'; + } + else if (*Prefix == SCANF_PREFIX_LONGLONG) + { + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + + if (strcpy_s(Out, iOutSize-(Out-BaseOut), scanf_longlongfmt) != SAFECRT_SUCCESS) + { + ERROR("strcpy_s failed\n"); + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + Out += strlen(scanf_longlongfmt); + } + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = *(*Fmt)++; + Result = TRUE; + } + else if (**Fmt == 'e' || **Fmt == 'E' || **Fmt == 'f' || + **Fmt == 'g' || **Fmt == 'G') + { + /* we can safely ignore the prefixes and only add the type*/ + *Type = SCANF_TYPE_FLOAT; + /* this gets rid of %E/%G since they're they're the + same when scanning */ + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = tolower( *(*Fmt)++ ); + Result = TRUE; + } + else if (**Fmt == 'n') + { + if (*Prefix == SCANF_PREFIX_SHORT) + { + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = 'h'; + } + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = *(*Fmt)++; + *Type = SCANF_TYPE_N; + Result = TRUE; + } + else if (**Fmt == '[') + { + /* There is a small compatibility problem in the handling of the [] + option in FreeBSD vs. Windows. In Windows, you can have [z-a] + as well as [a-z]. In FreeBSD, [z-a] fails. So, we need to + reverse the instances of z-a to a-z (and [m-e] to [e-m], etc). */ + + /* step 1 : copy the leading [ */ + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = '['; + (*Fmt)++; + + /* step 2 : copy a leading ^, if present */ + if( '^' == **Fmt ) + { + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = '^'; + (*Fmt)++; + } + + /* step 3 : copy a leading ], if present; a ] immediately after the + leading [ (or [^) does *not* end the sequence, it is part of the + characters to match */ + if( ']' == **Fmt ) + { + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = ']'; + (*Fmt)++; + } + + /* step 4 : if the next character is already a '-', it's not part of an + interval specifier, so just copy it */ + if('-' == **Fmt ) + { + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = '-'; + (*Fmt)++; + } + + /* ok then, process the rest of it */ + while( '\0' != **Fmt ) + { + if(']' == **Fmt) + { + /* ']' marks end of the format specifier; we're done */ + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = ']'; + (*Fmt)++; + break; + } + if('-' == **Fmt) + { + if( ']' == (*Fmt)[1] ) + { + /* got a '-', next character is the terminating ']'; + copy '-' literally */ + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = '-'; + (*Fmt)++; + } + else + { + /* got a '-' indicating an interval specifier */ + unsigned char prev, next; + + /* get the interval boundaries */ + prev = (*Fmt)[-1]; + next = (*Fmt)[1]; + + /* if boundaries were inverted, replace the already-copied + low boundary by the 'real' low boundary */ + if( prev > next ) + { + CHECK_OUT_IN_ITS_RANGE(Out-1,BaseOut,EndOut) + Out[-1] = next; + + /* ...and save the 'real' upper boundary, which will be + copied to 'Out' below */ + next = prev; + } + + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = '-'; + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = next; + + /* skip over the '-' and the next character, which we + already copied */ + (*Fmt)+=2; + } + } + else + { + /* plain character; just copy it */ + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = **Fmt; + (*Fmt)++; + } + } + + *Type = SCANF_TYPE_BRACKETS; + Result = TRUE; + } + else if (**Fmt == ' ') + { + *Type = SCANF_TYPE_SPACE; + } + + /* add %n so we know how far to increment the pointer */ + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = '%'; + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out++ = 'n'; + + CHECK_OUT_IN_ITS_RANGE(Out,BaseOut,EndOut) + *Out = 0; /* end the string */ + PAL_free(TempStr); + return Result; +} + +/******************************************************************************* +Function: + Internal_ScanfExtractFormatW + + -- see Internal_ScanfExtractFormatA above +*******************************************************************************/ +static BOOL Internal_ScanfExtractFormatW(LPCWSTR *Fmt, LPSTR Out, int iOutSize, LPBOOL Store, + LPINT Width, LPINT Prefix, LPINT Type) +{ + BOOL Result = FALSE; + LPSTR TempStr; + LPSTR TempStrPtr; + + *Width = -1; + *Store = TRUE; + *Prefix = -1; + *Type = -1; + + if (*Fmt && **Fmt == '%') + { + *Out++ = *(*Fmt)++; + } + else + { + return Result; + } + + /* we'll never need a temp string longer than the original */ + TempStrPtr = TempStr = (LPSTR) PAL_malloc(PAL_wcslen(*Fmt)+1); + if (!TempStr) + { + ERROR("PAL_malloc failed\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return Result; + } + + /* parse '*' flag which means don't store */ + if (**Fmt == '*') + { + *Store = FALSE; + *Out++ = *(*Fmt)++; + } + + /* grab width specifier */ + if (isdigit(**Fmt)) + { + TempStrPtr = TempStr; + while (isdigit(**Fmt)) + { + *TempStrPtr++ = **Fmt; + *Out++ = *(*Fmt)++; + } + *TempStrPtr = 0; /* end string */ + *Width = atoi(TempStr); + if (*Width < 0) + { + ERROR("atoi returned a negative value indicative of an overflow.\n"); + SetLastError(ERROR_INTERNAL_ERROR); + return Result; + } + } + +#ifdef HOST_64BIT + if (**Fmt == 'p') + { + *Prefix = SCANF_PREFIX_LONGLONG; + } +#endif + /* grab prefix of 'I64' for __int64 */ + if ((*Fmt)[0] == 'I' && (*Fmt)[1] == '6' && (*Fmt)[2] == '4') + { + /* convert to 'q'/'ll' so that Unix sscanf can handle it */ + *Fmt += 3; + *Prefix = SCANF_PREFIX_LONGLONG; + } + /* grab a prefix of 'h' */ + else if (**Fmt == 'h') + { + *Prefix = SCANF_PREFIX_SHORT; + ++(*Fmt); + } + /* grab prefix of 'l' or the undocumented 'w' (at least in MSDN) */ + else if (**Fmt == 'l' || **Fmt == 'w') + { + ++(*Fmt); +#ifdef HOST_64BIT + // Only want to change the prefix on 64 bit when inputing characters. + if (**Fmt == 'C' || **Fmt == 'S') +#endif + { + *Prefix = SCANF_PREFIX_LONG; /* give it a wide prefix */ + } + if (**Fmt == 'l') + { + *Prefix = SCANF_PREFIX_LONGLONG; + ++(*Fmt); + } + } + else if (**Fmt == 'L') + { + /* a prefix of 'L' seems to be ignored */ + ++(*Fmt); + } + + /* grab type 'c' */ + if (**Fmt == 'c' || **Fmt == 'C') + { + *Type = SCANF_TYPE_CHAR; + if (*Prefix != SCANF_PREFIX_SHORT && **Fmt == 'c') + { + *Prefix = SCANF_PREFIX_LONG; /* give it a wide prefix */ + } + if (*Prefix == SCANF_PREFIX_LONG) + { + *Out++ = 'l'; + } + *Out++ = 'c'; + ++(*Fmt); + Result = TRUE; + } + /* grab type 's' */ + else if (**Fmt == 's' || **Fmt == 'S') + { + *Type = SCANF_TYPE_STRING; + if (*Prefix != SCANF_PREFIX_SHORT && **Fmt == 's') + { + *Prefix = SCANF_PREFIX_LONG; /* give it a wide prefix */ + } + if (*Prefix == SCANF_PREFIX_LONG) + { + *Out++ = 'l'; + } + *Out++ = 's'; + ++(*Fmt); + Result = TRUE; + } + /* grab int types */ + else if (**Fmt == 'd' || **Fmt == 'i' || **Fmt == 'o' || + **Fmt == 'u' || **Fmt == 'x' || **Fmt == 'X' || + **Fmt == 'p') + { + *Type = SCANF_TYPE_INT; + if (*Prefix == SCANF_PREFIX_SHORT) + { + *Out++ = 'h'; + } + else if (*Prefix == SCANF_PREFIX_LONG) + { + *Out++ = 'l'; + } + else if (*Prefix == SCANF_PREFIX_LONGLONG) + { + if (strcpy_s(Out, iOutSize, scanf_longlongfmt) != SAFECRT_SUCCESS) + { + ERROR("strcpy_s failed\n"); + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + Out += strlen(scanf_longlongfmt); + } + *Out++ = *(*Fmt)++; + Result = TRUE; + } + else if (**Fmt == 'e' || **Fmt == 'E' || **Fmt == 'f' || + **Fmt == 'g' || **Fmt == 'G') + { + /* we can safely ignore the prefixes and only add the type*/ + *Type = SCANF_TYPE_FLOAT; + /* this gets rid of %E/%G since they're they're the + same when scanning */ + *Out++ = tolower( *(*Fmt)++ ); + Result = TRUE; + } + else if (**Fmt == 'n') + { + if (*Prefix == SCANF_PREFIX_SHORT) + { + *Out++ = 'h'; + } + *Out++ = *(*Fmt)++; + *Type = SCANF_TYPE_N; + Result = TRUE; + } + else if (**Fmt == '[') + { + /* There is a small compatibility problem in the handling of the [] + option in FreeBSD vs. Windows. In Windows, you can have [z-a] + as well as [a-z]. In FreeBSD, [z-a] fails. So, we need to + reverse the instances of z-a to a-z (and [m-e] to [e-m], etc). */ + + /* step 1 : copy the leading [ */ + *Out++ = '['; + (*Fmt)++; + + /* step 2 : copy a leading ^, if present */ + if( '^' == **Fmt ) + { + *Out++ = '^'; + (*Fmt)++; + } + + /* step 3 : copy a leading ], if present; a ] immediately after the + leading [ (or [^) does *not* end the sequence, it is part of the + characters to match */ + if( ']' == **Fmt ) + { + *Out++ = ']'; + (*Fmt)++; + } + + /* step 4 : if the next character is already a '-', it's not part of an + interval specifier, so just copy it */ + if('-' == **Fmt ) + { + *Out++ = '-'; + (*Fmt)++; + } + + /* ok then, process the rest of it */ + while( '\0' != **Fmt ) + { + if(']' == **Fmt) + { + /* ']' marks end of the format specifier; we're done */ + *Out++ = ']'; + (*Fmt)++; + break; + } + if('-' == **Fmt) + { + if( ']' == (*Fmt)[1] ) + { + /* got a '-', next character is the terminating ']'; + copy '-' literally */ + *Out++ = '-'; + (*Fmt)++; + } + else + { + /* got a '-' indicating an interval specifier */ + unsigned char prev, next; + + /* get the interval boundaries */ + prev = (*Fmt)[-1]; + next = (*Fmt)[1]; + + /* if boundaries were inverted, replace the already-copied + low boundary by the 'real' low boundary */ + if( prev > next ) + { + Out[-1] = next; + + /* ...and save the 'real' upper boundary, which will be + copied to 'Out' below */ + next = prev; + } + + *Out++ = '-'; + *Out++ = next; + + /* skip over the '-' and the next character, which we + already copied */ + (*Fmt)+=2; + } + } + else + { + /* plain character; just copy it */ + *Out++ = **Fmt; + (*Fmt)++; + } + } + + *Type = SCANF_TYPE_BRACKETS; + Result = TRUE; + } + else if (**Fmt == ' ') + { + *Type = SCANF_TYPE_SPACE; + } + + /* add %n so we know how far to increment the pointer */ + *Out++ = '%'; + *Out++ = 'n'; + + *Out = 0; /* end the string */ + PAL_free(TempStr); + return Result; +} + +/******************************************************************************* +Function: + PAL_wvsscanf + + Buffer + - buffer to parse values from + Format + - format string + ap + - stdarg parameter list +*******************************************************************************/ +int PAL_wvsscanf(LPCWSTR Buffer, LPCWSTR Format, va_list ap) +{ + INT Length = 0; + LPCWSTR Buff = Buffer; + LPCWSTR Fmt = Format; + CHAR TempBuff[1024]; /* used to hold a single % format string */ + BOOL Store; + INT Width; + INT Prefix; + INT Type = -1; + + while (*Fmt) + { + if (!*Buff && Length == 0) + { + Length = EOF; + break; + } + /* remove any number of blanks */ + else if (isspace(*Fmt)) + { + while (isspace(*Buff)) + { + ++Buff; + } + ++Fmt; + } + else if (*Fmt == '%' && + Internal_ScanfExtractFormatW(&Fmt, TempBuff, sizeof(TempBuff), &Store, + &Width, &Prefix, &Type)) + { + if (Prefix == SCANF_PREFIX_LONG && + (Type == SCANF_TYPE_STRING || Type == SCANF_TYPE_CHAR)) + { + int len = 0; + WCHAR *charPtr = 0; + + /* a single character */ + if (Type == SCANF_TYPE_CHAR && Width == -1) + { + len = Width = 1; + } + + /* calculate length of string to copy */ + while (Buff[len] && !isspace(Buff[len])) + { + if (Width != -1 && len >= Width) + { + break; + } + ++len; + } + + if (Store) + { + int i; + charPtr = va_arg(ap, WCHAR *); + + for (i = 0; i < len; i++) + { + charPtr[i] = Buff[i]; + } + if (Type == SCANF_TYPE_STRING) + { + /* end string */ + charPtr[len] = 0; + } + ++Length; + } + Buff += len; + } + /* this places the number of bytes stored into the next arg */ + else if (Type == SCANF_TYPE_N) + { + if (Prefix == SCANF_PREFIX_SHORT) + { + *(va_arg(ap, short *)) = Buff - Buffer; + } + else + { + *(va_arg(ap, LPLONG)) = Buff - Buffer; + } + } + /* types that sscanf can handle */ + else + { + int ret; + int n; + int size; + LPSTR newBuff = 0; + LPVOID voidPtr = NULL; + + size = WideCharToMultiByte(CP_ACP, 0, Buff, -1, 0, 0, 0, 0); + if (!size) + { + ASSERT("WideCharToMultiByte failed. Error is %d\n", + GetLastError()); + return -1; + } + newBuff = (LPSTR) PAL_malloc(size); + if (!newBuff) + { + ERROR("PAL_malloc failed\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return -1; + } + size = WideCharToMultiByte(CP_ACP, 0, Buff, size, + newBuff, size, 0, 0); + if (!size) + { + ASSERT("WideCharToMultiByte failed. Error is %d\n", + GetLastError()); + PAL_free(newBuff); + return -1; + } + + if (Store) + { + if (Type == SCANF_TYPE_BRACKETS) + { + WCHAR *strPtr; + int i; + + /* add a '*' to %[] --> %*[] */ + i = strlen(TempBuff) + 1; + while (i) + { + /* shift everything right one */ + TempBuff[i] = TempBuff[i - 1]; + --i; + } + TempBuff[0] = '%'; + TempBuff[1] = '*'; + + /* %n doesn't count as a conversion. Since we're + suppressing conversion of the %[], sscanf will + always return 0, so we can't use the return value + to determine success. Set n to 0 before the call; if + it's still 0 afterwards, we know the call failed */ + n = 0; + sscanf_s(newBuff, TempBuff, &n); + if(0 == n) + { + /* sscanf failed, nothing matched. set ret to 0, + so we know we have to break */ + ret = 0; + } + else + { + strPtr = va_arg(ap, WCHAR *); + for (i = 0; i < n; i++) + { + strPtr[i] = Buff[i]; + } + strPtr[n] = 0; /* end string */ + ret = 1; + } + } + else + { + voidPtr = va_arg(ap, LPVOID); + // sscanf_s requires that if we are trying to read "%s" or "%c", then + // the size of the buffer must follow the buffer we are trying to read into. + unsigned typeLen = 0; + if (Type == SCANF_TYPE_STRING) + { + // We don’t really know the size of the destination buffer provided by the + // caller. So we have to assume that the caller has allocated enough space + // to hold either the width specified in the format or the entire input + // string plus ‘\0’. + typeLen = ((Width > 0) ? Width : PAL_wcslen(Buffer)) + 1; + } + else if (Type == SCANF_TYPE_CHAR) + { + // Check whether the format string contains number of characters + // that should be read from the input string. + // Note: ‘\0’ does not get appended in the “%c†case. + typeLen = (Width > 0) ? Width : 1; + } + + if (typeLen > 0) + { + ret = sscanf_s(newBuff, TempBuff, voidPtr, typeLen, &n); + } + else + ret = sscanf_s(newBuff, TempBuff, voidPtr, &n); + } + } + else + { + ret = sscanf_s(newBuff, TempBuff, &n); + } + +#if SSCANF_CANNOT_HANDLE_MISSING_EXPONENT + if ((ret == 0) && (Type == SCANF_TYPE_FLOAT)) + { + ret = SscanfFloatCheckExponent(newBuff, TempBuff, voidPtr, &n); + } +#endif // SSCANF_CANNOT_HANDLE_MISSING_EXPONENT + + PAL_free(newBuff); + if (ret > 0) + { + Length += ret; + } + else + { + /* no match; break scan */ + break; + } + Buff += n; + } + } + else + { + /* grab, but not store */ + if (*Fmt == *Buff && Type != SCANF_TYPE_SPACE) + { + ++Fmt; + ++Buff; + } + /* doesn't match, break scan */ + else + { + break; + } + } + } + + return Length; +} + +/*++ +Function: + PAL_swscanf + +See MSDN doc. +--*/ +int +__cdecl +PAL_swscanf( + const wchar_16 *buffer, + const wchar_16 *format, + ...) +{ + int Length; + va_list ap; + + PERF_ENTRY(swscanf); + ENTRY("PAL_swscanf (buffer=%p (%S), format=%p (%S))\n", buffer, buffer, format, format); + + va_start(ap, format); + Length = PAL_wvsscanf(buffer, format, ap); + va_end(ap); + + LOGEXIT("PAL_swscanf returns int %d\n", Length); + PERF_EXIT(swscanf); + return Length; +} + + +#if SSCANF_CANNOT_HANDLE_MISSING_EXPONENT +/*++ +Function: + SscanfFloatCheckExponent + + Parameters: + buff: pointer to the buffer to be parsed; the target float must be at + the beginning of the buffer, except for any number of leading + spaces + floatFmt: must be "%e%n" (or "%f%n" or "%g%n") + voidptr: optional pointer to output variable (which should be a float) + pn: pointer to an int to receive the number of bytes parsed. + + Notes: + On some platforms (specifically AIX) sscanf fails to parse a float from + a string such as 12.34e (while it succeeds for e.g. 12.34a). Sscanf + initially interprets the 'e' as the keyword for the beginning of a + 10-exponent of a floating point in scientific notation (as in 12.34e5), + but then it fails to parse the actual exponent. At this point sscanf should + be able to fall back on the narrower pattern, and parse the floating point + in common decimal notation (i.e. 12.34). However AIX's sscanf fails to do + so and it does not parse any number. + This function checks the given string for a such case and removes + the 'e' before parsing the float. + +--*/ + +static int SscanfFloatCheckExponent(LPCSTR buff, LPCSTR floatFmt, + void * voidPtr, int * pn) +{ + int ret = 0; + int digits = 0; + int points = 0; + LPCSTR pos = buff; + + /* skip initial spaces */ + while (*pos && isspace(*pos)) + pos++; + + /* go to the end of a float, if there is one */ + while (*pos) + { + if (isdigit(*pos)) + digits++; + else if (*pos == '.') + { + if (++points > 1) + break; + } + else + break; + + pos++; + } + + /* check if it is something like 12.34e and the trailing 'e' is not + the suffix of a valid exponent of 10, such as 12.34e+5 */ + if ( digits > 0 && *pos && tolower(*pos) == 'e' && + !( *(pos+1) && + ( isdigit(*(pos+1)) || + ( (*(pos+1) == '+' || *(pos+1) == '-') && isdigit(*(pos+2)) ) + ) + ) + ) + { + CHAR * pLocBuf = (CHAR *)PAL_malloc((pos-buff+1)*sizeof(CHAR)); + if (pLocBuf) + { + memcpy(pLocBuf, buff, (pos-buff)*sizeof(CHAR)); + pLocBuf[pos-buff] = 0; + if (voidPtr) + ret = sscanf_s(pLocBuf, floatFmt, voidPtr, pn); + else + ret = sscanf_s(pLocBuf, floatFmt, pn); + PAL_free (pLocBuf); + } + } + return ret; +} +#endif // SSCANF_CANNOT_HANDLE_MISSING_EXPONENT diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/printfcpp.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/printfcpp.cpp new file mode 100644 index 0000000..037c3e9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/printfcpp.cpp @@ -0,0 +1,1773 @@ +// 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: + + printfcpp.cpp + +Abstract: + + Implementation of suspension safe printf functions. + +Revision History: + + + +--*/ + +#include "pal/corunix.hpp" +#include "pal/thread.hpp" +#include "pal/malloc.hpp" +#include "pal/file.hpp" +#include "pal/printfcpp.hpp" +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/cruntime.h" + +#include + +SET_DEFAULT_DEBUG_CHANNEL(CRT); + +using namespace CorUnix; + +static const char __nullstring[] = "(null)"; /* string to print on null ptr */ +static const WCHAR __wnullstring[] = W("(null)"); /* string to print on null ptr */ + +int CoreVfprintf(CPalThread *pthrCurrent, PAL_FILE *stream, const char *format, va_list ap); +int CoreVfwprintf(CPalThread *pthrCurrent, PAL_FILE *stream, const wchar_16 *format, va_list ap); + +extern "C" +{ + +/******************************************************************************* +Function: + Internal_Convertfwrite + This function is a wrapper around fwrite for cases where the buffer has + to be converted from WideChar to MultiByte +*******************************************************************************/ + +static int Internal_Convertfwrite(CPalThread *pthrCurrent, const void *buffer, size_t size, size_t count, FILE *stream, BOOL convert) +{ + int ret; + int iError = 0; + +#if FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL + clearerr (stream); +#endif + + if(convert) + { + int nsize; + LPSTR newBuff = 0; + nsize = WideCharToMultiByte(CP_ACP, 0,(LPCWSTR)buffer, count, 0, 0, 0, 0); + if (!nsize) + { + ASSERT("WideCharToMultiByte failed. Error is %d\n", GetLastError()); + return -1; + } + newBuff = (LPSTR) InternalMalloc(nsize); + if (!newBuff) + { + ERROR("InternalMalloc failed\n"); + pthrCurrent->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return -1; + } + nsize = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)buffer, count, newBuff, nsize, 0, 0); + if (!nsize) + { + ASSERT("WideCharToMultiByte failed. Error is %d\n", GetLastError()); + free(newBuff); + return -1; + } + ret = InternalFwrite(newBuff, 1, count, stream, &iError); + if (iError != 0) + { + ERROR("InternalFwrite did not write the whole buffer. Error is %d\n", iError); + free(newBuff); + return -1; + } + free(newBuff); + } + else + { + ret = InternalFwrite(buffer, size, count, stream, &iError); + if (iError != 0) + { + ERROR("InternalFwrite did not write the whole buffer. Error is %d\n", iError); + return -1; + } + } + return ret; + +} + +/******************************************************************************* +Function: + Internal_ExtractFormatA + +Paramaters: + Fmt + - format string to parse + - first character must be a '%' + - paramater gets updated to point to the character after + the % format string + Out + - buffer will contain the % format string + Flags + - paramater will be set with the PRINTF_FORMAT_FLAGS defined above + Width + - will contain the width specified by the format string + - -1 if none given + Precision + - will contain the precision specified in the format string + - -1 if none given + Prefix + - an enumeration of the type prefix + Type + - an enumeration of the type value + +Notes: + - I'm also handling the undocumented %ws, %wc, %w... + - %#10x, when we have a width greater than the length (i.e padding) the + length of the padding is not consistent with MS's wsprintf + (MS adds an extra 2 padding chars, length of "0x") + - MS's wsprintf seems to ingore a 'h' prefix for number types + - MS's "%p" is different than gcc's + e.g. printf("%p", NULL); + MS --> 00000000 + gcc --> 0x0 + - the length of the exponent (precision) for floating types is different + between MS and gcc + e.g. printf("%E", 256.0); + MS --> 2.560000E+002 + gcc --> 2.560000E+02 +*******************************************************************************/ +BOOL Internal_ExtractFormatA(CPalThread *pthrCurrent, LPCSTR *Fmt, LPSTR Out, LPINT Flags, + LPINT Width, LPINT Precision, LPINT Prefix, LPINT Type) +{ + BOOL Result = FALSE; + LPSTR TempStr; + LPSTR TempStrPtr; + + *Width = WIDTH_DEFAULT; + *Precision = PRECISION_DEFAULT; + *Flags = PFF_NONE; + *Prefix = PFF_PREFIX_DEFAULT; + *Type = PFF_TYPE_DEFAULT; + + if (*Fmt && **Fmt == '%') + { + *Out++ = *(*Fmt)++; + } + else + { + return Result; + } + + /* we'll never need a temp string longer than the original */ + TempStrPtr = TempStr = (LPSTR) InternalMalloc(strlen(*Fmt)+1); + if (!TempStr) + { + ERROR("InternalMalloc failed\n"); + pthrCurrent->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return Result; + } + + /* parse flags */ + while (**Fmt && (**Fmt == '-' || **Fmt == '+' || + **Fmt == '0' || **Fmt == ' ' || **Fmt == '#')) + { + switch (**Fmt) + { + case '-': + *Flags |= PFF_MINUS; break; + case '+': + *Flags |= PFF_PLUS; break; + case '0': + *Flags |= PFF_ZERO; break; + case ' ': + *Flags |= PFF_SPACE; break; + case '#': + *Flags |= PFF_POUND; break; + } + *Out++ = *(*Fmt)++; + } + /* '-' flag negates '0' flag */ + if ((*Flags & PFF_MINUS) && (*Flags & PFF_ZERO)) + { + *Flags -= PFF_ZERO; + } + + /* grab width specifier */ + if (isdigit((unsigned char) **Fmt)) + { + TempStrPtr = TempStr; + while (isdigit((unsigned char) **Fmt)) + { + *TempStrPtr++ = **Fmt; + *Out++ = *(*Fmt)++; + } + *TempStrPtr = 0; /* end string */ + *Width = atoi(TempStr); + if (*Width < 0) + { + ERROR("atoi returned a negative value indicative of an overflow.\n"); + pthrCurrent->SetLastError(ERROR_INTERNAL_ERROR); + return Result; + } + } + else if (**Fmt == '*') + { + *Width = WIDTH_STAR; + *Out++ = *(*Fmt)++; + if (isdigit((unsigned char) **Fmt)) + { + /* this is an invalid width because we have a * then a number */ + /* printf handles this by just printing the whole string */ + *Width = WIDTH_INVALID; + while (isdigit((unsigned char) **Fmt)) + { + *Out++ = *(*Fmt)++; + } + } + } + + + /* grab precision specifier */ + if (**Fmt == '.') + { + *Out++ = *(*Fmt)++; + if (isdigit((unsigned char) **Fmt)) + { + TempStrPtr = TempStr; + while (isdigit((unsigned char) **Fmt)) + { + *TempStrPtr++ = **Fmt; + *Out++ = *(*Fmt)++; + } + *TempStrPtr = 0; /* end string */ + *Precision = atoi(TempStr); + if (*Precision < 0) + { + ERROR("atoi returned a negative value indicative of an overflow.\n"); + pthrCurrent->SetLastError(ERROR_INTERNAL_ERROR); + return Result; + } + } + else if (**Fmt == '*') + { + *Precision = PRECISION_STAR; + *Out++ = *(*Fmt)++; + if (isdigit((unsigned char) **Fmt)) + { + /* this is an invalid precision because we have a .* then a number */ + /* printf handles this by just printing the whole string */ + *Precision = PRECISION_INVALID; + while (isdigit((unsigned char) **Fmt)) + { + *Out++ = *(*Fmt)++; + } + } + } + else + { + *Precision = PRECISION_DOT; + } + } + +#ifdef HOST_64BIT + if (**Fmt == 'p') + { + *Prefix = PFF_PREFIX_LONGLONG; + } +#endif + if ((*Fmt)[0] == 'I') + { + /* grab prefix of 'I64' for __int64 */ + if ((*Fmt)[1] == '6' && (*Fmt)[2] == '4') + { + /* convert to 'll' so that Unix snprintf can handle it */ + *Fmt += 3; + *Prefix = PFF_PREFIX_LONGLONG; + } + /* grab prefix of 'I32' for __int32 */ + else if ((*Fmt)[1] == '3' && (*Fmt)[2] == '2') + { + *Fmt += 3; + } + else + { + ++(*Fmt); + #ifdef HOST_64BIT + /* convert to 'll' so that Unix snprintf can handle it */ + *Prefix = PFF_PREFIX_LONGLONG; + #endif + } + } + /* grab a prefix of 'h' */ + else if (**Fmt == 'h') + { + *Prefix = PFF_PREFIX_SHORT; + ++(*Fmt); + } + /* grab prefix of 'l' or the undocumented 'w' (at least in MSDN) */ + else if (**Fmt == 'l' || **Fmt == 'w') + { + ++(*Fmt); +#ifdef HOST_64BIT + // Only want to change the prefix on 64 bit when printing characters. + if (**Fmt == 'c' || **Fmt == 's') +#endif + { + *Prefix = PFF_PREFIX_LONG; + } + if (**Fmt == 'l') + { + *Prefix = PFF_PREFIX_LONGLONG; + ++(*Fmt); + } + } + else if (**Fmt == 'L') + { + /* a prefix of 'L' seems to be ignored */ + ++(*Fmt); + } + + /* grab type 'c' */ + if (**Fmt == 'c' || **Fmt == 'C') + { + *Type = PFF_TYPE_CHAR; + if (*Prefix != PFF_PREFIX_SHORT && **Fmt == 'C') + { + *Prefix = PFF_PREFIX_LONG; /* give it a wide prefix */ + } + if (*Prefix == PFF_PREFIX_LONG) + { + *Out++ = 'l'; + } + *Out++ = 'c'; + ++(*Fmt); + Result = TRUE; + } + /* grab type 's' */ + else if (**Fmt == 's' || **Fmt == 'S') + { + *Type = PFF_TYPE_STRING; + if (*Prefix != PFF_PREFIX_SHORT && **Fmt == 'S') + { + *Prefix = PFF_PREFIX_LONG; /* give it a wide prefix */ + } + if (*Prefix == PFF_PREFIX_LONG) + { + *Out++ = 'l'; + } + *Out++ = 's'; + ++(*Fmt); + Result = TRUE; + } + /* grab int types */ + else if (**Fmt == 'd' || **Fmt == 'i' || **Fmt == 'o' || + **Fmt == 'u' || **Fmt == 'x' || **Fmt == 'X') + { + *Type = PFF_TYPE_INT; + if (*Prefix == PFF_PREFIX_SHORT) + { + *Out++ = 'h'; + } + else if (*Prefix == PFF_PREFIX_LONG) + { + *Out++ = 'l'; + } + else if (*Prefix == PFF_PREFIX_LONGLONG) + { + *Out++ = 'l'; + *Out++ = 'l'; + } + *Out++ = *(*Fmt)++; + Result = TRUE; + } + else if (**Fmt == 'e' || **Fmt == 'E' || **Fmt == 'f' || + **Fmt == 'g' || **Fmt == 'G') + { + /* we can safely ignore the prefixes and only add the type*/ + *Type = PFF_TYPE_FLOAT; + *Out++ = *(*Fmt)++; + Result = TRUE; + } + else if (**Fmt == 'n') + { + if (*Prefix == PFF_PREFIX_SHORT) + { + *Out++ = 'h'; + } + *Out++ = *(*Fmt)++; + *Type = PFF_TYPE_N; + Result = TRUE; + } + else if (**Fmt == 'p') + { + *Type = PFF_TYPE_P; + (*Fmt)++; + + if (*Prefix == PFF_PREFIX_LONGLONG) + { + if (*Precision == PRECISION_DEFAULT) + { + *Precision = 16; + *Out++ = '.'; + *Out++ = '1'; + *Out++ = '6'; + } + /* native *printf does not support %I64p + (actually %llp), so we need to cheat a little bit */ + *Out++ = 'l'; + *Out++ = 'l'; + } + else + { + if (*Precision == PRECISION_DEFAULT) + { + *Precision = 8; + *Out++ = '.'; + *Out++ = '8'; + } + } + *Out++ = 'X'; + Result = TRUE; + } + + *Out = 0; /* end the string */ + free(TempStr); + return Result; +} + +/******************************************************************************* +Function: + Internal_ExtractFormatW + + -- see Internal_ExtractFormatA above +*******************************************************************************/ +BOOL Internal_ExtractFormatW(CPalThread *pthrCurrent, LPCWSTR *Fmt, LPSTR Out, LPINT Flags, + LPINT Width, LPINT Precision, LPINT Prefix, LPINT Type) +{ + BOOL Result = FALSE; + LPSTR TempStr; + LPSTR TempStrPtr; + + *Width = WIDTH_DEFAULT; + *Precision = PRECISION_DEFAULT; + *Flags = PFF_NONE; + *Prefix = PFF_PREFIX_DEFAULT; + *Type = PFF_TYPE_DEFAULT; + + if (*Fmt && **Fmt == '%') + { + *Out++ = (CHAR) *(*Fmt)++; + } + else + { + return Result; + } + + /* we'll never need a temp string longer than the original */ + TempStrPtr = TempStr = (LPSTR) InternalMalloc(PAL_wcslen(*Fmt)+1); + if (!TempStr) + { + ERROR("InternalMalloc failed\n"); + pthrCurrent->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return Result; + } + + /* parse flags */ + while (**Fmt && (**Fmt == '-' || **Fmt == '+' || + **Fmt == '0' || **Fmt == ' ' || **Fmt == '#')) + { + switch (**Fmt) + { + case '-': + *Flags |= PFF_MINUS; break; + case '+': + *Flags |= PFF_PLUS; break; + case '0': + *Flags |= PFF_ZERO; break; + case ' ': + *Flags |= PFF_SPACE; break; + case '#': + *Flags |= PFF_POUND; break; + } + *Out++ = (CHAR) *(*Fmt)++; + } + /* '-' flag negates '0' flag */ + if ((*Flags & PFF_MINUS) && (*Flags & PFF_ZERO)) + { + *Flags -= PFF_ZERO; + } + + /* grab width specifier */ + if (isdigit(**Fmt)) + { + TempStrPtr = TempStr; + while (isdigit(**Fmt)) + { + *TempStrPtr++ = (CHAR) **Fmt; + *Out++ = (CHAR) *(*Fmt)++; + } + *TempStrPtr = 0; /* end string */ + *Width = atoi(TempStr); + if (*Width < 0) + { + ERROR("atoi returned a negative value indicative of an overflow.\n"); + pthrCurrent->SetLastError(ERROR_INTERNAL_ERROR); + return Result; + } + } + else if (**Fmt == '*') + { + *Width = WIDTH_STAR; + *Out++ = (CHAR) *(*Fmt)++; + if (isdigit(**Fmt)) + { + /* this is an invalid width because we have a * then a number */ + /* printf handles this by just printing the whole string */ + *Width = WIDTH_INVALID; + while (isdigit(**Fmt)) + { + *Out++ = (CHAR) *(*Fmt)++; + } + } + } + + /* grab precision specifier */ + if (**Fmt == '.') + { + *Out++ = (CHAR) *(*Fmt)++; + if (isdigit(**Fmt)) + { + TempStrPtr = TempStr; + while (isdigit(**Fmt)) + { + *TempStrPtr++ = (CHAR) **Fmt; + *Out++ = (CHAR) *(*Fmt)++; + } + *TempStrPtr = 0; /* end string */ + *Precision = atoi(TempStr); + if (*Precision < 0) + { + ERROR("atoi returned a negative value indicative of an overflow.\n"); + pthrCurrent->SetLastError(ERROR_INTERNAL_ERROR); + return Result; + } + } + else if (**Fmt == '*') + { + *Precision = PRECISION_STAR; + *Out++ = (CHAR) *(*Fmt)++; + if (isdigit(**Fmt)) + { + /* this is an invalid precision because we have a .* then a number */ + /* printf handles this by just printing the whole string */ + *Precision = PRECISION_INVALID; + while (isdigit(**Fmt)) + { + *Out++ = (CHAR) *(*Fmt)++; + } + } + } + else + { + *Precision = PRECISION_DOT; + } + } + +#ifdef HOST_64BIT + if (**Fmt == 'p') + { + *Prefix = PFF_PREFIX_LONGLONG; + } +#endif + if ((*Fmt)[0] == 'I') + { + /* grab prefix of 'I64' for __int64 */ + if ((*Fmt)[1] == '6' && (*Fmt)[2] == '4') + { + /* convert to 'll' so that Unix snprintf can handle it */ + *Fmt += 3; + *Prefix = PFF_PREFIX_LONGLONG; + } + /* grab prefix of 'I32' for __int32 */ + else if ((*Fmt)[1] == '3' && (*Fmt)[2] == '2') + { + *Fmt += 3; + } + else + { + ++(*Fmt); + #ifdef HOST_64BIT + /* convert to 'll' so that Unix snprintf can handle it */ + *Prefix = PFF_PREFIX_LONGLONG; + #endif + } + } + /* grab a prefix of 'h' */ + else if (**Fmt == 'h') + { + *Prefix = PFF_PREFIX_SHORT; + ++(*Fmt); + } + else if (**Fmt == 'l' || **Fmt == 'w') + { + ++(*Fmt); + #ifdef HOST_64BIT + // Only want to change the prefix on 64 bit when printing characters. + if (**Fmt == 'C' || **Fmt == 'S') +#endif + { + *Prefix = PFF_PREFIX_LONG_W; + } + if (**Fmt == 'l') + { + *Prefix = PFF_PREFIX_LONGLONG; + ++(*Fmt); + } + } + else if (**Fmt == 'L') + { + /* a prefix of 'L' seems to be ignored */ + ++(*Fmt); + } + + + /* grab type 'c' */ + if (**Fmt == 'c' || **Fmt == 'C') + { + *Type = PFF_TYPE_CHAR; + if (*Prefix != PFF_PREFIX_SHORT && **Fmt == 'c') + { + *Prefix = PFF_PREFIX_LONG; /* give it a wide prefix */ + } + if (*Prefix == PFF_PREFIX_LONG || *Prefix == PFF_PREFIX_LONG_W) + { + *Out++ = 'l'; + *Prefix = PFF_PREFIX_LONG; + } + *Out++ = 'c'; + ++(*Fmt); + Result = TRUE; + } + /* grab type 's' */ + else if (**Fmt == 's' || **Fmt == 'S' ) + { + if ( **Fmt == 'S' ) + { + *Type = PFF_TYPE_WSTRING; + } + else + { + *Type = PFF_TYPE_STRING; + } + if (*Prefix != PFF_PREFIX_SHORT && **Fmt == 's') + { + *Prefix = PFF_PREFIX_LONG; /* give it a wide prefix */ + } + if (*Prefix == PFF_PREFIX_LONG) + { + *Out++ = 'l'; + } + + *Out++ = 's'; + ++(*Fmt); + Result = TRUE; + } + /* grab int types */ + else if (**Fmt == 'd' || **Fmt == 'i' || **Fmt == 'o' || + **Fmt == 'u' || **Fmt == 'x' || **Fmt == 'X') + { + *Type = PFF_TYPE_INT; + if (*Prefix == PFF_PREFIX_SHORT) + { + *Out++ = 'h'; + } + else if (*Prefix == PFF_PREFIX_LONG || *Prefix == PFF_PREFIX_LONG_W) + { + *Out++ = 'l'; + *Prefix = PFF_PREFIX_LONG; + } + else if (*Prefix == PFF_PREFIX_LONGLONG) + { + *Out++ = 'l'; + *Out++ = 'l'; + } + *Out++ = *(*Fmt)++; + Result = TRUE; + } + else if (**Fmt == 'e' || **Fmt == 'E' || **Fmt == 'f' || + **Fmt == 'g' || **Fmt == 'G') + { + /* we can safely ignore the prefixes and only add the type*/ + if (*Prefix == PFF_PREFIX_LONG_W) + { + *Prefix = PFF_PREFIX_LONG; + } + + *Type = PFF_TYPE_FLOAT; + *Out++ = *(*Fmt)++; + Result = TRUE; + } + else if (**Fmt == 'n') + { + if (*Prefix == PFF_PREFIX_LONG_W) + { + *Prefix = PFF_PREFIX_LONG; + } + + if (*Prefix == PFF_PREFIX_SHORT) + { + *Out++ = 'h'; + } + *Out++ = *(*Fmt)++; + *Type = PFF_TYPE_N; + Result = TRUE; + } + else if (**Fmt == 'p') + { + *Type = PFF_TYPE_P; + (*Fmt)++; + + if (*Prefix == PFF_PREFIX_LONGLONG) + { + if (*Precision == PRECISION_DEFAULT) + { + *Precision = 16; + *Out++ = '.'; + *Out++ = '1'; + *Out++ = '6'; + } + /* native *printf does not support %I64p + (actually %llp), so we need to cheat a little bit */ + *Out++ = 'l'; + *Out++ = 'l'; + } + else + { + if (*Precision == PRECISION_DEFAULT) + { + *Precision = 8; + *Out++ = '.'; + *Out++ = '8'; + } + if (*Prefix == PFF_PREFIX_LONG_W) + { + *Prefix = PFF_PREFIX_LONG; + } + } + *Out++ = 'X'; + Result = TRUE; + } + + *Out = 0; /* end the string */ + free(TempStr); + return Result; +} + +/******************************************************************************* +Function: + Internal_AddPaddingVfprintf + +Parameters: + stream + - file stream to place padding and given string (In) + In + - string to place into (Out) accompanied with padding + Padding + - number of padding chars to add + Flags + - padding style flags (PRINTF_FORMAT_FLAGS) +*******************************************************************************/ + +INT Internal_AddPaddingVfprintf(CPalThread *pthrCurrent, PAL_FILE *stream, LPCSTR In, + INT Padding, INT Flags) +{ + LPSTR Out; + INT LengthInStr; + INT Length; + LPSTR OutOriginal; + INT Written; + + LengthInStr = strlen(In); + Length = LengthInStr; + + if (Padding > 0) + { + Length += Padding; + } + Out = (LPSTR) InternalMalloc(Length+1); + int iLength = Length+1; + if (!Out) + { + ERROR("InternalMalloc failed\n"); + pthrCurrent->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return -1; + } + OutOriginal = Out; + + if (Flags & PFF_MINUS) /* pad on right */ + { + if (strcpy_s(Out, iLength, In) != SAFECRT_SUCCESS) + { + ERROR("strcpy_s failed\n"); + pthrCurrent->SetLastError(ERROR_INSUFFICIENT_BUFFER); + Written = -1; + goto Done; + } + + Out += LengthInStr; + iLength -= LengthInStr; + } + if (Padding > 0) + { + iLength -= Padding; + if (Flags & PFF_ZERO) /* '0', pad with zeros */ + { + while (Padding--) + { + *Out++ = '0'; + } + } + else /* pad with spaces */ + { + while (Padding--) + { + *Out++ = ' '; + } + } + } + if (!(Flags & PFF_MINUS)) /* put 'In' after padding */ + { + if (strcpy_s(Out, iLength, In) != SAFECRT_SUCCESS) + { + ERROR("strcpy_s failed\n"); + pthrCurrent->SetLastError(ERROR_INSUFFICIENT_BUFFER); + Written = -1; + goto Done; + } + + Out += LengthInStr; + iLength -= LengthInStr; + } + +#if FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL + clearerr (stream->bsdFilePtr); +#endif + + Written = InternalFwrite(OutOriginal, 1, Length, stream->bsdFilePtr, &stream->PALferrorCode); + if (stream->PALferrorCode == PAL_FILE_ERROR) + { + ERROR("fwrite() failed with errno == %d\n", errno); + } + +Done: + free(OutOriginal); + + return Written; +} + +/******************************************************************************* +Function: + Internal_AddPaddingVfwprintf + +Parameters: + stream + - file stream to place padding and given string (In) + In + - string to place into (Out) accompanied with padding + Padding + - number of padding chars to add + Flags + - padding style flags (PRINTF_FORMAT_FLAGS) +*******************************************************************************/ +static INT Internal_AddPaddingVfwprintf(CPalThread *pthrCurrent, PAL_FILE *stream, LPWSTR In, + INT Padding, INT Flags,BOOL convert) +{ + LPWSTR Out; + LPWSTR OutOriginal; + INT LengthInStr; + INT Length; + INT Written = 0; + + LengthInStr = PAL_wcslen(In); + Length = LengthInStr; + + if (Padding > 0) + { + Length += Padding; + } + + int iLen = (Length+1); + Out = (LPWSTR) InternalMalloc(iLen * sizeof(WCHAR)); + if (!Out) + { + ERROR("InternalMalloc failed\n"); + pthrCurrent->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return -1; + } + OutOriginal = Out; + + if (Flags & PFF_MINUS) /* pad on right */ + { + if (wcscpy_s(Out, iLen, In) != SAFECRT_SUCCESS) + { + ERROR("wcscpy_s failed!\n"); + free(OutOriginal); + pthrCurrent->SetLastError(ERROR_INSUFFICIENT_BUFFER); + return -1; + } + Out += LengthInStr; + iLen -= LengthInStr; + } + if (Padding > 0) + { + iLen -= Padding; + if (Flags & PFF_ZERO) /* '0', pad with zeros */ + { + while (Padding--) + { + *Out++ = '0'; + } + } + else /* pad with spaces */ + { + while (Padding--) + { + *Out++ = ' '; + } + } + } + if (!(Flags & PFF_MINUS)) /* put 'In' after padding */ + { + if (wcscpy_s(Out, iLen, In) != SAFECRT_SUCCESS) + { + ERROR("wcscpy_s failed!\n"); + free(OutOriginal); + pthrCurrent->SetLastError(ERROR_INSUFFICIENT_BUFFER); + return -1; + } + + Out += LengthInStr; + iLen -= LengthInStr; + } + + if (Length > 0) { + Written = Internal_Convertfwrite(pthrCurrent, OutOriginal, sizeof(wchar_16), Length, + (FILE*)(stream->bsdFilePtr), convert); + + if (-1 == Written) + { + ERROR("fwrite() failed with errno == %d\n", errno); + } + free(OutOriginal); + } + + return Written; +} + +/******************************************************************************* +Function: + PAL_vfprintf + +Parameters: + stream + - out stream + Format + - format string + ap + - stdarg parameter list +*******************************************************************************/ + +int __cdecl PAL_vfprintf(PAL_FILE *stream, const char *format, va_list ap) +{ + return CoreVfprintf(InternalGetCurrentThread(), stream, format, ap); +} + +/******************************************************************************* +Function: + PAL_vfwprintf + +Parameters: + stream + - out stream + Format + - format string + ap + - stdarg parameter list +*******************************************************************************/ + +int __cdecl PAL_vfwprintf(PAL_FILE *stream, const wchar_16 *format, va_list ap) +{ + return CoreVfwprintf(InternalGetCurrentThread(), stream, format, ap); +} + +} // end extern "C" + +int CorUnix::InternalVfprintf(CPalThread *pthrCurrent, PAL_FILE *stream, const char *format, va_list ap) +{ + return CoreVfprintf(pthrCurrent, stream, format, ap); +} + +int CoreVfwprintf(CPalThread *pthrCurrent, PAL_FILE *stream, const wchar_16 *format, va_list aparg) +{ + CHAR TempBuff[1024]; /* used to hold a single % format string */ + LPCWSTR Fmt = format; + LPCWSTR TempWStr = NULL; + LPWSTR AllocedTempWStr = NULL; + LPWSTR WorkingWStr = NULL; + WCHAR TempWChar[2]; + INT Flags; + INT Width; + INT Precision; + INT Prefix; + INT Type; + INT TempInt; + int mbtowcResult; + int written=0; + int paddingReturnValue; + int ret; + va_list ap; + + /* fwprintf for now in the PAL is always used on file opened + in text mode. In those case the output should be ANSI not Unicode */ + BOOL textMode = TRUE; + + PERF_ENTRY(vfwprintf); + ENTRY("vfwprintf (stream=%p, format=%p (%S))\n", + stream, format, format); + + va_copy(ap, aparg); + + while (*Fmt) + { + if(*Fmt == '%' && + TRUE == Internal_ExtractFormatW(pthrCurrent, &Fmt, TempBuff, &Flags, + &Width, &Precision, + &Prefix, &Type)) + { + if (((Prefix == PFF_PREFIX_LONG || Prefix == PFF_PREFIX_LONG_W) && + (Type == PFF_TYPE_STRING || Type == PFF_TYPE_WSTRING)) || + (Type == PFF_TYPE_WSTRING && (Flags & PFF_ZERO) != 0)) + { + AllocedTempWStr = NULL; + + if (WIDTH_STAR == Width) + { + Width = va_arg(ap, INT); + } + else if (WIDTH_INVALID == Width) + { + /* both a '*' and a number, ignore, but remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } + + if (PRECISION_STAR == Precision) + { + Precision = va_arg(ap, INT); + } + else if (PRECISION_INVALID == Precision) + { + /* both a '*' and a number, ignore, but remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } + + if (Type == PFF_TYPE_STRING || Prefix == PFF_PREFIX_LONG_W) + { + TempWStr = va_arg(ap, LPWSTR); + } + else + { + /* %lS assumes a LPSTR argument. */ + LPCSTR s = va_arg(ap, LPSTR ); + if (s == NULL) + { + TempWStr = NULL; + } + else + { + UINT Length = 0; + Length = MultiByteToWideChar( CP_ACP, 0, s, -1, NULL, 0 ); + if ( Length != 0 ) + { + AllocedTempWStr = + (LPWSTR)InternalMalloc( (Length) * sizeof( WCHAR ) ); + + if ( AllocedTempWStr ) + { + MultiByteToWideChar( CP_ACP, 0, s, -1, + AllocedTempWStr, Length ); + TempWStr = AllocedTempWStr; + } + else + { + ERROR( "InternalMalloc failed.\n" ); + LOGEXIT("vfwprintf returns int -1\n"); + PERF_EXIT(vfwprintf); + va_end(ap); + return -1; + } + } + else + { + ASSERT( "Unable to convert from multibyte " + " to wide char.\n" ); + LOGEXIT("vfwprintf returns int -1\n"); + PERF_EXIT(vfwprintf); + va_end(ap); + return -1; + } + } + } + + if (TempWStr == NULL) + { + TempWStr = __wnullstring; + } + + INT Length = PAL_wcslen(TempWStr); + WorkingWStr = (LPWSTR) InternalMalloc((sizeof(WCHAR) * (Length + 1))); + if (!WorkingWStr) + { + ERROR("InternalMalloc failed\n"); + LOGEXIT("vfwprintf returns int -1\n"); + PERF_EXIT(vfwprintf); + pthrCurrent->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + free(AllocedTempWStr); + va_end(ap); + return -1; + } + if (PRECISION_DOT == Precision) + { + /* copy nothing */ + *WorkingWStr = 0; + Length = 0; + } + else if (Precision > 0 && Precision < Length) + { + if (wcsncpy_s(WorkingWStr, (Length + 1), TempWStr, Precision+1) != SAFECRT_SUCCESS) + { + ERROR("Internal_AddPaddingVfwprintf failed\n"); + free(AllocedTempWStr); + free(WorkingWStr); + LOGEXIT("wcsncpy_s failed!\n"); + PERF_EXIT(vfwprintf); + va_end(ap); + return (-1); + } + + Length = Precision; + } + /* copy everything */ + else + { + PAL_wcscpy(WorkingWStr, TempWStr); + } + + + /* do the padding (if needed)*/ + paddingReturnValue = + Internal_AddPaddingVfwprintf( pthrCurrent, stream, WorkingWStr, + Width - Length, + Flags,textMode); + + if (paddingReturnValue == -1) + { + ERROR("Internal_AddPaddingVfwprintf failed\n"); + free(AllocedTempWStr); + free(WorkingWStr); + LOGEXIT("vfwprintf returns int -1\n"); + PERF_EXIT(vfwprintf); + va_end(ap); + return (-1); + } + written += paddingReturnValue; + + free(WorkingWStr); + free(AllocedTempWStr); + } + else if (Prefix == PFF_PREFIX_LONG && Type == PFF_TYPE_CHAR) + { + if (WIDTH_STAR == Width || + WIDTH_INVALID == Width) + { + /* ignore (because it's a char), and remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } + + if (PRECISION_STAR == Precision || + PRECISION_INVALID == Precision) + { + /* ignore (because it's a char), and remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } + + TempWChar[0] = va_arg(ap, int); + TempWChar[1] = 0; + + /* do the padding (if needed)*/ + paddingReturnValue = + Internal_AddPaddingVfwprintf(pthrCurrent, stream, TempWChar, + Width - 1, + Flags,textMode); + if (paddingReturnValue == -1) + { + ERROR("Internal_AddPaddingVfwprintf failed\n"); + LOGEXIT("vfwprintf returns int -1\n"); + PERF_EXIT(vfwprintf); + va_end(ap); + return(-1); + } + written += paddingReturnValue; + } + /* this places the number of bytes written to the buffer in the + next arg */ + else if (Type == PFF_TYPE_N) + { + if (WIDTH_STAR == Width) + { + Width = va_arg(ap, INT); + } + + if (PRECISION_STAR == Precision) + { + Precision = va_arg(ap, INT); + } + + if (Prefix == PFF_PREFIX_SHORT) + { + *(va_arg(ap, short *)) = written; + } + else + { + *(va_arg(ap, LPLONG)) = written; + } + } + else + { + // Types that sprintf can handle. + + /* note: I'm using the wide buffer as a (char *) buffer when I + pass it to sprintf(). After I get the buffer back I make a + backup of the chars copied and then convert them to wide + and place them in the buffer (BufferPtr) */ + + // This argument will be limited to 1024 characters. + // It should be enough. + size_t TEMP_COUNT = 1024; + char TempSprintfStrBuffer[1024]; + char *TempSprintfStrPtr = NULL; + char *TempSprintfStr = TempSprintfStrBuffer; + LPWSTR TempWideBuffer; + + TempInt = 0; + // %h (short) doesn't seem to be handled properly by local sprintf, + // so we do the truncation ourselves for some cases. + if (Type == PFF_TYPE_P && Prefix == PFF_PREFIX_SHORT) + { + // Convert from pointer -> int -> short to avoid warnings. + long trunc1; + short trunc2; + + trunc1 = va_arg(ap, LONG); + trunc2 = (short)trunc1; + trunc1 = trunc2; + + TempInt = snprintf(TempSprintfStr, TEMP_COUNT, TempBuff, trunc1); + + if (TempInt < 0 || static_cast(TempInt) >= TEMP_COUNT) + { + if (NULL == (TempSprintfStrPtr = (char*)InternalMalloc(++TempInt))) + { + ERROR("InternalMalloc failed\n"); + LOGEXIT("vfwprintf returns int -1\n"); + PERF_EXIT(vfwprintf); + pthrCurrent->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + va_end(ap); + return -1; + } + + TempSprintfStr = TempSprintfStrPtr; + snprintf(TempSprintfStr, TempInt, TempBuff, trunc2); + } + } + else if (Type == PFF_TYPE_INT && Prefix == PFF_PREFIX_SHORT) + { + // Convert explicitly from int to short to get + // correct sign extension for shorts on all systems. + int n; + short s; + + n = va_arg(ap, int); + s = (short) n; + + TempInt = snprintf(TempSprintfStr, TEMP_COUNT, TempBuff, s); + + if (TempInt < 0 || static_cast(TempInt) >= TEMP_COUNT) + { + if (NULL == (TempSprintfStrPtr = (char*)InternalMalloc(++TempInt))) + { + ERROR("InternalMalloc failed\n"); + LOGEXIT("vfwprintf returns int -1\n"); + PERF_EXIT(vfwprintf); + pthrCurrent->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + va_end(ap); + return -1; + } + + TempSprintfStr = TempSprintfStrPtr; + snprintf(TempSprintfStr, TempInt, TempBuff, s); + } + } + else + { + va_list apcopy; + + va_copy(apcopy, ap); + TempInt = _vsnprintf_s(TempSprintfStr, TEMP_COUNT, _TRUNCATE, TempBuff, apcopy); + va_end(apcopy); + PAL_printf_arg_remover(&ap, Width, Precision, Type, Prefix); + + if (TempInt < 0 || static_cast(TempInt) >= TEMP_COUNT) + { + if (NULL == (TempSprintfStrPtr = (char*)InternalMalloc(++TempInt))) + { + ERROR("InternalMalloc failed\n"); + LOGEXIT("vfwprintf returns int -1\n"); + PERF_EXIT(vfwprintf); + pthrCurrent->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + va_end(ap); + return -1; + } + + TempSprintfStr = TempSprintfStrPtr; + va_copy(apcopy, ap); + _vsnprintf_s(TempSprintfStr, TempInt, _TRUNCATE, TempBuff, apcopy); + va_end(apcopy); + PAL_printf_arg_remover(&ap, Width, Precision, Type, Prefix); + } + } + + mbtowcResult = MultiByteToWideChar(CP_ACP, 0, + TempSprintfStr, -1, + NULL, 0); + + if (mbtowcResult == 0) + { + ERROR("MultiByteToWideChar failed\n"); + if(TempSprintfStrPtr) + { + free(TempSprintfStrPtr); + } + LOGEXIT("vfwprintf returns int -1\n"); + PERF_EXIT(vfwprintf); + va_end(ap); + return -1; + } + + TempWideBuffer = (LPWSTR) InternalMalloc(mbtowcResult*sizeof(WCHAR)); + if (!TempWideBuffer) + { + ERROR("InternalMalloc failed\n"); + LOGEXIT("vfwprintf returns int -1\n"); + PERF_EXIT(vfwprintf); + pthrCurrent->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + if(TempSprintfStrPtr) + { + free(TempSprintfStrPtr); + } + va_end(ap); + return -1; + } + + MultiByteToWideChar(CP_ACP, 0, TempSprintfStr, -1, + TempWideBuffer, mbtowcResult); + + ret = Internal_Convertfwrite( + pthrCurrent, + TempWideBuffer, + sizeof(wchar_16), + mbtowcResult-1, + (FILE*)stream->bsdFilePtr, + textMode); + + if (-1 == ret) + { + ERROR("fwrite() failed with errno == %d (%s)\n", errno, strerror(errno)); + LOGEXIT("vfwprintf returns int -1\n"); + PERF_EXIT(vfwprintf); + free(TempWideBuffer); + if(TempSprintfStrPtr) + { + free(TempSprintfStrPtr); + } + va_end(ap); + return -1; + } + if(TempSprintfStrPtr) + { + free(TempSprintfStrPtr); + } + free(TempWideBuffer); + } + } + else + { + ret = Internal_Convertfwrite( + pthrCurrent, + Fmt++, + sizeof(wchar_16), + 1, + (FILE*)stream->bsdFilePtr, + textMode); /* copy regular chars into buffer */ + + if (-1 == ret) + { + ERROR("fwrite() failed with errno == %d\n", errno); + LOGEXIT("vfwprintf returns int -1\n"); + PERF_EXIT(vfwprintf); + va_end(ap); + return -1; + } + ++written; + } + } + + LOGEXIT("vfwprintf returns int %d\n", written); + PERF_EXIT(vfwprintf); + va_end(ap); + return (written); +} + +int CoreVfprintf(CPalThread *pthrCurrent, PAL_FILE *stream, const char *format, va_list aparg) +{ + CHAR TempBuff[1024]; /* used to hold a single % format string */ + LPCSTR Fmt = format; + LPCWSTR TempWStr; + LPSTR TempStr; + WCHAR TempWChar; + INT Flags; + INT Width; + INT Precision; + INT Prefix; + INT Type; + INT Length; + INT TempInt; + int wctombResult; + int written = 0; + int paddingReturnValue; + va_list ap; + + PERF_ENTRY(vfprintf); + + va_copy(ap, aparg); + + while (*Fmt) + { + if (*Fmt == '%' && + TRUE == Internal_ExtractFormatA(pthrCurrent, &Fmt, TempBuff, &Flags, + &Width, &Precision, + &Prefix, &Type)) + { + if (Prefix == PFF_PREFIX_LONG && Type == PFF_TYPE_STRING) + { + if (WIDTH_STAR == Width) + { + Width = va_arg(ap, INT); + } + else if (WIDTH_INVALID == Width) + { + /* both a '*' and a number, ignore, but remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } + + if (PRECISION_STAR == Precision) + { + Precision = va_arg(ap, INT); + } + else if (PRECISION_INVALID == Precision) + { + /* both a '*' and a number, ignore, but remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } + + TempWStr = va_arg(ap, LPWSTR); + if (TempWStr == NULL)\ + { + TempWStr = __wnullstring; + } + Length = WideCharToMultiByte(CP_ACP, 0, TempWStr, -1, 0, + 0, 0, 0); + if (!Length) + { + ASSERT("WideCharToMultiByte failed. Error is %d\n", + GetLastError()); + PERF_EXIT(vfprintf); + va_end(ap); + return -1; + } + TempStr = (LPSTR) InternalMalloc(Length); + if (!TempStr) + { + ERROR("InternalMalloc failed\n"); + pthrCurrent->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + PERF_EXIT(vfprintf); + va_end(ap); + return -1; + } + if (PRECISION_DOT == Precision) + { + /* copy nothing */ + *TempStr = 0; + Length = 0; + } + else if (Precision > 0 && Precision < Length - 1) + { + Length = WideCharToMultiByte(CP_ACP, 0, TempWStr, + Precision, TempStr, Length, + 0, 0); + if (!Length) + { + ASSERT("WideCharToMultiByte failed. Error is %d\n", + GetLastError()); + free(TempStr); + PERF_EXIT(vfprintf); + va_end(ap); + return -1; + } + TempStr[Length] = 0; + Length = Precision; + } + /* copy everything */ + else + { + wctombResult = WideCharToMultiByte(CP_ACP, 0, TempWStr, -1, + TempStr, Length, 0, 0); + if (!wctombResult) + { + ASSERT("WideCharToMultiByte failed. Error is %d\n", + GetLastError()); + free(TempStr); + PERF_EXIT(vfprintf); + va_end(ap); + return -1; + } + --Length; /* exclude null char */ + } + + /* do the padding (if needed)*/ + paddingReturnValue = + Internal_AddPaddingVfprintf(pthrCurrent, stream, TempStr, + Width - Length, Flags); + if (-1 == paddingReturnValue) + { + ERROR("Internal_AddPaddingVfprintf failed\n"); + free(TempStr); + PERF_EXIT(vfprintf); + va_end(ap); + return -1; + } + written += paddingReturnValue; + + free(TempStr); + } + else if (Prefix == PFF_PREFIX_LONG && Type == PFF_TYPE_CHAR) + { + CHAR TempBuffer[5]; + if (WIDTH_STAR == Width || + WIDTH_INVALID == Width) + { + /* ignore (because it's a char), and remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } + if (PRECISION_STAR == Precision || + PRECISION_INVALID == Precision) + { + /* ignore (because it's a char), and remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } + + TempWChar = va_arg(ap, int); + Length = WideCharToMultiByte(CP_ACP, 0, &TempWChar, 1, + TempBuffer, sizeof(TempBuffer), + 0, 0); + if (!Length) + { + ASSERT("WideCharToMultiByte failed. Error is %d\n", + GetLastError()); + PERF_EXIT(vfprintf); + va_end(ap); + return -1; + } + TempBuffer[Length] = 0; + + /* do the padding (if needed)*/ + paddingReturnValue = + Internal_AddPaddingVfprintf(pthrCurrent, stream, TempBuffer, + Width - Length, Flags); + if (-1 == paddingReturnValue) + { + ERROR("Internal_AddPaddingVfprintf failed\n"); + PERF_EXIT(vfprintf); + va_end(ap); + return -1; + } + written += paddingReturnValue; + + } + /* this places the number of bytes written to the buffer in the + next arg */ + else if (Type == PFF_TYPE_N) + { + if (WIDTH_STAR == Width) + { + Width = va_arg(ap, INT); + } + if (PRECISION_STAR == Precision) + { + Precision = va_arg(ap, INT); + } + + if (Prefix == PFF_PREFIX_SHORT) + { + *(va_arg(ap, short *)) = written; + } + else + { + *(va_arg(ap, LPLONG)) = written; + } + } + else if (Type == PFF_TYPE_CHAR && (Flags & PFF_ZERO) != 0) + { + // Some versions of fprintf don't support 0-padded chars, + // so we handle them here. + char ch[2]; + + ch[0] = (char) va_arg(ap, int); + ch[1] = '\0'; + Length = 1; + paddingReturnValue = Internal_AddPaddingVfprintf( + pthrCurrent, + stream, + ch, + Width - Length, + Flags); + if (-1 == paddingReturnValue) + { + ERROR("Internal_AddPaddingVfprintf failed\n"); + PERF_EXIT(vfprintf); + va_end(ap); + return -1; + } + written += paddingReturnValue; + } + else if (Type == PFF_TYPE_STRING && (Flags & PFF_ZERO) != 0) + { + // Some versions of fprintf don't support 0-padded strings, + // so we handle them here. + const char *tempStr; + + tempStr = va_arg(ap, char *); + if (tempStr == NULL) + { + tempStr = __nullstring; + } + Length = strlen(tempStr); + paddingReturnValue = Internal_AddPaddingVfprintf( + pthrCurrent, + stream, + tempStr, + Width - Length, + Flags); + if (-1 == paddingReturnValue) + { + ERROR("Internal_AddPaddingVfprintf failed\n"); + PERF_EXIT(vfprintf); + va_end(ap); + return -1; + } + written += paddingReturnValue; + } + else + { + // Types that fprintf can handle. + TempInt = 0; + + // %h (short) doesn't seem to be handled properly by local sprintf, + // so we do the truncation ourselves for some cases. + if (Type == PFF_TYPE_P && Prefix == PFF_PREFIX_SHORT) + { + // Convert from pointer -> int -> short to avoid warnings. + long trunc1; + short trunc2; + + trunc1 = va_arg(ap, LONG); + trunc2 = (short)trunc1; + trunc1 = trunc2; + + TempInt = fprintf(stream->bsdFilePtr, TempBuff, trunc1); + } + else if (Type == PFF_TYPE_INT && Prefix == PFF_PREFIX_SHORT) + { + // Convert explicitly from int to short to get + // correct sign extension for shorts on all systems. + int n; + short s; + + n = va_arg(ap, int); + s = (short) n; + + TempInt = fprintf( stream->bsdFilePtr, TempBuff, s); + } + else + { + va_list apcopy; + va_copy(apcopy, ap); + TempInt = vfprintf(stream->bsdFilePtr, TempBuff, apcopy); + va_end(apcopy); + PAL_printf_arg_remover(&ap, Width, Precision, Type, Prefix); + } + + if (-1 == TempInt) + { + ERROR("vfprintf returned an error\n"); + } + else + { + written += TempInt; + } + } + } + else + { + +#if FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL + clearerr (stream->bsdFilePtr); +#endif + + InternalFwrite(Fmt++, 1, 1, stream->bsdFilePtr, &stream->PALferrorCode); /* copy regular chars into buffer */ + if (stream->PALferrorCode == PAL_FILE_ERROR) + { + ERROR("fwrite() failed with errno == %d\n", errno); + PERF_EXIT(vfprintf); + va_end(ap); + return -1; + } + ++written; + } + } + + va_end(ap); + + PERF_EXIT(vfprintf); + return written; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/silent_printf.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/silent_printf.cpp new file mode 100644 index 0000000..9a34a39 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/silent_printf.cpp @@ -0,0 +1,709 @@ +// 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: + + silent_printf.c + +Abstract: + + Implementation of a silent version of PAL_vsprintf and PAL_vfprintf function. + (without any reference to TRACE/ERROR/... macros, needed by the tracing macros) + +Revision History: + + + +--*/ + + +#include "pal/palinternal.h" +#include "pal/cruntime.h" +#include "pal/printfcpp.hpp" +#include "pal/thread.hpp" + +/* clip strings (%s, %S) at this number of characters */ +#define MAX_STR_LEN 300 + +static int Silent_WideCharToMultiByte(LPCWSTR lpWideCharStr, int cchWideChar, + LPSTR lpMultiByteStr, int cbMultiByte); +static BOOL Silent_ExtractFormatA(LPCSTR *Fmt, LPSTR Out, LPINT Flags, LPINT Width, + LPINT Precision, LPINT Prefix, LPINT Type); +static INT Silent_AddPaddingVfprintf(PAL_FILE *stream, LPSTR In, INT Padding, + INT Flags); + +static size_t Silent_PAL_wcslen(const wchar_16 *string); + +/*++ +Function: + PAL_vfprintf (silent version) + + for more details, see PAL_vfprintf in printf.c +--*/ +int Silent_PAL_vfprintf(PAL_FILE *stream, const char *format, va_list aparg) +{ + CHAR TempBuff[1024]; /* used to hold a single % format string */ + LPCSTR Fmt = format; + LPWSTR TempWStr; + LPSTR TempStr; + WCHAR TempWChar; + INT Flags; + INT Width; + INT Precision; + INT Prefix; + INT Type; + INT Length; + INT TempInt; + int wctombResult; + int written = 0; + int paddingReturnValue; + va_list ap; + + va_copy(ap, aparg); + + while (*Fmt) + { + if (*Fmt == '%' && + TRUE == Silent_ExtractFormatA(&Fmt, TempBuff, &Flags, &Width, + &Precision, &Prefix, &Type)) + { + if (Prefix == PFF_PREFIX_LONG && Type == PFF_TYPE_STRING) + { + if (WIDTH_STAR == Width) + { + Width = va_arg(ap, INT); + } + else if (WIDTH_INVALID == Width) + { + /* both a '*' and a number, ignore, but remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } + + if (PRECISION_STAR == Precision) + { + Precision = va_arg(ap, INT); + } + else if (PRECISION_INVALID == Precision) + { + /* both a '*' and a number, ignore, but remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } + + TempWStr = va_arg(ap, LPWSTR); + Length = Silent_WideCharToMultiByte(TempWStr, -1, 0, 0); + if (!Length) + { + va_end(ap); + return -1; + } + TempStr = (LPSTR) PAL_malloc(Length); + if (!TempStr) + { + va_end(ap); + return -1; + } + if (PRECISION_DOT == Precision) + { + /* copy nothing */ + *TempStr = 0; + Length = 0; + } + else if (Precision > 0 && Precision < Length - 1) + { + Length = Silent_WideCharToMultiByte(TempWStr, Precision, + TempStr, Length); + if (!Length) + { + PAL_free(TempStr); + va_end(ap); + return -1; + } + TempStr[Length] = 0; + Length = Precision; + } + /* copy everything */ + else + { + wctombResult = Silent_WideCharToMultiByte(TempWStr, -1, + TempStr, Length); + if (!wctombResult) + { + PAL_free(TempStr); + va_end(ap); + return -1; + } + --Length; /* exclude null char */ + } + + /* do the padding (if needed)*/ + paddingReturnValue = + Silent_AddPaddingVfprintf(stream, TempStr, Width - Length, Flags); + if (-1 == paddingReturnValue) + { + PAL_free(TempStr); + va_end(ap); + return -1; + } + written += paddingReturnValue; + + PAL_free(TempStr); + } + else if (Prefix == PFF_PREFIX_LONG && Type == PFF_TYPE_CHAR) + { + CHAR TempBuffer[4]; + if (WIDTH_STAR == Width || + WIDTH_INVALID == Width) + { + /* ignore (because it's a char), and remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } + if (PRECISION_STAR == Precision || + PRECISION_INVALID == Precision) + { + /* ignore (because it's a char), and remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } + + TempWChar = va_arg(ap, int); + Length = Silent_WideCharToMultiByte(&TempWChar, 1, TempBuffer, 4); + if (!Length) + { + va_end(ap); + return -1; + } + TempBuffer[Length] = 0; + + /* do the padding (if needed)*/ + paddingReturnValue = + Silent_AddPaddingVfprintf(stream, TempBuffer, + Width - Length, Flags); + if (-1 == paddingReturnValue) + { + va_end(ap); + return -1; + } + written += paddingReturnValue; + + } + /* this places the number of bytes written to the buffer in the + next arg */ + else if (Type == PFF_TYPE_N) + { + if (WIDTH_STAR == Width) + { + Width = va_arg(ap, INT); + } + if (PRECISION_STAR == Precision) + { + Precision = va_arg(ap, INT); + } + + if (Prefix == PFF_PREFIX_SHORT) + { + *(va_arg(ap, short *)) = written; + } + else + { + *(va_arg(ap, LPLONG)) = written; + } + } + /* types that sprintf can handle */ + else + { + TempInt = 0; + + /* %h (short) doesn't seem to be handled properly by local sprintf, + so lets do the truncation ourselves. (ptr -> int -> short to avoid + warnings */ + if (Type == PFF_TYPE_P && Prefix == PFF_PREFIX_SHORT) + { + long trunc1; + short trunc2; + + trunc1 = va_arg(ap, LONG); + trunc2 = (short)trunc1; + + TempInt = fprintf((FILE*)stream, TempBuff, trunc2); + } + else if (Type == PFF_TYPE_INT && Prefix == PFF_PREFIX_SHORT) + { + // Convert explicitly from int to short to get + // correct sign extension for shorts on all systems. + int n; + short s; + + n = va_arg(ap, int); + s = (short)n; + + TempInt = fprintf((FILE*)stream, TempBuff, s); + } + else + { + va_list apcopy; + va_copy(apcopy, ap); + TempInt = PAL_vfprintf(stream, TempBuff, apcopy); + va_end(apcopy); + PAL_printf_arg_remover(&ap, Width, Precision, Type, Prefix); + } + + if (-1 != TempInt) + { + written += TempInt; + } + } + } + else + { +#if FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL + clearerr((FILE*)stream); +#endif + + PAL_fwrite(Fmt++, 1, 1, stream); /* copy regular chars into buffer */ + if (stream->PALferrorCode == PAL_FILE_ERROR) + { + va_end(ap); + return -1; + } + ++written; + } + } + + va_end(ap); + return written; +} + +/*++ +Function: + WideCharToMultiByte (reduced and silent version) + +See MSDN doc. +--*/ +int Silent_WideCharToMultiByte(LPCWSTR lpWideCharStr, int cchWideChar, + LPSTR lpMultiByteStr, int cbMultiByte) +{ + INT retval =0; + + if ((lpWideCharStr == NULL)|| + (lpWideCharStr == (LPCWSTR) lpMultiByteStr)) + { + goto EXIT; + } + + if (cchWideChar == -1) + { + cchWideChar = Silent_PAL_wcslen(lpWideCharStr) + 1; + } + + if (cbMultiByte == 0) + { + retval = cchWideChar; + goto EXIT; + } + else if(cbMultiByte < cchWideChar) + { + retval = 0; + goto EXIT; + } + + retval = cchWideChar; + while(cchWideChar > 0) + { + if(*lpWideCharStr > 255) + { + *lpMultiByteStr = '?'; + } + else + { + *lpMultiByteStr = (unsigned char)*lpWideCharStr; + } + lpMultiByteStr++; + lpWideCharStr++; + cchWideChar--; + } + +EXIT: + return retval; +} + +/******************************************************************************* +Function: + Internal_ExtractFormatA (silent version) + + see Internal_ExtractFormatA function in printf.c +*******************************************************************************/ +BOOL Silent_ExtractFormatA(LPCSTR *Fmt, LPSTR Out, LPINT Flags, LPINT Width, LPINT Precision, LPINT Prefix, LPINT Type) +{ + BOOL Result = FALSE; + LPSTR TempStr; + LPSTR TempStrPtr; + + *Width = WIDTH_DEFAULT; + *Precision = PRECISION_DEFAULT; + *Flags = PFF_NONE; + *Prefix = PFF_PREFIX_DEFAULT; + *Type = PFF_TYPE_DEFAULT; + + if (*Fmt && **Fmt == '%') + { + *Out++ = *(*Fmt)++; + } + else + { + return Result; + } + + /* we'll never need a temp string longer than the original */ + TempStrPtr = TempStr = (LPSTR) PAL_malloc(strlen(*Fmt)+1); + if (!TempStr) + { + return Result; + } + + /* parse flags */ + while (**Fmt && (**Fmt == '-' || **Fmt == '+' || + **Fmt == '0' || **Fmt == ' ' || **Fmt == '#')) + { + switch (**Fmt) + { + case '-': + *Flags |= PFF_MINUS; break; + case '+': + *Flags |= PFF_PLUS; break; + case '0': + *Flags |= PFF_ZERO; break; + case ' ': + *Flags |= PFF_SPACE; break; + case '#': + *Flags |= PFF_POUND; break; + } + *Out++ = *(*Fmt)++; + } + /* '-' flag negates '0' flag */ + if ((*Flags & PFF_MINUS) && (*Flags & PFF_ZERO)) + { + *Flags -= PFF_ZERO; + } + + /* grab width specifier */ + if (isdigit((unsigned char) **Fmt)) + { + TempStrPtr = TempStr; + while (isdigit((unsigned char) **Fmt)) + { + *TempStrPtr++ = **Fmt; + *Out++ = *(*Fmt)++; + } + *TempStrPtr = 0; /* end string */ + *Width = atoi(TempStr); + if (*Width < 0) + { + SetLastError(ERROR_INTERNAL_ERROR); + return Result; + } + } + else if (**Fmt == '*') + { + *Width = WIDTH_STAR; + *Out++ = *(*Fmt)++; + if (isdigit((unsigned char) **Fmt)) + { + /* this is an invalid width because we have a * then a number */ + /* printf handles this by just printing the whole string */ + *Width = WIDTH_INVALID; + while (isdigit((unsigned char) **Fmt)) + { + *Out++ = *(*Fmt)++; + } + } + } + + + /* grab precision specifier */ + if (**Fmt == '.') + { + *Out++ = *(*Fmt)++; + if (isdigit((unsigned char) **Fmt)) + { + TempStrPtr = TempStr; + while (isdigit((unsigned char) **Fmt)) + { + *TempStrPtr++ = **Fmt; + *Out++ = *(*Fmt)++; + } + *TempStrPtr = 0; /* end string */ + *Precision = atoi(TempStr); + if (*Precision < 0) + { + SetLastError(ERROR_INTERNAL_ERROR); + return Result; + } + } + else if (**Fmt == '*') + { + *Precision = PRECISION_STAR; + *Out++ = *(*Fmt)++; + if (isdigit((unsigned char) **Fmt)) + { + /* this is an invalid precision because we have a .* then a + number */ + /* printf handles this by just printing the whole string */ + *Precision = PRECISION_INVALID; + while (isdigit((unsigned char) **Fmt)) + { + *Out++ = *(*Fmt)++; + } + } + } + else + { + *Precision = PRECISION_DOT; + } + } + +#ifdef HOST_64BIT + if (**Fmt == 'p') + { + *Prefix = PFF_PREFIX_LONGLONG; + } +#endif + /* grab prefix of 'I64' for __int64 */ + if ((*Fmt)[0] == 'I' && (*Fmt)[1] == '6' && (*Fmt)[2] == '4') + { + /* convert to 'll' so BSD's snprintf can handle it */ + *Fmt += 3; + *Prefix = PFF_PREFIX_LONGLONG; + } + /* grab a prefix of 'h' */ + else if (**Fmt == 'h') + { + *Prefix = PFF_PREFIX_SHORT; + ++(*Fmt); + } + /* grab prefix of 'l' or the undocumented 'w' (at least in MSDN) */ + else if (**Fmt == 'l' || **Fmt == 'w') + { + ++(*Fmt); +#ifdef HOST_64BIT + // Only want to change the prefix on 64 bit when printing characters. + if (**Fmt == 'c' || **Fmt == 's') +#endif + { + *Prefix = PFF_PREFIX_LONG; + } + } + else if (**Fmt == 'L') + { + /* a prefix of 'L' seems to be ignored */ + ++(*Fmt); + } + + /* grab type 'c' */ + if (**Fmt == 'c' || **Fmt == 'C') + { + *Type = PFF_TYPE_CHAR; + if (*Prefix != PFF_PREFIX_SHORT && **Fmt == 'C') + { + *Prefix = PFF_PREFIX_LONG; /* give it a wide prefix */ + } + if (*Prefix == PFF_PREFIX_LONG) + { + *Out++ = 'l'; + } + *Out++ = 'c'; + ++(*Fmt); + Result = TRUE; + } + /* grab type 's' */ + else if (**Fmt == 's' || **Fmt == 'S') + { + *Type = PFF_TYPE_STRING; + if (*Prefix != PFF_PREFIX_SHORT && **Fmt == 'S') + { + *Prefix = PFF_PREFIX_LONG; /* give it a wide prefix */ + } + if (*Prefix == PFF_PREFIX_LONG) + { + *Out++ = 'l'; + } + *Out++ = 's'; + ++(*Fmt); + Result = TRUE; + } + /* grab int types types */ + else if (**Fmt == 'd' || **Fmt == 'i' || **Fmt == 'o' || + **Fmt == 'u' || **Fmt == 'x' || **Fmt == 'X') + { + *Type = PFF_TYPE_INT; + if (*Prefix == PFF_PREFIX_SHORT) + { + *Out++ = 'h'; + } + else if (*Prefix == PFF_PREFIX_LONG) + { + *Out++ = 'l'; + } + else if (*Prefix == PFF_PREFIX_LONGLONG) + { + *Out++ = 'l'; + *Out++ = 'l'; + } + *Out++ = *(*Fmt)++; + Result = TRUE; + } + else if (**Fmt == 'e' || **Fmt == 'E' || **Fmt == 'f' || + **Fmt == 'g' || **Fmt == 'G') + { + /* we can safely ignore the prefixes and only add the type*/ + *Type = PFF_TYPE_FLOAT; + *Out++ = *(*Fmt)++; + Result = TRUE; + } + else if (**Fmt == 'n') + { + if (*Prefix == PFF_PREFIX_SHORT) + { + *Out++ = 'h'; + } + *Out++ = *(*Fmt)++; + *Type = PFF_TYPE_N; + Result = TRUE; + } + else if (**Fmt == 'p') + { + *Type = PFF_TYPE_P; + *Out++ = *(*Fmt)++; + + if (*Prefix == PFF_PREFIX_LONGLONG) + { + if (*Precision == PRECISION_DEFAULT) + { + *Precision = 16; + } + } + else + { + if (*Precision == PRECISION_DEFAULT) + { + *Precision = 8; + } + } + Result = TRUE; + } + + *Out = 0; /* end the string */ + PAL_free(TempStr); + return Result; +} + +/******************************************************************************* +Function: + AddPaddingVfprintf (silent version) + see Internal_AddPaddingVfprintf in printf.c +*******************************************************************************/ +INT Silent_AddPaddingVfprintf(PAL_FILE *stream, LPSTR In, INT Padding, INT Flags) +{ + LPSTR Out; + INT LengthInStr; + INT Length; + LPSTR OutOriginal; + INT Written; + + LengthInStr = strlen(In); + Length = LengthInStr; + + + if (Padding > 0) + { + Length += Padding; + } + Out = (LPSTR) PAL_malloc(Length+1); + int iLen = Length+1; + if (!Out) + { + return -1; + } + OutOriginal = Out; + + if (Flags & PFF_MINUS) /* pad on right */ + { + if (strcpy_s(Out, iLen, In) != SAFECRT_SUCCESS) + { + Written = -1; + goto Done; + } + + Out += LengthInStr; + iLen -= LengthInStr; + } + if (Padding > 0) + { + iLen -= Padding; + if (Flags & PFF_ZERO) /* '0', pad with zeros */ + { + while (Padding--) + { + *Out++ = '0'; + } + } + else /* pad with spaces */ + { + while (Padding--) + { + *Out++ = ' '; + } + } + } + if (!(Flags & PFF_MINUS)) /* put 'In' after padding */ + { + if (strcpy_s(Out, Length+1, In) != SAFECRT_SUCCESS) + { + Written = -1; + goto Done; + } + + Out += LengthInStr; + iLen -= LengthInStr; + } + +#if FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL + clearerr((FILE*)stream); +#endif + + Written = PAL_fwrite(OutOriginal, 1, Length, stream); + if (stream->PALferrorCode == PAL_FILE_ERROR) + { + Written = -1; + } + +Done: + PAL_free(OutOriginal); + return Written; +} + +/*++ +Function: + PAL_wcslen (silent version) + +See MSDN or the man page for wcslen. + +--*/ +size_t Silent_PAL_wcslen(const wchar_16 *string) +{ + size_t nChar = 0; + + if ( !string ) + { + return 0; + } + while (*string++) + { + nChar++; + } + + return nChar; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/string.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/string.cpp new file mode 100644 index 0000000..04c1918 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/string.cpp @@ -0,0 +1,205 @@ +// 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: + + string.cpp + +Abstract: + + Implementation of the string functions in the C runtime library that are Windows specific. + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/cruntime.h" + +#include +#include +#include +#include +#include +#include + + +SET_DEFAULT_DEBUG_CHANNEL(CRT); + +/*++ +Function: + _strnicmp + +compare at most count characters from two strings, ignoring case + +The strnicmp() function compares, with case insensitivity, at most count +characters from s1 to s2. All uppercase characters from s1 and s2 are +mapped to lowercase for the purposes of doing the comparison. + +Returns: + +Value Meaning + +< 0 s1 is less than s2 +0 s1 is equal to s2 +> 0 s1 is greater than s2 + +--*/ +int +__cdecl +_strnicmp( const char *s1, const char *s2, size_t count ) +{ + int ret; + + PERF_ENTRY(_strnicmp); + ENTRY("_strnicmp (s1=%p (%s), s2=%p (%s), count=%d)\n", s1?s1:"NULL", s1?s1:"NULL", s2?s2:"NULL", s2?s2:"NULL", count); + + ret = strncasecmp(s1, s2, count ); + + LOGEXIT("_strnicmp returning int %d\n", ret); + PERF_EXIT(_strnicmp); + return ret; +} + +/*++ +Function: + _stricmp + +compare two strings, ignoring case + +The stricmp() function compares, with case insensitivity, the string +pointed to by s1 to the string pointed to by s2. All uppercase +characters from s1 and s2 are mapped to lowercase for the purposes of +doing the comparison. + +Returns: + +Value Meaning + +< 0 s1 is less than s2 +0 s1 is equal to s2 +> 0 s1 is greater than s2 + +--*/ +int +__cdecl +_stricmp( + const char *s1, + const char *s2) +{ + int ret; + + PERF_ENTRY(_stricmp); + ENTRY("_stricmp (s1=%p (%s), s2=%p (%s))\n", s1?s1:"NULL", s1?s1:"NULL", s2?s2:"NULL", s2?s2:"NULL"); + + ret = strcasecmp(s1, s2); + + LOGEXIT("_stricmp returning int %d\n", ret); + PERF_EXIT(_stricmp); + return ret; +} + + +/*++ +Function: + PAL_strtoul + +Convert string to an unsigned long-integer value. + +Return Value + +strtoul returns the converted value, if any, or UINT32_MAX on +overflow. It returns 0 if no conversion can be performed. errno is +set to ERANGE if overflow or underflow occurs. + +Parameters + +szNumber Null-terminated string to convert to a ULONG +pszEnd Pointer to character that stops scan +nBase Number base to use + +Remarks + +strtoul stops reading the string szNumber at the first character it cannot +recognize as part of a number. This may be the terminating null +character, or it may be the first numeric character greater than or +equal to base. The LC_NUMERIC category setting of the current locale +determines recognition of the radix character in szNumber; for more +information, see setlocale. If pszEnd is not NULL, a pointer to the +character that stopped the scan is stored at the location pointed to +by pszEnd. If no conversion can be performed (no valid digits were +found or an invalid base was specified), the value of szNumber is stored +at the location pointed to by pszEnd. + +Notes : + MSDN states that only space and tab are accepted as leading whitespace, but + tests indicate that other whitespace characters (newline, carriage return, + etc) are also accepted. This matches the behavior on Unix systems. + + For strtoul, we need to check if the value to be returned + is outside the 32 bit range. If so, the returned value needs to be set + as appropriate, according to the MSDN pages and in all instances errno + must be set to ERANGE (The one exception is converting a string + representing a negative value to unsigned long). + Note that on 64 bit Windows, long's are still 32 bit. Thus, to match + Windows behavior, we must return long's in the 32 bit range. + --*/ + +/* The use of ULONG is by design, to ensure that a 32 bit value is always +returned from this function. If "unsigned long" is used instead of ULONG, +then a 64 bit value could be returned on 64 bit platforms like HP-UX, thus +breaking Windows behavior. */ +ULONG +__cdecl +PAL_strtoul(const char *szNumber, char **pszEnd, int nBase) +{ + unsigned long ulResult; + + PERF_ENTRY(strtoul); + ENTRY("strtoul (szNumber=%p (%s), pszEnd=%p, nBase=%d)\n", + szNumber?szNumber:"NULL", + szNumber?szNumber:"NULL", + pszEnd, + nBase); + + ulResult = strtoul(szNumber, pszEnd, nBase); + +#ifdef HOST_64BIT + if (ulResult > UINT32_MAX) + { + char ch = *szNumber; + while (isspace(ch)) + { + ch = *szNumber++; + } + /* If the string represents a positive number that is greater than + _UI32_MAX, set errno to ERANGE. Otherwise, don't set errno + to match Windows behavior. */ + if (ch != '-') + { + ulResult = UINT32_MAX; + errno = ERANGE; + } + } +#endif + + LOGEXIT("strtoul returning unsigned long %lu\n", ulResult); + PERF_EXIT(wcstoul); + + /* When returning unsigned long res from this function, it will be + implicitly cast to ULONG. This handles situations where a string that + represents a negative number is passed in to strtoul. The Windows + behavior is analogous to taking the binary equivalent of the negative + value and treating it as a positive number. Returning a ULONG from + this function, as opposed to native unsigned long, allows us to match + this behavior. The explicit cast to ULONG below is used to silence any + potential warnings due to the implicit casting. */ + return (ULONG)ulResult; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/stringtls.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/stringtls.cpp new file mode 100644 index 0000000..85f1158 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/stringtls.cpp @@ -0,0 +1,78 @@ +// 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: + + stringtls.cpp + +Abstract: + + Implementation of the string functions in the C runtime library that + are Windows specific and depend on per-thread data + + + +--*/ + +#include "pal/thread.hpp" +#include "pal/dbgmsg.h" + +#include +#include +#include +#include +#include + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(CRT); + +/*++ +Function: + PAL_strtok + +Finds the next token in a string. + +Return value: + +A pointer to the next token found in strToken. Returns NULL when no more +tokens are found. Each call modifies strToken by substituting a NULL +character for each delimiter that is encountered. + +Parameters: +strToken String cotaining token(s) +strDelimit Set of delimiter characters + +Remarks: +In FreeBSD, strtok is not re-entrant, strtok_r is. It manages re-entrancy +by using a passed-in context pointer (which will be stored in thread local +storage) According to the strtok MSDN documentation, "Calling these functions +simultaneously from multiple threads does not have undesirable effects", so +we need to use strtok_r. +--*/ +char * +__cdecl +PAL_strtok(char *strToken, const char *strDelimit) +{ + CPalThread *pThread = NULL; + char *retval=NULL; + + PERF_ENTRY(strtok); + ENTRY("strtok (strToken=%p (%s), strDelimit=%p (%s))\n", + strToken?strToken:"NULL", + strToken?strToken:"NULL", strDelimit?strDelimit:"NULL", strDelimit?strDelimit:"NULL"); + + pThread = InternalGetCurrentThread(); + + retval = strtok_r(strToken, strDelimit, &pThread->crtInfo.strtokContext); + + LOGEXIT("strtok returns %p (%s)\n", retval?retval:"NULL", retval?retval:"NULL"); + PERF_EXIT(strtok); + + return retval; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/thread.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/thread.cpp new file mode 100644 index 0000000..b4a249a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/thread.cpp @@ -0,0 +1,39 @@ +// 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: + + thread.c + +Abstract: + + Implementation of the threads/process functions in the C runtime library + that are Windows specific. + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/init.h" + +SET_DEFAULT_DEBUG_CHANNEL(CRT); + +void +PAL_exit(int status) +{ + PERF_ENTRY(exit); + ENTRY ("exit(status=%d)\n", status); + + /* should also clean up any resources allocated by pal/cruntime, if any */ + ExitProcess(status); + + LOGEXIT ("exit returns void"); + PERF_EXIT(exit); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/wchar.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/wchar.cpp new file mode 100644 index 0000000..01e05ce --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/wchar.cpp @@ -0,0 +1,1039 @@ +// 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: + + wchar.c + +Abstract: + + Implementation of wide char string functions. + + + +--*/ + + +#include "pal/palinternal.h" +#include "pal/cruntime.h" +#include "pal/dbgmsg.h" + +#include "pal/thread.hpp" +#include "pal/threadsusp.hpp" + + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +SET_DEFAULT_DEBUG_CHANNEL(CRT); + + +/*-- +Function: + _wtoi + +See MSDN doc +--*/ +int +__cdecl +_wtoi( + const wchar_16 *string) +{ + int len; + int ret; + char *tempStr; + + PERF_ENTRY(_wtoi); + ENTRY("_wtoi (string=%p)\n", string); + + len = WideCharToMultiByte(CP_ACP, 0, string, -1, 0, 0, 0, 0); + if (!len) + { + ASSERT("WideCharToMultiByte failed. Error is %d\n", + GetLastError()); + return -1; + } + tempStr = (char *) PAL_malloc(len); + if (!tempStr) + { + ERROR("PAL_malloc failed\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return -1; + } + len = WideCharToMultiByte(CP_ACP, 0, string, -1, tempStr, len, 0, 0); + if (!len) + { + ASSERT("WideCharToMultiByte failed. Error is %d\n", + GetLastError()); + PAL_free(tempStr); + return -1; + } + ret = atoi(tempStr); + + PAL_free(tempStr); + LOGEXIT("_wtoi returns int %d\n", ret); + PERF_EXIT(_wtoi); + return ret; +} + + +/*++ +Function: + _wcsnicmp + +Compare characters of two strings without regard to case + +Return Value + +The return value indicates the relationship between the substrings as follows. + +Return Value + +Description + +< 0 string1 substring less than string2 substring + 0 string1 substring identical to string2 substring +> 0 string1 substring greater than string2 substring + +Parameters + +string1, string2 Null-terminated strings to compare +count Number of characters to compare + +Remarks + +The _strnicmp function lexicographically compares, at most, the first +count characters of string1 and string2. The comparison is performed +without regard to case; _strnicmp is a case-insensitive version of +strncmp. The comparison ends if a terminating null character is +reached in either string before count characters are compared. If the +strings are equal when a terminating null character is reached in +either string before count characters are compared, the shorter string +is lesser. + +--*/ +int +__cdecl +_wcsnicmp( + const wchar_16 *string1, + const wchar_16 *string2, + size_t count) +{ + size_t i; + int diff = 0; + + PERF_ENTRY(_wcsnicmp); + ENTRY("_wcsnicmp (string1=%p (%S), string2=%p (%S), count=%lu)\n", + string1?string1:W16_NULLSTRING, + string1?string1:W16_NULLSTRING, string2?string2:W16_NULLSTRING, string2?string2:W16_NULLSTRING, + (unsigned long) count); + + for (i = 0; i < count; i++) + { + diff = towlower(string1[i]) - towlower(string2[i]); + if (diff != 0 || 0 == string1[i] || 0 == string2[i]) + { + break; + } + } + LOGEXIT("_wcsnicmp returning int %d\n", diff); + PERF_EXIT(_wcsnicmp); + return diff; +} + +/*++ +Function: + _wcsicmp + +Compare characters of two strings without regard to case + +Return Value + +The return value indicates the relationship between the substrings as follows. + +Return Value + +Description + +< 0 string1 substring less than string2 substring + 0 string1 substring identical to string2 substring +> 0 string1 substring greater than string2 substring + +Parameters + +string1, string2 Null-terminated strings to compare + +--*/ +int +__cdecl +_wcsicmp( + const wchar_16 *string1, + const wchar_16 *string2) +{ + int ret; + + PERF_ENTRY(_wcsicmp); + ENTRY("_wcsicmp (string1=%p (%S), string2=%p (%S))\n", + string1?string1:W16_NULLSTRING, + string1?string1:W16_NULLSTRING, string2?string2:W16_NULLSTRING, string2?string2:W16_NULLSTRING); + + ret = _wcsnicmp(string1, string2, 0x7fffffff); + + LOGEXIT("_wcsnicmp returns int %d\n", ret); + PERF_EXIT(_wcsicmp); + return ret; +} + + +/*++ +Function: + _wcslwr + +Convert a string to lowercase. + +Return Value + +Returns a pointer to the converted string. Because the modification is +done in place, the pointer returned is the same as the pointer passed +as the input argument. No return value is reserved to indicate an +error. + +Parameter + +string Null-terminated string to convert to lowercase + +Remarks + +--*/ +wchar_16 * +__cdecl +_wcslwr( + wchar_16 *string) +{ + int i; + + PERF_ENTRY(_wcslwr); + ENTRY("_wcslwr (string=%p (%S))\n", string?string:W16_NULLSTRING, string?string:W16_NULLSTRING); + + for (i=0 ; string[i] != 0; i++) + { + string[i] = towlower(string[i]); + } + + LOGEXIT("_wcslwr returning wchar_t %p (%S)\n", string?string:W16_NULLSTRING, string?string:W16_NULLSTRING); + PERF_EXIT(_wcslwr); + return string; +} + + +/*++ +Function: + PAL_wcstoul + +Convert string to an unsigned long-integer value. + +Return Value + +wcstoul returns the converted value, if any, or UINT32_MAX on +overflow. It returns 0 if no conversion can be performed. errno is +set to ERANGE if overflow or underflow occurs. + +Parameters + +nptr Null-terminated string to convert +endptr Pointer to character that stops scan +base Number base to use + +Remarks + +wcstoul stops reading the string nptr at the first character it cannot +recognize as part of a number. This may be the terminating null +character, or it may be the first numeric character greater than or +equal to base. The LC_NUMERIC category setting of the current locale +determines recognition of the radix character in nptr; for more +information, see setlocale. If endptr is not NULL, a pointer to the +character that stopped the scan is stored at the location pointed to +by endptr. If no conversion can be performed (no valid digits were +found or an invalid base was specified), the value of nptr is stored +at the location pointed to by endptr. + +Notes : + MSDN states that only space and tab are accepted as leading whitespace, but + tests indicate that other whitespace characters (newline, carriage return, + etc) are also accepted. This matches the behavior on Unix systems. + + For wcstol and wcstoul, we need to check if the value to be returned + is outside the 32 bit range. If so, the returned value needs to be set + as appropriate, according to the MSDN pages for wcstol and wcstoul, + and in all instances errno must be set to ERANGE (The one exception + is converting a string representing a negative value to unsigned long). + Note that on 64 bit Windows, long's are still 32 bit. Thus, to match + Windows behavior, we must return long's in the 32 bit range. +--*/ + +/* The use of ULONG is by design, to ensure that a 32 bit value is always +returned from this function. If "unsigned long" is used instead of ULONG, +then a 64 bit value could be returned on 64 bit platforms like HP-UX, thus +breaking Windows behavior .*/ +ULONG +__cdecl +PAL_wcstoul( + const wchar_16 *nptr, + wchar_16 **endptr, + int base) +{ + char *s_nptr = 0; + char *s_endptr = 0; + unsigned long res; + int size; + DWORD dwLastError = 0; + + PERF_ENTRY(wcstoul); + ENTRY("wcstoul (nptr=%p (%S), endptr=%p, base=%d)\n", nptr?nptr:W16_NULLSTRING, nptr?nptr:W16_NULLSTRING, + endptr, base); + + size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, NULL, 0, NULL, NULL); + if (!size) + { + dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); + SetLastError(ERROR_INVALID_PARAMETER); + res = 0; + goto PAL_wcstoulExit; + } + s_nptr = (char *)PAL_malloc(size); + if (!s_nptr) + { + ERROR("PAL_malloc failed\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + res = 0; + goto PAL_wcstoulExit; + } + size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, s_nptr, size, NULL, NULL); + if (!size) + { + dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); + SetLastError(ERROR_INVALID_PARAMETER); + res = 0; + goto PAL_wcstoulExit; + } + + res = strtoul(s_nptr, &s_endptr, base); + +#ifdef HOST_64BIT + if (res > UINT32_MAX) + { + wchar_16 wc = *nptr; + while (iswspace(wc)) + { + wc = *nptr++; + } + /* If the string represents a positive number that is greater than + _UI32_MAX, set errno to ERANGE. Otherwise, don't set errno + to match Windows behavior. */ + if (wc != '-') + { + res = UINT32_MAX; + errno = ERANGE; + } + } +#endif + + /* only ASCII characters will be accepted by strtol, and those always get + mapped to single-byte characters, so the first rejected character will + have the same index in the multibyte and widechar strings */ + if( endptr ) + { + size = s_endptr - s_nptr; + *endptr = (wchar_16 *)&nptr[size]; + } + +PAL_wcstoulExit: + PAL_free(s_nptr); + LOGEXIT("wcstoul returning unsigned long %lu\n", res); + PERF_EXIT(wcstoul); + + /* When returning unsigned long res from this function, it will be + implicitly cast to ULONG. This handles situations where a string that + represents a negative number is passed in to wcstoul. The Windows + behavior is analogous to taking the binary equivalent of the negative + value and treating it as a positive number. Returning a ULONG from + this function, as opposed to native unsigned long, allows us to match + this behavior. The explicit case to ULONG below is used to silence any + potential warnings due to the implicit casting. */ + return (ULONG)res; +} + +ULONGLONG +__cdecl +PAL__wcstoui64( + const wchar_16 *nptr, + wchar_16 **endptr, + int base) +{ + char *s_nptr = 0; + char *s_endptr = 0; + unsigned long long res; + int size; + DWORD dwLastError = 0; + + PERF_ENTRY(wcstoul); + ENTRY("_wcstoui64 (nptr=%p (%S), endptr=%p, base=%d)\n", nptr?nptr:W16_NULLSTRING, nptr?nptr:W16_NULLSTRING, + endptr, base); + + size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, NULL, 0, NULL, NULL); + if (!size) + { + dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); + SetLastError(ERROR_INVALID_PARAMETER); + res = 0; + goto PAL__wcstoui64Exit; + } + s_nptr = (char *)PAL_malloc(size); + if (!s_nptr) + { + ERROR("PAL_malloc failed\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + res = 0; + goto PAL__wcstoui64Exit; + } + size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, s_nptr, size, NULL, NULL); + if (!size) + { + dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); + SetLastError(ERROR_INVALID_PARAMETER); + res = 0; + goto PAL__wcstoui64Exit; + } + + res = strtoull(s_nptr, &s_endptr, base); + + /* only ASCII characters will be accepted by strtoull, and those always get + mapped to single-byte characters, so the first rejected character will + have the same index in the multibyte and widechar strings */ + if( endptr ) + { + size = s_endptr - s_nptr; + *endptr = (wchar_16 *)&nptr[size]; + } + +PAL__wcstoui64Exit: + PAL_free(s_nptr); + LOGEXIT("_wcstoui64 returning unsigned long long %llu\n", res); + PERF_EXIT(_wcstoui64); + + return res; +} + +WCHAR * __cdecl PAL_wcsncat(WCHAR *, const WCHAR *, size_t); + +/*++ +Function: + PAL_wcscat + +See MSDN or the man page for mcscat. + +--*/ +wchar_16 * +__cdecl +PAL_wcscat( + wchar_16 *strDestination, + const wchar_16 *strSource) +{ + wchar_16 *ret; + PERF_ENTRY(wcscat); + ENTRY("wcscat (strDestination=%p (%S), strSource=%p (%S))\n", + strDestination?strDestination:W16_NULLSTRING, + strDestination?strDestination:W16_NULLSTRING, strSource?strSource:W16_NULLSTRING, strSource?strSource:W16_NULLSTRING); + + ret = PAL_wcsncat( strDestination, strSource, PAL_wcslen( strSource ) ); + + LOGEXIT("wcscat returnng wchar_t %p (%S)\n", ret, ret); + PERF_EXIT(wcscat); + return ret; +} + + +/*++ +Function: + PAL_wcscpy + +See MSDN or the man page for mcscpy. + +--*/ +wchar_16 * +__cdecl +PAL_wcscpy( + wchar_16 *strDestination, + const wchar_16 *strSource) +{ + wchar_16 *start = strDestination; + + PERF_ENTRY(wcscpy); + ENTRY("wcscpy (strDestination=%p, strSource=%p (%S))\n", + strDestination, strSource ? strSource:W16_NULLSTRING, strSource ? strSource:W16_NULLSTRING); + + if (strDestination == NULL) + { + ERROR("invalid strDestination argument\n"); + LOGEXIT("wcscpy returning wchar_t NULL\n"); + PERF_EXIT(wcscpy); + return NULL; + } + + if (strSource == NULL) + { + ERROR("invalid strSource argument\n"); + LOGEXIT("wcscpy returning wchar_t NULL\n"); + PERF_EXIT(wcscpy); + return NULL; + } + + /* copy source string to destination string */ + while(*strSource) + { + *strDestination++ = *strSource++; + } + + /* add terminating null */ + *strDestination = '\0'; + + LOGEXIT("wcscpy returning wchar_t %p (%S)\n", start, start); + PERF_EXIT(wcscpy); + return start; +} + + +/*++ +Function: + PAL_wcslen + +See MSDN or the man page for wcslen. + +--*/ +size_t +__cdecl +PAL_wcslen( + const wchar_16 *string) +{ + size_t nChar = 0; + + PERF_ENTRY(wcslen); + ENTRY("wcslen (string=%p (%S))\n", string?string:W16_NULLSTRING, string?string:W16_NULLSTRING); + + if ( !string ) + { + LOGEXIT("wcslen returning size_t %u\n", 0); + PERF_EXIT(wcslen); + return 0; + } + while (*string++) + { + nChar++; + } + + LOGEXIT("wcslen returning size_t %u\n", nChar); + PERF_EXIT(wcslen); + return nChar; +} + + +/*++ +Function: + PAL_wcsncmp + +See MSDN or the man page for wcsncmp. +--*/ +int +__cdecl +PAL_wcsncmp( + const wchar_16 *string1, + const wchar_16 *string2, + size_t count) +{ + size_t i; + int diff = 0; + + PERF_ENTRY(wcsncmp); + ENTRY("wcsncmp (string1=%p (%S), string2=%p (%S) count=%lu)\n", + string1?string1:W16_NULLSTRING, + string1?string1:W16_NULLSTRING, string2?string2:W16_NULLSTRING, string2?string2:W16_NULLSTRING, + (unsigned long) count); + + for (i = 0; i < count; i++) + { + diff = string1[i] - string2[i]; + if (diff != 0) + { + break; + } + + /* stop if we reach the end of the string */ + if(string1[i]==0) + { + break; + } + } + LOGEXIT("wcsncmp returning int %d\n", diff); + PERF_EXIT(wcsncmp); + return diff; +} + +/*++ +Function: + PAL_wcscmp + +See MSDN or the man page for wcscmp. +--*/ +int +__cdecl +PAL_wcscmp( + const wchar_16 *string1, + const wchar_16 *string2) +{ + int ret; + + PERF_ENTRY(wcscmp); + ENTRY("wcscmp (string1=%p (%S), string2=%p (%S))\n", + string1?string1:W16_NULLSTRING, + string1?string1:W16_NULLSTRING, string2?string2:W16_NULLSTRING, string2?string2:W16_NULLSTRING); + + ret = PAL_wcsncmp(string1, string2, 0x7fffffff); + + LOGEXIT("wcscmp returns int %d\n", ret); + PERF_EXIT(wcscmp); + return ret; +} + +/*++ +Function: + PAL_wcschr + +See MSDN or man page for wcschr. + +--*/ +wchar_16 _WConst_return * +__cdecl +PAL_wcschr( + const wchar_16 * string, + wchar_16 c) +{ + PERF_ENTRY(wcschr); + ENTRY("wcschr (string=%p (%S), c=%C)\n", string?string:W16_NULLSTRING, string?string:W16_NULLSTRING, c); + + while (*string) + { + if (*string == c) + { + LOGEXIT("wcschr returning wchar_t %p (%S)\n", string, string); + PERF_EXIT(wcschr); + return (wchar_16 *) string; + } + string++; + } + + // Check if the comparand was \000 + if (*string == c) + return (wchar_16 *) string; + + LOGEXIT("wcschr returning wchar_t NULL\n"); + PERF_EXIT(wcschr); + return NULL; +} + + +/*++ +Function: + PAL_wcsrchr + +See MSDN or man page for wcsrchr. + +--*/ +wchar_16 _WConst_return * +__cdecl +PAL_wcsrchr( + const wchar_16 * string, + wchar_16 c) +{ + wchar_16 *last = NULL; + + PERF_ENTRY(wcsrchr); + ENTRY("wcsrchr (string=%p (%S), c=%C)\n", string?string:W16_NULLSTRING, string?string:W16_NULLSTRING, c); + + while (*string) + { + if (*string == c) + { + last = (wchar_16 *) string; + } + string++; + } + + LOGEXIT("wcsrchr returning wchar_t %p (%S)\n", last?last:W16_NULLSTRING, last?last:W16_NULLSTRING); + PERF_EXIT(wcsrchr); + return (wchar_16 *)last; +} + + +/*++ +Function: + PAL_wcspbrk + +See MSDN or man page for wcspbrk. +--*/ +const wchar_16 * +__cdecl +PAL_wcspbrk( + const wchar_16 *string, + const wchar_16 *strCharSet) +{ + PERF_ENTRY(wcspbrk); + ENTRY("wcspbrk (string=%p (%S), strCharSet=%p (%S))\n", + string?string:W16_NULLSTRING, + string?string:W16_NULLSTRING, strCharSet?strCharSet:W16_NULLSTRING, strCharSet?strCharSet:W16_NULLSTRING); + + while (*string) + { + if (PAL_wcschr(strCharSet, *string) != NULL) + { + LOGEXIT("wcspbrk returning wchar_t %p (%S)\n", string, string); + PERF_EXIT(wcspbrk); + return (wchar_16 *) string; + } + + string++; + } + + LOGEXIT("wcspbrk returning wchar_t NULL\n"); + PERF_EXIT(wcspbrk); + return NULL; +} + + +/*++ +Function: + PAL_wcsstr + +See MSDN or man page for wcsstr. +--*/ +const wchar_16 * +__cdecl +PAL_wcsstr( + const wchar_16 *string, + const wchar_16 *strCharSet) +{ + wchar_16 *ret = NULL; + int i; + + PERF_ENTRY(wcsstr); + ENTRY("wcsstr (string=%p (%S), strCharSet=%p (%S))\n", + string?string:W16_NULLSTRING, + string?string:W16_NULLSTRING, strCharSet?strCharSet:W16_NULLSTRING, strCharSet?strCharSet:W16_NULLSTRING); + + if (string == NULL) + { + ret = NULL; + goto leave; + } + + if (strCharSet == NULL) + { + ret = NULL; + goto leave; + } + + if (*strCharSet == 0) + { + ret = (wchar_16 *)string; + goto leave; + } + + while (*string != 0) + { + i = 0; + while (1) + { + if (*(strCharSet + i) == 0) + { + ret = (wchar_16 *) string; + goto leave; + } + else if (*(string + i) == 0) + { + ret = NULL; + goto leave; + } + else if (*(string + i) != *(strCharSet + i)) + { + break; + } + + i++; + } + string++; + } + + leave: + LOGEXIT("wcsstr returning wchar_t %p (%S)\n", ret?ret:W16_NULLSTRING, ret?ret:W16_NULLSTRING); + PERF_EXIT(wcsstr); + return ret; +} + +/*++ +Function : + + PAL_wcsncpy + +see msdn doc. +--*/ +wchar_16 * +__cdecl +PAL_wcsncpy( wchar_16 * strDest, const wchar_16 *strSource, size_t count ) +{ + UINT length = sizeof( wchar_16 ) * count; + PERF_ENTRY(wcsncpy); + ENTRY("wcsncpy( strDest:%p, strSource:%p (%S), count:%lu)\n", + strDest, strSource, strSource, (unsigned long) count); + + memset( strDest, 0, length ); + length = std::min( count, PAL_wcslen( strSource ) ) * sizeof( wchar_16 ); + memcpy( strDest, strSource, length ); + + LOGEXIT("wcsncpy returning (wchar_16*): %p\n", strDest); + PERF_EXIT(wcsncpy); + return strDest; +} + +/*++ +Function : + + wcsncat + +see msdn doc. +--*/ +wchar_16 * +__cdecl +PAL_wcsncat( wchar_16 * strDest, const wchar_16 *strSource, size_t count ) +{ + wchar_16 *start = strDest; + UINT LoopCount = 0; + UINT StrSourceLength = 0; + + PERF_ENTRY(wcsncat); + ENTRY( "wcsncat (strDestination=%p (%S), strSource=%p (%S), count=%lu )\n", + strDest ? strDest : W16_NULLSTRING, + strDest ? strDest : W16_NULLSTRING, + strSource ? strSource : W16_NULLSTRING, + strSource ? strSource : W16_NULLSTRING, (unsigned long) count); + + if ( strDest == NULL ) + { + ERROR("invalid strDest argument\n"); + LOGEXIT("wcsncat returning wchar_t NULL\n"); + PERF_EXIT(wcsncat); + return NULL; + } + + if ( strSource == NULL ) + { + ERROR("invalid strSource argument\n"); + LOGEXIT("wcsncat returning wchar_t NULL\n"); + PERF_EXIT(wcsncat); + return NULL; + } + + /* find end of source string */ + while ( *strDest ) + { + strDest++; + } + + StrSourceLength = PAL_wcslen( strSource ); + if ( StrSourceLength < count ) + { + count = StrSourceLength; + } + + /* concatenate new string */ + while( *strSource && LoopCount < count ) + { + *strDest++ = *strSource++; + LoopCount++; + } + + /* add terminating null */ + *strDest = '\0'; + + LOGEXIT("wcsncat returning wchar_t %p (%S)\n", start, start); + PERF_EXIT(wcsncat); + return start; +} + +static BOOL MISC_CRT_WCSTOD_IsValidCharacter( WCHAR c ) +{ + if ( c == '+' || c == '-' || c == '.' || ( c >= '0' && c <= '9' ) || + c == 'e' || c == 'E' || c == 'd' || c == 'D' ) + { + return TRUE; + } + return FALSE; +} + +/*++ +Function : + + wcstod + + There is a slight difference between the Windows version of wcstod + and the BSD versio of wcstod. + + Under Windows the string " -1b " returns -1.000000 stop char = 'b' + Under BSD the same string returns 0.000000 stop ' ' + +see msdn doc. +--*/ +double +__cdecl +PAL_wcstod( const wchar_16 * nptr, wchar_16 **endptr ) +{ + double RetVal = 0.0; + LPSTR lpStringRep = NULL; + LPWSTR lpStartOfExpression = (LPWSTR)nptr; + LPWSTR lpEndOfExpression = NULL; + UINT Length = 0; + + PERF_ENTRY(wcstod); + ENTRY( "wcstod( %p (%S), %p (%S) )\n", nptr, nptr, endptr , endptr ); + + if ( !nptr ) + { + ERROR( "nptr is invalid.\n" ); + LOGEXIT( "wcstod returning 0.0\n" ); + PERF_EXIT(wcstod); + return 0.0; + } + + /* Eat white space. */ + while ( iswspace( *lpStartOfExpression ) ) + { + lpStartOfExpression++; + } + + /* Get the end of the expression. */ + lpEndOfExpression = lpStartOfExpression; + while ( *lpEndOfExpression ) + { + if ( !MISC_CRT_WCSTOD_IsValidCharacter( *lpEndOfExpression ) ) + { + break; + } + lpEndOfExpression++; + } + + if ( lpEndOfExpression != lpStartOfExpression ) + { + Length = lpEndOfExpression - lpStartOfExpression; + lpStringRep = (LPSTR)PAL_malloc( Length + 1); + + if ( lpStringRep ) + { + if ( WideCharToMultiByte( CP_ACP, 0, lpStartOfExpression, Length, + lpStringRep, Length + 1 , + NULL, 0 ) != 0 ) + { + LPSTR ScanStop = NULL; + lpStringRep[Length]= 0; + RetVal = strtod( lpStringRep, &ScanStop ); + + /* See if strtod failed. */ + if ( RetVal == 0.0 && ScanStop == lpStringRep ) + { + ASSERT( "An error occurred in the conversion.\n" ); + lpEndOfExpression = (LPWSTR)nptr; + } + } + else + { + ASSERT( "Wide char to multibyte conversion failed.\n" ); + lpEndOfExpression = (LPWSTR)nptr; + } + } + else + { + ERROR( "Not enough memory.\n" ); + lpEndOfExpression = (LPWSTR)nptr; + } + } + else + { + ERROR( "Malformed expression.\n" ); + lpEndOfExpression = (LPWSTR)nptr; + } + + /* Set the stop scan character. */ + if ( endptr != NULL ) + { + *endptr = lpEndOfExpression; + } + + PAL_free( lpStringRep ); + LOGEXIT( "wcstod returning %f.\n", RetVal ); + PERF_EXIT(wcstod); + return RetVal; +} + +/*++ +Function: + PAL_wcscspn + +Finds the number of consecutive characters from the start of the string +that are not in the set. + +Return value: + +The number of characters from the start of the string that are not in +the set. + +Parameters: +string String +strCharSet Set of delimiter characters + +--*/ +size_t +__cdecl +PAL_wcscspn(const wchar_16 *string, const wchar_16 *strCharSet) +{ + const wchar_16 *temp; + size_t count = 0; + + PERF_ENTRY(wcscspn); + + while(*string != 0) + { + for(temp = strCharSet; *temp != 0; temp++) + { + if (*string == *temp) + { + PERF_EXIT(wcscspn); + return count; + } + } + count++; + string++; + } + PERF_EXIT(wcscspn); + return count; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/wchartls.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/wchartls.cpp new file mode 100644 index 0000000..ea9c0a5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/wchartls.cpp @@ -0,0 +1,126 @@ +// 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: + + wchartls.c + +Abstract: + + Implementation of wide char string functions that depend on per-thread data + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/thread.hpp" +#include "pal/dbgmsg.h" + +using namespace CorUnix; + + +SET_DEFAULT_DEBUG_CHANNEL(CRT); + +/*++ +Function: + PAL_wcstok + +Finds the next token in a wide character string. + +Return value: + +A pointer to the next token found in strToken. Returns NULL when no more +tokens are found. Each call modifies strToken by substituting a NULL +character for each delimiter that is encountered. + +Parameters: +strToken String containing token(s) +strDelimit Set of delimiter characters + +--*/ +WCHAR * +__cdecl +PAL_wcstok(WCHAR *strToken, const WCHAR *strDelimit) +{ + CPalThread *pThread = NULL; + WCHAR *retval = NULL; + WCHAR *delim_ptr; + WCHAR *next_context; /* string to save in TLS for future calls */ + + PERF_ENTRY(wcstok); + ENTRY("PAL_wcstok (strToken=%p (%S), strDelimit=%p (%S))\n", + strToken?strToken:W16_NULLSTRING, + strToken?strToken:W16_NULLSTRING, + strDelimit?strDelimit:W16_NULLSTRING, + strDelimit?strDelimit:W16_NULLSTRING); + + /* Get the per-thread buffer from the thread structure. */ + pThread = InternalGetCurrentThread(); + + if(NULL == strDelimit) + { + ERROR("delimiter string is NULL\n"); + goto done; + } + + /* get token string from TLS if none is provided */ + if(NULL == strToken) + { + TRACE("wcstok() called with NULL string, using previous string\n"); + strToken = pThread->crtInfo.wcstokContext; + if(NULL == strToken) + { + ERROR("wcstok called with NULL string without a previous call\n"); + goto done; + } + } + + /* first, skip all leading delimiters */ + while ((*strToken != '\0') && (PAL_wcschr(strDelimit,*strToken))) + { + strToken++; + } + + /* if there were only delimiters, there's no string */ + if('\0' == strToken[0]) + { + TRACE("end of string already reached, returning NULL\n"); + goto done; + } + + /* we're now at the beginning of the token; look for the first delimiter */ + delim_ptr = PAL_wcspbrk(strToken,strDelimit); + if(NULL == delim_ptr) + { + TRACE("no delimiters found, this is the last token\n"); + /* place the next context at the end of the string, so that subsequent + calls will return NULL */ + next_context = strToken+PAL_wcslen(strToken); + retval = strToken; + } + else + { + /* null-terminate current token */ + *delim_ptr=0; + + /* place the next context right after the delimiter */ + next_context = delim_ptr+1; + retval = strToken; + + TRACE("found delimiter; next token will be %p\n",next_context); + } + + pThread->crtInfo.wcstokContext = next_context; + +done: + LOGEXIT("PAL_wcstok() returns %p (%S)\n", retval?retval:W16_NULLSTRING, retval?retval:W16_NULLSTRING); + PERF_EXIT(wcstok); + return(retval); +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/CMakeLists.txt new file mode 100644 index 0000000..aaf4204 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/CMakeLists.txt @@ -0,0 +1,7 @@ +set(EVENT_MANIFEST ${VM_DIR}/ClrEtwAll.man) + +if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD) + add_subdirectory(lttngprovider) +else() + add_subdirectory(dummyprovider) +endif() diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/dummyprovider/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/dummyprovider/CMakeLists.txt new file mode 100644 index 0000000..39b9826 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/dummyprovider/CMakeLists.txt @@ -0,0 +1,43 @@ +include(FindPython) + +set (GENERATE_SCRIPT ${CLR_DIR}/src/scripts/genDummyProvider.py) + +set(GENERATE_COMMAND ${Python_EXECUTABLE} ${GENERATE_SCRIPT} --man ${EVENT_MANIFEST} --intermediate ${CMAKE_CURRENT_BINARY_DIR}) + +execute_process( + COMMAND ${GENERATE_COMMAND} --dry-run + RESULT_VARIABLE GEN_DUMMY_RESULT + OUTPUT_VARIABLE DUMMY_PROVIDER_OUTPUT + ERROR_VARIABLE GEN_DUMMY_ERRORS +) + +if (NOT GEN_DUMMY_RESULT EQUAL 0) + message(FATAL_ERROR "Failed to generate dummy event provider: ${GEN_DUMMY_ERRORS}") +endif() + +string(REPLACE "\n" ";" DUMMY_PROVIDER_OUTPUT ${DUMMY_PROVIDER_OUTPUT}) # turn the outputted list of files into a CMake list + +set (DUMMY_PROVIDER_SOURCES "") +set (TRACEPOINT_PROVIDER_SOURCES "") +foreach(DUMMY_PROVIDER_FILE ${DUMMY_PROVIDER_OUTPUT}) + file(TO_CMAKE_PATH ${DUMMY_PROVIDER_FILE} DUMMY_PROVIDER_FILE) + list(APPEND DUMMY_PROVIDER_SOURCES ${DUMMY_PROVIDER_FILE}) +endforeach() + +add_definitions(-DPAL_STDCPP_COMPAT=1) +include_directories(${COREPAL_SOURCE_DIR}/inc/rt) +include_directories(${CMAKE_CURRENT_BINARY_DIR}/dummy) + +add_custom_command(OUTPUT ${DUMMY_PROVIDER_SOURCES} + COMMAND ${GENERATE_COMMAND} + DEPENDS ${EVENT_MANIFEST} ${GENERATE_SCRIPT}) + +add_library(eventprovider + STATIC + ${DUMMY_PROVIDER_SOURCES} +) + +set_target_properties(eventprovider PROPERTIES LINKER_LANGUAGE CXX) + +# Install the static eventprovider library +install(TARGETS eventprovider DESTINATION lib) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/lttngprovider/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/lttngprovider/CMakeLists.txt new file mode 100644 index 0000000..234dea1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/lttngprovider/CMakeLists.txt @@ -0,0 +1,74 @@ +include(FindPython) +set (GENERATE_SCRIPT ${CLR_DIR}/src/scripts/genLttngProvider.py) + +set(GENERATE_COMMAND ${Python_EXECUTABLE} ${GENERATE_SCRIPT} --man ${EVENT_MANIFEST} --intermediate ${CMAKE_CURRENT_BINARY_DIR}) + +execute_process( + COMMAND ${GENERATE_COMMAND} --dry-run + RESULT_VARIABLE GEN_LTTNG_RESULT + OUTPUT_VARIABLE LTTNG_PROVIDER_OUTPUT + ERROR_VARIABLE GEN_LTTNG_ERRORS +) + +if (NOT GEN_LTTNG_RESULT EQUAL 0) + message(FATAL_ERROR "Failed to generate Lttng provider: ${GEN_LTTNG_ERRORS}") +endif() + +string(REPLACE "\n" ";" LTTNG_PROVIDER_OUTPUT ${LTTNG_PROVIDER_OUTPUT}) # turn the outputted list of files into a CMake list + +set (LTTNG_PROVIDER_SOURCES "") +set (TRACEPOINT_PROVIDER_SOURCES "") +set (LTTNG_HEADERS "") +foreach(LTTNG_PROVIDER_FILE ${LTTNG_PROVIDER_OUTPUT}) + file(TO_CMAKE_PATH ${LTTNG_PROVIDER_FILE} LTTNG_PROVIDER_FILE) + if ("${LTTNG_PROVIDER_FILE}" MATCHES "/lttng/traceptprov[a-z]+.cpp$") + list(APPEND TRACEPOINT_PROVIDER_SOURCES ${LTTNG_PROVIDER_FILE}) + elseif("${LTTNG_PROVIDER_FILE}" MATCHES "/lttng/eventprov[a-z]+.cpp$") + list(APPEND LTTNG_PROVIDER_SOURCES ${LTTNG_PROVIDER_FILE}) + else() + list(APPEND LTTNG_HEADERS ${LTTNG_PROVIDER_FILE}) + endif() +endforeach() + +add_definitions(-DPAL_STDCPP_COMPAT=1) +include_directories(${COREPAL_SOURCE_DIR}/inc/rt) +include_directories(${CMAKE_CURRENT_BINARY_DIR}/lttng) + +add_custom_command(OUTPUT ${LTTNG_PROVIDER_SOURCES} ${TRACEPOINT_PROVIDER_SOURCES} ${LTTNG_HEADERS} + COMMAND ${GENERATE_COMMAND} + DEPENDS ${EVENT_MANIFEST} ${GENERATE_SCRIPT}) + +set_source_files_properties( + ${LTTNG_PROVIDER_SOURCES} ${TRACEPOINT_PROVIDER_SOURCES} ${LTTNG_HEADERS} + PROPERTIES GENERATED TRUE) + +add_custom_target( + generated_eventing_headers + DEPENDS ${LTTNG_HEADERS}) + +add_library(eventprovider + STATIC + ${LTTNG_PROVIDER_SOURCES} + eventproviderhelpers.cpp +) + +add_library(coreclrtraceptprovider + SHARED + ${TRACEPOINT_PROVIDER_SOURCES} +) + +add_dependencies(eventprovider generated_eventing_headers) +add_dependencies(coreclrtraceptprovider generated_eventing_headers) + +find_library(LTTNG NAMES lttng-ust) + +target_link_libraries(coreclrtraceptprovider + ${LTTNG} +) + +set_target_properties(coreclrtraceptprovider PROPERTIES LINKER_LANGUAGE CXX) + +# Install the static eventprovider library +_install(TARGETS eventprovider DESTINATION lib) +# Install the static coreclrtraceptprovider library +install_clr(TARGETS coreclrtraceptprovider ADDITIONAL_DESTINATION sharedFramework) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/lttngprovider/eventproviderhelpers.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/lttngprovider/eventproviderhelpers.cpp new file mode 100644 index 0000000..b9d438c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/eventprovider/lttngprovider/eventproviderhelpers.cpp @@ -0,0 +1,85 @@ +// 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. + +#include "palrt.h" +#include "pal.h" +#include "stdlib.h" +#include "pal_mstypes.h" +#include "pal_error.h" +#include +#include + +#define wcslen PAL_wcslen + +bool ResizeBuffer(char *&buffer, size_t& size, size_t currLen, size_t newSize, bool &fixedBuffer) +{ + newSize = (size_t)(newSize * 1.5); + _ASSERTE(newSize > size); // check for overflow + + if (newSize < 32) + newSize = 32; + + // We can't use coreclr includes here so we use std::nothrow + // rather than the coreclr version + char *newBuffer = new (std::nothrow) char[newSize]; + + if (newBuffer == NULL) + return false; + + memcpy(newBuffer, buffer, currLen); + + if (!fixedBuffer) + delete[] buffer; + + buffer = newBuffer; + size = newSize; + fixedBuffer = false; + + return true; +} + +bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer) +{ + if(!src) return true; + if (offset + len > size) + { + if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer)) + return false; + } + + memcpy(buffer + offset, src, len); + offset += len; + return true; +} + +bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer) +{ + if(!str) return true; + size_t byteCount = (wcslen(str) + 1) * sizeof(*str); + + if (offset + byteCount > size) + { + if (!ResizeBuffer(buffer, size, offset, size + byteCount, fixedBuffer)) + return false; + } + + memcpy(buffer + offset, str, byteCount); + offset += byteCount; + return true; +} + +bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer) +{ + if(!str) return true; + size_t len = strlen(str) + 1; + if (offset + len > size) + { + if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer)) + return false; + } + + memcpy(buffer + offset, str, len); + offset += len; + return true; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machexception.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machexception.cpp new file mode 100644 index 0000000..4acafdd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machexception.cpp @@ -0,0 +1,1491 @@ +// 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: + + machexception.cpp + +Abstract: + + Implementation of MACH exception API functions. + +--*/ + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do this first + +#include "pal/thread.hpp" +#include "pal/seh.hpp" +#include "pal/palinternal.h" +#if HAVE_MACH_EXCEPTIONS +#include "machexception.h" +#include "pal/critsect.h" +#include "pal/debug.h" +#include "pal/init.h" +#include "pal/utils.h" +#include "pal/context.h" +#include "pal/malloc.hpp" +#include "pal/process.h" +#include "pal/virtual.h" +#include "pal/map.hpp" +#include "pal/environ.h" + +#include "machmessage.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace CorUnix; + +// The port we use to handle exceptions and to set the thread context +mach_port_t s_ExceptionPort; + +static DWORD s_PalInitializeFlags = 0; + +static const char * PAL_MACH_EXCEPTION_MODE = "PAL_MachExceptionMode"; + +// This struct is used to track the threads that need to have an exception forwarded +// to the next thread level port in the chain (if exists). An entry is added by the +// faulting sending a special message to the exception thread which saves it on an +// list that is searched when the restarted exception notification is received again. +struct ForwardedException +{ + ForwardedException *m_next; + thread_act_t Thread; + exception_type_t ExceptionType; + CPalThread *PalThread; +}; + +// The singly linked list and enumerator for the ForwardException struct +struct ForwardedExceptionList +{ +private: + ForwardedException *m_head; + ForwardedException *m_previous; + +public: + ForwardedException *Current; + + ForwardedExceptionList() + { + m_head = NULL; + MoveFirst(); + } + + void MoveFirst() + { + Current = m_head; + m_previous = NULL; + } + + bool IsEOL() + { + return Current == NULL; + } + + void MoveNext() + { + m_previous = Current; + Current = Current->m_next; + } + + void Add(ForwardedException *item) + { + item->m_next = m_head; + m_head = item; + } + + void Delete() + { + if (m_previous == NULL) + { + m_head = Current->m_next; + } + else + { + m_previous->m_next = Current->m_next; + } + free(Current); + + Current = m_head; + m_previous = NULL; + } +}; + +enum MachExceptionMode +{ + // special value to indicate we've not initialized yet + MachException_Uninitialized = -1, + + // These can be combined with bitwise OR to incrementally turn off + // functionality for diagnostics purposes. + // + // In practice, the following values are probably useful: + // 1: Don't turn illegal instructions into SEH exceptions. + // On Intel, stack misalignment usually shows up as an + // illegal instruction. PAL client code shouldn't + // expect to see any of these, so this option should + // always be safe to set. + // 2: Don't listen for breakpoint exceptions. This makes an + // SEH-based debugger (i.e., managed debugger) unusable, + // but you may need this option if you find that native + // breakpoints you set in PAL-dependent code don't work + // (causing hangs or crashes in the native debugger). + // 3: Combination of the above. + // This is the typical setting for development + // (unless you're working on the managed debugger). + // 7: In addition to the above, don't turn bad accesses and + // arithmetic exceptions into SEH. + // This is the typical setting for stress. + MachException_SuppressIllegal = 1, + MachException_SuppressDebugging = 2, + MachException_SuppressManaged = 4, + + // Default value to use if environment variable not set. + MachException_Default = 0, +}; + +/*++ +Function : + GetExceptionMask() + + Returns the mach exception mask for the exceptions to hook for a thread. + +Return value : + mach exception mask +--*/ +static +exception_mask_t +GetExceptionMask() +{ + static MachExceptionMode exMode = MachException_Uninitialized; + + if (exMode == MachException_Uninitialized) + { + exMode = MachException_Default; + + char* exceptionSettings = EnvironGetenv(PAL_MACH_EXCEPTION_MODE); + if (exceptionSettings) + { + exMode = (MachExceptionMode)atoi(exceptionSettings); + free(exceptionSettings); + } + else + { + if (PAL_IsDebuggerPresent()) + { + exMode = MachException_SuppressDebugging; + } + } + } + + exception_mask_t machExceptionMask = 0; + + if (s_PalInitializeFlags & PAL_INITIALIZE_REGISTER_SIGNALS) + { + if (!(exMode & MachException_SuppressIllegal)) + { + machExceptionMask |= PAL_EXC_ILLEGAL_MASK; + } + if (!(exMode & MachException_SuppressDebugging) && (s_PalInitializeFlags & PAL_INITIALIZE_DEBUGGER_EXCEPTIONS)) + { + // Always hook exception ports for breakpoint exceptions. + // The reason is that we don't know when a managed debugger + // will attach, so we have to be prepared. We don't want + // to later go through the thread list and hook exception + // ports for exactly those threads that currently are in + // this PAL. + machExceptionMask |= PAL_EXC_DEBUGGING_MASK; + } + if (!(exMode & MachException_SuppressManaged)) + { + machExceptionMask |= PAL_EXC_MANAGED_MASK; + } + } + + return machExceptionMask; +} + +/*++ +Function : + CPalThread::EnableMachExceptions + + Hook Mach exceptions, i.e., call thread_swap_exception_ports + to replace the thread's current exception ports with our own. + The previously active exception ports are saved. Called when + this thread enters a region of code that depends on this PAL. + +Return value : + ERROR_SUCCESS, if enabling succeeded + an error code, otherwise +--*/ +PAL_ERROR CorUnix::CPalThread::EnableMachExceptions() +{ + TRACE("%08X: Enter()\n", (unsigned int)(size_t)this); + + exception_mask_t machExceptionMask = GetExceptionMask(); + if (machExceptionMask != 0) + { +#ifdef _DEBUG + // verify that the arrays we've allocated to hold saved exception ports + // are the right size. + exception_mask_t countBits = PAL_EXC_ALL_MASK; + countBits = ((countBits & 0xAAAAAAAA) >> 1) + (countBits & 0x55555555); + countBits = ((countBits & 0xCCCCCCCC) >> 2) + (countBits & 0x33333333); + countBits = ((countBits & 0xF0F0F0F0) >> 4) + (countBits & 0x0F0F0F0F); + countBits = ((countBits & 0xFF00FF00) >> 8) + (countBits & 0x00FF00FF); + countBits = ((countBits & 0xFFFF0000) >> 16) + (countBits & 0x0000FFFF); + if (countBits != static_cast(CThreadMachExceptionHandlers::s_nPortsMax)) + { + ASSERT("s_nPortsMax is %u, but needs to be %u\n", + CThreadMachExceptionHandlers::s_nPortsMax, countBits); + } +#endif // _DEBUG + + NONPAL_TRACE("Enabling handlers for thread %08x exception mask %08x exception port %08x\n", + GetMachPortSelf(), machExceptionMask, s_ExceptionPort); + + CThreadMachExceptionHandlers *pSavedHandlers = GetSavedMachHandlers(); + + // Swap current handlers into temporary storage first. That's because it's possible (even likely) that + // some or all of the handlers might still be ours. In those cases we don't want to overwrite the + // chain-back entries with these useless self-references. + kern_return_t machret; + kern_return_t machretDeallocate; + thread_port_t thread = mach_thread_self(); + + machret = thread_swap_exception_ports( + thread, + machExceptionMask, + s_ExceptionPort, + EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, + THREAD_STATE_NONE, + pSavedHandlers->m_masks, + &pSavedHandlers->m_nPorts, + pSavedHandlers->m_handlers, + pSavedHandlers->m_behaviors, + pSavedHandlers->m_flavors); + + machretDeallocate = mach_port_deallocate(mach_task_self(), thread); + CHECK_MACH("mach_port_deallocate", machretDeallocate); + + if (machret != KERN_SUCCESS) + { + ASSERT("thread_swap_exception_ports failed: %d %s\n", machret, mach_error_string(machret)); + return UTIL_MachErrorToPalError(machret); + } + +#ifdef _DEBUG + NONPAL_TRACE("EnableMachExceptions: THREAD PORT count %d\n", pSavedHandlers->m_nPorts); + for (mach_msg_type_number_t i = 0; i < pSavedHandlers->m_nPorts; i++) + { + _ASSERTE(pSavedHandlers->m_handlers[i] != s_ExceptionPort); + NONPAL_TRACE("EnableMachExceptions: THREAD PORT mask %08x handler: %08x behavior %08x flavor %u\n", + pSavedHandlers->m_masks[i], + pSavedHandlers->m_handlers[i], + pSavedHandlers->m_behaviors[i], + pSavedHandlers->m_flavors[i]); + } +#endif // _DEBUG + } + return ERROR_SUCCESS; +} + +/*++ +Function : + CPalThread::DisableMachExceptions + + Unhook Mach exceptions, i.e., call thread_set_exception_ports + to restore the thread's exception ports with those we saved + in EnableMachExceptions. Called when this thread leaves a + region of code that depends on this PAL. + +Return value : + ERROR_SUCCESS, if disabling succeeded + an error code, otherwise +--*/ +PAL_ERROR CorUnix::CPalThread::DisableMachExceptions() +{ + TRACE("%08X: Leave()\n", (unsigned int)(size_t)this); + + PAL_ERROR palError = NO_ERROR; + + // We only store exceptions when we're installing exceptions. + if (0 == GetExceptionMask()) + return palError; + + // Get the handlers to restore. + CThreadMachExceptionHandlers *savedPorts = GetSavedMachHandlers(); + + kern_return_t MachRet = KERN_SUCCESS; + for (int i = 0; i < savedPorts->m_nPorts; i++) + { + // If no handler was ever set, thread_swap_exception_ports returns + // MACH_PORT_NULL for the handler and zero values for behavior + // and flavor. Unfortunately, the latter are invalid even for + // MACH_PORT_NULL when you use thread_set_exception_ports. + exception_behavior_t behavior = savedPorts->m_behaviors[i] ? savedPorts->m_behaviors[i] : EXCEPTION_DEFAULT; + thread_state_flavor_t flavor = savedPorts->m_flavors[i] ? savedPorts->m_flavors[i] : MACHINE_THREAD_STATE; + thread_port_t thread = mach_thread_self(); + MachRet = thread_set_exception_ports(thread, + savedPorts->m_masks[i], + savedPorts->m_handlers[i], + behavior, + flavor); + + kern_return_t MachRetDeallocate = mach_port_deallocate(mach_task_self(), thread); + CHECK_MACH("mach_port_deallocate", MachRetDeallocate); + + if (MachRet != KERN_SUCCESS) + break; + } + + if (MachRet != KERN_SUCCESS) + { + ASSERT("thread_set_exception_ports failed: %d\n", MachRet); + palError = UTIL_MachErrorToPalError(MachRet); + } + + return palError; +} + +#if !defined(HOST_AMD64) +extern "C" +void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachExceptionInfo *pMachExceptionInfo) +#else // defined(HOST_AMD64) + +// Since HijackFaultingThread pushed the context, exception record and info on the stack, we need to adjust the +// signature of PAL_DispatchException such that the corresponding arguments are considered to be on the stack +// per GCC64 calling convention rules. Hence, the first 6 dummy arguments (corresponding to RDI, RSI, RDX,RCX, R8, R9). +extern "C" +void PAL_DispatchException(DWORD64 dwRDI, DWORD64 dwRSI, DWORD64 dwRDX, DWORD64 dwRCX, DWORD64 dwR8, DWORD64 dwR9, PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachExceptionInfo *pMachExceptionInfo) +#endif // !defined(HOST_AMD64) +{ + CPalThread *pThread = InternalGetCurrentThread(); + + CONTEXT *contextRecord; + EXCEPTION_RECORD *exceptionRecord; + AllocateExceptionRecords(&exceptionRecord, &contextRecord); + + *contextRecord = *pContext; + *exceptionRecord = *pExRecord; + + contextRecord->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE; + bool continueExecution; + + { + // The exception object takes ownership of the exceptionRecord and contextRecord + PAL_SEHException exception(exceptionRecord, contextRecord); + + TRACE("PAL_DispatchException(EC %08x EA %p)\n", pExRecord->ExceptionCode, pExRecord->ExceptionAddress); + + continueExecution = SEHProcessException(&exception); + if (continueExecution) + { + // Make a copy of the exception records so that we can free them before restoring the context + *pContext = *contextRecord; + *pExRecord = *exceptionRecord; + } + + // The exception records are destroyed by the PAL_SEHException destructor now. + } + + if (continueExecution) + { + RtlRestoreContext(pContext, pExRecord); + } + + // Send the forward request to the exception thread to process + MachMessage sSendMessage; + sSendMessage.SendForwardException(s_ExceptionPort, pMachExceptionInfo, pThread); + + // Spin wait until this thread is hijacked by the exception thread + while (TRUE) + { + sched_yield(); + } +} + +#if defined(HOST_X86) || defined(HOST_AMD64) +extern "C" void PAL_DispatchExceptionWrapper(); +extern "C" int PAL_DispatchExceptionReturnOffset; +#endif // HOST_X86 || HOST_AMD64 + +/*++ +Function : + BuildExceptionRecord + + Sets up up an ExceptionRecord from an exception message + +Parameters : + exceptionInfo - exception info to build the exception record + pExceptionRecord - exception record to setup +*/ +static +void +BuildExceptionRecord( + MachExceptionInfo& exceptionInfo, // [in] exception info + EXCEPTION_RECORD *pExceptionRecord) // [out] Used to return exception parameters +{ + memset(pExceptionRecord, 0, sizeof(EXCEPTION_RECORD)); + + DWORD exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + + switch(exceptionInfo.ExceptionType) + { + // Could not access memory. subcode contains the bad memory address. + case EXC_BAD_ACCESS: + if (exceptionInfo.SubcodeCount != 2) + { + NONPAL_RETAIL_ASSERT("Got an unexpected subcode"); + exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + } + else + { + exceptionCode = EXCEPTION_ACCESS_VIOLATION; + + pExceptionRecord->NumberParameters = 2; + pExceptionRecord->ExceptionInformation[0] = 0; + pExceptionRecord->ExceptionInformation[1] = exceptionInfo.Subcodes[1]; + NONPAL_TRACE("subcodes[1] = %llx\n", exceptionInfo.Subcodes[1]); + } + break; + + // Instruction failed. Illegal or undefined instruction or operand. + case EXC_BAD_INSTRUCTION : + // TODO: Identify privileged instruction. Need to get the thread state and read the machine code. May + // be better to do this in the place that calls SEHProcessException, similar to how it's done on Linux. + exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + break; + + // Arithmetic exception; exact nature of exception is in subcode field. + case EXC_ARITHMETIC: + if (exceptionInfo.SubcodeCount != 2) + { + NONPAL_RETAIL_ASSERT("Got an unexpected subcode"); + exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + } + else + { + switch (exceptionInfo.Subcodes[0]) + { +#if defined(HOST_X86) || defined(HOST_AMD64) + case EXC_I386_DIV: + exceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO; + break; + case EXC_I386_INTO: + exceptionCode = EXCEPTION_INT_OVERFLOW; + break; + case EXC_I386_EXTOVR: + exceptionCode = EXCEPTION_FLT_OVERFLOW; + break; + case EXC_I386_BOUND: + exceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; + break; +#else +#error Trap code to exception mapping not defined for this architecture +#endif + default: + exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + break; + } + } + break; + + case EXC_SOFTWARE: +#if defined(HOST_X86) || defined(HOST_AMD64) + exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + break; +#else +#error Trap code to exception mapping not defined for this architecture +#endif + + // Trace, breakpoint, etc. Details in subcode field. + case EXC_BREAKPOINT: +#if defined(HOST_X86) || defined(HOST_AMD64) + if (exceptionInfo.Subcodes[0] == EXC_I386_SGL) + { + exceptionCode = EXCEPTION_SINGLE_STEP; + } + else if (exceptionInfo.Subcodes[0] == EXC_I386_BPT) + { + exceptionCode = EXCEPTION_BREAKPOINT; + } +#else +#error Trap code to exception mapping not defined for this architecture +#endif + else + { + WARN("unexpected subcode %d for EXC_BREAKPOINT", exceptionInfo.Subcodes[0]); + exceptionCode = EXCEPTION_BREAKPOINT; + } + break; + + + // System call requested. Details in subcode field. + case EXC_SYSCALL: + exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + break; + + // System call with a number in the Mach call range requested. Details in subcode field. + case EXC_MACH_SYSCALL: + exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + break; + + default: + NONPAL_ASSERT("Got unknown trap code %d\n", exceptionInfo.ExceptionType); + break; + } + + pExceptionRecord->ExceptionCode = exceptionCode; +} + +#ifdef _DEBUG +const char * +GetExceptionString( + exception_type_t exception +) +{ + switch(exception) + { + case EXC_BAD_ACCESS: + return "EXC_BAD_ACCESS"; + + case EXC_BAD_INSTRUCTION: + return "EXC_BAD_INSTRUCTION"; + + case EXC_ARITHMETIC: + return "EXC_ARITHMETIC"; + + case EXC_SOFTWARE: + return "EXC_SOFTWARE"; + + case EXC_BREAKPOINT: + return "EXC_BREAKPOINT"; + + case EXC_SYSCALL: + return "EXC_SYSCALL"; + + case EXC_MACH_SYSCALL: + return "EXC_MACH_SYSCALL"; + + default: + NONPAL_ASSERT("Got unknown trap code %d\n", exception); + break; + } + return "INVALID CODE"; +} +#endif // _DEBUG + +/*++ +Function : + HijackFaultingThread + + Sets the faulting thread up to return to PAL_DispatchException with an + ExceptionRecord and thread CONTEXT. + +Parameters: + thread - thread the exception happened + task - task the exception happened + message - exception message + +Return value : + None +--*/ +static +void +HijackFaultingThread( + mach_port_t thread, // [in] thread the exception happened on + mach_port_t task, // [in] task the exception happened on + MachMessage& message) // [in] exception message +{ + MachExceptionInfo exceptionInfo(thread, message); + EXCEPTION_RECORD exceptionRecord; + CONTEXT threadContext; + kern_return_t machret; + + // Fill in the exception record from the exception info + BuildExceptionRecord(exceptionInfo, &exceptionRecord); + +#ifdef HOST_X86 + threadContext.ContextFlags = CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS; +#else + threadContext.ContextFlags = CONTEXT_FLOATING_POINT; +#endif + CONTEXT_GetThreadContextFromThreadState(x86_FLOAT_STATE, (thread_state_t)&exceptionInfo.FloatState, &threadContext); + + threadContext.ContextFlags |= CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS; + CONTEXT_GetThreadContextFromThreadState(x86_THREAD_STATE, (thread_state_t)&exceptionInfo.ThreadState, &threadContext); + +#if defined(CORECLR) && (defined(HOST_X86) || defined(HOST_AMD64)) + // For CoreCLR we look more deeply at access violations to determine whether they're the result of a stack + // overflow. If so we'll terminate the process immediately (the current default policy of the CoreCLR EE). + // Otherwise we'll either A/V ourselves trying to set up the SEH exception record and context on the + // target thread's stack (unlike Windows there's no extra stack reservation to guarantee this can be done) + // or, and this the case we're trying to avoid, it's possible we'll succeed and the runtime will go ahead + // and process the SO like it was a simple AV. Since the runtime doesn't currently implement stack probing + // on non-Windows platforms, this could lead to data corruption (we have SO intolerant code in the runtime + // which manipulates global state under the assumption that an SO cannot occur due to a prior stack + // probe). + + // Determining whether an AV is really an SO is not quite straightforward. We can get stack bounds + // information from pthreads but (a) we only have the target Mach thread port and no way to map to a + // pthread easily and (b) the pthread functions lie about the bounds on the main thread. + + // Instead we inspect the target thread SP we just retrieved above and compare it with the AV address. If + // they both lie in the same page or the SP is at a higher address than the AV but in the same VM region, + // then we'll consider the AV to be an SO. Note that we can't assume that SP will be in the same page as + // the AV on an SO, even though we force GCC to generate stack probes on stack extension (-fstack-check). + // That's because GCC currently generates the probe *before* altering SP. Since a given stack extension can + // involve multiple pages and GCC generates all the required probes before updating SP in a single + // operation, the faulting probe can be at an address that is far removed from the thread's current value + // of SP. + + // In the case where the AV and SP aren't in the same or adjacent pages we check if the first page + // following the faulting address belongs in the same VM region as the current value of SP. Since all pages + // in a VM region have the same attributes this check eliminates the possibility that there's another guard + // page in the range between the fault and the SP, effectively establishing that the AV occurred in the + // guard page associated with the stack associated with the SP. + + // We are assuming here that thread stacks are always allocated in a single VM region. I've seen no + // evidence thus far that this is not the case (and the mere fact we rely on Mach apis already puts us on + // brittle ground anyway). + + // (a) SP always marks the current limit of the stack (in that all valid stack accesses will be of + // the form [SP + delta]). The Mac x86 ABI appears to guarantee this (or rather it does not + // guarantee that stack slots below SP will not be invalidated by asynchronous events such as + // interrupts, which mostly amounts to the same thing for user mode code). Note that the Mac PPC + // ABI does allow some (constrained) access below SP, but we're not currently supporting this + // platform. + // (b) All code will extend the stack "carefully" (by which we mean that stack extensions of more + // than one page in size will touch at least one byte in each intervening page (in decreasing + // address order), to guarantee that the guard page is hit before memory beyond the guard page is + // corrupted). Our managed jits always generate code which does this as does MSVC. GCC, however, + // does not do this by default. We have to explicitly provide the -fstack-check compiler option + // to enable the behavior. +#if (defined(HOST_X86) || defined(HOST_AMD64)) && defined(__APPLE__) + // Assume that AV isn't an SO to begin with. + bool fIsStackOverflow = false; + + if (exceptionRecord.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) + { + // Calculate the page base addresses for the fault and the faulting thread's SP. + int cbPage = getpagesize(); + char *pFaultPage = (char*)(exceptionRecord.ExceptionInformation[1] & ~(cbPage - 1)); +#ifdef HOST_X86 + char *pStackTopPage = (char*)(threadContext.Esp & ~(cbPage - 1)); +#elif defined(HOST_AMD64) + char *pStackTopPage = (char*)(threadContext.Rsp & ~(cbPage - 1)); +#endif + + if (pFaultPage == pStackTopPage || pFaultPage == (pStackTopPage - cbPage)) + { + // The easy case is when the AV occurred in the same or adjacent page as the stack pointer. + fIsStackOverflow = true; + } + else if (pFaultPage < pStackTopPage) + { + // Calculate the address of the page immediately following the fault and check that it + // lies in the same VM region as the stack pointer. + vm_address_t vm_address; + vm_size_t vm_size; + vm_region_flavor_t vm_flavor; + mach_msg_type_number_t infoCnt; +#ifdef HOST_64BIT + vm_region_basic_info_data_64_t info; + infoCnt = VM_REGION_BASIC_INFO_COUNT_64; + vm_flavor = VM_REGION_BASIC_INFO_64; +#else + vm_region_basic_info_data_t info; + infoCnt = VM_REGION_BASIC_INFO_COUNT; + vm_flavor = VM_REGION_BASIC_INFO; +#endif + mach_port_t object_name; + + vm_address = (vm_address_t)(pFaultPage + cbPage); + +#ifdef HOST_64BIT + machret = vm_region_64( +#else + machret = vm_region( +#endif + mach_task_self(), + &vm_address, + &vm_size, + vm_flavor, + (vm_region_info_t)&info, + &infoCnt, + &object_name); +#ifdef HOST_X86 + CHECK_MACH("vm_region", machret); +#elif defined(HOST_AMD64) + CHECK_MACH("vm_region_64", machret); +#endif + + // If vm_region updated the address we gave it then that address was not part of a region at all + // (and so this cannot be an SO). Otherwise check that the ESP lies in the region returned. + char *pRegionStart = (char*)vm_address; + char *pRegionEnd = (char*)vm_address + vm_size; + if (pRegionStart == (pFaultPage + cbPage) && pStackTopPage < pRegionEnd) + fIsStackOverflow = true; + } + +#if defined(HOST_AMD64) + if (!fIsStackOverflow) + { + // Check if we can read pointer sizeD bytes below the target thread's stack pointer. + // If we are unable to, then it implies we have run into SO. + void **targetSP = (void **)threadContext.Rsp; + vm_address_t targetAddr = (mach_vm_address_t)(targetSP); + targetAddr -= sizeof(void *); + vm_size_t vm_size = sizeof(void *); + char arr[8]; + vm_size_t data_count = 8; + machret = vm_read_overwrite(mach_task_self(), targetAddr, vm_size, (pointer_t)arr, &data_count); + if (machret == KERN_INVALID_ADDRESS) + { + fIsStackOverflow = true; + } + } +#endif // HOST_AMD64 + } +#else // (HOST_X86 || HOST_AMD64) && __APPLE__ +#error Platform not supported for correct stack overflow handling +#endif // (HOST_X86 || HOST_AMD64) && __APPLE__ +#endif // CORECLR && HOST_X86 + +#if defined(HOST_X86) + NONPAL_ASSERTE(exceptionInfo.ThreadState.tsh.flavor == x86_THREAD_STATE32); + + // Make a copy of the thread state because the one in exceptionInfo needs to be preserved to restore + // the state if the exception is forwarded. + x86_thread_state32_t ts32 = exceptionInfo.ThreadState.uts.ts32; + + // If we're in single step mode, disable it since we're going to call PAL_DispatchException + if (exceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) + { + ts32.eflags &= ~EFL_TF; + } + + exceptionRecord.ExceptionFlags = EXCEPTION_IS_SIGNAL; + exceptionRecord.ExceptionRecord = NULL; + exceptionRecord.ExceptionAddress = (void *)ts32.eip; + + void **FramePointer = (void **)ts32.esp; + + *--FramePointer = (void *)ts32.eip; + + // Construct a stack frame for a pretend activation of the function + // PAL_DispatchExceptionWrapper that serves only to make the stack + // correctly unwindable by the system exception unwinder. + // PAL_DispatchExceptionWrapper has an ebp frame, its local variables + // are the context and exception record, and it has just "called" + // PAL_DispatchException. + *--FramePointer = (void *)ts32.ebp; + ts32.ebp = (unsigned)FramePointer; + + // Put the context on the stack + FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(CONTEXT)); + // Make sure it's aligned - CONTEXT has 8-byte alignment + FramePointer = (void **)((ULONG_PTR)FramePointer - ((ULONG_PTR)FramePointer % 8)); + CONTEXT *pContext = (CONTEXT *)FramePointer; + *pContext = threadContext; + + // Put the exception record on the stack + FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(EXCEPTION_RECORD)); + EXCEPTION_RECORD *pExceptionRecord = (EXCEPTION_RECORD *)FramePointer; + *pExceptionRecord = exceptionRecord; + + FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(MachExceptionInfo)); + MachExceptionInfo *pMachExceptionInfo = (MachExceptionInfo *)FramePointer; + *pMachExceptionInfo = exceptionInfo; + + // Push arguments to PAL_DispatchException + FramePointer = (void **)((ULONG_PTR)FramePointer - 3 * sizeof(void *)); + + // Make sure it's aligned - ABI requires 16-byte alignment + FramePointer = (void **)((ULONG_PTR)FramePointer - ((ULONG_PTR)FramePointer % 16)); + FramePointer[0] = pContext; + FramePointer[1] = pExceptionRecord; + FramePointer[2] = pMachExceptionInfo; + + // Place the return address to right after the fake call in PAL_DispatchExceptionWrapper + FramePointer[-1] = (void *)((ULONG_PTR)PAL_DispatchExceptionWrapper + PAL_DispatchExceptionReturnOffset); + + // Make the instruction register point to DispatchException + ts32.eip = (unsigned)PAL_DispatchException; + ts32.esp = (unsigned)&FramePointer[-1]; // skip return address + + // Now set the thread state for the faulting thread so that PAL_DispatchException executes next + machret = thread_set_state(thread, x86_THREAD_STATE32, (thread_state_t)&ts32, x86_THREAD_STATE32_COUNT); + CHECK_MACH("thread_set_state(thread)", machret); +#elif defined(HOST_AMD64) + NONPAL_ASSERTE(exceptionInfo.ThreadState.tsh.flavor == x86_THREAD_STATE64); + + // Make a copy of the thread state because the one in exceptionInfo needs to be preserved to restore + // the state if the exception is forwarded. + x86_thread_state64_t ts64 = exceptionInfo.ThreadState.uts.ts64; + + // If we're in single step mode, disable it since we're going to call PAL_DispatchException + if (exceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) + { + ts64.__rflags &= ~EFL_TF; + } + + if (fIsStackOverflow) + { + exceptionRecord.ExceptionCode = EXCEPTION_STACK_OVERFLOW; + } + + exceptionRecord.ExceptionFlags = EXCEPTION_IS_SIGNAL; + exceptionRecord.ExceptionRecord = NULL; + exceptionRecord.ExceptionAddress = (void *)ts64.__rip; + + void **FramePointer; + + if (fIsStackOverflow) + { + // Allocate the minimal stack necessary for handling stack overflow + int stackOverflowStackSize = 7 * 4096; + // Align the size to virtual page size and add one virtual page as a stack guard + stackOverflowStackSize = ALIGN_UP(stackOverflowStackSize, GetVirtualPageSize()) + GetVirtualPageSize(); + void* stackOverflowHandlerStack = mmap(NULL, stackOverflowStackSize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + + if ((stackOverflowHandlerStack == MAP_FAILED) || mprotect((void*)stackOverflowHandlerStack, GetVirtualPageSize(), PROT_NONE) != 0) + { + // We are out of memory or we've failed to protect the guard page, so resort to just printing a stack overflow message and abort + write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1); + abort(); + } + + FramePointer = (void**)((size_t)stackOverflowHandlerStack + stackOverflowStackSize); + } + else + { + FramePointer = (void **)ts64.__rsp; + } + + *--FramePointer = (void *)ts64.__rip; + + // Construct a stack frame for a pretend activation of the function + // PAL_DispatchExceptionWrapper that serves only to make the stack + // correctly unwindable by the system exception unwinder. + // PAL_DispatchExceptionWrapper has an ebp frame, its local variables + // are the context and exception record, and it has just "called" + // PAL_DispatchException. + *--FramePointer = (void *)ts64.__rbp; + ts64.__rbp = (SIZE_T)FramePointer; + + // Put the context on the stack + FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(CONTEXT)); + // Make sure it's aligned - CONTEXT has 16-byte alignment + FramePointer = (void **)((ULONG_PTR)FramePointer - ((ULONG_PTR)FramePointer % 16)); + CONTEXT *pContext = (CONTEXT *)FramePointer; + *pContext = threadContext; + + // Put the exception record on the stack + FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(EXCEPTION_RECORD)); + EXCEPTION_RECORD *pExceptionRecord = (EXCEPTION_RECORD *)FramePointer; + *pExceptionRecord = exceptionRecord; + + FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(MachExceptionInfo)); + MachExceptionInfo *pMachExceptionInfo = (MachExceptionInfo *)FramePointer; + *pMachExceptionInfo = exceptionInfo; + + // Push arguments to PAL_DispatchException + FramePointer = (void **)((ULONG_PTR)FramePointer - 3 * sizeof(void *)); + + // Make sure it's aligned - ABI requires 16-byte alignment + FramePointer = (void **)((ULONG_PTR)FramePointer - ((ULONG_PTR)FramePointer % 16)); + FramePointer[0] = pContext; + FramePointer[1] = pExceptionRecord; + FramePointer[2] = pMachExceptionInfo; + + // Place the return address to right after the fake call in PAL_DispatchExceptionWrapper + FramePointer[-1] = (void *)((ULONG_PTR)PAL_DispatchExceptionWrapper + PAL_DispatchExceptionReturnOffset); + + // Make the instruction register point to DispatchException + ts64.__rip = (SIZE_T)PAL_DispatchException; + ts64.__rsp = (SIZE_T)&FramePointer[-1]; // skip return address + + // Now set the thread state for the faulting thread so that PAL_DispatchException executes next + machret = thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)&ts64, x86_THREAD_STATE64_COUNT); + CHECK_MACH("thread_set_state(thread)", machret); +#else +#error HijackFaultingThread not defined for this architecture +#endif +} + +/*++ +Function : + SuspendMachThread + + Suspend the specified thread. + +Parameters: + thread - mach thread port + +Return value : + KERN_SUCCESS if the suspend succeeded, other code in case of failure +--*/ +static +kern_return_t +SuspendMachThread(thread_act_t thread) +{ + kern_return_t machret; + + while (true) + { + machret = thread_suspend(thread); + if (machret != KERN_SUCCESS) + { + break; + } + + // Ensure that if the thread was running in the kernel, the kernel operation + // is safely aborted so that it can be restarted later. + machret = thread_abort_safely(thread); + if (machret == KERN_SUCCESS) + { + break; + } + + // The thread was running in the kernel executing a non-atomic operation + // that cannot be restarted, so we need to resume the thread and retry + machret = thread_resume(thread); + if (machret != KERN_SUCCESS) + { + break; + } + } + + return machret; +} + +/*++ +Function : + SEHExceptionThread + + Entry point for the thread that will listen for exception in any other thread. + + NOTE: This thread is not a PAL thread, and it must not be one. If it was, + exceptions on this thread would be delivered to the port this thread itself + is listening on. + + In particular, if another thread overflows its stack, the exception handling + thread receives a message. It will try to create a PAL_DispatchException + frame on the faulting thread, which will likely fault. If the exception + processing thread is not a PAL thread, the process gets terminated with a + bus error; if the exception processing thread was a PAL thread, we would see + a hang (since no thread is listening for the exception message that gets sent). + Of the two ugly behaviors, the bus error is definitely favorable. + + This means: no printf, no TRACE, no PAL allocation, no ExitProcess, + no LastError in this function and its helpers. To report fatal failure, + use NONPAL_RETAIL_ASSERT. + +Parameters : + void *args - not used + +Return value : + Never returns +--*/ +void * +SEHExceptionThread(void *args) +{ + ForwardedExceptionList feList; + MachMessage sReplyOrForward; + MachMessage sMessage; + kern_return_t machret; + thread_act_t thread; + + // Loop processing incoming messages forever. + while (true) + { + // Receive the next message. + sMessage.Receive(s_ExceptionPort); + + NONPAL_TRACE("Received message %s (%08x) from (remote) %08x to (local) %08x\n", + sMessage.GetMessageTypeName(), + sMessage.GetMessageType(), + sMessage.GetRemotePort(), + sMessage.GetLocalPort()); + + if (sMessage.IsSetThreadRequest()) + { + // Handle a request to set the thread context for the specified target thread. + CONTEXT sContext; + thread = sMessage.GetThreadContext(&sContext); + + // Suspend the target thread + machret = SuspendMachThread(thread); + CHECK_MACH("SuspendMachThread", machret); + + machret = CONTEXT_SetThreadContextOnPort(thread, &sContext); + CHECK_MACH("CONTEXT_SetThreadContextOnPort", machret); + + machret = thread_resume(thread); + CHECK_MACH("thread_resume", machret); + } + else if (sMessage.IsExceptionNotification()) + { + // This is a notification of an exception occurring on another thread. + exception_type_t exceptionType = sMessage.GetException(); + thread = sMessage.GetThread(); + +#ifdef _DEBUG + if (NONPAL_TRACE_ENABLED) + { + NONPAL_TRACE("ExceptionNotification %s (%u) thread %08x flavor %u\n", + GetExceptionString(exceptionType), + exceptionType, + thread, + sMessage.GetThreadStateFlavor()); + + int subcode_count = sMessage.GetExceptionCodeCount(); + for (int i = 0; i < subcode_count; i++) + NONPAL_TRACE("ExceptionNotification subcode[%d] = %llx\n", i, sMessage.GetExceptionCode(i)); + + x86_thread_state64_t threadStateActual; + unsigned int count = sizeof(threadStateActual) / sizeof(unsigned); + machret = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)&threadStateActual, &count); + CHECK_MACH("thread_get_state", machret); + + NONPAL_TRACE("ExceptionNotification actual rip %016llx rsp %016llx rbp %016llx rax %016llx r15 %016llx eflags %08llx\n", + threadStateActual.__rip, + threadStateActual.__rsp, + threadStateActual.__rbp, + threadStateActual.__rax, + threadStateActual.__r15, + threadStateActual.__rflags); + + x86_exception_state64_t threadExceptionState; + unsigned int ehStateCount = sizeof(threadExceptionState) / sizeof(unsigned); + machret = thread_get_state(thread, x86_EXCEPTION_STATE64, (thread_state_t)&threadExceptionState, &ehStateCount); + CHECK_MACH("thread_get_state", machret); + + NONPAL_TRACE("ExceptionNotification trapno %04x cpu %04x err %08x faultAddr %016llx\n", + threadExceptionState.__trapno, + threadExceptionState.__cpu, + threadExceptionState.__err, + threadExceptionState.__faultvaddr); + } +#endif // _DEBUG + + bool feFound = false; + feList.MoveFirst(); + + while (!feList.IsEOL()) + { + mach_port_type_t ePortType; + if (mach_port_type(mach_task_self(), feList.Current->Thread, &ePortType) != KERN_SUCCESS || (ePortType & MACH_PORT_TYPE_DEAD_NAME)) + { + NONPAL_TRACE("Forwarded exception: invalid thread port %08x\n", feList.Current->Thread); + + // Unlink and delete the forwarded exception instance + feList.Delete(); + } + else + { + if (feList.Current->Thread == thread) + { + bool isSameException = feList.Current->ExceptionType == exceptionType; + feFound = true; + + // Locate the record of previously installed handlers that the target thread keeps. + CThreadMachExceptionHandlers *pHandlers = feList.Current->PalThread->GetSavedMachHandlers(); + + // Unlink and delete the forwarded exception instance + feList.Delete(); + + // Check if the current exception type matches the forwarded one and whether + // there's a handler for the particular exception we've been handed. + MachExceptionHandler sHandler; + if (isSameException && pHandlers->GetHandler(exceptionType, &sHandler)) + { + NONPAL_TRACE("ForwardNotification thread %08x to handler %08x\n", thread, sHandler.m_handler); + sReplyOrForward.ForwardNotification(&sHandler, sMessage); + } + else + { + NONPAL_TRACE("ReplyToNotification KERN_FAILURE thread %08x port %08x sameException %d\n", + thread, sMessage.GetRemotePort(), isSameException); + sReplyOrForward.ReplyToNotification(sMessage, KERN_FAILURE); + } + break; + } + + feList.MoveNext(); + } + } + + if (!feFound) + { + NONPAL_TRACE("HijackFaultingThread thread %08x\n", thread); + HijackFaultingThread(thread, mach_task_self(), sMessage); + + // Send the result of handling the exception back in a reply. + NONPAL_TRACE("ReplyToNotification KERN_SUCCESS thread %08x port %08x\n", thread, sMessage.GetRemotePort()); + sReplyOrForward.ReplyToNotification(sMessage, KERN_SUCCESS); + } + } + else if (sMessage.IsForwardExceptionRequest()) + { + thread = sMessage.GetThread(); + + NONPAL_TRACE("ForwardExceptionRequest for thread %08x\n", thread); + + // Suspend the faulting thread. + machret = SuspendMachThread(thread); + CHECK_MACH("SuspendMachThread", machret); + + // Set the context back to the original faulting state. + MachExceptionInfo *pExceptionInfo = sMessage.GetExceptionInfo(); + pExceptionInfo->RestoreState(thread); + + // Allocate an forwarded exception entry + ForwardedException *pfe = (ForwardedException *)malloc(sizeof(ForwardedException)); + if (pfe == NULL) + { + NONPAL_RETAIL_ASSERT("Exception thread ran out of memory to track forwarded exception notifications"); + } + + // Save the forwarded exception entry away for the restarted exception message + pfe->Thread = thread; + pfe->ExceptionType = pExceptionInfo->ExceptionType; + pfe->PalThread = sMessage.GetPalThread(); + feList.Add(pfe); + + // Now let the thread run at the original exception context to restart the exception + NONPAL_TRACE("ForwardExceptionRequest resuming thread %08x exception type %08x\n", thread, pfe->ExceptionType); + machret = thread_resume(thread); + CHECK_MACH("thread_resume", machret); + } + else + { + NONPAL_RETAIL_ASSERT("Unknown message type: %u", sMessage.GetMessageType()); + } + } +} + +/*++ +Function : + MachExceptionInfo constructor + + Saves the exception info from the exception notification message and + the current thread state. + +Parameters: + thread - thread port to restore + message - exception message + +Return value : + none +--*/ +MachExceptionInfo::MachExceptionInfo(mach_port_t thread, MachMessage& message) +{ + kern_return_t machret; + + ExceptionType = message.GetException(); + SubcodeCount = message.GetExceptionCodeCount(); + NONPAL_RETAIL_ASSERTE(SubcodeCount >= 0 && SubcodeCount <= 2); + + for (int i = 0; i < SubcodeCount; i++) + Subcodes[i] = message.GetExceptionCode(i); + + mach_msg_type_number_t count = x86_THREAD_STATE_COUNT; + machret = thread_get_state(thread, x86_THREAD_STATE, (thread_state_t)&ThreadState, &count); + CHECK_MACH("thread_get_state", machret); + + count = x86_FLOAT_STATE_COUNT; + machret = thread_get_state(thread, x86_FLOAT_STATE, (thread_state_t)&FloatState, &count); + CHECK_MACH("thread_get_state(float)", machret); + + count = x86_DEBUG_STATE_COUNT; + machret = thread_get_state(thread, x86_DEBUG_STATE, (thread_state_t)&DebugState, &count); + CHECK_MACH("thread_get_state(debug)", machret); +} + +/*++ +Function : + MachExceptionInfo::RestoreState + + Restore the thread to the saved exception info state. + +Parameters: + thread - thread port to restore + +Return value : + none +--*/ +void MachExceptionInfo::RestoreState(mach_port_t thread) +{ + // If we are restarting a breakpoint, we need to bump the IP back one to + // point at the actual int 3 instructions. + if (ExceptionType == EXC_BREAKPOINT) + { + if (Subcodes[0] == EXC_I386_BPT) + { +#ifdef HOST_X86 + ThreadState.uts.ts32.eip--; +#elif defined(HOST_AMD64) + ThreadState.uts.ts64.__rip--; +#else +#error Platform not supported +#endif + } + } + kern_return_t machret = thread_set_state(thread, x86_THREAD_STATE, (thread_state_t)&ThreadState, x86_THREAD_STATE_COUNT); + CHECK_MACH("thread_set_state(thread)", machret); + + machret = thread_set_state(thread, x86_FLOAT_STATE, (thread_state_t)&FloatState, x86_FLOAT_STATE_COUNT); + CHECK_MACH("thread_set_state(float)", machret); + + machret = thread_set_state(thread, x86_DEBUG_STATE, (thread_state_t)&DebugState, x86_DEBUG_STATE_COUNT); + CHECK_MACH("thread_set_state(debug)", machret); +} + +/*++ +Function : + MachSetThreadContext + + Sets the context of the current thread by sending a notification + to the exception thread. + +Parameters: + lpContext - the CONTEXT to set the current thread + +Return value : + Doesn't return +--*/ +PAL_NORETURN +void +MachSetThreadContext(CONTEXT *lpContext) +{ + // We need to send a message to the worker thread so that it can set our thread context. + MachMessage sRequest; + sRequest.SendSetThread(s_ExceptionPort, lpContext); + + // Make sure we don't do anything + while (TRUE) + { + sched_yield(); + } +} + + +/*++ +Function : + SEHInitializeMachExceptions + + Initialize all SEH-related stuff related to mach exceptions + + flags - PAL_INITIALIZE flags + +Return value : + TRUE if SEH support initialization succeeded + FALSE otherwise +--*/ +BOOL +SEHInitializeMachExceptions(DWORD flags) +{ + pthread_t exception_thread; + kern_return_t machret; + + s_PalInitializeFlags = flags; + + if (flags & PAL_INITIALIZE_REGISTER_SIGNALS) + { + // Allocate a mach port that will listen in on exceptions + machret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &s_ExceptionPort); + if (machret != KERN_SUCCESS) + { + ASSERT("mach_port_allocate failed: %d\n", machret); + UTIL_SetLastErrorFromMach(machret); + return FALSE; + } + + // Insert the send right into the task + machret = mach_port_insert_right(mach_task_self(), s_ExceptionPort, s_ExceptionPort, MACH_MSG_TYPE_MAKE_SEND); + if (machret != KERN_SUCCESS) + { + ASSERT("mach_port_insert_right failed: %d\n", machret); + UTIL_SetLastErrorFromMach(machret); + return FALSE; + } + + // Create the thread that will listen to the exception for all threads + int createret = pthread_create(&exception_thread, NULL, SEHExceptionThread, NULL); + if (createret != 0) + { + ERROR("pthread_create failed, error is %d (%s)\n", createret, strerror(createret)); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + +#ifdef _DEBUG + if (NONPAL_TRACE_ENABLED) + { + CThreadMachExceptionHandlers taskHandlers; + machret = task_get_exception_ports(mach_task_self(), + PAL_EXC_ALL_MASK, + taskHandlers.m_masks, + &taskHandlers.m_nPorts, + taskHandlers.m_handlers, + taskHandlers.m_behaviors, + taskHandlers.m_flavors); + + if (machret == KERN_SUCCESS) + { + NONPAL_TRACE("SEHInitializeMachExceptions: TASK PORT count %d\n", taskHandlers.m_nPorts); + for (mach_msg_type_number_t i = 0; i < taskHandlers.m_nPorts; i++) + { + NONPAL_TRACE("SEHInitializeMachExceptions: TASK PORT mask %08x handler: %08x behavior %08x flavor %u\n", + taskHandlers.m_masks[i], + taskHandlers.m_handlers[i], + taskHandlers.m_behaviors[i], + taskHandlers.m_flavors[i]); + } + } + else + { + NONPAL_TRACE("SEHInitializeMachExceptions: task_get_exception_ports FAILED %d %s\n", machret, mach_error_string(machret)); + } + } +#endif // _DEBUG + } + + // Tell the system to ignore SIGPIPE signals rather than use the default + // behavior of terminating the process. Ignoring SIGPIPE will cause + // calls that would otherwise raise that signal to return EPIPE instead. + // The PAL expects EPIPE from those functions and won't handle a + // SIGPIPE signal. + signal(SIGPIPE, SIG_IGN); + + // We're done + return TRUE; +} + +extern "C" +void +ActivationHandler(CONTEXT* context) +{ + if (g_activationFunction != NULL) + { + g_activationFunction(context); + } + + RtlRestoreContext(context, NULL); + DebugBreak(); +} + +extern "C" void ActivationHandlerWrapper(); +extern "C" int ActivationHandlerReturnOffset; +extern "C" unsigned int XmmYmmStateSupport(); + +/*++ +Function : + InjectActivationInternal + + Sets up the specified thread to call the ActivationHandler. + +Parameters: + pThread - PAL thread instance + +Return value : + PAL_ERROR +--*/ +PAL_ERROR +InjectActivationInternal(CPalThread* pThread) +{ + PAL_ERROR palError; + + mach_port_t threadPort = pThread->GetMachPortSelf(); + + kern_return_t MachRet = SuspendMachThread(threadPort); + palError = (MachRet == KERN_SUCCESS) ? NO_ERROR : ERROR_GEN_FAILURE; + + if (palError == NO_ERROR) + { + mach_msg_type_number_t count; + + x86_exception_state64_t ExceptionState; + count = x86_EXCEPTION_STATE64_COUNT; + MachRet = thread_get_state(threadPort, + x86_EXCEPTION_STATE64, + (thread_state_t)&ExceptionState, + &count); + _ASSERT_MSG(MachRet == KERN_SUCCESS, "thread_get_state for x86_EXCEPTION_STATE64\n"); + + // Inject the activation only if the thread doesn't have a pending hardware exception + static const int MaxHardwareExceptionVector = 31; + if (ExceptionState.__trapno > MaxHardwareExceptionVector) + { + x86_thread_state64_t ThreadState; + count = x86_THREAD_STATE64_COUNT; + MachRet = thread_get_state(threadPort, + x86_THREAD_STATE64, + (thread_state_t)&ThreadState, + &count); + _ASSERT_MSG(MachRet == KERN_SUCCESS, "thread_get_state for x86_THREAD_STATE64\n"); + + if ((g_safeActivationCheckFunction != NULL) && g_safeActivationCheckFunction(ThreadState.__rip, /* checkingCurrentThread */ FALSE)) + { + // TODO: it would be nice to preserve the red zone in case a jitter would want to use it + // Do we really care about unwinding through the wrapper? + size_t* sp = (size_t*)ThreadState.__rsp; + *(--sp) = ThreadState.__rip; + *(--sp) = ThreadState.__rbp; + size_t rbpAddress = (size_t)sp; + size_t contextAddress = (((size_t)sp) - sizeof(CONTEXT)) & ~15; + size_t returnAddressAddress = contextAddress - sizeof(size_t); + *(size_t*)(returnAddressAddress) = ActivationHandlerReturnOffset + (size_t)ActivationHandlerWrapper; + + // Fill in the context in the helper frame with the full context of the suspended thread. + // The ActivationHandler will use the context to resume the execution of the thread + // 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"); + + // Make the instruction register point to ActivationHandler + ThreadState.__rip = (size_t)ActivationHandler; + ThreadState.__rsp = returnAddressAddress; + ThreadState.__rbp = rbpAddress; + ThreadState.__rdi = contextAddress; + + MachRet = thread_set_state(threadPort, + x86_THREAD_STATE64, + (thread_state_t)&ThreadState, + count); + _ASSERT_MSG(MachRet == KERN_SUCCESS, "thread_set_state\n"); + } + } + + MachRet = thread_resume(threadPort); + palError = (MachRet == ERROR_SUCCESS) ? NO_ERROR : ERROR_GEN_FAILURE; + } + else + { + printf("Suspension failed with error 0x%x\n", palError); + } + + return palError; +} + +#endif // HAVE_MACH_EXCEPTIONS diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machexception.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machexception.h new file mode 100644 index 0000000..98512ff --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machexception.h @@ -0,0 +1,45 @@ +// 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: + + machexception.h + +Abstract: + Private mach exception handling utilities for SEH + +--*/ + +#ifndef _MACHEXCEPTION_H_ +#define _MACHEXCEPTION_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +// List of exception types we will be watching for +// NOTE: if you change any of these, you need to adapt s_nMachExceptionPortsMax in thread.hpp +#define PAL_EXC_ILLEGAL_MASK (EXC_MASK_BAD_INSTRUCTION | EXC_MASK_EMULATION) +#define PAL_EXC_DEBUGGING_MASK (EXC_MASK_BREAKPOINT | EXC_MASK_SOFTWARE) +#define PAL_EXC_MANAGED_MASK (EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC) +#define PAL_EXC_ALL_MASK (PAL_EXC_ILLEGAL_MASK | PAL_EXC_DEBUGGING_MASK | PAL_EXC_MANAGED_MASK) + +// Process and thread initialization/cleanup/context routines +BOOL SEHInitializeMachExceptions(DWORD flags); +void MachExceptionInitializeDebug(void); +PAL_NORETURN void MachSetThreadContext(CONTEXT *lpContext); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _MACHEXCEPTION_H_ */ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machmessage.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machmessage.cpp new file mode 100644 index 0000000..aa83687 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machmessage.cpp @@ -0,0 +1,1383 @@ +// 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: + + machmessage.cpp + +Abstract: + + Abstraction over Mach messages used during exception handling. + +--*/ + +#include "config.h" +#include "pal/dbgmsg.h" +#include "pal/environ.h" +#include "pal/malloc.hpp" +#include "pal/thread.hpp" +#include "machmessage.h" + +#if HAVE_MACH_EXCEPTIONS + +// Construct an empty message. Use Receive() to form a message that can be inspected or SendSetThread(), +// ForwardNotification(), ReplyToNotification() or ForwardReply() to construct a message and sent it. +MachMessage::MachMessage() +{ + m_fPortsOwned = false; + ResetMessage(); +} + +// Listen for the next message on the given port and initialize this class with the contents. The message type +// must match one of the MessageTypes indicated above (or the process will be aborted). +void MachMessage::Receive(mach_port_t hPort) +{ + kern_return_t machret; + + // Erase any stale data. + ResetMessage(); + + // Pull the next Mach message into the buffer. + machret = mach_msg((mach_msg_header_t*)m_rgMessageBuffer, + MACH_RCV_MSG | MACH_RCV_LARGE | MACH_RCV_NOTIFY, + 0, + kcbMaxMessageSize, + hPort, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + CHECK_MACH("mach_msg()", machret); + + // Check it's one of the messages we're expecting. + switch (m_pMessage->header.msgh_id) + { + case SET_THREAD_MESSAGE_ID: + case FORWARD_EXCEPTION_MESSAGE_ID: + case EXCEPTION_RAISE_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + case EXCEPTION_RAISE_REPLY_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_REPLY_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_MESSAGE_ID: + case EXCEPTION_RAISE_64_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + case EXCEPTION_RAISE_REPLY_64_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_REPLY_64_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64_MESSAGE_ID: + case NOTIFY_SEND_ONCE_MESSAGE_ID: + break; + default: + NONPAL_RETAIL_ASSERT("Unsupported message type: %u", m_pMessage->header.msgh_id); + } + + m_fPortsOwned = true; +} + +// Indicates whether the message is a request to set the context of a thread. +bool MachMessage::IsSetThreadRequest() +{ + return m_pMessage->header.msgh_id == SET_THREAD_MESSAGE_ID; +} + +// Indicates whether the message is a request to forward the exception +bool MachMessage::IsForwardExceptionRequest() +{ + return m_pMessage->header.msgh_id == FORWARD_EXCEPTION_MESSAGE_ID; +} + +// Indicates whether the message is a notification that a send-once message was destroyed by the receiver. +bool MachMessage::IsSendOnceDestroyedNotify() +{ + return m_pMessage->header.msgh_id == NOTIFY_SEND_ONCE_MESSAGE_ID; +} + +// Indicates whether the message is a notification of an exception. +bool MachMessage::IsExceptionNotification() +{ + switch (m_pMessage->header.msgh_id) + { + case EXCEPTION_RAISE_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + case EXCEPTION_RAISE_64_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + return true; + default: + return false; + } +} + +// Indicates whether the message is a reply to a notification of an exception. +bool MachMessage::IsExceptionReply() +{ + switch (m_pMessage->header.msgh_id) + { + case EXCEPTION_RAISE_REPLY_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_REPLY_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_MESSAGE_ID: + case EXCEPTION_RAISE_REPLY_64_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_REPLY_64_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64_MESSAGE_ID: + return true; + default: + return false; + } +} + +// Returns the type code for a received message. +MachMessage::MessageType MachMessage::GetMessageType() +{ + return (MessageType)m_pMessage->header.msgh_id; +} + +// Returns a textual form of the type of a received message. Useful for logging. +const char *MachMessage::GetMessageTypeName() +{ + switch (GetMessageType()) + { + case SET_THREAD_MESSAGE_ID: + return "SET_THREAD"; + case FORWARD_EXCEPTION_MESSAGE_ID: + return "FORWARD_EXCEPTION"; + case EXCEPTION_RAISE_MESSAGE_ID: + return "EXCEPTION_RAISE"; + case EXCEPTION_RAISE_REPLY_MESSAGE_ID: + return "EXCEPTION_RAISE_REPLY"; + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + return "EXCEPTION_RAISE_STATE"; + case EXCEPTION_RAISE_STATE_REPLY_MESSAGE_ID: + return "EXCEPTION_RAISE_STATE_REPLY"; + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + return "EXCEPTION_RAISE_STATE_IDENTITY"; + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_MESSAGE_ID: + return "EXCEPTION_RAISE_STATE_IDENTITY_REPLY"; + case EXCEPTION_RAISE_64_MESSAGE_ID: + return "EXCEPTION_RAISE_64"; + case EXCEPTION_RAISE_REPLY_64_MESSAGE_ID: + return "EXCEPTION_RAISE_REPLY_64"; + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + return "EXCEPTION_RAISE_STATE_64"; + case EXCEPTION_RAISE_STATE_REPLY_64_MESSAGE_ID: + return "EXCEPTION_RAISE_STATE_REPLY_64"; + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + return "EXCEPTION_RAISE_STATE_IDENTITY_64"; + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64_MESSAGE_ID: + return "EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64"; + case NOTIFY_SEND_ONCE_MESSAGE_ID: + return "NOTIFY_SEND_ONCE"; + default: + return ""; + } +} + +// Returns the destination port (i.e. the port we listened on to receive this message). +mach_port_t MachMessage::GetLocalPort() +{ + return m_pMessage->header.msgh_local_port; +} + +// Returns the source port (the port sending the message) unless no reply is expected, in which case +// MACH_PORT_NULL is returned instead. +mach_port_t MachMessage::GetRemotePort() +{ + return m_pMessage->header.msgh_remote_port; +} + +// Do the work of getting ports from the message. +// * fCalculate -- calculate the thread port if the message did not contain it. +// * fValidate -- failfast if the message was not one expected to have a (calculable) thread port. +void MachMessage::GetPorts(bool fCalculate, bool fValidThread) +{ + switch (m_pMessage->header.msgh_id) + { + case SET_THREAD_MESSAGE_ID: + m_hThread = m_pMessage->data.set_thread.thread; + break; + + case FORWARD_EXCEPTION_MESSAGE_ID: + m_hThread = m_pMessage->data.forward_exception.thread; + break; + + case EXCEPTION_RAISE_MESSAGE_ID: + m_hThread = m_pMessage->data.raise.thread_port.name; + m_hTask = m_pMessage->data.raise.task_port.name; + break; + + case EXCEPTION_RAISE_64_MESSAGE_ID: + m_hThread = m_pMessage->data.raise_64.thread_port.name; + m_hTask = m_pMessage->data.raise_64.task_port.name; + break; + + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + if (fCalculate && m_hThread == MACH_PORT_NULL) + { + // This is a tricky case since the message itself doesn't contain the target thread. + m_hThread = GetThreadFromState(m_pMessage->data.raise_state.flavor, + m_pMessage->data.raise_state.old_state); + } + break; + + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + if (fCalculate && m_hThread == MACH_PORT_NULL) + { + // This is a tricky case since the message itself doesn't contain the target thread. + m_hThread = GetThreadFromState(m_pMessage->data.raise_state_64.flavor, + m_pMessage->data.raise_state_64.old_state); + } + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + m_hThread = m_pMessage->data.raise_state_identity.thread_port.name; + m_hTask = m_pMessage->data.raise_state_identity.task_port.name; + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + m_hThread = m_pMessage->data.raise_state_identity_64.thread_port.name; + m_hTask = m_pMessage->data.raise_state_identity_64.task_port.name; + break; + + default: + if (fValidThread) + { + NONPAL_RETAIL_ASSERT("Can only get thread from notification message."); + } + break; + } +} + +// Get the properties of a set thread or forward exception request. Fills in the provided +// context structure with the context from the message and returns the target thread to +// which the context should be applied. +thread_act_t MachMessage::GetThreadContext(CONTEXT *pContext) +{ + NONPAL_ASSERTE(IsSetThreadRequest()); + + memcpy(pContext, &m_pMessage->data.set_thread.new_context, sizeof(CONTEXT)); + m_hThread = m_pMessage->data.set_thread.thread; + return m_hThread; +} + +// Get the target thread for an exception notification message. +thread_act_t MachMessage::GetThread() +{ + GetPorts(true /* fCalculate */, true /* fValidThread */); + return m_hThread; +} + +// Get the exception type for an exception notification message. +exception_type_t MachMessage::GetException() +{ + switch (m_pMessage->header.msgh_id) + { + case EXCEPTION_RAISE_MESSAGE_ID: + return m_pMessage->data.raise.exception; + + case EXCEPTION_RAISE_64_MESSAGE_ID: + return m_pMessage->data.raise_64.exception; + + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + return m_pMessage->data.raise_state.exception; + + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + return m_pMessage->data.raise_state_64.exception; + + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + return m_pMessage->data.raise_state_identity.exception; + + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + return m_pMessage->data.raise_state_identity_64.exception; + + default: + NONPAL_RETAIL_ASSERT("Can only get exception from notification message."); + } +} + +// Get the count of sub-codes for an exception notification message. +int MachMessage::GetExceptionCodeCount() +{ + switch (m_pMessage->header.msgh_id) + { + case EXCEPTION_RAISE_MESSAGE_ID: + return m_pMessage->data.raise.code_count; + + case EXCEPTION_RAISE_64_MESSAGE_ID: + return m_pMessage->data.raise_64.code_count; + + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + return m_pMessage->data.raise_state.code_count; + + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + return m_pMessage->data.raise_state_64.code_count; + + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + return m_pMessage->data.raise_state_identity.code_count; + + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + return m_pMessage->data.raise_state_identity_64.code_count; + + default: + NONPAL_RETAIL_ASSERT("Can only get exception code count from notification message."); + } +} + +// Get the exception sub-code at the specified zero-based index for an exception notification message. +MACH_EH_TYPE(exception_data_type_t) MachMessage::GetExceptionCode(int iIndex) +{ + if (iIndex < 0 || iIndex >= GetExceptionCodeCount()) + { + NONPAL_RETAIL_ASSERT("GetExceptionCode() index out of range."); + } + + switch (m_pMessage->header.msgh_id) + { + case EXCEPTION_RAISE_MESSAGE_ID: + return (MACH_EH_TYPE(exception_data_type_t))m_pMessage->data.raise.code[iIndex]; + + case EXCEPTION_RAISE_64_MESSAGE_ID: + return m_pMessage->data.raise_64.code[iIndex]; + + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + return (MACH_EH_TYPE(exception_data_type_t))m_pMessage->data.raise_state.code[iIndex]; + + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + return m_pMessage->data.raise_state_64.code[iIndex]; + + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + return (MACH_EH_TYPE(exception_data_type_t))m_pMessage->data.raise_state_identity.code[iIndex]; + + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + return m_pMessage->data.raise_state_identity_64.code[iIndex]; + + default: + NONPAL_RETAIL_ASSERT("Can only get exception code from notification message."); + } +} + +// Fetch the thread state flavor from a notification or reply message (return THREAD_STATE_NONE for the +// messages that don't contain a thread state). +thread_state_flavor_t MachMessage::GetThreadStateFlavor() +{ + switch (m_pMessage->header.msgh_id) + { + case EXCEPTION_RAISE_MESSAGE_ID: + case EXCEPTION_RAISE_REPLY_MESSAGE_ID: + case EXCEPTION_RAISE_64_MESSAGE_ID: + case EXCEPTION_RAISE_REPLY_64_MESSAGE_ID: + return THREAD_STATE_NONE; + + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + return m_pMessage->data.raise_state.flavor; + + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + return m_pMessage->data.raise_state_64.flavor; + + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + return m_pMessage->data.raise_state_identity.flavor; + + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + return m_pMessage->data.raise_state_identity_64.flavor; + + case EXCEPTION_RAISE_STATE_REPLY_MESSAGE_ID: + return m_pMessage->data.raise_state_reply.flavor; + + case EXCEPTION_RAISE_STATE_REPLY_64_MESSAGE_ID: + return m_pMessage->data.raise_state_reply_64.flavor; + + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_MESSAGE_ID: + return m_pMessage->data.raise_state_identity_reply.flavor; + + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64_MESSAGE_ID: + return m_pMessage->data.raise_state_identity_reply_64.flavor; + + default: + NONPAL_RETAIL_ASSERT("Unsupported message type: %u", m_pMessage->header.msgh_id); + } +} + +// Get the thread state with the given flavor from the exception or exception reply message. If the message +// doesn't contain a thread state or the flavor of the state in the message doesn't match, the state will be +// fetched directly from the target thread instead (which can be computed implicitly for exception messages or +// passed explicitly for reply messages). +mach_msg_type_number_t MachMessage::GetThreadState(thread_state_flavor_t eFlavor, thread_state_t pState, thread_act_t thread) +{ + mach_msg_type_number_t count; + kern_return_t machret; + + switch (m_pMessage->header.msgh_id) + { + case EXCEPTION_RAISE_MESSAGE_ID: + case EXCEPTION_RAISE_REPLY_MESSAGE_ID: + case EXCEPTION_RAISE_64_MESSAGE_ID: + case EXCEPTION_RAISE_REPLY_64_MESSAGE_ID: + // No state in the message, fall through to get it directly from the thread. + break; + + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + { + // There's a state in the message, but we need to check that the flavor matches what the caller's + // after (if not we'll fall through and get the correct flavor below). + if (m_pMessage->data.raise_state.flavor == eFlavor) + { + count = m_pMessage->data.raise_state.old_state_count; + memcpy(pState, m_pMessage->data.raise_state.old_state, count * sizeof(natural_t)); + return count; + } + break; + } + + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + { + // There's a state in the message, but we need to check that the flavor matches what the caller's + // after (if not we'll fall through and get the correct flavor below). + if (m_pMessage->data.raise_state_64.flavor == eFlavor) + { + count = m_pMessage->data.raise_state_64.old_state_count; + memcpy(pState, m_pMessage->data.raise_state_64.old_state, count * sizeof(natural_t)); + return count; + } + break; + } + + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + { + // There's a state in the message, but we need to check that the flavor matches what the caller's + // after (if not we'll fall through and get the correct flavor below). + if (m_pMessage->data.raise_state_identity.flavor == eFlavor) + { + count = m_pMessage->data.raise_state_identity.old_state_count; + memcpy(pState, m_pMessage->data.raise_state_identity.old_state, count * sizeof(natural_t)); + return count; + } + break; + } + + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + { + // There's a state in the message, but we need to check that the flavor matches what the caller's + // after (if not we'll fall through and get the correct flavor below). + if (m_pMessage->data.raise_state_identity_64.flavor == eFlavor) + { + count = m_pMessage->data.raise_state_identity_64.old_state_count; + memcpy(pState, m_pMessage->data.raise_state_identity_64.old_state, count * sizeof(natural_t)); + return count; + } + break; + } + + case EXCEPTION_RAISE_STATE_REPLY_MESSAGE_ID: + { + // There's a state in the message, but we need to check that the flavor matches what the caller's + // after (if not we'll fall through and get the correct flavor below). + if (m_pMessage->data.raise_state_reply.flavor == eFlavor) + { + count = m_pMessage->data.raise_state_reply.new_state_count; + memcpy(pState, m_pMessage->data.raise_state_reply.new_state, count * sizeof(natural_t)); + return count; + } + break; + } + + case EXCEPTION_RAISE_STATE_REPLY_64_MESSAGE_ID: + { + // There's a state in the message, but we need to check that the flavor matches what the caller's + // after (if not we'll fall through and get the correct flavor below). + if (m_pMessage->data.raise_state_reply_64.flavor == eFlavor) + { + count = m_pMessage->data.raise_state_reply_64.new_state_count; + memcpy(pState, m_pMessage->data.raise_state_reply_64.new_state, count * sizeof(natural_t)); + return count; + } + break; + } + + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_MESSAGE_ID: + { + // There's a state in the message, but we need to check that the flavor matches what the caller's + // after (if not we'll fall through and get the correct flavor below). + if (m_pMessage->data.raise_state_identity_reply.flavor == eFlavor) + { + count = m_pMessage->data.raise_state_identity_reply.new_state_count; + memcpy(pState, m_pMessage->data.raise_state_identity_reply.new_state, count * sizeof(natural_t)); + return count; + } + break; + } + + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64_MESSAGE_ID: + { + // There's a state in the message, but we need to check that the flavor matches what the caller's + // after (if not we'll fall through and get the correct flavor below). + if (m_pMessage->data.raise_state_identity_reply_64.flavor == eFlavor) + { + count = m_pMessage->data.raise_state_identity_reply_64.new_state_count; + memcpy(pState, m_pMessage->data.raise_state_identity_reply_64.new_state, count * sizeof(natural_t)); + return count; + } + break; + } + + default: + NONPAL_RETAIL_ASSERT("Unsupported message type for requesting thread state."); + } + + // No state in the message or the flavor didn't match. Get the requested flavor of state directly from the + // thread instead. + count = THREAD_STATE_MAX; + machret = thread_get_state(thread ? thread : GetThread(), eFlavor, (thread_state_t)pState, &count); + CHECK_MACH("thread_get_state()", machret); + + return count; +} + +// Fetch the return code from a reply type message. +kern_return_t MachMessage::GetReturnCode() +{ + switch (m_pMessage->header.msgh_id) + { + case EXCEPTION_RAISE_REPLY_MESSAGE_ID: + return m_pMessage->data.raise_reply.ret; + + case EXCEPTION_RAISE_REPLY_64_MESSAGE_ID: + return m_pMessage->data.raise_reply_64.ret; + + case EXCEPTION_RAISE_STATE_REPLY_MESSAGE_ID: + return m_pMessage->data.raise_state_reply.ret; + + case EXCEPTION_RAISE_STATE_REPLY_64_MESSAGE_ID: + return m_pMessage->data.raise_state_reply_64.ret; + + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_MESSAGE_ID: + return m_pMessage->data.raise_state_identity_reply.ret; + + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64_MESSAGE_ID: + return m_pMessage->data.raise_state_identity_reply_64.ret; + + default: + NONPAL_RETAIL_ASSERT("Unsupported message type: %u", m_pMessage->header.msgh_id); + } +} + +// Initialize and send a request to set the register context of a particular thread. +void MachMessage::SendSetThread(mach_port_t hServerPort, CONTEXT *pContext) +{ + kern_return_t machret; + + // Set the message type. + m_pMessage->header.msgh_id = SET_THREAD_MESSAGE_ID; + + // Initialize the fields that don't need any further input (this depends on the message type having been + // set above). + InitFixedFields(); + + // Initialize type-specific fields. The receiving end is responsible for deallocating the thread port. + m_pMessage->data.set_thread.thread = mach_thread_self(); + memcpy(&m_pMessage->data.set_thread.new_context, pContext, sizeof(CONTEXT)); + + // Initialize header fields. + m_pMessage->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); + m_pMessage->header.msgh_remote_port = hServerPort; // Destination port + m_pMessage->header.msgh_local_port = MACH_PORT_NULL; // We expect no reply + + // Set the message header size field based on the contents of the message (call this function after all + // other fields have been initialized). + InitMessageSize(); + + // Send the formatted message. + machret = mach_msg((mach_msg_header_t*)m_pMessage, + MACH_SEND_MSG | MACH_MSG_OPTION_NONE, + m_pMessage->header.msgh_size, + 0, + MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + CHECK_MACH("mach_msg()", machret); + + // Erase any stale data. (This may not finish executing; nothing is needed to be freed here.) + ResetMessage(); +} + +void MachMessage::SendForwardException(mach_port_t hServerPort, MachExceptionInfo *pExceptionInfo, CPalThread *ppalThread) +{ + kern_return_t machret; + + // Set the message type. + m_pMessage->header.msgh_id = FORWARD_EXCEPTION_MESSAGE_ID; + + // Initialize the fields that don't need any further input (this depends on the message type having been + // set above). + InitFixedFields(); + + // Initialize type-specific fields. The receiving end is responsible for deallocating the thread port. + m_pMessage->data.forward_exception.thread = mach_thread_self(); + m_pMessage->data.forward_exception.ppalThread = ppalThread; + memcpy(&m_pMessage->data.forward_exception.exception_info, pExceptionInfo, sizeof(MachExceptionInfo)); + + // Initialize header fields. + m_pMessage->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); + m_pMessage->header.msgh_remote_port = hServerPort; // Destination port + m_pMessage->header.msgh_local_port = MACH_PORT_NULL; // We expect no reply + + // Set the message header size field based on the contents of the message (call this function after all + // other fields have been initialized). + InitMessageSize(); + + // Send the formatted message. + machret = mach_msg((mach_msg_header_t*)m_pMessage, + MACH_SEND_MSG | MACH_MSG_OPTION_NONE, + m_pMessage->header.msgh_size, + 0, + MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + CHECK_MACH("mach_msg()", machret); + + // Erase any stale data. + ResetMessage(); +} + +// Returns the pal thread instance for the forward exception message +CPalThread *MachMessage::GetPalThread() +{ + NONPAL_ASSERTE(IsForwardExceptionRequest()); + return m_pMessage->data.forward_exception.ppalThread; +} + +MachExceptionInfo *MachMessage::GetExceptionInfo() +{ + NONPAL_ASSERTE(IsForwardExceptionRequest()); + return &m_pMessage->data.forward_exception.exception_info; +} + +// Initialize the message to represent a forwarded version of the given exception notification message and +// send that message to the chain-back handler previously registered for the exception type being notified. +// The new message takes account of the fact that the target handler may not have requested the same notification +// behavior or flavor as our handler. A new Mach port is created to receive the reply, and this port is returned +// to the caller. Clean up the message afterwards. +void MachMessage::ForwardNotification(MachExceptionHandler *pHandler, MachMessage& message) +{ + kern_return_t machret; + + // Set the message type. + m_pMessage->header.msgh_id = MapBehaviorToNotificationType(pHandler->m_behavior); + + // Initialize the fields that don't need any further input (this depends on the message type having been + // set above). + InitFixedFields(); + + // Copy data from the incoming message. Use the getter and setter abstractions to simplify the act that + // the two messages may be in different formats (e.g. RAISE vs RAISE_STATE). We silently drop data that is + // not needed in the outgoing message and synthesize any required data that is not present in the incoming + // message. + SetThread(message.GetThread()); + SetException(message.GetException()); + + int cCodes = message.GetExceptionCodeCount(); + SetExceptionCodeCount(cCodes); + for (int i = 0; i < cCodes; i++) + SetExceptionCode(i, message.GetExceptionCode(i)); + + // Don't bother fetching thread state unless the destination actually requires it. + if (pHandler->m_flavor != THREAD_STATE_NONE) + { + thread_state_data_t threadState; + mach_msg_type_number_t count = message.GetThreadState(pHandler->m_flavor, (thread_state_t)&threadState); + SetThreadState(pHandler->m_flavor, (thread_state_t)&threadState, count); + } + + // Initialize header fields. + m_pMessage->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MOVE_SEND_ONCE); + m_pMessage->header.msgh_remote_port = pHandler->m_handler; // Forward to here + m_pMessage->header.msgh_local_port = message.GetRemotePort(); // The reply will come here + + // Set the message header size field based on the contents of the message (call this function after all + // other fields have been initialized). + InitMessageSize(); + + // Send the formatted message. + machret = mach_msg((mach_msg_header_t*)m_pMessage, + MACH_SEND_MSG | MACH_MSG_OPTION_NONE, + m_pMessage->header.msgh_size, + 0, + MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + CHECK_MACH("mach_msg()", machret); + + // Erase any stale data. + ResetMessage(); +} + +// Initialize the message to represent a reply to the given exception notification message +// and send that reply back to the original sender of the notification. This is used when +// our handler handles the exception rather than forwarding it to a chain-back handler. +// Clean up the message afterwards. +void MachMessage::ReplyToNotification(MachMessage& message, kern_return_t eResult) +{ + kern_return_t machret; + + // Set the message type. + m_pMessage->header.msgh_id = MapNotificationToReplyType(message.m_pMessage->header.msgh_id); + + // Initialize the fields that don't need any further input (this depends on the message type having been + // set above). + InitFixedFields(); + + SetReturnCode(eResult); + + thread_state_flavor_t eNotificationFlavor = message.GetThreadStateFlavor(); + if (eNotificationFlavor != THREAD_STATE_NONE) + { + // If the reply requires a thread state be sure to get it from the thread directly rather than the + // notification message (handling the exception is likely to have changed the thread state). + thread_state_data_t threadState; + mach_msg_type_number_t count = THREAD_STATE_MAX; + machret = thread_get_state(message.GetThread(), eNotificationFlavor, (thread_state_t)&threadState, &count); + + SetThreadState(eNotificationFlavor, (thread_state_t)&threadState, count); + } + + // Initialize header fields. + m_pMessage->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0); + m_pMessage->header.msgh_remote_port = message.GetRemotePort(); // Reply goes back to sender + m_pMessage->header.msgh_local_port = 0; // No reply to this expected + + // Set the message header size field based on the contents of the message (call this function after all + // other fields have been initialized). + InitMessageSize(); + + // Send the formatted message. + machret = mach_msg((mach_msg_header_t*)m_pMessage, + MACH_SEND_MSG | MACH_MSG_OPTION_NONE, + m_pMessage->header.msgh_size, + 0, + MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + CHECK_MACH("mach_msg()", machret); + + // Erase any stale data. + ResetMessage(); +} + +// Re-initializes this data structure (to the same state as default construction, containing no message). +void MachMessage::ResetMessage() +{ + // Clean up ports if we own them. + if (m_fPortsOwned) + { + kern_return_t machret; + + GetPorts(false /* fCalculate */, false /* fValidThread */); + if (m_hThread != MACH_PORT_NULL) + { + machret = mach_port_deallocate(mach_task_self(), m_hThread); + CHECK_MACH("mach_port_deallocate(m_hThread)", machret); + } + + if (m_hTask != MACH_PORT_NULL) + { + machret = mach_port_deallocate(mach_task_self(), m_hTask); + CHECK_MACH("mach_port_deallocate(m_hTask)", machret); + } + } + +#ifdef _DEBUG + memset(this, 0xcc, sizeof(*this)); +#endif + + m_pMessage = (mach_message_t*)m_rgMessageBuffer; + m_hThread = MACH_PORT_NULL; + m_hTask = MACH_PORT_NULL; + m_fPortsOwned = false; +} + +// Initialize those fields of a message that are invariant. This method expects that the msgh_id field has +// been filled in prior to the call so it can determine which non-header fields to initialize. +void MachMessage::InitFixedFields() +{ + switch (m_pMessage->header.msgh_id) + { + case SET_THREAD_MESSAGE_ID: + break; + + case FORWARD_EXCEPTION_MESSAGE_ID: + break; + + case EXCEPTION_RAISE_MESSAGE_ID: + m_pMessage->data.raise.msgh_body.msgh_descriptor_count = 0; + m_pMessage->data.raise.ndr = NDR_record; + m_pMessage->data.raise.task_port.name = mach_task_self(); + m_pMessage->data.raise.task_port.pad1 = 0; + m_pMessage->data.raise.task_port.pad2 = 0; + m_pMessage->data.raise.task_port.disposition = MACH_MSG_TYPE_COPY_SEND; + m_pMessage->data.raise.task_port.type = MACH_MSG_PORT_DESCRIPTOR; + m_hTask = mach_task_self(); + break; + + case EXCEPTION_RAISE_64_MESSAGE_ID: + m_pMessage->data.raise_64.msgh_body.msgh_descriptor_count = 0; + m_pMessage->data.raise_64.ndr = NDR_record; + m_pMessage->data.raise_64.task_port.name = mach_task_self(); + m_pMessage->data.raise_64.task_port.pad1 = 0; + m_pMessage->data.raise_64.task_port.pad2 = 0; + m_pMessage->data.raise_64.task_port.disposition = MACH_MSG_TYPE_COPY_SEND; + m_pMessage->data.raise_64.task_port.type = MACH_MSG_PORT_DESCRIPTOR; + m_hTask = mach_task_self(); + break; + + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + m_pMessage->data.raise_state.ndr = NDR_record; + break; + + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + m_pMessage->data.raise_state_64.ndr = NDR_record; + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + m_pMessage->data.raise_state_identity.msgh_body.msgh_descriptor_count = 0; + m_pMessage->data.raise_state_identity.ndr = NDR_record; + m_pMessage->data.raise_state_identity.task_port.name = mach_task_self(); + m_pMessage->data.raise_state_identity.task_port.pad1 = 0; + m_pMessage->data.raise_state_identity.task_port.pad2 = 0; + m_pMessage->data.raise_state_identity.task_port.disposition = MACH_MSG_TYPE_COPY_SEND; + m_pMessage->data.raise_state_identity.task_port.type = MACH_MSG_PORT_DESCRIPTOR; + m_hTask = mach_task_self(); + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + m_pMessage->data.raise_state_identity_64.msgh_body.msgh_descriptor_count = 0; + m_pMessage->data.raise_state_identity_64.ndr = NDR_record; + m_pMessage->data.raise_state_identity_64.task_port.name = mach_task_self(); + m_pMessage->data.raise_state_identity_64.task_port.pad1 = 0; + m_pMessage->data.raise_state_identity_64.task_port.pad2 = 0; + m_pMessage->data.raise_state_identity_64.task_port.disposition = MACH_MSG_TYPE_COPY_SEND; + m_pMessage->data.raise_state_identity_64.task_port.type = MACH_MSG_PORT_DESCRIPTOR; + m_hTask = mach_task_self(); + break; + + case EXCEPTION_RAISE_REPLY_MESSAGE_ID: + m_pMessage->data.raise_reply.ndr = NDR_record; + break; + + case EXCEPTION_RAISE_REPLY_64_MESSAGE_ID: + m_pMessage->data.raise_reply_64.ndr = NDR_record; + break; + + case EXCEPTION_RAISE_STATE_REPLY_MESSAGE_ID: + m_pMessage->data.raise_state_reply.ndr = NDR_record; + break; + + case EXCEPTION_RAISE_STATE_REPLY_64_MESSAGE_ID: + m_pMessage->data.raise_state_reply_64.ndr = NDR_record; + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_MESSAGE_ID: + m_pMessage->data.raise_state_identity_reply.ndr = NDR_record; + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64_MESSAGE_ID: + m_pMessage->data.raise_state_identity_reply_64.ndr = NDR_record; + break; + + default: + NONPAL_RETAIL_ASSERT("Unhandled message type: %u", m_pMessage->header.msgh_id); + } + + m_pMessage->header.msgh_reserved = 0; + + if (m_hTask) + { + kern_return_t machret; + // Addref the task, because the receiver will expect it to own it. (or, if we + // free it unsent, we'll expect to deallocate it). + machret = mach_port_mod_refs(mach_task_self(), m_hTask, MACH_PORT_RIGHT_SEND, 1); + } +} + +// Initialize the size field of the message header (msgh_size) based on the message type and other fields. +// This should be called after all other fields have been initialized. +void MachMessage::InitMessageSize() +{ + // Note that in particular the kernel is very particular about the size of messages with embedded thread + // states. The size of the message must reflect the exact size of the state flavor contained, not the + // maximum size of a thread state that the message format implies. + + switch (m_pMessage->header.msgh_id) + { + case SET_THREAD_MESSAGE_ID: + m_pMessage->header.msgh_size = sizeof(mach_msg_header_t) + sizeof(set_thread_request_t); + break; + + case FORWARD_EXCEPTION_MESSAGE_ID: + m_pMessage->header.msgh_size = sizeof(mach_msg_header_t) + sizeof(forward_exception_request_t); + break; + + case EXCEPTION_RAISE_MESSAGE_ID: + m_pMessage->header.msgh_size = sizeof(mach_msg_header_t) + sizeof(exception_raise_notification_t); + break; + + case EXCEPTION_RAISE_64_MESSAGE_ID: + m_pMessage->header.msgh_size = sizeof(mach_msg_header_t) + sizeof(exception_raise_notification_64_t); + break; + + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + m_pMessage->header.msgh_size = sizeof(mach_msg_header_t) + + offsetof(exception_raise_state_notification_t, old_state) + + (m_pMessage->data.raise_state.old_state_count * sizeof(natural_t)); + break; + + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + m_pMessage->header.msgh_size = sizeof(mach_msg_header_t) + + offsetof(exception_raise_state_notification_64_t, old_state) + + (m_pMessage->data.raise_state_64.old_state_count * sizeof(natural_t)); + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + m_pMessage->header.msgh_size = sizeof(mach_msg_header_t) + + offsetof(exception_raise_state_identity_notification_t, old_state) + + (m_pMessage->data.raise_state_identity.old_state_count * sizeof(natural_t)); + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + m_pMessage->header.msgh_size = sizeof(mach_msg_header_t) + + offsetof(exception_raise_state_identity_notification_64_t, old_state) + + (m_pMessage->data.raise_state_identity_64.old_state_count * sizeof(natural_t)); + break; + + case EXCEPTION_RAISE_REPLY_MESSAGE_ID: + m_pMessage->header.msgh_size = sizeof(mach_msg_header_t) + sizeof(exception_raise_reply_t); + break; + + case EXCEPTION_RAISE_REPLY_64_MESSAGE_ID: + m_pMessage->header.msgh_size = sizeof(mach_msg_header_t) + sizeof(exception_raise_reply_64_t); + break; + + case EXCEPTION_RAISE_STATE_REPLY_MESSAGE_ID: + m_pMessage->header.msgh_size = sizeof(mach_msg_header_t) + + offsetof(exception_raise_state_reply_t, new_state) + + (m_pMessage->data.raise_state_reply.new_state_count * sizeof(natural_t)); + break; + + case EXCEPTION_RAISE_STATE_REPLY_64_MESSAGE_ID: + m_pMessage->header.msgh_size = sizeof(mach_msg_header_t) + + offsetof(exception_raise_state_reply_64_t, new_state) + + (m_pMessage->data.raise_state_reply_64.new_state_count * sizeof(natural_t)); + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_MESSAGE_ID: + m_pMessage->header.msgh_size = sizeof(mach_msg_header_t) + + offsetof(exception_raise_state_identity_reply_t, new_state) + + (m_pMessage->data.raise_state_identity_reply.new_state_count * sizeof(natural_t)); + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64_MESSAGE_ID: + m_pMessage->header.msgh_size = sizeof(mach_msg_header_t) + + offsetof(exception_raise_state_identity_reply_64_t, new_state) + + (m_pMessage->data.raise_state_identity_reply_64.new_state_count * sizeof(natural_t)); + break; + + default: + NONPAL_RETAIL_ASSERT("Unhandled message type: %u", m_pMessage->header.msgh_id); + } +} + +// Given a thread's register context, locate and return the Mach port representing that thread. Only the +// x86_THREAD_STATE and x86_THREAD_STATE32 state flavors are supported for 32-bit. +thread_act_t MachMessage::GetThreadFromState(thread_state_flavor_t eFlavor, thread_state_t pState) +{ + SIZE_T targetSP; + + // Determine SP from the state provided based on its flavor (this algorithm only works with SP, so + // flavors that don't report this register can't be used). However, hosts that use RAISE_STATE and a + // flavor of state that don't contain SP should be very, very rare indeed (it's hard to imagine many + // useful exception handlers that receive neither the exception thread or the general registers of that + // thread). + switch (eFlavor) + { +#ifdef HOST_X86 + case x86_THREAD_STATE: + targetSP = ((x86_thread_state_t*)pState)->uts.ts32.esp; + break; + + case x86_THREAD_STATE32: + targetSP = ((x86_thread_state32_t*)pState)->esp; + break; +#elif defined(HOST_AMD64) + case x86_THREAD_STATE: + targetSP = ((x86_thread_state_t*)pState)->uts.ts64.__rsp; + break; + + case x86_THREAD_STATE64: + targetSP = ((x86_thread_state64_t*)pState)->__rsp; + break; +#else +#error Unexpected architecture. +#endif + default: + NONPAL_RETAIL_ASSERT("Unhandled thread state flavor: %u", eFlavor); + } + + // Capture the list of threads in the current task. Obviously this changes asynchronously to us, but that + // doesn't matter since we know the thread we're after is suspended in the kernel and can't go anywhere. + mach_msg_type_number_t cThreads; + thread_act_t *pThreads; + kern_return_t machret = task_threads(mach_task_self(), &pThreads, &cThreads); + CHECK_MACH("task_threads()", machret); + + // Iterate through each of the threads in the list. + for (mach_msg_type_number_t i = 0; i < cThreads; i++) + { + // Get the general register state of each thread. + x86_thread_state_t threadState; + mach_msg_type_number_t count = x86_THREAD_STATE_COUNT; + machret = thread_get_state(pThreads[i], x86_THREAD_STATE, (thread_state_t)&threadState, &count); + if (machret == KERN_SUCCESS) + { + // If a thread has the same SP as our target it should be the same thread (otherwise we have two + // threads sharing the same stack which is very bad). Conversely the thread we're looking for is + // suspended in the kernel so its SP should not change. We should always be able to find an exact + // match as a result. +#ifdef HOST_X86 + if (threadState.uts.ts32.esp == targetSP) +#elif defined(HOST_AMD64) + if (threadState.uts.ts64.__rsp == targetSP) +#else +#error Unexpected architecture. +#endif + { + thread_act_t thread = pThreads[i]; + + // Increment the refcount; the thread is a "send" right. + machret = mach_port_mod_refs(mach_task_self(), thread, MACH_PORT_RIGHT_SEND, 1); + CHECK_MACH("mach_port_mod_refs()", machret); + + // Deallocate the thread list now we're done with it. + machret = vm_deallocate(mach_task_self(), (vm_address_t)pThreads, cThreads * sizeof(thread_act_t)); + CHECK_MACH("vm_deallocate()", machret); + + // Return the thread we found. + return thread; + } + } + } + + // If we got here no thread matched. That shouldn't be possible. + NONPAL_RETAIL_ASSERT("Failed to locate thread from state."); +} + +// 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) + { + case EXCEPTION_DEFAULT: + return EXCEPTION_RAISE_MESSAGE_ID; + case EXCEPTION_STATE: + return EXCEPTION_RAISE_STATE_MESSAGE_ID; + case EXCEPTION_STATE_IDENTITY: + return EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID; + case MACH_EXCEPTION_CODES|EXCEPTION_DEFAULT: + return EXCEPTION_RAISE_64_MESSAGE_ID; + case MACH_EXCEPTION_CODES|EXCEPTION_STATE: + return EXCEPTION_RAISE_STATE_64_MESSAGE_ID; + case MACH_EXCEPTION_CODES|EXCEPTION_STATE_IDENTITY: + return EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID; + default: + NONPAL_RETAIL_ASSERT("Unsupported exception behavior type: %u", eBehavior); + } +} + +// Transform a Mach message ID for an exception notification into the corresponding ID for the reply. +mach_msg_id_t MachMessage::MapNotificationToReplyType(mach_msg_id_t eNotificationType) +{ + switch (eNotificationType) + { + case EXCEPTION_RAISE_MESSAGE_ID: + return EXCEPTION_RAISE_REPLY_MESSAGE_ID; + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + return EXCEPTION_RAISE_STATE_REPLY_MESSAGE_ID; + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + return EXCEPTION_RAISE_STATE_IDENTITY_REPLY_MESSAGE_ID; + case EXCEPTION_RAISE_64_MESSAGE_ID: + return EXCEPTION_RAISE_REPLY_64_MESSAGE_ID; + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + return EXCEPTION_RAISE_STATE_REPLY_64_MESSAGE_ID; + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + return EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64_MESSAGE_ID; + default: + NONPAL_RETAIL_ASSERT("Unsupported message type: %u", eNotificationType); + } +} + +// Set faulting thread in an exception notification message. +void MachMessage::SetThread(thread_act_t thread) +{ + bool fSet = false; + + switch (m_pMessage->header.msgh_id) + { + case EXCEPTION_RAISE_MESSAGE_ID: + m_pMessage->data.raise.thread_port.name = thread; + m_pMessage->data.raise.thread_port.pad1 = 0; + m_pMessage->data.raise.thread_port.pad2 = 0; + m_pMessage->data.raise.thread_port.disposition = MACH_MSG_TYPE_COPY_SEND; + m_pMessage->data.raise.thread_port.type = MACH_MSG_PORT_DESCRIPTOR; + fSet = true; + break; + + case EXCEPTION_RAISE_64_MESSAGE_ID: + m_pMessage->data.raise_64.thread_port.name = thread; + m_pMessage->data.raise_64.thread_port.pad1 = 0; + m_pMessage->data.raise_64.thread_port.pad2 = 0; + m_pMessage->data.raise_64.thread_port.disposition = MACH_MSG_TYPE_COPY_SEND; + m_pMessage->data.raise_64.thread_port.type = MACH_MSG_PORT_DESCRIPTOR; + fSet = true; + break; + + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + // No thread field in RAISE_STATE messages. + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + m_pMessage->data.raise_state_identity.thread_port.name = thread; + m_pMessage->data.raise_state_identity.thread_port.pad1 = 0; + m_pMessage->data.raise_state_identity.thread_port.pad2 = 0; + m_pMessage->data.raise_state_identity.thread_port.disposition = MACH_MSG_TYPE_COPY_SEND; + m_pMessage->data.raise_state_identity.thread_port.type = MACH_MSG_PORT_DESCRIPTOR; + fSet = true; + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + m_pMessage->data.raise_state_identity_64.thread_port.name = thread; + m_pMessage->data.raise_state_identity_64.thread_port.pad1 = 0; + m_pMessage->data.raise_state_identity_64.thread_port.pad2 = 0; + m_pMessage->data.raise_state_identity_64.thread_port.disposition = MACH_MSG_TYPE_COPY_SEND; + m_pMessage->data.raise_state_identity_64.thread_port.type = MACH_MSG_PORT_DESCRIPTOR; + fSet = true; + break; + + default: + NONPAL_RETAIL_ASSERT("Unsupported message type: %u", m_pMessage->header.msgh_id); + } + + if (fSet) + { + // Addref the thread port. + kern_return_t machret; + machret = mach_port_mod_refs(mach_task_self(), thread, MACH_PORT_RIGHT_SEND, 1); + } +} + +// Set exception type in an exception notification message. +void MachMessage::SetException(exception_type_t eException) +{ + switch (m_pMessage->header.msgh_id) + { + case EXCEPTION_RAISE_MESSAGE_ID: + m_pMessage->data.raise.exception = eException; + break; + + case EXCEPTION_RAISE_64_MESSAGE_ID: + m_pMessage->data.raise_64.exception = eException; + break; + + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + m_pMessage->data.raise_state.exception = eException; + break; + + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + m_pMessage->data.raise_state_64.exception = eException; + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + m_pMessage->data.raise_state_identity.exception = eException; + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + m_pMessage->data.raise_state_identity_64.exception = eException; + break; + + default: + NONPAL_RETAIL_ASSERT("Unsupported message type: %u", m_pMessage->header.msgh_id); + } +} + +// Set exception sub-code count in an exception notification message. +void MachMessage::SetExceptionCodeCount(int cCodes) +{ + switch (m_pMessage->header.msgh_id) + { + case EXCEPTION_RAISE_MESSAGE_ID: + m_pMessage->data.raise.code_count = cCodes; + break; + + case EXCEPTION_RAISE_64_MESSAGE_ID: + m_pMessage->data.raise_64.code_count = cCodes; + break; + + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + m_pMessage->data.raise_state.code_count = cCodes; + break; + + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + m_pMessage->data.raise_state_64.code_count = cCodes; + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + m_pMessage->data.raise_state_identity.code_count = cCodes; + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + m_pMessage->data.raise_state_identity_64.code_count = cCodes; + break; + + default: + NONPAL_RETAIL_ASSERT("Unsupported message type: %u", m_pMessage->header.msgh_id); + } +} + +// Set exception sub-code in an exception notification message. +void MachMessage::SetExceptionCode(int iIndex, MACH_EH_TYPE(exception_data_type_t) iCode) +{ + if (iIndex < 0 || iIndex > 1) + NONPAL_RETAIL_ASSERT("Exception code index out of range"); + + // Note that although the 64-bit message variants support 64-bit exception sub-codes the CoreCLR only + // supports 32-bit processes. We should never see the upper 32-bits containing a non-zero value therefore. + + switch (m_pMessage->header.msgh_id) + { + case EXCEPTION_RAISE_MESSAGE_ID: + m_pMessage->data.raise.code[iIndex] = (int)iCode; + break; + + case EXCEPTION_RAISE_64_MESSAGE_ID: + m_pMessage->data.raise_64.code[iIndex] = iCode; + break; + + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + m_pMessage->data.raise_state.code[iIndex] = (int)iCode; + break; + + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + m_pMessage->data.raise_state_64.code[iIndex] = iCode; + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + m_pMessage->data.raise_state_identity.code[iIndex] = (int)iCode; + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + m_pMessage->data.raise_state_identity_64.code[iIndex] = iCode; + break; + + default: + NONPAL_RETAIL_ASSERT("Unsupported message type: %u", m_pMessage->header.msgh_id); + } +} + +// Set return code in a reply message. +void MachMessage::SetReturnCode(kern_return_t eReturnCode) +{ + switch (m_pMessage->header.msgh_id) + { + case EXCEPTION_RAISE_REPLY_MESSAGE_ID: + m_pMessage->data.raise_reply.ret = eReturnCode; + break; + + case EXCEPTION_RAISE_REPLY_64_MESSAGE_ID: + m_pMessage->data.raise_reply_64.ret = eReturnCode; + break; + + case EXCEPTION_RAISE_STATE_REPLY_MESSAGE_ID: + m_pMessage->data.raise_state_reply.ret = eReturnCode; + break; + + case EXCEPTION_RAISE_STATE_REPLY_64_MESSAGE_ID: + m_pMessage->data.raise_state_reply_64.ret = eReturnCode; + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_MESSAGE_ID: + m_pMessage->data.raise_state_identity_reply.ret = eReturnCode; + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64_MESSAGE_ID: + m_pMessage->data.raise_state_identity_reply_64.ret = eReturnCode; + break; + + default: + NONPAL_RETAIL_ASSERT("Unsupported message type: %u", m_pMessage->header.msgh_id); + } +} + +// Set faulting thread register state in an exception notification or reply message. +void MachMessage::SetThreadState(thread_state_flavor_t eFlavor, thread_state_t pState, mach_msg_type_number_t count) +{ + switch (m_pMessage->header.msgh_id) + { + case EXCEPTION_RAISE_MESSAGE_ID: + case EXCEPTION_RAISE_REPLY_MESSAGE_ID: + case EXCEPTION_RAISE_64_MESSAGE_ID: + case EXCEPTION_RAISE_REPLY_64_MESSAGE_ID: + // No thread state in RAISE or RAISE_REPLY messages. + break; + + case EXCEPTION_RAISE_STATE_MESSAGE_ID: + m_pMessage->data.raise_state.flavor = eFlavor; + m_pMessage->data.raise_state.old_state_count = count; + memcpy(m_pMessage->data.raise_state.old_state, pState, count * sizeof(natural_t)); + break; + + case EXCEPTION_RAISE_STATE_64_MESSAGE_ID: + m_pMessage->data.raise_state_64.flavor = eFlavor; + m_pMessage->data.raise_state_64.old_state_count = count; + memcpy(m_pMessage->data.raise_state_64.old_state, pState, count * sizeof(natural_t)); + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID: + m_pMessage->data.raise_state_identity.flavor = eFlavor; + m_pMessage->data.raise_state_identity.old_state_count = count; + memcpy(m_pMessage->data.raise_state_identity.old_state, pState, count * sizeof(natural_t)); + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID: + m_pMessage->data.raise_state_identity_64.flavor = eFlavor; + m_pMessage->data.raise_state_identity_64.old_state_count = count; + memcpy(m_pMessage->data.raise_state_identity_64.old_state, pState, count * sizeof(natural_t)); + break; + + case EXCEPTION_RAISE_STATE_REPLY_MESSAGE_ID: + m_pMessage->data.raise_state_reply.flavor = eFlavor; + m_pMessage->data.raise_state_reply.new_state_count = count; + memcpy(m_pMessage->data.raise_state_reply.new_state, pState, count * sizeof(natural_t)); + break; + + case EXCEPTION_RAISE_STATE_REPLY_64_MESSAGE_ID: + m_pMessage->data.raise_state_reply_64.flavor = eFlavor; + m_pMessage->data.raise_state_reply_64.new_state_count = count; + memcpy(m_pMessage->data.raise_state_reply_64.new_state, pState, count * sizeof(natural_t)); + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_MESSAGE_ID: + m_pMessage->data.raise_state_identity_reply.flavor = eFlavor; + m_pMessage->data.raise_state_identity_reply.new_state_count = count; + memcpy(m_pMessage->data.raise_state_identity_reply.new_state, pState, count * sizeof(natural_t)); + break; + + case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64_MESSAGE_ID: + m_pMessage->data.raise_state_identity_reply_64.flavor = eFlavor; + m_pMessage->data.raise_state_identity_reply_64.new_state_count = count; + memcpy(m_pMessage->data.raise_state_identity_reply_64.new_state, pState, count * sizeof(natural_t)); + break; + + default: + NONPAL_RETAIL_ASSERT("Unsupported message type: %u", m_pMessage->header.msgh_id); + } +} + +#endif // HAVE_MACH_EXCEPTIONS diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machmessage.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machmessage.h new file mode 100644 index 0000000..91d4c97 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/machmessage.h @@ -0,0 +1,441 @@ +// 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: + + machmessage.h + +Abstract: + + Abstraction over Mach messages used during exception handling. + +--*/ + +#include +#include +#include + +using namespace CorUnix; + +#if HAVE_MACH_EXCEPTIONS + +#if defined(HOST_AMD64) +#define MACH_EH_TYPE(x) mach_##x +#else +#define MACH_EH_TYPE(x) x +#endif // defined(HOST_AMD64) + +// The vast majority of Mach calls we make in this module are critical: we cannot recover from failures of +// these methods (principally because we're handling hardware exceptions in the context of a single dedicated +// handler thread). The following macro encapsulates checking the return code from Mach methods and emitting +// some useful data and aborting the process on failure. +#define CHECK_MACH(_msg, machret) do { \ + if (machret != KERN_SUCCESS) \ + { \ + char _szError[1024]; \ + snprintf(_szError, _countof(_szError), "%s: %u: %s", __FUNCTION__, __LINE__, _msg); \ + mach_error(_szError, machret); \ + abort(); \ + } \ + } while (false) + +// This macro terminates the process with some useful debug info as above, but for the general failure points +// that have nothing to do with Mach. +#define NONPAL_RETAIL_ASSERT(_msg, ...) do { \ + printf("%s: %u: " _msg "\n", __FUNCTION__, __LINE__, ## __VA_ARGS__); \ + abort(); \ + } while (false) + +#define NONPAL_RETAIL_ASSERTE(_expr) do { \ + if (!(_expr)) \ + NONPAL_RETAIL_ASSERT("ASSERT: %s\n", #_expr); \ + } while (false) + +#ifdef _DEBUG + +#define NONPAL_TRACE_ENABLED EnvironGetenv("NONPAL_TRACING", /* copyValue */ false) + +#define NONPAL_ASSERT(_msg, ...) NONPAL_RETAIL_ASSERT(_msg, __VA_ARGS__) + +// Assert macro that doesn't rely on the PAL. +#define NONPAL_ASSERTE(_expr) do { \ + if (!(_expr)) \ + NONPAL_RETAIL_ASSERT("ASSERT: %s\n", #_expr); \ + } while (false) + +// Debug-only output with printf-style formatting. +#define NONPAL_TRACE(_format, ...) do { \ + if (NONPAL_TRACE_ENABLED) printf("NONPAL_TRACE: " _format, ## __VA_ARGS__); \ + } while (false) + +#else // _DEBUG + +#define NONPAL_TRACE_ENABLED false +#define NONPAL_ASSERT(_msg, ...) +#define NONPAL_ASSERTE(_expr) +#define NONPAL_TRACE(_format, ...) + +#endif // _DEBUG + +class MachMessage; + +// Contains all the exception and thread state information needed to forward the exception. +struct MachExceptionInfo +{ + exception_type_t ExceptionType; + mach_msg_type_number_t SubcodeCount; + MACH_EH_TYPE(exception_data_type_t) Subcodes[2]; + x86_thread_state_t ThreadState; + x86_float_state_t FloatState; + x86_debug_state_t DebugState; + + MachExceptionInfo(mach_port_t thread, MachMessage& message); + void RestoreState(mach_port_t thread); +}; + +// Abstraction of a subset of Mach message types. Provides accessors that hide the subtle differences in the +// message layout of similar message types. +class MachMessage +{ +public: + // The message types handled by this class. The values are the actual type codes set in the Mach message + // header. + enum MessageType + { + SET_THREAD_MESSAGE_ID = 1, + FORWARD_EXCEPTION_MESSAGE_ID = 2, + NOTIFY_SEND_ONCE_MESSAGE_ID = 71, + EXCEPTION_RAISE_MESSAGE_ID = 2401, + EXCEPTION_RAISE_STATE_MESSAGE_ID = 2402, + EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID = 2403, + EXCEPTION_RAISE_64_MESSAGE_ID = 2405, + EXCEPTION_RAISE_STATE_64_MESSAGE_ID = 2406, + EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID = 2407, + EXCEPTION_RAISE_REPLY_MESSAGE_ID = 2501, + EXCEPTION_RAISE_STATE_REPLY_MESSAGE_ID = 2502, + EXCEPTION_RAISE_STATE_IDENTITY_REPLY_MESSAGE_ID = 2503, + EXCEPTION_RAISE_REPLY_64_MESSAGE_ID = 2505, + EXCEPTION_RAISE_STATE_REPLY_64_MESSAGE_ID = 2506, + EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64_MESSAGE_ID = 2507 + }; + + // Construct an empty message. Use Receive() to form a message that can be inspected or SendSetThread(), + // ForwardNotification() or ReplyToNotification() to construct a message and sent it. + MachMessage(); + + // Listen for the next message on the given port and initialize this class with the contents. The message + // type must match one of the MessageTypes indicated above (or the process will be aborted). + void Receive(mach_port_t hPort); + + // Indicate whether a received message belongs to a particular semantic class. + bool IsSetThreadRequest(); // Message is a request to set the context of a particular thread + bool IsForwardExceptionRequest(); // Message is a request to forward the exception + bool IsSendOnceDestroyedNotify(); // Message is a notification that a send-once message was destroyed by the receiver + bool IsExceptionNotification(); // Message is a notification of an exception + bool IsExceptionReply(); // Message is a reply to the notification of an exception + + // Get properties of a received message header. + MessageType GetMessageType(); // The message type + const char *GetMessageTypeName(); // An ASCII representation of the message type for logging purposes + mach_port_t GetLocalPort(); // The destination port the message was sent to + mach_port_t GetRemotePort(); // The source port the message came from (if a reply is expected) + + // Get the properties of a set thread request. Fills in the provided context structure with the context + // from the message and returns the target thread to which the context should be applied. + thread_act_t GetThreadContext(CONTEXT *pContext); + + // Returns the pal thread instance for the forward exception message + CPalThread *GetPalThread(); + + // Returns the exception info from the forward exception message + MachExceptionInfo *GetExceptionInfo(); + + // Get properties of the type-specific portion of the message. The following properties are supported by + // exception notification messages only. + thread_act_t GetThread(); // Get the faulting thread + exception_type_t GetException(); // Get the exception type (e.g. EXC_BAD_ACCESS) + int GetExceptionCodeCount(); // Get the number of exception sub-codes + MACH_EH_TYPE(exception_data_type_t) GetExceptionCode(int iIndex); // Get the exception sub-code at the given index + + // Fetch the thread state flavor from a notification or reply message (return THREAD_STATE_NONE for the + // messages that don't contain a thread state). + thread_state_flavor_t GetThreadStateFlavor(); + + // Get the thread state with the given flavor from the exception or exception reply message. If the + // message doesn't contain a thread state or the flavor of the state in the message doesn't match, the + // state will be fetched directly from the target thread instead (which can be computed implicitly for + // exception messages or passed explicitly for reply messages). + mach_msg_type_number_t GetThreadState(thread_state_flavor_t eFlavor, thread_state_t pState, thread_act_t thread = NULL); + + // Fetch the return code from a reply type message. + kern_return_t GetReturnCode(); + + // Initialize and send a request to set the register context of a particular thread. + void SendSetThread(mach_port_t hServerPort, CONTEXT *pContext); + + // Initialize and send a request to forward the exception message to the notification thread + void SendForwardException(mach_port_t hServerPort, MachExceptionInfo *pExceptionInfo, CPalThread *ppalThread); + + // Initialize the message (overwriting any previous content) to represent a forwarded version of the given + // exception notification message and send that message to the chain-back handler previously registered + // for the exception type being notified. The new message takes account of the fact that the target + // handler may not have requested the same notification behavior or flavor as our handler. + void ForwardNotification(MachExceptionHandler *pHandler, MachMessage& message); + + // Initialize the message (overwriting any previous content) to represent a reply to the given exception + // notification and send that reply back to the original sender of the notification. This is used when our + // handler handles the exception rather than forwarding it to a chain-back handler. + void ReplyToNotification(MachMessage& message, kern_return_t eResult); + +private: + // The maximum size in bytes of any Mach message we can send or receive. Calculating an exact size for + // this is non trivial (basically because of the security trailers that Mach appends) but the current + // value has proven to be more than enough so far. + static const size_t kcbMaxMessageSize = 1500; + + // The following are structures describing the formats of the Mach messages we understand. + + // Request to set the register context on a particular thread. + // SET_THREAD_MESSAGE_ID + struct set_thread_request_t + { + thread_act_t thread; + CONTEXT new_context; + }; + + // Request to forward the exception notification + // FORWARD_EXCEPTION_MESSAGE_ID + struct forward_exception_request_t + { + thread_act_t thread; + CPalThread *ppalThread; + MachExceptionInfo exception_info; + }; + +#pragma pack(4) + + // EXCEPTION_RAISE_MESSAGE_ID + struct exception_raise_notification_t + { + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread_port; + mach_msg_port_descriptor_t task_port; + NDR_record_t ndr; + exception_type_t exception; + mach_msg_type_number_t code_count; + exception_data_type_t code[2]; + }; + + // EXCEPTION_RAISE_REPLY_MESSAGE_ID + struct exception_raise_reply_t + { + NDR_record_t ndr; + kern_return_t ret; + }; + + // EXCEPTION_RAISE_64_MESSAGE_ID + struct exception_raise_notification_64_t + { + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread_port; + mach_msg_port_descriptor_t task_port; + NDR_record_t ndr; + exception_type_t exception; + mach_msg_type_number_t code_count; + mach_exception_data_type_t code[2]; + }; + + // EXCEPTION_RAISE_REPLY_64_MESSAGE_ID + struct exception_raise_reply_64_t + { + NDR_record_t ndr; + kern_return_t ret; + }; + + // EXCEPTION_RAISE_STATE_MESSAGE_ID + struct exception_raise_state_notification_t + { + NDR_record_t ndr; + exception_type_t exception; + mach_msg_type_number_t code_count; + exception_data_type_t code[2]; + thread_state_flavor_t flavor; + mach_msg_type_number_t old_state_count; + natural_t old_state[THREAD_STATE_MAX]; + }; + + // EXCEPTION_RAISE_STATE_REPLY_MESSAGE_ID + struct exception_raise_state_reply_t + { + NDR_record_t ndr; + kern_return_t ret; + thread_state_flavor_t flavor; + mach_msg_type_number_t new_state_count; + natural_t new_state[THREAD_STATE_MAX]; + }; + + // EXCEPTION_RAISE_STATE_64_MESSAGE_ID + struct exception_raise_state_notification_64_t + { + NDR_record_t ndr; + exception_type_t exception; + mach_msg_type_number_t code_count; + mach_exception_data_type_t code[2]; + thread_state_flavor_t flavor; + mach_msg_type_number_t old_state_count; + natural_t old_state[THREAD_STATE_MAX]; + }; + + // EXCEPTION_RAISE_STATE_REPLY_64_MESSAGE_ID + struct exception_raise_state_reply_64_t + { + NDR_record_t ndr; + kern_return_t ret; + thread_state_flavor_t flavor; + mach_msg_type_number_t new_state_count; + natural_t new_state[THREAD_STATE_MAX]; + }; + + // EXCEPTION_RAISE_STATE_IDENTITY_MESSAGE_ID + struct exception_raise_state_identity_notification_t + { + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread_port; + mach_msg_port_descriptor_t task_port; + NDR_record_t ndr; + exception_type_t exception; + mach_msg_type_number_t code_count; + exception_data_type_t code[2]; + thread_state_flavor_t flavor; + mach_msg_type_number_t old_state_count; + natural_t old_state[THREAD_STATE_MAX]; + }; + + // EXCEPTION_RAISE_STATE_IDENTITY_REPLY_MESSAGE_ID + struct exception_raise_state_identity_reply_t + { + NDR_record_t ndr; + kern_return_t ret; + thread_state_flavor_t flavor; + mach_msg_type_number_t new_state_count; + natural_t new_state[THREAD_STATE_MAX]; + }; + + // EXCEPTION_RAISE_STATE_IDENTITY_64_MESSAGE_ID + struct exception_raise_state_identity_notification_64_t + { + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread_port; + mach_msg_port_descriptor_t task_port; + NDR_record_t ndr; + exception_type_t exception; + mach_msg_type_number_t code_count; + mach_exception_data_type_t code[2]; + thread_state_flavor_t flavor; + mach_msg_type_number_t old_state_count; + natural_t old_state[THREAD_STATE_MAX]; + }; + + // EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64_MESSAGE_ID + struct exception_raise_state_identity_reply_64_t + { + NDR_record_t ndr; + kern_return_t ret; + thread_state_flavor_t flavor; + mach_msg_type_number_t new_state_count; + natural_t new_state[THREAD_STATE_MAX]; + }; + +#pragma pack() + + // All the above messages are sent with a standard Mach header prepended. This structure unifies the + // message formats. + struct mach_message_t + { + mach_msg_header_t header; + union + { + set_thread_request_t set_thread; + forward_exception_request_t forward_exception; + exception_raise_notification_t raise; + exception_raise_state_notification_t raise_state; + exception_raise_state_identity_notification_t raise_state_identity; + exception_raise_notification_64_t raise_64; + exception_raise_state_notification_64_t raise_state_64; + exception_raise_state_identity_notification_64_t raise_state_identity_64; + exception_raise_reply_t raise_reply; + exception_raise_state_reply_t raise_state_reply; + exception_raise_state_identity_reply_t raise_state_identity_reply; + exception_raise_reply_64_t raise_reply_64; + exception_raise_state_reply_64_t raise_state_reply_64; + exception_raise_state_identity_reply_64_t raise_state_identity_reply_64; + } data; + } __attribute__((packed));; + + // Re-initializes this data structure (to the same state as default construction, containing no message). + void ResetMessage(); + + // Initialize those fields of a message that are invariant. This method expects that the msgh_id field has + // been filled in prior to the call so it can determine which non-header fields to initialize. + void InitFixedFields(); + + // Initialize the size field of the message header (msgh_size) based on the message type and other fields. + // This should be called after all other fields have been initialized. + void InitMessageSize(); + + // Do the work of getting ports from the message. + // * fCalculate -- calculate the thread port if the message did not contain it. + // * fValidate -- failfast if the message was not one expected to have a (calculable) thread port. + void GetPorts(bool fCalculate, bool fValidThread); + + // Given a thread's register context, locate and return the Mach port representing that thread. Only the + // 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 an exception handler behavior type into the corresponding Mach message ID for the + // notification. + mach_msg_id_t MapBehaviorToNotificationType(exception_behavior_t eBehavior); + + // Transform a Mach message ID for an exception notification into the corresponding ID for the reply. + mach_msg_id_t MapNotificationToReplyType(mach_msg_id_t eNotificationType); + + // The following methods initialize fields on the message prior to transmission. Each is valid for either + // notification, replies or both. If a particular setter is defined for replies, say, then it will be a + // no-op for any replies which don't contain that field. This makes transforming between notifications and + // replies of different types simpler (we can copy a super-set of all fields between the two, but only + // those operations that make sense will do any work). + + // Defined for notifications: + void SetThread(thread_act_t thread); + void SetException(exception_type_t eException); + void SetExceptionCodeCount(int cCodes); + void SetExceptionCode(int iIndex, MACH_EH_TYPE(exception_data_type_t) iCode); + + // Defined for replies: + void SetReturnCode(kern_return_t eReturnCode); + + // Defined for both notifications and replies. + void SetThreadState(thread_state_flavor_t eFlavor, thread_state_t pState, mach_msg_type_number_t count); + + // Maximally sized buffer for the message to be received into or transmitted out of this class. + unsigned char m_rgMessageBuffer[kcbMaxMessageSize]; + + // Initialized by ResetMessage() to point to the buffer above. Gives a typed view of the encapsulated Mach + // message. + mach_message_t *m_pMessage; + + // Cached value of GetThread() or MACH_PORT_NULL if that has not been computed yet. + thread_act_t m_hThread; + + // Cached value of the task port or MACH_PORT_NULL if the message doesn't have one. + mach_port_t m_hTask; + + // Considered whether we are responsible for the deallocation of the ports in + // this message. It is true for messages we receive, and false for messages we send. + bool m_fPortsOwned; +}; + +#endif // HAVE_MACH_EXCEPTIONS diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/remote-unwind.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/remote-unwind.cpp new file mode 100644 index 0000000..355905e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/remote-unwind.cpp @@ -0,0 +1,482 @@ +// 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: + + remote-unwind.cpp + +Abstract: + + Implementation of out of context unwind using libunwind8 + remote unwind API. + +This file contains code based on libunwind8 + +Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--*/ + +#include "config.h" +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/critsect.h" +#include "pal/debug.h" +#include "pal_endian.h" +#include "pal.h" +#define __STDC_FORMAT_MACROS +#include +#include + +// Sub-headers included from the libunwind.h contain an empty struct +// and clang issues a warning. Until the libunwind is fixed, disable +// the warning. +#ifdef __llvm__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextern-c-compat" +#endif +#include +#ifdef __llvm__ +#pragma clang diagnostic pop +#endif + +SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); + +#if defined(HAVE_UNW_GET_ACCESSORS) + +#include +#include + +#if defined(HOST_X86) || defined(HOST_ARM) +#define PRIx PRIx32 +#define PRIu PRIu32 +#define PRId PRId32 +#define PRIA "08" +#define PRIxA PRIA PRIx +#elif defined(HOST_AMD64) || defined(HOST_ARM64) +#define PRIx PRIx64 +#define PRIu PRIu64 +#define PRId PRId64 +#define PRIA "016" +#define PRIxA PRIA PRIx +#endif + +#ifndef ElfW +#define ElfW(foo) Elf_ ## foo +#endif +#define Ehdr ElfW(Ehdr) +#define Phdr ElfW(Phdr) +#define Shdr ElfW(Shdr) +#define Nhdr ElfW(Nhdr) +#define Dyn ElfW(Dyn) + +extern "C" int +_OOP_find_proc_info( + unw_word_t start_ip, + unw_word_t end_ip, + unw_word_t eh_frame_table, + unw_word_t eh_frame_table_len, + unw_word_t exidx_frame_table, + unw_word_t exidx_frame_table_len, + unw_addr_space_t as, + unw_word_t ip, + unw_proc_info_t *pi, + int need_unwind_info, + void *arg); + +extern void GetContextPointers( + unw_cursor_t *cursor, + unw_context_t *unwContext, + KNONVOLATILE_CONTEXT_POINTERS *contextPointers); + +typedef struct _libunwindInfo +{ + SIZE_T BaseAddress; + CONTEXT *Context; + UnwindReadMemoryCallback ReadMemory; +} libunwindInfo; + +static void UnwindContextToContext(unw_cursor_t *cursor, CONTEXT *winContext) +{ +#if defined(HOST_AMD64) + unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Rip); + unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Rsp); + unw_get_reg(cursor, UNW_X86_64_RBP, (unw_word_t *) &winContext->Rbp); + unw_get_reg(cursor, UNW_X86_64_RBX, (unw_word_t *) &winContext->Rbx); + unw_get_reg(cursor, UNW_X86_64_R12, (unw_word_t *) &winContext->R12); + 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(HOST_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(HOST_ARM) + unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc); + unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp); + unw_get_reg(cursor, UNW_ARM_R4, (unw_word_t *) &winContext->R4); + unw_get_reg(cursor, UNW_ARM_R5, (unw_word_t *) &winContext->R5); + unw_get_reg(cursor, UNW_ARM_R6, (unw_word_t *) &winContext->R6); + unw_get_reg(cursor, UNW_ARM_R7, (unw_word_t *) &winContext->R7); + unw_get_reg(cursor, UNW_ARM_R8, (unw_word_t *) &winContext->R8); + unw_get_reg(cursor, UNW_ARM_R9, (unw_word_t *) &winContext->R9); + unw_get_reg(cursor, UNW_ARM_R10, (unw_word_t *) &winContext->R10); + unw_get_reg(cursor, UNW_ARM_R11, (unw_word_t *) &winContext->R11); + unw_get_reg(cursor, UNW_ARM_R14, (unw_word_t *) &winContext->Lr); + TRACE("sp %p pc %p lr %p\n", winContext->Sp, winContext->Pc, winContext->Lr); +#elif defined(HOST_ARM64) + unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc); + unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp); + unw_get_reg(cursor, UNW_AARCH64_X19, (unw_word_t *) &winContext->X19); + unw_get_reg(cursor, UNW_AARCH64_X20, (unw_word_t *) &winContext->X20); + unw_get_reg(cursor, UNW_AARCH64_X21, (unw_word_t *) &winContext->X21); + unw_get_reg(cursor, UNW_AARCH64_X22, (unw_word_t *) &winContext->X22); + unw_get_reg(cursor, UNW_AARCH64_X23, (unw_word_t *) &winContext->X23); + unw_get_reg(cursor, UNW_AARCH64_X24, (unw_word_t *) &winContext->X24); + unw_get_reg(cursor, UNW_AARCH64_X25, (unw_word_t *) &winContext->X25); + unw_get_reg(cursor, UNW_AARCH64_X26, (unw_word_t *) &winContext->X26); + unw_get_reg(cursor, UNW_AARCH64_X27, (unw_word_t *) &winContext->X27); + unw_get_reg(cursor, UNW_AARCH64_X28, (unw_word_t *) &winContext->X28); + unw_get_reg(cursor, UNW_AARCH64_X29, (unw_word_t *) &winContext->Fp); + unw_get_reg(cursor, UNW_AARCH64_X30, (unw_word_t *) &winContext->Lr); + TRACE("sp %p pc %p lr %p fp %p\n", winContext->Sp, winContext->Pc, winContext->Lr, winContext->Fp); +#else +#error unsupported architecture +#endif +} + +static int +get_dyn_info_list_addr(unw_addr_space_t as, unw_word_t *dilap, void *arg) +{ + return -UNW_ENOINFO; +} + +static int +access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, int write, void *arg) +{ + if (write) + { + ASSERT("Memory write must never be called by libunwind during stackwalk\n"); + return -UNW_EINVAL; + } + const auto *info = (libunwindInfo*)arg; + + if (info->ReadMemory((PVOID)addr, valp, sizeof(*valp))) + { + return UNW_ESUCCESS; + } + else + { + return -UNW_EUNSPEC; + } +} + +static int +access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, int write, void *arg) +{ + if (write) + { + ASSERT("Register write must never be called by libunwind during stackwalk\n"); + return -UNW_EREADONLYREG; + } + + const auto *info = (libunwindInfo*)arg; + CONTEXT *winContext = info->Context; + + switch (regnum) + { +#if defined(HOST_AMD64) + case UNW_REG_IP: *valp = (unw_word_t)winContext->Rip; break; + case UNW_REG_SP: *valp = (unw_word_t)winContext->Rsp; break; + case UNW_X86_64_RBP: *valp = (unw_word_t)winContext->Rbp; break; + case UNW_X86_64_RBX: *valp = (unw_word_t)winContext->Rbx; break; + case UNW_X86_64_R12: *valp = (unw_word_t)winContext->R12; break; + case UNW_X86_64_R13: *valp = (unw_word_t)winContext->R13; break; + case UNW_X86_64_R14: *valp = (unw_word_t)winContext->R14; break; + case UNW_X86_64_R15: *valp = (unw_word_t)winContext->R15; break; +#elif defined(HOST_X86) + case UNW_REG_IP: *valp = (unw_word_t)winContext->Eip; break; + case UNW_REG_SP: *valp = (unw_word_t)winContext->Esp; break; + case UNW_X86_EBX: *valp = (unw_word_t)winContext->Ebx; break; + case UNW_X86_ESI: *valp = (unw_word_t)winContext->Esi; break; + case UNW_X86_EDI: *valp = (unw_word_t)winContext->Edi; break; + case UNW_X86_EBP: *valp = (unw_word_t)winContext->Ebp; break; +#elif defined(HOST_ARM) + case UNW_ARM_R4: *valp = (unw_word_t)winContext->R4; break; + case UNW_ARM_R5: *valp = (unw_word_t)winContext->R5; break; + case UNW_ARM_R6: *valp = (unw_word_t)winContext->R6; break; + case UNW_ARM_R7: *valp = (unw_word_t)winContext->R7; break; + case UNW_ARM_R8: *valp = (unw_word_t)winContext->R8; break; + case UNW_ARM_R9: *valp = (unw_word_t)winContext->R9; break; + case UNW_ARM_R10: *valp = (unw_word_t)winContext->R10; break; + case UNW_ARM_R11: *valp = (unw_word_t)winContext->R11; break; + case UNW_ARM_R13: *valp = (unw_word_t)winContext->Sp; break; + case UNW_ARM_R14: *valp = (unw_word_t)winContext->Lr; break; + case UNW_ARM_R15: *valp = (unw_word_t)winContext->Pc; break; +#elif defined(HOST_ARM64) + case UNW_AARCH64_X19: *valp = (unw_word_t)winContext->X19; break; + case UNW_AARCH64_X20: *valp = (unw_word_t)winContext->X20; break; + case UNW_AARCH64_X21: *valp = (unw_word_t)winContext->X21; break; + case UNW_AARCH64_X22: *valp = (unw_word_t)winContext->X22; break; + case UNW_AARCH64_X23: *valp = (unw_word_t)winContext->X23; break; + case UNW_AARCH64_X24: *valp = (unw_word_t)winContext->X24; break; + case UNW_AARCH64_X25: *valp = (unw_word_t)winContext->X25; break; + case UNW_AARCH64_X26: *valp = (unw_word_t)winContext->X26; break; + case UNW_AARCH64_X27: *valp = (unw_word_t)winContext->X27; break; + case UNW_AARCH64_X28: *valp = (unw_word_t)winContext->X28; break; + case UNW_AARCH64_X29: *valp = (unw_word_t)winContext->Fp; break; + case UNW_AARCH64_X30: *valp = (unw_word_t)winContext->Lr; break; + case UNW_AARCH64_SP: *valp = (unw_word_t)winContext->Sp; break; + case UNW_AARCH64_PC: *valp = (unw_word_t)winContext->Pc; break; +#else +#error unsupported architecture +#endif + default: + ASSERT("Attempt to read an unknown register %d\n", regnum); + return -UNW_EBADREG; + } + TRACE("REG: %d %p\n", regnum, *valp); + return UNW_ESUCCESS; +} + +static int +access_fpreg(unw_addr_space_t as, unw_regnum_t regnum, unw_fpreg_t *fpvalp, int write, void *arg) +{ + ASSERT("Not supposed to be ever called\n"); + return -UNW_EINVAL; +} + +static int +resume(unw_addr_space_t as, unw_cursor_t *cp, void *arg) +{ + ASSERT("Not supposed to be ever called\n"); + return -UNW_EINVAL; +} + +static int +get_proc_name(unw_addr_space_t as, unw_word_t addr, char *bufp, size_t buf_len, unw_word_t *offp, void *arg) +{ + ASSERT("Not supposed to be ever called\n"); + return -UNW_EINVAL; +} + +static int +find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pip, int need_unwind_info, void *arg) +{ + const auto *info = (libunwindInfo*)arg; + memset(pip, 0, sizeof(*pip)); + + Ehdr ehdr; + if (!info->ReadMemory((void*)info->BaseAddress, &ehdr, sizeof(ehdr))) { + ERROR("ELF: reading ehdr %p\n", info->BaseAddress); + return -UNW_EINVAL; + } + Phdr* phdrAddr = reinterpret_cast(info->BaseAddress + ehdr.e_phoff); + int phnum = ehdr.e_phnum; + TRACE("ELF: base %p ip %p e_type %d e_phnum %d e_phoff %p\n", info->BaseAddress, ip, ehdr.e_type, ehdr.e_phnum, ehdr.e_phoff); + + unw_word_t loadbias = info->BaseAddress; + for (int i = 0; i < phnum; i++) + { + Phdr ph; + if (!info->ReadMemory(phdrAddr + i, &ph, sizeof(ph))) { + ERROR("ELF: reading phdrAddr %p\n", phdrAddr + i); + return -UNW_EINVAL; + } + if (ph.p_type == PT_LOAD && ph.p_offset == 0) + { + loadbias -= ph.p_vaddr; + TRACE("PHDR: loadbias %p\n", loadbias); + break; + } + } + + unw_word_t start_ip = (unw_word_t)-1; + unw_word_t end_ip = 0; + + // The eh_frame header address + unw_word_t ehFrameHdrAddr = 0; + unw_word_t ehFrameHdrLen = 0; + + // The arm exidx header address + unw_word_t exidxFrameHdrAddr = 0; + unw_word_t exidxFrameHdrLen = 0; + + // Search for the module's dynamic header and unwind frames + Dyn* dynamicAddr = nullptr; + + for (int i = 0; i < phnum; i++, phdrAddr++) + { + Phdr ph; + if (!info->ReadMemory(phdrAddr, &ph, sizeof(ph))) { + ERROR("ELF: reading phdrAddr %p\n", phdrAddr); + return -UNW_EINVAL; + } + TRACE("ELF: phdr %p type %d (%x) vaddr %" PRIxA " memsz %" PRIxA " paddr %" PRIxA " filesz %" PRIxA " offset %" PRIxA " align %" PRIxA "\n", + phdrAddr, ph.p_type, ph.p_type, ph.p_vaddr, ph.p_memsz, ph.p_paddr, ph.p_filesz, ph.p_offset, ph.p_align); + + switch (ph.p_type) + { + case PT_LOAD: + if ((ip >= (loadbias + ph.p_vaddr)) && (ip < (loadbias + ph.p_vaddr + ph.p_memsz))) { + start_ip = loadbias + ph.p_vaddr; + end_ip = start_ip + ph.p_memsz; + TRACE("ELF: found start_ip/end_ip\n"); + } + break; + + case PT_DYNAMIC: + dynamicAddr = reinterpret_cast(loadbias + ph.p_vaddr); + break; + + case PT_GNU_EH_FRAME: + ehFrameHdrAddr = loadbias + ph.p_vaddr; + ehFrameHdrLen = ph.p_memsz; + break; + +#ifdef PT_ARM_EXIDX + case PT_ARM_EXIDX: + exidxFrameHdrAddr = loadbias + ph.p_vaddr; + exidxFrameHdrLen = ph.p_memsz; + break; +#endif + } + } + + if (dynamicAddr != nullptr) + { + for (;;) + { + Dyn dyn; + if (!info->ReadMemory(dynamicAddr, &dyn, sizeof(dyn))) { + ERROR("ELF: reading dynamicAddr %p\n", dynamicAddr); + return -UNW_EINVAL; + } + if (dyn.d_tag == DT_PLTGOT) { + TRACE("ELF: dyn %p tag %d (%x) d_ptr %p\n", dynamicAddr, dyn.d_tag, dyn.d_tag, dyn.d_un.d_ptr); + pip->gp = dyn.d_un.d_ptr; + break; + } + else if (dyn.d_tag == DT_NULL) { + break; + } + dynamicAddr++; + } + } + + return _OOP_find_proc_info(start_ip, end_ip, ehFrameHdrAddr, ehFrameHdrLen, exidxFrameHdrAddr, exidxFrameHdrLen, as, ip, pip, need_unwind_info, arg); +} + +static void +put_unwind_info(unw_addr_space_t as, unw_proc_info_t *pip, void *arg) +{ +} + +static unw_accessors_t unwind_accessors = +{ + .find_proc_info = find_proc_info, + .put_unwind_info = put_unwind_info, + .get_dyn_info_list_addr = get_dyn_info_list_addr, + .access_mem = access_mem, + .access_reg = access_reg, + .access_fpreg = access_fpreg, + .resume = resume, + .get_proc_name = get_proc_name +}; + +/*++ +Function: + PAL_VirtualUnwindOutOfProc + + Unwind the stack given the context for a "remote" target using the + provided read memory callback. + + Assumes the IP is in the module of the base address provided (coreclr). + +Parameters: + context - the start context in the target + contextPointers - the context of the next frame + baseAddress - base address of the module to find the unwind info + readMemoryCallback - reads memory from the target +--*/ +BOOL +PALAPI +PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers, SIZE_T baseAddress, UnwindReadMemoryCallback readMemoryCallback) +{ + unw_addr_space_t addrSpace = 0; + unw_cursor_t cursor; + libunwindInfo info; + BOOL result = FALSE; + int st; + + info.BaseAddress = baseAddress; + info.Context = context; + info.ReadMemory = readMemoryCallback; + + addrSpace = unw_create_addr_space(&unwind_accessors, 0); + + st = unw_init_remote(&cursor, addrSpace, &info); + if (st < 0) + { + result = FALSE; + goto exit; + } + + st = unw_step(&cursor); + if (st < 0) + { + result = FALSE; + goto exit; + } + + UnwindContextToContext(&cursor, context); + + if (contextPointers != NULL) + { + GetContextPointers(&cursor, NULL, contextPointers); + } + result = TRUE; + +exit: + if (addrSpace != 0) + { + unw_destroy_addr_space(addrSpace); + } + return result; +} + +#else + +BOOL +PALAPI +PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers, SIZE_T baseAddress, UnwindReadMemoryCallback readMemoryCallback) +{ + return FALSE; +} + +#endif // defined(HOST_AMD64) && defined(HAVE_UNW_GET_ACCESSORS) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/seh-unwind.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/seh-unwind.cpp new file mode 100644 index 0000000..53c86a0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/seh-unwind.cpp @@ -0,0 +1,521 @@ +// 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: + + seh-unwind.cpp + +Abstract: + + Implementation of exception API functions based on + the Unwind API. + + + +--*/ + +#include "pal/context.h" +#include "pal.h" +#include + +#define UNW_LOCAL_ONLY +// Sub-headers included from the libunwind.h contain an empty struct +// and clang issues a warning. Until the libunwind is fixed, disable +// the warning. +#ifdef __llvm__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextern-c-compat" +#endif +#include +#ifdef __llvm__ +#pragma clang diagnostic pop +#endif + +//---------------------------------------------------------------------- +// Virtual Unwinding +//---------------------------------------------------------------------- + +#if UNWIND_CONTEXT_IS_UCONTEXT_T + +#if defined(HOST_AMD64) +#define ASSIGN_UNWIND_REGS \ + ASSIGN_REG(Rip) \ + ASSIGN_REG(Rsp) \ + ASSIGN_REG(Rbp) \ + ASSIGN_REG(Rbx) \ + ASSIGN_REG(R12) \ + ASSIGN_REG(R13) \ + ASSIGN_REG(R14) \ + ASSIGN_REG(R15) +#elif defined(HOST_ARM64) +#define ASSIGN_UNWIND_REGS \ + ASSIGN_REG(Pc) \ + ASSIGN_REG(Sp) \ + ASSIGN_REG(Fp) \ + ASSIGN_REG(Lr) \ + ASSIGN_REG(X19) \ + ASSIGN_REG(X20) \ + ASSIGN_REG(X21) \ + ASSIGN_REG(X22) \ + ASSIGN_REG(X23) \ + ASSIGN_REG(X24) \ + ASSIGN_REG(X25) \ + ASSIGN_REG(X26) \ + ASSIGN_REG(X27) \ + ASSIGN_REG(X28) +#elif defined(HOST_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 + +static void WinContextToUnwindContext(CONTEXT *winContext, unw_context_t *unwContext) +{ +#define ASSIGN_REG(reg) MCREG_##reg(unwContext->uc_mcontext) = winContext->reg; + ASSIGN_UNWIND_REGS +#undef ASSIGN_REG +} +#else +static void WinContextToUnwindContext(CONTEXT *winContext, unw_context_t *unwContext) +{ +#if defined(HOST_ARM) + // Assuming that unw_set_reg() on cursor will point the cursor to the + // supposed stack frame is dangerous for libunwind-arm in Linux. + // It is because libunwind's unw_cursor_t has other data structure + // initialized by unw_init_local(), which are not updated by + // unw_set_reg(). + unwContext->regs[0] = 0; + unwContext->regs[1] = 0; + unwContext->regs[2] = 0; + unwContext->regs[3] = 0; + unwContext->regs[4] = winContext->R4; + unwContext->regs[5] = winContext->R5; + unwContext->regs[6] = winContext->R6; + unwContext->regs[7] = winContext->R7; + unwContext->regs[8] = winContext->R8; + unwContext->regs[9] = winContext->R9; + unwContext->regs[10] = winContext->R10; + unwContext->regs[11] = winContext->R11; + unwContext->regs[12] = 0; + unwContext->regs[13] = winContext->Sp; + unwContext->regs[14] = winContext->Lr; + unwContext->regs[15] = winContext->Pc; +#endif +} + +static void WinContextToUnwindCursor(CONTEXT *winContext, unw_cursor_t *cursor) +{ +#if defined(HOST_AMD64) + unw_set_reg(cursor, UNW_REG_IP, winContext->Rip); + unw_set_reg(cursor, UNW_REG_SP, winContext->Rsp); + unw_set_reg(cursor, UNW_X86_64_RBP, winContext->Rbp); + unw_set_reg(cursor, UNW_X86_64_RBX, winContext->Rbx); + unw_set_reg(cursor, UNW_X86_64_R12, winContext->R12); + 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(HOST_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 + +void UnwindContextToWinContext(unw_cursor_t *cursor, CONTEXT *winContext) +{ +#if defined(HOST_AMD64) + unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Rip); + unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Rsp); + unw_get_reg(cursor, UNW_X86_64_RBP, (unw_word_t *) &winContext->Rbp); + unw_get_reg(cursor, UNW_X86_64_RBX, (unw_word_t *) &winContext->Rbx); + unw_get_reg(cursor, UNW_X86_64_R12, (unw_word_t *) &winContext->R12); + 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(HOST_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(HOST_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); + unw_get_reg(cursor, UNW_ARM_R14, (unw_word_t *) &winContext->Lr); + unw_get_reg(cursor, UNW_ARM_R4, (unw_word_t *) &winContext->R4); + unw_get_reg(cursor, UNW_ARM_R5, (unw_word_t *) &winContext->R5); + unw_get_reg(cursor, UNW_ARM_R6, (unw_word_t *) &winContext->R6); + unw_get_reg(cursor, UNW_ARM_R7, (unw_word_t *) &winContext->R7); + unw_get_reg(cursor, UNW_ARM_R8, (unw_word_t *) &winContext->R8); + unw_get_reg(cursor, UNW_ARM_R9, (unw_word_t *) &winContext->R9); + unw_get_reg(cursor, UNW_ARM_R10, (unw_word_t *) &winContext->R10); + unw_get_reg(cursor, UNW_ARM_R11, (unw_word_t *) &winContext->R11); +#elif defined(HOST_ARM64) + unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc); + unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp); + unw_get_reg(cursor, UNW_AARCH64_X29, (unw_word_t *) &winContext->Fp); + unw_get_reg(cursor, UNW_AARCH64_X30, (unw_word_t *) &winContext->Lr); + unw_get_reg(cursor, UNW_AARCH64_X19, (unw_word_t *) &winContext->X19); + unw_get_reg(cursor, UNW_AARCH64_X20, (unw_word_t *) &winContext->X20); + unw_get_reg(cursor, UNW_AARCH64_X21, (unw_word_t *) &winContext->X21); + unw_get_reg(cursor, UNW_AARCH64_X22, (unw_word_t *) &winContext->X22); + unw_get_reg(cursor, UNW_AARCH64_X23, (unw_word_t *) &winContext->X23); + unw_get_reg(cursor, UNW_AARCH64_X24, (unw_word_t *) &winContext->X24); + unw_get_reg(cursor, UNW_AARCH64_X25, (unw_word_t *) &winContext->X25); + unw_get_reg(cursor, UNW_AARCH64_X26, (unw_word_t *) &winContext->X26); + unw_get_reg(cursor, UNW_AARCH64_X27, (unw_word_t *) &winContext->X27); + unw_get_reg(cursor, UNW_AARCH64_X28, (unw_word_t *) &winContext->X28); +#else +#error unsupported architecture +#endif +} + +static void GetContextPointer(unw_cursor_t *cursor, unw_context_t *unwContext, int reg, SIZE_T **contextPointer) +{ +#if defined(HAVE_UNW_GET_SAVE_LOC) + unw_save_loc_t saveLoc; + unw_get_save_loc(cursor, reg, &saveLoc); + if (saveLoc.type == UNW_SLT_MEMORY) + { + SIZE_T *pLoc = (SIZE_T *)saveLoc.u.addr; + // Filter out fake save locations that point to unwContext + if (unwContext == NULL || (pLoc < (SIZE_T *)unwContext) || ((SIZE_T *)(unwContext + 1) <= pLoc)) + *contextPointer = (SIZE_T *)saveLoc.u.addr; + } +#else + // Returning NULL indicates that we don't have context pointers available + *contextPointer = NULL; +#endif +} + +void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, KNONVOLATILE_CONTEXT_POINTERS *contextPointers) +{ +#if defined(HOST_AMD64) + GetContextPointer(cursor, unwContext, UNW_X86_64_RBP, &contextPointers->Rbp); + GetContextPointer(cursor, unwContext, UNW_X86_64_RBX, &contextPointers->Rbx); + GetContextPointer(cursor, unwContext, UNW_X86_64_R12, &contextPointers->R12); + 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(HOST_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(HOST_ARM) + GetContextPointer(cursor, unwContext, UNW_ARM_R4, &contextPointers->R4); + GetContextPointer(cursor, unwContext, UNW_ARM_R5, &contextPointers->R5); + GetContextPointer(cursor, unwContext, UNW_ARM_R6, &contextPointers->R6); + GetContextPointer(cursor, unwContext, UNW_ARM_R7, &contextPointers->R7); + GetContextPointer(cursor, unwContext, UNW_ARM_R8, &contextPointers->R8); + GetContextPointer(cursor, unwContext, UNW_ARM_R9, &contextPointers->R9); + GetContextPointer(cursor, unwContext, UNW_ARM_R10, &contextPointers->R10); + GetContextPointer(cursor, unwContext, UNW_ARM_R11, &contextPointers->R11); +#elif defined(HOST_ARM64) + GetContextPointer(cursor, unwContext, UNW_AARCH64_X19, &contextPointers->X19); + GetContextPointer(cursor, unwContext, UNW_AARCH64_X20, &contextPointers->X20); + GetContextPointer(cursor, unwContext, UNW_AARCH64_X21, &contextPointers->X21); + GetContextPointer(cursor, unwContext, UNW_AARCH64_X22, &contextPointers->X22); + GetContextPointer(cursor, unwContext, UNW_AARCH64_X23, &contextPointers->X23); + GetContextPointer(cursor, unwContext, UNW_AARCH64_X24, &contextPointers->X24); + GetContextPointer(cursor, unwContext, UNW_AARCH64_X25, &contextPointers->X25); + GetContextPointer(cursor, unwContext, UNW_AARCH64_X26, &contextPointers->X26); + GetContextPointer(cursor, unwContext, UNW_AARCH64_X27, &contextPointers->X27); + GetContextPointer(cursor, unwContext, UNW_AARCH64_X28, &contextPointers->X28); + GetContextPointer(cursor, unwContext, UNW_AARCH64_X29, &contextPointers->Fp); +#else +#error unsupported architecture +#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; + + 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 windows style context 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) + { + CONTEXT* signalContext = (CONTEXT*)(CONTEXTGetFP(context) + g_common_signal_handler_context_locvar_offset); + memcpy_s(context, sizeof(CONTEXT), signalContext, sizeof(CONTEXT)); + + return TRUE; + } +#endif + + if ((context->ContextFlags & CONTEXT_EXCEPTION_ACTIVE) != 0) + { + // The current frame is a source of hardware exception. Due to the fact that + // we use the low level unwinder to unwind just one frame a time, the + // unwinder doesn't have the signal_frame flag set. So it doesn't + // know that it should not decrement the PC before looking up the unwind info. + // 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, curPc + 1); + } + +#if !UNWIND_CONTEXT_IS_UCONTEXT_T + st = unw_getcontext(&unwContext); + if (st < 0) + { + return FALSE; + } +#endif + + WinContextToUnwindContext(context, &unwContext); + + st = unw_init_local(&cursor, &unwContext); + if (st < 0) + { + return FALSE; + } + +#if !UNWIND_CONTEXT_IS_UCONTEXT_T + // Set the unwind context to the specified windows context + WinContextToUnwindCursor(context, &cursor); +#endif + + st = unw_step(&cursor); + if (st < 0) + { + return FALSE; + } + + // Check if the frame we have unwound to is a frame that caused + // synchronous signal, like a hardware exception and record it + // in the context flags. + if (unw_is_signal_frame(&cursor) > 0) + { + context->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE; +#if defined(HOST_ARM) || defined(HOST_ARM64) || defined(HOST_X86) + context->ContextFlags &= ~CONTEXT_UNWOUND_TO_CALL; +#endif // HOST_ARM || HOST_ARM64 + } + else + { + context->ContextFlags &= ~CONTEXT_EXCEPTION_ACTIVE; +#if defined(HOST_ARM) || defined(HOST_ARM64) || defined(HOST_X86) + context->ContextFlags |= CONTEXT_UNWOUND_TO_CALL; +#endif // HOST_ARM || HOST_ARM64 + } + + // Update the passed in windows context to reflect the unwind + // + UnwindContextToWinContext(&cursor, context); + + // On some OSes / architectures if it unwound all the way to _start + // (__libc_start_main on arm64 Linux with glibc older than 2.27). + // >= 0 is returned 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 x64 Linux. + // + if (st >= 0 && CONTEXTGetPC(context) == curPc) + { + CONTEXTSetPC(context, 0); + } + + if (contextPointers != NULL) + { + GetContextPointers(&cursor, &unwContext, contextPointers); + } + return TRUE; +} + +struct ExceptionRecords +{ + CONTEXT ContextRecord; + EXCEPTION_RECORD ExceptionRecord; +}; + +// Max number of fallback contexts that are used when malloc fails to allocate ExceptionRecords structure +static const int MaxFallbackContexts = sizeof(size_t) * 8; +// Array of fallback contexts +static ExceptionRecords s_fallbackContexts[MaxFallbackContexts]; +// Bitmap used for allocating fallback contexts - bits set to 1 represent already allocated context. +static volatile size_t s_allocatedContextsBitmap = 0; + +/*++ +Function: + AllocateExceptionRecords + + Allocate EXCEPTION_RECORD and CONTEXT structures for an exception. +Parameters: + exceptionRecord - output pointer to the allocated exception record + contextRecord - output pointer to the allocated context record +--*/ +VOID +AllocateExceptionRecords(EXCEPTION_RECORD** exceptionRecord, CONTEXT** contextRecord) +{ + ExceptionRecords* records; + if (posix_memalign((void**)&records, alignof(ExceptionRecords), sizeof(ExceptionRecords)) != 0) + { + size_t bitmap; + size_t newBitmap; + int index; + + do + { + bitmap = s_allocatedContextsBitmap; + index = __builtin_ffsl(~bitmap) - 1; + if (index < 0) + { + PROCAbort(); + } + + newBitmap = bitmap | ((size_t)1 << index); + } + while (__sync_val_compare_and_swap(&s_allocatedContextsBitmap, bitmap, newBitmap) != bitmap); + + records = &s_fallbackContexts[index]; + } + + *contextRecord = &records->ContextRecord; + *exceptionRecord = &records->ExceptionRecord; +} + +/*++ +Function: + PAL_FreeExceptionRecords + + Free EXCEPTION_RECORD and CONTEXT structures of an exception that were allocated by the + AllocateExceptionRecords. +Parameters: + exceptionRecord - exception record + contextRecord - context record +--*/ +VOID +PALAPI +PAL_FreeExceptionRecords(IN EXCEPTION_RECORD *exceptionRecord, IN CONTEXT *contextRecord) +{ + // Both records are allocated at once and the allocated memory starts at the contextRecord + ExceptionRecords* records = (ExceptionRecords*)contextRecord; + if ((records >= &s_fallbackContexts[0]) && (records < &s_fallbackContexts[MaxFallbackContexts])) + { + int index = records - &s_fallbackContexts[0]; + __sync_fetch_and_and(&s_allocatedContextsBitmap, ~((size_t)1 << index)); + } + else + { + free(contextRecord); + } +} + +/*++ +Function: + RtlpRaiseException + +Parameters: + ExceptionRecord - the Windows exception record to throw + +Note: + The name of this function and the name of the ExceptionRecord + parameter is used in the sos lldb plugin code to read the exception + record. See coreclr\src\ToolBox\SOS\lldbplugin\services.cpp. + + This function must not be inlined or optimized so the below PAL_VirtualUnwind + calls end up with RaiseException caller's context and so the above debugger + code finds the function and ExceptionRecord parameter. +--*/ +PAL_NORETURN +__attribute__((noinline)) +__attribute__((NOOPT_ATTRIBUTE)) +static void +RtlpRaiseException(EXCEPTION_RECORD *ExceptionRecord, CONTEXT *ContextRecord) +{ + throw PAL_SEHException(ExceptionRecord, ContextRecord); +} + +/*++ +Function: + RaiseException + +See MSDN doc. +--*/ +// no PAL_NORETURN, as callers must assume this can return for continuable exceptions. +__attribute__((noinline)) +VOID +PALAPI +RaiseException(IN DWORD dwExceptionCode, + IN DWORD dwExceptionFlags, + IN DWORD nNumberOfArguments, + IN CONST ULONG_PTR *lpArguments) +{ + // PERF_ENTRY_ONLY is used here because RaiseException may or may not + // return. We can not get latency data without PERF_EXIT. For this reason, + // PERF_ENTRY_ONLY is used to profile frequency only. + PERF_ENTRY_ONLY(RaiseException); + ENTRY("RaiseException(dwCode=%#x, dwFlags=%#x, nArgs=%u, lpArguments=%p)\n", + dwExceptionCode, dwExceptionFlags, nNumberOfArguments, lpArguments); + + /* Validate parameters */ + if (dwExceptionCode & RESERVED_SEH_BIT) + { + WARN("Exception code %08x has bit 28 set; clearing it.\n", dwExceptionCode); + dwExceptionCode ^= RESERVED_SEH_BIT; + } + + if (nNumberOfArguments > EXCEPTION_MAXIMUM_PARAMETERS) + { + WARN("Number of arguments (%d) exceeds the limit " + "EXCEPTION_MAXIMUM_PARAMETERS (%d); ignoring extra parameters.\n", + nNumberOfArguments, EXCEPTION_MAXIMUM_PARAMETERS); + nNumberOfArguments = EXCEPTION_MAXIMUM_PARAMETERS; + } + + CONTEXT *contextRecord; + EXCEPTION_RECORD *exceptionRecord; + AllocateExceptionRecords(&exceptionRecord, &contextRecord); + + ZeroMemory(exceptionRecord, sizeof(EXCEPTION_RECORD)); + + exceptionRecord->ExceptionCode = dwExceptionCode; + exceptionRecord->ExceptionFlags = dwExceptionFlags; + exceptionRecord->ExceptionRecord = NULL; + exceptionRecord->ExceptionAddress = NULL; // will be set by RtlpRaiseException + exceptionRecord->NumberParameters = nNumberOfArguments; + if (nNumberOfArguments) + { + CopyMemory(exceptionRecord->ExceptionInformation, lpArguments, + nNumberOfArguments * sizeof(ULONG_PTR)); + } + + // Capture the context of RaiseException. + ZeroMemory(contextRecord, sizeof(CONTEXT)); + contextRecord->ContextFlags = CONTEXT_FULL; + CONTEXT_CaptureContext(contextRecord); + + // We have to unwind one level to get the actual context user code could be resumed at. + PAL_VirtualUnwind(contextRecord, NULL); + + exceptionRecord->ExceptionAddress = (void *)CONTEXTGetPC(contextRecord); + + RtlpRaiseException(exceptionRecord, contextRecord); + + LOGEXIT("RaiseException returns\n"); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/seh.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/seh.cpp new file mode 100644 index 0000000..ee022b4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/seh.cpp @@ -0,0 +1,407 @@ +// 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: + + seh.cpp + +Abstract: + + Implementation of exception API functions. + + + +--*/ + +#include "pal/thread.hpp" +#include "pal/handleapi.hpp" +#include "pal/seh.hpp" +#include "pal/dbgmsg.h" +#include "pal/critsect.h" +#include "pal/debug.h" +#include "pal/init.h" +#include "pal/process.h" +#include "pal/malloc.hpp" +#include "pal/signal.hpp" +#include "pal/virtual.h" + +#if HAVE_MACH_EXCEPTIONS +#include "machexception.h" +#else +#include +#endif + +#include +#include +#include +#include +#include + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); + +/* Constant and type definitions **********************************************/ + +/* Bit 28 of exception codes is reserved. */ +const UINT RESERVED_SEH_BIT = 0x800000; + +/* Internal variables definitions **********************************************/ + +PHARDWARE_EXCEPTION_HANDLER g_hardwareExceptionHandler = NULL; +// Function to check if an activation can be safely injected at a specified context +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 **********************************************/ + +/*++ +Function : + SEHInitialize + + Initialize all SEH-related stuff (signals, etc) + +Parameters : + CPalThread * pthrCurrent : reference to the current thread. + PAL initialize flags + +Return value : + TRUE if SEH support initialization succeeded + FALSE otherwise +--*/ +BOOL +SEHInitialize (CPalThread *pthrCurrent, DWORD flags) +{ + if (!SEHInitializeSignals(pthrCurrent, flags)) + { + ERROR("SEHInitializeSignals failed!\n"); + SEHCleanup(); + return FALSE; + } + + return TRUE; +} + +/*++ +Function : + SEHCleanup + + Undo work done by SEHInitialize + +Parameters : + None + + (no return value) + +--*/ +VOID +SEHCleanup() +{ + TRACE("Cleaning up SEH\n"); + + SEHCleanupSignals(); +} + +/*++ +Function: + PAL_SetHardwareExceptionHandler + + Register a hardware exception handler. + +Parameters: + handler - exception handler + +Return value: + None +--*/ +VOID +PALAPI +PAL_SetHardwareExceptionHandler( + IN PHARDWARE_EXCEPTION_HANDLER exceptionHandler, + IN PHARDWARE_EXCEPTION_SAFETY_CHECK_FUNCTION exceptionCheckFunction) +{ + g_hardwareExceptionHandler = exceptionHandler; + g_safeExceptionCheckFunction = exceptionCheckFunction; +} + +/*++ +Function: + PAL_SetGetGcMarkerExceptionCode + + Register a function that determines if the specified IP has code that is a GC marker for GCCover. + +Parameters: + getGcMarkerExceptionCode - the function to register + +Return value: + None +--*/ +VOID +PALAPI +PAL_SetGetGcMarkerExceptionCode( + IN PGET_GCMARKER_EXCEPTION_CODE getGcMarkerExceptionCode) +{ + g_getGcMarkerExceptionCode = getGcMarkerExceptionCode; +} + +EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); + +/*++ +Function: + PAL_ThrowExceptionFromContext + + 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. + +Parameters: + CONTEXT* context - context from which the exception will be thrown + PAL_SEHException* ex - the exception to throw. +--*/ +VOID +PALAPI +PAL_ThrowExceptionFromContext(CONTEXT* context, PAL_SEHException* ex) +{ + // We need to make a copy of the exception off stack, since the "ex" is located in one of the stack + // frames that will become obsolete by the ThrowExceptionFromContextInternal and the ThrowExceptionHelper + // could overwrite the "ex" object by stack e.g. when allocating the low level exception object for "throw". + static __thread BYTE threadLocalExceptionStorage[sizeof(PAL_SEHException)]; + ThrowExceptionFromContextInternal(context, new (threadLocalExceptionStorage) PAL_SEHException(std::move(*ex))); +} + +/*++ +Function: + ThrowExceptionHelper + + Helper function to throw the passed in exception. + It is called from the assembler function ThrowExceptionFromContextInternal + +Parameters: + PAL_SEHException* ex - the exception to throw. +--*/ +extern "C" +#ifdef HOST_X86 +void __fastcall ThrowExceptionHelper(PAL_SEHException* ex) +#else // HOST_X86 +void ThrowExceptionHelper(PAL_SEHException* ex) +#endif // !HOST_X86 +{ + throw std::move(*ex); +} + +/*++ +Function: + EnsureExceptionRecordsOnHeap + + Helper function to move records from stack to heap. + +Parameters: + PAL_SEHException* exception +--*/ +static void EnsureExceptionRecordsOnHeap(PAL_SEHException* exception) +{ + if( !exception->RecordsOnStack || + exception->ExceptionPointers.ExceptionRecord == NULL ) + { + return; + } + + CONTEXT* contextRecord = exception->ExceptionPointers.ContextRecord; + EXCEPTION_RECORD* exceptionRecord = exception->ExceptionPointers.ExceptionRecord; + + CONTEXT* contextRecordCopy; + EXCEPTION_RECORD* exceptionRecordCopy; + AllocateExceptionRecords(&exceptionRecordCopy, &contextRecordCopy); + + *exceptionRecordCopy = *exceptionRecord; + *contextRecordCopy = *contextRecord; + + exception->ExceptionPointers.ExceptionRecord = exceptionRecordCopy; + exception->ExceptionPointers.ContextRecord = contextRecordCopy; + exception->RecordsOnStack = false; +} + +/*++ +Function: + SEHProcessException + + Send the PAL exception to any handler registered. + +Parameters: + PAL_SEHException* exception + +Return value: + Returns TRUE if the exception happened in managed code and the execution should + continue (with possibly modified context). + Returns FALSE if the exception happened in managed code and it was not handled. + In case the exception was handled by calling a catch handler, it doesn't return at all. +--*/ +BOOL +SEHProcessException(PAL_SEHException* exception) +{ + g_SEHProcessExceptionReturnAddress = __builtin_return_address(0); + + CONTEXT* contextRecord = exception->GetContextRecord(); + EXCEPTION_RECORD* exceptionRecord = exception->GetExceptionRecord(); + + if (!IsInDebugBreak(exceptionRecord->ExceptionAddress)) + { + if (g_hardwareExceptionHandler != NULL) + { + _ASSERTE(g_safeExceptionCheckFunction != NULL); + // Check if it is safe to handle the hardware exception (the exception happened in managed code + // or in a jitter helper or it is a debugger breakpoint) + if (g_safeExceptionCheckFunction(contextRecord, exceptionRecord)) + { + EnsureExceptionRecordsOnHeap(exception); + if (g_hardwareExceptionHandler(exception)) + { + // The exception happened in managed code and the execution should continue. + return TRUE; + } + + // The exception was a single step or a breakpoint and it was not handled by the debugger. + } + } + + if (CatchHardwareExceptionHolder::IsEnabled()) + { + EnsureExceptionRecordsOnHeap(exception); + PAL_ThrowExceptionFromContext(exception->GetContextRecord(), exception); + } + } + + // Unhandled hardware exception pointers->ExceptionRecord->ExceptionCode at pointers->ExceptionRecord->ExceptionAddress + return FALSE; +} + +/*++ +Function : + SEHEnable + + Enable SEH-related stuff on this thread + +Parameters: + CPalThread * pthrCurrent : reference to the current thread. + +Return value : + TRUE if enabling succeeded + FALSE otherwise +--*/ +extern "C" +PAL_ERROR SEHEnable(CPalThread *pthrCurrent) +{ +#if HAVE_MACH_EXCEPTIONS + return pthrCurrent->EnableMachExceptions(); +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__sun) + return NO_ERROR; +#else// HAVE_MACH_EXCEPTIONS +#error not yet implemented +#endif // HAVE_MACH_EXCEPTIONS +} + +/*++ +Function : + SEHDisable + + Disable SEH-related stuff on this thread + +Parameters: + CPalThread * pthrCurrent : reference to the current thread. + +Return value : + TRUE if enabling succeeded + FALSE otherwise +--*/ +extern "C" +PAL_ERROR SEHDisable(CPalThread *pthrCurrent) +{ +#if HAVE_MACH_EXCEPTIONS + return pthrCurrent->DisableMachExceptions(); +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__sun) + return NO_ERROR; +#else // HAVE_MACH_EXCEPTIONS +#error not yet implemented +#endif // HAVE_MACH_EXCEPTIONS +} + +/*++ + + CatchHardwareExceptionHolder implementation + +--*/ + +extern "C" +void +PALAPI +PAL_CatchHardwareExceptionHolderEnter() +{ + CPalThread *pThread = InternalGetCurrentThread(); + pThread->IncrementHardwareExceptionHolderCount(); +} + +extern "C" +void +PALAPI +PAL_CatchHardwareExceptionHolderExit() +{ + CPalThread *pThread = InternalGetCurrentThread(); + pThread->DecrementHardwareExceptionHolderCount(); +} + +bool CatchHardwareExceptionHolder::IsEnabled() +{ + CPalThread *pThread = GetCurrentPalThread(); + return pThread ? pThread->IsHardwareExceptionsEnabled() : false; +} + +/*++ + + NativeExceptionHolderBase implementation + +--*/ + +#if defined(__GNUC__) +static __thread +#else // __GNUC__ +__declspec(thread) static +#endif // !__GNUC__ +NativeExceptionHolderBase *t_nativeExceptionHolderHead = nullptr; + +extern "C" +NativeExceptionHolderBase ** +PAL_GetNativeExceptionHolderHead() +{ + return &t_nativeExceptionHolderHead; +} + +NativeExceptionHolderBase * +NativeExceptionHolderBase::FindNextHolder(NativeExceptionHolderBase *currentHolder, PVOID stackLowAddress, PVOID stackHighAddress) +{ + NativeExceptionHolderBase *holder = (currentHolder == nullptr) ? t_nativeExceptionHolderHead : currentHolder->m_next; + + while (holder != nullptr) + { + if (((void *)holder >= stackLowAddress) && ((void *)holder < stackHighAddress)) + { + return holder; + } + // Get next holder + holder = holder->m_next; + } + + return nullptr; +} + +#include "seh-unwind.cpp" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/signal.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/signal.cpp new file mode 100644 index 0000000..b142bbd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/exception/signal.cpp @@ -0,0 +1,1002 @@ +// 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: + + exception/signal.cpp + +Abstract: + + Signal handler implementation (map signals to exceptions) + + + +--*/ + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do this first + +#include "pal/corunix.hpp" +#include "pal/handleapi.hpp" +#include "pal/process.h" +#include "pal/thread.hpp" +#include "pal/threadinfo.hpp" +#include "pal/threadsusp.hpp" +#include "pal/seh.hpp" +#include "pal/signal.hpp" + +#include "pal/palinternal.h" + +#include +#include + +#if !HAVE_MACH_EXCEPTIONS +#include "pal/init.h" +#include "pal/debug.h" +#include "pal/virtual.h" +#include "pal/utils.h" + +#include +#include +#include +#include +#include + +#include "pal/context.h" + +#ifdef SIGRTMIN +#define INJECT_ACTIVATION_SIGNAL SIGRTMIN +#endif + +#if !defined(INJECT_ACTIVATION_SIGNAL) && defined(FEATURE_HIJACK) +#error FEATURE_HIJACK requires INJECT_ACTIVATION_SIGNAL to be defined +#endif +#endif // !HAVE_MACH_EXCEPTIONS + +using namespace CorUnix; + +/* local type definitions *****************************************************/ + +typedef void (*SIGFUNC)(int, siginfo_t *, void *); + +/* internal function declarations *********************************************/ + +static void sigterm_handler(int code, siginfo_t *siginfo, void *context); +#if !HAVE_MACH_EXCEPTIONS +static void sigill_handler(int code, siginfo_t *siginfo, void *context); +static void sigfpe_handler(int code, siginfo_t *siginfo, void *context); +static void sigsegv_handler(int code, siginfo_t *siginfo, void *context); +static void sigtrap_handler(int code, siginfo_t *siginfo, void *context); +static void sigbus_handler(int code, siginfo_t *siginfo, void *context); +static void sigint_handler(int code, siginfo_t *siginfo, void *context); +static void sigquit_handler(int code, siginfo_t *siginfo, void *context); + +static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext, int numParams, ...); + +#ifdef INJECT_ACTIVATION_SIGNAL +static void inject_activation_handler(int code, siginfo_t *siginfo, void *context); +#endif +#endif // !HAVE_MACH_EXCEPTIONS + +static void handle_signal(int signal_id, SIGFUNC sigfunc, struct sigaction *previousAction, int additionalFlags = 0, bool skipIgnored = false); +static void restore_signal(int signal_id, struct sigaction *previousAction); +static void restore_signal_and_resend(int code, struct sigaction* action); + +/* internal data declarations *********************************************/ + +#if !HAVE_MACH_EXCEPTIONS +bool g_registered_signal_handlers = false; +bool g_enable_alternate_stack_check = false; +#endif // !HAVE_MACH_EXCEPTIONS + +static bool g_registered_sigterm_handler = false; + +struct sigaction g_previous_sigterm; +#if !HAVE_MACH_EXCEPTIONS +struct sigaction g_previous_sigill; +struct sigaction g_previous_sigtrap; +struct sigaction g_previous_sigfpe; +struct sigaction g_previous_sigbus; +struct sigaction g_previous_sigsegv; +struct sigaction g_previous_sigint; +struct sigaction g_previous_sigquit; + +#ifdef INJECT_ACTIVATION_SIGNAL +struct sigaction g_previous_activation; +#endif + +// Offset of the local variable containing pointer to windows style context in the common_signal_handler function. +// This offset is relative to the frame pointer. +int g_common_signal_handler_context_locvar_offset = 0; + +// TOP of special stack for handling stack overflow +volatile void* g_stackOverflowHandlerStack = NULL; + +// Flag that is or-ed with SIGSEGV to indicate that the SIGSEGV was a stack overflow +const int StackOverflowFlag = 0x40000000; + +#endif // !HAVE_MACH_EXCEPTIONS + +/* public function definitions ************************************************/ + +/*++ +Function : + SEHInitializeSignals + + Set up signal handlers to catch signals and translate them to exceptions + +Parameters : + None + +Return : + TRUE in case of a success, FALSE otherwise +--*/ +BOOL SEHInitializeSignals(CorUnix::CPalThread *pthrCurrent, DWORD flags) +{ + TRACE("Initializing signal handlers\n"); + +#if !HAVE_MACH_EXCEPTIONS + + char* enableAlternateStackCheck = getenv("COMPlus_EnableAlternateStackCheck"); + + g_enable_alternate_stack_check = enableAlternateStackCheck && (strtoul(enableAlternateStackCheck, NULL, 10) != 0); + + if (flags & PAL_INITIALIZE_REGISTER_SIGNALS) + { + g_registered_signal_handlers = true; + + /* we call handle_signal for every possible signal, even + if we don't provide a signal handler. + + handle_signal will set SA_RESTART flag for specified signal. + Therefore, all signals will have SA_RESTART flag set, preventing + slow Unix system calls from being interrupted. On systems without + siginfo_t, SIGKILL and SIGSTOP can't be restarted, so we don't + handle those signals. Both the Darwin and FreeBSD man pages say + that SIGKILL and SIGSTOP can't be handled, but FreeBSD allows us + to register a handler for them anyway. We don't do that. + + see sigaction man page for more details + */ + handle_signal(SIGILL, sigill_handler, &g_previous_sigill); + handle_signal(SIGTRAP, sigtrap_handler, &g_previous_sigtrap); + handle_signal(SIGFPE, sigfpe_handler, &g_previous_sigfpe); + handle_signal(SIGBUS, sigbus_handler, &g_previous_sigbus); + // SIGSEGV handler runs on a separate stack so that we can handle stack overflow + handle_signal(SIGSEGV, sigsegv_handler, &g_previous_sigsegv, SA_ONSTACK); + // We don't setup a handler for SIGINT/SIGQUIT when those signals are ignored. + // Otherwise our child processes would reset to the default on exec causing them + // to terminate on these signals. + handle_signal(SIGINT, sigint_handler, &g_previous_sigint, 0 /* additionalFlags */, true /* skipIgnored */); + handle_signal(SIGQUIT, sigquit_handler, &g_previous_sigquit, 0 /* additionalFlags */, true /* skipIgnored */); + +#ifdef INJECT_ACTIVATION_SIGNAL + handle_signal(INJECT_ACTIVATION_SIGNAL, inject_activation_handler, &g_previous_activation); +#endif + if (!pthrCurrent->EnsureSignalAlternateStack()) + { + return FALSE; + } + + // Allocate the minimal stack necessary for handling stack overflow + int stackOverflowStackSize = ALIGN_UP(sizeof(SignalHandlerWorkerReturnPoint), 16) + 7 * 4096; + // Align the size to virtual page size and add one virtual page as a stack guard + stackOverflowStackSize = ALIGN_UP(stackOverflowStackSize, GetVirtualPageSize()) + GetVirtualPageSize(); + int flags = MAP_ANONYMOUS | MAP_PRIVATE; +#ifdef MAP_STACK + flags |= MAP_STACK; +#endif + g_stackOverflowHandlerStack = mmap(NULL, stackOverflowStackSize, PROT_READ | PROT_WRITE, flags, -1, 0); + if (g_stackOverflowHandlerStack == MAP_FAILED) + { + return FALSE; + } + + // create a guard page for the alternate stack + int st = mprotect((void*)g_stackOverflowHandlerStack, GetVirtualPageSize(), PROT_NONE); + if (st != 0) + { + munmap((void*)g_stackOverflowHandlerStack, stackOverflowStackSize); + return FALSE; + } + + g_stackOverflowHandlerStack = (void*)((size_t)g_stackOverflowHandlerStack + stackOverflowStackSize); + } + + /* The default action for SIGPIPE is process termination. + Since SIGPIPE can be signaled when trying to write on a socket for which + the connection has been dropped, we need to tell the system we want + to ignore this signal. + + Instead of terminating the process, the system call which would had + issued a SIGPIPE will, instead, report an error and set errno to EPIPE. + */ + signal(SIGPIPE, SIG_IGN); +#endif // !HAVE_MACH_EXCEPTIONS + + if (flags & PAL_INITIALIZE_REGISTER_SIGTERM_HANDLER) + { + g_registered_sigterm_handler = true; + handle_signal(SIGTERM, sigterm_handler, &g_previous_sigterm); + } + + return TRUE; +} + +/*++ +Function : + SEHCleanupSignals + + Restore default signal handlers + +Parameters : + None + + (no return value) + +note : +reason for this function is that during PAL_Terminate, we reach a point where +SEH isn't possible anymore (handle manager is off, etc). Past that point, +we can't avoid crashing on a signal. +--*/ +void SEHCleanupSignals() +{ + TRACE("Restoring default signal handlers\n"); + +#if !HAVE_MACH_EXCEPTIONS + if (g_registered_signal_handlers) + { + restore_signal(SIGILL, &g_previous_sigill); + restore_signal(SIGTRAP, &g_previous_sigtrap); + restore_signal(SIGFPE, &g_previous_sigfpe); + restore_signal(SIGBUS, &g_previous_sigbus); + restore_signal(SIGSEGV, &g_previous_sigsegv); + restore_signal(SIGINT, &g_previous_sigint); + restore_signal(SIGQUIT, &g_previous_sigquit); +#ifdef INJECT_ACTIVATION_SIGNAL + restore_signal(INJECT_ACTIVATION_SIGNAL, &g_previous_activation); +#endif + } +#endif // !HAVE_MACH_EXCEPTIONS + + if (g_registered_sigterm_handler) + { + restore_signal(SIGTERM, &g_previous_sigterm); + } +} + +/* internal function definitions **********************************************/ + +#if !HAVE_MACH_EXCEPTIONS +/*++ +Function : + invoke_previous_action + + synchronously invokes the previous action or aborts when that is not possible + +Parameters : + action : previous sigaction struct + code : signal code + siginfo : signal siginfo + context : signal context + signalRestarts: BOOL state : TRUE if the process will be signalled again + + (no return value) +--*/ +static void invoke_previous_action(struct sigaction* action, int code, siginfo_t *siginfo, void *context, bool signalRestarts = true) +{ + _ASSERTE(action != NULL); + + if (action->sa_flags & SA_SIGINFO) + { + // Directly call the previous handler. + _ASSERTE(action->sa_sigaction != NULL); + action->sa_sigaction(code, siginfo, context); + } + else + { + if (action->sa_handler == SIG_IGN) + { + if (signalRestarts) + { + // This signal mustn't be ignored because it will be restarted. + PROCAbort(); + } + return; + } + else if (action->sa_handler == SIG_DFL) + { + if (signalRestarts) + { + // Restore the original and restart h/w exception. + restore_signal(code, action); + } + else + { + // We can't invoke the original handler because returning from the + // handler doesn't restart the exception. + PROCAbort(); + } + } + else + { + // Directly call the previous handler. + _ASSERTE(action->sa_handler != NULL); + action->sa_handler(code); + } + } + + PROCNotifyProcessShutdown(); + PROCCreateCrashDumpIfEnabled(); +} + +/*++ +Function : + sigill_handler + + handle SIGILL signal (EXCEPTION_ILLEGAL_INSTRUCTION, others?) + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + + (no return value) +--*/ +static void sigill_handler(int code, siginfo_t *siginfo, void *context) +{ + if (PALIsInitialized()) + { + if (common_signal_handler(code, siginfo, context, 0)) + { + return; + } + } + + invoke_previous_action(&g_previous_sigill, code, siginfo, context); +} + +/*++ +Function : + sigfpe_handler + + handle SIGFPE signal (division by zero, floating point exception) + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + + (no return value) +--*/ +static void sigfpe_handler(int code, siginfo_t *siginfo, void *context) +{ + if (PALIsInitialized()) + { + if (common_signal_handler(code, siginfo, context, 0)) + { + return; + } + } + + invoke_previous_action(&g_previous_sigfpe, code, siginfo, context); +} + +/*++ +Function : + signal_handler_worker + + Handles signal on the original stack where the signal occured. + Invoked via setcontext. + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + returnPoint - context to which the function returns if the common_signal_handler returns + + (no return value) +--*/ +extern "C" void signal_handler_worker(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint) +{ + // TODO: First variable parameter says whether a read (0) or write (non-0) caused the + // fault. We must disassemble the instruction at record.ExceptionAddress + // to correctly fill in this value. + + // Unmask the activation signal now that we are running on the original stack of the thread + sigset_t signal_set; + sigemptyset(&signal_set); + sigaddset(&signal_set, INJECT_ACTIVATION_SIGNAL); + + int sigmaskRet = pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL); + if (sigmaskRet != 0) + { + ASSERT("pthread_sigmask failed; error number is %d\n", sigmaskRet); + } + + returnPoint->returnFromHandler = common_signal_handler(code, siginfo, context, 2, (size_t)0, (size_t)siginfo->si_addr); + + // We are going to return to the alternate stack, so block the activation signal again + sigmaskRet = pthread_sigmask(SIG_BLOCK, &signal_set, NULL); + if (sigmaskRet != 0) + { + ASSERT("pthread_sigmask failed; error number is %d\n", sigmaskRet); + } + + RtlRestoreContext(&returnPoint->context, NULL); +} + +/*++ +Function : + IsRunningOnAlternateStack + + Detects if the current signal handlers is running on an alternate stack + +Parameters : + The context of the signal + +Return : + true if we are running on an alternate stack + +--*/ +bool IsRunningOnAlternateStack(void *context) +{ + bool isRunningOnAlternateStack; + if (g_enable_alternate_stack_check) + { + // Note: WSL doesn't return the alternate signal ranges in the uc_stack (the whole structure is zeroed no + // matter whether the code is running on an alternate stack or not). So the check would always fail on WSL. + stack_t *signalStack = &((native_context_t *)context)->uc_stack; + // Check if the signalStack local variable address is within the alternate stack range. If it is not, + // then either the alternate stack was not installed at all or the current method is not running on it. + void* alternateStackEnd = (char *)signalStack->ss_sp + signalStack->ss_size; + isRunningOnAlternateStack = ((signalStack->ss_flags & SS_DISABLE) == 0) && (signalStack->ss_sp <= &signalStack) && (&signalStack < alternateStackEnd); + } + else + { + // If alternate stack check is disabled, consider always that we are running on an alternate + // signal handler stack. + isRunningOnAlternateStack = true; + } + + return isRunningOnAlternateStack; +} + +/*++ +Function : + SwitchStackAndExecuteHandler + + Switch to the stack specified by the sp argument + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + sp - stack pointer of the stack to execute the handler on. + If sp == 0, execute it on the original stack where the signal has occured. +Return : + The return value from the signal handler +--*/ +static bool SwitchStackAndExecuteHandler(int code, siginfo_t *siginfo, void *context, size_t sp) +{ + // Establish a return point in case the common_signal_handler returns + + volatile bool contextInitialization = true; + + void *ptr = alloca(sizeof(SignalHandlerWorkerReturnPoint) + alignof(SignalHandlerWorkerReturnPoint) - 1); + SignalHandlerWorkerReturnPoint *pReturnPoint = (SignalHandlerWorkerReturnPoint *)ALIGN_UP(ptr, alignof(SignalHandlerWorkerReturnPoint)); + RtlCaptureContext(&pReturnPoint->context); + + // When the signal handler worker completes, it uses setcontext to return to this point + + if (contextInitialization) + { + contextInitialization = false; + ExecuteHandlerOnCustomStack(code, siginfo, context, sp, pReturnPoint); + _ASSERTE(FALSE); // The ExecuteHandlerOnCustomStack should never return + } + + return pReturnPoint->returnFromHandler; +} + +/*++ +Function : + sigsegv_handler + + handle SIGSEGV signal (EXCEPTION_ACCESS_VIOLATION, others) + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + + (no return value) +--*/ +static void sigsegv_handler(int code, siginfo_t *siginfo, void *context) +{ + if (PALIsInitialized()) + { + // First check if we have a stack overflow + size_t sp = (size_t)GetNativeContextSP((native_context_t *)context); + size_t failureAddress = (size_t)siginfo->si_addr; + + // If the failure address is at most one page above or below the stack pointer, + // we have a stack overflow. + if ((failureAddress - (sp - GetVirtualPageSize())) < 2 * GetVirtualPageSize()) + { + if (GetCurrentPalThread()) + { + size_t handlerStackTop = __sync_val_compare_and_swap((size_t*)&g_stackOverflowHandlerStack, (size_t)g_stackOverflowHandlerStack, 0); + if (handlerStackTop == 0) + { + // We have only one stack for handling stack overflow preallocated. We let only the first thread that hits stack overflow to + // run the exception handling code on that stack (which ends up just dumping the stack trace and aborting the process). + // Other threads are held spinning and sleeping here until the process exits. + while (true) + { + sleep(1); + } + } + + if (SwitchStackAndExecuteHandler(code | StackOverflowFlag, siginfo, context, (size_t)handlerStackTop)) + { + PROCAbort(); + } + } + else + { + (void)write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1); + PROCAbort(); + } + } + + // Now that we know the SIGSEGV didn't happen due to a stack overflow, execute the common + // hardware signal handler on the original stack. + + if (GetCurrentPalThread() && IsRunningOnAlternateStack(context)) + { + if (SwitchStackAndExecuteHandler(code, siginfo, context, 0 /* sp */)) // sp == 0 indicates execution on the original stack + { + return; + } + } + else + { + // The code flow gets here when the signal handler is not running on an alternate stack or when it wasn't created + // by coreclr. In both cases, we execute the common_signal_handler directly. + // If thread isn't created by coreclr and has alternate signal stack GetCurrentPalThread() will return NULL too. + // But since in this case we don't handle hardware exceptions (IsSafeToHandleHardwareException returns false) + // we can call common_signal_handler on the alternate stack. + if (common_signal_handler(code, siginfo, context, 2, (size_t)0, (size_t)siginfo->si_addr)) + { + return; + } + } + } + + invoke_previous_action(&g_previous_sigsegv, code, siginfo, context); +} + +/*++ +Function : + sigtrap_handler + + handle SIGTRAP signal (EXCEPTION_SINGLE_STEP, EXCEPTION_BREAKPOINT) + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + + (no return value) +--*/ +static void sigtrap_handler(int code, siginfo_t *siginfo, void *context) +{ + if (PALIsInitialized()) + { + if (common_signal_handler(code, siginfo, context, 0)) + { + return; + } + } + + // The signal doesn't restart, returning from a SIGTRAP handler continues execution past the trap. + invoke_previous_action(&g_previous_sigtrap, code, siginfo, context, /* signalRestarts */ false); +} + +/*++ +Function : + sigbus_handler + + handle SIGBUS signal (EXCEPTION_ACCESS_VIOLATION?) + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + + (no return value) +--*/ +static void sigbus_handler(int code, siginfo_t *siginfo, void *context) +{ + if (PALIsInitialized()) + { + // TODO: First variable parameter says whether a read (0) or write (non-0) caused the + // fault. We must disassemble the instruction at record.ExceptionAddress + // to correctly fill in this value. + if (common_signal_handler(code, siginfo, context, 2, (size_t)0, (size_t)siginfo->si_addr)) + { + return; + } + } + + invoke_previous_action(&g_previous_sigbus, code, siginfo, context); +} + +/*++ +Function : + sigint_handler + + handle SIGINT signal + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + + (no return value) +--*/ +static void sigint_handler(int code, siginfo_t *siginfo, void *context) +{ + PROCNotifyProcessShutdown(); + + restore_signal_and_resend(code, &g_previous_sigint); +} + +/*++ +Function : + sigquit_handler + + handle SIGQUIT signal + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + + (no return value) +--*/ +static void sigquit_handler(int code, siginfo_t *siginfo, void *context) +{ + PROCNotifyProcessShutdown(); + + restore_signal_and_resend(code, &g_previous_sigquit); +} +#endif // !HAVE_MACH_EXCEPTIONS + +/*++ +Function : + sigterm_handler + + handle SIGTERM signal + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + + (no return value) +--*/ +static void sigterm_handler(int code, siginfo_t *siginfo, void *context) +{ + if (PALIsInitialized()) + { + // g_pSynchronizationManager shouldn't be null if PAL is initialized. + _ASSERTE(g_pSynchronizationManager != nullptr); + + g_pSynchronizationManager->SendTerminationRequestToWorkerThread(); + } + else + { + restore_signal_and_resend(SIGTERM, &g_previous_sigterm); + } +} + +#if !HAVE_MACH_EXCEPTIONS +#ifdef INJECT_ACTIVATION_SIGNAL +/*++ +Function : + inject_activation_handler + + Handle the INJECT_ACTIVATION_SIGNAL signal. This signal interrupts a running thread + so it can call the activation function that was specified when sending the signal. + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + +(no return value) +--*/ +static void inject_activation_handler(int code, siginfo_t *siginfo, void *context) +{ + // Only accept activations from the current process + if (g_activationFunction != NULL && siginfo->si_pid == getpid()) + { + _ASSERTE(g_safeActivationCheckFunction != NULL); + + native_context_t *ucontext = (native_context_t *)context; + + CONTEXT winContext; + CONTEXTFromNativeContext( + ucontext, + &winContext, + CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT); + + if (g_safeActivationCheckFunction(CONTEXTGetPC(&winContext), /* checkingCurrentThread */ TRUE)) + { + int savedErrNo = errno; // Make sure that errno is not modified + g_activationFunction(&winContext); + errno = savedErrNo; + + // Activation function may have modified the context, so update it. + CONTEXTToNativeContext(&winContext, ucontext); + } + } + else + { + // Call the original handler when it is not ignored or default (terminate). + if (g_previous_activation.sa_flags & SA_SIGINFO) + { + _ASSERTE(g_previous_activation.sa_sigaction != NULL); + g_previous_activation.sa_sigaction(code, siginfo, context); + } + else + { + if (g_previous_activation.sa_handler != SIG_IGN && + g_previous_activation.sa_handler != SIG_DFL) + { + _ASSERTE(g_previous_activation.sa_handler != NULL); + g_previous_activation.sa_handler(code); + } + } + } +} +#endif + +/*++ +Function : + InjectActivationInternal + + Interrupt the specified thread and have it call the activationFunction passed in + +Parameters : + pThread - target PAL thread + activationFunction - function to call + +(no return value) +--*/ +PAL_ERROR InjectActivationInternal(CorUnix::CPalThread* pThread) +{ +#ifdef INJECT_ACTIVATION_SIGNAL + int status = pthread_kill(pThread->GetPThreadSelf(), INJECT_ACTIVATION_SIGNAL); + // We can get EAGAIN when printing stack overflow stack trace and when other threads hit + // stack overflow too. Those are held in the sigsegv_handler with blocked signals until + // the process exits. + if ((status != 0) && (status != EAGAIN)) + { + // Failure to send the signal is fatal. There are only two cases when sending + // the signal can fail. First, if the signal ID is invalid and second, + // if the thread doesn't exist anymore. + PROCAbort(); + } + + return NO_ERROR; +#else + return ERROR_CANCELLED; +#endif +} + +/*++ +Function : + signal_ignore_handler + + Simple signal handler which does nothing + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + +(no return value) +--*/ +static void signal_ignore_handler(int code, siginfo_t *siginfo, void *context) +{ +} + + +void PAL_IgnoreProfileSignal(int signalNum) +{ +#if !HAVE_MACH_EXCEPTIONS + // Add a signal handler which will ignore signals + // This will allow signal to be used as a marker in perf recording. + // This will be used as an aid to synchronize recorded profile with + // test cases + // + // signal(signalNum, SGN_IGN) can not be used here. It will ignore + // the signal in kernel space and therefore generate no recordable + // event for profiling. Preventing it being used for profile + // synchronization + // + // Since this is only used in rare circumstances no attempt to + // restore the old handler will be made + handle_signal(signalNum, signal_ignore_handler, 0); +#endif +} + + +/*++ +Function : + common_signal_handler + + common code for all signal handlers + +Parameters : + int code : signal received + siginfo_t *siginfo : siginfo passed to the signal handler + void *context : context structure passed to the signal handler + int numParams : number of variable parameters of the exception + ... : variable parameters of the exception (each of size_t type) + + Returns true if the execution should continue or false if the exception was unhandled +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; + CONTEXT signalContextRecord; + EXCEPTION_RECORD exceptionRecord; + native_context_t *ucontext; + + ucontext = (native_context_t *)sigcontext; + g_common_signal_handler_context_locvar_offset = (int)((char*)&signalContextRecord - (char*)__builtin_frame_address(0)); + + if (code == (SIGSEGV | StackOverflowFlag)) + { + exceptionRecord.ExceptionCode = EXCEPTION_STACK_OVERFLOW; + code &= ~StackOverflowFlag; + } + else + { + exceptionRecord.ExceptionCode = CONTEXTGetExceptionCodeForSignal(siginfo, ucontext); + } + exceptionRecord.ExceptionFlags = EXCEPTION_IS_SIGNAL; + exceptionRecord.ExceptionRecord = NULL; + exceptionRecord.ExceptionAddress = GetNativeContextPC(ucontext); + exceptionRecord.NumberParameters = numParams; + + va_list params; + va_start(params, numParams); + + for (int i = 0; i < numParams; i++) + { + exceptionRecord.ExceptionInformation[i] = va_arg(params, size_t); + } + + // Pre-populate context with data from current frame, because ucontext doesn't have some data (e.g. SS register) + // which is required for restoring context + RtlCaptureContext(&signalContextRecord); + + ULONG contextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT; + +#if defined(HOST_AMD64) + contextFlags |= CONTEXT_XSTATE; +#endif + + // Fill context record with required information. from pal.h: + // On non-Win32 platforms, the CONTEXT pointer in the + // PEXCEPTION_POINTERS will contain at least the CONTEXT_CONTROL registers. + CONTEXTFromNativeContext(ucontext, &signalContextRecord, contextFlags); + + /* Unmask signal so we can receive it again */ + sigemptyset(&signal_set); + sigaddset(&signal_set, code); + int sigmaskRet = pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL); + if (sigmaskRet != 0) + { + ASSERT("pthread_sigmask failed; error number is %d\n", sigmaskRet); + } + + signalContextRecord.ContextFlags |= CONTEXT_EXCEPTION_ACTIVE; + + // The exception object takes ownership of the exceptionRecord and contextRecord + PAL_SEHException exception(&exceptionRecord, &signalContextRecord, true); + + if (SEHProcessException(&exception)) + { + // Exception handling may have modified the context, so update it. + CONTEXTToNativeContext(exception.ExceptionPointers.ContextRecord, ucontext); + return true; + } + + return false; +} +#endif // !HAVE_MACH_EXCEPTIONS + +/*++ +Function : + handle_signal + + register handler for specified signal + +Parameters : + int signal_id : signal to handle + SIGFUNC sigfunc : signal handler + previousAction : previous sigaction struct + + (no return value) + +note : if sigfunc is NULL, the default signal handler is restored +--*/ +void handle_signal(int signal_id, SIGFUNC sigfunc, struct sigaction *previousAction, int additionalFlags, bool skipIgnored) +{ + struct sigaction newAction; + + newAction.sa_flags = SA_RESTART | additionalFlags; + newAction.sa_handler = NULL; + newAction.sa_sigaction = sigfunc; + newAction.sa_flags |= SA_SIGINFO; + sigemptyset(&newAction.sa_mask); + +#ifdef INJECT_ACTIVATION_SIGNAL + if ((additionalFlags & SA_ONSTACK) != 0) + { + // A handler that runs on a separate stack should not be interrupted by the activation signal + // until it switches back to the regular stack, since that signal's handler would run on the + // limited separate stack and likely run into a stack overflow. + sigaddset(&newAction.sa_mask, INJECT_ACTIVATION_SIGNAL); + } +#endif + + if (skipIgnored) + { + if (-1 == sigaction(signal_id, NULL, previousAction)) + { + ASSERT("handle_signal: sigaction() call failed with error code %d (%s)\n", + errno, strerror(errno)); + } + else if (previousAction->sa_handler == SIG_IGN) + { + return; + } + } + + if (-1 == sigaction(signal_id, &newAction, previousAction)) + { + ASSERT("handle_signal: sigaction() call failed with error code %d (%s)\n", + errno, strerror(errno)); + } +} + +/*++ +Function : + restore_signal + + restore handler for specified signal + +Parameters : + int signal_id : signal to handle + previousAction : previous sigaction struct to restore + + (no return value) +--*/ +void restore_signal(int signal_id, struct sigaction *previousAction) +{ + if (-1 == sigaction(signal_id, previousAction, NULL)) + { + ASSERT("restore_signal: sigaction() call failed with error code %d (%s)\n", + errno, strerror(errno)); + } +} + +/*++ +Function : + restore_signal_and_resend + + restore handler for specified signal and signal the process + +Parameters : + int signal_id : signal to handle + previousAction : previous sigaction struct to restore + + (no return value) +--*/ +void restore_signal_and_resend(int signal_id, struct sigaction* previousAction) +{ + restore_signal(signal_id, previousAction); + kill(gPID, signal_id); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/directory.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/directory.cpp new file mode 100644 index 0000000..4711ff7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/directory.cpp @@ -0,0 +1,725 @@ +// 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: + + directory.c + +Abstract: + + Implementation of the file WIN API for the PAL + +Revision History: + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/file.h" +#include "pal/stackstring.hpp" + +#include +#include +#include +#include +#include + +SET_DEFAULT_DEBUG_CHANNEL(FILE); + + + +/*++ +Function: + CreateDirectoryW + +Note: + lpSecurityAttributes always NULL. + +See MSDN doc. +--*/ +BOOL +PALAPI +CreateDirectoryW( + IN LPCWSTR lpPathName, + IN LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + BOOL bRet = FALSE; + DWORD dwLastError = 0; + int mb_size; + char *mb_dir = NULL; + + PERF_ENTRY(CreateDirectoryW); + ENTRY("CreateDirectoryW(lpPathName=%p (%S), lpSecurityAttr=%p)\n", + lpPathName?lpPathName:W16_NULLSTRING, + lpPathName?lpPathName:W16_NULLSTRING, lpSecurityAttributes); + + if ( lpSecurityAttributes ) + { + ASSERT("lpSecurityAttributes is not NULL as it should be\n"); + dwLastError = ERROR_INVALID_PARAMETER; + goto done; + } + + /* translate the wide char lpPathName string to multibyte string */ + if(0 == (mb_size = WideCharToMultiByte( CP_ACP, 0, lpPathName, -1, NULL, 0, + NULL, NULL ))) + { + ASSERT("WideCharToMultiByte failure! error is %d\n", GetLastError()); + dwLastError = ERROR_INTERNAL_ERROR; + goto done; + } + + if (((mb_dir = (char *)PAL_malloc(mb_size)) == NULL) || + (WideCharToMultiByte( CP_ACP, 0, lpPathName, -1, mb_dir, mb_size, NULL, + NULL) != mb_size)) + { + ASSERT("WideCharToMultiByte or PAL_malloc failure! LastError:%d errno:%d\n", + GetLastError(), errno); + dwLastError = ERROR_INTERNAL_ERROR; + goto done; + } + + bRet = CreateDirectoryA(mb_dir,NULL); +done: + if( dwLastError ) + { + SetLastError( dwLastError ); + } + if (mb_dir != NULL) + { + PAL_free(mb_dir); + } + LOGEXIT("CreateDirectoryW returns BOOL %d\n", bRet); + PERF_EXIT(CreateDirectoryW); + return bRet; +} + +/*++ +Routine Name: + + RemoveDirectoryHelper + +Routine Description: + + Core function which removes a directory. Called by RemoveDirectory[AW] + +Parameters: + + LPSTR lpPathName - [in/out] + The directory name to remove. It is converted in place to a unix path. + +Return Value: + + BOOL - + TRUE <=> successful + +--*/ + +static +BOOL +RemoveDirectoryHelper ( + PathCharString& lpPathName, + LPDWORD dwLastError +) +{ + BOOL bRet = FALSE; + *dwLastError = 0; + + FILEDosToUnixPathA( lpPathName ); + + if ( rmdir(lpPathName) != 0 ) + { + TRACE("Removal of directory [%s] was unsuccessful, errno = %d.\n", + lpPathName.GetString(), errno); + + switch( errno ) + { + case ENOTDIR: + /* FALL THROUGH */ + case ENOENT: + { + struct stat stat_data; + + if ( stat( lpPathName, &stat_data) == 0 && + (stat_data.st_mode & S_IFMT) == S_IFREG ) + { + /* Not a directory, it is a file. */ + *dwLastError = ERROR_DIRECTORY; + } + else + { + FILEGetProperNotFoundError( lpPathName, dwLastError ); + } + break; + } + case ENOTEMPTY: + *dwLastError = ERROR_DIR_NOT_EMPTY; + break; + default: + *dwLastError = ERROR_ACCESS_DENIED; + } + } + else { + TRACE("Removal of directory [%s] was successful.\n", lpPathName.GetString()); + bRet = TRUE; + } + + return bRet; +} + +/*++ +Function: + RemoveDirectoryA + +See MSDN doc. +--*/ +BOOL +PALAPI +RemoveDirectoryA( + IN LPCSTR lpPathName) +{ + DWORD dwLastError = 0; + BOOL bRet = FALSE; + PathCharString mb_dirPathString; + + PERF_ENTRY(RemoveDirectoryA); + ENTRY("RemoveDirectoryA(lpPathName=%p (%s))\n", + lpPathName, + lpPathName); + + if (lpPathName == NULL) + { + dwLastError = ERROR_PATH_NOT_FOUND; + goto done; + } + + if (!mb_dirPathString.Set(lpPathName, strlen(lpPathName))) + { + WARN("Set failed !\n"); + dwLastError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + bRet = RemoveDirectoryHelper (mb_dirPathString, &dwLastError); + +done: + if( dwLastError ) + { + SetLastError( dwLastError ); + } + + LOGEXIT("RemoveDirectoryA returns BOOL %d\n", bRet); + PERF_EXIT(RemoveDirectoryA); + return bRet; +} + +/*++ +Function: + RemoveDirectoryW + +See MSDN doc. +--*/ +BOOL +PALAPI +RemoveDirectoryW( + IN LPCWSTR lpPathName) +{ + PathCharString mb_dirPathString; + int mb_size; + DWORD dwLastError = 0; + BOOL bRet = FALSE; + size_t length; + char * mb_dir = NULL; + + PERF_ENTRY(RemoveDirectoryW); + ENTRY("RemoveDirectoryW(lpPathName=%p (%S))\n", + lpPathName?lpPathName:W16_NULLSTRING, + lpPathName?lpPathName:W16_NULLSTRING); + + if (lpPathName == NULL) + { + dwLastError = ERROR_PATH_NOT_FOUND; + goto done; + } + + length = (PAL_wcslen(lpPathName)+1) * 3; + mb_dir = mb_dirPathString.OpenStringBuffer(length); + if (NULL == mb_dir) + { + dwLastError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + mb_size = WideCharToMultiByte( CP_ACP, 0, lpPathName, -1, mb_dir, length, + NULL, NULL ); + + if( mb_size == 0 ) + { + mb_dirPathString.CloseBuffer(0); + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + dwLastError = ERROR_INTERNAL_ERROR; + goto done; + } + + mb_dirPathString.CloseBuffer(mb_size - 1); + + if ((bRet = RemoveDirectoryHelper (mb_dirPathString, &dwLastError))) + { + TRACE("Removal of directory [%s] was successful.\n", mb_dir); + } + +done: + if( dwLastError ) + { + SetLastError( dwLastError ); + } + + LOGEXIT("RemoveDirectoryW returns BOOL %d\n", bRet); + PERF_EXIT(RemoveDirectoryW); + return bRet; +} + + +/*++ +Function: + GetCurrentDirectoryA + +--*/ +DWORD +GetCurrentDirectoryA(PathCharString& lpBuffer) +{ + DWORD dwDirLen = 0; + DWORD dwLastError = 0; + + char *current_dir; + + PERF_ENTRY(GetCurrentDirectoryA); + ENTRY("GetCurrentDirectoryA(lpBuffer=%p)\n", lpBuffer.GetString()); + + current_dir = lpBuffer.OpenStringBuffer(MAX_PATH); + /* NULL first arg means getcwd will allocate the string */ + current_dir = getcwd( current_dir, MAX_PATH); + + if (current_dir != NULL ) + { + dwDirLen = strlen( current_dir ); + lpBuffer.CloseBuffer(dwDirLen); + goto done; + } + else if ( errno == ERANGE ) + { + lpBuffer.CloseBuffer(0); + current_dir = getcwd( NULL, 0); + } + + if ( !current_dir ) + { + WARN("Getcwd failed with errno=%d [%s]\n", errno, strerror(errno)); + dwLastError = DIRGetLastErrorFromErrno(); + dwDirLen = 0; + goto done; + } + + dwDirLen = strlen( current_dir ); + lpBuffer.Set(current_dir, dwDirLen); + PAL_free(current_dir); +done: + + if ( dwLastError ) + { + SetLastError(dwLastError); + } + + LOGEXIT("GetCurrentDirectoryA returns DWORD %u\n", dwDirLen); + PERF_EXIT(GetCurrentDirectoryA); + return dwDirLen; +} + +/*++ +Function: + GetCurrentDirectoryA + +See MSDN doc. +--*/ +DWORD +PALAPI +GetCurrentDirectoryA( + IN DWORD nBufferLength, + OUT LPSTR lpBuffer) +{ + + PathCharString lpBufferString; + DWORD dwDirLen = GetCurrentDirectoryA(lpBufferString); + + /* if the supplied buffer isn't long enough, return the required + length, including room for the NULL terminator */ + if ( nBufferLength <= dwDirLen ) + { + ++dwDirLen; /* include space for the NULL */ + } + else + { + strcpy_s( lpBuffer, nBufferLength, lpBufferString ); + } + + return dwDirLen; +} + +/*++ +Function: + GetCurrentDirectoryW + +See MSDN doc. +--*/ +DWORD +PALAPI +GetCurrentDirectoryW( + IN DWORD nBufferLength, + OUT LPWSTR lpBuffer) +{ + DWORD dwWideLen = 0; + DWORD dwLastError = ERROR_BAD_PATHNAME; + int dir_len; + PathCharString current_dir; + + PERF_ENTRY(GetCurrentDirectoryW); + ENTRY("GetCurrentDirectoryW(nBufferLength=%u, lpBuffer=%p)\n", + nBufferLength, lpBuffer); + + + dir_len = GetCurrentDirectoryA(current_dir); + + if( dir_len == 0) + { + dwLastError = DIRGetLastErrorFromErrno(); + goto done; + } + + dwWideLen = MultiByteToWideChar( CP_ACP, 0, + current_dir, dir_len, + NULL, 0 ); + + /* if the supplied buffer isn't long enough, return the required + length, including room for the NULL terminator */ + if ( nBufferLength > dwWideLen ) + { + if(!MultiByteToWideChar( CP_ACP, 0, current_dir, dir_len + 1, + lpBuffer, nBufferLength )) + { + ASSERT("MultiByteToWideChar failure!\n"); + dwWideLen = 0; + dwLastError = ERROR_INTERNAL_ERROR; + } + } + else + { + ++dwWideLen; /* include the space for the NULL */ + } + +done: + + if ( dwLastError ) + { + SetLastError(dwLastError); + } + + LOGEXIT("GetCurrentDirectoryW returns DWORD %u\n", dwWideLen); + PERF_EXIT(GetCurrentDirectoryW); + return dwWideLen; +} + + +/*++ +Function: + SetCurrentDirectoryW + +See MSDN doc. +--*/ +BOOL +PALAPI +SetCurrentDirectoryW( + IN LPCWSTR lpPathName) +{ + BOOL bRet; + DWORD dwLastError = 0; + PathCharString dirPathString; + int size; + size_t length; + char * dir = NULL; + + PERF_ENTRY(SetCurrentDirectoryW); + ENTRY("SetCurrentDirectoryW(lpPathName=%p (%S))\n", + lpPathName?lpPathName:W16_NULLSTRING, + lpPathName?lpPathName:W16_NULLSTRING); + + /*check if the given path is null. If so + return FALSE*/ + if (lpPathName == NULL ) + { + ERROR("Invalid path/directory name\n"); + dwLastError = ERROR_INVALID_NAME; + bRet = FALSE; + goto done; + } + + length = (PAL_wcslen(lpPathName)+1) * 3; + dir = dirPathString.OpenStringBuffer(length); + if (NULL == dir) + { + dwLastError = ERROR_NOT_ENOUGH_MEMORY; + bRet = FALSE; + goto done; + } + + size = WideCharToMultiByte( CP_ACP, 0, lpPathName, -1, dir, length, + NULL, NULL ); + + if( size == 0 ) + { + dirPathString.CloseBuffer(0); + dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + dwLastError = ERROR_INTERNAL_ERROR; + bRet = FALSE; + goto done; + } + + dirPathString.CloseBuffer(size - 1); + bRet = SetCurrentDirectoryA(dir); +done: + if( dwLastError ) + { + SetLastError(dwLastError); + } + + LOGEXIT("SetCurrentDirectoryW returns BOOL %d\n", bRet); + PERF_EXIT(SetCurrentDirectoryW); + return bRet; +} + +/*++ +Function: + CreateDirectoryA + +Note: + lpSecurityAttributes always NULL. + +See MSDN doc. +--*/ +BOOL +PALAPI +CreateDirectoryA( + IN LPCSTR lpPathName, + IN LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + BOOL bRet = FALSE; + DWORD dwLastError = 0; + PathCharString realPath; + char* realPathBuf; + LPSTR unixPathName = NULL; + int pathLength; + int i; + const int mode = S_IRWXU | S_IRWXG | S_IRWXO; + + PERF_ENTRY(CreateDirectoryA); + ENTRY("CreateDirectoryA(lpPathName=%p (%s), lpSecurityAttr=%p)\n", + lpPathName?lpPathName:"NULL", + lpPathName?lpPathName:"NULL", lpSecurityAttributes); + + if ( lpSecurityAttributes ) + { + ASSERT("lpSecurityAttributes is not NULL as it should be\n"); + dwLastError = ERROR_INVALID_PARAMETER; + goto done; + } + + // Windows returns ERROR_PATH_NOT_FOUND when called with NULL. + // If we don't have this check, strdup(NULL) segfaults. + if (lpPathName == NULL) + { + ERROR("CreateDirectoryA called with NULL pathname!\n"); + dwLastError = ERROR_PATH_NOT_FOUND; + goto done; + } + + unixPathName = PAL__strdup(lpPathName); + if (unixPathName == NULL ) + { + ERROR("PAL__strdup() failed\n"); + dwLastError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + FILEDosToUnixPathA( unixPathName ); + // Remove any trailing slashes at the end because mkdir might not + // handle them appropriately on all platforms. + pathLength = strlen(unixPathName); + i = pathLength; + while(i > 1) + { + if(unixPathName[i - 1] =='/') + { + unixPathName[i - 1]='\0'; + i--; + } + else + { + break; + } + } + + + // Get an absolute path. + if (unixPathName[0] == '/') + { + realPathBuf = unixPathName; + } + else + { + + DWORD len = GetCurrentDirectoryA(realPath); + if (len == 0 || !realPath.Reserve(realPath.GetCount() + pathLength + 1 )) + { + dwLastError = DIRGetLastErrorFromErrno(); + WARN("Getcwd failed with errno=%d \n", dwLastError); + goto done; + } + + realPath.Append("/", 1); + realPath.Append(unixPathName, pathLength); + realPathBuf = realPath.OpenStringBuffer(realPath.GetCount()); + } + + // Canonicalize the path so we can determine its length. + FILECanonicalizePath(realPathBuf); + + if ( mkdir(realPathBuf, mode) != 0 ) + { + TRACE("Creation of directory [%s] was unsuccessful, errno = %d.\n", + unixPathName, errno); + + switch( errno ) + { + case ENOTDIR: + /* FALL THROUGH */ + case ENOENT: + FILEGetProperNotFoundError( realPathBuf, &dwLastError ); + goto done; + case EEXIST: + dwLastError = ERROR_ALREADY_EXISTS; + break; + default: + dwLastError = ERROR_ACCESS_DENIED; + } + } + else + { + TRACE("Creation of directory [%s] was successful.\n", unixPathName); + bRet = TRUE; + } + + realPath.CloseBuffer(0); //The PathCharString usage is done +done: + if( dwLastError ) + { + SetLastError( dwLastError ); + } + PAL_free( unixPathName ); + LOGEXIT("CreateDirectoryA returns BOOL %d\n", bRet); + PERF_EXIT(CreateDirectoryA); + return bRet; +} + +/*++ +Function: + SetCurrentDirectoryA + +See MSDN doc. +--*/ +BOOL +PALAPI +SetCurrentDirectoryA( + IN LPCSTR lpPathName) +{ + BOOL bRet = FALSE; + DWORD dwLastError = 0; + int result; + LPSTR unixPathName = NULL; + + PERF_ENTRY(SetCurrentDirectoryA); + ENTRY("SetCurrentDirectoryA(lpPathName=%p (%s))\n", + lpPathName?lpPathName:"NULL", + lpPathName?lpPathName:"NULL"); + + /*check if the given path is null. If so + return FALSE*/ + if (lpPathName == NULL ) + { + ERROR("Invalid path/directory name\n"); + dwLastError = ERROR_INVALID_NAME; + goto done; + } + + unixPathName = PAL__strdup(lpPathName); + if (unixPathName == NULL ) + { + ERROR("PAL__strdup() failed\n"); + dwLastError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + FILEDosToUnixPathA( unixPathName ); + + TRACE("Attempting to open Unix dir [%s]\n", unixPathName); + result = chdir(unixPathName); + + if ( result == 0 ) + { + bRet = TRUE; + } + else + { + if ( errno == ENOTDIR || errno == ENOENT ) + { + struct stat stat_data; + + if ( stat( unixPathName, &stat_data) == 0 && + (stat_data.st_mode & S_IFMT) == S_IFREG ) + { + /* Not a directory, it is a file. */ + dwLastError = ERROR_DIRECTORY; + } + else + { + FILEGetProperNotFoundError( unixPathName, &dwLastError ); + } + TRACE("chdir() failed, path was invalid.\n"); + } + else + { + dwLastError = ERROR_ACCESS_DENIED; + ERROR("chdir() failed; errno is %d (%s)\n", errno, strerror(errno)); + } + } + + +done: + if( dwLastError ) + { + SetLastError(dwLastError); + } + + if(unixPathName != NULL) + { + PAL_free( unixPathName ); + } + + LOGEXIT("SetCurrentDirectoryA returns BOOL %d\n", bRet); + PERF_EXIT(SetCurrentDirectoryA); + return bRet; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/file.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/file.cpp new file mode 100644 index 0000000..92695fd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/file.cpp @@ -0,0 +1,4182 @@ +// 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: + + file.cpp + +Abstract: + + Implementation of the file WIN API for the PAL + + + +--*/ + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(FILE); // some headers have code with asserts, so do this first + +#include "pal/thread.hpp" +#include "pal/file.hpp" +#include "pal/malloc.hpp" +#include "pal/stackstring.hpp" + +#include "pal/palinternal.h" +#include "pal/file.h" +#include "pal/filetime.h" +#include "pal/utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace CorUnix; + +int MaxWCharToAcpLengthFactor = 3; + +PAL_ERROR +InternalSetFilePointerForUnixFd( + int iUnixFd, + LONG lDistanceToMove, + PLONG lpDistanceToMoveHigh, + DWORD dwMoveMethod, + PLONG lpNewFilePointerLow + ); + +void +CFileProcessLocalDataCleanupRoutine( + CPalThread *pThread, + IPalObject *pObjectToCleanup + ); + +void +FileCleanupRoutine( + CPalThread *pThread, + IPalObject *pObjectToCleanup, + bool fShutdown, + bool fCleanupSharedState + ); + +CObjectType CorUnix::otFile( + otiFile, + FileCleanupRoutine, + NULL, // No initialization routine + 0, // No immutable data + NULL, // No immutable data copy routine + NULL, // No immutable data cleanup routine + sizeof(CFileProcessLocalData), + CFileProcessLocalDataCleanupRoutine, + 0, // No shared data + GENERIC_READ|GENERIC_WRITE, // Ignored -- no Win32 object security support + CObjectType::SecuritySupported, + CObjectType::OSPersistedSecurityInfo, + CObjectType::UnnamedObject, + CObjectType::LocalDuplicationOnly, + CObjectType::UnwaitableObject, + CObjectType::SignalingNotApplicable, + CObjectType::ThreadReleaseNotApplicable, + CObjectType::OwnershipNotApplicable + ); + +CAllowedObjectTypes CorUnix::aotFile(otiFile); + +void +CFileProcessLocalDataCleanupRoutine( + CPalThread *pThread, + IPalObject *pObjectToCleanup + ) +{ + PAL_ERROR palError; + CFileProcessLocalData *pLocalData = NULL; + IDataLock *pLocalDataLock = NULL; + + palError = pObjectToCleanup->GetProcessLocalData( + pThread, + ReadLock, + &pLocalDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + ASSERT("Unable to obtain data to cleanup file object"); + return; + } + + free(pLocalData->unix_filename); + + pLocalDataLock->ReleaseLock(pThread, FALSE); +} + +void +FileCleanupRoutine( + CPalThread *pThread, + IPalObject *pObjectToCleanup, + bool fShutdown, + bool fCleanupSharedState + ) +{ + PAL_ERROR palError; + CFileProcessLocalData *pLocalData = NULL; + IDataLock *pLocalDataLock = NULL; + + palError = pObjectToCleanup->GetProcessLocalData( + pThread, + ReadLock, + &pLocalDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + ASSERT("Unable to obtain data to cleanup file object"); + return; + } + + if (!fShutdown && -1 != pLocalData->unix_fd) + { + close(pLocalData->unix_fd); + } + + pLocalDataLock->ReleaseLock(pThread, FALSE); +} + +typedef enum +{ + PIID_STDIN_HANDLE, + PIID_STDOUT_HANDLE, + PIID_STDERR_HANDLE +} PROCINFO_ID; + +#define PAL_LEGAL_FLAGS_ATTRIBS (FILE_ATTRIBUTE_NORMAL| \ + FILE_FLAG_SEQUENTIAL_SCAN| \ + FILE_FLAG_WRITE_THROUGH| \ + FILE_FLAG_NO_BUFFERING| \ + FILE_FLAG_RANDOM_ACCESS| \ + FILE_FLAG_BACKUP_SEMANTICS) + +/* Static global. The init function must be called +before any other functions and if it is not successful, +no other functions should be done. */ +static HANDLE pStdIn = INVALID_HANDLE_VALUE; +static HANDLE pStdOut = INVALID_HANDLE_VALUE; +static HANDLE pStdErr = INVALID_HANDLE_VALUE; + +/*++ +Function : + FILEGetProperNotFoundError + +Returns the proper error code, based on the +Windows behavior. + + IN LPSTR lpPath - The path to check. + LPDWORD lpErrorCode - The error to set. +*/ +void FILEGetProperNotFoundError( LPCSTR lpPath, LPDWORD lpErrorCode ) +{ + struct stat stat_data; + LPSTR lpDupedPath = NULL; + LPSTR lpLastPathSeparator = NULL; + + TRACE( "FILEGetProperNotFoundError( %s )\n", lpPath?lpPath:"(null)" ); + + if ( !lpErrorCode ) + { + ASSERT( "lpErrorCode has to be valid\n" ); + return; + } + + if ( NULL == ( lpDupedPath = strdup(lpPath) ) ) + { + ERROR( "strdup() failed!\n" ); + *lpErrorCode = ERROR_NOT_ENOUGH_MEMORY; + return; + } + + /* Determine whether it's a file not found or path not found. */ + lpLastPathSeparator = strrchr( lpDupedPath, '/'); + if ( lpLastPathSeparator != NULL ) + { + *lpLastPathSeparator = '\0'; + + /* If the last path component is a directory, + we return file not found. If it's a file or + doesn't exist, we return path not found. */ + if ( '\0' == *lpDupedPath || + ( stat( lpDupedPath, &stat_data ) == 0 && + ( stat_data.st_mode & S_IFMT ) == S_IFDIR ) ) + { + TRACE( "ERROR_FILE_NOT_FOUND\n" ); + *lpErrorCode = ERROR_FILE_NOT_FOUND; + } + else + { + TRACE( "ERROR_PATH_NOT_FOUND\n" ); + *lpErrorCode = ERROR_PATH_NOT_FOUND; + } + } + else + { + TRACE( "ERROR_FILE_NOT_FOUND\n" ); + *lpErrorCode = ERROR_FILE_NOT_FOUND; + } + + free(lpDupedPath); + lpDupedPath = NULL; + TRACE( "FILEGetProperNotFoundError returning TRUE\n" ); + return; +} + +/*++ +Function : + FILEGetLastErrorFromErrnoAndFilename + +Returns the proper error code for errno, or, if errno is ENOENT, +based on the Windows behavior for nonexistent filenames. + + IN LPSTR lpPath - The path to check. +*/ +PAL_ERROR FILEGetLastErrorFromErrnoAndFilename(LPCSTR lpPath) +{ + PAL_ERROR palError; + if (ENOENT == errno) + { + FILEGetProperNotFoundError(lpPath, &palError); + } + else + { + palError = FILEGetLastErrorFromErrno(); + } + return palError; +} + +BOOL +CorUnix::RealPathHelper(LPCSTR lpUnixPath, PathCharString& lpBuffer) +{ + StringHolder lpRealPath; + lpRealPath = realpath(lpUnixPath, NULL); + if (lpRealPath.IsNull()) + { + return FALSE; + } + + lpBuffer.Set(lpRealPath, strlen(lpRealPath)); + return TRUE; +} +/*++ +InternalCanonicalizeRealPath + Wraps realpath() to hide platform differences. See the man page for + realpath(3) for details of how realpath() works. + + On systems on which realpath() allows the last path component to not + exist, this is a straight thunk through to realpath(). On other + systems, we remove the last path component, then call realpath(). + +--*/ +PAL_ERROR +CorUnix::InternalCanonicalizeRealPath(LPCSTR lpUnixPath, PathCharString& lpBuffer) +{ + PAL_ERROR palError = NO_ERROR; + +#if !REALPATH_SUPPORTS_NONEXISTENT_FILES + StringHolder lpExistingPath; + LPSTR pchSeparator = NULL; + LPSTR lpFilename = NULL; + DWORD cchBuffer = 0; + DWORD cchFilename = 0; +#endif // !REALPATH_SUPPORTS_NONEXISTENT_FILES + + if (lpUnixPath == NULL) + { + ERROR ("Invalid argument to InternalCanonicalizeRealPath\n"); + palError = ERROR_INVALID_PARAMETER; + goto LExit; + } + +#if REALPATH_SUPPORTS_NONEXISTENT_FILES + RealPathHelper(lpUnixPath, lpBuffer); +#else // !REALPATH_SUPPORTS_NONEXISTENT_FILES + + lpExistingPath = strdup(lpUnixPath); + if (lpExistingPath.IsNull()) + { + ERROR ("strdup failed with error %d\n", errno); + palError = ERROR_NOT_ENOUGH_MEMORY; + goto LExit; + } + + pchSeparator = strrchr(lpExistingPath, '/'); + if (pchSeparator == NULL) + { + PathCharString pszCwdBuffer; + + if (GetCurrentDirectoryA(pszCwdBuffer)== 0) + { + WARN("getcwd(NULL) failed with error %d\n", errno); + palError = DIRGetLastErrorFromErrno(); + goto LExit; + } + + if (! RealPathHelper(pszCwdBuffer, lpBuffer)) + { + WARN("realpath() failed with error %d\n", errno); + palError = FILEGetLastErrorFromErrno(); +#if defined(HOST_AMD64) + // If we are here, then we tried to invoke realpath + // against a directory. + // + // On Mac64, realpath implementation differs from Mac32 + // by *not* supporting invalid filenames in the path (while + // Mac32 implementation does). + // + // Thus, if we are here, and the error code we see is + // ERROR_FILE_NOT_FOUND, then we should map it to + // ERROR_PATH_NOT_FOUND since it was a directory that + // was not found (and not a file). + if (palError == ERROR_FILE_NOT_FOUND) + { + // Since lpBuffer can be modified by the realpath call, + // and can result in a truncated subset of the original buffer, + // we use strstr as a level of safety. + if (strstr(pszCwdBuffer, lpBuffer) != 0) + { + palError = ERROR_PATH_NOT_FOUND; + } + } +#endif // defined(HOST_AMD64) + + goto LExit; + } + lpFilename = lpExistingPath; + } + else + { +#if defined(HOST_AMD64) + bool fSetFilename = true; + // Since realpath implementation cannot handle inexistent filenames, + // check if we are going to truncate the "/" corresponding to the + // root folder (e.g. case of "/Volumes"). If so: + // + // 1) Set the seperator to point to the NULL terminator of the specified + // file/folder name. + // + // 2) Null terminate lpBuffer + // + // 3) Since there is no explicit filename component in lpExistingPath (as + // we only have "/" corresponding to the root), set lpFilename to NULL, + // alongwith a flag indicating that it has already been set. + if (pchSeparator == lpExistingPath) + { + pchSeparator = lpExistingPath+strlen(lpExistingPath); + + // Set the lpBuffer to NULL + lpBuffer.Clear(); + lpFilename = NULL; + fSetFilename = false; + } + else +#endif // defined(HOST_AMD64) + *pchSeparator = '\0'; + + if (!RealPathHelper(lpExistingPath, lpBuffer)) + { + WARN("realpath() failed with error %d\n", errno); + palError = FILEGetLastErrorFromErrno(); + +#if defined(HOST_AMD64) + // If we are here, then we tried to invoke realpath + // against a directory after stripping out the filename + // from the original path. + // + // On Mac64, realpath implementation differs from Mac32 + // by *not* supporting invalid filenames in the path (while + // Mac32 implementation does). + // + // Thus, if we are here, and the error code we see is + // ERROR_FILE_NOT_FOUND, then we should map it to + // ERROR_PATH_NOT_FOUND since it was a directory that + // was not found (and not a file). + if (palError == ERROR_FILE_NOT_FOUND) + { + // Since lpBuffer can be modified by the realpath call, + // and can result in a truncated subset of the original buffer, + // we use strstr as a level of safety. + if (strstr(lpExistingPath, lpBuffer) != 0) + { + palError = ERROR_PATH_NOT_FOUND; + } + } +#endif // defined(HOST_AMD64) + + goto LExit; + } + +#if defined(HOST_AMD64) + if (fSetFilename == true) +#endif // defined(HOST_AMD64) + lpFilename = pchSeparator + 1; + } + +#if defined(HOST_AMD64) + if (lpFilename == NULL) + goto LExit; +#endif // HOST_AMD64 + + if (!lpBuffer.Append("/",1) || !lpBuffer.Append(lpFilename, strlen(lpFilename))) + { + ERROR ("Append failed!\n"); + palError = ERROR_INSUFFICIENT_BUFFER; + + // Doing a goto here since we want to exit now. This will work + // incase someone else adds another if clause below us. + goto LExit; + } + +#endif // REALPATH_SUPPORTS_NONEXISTENT_FILES +LExit: + + if ((palError == NO_ERROR) && lpBuffer.IsEmpty()) + { + // convert all these into ERROR_PATH_NOT_FOUND + palError = ERROR_PATH_NOT_FOUND; + } + + return palError; +} + +PAL_ERROR +CorUnix::InternalCreateFile( + CPalThread *pThread, + LPCSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile, + HANDLE *phFile + ) +{ + PAL_ERROR palError = 0; + IPalObject *pFileObject = NULL; + IPalObject *pRegisteredFile = NULL; + IDataLock *pDataLock = NULL; + CFileProcessLocalData *pLocalData = NULL; + CObjectAttributes oaFile(NULL, lpSecurityAttributes); + BOOL fFileExists = FALSE; + + BOOL inheritable = FALSE; + PathCharString lpUnixPath; + int filed = -1; + int create_flags = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + int open_flags = 0; + + // track whether we've created the file with the intended name, + // so that it can be removed on failure exit + BOOL bFileCreated = FALSE; + + const char* szNonfilePrefix = "\\\\.\\"; + PathCharString lpFullUnixPath; + + /* for dwShareMode only three flags are accepted */ + if ( dwShareMode & ~(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) ) + { + ASSERT( "dwShareMode is invalid\n" ); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + + if ( lpFileName == NULL ) + { + ERROR("InternalCreateFile called with NULL filename\n"); + palError = ERROR_PATH_NOT_FOUND; + goto done; + } + + if ( strncmp(lpFileName, szNonfilePrefix, strlen(szNonfilePrefix)) == 0 ) + { + ERROR("InternalCreateFile does not support paths beginning with %s\n", szNonfilePrefix); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + + if( !lpUnixPath.Set(lpFileName,strlen(lpFileName))) + { + ERROR("strdup() failed\n"); + palError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + FILEDosToUnixPathA( lpUnixPath ); + + // Compute the absolute pathname to the file. This pathname is used + // to determine if two file names represent the same file. + palError = InternalCanonicalizeRealPath(lpUnixPath, lpFullUnixPath); + if (palError != NO_ERROR) + { + goto done; + } + + lpUnixPath.Set(lpFullUnixPath); + + switch( dwDesiredAccess ) + { + case 0: + /* Device Query Access was requested. let's use open() with + no flags, it's basically the equivalent of O_RDONLY, since + O_RDONLY is defined as 0x0000 */ + break; + case( GENERIC_READ ): + open_flags |= O_RDONLY; + break; + case( GENERIC_WRITE ): + open_flags |= O_WRONLY; + break; + case( GENERIC_READ | GENERIC_WRITE ): + open_flags |= O_RDWR; + break; + default: + ERROR("dwDesiredAccess value of %d is invalid\n", dwDesiredAccess); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + + TRACE("open flags are 0x%lx\n", open_flags); + + if ( lpSecurityAttributes ) + { + if ( lpSecurityAttributes->nLength != sizeof( SECURITY_ATTRIBUTES ) || + lpSecurityAttributes->lpSecurityDescriptor != NULL || + !lpSecurityAttributes->bInheritHandle ) + { + ASSERT("lpSecurityAttributes points to invalid values.\n"); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + inheritable = TRUE; + } + + if ( (dwFlagsAndAttributes & PAL_LEGAL_FLAGS_ATTRIBS) != + dwFlagsAndAttributes) + { + ASSERT("Bad dwFlagsAndAttributes\n"); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + else if (dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS) + { + /* Override the open flags, and always open as readonly. This + flag is used when opening a directory, to change its + creation/modification/access times. On Windows, the directory + must be open for write, but on Unix, it needs to be readonly. */ + open_flags = O_RDONLY; + } else { + struct stat st; + + if (stat(lpUnixPath, &st) == 0 && (st.st_mode & S_IFDIR)) + { + /* The file exists and it is a directory. Without + FILE_FLAG_BACKUP_SEMANTICS, Win32 CreateFile always fails + to open directories. */ + palError = ERROR_ACCESS_DENIED; + goto done; + } + } + + if ( hTemplateFile ) + { + ASSERT("hTemplateFile is not NULL, as it should be.\n"); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + + /* NB: According to MSDN docs, When CREATE_ALWAYS or OPEN_ALWAYS is + set, CreateFile should SetLastError to ERROR_ALREADY_EXISTS, + even though/if CreateFile will be successful. + */ + switch( dwCreationDisposition ) + { + case( CREATE_ALWAYS ): + // check whether the file exists + if ( access( lpUnixPath, F_OK ) == 0 ) + { + fFileExists = TRUE; + } + open_flags |= O_CREAT | O_TRUNC; + break; + case( CREATE_NEW ): + open_flags |= O_CREAT | O_EXCL; + break; + case( OPEN_EXISTING ): + /* don't need to do anything here */ + break; + case( OPEN_ALWAYS ): + if ( access( lpUnixPath, F_OK ) == 0 ) + { + fFileExists = TRUE; + } + open_flags |= O_CREAT; + break; + case( TRUNCATE_EXISTING ): + open_flags |= O_TRUNC; + break; + default: + ASSERT("dwCreationDisposition value of %d is not valid\n", + dwCreationDisposition); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + + if ( dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING ) + { + TRACE("I/O will be unbuffered\n"); +#ifdef O_DIRECT + open_flags |= O_DIRECT; +#endif + } + else + { + TRACE("I/O will be buffered\n"); + } + + filed = InternalOpen(lpUnixPath, open_flags, create_flags); + TRACE("Allocated file descriptor [%d]\n", filed); + + if ( filed < 0 ) + { + TRACE("open() failed; error is %s (%d)\n", strerror(errno), errno); + palError = FILEGetLastErrorFromErrnoAndFilename(lpUnixPath); + goto done; + } + + // Deduce whether we created a file in the previous operation (there's a + // small timing window between the access() used to determine fFileExists + // and the open() operation, but there's not much we can do about that. + bFileCreated = (dwCreationDisposition == CREATE_ALWAYS || + dwCreationDisposition == CREATE_NEW || + dwCreationDisposition == OPEN_ALWAYS) && + !fFileExists; + +#ifndef O_DIRECT + if ( dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING ) + { +#ifdef F_NOCACHE + if (-1 == fcntl(filed, F_NOCACHE, 1)) + { + ASSERT("Can't set F_NOCACHE; fcntl() failed. errno is %d (%s)\n", + errno, strerror(errno)); + palError = ERROR_INTERNAL_ERROR; + goto done; + } +#elif HAVE_DIRECTIO + if (-1 == directio(filed, DIRECTIO_ON)) + { + ASSERT("Can't set DIRECTIO_ON; directio() failed. errno is %d (%s)\n", + errno, strerror(errno)); + palError = ERROR_INTERNAL_ERROR; + goto done; + } +#else +#error Insufficient support for uncached I/O on this platform +#endif + } +#endif + + /* make file descriptor close-on-exec; inheritable handles will get + "uncloseonexeced" in CreateProcess if they are actually being inherited*/ + if(-1 == fcntl(filed,F_SETFD, FD_CLOEXEC)) + { + ASSERT("can't set close-on-exec flag; fcntl() failed. errno is %d " + "(%s)\n", errno, strerror(errno)); + palError = ERROR_INTERNAL_ERROR; + goto done; + } + + palError = g_pObjectManager->AllocateObject( + pThread, + &otFile, + &oaFile, + &pFileObject + ); + + if (NO_ERROR != palError) + { + goto done; + } + + palError = pFileObject->GetProcessLocalData( + pThread, + WriteLock, + &pDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + goto done; + } + + _ASSERTE(pLocalData->unix_filename == NULL); + pLocalData->unix_filename = strdup(lpUnixPath); + if (pLocalData->unix_filename == NULL) + { + ASSERT("Unable to copy string\n"); + palError = ERROR_INTERNAL_ERROR; + goto done; + } + + pLocalData->inheritable = inheritable; + pLocalData->unix_fd = filed; + pLocalData->open_flags = open_flags; + pLocalData->open_flags_deviceaccessonly = (dwDesiredAccess == 0); + + // + // We've finished initializing our local data, so release that lock + // + + pDataLock->ReleaseLock(pThread, TRUE); + pDataLock = NULL; + + palError = g_pObjectManager->RegisterObject( + pThread, + pFileObject, + &aotFile, + phFile, + &pRegisteredFile + ); + + // + // pFileObject is invalidated by the call to RegisterObject, so NULL it + // out here to ensure that we don't try to release a reference on + // it down the line. + // + + pFileObject = NULL; + +done: + + // At this point, if we've been successful, palError will be NO_ERROR. + // CreateFile can return ERROR_ALREADY_EXISTS in some success cases; + // those cases are flagged by fFileExists and are handled below. + if (NO_ERROR != palError) + { + if (filed >= 0) + { + close(filed); + } + if (bFileCreated) + { + if (-1 == unlink(lpUnixPath)) + { + WARN("can't delete file; unlink() failed with errno %d (%s)\n", + errno, strerror(errno)); + } + } + } + + if (NULL != pDataLock) + { + pDataLock->ReleaseLock(pThread, TRUE); + } + + if (NULL != pFileObject) + { + pFileObject->ReleaseReference(pThread); + } + + if (NULL != pRegisteredFile) + { + pRegisteredFile->ReleaseReference(pThread); + } + + if (NO_ERROR == palError && fFileExists) + { + palError = ERROR_ALREADY_EXISTS; + } + + return palError; +} + +/*++ +Function: + CreateFileA + +Note: + Only bInherit flag is used from the LPSECURITY_ATTRIBUTES struct. + Desired access is READ, WRITE or 0 + Share mode is READ, WRITE or DELETE + +See MSDN doc. +--*/ +HANDLE +PALAPI +CreateFileA( + IN LPCSTR lpFileName, + IN DWORD dwDesiredAccess, + IN DWORD dwShareMode, + IN LPSECURITY_ATTRIBUTES lpSecurityAttributes, + IN DWORD dwCreationDisposition, + IN DWORD dwFlagsAndAttributes, + IN HANDLE hTemplateFile + ) +{ + CPalThread *pThread; + PAL_ERROR palError = NO_ERROR; + HANDLE hRet = INVALID_HANDLE_VALUE; + + PERF_ENTRY(CreateFileA); + ENTRY("CreateFileA(lpFileName=%p (%s), dwAccess=%#x, dwShareMode=%#x, " + "lpSecurityAttr=%p, dwDisposition=%#x, dwFlags=%#x, " + "hTemplateFile=%p )\n",lpFileName?lpFileName:"NULL",lpFileName?lpFileName:"NULL", dwDesiredAccess, + dwShareMode, lpSecurityAttributes, dwCreationDisposition, + dwFlagsAndAttributes, hTemplateFile); + + pThread = InternalGetCurrentThread(); + + palError = InternalCreateFile( + pThread, + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile, + &hRet + ); + + // + // We always need to set last error, even on success: + // we need to protect ourselves from the situation + // where last error is set to ERROR_ALREADY_EXISTS on + // entry to the function + // + + pThread->SetLastError(palError); + + LOGEXIT("CreateFileA returns HANDLE %p\n", hRet); + PERF_EXIT(CreateFileA); + return hRet; +} + + +/*++ +Function: + CreateFileW + +Note: + Only bInherit flag is used from the LPSECURITY_ATTRIBUTES struct. + Desired access is READ, WRITE or 0 + Share mode is READ, WRITE or DELETE + +See MSDN doc. +--*/ +HANDLE +PALAPI +CreateFileW( + IN LPCWSTR lpFileName, + IN DWORD dwDesiredAccess, + IN DWORD dwShareMode, + IN LPSECURITY_ATTRIBUTES lpSecurityAttributes, + IN DWORD dwCreationDisposition, + IN DWORD dwFlagsAndAttributes, + IN HANDLE hTemplateFile) +{ + CPalThread *pThread; + PAL_ERROR palError = NO_ERROR; + PathCharString namePathString; + char * name; + int size; + int length = 0; + HANDLE hRet = INVALID_HANDLE_VALUE; + + PERF_ENTRY(CreateFileW); + ENTRY("CreateFileW(lpFileName=%p (%S), dwAccess=%#x, dwShareMode=%#x, " + "lpSecurityAttr=%p, dwDisposition=%#x, dwFlags=%#x, hTemplateFile=%p )\n", + lpFileName?lpFileName:W16_NULLSTRING, + lpFileName?lpFileName:W16_NULLSTRING, dwDesiredAccess, dwShareMode, + lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, + hTemplateFile); + + pThread = InternalGetCurrentThread(); + + if (lpFileName != NULL) + { + length = (PAL_wcslen(lpFileName)+1) * MaxWCharToAcpLengthFactor; + } + + name = namePathString.OpenStringBuffer(length); + if (NULL == name) + { + palError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + size = WideCharToMultiByte( CP_ACP, 0, lpFileName, -1, name, length, + NULL, NULL ); + + if( size == 0 ) + { + namePathString.CloseBuffer(0); + DWORD dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + palError = ERROR_INTERNAL_ERROR; + goto done; + } + + namePathString.CloseBuffer(size - 1); + + palError = InternalCreateFile( + pThread, + name, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile, + &hRet + ); + + // + // We always need to set last error, even on success: + // we need to protect ourselves from the situation + // where last error is set to ERROR_ALREADY_EXISTS on + // entry to the function + // + +done: + pThread->SetLastError(palError); + LOGEXIT( "CreateFileW returns HANDLE %p\n", hRet ); + PERF_EXIT(CreateFileW); + return hRet; +} + + +/*++ +Function: + CopyFileW + +See MSDN doc. + +Notes: + There are several (most) error paths here that do not call SetLastError(). +This is because we know that CreateFile, ReadFile, and WriteFile will do so, +and will have a much better idea of the specific error. +--*/ +BOOL +PALAPI +CopyFileW( + IN LPCWSTR lpExistingFileName, + IN LPCWSTR lpNewFileName, + IN BOOL bFailIfExists) +{ + CPalThread *pThread; + PathCharString sourcePathString; + PathCharString destPathString; + char * source; + char * dest; + int src_size, dest_size, length = 0; + BOOL bRet = FALSE; + + PERF_ENTRY(CopyFileW); + ENTRY("CopyFileW(lpExistingFileName=%p (%S), lpNewFileName=%p (%S), bFailIfExists=%d)\n", + lpExistingFileName?lpExistingFileName:W16_NULLSTRING, + lpExistingFileName?lpExistingFileName:W16_NULLSTRING, + lpNewFileName?lpNewFileName:W16_NULLSTRING, + lpNewFileName?lpNewFileName:W16_NULLSTRING, bFailIfExists); + + pThread = InternalGetCurrentThread(); + if (lpExistingFileName != NULL) + { + length = (PAL_wcslen(lpExistingFileName)+1) * MaxWCharToAcpLengthFactor; + } + + source = sourcePathString.OpenStringBuffer(length); + if (NULL == source) + { + pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + + src_size = WideCharToMultiByte( CP_ACP, 0, lpExistingFileName, -1, source, length, + NULL, NULL ); + + if( src_size == 0 ) + { + sourcePathString.CloseBuffer(0); + DWORD dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + pThread->SetLastError(ERROR_INTERNAL_ERROR); + goto done; + } + + sourcePathString.CloseBuffer(src_size - 1); + length = 0; + + if (lpNewFileName != NULL) + { + length = (PAL_wcslen(lpNewFileName)+1) * MaxWCharToAcpLengthFactor; + } + + dest = destPathString.OpenStringBuffer(length); + if (NULL == dest) + { + pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + dest_size = WideCharToMultiByte( CP_ACP, 0, lpNewFileName, -1, dest, length, + NULL, NULL ); + + if( dest_size == 0 ) + { + destPathString.CloseBuffer(0); + DWORD dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + pThread->SetLastError(ERROR_INTERNAL_ERROR); + goto done; + } + + destPathString.CloseBuffer(dest_size - 1); + bRet = CopyFileA(source,dest,bFailIfExists); + +done: + LOGEXIT("CopyFileW returns BOOL %d\n", bRet); + PERF_EXIT(CopyFileW); + return bRet; +} + + +/*++ +Function: + DeleteFileA + +See MSDN doc. +--*/ +BOOL +PALAPI +DeleteFileA( + IN LPCSTR lpFileName) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pThread; + int result; + BOOL bRet = FALSE; + DWORD dwLastError = 0; + PathCharString lpunixFileName; + PathCharString lpFullunixFileName; + + PERF_ENTRY(DeleteFileA); + ENTRY("DeleteFileA(lpFileName=%p (%s))\n", lpFileName?lpFileName:"NULL", lpFileName?lpFileName:"NULL"); + + pThread = InternalGetCurrentThread(); + + if( !lpunixFileName.Set(lpFileName, strlen(lpFileName))) + { + palError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + FILEDosToUnixPathA( lpunixFileName ); + + // Compute the absolute pathname to the file. This pathname is used + // to determine if two file names represent the same file. + palError = InternalCanonicalizeRealPath(lpunixFileName, lpFullunixFileName); + if (palError != NO_ERROR) + { + if (!lpFullunixFileName.Set(lpunixFileName, strlen(lpunixFileName))) + { + palError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + } + + result = unlink( lpFullunixFileName ); + + if (result < 0) + { + TRACE("unlink returns %d\n", result); + dwLastError = FILEGetLastErrorFromErrnoAndFilename(lpFullunixFileName); + } + else + { + bRet = TRUE; + } + +done: + if(dwLastError) + { + pThread->SetLastError( dwLastError ); + } + + LOGEXIT("DeleteFileA returns BOOL %d\n", bRet); + PERF_EXIT(DeleteFileA); + return bRet; +} + +/*++ +Function: + DeleteFileW + +See MSDN doc. +--*/ +BOOL +PALAPI +DeleteFileW( + IN LPCWSTR lpFileName) +{ + CPalThread *pThread; + int size; + PathCharString namePS; + char * name; + int length = 0; + BOOL bRet = FALSE; + + PERF_ENTRY(DeleteFileW); + ENTRY("DeleteFileW(lpFileName=%p (%S))\n", + lpFileName?lpFileName:W16_NULLSTRING, + lpFileName?lpFileName:W16_NULLSTRING); + + pThread = InternalGetCurrentThread(); + + if (lpFileName != NULL) + { + length = (PAL_wcslen(lpFileName)+1) * MaxWCharToAcpLengthFactor; + } + + name = namePS.OpenStringBuffer(length); + if (NULL == name) + { + pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + + size = WideCharToMultiByte( CP_ACP, 0, lpFileName, -1, name, length, + NULL, NULL ); + + if( size == 0 ) + { + namePS.CloseBuffer(0); + DWORD dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + pThread->SetLastError(ERROR_INTERNAL_ERROR); + bRet = FALSE; + goto done; + } + + namePS.CloseBuffer(size - 1); + bRet = DeleteFileA( name ); + +done: + LOGEXIT("DeleteFileW returns BOOL %d\n", bRet); + PERF_EXIT(DeleteFileW); + return bRet; +} + + +/*++ +Function: + MoveFileExA + +See MSDN doc. +--*/ +BOOL +PALAPI +MoveFileExA( + IN LPCSTR lpExistingFileName, + IN LPCSTR lpNewFileName, + IN DWORD dwFlags) +{ + CPalThread *pThread; + int result; + PathCharString source; + PathCharString dest; + BOOL bRet = TRUE; + DWORD dwLastError = 0; + + PERF_ENTRY(MoveFileExA); + ENTRY("MoveFileExA(lpExistingFileName=%p (%S), lpNewFileName=%p (%S), " + "dwFlags=%#x)\n", + lpExistingFileName?lpExistingFileName:"NULL", + lpExistingFileName?lpExistingFileName:"NULL", + lpNewFileName?lpNewFileName:"NULL", + lpNewFileName?lpNewFileName:"NULL", dwFlags); + + pThread = InternalGetCurrentThread(); + /* only two flags are accepted */ + if ( dwFlags & ~(MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING) ) + { + ASSERT( "dwFlags is invalid\n" ); + dwLastError = ERROR_INVALID_PARAMETER; + goto done; + } + + + if( !source.Set(lpExistingFileName, strlen(lpExistingFileName))) + { + dwLastError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + FILEDosToUnixPathA( source ); + + if( !dest.Set(lpNewFileName, strlen(lpNewFileName))) + { + dwLastError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + FILEDosToUnixPathA( dest ); + + if ( !(dwFlags & MOVEFILE_REPLACE_EXISTING) ) + { +#if HAVE_CASE_SENSITIVE_FILESYSTEM + if ( strcmp(source, dest) != 0 ) +#else // HAVE_CASE_SENSITIVE_FILESYSTEM + if ( strcasecmp(source, dest) != 0 ) +#endif // HAVE_CASE_SENSITIVE_FILESYSTEM + { + // Let things proceed normally if source and + // dest are the same. + if ( access(dest, F_OK) == 0 ) + { + dwLastError = ERROR_ALREADY_EXISTS; + goto done; + } + } + } + + result = rename( source, dest ); + if ((result < 0) && (dwFlags & MOVEFILE_REPLACE_EXISTING) && + ((errno == ENOTDIR) || (errno == EEXIST))) + { + bRet = DeleteFileA( lpNewFileName ); + + if ( bRet ) + { + result = rename( source, dest ); + } + else + { + dwLastError = GetLastError(); + } + } + + if ( result < 0 ) + { + switch( errno ) + { + case EXDEV: /* we tried to link across devices */ + + if ( dwFlags & MOVEFILE_COPY_ALLOWED ) + { + BOOL bFailIfExists = !(dwFlags & MOVEFILE_REPLACE_EXISTING); + + /* if CopyFile fails here, so should MoveFailEx */ + bRet = CopyFileA( lpExistingFileName, + lpNewFileName, + bFailIfExists ); + /* CopyFile should set the appropriate error */ + if ( !bRet ) + { + dwLastError = GetLastError(); + } + else + { + if (!DeleteFileA(lpExistingFileName)) + { + ERROR("Failed to delete the source file\n"); + dwLastError = GetLastError(); + + /* Delete the destination file if we're unable to delete + the source file */ + if (!DeleteFileA(lpNewFileName)) + { + ERROR("Failed to delete the destination file\n"); + } + } + } + } + else + { + dwLastError = ERROR_ACCESS_DENIED; + } + break; + case EINVAL: // tried to rename "." or ".." + dwLastError = ERROR_SHARING_VIOLATION; + break; + case ENOENT: + { + struct stat buf; + if (lstat(source, &buf) == -1) + { + FILEGetProperNotFoundError(source, &dwLastError); + } + else + { + dwLastError = ERROR_PATH_NOT_FOUND; + } + } + break; + default: + dwLastError = FILEGetLastErrorFromErrno(); + break; + } + } + +done: + if ( dwLastError ) + { + pThread->SetLastError( dwLastError ); + bRet = FALSE; + } + + LOGEXIT( "MoveFileExA returns BOOL %d\n", bRet ); + PERF_EXIT(MoveFileExA); + return bRet; +} + +/*++ +Function: + MoveFileExW + +See MSDN doc. +--*/ +BOOL +PALAPI +MoveFileExW( + IN LPCWSTR lpExistingFileName, + IN LPCWSTR lpNewFileName, + IN DWORD dwFlags) +{ + CPalThread *pThread; + PathCharString sourcePS; + PathCharString destPS; + char * source; + char * dest; + int length = 0; + int src_size,dest_size; + BOOL bRet = FALSE; + + PERF_ENTRY(MoveFileExW); + ENTRY("MoveFileExW(lpExistingFileName=%p (%S), lpNewFileName=%p (%S), dwFlags=%#x)\n", + lpExistingFileName?lpExistingFileName:W16_NULLSTRING, + lpExistingFileName?lpExistingFileName:W16_NULLSTRING, + lpNewFileName?lpNewFileName:W16_NULLSTRING, + lpNewFileName?lpNewFileName:W16_NULLSTRING, dwFlags); + + pThread = InternalGetCurrentThread(); + + if (lpExistingFileName != NULL) + { + length = (PAL_wcslen(lpExistingFileName)+1) * MaxWCharToAcpLengthFactor; + } + + source = sourcePS.OpenStringBuffer(length); + if (NULL == source) + { + pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + src_size = WideCharToMultiByte( CP_ACP, 0, lpExistingFileName, -1, source, length, + NULL, NULL ); + if( src_size == 0 ) + { + sourcePS.CloseBuffer(0); + DWORD dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + pThread->SetLastError(ERROR_INTERNAL_ERROR); + goto done; + } + + sourcePS.CloseBuffer(src_size - 1); + length = 0; + if (lpNewFileName != NULL) + { + length = (PAL_wcslen(lpNewFileName)+1) * MaxWCharToAcpLengthFactor; + } + + dest = destPS.OpenStringBuffer(length); + if (NULL == dest) + { + pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + dest_size = WideCharToMultiByte( CP_ACP, 0, lpNewFileName, -1, dest, length, + NULL, NULL ); + + if( dest_size == 0 ) + { + destPS.CloseBuffer(0); + DWORD dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + pThread->SetLastError(ERROR_INTERNAL_ERROR); + goto done; + } + + destPS.CloseBuffer(dest_size - 1); + bRet = MoveFileExA(source,dest,dwFlags); + +done: + LOGEXIT("MoveFileExW returns BOOL %d\n", bRet); + PERF_EXIT(MoveFileExW); + return bRet; +} + +/*++ +Function: + GetFileAttributesA + +Note: + Checking for directory and read-only file. + +Caveats: + There are some important things to note about this implementation, which +are due to the differences between the FAT filesystem and Unix filesystems: + +- fifo's, sockets, and symlinks will return -1, and GetLastError() will + return ERROR_ACCESS_DENIED + +- if a file is write-only, or has no permissions at all, it is treated + the same as if it had mode 'rw'. This is consistent with behaviour on + NTFS files with the same permissions. + +- the following flags will never be returned: + +FILE_ATTRIBUTE_SYSTEM +FILE_ATTRIBUTE_ARCHIVE +FILE_ATTRIBUTE_HIDDEN + +--*/ +DWORD +PALAPI +GetFileAttributesA( + IN LPCSTR lpFileName) +{ + CPalThread *pThread; + struct stat stat_data; + DWORD dwAttr = 0; + DWORD dwLastError = 0; + PathCharString unixFileName; + + PERF_ENTRY(GetFileAttributesA); + ENTRY("GetFileAttributesA(lpFileName=%p (%s))\n", lpFileName?lpFileName:"NULL", lpFileName?lpFileName:"NULL"); + + pThread = InternalGetCurrentThread(); + if (lpFileName == NULL) + { + dwLastError = ERROR_PATH_NOT_FOUND; + goto done; + } + + + if( !unixFileName.Set(lpFileName, strlen(lpFileName))) + { + dwLastError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + FILEDosToUnixPathA( unixFileName ); + + if ( stat(unixFileName, &stat_data) != 0 ) + { + dwLastError = FILEGetLastErrorFromErrnoAndFilename(unixFileName); + goto done; + } + + if ( (stat_data.st_mode & S_IFMT) == S_IFDIR ) + { + dwAttr |= FILE_ATTRIBUTE_DIRECTORY; + } + else if ( (stat_data.st_mode & S_IFMT) != S_IFREG ) + { + ERROR("Not a regular file or directory, S_IFMT is %#x\n", + stat_data.st_mode & S_IFMT); + dwLastError = ERROR_ACCESS_DENIED; + goto done; + } + + if ( UTIL_IsReadOnlyBitsSet( &stat_data ) ) + { + dwAttr |= FILE_ATTRIBUTE_READONLY; + } + + /* finally, if nothing is set... */ + if ( dwAttr == 0 ) + { + dwAttr = FILE_ATTRIBUTE_NORMAL; + } + +done: + if (dwLastError) + { + pThread->SetLastError(dwLastError); + dwAttr = INVALID_FILE_ATTRIBUTES; + } + + LOGEXIT("GetFileAttributesA returns DWORD %#x\n", dwAttr); + PERF_EXIT(GetFileAttributesA); + return dwAttr; +} + + + + +/*++ +Function: + GetFileAttributesW + +Note: + Checking for directory and read-only file + +See MSDN doc. +--*/ +DWORD +PALAPI +GetFileAttributesW( + IN LPCWSTR lpFileName) +{ + CPalThread *pThread; + int size; + PathCharString filenamePS; + int length = 0; + char * filename; + DWORD dwRet = (DWORD) -1; + + PERF_ENTRY(GetFileAttributesW); + ENTRY("GetFileAttributesW(lpFileName=%p (%S))\n", + lpFileName?lpFileName:W16_NULLSTRING, + lpFileName?lpFileName:W16_NULLSTRING); + + pThread = InternalGetCurrentThread(); + if (lpFileName == NULL) + { + pThread->SetLastError(ERROR_PATH_NOT_FOUND); + goto done; + } + + length = (PAL_wcslen(lpFileName)+1) * MaxWCharToAcpLengthFactor; + filename = filenamePS.OpenStringBuffer(length); + if (NULL == filename) + { + pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + size = WideCharToMultiByte( CP_ACP, 0, lpFileName, -1, filename, length, + NULL, NULL ); + + if( size == 0 ) + { + filenamePS.CloseBuffer(0); + DWORD dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + pThread->SetLastError(ERROR_INTERNAL_ERROR); + } + else + { + filenamePS.CloseBuffer(size - 1); + dwRet = GetFileAttributesA( filename ); + } + +done: + LOGEXIT("GetFileAttributesW returns DWORD %#x\n", dwRet); + PERF_EXIT(GetFileAttributesW); + return dwRet; +} + + +/*++ +Function: + GetFileAttributesExW + +See MSDN doc, and notes for GetFileAttributesW. +--*/ +BOOL +PALAPI +GetFileAttributesExW( + IN LPCWSTR lpFileName, + IN GET_FILEEX_INFO_LEVELS fInfoLevelId, + OUT LPVOID lpFileInformation) +{ + CPalThread *pThread; + BOOL bRet = FALSE; + DWORD dwLastError = 0; + LPWIN32_FILE_ATTRIBUTE_DATA attr_data; + + struct stat stat_data; + + char * name; + PathCharString namePS; + int length = 0; + int size; + + PERF_ENTRY(GetFileAttributesExW); + ENTRY("GetFileAttributesExW(lpFileName=%p (%S), fInfoLevelId=%d, " + "lpFileInformation=%p)\n", lpFileName?lpFileName:W16_NULLSTRING, lpFileName?lpFileName:W16_NULLSTRING, + fInfoLevelId, lpFileInformation); + + pThread = InternalGetCurrentThread(); + if ( fInfoLevelId != GetFileExInfoStandard ) + { + ASSERT("Unrecognized value for fInfoLevelId=%d\n", fInfoLevelId); + dwLastError = ERROR_INVALID_PARAMETER; + goto done; + } + + if ( !lpFileInformation ) + { + ASSERT("lpFileInformation is NULL\n"); + dwLastError = ERROR_INVALID_PARAMETER; + goto done; + } + + if (lpFileName == NULL) + { + dwLastError = ERROR_PATH_NOT_FOUND; + goto done; + } + + length = (PAL_wcslen(lpFileName)+1) * MaxWCharToAcpLengthFactor; + name = namePS.OpenStringBuffer(length); + if (NULL == name) + { + dwLastError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + size = WideCharToMultiByte( CP_ACP, 0, lpFileName, -1, name, length, + NULL, NULL ); + + if( size == 0 ) + { + namePS.CloseBuffer(0); + dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + dwLastError = ERROR_INTERNAL_ERROR; + goto done; + } + + namePS.CloseBuffer(size - 1); + attr_data = (LPWIN32_FILE_ATTRIBUTE_DATA)lpFileInformation; + + attr_data->dwFileAttributes = GetFileAttributesW(lpFileName); + /* assume that GetFileAttributes will call SetLastError appropriately */ + if ( attr_data->dwFileAttributes == (DWORD)-1 ) + { + goto done; + } + + FILEDosToUnixPathA(name); + /* do the stat */ + if ( stat(name, &stat_data) != 0 ) + { + ERROR("stat failed on %S\n", lpFileName); + dwLastError = FILEGetLastErrorFromErrnoAndFilename(name); + goto done; + } + + /* get the file times */ + attr_data->ftCreationTime = + FILEUnixTimeToFileTime( stat_data.st_ctime, + ST_CTIME_NSEC(&stat_data) ); + attr_data->ftLastAccessTime = + FILEUnixTimeToFileTime( stat_data.st_atime, + ST_ATIME_NSEC(&stat_data) ); + attr_data->ftLastWriteTime = + FILEUnixTimeToFileTime( stat_data.st_mtime, + ST_MTIME_NSEC(&stat_data) ); + + /* if Unix mtime is greater than atime, return mtime + as the last access time */ + if (CompareFileTime(&attr_data->ftLastAccessTime, + &attr_data->ftLastWriteTime) < 0) + { + attr_data->ftLastAccessTime = attr_data->ftLastWriteTime; + } + + /* if Unix ctime is greater than mtime, return mtime + as the create time */ + if (CompareFileTime(&attr_data->ftLastWriteTime, + &attr_data->ftCreationTime) < 0) + { + attr_data->ftCreationTime = attr_data->ftLastWriteTime; + } + + /* Get the file size. GetFileSize is not used because it gets the + size of an already-open file */ + attr_data->nFileSizeLow = (DWORD) stat_data.st_size; +#if SIZEOF_OFF_T > 4 + attr_data->nFileSizeHigh = (DWORD)(stat_data.st_size >> 32); +#else + attr_data->nFileSizeHigh = 0; +#endif + + bRet = TRUE; + +done: + if (dwLastError) pThread->SetLastError(dwLastError); + + LOGEXIT("GetFileAttributesExW returns BOOL %d\n", bRet); + PERF_EXIT(GetFileAttributesExW); + return bRet; +} + +/*++ +Function: + SetFileAttributesA + +Notes: + Used for setting read-only attribute on file only. + +--*/ +BOOL +PALAPI +SetFileAttributesA( + IN LPCSTR lpFileName, + IN DWORD dwFileAttributes) +{ + CPalThread *pThread; + struct stat stat_data; + mode_t new_mode; + + DWORD dwLastError = 0; + BOOL bRet = FALSE; + LPSTR unixFileName = NULL; + + PERF_ENTRY(SetFileAttributesA); + ENTRY("SetFileAttributesA(lpFileName=%p (%s), dwFileAttributes=%#x)\n", + lpFileName?lpFileName:"NULL", + lpFileName?lpFileName:"NULL", dwFileAttributes); + + pThread = InternalGetCurrentThread(); + + /* Windows behavior for SetFileAttributes is that any valid attributes + are set on a file and any invalid attributes are ignored. SetFileAttributes + returns success and does not set an error even if some or all of the + attributes are invalid. If all the attributes are invalid, SetFileAttributes + sets a file's attribute to NORMAL. */ + + /* If dwFileAttributes does not contain READONLY or NORMAL, set it to NORMAL + and print a warning message. */ + if ( !(dwFileAttributes & (FILE_ATTRIBUTE_READONLY |FILE_ATTRIBUTE_NORMAL)) ) + { + dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + WARN("dwFileAttributes(%#x) contains attributes that are either not supported " + "or cannot be set via SetFileAttributes.\n"); + } + + if ( (dwFileAttributes & FILE_ATTRIBUTE_NORMAL) && + (dwFileAttributes != FILE_ATTRIBUTE_NORMAL) ) + { + WARN("Ignoring FILE_ATTRIBUTE_NORMAL -- it must be used alone\n"); + } + + if (lpFileName == NULL) + { + dwLastError = ERROR_FILE_NOT_FOUND; + goto done; + } + + if ((unixFileName = strdup(lpFileName)) == NULL) + { + ERROR("strdup() failed\n"); + dwLastError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + FILEDosToUnixPathA( unixFileName ); + if ( stat(unixFileName, &stat_data) != 0 ) + { + TRACE("stat failed on %s; errno is %d (%s)\n", + unixFileName, errno, strerror(errno)); + dwLastError = FILEGetLastErrorFromErrnoAndFilename(unixFileName); + goto done; + } + + new_mode = stat_data.st_mode; + TRACE("st_mode is %#x\n", new_mode); + + /* if we can't do GetFileAttributes on it, don't do SetFileAttributes */ + if ( !(new_mode & S_IFREG) && !(new_mode & S_IFDIR) ) + { + ERROR("Not a regular file or directory, S_IFMT is %#x\n", + new_mode & S_IFMT); + dwLastError = ERROR_ACCESS_DENIED; + goto done; + } + + /* set or unset the "read-only" attribute */ + if (dwFileAttributes & FILE_ATTRIBUTE_READONLY) + { + /* remove the write bit from everybody */ + new_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); + } + else + { + /* give write permission to the owner if the owner + * already has read permission */ + if ( new_mode & S_IRUSR ) + { + new_mode |= S_IWUSR; + } + } + TRACE("new mode is %#x\n", new_mode); + + bRet = TRUE; + if ( new_mode != stat_data.st_mode ) + { + if ( chmod(unixFileName, new_mode) != 0 ) + { + ERROR("chmod(%s, %#x) failed\n", unixFileName, new_mode); + dwLastError = FILEGetLastErrorFromErrnoAndFilename(unixFileName); + bRet = FALSE; + } + } + +done: + if (dwLastError) + { + pThread->SetLastError(dwLastError); + } + + free(unixFileName); + + LOGEXIT("SetFileAttributesA returns BOOL %d\n", bRet); + PERF_EXIT(SetFileAttributesA); + return bRet; +} + +/*++ +Function: + SetFileAttributesW + +Notes: + Used for setting read-only attribute on file only. + +--*/ +BOOL +PALAPI +SetFileAttributesW( + IN LPCWSTR lpFileName, + IN DWORD dwFileAttributes) +{ + CPalThread *pThread; + char * name; + PathCharString namePS; + int length = 0; + int size; + + DWORD dwLastError = 0; + BOOL bRet = FALSE; + + PERF_ENTRY(SetFileAttributesW); + ENTRY("SetFileAttributesW(lpFileName=%p (%S), dwFileAttributes=%#x)\n", + lpFileName?lpFileName:W16_NULLSTRING, + lpFileName?lpFileName:W16_NULLSTRING, dwFileAttributes); + + pThread = InternalGetCurrentThread(); + if (lpFileName == NULL) + { + dwLastError = ERROR_PATH_NOT_FOUND; + goto done; + } + + length = (PAL_wcslen(lpFileName)+1) * MaxWCharToAcpLengthFactor; + name = namePS.OpenStringBuffer(length); + if (NULL == name) + { + dwLastError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + size = WideCharToMultiByte( CP_ACP, 0, lpFileName, -1, name, length, + NULL, NULL ); + + if( size == 0 ) + { + namePS.CloseBuffer(0); + dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + dwLastError = ERROR_INVALID_PARAMETER; + goto done; + } + namePS.CloseBuffer(size - 1); + bRet = SetFileAttributesA(name,dwFileAttributes); + +done: + if (dwLastError) pThread->SetLastError(dwLastError); + + LOGEXIT("SetFileAttributes returns BOOL %d\n", bRet); + PERF_EXIT(SetFileAttributesW); + return bRet; +} + +PAL_ERROR +CorUnix::InternalWriteFile( + CPalThread *pThread, + HANDLE hFile, + LPCVOID lpBuffer, + DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, + LPOVERLAPPED lpOverlapped + ) +{ + PAL_ERROR palError = 0; + IPalObject *pFileObject = NULL; + CFileProcessLocalData *pLocalData = NULL; + IDataLock *pLocalDataLock = NULL; + int ifd; + + LONG writeOffsetStartLow = 0, writeOffsetStartHigh = 0; + int res; + + if (NULL != lpNumberOfBytesWritten) + { + // + // This must be set to 0 before any other error checking takes + // place, per MSDN + // + + *lpNumberOfBytesWritten = 0; + } + else + { + ASSERT( "lpNumberOfBytesWritten is NULL\n" ); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + + // Win32 WriteFile disallows writing to STD_INPUT_HANDLE + if (hFile == INVALID_HANDLE_VALUE || hFile == pStdIn) + { + palError = ERROR_INVALID_HANDLE; + goto done; + } + else if ( lpOverlapped ) + { + ASSERT( "lpOverlapped is not NULL, as it should be.\n" ); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hFile, + &aotFile, + &pFileObject + ); + + if (NO_ERROR != palError) + { + goto done; + } + + palError = pFileObject->GetProcessLocalData( + pThread, + ReadLock, + &pLocalDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + goto done; + } + + if (pLocalData->open_flags_deviceaccessonly == TRUE) + { + ERROR("File open for device access only\n"); + palError = ERROR_ACCESS_DENIED; + goto done; + } + + ifd = pLocalData->unix_fd; + + // + // Release the data lock before performing the (possibly blocking) + // write call + // + + pLocalDataLock->ReleaseLock(pThread, FALSE); + pLocalDataLock = NULL; + pLocalData = NULL; + +#if WRITE_0_BYTES_HANGS_TTY + if( nNumberOfBytesToWrite == 0 && isatty(ifd) ) + { + res = 0; + *lpNumberOfBytesWritten = 0; + goto done; + } +#endif + + res = write( ifd, lpBuffer, nNumberOfBytesToWrite ); + TRACE("write() returns %d\n", res); + + if ( res >= 0 ) + { + *lpNumberOfBytesWritten = res; + } + else + { + palError = FILEGetLastErrorFromErrno(); + } + +done: + + if (NULL != pLocalDataLock) + { + pLocalDataLock->ReleaseLock(pThread, FALSE); + } + + if (NULL != pFileObject) + { + pFileObject->ReleaseReference(pThread); + } + + return palError; +} + + +/*++ +Function: + WriteFileW + +Note: + lpOverlapped always NULL. + +See MSDN doc. +--*/ +BOOL +PALAPI +WriteFile( + IN HANDLE hFile, + IN LPCVOID lpBuffer, + IN DWORD nNumberOfBytesToWrite, + OUT LPDWORD lpNumberOfBytesWritten, + IN LPOVERLAPPED lpOverlapped) +{ + PAL_ERROR palError; + CPalThread *pThread; + + PERF_ENTRY(WriteFile); + ENTRY("WriteFile(hFile=%p, lpBuffer=%p, nToWrite=%u, lpWritten=%p, " + "lpOverlapped=%p)\n", hFile, lpBuffer, nNumberOfBytesToWrite, + lpNumberOfBytesWritten, lpOverlapped); + + pThread = InternalGetCurrentThread(); + + palError = InternalWriteFile( + pThread, + hFile, + lpBuffer, + nNumberOfBytesToWrite, + lpNumberOfBytesWritten, + lpOverlapped + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("WriteFile returns BOOL %d\n", NO_ERROR == palError); + PERF_EXIT(WriteFile); + return NO_ERROR == palError; +} + +PAL_ERROR +CorUnix::InternalReadFile( + CPalThread *pThread, + HANDLE hFile, + LPVOID lpBuffer, + DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, + LPOVERLAPPED lpOverlapped + ) +{ + PAL_ERROR palError = 0; + IPalObject *pFileObject = NULL; + CFileProcessLocalData *pLocalData = NULL; + IDataLock *pLocalDataLock = NULL; + int ifd; + + LONG readOffsetStartLow = 0, readOffsetStartHigh = 0; + int res; + + if (NULL != lpNumberOfBytesRead) + { + // + // This must be set to 0 before any other error checking takes + // place, per MSDN + // + + *lpNumberOfBytesRead = 0; + } + else + { + ERROR( "lpNumberOfBytesRead is NULL\n" ); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + + if (INVALID_HANDLE_VALUE == hFile) + { + ERROR( "Invalid file handle\n" ); + palError = ERROR_INVALID_HANDLE; + goto done; + } + else if (NULL != lpOverlapped) + { + ASSERT( "lpOverlapped is not NULL, as it should be.\n" ); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + else if (NULL == lpBuffer) + { + ERROR( "Invalid parameter. (lpBuffer:%p)\n", lpBuffer); + palError = ERROR_NOACCESS; + goto done; + } + + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hFile, + &aotFile, + &pFileObject + ); + + if (NO_ERROR != palError) + { + goto done; + } + + palError = pFileObject->GetProcessLocalData( + pThread, + ReadLock, + &pLocalDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + goto done; + } + + if (pLocalData->open_flags_deviceaccessonly == TRUE) + { + ERROR("File open for device access only\n"); + palError = ERROR_ACCESS_DENIED; + goto done; + } + + ifd = pLocalData->unix_fd; + + // + // Release the data lock before performing the (possibly blocking) + // read call + // + + pLocalDataLock->ReleaseLock(pThread, FALSE); + pLocalDataLock = NULL; + pLocalData = NULL; + +Read: + TRACE("Reading from file descriptor %d\n", ifd); + res = read(ifd, lpBuffer, nNumberOfBytesToRead); + TRACE("read() returns %d\n", res); + + if (res >= 0) + { + *lpNumberOfBytesRead = res; + } + else if (errno == EINTR) + { + // Try to read again. + goto Read; + } + else + { + palError = FILEGetLastErrorFromErrno(); + } + +done: + + if (NULL != pLocalDataLock) + { + pLocalDataLock->ReleaseLock(pThread, FALSE); + } + + if (NULL != pFileObject) + { + pFileObject->ReleaseReference(pThread); + } + + return palError; +} + +/*++ +Function: + ReadFile + +Note: + lpOverlapped always NULL. + +See MSDN doc. +--*/ +BOOL +PALAPI +ReadFile( + IN HANDLE hFile, + OUT LPVOID lpBuffer, + IN DWORD nNumberOfBytesToRead, + OUT LPDWORD lpNumberOfBytesRead, + IN LPOVERLAPPED lpOverlapped) +{ + PAL_ERROR palError; + CPalThread *pThread; + + PERF_ENTRY(ReadFile); + ENTRY("ReadFile(hFile=%p, lpBuffer=%p, nToRead=%u, " + "lpRead=%p, lpOverlapped=%p)\n", + hFile, lpBuffer, nNumberOfBytesToRead, + lpNumberOfBytesRead, lpOverlapped); + + pThread = InternalGetCurrentThread(); + + palError = InternalReadFile( + pThread, + hFile, + lpBuffer, + nNumberOfBytesToRead, + lpNumberOfBytesRead, + lpOverlapped + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("ReadFile returns BOOL %d\n", NO_ERROR == palError); + PERF_EXIT(ReadFile); + return NO_ERROR == palError; +} + + +/*++ +Function: + GetStdHandle + +See MSDN doc. +--*/ +HANDLE +PALAPI +GetStdHandle( + IN DWORD nStdHandle) +{ + CPalThread *pThread; + HANDLE hRet = INVALID_HANDLE_VALUE; + + PERF_ENTRY(GetStdHandle); + ENTRY("GetStdHandle(nStdHandle=%#x)\n", nStdHandle); + + pThread = InternalGetCurrentThread(); + switch( nStdHandle ) + { + case STD_INPUT_HANDLE: + hRet = pStdIn; + break; + case STD_OUTPUT_HANDLE: + hRet = pStdOut; + break; + case STD_ERROR_HANDLE: + hRet = pStdErr; + break; + default: + ERROR("nStdHandle is invalid\n"); + pThread->SetLastError(ERROR_INVALID_PARAMETER); + break; + } + + LOGEXIT("GetStdHandle returns HANDLE %p\n", hRet); + PERF_EXIT(GetStdHandle); + return hRet; +} + +PAL_ERROR +CorUnix::InternalSetEndOfFile( + CPalThread *pThread, + HANDLE hFile + ) +{ + PAL_ERROR palError = 0; + IPalObject *pFileObject = NULL; + CFileProcessLocalData *pLocalData = NULL; + IDataLock *pLocalDataLock = NULL; + + off_t curr = 0; + + if (INVALID_HANDLE_VALUE == hFile) + { + ERROR( "Invalid file handle\n" ); + palError = ERROR_INVALID_HANDLE; + goto InternalSetEndOfFileExit; + } + + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hFile, + &aotFile, + &pFileObject + ); + + if (NO_ERROR != palError) + { + goto InternalSetEndOfFileExit; + } + + palError = pFileObject->GetProcessLocalData( + pThread, + ReadLock, + &pLocalDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + goto InternalSetEndOfFileExit; + } + + if (pLocalData->open_flags_deviceaccessonly == TRUE) + { + ERROR("File open for device access only\n"); + palError = ERROR_ACCESS_DENIED; + goto InternalSetEndOfFileExit; + } + + curr = lseek(pLocalData->unix_fd, 0, SEEK_CUR); + + TRACE("current file pointer offset is %u\n", curr); + if ( curr < 0 ) + { + ERROR("lseek returned %ld\n", curr); + palError = FILEGetLastErrorFromErrno(); + goto InternalSetEndOfFileExit; + } + +#if SIZEOF_OFF_T > 4 +#if !HAVE_FTRUNCATE_LARGE_LENGTH_SUPPORT + // ftruncate will return the wrong value for some large lengths. + // We'll short-circuit the process and simply return failure for + // the set of values that covers those cases, all of which would + // have failed anyway on any standard-sized hard drive. + if (curr >= 0xFFFFFFFF000ULL) + { + ERROR("Skipping ftruncate because the offset is too large\n"); + palError = ERROR_INVALID_PARAMETER; + goto InternalSetEndOfFileExit; + } +#endif // !HAVE_FTRUNCATE_LARGE_LENGTH_SUPPORT +#endif // SIZEOF_OFF_T + +#if HAS_FTRUNCATE_LENGTH_ISSUE + // Perform an additional check to make sure that there's likely to be enough free space to satisfy the + // request. Do this because it's been observed on Mac OSX that ftruncate can return failure but still + // extend the file to consume the remainder of free space. + // + struct statfs sFileSystemStats; + off_t cbFreeSpace; + if (fstatfs(pLocalData->unix_fd, &sFileSystemStats) != 0) + { + ERROR("fstatfs failed\n"); + palError = FILEGetLastErrorFromErrno(); + goto InternalSetEndOfFileExit; + } + + // Free space is free blocks times the size of each block in bytes. + cbFreeSpace = (off_t)sFileSystemStats.f_bavail * (off_t)sFileSystemStats.f_bsize; + + if (curr > cbFreeSpace) + { + ERROR("Not enough disk space for ftruncate\n"); + palError = ERROR_DISK_FULL; + goto InternalSetEndOfFileExit; + } +#endif // HAS_FTRUNCATE_LENGTH_ISSUE + + if ( ftruncate(pLocalData->unix_fd, curr) != 0 ) + { + ERROR("ftruncate failed\n"); + if ( errno == EACCES ) + { + ERROR("file may not be writable\n"); + } + palError = FILEGetLastErrorFromErrno(); + goto InternalSetEndOfFileExit; + } + + +InternalSetEndOfFileExit: + + // Windows starts returning ERROR_INVALID_PARAMETER at an arbitrary file size (~16TB). The file system + // underneath us may be able to support larger and it would be a shame to prevent that. As a compromise, + // if the operation fails and the file size was above the Windows limit map ERROR_DISK_FULL to + // ERROR_INVALID_PARAMETER. + // curr has been checked to be positive after getting the value from lseek. The following cast is put to + // suppress the compilation warning. + if (palError == ERROR_DISK_FULL && (static_cast(curr) > 0x00000fffffff0000ULL ) ) + palError = ERROR_INVALID_PARAMETER; + + if (NULL != pLocalDataLock) + { + pLocalDataLock->ReleaseLock(pThread, FALSE); + } + + if (NULL != pFileObject) + { + pFileObject->ReleaseReference(pThread); + } + + return palError; +} + + + +/*++ +Function: + SetEndOfFile + +See MSDN doc. +--*/ +BOOL +PALAPI +SetEndOfFile( + IN HANDLE hFile) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pThread;; + + PERF_ENTRY(SetEndOfFile); + ENTRY("SetEndOfFile(hFile=%p)\n", hFile); + + pThread = InternalGetCurrentThread(); + + palError = InternalSetEndOfFile( + pThread, + hFile + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("SetEndOfFile returns BOOL %d\n", NO_ERROR == palError); + PERF_EXIT(SetEndOfFile); + return NO_ERROR == palError; +} + +// +// We need to break out the actual mechanics of setting the file pointer +// on the unix FD for InternalReadFile and InternalWriteFile, as they +// need to call this routine in order to determine the value of the +// current file pointer when computing the scope of their transaction +// lock. If we didn't break out this logic we'd end up referencing the file +// handle multiple times, and, in the process, would attempt to recursively +// obtain the local process data lock for the underlying file object. +// + +PAL_ERROR +InternalSetFilePointerForUnixFd( + int iUnixFd, + LONG lDistanceToMove, + PLONG lpDistanceToMoveHigh, + DWORD dwMoveMethod, + PLONG lpNewFilePointerLow + ) +{ + PAL_ERROR palError = NO_ERROR; + int seek_whence = 0; + __int64 seek_offset = 0LL; + __int64 seek_res = 0LL; + off_t old_offset; + + switch( dwMoveMethod ) + { + case FILE_BEGIN: + seek_whence = SEEK_SET; + break; + case FILE_CURRENT: + seek_whence = SEEK_CUR; + break; + case FILE_END: + seek_whence = SEEK_END; + break; + default: + ERROR("dwMoveMethod = %d is invalid\n", dwMoveMethod); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + + // + // According to MSDN, if lpDistanceToMoveHigh is not null, + // lDistanceToMove is treated as unsigned; + // it is treated as signed otherwise + // + + if ( lpDistanceToMoveHigh ) + { + /* set the high 32 bits of the offset */ + seek_offset = ((__int64)*lpDistanceToMoveHigh << 32); + + /* set the low 32 bits */ + /* cast to unsigned long to avoid sign extension */ + seek_offset |= (ULONG) lDistanceToMove; + } + else + { + seek_offset |= lDistanceToMove; + } + + /* store the current position, in case the lseek moves the pointer + before the beginning of the file */ + old_offset = lseek(iUnixFd, 0, SEEK_CUR); + if (old_offset == -1) + { + ERROR("lseek(fd,0,SEEK_CUR) failed errno:%d (%s)\n", + errno, strerror(errno)); + palError = ERROR_ACCESS_DENIED; + goto done; + } + + // Check to see if we're going to seek to a negative offset. + // If we're seeking from the beginning or the current mark, + // this is simple. + if ((seek_whence == SEEK_SET && seek_offset < 0) || + (seek_whence == SEEK_CUR && seek_offset + old_offset < 0)) + { + palError = ERROR_NEGATIVE_SEEK; + goto done; + } + else if (seek_whence == SEEK_END && seek_offset < 0) + { + // We need to determine if we're seeking past the + // beginning of the file, but we don't want to adjust + // the mark in the process. stat is the only way to + // do that. + struct stat fileData; + int result; + + result = fstat(iUnixFd, &fileData); + if (result == -1) + { + // It's a bad fd. This shouldn't happen because + // we've already called lseek on it, but you + // never know. This is the best we can do. + palError = ERROR_ACCESS_DENIED; + goto done; + } + if (fileData.st_size < -seek_offset) + { + // Seeking past the beginning. + palError = ERROR_NEGATIVE_SEEK; + goto done; + } + } + + seek_res = (__int64)lseek( iUnixFd, + seek_offset, + seek_whence ); + if ( seek_res < 0 ) + { + /* lseek() returns -1 on error, but also can seek to negative + file offsets, so -1 can also indicate a successful seek to offset + -1. Win32 doesn't allow negative file offsets, so either case + is an error. */ + ERROR("lseek failed errno:%d (%s)\n", errno, strerror(errno)); + lseek(iUnixFd, old_offset, SEEK_SET); + palError = ERROR_ACCESS_DENIED; + } + else + { + /* store high-order DWORD */ + if ( lpDistanceToMoveHigh ) + *lpDistanceToMoveHigh = (DWORD)(seek_res >> 32); + + /* return low-order DWORD of seek result */ + *lpNewFilePointerLow = (DWORD)seek_res; + } + +done: + + return palError; +} + +PAL_ERROR +CorUnix::InternalSetFilePointer( + CPalThread *pThread, + HANDLE hFile, + LONG lDistanceToMove, + PLONG lpDistanceToMoveHigh, + DWORD dwMoveMethod, + PLONG lpNewFilePointerLow + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pFileObject = NULL; + CFileProcessLocalData *pLocalData = NULL; + IDataLock *pLocalDataLock = NULL; + + if (INVALID_HANDLE_VALUE == hFile) + { + ERROR( "Invalid file handle\n" ); + palError = ERROR_INVALID_HANDLE; + goto InternalSetFilePointerExit; + } + + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hFile, + &aotFile, + &pFileObject + ); + + if (NO_ERROR != palError) + { + goto InternalSetFilePointerExit; + } + + palError = pFileObject->GetProcessLocalData( + pThread, + ReadLock, + &pLocalDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + goto InternalSetFilePointerExit; + } + + palError = InternalSetFilePointerForUnixFd( + pLocalData->unix_fd, + lDistanceToMove, + lpDistanceToMoveHigh, + dwMoveMethod, + lpNewFilePointerLow + ); + +InternalSetFilePointerExit: + + if (NULL != pLocalDataLock) + { + pLocalDataLock->ReleaseLock(pThread, FALSE); + } + + if (NULL != pFileObject) + { + pFileObject->ReleaseReference(pThread); + } + + return palError; +} + +/*++ +Function: + SetFilePointer + +See MSDN doc. +--*/ +DWORD +PALAPI +SetFilePointer( + IN HANDLE hFile, + IN LONG lDistanceToMove, + IN PLONG lpDistanceToMoveHigh, + IN DWORD dwMoveMethod) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pThread; + LONG lNewFilePointerLow = 0; + + PERF_ENTRY(SetFilePointer); + ENTRY("SetFilePointer(hFile=%p, lDistance=%d, lpDistanceHigh=%p, " + "dwMoveMethod=%#x)\n", hFile, lDistanceToMove, + lpDistanceToMoveHigh, dwMoveMethod); + + pThread = InternalGetCurrentThread(); + + palError = InternalSetFilePointer( + pThread, + hFile, + lDistanceToMove, + lpDistanceToMoveHigh, + dwMoveMethod, + &lNewFilePointerLow + ); + + if (NO_ERROR != palError) + { + lNewFilePointerLow = INVALID_SET_FILE_POINTER; + } + + /* This function must always call SetLastError - even if successful. + If we seek to a value greater than 2^32 - 1, we will effectively be + returning a negative value from this function. Now, let's say that + returned value is -1. Furthermore, assume that win32error has been + set before even entering this function. Then, when this function + returns to SetFilePointer in win32native.cs, it will have returned + -1 and win32error will have been set, which will cause an error to be + returned. Since -1 may not be an error in this case and since we + can't assume that the win32error is related to SetFilePointer, + we need to always call SetLastError here. That way, if this function + succeeds, SetFilePointer in win32native won't mistakenly determine + that it failed. */ + pThread->SetLastError(palError); + + LOGEXIT("SetFilePointer returns DWORD %#x\n", lNewFilePointerLow); + PERF_EXIT(SetFilePointer); + return lNewFilePointerLow; +} + +/*++ +Function: + SetFilePointerEx + +See MSDN doc. +--*/ +BOOL +PALAPI +SetFilePointerEx( + IN HANDLE hFile, + IN LARGE_INTEGER liDistanceToMove, + OUT PLARGE_INTEGER lpNewFilePointer, + IN DWORD dwMoveMethod) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pThread; + BOOL Ret = FALSE; + + PERF_ENTRY(SetFilePointerEx); + ENTRY("SetFilePointerEx(hFile=%p, liDistanceToMove=0x%llx, " + "lpNewFilePointer=%p (0x%llx), dwMoveMethod=0x%x)\n", hFile, + liDistanceToMove.QuadPart, lpNewFilePointer, + (lpNewFilePointer) ? (*lpNewFilePointer).QuadPart : 0, dwMoveMethod); + + LONG lDistanceToMove; + lDistanceToMove = (LONG)liDistanceToMove.u.LowPart; + LONG lDistanceToMoveHigh; + lDistanceToMoveHigh = liDistanceToMove.u.HighPart; + + LONG lNewFilePointerLow = 0; + + pThread = InternalGetCurrentThread(); + + palError = InternalSetFilePointer( + pThread, + hFile, + lDistanceToMove, + &lDistanceToMoveHigh, + dwMoveMethod, + &lNewFilePointerLow + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + else + { + if (lpNewFilePointer != NULL) + { + lpNewFilePointer->u.LowPart = (DWORD)lNewFilePointerLow; + lpNewFilePointer->u.HighPart = (DWORD)lDistanceToMoveHigh; + } + Ret = TRUE; + } + + LOGEXIT("SetFilePointerEx returns BOOL %d\n", Ret); + PERF_EXIT(SetFilePointerEx); + return Ret; +} + +PAL_ERROR +CorUnix::InternalGetFileSize( + CPalThread *pThread, + HANDLE hFile, + DWORD *pdwFileSizeLow, + DWORD *pdwFileSizeHigh + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pFileObject = NULL; + CFileProcessLocalData *pLocalData = NULL; + IDataLock *pLocalDataLock = NULL; + + struct stat stat_data; + + if (INVALID_HANDLE_VALUE == hFile) + { + ERROR( "Invalid file handle\n" ); + palError = ERROR_INVALID_HANDLE; + goto InternalGetFileSizeExit; + } + + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hFile, + &aotFile, + &pFileObject + ); + + if (NO_ERROR != palError) + { + goto InternalGetFileSizeExit; + } + + palError = pFileObject->GetProcessLocalData( + pThread, + ReadLock, + &pLocalDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + goto InternalGetFileSizeExit; + } + + if (fstat(pLocalData->unix_fd, &stat_data) != 0) + { + ERROR("fstat failed of file descriptor %d\n", pLocalData->unix_fd); + palError = FILEGetLastErrorFromErrno(); + goto InternalGetFileSizeExit; + } + + *pdwFileSizeLow = (DWORD)stat_data.st_size; + + if (NULL != pdwFileSizeHigh) + { +#if SIZEOF_OFF_T > 4 + *pdwFileSizeHigh = (DWORD)(stat_data.st_size >> 32); +#else + *pdwFileSizeHigh = 0; +#endif + } + +InternalGetFileSizeExit: + + if (NULL != pLocalDataLock) + { + pLocalDataLock->ReleaseLock(pThread, FALSE); + } + + if (NULL != pFileObject) + { + pFileObject->ReleaseReference(pThread); + } + + return palError; +} + +/*++ +Function: + GetFileSize + +See MSDN doc. +--*/ +DWORD +PALAPI +GetFileSize( + IN HANDLE hFile, + OUT LPDWORD lpFileSizeHigh) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pThread; + DWORD dwFileSizeLow; + + PERF_ENTRY(GetFileSize); + ENTRY("GetFileSize(hFile=%p, lpFileSizeHigh=%p)\n", hFile, lpFileSizeHigh); + + pThread = InternalGetCurrentThread(); + + palError = InternalGetFileSize( + pThread, + hFile, + &dwFileSizeLow, + lpFileSizeHigh + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + dwFileSizeLow = INVALID_FILE_SIZE; + } + + LOGEXIT("GetFileSize returns DWORD %u\n", dwFileSizeLow); + PERF_EXIT(GetFileSize); + return dwFileSizeLow; +} + +/*++ +Function: +GetFileSizeEx + +See MSDN doc. +--*/ +BOOL +PALAPI GetFileSizeEx( +IN HANDLE hFile, +OUT PLARGE_INTEGER lpFileSize) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pThread; + DWORD dwFileSizeHigh; + DWORD dwFileSizeLow; + + PERF_ENTRY(GetFileSizeEx); + ENTRY("GetFileSizeEx(hFile=%p, lpFileSize=%p)\n", hFile, lpFileSize); + + pThread = InternalGetCurrentThread(); + + if (lpFileSize != NULL) + { + palError = InternalGetFileSize( + pThread, + hFile, + &dwFileSizeLow, + &dwFileSizeHigh + ); + + if (NO_ERROR == palError) + { + lpFileSize->u.LowPart = dwFileSizeLow; + lpFileSize->u.HighPart = dwFileSizeHigh; + } + } + else + { + palError = ERROR_INVALID_PARAMETER; + } + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("GetFileSizeEx returns BOOL %d\n", NO_ERROR == palError); + PERF_EXIT(GetFileSizeEx); + return NO_ERROR == palError; +} + +PAL_ERROR +CorUnix::InternalFlushFileBuffers( + CPalThread *pThread, + HANDLE hFile + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pFileObject = NULL; + CFileProcessLocalData *pLocalData = NULL; + IDataLock *pLocalDataLock = NULL; + + if (INVALID_HANDLE_VALUE == hFile) + { + ERROR( "Invalid file handle\n" ); + palError = ERROR_INVALID_HANDLE; + goto InternalFlushFileBuffersExit; + } + + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hFile, + &aotFile, + &pFileObject + ); + + if (NO_ERROR != palError) + { + goto InternalFlushFileBuffersExit; + } + + palError = pFileObject->GetProcessLocalData( + pThread, + ReadLock, + &pLocalDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + goto InternalFlushFileBuffersExit; + } + + if (pLocalData->open_flags_deviceaccessonly == TRUE) + { + ERROR("File open for device access only\n"); + palError = ERROR_ACCESS_DENIED; + goto InternalFlushFileBuffersExit; + } + +#if HAVE_FSYNC || defined(__APPLE__) + do + { + +#if defined(__APPLE__) + if (fcntl(pLocalData->unix_fd, F_FULLFSYNC) != -1) + break; +#else // __APPLE__ + if (fsync(pLocalData->unix_fd) == 0) + break; +#endif // __APPLE__ + + switch (errno) + { + case EINTR: + // Execution was interrupted by a signal, so restart. + TRACE("fsync(%d) was interrupted. Restarting\n", pLocalData->unix_fd); + break; + + default: + palError = FILEGetLastErrorFromErrno(); + WARN("fsync(%d) failed with error %d\n", pLocalData->unix_fd, errno); + break; + } + } while (NO_ERROR == palError); +#else // HAVE_FSYNC + /* flush all buffers out to disk - there is no way to flush + an individual file descriptor's buffers out. */ + sync(); +#endif // HAVE_FSYNC else + + +InternalFlushFileBuffersExit: + + if (NULL != pLocalDataLock) + { + pLocalDataLock->ReleaseLock(pThread, FALSE); + } + + if (NULL != pFileObject) + { + pFileObject->ReleaseReference(pThread); + } + + return palError; +} + + +/*++ +Function: + FlushFileBuffers + +See MSDN doc. +--*/ +BOOL +PALAPI +FlushFileBuffers( + IN HANDLE hFile) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pThread; + + PERF_ENTRY(FlushFileBuffers); + ENTRY("FlushFileBuffers(hFile=%p)\n", hFile); + + pThread = InternalGetCurrentThread(); + + palError = InternalFlushFileBuffers( + pThread, + hFile + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("FlushFileBuffers returns BOOL %d\n", NO_ERROR == palError); + PERF_EXIT(FlushFileBuffers); + return NO_ERROR == palError; +} + +#define ENSURE_UNIQUE_NOT_ZERO \ + if ( uUniqueSeed == 0 ) \ + {\ + uUniqueSeed++;\ + } + +/*++ + Function: + GetTempFileNameA + +uUnique is always 0. + --*/ +const int MAX_PREFIX = 3; +const int MAX_SEEDSIZE = 8; /* length of "unique portion of + the string, plus extension(FFFF.TMP). */ +static USHORT uUniqueSeed = 0; +static BOOL IsInitialized = FALSE; + +UINT +PALAPI +GetTempFileNameA( + IN LPCSTR lpPathName, + IN LPCSTR lpPrefixString, + IN UINT uUnique, + OUT LPSTR lpTempFileName) +{ + CPalThread *pThread; + CHAR * full_name; + PathCharString full_namePS; + int length; + CHAR * file_template; + PathCharString file_templatePS; + CHAR chLastPathNameChar; + + HANDLE hTempFile; + UINT uRet = 0; + DWORD dwError; + USHORT uLoopCounter = 0; + + PERF_ENTRY(GetTempFileNameA); + ENTRY("GetTempFileNameA(lpPathName=%p (%s), lpPrefixString=%p (%s), uUnique=%u, " + "lpTempFileName=%p)\n", lpPathName?lpPathName:"NULL", lpPathName?lpPathName:"NULL", + lpPrefixString?lpPrefixString:"NULL", + lpPrefixString?lpPrefixString:"NULL", uUnique, + lpTempFileName?lpTempFileName:"NULL"); + + pThread = InternalGetCurrentThread(); + if ( !IsInitialized ) + { + uUniqueSeed = (USHORT)( time( NULL ) ); + + /* On the off chance 0 is returned. + 0 being the error return code. */ + ENSURE_UNIQUE_NOT_ZERO + IsInitialized = TRUE; + } + + if ( !lpPathName || *lpPathName == '\0' ) + { + pThread->SetLastError( ERROR_DIRECTORY ); + goto done; + } + + if ( NULL == lpTempFileName ) + { + ERROR( "lpTempFileName cannot be NULL\n" ); + pThread->SetLastError( ERROR_INVALID_PARAMETER ); + goto done; + } + + if ( strlen( lpPathName ) + MAX_SEEDSIZE + MAX_PREFIX >= MAX_LONGPATH ) + { + WARN( "File names larger than MAX_LONGPATH (%d)!\n", MAX_LONGPATH ); + pThread->SetLastError( ERROR_FILENAME_EXCED_RANGE ); + goto done; + } + + length = strlen(lpPathName) + MAX_SEEDSIZE + MAX_PREFIX + 10; + file_template = file_templatePS.OpenStringBuffer(length); + if (NULL == file_template) + { + pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + *file_template = '\0'; + strcat_s( file_template, file_templatePS.GetSizeOf(), lpPathName ); + file_templatePS.CloseBuffer(length); + + chLastPathNameChar = file_template[strlen(file_template)-1]; + if (chLastPathNameChar != '\\' && chLastPathNameChar != '/') + { + strcat_s( file_template, file_templatePS.GetSizeOf(), "\\" ); + } + + if ( lpPrefixString ) + { + strncat_s( file_template, file_templatePS.GetSizeOf(), lpPrefixString, MAX_PREFIX ); + } + FILEDosToUnixPathA( file_template ); + strncat_s( file_template, file_templatePS.GetSizeOf(), "%.4x.TMP", MAX_SEEDSIZE ); + + /* Create the file. */ + dwError = GetLastError(); + pThread->SetLastError( NOERROR ); + + length = strlen(file_template) + MAX_SEEDSIZE + MAX_PREFIX; + full_name = full_namePS.OpenStringBuffer(length); + if (NULL == full_name) + { + pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + sprintf_s( full_name, full_namePS.GetSizeOf(), file_template, (0 == uUnique) ? uUniqueSeed : uUnique); + full_namePS.CloseBuffer(length); + + hTempFile = CreateFileA( full_name, GENERIC_WRITE, + FILE_SHARE_READ, NULL, CREATE_NEW, 0, NULL ); + + if (uUnique == 0) + { + /* The USHORT will overflow back to 0 if we go past + 65536 files, so break the loop after 65536 iterations. + If the CreateFile call was not successful within that + number of iterations, then there are no temp file names + left for that directory. */ + while ( ERROR_PATH_NOT_FOUND != GetLastError() && + INVALID_HANDLE_VALUE == hTempFile && uLoopCounter < 0xFFFF ) + { + uUniqueSeed++; + ENSURE_UNIQUE_NOT_ZERO; + + pThread->SetLastError( NOERROR ); + sprintf_s( full_name, full_namePS.GetSizeOf(), file_template, uUniqueSeed ); + hTempFile = CreateFileA( full_name, GENERIC_WRITE, + FILE_SHARE_READ, NULL, CREATE_NEW, 0, NULL ); + uLoopCounter++; + + } + } + + /* Reset the error code.*/ + if ( NOERROR == GetLastError() ) + { + pThread->SetLastError( dwError ); + } + + /* Windows sets ERROR_FILE_EXISTS,if there + are no available temp files. */ + if ( INVALID_HANDLE_VALUE != hTempFile ) + { + if (0 == uUnique) + { + uRet = uUniqueSeed; + uUniqueSeed++; + ENSURE_UNIQUE_NOT_ZERO; + } + else + { + uRet = uUnique; + } + + if ( CloseHandle( hTempFile ) ) + { + if (strcpy_s( lpTempFileName, MAX_LONGPATH, full_name ) != SAFECRT_SUCCESS) + { + ERROR( "strcpy_s failed!\n"); + pThread->SetLastError( ERROR_FILENAME_EXCED_RANGE ); + *lpTempFileName = '\0'; + uRet = 0; + } + } + else + { + ASSERT( "Unable to close the handle %p\n", hTempFile ); + pThread->SetLastError( ERROR_INTERNAL_ERROR ); + *lpTempFileName = '\0'; + uRet = 0; + } + } + else if ( INVALID_HANDLE_VALUE == hTempFile && uLoopCounter < 0xFFFF ) + { + ERROR( "Unable to create temp file. \n" ); + uRet = 0; + + if ( ERROR_PATH_NOT_FOUND == GetLastError() ) + { + /* CreateFile failed because it could not + find the path. */ + pThread->SetLastError( ERROR_DIRECTORY ); + } /* else use the lasterror value from CreateFileA */ + } + else + { + TRACE( "65535 files already exist in the directory. " + "No temp files available for creation.\n" ); + pThread->SetLastError( ERROR_FILE_EXISTS ); + } + +done: + LOGEXIT("GetTempFileNameA returns UINT %u\n", uRet); + PERF_EXIT(GetTempFileNameA); + return uRet; + +} + +/*++ +Function: + GetTempFileNameW + +uUnique is always 0. +--*/ +UINT +PALAPI +GetTempFileNameW( + IN LPCWSTR lpPathName, + IN LPCWSTR lpPrefixString, + IN UINT uUnique, + OUT LPWSTR lpTempFileName) +{ + CPalThread *pThread; + INT path_size = 0; + INT prefix_size = 0; + CHAR * full_name; + CHAR * prefix_string; + CHAR * tempfile_name; + PathCharString full_namePS, prefix_stringPS; + INT length = 0; + UINT uRet; + + PERF_ENTRY(GetTempFileNameW); + ENTRY("GetTempFileNameW(lpPathName=%p (%S), lpPrefixString=%p (%S), uUnique=%u, " + "lpTempFileName=%p)\n", lpPathName?lpPathName:W16_NULLSTRING, lpPathName?lpPathName:W16_NULLSTRING, + lpPrefixString?lpPrefixString:W16_NULLSTRING, + lpPrefixString?lpPrefixString:W16_NULLSTRING,uUnique, lpTempFileName); + + pThread = InternalGetCurrentThread(); + /* Sanity checks. */ + if ( !lpPathName || *lpPathName == '\0' ) + { + pThread->SetLastError( ERROR_DIRECTORY ); + uRet = 0; + goto done; + } + + length = (PAL_wcslen(lpPathName)+1) * MaxWCharToAcpLengthFactor; + full_name = full_namePS.OpenStringBuffer(length); + if (NULL == full_name) + { + pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + uRet = 0; + goto done; + } + path_size = WideCharToMultiByte( CP_ACP, 0, lpPathName, -1, full_name, + length, NULL, NULL ); + + if( path_size == 0 ) + { + full_namePS.CloseBuffer(0); + DWORD dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + pThread->SetLastError(ERROR_INTERNAL_ERROR); + uRet = 0; + goto done; + } + + full_namePS.CloseBuffer(path_size - 1); + + if (lpPrefixString != NULL) + { + length = (PAL_wcslen(lpPrefixString)+1) * MaxWCharToAcpLengthFactor; + prefix_string = prefix_stringPS.OpenStringBuffer(length); + if (NULL == prefix_string) + { + pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + uRet = 0; + goto done; + } + prefix_size = WideCharToMultiByte( CP_ACP, 0, lpPrefixString, -1, + prefix_string, + MAX_LONGPATH - path_size - MAX_SEEDSIZE, + NULL, NULL ); + + if( prefix_size == 0 ) + { + prefix_stringPS.CloseBuffer(0); + DWORD dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + pThread->SetLastError(ERROR_INTERNAL_ERROR); + uRet = 0; + goto done; + } + prefix_stringPS.CloseBuffer(prefix_size - 1); + } + + tempfile_name = (char*)InternalMalloc(MAX_LONGPATH); + if (tempfile_name == NULL) + { + pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + uRet = 0; + goto done; + } + + uRet = GetTempFileNameA(full_name, + (lpPrefixString == NULL) ? NULL : prefix_string, + 0, tempfile_name); + if (uRet) + { + path_size = MultiByteToWideChar( CP_ACP, 0, tempfile_name, -1, + lpTempFileName, MAX_LONGPATH ); + + free(tempfile_name); + tempfile_name = NULL; + if (!path_size) + { + DWORD dwLastError = GetLastError(); + if (dwLastError == ERROR_INSUFFICIENT_BUFFER) + { + WARN("File names larger than MAX_PATH_FNAME (%d)! \n", MAX_LONGPATH); + dwLastError = ERROR_FILENAME_EXCED_RANGE; + } + else + { + ASSERT("MultiByteToWideChar failure! error is %d", dwLastError); + dwLastError = ERROR_INTERNAL_ERROR; + } + pThread->SetLastError(dwLastError); + uRet = 0; + } + } + +done: + LOGEXIT("GetTempFileNameW returns UINT %u\n", uRet); + PERF_EXIT(GetTempFileNameW); + return uRet; +} + +/*++ +Function: + FILEGetLastErrorFromErrno + +Convert errno into the appropriate win32 error and return it. +--*/ +DWORD FILEGetLastErrorFromErrno( void ) +{ + DWORD dwRet; + + switch(errno) + { + case 0: + dwRet = ERROR_SUCCESS; + break; + case ENAMETOOLONG: + dwRet = ERROR_FILENAME_EXCED_RANGE; + break; + case ENOTDIR: + dwRet = ERROR_PATH_NOT_FOUND; + break; + case ENOENT: + dwRet = ERROR_FILE_NOT_FOUND; + break; + case EACCES: + case EPERM: + case EROFS: + case EISDIR: + dwRet = ERROR_ACCESS_DENIED; + break; + case EEXIST: + dwRet = ERROR_ALREADY_EXISTS; + break; + case ENOTEMPTY: + dwRet = ERROR_DIR_NOT_EMPTY; + break; + case EBADF: + dwRet = ERROR_INVALID_HANDLE; + break; + case ENOMEM: + dwRet = ERROR_NOT_ENOUGH_MEMORY; + break; + case EBUSY: + dwRet = ERROR_BUSY; + break; + case ENOSPC: + case EDQUOT: + dwRet = ERROR_DISK_FULL; + break; + case ELOOP: + dwRet = ERROR_BAD_PATHNAME; + break; + case EIO: + dwRet = ERROR_WRITE_FAULT; + break; + case EMFILE: + dwRet = ERROR_TOO_MANY_OPEN_FILES; + break; + case ERANGE: + dwRet = ERROR_BAD_PATHNAME; + break; + default: + ERROR("unexpected errno %d (%s); returning ERROR_GEN_FAILURE\n", + errno, strerror(errno)); + dwRet = ERROR_GEN_FAILURE; + } + + TRACE("errno = %d (%s), LastError = %d\n", errno, strerror(errno), dwRet); + + return dwRet; +} + +/*++ +Function: + DIRGetLastErrorFromErrno + +Convert errno into the appropriate win32 error and return it. +--*/ +DWORD DIRGetLastErrorFromErrno( void ) +{ + if (errno == ENOENT) + return ERROR_PATH_NOT_FOUND; + else + return FILEGetLastErrorFromErrno(); +} + + +/*++ +Function: + CopyFileA + +See MSDN doc. + +Notes: + There are several (most) error paths here that do not call SetLastError(). +This is because we know that CreateFile, ReadFile, and WriteFile will do so, +and will have a much better idea of the specific error. +--*/ +BOOL +PALAPI +CopyFileA( + IN LPCSTR lpExistingFileName, + IN LPCSTR lpNewFileName, + IN BOOL bFailIfExists) +{ + CPalThread *pThread; + HANDLE hSource = INVALID_HANDLE_VALUE; + HANDLE hDest = INVALID_HANDLE_VALUE; + DWORD dwDestCreationMode; + BOOL bGood = FALSE; + DWORD dwSrcFileAttributes; + struct stat SrcFileStats; + + LPSTR lpUnixPath = NULL; + const int buffer_size = 16*1024; + char *buffer = (char*)alloca(buffer_size); + DWORD bytes_read; + DWORD bytes_written; + int permissions; + + + PERF_ENTRY(CopyFileA); + ENTRY("CopyFileA(lpExistingFileName=%p (%s), lpNewFileName=%p (%s), bFailIfExists=%d)\n", + lpExistingFileName?lpExistingFileName:"NULL", + lpExistingFileName?lpExistingFileName:"NULL", + lpNewFileName?lpNewFileName:"NULL", + lpNewFileName?lpNewFileName:"NULL", bFailIfExists); + + pThread = InternalGetCurrentThread(); + if ( bFailIfExists ) + { + dwDestCreationMode = CREATE_NEW; + } + else + { + dwDestCreationMode = CREATE_ALWAYS; + } + + hSource = CreateFileA( lpExistingFileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + 0, + NULL ); + + if ( hSource == INVALID_HANDLE_VALUE ) + { + ERROR("CreateFileA failed for %s\n", lpExistingFileName); + goto done; + } + + /* Need to preserve the file attributes */ + dwSrcFileAttributes = GetFileAttributes(lpExistingFileName); + if (dwSrcFileAttributes == 0xffffffff) + { + ERROR("GetFileAttributes failed for %s\n", lpExistingFileName); + goto done; + } + + /* Need to preserve the owner/group and chmod() flags */ + lpUnixPath = strdup(lpExistingFileName); + if ( lpUnixPath == NULL ) + { + ERROR("strdup() failed\n"); + pThread->SetLastError(FILEGetLastErrorFromErrno()); + goto done; + } + FILEDosToUnixPathA(lpUnixPath); + if (stat (lpUnixPath, &SrcFileStats) == -1) + { + ERROR("stat() failed for %s\n", lpExistingFileName); + pThread->SetLastError(FILEGetLastErrorFromErrnoAndFilename(lpUnixPath)); + goto done; + } + + hDest = CreateFileA( lpNewFileName, + GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + dwDestCreationMode, + 0, + NULL ); + + if ( hDest == INVALID_HANDLE_VALUE ) + { + ERROR("CreateFileA failed for %s\n", lpNewFileName); + goto done; + } + + free(lpUnixPath); + lpUnixPath = strdup(lpNewFileName); + if ( lpUnixPath == NULL ) + { + ERROR("strdup() failed\n"); + pThread->SetLastError(FILEGetLastErrorFromErrno()); + goto done; + } + FILEDosToUnixPathA( lpUnixPath ); + + + // We don't set file attributes in CreateFile. The only attribute + // that is reflected on disk in Unix is read-only, and we set that + // here. + permissions = (S_IRWXU | S_IRWXG | S_IRWXO); + if ((dwSrcFileAttributes & FILE_ATTRIBUTE_READONLY) != 0) + { + permissions &= ~(S_IWUSR | S_IWGRP | S_IWOTH); + } + + /* Make sure the new file has the same chmod() flags. */ + if (chmod(lpUnixPath, SrcFileStats.st_mode & permissions) == -1) + { + WARN ("chmod() failed to set mode 0x%x on new file\n", + SrcFileStats.st_mode & permissions); + pThread->SetLastError(FILEGetLastErrorFromErrnoAndFilename(lpUnixPath)); + goto done; + } + + while( (bGood = ReadFile( hSource, buffer, buffer_size, &bytes_read, NULL )) + && bytes_read > 0 ) + { + bGood = ( WriteFile( hDest, buffer, bytes_read, &bytes_written, NULL ) + && bytes_written == bytes_read); + if (!bGood) break; + } + + if (!bGood) + { + ERROR("Copy failed\n"); + + if ( !CloseHandle(hDest) || + !DeleteFileA(lpNewFileName) ) + { + ERROR("Unable to clean up partial copy\n"); + } + hDest = INVALID_HANDLE_VALUE; + + goto done; + } + +done: + + if ( hSource != INVALID_HANDLE_VALUE ) + { + CloseHandle( hSource ); + } + if ( hDest != INVALID_HANDLE_VALUE ) + { + CloseHandle( hDest ); + } + if (lpUnixPath) + { + free(lpUnixPath); + } + + LOGEXIT("CopyFileA returns BOOL %d\n", bGood); + PERF_EXIT(CopyFileA); + return bGood; +} + + +PAL_ERROR +CorUnix::InternalCreatePipe( + CPalThread *pThread, + HANDLE *phReadPipe, + HANDLE *phWritePipe, + LPSECURITY_ATTRIBUTES lpPipeAttributes, + DWORD nSize + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pReadFileObject = NULL; + IPalObject *pReadRegisteredFile = NULL; + IPalObject *pWriteFileObject = NULL; + IPalObject *pWriteRegisteredFile = NULL; + IDataLock *pDataLock = NULL; + CFileProcessLocalData *pLocalData = NULL; + CObjectAttributes oaFile(NULL, lpPipeAttributes); + + int readWritePipeDes[2] = {-1, -1}; + + if ((phReadPipe == NULL) || (phWritePipe == NULL)) + { + ERROR("One of the two parameters hReadPipe(%p) and hWritePipe(%p) is Null\n",phReadPipe,phWritePipe); + palError = ERROR_INVALID_PARAMETER; + goto InternalCreatePipeExit; + } + + if ((lpPipeAttributes == NULL) || + (lpPipeAttributes->bInheritHandle == FALSE) || + (lpPipeAttributes->lpSecurityDescriptor != NULL)) + { + ASSERT("invalid security attributes!\n"); + palError = ERROR_INVALID_PARAMETER; + goto InternalCreatePipeExit; + } + + if (pipe(readWritePipeDes) == -1) + { + ERROR("pipe() call failed errno:%d (%s) \n", errno, strerror(errno)); + palError = ERROR_INTERNAL_ERROR; + goto InternalCreatePipeExit; + } + + /* enable close-on-exec for both pipes; if one gets passed to CreateProcess + it will be "uncloseonexeced" in order to be inherited */ + if(-1 == fcntl(readWritePipeDes[0],F_SETFD,FD_CLOEXEC)) + { + ASSERT("can't set close-on-exec flag; fcntl() failed. errno is %d " + "(%s)\n", errno, strerror(errno)); + palError = ERROR_INTERNAL_ERROR; + goto InternalCreatePipeExit; + } + if(-1 == fcntl(readWritePipeDes[1],F_SETFD,FD_CLOEXEC)) + { + ASSERT("can't set close-on-exec flag; fcntl() failed. errno is %d " + "(%s)\n", errno, strerror(errno)); + palError = ERROR_INTERNAL_ERROR; + goto InternalCreatePipeExit; + } + + // + // Setup the object for the read end of the pipe + // + + palError = g_pObjectManager->AllocateObject( + pThread, + &otFile, + &oaFile, + &pReadFileObject + ); + + if (NO_ERROR != palError) + { + goto InternalCreatePipeExit; + } + + palError = pReadFileObject->GetProcessLocalData( + pThread, + WriteLock, + &pDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + goto InternalCreatePipeExit; + } + + pLocalData->inheritable = TRUE; + pLocalData->open_flags = O_RDONLY; + + // + // After storing the file descriptor in the object's local data + // we want to clear it from the array to prevent a possible double + // close if an error occurs. + // + + pLocalData->unix_fd = readWritePipeDes[0]; + readWritePipeDes[0] = -1; + + pDataLock->ReleaseLock(pThread, TRUE); + pDataLock = NULL; + + // + // Setup the object for the write end of the pipe + // + + palError = g_pObjectManager->AllocateObject( + pThread, + &otFile, + &oaFile, + &pWriteFileObject + ); + + if (NO_ERROR != palError) + { + goto InternalCreatePipeExit; + } + + palError = pWriteFileObject->GetProcessLocalData( + pThread, + WriteLock, + &pDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + goto InternalCreatePipeExit; + } + + pLocalData->inheritable = TRUE; + pLocalData->open_flags = O_WRONLY; + + // + // After storing the file descriptor in the object's local data + // we want to clear it from the array to prevent a possible double + // close if an error occurs. + // + + pLocalData->unix_fd = readWritePipeDes[1]; + readWritePipeDes[1] = -1; + + pDataLock->ReleaseLock(pThread, TRUE); + pDataLock = NULL; + + // + // Register the pipe objects + // + + palError = g_pObjectManager->RegisterObject( + pThread, + pReadFileObject, + &aotFile, + phReadPipe, + &pReadRegisteredFile + ); + + // + // pReadFileObject is invalidated by the call to RegisterObject, so NULL it + // out here to ensure that we don't try to release a reference on + // it down the line. + // + + pReadFileObject = NULL; + + if (NO_ERROR != palError) + { + goto InternalCreatePipeExit; + } + + palError = g_pObjectManager->RegisterObject( + pThread, + pWriteFileObject, + &aotFile, + phWritePipe, + &pWriteRegisteredFile + ); + + // + // pWriteFileObject is invalidated by the call to RegisterObject, so NULL it + // out here to ensure that we don't try to release a reference on + // it down the line. + // + + pWriteFileObject = NULL; + +InternalCreatePipeExit: + + if (NO_ERROR != palError) + { + if (-1 != readWritePipeDes[0]) + { + close(readWritePipeDes[0]); + } + + if (-1 != readWritePipeDes[1]) + { + close(readWritePipeDes[1]); + } + } + + if (NULL != pReadFileObject) + { + pReadFileObject->ReleaseReference(pThread); + } + + if (NULL != pReadRegisteredFile) + { + pReadRegisteredFile->ReleaseReference(pThread); + } + + if (NULL != pWriteFileObject) + { + pWriteFileObject->ReleaseReference(pThread); + } + + if (NULL != pWriteRegisteredFile) + { + pWriteRegisteredFile->ReleaseReference(pThread); + } + + return palError; +} + +/*++ +Function: + CreatePipe + +See MSDN doc. +--*/ +PALIMPORT +BOOL +PALAPI +CreatePipe( + OUT PHANDLE hReadPipe, + OUT PHANDLE hWritePipe, + IN LPSECURITY_ATTRIBUTES lpPipeAttributes, + IN DWORD nSize) +{ + PAL_ERROR palError; + CPalThread *pThread; + + PERF_ENTRY(CreatePipe); + ENTRY("CreatePipe(hReadPipe:%p, hWritePipe:%p, lpPipeAttributes:%p, nSize:%d\n", + hReadPipe, hWritePipe, lpPipeAttributes, nSize); + + pThread = InternalGetCurrentThread(); + + palError = InternalCreatePipe( + pThread, + hReadPipe, + hWritePipe, + lpPipeAttributes, + nSize + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("CreatePipe return %s\n", NO_ERROR == palError ? "TRUE":"FALSE"); + PERF_EXIT(CreatePipe); + return NO_ERROR == palError; +} + +/*++ +init_std_handle [static] + +utility function for FILEInitStdHandles. do the work that is common to all +three standard handles + +Parameters: + HANDLE pStd : Defines which standard handle to assign + FILE *stream : file stream to associate to handle + +Return value: + handle for specified stream, or INVALID_HANDLE_VALUE on failure +--*/ +static HANDLE init_std_handle(HANDLE * pStd, FILE *stream) +{ + CPalThread *pThread = InternalGetCurrentThread(); + PAL_ERROR palError = NO_ERROR; + IPalObject *pFileObject = NULL; + IPalObject *pRegisteredFile = NULL; + IDataLock *pDataLock = NULL; + CFileProcessLocalData *pLocalData = NULL; + CObjectAttributes oa; + + HANDLE hFile = INVALID_HANDLE_VALUE; + int new_fd = -1; + + /* duplicate the FILE *, so that we can fclose() in FILECloseHandle without + closing the original */ + new_fd = fcntl(fileno(stream), F_DUPFD_CLOEXEC, 0); // dup, but with CLOEXEC + if(-1 == new_fd) + { + ERROR("dup() failed; errno is %d (%s)\n", errno, strerror(errno)); + goto done; + } + + palError = g_pObjectManager->AllocateObject( + pThread, + &otFile, + &oa, + &pFileObject + ); + + if (NO_ERROR != palError) + { + goto done; + } + + palError = pFileObject->GetProcessLocalData( + pThread, + WriteLock, + &pDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + goto done; + } + + pLocalData->inheritable = TRUE; + pLocalData->unix_fd = new_fd; + pLocalData->open_flags = 0; + pLocalData->open_flags_deviceaccessonly = FALSE; + + // + // We've finished initializing our local data, so release that lock + // + + pDataLock->ReleaseLock(pThread, TRUE); + pDataLock = NULL; + + palError = g_pObjectManager->RegisterObject( + pThread, + pFileObject, + &aotFile, + &hFile, + &pRegisteredFile + ); + + // + // pFileObject is invalidated by the call to RegisterObject, so NULL it + // out here to ensure that we don't try to release a reference on + // it down the line. + // + + pFileObject = NULL; + +done: + + if (NULL != pDataLock) + { + pDataLock->ReleaseLock(pThread, TRUE); + } + + if (NULL != pFileObject) + { + pFileObject->ReleaseReference(pThread); + } + + if (NULL != pRegisteredFile) + { + pRegisteredFile->ReleaseReference(pThread); + } + + if (NO_ERROR == palError) + { + *pStd = hFile; + } + else if (-1 != new_fd) + { + close(new_fd); + } + + return hFile; +} + + +/*++ +FILEInitStdHandles + +Create handle objects for stdin, stdout and stderr + +(no parameters) + +Return value: + TRUE on success, FALSE on failure +--*/ +BOOL FILEInitStdHandles(void) +{ + HANDLE stdin_handle; + HANDLE stdout_handle; + HANDLE stderr_handle; + + TRACE("creating handle objects for stdin, stdout, stderr\n"); + + stdin_handle = init_std_handle(&pStdIn, stdin); + if(INVALID_HANDLE_VALUE == stdin_handle) + { + ERROR("failed to create stdin handle\n"); + goto fail; + } + + stdout_handle = init_std_handle(&pStdOut, stdout); + if(INVALID_HANDLE_VALUE == stdout_handle) + { + ERROR("failed to create stdout handle\n"); + CloseHandle(stdin_handle); + goto fail; + } + + stderr_handle = init_std_handle(&pStdErr, stderr); + if(INVALID_HANDLE_VALUE == stderr_handle) + { + ERROR("failed to create stderr handle\n"); + CloseHandle(stdin_handle); + CloseHandle(stdout_handle); + goto fail; + } + return TRUE; + +fail: + pStdIn = INVALID_HANDLE_VALUE; + pStdOut = INVALID_HANDLE_VALUE; + pStdErr = INVALID_HANDLE_VALUE; + return FALSE; +} + +/*++ +FILECleanupStdHandles + +Remove all regions, locked by a file pointer, from shared memory + +(no parameters) + +--*/ +void FILECleanupStdHandles(void) +{ + HANDLE stdin_handle; + HANDLE stdout_handle; + HANDLE stderr_handle; + + TRACE("closing standard handles\n"); + stdin_handle = pStdIn; + stdout_handle = pStdOut; + stderr_handle = pStdErr; + + pStdIn = INVALID_HANDLE_VALUE; + pStdOut = INVALID_HANDLE_VALUE; + pStdErr = INVALID_HANDLE_VALUE; + + if (stdin_handle != INVALID_HANDLE_VALUE) + { + CloseHandle(stdin_handle); + } + + if (stdout_handle != INVALID_HANDLE_VALUE) + { + CloseHandle(stdout_handle); + } + + if (stderr_handle != INVALID_HANDLE_VALUE) + { + CloseHandle(stderr_handle); + } +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/filetime.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/filetime.cpp new file mode 100644 index 0000000..34e4dcc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/filetime.cpp @@ -0,0 +1,317 @@ +// 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: + + filetime.cpp + +Abstract: + + Implementation of the file WIN API related to file time. + +Notes: + +One very important thing to note is that on BSD systems, the stat structure +stores nanoseconds for the time-related fields. This is implemented by +replacing the time_t fields st_atime, st_mtime, and st_ctime by timespec +structures, instead named st_atimespec, st_mtimespec, and st_ctimespec. + +However, if _POSIX_SOURCE is defined, the fields are time_t values and use +their POSIX names. For compatibility purposes, when _POSIX_SOURCE is NOT +defined, the time-related fields are defined in sys/stat.h as: + +#ifndef _POSIX_SOURCE +#define st_atime st_atimespec.tv_sec +#define st_mtime st_mtimespec.tv_sec +#define st_ctime st_ctimespec.tv_sec +#endif + +Furthermore, if _POSIX_SOURCE is defined, the structure still has +additional fields for nanoseconds, named st_atimensec, st_mtimensec, and +st_ctimensec. + +In the PAL, there is a configure check to see if the system supports +nanoseconds for the time-related fields. This source file also sets macros +so that STAT_ATIME_NSEC etc. will always refer to the appropriate field +if it exists, and are defined as 0 otherwise. + +-- + +Also note that there is no analog to "creation time" on Linux systems. +Instead, we use the inode change time, which is set to the current time +whenever mtime changes or when chmod, chown, etc. syscalls modify the +file status; or mtime if older. Ideally we would use birthtime when +available. + + +--*/ + +#include "pal/corunix.hpp" +#include "pal/dbgmsg.h" +#include "pal/filetime.h" +#include "pal/thread.hpp" +#include "pal/file.hpp" + +#include +#include +#include +#include + +#if HAVE_SYS_TIME_H +#include +#endif // HAVE_SYS_TIME_H + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(FILE); + +// In safemath.h, Template SafeInt uses macro _ASSERTE, which need to use variable +// defdbgchan defined by SET_DEFAULT_DEBUG_CHANNEL. Therefore, the include statement +// should be placed after the SET_DEFAULT_DEBUG_CHANNEL(FILE) +#include + +/* Magic number explanation: + + To 1970: + Both epochs are Gregorian. 1970 - 1601 = 369. Assuming a leap + year every four years, 369 / 4 = 92. However, 1700, 1800, and 1900 + were NOT leap years, so 89 leap years, 280 non-leap years. + 89 * 366 + 280 * 365 = 134774 days between epochs. Of course + 60 * 60 * 24 = 86400 seconds per day, so 134774 * 86400 = + 11644473600 = SECS_BETWEEN_1601_AND_1970_EPOCHS. + + To 2001: + Again, both epochs are Gregorian. 2001 - 1601 = 400. Assuming a leap + year every four years, 400 / 4 = 100. However, 1700, 1800, and 1900 + were NOT leap years (2000 was because it was divisible by 400), so + 97 leap years, 303 non-leap years. + 97 * 366 + 303 * 365 = 146097 days between epochs. 146097 * 86400 = + 12622780800 = SECS_BETWEEN_1601_AND_2001_EPOCHS. + + This result is also confirmed in the MSDN documentation on how + to convert a time_t value to a win32 FILETIME. +*/ +static const __int64 SECS_BETWEEN_1601_AND_1970_EPOCHS = 11644473600LL; +static const __int64 SECS_TO_100NS = 10000000; /* 10^7 */ + +#ifdef __APPLE__ +static const __int64 SECS_BETWEEN_1601_AND_2001_EPOCHS = 12622780800LL; +#endif // __APPLE__ + +/*++ +Function: + CompareFileTime + +See MSDN doc. +--*/ +LONG +PALAPI +CompareFileTime( + IN CONST FILETIME *lpFileTime1, + IN CONST FILETIME *lpFileTime2) +{ + __int64 First; + __int64 Second; + + long Ret; + + PERF_ENTRY(CompareFileTime); + ENTRY("CompareFileTime(lpFileTime1=%p lpFileTime2=%p)\n", + lpFileTime1, lpFileTime2); + + First = ((__int64)lpFileTime1->dwHighDateTime << 32) + + lpFileTime1->dwLowDateTime; + Second = ((__int64)lpFileTime2->dwHighDateTime << 32) + + lpFileTime2->dwLowDateTime; + + if ( First < Second ) + { + Ret = -1; + } + else if ( First > Second ) + { + Ret = 1; + } + else + { + Ret = 0; + } + + LOGEXIT("CompareFileTime returns LONG %ld\n", Ret); + PERF_EXIT(CompareFileTime); + return Ret; +} + + +/*++ +Function: + GetSystemTimeAsFileTime + +See MSDN doc. +--*/ +VOID +PALAPI +GetSystemTimeAsFileTime( + OUT LPFILETIME lpSystemTimeAsFileTime) +{ + PERF_ENTRY(GetSystemTimeAsFileTime); + ENTRY("GetSystemTimeAsFileTime(lpSystemTimeAsFileTime=%p)\n", + lpSystemTimeAsFileTime); + +#if HAVE_WORKING_CLOCK_GETTIME + struct timespec Time; + if (clock_gettime(CLOCK_REALTIME, &Time) == 0) + { + *lpSystemTimeAsFileTime = FILEUnixTimeToFileTime( Time.tv_sec, Time.tv_nsec ); + } +#else + struct timeval Time; + if (gettimeofday(&Time, NULL) == 0) + { + /* use (tv_usec * 1000) because 2nd arg is in nanoseconds */ + *lpSystemTimeAsFileTime = FILEUnixTimeToFileTime( Time.tv_sec, Time.tv_usec * 1000); + } +#endif + else + { + /* no way to indicate failure, so set time to zero */ + ASSERT("clock_gettime or gettimeofday failed"); + *lpSystemTimeAsFileTime = FILEUnixTimeToFileTime( 0, 0 ); + } + + LOGEXIT("GetSystemTimeAsFileTime returns.\n"); + PERF_EXIT(GetSystemTimeAsFileTime); +} + + +#ifdef __APPLE__ +/*++ +Function: + FILECFAbsoluteTimeToFileTime + +Convert a CFAbsoluteTime value to a win32 FILETIME structure, as described +in MSDN documentation. CFAbsoluteTime is the number of seconds elapsed since +00:00 01 January 2001 UTC (Mac OS X epoch), while FILETIME represents a +64-bit number of 100-nanosecond intervals that have passed since 00:00 +01 January 1601 UTC (win32 epoch). +--*/ +FILETIME FILECFAbsoluteTimeToFileTime( CFAbsoluteTime sec ) +{ + __int64 Result; + FILETIME Ret; + + Result = ((__int64)sec + SECS_BETWEEN_1601_AND_2001_EPOCHS) * SECS_TO_100NS; + + Ret.dwLowDateTime = (DWORD)Result; + Ret.dwHighDateTime = (DWORD)(Result >> 32); + + TRACE("CFAbsoluteTime = [%9f] converts to Win32 FILETIME = [%#x:%#x]\n", + sec, Ret.dwHighDateTime, Ret.dwLowDateTime); + + return Ret; +} +#endif // __APPLE__ + + +/*++ +Function: + FILEUnixTimeToFileTime + +Convert a time_t value to a win32 FILETIME structure, as described in +MSDN documentation. time_t is the number of seconds elapsed since +00:00 01 January 1970 UTC (Unix epoch), while FILETIME represents a +64-bit number of 100-nanosecond intervals that have passed since 00:00 +01 January 1601 UTC (win32 epoch). +--*/ +FILETIME FILEUnixTimeToFileTime( time_t sec, long nsec ) +{ + __int64 Result; + FILETIME Ret; + + Result = ((__int64)sec + SECS_BETWEEN_1601_AND_1970_EPOCHS) * SECS_TO_100NS + + (nsec / 100); + + Ret.dwLowDateTime = (DWORD)Result; + Ret.dwHighDateTime = (DWORD)(Result >> 32); + + TRACE("Unix time = [%ld.%09ld] converts to Win32 FILETIME = [%#x:%#x]\n", + sec, nsec, Ret.dwHighDateTime, Ret.dwLowDateTime); + + return Ret; +} + + +/** +Function + + FileTimeToSystemTime() + + Helper function for FileTimeToDosTime. + Converts the necessary file time attibutes to system time, for + easier manipulation in FileTimeToDosTime. + +--*/ +BOOL PALAPI FileTimeToSystemTime( CONST FILETIME * lpFileTime, + LPSYSTEMTIME lpSystemTime ) +{ + UINT64 FileTime = 0; + time_t UnixFileTime = 0; + struct tm * UnixSystemTime = 0; + + /* Combine the file time. */ + FileTime = lpFileTime->dwHighDateTime; + FileTime <<= 32; + FileTime |= (UINT)lpFileTime->dwLowDateTime; + bool isSafe = ClrSafeInt::subtraction( + FileTime, + SECS_BETWEEN_1601_AND_1970_EPOCHS * SECS_TO_100NS, + FileTime); + + if (isSafe == true) + { +#if HAVE_GMTIME_R + struct tm timeBuf; +#endif /* HAVE_GMTIME_R */ + /* Convert file time to unix time. */ + if (((INT64)FileTime) < 0) + { + UnixFileTime = -1 - ( ( -FileTime - 1 ) / 10000000 ); + } + else + { + UnixFileTime = FileTime / 10000000; + } + + /* Convert unix file time to Unix System time. */ +#if HAVE_GMTIME_R + UnixSystemTime = gmtime_r( &UnixFileTime, &timeBuf ); +#else /* HAVE_GMTIME_R */ + UnixSystemTime = gmtime( &UnixFileTime ); +#endif /* HAVE_GMTIME_R */ + + /* Convert unix system time to Windows system time. */ + lpSystemTime->wDay = UnixSystemTime->tm_mday; + + /* Unix time counts January as a 0, under Windows it is 1*/ + lpSystemTime->wMonth = UnixSystemTime->tm_mon + 1; + /* Unix time returns the year - 1900, Windows returns the current year*/ + lpSystemTime->wYear = UnixSystemTime->tm_year + 1900; + + lpSystemTime->wSecond = UnixSystemTime->tm_sec; + lpSystemTime->wMinute = UnixSystemTime->tm_min; + lpSystemTime->wHour = UnixSystemTime->tm_hour; + return TRUE; + } + else + { + ERROR( "The file time is to large.\n" ); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/find.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/find.cpp new file mode 100644 index 0000000..9bbf3f2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/find.cpp @@ -0,0 +1,1007 @@ +// 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: + + find.c + +Abstract: + + Implementation of the FindFile function family + +Revision History: + + + +--*/ + +#include "pal/thread.hpp" +#include "pal/malloc.hpp" +#include "pal/file.hpp" +#include "pal/stackstring.hpp" + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/file.h" +#include "pal/filetime.h" + +#include +#include +#include +#include + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(FILE); + +namespace CorUnix +{ + int InternalGlob( + const char *szPattern, + int nFlags, +#if ERROR_FUNC_FOR_GLOB_HAS_FIXED_PARAMS + int (*pnErrFunc)(const char *, int), +#else + int (*pnErrFunc)(...), +#endif + glob_t *pgGlob + ); + + /*++ + InternalGlob + + Input parameters: + + szPattern = pointer to a pathname pattern to be expanded + nFlags = arguments to modify the behavior of glob + pnErrFunc = pointer to a routine that handles errors during the glob call + pgGlob = pointer to a glob structure + + Return value: + 0 on success, -1 on failure. + + Some platforms expect the error function for glob to take a variable number + of parameters, whereas other platforms insist that the error function take + a const char * and an int. A test in configure determines which is the case + for each platform and sets ERROR_FUNC_FOR_GLOB_HAS_FIXED_PARAMS + to 1 if the error func must have the char * and int parameters. + --*/ + int + InternalGlob( + const char *szPattern, + int nFlags, +#if ERROR_FUNC_FOR_GLOB_HAS_FIXED_PARAMS + int (*pnErrFunc)(const char *, int), +#else + int (*pnErrFunc)(...), +#endif + glob_t *pgGlob + ) + { + int nRet = -1; + nRet = glob(szPattern, nFlags, pnErrFunc, pgGlob); + return nRet; + } +} + +static BOOL FILEDosGlobA( + CPalThread *pthrCurrent, + const char *pattern, + int flags, + glob_t *pgGlob ); + +static int FILEGlobQsortCompare(const void *in_str1, const void *in_str2); + +static int FILEGlobFromSplitPath( + const char *dir, + const char *fname, + const char *ext, + int flags, + glob_t *pgGlob ); + +/*++ +Function: + FindFirstFileA + +See MSDN doc. +--*/ +HANDLE +PALAPI +FindFirstFileA( + IN LPCSTR lpFileName, + OUT LPWIN32_FIND_DATAA lpFindFileData) +{ + HANDLE hRet = INVALID_HANDLE_VALUE; + DWORD dwLastError = NO_ERROR; + find_obj *find_data = NULL; + CPalThread *pthrCurrent = InternalGetCurrentThread(); + + PERF_ENTRY(FindFirstFileA); + ENTRY("FindFirstFileA(lpFileName=%p (%s), lpFindFileData=%p)\n", + lpFileName?lpFileName:"NULL", + lpFileName?lpFileName:"NULL", lpFindFileData); + + if(NULL == lpFileName) + { + ERROR("lpFileName is NULL!\n"); + dwLastError = ERROR_PATH_NOT_FOUND; + goto done; + } + if(NULL == lpFindFileData) + { + ASSERT("lpFindFileData is NULL!\n"); + dwLastError = ERROR_INVALID_PARAMETER; + goto done; + } + + find_data = (find_obj *)InternalMalloc(sizeof(find_obj)); + if ( find_data == NULL ) + { + ERROR("Unable to allocate memory for find_data\n"); + dwLastError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + find_data->self_addr = find_data; + + // Clear the glob_t so we can safely call globfree() on it + // regardless of whether FILEDosGlobA ends up calling glob(). + memset(&(find_data->gGlob), 0, sizeof(find_data->gGlob)); + + if (!FILEDosGlobA(pthrCurrent, lpFileName, 0, &(find_data->gGlob))) + { + // FILEDosGlobA will call SetLastError() on failure. + goto done; + } + else + { + // Check if there's at least one match. + if (find_data->gGlob.gl_pathc == 0) + { + /* Testing has indicated that for this API the + * last errors are as follows + * c:\temp\foo.txt - no error + * c:\temp\foo - ERROR_FILE_NOT_FOUND + * c:\temp\foo\bar - ERROR_PATH_NOT_FOUND + * c:\temp\foo.txt\bar - ERROR_DIRECTORY + * + */ + LPSTR lpTemp = strdup((LPSTR)lpFileName); + if ( !lpTemp ) + { + ERROR( "strdup failed!\n" ); + SetLastError( ERROR_INTERNAL_ERROR ); + goto done; + } + FILEDosToUnixPathA( lpTemp ); + FILEGetProperNotFoundError( lpTemp, &dwLastError ); + + if ( ERROR_PATH_NOT_FOUND == dwLastError ) + { + /* If stripping the last segment reveals a file name then + the error is ERROR_DIRECTORY. */ + struct stat stat_data; + LPSTR lpLastPathSeparator = NULL; + + lpLastPathSeparator = strrchr( lpTemp, '/'); + + if ( lpLastPathSeparator != NULL ) + { + *lpLastPathSeparator = '\0'; + + if ( stat( lpTemp, &stat_data) == 0 && + (stat_data.st_mode & S_IFMT) == S_IFREG ) + { + dwLastError = ERROR_DIRECTORY; + } + } + } + free(lpTemp); + lpTemp = NULL; + goto done; + } + + find_data->next = find_data->gGlob.gl_pathv; + } + + if ( FindNextFileA( (HANDLE)find_data, lpFindFileData ) ) + { + hRet = (HANDLE)find_data; + } + +done: + + if ( hRet == INVALID_HANDLE_VALUE ) + { + if(NULL != find_data) + { + // Call globfree only when there is any pattern match + // otherwise, HPUX C library segfaults. + if (NULL != find_data->gGlob.gl_pathv) + { + globfree( &(find_data->gGlob) ); + } + free(find_data); + } + if (dwLastError) + { + SetLastError(dwLastError); + } + } + + LOGEXIT("FindFirstFileA returns HANDLE %p\n", hRet ); + PERF_EXIT(FindFirstFileA); + return hRet; +} + + +/*++ +Function: + FindFirstFileW + +See MSDN doc. +--*/ +HANDLE +PALAPI +FindFirstFileW( + IN LPCWSTR lpFileName, + OUT LPWIN32_FIND_DATAW lpFindFileData) +{ + // MAX_PATH_FNAME in this context is a file name, not a full path to a file. + HANDLE retval = INVALID_HANDLE_VALUE; + CHAR FileNameA[MAX_PATH_FNAME]; + WIN32_FIND_DATAA FindFileDataA; + + PERF_ENTRY(FindFirstFileW); + ENTRY("FindFirstFileW(lpFileName=%p (%S), lpFindFileData=%p)\n", + lpFileName?lpFileName:W16_NULLSTRING, + lpFileName?lpFileName:W16_NULLSTRING, lpFindFileData); + + if(NULL == lpFileName) + { + ERROR("lpFileName is NULL!\n"); + SetLastError(ERROR_PATH_NOT_FOUND); + goto done; + } + + if(NULL == lpFindFileData) + { + ERROR("lpFindFileData is NULL!\n"); + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + if( 0 == WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, lpFileName, -1, + FileNameA, MAX_PATH_FNAME, NULL, NULL)) + { + DWORD dwLastError = GetLastError(); + if (dwLastError == ERROR_INSUFFICIENT_BUFFER) + { + WARN("lpFileName is larger than MAX_PATH_FNAME (%d)!\n", MAX_PATH_FNAME); + SetLastError(ERROR_FILENAME_EXCED_RANGE); + } + else + { + ASSERT("WideCharToMultiByte failed! error is %d\n", dwLastError); + SetLastError(ERROR_INTERNAL_ERROR); + } + goto done; + } + + retval = FindFirstFileA(FileNameA, &FindFileDataA); + if( INVALID_HANDLE_VALUE == retval ) + { + TRACE("FindFirstFileA failed!\n"); + goto done; + } + + lpFindFileData->dwFileAttributes = FindFileDataA.dwFileAttributes; + lpFindFileData->dwReserved0 = FindFileDataA.dwReserved0; + lpFindFileData->dwReserved1 = FindFileDataA.dwReserved1; + lpFindFileData->ftCreationTime = FindFileDataA.ftCreationTime; + lpFindFileData->ftLastAccessTime = FindFileDataA.ftLastAccessTime; + lpFindFileData->ftLastWriteTime = FindFileDataA.ftLastWriteTime; + lpFindFileData->nFileSizeHigh = FindFileDataA.nFileSizeHigh; + lpFindFileData->nFileSizeLow = FindFileDataA.nFileSizeLow; + + /* no 8.3 file names */ + lpFindFileData->cAlternateFileName[0] = 0; + + if( 0 == MultiByteToWideChar(CP_ACP, 0, FindFileDataA.cFileName, -1, + lpFindFileData->cFileName, MAX_PATH_FNAME)) + { + DWORD dwLastError = GetLastError(); + if (dwLastError == ERROR_INSUFFICIENT_BUFFER) + { + WARN("FindFileDataA.cFileName is larger than MAX_PATH_FNAME (%d)!\n", MAX_PATH_FNAME); + SetLastError(ERROR_FILENAME_EXCED_RANGE); + } + else + { + ASSERT("MultiByteToWideChar failed! error is %d\n", dwLastError); + SetLastError(ERROR_INTERNAL_ERROR); + } + FindClose(retval); + retval = INVALID_HANDLE_VALUE; + } +done: + LOGEXIT("FindFirstFileW returns HANDLE %p\n", retval); + PERF_EXIT(FindFirstFileW); + return retval; +} + + +/*++ +Function: + FindNextFileA + +See MSDN doc. +--*/ +BOOL +PALAPI +FindNextFileA( + IN HANDLE hFindFile, + OUT LPWIN32_FIND_DATAA lpFindFileData) +{ + find_obj *find_data; + + BOOL bRet = FALSE; + DWORD dwLastError = 0; + DWORD Attr; + + PERF_ENTRY(FindNextFileA); + ENTRY("FindNextFileA(hFindFile=%p, lpFindFileData=%p)\n", + hFindFile, lpFindFileData); + + find_data = (find_obj*)hFindFile; + + if ( hFindFile == INVALID_HANDLE_VALUE || + find_data == NULL || + find_data->self_addr != find_data ) + { + TRACE("FindNextFileA received an invalid handle\n"); + dwLastError = ERROR_INVALID_HANDLE; + goto done; + } + + if ( find_data->next) + { + struct stat stat_data; + char ext[_MAX_EXT]; + int stat_result; + + while (*(find_data->next)) + { + char *path = *(find_data->next); + + TRACE("Found [%s]\n", path); + + // 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_s failed on %s\n", path); + dwLastError = ERROR_INTERNAL_ERROR; + goto done; + } + strcat_s( find_data->fname, sizeof(find_data->fname), ext ); + + /* get the attributes, but continue if it fails */ + Attr = GetFileAttributesA(path); + if (Attr == INVALID_FILE_ATTRIBUTES) + { + WARN("GetFileAttributes returned -1 on file [%s]\n", + *(find_data->next)); + } + lpFindFileData->dwFileAttributes = Attr; + + /* Note that cFileName is NOT the relative path */ + if (strcpy_s( lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName), find_data->fname ) != SAFECRT_SUCCESS) + { + TRACE("strcpy_s failed!\n"); + dwLastError = ERROR_FILENAME_EXCED_RANGE; + goto done; + } + + /* we don't support 8.3 filenames, so just leave it empty */ + lpFindFileData->cAlternateFileName[0] = 0; + + /* get the filetimes */ + stat_result = stat(path, &stat_data) == 0 || + lstat(path, &stat_data) == 0; + + find_data->next++; + + if ( stat_result ) + { + lpFindFileData->ftCreationTime = + FILEUnixTimeToFileTime( stat_data.st_ctime, + ST_CTIME_NSEC(&stat_data) ); + lpFindFileData->ftLastAccessTime = + FILEUnixTimeToFileTime( stat_data.st_atime, + ST_ATIME_NSEC(&stat_data) ); + lpFindFileData->ftLastWriteTime = + FILEUnixTimeToFileTime( stat_data.st_mtime, + ST_MTIME_NSEC(&stat_data) ); + + /* if Unix mtime is greater than atime, return mtime + as the last access time */ + if (CompareFileTime(&lpFindFileData->ftLastAccessTime, + &lpFindFileData->ftLastWriteTime) < 0) + { + lpFindFileData->ftLastAccessTime = lpFindFileData->ftLastWriteTime; + } + + /* if Unix ctime is greater than mtime, return mtime + as the create time */ + if (CompareFileTime(&lpFindFileData->ftLastWriteTime, + &lpFindFileData->ftCreationTime) < 0) + { + lpFindFileData->ftCreationTime = lpFindFileData->ftLastWriteTime; + } + + /* get file size */ + lpFindFileData->nFileSizeLow = (DWORD)stat_data.st_size; + #if SIZEOF_OFF_T > 4 + lpFindFileData->nFileSizeHigh = + (DWORD)(stat_data.st_size >> 32); + #else + lpFindFileData->nFileSizeHigh = 0; + #endif + + bRet = TRUE; + break; + } + } + if(!bRet) + { + dwLastError = ERROR_NO_MORE_FILES; + } + } + else + { + + ASSERT("find_data->next is (mysteriously) NULL\n"); + } + +done: + if (dwLastError) + { + SetLastError(dwLastError); + } + + LOGEXIT("FindNextFileA returns BOOL %d\n", bRet); + PERF_EXIT(FindNextFileA); + return bRet; +} + + +/*++ +Function: + FindNextFileW + +See MSDN doc. +--*/ +BOOL +PALAPI +FindNextFileW( + IN HANDLE hFindFile, + OUT LPWIN32_FIND_DATAW lpFindFileData) +{ + BOOL retval = FALSE; + WIN32_FIND_DATAA FindFileDataA; + + PERF_ENTRY(FindNextFileW); + ENTRY("FindNextFileW(hFindFile=%p, lpFindFileData=%p)\n", + hFindFile, lpFindFileData); + + retval = FindNextFileA(hFindFile, &FindFileDataA); + if(!retval) + { + WARN("FindNextFileA failed!\n"); + goto done; + } + + lpFindFileData->dwFileAttributes = FindFileDataA.dwFileAttributes; + lpFindFileData->dwReserved0 = FindFileDataA.dwReserved0; + lpFindFileData->dwReserved1 = FindFileDataA.dwReserved1; + lpFindFileData->ftCreationTime = FindFileDataA.ftCreationTime; + lpFindFileData->ftLastAccessTime = FindFileDataA.ftLastAccessTime; + lpFindFileData->ftLastWriteTime = FindFileDataA.ftLastWriteTime; + lpFindFileData->nFileSizeHigh = FindFileDataA.nFileSizeHigh; + lpFindFileData->nFileSizeLow = FindFileDataA.nFileSizeLow; + + /* no 8.3 file names */ + lpFindFileData->cAlternateFileName[0] = 0; + + if( 0 == MultiByteToWideChar(CP_ACP, 0, FindFileDataA.cFileName, -1, + lpFindFileData->cFileName, MAX_PATH_FNAME)) + { + DWORD dwLastError = GetLastError(); + if (dwLastError == ERROR_INSUFFICIENT_BUFFER) + { + WARN("FindFileDataA.cFileName is larger than MAX_PATH_FNAME (%d)!\n", MAX_PATH_FNAME); + SetLastError(ERROR_FILENAME_EXCED_RANGE); + } + else + { + ASSERT("MultiByteToWideChar failed! error is %d\n", dwLastError); + SetLastError(ERROR_INTERNAL_ERROR); + } + retval = FALSE; + } + +done: + LOGEXIT("FindNextFileW returns BOOL %d\n", retval); + PERF_EXIT(FindNextFileW); + return retval; +} + + +/*++ +Function: + FindClose + +See MSDN doc. +--*/ +BOOL +PALAPI +FindClose( + IN OUT HANDLE hFindFile) +{ + find_obj *find_data; + BOOL hRet = TRUE; + DWORD dwLastError = 0; + + PERF_ENTRY(FindClose); + ENTRY("FindClose(hFindFile=%p)\n", hFindFile); + + find_data = (find_obj*)hFindFile; + + if ( hFindFile == INVALID_HANDLE_VALUE || + find_data == NULL || + find_data->self_addr != find_data ) + { + ERROR("Invalid find handle\n"); + hRet = FALSE; + dwLastError = ERROR_INVALID_PARAMETER; + goto done; + } + + find_data->self_addr = NULL; + + // Call globfree only when there is any pattern match + // otherwise, HPUX C library segfaults. + if (NULL != find_data->gGlob.gl_pathv) + { + globfree( &(find_data->gGlob) ); + } + free(find_data); + +done: + if (dwLastError) + { + SetLastError(dwLastError); + } + + LOGEXIT("FindClose returns BOOL %d\n", hRet); + PERF_EXIT(FindClose); + return hRet; +} + + +/*++ +Function: + FILEMakePathA + +Mimics _makepath from windows, except it's a bit safer. +Any or all of dir, fname, and ext can be NULL. +--*/ +static int FILEMakePathA( char *buff, + int buff_size, + const char *dir, + const char *fname, + const char *ext ) +{ + int dir_len = 0; + int fname_len = 0; + int ext_len = 0; + int len; + char *p; + + TRACE("Attempting to assemble path from [%s][%s][%s], buff_size = %d\n", + dir?dir:"NULL", fname?fname:"NULL", ext?ext:"NULL", buff_size); + + if (dir) dir_len = strlen(dir); + if (fname) fname_len = strlen(fname); + if (ext) ext_len = strlen(ext); + + len = dir_len + fname_len + ext_len + 1; + + TRACE("Required buffer size is %d bytes\n", len); + + if ( len > buff_size ) + { + ERROR("Buffer is too small (%d bytes), needs %d bytes\n", + buff_size, len); + return -1; + } + else + { + buff[0] = 0; + + p = buff; + if (dir_len > 0) + { + if (strncpy_s( buff, buff_size, dir, dir_len + 1 ) != SAFECRT_SUCCESS) + { + ERROR("FILEMakePathA: strncpy_s failed\n"); + return -1; + } + + p += dir_len; + buff_size-= dir_len; + } + if (fname_len > 0) + { + if (strncpy_s( p, buff_size, fname, fname_len + 1 ) != SAFECRT_SUCCESS) + { + ERROR("FILEMakePathA: strncpy_s failed\n"); + return -1; + } + + p += fname_len; + buff_size-=fname_len; + } + if (ext_len > 0) + { + if (strncpy_s( p, buff_size, ext, ext_len + 1) != SAFECRT_SUCCESS) + { + ERROR("FILEMakePathA: strncpy_s failed\n"); + return -1; + } + } + + TRACE("FILEMakePathA assembled [%s]\n", buff); + return len - 1; + } +} + + +/*++ + FILEGlobQsortCompare + + Comparison function required by qsort, so that the + . and .. directories end up on top of the sorted list + of directories. +--*/ +static int FILEGlobQsortCompare(const void *in_str1, const void *in_str2) +{ + char **str1 = (char**)in_str1; + char **str2 = (char**)in_str2; + const int FIRST_ARG_LESS = -1; + const int FIRST_ARG_EQUAL = 0; + const int FIRST_ARG_GREATER = 1; + + /* If both strings are equal, return immediately */ + if (strcmp(*(str1), *(str2)) == 0) + { + return(FIRST_ARG_EQUAL); + } + + /* Have '.' always on top than any other search result */ + if (strcmp(*(str1), ".") == 0) + { + return (FIRST_ARG_LESS); + } + if (strcmp(*(str2), ".") == 0) + { + return (FIRST_ARG_GREATER); + } + + /* Have '..' next on top, over any other search result */ + if (strcmp(*(str1), "..") == 0) + { + return (FIRST_ARG_LESS); + } + if (strcmp(*(str2), "..") == 0) + { + return (FIRST_ARG_GREATER); + } + + /* Finally, let strcmp do the rest for us */ + return (strcmp(*(str1),*(str2))); +} + +/*++ +Function: + FILEEscapeSquareBrackets + +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_s. +--*/ +static void FILEEscapeSquareBrackets(char *pattern, char *escaped_pattern) +{ + TRACE("Entering FILEEscapeSquareBrackets: [%p (%s)][%p]\n", + pattern,pattern,escaped_pattern); + +#if _ENABLE_DEBUG_MESSAGES_ + char *escaped_pattern_base = escaped_pattern; +#endif // _ENABLE_DEBUG_MESSAGES_ + + while(*pattern) + { + if('[' == *pattern || ']' == *pattern) + { + *escaped_pattern = '\\'; + escaped_pattern++; + } + *escaped_pattern = *pattern; + pattern++; + escaped_pattern++; + } + *escaped_pattern='\0'; + + TRACE("FILEEscapeSquareBrackets done. escaped_pattern=%s\n", + escaped_pattern_base); +} + + +/*++ +Function: + FILEGlobFromSplitPath + +Simple wrapper function around glob(3), except that the pattern is accepted +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. +--*/ +static int FILEGlobFromSplitPath( const char *dir, + const char *fname, + const char *ext, + int flags, + glob_t *pgGlob ) +{ + int Ret; + PathCharString PatternPS; + PathCharString EscapedPatternPS; + char * Pattern; + int length = 0; + char * EscapedPattern; + + TRACE("We shall attempt to glob from components [%s][%s][%s]\n", + dir?dir:"NULL", fname?fname:"NULL", ext?ext:"NULL"); + + if (dir) length = strlen(dir); + if (fname) length += strlen(fname); + if (ext) length += strlen(ext); + + Pattern = PatternPS.OpenStringBuffer(length); + if (NULL == Pattern) + { + ERROR("Not Enough memory."); + return -1; + } + FILEMakePathA( Pattern, length+1, dir, fname, ext ); + PatternPS.CloseBuffer(length); + TRACE("Assembled Pattern = [%s]\n", Pattern); + + /* special handling is needed to handle the case where + filename contains '[' and ']' */ + EscapedPattern = EscapedPatternPS.OpenStringBuffer(length*2); + if (NULL == EscapedPattern) + { + ERROR("Not Enough memory."); + return -1; + } + FILEEscapeSquareBrackets( Pattern, EscapedPattern); + EscapedPatternPS.CloseBuffer(strlen(EscapedPattern)); +#ifdef GLOB_QUOTE + flags |= GLOB_QUOTE; +#endif // GLOB_QUOTE + Ret = InternalGlob(EscapedPattern, flags, NULL, pgGlob); + +#ifdef GLOB_NOMATCH + if (Ret == GLOB_NOMATCH) + { + // pgGlob->gl_pathc will be 0 in this case. We'll check + // the return value to see if an error occurred, so we + // don't want to return an error if we simply didn't match + // anything. + Ret = 0; + } +#endif // GLOB_NOMATCH + + /* Ensure that . and .. are placed in front, and sort the rest */ + qsort(pgGlob->gl_pathv, pgGlob->gl_pathc, sizeof(char*), + FILEGlobQsortCompare); + TRACE("Result of glob() is %d\n", Ret); + + return Ret; +} + + +/*++ +Function: + FILEDosGlobA + +Generate pathnames matching a DOS globbing pattern. This function has a similar +prototype to glob(3), and fulfils the same purpose. However, DOS globbing +is slightly different than Unix in the following ways: + +- '.*' at the end of a pattern means "any file extension, or none at all", +whereas Unix has no concept of file extensions, and will match the '.' like +any other character + +- on Unix, filenames beginning with '.' must be explicitly matched. This is +not true in DOS + +- in DOS, the first two entries (if they match) will be '.' and '..', followed +by all other matching entries sorted in ASCII order. In Unix, all entries are +treated equally, so '+file' would appear before '.' and '..' + +- DOS globbing will fail if any wildcard characters occur before the last path +separator + +This implementation of glob implements the DOS behavior in all these cases, +but otherwise attempts to behave exactly like POSIX glob. The only exception +is its return value -- it returns TRUE if it succeeded (finding matches or +finding no matches but without any error occurring) or FALSE if any error +occurs. It calls SetLastError() if it returns FALSE. + +Sorting doesn't seem to be consistent on all Windows platform, and it's +not required for CoreCLR to have the same sorting algorithm as Windows 2000. +This implementation will give slightly different result for the sort list +than Windows 2000. + +--*/ +static BOOL FILEDosGlobA( CPalThread *pthrCurrent, + const char *pattern, + int flags, + glob_t *pgGlob ) +{ + char Dir[_MAX_DIR]; + char FilenameBuff[_MAX_FNAME + 1]; + char *Filename = FilenameBuff + 1; + char Ext[_MAX_EXT]; + int A, B, C; + BOOL result = TRUE; + int globResult = 0; + + Dir[0] = 0; + FilenameBuff[0] = '.'; + FilenameBuff[1] = 0; + Ext[0] = 0; + + _splitpath_s( pattern, NULL, 0, Dir, _MAX_DIR, Filename, _MAX_FNAME+1, Ext, _MAX_EXT); + + /* check to see if _splitpath_s failed */ + if ( Filename[0] == 0 ) + { + if ( Dir[0] == 0 ) + { + ERROR("_splitpath_s failed on path [%s]\n", pattern); + } + else + { + ERROR("Pattern contains a trailing backslash\n"); + } + SetLastError(ERROR_PATH_NOT_FOUND); + result = FALSE; + goto done; + } + + TRACE("glob pattern [%s] split into [%s][%s][%s]\n", + pattern, Dir, Filename, Ext); + + if ( strchr(Dir, '*') != NULL || strchr(Dir, '?') != NULL ) + { + ERROR("Found wildcard character(s) ('*' and/or '?') before " + "last path separator\n"); + SetLastError(ERROR_PATH_NOT_FOUND); + result = FALSE; + goto done; + } + + if (Dir[0] != 0) + { + FILEDosToUnixPathA( Dir ); + } + + /* The meat of the routine happens below. Basically, there are three + special things to check for: + + (A) If the extension is _exactly_ '.*', we will need to do two globs, + one for 'filename.*' and one for 'filename', EXCEPT if (B) the last + character of filename is '*', in which case we can eliminate the + extension altogether, since '*.*' and '*' are the same in DOS. + (C) If the first character of the filename is '*', we need to do + an additional glob for each one we have already done, except with + '.' prepended to the filename of the patterns, because in Unix, + hidden files need to be matched explicitly. + + We can ignore the extension by calling FILEGlobFromSplitPath with + the extension parameter as "", and we can prepend '.' to the + filename by using (Filename - 1), since Filename conveniently points + to the second character of a buffer which happens to have '.' as + its first character. + */ + + A = strncmp(Ext, ".*", 3) == 0; + B = (Filename[strlen(Filename) - 1] == '*'); + C = (*Filename == '*'); + + TRACE("Extension IS%s '.*', filename DOES%s end with '*', " + "and filename DOES%s begin with '*'\n", + A?"":" NOT", B?"":" NOT", C?"":" NOT"); + + if ( !(A && B) ) + { + /* the original pattern */ + globResult = FILEGlobFromSplitPath(Dir, Filename, Ext, 0, pgGlob); + if ( globResult != 0 ) + { + goto done; + } + + if (C) + { + /* the original pattern but '.' prepended to filename */ + globResult = FILEGlobFromSplitPath(Dir, Filename - 1, Ext, + GLOB_APPEND, pgGlob); + if ( globResult != 0 ) + { + goto done; + } + } + } + + if (A) + { + /* if (A && B), this is the first glob() call. The first call + to glob must use flags = 0, while proceeding calls should + set the GLOB_APPEND flag. */ + globResult = FILEGlobFromSplitPath(Dir, Filename, "", + (A && B)?0:GLOB_APPEND, pgGlob); + if ( globResult != 0 ) + { + goto done; + } + + if (C) + { + /* omit the extension and prepend '.' to filename */ + globResult = FILEGlobFromSplitPath(Dir, Filename - 1, "", + GLOB_APPEND, pgGlob); + if ( globResult != 0 ) + { + goto done; + } + } + } + +done: + if (globResult != 0) + { + if (globResult == GLOB_NOSPACE) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } + else + { + SetLastError(ERROR_INTERNAL_ERROR); + } + result = FALSE; + } + TRACE("Returning %d\n", result); + return result; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/path.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/path.cpp new file mode 100644 index 0000000..890c4d9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/file/path.cpp @@ -0,0 +1,978 @@ +// 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: + + path.c + +Abstract: + + Implementation of all functions related to path support + +Revision History: + + + +--*/ + +#include "pal/thread.hpp" +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/file.h" +#include "pal/malloc.hpp" +#include "pal/stackstring.hpp" + +#include + +#include +#include + +SET_DEFAULT_DEBUG_CHANNEL(FILE); + + +// In safemath.h, Template SafeInt uses macro _ASSERTE, which need to use variable +// defdbgchan defined by SET_DEFAULT_DEBUG_CHANNEL. Therefore, the include statement +// should be placed after the SET_DEFAULT_DEBUG_CHANNEL(FILE) +#include + +int MaxWCharToAcpLengthRatio = 3; +/*++ +Function: + GetFullPathNameA + +See MSDN doc. +--*/ +DWORD +PALAPI +GetFullPathNameA( + IN LPCSTR lpFileName, + IN DWORD nBufferLength, + OUT LPSTR lpBuffer, + OUT LPSTR *lpFilePart) +{ + DWORD nReqPathLen, nRet = 0; + PathCharString unixPath; + LPSTR unixPathBuf; + BOOL fullPath = FALSE; + + PERF_ENTRY(GetFullPathNameA); + ENTRY("GetFullPathNameA(lpFileName=%p (%s), nBufferLength=%u, lpBuffer=%p, " + "lpFilePart=%p)\n", + lpFileName?lpFileName:"NULL", + lpFileName?lpFileName:"NULL", nBufferLength, lpBuffer, lpFilePart); + + if(NULL == lpFileName) + { + WARN("lpFileName is NULL\n"); + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + + /* find out if lpFileName is a partial or full path */ + if ('\\' == *lpFileName || '/' == *lpFileName) + { + fullPath = TRUE; + } + + if(fullPath) + { + if( !unixPath.Set(lpFileName, strlen(lpFileName))) + { + ERROR("Set() failed;\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + } + else + { + + /* build full path */ + if(!GetCurrentDirectoryA(unixPath)) + { + /* no reason for this to fail now... */ + ASSERT("GetCurrentDirectoryA() failed! lasterror is %#xd\n", + GetLastError()); + SetLastError(ERROR_INTERNAL_ERROR); + goto done; + } + + if (!unixPath.Append("/", 1) || + !unixPath.Append(lpFileName,strlen(lpFileName)) + ) + { + ERROR("Append failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + + } + + unixPathBuf = unixPath.OpenStringBuffer(unixPath.GetCount()); + /* do conversion to Unix path */ + FILEDosToUnixPathA( unixPathBuf ); + + /* now we can canonicalize this */ + FILECanonicalizePath(unixPathBuf); + + /* at last, we can figure out how long this path is */ + nReqPathLen = strlen(unixPathBuf); + + unixPath.CloseBuffer(nReqPathLen); + nReqPathLen++; + if(nBufferLength < nReqPathLen) + { + TRACE("reporting insufficient buffer : minimum is %d, caller " + "provided %d\n", nReqPathLen, nBufferLength); + nRet = nReqPathLen; + goto done; + } + + nRet = nReqPathLen-1; + strcpy_s(lpBuffer, nBufferLength, unixPath); + + /* locate the filename component if caller cares */ + if(lpFilePart) + { + *lpFilePart = strrchr(lpBuffer, '/'); + + if (*lpFilePart == NULL) + { + ASSERT("Not able to find '/' in the full path.\n"); + SetLastError( ERROR_INTERNAL_ERROR ); + nRet = 0; + goto done; + } + else + { + (*lpFilePart)++; + } + } + +done: + LOGEXIT("GetFullPathNameA returns DWORD %u\n", nRet); + PERF_EXIT(GetFullPathNameA); + return nRet; +} + + +/*++ +Function: + GetFullPathNameW + +See MSDN doc. +--*/ +DWORD +PALAPI +GetFullPathNameW( + IN LPCWSTR lpFileName, + IN DWORD nBufferLength, + OUT LPWSTR lpBuffer, + OUT LPWSTR *lpFilePart) +{ + LPSTR fileNameA; + CHAR * bufferA; + size_t bufferASize = 0; + PathCharString bufferAPS; + LPSTR lpFilePartA; + int fileNameLength; + int srcSize; + DWORD length; + DWORD nRet = 0; + + PERF_ENTRY(GetFullPathNameW); + ENTRY("GetFullPathNameW(lpFileName=%p (%S), nBufferLength=%u, lpBuffer=%p" + ", lpFilePart=%p)\n", + lpFileName?lpFileName:W16_NULLSTRING, + lpFileName?lpFileName:W16_NULLSTRING, nBufferLength, + lpBuffer, lpFilePart); + + + fileNameLength = WideCharToMultiByte(CP_ACP, 0, lpFileName, + -1, NULL, 0, NULL, NULL); + if (fileNameLength == 0) + { + /* Couldn't convert to ANSI. That's odd. */ + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + else + { + fileNameA = static_cast(alloca(fileNameLength)); + } + + /* Now convert lpFileName to ANSI. */ + srcSize = WideCharToMultiByte (CP_ACP, 0, lpFileName, + -1, fileNameA, fileNameLength, + NULL, NULL ); + if( srcSize == 0 ) + { + DWORD dwLastError = GetLastError(); + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + + bufferASize = nBufferLength * MaxWCharToAcpLengthRatio; + bufferA = bufferAPS.OpenStringBuffer(bufferASize); + if (NULL == bufferA) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + length = GetFullPathNameA(fileNameA, bufferASize, bufferA, &lpFilePartA); + bufferAPS.CloseBuffer(length); + + if (length == 0 || length > bufferASize) + { + /* Last error is set by GetFullPathNameA */ + nRet = length; + goto done; + } + + /* Convert back to Unicode the result */ + nRet = MultiByteToWideChar( CP_ACP, 0, bufferA, -1, + lpBuffer, nBufferLength ); + + if (nRet == 0) + { + if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) + { + /* get the required length */ + nRet = MultiByteToWideChar( CP_ACP, 0, bufferA, -1, + NULL, 0 ); + SetLastError(ERROR_BUFFER_OVERFLOW); + } + + goto done; + } + + /* MultiByteToWideChar counts the trailing NULL, but + GetFullPathName does not. */ + nRet--; + + /* now set lpFilePart */ + if (lpFilePart != NULL) + { + *lpFilePart = lpBuffer; + *lpFilePart += MultiByteToWideChar( CP_ACP, 0, bufferA, + lpFilePartA - bufferA, NULL, 0); + } + +done: + LOGEXIT("GetFullPathNameW returns DWORD %u\n", nRet); + PERF_EXIT(GetFullPathNameW); + return nRet; +} + + +/*++ +Function: + GetTempPathA + +See MSDN. + +Notes: + On Windows, the temp path is determined by the following steps: + 1. The value of the "TMP" environment variable, or if it doesn't exist, + 2. The value of the "TEMP" environment variable, or if it doesn't exist, + 3. The Windows directory. + + On Unix, we follow in spirit: + 1. The value of the "TMPDIR" environment variable, or if it doesn't exist, + 2. The /tmp directory. + This is the same approach employed by mktemp. + +--*/ +DWORD +PALAPI +GetTempPathA( + IN DWORD nBufferLength, + OUT LPSTR lpBuffer) +{ + DWORD dwPathLen = 0; + + PERF_ENTRY(GetTempPathA); + ENTRY("GetTempPathA(nBufferLength=%u, lpBuffer=%p)\n", + nBufferLength, lpBuffer); + + if ( !lpBuffer ) + { + ERROR( "lpBuffer was not a valid pointer.\n" ) + SetLastError( ERROR_INVALID_PARAMETER ); + LOGEXIT("GetTempPathA returns DWORD %u\n", dwPathLen); + PERF_EXIT(GetTempPathA); + return 0; + } + + /* Try the TMPDIR environment variable. This is the same env var checked by mktemp. */ + dwPathLen = GetEnvironmentVariableA("TMPDIR", lpBuffer, nBufferLength); + if (dwPathLen > 0) + { + /* The env var existed. dwPathLen will be the length without null termination + * if the entire value was successfully retrieved, or it'll be the length + * required to store the value with null termination. + */ + if (dwPathLen < nBufferLength) + { + /* The environment variable fit in the buffer. Make sure it ends with '/'. */ + if (lpBuffer[dwPathLen - 1] != '/') + { + /* If adding the slash would still fit in our provided buffer, do it. Otherwise, + * let the caller know how much space would be needed. + */ + if (dwPathLen + 2 <= nBufferLength) + { + lpBuffer[dwPathLen++] = '/'; + lpBuffer[dwPathLen] = '\0'; + } + else + { + dwPathLen += 2; + } + } + } + else /* dwPathLen >= nBufferLength */ + { + /* The value is too long for the supplied buffer. dwPathLen will now be the + * length required to hold the value, but we don't know whether that value + * is going to be '/' terminated. Since we'll need enough space for the '/', and since + * a caller would assume that the dwPathLen we return will be sufficient, + * we make sure to account for it in dwPathLen even if that means we end up saying + * one more byte of space is needed than actually is. + */ + dwPathLen++; + } + } + else /* env var not found or was empty */ + { + /* no luck, use /tmp/ or /data/local/tmp on Android */ + const char *defaultDir = TEMP_DIRECTORY_PATH; + size_t defaultDirLen = strlen(defaultDir); + if (defaultDirLen < nBufferLength) + { + dwPathLen = defaultDirLen; + strcpy_s(lpBuffer, nBufferLength, defaultDir); + } + else + { + /* get the required length */ + dwPathLen = defaultDirLen + 1; + } + } + + if ( dwPathLen >= nBufferLength ) + { + ERROR("Buffer is too small, need space for %d characters including null termination\n", dwPathLen); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + } + + LOGEXIT("GetTempPathA returns DWORD %u\n", dwPathLen); + PERF_EXIT(GetTempPathA); + return dwPathLen; +} + +/*++ +Function: + GetTempPathW + +See MSDN. +See also the comment for GetTempPathA. +--*/ +DWORD +PALAPI +GetTempPathW( + IN DWORD nBufferLength, + OUT LPWSTR lpBuffer) +{ + PERF_ENTRY(GetTempPathW); + ENTRY("GetTempPathW(nBufferLength=%u, lpBuffer=%p)\n", + nBufferLength, lpBuffer); + + if (!lpBuffer) + { + ERROR("lpBuffer was not a valid pointer.\n") + SetLastError(ERROR_INVALID_PARAMETER); + LOGEXIT("GetTempPathW returns DWORD 0\n"); + PERF_EXIT(GetTempPathW); + return 0; + } + + char TempBuffer[nBufferLength > 0 ? nBufferLength : 1]; + DWORD dwRetVal = GetTempPathA( nBufferLength, TempBuffer ); + + if ( dwRetVal >= nBufferLength ) + { + ERROR( "lpBuffer was not large enough.\n" ) + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + *lpBuffer = '\0'; + } + else if ( dwRetVal != 0 ) + { + /* Convert to wide. */ + if ( 0 == MultiByteToWideChar( CP_ACP, 0, TempBuffer, -1, + lpBuffer, dwRetVal + 1 ) ) + { + ASSERT( "An error occurred while converting the string to wide.\n" ); + SetLastError( ERROR_INTERNAL_ERROR ); + dwRetVal = 0; + } + } + else + { + ERROR( "The function failed.\n" ); + *lpBuffer = '\0'; + } + + LOGEXIT("GetTempPathW returns DWORD %u\n", dwRetVal ); + PERF_EXIT(GetTempPathW); + return dwRetVal; +} + + + +/*++ +Function: + FileDosToUnixPathA + +Abstract: + Change a DOS path to a Unix path. + + Replaces '\' by '/' + +Parameter: + IN/OUT lpPath: path to be modified +--*/ +void +FILEDosToUnixPathA( + LPSTR lpPath) +{ + LPSTR p; + + TRACE("Original DOS path = [%s]\n", lpPath); + + if (!lpPath) + { + return; + } + + for (p = lpPath; *p; p++) + { + /* Replace \ with / */ + if (*p == '\\') + { + *p = '/'; + } + } + + TRACE("Resulting Unix path = [%s]\n", lpPath); +} + +void +FILEDosToUnixPathA( + PathCharString& lpPath) +{ + + SIZE_T len = lpPath.GetCount(); + LPSTR lpPathBuf = lpPath.OpenStringBuffer(len); + FILEDosToUnixPathA(lpPathBuf); + lpPath.CloseBuffer(len); + +} + + +/*++ +Function: + FILEGetDirectoryFromFullPathA + +Parse the given path. If it contains a directory part and a file part, +put the directory part into the supplied buffer, and return the number of +characters written to the buffer. If the buffer is not large enough, +return the required size of the buffer including the NULL character. If +there is no directory part in the path, return 0. +--*/ +DWORD FILEGetDirectoryFromFullPathA( LPCSTR lpFullPath, + DWORD nBufferLength, + LPSTR lpBuffer ) +{ + size_t full_len, dir_len, i; + LPCSTR lpDirEnd; + DWORD dwRetLength; + + full_len = strlen( lpFullPath ); + + /* look for the first path separator backwards */ + lpDirEnd = lpFullPath + full_len - 1; + while( lpDirEnd >= lpFullPath && *lpDirEnd != '/' && *lpDirEnd != '\\') + --lpDirEnd; + + dir_len = lpDirEnd - lpFullPath + 1; /* +1 for fencepost */ + + if ( dir_len <= 0 ) + { + dwRetLength = 0; + } + else if (dir_len >= nBufferLength) + { + dwRetLength = dir_len + 1; /* +1 for NULL char */ + } + else + { + /* put the directory into the buffer, including 1 or more + trailing path separators */ + for( i = 0; i < dir_len; ++i ) + *(lpBuffer + i) = *(lpFullPath + i); + + *(lpBuffer + i) = '\0'; + + dwRetLength = dir_len; + } + + return( dwRetLength ); +} + +/*++ +FILECanonicalizePath + Removes all instances of '/./', '/../' and '//' from an absolute path. + +Parameters: + LPSTR lpUnixPath : absolute path to modify, in Unix format + +(no return value) + +Notes : +-behavior is undefined if path is not absolute +-the order of steps *is* important: /one/./../two would give /one/two + instead of /two if step 3 was done before step 2 +-reason for this function is that GetFullPathName can't use realpath(), since + realpath() requires the given path to be valid and GetFullPathName does not. +--*/ +void FILECanonicalizePath(LPSTR lpUnixPath) +{ + LPSTR slashslashptr; + LPSTR dotdotptr; + LPSTR slashdotptr; + LPSTR slashptr; + + /* step 1 : replace '//' sequences by a single '/' */ + + slashslashptr = lpUnixPath; + while(1) + { + slashslashptr = strstr(slashslashptr,"//"); + if(NULL == slashslashptr) + { + break; + } + /* remove extra '/' */ + TRACE("stripping '//' from %s\n", lpUnixPath); + memmove(slashslashptr,slashslashptr+1,strlen(slashslashptr+1)+1); + } + + /* step 2 : replace '/./' sequences by a single '/' */ + + slashdotptr = lpUnixPath; + while(1) + { + slashdotptr = strstr(slashdotptr,"/./"); + if(NULL == slashdotptr) + { + break; + } + /* strip the extra '/.' */ + TRACE("removing '/./' sequence from %s\n", lpUnixPath); + memmove(slashdotptr,slashdotptr+2,strlen(slashdotptr+2)+1); + } + + /* step 3 : replace '//../' sequences by a single '/' */ + + while(1) + { + dotdotptr = strstr(lpUnixPath,"/../"); + if(NULL == dotdotptr) + { + break; + } + if(dotdotptr == lpUnixPath) + { + /* special case : '/../' at the beginning of the path are replaced + by a single '/' */ + TRACE("stripping leading '/../' from %s\n", lpUnixPath); + memmove(lpUnixPath, lpUnixPath+3,strlen(lpUnixPath+3)+1); + continue; + } + + /* null-terminate the string before the '/../', so that strrchr will + start looking right before it */ + *dotdotptr = '\0'; + slashptr = strrchr(lpUnixPath,'/'); + if(NULL == slashptr) + { + /* this happens if this function was called with a relative path. + don't do that. */ + ASSERT("can't find leading '/' before '/../ sequence\n"); + break; + } + TRACE("removing '//../' sequence from %s\n", lpUnixPath); + memmove(slashptr,dotdotptr+3,strlen(dotdotptr+3)+1); + } + + /* step 4 : remove a trailing '/..' */ + + dotdotptr = strstr(lpUnixPath,"/.."); + if(dotdotptr == lpUnixPath) + { + /* if the full path is simply '/..', replace it by '/' */ + lpUnixPath[1] = '\0'; + } + else if(NULL != dotdotptr && '\0' == dotdotptr[3]) + { + *dotdotptr = '\0'; + slashptr = strrchr(lpUnixPath,'/'); + if(NULL != slashptr) + { + /* make sure the last slash isn't the root */ + if (slashptr == lpUnixPath) + { + lpUnixPath[1] = '\0'; + } + else + { + *slashptr = '\0'; + } + } + } + + /* step 5 : remove a traling '/.' */ + + slashdotptr = strstr(lpUnixPath,"/."); + if (slashdotptr != NULL && slashdotptr[2] == '\0') + { + if(slashdotptr == lpUnixPath) + { + // if the full path is simply '/.', replace it by '/' */ + lpUnixPath[1] = '\0'; + } + else + { + *slashdotptr = '\0'; + } + } +} + + +/*++ +Function: + SearchPathW + +See MSDN doc. + +PAL-specific notes : +-lpPath must be non-NULL; path delimiters are platform-dependent (':' for Unix) +-lpFileName must be non-NULL, may be an absolute path +-lpExtension must be NULL +-lpFilePart (if non-NULL) doesn't need to be used (but we do) +--*/ +DWORD +PALAPI +SearchPathW( + IN LPCWSTR lpPath, + IN LPCWSTR lpFileName, + IN LPCWSTR lpExtension, + IN DWORD nBufferLength, + OUT LPWSTR lpBuffer, + OUT LPWSTR *lpFilePart + ) +{ + DWORD nRet = 0; + WCHAR * FullPath; + size_t FullPathLength = 0; + PathWCharString FullPathPS; + LPCWSTR pPathStart; + LPCWSTR pPathEnd; + size_t PathLength; + size_t FileNameLength; + DWORD dw; + DWORD length; + char * AnsiPath; + PathCharString AnsiPathPS; + size_t CanonicalPathLength; + int canonical_size; + WCHAR * CanonicalPath; + PathWCharString CanonicalPathPS; + + PERF_ENTRY(SearchPathW); + ENTRY("SearchPathW(lpPath=%p (%S), lpFileName=%p (%S), lpExtension=%p, " + "nBufferLength=%u, lpBuffer=%p, lpFilePart=%p)\n", + lpPath, + lpPath, lpFileName, lpFileName, lpExtension, nBufferLength, lpBuffer, + lpFilePart); + + /* validate parameters */ + + if(NULL == lpPath) + { + ASSERT("lpPath may not be NULL\n"); + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + if(NULL == lpFileName) + { + ASSERT("lpFileName may not be NULL\n"); + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + if(NULL != lpExtension) + { + ASSERT("lpExtension must be NULL, is %p instead\n", lpExtension); + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + + /* special case : if file name contains absolute path, don't search the + provided path */ + if('\\' == lpFileName[0] || '/' == lpFileName[0]) + { + /* Canonicalize the path to deal with back-to-back '/', etc. */ + length = MAX_LONGPATH; //Use it for first try + CanonicalPath = CanonicalPathPS.OpenStringBuffer(length); + if (NULL == CanonicalPath) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + dw = GetFullPathNameW(lpFileName, length+1, CanonicalPath, NULL); + CanonicalPathPS.CloseBuffer(dw); + if (length+1 < dw) + { + CanonicalPath = CanonicalPathPS.OpenStringBuffer(dw-1); + if (NULL == CanonicalPath) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + dw = GetFullPathNameW(lpFileName, dw, CanonicalPath, NULL); + CanonicalPathPS.CloseBuffer(dw); + } + + if (dw == 0) + { + WARN("couldn't canonicalize path <%S>, error is %#x. failing.\n", + lpPath, GetLastError()); + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + + /* see if the file exists */ + CanonicalPathLength = (PAL_wcslen(CanonicalPath)+1) * MaxWCharToAcpLengthRatio; + AnsiPath = AnsiPathPS.OpenStringBuffer(CanonicalPathLength); + if (NULL == AnsiPath) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + canonical_size = WideCharToMultiByte(CP_ACP, 0, CanonicalPath, -1, + AnsiPath, CanonicalPathLength, NULL, NULL); + AnsiPathPS.CloseBuffer(canonical_size); + + if(0 == access(AnsiPath, F_OK)) + { + /* found it */ + nRet = dw; + } + } + else + { + LPCWSTR pNextPath; + + pNextPath = lpPath; + + FileNameLength = PAL_wcslen(lpFileName); + + while (*pNextPath) + { + pPathStart = pNextPath; + + /* get a pointer to the end of the first path in pPathStart */ + pPathEnd = PAL_wcschr(pPathStart, ':'); + if (!pPathEnd) + { + pPathEnd = pPathStart + PAL_wcslen(pPathStart); + /* we want to break out of the loop after this pass, so let + *pNextPath be '\0' */ + pNextPath = pPathEnd; + } + else + { + /* point to the next component in the path string */ + pNextPath = pPathEnd+1; + } + + PathLength = pPathEnd-pPathStart; + + if(0 == PathLength) + { + /* empty component : there were 2 consecutive ':' */ + continue; + } + + /* Construct a pathname by concatenating one path from lpPath, '/' + and lpFileName */ + FullPathLength = PathLength + FileNameLength; + FullPath = FullPathPS.OpenStringBuffer(FullPathLength+1); + if (NULL == FullPath) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + memcpy(FullPath, pPathStart, PathLength*sizeof(WCHAR)); + FullPath[PathLength] = '/'; + PAL_wcscpy(&FullPath[PathLength+1], lpFileName); + + FullPathPS.CloseBuffer(FullPathLength+1); + + /* Canonicalize the path to deal with back-to-back '/', etc. */ + length = MAX_LONGPATH; //Use it for first try + CanonicalPath = CanonicalPathPS.OpenStringBuffer(length); + if (NULL == CanonicalPath) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + dw = GetFullPathNameW(FullPath, length+1, + CanonicalPath, NULL); + CanonicalPathPS.CloseBuffer(dw); + + if (length+1 < dw) + { + CanonicalPath = CanonicalPathPS.OpenStringBuffer(dw-1); + if (NULL == CanonicalPath) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + dw = GetFullPathNameW(FullPath, dw, CanonicalPath, NULL); + CanonicalPathPS.CloseBuffer(dw); + } + + if (dw == 0) + { + /* Call failed - possibly low memory. Skip the path */ + WARN("couldn't canonicalize path <%S>, error is %#x. " + "skipping it\n", FullPath, GetLastError()); + continue; + } + + /* see if the file exists */ + CanonicalPathLength = (PAL_wcslen(CanonicalPath)+1) * MaxWCharToAcpLengthRatio; + AnsiPath = AnsiPathPS.OpenStringBuffer(CanonicalPathLength); + if (NULL == AnsiPath) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + canonical_size = WideCharToMultiByte(CP_ACP, 0, CanonicalPath, -1, + AnsiPath, CanonicalPathLength, NULL, NULL); + AnsiPathPS.CloseBuffer(canonical_size); + + if(0 == access(AnsiPath, F_OK)) + { + /* found it */ + nRet = dw; + break; + } + } + } + + if (nRet == 0) + { + /* file not found anywhere; say so. in Windows, this always seems to say + FILE_NOT_FOUND, even if path doesn't exist */ + SetLastError(ERROR_FILE_NOT_FOUND); + } + else + { + /* find out the required buffer size, copy path to buffer if it's + large enough */ + nRet = PAL_wcslen(CanonicalPath)+1; + if(nRet <= nBufferLength) + { + if(NULL == lpBuffer) + { + /* Windows merily crashes here, but let's not */ + ERROR("caller told us buffer size was %d, but buffer is NULL\n", + nBufferLength); + SetLastError(ERROR_INVALID_PARAMETER); + nRet = 0; + goto done; + } + PAL_wcscpy(lpBuffer, CanonicalPath); + + /* don't include the null-terminator in the count if buffer was + large enough */ + nRet--; + + if(NULL != lpFilePart) + { + *lpFilePart = PAL_wcsrchr(lpBuffer, '/'); + if(NULL == *lpFilePart) + { + ASSERT("no '/' in full path!\n"); + } + else + { + /* point to character after last '/' */ + (*lpFilePart)++; + } + } + } + } +done: + LOGEXIT("SearchPathW returns DWORD %u\n", nRet); + PERF_EXIT(SearchPathW); + return nRet; +} + +/*++ +Function: + PathFindFileNameW + +See MSDN doc. +--*/ +LPWSTR +PALAPI +PathFindFileNameW( + IN LPCWSTR pPath + ) +{ + PERF_ENTRY(PathFindFileNameW); + ENTRY("PathFindFileNameW(pPath=%p (%S))\n", + pPath?pPath:W16_NULLSTRING, + pPath?pPath:W16_NULLSTRING); + + LPWSTR ret = (LPWSTR)pPath; + if (ret != NULL && *ret != W('\0')) + { + ret = PAL_wcschr(ret, W('\0')) - 1; + if (ret > pPath && *ret == W('/')) + { + ret--; + } + while (ret > pPath && *ret != W('/')) + { + ret--; + } + if (*ret == W('/') && *(ret + 1) != W('\0')) + { + ret++; + } + } + + LOGEXIT("PathFindFileNameW returns %S\n", ret); + PERF_EXIT(PathFindFileNameW); + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/handlemgr/handleapi.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/handlemgr/handleapi.cpp new file mode 100644 index 0000000..c88a768 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/handlemgr/handleapi.cpp @@ -0,0 +1,332 @@ +// 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: + + handleapi.cpp + +Abstract: + + Implementation of the handle management APIs + + + +--*/ + +#include "pal/handleapi.hpp" +#include "pal/handlemgr.hpp" +#include "pal/thread.hpp" +#include "pal/procobj.hpp" +#include "pal/dbgmsg.h" +#include "pal/process.h" + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(HANDLE); + +CAllowedObjectTypes aotDuplicateHandle(TRUE); + +PAL_ERROR +CloseSpecialHandle( + HANDLE hObject + ); + +/*++ +Function: + DuplicateHandle + +See MSDN doc. + +PAL-specific behavior : + -Source and Target process needs to be the current process. + -lpTargetHandle must be non-NULL + -dwDesiredAccess is ignored + -bInheritHandle must be FALSE + -dwOptions must be a combo of DUPLICATE_SAME_ACCESS and + DUPLICATE_CLOSE_SOURCE + +--*/ +BOOL +PALAPI +DuplicateHandle( + IN HANDLE hSourceProcessHandle, + IN HANDLE hSourceHandle, + IN HANDLE hTargetProcessHandle, + OUT LPHANDLE lpTargetHandle, + IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN DWORD dwOptions) +{ + PAL_ERROR palError; + CPalThread *pThread; + + PERF_ENTRY(DuplicateHandle); + ENTRY("DuplicateHandle( hSrcProcHandle=%p, hSrcHandle=%p, " + "hTargetProcHandle=%p, lpTargetHandle=%p, dwAccess=%#x, " + "bInheritHandle=%d, dwOptions=%#x) \n", hSourceProcessHandle, + hSourceHandle, hTargetProcessHandle, lpTargetHandle, + dwDesiredAccess, bInheritHandle, dwOptions); + + pThread = InternalGetCurrentThread(); + + palError = InternalDuplicateHandle( + pThread, + hSourceProcessHandle, + hSourceHandle, + hTargetProcessHandle, + lpTargetHandle, + bInheritHandle, + dwOptions + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("DuplicateHandle returns BOOL %d\n", (NO_ERROR == palError)); + PERF_EXIT(DuplicateHandle); + return (NO_ERROR == palError); +} + +PAL_ERROR +CorUnix::InternalDuplicateHandle( + CPalThread *pThread, + HANDLE hSourceProcess, + HANDLE hSource, + HANDLE hTargetProcess, + LPHANDLE phDuplicate, + BOOL bInheritHandle, + DWORD dwOptions + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pobjSource = NULL; + + DWORD source_process_id; + DWORD target_process_id; + DWORD cur_process_id; + + cur_process_id = GetCurrentProcessId(); + source_process_id = PROCGetProcessIDFromHandle(hSourceProcess); + target_process_id = PROCGetProcessIDFromHandle(hTargetProcess); + + /* Check validity of process handles */ + if (0 == source_process_id || 0 == target_process_id) + { + ASSERT("Can't duplicate handle: invalid source or destination process"); + palError = ERROR_INVALID_PARAMETER; + goto InternalDuplicateHandleExit; + } + + /* At least source or target process should be the current process. */ + if (source_process_id != cur_process_id + && target_process_id != cur_process_id) + { + ASSERT("Can't duplicate handle : neither source or destination" + "processes are from current process"); + palError = ERROR_INVALID_PARAMETER; + goto InternalDuplicateHandleExit; + } + + if (FALSE != bInheritHandle) + { + ASSERT("Can't duplicate handle : bInheritHandle is not FALSE.\n"); + palError = ERROR_INVALID_PARAMETER; + goto InternalDuplicateHandleExit; + } + + if (dwOptions & ~(DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) + { + ASSERT( + "Can't duplicate handle : dwOptions is %#x which is not " + "a subset of (DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE) " + "(%#x).\n", + dwOptions, + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); + palError = ERROR_INVALID_PARAMETER; + goto InternalDuplicateHandleExit; + } + + if (0 == (dwOptions & DUPLICATE_SAME_ACCESS)) + { + ASSERT( + "Can't duplicate handle : dwOptions is %#x which does not " + "include DUPLICATE_SAME_ACCESS (%#x).\n", + dwOptions, + DUPLICATE_SAME_ACCESS); + palError = ERROR_INVALID_PARAMETER; + goto InternalDuplicateHandleExit; + } + + if (NULL == phDuplicate) + { + ASSERT("Can't duplicate handle : lpTargetHandle is NULL.\n"); + goto InternalDuplicateHandleExit; + } + + /* Since handles can be remoted to others processes using PAL_LocalHsndleToRemote + and PAL_RemoteHandleToLocal, DuplicateHandle needs some special handling + when this scenario occurs. + + if hSourceProcessHandle is from another process OR + hTargetProcessHandle is from another process but both aren't + ( handled above ) return hSourceHandle. + */ + if (source_process_id != cur_process_id + || target_process_id != cur_process_id) + { + *phDuplicate = hSource; + palError = NO_ERROR; + goto InternalDuplicateHandleExit; + } + + // + // Obtain the source IPalObject + // + + if (!HandleIsSpecial(hSource)) + { + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hSource, + &aotDuplicateHandle, + &pobjSource + ); + + if (NO_ERROR != palError) + { + ERROR("Unable to get object for source handle %p (%i)\n", hSource, palError); + goto InternalDuplicateHandleExit; + } + } + else if (hPseudoCurrentProcess == hSource) + { + TRACE("Duplicating process pseudo handle(%p)\n", hSource); + + pobjSource = g_pobjProcess; + pobjSource->AddReference(); + } + else if (hPseudoCurrentThread == hSource) + { + TRACE("Duplicating thread pseudo handle(%p)\n", hSource); + + pobjSource = pThread->GetThreadObject(); + pobjSource->AddReference(); + } + else + { + ASSERT("Duplication not supported for this special handle (%p)\n", hSource); + palError = ERROR_INVALID_HANDLE; + goto InternalDuplicateHandleExit; + } + + palError = g_pObjectManager->ObtainHandleForObject( + pThread, + pobjSource, + phDuplicate + ); + +InternalDuplicateHandleExit: + + if (NULL != pobjSource) + { + pobjSource->ReleaseReference(pThread); + } + + if (dwOptions & DUPLICATE_CLOSE_SOURCE) + { + // + // Since DUPLICATE_CLOSE_SOURCE was specified the source handle + // MUST be closed, even if an error occurred during the duplication + // process + // + + TRACE("DuplicateHandle closing source handle %p\n", hSource); + InternalCloseHandle(pThread, hSource); + } + + return palError; +} + +/*++ +Function: + CloseHandle + +See MSDN doc. + +Note : according to MSDN, FALSE is returned in case of error. But also +according to MSDN, closing an invalid handle raises an exception when running a +debugger [or, alternately, if a special registry key is set]. This behavior is +not required in the PAL, so we'll always return FALSE. +--*/ +BOOL +PALAPI +CloseHandle( + IN OUT HANDLE hObject) +{ + CPalThread *pThread; + PAL_ERROR palError; + + PERF_ENTRY(CloseHandle); + ENTRY("CloseHandle (hObject=%p) \n", hObject); + + pThread = InternalGetCurrentThread(); + + palError = InternalCloseHandle( + pThread, + hObject + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("CloseHandle returns BOOL %d\n", (NO_ERROR == palError)); + PERF_EXIT(CloseHandle); + return (NO_ERROR == palError); +} + +PAL_ERROR +CorUnix::InternalCloseHandle( + CPalThread * pThread, + HANDLE hObject + ) +{ + PAL_ERROR palError = NO_ERROR; + + if (!HandleIsSpecial(hObject)) + { + palError = g_pObjectManager->RevokeHandle( + pThread, + hObject + ); + } + else + { + palError = CloseSpecialHandle(hObject); + } + + return palError; +} + +PAL_ERROR +CloseSpecialHandle( + HANDLE hObject + ) +{ + if ((hObject == hPseudoCurrentThread) || + (hObject == hPseudoCurrentProcess)) + { + return NO_ERROR; + } + + return ERROR_INVALID_HANDLE; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/handlemgr/handlemgr.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/handlemgr/handlemgr.cpp new file mode 100644 index 0000000..661b9d5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/handlemgr/handlemgr.cpp @@ -0,0 +1,321 @@ +// 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: + + handlemgr.cpp + +Abstract: + + Implementation of a basic handle table + + + +--*/ + +#include "pal/thread.hpp" +#include "pal/handlemgr.hpp" +#include "pal/cs.hpp" +#include "pal/malloc.hpp" +#include "pal/dbgmsg.h" + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(HANDLE); + +/* Constants */ +/* Special handles */ +/* Pseudo handles constant for current thread and process */ +const HANDLE hPseudoCurrentProcess = (HANDLE) 0xFFFFFF01; +const HANDLE hPseudoCurrentThread = (HANDLE) 0xFFFFFF03; +/* Pseudo handle constant for the global IO Completion port */ +const HANDLE hPseudoGlobalIOCP = (HANDLE) 0xFFFFFF05; + +PAL_ERROR +CSimpleHandleManager::Initialize( + void + ) +{ + PAL_ERROR palError = NO_ERROR; + + InternalInitializeCriticalSection(&m_csLock); + m_fLockInitialized = TRUE; + + m_dwTableGrowthRate = c_BasicGrowthRate; + + /* initialize the handle table - the free list is stored in the 'object' + field, with the head in the global 'm_hiFreeListStart'. */ + m_dwTableSize = m_dwTableGrowthRate; + + m_rghteHandleTable = reinterpret_cast(InternalMalloc((m_dwTableSize * sizeof(HANDLE_TABLE_ENTRY)))); + if(NULL == m_rghteHandleTable) + { + ERROR("Unable to create initial handle table array"); + palError = ERROR_OUTOFMEMORY; + goto InitializeExit; + } + + for (DWORD i = 0; i < m_dwTableSize; i++) + { + m_rghteHandleTable[i].u.hiNextIndex = i + 1; + m_rghteHandleTable[i].fEntryAllocated = FALSE; + } + + m_rghteHandleTable[m_dwTableSize - 1].u.hiNextIndex = (HANDLE_INDEX)-1; + + m_hiFreeListStart = 0; + m_hiFreeListEnd = m_dwTableSize - 1; + + TRACE("Handle Manager initialization complete.\n"); + +InitializeExit: + + return palError; +} + +PAL_ERROR +CSimpleHandleManager::AllocateHandle( + CPalThread *pThread, + IPalObject *pObject, + HANDLE *ph + ) +{ + PAL_ERROR palError = NO_ERROR; + DWORD dwIndex; + + Lock(pThread); + + /* if no free handles are available, we need to grow the handle table and + add new handles to the pool */ + if (m_hiFreeListStart == c_hiInvalid) + { + HANDLE_TABLE_ENTRY* rghteTempTable; + + TRACE("Handle pool empty (%d handles allocated), growing handle table " + "by %d entries.\n", m_dwTableSize, m_dwTableGrowthRate ); + + /* make sure handle values don't overflow */ + if (m_dwTableSize + m_dwTableGrowthRate >= c_MaxIndex) + { + WARN("Unable to allocate handle : maximum (%d) reached!\n", + m_dwTableSize); + palError = ERROR_OUTOFMEMORY; + goto AllocateHandleExit; + } + + /* grow handle table */ + rghteTempTable = reinterpret_cast(InternalRealloc( + m_rghteHandleTable, + (m_dwTableSize + m_dwTableGrowthRate) * sizeof(HANDLE_TABLE_ENTRY))); + + if (NULL == rghteTempTable) + { + WARN("not enough memory to grow handle table!\n"); + palError = ERROR_OUTOFMEMORY; + goto AllocateHandleExit; + } + m_rghteHandleTable = rghteTempTable; + + /* update handle table and handle pool */ + for (DWORD dw = m_dwTableSize; dw < m_dwTableSize + m_dwTableGrowthRate; dw += 1) + { + /* new handles are initially invalid */ + /* the last "old" handle was m_dwTableSize-1, so the new + handles range from m_dwTableSize to + m_dwTableSize+m_dwTableGrowthRate-1 */ + m_rghteHandleTable[dw].u.hiNextIndex = dw + 1; + m_rghteHandleTable[dw].fEntryAllocated = FALSE; + } + + m_hiFreeListStart = m_dwTableSize; + m_dwTableSize += m_dwTableGrowthRate; + m_rghteHandleTable[m_dwTableSize - 1].u.hiNextIndex = (HANDLE_INDEX)-1; + m_hiFreeListEnd = m_dwTableSize - 1; + + } + + /* take the next free handle */ + dwIndex = m_hiFreeListStart; + + /* remove the handle from the pool */ + m_hiFreeListStart = m_rghteHandleTable[dwIndex].u.hiNextIndex; + + /* clear the tail record if this is the last handle slot available */ + if(m_hiFreeListStart == c_hiInvalid) + { + m_hiFreeListEnd = c_hiInvalid; + } + + /* save the data associated with the new handle */ + *ph = HandleIndexToHandle(dwIndex); + + pObject->AddReference(); + m_rghteHandleTable[dwIndex].u.pObject = pObject; + m_rghteHandleTable[dwIndex].fEntryAllocated = TRUE; + +AllocateHandleExit: + + Unlock(pThread); + + return palError; +} + +PAL_ERROR +CSimpleHandleManager::GetObjectFromHandle( + CPalThread *pThread, + HANDLE h, + IPalObject **ppObject + ) +{ + PAL_ERROR palError = NO_ERROR; + HANDLE_INDEX hi; + + Lock(pThread); + + if (!ValidateHandle(h)) + { + ERROR("Tried to dereference an invalid handle %p\n", h); + palError = ERROR_INVALID_HANDLE; + goto GetObjectFromHandleExit; + } + + hi = HandleToHandleIndex(h); + + *ppObject = m_rghteHandleTable[hi].u.pObject; + (*ppObject)->AddReference(); + +GetObjectFromHandleExit: + + Unlock(pThread); + + return palError; +} + +PAL_ERROR +CSimpleHandleManager::FreeHandle( + CPalThread *pThread, + HANDLE h + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pobj = NULL; + HANDLE_INDEX hi = HandleToHandleIndex(h); + + Lock(pThread); + + if (!ValidateHandle(h)) + { + ERROR("Trying to free invalid handle %p.\n", h); + palError = ERROR_INVALID_HANDLE; + goto FreeHandleExit; + } + + if (HandleIsSpecial(h)) + { + ASSERT("Trying to free Special Handle %p.\n", h); + palError = ERROR_INVALID_HANDLE; + goto FreeHandleExit; + } + + pobj = m_rghteHandleTable[hi].u.pObject; + m_rghteHandleTable[hi].fEntryAllocated = FALSE; + + /* add handle to the free pool */ + if(m_hiFreeListEnd != c_hiInvalid) + { + m_rghteHandleTable[m_hiFreeListEnd].u.hiNextIndex = hi; + } + else + { + m_hiFreeListStart = hi; + } + + m_rghteHandleTable[hi].u.hiNextIndex = c_hiInvalid; + m_hiFreeListEnd = hi; + +FreeHandleExit: + + Unlock(pThread); + + if (NULL != pobj) + { + pobj->ReleaseReference(pThread); + } + + return palError; +} + +/*++ +Function : + ValidateHandle + + Check if a handle was allocated by this handle manager + +Parameters : + HANDLE handle : handle to check. + +Return Value : + TRUE if valid, FALSE if invalid. +--*/ +bool CSimpleHandleManager::ValidateHandle(HANDLE handle) +{ + DWORD dwIndex; + + if (NULL == m_rghteHandleTable) + { + ASSERT("Handle Manager is not initialized!\n"); + return FALSE; + } + + if (handle == INVALID_HANDLE_VALUE || handle == 0) + { + TRACE( "INVALID_HANDLE_VALUE or NULL value is not a valid handle.\n" ); + return FALSE; + } + + if (HandleIsSpecial(handle)) + { + // + // Special handles are valid in the general sense. They are not valid + // in this context, though, as they were not allocated by the handle + // manager. Hitting this case indicates a logic error within the PAL + // (since clients of the handle manager should have already dealt with + // the specialness of the handle) so we assert here. + // + + ASSERT ("Handle %p is a special handle, returning FALSE.\n", handle); + return FALSE; + } + + dwIndex = HandleToHandleIndex(handle); + + if (dwIndex >= m_dwTableSize) + { + WARN( "The handle value(%p) is out of the bounds for the handle table.\n", handle ); + return FALSE; + } + + if (!m_rghteHandleTable[dwIndex].fEntryAllocated) + { + WARN("The handle value (%p) has not been allocated\n", handle); + return FALSE; + } + + return TRUE; +} + +bool +CorUnix::HandleIsSpecial( + HANDLE h + ) +{ + return (hPseudoCurrentProcess == h || + hPseudoCurrentThread == h || + hPseudoGlobalIOCP == h); +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cert.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cert.hpp new file mode 100644 index 0000000..609864f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cert.hpp @@ -0,0 +1,33 @@ +// 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: + + include/pal/cert.hpp + +Abstract: + Header file for cert structures + + + +--*/ + +#ifndef _PAL_CERT_HPP_ +#define _PAL_CERT_HPP_ + +#include "corunix.hpp" + +#include + +CorUnix::PAL_ERROR OIDToStr(CSSM_DATA &data, CHAR *&oidStrOut); + +CSSM_RETURN InitCSSMModule(const CSSM_GUID *inGuid, CSSM_SERVICE_TYPE inService, + CSSM_MODULE_HANDLE_PTR outModule); +CSSM_RETURN TermCSSMModule(const CSSM_GUID *inGuid, CSSM_MODULE_HANDLE_PTR inModule); + +#endif // !_PAL_CERT_HPP_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cgroup.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cgroup.h new file mode 100644 index 0000000..3f03d91 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cgroup.h @@ -0,0 +1,37 @@ +// 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: + + include/pal/cgroup.h + +Abstract: + + Header file for the CGroup related functions. + + + +--*/ + +#ifndef _PAL_CGROUP_H_ +#define _PAL_CGROUP_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +void InitializeCGroup(); +void CleanupCGroup(); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _PAL_CGROUP_H_ */ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/context.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/context.h new file mode 100644 index 0000000..9313fc5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/context.h @@ -0,0 +1,825 @@ +// 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: + + include/pal/context.h + +Abstract: + + Header file for thread context utility functions. + + + +--*/ + +#ifndef _PAL_CONTEXT_H_ +#define _PAL_CONTEXT_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +#include +#include + +#if !HAVE_MACH_EXCEPTIONS +/* A type to wrap the native context type, which is ucontext_t on some + * platforms and another type elsewhere. */ +#if HAVE_UCONTEXT_T +#include + +typedef ucontext_t native_context_t; +#else // HAVE_UCONTEXT_T +#error Native context type is not known on this platform! +#endif // HAVE_UCONTEXT_T + +#if defined(XSTATE_SUPPORTED) && !HAVE_PUBLIC_XSTATE_STRUCT +namespace asm_sigcontext +{ +#include +}; +using asm_sigcontext::_fpx_sw_bytes; +using asm_sigcontext::_xstate; +#endif // defined(XSTATE_SUPPORTED) && !HAVE_PUBLIC_XSTATE_STRUCT + +#else // !HAVE_MACH_EXCEPTIONS +#include +#include +#endif // !HAVE_MACH_EXCEPTIONS else + +#if HAVE___GREGSET_T + +#ifdef HOST_64BIT +#define MCREG_Rbx(mc) ((mc).__gregs[_REG_RBX]) +#define MCREG_Rcx(mc) ((mc).__gregs[_REG_RCX]) +#define MCREG_Rdx(mc) ((mc).__gregs[_REG_RDX]) +#define MCREG_Rsi(mc) ((mc).__gregs[_REG_RSI]) +#define MCREG_Rdi(mc) ((mc).__gregs[_REG_RDI]) +#define MCREG_Rbp(mc) ((mc).__gregs[_REG_RBP]) +#define MCREG_Rax(mc) ((mc).__gregs[_REG_RAX]) +#define MCREG_Rip(mc) ((mc).__gregs[_REG_RIP]) +#define MCREG_Rsp(mc) ((mc).__gregs[_REG_RSP]) +#define MCREG_SegCs(mc) ((mc).__gregs[_REG_CS]) +#define MCREG_SegSs(mc) ((mc).__gregs[_REG_SS]) +#define MCREG_R8(mc) ((mc).__gregs[_REG_R8]) +#define MCREG_R9(mc) ((mc).__gregs[_REG_R9]) +#define MCREG_R10(mc) ((mc).__gregs[_REG_R10]) +#define MCREG_R11(mc) ((mc).__gregs[_REG_R11]) +#define MCREG_R12(mc) ((mc).__gregs[_REG_R12]) +#define MCREG_R13(mc) ((mc).__gregs[_REG_R13]) +#define MCREG_R14(mc) ((mc).__gregs[_REG_R14]) +#define MCREG_R15(mc) ((mc).__gregs[_REG_R15]) +#define MCREG_EFlags(mc) ((mc).__gregs[_REG_RFLAGS]) + +#define FPREG_Xmm(uc, index) *(M128A*)&(((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_xmm[index]) + +#define FPREG_St(uc, index) *(M128A*)&(((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_87_ac[index]) + +#define FPREG_ControlWord(uc) (((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_cw) +#define FPREG_StatusWord(uc) (((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_sw) +#define FPREG_TagWord(uc) (((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_tw) +#define FPREG_ErrorOffset(uc) (*(DWORD*) &(((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_ip)) +#define FPREG_ErrorSelector(uc) *((WORD*) &(((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_ip) + 2) +#define FPREG_DataOffset(uc) (*(DWORD*) &(((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_dp)) +#define FPREG_DataSelector(uc) *((WORD*) &(((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_dp) + 2) +#define FPREG_MxCsr(uc) (((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_mxcsr) +#define FPREG_MxCsr_Mask(uc) (((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_mxcsr_mask) + +#else // HOST_64BIT + +#define MCREG_Ebx(mc) ((mc).__gregs[_REG_EBX]) +#define MCREG_Ecx(mc) ((mc).__gregs[_REG_ECX]) +#define MCREG_Edx(mc) ((mc).__gregs[_REG_EDX]) +#define MCREG_Esi(mc) ((mc).__gregs[_REG_ESI]) +#define MCREG_Edi(mc) ((mc).__gregs[_REG_EDI]) +#define MCREG_Ebp(mc) ((mc).__gregs[_REG_EBP]) +#define MCREG_Eax(mc) ((mc).__gregs[_REG_EAX]) +#define MCREG_Eip(mc) ((mc).__gregs[_REG_EIP]) +#define MCREG_Esp(mc) ((mc).__gregs[_REG_ESP]) +#define MCREG_SegCs(mc) ((mc).__gregs[_REG_CS]) +#define MCREG_SegSs(mc) ((mc).__gregs[_REG_SS]) +#define MCREG_EFlags(mc) ((mc).__gregs[_REG_RFLAGS]) + +#endif // HOST_64BIT + +#elif HAVE_GREGSET_T + +#ifdef HOST_64BIT +#define MCREG_Rbx(mc) ((mc).gregs[REG_RBX]) +#define MCREG_Rcx(mc) ((mc).gregs[REG_RCX]) +#define MCREG_Rdx(mc) ((mc).gregs[REG_RDX]) +#define MCREG_Rsi(mc) ((mc).gregs[REG_RSI]) +#define MCREG_Rdi(mc) ((mc).gregs[REG_RDI]) +#define MCREG_Rbp(mc) ((mc).gregs[REG_RBP]) +#define MCREG_Rax(mc) ((mc).gregs[REG_RAX]) +#define MCREG_Rip(mc) ((mc).gregs[REG_RIP]) +#define MCREG_Rsp(mc) ((mc).gregs[REG_RSP]) +#ifdef REG_CSGSFS +#define MCREG_SegCs(mc) (*(WORD*)&((mc).gregs[REG_CSGSFS])) +#else +#define MCREG_SegCs(mc) (*(WORD*)&((mc).gregs[REG_CS])) +#endif +#define MCREG_R8(mc) ((mc).gregs[REG_R8]) +#define MCREG_R9(mc) ((mc).gregs[REG_R9]) +#define MCREG_R10(mc) ((mc).gregs[REG_R10]) +#define MCREG_R11(mc) ((mc).gregs[REG_R11]) +#define MCREG_R12(mc) ((mc).gregs[REG_R12]) +#define MCREG_R13(mc) ((mc).gregs[REG_R13]) +#define MCREG_R14(mc) ((mc).gregs[REG_R14]) +#define MCREG_R15(mc) ((mc).gregs[REG_R15]) + +#if HAVE_FPREGS_WITH_CW +#define FPREG_Fpstate(uc) (&((uc)->uc_mcontext.fpregs.fp_reg_set.fpchip_state)) + +#define FPREG_Xmm(uc, index) *(M128A*)&(FPREG_Fpstate(uc)->xmm[index]) +#define FPREG_St(uc, index) *(M128A*)&(FPREG_Fpstate(uc)->st[index]) +#define FPREG_ControlWord(uc) (FPREG_Fpstate(uc)->cw) +#define FPREG_StatusWord(uc) (FPREG_Fpstate(uc)->sw) +#define FPREG_MxCsr_Mask(uc) (FPREG_Fpstate(uc)->mxcsr_mask) + +// on SunOS, fctw and __fx_rsvd are uint8_t, whereas on linux ftw is uint16_t, +// so we use split and join technique for these two uint8_t members at call sites. +#define FPREG_TagWord1(uc) (FPREG_Fpstate(uc)->fctw) +#define FPREG_TagWord2(uc) (FPREG_Fpstate(uc)->__fx_rsvd) +#else +#define FPREG_Fpstate(uc) ((uc)->uc_mcontext.fpregs) + +#define FPREG_Xmm(uc, index) *(M128A*)&(FPREG_Fpstate(uc)->_xmm[index]) +#define FPREG_St(uc, index) *(M128A*)&(FPREG_Fpstate(uc)->_st[index]) +#define FPREG_ControlWord(uc) (FPREG_Fpstate(uc)->cwd) +#define FPREG_StatusWord(uc) (FPREG_Fpstate(uc)->swd) +#define FPREG_TagWord(uc) (FPREG_Fpstate(uc)->ftw) +#define FPREG_MxCsr_Mask(uc) (FPREG_Fpstate(uc)->mxcr_mask) +#endif + +#define FPREG_ErrorOffset(uc) *(DWORD*)&(FPREG_Fpstate(uc)->rip) +#define FPREG_ErrorSelector(uc) *(((WORD*)&(FPREG_Fpstate(uc)->rip)) + 2) +#define FPREG_DataOffset(uc) *(DWORD*)&(FPREG_Fpstate(uc)->rdp) +#define FPREG_DataSelector(uc) *(((WORD*)&(FPREG_Fpstate(uc)->rdp)) + 2) +#define FPREG_MxCsr(uc) (FPREG_Fpstate(uc)->mxcsr) + +///////////////////// +// Extended state + +#ifdef XSTATE_SUPPORTED + +#if HAVE_FPSTATE_GLIBC_RESERVED1 +#define FPSTATE_RESERVED __glibc_reserved1 +#else +#define FPSTATE_RESERVED padding +#endif + +// The mask for YMM registers presence flag stored in the xfeatures (formerly xstate_bv). On current Linuxes, this definition is +// only in internal headers, so we define it here. The xfeatures (formerly xstate_bv) is extracted from the processor xstate bit +// vector register, so the value is OS independent. +#ifndef XSTATE_YMM +#define XSTATE_YMM 4 +#endif + +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 + // indicate information about extended state. + _ASSERTE(reinterpret_cast(&FPREG_Fpstate(uc)->FPSTATE_RESERVED[12]) - reinterpret_cast(FPREG_Fpstate(uc)) == 464); + + _ASSERTE(FPREG_Fpstate(uc) != nullptr); + + return reinterpret_cast<_fpx_sw_bytes *>(&FPREG_Fpstate(uc)->FPSTATE_RESERVED[12]); +} + +inline UINT32 FPREG_ExtendedSize(const ucontext_t *uc) +{ + _ASSERTE(FPREG_FpxSwBytes(uc)->magic1 == FP_XSTATE_MAGIC1); + return FPREG_FpxSwBytes(uc)->extended_size; +} + +inline bool FPREG_HasYmmRegisters(const ucontext_t *uc) +{ + // See comments in /usr/include/x86_64-linux-gnu/asm/sigcontext.h for info on how to detect if extended state is present + static_assert_no_msg(FP_XSTATE_MAGIC2_SIZE == sizeof(UINT32)); + + if (FPREG_FpxSwBytes(uc)->magic1 != FP_XSTATE_MAGIC1) + { + return false; + } + + UINT32 extendedSize = FPREG_ExtendedSize(uc); + if (extendedSize < sizeof(_xstate)) + { + return false; + } + + _ASSERTE(extendedSize >= FP_XSTATE_MAGIC2_SIZE); + if (*reinterpret_cast(reinterpret_cast(FPREG_Fpstate(uc)) + (extendedSize - FP_XSTATE_MAGIC2_SIZE)) + != FP_XSTATE_MAGIC2) + { + return false; + } + +#if HAVE__FPX_SW_BYTES_WITH_XSTATE_BV + return (FPREG_FpxSwBytes(uc)->xstate_bv & XSTATE_YMM) != 0; +#else + return (FPREG_FpxSwBytes(uc)->xfeatures & XSTATE_YMM) != 0; +#endif +} + +inline void *FPREG_Xstate_Ymmh(const ucontext_t *uc) +{ + static_assert_no_msg(sizeof(reinterpret_cast<_xstate *>(FPREG_Fpstate(uc))->ymmh.ymmh_space) == 16 * 16); + _ASSERTE(FPREG_HasYmmRegisters(uc)); + + return reinterpret_cast<_xstate *>(FPREG_Fpstate(uc))->ymmh.ymmh_space; +} + +#endif // XSTATE_SUPPORTED + +///////////////////// + +#else // HOST_64BIT + +#define MCREG_Ebx(mc) ((mc).gregs[REG_EBX]) +#define MCREG_Ecx(mc) ((mc).gregs[REG_ECX]) +#define MCREG_Edx(mc) ((mc).gregs[REG_EDX]) +#define MCREG_Esi(mc) ((mc).gregs[REG_ESI]) +#define MCREG_Edi(mc) ((mc).gregs[REG_EDI]) +#define MCREG_Ebp(mc) ((mc).gregs[REG_EBP]) +#define MCREG_Eax(mc) ((mc).gregs[REG_EAX]) +#define MCREG_Eip(mc) ((mc).gregs[REG_EIP]) +#define MCREG_Esp(mc) ((mc).gregs[REG_ESP]) +#define MCREG_SegCs(mc) ((mc).gregs[REG_CS]) +#define MCREG_SegSs(mc) ((mc).gregs[REG_SS]) + +#endif // HOST_64BIT + +#ifdef REG_EFL +#define MCREG_EFlags(mc) ((mc).gregs[REG_EFL]) +#else +#define MCREG_EFlags(mc) ((mc).gregs[EFL]) +#endif + +#else // HAVE_GREGSET_T + +#ifdef HOST_64BIT + +#if defined(HOST_ARM64) +#define MCREG_X0(mc) ((mc).regs[0]) +#define MCREG_X1(mc) ((mc).regs[1]) +#define MCREG_X2(mc) ((mc).regs[2]) +#define MCREG_X3(mc) ((mc).regs[3]) +#define MCREG_X4(mc) ((mc).regs[4]) +#define MCREG_X5(mc) ((mc).regs[5]) +#define MCREG_X6(mc) ((mc).regs[6]) +#define MCREG_X7(mc) ((mc).regs[7]) +#define MCREG_X8(mc) ((mc).regs[8]) +#define MCREG_X9(mc) ((mc).regs[9]) +#define MCREG_X10(mc) ((mc).regs[10]) +#define MCREG_X11(mc) ((mc).regs[11]) +#define MCREG_X12(mc) ((mc).regs[12]) +#define MCREG_X13(mc) ((mc).regs[13]) +#define MCREG_X14(mc) ((mc).regs[14]) +#define MCREG_X15(mc) ((mc).regs[15]) +#define MCREG_X16(mc) ((mc).regs[16]) +#define MCREG_X17(mc) ((mc).regs[17]) +#define MCREG_X18(mc) ((mc).regs[18]) +#define MCREG_X19(mc) ((mc).regs[19]) +#define MCREG_X20(mc) ((mc).regs[20]) +#define MCREG_X21(mc) ((mc).regs[21]) +#define MCREG_X22(mc) ((mc).regs[22]) +#define MCREG_X23(mc) ((mc).regs[23]) +#define MCREG_X24(mc) ((mc).regs[24]) +#define MCREG_X25(mc) ((mc).regs[25]) +#define MCREG_X26(mc) ((mc).regs[26]) +#define MCREG_X27(mc) ((mc).regs[27]) +#define MCREG_X28(mc) ((mc).regs[28]) +#define MCREG_Fp(mc) ((mc).regs[29]) +#define MCREG_Lr(mc) ((mc).regs[30]) + +#define MCREG_Sp(mc) ((mc).sp) +#define MCREG_Pc(mc) ((mc).pc) +#define MCREG_Cpsr(mc) ((mc).pstate) + + +inline +fpsimd_context* GetNativeSigSimdContext(native_context_t *mc) +{ + size_t size = 0; + + do + { + fpsimd_context* fp = reinterpret_cast(&mc->uc_mcontext.__reserved[size]); + + if(fp->head.magic == FPSIMD_MAGIC) + { + _ASSERTE(fp->head.size >= sizeof(fpsimd_context)); + _ASSERTE(size + fp->head.size <= sizeof(mc->uc_mcontext.__reserved)); + + return fp; + } + + if (fp->head.size == 0) + { + break; + } + + size += fp->head.size; + } while (size + sizeof(fpsimd_context) <= sizeof(mc->uc_mcontext.__reserved)); + + _ASSERTE(false); + + return nullptr; +} + +inline +const fpsimd_context* GetConstNativeSigSimdContext(const native_context_t *mc) +{ + return GetNativeSigSimdContext(const_cast(mc)); +} + +#else + // For FreeBSD, as found in x86/ucontext.h +#define MCREG_Rbp(mc) ((mc).mc_rbp) +#define MCREG_Rip(mc) ((mc).mc_rip) +#define MCREG_Rsp(mc) ((mc).mc_rsp) +#define MCREG_Rsi(mc) ((mc).mc_rsi) +#define MCREG_Rdi(mc) ((mc).mc_rdi) +#define MCREG_Rbx(mc) ((mc).mc_rbx) +#define MCREG_Rdx(mc) ((mc).mc_rdx) +#define MCREG_Rcx(mc) ((mc).mc_rcx) +#define MCREG_Rax(mc) ((mc).mc_rax) +#define MCREG_R8(mc) ((mc).mc_r8) +#define MCREG_R9(mc) ((mc).mc_r9) +#define MCREG_R10(mc) ((mc).mc_r10) +#define MCREG_R11(mc) ((mc).mc_r11) +#define MCREG_R12(mc) ((mc).mc_r12) +#define MCREG_R13(mc) ((mc).mc_r13) +#define MCREG_R14(mc) ((mc).mc_r14) +#define MCREG_R15(mc) ((mc).mc_r15) +#define MCREG_EFlags(mc) ((mc).mc_rflags) +#define MCREG_SegCs(mc) ((mc).mc_cs) + + // from x86/fpu.h: struct __envxmm64 +#define FPSTATE(uc) ((savefpu*)((uc)->uc_mcontext.mc_fpstate)) +#define FPREG_ControlWord(uc) FPSTATE(uc)->sv_env.en_cw +#define FPREG_StatusWord(uc) FPSTATE(uc)->sv_env.en_sw +#define FPREG_TagWord(uc) FPSTATE(uc)->sv_env.en_tw +#define FPREG_MxCsr(uc) FPSTATE(uc)->sv_env.en_mxcsr +#define FPREG_MxCsr_Mask(uc) FPSTATE(uc)->sv_env.en_mxcsr_mask +#define FPREG_ErrorOffset(uc) *(DWORD*) &(FPSTATE(uc)->sv_env.en_rip) +#define FPREG_ErrorSelector(uc) *((WORD*) &(FPSTATE(uc)->sv_env.en_rip) + 2) +#define FPREG_DataOffset(uc) *(DWORD*) &(FPSTATE(uc)->sv_env.en_rdp) +#define FPREG_DataSelector(uc) *((WORD*) &(FPSTATE(uc)->sv_env.en_rdp) + 2) + +#define FPREG_Xmm(uc, index) *(M128A*) &(FPSTATE(uc)->sv_xmm[index]) +#define FPREG_St(uc, index) *(M128A*) &(FPSTATE(uc)->sv_fp[index].fp_acc) +#endif + +#else // HOST_64BIT + +#if defined(HOST_ARM) + +#define MCREG_R0(mc) ((mc).arm_r0) +#define MCREG_R1(mc) ((mc).arm_r1) +#define MCREG_R2(mc) ((mc).arm_r2) +#define MCREG_R3(mc) ((mc).arm_r3) +#define MCREG_R4(mc) ((mc).arm_r4) +#define MCREG_R5(mc) ((mc).arm_r5) +#define MCREG_R6(mc) ((mc).arm_r6) +#define MCREG_R7(mc) ((mc).arm_r7) +#define MCREG_R8(mc) ((mc).arm_r8) +#define MCREG_R9(mc) ((mc).arm_r9) +#define MCREG_R10(mc) ((mc).arm_r10) +#define MCREG_R11(mc) ((mc).arm_fp) +#define MCREG_R12(mc) ((mc).arm_ip) +#define MCREG_Sp(mc) ((mc).arm_sp) +#define MCREG_Lr(mc) ((mc).arm_lr) +#define MCREG_Pc(mc) ((mc).arm_pc) +#define MCREG_Cpsr(mc) ((mc).arm_cpsr) + + +// Flatterned layout of the arm kernel struct vfp_sigframe +struct VfpSigFrame +{ + DWORD magic; + DWORD size; + DWORD64 D[32]; // Some arm cpus have 16 D registers. The kernel will ignore the extra. + DWORD Fpscr; + DWORD Padding; + DWORD Fpexc; + DWORD Fpinst; + DWORD Fpinst2; + DWORD Padding2; +}; + +inline +VfpSigFrame* GetNativeSigSimdContext(native_context_t *mc) +{ + size_t size = 0; + + const DWORD VfpMagic = 0x56465001; // VFP_MAGIC from arm kernel + + do + { + VfpSigFrame* fp = reinterpret_cast(&mc->uc_regspace[size]); + + if (fp->magic == VfpMagic) + { + _ASSERTE(fp->size == sizeof(VfpSigFrame)); + _ASSERTE(size + fp->size <= sizeof(mc->uc_regspace)); + + return fp; + } + + if (fp->size == 0) + { + break; + } + + size += fp->size; + } while (size + sizeof(VfpSigFrame) <= sizeof(mc->uc_regspace)); + + // VFP is not required on all armv7 processors, this structure may not be present + + return nullptr; +} + +inline +const VfpSigFrame* GetConstNativeSigSimdContext(const native_context_t *mc) +{ + return GetNativeSigSimdContext(const_cast(mc)); +} + +#elif defined(HOST_X86) + +#define MCREG_Ebx(mc) ((mc).mc_ebx) +#define MCREG_Ecx(mc) ((mc).mc_ecx) +#define MCREG_Edx(mc) ((mc).mc_edx) +#define MCREG_Esi(mc) ((mc).mc_esi) +#define MCREG_Edi(mc) ((mc).mc_edi) +#define MCREG_Ebp(mc) ((mc).mc_ebp) +#define MCREG_Eax(mc) ((mc).mc_eax) +#define MCREG_Eip(mc) ((mc).mc_eip) +#define MCREG_SegCs(mc) ((mc).mc_cs) +#define MCREG_EFlags(mc) ((mc).mc_eflags) +#define MCREG_Esp(mc) ((mc).mc_esp) +#define MCREG_SegSs(mc) ((mc).mc_ss) + +#else +#error "Unsupported arch" +#endif + +#endif // HOST_64BIT + +#endif // HAVE_GREGSET_T + + +#if HAVE_PT_REGS + +#ifdef HOST_64BIT +#define PTREG_Rbx(ptreg) ((ptreg).rbx) +#define PTREG_Rcx(ptreg) ((ptreg).rcx) +#define PTREG_Rdx(ptreg) ((ptreg).rdx) +#define PTREG_Rsi(ptreg) ((ptreg).rsi) +#define PTREG_Rdi(ptreg) ((ptreg).rdi) +#define PTREG_Rbp(ptreg) ((ptreg).rbp) +#define PTREG_Rax(ptreg) ((ptreg).rax) +#define PTREG_Rip(ptreg) ((ptreg).rip) +#define PTREG_SegCs(ptreg) ((ptreg).cs) +#define PTREG_SegSs(ptreg) ((ptreg).ss) +#define PTREG_Rsp(ptreg) ((ptreg).rsp) +#define PTREG_R8(ptreg) ((ptreg).r8) +#define PTREG_R9(ptreg) ((ptreg).r9) +#define PTREG_R10(ptreg) ((ptreg).r10) +#define PTREG_R11(ptreg) ((ptreg).r11) +#define PTREG_R12(ptreg) ((ptreg).r12) +#define PTREG_R13(ptreg) ((ptreg).r13) +#define PTREG_R14(ptreg) ((ptreg).r14) +#define PTREG_R15(ptreg) ((ptreg).r15) + +#else // HOST_64BIT + +#if defined(HOST_ARM) +#define PTREG_R0(ptreg) ((ptreg).uregs[0]) +#define PTREG_R1(ptreg) ((ptreg).uregs[1]) +#define PTREG_R2(ptreg) ((ptreg).uregs[2]) +#define PTREG_R3(ptreg) ((ptreg).uregs[3]) +#define PTREG_R4(ptreg) ((ptreg).uregs[4]) +#define PTREG_R5(ptreg) ((ptreg).uregs[5]) +#define PTREG_R6(ptreg) ((ptreg).uregs[6]) +#define PTREG_R7(ptreg) ((ptreg).uregs[7]) +#define PTREG_R8(ptreg) ((ptreg).uregs[8]) +#define PTREG_R9(ptreg) ((ptreg).uregs[9]) +#define PTREG_R10(ptreg) ((ptreg).uregs[10]) +#define PTREG_R11(ptreg) ((ptreg).uregs[11]) +#define PTREG_R12(ptreg) ((ptreg).uregs[12]) +#define PTREG_Sp(ptreg) ((ptreg).uregs[13]) +#define PTREG_Lr(ptreg) ((ptreg).uregs[14]) +#define PTREG_Pc(ptreg) ((ptreg).uregs[15]) +#define PTREG_Cpsr(ptreg) ((ptreg).uregs[16]) +#elif defined(HOST_X86) +#define PTREG_Ebx(ptreg) ((ptreg).ebx) +#define PTREG_Ecx(ptreg) ((ptreg).ecx) +#define PTREG_Edx(ptreg) ((ptreg).edx) +#define PTREG_Esi(ptreg) ((ptreg).esi) +#define PTREG_Edi(ptreg) ((ptreg).edi) +#define PTREG_Ebp(ptreg) ((ptreg).ebp) +#define PTREG_Eax(ptreg) ((ptreg).eax) +#define PTREG_Eip(ptreg) ((ptreg).eip) +#define PTREG_SegCs(ptreg) ((ptreg).xcs) +#define PTREG_SegSs(ptreg) ((ptreg).xss) +#define PTREG_Esp(ptreg) ((ptreg).esp) +#else +#error "Unsupported arch" +#endif + +#endif // HOST_64BIT + + +#define PTREG_EFlags(ptreg) ((ptreg).eflags) + +#endif // HAVE_PT_REGS + + + +#if HAVE_BSD_REGS_T + +#ifndef BSD_REGS_STYLE +#error "struct reg" has unrecognized format +#endif + +#ifdef HOST_64BIT + +#define BSDREG_Rbx(reg) BSD_REGS_STYLE(reg,RBX,rbx) +#define BSDREG_Rcx(reg) BSD_REGS_STYLE(reg,RCX,rcx) +#define BSDREG_Rdx(reg) BSD_REGS_STYLE(reg,RDX,rdx) +#define BSDREG_Rsi(reg) BSD_REGS_STYLE(reg,RSI,rsi) +#define BSDREG_Rdi(reg) BSD_REGS_STYLE(reg,RDI,rdi) +#define BSDREG_Rbp(reg) BSD_REGS_STYLE(reg,RBP,rbp) +#define BSDREG_Rax(reg) BSD_REGS_STYLE(reg,RAX,rax) +#define BSDREG_Rip(reg) BSD_REGS_STYLE(reg,RIP,rip) +#define BSDREG_SegCs(reg) BSD_REGS_STYLE(reg,CS,cs) +#define BSDREG_SegSs(reg) BSD_REGS_STYLE(reg,SS,ss) +#define BSDREG_Rsp(reg) BSD_REGS_STYLE(reg,RSP,rsp) +#define BSDREG_R8(reg) BSD_REGS_STYLE(reg,R8,r8) +#define BSDREG_R9(reg) BSD_REGS_STYLE(reg,R9,r9) +#define BSDREG_R10(reg) BSD_REGS_STYLE(reg,R10,r10) +#define BSDREG_R11(reg) BSD_REGS_STYLE(reg,R11,r11) +#define BSDREG_R12(reg) BSD_REGS_STYLE(reg,R12,r12) +#define BSDREG_R13(reg) BSD_REGS_STYLE(reg,R13,r13) +#define BSDREG_R14(reg) BSD_REGS_STYLE(reg,R14,r14) +#define BSDREG_R15(reg) BSD_REGS_STYLE(reg,R15,r15) +#define BSDREG_EFlags(reg) BSD_REGS_STYLE(reg,RFLAGS,rflags) + +#else // HOST_64BIT + +#define BSDREG_Ebx(reg) BSD_REGS_STYLE(reg,EBX,ebx) +#define BSDREG_Ecx(reg) BSD_REGS_STYLE(reg,ECX,ecx) +#define BSDREG_Edx(reg) BSD_REGS_STYLE(reg,EDX,edx) +#define BSDREG_Esi(reg) BSD_REGS_STYLE(reg,ESI,esi) +#define BSDREG_Edi(reg) BSD_REGS_STYLE(reg,EDI,edi) +#define BSDREG_Ebp(reg) BSD_REGS_STYLE(reg,EDP,ebp) +#define BSDREG_Eax(reg) BSD_REGS_STYLE(reg,EAX,eax) +#define BSDREG_Eip(reg) BSD_REGS_STYLE(reg,EIP,eip) +#define BSDREG_SegCs(reg) BSD_REGS_STYLE(reg,CS,cs) +#define BSDREG_EFlags(reg) BSD_REGS_STYLE(reg,EFLAGS,eflags) +#define BSDREG_Esp(reg) BSD_REGS_STYLE(reg,ESP,esp) +#define BSDREG_SegSs(reg) BSD_REGS_STYLE(reg,SS,ss) + +#endif // HOST_64BIT + +#endif // HAVE_BSD_REGS_T + +inline static DWORD64 CONTEXTGetPC(LPCONTEXT pContext) +{ +#if defined(HOST_AMD64) + return pContext->Rip; +#elif defined(HOST_X86) + return pContext->Eip; +#elif defined(HOST_ARM64) || defined(HOST_ARM) + return pContext->Pc; +#else +#error "don't know how to get the program counter for this architecture" +#endif +} + +inline static void CONTEXTSetPC(LPCONTEXT pContext, DWORD64 pc) +{ +#if defined(HOST_AMD64) + pContext->Rip = pc; +#elif defined(HOST_X86) + pContext->Eip = pc; +#elif defined(HOST_ARM64) || defined(HOST_ARM) + pContext->Pc = pc; +#else +#error "don't know how to set the program counter for this architecture" +#endif +} + +inline static DWORD64 CONTEXTGetFP(LPCONTEXT pContext) +{ +#if defined(HOST_AMD64) + return pContext->Rbp; +#elif defined(HOST_X86) + return pContext->Ebp; +#elif defined(HOST_ARM) + return pContext->R7; +#elif defined(HOST_ARM64) + return pContext->Fp; +#else +#error "don't know how to get the frame pointer for this architecture" +#endif +} + +/*++ +Function : + CONTEXT_CaptureContext + + Captures the context of the caller. + The returned context is suitable for performing + a virtual unwind. + +Parameters : + LPCONTEXT lpContext : new context + +--*/ +void +PALAPI +CONTEXT_CaptureContext( + LPCONTEXT lpContext + ); + +/*++ +Function : + CONTEXT_SetThreadContext + + Processor-dependent implementation of SetThreadContext + +Parameters : + HANDLE hThread : thread whose context is to be set + CONTEXT *lpContext : new context + +Return value : + TRUE on success, FALSE on failure + +--*/ +BOOL +CONTEXT_SetThreadContext( + DWORD dwProcessId, + pthread_t self, + CONST CONTEXT *lpContext + ); + +/*++ +Function : + CONTEXT_GetThreadContext + + Processor-dependent implementation of GetThreadContext + +Parameters : + HANDLE hThread : thread whose context is to retrieved + LPCONTEXT lpContext : destination for thread's context + +Return value : + TRUE on success, FALSE on failure + +--*/ +BOOL +CONTEXT_GetThreadContext( + DWORD dwProcessId, + pthread_t self, + LPCONTEXT lpContext); + +#if HAVE_MACH_EXCEPTIONS +/*++ +Function: + CONTEXT_GetThreadContextFromPort + + Helper for GetThreadContext that uses a mach_port +--*/ +kern_return_t +CONTEXT_GetThreadContextFromPort( + mach_port_t Port, + LPCONTEXT lpContext); + +/*++ +Function: + SetThreadContextOnPort + + Helper for CONTEXT_SetThreadContext +--*/ +kern_return_t +CONTEXT_SetThreadContextOnPort( + mach_port_t Port, + IN CONST CONTEXT *lpContext); + +/*++ +Function: + GetThreadContextFromThreadState + + Helper for mach exception support +--*/ +void +CONTEXT_GetThreadContextFromThreadState( + thread_state_flavor_t stateFlavor, + thread_state_t threadState, + LPCONTEXT lpContext); + +#else // HAVE_MACH_EXCEPTIONS +/*++ +Function : + CONTEXTToNativeContext + + Converts a CONTEXT record to a native context. + +Parameters : + CONST CONTEXT *lpContext : CONTEXT to convert, including + flags that determine which registers are valid in + lpContext and which ones to set in native + native_context_t *native : native context to fill in + +Return value : + None + +--*/ +void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native); + +/*++ +Function : + CONTEXTFromNativeContext + + Converts a native context to a CONTEXT record. + +Parameters : + const native_context_t *native : native context to convert + LPCONTEXT lpContext : CONTEXT to fill in + ULONG contextFlags : flags that determine which registers are valid in + native and which ones to set in lpContext + +Return value : + None + +--*/ +void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContext, + ULONG contextFlags); + +/*++ +Function : + GetNativeContextPC + + Returns the program counter from the native context. + +Parameters : + const native_context_t *context : native context + +Return value : + The program counter from the native context. + +--*/ +LPVOID GetNativeContextPC(const native_context_t *context); + +/*++ +Function : + GetNativeContextSP + + Returns the stack pointer from the native context. + +Parameters : + const native_context_t *native : native context + +Return value : + The stack pointer from the native context. + +--*/ +LPVOID GetNativeContextSP(const native_context_t *context); + +/*++ +Function : + CONTEXTGetExceptionCodeForSignal + + Translates signal and context information to a Win32 exception code. + +Parameters : + const siginfo_t *siginfo : signal information from a signal handler + const native_context_t *context : context information + +Return value : + The Win32 exception code that corresponds to the signal and context + information. + +--*/ +DWORD CONTEXTGetExceptionCodeForSignal(const siginfo_t *siginfo, + const native_context_t *context); + +#endif // HAVE_MACH_EXCEPTIONS else + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // _PAL_CONTEXT_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/corunix.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/corunix.hpp new file mode 100644 index 0000000..af6b239 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/corunix.hpp @@ -0,0 +1,1272 @@ +// 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: + + corunix.hpp + +Abstract: + + Internal interface and object definitions + + + +--*/ + +#ifndef _CORUNIX_H +#define _CORUNIX_H + +#include "palinternal.h" + +namespace CorUnix +{ + typedef DWORD PAL_ERROR; + + // + // Forward declarations for classes defined in other headers + // + + class CPalThread; + + // + // Forward declarations for items in this header + // + + class CObjectType; + class IPalObject; + + // + // A simple counted string class. Using counted strings + // allows for some optimizations when searching for a matching string. + // + + class CPalString + { + protected: + + const WCHAR *m_pwsz; // NULL terminated + + // + // Length of string, not including terminating NULL + // + + DWORD m_dwStringLength; + + // + // Length of buffer backing string; must be at least 1+dwStringLength + // + + DWORD m_dwMaxLength; + + public: + + CPalString() + : + m_pwsz(NULL), + m_dwStringLength(0), + m_dwMaxLength(0) + { + }; + + CPalString( + const WCHAR *pwsz + ) + { + SetString(pwsz); + }; + + void + SetString( + const WCHAR *pwsz + ) + { + SetStringWithLength(pwsz, PAL_wcslen(pwsz)); + }; + + void + SetStringWithLength( + const WCHAR *pwsz, + DWORD dwStringLength + ) + { + m_pwsz = pwsz; + m_dwStringLength = dwStringLength; + m_dwMaxLength = m_dwStringLength + 1; + + }; + + PAL_ERROR + CopyString( + CPalString *psSource + ); + + void + FreeBuffer(); + + const WCHAR * + GetString() + { + return m_pwsz; + }; + + DWORD + GetStringLength() + { + return m_dwStringLength; + }; + + DWORD + GetMaxLength() + { + return m_dwMaxLength; + }; + + }; + + // + // Signature of the cleanup routine that is to be called for an object + // type when: + // 1) The object's refcount drops to 0 + // 2) A process is shutting down + // 3) A process has released all local references to the object + // + // The cleanup routine must only cleanup the object's shared state + // when the last parameter (fCleanupSharedSate) is TRUE. When + // fCleanupSharedState is FALSE the cleanup routine must not attempt + // to access the shared data for the object, as another process may + // have already deleted it. ($$REIVEW -- would someone ever need access + // to the shared data in order to cleanup process local state?) + // + // When the third paramter (fShutdown) is TRUE the process is in + // the act of exiting. The cleanup routine should not perform any + // unnecessary cleanup operations (e.g., closing file descriptors, + // since the OS will automatically close them when the process exits) + // in this situation. + // + + typedef void (*OBJECTCLEANUPROUTINE) ( + CPalThread *, // pThread + IPalObject *, // pObjectToCleanup + bool, // fShutdown + bool // fCleanupSharedState + ); + + // + // Signature of the initialization routine that is to be called + // when the first reference within a process to an existing + // object comes into existence. This routine is responsible for + // initializing the object's process local data, based on the + // immutable and shared data. The thread that this routine is + // called on holds an implicit read lock on the shared data. + // + + typedef PAL_ERROR (*OBJECTINITROUTINE) ( + CPalThread *, // pThread + CObjectType *, // pObjectType + void *, // pImmutableData + void *, // pSharedData + void * // pProcessLocalData + ); + + typedef void (*OBJECT_IMMUTABLE_DATA_COPY_ROUTINE) ( + void *, + void *); + typedef void (*OBJECT_IMMUTABLE_DATA_CLEANUP_ROUTINE) ( + void *); + typedef void (*OBJECT_PROCESS_LOCAL_DATA_CLEANUP_ROUTINE) ( + CPalThread *, // pThread + IPalObject *); + + enum PalObjectTypeId + { + otiAutoResetEvent = 0, + otiManualResetEvent, + otiMutex, + otiNamedMutex, + otiSemaphore, + otiFile, + otiFileMapping, + otiSocket, + otiProcess, + otiThread, + otiIOCompletionPort, + ObjectTypeIdCount // This entry must come last in the enumeration + }; + + // + // There should be one instance of CObjectType for each supported + // type in a process; this allows for pointer equality tests + // to be used (though in general it's probably better to use + // checks based on the type ID). All members of this structure are + // immutable. + // + // The data size members control how much space will be allocated for + // instances of this object. Any or all of those members may be 0. + // + // dwSupportedAccessRights is the mask of valid access bits for this + // object type. Supported generic rights should not be included in + // this member. + // + // The generic access rights mapping (structure TBD) defines how the + // supported generic access rights (e.g., GENERIC_READ) map to the + // specific access rights for this object type. + // + // If instances of this object may have a security descriptor set on + // them eSecuritySupport should be set to SecuritySupported. If the OS can + // persist security information for the object type (as would be the case + // for, say, files) eSecurityPersistence should be set to + // OSPersistedSecurityInfo. + // + // If the object may have a name eObjectNameSupport should be + // ObjectCanHaveName. A named object can be opened in more than one + // process. + // + // If it is possible to duplicate a handle to an object across process + // boundaries then eHandleDuplicationSupport should be set to + // CrossProcessDuplicationAllowed. Note that it is possible to have + // an object type where eObjectNameSupport is ObjectCanHaveName and + // eHandleDuplicationSupport is LocalDuplicationOnly. For these object + // types an unnamed object instance will only have references from + // the creating process. + // + // If the object may be waited on eSynchronizationSupport should be + // WaitableObject. (Note that this implies that object type supports + // the SYNCHRONIZE access right.) + // + // The remaining members describe the wait-object semantics for the + // object type when eSynchronizationSupport is WaitableObject: + // + // * eSignalingSemantics: SingleTransitionObject for objects that, once + // they transition to the signaled state, can never transition back to + // the unsignaled state (e.g., processes and threads) + // + // * eThreadReleaseSemantics: if ThreadReleaseAltersSignalCount the object's + // signal count is decremented when a waiting thread is released; otherwise, + // the signal count is not modified (as is desired for a manual reset event). + // Must be ThreadReleaseHasNoSideEffects if eSignalingSemantics is + // SingleTransitionObject + // + // * eOwnershipSemantics: OwnershipTracked only for mutexes, for which the + // previous two items must also ObjectCanBeUnsignaled and + // ThreadReleaseAltersSignalCount. + // + + class CObjectType + { + public: + + enum SecuritySupport + { + SecuritySupported, + SecurityNotSupported + }; + + enum SecurityPersistence + { + OSPersistedSecurityInfo, + SecurityInfoNotPersisted + }; + + enum ObjectNameSupport + { + ObjectCanHaveName, + UnnamedObject + }; + + enum HandleDuplicationSupport + { + CrossProcessDuplicationAllowed, + LocalDuplicationOnly + }; + + enum SynchronizationSupport + { + WaitableObject, + UnwaitableObject + }; + + enum SignalingSemantics + { + ObjectCanBeUnsignaled, + SingleTransitionObject, + SignalingNotApplicable + }; + + enum ThreadReleaseSemantics + { + ThreadReleaseAltersSignalCount, + ThreadReleaseHasNoSideEffects, + ThreadReleaseNotApplicable + }; + + enum OwnershipSemantics + { + OwnershipTracked, + NoOwner, + OwnershipNotApplicable + }; + + private: + + // + // Array that maps object type IDs to the corresponding + // CObjectType instance + // + + static CObjectType* s_rgotIdMapping[]; + + PalObjectTypeId m_eTypeId; + OBJECTCLEANUPROUTINE m_pCleanupRoutine; + OBJECTINITROUTINE m_pInitRoutine; + DWORD m_dwImmutableDataSize; + OBJECT_IMMUTABLE_DATA_COPY_ROUTINE m_pImmutableDataCopyRoutine; + OBJECT_IMMUTABLE_DATA_CLEANUP_ROUTINE m_pImmutableDataCleanupRoutine; + DWORD m_dwProcessLocalDataSize; + OBJECT_PROCESS_LOCAL_DATA_CLEANUP_ROUTINE m_pProcessLocalDataCleanupRoutine; + DWORD m_dwSharedDataSize; + DWORD m_dwSupportedAccessRights; + // Generic access rights mapping + SecuritySupport m_eSecuritySupport; + SecurityPersistence m_eSecurityPersistence; + ObjectNameSupport m_eObjectNameSupport; + HandleDuplicationSupport m_eHandleDuplicationSupport; + SynchronizationSupport m_eSynchronizationSupport; + SignalingSemantics m_eSignalingSemantics; + ThreadReleaseSemantics m_eThreadReleaseSemantics; + OwnershipSemantics m_eOwnershipSemantics; + + public: + + CObjectType( + PalObjectTypeId eTypeId, + OBJECTCLEANUPROUTINE pCleanupRoutine, + OBJECTINITROUTINE pInitRoutine, + DWORD dwImmutableDataSize, + OBJECT_IMMUTABLE_DATA_COPY_ROUTINE pImmutableDataCopyRoutine, + OBJECT_IMMUTABLE_DATA_CLEANUP_ROUTINE pImmutableDataCleanupRoutine, + DWORD dwProcessLocalDataSize, + OBJECT_PROCESS_LOCAL_DATA_CLEANUP_ROUTINE pProcessLocalDataCleanupRoutine, + DWORD dwSharedDataSize, + DWORD dwSupportedAccessRights, + SecuritySupport eSecuritySupport, + SecurityPersistence eSecurityPersistence, + ObjectNameSupport eObjectNameSupport, + HandleDuplicationSupport eHandleDuplicationSupport, + SynchronizationSupport eSynchronizationSupport, + SignalingSemantics eSignalingSemantics, + ThreadReleaseSemantics eThreadReleaseSemantics, + OwnershipSemantics eOwnershipSemantics + ) + : + m_eTypeId(eTypeId), + m_pCleanupRoutine(pCleanupRoutine), + m_pInitRoutine(pInitRoutine), + m_dwImmutableDataSize(dwImmutableDataSize), + m_pImmutableDataCopyRoutine(pImmutableDataCopyRoutine), + m_pImmutableDataCleanupRoutine(pImmutableDataCleanupRoutine), + m_dwProcessLocalDataSize(dwProcessLocalDataSize), + m_pProcessLocalDataCleanupRoutine(pProcessLocalDataCleanupRoutine), + m_dwSharedDataSize(dwSharedDataSize), + m_dwSupportedAccessRights(dwSupportedAccessRights), + m_eSecuritySupport(eSecuritySupport), + m_eSecurityPersistence(eSecurityPersistence), + m_eObjectNameSupport(eObjectNameSupport), + m_eHandleDuplicationSupport(eHandleDuplicationSupport), + m_eSynchronizationSupport(eSynchronizationSupport), + m_eSignalingSemantics(eSignalingSemantics), + m_eThreadReleaseSemantics(eThreadReleaseSemantics), + m_eOwnershipSemantics(eOwnershipSemantics) + { + s_rgotIdMapping[eTypeId] = this; + }; + + static + CObjectType * + GetObjectTypeById( + PalObjectTypeId otid + ) + { + return s_rgotIdMapping[otid]; + }; + + PalObjectTypeId + GetId( + void + ) + { + return m_eTypeId; + }; + + OBJECTCLEANUPROUTINE + GetObjectCleanupRoutine( + void + ) + { + return m_pCleanupRoutine; + }; + + OBJECTINITROUTINE + GetObjectInitRoutine( + void + ) + { + return m_pInitRoutine; + }; + + DWORD + GetImmutableDataSize( + void + ) + { + return m_dwImmutableDataSize; + }; + + void + SetImmutableDataCopyRoutine( + OBJECT_IMMUTABLE_DATA_COPY_ROUTINE ptr + ) + { + m_pImmutableDataCopyRoutine = ptr; + }; + + OBJECT_IMMUTABLE_DATA_COPY_ROUTINE + GetImmutableDataCopyRoutine( + void + ) + { + return m_pImmutableDataCopyRoutine; + }; + + void + SetImmutableDataCleanupRoutine( + OBJECT_IMMUTABLE_DATA_CLEANUP_ROUTINE ptr + ) + { + m_pImmutableDataCleanupRoutine = ptr; + }; + + OBJECT_IMMUTABLE_DATA_CLEANUP_ROUTINE + GetImmutableDataCleanupRoutine( + void + ) + { + return m_pImmutableDataCleanupRoutine; + } + + DWORD + GetProcessLocalDataSize( + void + ) + { + return m_dwProcessLocalDataSize; + }; + + OBJECT_PROCESS_LOCAL_DATA_CLEANUP_ROUTINE + GetProcessLocalDataCleanupRoutine( + void + ) + { + return m_pProcessLocalDataCleanupRoutine; + } + + DWORD + GetSharedDataSize( + void + ) + { + return m_dwSharedDataSize; + }; + + DWORD + GetSupportedAccessRights( + void + ) + { + return m_dwSupportedAccessRights; + }; + + // Generic access rights mapping + + SecuritySupport + GetSecuritySupport( + void + ) + { + return m_eSecuritySupport; + }; + + SecurityPersistence + GetSecurityPersistence( + void + ) + { + return m_eSecurityPersistence; + }; + + ObjectNameSupport + GetObjectNameSupport( + void + ) + { + return m_eObjectNameSupport; + }; + + HandleDuplicationSupport + GetHandleDuplicationSupport( + void + ) + { + return m_eHandleDuplicationSupport; + }; + + SynchronizationSupport + GetSynchronizationSupport( + void + ) + { + return m_eSynchronizationSupport; + }; + + SignalingSemantics + GetSignalingSemantics( + void + ) + { + return m_eSignalingSemantics; + }; + + ThreadReleaseSemantics + GetThreadReleaseSemantics( + void + ) + { + return m_eThreadReleaseSemantics; + }; + + OwnershipSemantics + GetOwnershipSemantics( + void + ) + { + return m_eOwnershipSemantics; + }; + }; + + class CAllowedObjectTypes + { + private: + + bool m_rgfAllowedTypes[ObjectTypeIdCount]; + + public: + + bool + IsTypeAllowed(PalObjectTypeId eTypeId); + + // + // Constructor for multiple allowed types + // + + CAllowedObjectTypes( + PalObjectTypeId rgAllowedTypes[], + DWORD dwAllowedTypeCount + ); + + // + // Single allowed type constructor + // + + CAllowedObjectTypes( + PalObjectTypeId eAllowedType + ); + + // + // Allow all types or no types constructor + // + + CAllowedObjectTypes( + bool fAllowAllObjectTypes + ) + { + for (DWORD dw = 0; dw < ObjectTypeIdCount; dw += 1) + { + m_rgfAllowedTypes[dw] = fAllowAllObjectTypes; + } + }; + + ~CAllowedObjectTypes() + { + }; + }; + + // + // Attributes for a given object instance. If the object does not have + // a name the sObjectName member should be zero'd out. If the default + // security attributes are desired then pSecurityAttributes should + // be NULL. + // + + class CObjectAttributes + { + public: + + CPalString sObjectName; + LPSECURITY_ATTRIBUTES pSecurityAttributes; + + CObjectAttributes( + const WCHAR *pwszObjectName, + LPSECURITY_ATTRIBUTES pSecurityAttributes_ + ) + : + pSecurityAttributes(pSecurityAttributes_) + { + if (NULL != pwszObjectName) + { + sObjectName.SetString(pwszObjectName); + } + }; + + CObjectAttributes() + : + pSecurityAttributes(NULL) + { + }; + }; + + // + // ISynchStateController is used to modify any object's synchronization + // state. It is intended to be used from within the APIs exposed for + // various objects (e.g., SetEvent, ReleaseMutex, etc.). + // + // Each ISynchStateController instance implicitly holds what should be + // viewed as the global dispatcher lock, and as such should be released + // as quickly as possible. An ISynchStateController instance is bound to + // the thread that requested it; it may not be passed to a different + // thread. + // + + class ISynchStateController + { + public: + + virtual + PAL_ERROR + GetSignalCount( + LONG *plSignalCount + ) = 0; + + virtual + PAL_ERROR + SetSignalCount( + LONG lNewCount + ) = 0; + + virtual + PAL_ERROR + IncrementSignalCount( + LONG lAmountToIncrement + ) = 0; + + virtual + PAL_ERROR + DecrementSignalCount( + LONG lAmountToDecrement + ) = 0; + + // + // The following two routines may only be used for object types + // where eOwnershipSemantics is OwnershipTracked (i.e., mutexes). + // + + // + // SetOwner is intended to be used in the implementation of + // CreateMutex when bInitialOwner is TRUE. It must be called + // before the new object instance is registered with the + // handle manager. Any other call to this method is an error. + // + + virtual + PAL_ERROR + SetOwner( + CPalThread *pNewOwningThread + ) = 0; + + // + // DecrementOwnershipCount returns an error if the object + // is unowned, or if the thread this controller is bound to + // is not the owner of the object. + // + + virtual + PAL_ERROR + DecrementOwnershipCount( + void + ) = 0; + + virtual + void + ReleaseController( + void + ) = 0; + }; + + // + // ISynchWaitController is used to indicate a thread's desire to wait for + // an object (which possibly includes detecting instances where the wait + // can be satisfied without blocking). It is intended to be used by object + // wait function (WaitForSingleObject, etc.). + // + // Each ISynchWaitController instance implicitly holds what should be + // viewed as the global dispatcher lock, and as such should be released + // as quickly as possible. An ISynchWaitController instance is bound to + // the thread that requested it; it may not be passed to a different + // thread. + // + // A thread may hold multiple ISynchWaitController instances + // simultaneously. + // + + enum WaitType + { + SingleObject, + MultipleObjectsWaitOne, + MultipleObjectsWaitAll + }; + + class ISynchWaitController + { + public: + + // + // CanThreadWaitWithoutBlocking informs the caller if a wait + // operation may succeed immediately, but does not actually + // alter any object state. ReleaseWaitingThreadWithoutBlocking + // alters the object state, and will return an error if it is + // not possible for the wait to be immediately satisfied. + // + + virtual + PAL_ERROR + CanThreadWaitWithoutBlocking( + bool *pfCanWaitWithoutBlocking, // OUT + bool *pfAbandoned + ) = 0; + + virtual + PAL_ERROR + ReleaseWaitingThreadWithoutBlocking( + ) = 0; + + // + // dwIndex is intended for MultipleObjectsWaitOne situations. The + // index for the object that becomes signaled and satisfies the + // wait will be returned in the call to BlockThread. + // + + virtual + PAL_ERROR + RegisterWaitingThread( + WaitType eWaitType, + DWORD dwIndex, + bool fAltertable, + bool fPrioritize + ) = 0; + + // + // Why is there no unregister waiting thread routine? Unregistration + // is the responsibility of the synchronization provider, not the + // implementation of the wait object routines. (I can be convinced + // that this isn't the best approach, though...) + // + + virtual + void + ReleaseController( + void + ) = 0; + }; + + enum LockType + { + ReadLock, + WriteLock + }; + + class IDataLock + { + public: + + // + // If a thread obtains a write lock but does not actually + // modify any data it should set fDataChanged to FALSE. If + // a thread obtain a read lock and does actually modify any + // data it should be taken out back and shot. + // + + virtual + void + ReleaseLock( + CPalThread *pThread, // IN, OPTIONAL + bool fDataChanged + ) = 0; + }; + + // + // The following two enums are part of the local object + // optimizations + // + + enum ObjectDomain + { + ProcessLocalObject, + SharedObject + }; + + enum WaitDomain + { + LocalWait, // All objects in the wait set are local to this process + MixedWait, // Some objects are local; some are shared + SharedWait // All objects in the wait set are shared + }; + + class IPalObject + { + public: + + virtual + CObjectType * + GetObjectType( + VOID + ) = 0; + + virtual + CObjectAttributes * + GetObjectAttributes( + VOID + ) = 0; + + virtual + PAL_ERROR + GetImmutableData( + void **ppvImmutableData // OUT + ) = 0; + + // + // The following two routines obtain either a read or write + // lock on the data in question. If a thread needs to examine + // both process-local and shared data simultaneously it must obtain + // the shared data first. A thread may not hold data locks + // on two different objects at the same time. + // + + virtual + PAL_ERROR + GetProcessLocalData( + CPalThread *pThread, // IN, OPTIONAL + LockType eLockRequest, + IDataLock **ppDataLock, // OUT + void **ppvProcessLocalData // OUT + ) = 0; + + virtual + PAL_ERROR + GetSharedData( + CPalThread *pThread, // IN, OPTIONAL + LockType eLockRequest, + IDataLock **ppDataLock, // OUT + void **ppvSharedData // OUT + ) = 0; + + // + // The following two routines obtain the global dispatcher lock. + // If a thread needs to make use of a synchronization interface + // and examine object data it must obtain the synchronization + // interface first. A thread is allowed to hold synchronization + // interfaces for multiple objects at the same time if it obtains + // all of the interfaces through a single call (see IPalSynchronizationManager + // below). + // + // The single-call restriction allows the underlying implementation + // to possibly segement the global dispatcher lock. If this restriction + // were not in place (i.e., if a single thread were allowed to call + // GetSynchXXXController for multiple objects) no such segmentation + // would be possible as there would be no way know in what order a + // thread would choose to obtain the controllers. + // + // Note: this design precludes simultaneous acquisition of both + // the state and wait controller for an object but there are + // currently no places where doing so would be necessary. + // + + virtual + PAL_ERROR + GetSynchStateController( + CPalThread *pThread, // IN, OPTIONAL + ISynchStateController **ppStateController // OUT + ) = 0; + + virtual + PAL_ERROR + GetSynchWaitController( + CPalThread *pThread, // IN, OPTIONAL + ISynchWaitController **ppWaitController // OUT + ) = 0; + + virtual + DWORD + AddReference( + void + ) = 0; + + virtual + DWORD + ReleaseReference( + CPalThread *pThread + ) = 0; + + // + // This routine is mainly intended for the synchronization + // manager. The promotion / process synch lock must be held + // before calling this routine. + // + + virtual + ObjectDomain + GetObjectDomain( + void + ) = 0; + + // + // This routine is only for use by the synchronization manager + // (specifically, for GetSynch*ControllersForObjects). The + // caller must have acquired the appropriate lock before + // (whatever exactly that must be) before calling this routine. + // + + virtual + PAL_ERROR + GetObjectSynchData( + VOID **ppvSynchData // OUT + ) = 0; + + }; + + class IPalProcess + { + public: + virtual + DWORD + GetProcessID( + void + ) = 0; + }; + + class IPalObjectManager + { + public: + + // + // Object creation (e.g., what is done by CreateEvent) is a two step + // process. First, the new object is allocated and the initial + // properties set (e.g., initially signaled). Next, the object is + // registered, yielding a handle. If an object of the same name + // and appropriate type already existed the returned handle will refer + // to the previously existing object, and the newly allocated object + // will have been thrown away. + // + // (The two phase process minimizes the amount of time that any + // namespace locks need to be held. While some wasted work may be + // done in the existing object case that work only impacts the calling + // thread. Checking first for existence and then allocating and + // initializing on failure requires any namespace lock to be held for + // a much longer period of time, impacting the entire system.) + // + + virtual + PAL_ERROR + AllocateObject( + CPalThread *pThread, // IN, OPTIONAL + CObjectType *pType, + CObjectAttributes *pAttributes, + IPalObject **ppNewObject // OUT + ) = 0; + + // + // After calling RegisterObject pObjectToRegister is no + // longer valid. If successful there are two references + // on the returned object -- one for the handle, and one + // for the instance returned in ppRegisteredObject. The + // caller, therefore, is responsible for releasing the + // latter. + // + // For named object pAllowedTypes specifies what type of + // existing objects can be returned in ppRegisteredObjects. + // This is primarily intended for CreateEvent, so that + // a ManualResetEvent can be returned when attempting to + // register an AutoResetEvent (and vice-versa). pAllowedTypes + // must include the type of pObjectToRegister. + // + + virtual + PAL_ERROR + RegisterObject( + CPalThread *pThread, // IN, OPTIONAL + IPalObject *pObjectToRegister, + CAllowedObjectTypes *pAllowedTypes, + HANDLE *pHandle, // OUT + IPalObject **ppRegisteredObject // OUT + ) = 0; + + // + // LocateObject is used for OpenXXX routines. ObtainHandleForObject + // is needed for the OpenXXX routines and DuplicateHandle. + // + + virtual + PAL_ERROR + LocateObject( + CPalThread *pThread, // IN, OPTIONAL + CPalString *psObjectToLocate, + CAllowedObjectTypes *pAllowedTypes, + IPalObject **ppObject // OUT + ) = 0; + + // + // pProcessForHandle is to support cross-process handle + // duplication. It only needs to be specified when acquiring + // a handle meant for use in a different process; it should + // be left NULL when acquiring a handle for the current + // process. + // + + virtual + PAL_ERROR + ObtainHandleForObject( + CPalThread *pThread, // IN, OPTIONAL + IPalObject *pObject, + HANDLE *pNewHandle // OUT + ) = 0; + + virtual + PAL_ERROR + RevokeHandle( + CPalThread *pThread, // IN, OPTIONAL + HANDLE hHandleToRevoke + ) = 0; + + // + // The Reference routines are called to obtain the + // object that a handle refers to. The caller must + // specify the rights that the handle must hold for + // the operation that it is about to perform. The caller + // is responsible for converting generic rights to specific + // rights. The caller must also specify what object types + // are permissible for the object. + // + // The returned object[s], on success, are referenced, + // and the caller is responsible for releasing those references + // when appropriate. + // + + virtual + PAL_ERROR + ReferenceObjectByHandle( + CPalThread *pThread, // IN, OPTIONAL + HANDLE hHandleToReference, + CAllowedObjectTypes *pAllowedTypes, + IPalObject **ppObject // OUT + ) = 0; + + // + // This routine is intended for WaitForMultipleObjects[Ex] + // + + virtual + PAL_ERROR + ReferenceMultipleObjectsByHandleArray( + CPalThread *pThread, // IN, OPTIONAL + HANDLE rghHandlesToReference[], + DWORD dwHandleCount, + CAllowedObjectTypes *pAllowedTypes, + IPalObject *rgpObjects[] // OUT + ) = 0; + }; + + extern IPalObjectManager *g_pObjectManager; + + enum ThreadWakeupReason + { + WaitSucceeded, + Alerted, + MutexAbondoned, + WaitTimeout, + WaitFailed + }; + + class IPalSynchronizationManager + { + public: + + // + // A thread calls BlockThread to put itself to sleep after it has + // registered itself with the objects it is to wait on. A thread + // need not have registered with any objects, as would occur in + // the implementation of Sleep[Ex]. + // + // Needless to say a thread must not be holding any PAL locks + // directly or implicitly (e.g., by holding a reference to a + // synchronization controller) when it calls this method. + // + + virtual + PAL_ERROR + BlockThread( + CPalThread *pCurrentThread, + DWORD dwTimeout, + bool fAlertable, + bool fIsSleep, + ThreadWakeupReason *peWakeupReason, // OUT + DWORD *pdwSignaledObject // OUT + ) = 0; + + virtual + PAL_ERROR + AbandonObjectsOwnedByThread( + CPalThread *pCallingThread, + CPalThread *pTargetThread + ) = 0; + + virtual + PAL_ERROR + QueueUserAPC( + CPalThread *pThread, + CPalThread *pTargetThread, + PAPCFUNC pfnAPC, + ULONG_PTR dwData + ) = 0; + + virtual + bool + AreAPCsPending( + CPalThread *pThread + ) = 0; + + virtual + PAL_ERROR + DispatchPendingAPCs( + CPalThread *pThread + ) = 0; + + virtual + PAL_ERROR + SendTerminationRequestToWorkerThread() = 0; + + // + // This routine is primarily meant for use by WaitForMultipleObjects[Ex]. + // The caller must individually release each of the returned controller + // interfaces. + // + + virtual + PAL_ERROR + GetSynchWaitControllersForObjects( + CPalThread *pThread, + IPalObject *rgObjects[], + DWORD dwObjectCount, + ISynchWaitController *rgControllers[] + ) = 0; + + virtual + PAL_ERROR + GetSynchStateControllersForObjects( + CPalThread *pThread, + IPalObject *rgObjects[], + DWORD dwObjectCount, + ISynchStateController *rgControllers[] + ) = 0; + + // + // These following routines are meant for use only by IPalObject + // implementations. The first two routines are used to + // allocate and free an object's synchronization state; the third + // is called during object promotion. + // + + virtual + PAL_ERROR + AllocateObjectSynchData( + CObjectType *pObjectType, + ObjectDomain eObjectDomain, + VOID **ppvSynchData // OUT + ) = 0; + + virtual + void + FreeObjectSynchData( + CObjectType *pObjectType, + ObjectDomain eObjectDomain, + VOID *pvSynchData + ) = 0; + + virtual + PAL_ERROR + PromoteObjectSynchData( + CPalThread *pThread, + VOID *pvLocalSynchData, + VOID **ppvSharedSynchData // OUT + ) = 0; + + // + // The next two routines provide access to the process-wide + // synchronization lock + // + + virtual + void + AcquireProcessLock( + CPalThread *pThread + ) = 0; + + virtual + void + ReleaseProcessLock( + CPalThread *pThread + ) = 0; + + // + // The final routines are used by IPalObject::GetSynchStateController + // and IPalObject::GetSynchWaitController + // + + virtual + PAL_ERROR + CreateSynchStateController( + CPalThread *pThread, // IN, OPTIONAL + CObjectType *pObjectType, + VOID *pvSynchData, + ObjectDomain eObjectDomain, + ISynchStateController **ppStateController // OUT + ) = 0; + + virtual + PAL_ERROR + CreateSynchWaitController( + CPalThread *pThread, // IN, OPTIONAL + CObjectType *pObjectType, + VOID *pvSynchData, + ObjectDomain eObjectDomain, + ISynchWaitController **ppWaitController // OUT + ) = 0; + }; + + extern IPalSynchronizationManager *g_pSynchronizationManager; + +} + +#endif // _CORUNIX_H + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/corunix.inl b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/corunix.inl new file mode 100644 index 0000000..ab0ac70 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/corunix.inl @@ -0,0 +1,55 @@ +// 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: + + + +--*/ + +#ifndef _CORUNIX_INL +#define _CORUNIX_INL + +#include "corunix.hpp" +#include "dbgmsg.h" + +namespace CorUnix +{ + + bool CAllowedObjectTypes::IsTypeAllowed(PalObjectTypeId eTypeId) + { + _ASSERTE(eTypeId != ObjectTypeIdCount); + return m_rgfAllowedTypes[eTypeId]; + }; + + CAllowedObjectTypes::CAllowedObjectTypes( + PalObjectTypeId rgAllowedTypes[], + DWORD dwAllowedTypeCount + ) + { + ZeroMemory(m_rgfAllowedTypes, sizeof(m_rgfAllowedTypes)); + for (DWORD dw = 0; dw < dwAllowedTypeCount; dw += 1) + { + _ASSERTE(rgAllowedTypes[dw] != ObjectTypeIdCount); + m_rgfAllowedTypes[rgAllowedTypes[dw]] = TRUE; + } + }; + + CAllowedObjectTypes::CAllowedObjectTypes( + PalObjectTypeId eAllowedType + ) + { + ZeroMemory(m_rgfAllowedTypes, sizeof(m_rgfAllowedTypes)); + + _ASSERTE(eAllowedType != ObjectTypeIdCount); + m_rgfAllowedTypes[eAllowedType] = TRUE; + }; +} + +#endif // _CORUNIX_H + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/critsect.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/critsect.h new file mode 100644 index 0000000..aeda121 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/critsect.h @@ -0,0 +1,45 @@ +// 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: + + include/pal/critsect.h + +Abstract: + + Header file for the critical sections functions. + + + +--*/ + +#ifndef _PAL_CRITSECT_H_ +#define _PAL_CRITSECT_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +VOID InternalInitializeCriticalSection(CRITICAL_SECTION *pcs); +VOID InternalDeleteCriticalSection(CRITICAL_SECTION *pcs); + +/* The following PALCEnterCriticalSection and PALCLeaveCriticalSection + functions are intended to provide CorUnix's InternalEnterCriticalSection + and InternalLeaveCriticalSection functionalities to legacy C code, + which has no knowledge of CPalThread, classes and namespaces. +*/ +VOID PALCEnterCriticalSection(CRITICAL_SECTION *pcs); +VOID PALCLeaveCriticalSection(CRITICAL_SECTION *pcs); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _PAL_CRITSECT_H_ */ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cruntime.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cruntime.h new file mode 100644 index 0000000..00c91b6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cruntime.h @@ -0,0 +1,185 @@ +// 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: + + include/pal/cruntime.h + +Abstract: + + Header file for C runtime utility functions. + + + +--*/ + +#ifndef _PAL_CRUNTIME_H_ +#define _PAL_CRUNTIME_H_ + +#include +#include +#include + +#ifdef __cplusplus +typedef char16_t wchar_16; // __wchar_16 (which is defined in palinternal.h) is defined as wchar_16_cpp. + +extern "C" +{ +#endif // __cplusplus + +typedef enum +{ + PFF_NONE = 0, + PFF_MINUS = 1, + PFF_POUND = 2, + PFF_ZERO = 4, + PFF_SPACE = 8, + PFF_PLUS = 16 +}PRINTF_FORMAT_FLAGS; + +typedef enum +{ + WIDTH_DEFAULT = -1, + WIDTH_STAR = -2, /* e.g. "%*.10s" */ + WIDTH_INVALID = -3 /* e.g. "%*3.10s" */ +}WIDTH_FLAGS; + +typedef enum +{ + PRECISION_DEFAULT = -1, + PRECISION_STAR = -2, /* e.g. "%10.*s" */ + PRECISION_DOT = -3, /* e.g. "%10.s" */ + PRECISION_INVALID = -4 /* e.g. "%10.*3s" */ +}PRECISION_FLAGS; + +typedef enum +{ + PFF_PREFIX_DEFAULT = -1, + PFF_PREFIX_SHORT = 1, + PFF_PREFIX_LONG = 2, + PFF_PREFIX_LONGLONG = 3, + PFF_PREFIX_LONG_W = 4 +}PRINTF_PREFIXES; + +typedef enum +{ + PFF_TYPE_DEFAULT = -1, + PFF_TYPE_CHAR = 1, + PFF_TYPE_STRING = 2, + PFF_TYPE_WSTRING = 3, + PFF_TYPE_INT = 4, + PFF_TYPE_P = 5, + PFF_TYPE_N = 6, + PFF_TYPE_FLOAT = 7 +}PRINTF_TYPES; + +typedef enum +{ + SCANF_PREFIX_SHORT = 1, + SCANF_PREFIX_LONG = 2, + SCANF_PREFIX_LONGLONG = 3 +}SCANF_PREFIXES; + +typedef enum +{ + SCANF_TYPE_CHAR = 1, + SCANF_TYPE_STRING = 2, + SCANF_TYPE_INT = 3, + SCANF_TYPE_N = 4, + SCANF_TYPE_FLOAT = 5, + SCANF_TYPE_BRACKETS = 6, + SCANF_TYPE_SPACE = 7 +}SCANF_TYPES; + +/******************************************************************************* +Function: + PAL_printf_arg_remover + +Parameters: + ap + - pointer to the va_list from which to remove arguments + Width + - the width of the current format option + Precision + - the precision of the current format option + Type + - the type of the argument for the current format option + Prefix + - the prefix for the current format option +*******************************************************************************/ +void PAL_printf_arg_remover(va_list *ap, INT Width, INT Precision, INT Type, INT Prefix); + +/*++ +Function: + Silent_PAL_vsnprintf + +See MSDN doc. +--*/ +INT Silent_PAL_vsnprintf(LPSTR Buffer, INT Count, LPCSTR Format, va_list ap); + +/*++ +Function: + Silent_PAL_vfprintf + +See MSDN doc. +--*/ +int Silent_PAL_vfprintf(PAL_FILE *stream, const char *format, va_list ap); + + + + +/*++ + +struct PAL_FILE. +Used to mimic the behavior of windows. +fwrite under windows can set the ferror flag, +under BSD fwrite doesn't. +--*/ +struct _FILE +{ + FILE * bsdFilePtr; /* The BSD file to be passed to the + functions needing it. */ + + INT PALferrorCode; /* The ferror code that fwrite sets, + incase of error */ + + BOOL bTextMode; /* Boolean variable to denote that the + fle is opened in text/binary mode*/ +#if UNGETC_NOT_RETURN_EOF + BOOL bWriteOnlyMode;/* Boolean variable to denote that the + fle is opened in write-only mode*/ +#endif //UNGETC_NOT_RETURN_EOF +}; + +enum CRT_ERROR_CODES +{ + PAL_FILE_NOERROR = 0, + PAL_FILE_ERROR +}; + +/* Global variables storing the std streams. Defined in cruntime/file.c. */ +extern PAL_FILE PAL_Stdout; +extern PAL_FILE PAL_Stdin; +extern PAL_FILE PAL_Stderr; + +/*++ + +Functio: + + CRTInitStdStreams. + + Initilizes the standard streams. + Returns TRUE on success, FALSE otherwise. +--*/ +BOOL CRTInitStdStreams( void ); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _PAL_CRUNTIME_H_ */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cs.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cs.hpp new file mode 100644 index 0000000..fb21723 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/cs.hpp @@ -0,0 +1,54 @@ +// 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. + +/////////////////////////////////////////////////////////////////////////////// +// +// File: +// cs.cpp +// +// Purpose: +// Header file for critical sections implementation +// + +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _PAL_CS_HPP +#define _PAL_CS_HPP + +#include "corunix.hpp" +#include "critsect.h" + +namespace CorUnix +{ + void CriticalSectionSubSysInitialize(void); + + void InternalInitializeCriticalSectionAndSpinCount( + PCRITICAL_SECTION pCriticalSection, + DWORD dwSpinCount, + bool fInternal); + + void InternalEnterCriticalSection( + CPalThread *pThread, + CRITICAL_SECTION *pcs + ); + + void InternalLeaveCriticalSection( + CPalThread *pThread, + CRITICAL_SECTION *pcs + ); + + bool InternalTryEnterCriticalSection( + CPalThread * pThread, + PCRITICAL_SECTION pCriticalSection); + +#ifdef _DEBUG + void PALCS_ReportStatisticalData(void); + void PALCS_DumpCSList(); +#endif // _DEBUG + +} + +#endif // _PAL_CS_HPP + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/dbgmsg.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/dbgmsg.h new file mode 100644 index 0000000..f80dada --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/dbgmsg.h @@ -0,0 +1,529 @@ +// 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: + + include/pal/dbgmsg.h + +Abstract: + Header file for Debug Message utilities. Output macros, type definitions, + extern variables. See overview section below for usage details. + +--*/ + +/* +Overview of Debug Message utilities + +Use debug channels to selectively output information to the console. + +Available macros : + + - SET_DEFAULT_DEBUG_CHANNEL + + This defines the channel to use with the macros TRACE, ERROR, etc + Use this macro once at the beginning of your source file. + (impl. details : this declares a constant static variable defdbgchan and + sets it to the apropriate channel) + + usage : SET_DEFAULT_DEBUG_CHANNEL(somechannel); + + - TRACE, ENTRY, WARN, ERROR, DBGOUT + + Use this to output debug messages to the default debug channel (set with + SET_DEFAULT_DEBUG_CHANNEL). Messages will only be output if the channel is + active for the specified level. + + usage : TRACE("printf format string", params...); + + - TRACE_, ENTRY_, WARN_, ERROR_, DBGOUT_ + + Use this to autput debug messages to a channel other than the default. + + usage : TRACE_(someotherchannel)("printf format string",params...); + ^ ^^ ^ + don't forget the double set of parentheses! + +Available channels : + PAL : PAL-specific functionalities (PAL_Initialize, etc.) + LOADER : Loading API (LoadLibrary, etc); loader application + HANDLE : Handle manager (CloseHandle, etc.) + SHMEM : Shared Memory functions (for IPC) + PROCESS : Process related APIs + THREAD : Threading mechanism + EXCEPT : Structured Exception Handling functions + CRT : PAL implementation of the C Runtime Library functions + UNICODE : Unicode support API + ARCH : platform-dependent stuff + SYNC : Management of synchronization objects + FILE : File I/O API + VIRTUAL : Virtual memory and File mapping + MEM : Memory management (except Virtual* stuff) + SOCKET : WINSOCK implementation + DEBUG : Debugging API (ReadProcessMemory, etc.) + LOCALE : Locale support API + MISC : what doesn't fit anywhere else. + MUTEX : Mutex management functions + CRITSEC : Critical section API + POLL : ? + CRYPT : Cryptographic functions + SHFOLDER: Shared (well-known) folder functions + SXS : Side-by-side PALs (if supported) + + Note : Most channels correspond to subdirectories $(PALROOT) + Note 2 : DON'T write TRACE("PAL") or TRACE(DCI_PAL), write TRACE(PAL) + +Available debug levels : + ENTRY : use this at the beginning of a function to print parameters. + TRACE : use this to output informational messages. + WARN : use this to report non-critical problems. + ERROR : use this to report critical problems. + + DBGOUT: same as TRACE, but does not output line headers (thread ID, etc) + +Format specifiers : + These trace functions currently use the native fprintf() to output data. + All standard printf format specifiers should therefore work, while Microsoft + extensions will not. + There is one special case to consider : wide strings and wide characters. + Microsoft's extensions to printf include the specifiers %S and %C for + printing strings and characters of wchar_t. In the C99 standard, + the specifiers %ls and %ls serve the same purpose. However, Windows defines + wchar_t as a 16bit int, which is NOT guaranteed to match implementations + on other platforms. glibc on a x86 defines wchar_t as a 32bit int. + For this reason, %S and %C should be used in TRACE functions to output + Windows wide strings (of type wchar_t or WCHAR). To output wide-strings + in a platforms native format (litterals L"string" or variables of type + wchar_native), the specifiers %ls and %lc should be used instead. + +Using Debug channels at Run Time + To tell the PAL which debug channels should be open and which should be + closed, set the environment variable PAL_DBG_CHANNELS according to the + following syntax : + [+|-].[: ...] + + opens a channel, - closes it; + must be one of PAL, FILE, (etc), or the wildcard "all" + must be TRACE, ENTRY, WARN, ERROR or "all" + + Examples (for bash): + + export PAL_DBG_CHANNELS="+PAL.TRACE:-FILE.ERROR" + export PAL_DBG_CHANNELS="+all.ENTRY" + export PAL_DBG_CHANNELS="-all.all" + + To explicitly redirect the output of debug messages to a file (instead of + relying on the shell's > and |), set the environment variable + PAL_API_TRACING to the name of the file to write to. It can also be set to + "stdout" or "stderr". If PAL_API_TRACING is not set, output will go to + stderr. + + ASSERT() messages cannot be controlled with PAL_DBG_CHANNELS; they can be + globally disabled (in debug builds) by setting the environment variable + PAL_DISABLE_ASSERTS to 1. In release builds, they will always be disabled + + The environment variable "PAL_API_LEVELS" determines how many levels of + nesting will be allowed in ENTRY calls; if not set, the default is 1; a + value of 0 will allow infinite nesting, but will not indent the output + + It is possible to disable/enable all channels during the execution of a + process; this involves using a debugger to modify a variable within the + address space of the running process. the variable is named + 'dbg_master_switch'; if set to zero, all debug chanels will be closed; if + set to nonzero, channels will be open or closed based on PAL_DBG_CHANNELS + + Notes : + If _ENABLE_DEBUG_MESSAGES_ was not defined at build-time, no debug messages + will be generated. + If _ENABLE_DEBUG_MESSAGES_ was defined, all debug levels will be enabled, + but all channels will be closed by default + + Another configure option is --enable-appendtraces + Normally, if the file specified by PAL_API_TRACING exists, its content will + be overwritten when a PAL process starts using it. If --enable-appendtraces + is used, debug output will be appended at the end of the file instead. + + + + */ + +#ifndef _PAL_DBGMSG_H_ +#define _PAL_DBGMSG_H_ + +#include "pal/palinternal.h" +#include "config.h" +#include "pal/perftrace.h" +#include "pal/debug.h" +#include "pal/thread.hpp" + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/* Channel identifiers */ +typedef enum +{ + DCI_PAL, + DCI_LOADER, + DCI_HANDLE, + DCI_SHMEM, + DCI_PROCESS, + DCI_THREAD, + DCI_EXCEPT, + DCI_CRT, + DCI_UNICODE, + DCI_ARCH, + DCI_SYNC, + DCI_FILE, + DCI_VIRTUAL, + DCI_MEM, + DCI_SOCKET, + DCI_DEBUG, + DCI_LOCALE, + DCI_MISC, + DCI_MUTEX, + DCI_CRITSEC, + DCI_POLL, + DCI_CRYPT, + DCI_SHFOLDER, + DCI_SXS, + DCI_NUMA, + // Please make sure to update dbg_channel_names when adding entries here. + + // Do not remove this line, as it indicates the end of the list + DCI_LAST +} DBG_CHANNEL_ID; + +/* Level identifiers */ +typedef enum +{ + DLI_ENTRY, + DLI_TRACE, + DLI_WARN, + DLI_ERROR, + DLI_ASSERT, + DLI_EXIT, + + DLI_LAST +} DBG_LEVEL_ID; + + +/* extern variables */ + +// Change W16_NULLSTRING to external variable to avoid multiple warnings showing up in prefast +extern LPCWSTR W16_NULLSTRING; + +extern DWORD dbg_channel_flags[DCI_LAST]; +extern BOOL g_Dbg_asserts_enabled; + +/* we must use stdio functions directly rather that rely on PAL functions for + output, because those functions do tracing and we need to avoid recursion */ +extern FILE *output_file; + +/* master switch for debug channel enablement, to be modified by debugger */ +extern Volatile dbg_master_switch ; + + +/* conditionnal compilation for other debug messages */ +#if !_ENABLE_DEBUG_MESSAGES_ + +/* compile out these trace levels; see the definition of NOTRACE */ +#define TRACE NOTRACE +#define TRACE_(x) NOTRACE +#define WARN NOTRACE +#define WARN_(x) NOTRACE +#define ENTRY_EXTERNAL NOTRACE +#define ENTRY NOTRACE +#define ENTRY_(x) NOTRACE +#define LOGEXIT NOTRACE +#define LOGEXIT_(x) NOTRACE +#define DBGOUT NOTRACE +#define DBGOUT_(x) NOTRACE +#define ERROR NOTRACE +#define ERROR_(x) NOTRACE +#define DBG_PRINTF(level, channel, bHeader) NOTRACE + +#define CHECK_STACK_ALIGN + +#define SET_DEFAULT_DEBUG_CHANNEL(x) +#define DBG_ENABLED(level, channel) + +#else /* _ENABLE_DEBUG_MESSAGES_ */ + +/* output macros */ + +#define SET_DEFAULT_DEBUG_CHANNEL(x) \ + static const DBG_CHANNEL_ID defdbgchan = DCI_##x + +/* Is debug output enabled for the given level and channel? */ +#define DBG_ENABLED(level, channel) (output_file && \ + dbg_master_switch && \ + (dbg_channel_flags[channel] & (1 << (level)))) +#define TRACE \ + DBG_PRINTF(DLI_TRACE,defdbgchan,TRUE) + +#define TRACE_(x) \ + DBG_PRINTF(DLI_TRACE,DCI_##x,TRUE) + +#define WARN \ + DBG_PRINTF(DLI_WARN,defdbgchan,TRUE) + +#define WARN_(x) \ + DBG_PRINTF(DLI_WARN,DCI_##x,TRUE) + +#if _DEBUG && defined(__APPLE__) +bool DBG_ShouldCheckStackAlignment(); +#define CHECK_STACK_ALIGN if (DBG_ShouldCheckStackAlignment()) DBG_CheckStackAlignment() +#else +#define CHECK_STACK_ALIGN +#endif + +#define ENTRY_EXTERNAL \ + CHECK_STACK_ALIGN; \ + DBG_PRINTF(DLI_ENTRY, defdbgchan,TRUE) + +#define ENTRY \ + CHECK_STACK_ALIGN; \ + DBG_PRINTF(DLI_ENTRY, defdbgchan,TRUE) + +#define ENTRY_(x) \ + CHECK_STACK_ALIGN; \ + DBG_PRINTF(DLI_ENTRY, DCI_##x,TRUE) + +#define LOGEXIT \ + DBG_PRINTF(DLI_EXIT, defdbgchan,TRUE) + +#define LOGEXIT_(x) \ + DBG_PRINTF(DLI_EXIT, DCI_##x,TRUE) + +#define DBGOUT \ + DBG_PRINTF(DLI_TRACE,defdbgchan,FALSE) + +#define DBGOUT_(x) \ + DBG_PRINTF(DLI_TRACE,DCI_##x,FALSE) + +/*Added this code here to stop error messages + *from appearing in retail build*/ +#define ERROR \ + DBG_PRINTF(DLI_ERROR,defdbgchan,TRUE) + +#define ERROR_(x) \ + DBG_PRINTF(DLI_ERROR,DCI_##x,TRUE) + +#define DBG_PRINTF(level, channel, bHeader) \ +{\ + if( DBG_ENABLED(level, channel) ) { \ + DBG_CHANNEL_ID __chanid=channel;\ + DBG_LEVEL_ID __levid=level;\ + BOOL __bHeader = bHeader;\ + DBG_PRINTF2 + +#define DBG_PRINTF2(...)\ + DBG_printf(__chanid,__levid,__bHeader,__FUNCTION__,__FILE__,__LINE__,__VA_ARGS__);\ + }\ +} + +#endif /* _ENABLE_DEBUG_MESSAGES_ */ + +/* define NOTRACE as nothing; this will absorb the variable-argument list used + in tracing macros */ +#define NOTRACE(...) + +#if !defined(_DEBUG) + +#define ASSERT(...) +#define _ASSERT(expr) +#define _ASSERTE(expr) +#define _ASSERT_MSG(...) + +#else /* defined(_DEBUG) */ + +inline void ANALYZER_NORETURN AssertBreak() +{ + if(g_Dbg_asserts_enabled) + { + DebugBreak(); + } +} + +#define ASSERT(...) \ +{ \ + if (output_file && dbg_master_switch) \ + { \ + DBG_printf(defdbgchan,DLI_ASSERT,TRUE,__FUNCTION__,__FILE__,__LINE__,__VA_ARGS__); \ + } \ + AssertBreak(); \ +} + +#define _ASSERT(expr) do { if (!(expr)) { ASSERT(""); } } while(0) +#define _ASSERTE(expr) do { if (!(expr)) { ASSERT("Expression: " #expr "\n"); } } while(0) +#define _ASSERT_MSG(expr, ...) \ + do { \ + if (!(expr)) \ + { \ + ASSERT("Expression: " #expr ", Description: " __VA_ARGS__); \ + } \ + } while(0) + +#endif /* !_DEBUG */ + +/* Function declarations */ + +/*++ +Function : + DBG_init_channels + + Initialize debug channel information based on environment settings + Call this only once at startup. + + (no parameters, no return value) +--*/ +BOOL DBG_init_channels(void); + +/*++ +Function : + DBG_close_channels + + Close the output file for debug messages. + + (no parameters, no return value) +--*/ +void DBG_close_channels(void); + +/*++ +Function : + DBG_preprintf + + Internal function for debug channels; don't use. + This function outputs the header information for debug messages (channel, + level, etc). + +Parameters : + DBG_CHANNEL_ID channel : debug channel to use + DBG_LEVEL_ID level : debug message level + BOOL bHeader : whether or not to output message header (thread id, etc) + LPSTR file : current file + INT line : line number + +Return Value : + TRUE if there's an output file, FALSE otherwise. this is so that + DBG_printf_plain doesn't get called unnecessarily. + +Notes : + This function is only used with compilers that don't support + variable-argument macros. It enters a critical section, which is left in + DBG_printf_plain. +--*/ +BOOL DBG_preprintf(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader, + LPSTR file, INT line); + +/*++ +Function : + DBG_printf + + Internal function for debug channels; don't use. + This function outputs a complete debug message, without function name. + +Parameters : + DBG_CHANNEL_ID channel : debug channel to use + DBG_LEVEL_ID level : debug message level + BOOL bHeader : whether or not to output message header (thread id, etc) + LPCSTR function : current function + LPCSTR file : current file + INT line : line number + LPCSTR format, ... : standard printf parameter list. + +Return Value : + always 1. + +Notes : + This function requires that the compiler support the C99 flavor of + variable-argument macros, and that they support the __FUNCTION__ + pseudo-macro. + +--*/ +#if __GNUC__ && CHECK_TRACE_SPECIFIERS +/* if requested, use an __attribute__ feature to ask gcc to check that format + specifiers match their parameters */ +int DBG_printf(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader, + LPCSTR function, LPCSTR file, INT line, LPCSTR format, ...) + __attribute__ ((format (printf,7, 8))); +#else +int DBG_printf(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader, + LPCSTR function, LPCSTR file, INT line, LPCSTR format, ...); +#endif + +/*++ +Function : + DBG_printf_plain + + Internal function for debug channels; don't use. + This function output the user-specified part of a debug-message. + +Parameters : + LPSTR format, ... : standard printf parameter list. + +Return value : + always 1. + +Notes : + This function is only used with compilers that don't support + variable-argument macros. It will leave the critical section entered in + DBG_preprintf. + +--*/ +int DBG_printf_plain(LPSTR format, ...); + +/*++ +Function : + DBG_change_entrylevel + + retrieve current ENTRY nesting level and [optionnally] modify it + +Parameters : + int new_level : value to which the nesting level must be set, or -1 + +Return value : + nesting level at the time the function was called + +Notes: +if new_level is -1, the nesting level will not be modified +--*/ +int DBG_change_entrylevel(int new_level); + +#ifdef __APPLE__ +/*++ +Function : + PAL_DisplayDialog + + Display a simple modal dialog with an alert icon and a single OK button. Caller supplies the title of the + dialog and the main text. The dialog is displayed only if the COMPlus_EnableAssertDialog environment + variable is set to the value "1". + +--*/ +void PAL_DisplayDialog(const char *szTitle, const char *szText); + +/*++ +Function : + PAL_DisplayDialogFormatted + + As above but takes a printf-style format string and insertion values to form the main text. + +--*/ +void PAL_DisplayDialogFormatted(const char *szTitle, const char *szTextFormat, ...); +#else // __APPLE__ +#define PAL_DisplayDialog(_szTitle, _szText) +#define PAL_DisplayDialogFormatted(_szTitle, _szTextFormat, args...) +#endif // __APPLE__ + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _PAL_DBGMSG_H_ */ + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/debug.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/debug.h new file mode 100644 index 0000000..5f8a307 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/debug.h @@ -0,0 +1,86 @@ +// 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: + + include/pal/debug.h + +Abstract: + + Debug API utility functions + + + +--*/ + +#ifndef _PAL_DEBUG_H_ +#define _PAL_DEBUG_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/*++ +Function : + DBG_DebugBreak + + Processor-dependent implementation of DebugBreak + +(no parameters, no return value) +--*/ +extern "C" VOID +DBG_DebugBreak(); + +/*++ +Function: + IsInDebugBreak(addr) + + Returns true if the address is in DBG_DebugBreak. + +--*/ +BOOL +IsInDebugBreak(void *addr); + +/*++ +Function : + DBG_FlushInstructionCache + + Processor-dependent implementation of FlushInstructionCache + +Parameters : + LPCVOID lpBaseAddress: start of region to flush + SIZE_T dwSize : length of region to flush + +Return value : + TRUE on success, FALSE on failure + +--*/ +BOOL +DBG_FlushInstructionCache( + IN LPCVOID lpBaseAddress, + IN SIZE_T dwSize); + +#if defined(__APPLE__) +/*++ +Function: + DBG_CheckStackAlignment + + The Apple ABI requires 16-byte alignment on the stack pointer. + This function traps/interrupts otherwise. +--*/ +VOID +DBG_CheckStackAlignment(); +#endif + + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif //PAL_DEBUG_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/environ.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/environ.h new file mode 100644 index 0000000..cfb9771 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/environ.h @@ -0,0 +1,78 @@ +// 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: + + include/pal/environ.h + +Abstract: + Header file for functions manipulating environment variables + + +--*/ + +#ifndef __ENVIRON_H_ +#define __ENVIRON_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/*++ +Variables : + + palEnvironment: a global variable equivalent to environ on systems on + which that exists, and a pointer to an array of environment + strings on systems without environ. + gcsEnvironment: critical section to synchronize access to palEnvironment +--*/ +extern char **palEnvironment; +extern CRITICAL_SECTION gcsEnvironment; + +/*++ + +Function: + EnvironInitialize + +Initialization function for the PAL environment code. +--*/ +BOOL EnvironInitialize(); + +/*++ +Function: + EnvironGetenv + +Get the value of environment variable with the given name. +--*/ +char *EnvironGetenv(const char *name, BOOL copyValue = TRUE); + +/*++ +Function: + EnvironPutenv + +Add the environment variable string provided to the PAL version +of the environment. +--*/ +BOOL EnvironPutenv(const char *string, BOOL deleteIfEmpty); + +/*++ +Function: + EnvironUnsetenv + +Remove the environment variable with the given name from the PAL +version of the environment if it exists. +--*/ +void EnvironUnsetenv(const char *name); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* __ENVIRON_H_ */ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/event.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/event.hpp new file mode 100644 index 0000000..b71bd10 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/event.hpp @@ -0,0 +1,60 @@ +// 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: + + event.hpp + +Abstract: + + Event object structure definition. + + + +--*/ + +#ifndef _PAL_EVENT_H_ +#define _PAL_EVENT_H_ + +#include "corunix.hpp" + +namespace CorUnix +{ + extern CObjectType otManualResetEvent; + extern CObjectType otAutoResetEvent; + + PAL_ERROR + InternalCreateEvent( + CPalThread *pThread, + LPSECURITY_ATTRIBUTES lpEventAttributes, + BOOL bManualReset, + BOOL bInitialState, + LPCWSTR lpName, + HANDLE *phEvent + ); + + PAL_ERROR + InternalSetEvent( + CPalThread *pThread, + HANDLE hEvent, + BOOL fSetEvent + ); + +} + +#endif //PAL_EVENT_H_ + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/fakepoll.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/fakepoll.h new file mode 100644 index 0000000..33f7182 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/fakepoll.h @@ -0,0 +1,68 @@ +// 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. + +// fakepoll.h +// poll using select +// Warning: a call to this poll() takes about 4K of stack space. + +// Greg Parker gparker@cs.stanford.edu December 2000 +// This code is in the public domain and may be copied or modified without +// permission. + +// Located at . + + + + +#ifndef _FAKE_POLL_H +#define _FAKE_POLL_H + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +#ifdef FD_SETSIZE +#undef FD_SETSIZE +#endif +#define FD_SETSIZE OPEN_MAX + +typedef struct pollfd { + int fd; /* file desc to poll */ + short events; /* events of interest on fd */ + short revents; /* events that occurred on fd */ +} pollfd_t; + +// Typically defined in sys/stropts.h and used for an infinite timeout. +#ifndef _INFTIM +#define _INFTIM -1 +#endif +#ifndef INFTIM +#define INFTIM _INFTIM +#endif + +// poll flags +#define POLLIN 0x0001 +#define POLLOUT 0x0004 +#define POLLERR 0x0008 + +// synonyms +#define POLLNORM POLLIN +#define POLLPRI POLLIN +#define POLLRDNORM POLLIN +#define POLLRDBAND POLLIN +#define POLLWRNORM POLLOUT +#define POLLWRBAND POLLOUT + +// ignored +#define POLLHUP 0x0010 +#define POLLNVAL 0x0020 + +int poll(struct pollfd *pollSet, int pollCount, int pollTimeout); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _FAKE_POLL_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/file.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/file.h new file mode 100644 index 0000000..d661774 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/file.h @@ -0,0 +1,225 @@ +// 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: + + include/pal/file.h + +Abstract: + Header file for file utility functions. + +Revision History: + + + +--*/ + +#ifndef _PAL_FILE_H_ +#define _PAL_FILE_H_ + +#include "pal/shmemory.h" +#include "pal/stackstring.hpp" +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +typedef struct _find_handle +{ + struct _find_handle *self_addr; /* for pointer verification */ + + char dir[_MAX_DIR]; + char fname[MAX_PATH_FNAME]; /* includes extension */ + glob_t gGlob; + char **next; +} find_obj; + +/*++ +FILECanonicalizePath + Removes all instances of '/./', '/../' and '//' from an absolute path. + +Parameters: + LPSTR lpUnixPath : absolute path to modify, in Unix format + +(no return value) + +Notes : +-behavior is undefined if path is not absolute +-the order of steps *is* important: /one/./../two would give /one/two + instead of /two if step 3 was done before step 2 +-reason for this function is that GetFullPathName can't use realpath(), since + realpath() requires the given path to be valid and GetFullPathName does not. +--*/ +void FILECanonicalizePath(LPSTR lpUnixPath); + +/*++ +Function: + FileDosToUnixPathA + +Abstract: + Change a DOS path to a Unix path. Replace '\' by '/'. + +Parameter: + IN/OUT lpPath: path to be modified +--*/ +void +FILEDosToUnixPathA(LPSTR lpPath); + +/*++ +Function: + FILEGetDirectoryFromFullPathA + +Parse the given path. If it contains a directory part and a file part, +put the directory part into the supplied buffer, and return the number of +characters written to the buffer. If the buffer is not large enough, +return the required size of the buffer including the NULL character. If +there is no directory part in the path, return 0. +--*/ +DWORD FILEGetDirectoryFromFullPathA( LPCSTR lpFullPath, + DWORD nBufferLength, + LPSTR lpBuffer ); + +/*++ +Function: + FILEGetLastErrorFromErrno + +Convert errno into the appropriate win32 error and return it. +--*/ +DWORD FILEGetLastErrorFromErrno( void ); + +/*++ +Function: + DIRGetLastErrorFromErrno + +Convert errno into the appropriate win32 error and return it. +--*/ +DWORD DIRGetLastErrorFromErrno( void ); + +/*++ +FILEInitStdHandles + +Create handle objects for stdin, stdout and stderr + +(no parameters) + +Return value: + TRUE on success, FALSE on failure +--*/ +BOOL FILEInitStdHandles(void); + +/*++ +FILECleanupStdHandles + +Close promary handles for stdin, stdout and stderr + +(no parameters, no return value) +--*/ +void FILECleanupStdHandles(void); + +/*++ + +Function : + FILEGetProperNotFoundError + +Returns the proper error code, based on the +Windows behavoir. + + IN LPSTR lpPath - The path to check. + LPDWORD lpErrorCode - The error to set. +*/ +void FILEGetProperNotFoundError( LPCSTR lpPath, LPDWORD lpErrorCode ); + +/*++ +PAL_fflush + +Calls fflush + +Input parameters: + +PAL_FILE *stream = stream to be flushed. + +Return value: + 0 is returned on success, otherwise EOF is returned. +--*/ +int _cdecl PAL_fflush( PAL_FILE *stream ); + +/*++ +PAL_fgets + +Wrapper function for InternalFgets. + +Input parameters: + +sz = stores characters read from the given file stream +nSize = number of characters to be read +pf = stream to read characters from + +Return value: + Returns a pointer to the string storing the characters on success + and NULL on failure. +--*/ +char * __cdecl PAL_fgets(char *sz, int nSize, PAL_FILE *pf); + +/*++ +PAL_fwrite + +Wrapper function for InternalFwrite + +Input parameters: + +pvBuffer = array of objects to write to the given file stream +nSize = size of a object in bytes +nCount = number of objects to write +pf = stream to write characters to + +Return value: + Returns the number of objects written. +--*/ +size_t __cdecl PAL_fwrite(const void *pvBuffer, size_t nSize, size_t nCount, PAL_FILE *pf); + +/*++ +PAL__open + +Wrapper function for InternalOpen. + +Input parameters: + +szPath = pointer to a pathname of a file to be opened +nFlags = arguments that control how the file should be accessed +mode = file permission settings that are used only when a file is created + +Return value: + File descriptor on success, -1 on failure +--*/ +int __cdecl PAL__open(const char *szPath, int nFlags, ...); + +/*++ +PAL_fseek + +Wrapper function for fseek + +Input parameters: + +pf = a given file stream +lOffset = distance from position to set file-position indicator +nWhence = method used to determine the file_position indicator location relative to lOffset + +Return value: + 0 on success, -1 on failure. +--*/ +int _cdecl PAL_fseek(PAL_FILE *pf, LONG lOffset, int nWhence); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _PAL_FILE_H_ */ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/file.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/file.hpp new file mode 100644 index 0000000..308f70e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/file.hpp @@ -0,0 +1,272 @@ +// 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: + + include/pal/file.hpp + +Abstract: + Header file for file utility functions. + +Revision History: + + + +--*/ + +#ifndef _PAL_FILE_HPP_ +#define _PAL_FILE_HPP_ + +#include "corunix.hpp" +#include "pal/stackstring.hpp" +#include +#include +#include + + +namespace CorUnix +{ + extern CObjectType otFile; + extern CAllowedObjectTypes aotFile; + + class CFileProcessLocalData + { + public: + int unix_fd; + int open_flags; /* stores Unix file creation flags */ + BOOL open_flags_deviceaccessonly; + CHAR *unix_filename; + BOOL inheritable; + }; + + PAL_ERROR + InternalCreateFile( + CPalThread *pThread, + LPCSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile, + HANDLE *pFileHandle + ); + + PAL_ERROR + InternalWriteFile( + CPalThread *pThread, + HANDLE hFile, + LPCVOID lpBuffer, + DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, + LPOVERLAPPED lpOverlapped + ); + + PAL_ERROR + InternalReadFile( + CPalThread *pThread, + HANDLE hFile, + LPVOID lpBuffer, + DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, + LPOVERLAPPED lpOverlapped + ); + + PAL_ERROR + InternalSetEndOfFile( + CPalThread *pThread, + HANDLE hFile + ); + + PAL_ERROR + InternalGetFileSize( + CPalThread *pThread, + HANDLE hFile, + DWORD *pdwFileSizeLow, + DWORD *pdwFileSizeHigh + ); + + PAL_ERROR + InternalFlushFileBuffers( + CPalThread *pThread, + HANDLE hFile + ); + + PAL_ERROR + InternalCreatePipe( + CPalThread *pThread, + HANDLE *phReadPipe, + HANDLE *phWritePipe, + LPSECURITY_ATTRIBUTES lpPipeAttributes, + DWORD nSize + ); + + PAL_ERROR + InternalSetFilePointer( + CPalThread *pThread, + HANDLE hFile, + LONG lDistanceToMove, + PLONG lpDistanceToMoveHigh, + DWORD dwMoveMethod, + PLONG lpNewFilePointerLow + ); + + BOOL + RealPathHelper(LPCSTR lpUnixPath, PathCharString& lpBuffer); + /*++ + InternalCanonicalizeRealPath + Wraps realpath() to hide platform differences. See the man page for + realpath(3) for details of how realpath() works. + + On systems on which realpath() allows the last path component to not + exist, this is a straight thunk through to realpath(). On other + systems, we remove the last path component, then call realpath(). + --*/ + PAL_ERROR + InternalCanonicalizeRealPath( + LPCSTR lpUnixPath, + PathCharString& lpBuffer + ); + + /*++ + InternalFgets + Wraps fgets + --*/ + char * + InternalFgets( + char *sz, + int nSize, + FILE *f, + bool fTextMode + ); + + /*++ + InternalFwrite + Wraps fwrite + --*/ + size_t + InternalFwrite( + const void *pvBuffer, + size_t nSize, + size_t nCount, + FILE *f, + INT *pnErrorCode + ); + + /*++ + InternalOpen + Wraps open + --*/ + int + InternalOpen( + const char *szFilename, + int nFlags, + ... + ); +} + +extern "C" +{ + +// +// These routines should all be separated out into something along the lines +// of fileutils.* (instead of being commingled with the core file object +// code). +// + +/*++ +FILECanonicalizePath + Removes all instances of '/./', '/../' and '//' from an absolute path. + +Parameters: + LPSTR lpUnixPath : absolute path to modify, in Unix format + +(no return value) + +Notes : +-behavior is undefined if path is not absolute +-the order of steps *is* important: /one/./../two would give /one/two + instead of /two if step 3 was done before step 2 +-reason for this function is that GetFullPathName can't use realpath(), since + realpath() requires the given path to be valid and GetFullPathName does not. +--*/ +void FILECanonicalizePath(LPSTR lpUnixPath); + +/*++ +Function: + FileDosToUnixPathA + +Abstract: + Change a DOS path to a Unix path. Replace '\' by '/'. + +Parameter: + IN/OUT lpPath: path to be modified +--*/ +void +FILEDosToUnixPathA(LPSTR lpPath); + +/*++ +Function: + FILEGetDirectoryFromFullPathA + +Parse the given path. If it contains a directory part and a file part, +put the directory part into the supplied buffer, and return the number of +characters written to the buffer. If the buffer is not large enough, +return the required size of the buffer including the NULL character. If +there is no directory part in the path, return 0. +--*/ +DWORD FILEGetDirectoryFromFullPathA( LPCSTR lpFullPath, + DWORD nBufferLength, + LPSTR lpBuffer ); + +/*++ +Function: + FILEGetLastErrorFromErrno + +Convert errno into the appropriate win32 error and return it. +--*/ +DWORD FILEGetLastErrorFromErrno( void ); + +/*++ +FILEInitStdHandles + +Create handle objects for stdin, stdout and stderr + +(no parameters) + +Return value: + TRUE on success, FALSE on failure +--*/ +BOOL FILEInitStdHandles(void); + +/*++ +FILECleanupStdHandles + +Close primary handles for stdin, stdout and stderr + +(no parameters, no return value) +--*/ +void FILECleanupStdHandles(void); + +/*++ + +Function : + FILEGetProperNotFoundError + +Returns the proper error code, based on the +Windows behavoir. + + IN LPSTR lpPath - The path to check. + LPDWORD lpErrorCode - The error to set. +*/ +void FILEGetProperNotFoundError( LPCSTR lpPath, LPDWORD lpErrorCode ); + +} + +#endif /* _PAL_FILE_HPP_ */ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/filetime.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/filetime.h new file mode 100644 index 0000000..71a04d2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/filetime.h @@ -0,0 +1,88 @@ +// 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: + + include/pal/filetime.h + +Abstract: + + Header file for utility functions having to do with file times. + +Revision History: + + + +--*/ + +#ifndef _PAL_FILETIME_H_ +#define _PAL_FILETIME_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/* Provide consistent access to nanosecond fields, if they exist. */ + +#if HAVE_STAT_TIMESPEC + +#define ST_ATIME_NSEC(statstruct) ((statstruct)->st_atimespec.tv_nsec) +#define ST_MTIME_NSEC(statstruct) ((statstruct)->st_mtimespec.tv_nsec) +#define ST_CTIME_NSEC(statstruct) ((statstruct)->st_ctimespec.tv_nsec) + +#else /* HAVE_STAT_TIMESPEC */ + +#if HAVE_STAT_TIM + +#define ST_ATIME_NSEC(statstruct) ((statstruct)->st_atim.tv_nsec) +#define ST_MTIME_NSEC(statstruct) ((statstruct)->st_mtim.tv_nsec) +#define ST_CTIME_NSEC(statstruct) ((statstruct)->st_ctim.tv_nsec) + +#else /* HAVE_STAT_TIM */ + +#if HAVE_STAT_NSEC + +#define ST_ATIME_NSEC(statstruct) ((statstruct)->st_atimensec) +#define ST_MTIME_NSEC(statstruct) ((statstruct)->st_mtimensec) +#define ST_CTIME_NSEC(statstruct) ((statstruct)->st_ctimensec) + +#else /* HAVE_STAT_NSEC */ + +#define ST_ATIME_NSEC(statstruct) 0 +#define ST_MTIME_NSEC(statstruct) 0 +#define ST_CTIME_NSEC(statstruct) 0 + +#endif /* HAVE_STAT_NSEC */ +#endif /* HAVE_STAT_TIM */ +#endif /* HAVE_STAT_TIMESPEC */ + +FILETIME FILEUnixTimeToFileTime( time_t sec, long nsec ); + +#ifdef __APPLE__ +#include + +FILETIME FILECFAbsoluteTimeToFileTime( CFAbsoluteTime sec ); +#endif // __APPLE__ + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _PAL_FILE_H_ */ + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/handleapi.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/handleapi.hpp new file mode 100644 index 0000000..ac1c3d9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/handleapi.hpp @@ -0,0 +1,47 @@ +// 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: + + handleapi.hpp + +Abstract: + + Declaration of the handle management APIs + + + +--*/ + +#ifndef _HANDLEAPI_HPP +#define _HANDLEAPI_HPP + +#include "corunix.hpp" + +namespace CorUnix +{ + PAL_ERROR + InternalDuplicateHandle( + CPalThread *pThread, + HANDLE hSourceProcess, + HANDLE hSource, + HANDLE hTargetProcess, + LPHANDLE phDuplicate, + BOOL bInheritHandle, + DWORD dwOptions + ); + + PAL_ERROR + InternalCloseHandle( + CPalThread *pThread, + HANDLE hObject + ); +} + +#endif // _HANDLEAPI_HPP + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/handlemgr.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/handlemgr.hpp new file mode 100644 index 0000000..b1f8c16 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/handlemgr.hpp @@ -0,0 +1,174 @@ +// 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: + + handlemgr.hpp + +Abstract: + + Simple handle table manager class + + + +--*/ + +#ifndef _PAL_HANDLEMGR_H_ +#define _PAL_HANDLEMGR_H_ + + +#include "corunix.hpp" +#include "cs.hpp" +#include "pal/thread.hpp" +#include "pal/malloc.hpp" + + +/* Pseudo handles constant for current thread and process */ +extern const HANDLE hPseudoCurrentProcess; +extern const HANDLE hPseudoCurrentThread; +extern const HANDLE hPseudoGlobalIOCP; + +namespace CorUnix +{ + class CSimpleHandleManager + { + private: + enum { c_BasicGrowthRate = 1024 }; + enum { c_MaxIndex = 0x3FFFFFFE }; + + typedef UINT_PTR HANDLE_INDEX; + static const HANDLE_INDEX c_hiInvalid = (HANDLE_INDEX) -1; + + HANDLE + HandleIndexToHandle(HANDLE_INDEX hi) + { + return (HANDLE) ((hi + 1) << 2); + }; + + HANDLE_INDEX + HandleToHandleIndex(HANDLE h) + { + return (HANDLE_INDEX) (((UINT_PTR) h) >> 2) - 1; + }; + + typedef struct _HANDLE_TABLE_ENTRY + { + union + { + IPalObject *pObject; + HANDLE_INDEX hiNextIndex; + } u; + + bool fEntryAllocated; + } HANDLE_TABLE_ENTRY; + + HANDLE_INDEX m_hiFreeListStart; + HANDLE_INDEX m_hiFreeListEnd; + + DWORD m_dwTableSize; + DWORD m_dwTableGrowthRate; + HANDLE_TABLE_ENTRY* m_rghteHandleTable; + + CRITICAL_SECTION m_csLock; + bool m_fLockInitialized; + + bool ValidateHandle(HANDLE h); + + public: + + CSimpleHandleManager() + : + m_hiFreeListStart(c_hiInvalid), + m_hiFreeListEnd(c_hiInvalid), + m_dwTableSize(0), + m_dwTableGrowthRate(c_BasicGrowthRate), + m_rghteHandleTable(NULL), + m_fLockInitialized(FALSE) + { + }; + + virtual + ~CSimpleHandleManager() + { + if (m_fLockInitialized) + { + DeleteCriticalSection(&m_csLock); + } + + if (NULL != m_rghteHandleTable) + { + free(m_rghteHandleTable); + } + } + + PAL_ERROR + Initialize( + void + ); + + PAL_ERROR + AllocateHandle( + CPalThread *pThread, + IPalObject *pObject, + HANDLE *ph + ); + + // + // On success this will add a reference to the returned object. + // + + PAL_ERROR + GetObjectFromHandle( + CPalThread *pThread, + HANDLE h, + IPalObject **ppObject + ); + + PAL_ERROR + FreeHandle( + CPalThread *pThread, + HANDLE h + ); + + void + Lock( + CPalThread *pThread + ) + { + InternalEnterCriticalSection(pThread, &m_csLock); + }; + + void + Unlock( + CPalThread *pThread + ) + { + InternalLeaveCriticalSection(pThread, &m_csLock); + }; + }; + + bool + HandleIsSpecial( + HANDLE h + ); +} + +#endif // _PAL_HANDLEMGR_H_ + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/init.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/init.h new file mode 100644 index 0000000..4f6a2b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/init.h @@ -0,0 +1,115 @@ +// 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: + + include/pal/init.h + +Abstract: + Header file for PAL init utility functions. Those functions + are only use by the PAL itself. + +Revision History: + + + +--*/ + +#ifndef _PAL_INIT_H_ +#define _PAL_INIT_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/*++ +Function: + PALCommonCleanup + +Utility function to prepare for shutdown. + +--*/ +void PALCommonCleanup(); + +extern Volatile init_count; + +extern SIZE_T g_defaultStackSize; + +extern BOOL g_useDefaultBaseAddr; + +/*++ +MACRO: + PALIsInitialized + +Returns TRUE if the PAL is in an initialized state +(#calls to PAL_Initialize > #calls to PAL_Terminate) + +Warning : this will only report the PAL's state at the moment it is called. +If it is necessary to ensure the PAL remains initialized (or not) while doing +some work, the Initialization lock (PALInitLock()) should be held. +--*/ +#define PALIsInitialized() (0 < init_count) + +/*++ +Function: + PALIsThreadDataInitialized + +Returns TRUE if startup has reached a point where thread data is available +--*/ +BOOL +PALIsThreadDataInitialized(); + +/*++ +Function: + PALIsShuttingDown + +Returns TRUE if the some thread has declared intent to shutdown +--*/ +BOOL +PALIsShuttingDown(); + +/*++ +Function: + PALSetShutdownIntent + +Delcares intent to shutdown +--*/ +void +PALSetShutdownIntent(); + +/*++ +Function: + PALInitLock + +Take the initializaiton critical section (init_critsec). necessary to serialize +TerminateProcess along with PAL_Terminate and PAL_Initialize + +(no parameters) + +Return value : + TRUE if critical section existed (and was acquired) + FALSE if critical section doens't exist yet +--*/ +BOOL PALInitLock(void); + +/*++ +Function: + PALInitUnlock + +Release the initialization critical section (init_critsec). + +(no parameters, no return value) +--*/ +void PALInitUnlock(void); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _PAL_INIT_H_ */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/list.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/list.h new file mode 100644 index 0000000..cd78c0f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/list.h @@ -0,0 +1,141 @@ +// 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: + + list.h + +Abstract: + + Doubly-linked list manipulation macros (from ntrtl.h) + +Revision History: + + + +--*/ + +#ifndef _LIST_H_INCLUDED +#define _LIST_H_INCLUDED + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +typedef struct _LIST_ENTRY { + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +} LIST_ENTRY, *PLIST_ENTRY; + +// +// VOID +// InitializeListHead( +// PLIST_ENTRY ListHead +// ); +// + +#define InitializeListHead(ListHead) (\ + (ListHead)->Flink = (ListHead)->Blink = (ListHead)) + +// +// BOOLEAN +// IsListEmpty( +// PLIST_ENTRY ListHead +// ); +// + +#define IsListEmpty(ListHead) \ + ((ListHead)->Flink == (ListHead)) + +// +// PLIST_ENTRY +// RemoveHeadList( +// PLIST_ENTRY ListHead +// ); +// + +#define RemoveHeadList(ListHead) \ + (ListHead)->Flink;\ + {RemoveEntryList((ListHead)->Flink)} + +// +// PLIST_ENTRY +// RemoveTailList( +// PLIST_ENTRY ListHead +// ); +// + +#define RemoveTailList(ListHead) \ + (ListHead)->Blink;\ + {RemoveEntryList((ListHead)->Blink)} + +// +// VOID +// RemoveEntryList( +// PLIST_ENTRY Entry +// ); +// + +#define RemoveEntryList(Entry) {\ + PLIST_ENTRY _EX_Blink;\ + PLIST_ENTRY _EX_Flink;\ + _EX_Flink = (Entry)->Flink;\ + _EX_Blink = (Entry)->Blink;\ + _EX_Blink->Flink = _EX_Flink;\ + _EX_Flink->Blink = _EX_Blink;\ + } + +// +// VOID +// InsertTailList( +// PLIST_ENTRY ListHead, +// PLIST_ENTRY Entry +// ); +// + +#define InsertTailList(ListHead,Entry) {\ + PLIST_ENTRY _EX_Blink;\ + PLIST_ENTRY _EX_ListHead;\ + _EX_ListHead = (ListHead);\ + _EX_Blink = _EX_ListHead->Blink;\ + (Entry)->Flink = _EX_ListHead;\ + (Entry)->Blink = _EX_Blink;\ + _EX_Blink->Flink = (Entry);\ + _EX_ListHead->Blink = (Entry);\ + } + +// +// VOID +// InsertHeadList( +// PLIST_ENTRY ListHead, +// PLIST_ENTRY Entry +// ); +// + +#define InsertHeadList(ListHead,Entry) {\ + PLIST_ENTRY _EX_Flink;\ + PLIST_ENTRY _EX_ListHead;\ + _EX_ListHead = (ListHead);\ + _EX_Flink = _EX_ListHead->Flink;\ + (Entry)->Flink = _EX_Flink;\ + (Entry)->Blink = _EX_ListHead;\ + _EX_Flink->Blink = (Entry);\ + _EX_ListHead->Flink = (Entry);\ + } + +#define CONTAINING_RECORD(address, type, field) ((type *)( \ + (PCHAR)(address) - \ + (ULONG_PTR)(&((type *)0)->field))) + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // _LIST_H_INCLUDED + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/malloc.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/malloc.hpp new file mode 100644 index 0000000..580b6a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/malloc.hpp @@ -0,0 +1,166 @@ +// 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: + + pal/malloc.hpp + +Abstract: + Declarations for suspension safe memory allocation functions + + + +--*/ + +#ifndef _MALLOC_HPP +#define _MALLOC_HPP + +#include "pal/corunix.hpp" +#include "pal/thread.hpp" + +#include +#include +#include + +extern "C" +{ + void * + __cdecl + PAL_realloc( + void* pvMemblock, + size_t szSize + ); + + void * + __cdecl + PAL_malloc( + size_t szSize + ); + + void + __cdecl + PAL_free( + void *pvMem + ); + + char * + __cdecl + PAL__strdup( + const char *c_szStr + ); +} + +namespace CorUnix{ + + void * + InternalRealloc( + void *pvMemblock, + size_t szSize + ); + + void * + InternalMalloc( + size_t szSize + ); + + // Define common code for "new" style allocators below. +#define INTERNAL_NEW_COMMON() \ + T *pMem = (T*)InternalMalloc(sizeof(T)); \ + if (pMem == NULL) \ + return NULL; + + // Define "new" style allocators (which allocate then call a constructor) for different numbers of + // constructor arguments. Added based on usage. + + // Default constructor (0 args) case. + template + T* InternalNew() + { + INTERNAL_NEW_COMMON(); + return new (pMem) T(); + } + + // 1 arg case. + template + T* InternalNew(A1 arg1) + { + INTERNAL_NEW_COMMON(); + return new (pMem) T(arg1); + } + + // 2 args case. + template + T* InternalNew(A1 arg1, A2 arg2) + { + INTERNAL_NEW_COMMON(); + return new (pMem) T(arg1, arg2); + } + + // 3 args case. + template + T* InternalNew(A1 arg1, A2 arg2, A3 arg3) + { + INTERNAL_NEW_COMMON(); + return new (pMem) T(arg1, arg2, arg3); + } + + // 4 args case. + template + T* InternalNew(A1 arg1, A2 arg2, A3 arg3, A4 arg4) + { + INTERNAL_NEW_COMMON(); + return new (pMem) T(arg1, arg2, arg3, arg4); + } + + // 5 args case. + template + T* InternalNew(A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5) + { + INTERNAL_NEW_COMMON(); + return new (pMem) T(arg1, arg2, arg3, arg4, arg5); + } + + template T* InternalNewArray(size_t cElements) + { + size_t cbSize = (cElements * sizeof(T)) + sizeof(size_t); + T *pMem; + + pMem = (T*)InternalMalloc(cbSize); + + if (pMem == NULL) + return NULL; + + *(size_t*)pMem = cElements; + pMem = (T*)((size_t*)pMem + 1); + + return new (pMem) T[cElements](); + } + + template void InternalDelete(T *p) + { + if (p) + { + p->~T(); + free(p); + } + } + + template void InternalDeleteArray(T *p) + { + if (p) + { + size_t *pRealMem = (size_t*)p - 1; + size_t cElements = *pRealMem; + for (size_t i = 0; i < cElements; i++) + p[i].~T(); + free(pRealMem); + } + } +} + +#endif // _MALLOC_HPP diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/map.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/map.h new file mode 100644 index 0000000..2b53747 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/map.h @@ -0,0 +1,52 @@ +// 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: + + include/pal/map.h + +Abstract: + + Header file for file mapping functions. + + + +--*/ + +#ifndef _PAL_MAP_H_ +#define _PAL_MAP_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/*++ +Function : + MAPGetRegionInfo + + Parameters: + lpAddress: pointer to the starting memory location, not necessary + to be rounded to the page location + + lpBuffer: if this function finds information about the specified address, + the information is stored in this struct + + Note: This function is to be used in virtual.c + + Returns TRUE if this function finds information about the specified address +--*/ + +BOOL MAPGetRegionInfo(LPVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _PAL_MAP_H_ */ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/map.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/map.hpp new file mode 100644 index 0000000..eba0d88 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/map.hpp @@ -0,0 +1,207 @@ +// 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: + + include/pal/map.hpp + +Abstract: + + Header file for file mapping functions. + + + +--*/ + +#ifndef _PAL_MAP_H_ +#define _PAL_MAP_H_ + +#include "corunix.hpp" +#include + +extern "C" +{ +#include "list.h" + +#ifndef NO_INO +#define NO_INO ((ino_t)-1) +#endif + + /*++ + Function : + MapInitialize + + Initialize the critical sections. + + Return value: + TRUE if initialization succeeded + FALSE otherwise + --*/ + BOOL MAPInitialize( void ); + + /*++ + Function : + MapCleanup + + Deletes the critical sections. + + --*/ + void MAPCleanup( void ); + + /*++ + Function : + MAPGetRegionInfo + + Parameters: + lpAddress: pointer to the starting memory location, not necessary + to be rounded to the page location + + lpBuffer: if this function finds information about the specified address, + the information is stored in this struct + + Note: This function is to be used in virtual.c + + Returns TRUE if this function finds information about the specified address + --*/ + + BOOL MAPGetRegionInfo(LPVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer); + + /*++ + MAPMapPEFile - + + Map a PE format file into memory like Windows LoadLibrary() would do. + Doesn't apply base relocations if the function is relocated. + + Parameters: + IN hFile - file to map + + Return value: + non-NULL - the base address of the mapped image + NULL - error, with last error set. + --*/ + + void * MAPMapPEFile(HANDLE hFile); + + /*++ + Function : + MAPUnmapPEFile - unmap a PE file, and remove it from the recorded list of PE files mapped + + returns TRUE if successful, FALSE otherwise + --*/ + BOOL MAPUnmapPEFile(LPCVOID lpAddress); + + /*++ + Function : + MAPMarkSectionAsNotNeeded - mark a section as NotNeeded + returns TRUE if successful, FALSE otherwise + --*/ + BOOL MAPMarkSectionAsNotNeeded(LPCVOID lpAddress); +} + +namespace CorUnix +{ + extern CObjectType otFileMapping; + +#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + typedef struct _NativeMapHolder + { + Volatile ref_count; + LPVOID address; + SIZE_T size; + SIZE_T offset; /* for future use */ + } NativeMapHolder; +#endif + + /* Process specific information. This + structure is not stored in shared memory.*/ + typedef struct _MVL + { + LIST_ENTRY Link; + + // + // Each MVL entry holds a reference to its parent file + // mapping object. + // + + IPalObject *pFileMapping; + +#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + NativeMapHolder * pNMHolder; /* Ref-counted holder for memory mapping */ + dev_t MappedFileDevNum; /* ID of device containing the file to be mapped */ + ino_t MappedFileInodeNum; /* Inode number of file to be mapped. + These two fields are used used to uniquely + identify files on systems that do not allow + more than one shared mmapping per region of + physical file, per process */ +#endif + LPVOID lpAddress; /* The pointer to the mapped memory. */ + SIZE_T NumberOfBytesToMap; /* Number of bytes to map. */ + DWORD dwDesiredAccess; /* Desired access. */ + LPVOID lpPEBaseAddress; /* If this mapping is part of a PE file mapping, this is the + base address pointer of the PE file (used to find all + parts of the PE file mapping to allow PE file unload). + Otherwise, it is NULL. */ + } MAPPED_VIEW_LIST, * PMAPPED_VIEW_LIST; + + class CFileMappingImmutableData + { + public: + CHAR *lpFileName; + UINT MaxSize; // The max size of the file mapping object + DWORD flProtect; // Protection desired for the file view + BOOL bPALCreatedTempFile; // TRUE if it's a PAL created file + DWORD dwDesiredAccessWhenOpened; // FILE_MAP_WRITE etc + }; + + class CFileMappingProcessLocalData + { + public: + INT UnixFd; /* File descriptor. */ + +#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + dev_t MappedFileDevNum; /* ID of device containing the file to be mapped */ + ino_t MappedFileInodeNum; /* Inode number of file to be mapped. + These two fields are used used to uniquely + identify files on systems that do not allow + more than one shared mmapping per region of + physical file, per process */ +#endif + }; + + PAL_ERROR + InternalCreateFileMapping( + CPalThread *pThread, + HANDLE hFile, + LPSECURITY_ATTRIBUTES lpFileMappingAttributes, + DWORD flProtect, + DWORD dwMaximumSizeHigh, + DWORD dwMaximumSizeLow, + LPCWSTR lpName, + HANDLE *phMapping + ); + + PAL_ERROR + InternalMapViewOfFile( + CPalThread *pThread, + HANDLE hFileMappingObject, + DWORD dwDesiredAccess, + DWORD dwFileOffsetHigh, + DWORD dwFileOffsetLow, + SIZE_T dwNumberOfBytesToMap, + LPVOID *ppvBaseAddress + ); + + PAL_ERROR + InternalUnmapViewOfFile( + CPalThread *pThread, + LPCVOID lpBaseAddress + ); + +} + +#endif /* _PAL_MAP_H_ */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/misc.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/misc.h new file mode 100644 index 0000000..65d59ae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/misc.h @@ -0,0 +1,83 @@ +// 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: + + include/pal/misc.h + +Abstract: + Header file for the initialization and clean up functions + for the misc Win32 functions + + + +--*/ + +#ifndef __MISC_H_ +#define __MISC_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/*++ +Function : + + PAL_rand + + Calls rand and mitigates the difference between RAND_MAX + on Windows and FreeBSD. +--*/ +int __cdecl PAL_rand(void); + +/*++ +Function : + + PAL_time +--*/ +PAL_time_t __cdecl PAL_time(PAL_time_t*); + +/*++ +Function: +TIMEInitialize + +Return value: +TRUE if initialize succeeded +FALSE otherwise + +--*/ +BOOL TIMEInitialize( void ); + +/*++ +Function : + MsgBoxInitialize + + Initialize the critical sections. + +Return value: + TRUE if initialize succeeded + FALSE otherwise + +--*/ +BOOL MsgBoxInitialize( void ); + +/*++ +Function : + MsgBoxCleanup + + Deletes the critical sections. + +--*/ +void MsgBoxCleanup( void ); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* __MISC_H_ */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/module.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/module.h new file mode 100644 index 0000000..bb409b8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/module.h @@ -0,0 +1,203 @@ +// 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: + + include/pal/module.h + +Abstract: + Header file for modle management utilities. + + + +--*/ + +#ifndef _PAL_MODULE_H_ +#define _PAL_MODULE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +typedef BOOL (PALAPI_NOEXPORT *PDLLMAIN)(HINSTANCE, DWORD, LPVOID); /* entry point of module */ +typedef HINSTANCE (PALAPI_NOEXPORT *PREGISTER_MODULE)(LPCSTR); /* used to create the HINSTANCE for above DLLMain entry point */ +typedef VOID (PALAPI_NOEXPORT *PUNREGISTER_MODULE)(HINSTANCE); /* used to cleanup the HINSTANCE for above DLLMain entry point */ + +typedef struct _MODSTRUCT +{ + HMODULE self; /* circular reference to this module */ + NATIVE_LIBRARY_HANDLE dl_handle; /* handle returned by dlopen() */ + HINSTANCE hinstance; /* handle returned by PAL_RegisterLibrary */ + LPWSTR lib_name; /* full path of module */ + INT refcount; /* reference count */ + /* -1 means infinite reference count - module is never released */ + BOOL threadLibCalls; /* TRUE for DLL_THREAD_ATTACH/DETACH notifications enabled, FALSE if they are disabled */ + +#if RETURNS_NEW_HANDLES_ON_REPEAT_DLOPEN + ino_t inode; + dev_t device; +#endif + + PDLLMAIN pDllMain; /* entry point of module */ + + /* reference to next and previous modules in list (in load order) */ + struct _MODSTRUCT *next; + struct _MODSTRUCT *prev; +} MODSTRUCT; + + +/*++ +Function : + LOADInitializeModules + + Initialize the process-wide list of modules + +Parameters : + None + +Return value : + TRUE on success, FALSE on failure + +--*/ +BOOL LOADInitializeModules(); + +/*++ +Function : + LOADSetExeName + + Set the exe name path + +Parameters : + LPWSTR man exe path and name + +Return value : + TRUE if initialization succeedded + FALSE otherwise + +--*/ +BOOL LOADSetExeName(LPWSTR name); + +/*++ +Function : + LOADCallDllMain + + Call DllMain for all modules (that have one) with the given "fwReason" + +Parameters : + DWORD dwReason : parameter to pass down to DllMain, one of DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH, + DLL_THREAD_ATTACH, DLL_THREAD_DETACH + + LPVOID lpReserved : parameter to pass down to DllMain + If dwReason is DLL_PROCESS_ATTACH, lpvReserved is NULL for dynamic loads and non-NULL for static loads. + If dwReason is DLL_PROCESS_DETACH, lpvReserved is NULL if DllMain has been called by using FreeLibrary + and non-NULL if DllMain has been called during process termination. + +(no return value) + +Notes : + This is used to send DLL_THREAD_*TACH messages to modules +--*/ +void LOADCallDllMain(DWORD dwReason, LPVOID lpReserved); + +/*++ +Function: + LockModuleList + +Abstract + Enter the critical section associated to the module list + +Parameter + void + +Return + void +--*/ +void LockModuleList(); + +/*++ +Function: + UnlockModuleList + +Abstract + Leave the critical section associated to the module list + +Parameter + void + +Return + void +--*/ +void UnlockModuleList(); + +/*++ +Function: + PAL_LOADLoadPEFile + +Abstract + Loads a PE file into memory. Properly maps all of the sections in the PE file. Returns a pointer to the + loaded base. + +Parameters: + IN hFile - The file to load + +Return value: + A valid base address if successful. + 0 if failure +--*/ +void * PAL_LOADLoadPEFile(HANDLE hFile); + +/*++ + PAL_LOADUnloadPEFile + + Unload a PE file that was loaded by PAL_LOADLoadPEFile(). + +Parameters: + IN ptr - the file pointer returned by PAL_LOADLoadPEFile() + +Return value: + TRUE - success + FALSE - failure (incorrect ptr, etc.) +--*/ +BOOL PAL_LOADUnloadPEFile(void * ptr); + +/*++ + LOADInitializeCoreCLRModule + + Run the initialization methods for CoreCLR module. + +Parameters: + None + +Return value: + TRUE if successful + FALSE if failure +--*/ +BOOL LOADInitializeCoreCLRModule(); + +/*++ +Function : + LOADGetPalLibrary + + Load and initialize the PAL module. + +Parameters : + None + +Return value : + handle to loaded module + +--*/ +MODSTRUCT *LOADGetPalLibrary(); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _PAL_MODULE_H_ */ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/modulename.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/modulename.h new file mode 100644 index 0000000..20001f8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/modulename.h @@ -0,0 +1,36 @@ +// 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: + + include/pal/modulename.h + +Abstract: + Header file for functions to get the name of a module + +Revision History: + + + +--*/ + +#ifndef _PAL_MODULENAME_H_ +#define _PAL_MODULENAME_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +const char *PAL_dladdr(LPVOID ProcAddress); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /*_PAL_MODULENAME_H_*/ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/mutex.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/mutex.hpp new file mode 100644 index 0000000..8aa9a53 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/mutex.hpp @@ -0,0 +1,189 @@ +// 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: + + mutex.hpp + +Abstract: + + Mutex object structure definition. + + + +--*/ + +#ifndef _PAL_MUTEX_H_ +#define _PAL_MUTEX_H_ + +#include "corunix.hpp" +#include "sharedmemory.h" + +#include + +namespace CorUnix +{ + extern CObjectType otMutex; + extern CObjectType otNamedMutex; + + PAL_ERROR + InternalCreateMutex( + CPalThread *pThread, + LPSECURITY_ATTRIBUTES lpMutexAttributes, + BOOL bInitialOwner, + LPCSTR lpName, + HANDLE *phMutex + ); + + PAL_ERROR + InternalReleaseMutex( + CPalThread *pThread, + HANDLE hMutex + ); + + PAL_ERROR + InternalOpenMutex( + CPalThread *pThread, + LPCSTR lpName, + HANDLE *phMutex + ); + +} + +#define SYNCSPINLOCK_F_ASYMMETRIC 1 + +#define SPINLOCKInit(lock) (*(lock) = 0) +#define SPINLOCKDestroy SPINLOCKInit + +void SPINLOCKAcquire (LONG * lock, unsigned int flags); +void SPINLOCKRelease (LONG * lock); +DWORD SPINLOCKTryAcquire (LONG * lock); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Named mutex + +// Temporarily disabling usage of pthread process-shared mutexes on ARM/ARM64 due to functional issues that cannot easily be +// detected with code due to hangs. See https://github.com/dotnet/coreclr/issues/5456. +#if HAVE_FULLY_FEATURED_PTHREAD_MUTEXES && HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES && !(defined(HOST_ARM) || defined(HOST_ARM64) || defined(__FreeBSD__)) + #define NAMED_MUTEX_USE_PTHREAD_MUTEX 1 +#else + #define NAMED_MUTEX_USE_PTHREAD_MUTEX 0 +#endif + +enum class NamedMutexError : DWORD +{ + MaximumRecursiveLocksReached = ERROR_NOT_ENOUGH_MEMORY, + ThreadHasNotAcquiredMutex = ERROR_NOT_OWNER, + Unknown = ERROR_NOT_ENOUGH_MEMORY +}; + +enum class MutexTryAcquireLockResult +{ + AcquiredLock, + AcquiredLockButMutexWasAbandoned, + TimedOut +}; + +#if NAMED_MUTEX_USE_PTHREAD_MUTEX +class MutexHelpers +{ +public: + static void InitializeProcessSharedRobustRecursiveMutex(pthread_mutex_t *mutex); + static void DestroyMutex(pthread_mutex_t *mutex); + + static MutexTryAcquireLockResult TryAcquireLock(pthread_mutex_t *mutex, DWORD timeoutMilliseconds); + static void ReleaseLock(pthread_mutex_t *mutex); +}; +#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX + +class NamedMutexSharedData +{ +private: +#if NAMED_MUTEX_USE_PTHREAD_MUTEX + pthread_mutex_t m_lock; +#else // !NAMED_MUTEX_USE_PTHREAD_MUTEX + UINT32 m_timedWaiterCount; +#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX + UINT32 m_lockOwnerProcessId; + UINT64 m_lockOwnerThreadId; + bool m_isAbandoned; + +public: + NamedMutexSharedData(); + ~NamedMutexSharedData(); + +#if NAMED_MUTEX_USE_PTHREAD_MUTEX +public: + pthread_mutex_t *GetLock(); +#else // !NAMED_MUTEX_USE_PTHREAD_MUTEX +public: + bool HasAnyTimedWaiters() const; + void IncTimedWaiterCount(); + void DecTimedWaiterCount(); +#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX + +public: + bool IsAbandoned() const; + void SetIsAbandoned(bool isAbandoned); + +public: + bool IsLockOwnedByAnyThread() const; + bool IsLockOwnedByCurrentThread() const; + void SetLockOwnerToCurrentThread(); + void ClearLockOwner(); +}; + +class NamedMutexProcessData : public SharedMemoryProcessDataBase +{ +private: + static const UINT8 SyncSystemVersion; + static const DWORD PollLoopMaximumSleepMilliseconds; + +private: + SharedMemoryProcessDataHeader *m_processDataHeader; + NamedMutexSharedData *m_sharedData; + SIZE_T m_lockCount; +#if !NAMED_MUTEX_USE_PTHREAD_MUTEX + HANDLE m_processLockHandle; + int m_sharedLockFileDescriptor; +#endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX + CorUnix::CPalThread *m_lockOwnerThread; + NamedMutexProcessData *m_nextInThreadOwnedNamedMutexList; + +public: + static SharedMemoryProcessDataHeader *CreateOrOpen(LPCSTR name, bool acquireLockIfCreated, bool *createdRef); + static SharedMemoryProcessDataHeader *Open(LPCSTR name); +private: + static SharedMemoryProcessDataHeader *CreateOrOpen(LPCSTR name, bool createIfNotExist, bool acquireLockIfCreated, bool *createdRef); + +public: + NamedMutexProcessData( + SharedMemoryProcessDataHeader *processDataHeader + #if !NAMED_MUTEX_USE_PTHREAD_MUTEX + , + int sharedLockFileDescriptor + #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX + ); + virtual void Close(bool isAbruptShutdown, bool releaseSharedData) override; + +private: + NamedMutexSharedData *GetSharedData() const; + void SetLockOwnerThread(CorUnix::CPalThread *lockOwnerThread); +public: + NamedMutexProcessData *GetNextInThreadOwnedNamedMutexList() const; + void SetNextInThreadOwnedNamedMutexList(NamedMutexProcessData *next); + +public: + MutexTryAcquireLockResult TryAcquireLock(DWORD timeoutMilliseconds); + void ReleaseLock(); + void Abandon(); +private: + void ActuallyReleaseLock(); +}; + +#endif //_PAL_MUTEX_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/numa.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/numa.h new file mode 100644 index 0000000..5ed998c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/numa.h @@ -0,0 +1,39 @@ +// 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: + + include/pal/numa.h + +Abstract: + + Header file for the NUMA functions. + + + +--*/ + +#ifndef _PAL_NUMA_H_ +#define _PAL_NUMA_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +BOOL +NUMASupportInitialize(); + +VOID +NUMASupportCleanup(); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _PAL_CRITSECT_H_ */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/palinternal.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/palinternal.h new file mode 100644 index 0000000..c45ad25 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/palinternal.h @@ -0,0 +1,733 @@ +// 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: + + palinternal.h + +Abstract: + + CoreCLR Platform Adaptation Layer (PAL) header file used by source + file part of the PAL implementation. This is a wrapper over + pal/inc/pal.h. It allows avoiding name collisions when including + system header files, and it allows redirecting calls to 'standard' functions + to their PAL counterpart + +Details : + +A] Rationale (see B] for the quick recipe) +There are 2 types of namespace collisions that must be handled. + +1) standard functions declared in pal.h, which do not need to be + implemented in the PAL because the system's implementation is sufficient. + + (examples : memcpy, strlen, fclose) + + The problem with these is that a prototype for them is provided both in + pal.h and in a system header (stdio.h, etc). If a PAL file needs to + include the files containing both prototypes, the compiler may complain + about the multiple declarations. + + To avoid this, the inclusion of pal.h must be wrapped in a + #define/#undef pair, which will effectiveily "hide" the pal.h + declaration by renaming it to something else. this is done by palinternal.h + in this way : + + #define some_function DUMMY_some_function + #include + #undef some_function + + when a PAL source file includes palinternal.h, it will see a prototype for + DUMMY_some_function instead of some_function; so when it includes the + system header with the "real" prototype, no collision occurs. + + (note : technically, no functions should ever be treated this way, all + system functions should be wrapped according to method 2, so that call + logging through ENTRY macros is done for all functions n the PAL. However + this reason alone is not currently considered enough to warrant a wrapper) + +2) standard functions which must be reimplemented by the PAL, because the + system's implementation does not offer suitable functionnality. + + (examples : widestring functions, networking) + + Here, the problem is more complex. The PAL must provide functions with the + same name as system functions. Due to the nature of Unix dynamic linking, + if this is done, the PAL's implementation will effectively mask the "real" + function, so that all calls are directed to it. This makes it impossible for + a function to be implemented as calling its counterpart in the system, plus + some extra work, because instead of calling the system's implementation, the + function would only call itself in an infinitely recursing nightmare. Even + worse, if by bad luck the system libraries attempt to call the function for + which the PAL provides an implementation, it is the PAL's version that will + be called. + It is therefore necessary to give the PAL's implementation of such functions + a different name. However, PAL consumers (applications built on top of the + PAL) must be able to call the function by its 'official' name, not the PAL's + internal name. + This can be done with some more macro magic, by #defining the official name + to the internal name *in pal.h*. : + + #define some_function PAL_some_function + + This way, while PAL consumer code can use the official name, it is the + internal name that wil be seen at compile time. + However, one extra step is needed. While PAL consumers must use the PAL's + implementation of these functions, the PAL itself must still have access to + the "real" functions. This is done by #undefining in palinternal.h the names + #defined in pal.h : + + #include + #undef some_function. + + At this point, code in the PAL implementation can access *both* its own + implementation of the function (with PAL_some_function) *and* the system's + implementation (with some_function) + + [side note : for the Win32 PAL, this can be accomplished without touching + pal.h. In Windows, symbols in in dynamic libraries are resolved at + compile time. if an application that uses some_function is only linked to + pal.dll, some_function will be resolved to the version in that DLL, + even if other DLLs in the system provide other implementations. In addition, + the function in the DLL can actually have a different name (e.g. + PAL_some_function), to which the 'official' name is aliased when the DLL + is compiled. All this is not possible with Unix dynamic linking, where + symbols are resolved at run-time in a first-found-first-used order. A + module may end up using the symbols from a module it was never linked with, + simply because that module was located somewhere in the dependency chain. ] + + It should be mentionned that even if a function name is not documented as + being implemented in the system, it can still cause problems if it exists. + This is especially a problem for functions in the "reserved" namespace + (names starting with an underscore : _exit, etc). (We shouldn't really be + implementing functions with such a name, but we don't really have a choice) + If such a case is detected, it should be wrapped according to method 2 + + Note that for all this to work, it is important for the PAL's implementation + files to #include palinternal.h *before* any system files, and to never + include pal.h directly. + +B] Procedure for name conflict resolution : + +When adding a function to pal.h, which is implemented by the system and +which does not need a different implementation : + +- add a #define function_name DUMMY_function_name to palinternal.h, after all + the other DUMMY_ #defines (above the #include line) +- add the function's prototype to pal.h (if that isn't already done) +- add a #undef function_name to palinternal.h near all the other #undefs + (after the #include line) + +When overriding a system function with the PAL's own implementation : + +- add a #define function_name PAL_function_name to pal.h, somewhere + before the function's prototype, inside a #ifndef _MSCVER/#endif pair + (to avoid affecting the Win32 build) +- add a #undef function_name to palinternal.h near all the other #undefs + (after the #include line) +- implement the function in the pal, naming it PAL_function_name +- within the PAL, call PAL_function_name() to call the PAL's implementation, +function_name() to call the system's implementation + + + +--*/ + +#ifndef _PAL_INTERNAL_H_ +#define _PAL_INTERNAL_H_ + +#define PAL_IMPLEMENTATION + +/* Include our configuration information so it's always present when + compiling PAL implementation files. */ +#include "config.h" + +#ifdef DEBUG +#define _ENABLE_DEBUG_MESSAGES_ 1 +#else +#define _ENABLE_DEBUG_MESSAGES_ 0 +#endif + +/* Include type_traits before including the pal.h. On newer glibcxx versions, + the type_traits fail to compile if we redefine the wchar_t before including + the header */ +#include + +#ifdef PAL_PERF +#include "pal_perf.h" +#endif + +/* C runtime functions needed to be renamed to avoid duplicate definition + of those functions when including standard C header files */ +#if !defined(_DEBUG) +#define memcpy DUMMY_memcpy +#endif //!defined(_DEBUG) +#define memcmp DUMMY_memcmp +#define memset DUMMY_memset +#define memmove DUMMY_memmove +#define memchr DUMMY_memchr +#define strlen DUMMY_strlen +#define stricmp DUMMY_stricmp +#define strstr DUMMY_strstr +#define strcmp DUMMY_strcmp +#define strcat DUMMY_strcat +#define strncat DUMMY_strncat +#define strcpy DUMMY_strcpy +#define strcspn DUMMY_strcspn +#define strncmp DUMMY_strncmp +#define strncpy DUMMY_strncpy +#define strchr DUMMY_strchr +#define strrchr DUMMY_strrchr +#define strpbrk DUMMY_strpbrk +#define strtod DUMMY_strtod +#define strspn DUMMY_strspn +#define tolower DUMMY_tolower +#define toupper DUMMY_toupper +#define islower DUMMY_islower +#define isupper DUMMY_isupper +#define isprint DUMMY_isprint +#define isdigit DUMMY_isdigit +#define iswalpha DUMMY_iswalpha +#define iswdigit DUMMY_iswdigit +#define iswupper DUMMY_iswupper +#define towupper DUMMY_towupper +#define towlower DUMMY_towlower +#define iswprint DUMMY_iswprint +#define iswspace DUMMY_iswspace +#define iswxdigit DUMMY_iswxdigit +#define wint_t DUMMY_wint_t +#define srand DUMMY_srand +#define atoi DUMMY_atoi +#define atof DUMMY_atof +#define size_t DUMMY_size_t +#define time_t PAL_time_t +#define va_list DUMMY_va_list +#define abs DUMMY_abs +#define llabs DUMMY_llabs +#define ceil DUMMY_ceil +#define cos DUMMY_cos +#define cosh DUMMY_cosh +#define fabs DUMMY_fabs +#define floor DUMMY_floor +#define fmod DUMMY_fmod +#define modf DUMMY_modf +#define sin DUMMY_sin +#define sinh DUMMY_sinh +#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 + defined in pal.h */ +#define PAL_RAND_MAX 0x7fff + +/* The standard headers define isspace and isxdigit as macros and functions, + To avoid redefinition problems, undefine those macros. */ +#ifdef isspace +#undef isspace +#endif +#ifdef isxdigit +#undef isxdigit +#endif +#ifdef isalpha +#undef isalpha +#endif +#ifdef isalnum +#undef isalnum +#endif +#define isspace DUMMY_isspace +#define isxdigit DUMMY_isxdigit +#define isalpha DUMMY_isalpha +#define isalnum DUMMY_isalnum + +#ifdef stdin +#undef stdin +#endif +#ifdef stdout +#undef stdout +#endif +#ifdef stderr +#undef stderr +#endif + +#ifdef SCHAR_MIN +#undef SCHAR_MIN +#endif +#ifdef SCHAR_MAX +#undef SCHAR_MAX +#endif +#ifdef SHRT_MIN +#undef SHRT_MIN +#endif +#ifdef SHRT_MAX +#undef SHRT_MAX +#endif +#ifdef UCHAR_MAX +#undef UCHAR_MAX +#endif +#ifdef USHRT_MAX +#undef USHRT_MAX +#endif +#ifdef ULONG_MAX +#undef ULONG_MAX +#endif +#ifdef LONG_MIN +#undef LONG_MIN +#endif +#ifdef LONG_MAX +#undef LONG_MAX +#endif +#ifdef RAND_MAX +#undef RAND_MAX +#endif +#ifdef DBL_MAX +#undef DBL_MAX +#endif +#ifdef FLT_MAX +#undef FLT_MAX +#endif +#ifdef __record_type_class +#undef __record_type_class +#endif +#ifdef __real_type_class +#undef __real_type_class +#endif + +// The standard headers define va_start and va_end as macros, +// To avoid redefinition problems, undefine those macros. +#ifdef va_start +#undef va_start +#endif +#ifdef va_end +#undef va_end +#endif +#ifdef va_copy +#undef va_copy +#endif + +#define ptrdiff_t PAL_ptrdiff_t +#define intptr_t PAL_intptr_t +#define uintptr_t PAL_uintptr_t +#define timeval PAL_timeval +#define FILE PAL_FILE + +#include "pal.h" +#include "palprivate.h" + +#include "mbusafecrt.h" + +#ifdef _VAC_ +#undef CHAR_BIT +#undef va_arg +#endif + +#if !defined(_MSC_VER) && defined(HOST_64BIT) +#undef _BitScanForward64 +#undef _BitScanReverse64 +#endif + +/* pal.h defines alloca(3) as a compiler builtin. + Redefining it to native libc will result in undefined breakage because + a compiler is allowed to make assumptions about the stack and frame + pointers. */ + +/* Undef all functions and types previously defined so those functions and + types could be mapped to the C runtime and socket implementation of the + native OS */ +#undef exit +#undef memcpy +#undef memcmp +#undef memset +#undef memmove +#undef memchr +#undef strlen +#undef strnlen +#undef wcsnlen +#undef stricmp +#undef strstr +#undef strcmp +#undef strcat +#undef strcspn +#undef strncat +#undef strcpy +#undef strncmp +#undef strncpy +#undef strchr +#undef strrchr +#undef strpbrk +#undef strtoul +#undef strtod +#undef strspn +#undef strtok +#undef strdup +#undef tolower +#undef toupper +#undef islower +#undef isupper +#undef isprint +#undef isdigit +#undef isspace +#undef iswdigit +#undef iswxdigit +#undef iswalpha +#undef iswprint +#undef isxdigit +#undef isalpha +#undef isalnum +#undef iswalpha +#undef iswdigit +#undef iswupper +#undef towupper +#undef towlower +#undef wint_t +#undef atoi +#undef atof +#undef malloc +#undef realloc +#undef free +#undef qsort +#undef bsearch +#undef time +#undef FILE +#undef fclose +#undef fopen +#undef fread +#undef ferror +#undef ftell +#undef fflush +#undef fwrite +#undef fgets +#undef fputs +#undef fseek +#undef fgetpos +#undef fsetpos +#undef getcwd +#undef _flushall +#undef setvbuf +#undef unlink +#undef size_t +#undef time_t +#undef va_list +#undef va_start +#undef va_end +#undef va_copy +#undef stdin +#undef stdout +#undef stderr +#undef abs +#undef llabs +#undef acos +#undef acosh +#undef asin +#undef asinh +#undef atan +#undef atanh +#undef atan2 +#undef cbrt +#undef ceil +#undef cos +#undef cosh +#undef exp +#undef fabs +#undef floor +#undef fmod +#undef fma +#undef ilogb +#undef log +#undef log2 +#undef log10 +#undef modf +#undef pow +#undef scalbn +#undef sin +#undef sinh +#undef sqrt +#undef tan +#undef tanh +#undef acosf +#undef acoshf +#undef asinf +#undef asinhf +#undef atanf +#undef atanhf +#undef atan2f +#undef cbrtf +#undef ceilf +#undef cosf +#undef coshf +#undef expf +#undef fabsf +#undef floorf +#undef fmodf +#undef fmaf +#undef ilogbf +#undef logf +#undef log2f +#undef log10f +#undef modff +#undef powf +#undef scalbnf +#undef sinf +#undef sinhf +#undef sqrtf +#undef tanf +#undef tanhf +#undef rand +#undef srand +#undef errno +#undef getenv +#undef open +#undef glob + +#undef ptrdiff_t +#undef intptr_t +#undef uintptr_t +#undef timeval + + +#undef printf +#undef fprintf +#undef fwprintf +#undef vfprintf +#undef vfwprintf +#undef vprintf +#undef wprintf +#undef wcstod +#undef wcstoul +#undef _wcstoui64 +#undef wcscat +#undef wcscpy +#undef wcslen +#undef wcsncmp +#undef wcschr +#undef wcsrchr +#undef swscanf +#undef wcspbrk +#undef wcsstr +#undef wcscmp +#undef wcsncpy +#undef wcstok +#undef wcscspn +#undef iswupper +#undef iswspace +#undef towlower +#undef towupper +#undef wvsnprintf + +#ifdef HOST_AMD64 +#undef _mm_getcsr +#undef _mm_setcsr +#endif // HOST_AMD64 + +#undef min +#undef max + +#undef SCHAR_MIN +#undef SCHAR_MAX +#undef UCHAR_MAX +#undef SHRT_MIN +#undef SHRT_MAX +#undef USHRT_MAX +#undef LONG_MIN +#undef LONG_MAX +#undef ULONG_MAX +#undef RAND_MAX +#undef DBL_MAX +#undef FLT_MAX +#undef __record_type_class +#undef __real_type_class + +#if HAVE_CHAR_BIT +#undef CHAR_BIT +#endif + +// We need a sigsetjmp prototype in pal.h for the SEH macros, but we +// can't use the "real" prototype (because we don't want to define sigjmp_buf). +// So we must rename the "real" sigsetjmp to avoid redefinition errors. +#define sigsetjmp REAL_sigsetjmp +#define siglongjmp REAL_siglongjmp +#include +#undef sigsetjmp +#undef siglongjmp + +#undef _SIZE_T_DEFINED + +#define _DONT_USE_CTYPE_INLINE_ +#if HAVE_RUNETYPE_H +#include +#endif +#include + +// Don't use C++ wrappers for stdlib.h +// https://gcc.gnu.org/ml/libstdc++/2016-01/msg00025.html +#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS 1 + +#define _WITH_GETLINE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __APPLE__ + +#undef GetCurrentThread +#include + +#include + +#endif // __APPLE__ + +/* we don't really need this header here, but by including it we make sure + we'll catch any definition conflicts */ +#include + +#include + +#if !HAVE_INFTIM +#define INFTIM -1 +#endif // !HAVE_INFTIM + +#define OffsetOf(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER) + +#undef assert +#define assert (Use__ASSERTE_instead_of_assert) assert + +#define string_countof(a) (sizeof(a) / sizeof(a[0]) - 1) + +#ifndef __ANDROID__ +#define TEMP_DIRECTORY_PATH "/tmp/" +#else +// On Android, "/tmp/" doesn't exist; temporary files should go to +// /data/local/tmp/ +#define TEMP_DIRECTORY_PATH "/data/local/tmp/" +#endif + +#define PROCESS_PIPE_NAME_PREFIX ".dotnet-pal-processpipe" + +#ifdef __APPLE__ +#define APPLICATION_CONTAINER_BASE_PATH_SUFFIX "/Library/Group Containers/" + +// Not much to go with, but Max semaphore length on Mac is 31 characters. In a sandbox, the semaphore name +// must be prefixed with an application group ID. This will be 10 characters for developer ID and extra 2 +// characters for group name. For example ABCDEFGHIJ.MS. We still need some characters left +// for the actual semaphore names. +#define MAX_APPLICATION_GROUP_ID_LENGTH 13 +#endif // __APPLE__ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +typedef enum _TimeConversionConstants +{ + tccSecondsToMillieSeconds = 1000, // 10^3 + tccSecondsToMicroSeconds = 1000000, // 10^6 + tccSecondsToNanoSeconds = 1000000000, // 10^9 + tccMillieSecondsToMicroSeconds = 1000, // 10^3 + tccMillieSecondsToNanoSeconds = 1000000, // 10^6 + tccMicroSecondsToNanoSeconds = 1000, // 10^3 + tccSecondsTo100NanoSeconds = 10000000, // 10^7 + tccMicroSecondsTo100NanoSeconds = 10 // 10^1 +} TimeConversionConstants; + +#ifdef __cplusplus +} + +bool +ReadMemoryValueFromFile(const char* filename, uint64_t* val); + +#ifdef __APPLE__ +bool +GetApplicationContainerFolder(PathCharString& buffer, const char *applicationGroupId, int applicationGroupIdLength); +#endif // __APPLE__ + +/* This is duplicated in utilcode.h for CLR, with cooler type-traits */ +template +inline +T* InterlockedExchangePointerT( + T* volatile *Target, + T* Value) +{ + return (T*)(InterlockedExchangePointer( + (PVOID volatile*)Target, + (PVOID)Value)); +} + +template +inline +T* InterlockedCompareExchangePointerT( + T* volatile *destination, + T* exchange, + T* comparand) +{ + return (T*)(InterlockedCompareExchangePointer( + (PVOID volatile*)destination, + (PVOID)exchange, + (PVOID)comparand)); +} + +template +inline T* InterlockedExchangePointerT( + T* volatile * target, + int value) // When NULL is provided as argument. +{ + //STATIC_ASSERT(value == 0); + return InterlockedExchangePointerT(target, reinterpret_cast(value)); +} + +template +inline T* InterlockedCompareExchangePointerT( + T* volatile * destination, + int exchange, // When NULL is provided as argument. + T* comparand) +{ + //STATIC_ASSERT(exchange == 0); + return InterlockedCompareExchangePointerT(destination, reinterpret_cast(exchange), comparand); +} + +template +inline T* InterlockedCompareExchangePointerT( + T* volatile * destination, + T* exchange, + int comparand) // When NULL is provided as argument. +{ + //STATIC_ASSERT(comparand == 0); + return InterlockedCompareExchangePointerT(destination, exchange, reinterpret_cast(comparand)); +} + +#undef InterlockedExchangePointer +#define InterlockedExchangePointer InterlockedExchangePointerT +#undef InterlockedCompareExchangePointer +#define InterlockedCompareExchangePointer InterlockedCompareExchangePointerT + +#include "volatile.h" + +const char StackOverflowMessage[] = "Stack overflow.\n"; + +#endif // __cplusplus + +#endif /* _PAL_INTERNAL_H_ */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/perftrace.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/perftrace.h new file mode 100644 index 0000000..8cfe3b1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/perftrace.h @@ -0,0 +1,70 @@ +// 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: + + include/pal/perftrace.h + +Abstract: + Header file for PAL Performance trace utilities. + + + +--*/ + +/* +Overview of PAL Performance utilities + + */ + +#ifndef _PAL_PERFTRACE_H_ +#define _PAL_PERFTRACE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +#if PAL_PERF +#define PERF_ENTRY(x) \ + ULONGLONG pal_perf_start_tick = 0;\ + PERFLogFunctionEntry( PAL_PERF_##x, &pal_perf_start_tick ) +#define PERF_EXIT(x) \ + PERFLogFunctionExit( PAL_PERF_##x, &pal_perf_start_tick ) +#define PERF_ENTRY_ONLY(x) \ + PERFNoLatencyProfileEntry( PAL_PERF_##x ) + +BOOL PERFInitialize(LPWSTR command_line, LPWSTR exe_path) ; +void PERFTerminate( ); +BOOL PERFAllocThreadInfo( ); +void PERFLogFunctionExit(unsigned int pal_api_id, ULONGLONG *pal_perf_start_tick); +void PERFLogFunctionEntry(unsigned int pal_api_id, ULONGLONG *pal_perf_start_tick); +void PERFEnableThreadProfile(BOOL isInternal); +void PERFDisableThreadProfile(BOOL isInternal); +void PERFEnableProcessProfile( ); +void PERFDisableProcessProfile( ); +BOOL PERFIsProcessProfileEnabled( ); +void PERFNoLatencyProfileEntry(unsigned int pal_api_id ); +void PERFCalibrate(const char* msg); + +#else /* PAL_PERF */ + +#define PERF_ENTRY(x) +#define PERF_ENTRY_ONLY(x) +#define PERF_EXIT(x) + +#endif /* PAL_PERF */ + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _PAL_PERFTRACE_H_ */ + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/printfcpp.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/printfcpp.hpp new file mode 100644 index 0000000..2201cd9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/printfcpp.hpp @@ -0,0 +1,78 @@ +// 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: + + pal/printfcpp.hpp + +Abstract: + Declarations for suspension safe memory allocation functions + + + +--*/ + +#ifndef _PRINTFCPP_HPP +#define _PRINTFCPP_HPP + +#ifdef __cplusplus +#include "pal/threadinfo.hpp" +#endif + +#include + +#ifdef __cplusplus +typedef char16_t wchar_16; // __wchar_16_cpp (which is defined in palinternal.h) needs to be redefined to wchar_16. + +extern "C" +{ + int + __cdecl + PAL_vfprintf( + PAL_FILE *stream, + const char *format, + va_list ap); + + int + __cdecl + PAL_vfwprintf( + PAL_FILE *stream, + const wchar_16 *format, + va_list ap); +} + +namespace CorUnix +{ + int + InternalVfprintf( + CPalThread *pthrCurrent, + PAL_FILE *stream, + const char *format, + va_list ap); + +} +#else // __cplusplus + + int + __cdecl + PAL_vfprintf( + PAL_FILE *stream, + const char *format, + va_list ap); + + int + __cdecl + PAL_vfwprintf( + PAL_FILE *stream, + const wchar_16 *format, + va_list ap); + +#endif // __cplusplus + +#endif // _PRINTFCPP_HPP + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/process.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/process.h new file mode 100644 index 0000000..674b0f4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/process.h @@ -0,0 +1,196 @@ +// 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: + + include/pal/process.h + +Abstract: + + Miscellaneous process related functions. + +Revision History: + + + +--*/ + +#ifndef _PAL_PROCESS_H_ +#define _PAL_PROCESS_H_ + +#include "pal/palinternal.h" +#include "pal/stackstring.hpp" + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/* thread ID of thread that has initiated an ExitProcess (or TerminateProcess). + this is to make sure only one thread cleans up the PAL, and also to prevent + calls to CreateThread from succeeding once shutdown has started + [defined in process.c] +*/ +extern Volatile terminator; + +// The process and session ID of this process, so we can avoid excessive calls to getpid() and getsid(). +extern DWORD gPID; +extern DWORD gSID; + +extern LPWSTR pAppDir; + +// The Mac sandbox application group ID (if exists) and container (shared) path +#ifdef __APPLE__ +extern LPCSTR gApplicationGroupId; +extern int gApplicationGroupIdLength; +#endif // __APPLE__ +extern PathCharString *gSharedFilesPath; + +/*++ +Function: + PROCGetProcessIDFromHandle + +Abstract + Return the process ID from a process handle +--*/ +DWORD PROCGetProcessIDFromHandle(HANDLE hProcess); + +/*++ +Function: + PROCCreateInitialProcess + +Abstract + Initialize all the structures for the initial process. + +Parameter + lpwstrCmdLine: Command line. + lpwstrFullPath : Full path to executable + +Return + TRUE: if successful + FALSE: otherwise + +Notes : + This function takes ownership of lpwstrCmdLine, but not of lpwstrFullPath +--*/ +BOOL PROCCreateInitialProcess(LPWSTR lpwstrCmdLine, LPWSTR lpwstrFullPath); + +/*++ +Function: + PROCCleanupInitialProcess + +Abstract + Cleanup all the structures for the initial process. + +Parameter + VOID + +Return + VOID + +--*/ +VOID PROCCleanupInitialProcess(VOID); + +#if USE_SYSV_SEMAPHORES +/*++ +Function: + PROCCleanupThreadSemIds(VOID); + +Abstract + Cleanup SysV semaphore ids for all threads. + +(no parameters, no return value) +--*/ +VOID PROCCleanupThreadSemIds(VOID); +#endif + +/*++ +Function: + PROCProcessLock + +Abstract + Enter the critical section associated to the current process +--*/ +VOID PROCProcessLock(VOID); + + +/*++ +Function: + PROCProcessUnlock + +Abstract + Leave the critical section associated to the current process +--*/ +VOID PROCProcessUnlock(VOID); + +/*++ +Function + PROCAbortInitialize() + +Abstract + Initialize the process abort crash dump program file path and + name. Doing all of this ahead of time so nothing is allocated + or copied in PROCAbort/signal handler. + +Return + TRUE - succeeds, FALSE - fails + +--*/ +BOOL PROCAbortInitialize(); + +/*++ +Function: + PROCAbort() + + Aborts the process after calling the shutdown cleanup handler. This function + should be called instead of calling abort() directly. + + Does not return +--*/ +PAL_NORETURN +VOID PROCAbort(); + +/*++ +Function: + PROCNotifyProcessShutdown + + Calls the abort handler to do any shutdown cleanup. Call be + called from the unhandled native exception handler. + +(no return value) +--*/ +VOID PROCNotifyProcessShutdown(); + +/*++ +Function: + PROCCreateCrashDumpIfEnabled + + Creates crash dump of the process (if enabled). Can be + called from the unhandled native exception handler. + +(no return value) +--*/ +VOID PROCCreateCrashDumpIfEnabled(); + +/*++ +Function: + InitializeFlushProcessWriteBuffers + +Abstract + This function initializes data structures needed for the FlushProcessWriteBuffers +Return + TRUE if it succeeded, FALSE otherwise +--*/ +BOOL InitializeFlushProcessWriteBuffers(); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif //PAL_PROCESS_H_ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/procobj.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/procobj.hpp new file mode 100644 index 0000000..50c162c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/procobj.hpp @@ -0,0 +1,124 @@ +// 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: + + include/pal/procobj.hpp + +Abstract: + Header file for process structures + + + +--*/ + +#ifndef _PAL_PROCOBJ_HPP_ +#define _PAL_PROCOBJ_HPP_ + +#include "corunix.hpp" + +namespace CorUnix +{ + extern CObjectType otProcess; + + typedef enum + { + PS_IDLE, + PS_STARTING, + PS_RUNNING, + PS_DONE + } PROCESS_STATE; + + // + // Struct for process module list (EnumProcessModules) + // + struct ProcessModules + { + ProcessModules *Next; + PVOID BaseAddress; + CHAR Name[0]; + }; + + // + // Ideally dwProcessId would be part of the process object's immutable + // data. Doing so, though, creates complications in CreateProcess. The + // contents of the immutable data for a new object must be set before + // that object is registered with the object manager (as the object + // manager may make a copy of the immutable data). The PID for a new + // process, though, is not known until after creation. Registering the + // process object after process creation creates an undesirable error path + // -- if we are not able to register the process object (say, because of + // a low resource condition) we would be forced to return an error to + // the caller of CreateProcess, even though the new process was actually + // created... + // + // Note: we could work around this by effectively always going down + // the create suspended path. That is, the new process would not exec until + // the parent process released it. It's unclear how much benefit this would + // provide us. + // + + class CProcProcessLocalData + { + public: + CProcProcessLocalData() + : + dwProcessId(0), + ps(PS_IDLE), + dwExitCode(0), + lAttachCount(0), + pProcessModules(NULL), + cProcessModules(0) + { + }; + + ~CProcProcessLocalData(); + + DWORD dwProcessId; + PROCESS_STATE ps; + DWORD dwExitCode; + LONG lAttachCount; + ProcessModules *pProcessModules; + DWORD cProcessModules; + }; + + PAL_ERROR + InternalCreateProcess( + CPalThread *pThread, + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation + ); + + PAL_ERROR + InitializeProcessData( + void + ); + + PAL_ERROR + InitializeProcessCommandLine( + LPWSTR lpwstrCmdLine, + LPWSTR lpwstrFullPath + ); + + PAL_ERROR + CreateInitialProcessAndThreadObjects( + CPalThread *pThread + ); + + extern IPalObject *g_pobjProcess; +} + +#endif // _PAL_PROCOBJ_HPP_ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/seh.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/seh.hpp new file mode 100644 index 0000000..ba04d14 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/seh.hpp @@ -0,0 +1,150 @@ +// 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: + + include/pal/seh.hpp + +Abstract: + Header file for public Structured Exception Handling stuff + + + +--*/ + +#ifndef _PAL_SEH_HPP_ +#define _PAL_SEH_HPP_ + +#include "config.h" +#include "pal/palinternal.h" +#include "pal/corunix.hpp" + +// Uncomment this define to turn off the signal handling thread. +// #define DO_NOT_USE_SIGNAL_HANDLING_THREAD + +/*++ +Function : + SEHInitialize + + Initialize all SEH-related stuff (signals, etc) + +Parameters: + CPalThread * pthrCurrent : reference to the current thread. + flags : PAL initialize flags + +Return value: + TRUE if SEH support initialization succeeded, + FALSE otherwise + +--*/ +BOOL +SEHInitialize(CorUnix::CPalThread *pthrCurrent, DWORD flags); + +/*++ +Function : + SEHCleanup + + Clean up SEH-related stuff(signals, etc) + +Parameters: + None + + (no return value) +--*/ +VOID +SEHCleanup(); + +/*++ +Function: + SEHProcessException + + Send the PAL exception to any handler registered. + +Parameters: + PAL_SEHException* exception + +Return value: + Returns TRUE if the exception happened in managed code and the execution should + continue (with possibly modified context). + Returns FALSE if the exception happened in managed code and it was not handled. + In case the exception was handled by calling a catch handler, it doesn't return at all. +--*/ +BOOL +SEHProcessException(PAL_SEHException* exception); + +/*++ +Function: + AllocateExceptionRecords + +Parameters: + exceptionRecord - output pointer to the allocated Windows exception record + contextRecord - output pointer to the allocated Windows context record +--*/ +VOID +AllocateExceptionRecords(EXCEPTION_RECORD** exceptionRecord, CONTEXT** contextRecord); + +#if !HAVE_MACH_EXCEPTIONS +// TODO: Implement for Mach exceptions. Not in CoreCLR surface area. +/*++ +Function : + SEHHandleControlEvent + + handle Control-C and Control-Break events (call handler routines, + notify debugger) + +Parameters : + DWORD event : event that occurred + LPVOID eip : instruction pointer when exception occurred + +(no return value) + +Notes : + Handlers are called on a last-installed, first called basis, until a + handler returns TRUE. If no handler returns TRUE (or no hanlder is + installed), the default behavior is to call ExitProcess +--*/ +void SEHHandleControlEvent(DWORD event, LPVOID eip); +#endif // !HAVE_MACH_EXCEPTIONS + +extern "C" +{ + +/*++ +Function : + SEHEnable + + Enable SEH-related stuff on this thread + +Parameters: + CPalThread * pthrCurrent : reference to the current thread. + +Return value : + ERROR_SUCCESS, if enabling succeeded + an error code, otherwise +--*/ +CorUnix::PAL_ERROR SEHEnable(CorUnix::CPalThread *pthrCurrent); + +/*++ +Function : + SEHDisable + + Disable SEH-related stuff on this thread + +Parameters: + CPalThread * pthrCurrent : reference to the current thread. + +Return value : + ERROR_SUCCESS, if enabling succeeded + an error code, otherwise +--*/ +CorUnix::PAL_ERROR SEHDisable(CorUnix::CPalThread *pthrCurrent); + +} + +#endif /* _PAL_SEH_HPP_ */ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/semaphore.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/semaphore.hpp new file mode 100644 index 0000000..f0bb130 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/semaphore.hpp @@ -0,0 +1,65 @@ +// 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: + + semaphore.hpp + +Abstract: + + Semaphore object structure definition. + + + +--*/ + +#ifndef _PAL_SEMAPHORE_H_ +#define _PAL_SEMAPHORE_H_ + +#include "corunix.hpp" + +namespace CorUnix +{ + extern CObjectType otSemaphore; + + typedef struct + { + LONG lMaximumCount; + } SemaphoreImmutableData; + + PAL_ERROR + InternalCreateSemaphore( + CPalThread *pThread, + LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + LONG lInitialCount, + LONG lMaximumCount, + LPCWSTR lpName, + HANDLE *phSemaphore + ); + + PAL_ERROR + InternalReleaseSemaphore( + CPalThread *pThread, + HANDLE hSemaphore, + LONG lReleaseCount, + LPLONG lpPreviousCount + ); + +} + +#endif //_PAL_SEMAPHORE_H_ + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/sharedmemory.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/sharedmemory.h new file mode 100644 index 0000000..74e1cd4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/sharedmemory.h @@ -0,0 +1,283 @@ +// 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. + +#ifndef _PAL_SHARED_MEMORY_H_ +#define _PAL_SHARED_MEMORY_H_ + +#include "corunix.hpp" + +#ifndef static_assert_no_msg +#define static_assert_no_msg( cond ) static_assert( cond, #cond ) +#endif // !static_assert_no_msg + +#ifndef _countof +#define _countof(a) (sizeof(a) / sizeof(a[0])) +#endif // !_countof + +// The folder used for storing shared memory files and their lock files is defined in +// the gSharedFilesPath global variable. The value of the variable depends on which +// OS is being used, and if the application is running in a sandbox in Mac. +// gSharedFilesPath ends with '/' +// - Global shared memory files go in: +// {gSharedFilesPath}/.dotnet/shm/global/ +// - Session-scoped shared memory files go in: +// {gSharedFilesPath}/.dotnet/shm/session/ +// - Lock files associated with global shared memory files go in: +// {gSharedFilesPath}/.dotnet/lockfiles/global/ +// - Lock files associated with session-scoped shared memory files go in: +// {gSharedFilesPath}/.dotnet/lockfiles/session/ + +#define SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT (_MAX_FNAME - 1) +#define SHARED_MEMORY_MAX_NAME_CHAR_COUNT (string_countof("Global\\") + SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT) + +#define SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_NAME ".dotnet" +#define SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_NAME ".dotnet/shm" +#define SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME ".dotnet/lockfiles" +static_assert_no_msg(_countof(SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME) >= _countof(SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_NAME)); + +#define SHARED_MEMORY_GLOBAL_DIRECTORY_NAME "global" +#define SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX "session" +static_assert_no_msg(_countof(SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX) >= _countof(SHARED_MEMORY_GLOBAL_DIRECTORY_NAME)); + +#define SHARED_MEMORY_UNIQUE_TEMP_NAME_TEMPLATE ".coreclr.XXXXXX" + +#define SHARED_MEMORY_MAX_SESSION_ID_CHAR_COUNT (10) + +// Note that this Max size does not include the prefix folder path size which is unknown (in the case of sandbox) until runtime +#define SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT \ + ( \ + string_countof(SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME) + \ + 1 /* path separator */ + \ + string_countof(SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX) + \ + SHARED_MEMORY_MAX_SESSION_ID_CHAR_COUNT + \ + 1 /* path separator */ + \ + SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT \ + ) + +class AutoFreeBuffer +{ +private: + void *m_buffer; + bool m_cancel; + +public: + AutoFreeBuffer(void *buffer); + ~AutoFreeBuffer(); + +public: + void Cancel(); +}; + +enum class SharedMemoryError : DWORD +{ + NameEmpty = ERROR_INVALID_PARAMETER, + NameTooLong = ERROR_FILENAME_EXCED_RANGE, + NameInvalid = ERROR_INVALID_NAME, + HeaderMismatch = ERROR_INVALID_HANDLE, + OutOfMemory = ERROR_NOT_ENOUGH_MEMORY, + IO = ERROR_OPEN_FAILED +}; + +class SharedMemoryException +{ +private: + DWORD m_errorCode; + +public: + SharedMemoryException(DWORD errorCode); + DWORD GetErrorCode() const; +}; + +class SharedMemoryHelpers +{ +private: + static const mode_t PermissionsMask_CurrentUser_ReadWriteExecute; + static const mode_t PermissionsMask_AllUsers_ReadWrite; + static const mode_t PermissionsMask_AllUsers_ReadWriteExecute; +public: + static const UINT32 InvalidProcessId; + static const SIZE_T InvalidThreadId; + static const UINT64 InvalidSharedThreadId; + +public: + static SIZE_T AlignDown(SIZE_T value, SIZE_T alignment); + static SIZE_T AlignUp(SIZE_T value, SIZE_T alignment); + + static void *Alloc(SIZE_T byteCount); + + template static void BuildSharedFilesPath(PathCharString& destination, const char (&suffix)[SuffixByteCount]); + static void BuildSharedFilesPath(PathCharString& destination, const char *suffix, int suffixByteCount); + static bool AppendUInt32String(PathCharString& destination, UINT32 value); + + static bool EnsureDirectoryExists(const char *path, bool isGlobalLockAcquired, bool createIfNotExist = true, bool isSystemDirectory = false); +private: + static int Open(LPCSTR path, int flags, mode_t mode = static_cast(0)); +public: + static int OpenDirectory(LPCSTR path); + static int CreateOrOpenFile(LPCSTR path, bool createIfNotExist = true, bool *createdRef = nullptr); + static void CloseFile(int fileDescriptor); + + static SIZE_T GetFileSize(int fileDescriptor); + static void SetFileSize(int fileDescriptor, SIZE_T byteCount); + + static void *MemoryMapFile(int fileDescriptor, SIZE_T byteCount); + + static bool TryAcquireFileLock(int fileDescriptor, int operation); + static void ReleaseFileLock(int fileDescriptor); + + static void VerifyStringOperation(bool success); + static void VerifyStringOperation(BOOL success) + { + VerifyStringOperation(success != FALSE); + } +}; + +class SharedMemoryId +{ +private: + LPCSTR m_name; + SIZE_T m_nameCharCount; + bool m_isSessionScope; // false indicates global scope + +public: + SharedMemoryId(); + SharedMemoryId(LPCSTR name, SIZE_T nameCharCount, bool isSessionScope); + SharedMemoryId(LPCSTR name); + +public: + LPCSTR GetName() const; + SIZE_T GetNameCharCount() const; + bool IsSessionScope() const; + bool Equals(SharedMemoryId *other) const; + +public: + bool AppendSessionDirectoryName(PathCharString& path) const; +}; + +enum class SharedMemoryType : UINT8 +{ + Mutex +}; + +class SharedMemorySharedDataHeader +{ +private: + union + { + struct + { + SharedMemoryType m_type; + UINT8 m_version; + }; + UINT64 _raw; // use the same size for the header on all archs, and align the data to a pointer + }; + +public: + static SIZE_T DetermineTotalByteCount(SIZE_T dataByteCount); + +public: + SharedMemorySharedDataHeader(SharedMemoryType type, UINT8 version); + +public: + SharedMemoryType GetType() const; + UINT8 GetVersion() const; + void *GetData(); +}; + +class SharedMemoryProcessDataBase +{ +public: + virtual void Close(bool isAbruptShutdown, bool releaseSharedData) + { + } + + virtual ~SharedMemoryProcessDataBase() + { + } +}; + +class SharedMemoryProcessDataHeader +{ +private: + SIZE_T m_refCount; + SharedMemoryId m_id; + SharedMemoryProcessDataBase *m_data; + int m_fileDescriptor; + SharedMemorySharedDataHeader *m_sharedDataHeader; + SIZE_T m_sharedDataTotalByteCount; + SharedMemoryProcessDataHeader *m_nextInProcessDataHeaderList; + +public: + static SharedMemoryProcessDataHeader *CreateOrOpen(LPCSTR name, SharedMemorySharedDataHeader requiredSharedDataHeader, SIZE_T sharedDataByteCount, bool createIfNotExist, bool *createdRef); + +public: + static SharedMemoryProcessDataHeader *PalObject_GetProcessDataHeader(CorUnix::IPalObject *object); + static void PalObject_SetProcessDataHeader(CorUnix::IPalObject *object, SharedMemoryProcessDataHeader *processDataHeader); + static void PalObject_Close(CorUnix::CPalThread *thread, CorUnix::IPalObject *object, bool isShuttingDown, bool cleanUpPalSharedState); + +private: + SharedMemoryProcessDataHeader(SharedMemoryId *id, int fileDescriptor, SharedMemorySharedDataHeader *sharedDataHeader, SIZE_T sharedDataTotalByteCount); +public: + static SharedMemoryProcessDataHeader *New(SharedMemoryId *id, int fileDescriptor, SharedMemorySharedDataHeader *sharedDataHeader, SIZE_T sharedDataTotalByteCount); + ~SharedMemoryProcessDataHeader(); + void Close(); + +public: + SharedMemoryId *GetId(); + SharedMemoryProcessDataBase *GetData() const; + void SetData(SharedMemoryProcessDataBase *data); + SharedMemorySharedDataHeader *GetSharedDataHeader() const; + SIZE_T GetSharedDataTotalByteCount() const; + SharedMemoryProcessDataHeader *GetNextInProcessDataHeaderList() const; + void SetNextInProcessDataHeaderList(SharedMemoryProcessDataHeader *next); + +public: + void IncRefCount(); + void DecRefCount(); +}; + +class SharedMemoryManager +{ +private: + static CRITICAL_SECTION s_creationDeletionProcessLock; + static int s_creationDeletionLockFileDescriptor; + + static PathCharString* s_runtimeTempDirectoryPath; + static PathCharString* s_sharedMemoryDirectoryPath; + +private: + static SharedMemoryProcessDataHeader *s_processDataHeaderListHead; + +#ifdef _DEBUG +private: + static SIZE_T s_creationDeletionProcessLockOwnerThreadId; + static SIZE_T s_creationDeletionFileLockOwnerThreadId; +#endif // _DEBUG + +public: + static bool StaticInitialize(); + static void StaticClose(); + +public: + static void AcquireCreationDeletionProcessLock(); + static void ReleaseCreationDeletionProcessLock(); + static void AcquireCreationDeletionFileLock(); + static void ReleaseCreationDeletionFileLock(); + +public: + static bool CopySharedMemoryBasePath(PathCharString& destination); + +#ifdef _DEBUG +public: + static bool IsCreationDeletionProcessLockAcquired(); + static bool IsCreationDeletionFileLockAcquired(); +#endif // _DEBUG + +public: + static void AddProcessDataHeader(SharedMemoryProcessDataHeader *processDataHeader); + static void RemoveProcessDataHeader(SharedMemoryProcessDataHeader *processDataHeader); + static SharedMemoryProcessDataHeader *FindProcessDataHeader(SharedMemoryId *id); +}; + +#endif // !_PAL_SHARED_MEMORY_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/sharedmemory.inl b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/sharedmemory.inl new file mode 100644 index 0000000..3a0c979 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/sharedmemory.inl @@ -0,0 +1,22 @@ +// 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. + +#ifndef _PAL_SHARED_MEMORY_INL_ +#define _PAL_SHARED_MEMORY_INL_ + +#include "sharedmemory.h" + +#include "dbgmsg.h" + +#include + +template +void SharedMemoryHelpers::BuildSharedFilesPath( + PathCharString& destination, + const char (&suffix)[SuffixByteCount]) +{ + BuildSharedFilesPath(destination, suffix, SuffixByteCount - 1); +} + +#endif // !_PAL_SHARED_MEMORY_INL_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/shm.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/shm.hpp new file mode 100644 index 0000000..1baca7c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/shm.hpp @@ -0,0 +1,40 @@ +// 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: + + include/pal/shm.hpp + +Abstract: + C++ typesafe accessors for shared memory routines + + + +--*/ + +#ifndef _SHM_HPP_ +#define _SHM_HPP_ + +#include "shmemory.h" + +// +// Some compilers (e.g., HPUX/IA64) warn about using NULL to initialize +// something of type SHMPTR, since SHMPTR is defined as DWORD_PTR, which +// isn't considered a pointer type... +// + +#define SHMPTR_TO_TYPED_PTR(type, shmptr) reinterpret_cast(shmptr) + +/* Set ptr to NULL if shmPtr == 0, else set ptr to SHMPTR_TO_TYPED_PTR(type, shmptr) + return FALSE if SHMPTR_TO_TYPED_PTR returns NULL ptr from non null shmptr, + TRUE otherwise */ +#define SHMPTR_TO_TYPED_PTR_BOOL(type, ptr, shmptr) \ + ((shmptr != 0) ? ((ptr = SHMPTR_TO_TYPED_PTR(type, shmptr)) != NULL) : ((ptr = NULL) == NULL)) + +#endif // _SHM_HPP_ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/shmemory.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/shmemory.h new file mode 100644 index 0000000..b414031 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/shmemory.h @@ -0,0 +1,125 @@ +// 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: + + include/pal/shmemory.h + +Abstract: + Header file for interface to shared memory + +How to use : + +Lock/Release functions must be used when manipulating data in shared memory, to ensure inter-process synchronization. + + + +--*/ + +#ifndef _PAL_SHMEMORY_H_ +#define _PAL_SHMEMORY_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/* +Type for shared memory blocks + */ +typedef LPVOID SHMPTR; + +typedef enum { + SIID_NAMED_OBJECTS, + SIID_FILE_LOCKS, + + SIID_LAST +} SHM_INFO_ID; + +/*++ +SHMInitialize + +Hook this process into the PAL shared memory system; initialize the shared +memory if no other process has done it. +--*/ +BOOL SHMInitialize(void); + +/*++ +SHMCleanup + +Release all shared memory resources held; remove ourselves from the list of +registered processes, and remove all shared memory files if no process remains +--*/ +void SHMCleanup(void); + +/*++ +SHMLock + +Restrict shared memory access to the current thread of the current process + +(no parameters) + +Return value : + New lock count +--*/ +int SHMLock(void); + +/*++ +SHMRelease + +Release a lock on shared memory taken with SHMLock. + +(no parameters) + +Return value : + New lock count +--*/ +int SHMRelease(void); + + +/*++ +Function : + SHMGetInfo + + Retrieve some information from shared memory + +Parameters : + SHM_INFO_ID element : identifier of element to retrieve + +Return value : + Value of specified element + +Notes : + The SHM lock should be held while manipulating shared memory +--*/ +SHMPTR SHMGetInfo(SHM_INFO_ID element); + +/*++ +Function : + SHMSetInfo + + Place some information into shared memory + +Parameters : + SHM_INFO_ID element : identifier of element to save + SHMPTR value : new value of element + +Return value : + TRUE if successful, FALSE otherwise. + +Notes : + The SHM lock should be held while manipulating shared memory +--*/ +BOOL SHMSetInfo(SHM_INFO_ID element, SHMPTR value); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _PAL_SHMEMORY_H_ */ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/signal.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/signal.hpp new file mode 100644 index 0000000..7b5e1d7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/signal.hpp @@ -0,0 +1,121 @@ +// 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: + + include/pal/signal.hpp + +Abstract: + Private signal handling utilities for SEH + + + +--*/ + +#ifndef _PAL_SIGNAL_HPP_ +#define _PAL_SIGNAL_HPP_ + +#if !HAVE_MACH_EXCEPTIONS + +// Return context and status for the signal_handler_worker. +struct SignalHandlerWorkerReturnPoint +{ + bool returnFromHandler; + CONTEXT context; +}; + +extern bool g_registered_signal_handlers; +extern bool g_enable_alternate_stack_check; + +/*++ +Function : + CallSignalHandlerWrapperX + + These functions are never called, only a fake stack frame will be setup to have a return + address set to SignalHandlerWorkerReturnX during SIGSEGV handling. + It enables the unwinder to unwind stack from the handling code to the actual failure site. + + There are four variants of this function based on what stack alignment needs to be done + to ensure properly aligned stack pointer at the call site of the signal_handler_worker. + +Parameters : + none + + (no return value) +--*/ +extern "C" void CallSignalHandlerWrapper0(); +extern "C" void CallSignalHandlerWrapper4(); +extern "C" void CallSignalHandlerWrapper8(); +extern "C" void CallSignalHandlerWrapper12(); + +// Offset of the return address from the signal_handler_worker in the CallSignalHandlerWrapperX +// relative to the start of the function. +// There are four offsets matching the stack alignments as described in the function header above. +extern "C" int SignalHandlerWorkerReturnOffset0; +extern "C" int SignalHandlerWorkerReturnOffset4; +extern "C" int SignalHandlerWorkerReturnOffset8; +extern "C" int SignalHandlerWorkerReturnOffset12; + +/*++ +Function : + signal_handler_worker + + Handles signal on the original stack where the signal occured. + Invoked via setcontext. + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + returnPoint - context to which the function returns if the common_signal_handler returns + + (no return value) +--*/ +extern "C" void signal_handler_worker(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint); + +/*++ +Function : + ExecuteHandlerOnCustomStack + + Execute signal handler on a custom stack, the current stack pointer is specified by the customSp + If the customSp is 0, then the handler is executed on the original stack where the signal was fired. + It installs a fake stack frame to enable stack unwinding to the signal source location. + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + returnPoint - context to which the function returns if the common_signal_handler returns + + (no return value) +--*/ +void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t sp, SignalHandlerWorkerReturnPoint* returnPoint); + +#endif // !HAVE_MACH_EXCEPTIONS + +/*++ +Function : + SEHInitializeSignals + + Set-up signal handlers to catch signals and translate them to exceptions + +Parameters : + flags: PAL initialization flags + +Return : + TRUE in case of a success, FALSE otherwise +--*/ +BOOL SEHInitializeSignals(CorUnix::CPalThread *pthrCurrent, DWORD flags); + +/*++ +Function : + SEHCleanupSignals + + Restore default signal handlers + + (no parameters, no return value) +--*/ +void SEHCleanupSignals(); + +#endif /* _PAL_SIGNAL_HPP_ */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/stackstring.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/stackstring.hpp new file mode 100644 index 0000000..a37da80 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/stackstring.hpp @@ -0,0 +1,268 @@ +// 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. + +#ifndef __STACKSTRING_H_ +#define __STACKSTRING_H_ + +template +class StackString +{ +private: + T m_innerBuffer[STACKCOUNT + 1]; + T * m_buffer; + SIZE_T m_size; // actual allocated size + SIZE_T m_count; // actual length of string + + void NullTerminate() + { + m_buffer[m_count] = 0; + } + + void DeleteBuffer() + { + if (m_innerBuffer != m_buffer) + PAL_free(m_buffer); + + m_buffer = NULL; + return; + } + + BOOL ReallocateBuffer(SIZE_T count) + { + // count is always > STACKCOUNT here. + // We got so far, we will allocate a little extra + // to prevent frequent allocations +#if _DEBUG + SIZE_T count_allocated = count; +#else + SIZE_T count_allocated = count + 100; +#endif //_DEBUG + + BOOL dataOnStack = m_buffer == m_innerBuffer; + if( dataOnStack ) + { + m_buffer = NULL; + } + + T * newBuffer = (T *)PAL_realloc(m_buffer, (count_allocated + 1) * sizeof(T)); + if (NULL == newBuffer) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + + DeleteBuffer(); + m_count = 0; + m_buffer = m_innerBuffer; + return FALSE; + } + + if( dataOnStack) + { + CopyMemory(newBuffer, m_innerBuffer, (m_count + 1) * sizeof(T)); + } + + m_buffer = newBuffer; + m_count = count; + m_size = count_allocated + 1; + + return TRUE; + } + + BOOL HasAvailableMemory(SIZE_T count) + { + return (count < m_size); + } + + //NOTE: Always call this before modifying the underlying buffer + BOOL Resize(SIZE_T count) + { + + if (NULL == m_buffer) + { + m_buffer = m_innerBuffer; + } + + if (HasAvailableMemory(count)) + { + m_count = count; + } + else + { + if (count > STACKCOUNT) + { + return ReallocateBuffer(count); + } + else + { + m_count = count; + m_size = STACKCOUNT+1; + } + } + + return TRUE; + } + + StackString(const StackString &s) + { + Set(s); + } + +public: + StackString() + : m_buffer(m_innerBuffer), m_size(STACKCOUNT+1), m_count(0) + { + } + + + BOOL Set(const T * buffer, SIZE_T count) + { + if (!Resize(count)) + return FALSE; + + CopyMemory(m_buffer, buffer, (count + 1) * sizeof(T)); + NullTerminate(); + return TRUE; + } + + BOOL Set(const StackString &s) + { + return Set(s.m_buffer, s.m_count); + } + + template BOOL Set(const T (&buffer)[bufferLength]) + { + // bufferLength includes terminator character + return Set(buffer, bufferLength - 1); + } + + SIZE_T GetCount() const + { + return m_count; + } + + SIZE_T GetSizeOf() const + { + return m_size * sizeof(T); + } + + CONST T * GetString() const + { + return (const T *)m_buffer; + } + + operator const T * () const { return GetString(); } + + //Always preserves the existing content + T * OpenStringBuffer(SIZE_T count) + { + T * result = NULL; + if (Resize(count)) + { + result = (T *)m_buffer; + } + return result; + } + + T * OpenStringBuffer() + { + return m_buffer; + } + + //count should not include the terminating null + void CloseBuffer(SIZE_T count) + { + if (m_count > count) + m_count = count; + + NullTerminate(); + return; + } + + //Call this with the best estimate if you want to + //prevent possible reallocations on further operations + BOOL Reserve(SIZE_T count) + { + SIZE_T endpos = m_count; + + if (!Resize(count)) + return FALSE; + + m_count = endpos; + NullTerminate(); + + return TRUE; + } + + //count Should not include the terminating null + BOOL Append(const T * buffer, SIZE_T count) + { + SIZE_T endpos = m_count; + if (!Resize(m_count + count)) + return FALSE; + + CopyMemory(&m_buffer[endpos], buffer, (count + 1) * sizeof(T)); + NullTerminate(); + return TRUE; + } + + BOOL Append(const StackString &s) + { + return Append(s.GetString(), s.GetCount()); + } + + template BOOL Append(const T (&buffer)[bufferLength]) + { + // bufferLength includes terminator character + return Append(buffer, bufferLength - 1); + } + + BOOL Append(T ch) + { + SIZE_T endpos = m_count; + if (!Resize(m_count + 1)) + return FALSE; + + m_buffer[endpos] = ch; + NullTerminate(); + return TRUE; + } + + BOOL IsEmpty() + { + return 0 == m_buffer[0]; + } + + void Clear() + { + m_count = 0; + NullTerminate(); + } + + ~StackString() + { + DeleteBuffer(); + } +}; + +#if _DEBUG +typedef StackString<32, CHAR> PathCharString; +typedef StackString<32, WCHAR> PathWCharString; +#else +typedef StackString PathCharString; +typedef StackString PathWCharString; +#endif +#endif + +// Some Helper Definitions +BOOL +PAL_GetPALDirectoryW( + PathWCharString& lpDirectoryName); +BOOL +PAL_GetPALDirectoryA( + PathCharString& lpDirectoryName); +DWORD +GetCurrentDirectoryA( + PathCharString& lpBuffer); +void +FILEDosToUnixPathA( + PathCharString& lpPath); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/synchcache.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/synchcache.hpp new file mode 100644 index 0000000..9275765 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/synchcache.hpp @@ -0,0 +1,397 @@ +// 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: + + include/pal/synchcache.hpp + +Abstract: + Simple look-aside cache for unused objects with default + constructor or no constructor + + + +--*/ + +#ifndef _SYNCH_CACHE_H_ +#define _SYNCH_CACHE_H_ + +#include "pal/thread.hpp" +#include "pal/malloc.hpp" + +namespace CorUnix +{ + template class CSynchCache + { + typedef union _USynchCacheStackNode + { + union _USynchCacheStackNode * next; + BYTE objraw[sizeof(T)]; + } USynchCacheStackNode; + + static const int MaxDepth = 256; + + Volatile m_pHead; + CRITICAL_SECTION m_cs; + Volatile m_iDepth; + int m_iMaxDepth; +#ifdef _DEBUG + int m_iMaxTrackedDepth; +#endif + + void Lock(CPalThread * pthrCurrent) + { InternalEnterCriticalSection(pthrCurrent, &m_cs); } + void Unlock(CPalThread * pthrCurrent) + { InternalLeaveCriticalSection(pthrCurrent, &m_cs); } + + public: + CSynchCache(int iMaxDepth = MaxDepth) : + m_pHead(NULL), + m_iDepth(0), + m_iMaxDepth(iMaxDepth) +#ifdef _DEBUG + ,m_iMaxTrackedDepth(0) +#endif + { + InternalInitializeCriticalSection(&m_cs); + if (m_iMaxDepth < 0) + { + m_iMaxDepth = 0; + } + } + + ~CSynchCache() + { + Flush(NULL, true); + InternalDeleteCriticalSection(&m_cs); + } + +#ifdef _DEBUG + int GetMaxTrackedDepth() { return m_iMaxTrackedDepth; } +#endif + + T * Get(CPalThread * pthrCurrent) + { + T * pObj = NULL; + + Get(pthrCurrent, 1, &pObj); + return pObj; + } + + int Get(CPalThread * pthrCurrent, int n, T ** ppObjs) + { + void * pvObjRaw; + USynchCacheStackNode * pNode; + int i = 0,j; + + Lock(pthrCurrent); + pNode = m_pHead; + while (pNode && i < n) + { + ppObjs[i] = (T *)pNode; + pNode = pNode->next; + i++; + } + m_pHead = pNode; + m_iDepth -= i; + +#ifdef _DEBUG + if (NULL == m_pHead && m_iDepth != 0) + { + // Can't use ASSERT here, since this is header + // is included by other headers with inline methods + // which causes template instatiation in the header + // where the DEBUG CHANNEL is not defined and cannot + // be defined + fprintf(stderr,"SYNCCACHE: Invalid cache depth value"); + DebugBreak(); + } +#endif // _DEBUG + + Unlock(pthrCurrent); + + for (j=i;j(); + if (NULL == pvObjRaw) + break; +#ifdef _DEBUG + memset(pvObjRaw, 0, sizeof(USynchCacheStackNode)); +#endif + ppObjs[j] = reinterpret_cast(pvObjRaw); + } + + for (i=0;i(pobj); + + if (NULL == pobj) + { + return; + } + + pobj->~T(); + + Lock(pthrCurrent); + if (m_iDepth < m_iMaxDepth) + { +#ifdef _DEBUG + if (m_iDepth > m_iMaxTrackedDepth) + { + m_iMaxTrackedDepth = m_iDepth; + } +#endif + pNode->next = m_pHead; + m_pHead = pNode; + m_iDepth++; + } + else + { + InternalDelete((char *)pNode); + } + Unlock(pthrCurrent); + } + + void Flush(CPalThread * pthrCurrent, bool fDontLock = false) + { + USynchCacheStackNode * pNode, * pTemp; + + if (!fDontLock) + { + Lock(pthrCurrent); + } + pNode = m_pHead; + m_pHead = NULL; + m_iDepth = 0; + if (!fDontLock) + { + Unlock(pthrCurrent); + } + + while (pNode) + { + pTemp = pNode; + pNode = pNode->next; + InternalDelete((char *)pTemp); + } + } + }; + + template class CSHRSynchCache + { + union _USHRSynchCacheStackNode; // fwd declaration + typedef struct _SHRCachePTRs + { + union _USHRSynchCacheStackNode * pNext; + SharedID shrid; + } SHRCachePTRs; + typedef union _USHRSynchCacheStackNode + { + SHRCachePTRs pointers; + BYTE objraw[sizeof(T)]; + } USHRSynchCacheStackNode; + + static const int MaxDepth = 256; + static const int PreAllocFactor = 10; // Everytime a Get finds no available + // cached raw intances, it preallocates + // MaxDepth/PreAllocFactor new raw + // instances and store them into the + // cache before continuing + + Volatile m_pHead; + CRITICAL_SECTION m_cs; + Volatile m_iDepth; + int m_iMaxDepth; +#ifdef _DEBUG + int m_iMaxTrackedDepth; +#endif + + void Lock(CPalThread * pthrCurrent) + { InternalEnterCriticalSection(pthrCurrent, &m_cs); } + void Unlock(CPalThread * pthrCurrent) + { InternalLeaveCriticalSection(pthrCurrent, &m_cs); } + + public: + CSHRSynchCache(int iMaxDepth = MaxDepth) : + m_pHead(NULL), + m_iDepth(0), + m_iMaxDepth(iMaxDepth) +#ifdef _DEBUG + ,m_iMaxTrackedDepth(0) +#endif + { + InternalInitializeCriticalSection(&m_cs); + if (m_iMaxDepth < 0) + { + m_iMaxDepth = 0; + } + } + + ~CSHRSynchCache() + { + Flush(NULL, true); + InternalDeleteCriticalSection(&m_cs); + } + +#ifdef _DEBUG + int GetMaxTrackedDepth() { return m_iMaxTrackedDepth; } +#endif + + SharedID Get(CPalThread * pthrCurrent) + { + SharedID shridObj = NULL; + + Get(pthrCurrent, 1, &shridObj); + return shridObj; + } + + int Get(CPalThread * pthrCurrent, int n, SharedID * shridpObjs) + { + SharedID shridObj; + void * pvObjRaw = NULL; + USHRSynchCacheStackNode * pNode; + int i = 0, j, k; + + Lock(pthrCurrent); + pNode = m_pHead; + while (pNode && i < n) + { + shridpObjs[i] = pNode->pointers.shrid; + pvObjRaw = (void *)pNode; + pNode = pNode->pointers.pNext; + i++; + } + m_pHead = pNode; + m_iDepth -= i; + +#ifdef _DEBUG + if (NULL == m_pHead && m_iDepth != 0) + { + // Can't use ASSERT here, since this is header + // (see comment above) + fprintf(stderr,"SYNCCACHE: Invalid cache depth value"); + DebugBreak(); + } +#endif // _DEBUG + + if (0 == m_iDepth) + { + for (k=0; k(pNode), 0, sizeof(USHRSynchCacheStackNode)); +#endif + pNode->pointers.shrid = shridObj; + pNode->pointers.pNext = m_pHead; + m_pHead = pNode; + m_iDepth++; + } + } + + Unlock(pthrCurrent); + + for (j=i;j(pNode); + + pObj->~T(); + + pNode->pointers.shrid = shridObj; + + Lock(pthrCurrent); + if (m_iDepth < m_iMaxDepth) + { + m_iDepth++; +#ifdef _DEBUG + if (m_iDepth > m_iMaxTrackedDepth) + { + m_iMaxTrackedDepth = m_iDepth; + } +#endif + pNode->pointers.pNext = m_pHead; + m_pHead = pNode; + } + else + { + free(shridObj); + } + Unlock(pthrCurrent); + } + + void Flush(CPalThread * pthrCurrent, bool fDontLock = false) + { + USHRSynchCacheStackNode * pNode, * pTemp; + SharedID shridTemp; + + if (!fDontLock) + { + Lock(pthrCurrent); + } + pNode = m_pHead; + m_pHead = NULL; + m_iDepth = 0; + if (!fDontLock) + { + Unlock(pthrCurrent); + } + + while (pNode) + { + pTemp = pNode; + pNode = pNode->pointers.pNext; + shridTemp = pTemp->pointers.shrid; + free(shridTemp); + } + } + }; +} + +#endif // _SYNCH_CACHE_H_ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/synchobjects.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/synchobjects.hpp new file mode 100644 index 0000000..66d4710 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/synchobjects.hpp @@ -0,0 +1,219 @@ +// 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: + + include/pal/synchobjects.hpp + +Abstract: + Header file for synchronization manager and controllers + + + +--*/ + +#ifndef _SINCHOBJECTS_HPP_ +#define _SINCHOBJECTS_HPP_ + +#include "corunix.hpp" +#include "threadinfo.hpp" +#include "mutex.hpp" +#include "shm.hpp" +#include "list.h" + +#include + +#define SharedID SHMPTR +#define SharedIDToPointer(shID) SHMPTR_TO_TYPED_PTR(PVOID, shID) +#define SharedIDToTypePointer(TYPE,shID) SHMPTR_TO_TYPED_PTR(TYPE, shID) + +namespace CorUnix +{ + DWORD InternalWaitForMultipleObjectsEx( + CPalThread * pthrCurrent, + DWORD nCount, + CONST HANDLE *lpHandles, + BOOL bWaitAll, + DWORD dwMilliseconds, + BOOL bAlertable, + BOOL bPrioritize = FALSE); + + DWORD InternalSignalObjectAndWait( + CPalThread *thread, + HANDLE hObjectToSignal, + HANDLE hObjectToWaitOn, + DWORD dwMilliseconds, + BOOL bAlertable); + + PAL_ERROR InternalSleepEx( + CPalThread * pthrCurrent, + DWORD dwMilliseconds, + BOOL bAlertable); + + enum THREAD_STATE + { + TS_IDLE, + TS_STARTING, + TS_RUNNING, + TS_FAILED, + TS_DONE, + }; + + // forward declarations + struct _ThreadWaitInfo; + struct _WaitingThreadsListNode; + class CSynchData; + + typedef struct _WaitingThreadsListNode * PWaitingThreadsListNode; + typedef struct _OwnedObjectsListNode * POwnedObjectsListNode; + typedef struct _ThreadApcInfoNode * PThreadApcInfoNode; + + typedef struct _ThreadWaitInfo + { + WaitType wtWaitType; + WaitDomain wdWaitDomain; + LONG lObjCount; + LONG lSharedObjCount; + CPalThread * pthrOwner; + PWaitingThreadsListNode rgpWTLNodes[MAXIMUM_WAIT_OBJECTS]; + + _ThreadWaitInfo() : wtWaitType(SingleObject), wdWaitDomain(LocalWait), + lObjCount(0), lSharedObjCount(0), + pthrOwner(NULL) {} + } ThreadWaitInfo; + + typedef struct _ThreadNativeWaitData + { + pthread_mutex_t mutex; + pthread_cond_t cond; + int iPred; + DWORD dwObjectIndex; + ThreadWakeupReason twrWakeupReason; + bool fInitialized; + + _ThreadNativeWaitData() : + iPred(0), + dwObjectIndex(0), + twrWakeupReason(WaitSucceeded), + fInitialized(false) + { + } + + ~_ThreadNativeWaitData(); + } ThreadNativeWaitData; + + class CThreadSynchronizationInfo : public CThreadInfoInitializer + { + friend class CPalSynchronizationManager; + friend class CSynchWaitController; + + THREAD_STATE m_tsThreadState; + SharedID m_shridWaitAwakened; + Volatile m_lLocalSynchLockCount; + Volatile m_lSharedSynchLockCount; + LIST_ENTRY m_leOwnedObjsList; + + CRITICAL_SECTION m_ownedNamedMutexListLock; + NamedMutexProcessData *m_ownedNamedMutexListHead; + + ThreadNativeWaitData m_tnwdNativeData; + ThreadWaitInfo m_twiWaitInfo; + +#ifdef SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + static const int PendingSignalingsArraySize = 10; + LONG m_lPendingSignalingCount; + CPalThread * m_rgpthrPendingSignalings[PendingSignalingsArraySize]; + LIST_ENTRY m_lePendingSignalingsOverflowList; +#endif // SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + + public: + + CThreadSynchronizationInfo(); + virtual ~CThreadSynchronizationInfo(); + + // + // CThreadInfoInitializer methods + // + virtual PAL_ERROR InitializePreCreate(void); + + virtual PAL_ERROR InitializePostCreate( + CPalThread *pthrCurrent, + SIZE_T threadId, + DWORD dwLwpId + ); + + THREAD_STATE GetThreadState(void) + { + return m_tsThreadState; + }; + + void SetThreadState(THREAD_STATE tsThreadState) + { + m_tsThreadState = tsThreadState; + }; + + ThreadNativeWaitData * GetNativeData() + { + return &m_tnwdNativeData; + } + +#if SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + PAL_ERROR RunDeferredThreadConditionSignalings(); +#endif // SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + + // NOTE: the following methods provide non-synchronized access to + // the list of owned objects for this thread. Any thread + // accessing this list MUST own the appropriate + // synchronization lock(s). + void AddObjectToOwnedList(POwnedObjectsListNode pooln); + void RemoveObjectFromOwnedList(POwnedObjectsListNode pooln); + POwnedObjectsListNode RemoveFirstObjectFromOwnedList(void); + + void AddOwnedNamedMutex(NamedMutexProcessData *processData); + void RemoveOwnedNamedMutex(NamedMutexProcessData *processData); + NamedMutexProcessData *RemoveFirstOwnedNamedMutex(); + bool OwnsNamedMutex(NamedMutexProcessData *processData); + + // The following methods provide access to the native wait lock for + // those implementations that need a lock to protect the support for + // native thread blocking (e.g.: pthread conditions) + void AcquireNativeWaitLock(void); + void ReleaseNativeWaitLock(void); + bool TryAcquireNativeWaitLock(void); + }; + + class CThreadApcInfo : public CThreadInfoInitializer + { + friend class CPalSynchronizationManager; + + PThreadApcInfoNode m_ptainHead; + PThreadApcInfoNode m_ptainTail; + + public: + CThreadApcInfo() : + m_ptainHead(NULL), + m_ptainTail(NULL) + { + } + }; + + class CPalSynchMgrController + { + public: + static IPalSynchronizationManager * CreatePalSynchronizationManager(); + + static PAL_ERROR StartWorker(CPalThread * pthrCurrent); + + static PAL_ERROR PrepareForShutdown(void); + + static PAL_ERROR Shutdown(CPalThread *pthrCurrent, bool fFullCleanup); + }; +} + +#endif // _SINCHOBJECTS_HPP_ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/thread.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/thread.hpp new file mode 100644 index 0000000..cb4cb9f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/thread.hpp @@ -0,0 +1,791 @@ +// 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: + + include/pal/thread.hpp + +Abstract: + Header file for thread structures + + + +--*/ + +#ifndef _PAL_THREAD_HPP_ +#define _PAL_THREAD_HPP_ + +#include "corunix.hpp" +#include "shm.hpp" +#include "cs.hpp" + +#include +#include +#if HAVE_MACH_EXCEPTIONS +#include +#endif // HAVE_MACH_EXCEPTIONS + +#include "threadsusp.hpp" +#include "threadinfo.hpp" +#include "synchobjects.hpp" +#include + +namespace CorUnix +{ + enum PalThreadType + { + UserCreatedThread, + PalWorkerThread, + SignalHandlerThread + }; + + PAL_ERROR + InternalCreateThread( + CPalThread *pThread, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + DWORD dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + PalThreadType eThreadType, + SIZE_T* pThreadId, + HANDLE *phThread + ); + + PAL_ERROR + InternalGetThreadPriority( + CPalThread *pThread, + HANDLE hTargetThread, + int *piNewPriority + ); + + PAL_ERROR + InternalSetThreadPriority( + CPalThread *pThread, + HANDLE hTargetThread, + int iNewPriority + ); + + PAL_ERROR + InternalGetThreadDataFromHandle( + CPalThread *pThread, + HANDLE hThread, + CPalThread **ppTargetThread, + IPalObject **ppobjThread + ); + + VOID + InternalEndCurrentThread( + CPalThread *pThread + ); + + PAL_ERROR + InternalCreateDummyThread( + CPalThread *pThread, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + CPalThread **ppDummyThread, + HANDLE *phThread + ); + + PAL_ERROR + InternalSetThreadDescription( + CPalThread *, + HANDLE, + PCWSTR + ); + + PAL_ERROR + CreateThreadData( + CPalThread **ppThread + ); + + PAL_ERROR + CreateThreadObject( + CPalThread *pThread, + CPalThread *pNewThread, + HANDLE *phThread + ); + + BOOL + GetThreadTimesInternal( + IN HANDLE hThread, + OUT LPFILETIME lpKernelTime, + OUT LPFILETIME lpUserTime); + +#if HAVE_MACH_EXCEPTIONS + + // Structure used to return data about a single handler to a caller. + struct MachExceptionHandler + { + exception_mask_t m_mask; + exception_handler_t m_handler; + exception_behavior_t m_behavior; + thread_state_flavor_t m_flavor; + }; + + // Class abstracting previously registered Mach exception handlers for a thread. + struct CThreadMachExceptionHandlers + { + public: + // Maximum number of exception ports we hook. Must be the count + // of all bits set in the exception masks defined in machexception.h. + static const int s_nPortsMax = 6; + + // Saved exception ports, exactly as returned by + // thread_swap_exception_ports. + mach_msg_type_number_t m_nPorts; + exception_mask_t m_masks[s_nPortsMax]; + exception_handler_t m_handlers[s_nPortsMax]; + exception_behavior_t m_behaviors[s_nPortsMax]; + thread_state_flavor_t m_flavors[s_nPortsMax]; + + CThreadMachExceptionHandlers() : + m_nPorts(-1) + { + } + + // Get handler details for a given type of exception. If successful the structure pointed at by + // pHandler is filled in and true is returned. Otherwise false is returned. + bool GetHandler(exception_type_t eException, MachExceptionHandler *pHandler); + + private: + // Look for a handler for the given exception within the given handler node. Return its index if + // successful or -1 otherwise. + int GetIndexOfHandler(exception_mask_t bmExceptionMask); + }; +#endif // HAVE_MACH_EXCEPTIONS + + class CThreadCRTInfo : public CThreadInfoInitializer + { + public: + CHAR * strtokContext; // Context for strtok function + WCHAR * wcstokContext; // Context for wcstok function + + CThreadCRTInfo() : + strtokContext(NULL), + wcstokContext(NULL) + { + }; + }; + + class CPalThread + { + friend + PAL_ERROR + InternalCreateThread( + CPalThread *, + LPSECURITY_ATTRIBUTES, + DWORD, + LPTHREAD_START_ROUTINE, + LPVOID, + DWORD, + PalThreadType, + SIZE_T*, + HANDLE* + ); + + friend + PAL_ERROR + InternalCreateDummyThread( + CPalThread *pThread, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + CPalThread **ppDummyThread, + HANDLE *phThread + ); + + friend + PAL_ERROR + InternalSetThreadPriority( + CPalThread *, + HANDLE, + int + ); + + friend + PAL_ERROR + InternalSetThreadDescription( + CPalThread *, + HANDLE, + PCWSTR + ); + + friend + PAL_ERROR + CreateThreadData( + CPalThread **ppThread + ); + + friend + PAL_ERROR + CreateThreadObject( + CPalThread *pThread, + CPalThread *pNewThread, + HANDLE *phThread + ); + + private: + + CPalThread *m_pNext; + DWORD m_dwExitCode; + BOOL m_fExitCodeSet; + CRITICAL_SECTION m_csLock; + bool m_fLockInitialized; + bool m_fIsDummy; + + // + // Minimal reference count, used primarily for cleanup purposes. A + // new thread object has an initial refcount of 1. This initial + // reference is removed by CorUnix::InternalEndCurrentThread. + // + // The only other spot the refcount is touched is from within + // CPalObjectBase::ReleaseReference -- incremented before the + // destructors for an ojbect are called, and decremented afterwords. + // This permits the freeing of the thread structure to happen after + // the freeing of the enclosing thread object has completed. + // + + LONG m_lRefCount; + + // + // The IPalObject for this thread. The thread will release its reference + // to this object when it exits. + // + + IPalObject *m_pThreadObject; + + // + // Thread ID info + // + + SIZE_T m_threadId; + DWORD m_dwLwpId; + pthread_t m_pthreadSelf; + +#if HAVE_MACH_THREADS + mach_port_t m_machPortSelf; +#endif + + // > 0 when there is an exception holder which causes h/w + // exceptions to be sent down the C++ exception chain. + int m_hardwareExceptionHolderCount; + + // + // Start info + // + + LPTHREAD_START_ROUTINE m_lpStartAddress; + LPVOID m_lpStartParameter; + BOOL m_bCreateSuspended; + + int m_iThreadPriority; + PalThreadType m_eThreadType; + + // + // pthread mutex / condition variable for gating thread startup. + // InternalCreateThread waits on the condition variable to determine + // when the new thread has reached passed all failure points in + // the entry routine + // + + pthread_mutex_t m_startMutex; + pthread_cond_t m_startCond; + bool m_fStartItemsInitialized; + bool m_fStartStatus; + bool m_fStartStatusSet; + + // Base address of the stack of this thread + void* m_stackBase; + // Limit address of the stack of this thread + void* m_stackLimit; + // Signal handler's alternate stack to help with stack overflow + void* m_alternateStack; + + // + // The thread entry routine (called from InternalCreateThread) + // + + static void* ThreadEntry(void * pvParam); + + // + // Data for PAL side-by-side support + // + + private: +#if HAVE_MACH_EXCEPTIONS + // Record of Mach exception handlers that were already registered when we register our own CoreCLR + // specific handlers. + CThreadMachExceptionHandlers m_sMachExceptionHandlers; +#endif // HAVE_MACH_EXCEPTIONS + + public: + + // + // Embedded information for areas owned by other subsystems + // + + CThreadSynchronizationInfo synchronizationInfo; + CThreadSuspensionInfo suspensionInfo; + CThreadApcInfo apcInfo; + CThreadCRTInfo crtInfo; + + CPalThread() + : + m_pNext(NULL), + m_dwExitCode(STILL_ACTIVE), + m_fExitCodeSet(FALSE), + m_fLockInitialized(FALSE), + m_fIsDummy(FALSE), + m_lRefCount(1), + m_pThreadObject(NULL), + m_threadId(0), + m_dwLwpId(0), + m_pthreadSelf(0), +#if HAVE_MACH_THREADS + m_machPortSelf(0), +#endif + m_hardwareExceptionHolderCount(0), + m_lpStartAddress(NULL), + m_lpStartParameter(NULL), + m_bCreateSuspended(FALSE), + m_iThreadPriority(THREAD_PRIORITY_NORMAL), + m_eThreadType(UserCreatedThread), + m_fStartItemsInitialized(FALSE), + m_fStartStatus(FALSE), + m_fStartStatusSet(FALSE), + m_stackBase(NULL), + m_stackLimit(NULL), + m_alternateStack(NULL) + { + }; + + virtual ~CPalThread(); + + PAL_ERROR + RunPreCreateInitializers( + void + ); + + // + // m_threadId and m_dwLwpId must be set before calling + // RunPostCreateInitializers + // + + PAL_ERROR + RunPostCreateInitializers( + void + ); + + // + // SetStartStatus is called by THREADEntry or InternalSuspendNewThread + // to inform InternalCreateThread of the results of the thread's + // initialization. InternalCreateThread calls WaitForStartStatus to + // obtain this information (and will not return to its caller until + // the info is available). + // + + void + SetStartStatus( + bool fStartSucceeded + ); + + bool + WaitForStartStatus( + void + ); + + void + Lock( + CPalThread *pThread + ) + { + InternalEnterCriticalSection(pThread, &m_csLock); + }; + + void + Unlock( + CPalThread *pThread + ) + { + InternalLeaveCriticalSection(pThread, &m_csLock); + }; + + // + // The following three methods provide access to the + // native lock used to protect thread native wait data. + // + + void + AcquireNativeWaitLock( + void + ) + { + synchronizationInfo.AcquireNativeWaitLock(); + } + + void + ReleaseNativeWaitLock( + void + ) + { + synchronizationInfo.ReleaseNativeWaitLock(); + } + + bool + TryAcquireNativeWaitLock( + void + ) + { + return synchronizationInfo.TryAcquireNativeWaitLock(); + } + + static void + SetLastError( + DWORD dwLastError + ) + { + // Reuse errno to store last error + errno = dwLastError; + }; + + static DWORD + GetLastError( + void + ) + { + // Reuse errno to store last error + return errno; + }; + + void + SetExitCode( + DWORD dwExitCode + ) + { + m_dwExitCode = dwExitCode; + m_fExitCodeSet = TRUE; + }; + + BOOL + GetExitCode( + DWORD *pdwExitCode + ) + { + *pdwExitCode = m_dwExitCode; + return m_fExitCodeSet; + }; + + SIZE_T + GetThreadId( + void + ) + { + return m_threadId; + }; + + DWORD + GetLwpId( + void + ) + { + return m_dwLwpId; + }; + + pthread_t + GetPThreadSelf( + void + ) + { + return m_pthreadSelf; + }; + +#if HAVE_MACH_THREADS + mach_port_t + GetMachPortSelf( + void + ) + { + return m_machPortSelf; + }; +#endif + + bool + IsHardwareExceptionsEnabled() + { + return m_hardwareExceptionHolderCount > 0; + } + + inline void + IncrementHardwareExceptionHolderCount() + { + ++m_hardwareExceptionHolderCount; + } + + inline void + DecrementHardwareExceptionHolderCount() + { + --m_hardwareExceptionHolderCount; + } + + LPTHREAD_START_ROUTINE + GetStartAddress( + void + ) + { + return m_lpStartAddress; + }; + + LPVOID + GetStartParameter( + void + ) + { + return m_lpStartParameter; + }; + + BOOL + GetCreateSuspended( + void + ) + { + return m_bCreateSuspended; + }; + + PalThreadType + GetThreadType( + void + ) + { + return m_eThreadType; + }; + + int + GetThreadPriority( + void + ) + { + return m_iThreadPriority; + }; + + IPalObject * + GetThreadObject( + void + ) + { + return m_pThreadObject; + } + + BOOL + IsDummy( + void + ) + { + return m_fIsDummy; + }; + + CPalThread* + GetNext( + void + ) + { + return m_pNext; + }; + + void + SetNext( + CPalThread *pNext + ) + { + m_pNext = pNext; + }; + +#if !HAVE_MACH_EXCEPTIONS + BOOL + EnsureSignalAlternateStack( + void + ); + + void + FreeSignalAlternateStack( + void + ); +#endif // !HAVE_MACH_EXCEPTIONS + + void + AddThreadReference( + void + ); + + void + ReleaseThreadReference( + void + ); + + // Get base address of the current thread's stack + static + void * + GetStackBase( + void + ); + + // Get cached base address of this thread's stack + // Can be called only for the current thread. + void * + GetCachedStackBase( + void + ); + + // Get limit address of the current thread's stack + static + void * + GetStackLimit( + void + ); + + // Get cached limit address of this thread's stack + // Can be called only for the current thread. + void * + GetCachedStackLimit( + void + ); + +#if HAVE_MACH_EXCEPTIONS + // Hook Mach exceptions, i.e., call thread_swap_exception_ports + // to replace the thread's current exception ports with our own. + // The previously active exception ports are saved. Called when + // this thread enters a region of code that depends on this PAL. + // Should only fail on internal errors. + PAL_ERROR EnableMachExceptions(); + + // Unhook Mach exceptions, i.e., call thread_set_exception_ports + // to restore the thread's exception ports with those we saved + // in EnableMachExceptions. Called when this thread leaves a + // region of code that depends on this PAL. Should only fail + // on internal errors. + PAL_ERROR DisableMachExceptions(); + + // The exception handling thread needs to be able to get at the list of handlers that installing our + // own handler on a thread has displaced (in case we need to forward an exception that we don't want + // to handle). + CThreadMachExceptionHandlers *GetSavedMachHandlers() + { + return &m_sMachExceptionHandlers; + } +#endif // HAVE_MACH_EXCEPTIONS + }; + + extern "C" CPalThread *CreateCurrentThreadData(); + + inline CPalThread *GetCurrentPalThread() + { + return reinterpret_cast(pthread_getspecific(thObjKey)); + } + + inline CPalThread *InternalGetCurrentThread() + { + CPalThread *pThread = GetCurrentPalThread(); + if (pThread == nullptr) + pThread = CreateCurrentThreadData(); + return pThread; + } + +/*** + + $$TODO: These are needed only to support cross-process thread duplication + + class CThreadImmutableData + { + public: + DWORD dwProcessId; + }; + + class CThreadSharedData + { + public: + DWORD dwThreadId; + DWORD dwExitCode; + }; +***/ + + // + // The process local information for a thread is just a pointer + // to the underlying CPalThread object. + // + + class CThreadProcessLocalData + { + public: + CPalThread *pThread; + }; + + extern CObjectType otThread; +} + +BOOL +TLSInitialize( + void + ); + +VOID +TLSCleanup( + void + ); + +extern PAL_ActivationFunction g_activationFunction; +extern PAL_SafeActivationCheckFunction g_safeActivationCheckFunction; + +/*++ +Macro: + THREADSilentGetCurrentThreadId + +Abstract: + Same as GetCurrentThreadId, but it doesn't output any traces. + It is useful for tracing functions to display the thread ID + without generating any new traces. + + TODO: how does the perf of pthread_self compare to + InternalGetCurrentThread when we find the thread in the + cache? + + If the perf of pthread_self is comparable to that of the stack + bounds based lookaside system, why aren't we using it in the + cache? + + In order to match the thread ids that debuggers use at least for + linux we need to use gettid(). + +--*/ +#if defined(__linux__) +#define PlatformGetCurrentThreadId() (SIZE_T)syscall(SYS_gettid) +#elif defined(__APPLE__) +inline SIZE_T PlatformGetCurrentThreadId() { + uint64_t tid; + pthread_threadid_np(pthread_self(), &tid); + return (SIZE_T)tid; +} +#elif defined(__FreeBSD__) +#include +inline SIZE_T PlatformGetCurrentThreadId() { + long tid; + thr_self(&tid); + return (SIZE_T)tid; +} +#elif defined(__NetBSD__) +#include +#define PlatformGetCurrentThreadId() (SIZE_T)_lwp_self() +#else +#define PlatformGetCurrentThreadId() (SIZE_T)pthread_self() +#endif + +inline SIZE_T THREADSilentGetCurrentThreadId() { + static __thread SIZE_T tid; + if (!tid) + tid = PlatformGetCurrentThreadId(); + return tid; +} + +#endif // _PAL_THREAD_HPP_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/threadinfo.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/threadinfo.hpp new file mode 100644 index 0000000..8819a5a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/threadinfo.hpp @@ -0,0 +1,101 @@ +// 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: + + include/pal/threadinfo.hpp + +Abstract: + Header file for thread info initialzer + + + +--*/ + +#ifndef _PAL_THREADINFO_H_ +#define _PAL_THREADINFO_H_ + +#include "corunix.hpp" + +namespace CorUnix +{ + // + // There are a number of different functional areas for which we need to + // store per-thread data: + // * synchronization + // * structure exception handling + // * asynchronous procedure calls + // * thread suspension + // * thread-local storage + // * CRT per-thread buffers + // + // For each of the above functional areas we build a class that stores + // the necessary data. An instance of each of these classes is embedded + // in the main thread class. The classes must not have any failure paths + // in their constructors. Each class inherits from a common parent class + // that exposes two virtual initialization routines (which may return an + // error). The first initialization routine is called after the thread + // object is allocated, but before the new thread is created. Any + // initialization that is not dependant on knowledge of the new thread's + // ID (and by extension need not run in the context of the new thread) + // should take place in the first routine. Work that must run in the + // context of the new thread or that must know the new thread's ID + // should take place in the second initialization routine. + // + + class CThreadInfoInitializer + { + public: + + // + // InitializePreCreate is called before the new thread is started. + // Any allocations or other initializations that may fail that do + // not need to run in the context of the new thread (or know the + // new thread's ID) should take place in this routine. + // + + virtual + PAL_ERROR + InitializePreCreate( + void + ) + { + return NO_ERROR; + }; + + // + // InitializePostCreate is called from within the context of the + // new thread. + // + + virtual + PAL_ERROR + InitializePostCreate( + CPalThread *pThread, + SIZE_T threadId, + DWORD dwLwpId + ) + { + return NO_ERROR; + }; + }; + + // + // InternalGetCurrentThread obtains the CPalThread instance for the + // calling thread. That instance should only be used by the calling + // thread. If another thread will at some point need access to this + // thread information it should be given a referenced pointer to + // the IPalObject stored within the CPalThread. + // + + extern pthread_key_t thObjKey; + + CPalThread *InternalGetCurrentThread(); +} + +#endif // _PAL_THREADINFO_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/threadsusp.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/threadsusp.hpp new file mode 100644 index 0000000..76fd447 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/threadsusp.hpp @@ -0,0 +1,384 @@ +// 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: + + include/pal/threadsusp.hpp + +Abstract: + Declarations for thread suspension + + + +--*/ + +#ifndef _PAL_THREADSUSP_HPP +#define _PAL_THREADSUSP_HPP + +// Need this ifdef since this header is included by .c files so they can use the diagnostic function. +#ifdef __cplusplus + +// Note: do not include malloc.hpp from this header. The template InternalDelete +// needs to know the layout of class CPalThread, which includes a member of type +// CThreadSuspensionInfo, which is defined later in this header, and it is not +// yet known at this point. +// If any future change should bring this issue back, the circular dependency can +// be further broken by making the InternalDelete's CPalThread argument a +// templatized argument, so that type checking on it takes place only at +// instantiation time. +#include "pal/threadinfo.hpp" +#include "pal/thread.hpp" +#include "pal/printfcpp.hpp" +#include "pal/mutex.hpp" +#include "pal/init.h" +#if !HAVE_MACH_EXCEPTIONS +#include +#endif // !HAVE_MACH_EXCEPTIONS +#include +#include + +// We have a variety of options for synchronizing thread suspensions and resumptions between the requestor and +// target threads. Analyze the various capabilities given to us by configure and define one of three macros +// here for simplicity: +// USE_POSIX_SEMAPHORES +// USE_SYSV_SEMAPHORES +// USE_PTHREAD_CONDVARS +#if HAS_POSIX_SEMAPHORES + +// Favor posix semaphores. +#define USE_POSIX_SEMAPHORES 1 + +#if HAVE_SYS_SEMAPHORE_H +#include +#elif HAVE_SEMAPHORE_H +#include +#endif // HAVE_SYS_SEMAPHORE_H + +#elif HAS_PTHREAD_MUTEXES && HAVE_MACH_EXCEPTIONS + +// Can only use the pthread solution if we're not using signals since pthread mutexes are not signal safe. +#define USE_PTHREAD_CONDVARS 1 + +#include + +#elif HAS_SYSV_SEMAPHORES + +// SYSV semaphores are our last choice since they're shared across processes so it's possible to leak them +// on abnormal process termination. +#define USE_SYSV_SEMAPHORES 1 + +#include +#include + +#else +#error "Don't know how to synchronize thread suspends and resumes on this platform" +#endif // HAS_POSIX_SEMAPHORES + +#include + +namespace CorUnix +{ +#ifdef _DEBUG +#define MAX_TRACKED_CRITSECS 8 +#endif + + PAL_ERROR + InternalResumeThread( + CPalThread *pthrResumer, + HANDLE hTarget, + DWORD *pdwSuspendCount + ); + + class CThreadSuspensionInfo : public CThreadInfoInitializer + { + private: + BOOL m_fPending; // TRUE if a suspension is pending on a thread (because the thread is in an unsafe region) + BOOL m_fSelfsusp; // TRUE if thread is self suspending and while thread is self suspended + BOOL m_fSuspendedForShutdown; // TRUE once the thread is suspended during PAL cleanup + int m_nBlockingPipe; // blocking pipe used for a process that was created suspended +#ifdef _DEBUG + Volatile m_lNumThreadsSuspendedByThisThread; // number of threads that this thread has suspended; used for suspension diagnostics +#endif +#if DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX + int m_nSpinlock; // thread's suspension spinlock, which is used to synchronize suspension and resumption attempts +#else // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX + pthread_mutex_t m_ptmSuspmutex; // thread's suspension mutex, which is used to synchronize suspension and resumption attempts + BOOL m_fSuspmutexInitialized; +#endif // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX +#if USE_POSIX_SEMAPHORES + sem_t m_semSusp; // suspension semaphore + sem_t m_semResume; // resumption semaphore + BOOL m_fSemaphoresInitialized; +#elif USE_SYSV_SEMAPHORES + // necessary id's and sembuf structures for SysV semaphores + int m_nSemsuspid; // id for the suspend semaphore + int m_nSemrespid; // id for the resume semaphore + struct sembuf m_sbSemwait; // struct representing a wait operation + struct sembuf m_sbSempost; // struct representing a post operation +#elif USE_PTHREAD_CONDVARS + pthread_cond_t m_condSusp; // suspension condition variable + pthread_mutex_t m_mutexSusp; // mutex associated with the condition above + BOOL m_fSuspended; // set to true once the suspend has been acknowledged + + pthread_cond_t m_condResume; // resumption condition variable + pthread_mutex_t m_mutexResume; // mutex associated with the condition above + BOOL m_fResumed; // set to true once the resume has been acknowledged + + BOOL m_fSemaphoresInitialized; +#endif // USE_POSIX_SEMAPHORES + + /* Most of the variables above are either accessed by a thread + holding the appropriate suspension mutex(es) or are only + accessed by their own threads (and thus don't require + synchronization). + + m_fPending, m_fSuspendedForShutdown, + m_fSuspendSignalSent, and m_fResumeSignalSent + may be set by a different thread than the owner and thus + require synchronization. + + m_fSelfsusp is set to TRUE only by its own thread but may be later + accessed by other threads. + + m_lNumThreadsSuspendedByThisThread is accessed by its owning + thread and therefore does not require synchronization. */ + +#ifdef _DEBUG + VOID + IncrNumThreadsSuspendedByThisThread( + ) + { + InterlockedIncrement(&m_lNumThreadsSuspendedByThisThread); + }; + + VOID + DecrNumThreadsSuspendedByThisThread( + ) + { + InterlockedDecrement(&m_lNumThreadsSuspendedByThisThread); + }; +#endif + + VOID + AcquireSuspensionLocks( + CPalThread *pthrSuspender, + CPalThread *pthrTarget + ); + + VOID + ReleaseSuspensionLocks( + CPalThread *pthrSuspender, + CPalThread *pthrTarget + ); + +#if USE_POSIX_SEMAPHORES + sem_t* + GetSuspendSemaphore( + void + ) + { + return &m_semSusp; + }; + + sem_t* + GetResumeSemaphore( + void + ) + { + return &m_semResume; + }; +#elif USE_SYSV_SEMAPHORES + int + GetSuspendSemaphoreId( + void + ) + { + return m_nSemsuspid; + }; + + sembuf* + GetSemaphorePostBuffer( + void + ) + { + return &m_sbSempost; + }; +#endif // USE_POSIX_SEMAPHORES + +#if DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX + LONG* + GetSuspensionSpinlock( + void + ) + { + return &m_nSpinlock; + } +#else // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX + pthread_mutex_t* + GetSuspensionMutex( + void + ) + { + return &m_ptmSuspmutex; + } +#endif // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX + + void + SetSuspPending( + BOOL fPending + ) + { + m_fPending = fPending; + }; + + BOOL + GetSuspPending( + void + ) + { + return m_fPending; + }; + + void + SetSelfSusp( + BOOL fSelfsusp + ) + { + m_fSelfsusp = fSelfsusp; + }; + + BOOL + GetSelfSusp( + void + ) + { + return m_fSelfsusp; + }; + + void + PostOnSuspendSemaphore(); + + void + WaitOnSuspendSemaphore(); + + void + PostOnResumeSemaphore(); + + void + WaitOnResumeSemaphore(); + + static + BOOL + TryAcquireSuspensionLock( + CPalThread* pthrTarget + ); + + int GetBlockingPipe( + void + ) + { + return m_nBlockingPipe; + }; + + public: + virtual PAL_ERROR InitializePreCreate(); + + CThreadSuspensionInfo() + : m_fPending(FALSE) + , m_fSelfsusp(FALSE) + , m_fSuspendedForShutdown(FALSE) + , m_nBlockingPipe(-1) +#ifdef _DEBUG + , m_lNumThreadsSuspendedByThisThread(0) +#endif // _DEBUG +#if !DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX + , m_fSuspmutexInitialized(FALSE) +#endif +#if USE_POSIX_SEMAPHORES || USE_PTHREAD_CONDVARS + , m_fSemaphoresInitialized(FALSE) +#endif + { + InitializeSuspensionLock(); + }; + + virtual ~CThreadSuspensionInfo(); + +#ifdef _DEBUG + LONG + GetNumThreadsSuspendedByThisThread( + void + ) + { + return m_lNumThreadsSuspendedByThisThread; + }; +#endif // _DEBUG + +#if USE_SYSV_SEMAPHORES + void + DestroySemaphoreIds( + void + ); +#endif + void + SetSuspendedForShutdown( + BOOL fSuspendedForShutdown + ) + { + m_fSuspendedForShutdown = fSuspendedForShutdown; + }; + + BOOL + GetSuspendedForShutdown( + void + ) + { + return m_fSuspendedForShutdown; + }; + + void + AcquireSuspensionLock( + CPalThread *pthrCurrent + ); + + void + ReleaseSuspensionLock( + CPalThread *pthrCurrent + ); + + PAL_ERROR + InternalSuspendNewThreadFromData( + CPalThread *pThread + ); + + PAL_ERROR + InternalResumeThreadFromData( + CPalThread *pthrResumer, + CPalThread *pthrTarget, + DWORD *pdwSuspendCount + ); + + VOID InitializeSuspensionLock(); + + void SetBlockingPipe( + int nBlockingPipe + ) + { + m_nBlockingPipe = nBlockingPipe; + }; + }; +} //end CorUnix + +extern const BYTE WAKEUPCODE; // use for pipe reads during self suspend. +#endif // __cplusplus + +#ifdef USE_GLOBAL_LOCK_FOR_SUSPENSION +extern LONG g_ssSuspensionLock; +#endif + +#endif // _PAL_THREADSUSP_HPP + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/unicodedata.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/unicodedata.h new file mode 100644 index 0000000..42b4139 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/unicodedata.h @@ -0,0 +1,32 @@ +// 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. + +#ifndef _PAL_UNICODEDATA_H_ +#define _PAL_UNICODEDATA_H_ + +#include "pal/palinternal.h" + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +#define UPPER_CASE 1 +#define LOWER_CASE 2 + +typedef struct +{ + WCHAR nUnicodeValue; + WORD nFlag; + WCHAR nOpposingCase; +} UnicodeDataRec; + +extern CONST UnicodeDataRec UnicodeData[]; +extern CONST UINT UNICODE_DATA_SIZE; + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _UNICODE_DATA_H_ */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/utf8.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/utf8.h new file mode 100644 index 0000000..2516caa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/utf8.h @@ -0,0 +1,53 @@ +// 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: + + include/pal/utf8.h + +Abstract: + Header file for UTF-8 conversion functions. + +Revision History: + + + +--*/ + +#ifndef _PAL_UTF8_H_ +#define _PAL_UTF8_H_ + +#include /* for WCHAR */ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/*++ +Function : + UTF8ToUnicode + + Convert a string from UTF-8 to UTF-16 (UCS-2) +--*/ +int UTF8ToUnicode(LPCSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest, DWORD dwFlags); + + +/*++ +Function : + UnicodeToUTF8 + + Convert a string from UTF-16 (UCS-2) to UTF-8 +--*/ +int UnicodeToUTF8(LPCWSTR lpSrcStr, int cchSrc, LPSTR lpDestStr, int cchDest); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _PAL_UTF8_H_ */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/utils.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/utils.h new file mode 100644 index 0000000..26e93c1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/utils.h @@ -0,0 +1,215 @@ +// 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: + + include/pal/utils.h + +Abstract: + Miscellaneous helper functions for the PAL, which don't fit anywhere else + + + +--*/ + +#ifndef _PAL_UTILS_H_ +#define _PAL_UTILS_H_ + +#include + +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Alignment helpers (copied for PAL use from stdmacros.h) + +inline size_t ALIGN_UP(size_t val, size_t alignment) +{ + // alignment must be a power of 2 for this implementation to work (need modulo otherwise) + _ASSERTE(0 == (alignment & (alignment - 1))); + size_t result = (val + (alignment - 1)) & ~(alignment - 1); + _ASSERTE(result >= val); // check for overflow + return result; +} + +inline void* ALIGN_UP(void* val, size_t alignment) +{ + return (void*)ALIGN_UP((size_t)val, alignment); +} + +inline uint8_t* ALIGN_UP(uint8_t* val, size_t alignment) +{ + return (uint8_t*)ALIGN_UP((size_t)val, alignment); +} + +inline size_t ALIGN_DOWN(size_t val, size_t alignment) +{ + // alignment must be a power of 2 for this implementation to work (need modulo otherwise) + _ASSERTE(0 == (alignment & (alignment - 1))); + size_t result = val & ~(alignment - 1); + return result; +} + +inline void* ALIGN_DOWN(void* val, size_t alignment) +{ + return (void*)ALIGN_DOWN((size_t)val, alignment); +} + +inline uint8_t* ALIGN_DOWN(uint8_t* val, size_t alignment) +{ + return (uint8_t*)ALIGN_DOWN((size_t)val, alignment); +} + +inline BOOL IS_ALIGNED(size_t val, size_t alignment) +{ + // alignment must be a power of 2 for this implementation to work (need modulo otherwise) + _ASSERTE(0 == (alignment & (alignment - 1))); + return 0 == (val & (alignment - 1)); +} + +inline BOOL IS_ALIGNED(const void* val, size_t alignment) +{ + return IS_ALIGNED((size_t)val, alignment); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/*++ +Function: + UTIL_inverse_wcspbrk + + Opposite of wcspbrk : searches a string for the first character NOT in the + given set + +Parameters : + LPWSTR lpwstr : string to search + LPCWSTR charset : list of characters to search for + +Return value : + pointer to first character of lpwstr that isn't in the set + NULL if all characters are in the set +--*/ +LPWSTR UTIL_inverse_wcspbrk(LPWSTR lpwstr, LPCWSTR charset); + +/*++ +Function : + UTIL_IsReadOnlyBitsSet + + Takes a struct stat * + Returns true if the file is read only, +--*/ +BOOL UTIL_IsReadOnlyBitsSet( struct stat * stat_data ); + +/*++ +Function : + UTIL_IsExecuteBitsSet + + Takes a struct stat * + Returns true if the file is executable. +--*/ +BOOL UTIL_IsExecuteBitsSet( struct stat * stat_data ); + + +/*++ +Function : + UTIL_WCToMB_Alloc + + Converts a wide string to a multibyte string, allocating the required buffer + +Parameters : + LPCWSTR lpWideCharStr : string to convert + int cchWideChar : number of wide characters to convert + (-1 to convert a complete null-termnated string) + +Return Value : + newly allocated buffer containing the converted string. Conversion is + performed using CP_ACP. Buffer is allocated with malloc(), release it + with free(). + In case if failure, LastError will be set. +--*/ +LPSTR UTIL_WCToMB_Alloc(LPCWSTR lpWideCharStr, int cchWideChar); + +/*++ +Function : + UTIL_MBToWC_Alloc + + Converts a multibyte string to a wide string, allocating the required buffer + +Parameters : + LPCSTR lpMultiByteStr : string to convert + int cbMultiByte : number of bytes to convert + (-1 to convert a complete null-termnated string) + +Return Value : + newly allocated buffer containing the converted string. Conversion is + performed using CP_ACP. Buffer is allocated with malloc(), release it + with free(). + In case if failure, LastError will be set. +--*/ +LPWSTR UTIL_MBToWC_Alloc(LPCSTR lpMultiByteStr, int cbMultiByte); + +#if HAVE_VM_ALLOCATE +#include + +/*++ +Function: + UTIL_MachErrorToPalError + + Maps a Mach kern_return_t to a Win32 error code. +--*/ +DWORD UTIL_MachErrorToPalError(kern_return_t MachReturn); + +/*++ +Function: + UTIL_SetLastErrorFromMach + + Sets Win32 LastError according to the argument Mach kern_return_t value, + provided it indicates an error. If the argument indicates success, does + not modify LastError. +--*/ +void UTIL_SetLastErrorFromMach(kern_return_t MachReturn); + +#endif //HAVE_VM_ALLOCATE + +BOOL IsRunningOnMojaveHardenedRuntime(); + +#ifdef __cplusplus +} +#endif // __cplusplus +class StringHolder + { + private: + LPSTR data; + public: + StringHolder() : data(NULL) { } + ~StringHolder() + { + PAL_free( data); + } + + operator LPSTR () { return data;} + + StringHolder& operator= (LPSTR value) + { + data = value; + return *this; + } + + BOOL IsNull() + { + return data == NULL; + } + + }; +#endif /* _PAL_UTILS_H_ */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/virtual.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/virtual.h new file mode 100644 index 0000000..14b133a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/include/pal/virtual.h @@ -0,0 +1,215 @@ +// 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: + + include/pal/virtual.h + +Abstract: + Header file for virtual memory management. + + + +--*/ + +#ifndef _PAL_VIRTUAL_H_ +#define _PAL_VIRTUAL_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +typedef struct _CMI { + + struct _CMI * pNext; /* Link to the next entry. */ + struct _CMI * pPrevious; /* Link to the previous entry. */ + + UINT_PTR startBoundary; /* Starting location of the region. */ + SIZE_T memSize; /* Size of the entire region.. */ + + DWORD accessProtection; /* Initial allocation access protection. */ + DWORD allocationType; /* Initial allocation type. */ + + BYTE * pAllocState; /* Individual allocation type tracking for each */ + /* page in the region. */ + + BYTE * pProtectionState; /* Individual allocation type tracking for each */ + /* page in the region. */ + +} CMI, * PCMI; + +enum VIRTUAL_CONSTANTS +{ + /* Allocation type. */ + VIRTUAL_COMMIT_ALL_BITS = 0xFF, + VIRTUAL_RESERVE_ALL_BITS = 0x0, + + /* Protection Type. */ + VIRTUAL_READONLY, + VIRTUAL_READWRITE, + VIRTUAL_EXECUTE_READWRITE, + VIRTUAL_NOACCESS, + VIRTUAL_EXECUTE, + VIRTUAL_EXECUTE_READ, + + VIRTUAL_64KB = 0x10000 +}; + +size_t GetVirtualPageSize(); + +/*++ +Function : + VIRTUALInitialize + + Initialize the critical sections. + +Return value: + TRUE if initialization succeeded + FALSE otherwise. +--*/ +BOOL VIRTUALInitialize(bool initializeExecutableMemoryAllocator); + +/*++ +Function : + VIRTUALCleanup + + Deletes the critical sections. + +--*/ +void VIRTUALCleanup( void ); + +#ifdef __cplusplus +} + +/*++ +Class: + ExecutableMemoryAllocator + + This class implements a virtual memory allocator for JIT'ed code. + The purpose of this allocator is to opportunistically reserve a chunk of virtual memory + that is located near the coreclr library (within 2GB range) that can be later used by + JIT. Having executable memory close to the coreclr library allows JIT to generate more + efficient code (by avoiding usage of jump stubs) and thus it can significantly improve + performance of the application. + + This allocator is integrated with the VirtualAlloc/Reserve code. If VirtualAlloc has been + called with the MEM_RESERVE_EXECUTABLE flag then it will first try to obtain the requested size + of virtual memory from ExecutableMemoryAllocator. If ExecutableMemoryAllocator runs out of + the reserved memory (or fails to allocate it during initialization) then VirtualAlloc/Reserve code + will simply fall back to reserving memory using OS APIs. + + Notes: + - the memory allocated by this class is NOT committed by default. It is responsibility + of the caller to commit the virtual memory before accessing it. + - in addition, this class does not provide ability to free the reserved memory. The caller + has full control of the memory it got from this allocator (i.e. the caller becomes + the owner of the allocated memory), so it is caller's responsibility to free the memory + if it is no longer needed. +--*/ +class ExecutableMemoryAllocator +{ +public: + /*++ + Function: + Initialize + + This function initializes the allocator. It should be called early during process startup + (when process address space is pretty much empty) in order to have a chance to reserve + sufficient amount of memory that is close to the coreclr library. + --*/ + void Initialize(); + + /*++ + Function: + AllocateMemory + + This function attempts to allocate the requested amount of memory from its reserved virtual + address space. The function will return null if the allocation request cannot + be satisfied by the memory that is currently available in the allocator. + --*/ + void* AllocateMemory(SIZE_T allocationSize); + + /*++ + Function: + AllocateMemory + + This function attempts to allocate the requested amount of memory from its reserved virtual + address space, if memory is available within the specified range. The function will return + null if the allocation request cannot satisfied by the memory that is currently available in + the allocator. + --*/ + void *AllocateMemoryWithinRange(const void *beginAddress, const void *endAddress, SIZE_T allocationSize); + +private: + /*++ + Function: + TryReserveInitialMemory + + This function is called during initialization. It opportunistically tries to reserve + a large chunk of virtual memory that can be later used to store JIT'ed code. + --*/ + void TryReserveInitialMemory(); + + /*++ + Function: + GenerateRandomStartOffset + + This function returns a random offset (in multiples of the virtual page size) + at which the allocator should start allocating memory from its reserved memory range. + --*/ + int32_t GenerateRandomStartOffset(); + +private: + // There does not seem to be an easy way find the size of a library on Unix. + // So this constant represents an approximation of the libcoreclr size (on debug build) + // that can be used to calculate an approximate location of the memory that + // is in 2GB range from the coreclr library. In addition, having precise size of libcoreclr + // is not necessary for the calculations. + static const int32_t CoreClrLibrarySize = 100 * 1024 * 1024; + + // This constant represent the max size of the virtual memory that this allocator + // will try to reserve during initialization. We want all JIT-ed code and the + // entire libcoreclr to be located in a 2GB range. + static const int32_t MaxExecutableMemorySize = 0x7FFF0000; + static const int32_t MaxExecutableMemorySizeNearCoreClr = MaxExecutableMemorySize - CoreClrLibrarySize; + + // Start address of the reserved virtual address space + void* m_startAddress; + + // Next available address in the reserved address space + void* m_nextFreeAddress; + + // Total size of the virtual memory that the allocator has been able to + // reserve during its initialization. + int32_t m_totalSizeOfReservedMemory; + + // Remaining size of the reserved virtual memory that can be used to satisfy allocation requests. + int32_t m_remainingReservedMemory; +}; + +#endif // __cplusplus + +/*++ +Function : + ReserveMemoryFromExecutableAllocator + + This function is used to reserve a region of virual memory (not commited) + that is located close to the coreclr library. The memory comes from the virtual + address range that is managed by ExecutableMemoryAllocator. +--*/ +void* ReserveMemoryFromExecutableAllocator(CorUnix::CPalThread* pthrCurrent, SIZE_T allocationSize); + +#endif /* _PAL_VIRTUAL_H_ */ + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/init/pal.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/init/pal.cpp new file mode 100644 index 0000000..b25924e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/init/pal.cpp @@ -0,0 +1,1368 @@ +// 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: + + init/pal.cpp + +Abstract: + + Implementation of PAL exported functions not part of the Win32 API. + + + +--*/ + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(PAL); // some headers have code with asserts, so do this first + +#include "pal/thread.hpp" +#include "pal/synchobjects.hpp" +#include "pal/procobj.hpp" +#include "pal/cs.hpp" +#include "pal/file.hpp" +#include "pal/map.hpp" +#include "../objmgr/shmobjectmanager.hpp" +#include "pal/seh.hpp" +#include "pal/palinternal.h" +#include "pal/sharedmemory.h" +#include "pal/shmemory.h" +#include "pal/process.h" +#include "../thread/procprivate.hpp" +#include "pal/module.h" +#include "pal/virtual.h" +#include "pal/misc.h" +#include "pal/environ.h" +#include "pal/utils.h" +#include "pal/debug.h" +#include "pal/init.h" +#include "pal/numa.h" +#include "pal/stackstring.hpp" +#include "pal/cgroup.h" + +#if HAVE_MACH_EXCEPTIONS +#include "../exception/machexception.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_POLL +#include +#else +#include "pal/fakepoll.h" +#endif // HAVE_POLL + +#if defined(__APPLE__) +#include +int CacheLineSize; +#endif //__APPLE__ + +#ifdef __APPLE__ +#include +#endif // __APPLE__ + +#ifdef __NetBSD__ +#include +#include +#include +#include +#endif + +#include + +using namespace CorUnix; + +// +// $$TODO The C++ compiler doesn't like pal/cruntime.h so duplicate the +// necessary prototype here +// + +extern "C" BOOL CRTInitStdStreams( void ); + +Volatile init_count = 0; +Volatile shutdown_intent = 0; +Volatile g_coreclrInitialized = 0; +static BOOL g_fThreadDataAvailable = FALSE; +static pthread_mutex_t init_critsec_mutex = PTHREAD_MUTEX_INITIALIZER; + +// The default minimum stack size +SIZE_T g_defaultStackSize = 0; + +// The default value of parameter, whether to mmap images at default base address or not +BOOL g_useDefaultBaseAddr = FALSE; + +/* critical section to protect access to init_count. This is allocated on the + very first PAL_Initialize call, and is freed afterward. */ +static PCRITICAL_SECTION init_critsec = NULL; + +static DWORD g_initializeDLLFlags = PAL_INITIALIZE_DLL; + +static int Initialize(int argc, const char *const argv[], DWORD flags); +static BOOL INIT_IncreaseDescriptorLimit(void); +static LPWSTR INIT_FormatCommandLine (int argc, const char * const *argv); +static LPWSTR INIT_ConvertEXEPath(LPCSTR exe_name); +static BOOL INIT_SharedFilesPath(void); + +#ifdef _DEBUG +extern void PROCDumpThreadList(void); +#endif + +#if defined(__APPLE__) +static bool RunningNatively() +{ + int ret = 0; + size_t sz = sizeof(ret); + if (sysctlbyname("sysctl.proc_native", &ret, &sz, NULL, 0) != 0) + { + // if the sysctl failed, we'll assume this OS does not support + // binary translation - so we must be running natively. + return true; + } + return ret != 0; +} +#endif // __APPLE__ + +/*++ +Function: + PAL_Initialize + +Abstract: + This function is the first function of the PAL to be called. + Internal structure initialization is done here. It could be called + several time by the same process, a reference count is kept. + +Return: + 0 if successful + -1 if it failed + +--*/ +int +PALAPI +PAL_Initialize( + int argc, + char *const argv[]) +{ + return Initialize(argc, argv, PAL_INITIALIZE); +} + +/*++ +Function: + PAL_InitializeWithFlags + +Abstract: + This function is the first function of the PAL to be called. + Internal structure initialization is done here. It could be called + several time by the same process, a reference count is kept. + +Return: + 0 if successful + -1 if it failed + +--*/ +int +PALAPI +PAL_InitializeWithFlags( + int argc, + const char *const argv[], + DWORD flags) +{ + return Initialize(argc, argv, flags); +} + +/*++ +Function: + PAL_InitializeDLL + +Abstract: + Initializes the non-runtime DLLs/modules like the DAC and SOS. + +Return: + 0 if successful + -1 if it failed + +--*/ +int +PALAPI +PAL_InitializeDLL() +{ + return Initialize(0, NULL, g_initializeDLLFlags); +} + +/*++ +Function: + PAL_SetInitializeDLLFlags + +Abstract: + This sets the global PAL_INITIALIZE flags that PAL_InitializeDLL + will use. It needs to be called before any PAL_InitializeDLL call + is made so typical it is used in a __attribute__((constructor)) + function to make sure. + +Return: + none + +--*/ +void +PALAPI +PAL_SetInitializeDLLFlags( + DWORD flags) +{ + g_initializeDLLFlags = flags; +} + +#ifdef ENSURE_PRIMARY_STACK_SIZE +/*++ +Function: + EnsureStackSize + +Abstract: + This fixes a problem on MUSL where the initial stack size reported by the + pthread_attr_getstack is about 128kB, but this limit is not fixed and + the stack can grow dynamically. The problem is that it makes the + functions ReflectionInvocation::[Try]EnsureSufficientExecutionStack + to fail for real life scenarios like e.g. compilation of corefx. + Since there is no real fixed limit for the stack, the code below + ensures moving the stack limit to a value that makes reasonable + real life scenarios work. + +--*/ +__attribute__((noinline,NOOPT_ATTRIBUTE)) +void +EnsureStackSize(SIZE_T stackSize) +{ + volatile uint8_t *s = (uint8_t *)_alloca(stackSize); + *s = 0; +} +#endif // ENSURE_PRIMARY_STACK_SIZE + +/*++ +Function: + InitializeDefaultStackSize + +Abstract: + Initializes the default stack size. + +--*/ +void +InitializeDefaultStackSize() +{ + char* defaultStackSizeStr = getenv("COMPlus_DefaultStackSize"); + if (defaultStackSizeStr != NULL) + { + errno = 0; + // Like all numeric values specific by the COMPlus_xxx variables, it is a + // hexadecimal string without any prefix. + long int size = strtol(defaultStackSizeStr, NULL, 16); + + if (errno == 0) + { + g_defaultStackSize = std::max(size, (long int)PTHREAD_STACK_MIN); + } + } + +#ifdef ENSURE_PRIMARY_STACK_SIZE + if (g_defaultStackSize == 0) + { + // Set the default minimum stack size for MUSL to the same value as we + // use on Windows. + g_defaultStackSize = 1536 * 1024; + } +#endif // ENSURE_PRIMARY_STACK_SIZE +} + +/*++ +Function: + Initialize + +Abstract: + Common PAL initialization function. + +Return: + 0 if successful + -1 if it failed + +--*/ +int +Initialize( + int argc, + const char *const argv[], + DWORD flags) +{ + PAL_ERROR palError = ERROR_GEN_FAILURE; + CPalThread *pThread = NULL; + CSharedMemoryObjectManager *pshmom = NULL; + LPWSTR command_line = NULL; + LPWSTR exe_path = NULL; + int retval = -1; + bool fFirstTimeInit = false; + + /* the first ENTRY within the first call to PAL_Initialize is a special + case, since debug channels are not initialized yet. So in that case the + ENTRY will be called after the DBG channels initialization */ + ENTRY_EXTERNAL("PAL_Initialize(argc = %d argv = %p)\n", argc, argv); + + /*Firstly initiate a lastError */ + SetLastError(ERROR_GEN_FAILURE); + +#ifdef __APPLE__ + if (!RunningNatively()) + { + SetLastError(ERROR_BAD_FORMAT); + goto exit; + } +#endif // __APPLE__ + + CriticalSectionSubSysInitialize(); + + if(NULL == init_critsec) + { + pthread_mutex_lock(&init_critsec_mutex); // prevents race condition of two threads + // initializing the critical section. + if(NULL == init_critsec) + { + static CRITICAL_SECTION temp_critsec; + + // Want this critical section to NOT be internal to avoid the use of unsafe region markers. + InternalInitializeCriticalSectionAndSpinCount(&temp_critsec, 0, false); + + if(NULL != InterlockedCompareExchangePointer(&init_critsec, &temp_critsec, NULL)) + { + // Another thread got in before us! shouldn't happen, if the PAL + // isn't initialized there shouldn't be any other threads + WARN("Another thread initialized the critical section\n"); + InternalDeleteCriticalSection(&temp_critsec); + } + } + pthread_mutex_unlock(&init_critsec_mutex); + } + + InternalEnterCriticalSection(pThread, init_critsec); // here pThread is always NULL + + if (init_count == 0) + { + // Set our pid and sid. + gPID = getpid(); + gSID = getsid(gPID); + + // Initialize the thread local storage + if (FALSE == TLSInitialize()) + { + palError = ERROR_PALINIT_TLS; + goto done; + } + + // Initialize debug channel settings before anything else. + if (FALSE == DBG_init_channels()) + { + palError = ERROR_PALINIT_DBG_CHANNELS; + goto CLEANUP0a; + } + + // The gSharedFilesPath is allocated dynamically so its destructor does not get + // called unexpectedly during cleanup + gSharedFilesPath = InternalNew(); + if (gSharedFilesPath == nullptr) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto CLEANUP0a; + } + + if (INIT_SharedFilesPath() == FALSE) + { + goto CLEANUP0a; + } + + fFirstTimeInit = true; + + InitializeDefaultStackSize(); + +#ifdef ENSURE_PRIMARY_STACK_SIZE + if (flags & PAL_INITIALIZE_ENSURE_STACK_SIZE) + { + EnsureStackSize(g_defaultStackSize); + } +#endif // ENSURE_PRIMARY_STACK_SIZE + +#ifdef FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION + char* useDefaultBaseAddr = getenv("COMPlus_UseDefaultBaseAddr"); + if (useDefaultBaseAddr != NULL) + { + errno = 0; + // Like all numeric values specific by the COMPlus_xxx variables, it is a + // hexadecimal string without any prefix. + long int flag = strtol(useDefaultBaseAddr, NULL, 16); + + if (errno == 0) + { + g_useDefaultBaseAddr = (BOOL) flag; + } + } +#endif // FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION + + InitializeCGroup(); + + // Initialize the environment. + if (FALSE == EnvironInitialize()) + { + palError = ERROR_PALINIT_ENV; + goto CLEANUP0; + } + + if (!INIT_IncreaseDescriptorLimit()) + { + ERROR("Unable to increase the file descriptor limit!\n"); + // We can continue if this fails; we'll just have problems if + // we use large numbers of threads or have many open files. + } + + if (!SharedMemoryManager::StaticInitialize()) + { + ERROR("Shared memory static initialization failed!\n"); + palError = ERROR_PALINIT_SHARED_MEMORY_MANAGER; + goto CLEANUP0; + } + + /* initialize the shared memory infrastructure */ + if (!SHMInitialize()) + { + ERROR("Shared memory initialization failed!\n"); + palError = ERROR_PALINIT_SHM; + goto CLEANUP0; + } + + // + // Initialize global process data + // + + palError = InitializeProcessData(); + if (NO_ERROR != palError) + { + ERROR("Unable to initialize process data\n"); + goto CLEANUP1; + } + +#if HAVE_MACH_EXCEPTIONS + // Mach exception port needs to be set up before the thread + // data or threads are set up. + if (!SEHInitializeMachExceptions(flags)) + { + ERROR("SEHInitializeMachExceptions failed!\n"); + palError = ERROR_PALINIT_INITIALIZE_MACH_EXCEPTION; + goto CLEANUP1; + } +#endif // HAVE_MACH_EXCEPTIONS + + // + // Allocate the initial thread data + // + + palError = CreateThreadData(&pThread); + if (NO_ERROR != palError) + { + ERROR("Unable to create initial thread data\n"); + goto CLEANUP1a; + } + + PROCAddThread(pThread, pThread); + + // + // It's now safe to access our thread data + // + + g_fThreadDataAvailable = TRUE; + + // + // Initialize module manager + // + if (FALSE == LOADInitializeModules()) + { + ERROR("Unable to initialize module manager\n"); + palError = ERROR_PALINIT_MODULE_MANAGER; + goto CLEANUP1b; + } + + // + // Initialize the object manager + // + + pshmom = InternalNew(); + if (NULL == pshmom) + { + ERROR("Unable to allocate new object manager\n"); + palError = ERROR_OUTOFMEMORY; + goto CLEANUP1b; + } + + palError = pshmom->Initialize(); + if (NO_ERROR != palError) + { + ERROR("object manager initialization failed!\n"); + InternalDelete(pshmom); + goto CLEANUP1b; + } + + g_pObjectManager = pshmom; + + // + // Initialize the synchronization manager + // + g_pSynchronizationManager = + CPalSynchMgrController::CreatePalSynchronizationManager(); + + if (NULL == g_pSynchronizationManager) + { + palError = ERROR_NOT_ENOUGH_MEMORY; + ERROR("Failure creating synchronization manager\n"); + goto CLEANUP1c; + } + } + else + { + pThread = InternalGetCurrentThread(); + } + + palError = ERROR_GEN_FAILURE; + + if (argc > 0 && argv != NULL) + { + /* build the command line */ + command_line = INIT_FormatCommandLine(argc, argv); + if (NULL == command_line) + { + ERROR("Error building command line\n"); + palError = ERROR_PALINIT_COMMAND_LINE; + goto CLEANUP1d; + } + + /* find out the application's full path */ + exe_path = INIT_ConvertEXEPath(argv[0]); + if (NULL == exe_path) + { + ERROR("Unable to find exe path\n"); + palError = ERROR_PALINIT_CONVERT_EXE_PATH; + goto CLEANUP1e; + } + + palError = InitializeProcessCommandLine( + command_line, + exe_path); + + if (NO_ERROR != palError) + { + ERROR("Unable to initialize command line\n"); + goto CLEANUP2; + } + + // InitializeProcessCommandLine took ownership of this memory. + command_line = NULL; + +#ifdef PAL_PERF + // Initialize the Profiling structure + if(FALSE == PERFInitialize(command_line, exe_path)) + { + ERROR("Performance profiling initial failed\n"); + palError = ERROR_PALINIT_PERF; + goto CLEANUP2; + } + PERFAllocThreadInfo(); +#endif + + if (!LOADSetExeName(exe_path)) + { + ERROR("Unable to set exe name\n"); + palError = ERROR_PALINIT_SET_EXE_NAME; + goto CLEANUP2; + } + + // LOADSetExeName took ownership of this memory. + exe_path = NULL; + } + + if (init_count == 0) + { + // + // Create the initial process and thread objects + // + palError = CreateInitialProcessAndThreadObjects(pThread); + if (NO_ERROR != palError) + { + ERROR("Unable to create initial process and thread objects\n"); + goto CLEANUP2; + } + + palError = ERROR_GEN_FAILURE; + + if (FALSE == TIMEInitialize()) + { + ERROR("Unable to initialize TIME support\n"); + palError = ERROR_PALINIT_TIME; + goto CLEANUP6; + } + + /* Initialize the File mapping critical section. */ + if (FALSE == MAPInitialize()) + { + ERROR("Unable to initialize file mapping support\n"); + palError = ERROR_PALINIT_MAP; + goto CLEANUP6; + } + + /* Initialize the Virtual* functions. */ + bool initializeExecutableMemoryAllocator = (flags & PAL_INITIALIZE_EXEC_ALLOCATOR) != 0; + if (FALSE == VIRTUALInitialize(initializeExecutableMemoryAllocator)) + { + ERROR("Unable to initialize virtual memory support\n"); + palError = ERROR_PALINIT_VIRTUAL; + goto CLEANUP10; + } + + if (flags & PAL_INITIALIZE_SYNC_THREAD) + { + // + // Tell the synchronization manager to start its worker thread + // + palError = CPalSynchMgrController::StartWorker(pThread); + if (NO_ERROR != palError) + { + ERROR("Synch manager failed to start worker thread\n"); + goto CLEANUP13; + } + } + + /* initialize structured exception handling stuff (signals, etc) */ + if (FALSE == SEHInitialize(pThread, flags)) + { + ERROR("Unable to initialize SEH support\n"); + palError = ERROR_PALINIT_SEH; + goto CLEANUP13; + } + + if (flags & PAL_INITIALIZE_STD_HANDLES) + { + /* create file objects for standard handles */ + if (!FILEInitStdHandles()) + { + ERROR("Unable to initialize standard file handles\n"); + palError = ERROR_PALINIT_STD_HANDLES; + goto CLEANUP14; + } + } + + if (FALSE == CRTInitStdStreams()) + { + ERROR("Unable to initialize CRT standard streams\n"); + palError = ERROR_PALINIT_STD_STREAMS; + goto CLEANUP15; + } + + if (FALSE == NUMASupportInitialize()) + { + ERROR("Unable to initialize NUMA support\n"); + palError = ERROR_PALINIT_NUMA; + goto CLEANUP15; + } + + TRACE("First-time PAL initialization complete.\n"); + init_count++; + + /* Set LastError to a non-good value - functions within the + PAL startup may set lasterror to a nonzero value. */ + SetLastError(NO_ERROR); + retval = 0; + } + else + { + init_count++; + + TRACE("Initialization count increases to %d\n", init_count.Load()); + + SetLastError(NO_ERROR); + retval = 0; + } + goto done; + + NUMASupportCleanup(); + /* No cleanup required for CRTInitStdStreams */ +CLEANUP15: + FILECleanupStdHandles(); +CLEANUP14: + SEHCleanup(); +CLEANUP13: + VIRTUALCleanup(); +CLEANUP10: + MAPCleanup(); +CLEANUP6: + PROCCleanupInitialProcess(); +CLEANUP2: + free(exe_path); +CLEANUP1e: + free(command_line); +CLEANUP1d: + // Cleanup synchronization manager +CLEANUP1c: + // Cleanup object manager +CLEANUP1b: + // Cleanup initial thread data +CLEANUP1a: + // Cleanup global process data +CLEANUP1: + SHMCleanup(); +CLEANUP0: + CleanupCGroup(); +CLEANUP0a: + TLSCleanup(); + ERROR("PAL_Initialize failed\n"); + SetLastError(palError); +done: +#ifdef PAL_PERF + if( retval == 0) + { + PERFEnableProcessProfile(); + PERFEnableThreadProfile(FALSE); + PERFCalibrate("Overhead of PERF entry/exit"); + } +#endif + + InternalLeaveCriticalSection(pThread, init_critsec); + + if (fFirstTimeInit && 0 == retval) + { + _ASSERTE(NULL != pThread); + } + + if (retval != 0 && GetLastError() == ERROR_SUCCESS) + { + ASSERT("returning failure, but last error not set\n"); + } + +#ifdef __APPLE__ +exit : +#endif // __APPLE__ + LOGEXIT("PAL_Initialize returns int %d\n", retval); + return retval; +} + + +/*++ +Function: + PAL_InitializeCoreCLR + +Abstract: + A replacement for PAL_Initialize when loading CoreCLR. Instead of taking a command line (which CoreCLR + instances aren't given anyway) the path into which the CoreCLR is installed is supplied instead. This is + cached so that PAL_GetPALDirectoryW can return it later. + + This routine also makes sure the psuedo dynamic libraries PALRT and mscorwks have their initialization + methods called. + +Return: + ERROR_SUCCESS if successful + An error code, if it failed + +--*/ +PAL_ERROR +PALAPI +PAL_InitializeCoreCLR(const char *szExePath) +{ + // Fake up a command line to call PAL initialization with. + int result = Initialize(1, &szExePath, PAL_INITIALIZE_CORECLR); + if (result != 0) + { + return GetLastError(); + } + + // Check for a repeated call (this is a no-op). + if (InterlockedIncrement(&g_coreclrInitialized) > 1) + { + return ERROR_SUCCESS; + } + + // Now that the PAL is initialized it's safe to call the initialization methods for the code that used to + // be dynamically loaded libraries but is now statically linked into CoreCLR just like the PAL, i.e. the + // PAL RT and mscorwks. + if (!LOADInitializeCoreCLRModule()) + { + return ERROR_DLL_INIT_FAILED; + } + + if (!PROCAbortInitialize()) + { + printf("PROCAbortInitialize FAILED %d (%s)\n", errno, strerror(errno)); + return ERROR_PALINIT_PROCABORT_INITIALIZE; + } + + if (!InitializeFlushProcessWriteBuffers()) + { + return ERROR_PALINIT_INITIALIZE_FLUSH_PROCESS_WRITE_BUFFERS; + } + + return ERROR_SUCCESS; +} + +/*++ +Function: +PAL_IsDebuggerPresent + +Abstract: +This function should be used to determine if a debugger is attached to the process. +--*/ +PALIMPORT +BOOL +PALAPI +PAL_IsDebuggerPresent() +{ +#if defined(__linux__) + BOOL debugger_present = FALSE; + char buf[2048]; + + int status_fd = open("/proc/self/status", O_RDONLY); + if (status_fd == -1) + { + return FALSE; + } + ssize_t num_read = read(status_fd, buf, sizeof(buf) - 1); + + if (num_read > 0) + { + static const char TracerPid[] = "TracerPid:"; + char *tracer_pid; + + buf[num_read] = '\0'; + tracer_pid = strstr(buf, TracerPid); + if (tracer_pid) + { + debugger_present = !!atoi(tracer_pid + sizeof(TracerPid) - 1); + } + } + + close(status_fd); + + return debugger_present; +#elif defined(__APPLE__) + struct kinfo_proc info = {}; + size_t size = sizeof(info); + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() }; + int ret = sysctl(mib, sizeof(mib)/sizeof(*mib), &info, &size, NULL, 0); + + if (ret == 0) + return ((info.kp_proc.p_flag & P_TRACED) != 0); + + return FALSE; +#elif defined(__NetBSD__) + int traced; + kvm_t *kd; + int cnt; + + struct kinfo_proc *info; + + kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open"); + if (kd == NULL) + return FALSE; + + info = kvm_getprocs(kd, KERN_PROC_PID, getpid(), &cnt); + if (info == NULL || cnt < 1) + { + kvm_close(kd); + return FALSE; + } + + traced = info->kp_proc.p_slflag & PSL_TRACED; + kvm_close(kd); + + if (traced != 0) + return TRUE; + else + return FALSE; +#else + return FALSE; +#endif +} + +/*++ +Function: + PAL_Shutdown + +Abstract: + This function shuts down the PAL WITHOUT exiting the current process. +--*/ +void +PALAPI +PAL_Shutdown( + void) +{ + TerminateCurrentProcessNoExit(FALSE /* bTerminateUnconditionally */); +} + +/*++ +Function: + PAL_Terminate + +Abstract: + This function is the called when a thread has finished using the PAL + library. It shuts down PAL and exits the current process. +--*/ +void +PALAPI +PAL_Terminate( + void) +{ + PAL_TerminateEx(0); +} + +/*++ +Function: +PAL_TerminateEx + +Abstract: +This function is the called when a thread has finished using the PAL +library. It shuts down PAL and exits the current process with +the specified exit code. +--*/ +void +PALAPI +PAL_TerminateEx( + int exitCode) +{ + ENTRY_EXTERNAL("PAL_TerminateEx()\n"); + + if (NULL == init_critsec) + { + /* note that these macros probably won't output anything, since the + debug channels haven't been initialized yet */ + ASSERT("PAL_Initialize has never been called!\n"); + LOGEXIT("PAL_Terminate returns.\n"); + } + + // Declare the beginning of shutdown + PALSetShutdownIntent(); + + LOGEXIT("PAL_TerminateEx is exiting the current process.\n"); + exit(exitCode); +} + +/*++ +Function: + PALIsThreadDataInitialized + +Returns TRUE if startup has reached a point where thread data is available +--*/ +BOOL PALIsThreadDataInitialized() +{ + return g_fThreadDataAvailable; +} + +/*++ +Function: + PALCommonCleanup + + Utility function to prepare for shutdown. + +--*/ +void +PALCommonCleanup() +{ + static bool cleanupDone = false; + + // Declare the beginning of shutdown + PALSetShutdownIntent(); + + if (!cleanupDone) + { + cleanupDone = true; + + // + // Let the synchronization manager know we're about to shutdown + // + CPalSynchMgrController::PrepareForShutdown(); + + SharedMemoryManager::StaticClose(); + +#ifdef _DEBUG + PROCDumpThreadList(); +#endif + } +} + +BOOL PALIsShuttingDown() +{ + /* TODO: This function may be used to provide a reader/writer-like + mechanism (or a ref counting one) to prevent PAL APIs that need to access + PAL runtime data, from working when PAL is shutting down. Each of those API + should acquire a read access while executing. The shutting down code would + acquire a write lock, i.e. suspending any new incoming reader, and waiting + for the current readers to be done. That would allow us to get rid of the + dangerous suspend-all-other-threads at shutdown time */ + return shutdown_intent; +} + +void PALSetShutdownIntent() +{ + /* TODO: See comment in PALIsShuttingDown */ + shutdown_intent = TRUE; +} + +/*++ +Function: + PALInitLock + +Take the initializaiton critical section (init_critsec). necessary to serialize +TerminateProcess along with PAL_Terminate and PAL_Initialize + +(no parameters) + +Return value : + TRUE if critical section existed (and was acquired) + FALSE if critical section doens't exist yet +--*/ +BOOL PALInitLock(void) +{ + if(!init_critsec) + { + return FALSE; + } + + CPalThread * pThread = + (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : NULL); + + InternalEnterCriticalSection(pThread, init_critsec); + return TRUE; +} + +/*++ +Function: + PALInitUnlock + +Release the initialization critical section (init_critsec). + +(no parameters, no return value) +--*/ +void PALInitUnlock(void) +{ + if(!init_critsec) + { + return; + } + + CPalThread * pThread = + (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : NULL); + + InternalLeaveCriticalSection(pThread, init_critsec); +} + +/* Internal functions *********************************************************/ + +/*++ +Function: + INIT_IncreaseDescriptorLimit [internal] + +Abstract: + Calls setrlimit(2) to increase the maximum number of file descriptors + this process can open. + +Return value: + TRUE if the call to setrlimit succeeded; FALSE otherwise. +--*/ +static BOOL INIT_IncreaseDescriptorLimit(void) +{ +#ifndef DONT_SET_RLIMIT_NOFILE + struct rlimit rlp; + int result; + + result = getrlimit(RLIMIT_NOFILE, &rlp); + if (result != 0) + { + return FALSE; + } + // Set our soft limit for file descriptors to be the same + // as the max limit. + rlp.rlim_cur = rlp.rlim_max; +#ifdef __APPLE__ + // Based on compatibility note in setrlimit(2) manpage for OSX, + // trim the limit to OPEN_MAX. + if (rlp.rlim_cur > OPEN_MAX) + { + rlp.rlim_cur = OPEN_MAX; + } +#endif + result = setrlimit(RLIMIT_NOFILE, &rlp); + if (result != 0) + { + return FALSE; + } +#endif // !DONT_SET_RLIMIT_NOFILE + return TRUE; +} + +/*++ +Function: + INIT_FormatCommandLine [Internal] + +Abstract: + This function converts an array of arguments (argv) into a Unicode + command-line for use by GetCommandLineW + +Parameters : + int argc : number of arguments in argv + char **argv : argument list in an array of NULL-terminated strings + +Return value : + pointer to Unicode command line. This is a buffer allocated with malloc; + caller is responsible for freeing it with free() + +Note : not all peculiarities of Windows command-line processing are supported; + +-what is supported : + -arguments with white-space must be double quoted (we'll just double-quote + all arguments to simplify things) + -some characters must be escaped with \ : particularly, the double-quote, + to avoid confusion with the double-quotes at the start and end of + arguments, and \ itself, to avoid confusion with escape sequences. +-what is not supported: + -under Windows, \\ is interpreted as an escaped \ ONLY if it's followed by + an escaped double-quote \". \\\" is passed to argv as \", but \\a is + passed to argv as \\a... there may be other similar cases + -there may be other characters which must be escaped +--*/ +static LPWSTR INIT_FormatCommandLine (int argc, const char * const *argv) +{ + LPWSTR retval; + LPSTR command_line=NULL, command_ptr; + LPCSTR arg_ptr; + INT length, i,j; + BOOL bQuoted = FALSE; + + /* list of characters that need no be escaped with \ when building the + command line. currently " and \ */ + LPCSTR ESCAPE_CHARS="\"\\"; + + /* allocate temporary memory for the string. Play it safe : + double the length of each argument (in case they're composed + exclusively of escaped characters), and add 3 (for the double-quotes + and separating space). This is temporary anyway, we return a LPWSTR */ + length=0; + for(i=0; i(InternalMalloc(length)); + + if(!command_line) + { + ERROR("couldn't allocate memory for command line!\n"); + return NULL; + } + + command_ptr=command_line; + for(i=0; i(InternalMalloc((sizeof(WCHAR)*i))); + if(retval == NULL) + { + ERROR("can't allocate memory for Unicode command line!\n"); + free(command_line); + return NULL; + } + + if(!MultiByteToWideChar(CP_ACP, 0,command_line, i, retval, i)) + { + ASSERT("MultiByteToWideChar failure\n"); + free(retval); + retval = NULL; + } + else + TRACE("Command line is %s\n", command_line); + + free(command_line); + return retval; +} + +/*++ +Function: + INIT_ConvertEXEPath + +Abstract: + Check whether the executable path is valid, and convert its type (LPCSTR -> LPWSTR) + +Parameters: + LPCSTR exe_name : full path of the current executable + +Return: + pointer to buffer containing the full path. This buffer must be released + by the caller using free() + +Notes : + this function assumes that "exe_name" is in Unix style (no \) +--*/ +static LPWSTR INIT_ConvertEXEPath(LPCSTR exe_path) +{ + PathCharString real_path; + LPWSTR return_value; + INT return_size; + struct stat theStats; + + if (!strchr(exe_path, '/')) + { + ERROR( "The exe path is not fully specified\n" ); + return NULL; + } + + if (-1 == stat(exe_path, &theStats)) + { + ERROR( "The file does not exist\n" ); + return NULL; + } + + if (!CorUnix::RealPathHelper(exe_path, real_path)) + { + ERROR("realpath() failed!\n"); + return NULL; + } + + return_size = MultiByteToWideChar(CP_ACP, 0, real_path, -1, NULL, 0); + if (0 == return_size) + { + ASSERT("MultiByteToWideChar failure\n"); + return NULL; + } + + return_value = reinterpret_cast(InternalMalloc((return_size*sizeof(WCHAR)))); + if (NULL == return_value) + { + ERROR("Not enough memory to create full path\n"); + return NULL; + } + else + { + if (!MultiByteToWideChar(CP_ACP, 0, real_path, -1, + return_value, return_size)) + { + ASSERT("MultiByteToWideChar failure\n"); + free(return_value); + return_value = NULL; + } + else + { + TRACE("full path to executable is %s\n", real_path.GetString()); + } + } + + return return_value; +} + +/*++ +Function: + INIT_SharedFilesPath + +Abstract: + Initializes the shared application +--*/ +static BOOL INIT_SharedFilesPath(void) +{ +#ifdef __APPLE__ + // Store application group Id. It will be null if not set + gApplicationGroupId = getenv("DOTNET_SANDBOX_APPLICATION_GROUP_ID"); + + if (nullptr != gApplicationGroupId) + { + // Verify the length of the application group ID + gApplicationGroupIdLength = strlen(gApplicationGroupId); + if (gApplicationGroupIdLength > MAX_APPLICATION_GROUP_ID_LENGTH) + { + SetLastError(ERROR_BAD_LENGTH); + return FALSE; + } + + // In sandbox, all IPC files (locks, pipes) should be written to the application group + // container. There will be no write permissions to TEMP_DIRECTORY_PATH + if (!GetApplicationContainerFolder(*gSharedFilesPath, gApplicationGroupId, gApplicationGroupIdLength)) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + // Verify the size of the path won't exceed maximum allowed size + if (gSharedFilesPath->GetCount() + SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT + 1 /* null terminator */ > MAX_LONGPATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return FALSE; + } + + // Check if the path already exists and it's a directory + struct stat statInfo; + int statResult = stat(*gSharedFilesPath, &statInfo); + + // If the path exists, check that it's a directory + if (statResult != 0 || !(statInfo.st_mode & S_IFDIR)) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return FALSE; + } + + return TRUE; + } +#endif // __APPLE__ + + // If we are here, then we are not in sandbox mode, resort to TEMP_DIRECTORY_PATH as shared files path + return gSharedFilesPath->Set(TEMP_DIRECTORY_PATH); + + // We can verify statically the non sandboxed case, since the size is known during compile time + static_assert_no_msg(string_countof(TEMP_DIRECTORY_PATH) + SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT + 1 /* null terminator */ <= MAX_LONGPATH); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/init/sxs.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/init/sxs.cpp new file mode 100644 index 0000000..e37b231 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/init/sxs.cpp @@ -0,0 +1,98 @@ +// 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. + +/*++ + + + + + +--*/ + +#include "pal/dbgmsg.h" +#include "pal/thread.hpp" +#include "../thread/procprivate.hpp" +#include "pal/module.h" +#include "pal/process.h" +#include "pal/seh.hpp" +#include "pal/signal.hpp" + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(SXS); + +PAL_ERROR AllocatePalThread(CPalThread **ppThread); + +/*++ +Function: + CreateCurrentThreadData + +Abstract: + This function is called by the InternalGetOrCreateCurrentThread inlined + function to create the thread data when it is null meaning the thread has + never been in this PAL. + +Warning: + If the allocation fails, this function asserts and exits the process. +--*/ +extern "C" CPalThread * +CreateCurrentThreadData() +{ + CPalThread *pThread = NULL; + + if (PALIsThreadDataInitialized()) { + PAL_ERROR palError = AllocatePalThread(&pThread); + if (NO_ERROR != palError) + { + ASSERT("Unable to allocate pal thread: error %d - aborting\n", palError); + PROCAbort(); + } + } + + return pThread; +} + +PAL_ERROR +AllocatePalThread(CPalThread **ppThread) +{ + CPalThread *pThread = NULL; + PAL_ERROR palError; + + palError = CreateThreadData(&pThread); + if (NO_ERROR != palError) + { + goto exit; + } + +#if !HAVE_MACH_EXCEPTIONS + // Ensure alternate stack for SIGSEGV handling. Our SIGSEGV handler is set to + // run on an alternate stack and the stack needs to be allocated per thread. + if (!pThread->EnsureSignalAlternateStack()) + { + ERROR("Cannot allocate alternate stack for SIGSEGV handler!\n"); + palError = ERROR_NOT_ENOUGH_MEMORY; + goto exit; + } +#endif // !HAVE_MACH_EXCEPTIONS + + HANDLE hThread; + palError = CreateThreadObject(pThread, pThread, &hThread); + if (NO_ERROR != palError) + { + pthread_setspecific(thObjKey, NULL); + pThread->ReleaseThreadReference(); + goto exit; + } + + // Like CreateInitialProcessAndThreadObjects, we do not need this + // thread handle, since we're not returning it to anyone who will + // possibly release it. + (void)g_pObjectManager->RevokeHandle(pThread, hThread); + + PROCAddThread(pThread, pThread); + +exit: + *ppThread = pThread; + return palError; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/.gitignore b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/.gitignore new file mode 100644 index 0000000..7b7905f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/.gitignore @@ -0,0 +1,79 @@ +*.la +*.a +*.o +*.lo +*~ +*.pc + +.libs/ +.deps/ + +.dirstamp +Makefile +Makefile.in + +INSTALL +aclocal.m4 +autom4te.cache/ +config.log +config.status +config/ +configure +libtool + +doc/common.tex + +src/[GL]cursor_i.h +src/mk_[GL]cursor_i.s + +include/config.h +include/config.h.in +include/libunwind-common.h +include/stamp-h1 +include/libunwind.h +include/tdep/libunwind_i.h + +tests/[GL]test-bt +tests/[GL]test-concurrent +tests/[GL]test-dyn1 +tests/[GL]test-exc +tests/[GL]test-init +tests/[GL]test-resume-sig +tests/[GL]test-resume-sig-rt +tests/[GL]perf-simple +tests/Ltest-nomalloc +tests/Ltest-nocalloc +tests/Lperf-simple +tests/Lrs-race +tests/Ltest-varargs +tests/check-namespace.sh +tests/crasher +tests/forker +tests/mapper +tests/rs-race +tests/test-async-sig +tests/test-coredump-unwind +tests/test-flush-cache +tests/test-init-remote +tests/test-mem +tests/test-ptrace +tests/test-setjmp +tests/test-strerror +tests/test-proc-info +tests/test-ptrace-misc +tests/test-reg-state +tests/test-varargs +tests/test-static-link +tests/[GL]test-trace +tests/[GL]perf-trace +tests/Ltest-cxx-exceptions +tests/Ltest-init-local-signal +tests/Ltest-mem-validate +tests/[GL]ia64-test-nat +tests/[GL]ia64-test-rbs +tests/[GL]ia64-test-readonly +tests/[GL]ia64-test-stack +tests/ia64-test-dyn1 +tests/ia64-test-sig +tests/*.log +tests/*.trs diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/.travis.yml b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/.travis.yml new file mode 100644 index 0000000..4a74b4a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/.travis.yml @@ -0,0 +1,18 @@ +sudo: required +language: c +compiler: gcc +env: +- TARGET=x86_64-linux-gnu +- TARGET=x86-linux-gnu +- TARGET=arm-linux-gnueabihf +- TARGET=aarch64-linux-gnu +- TARGET=mipsel-unknown-linux-gnu +# Currently experiencing build failures here +#- TARGET=powerpc64-linux-gnu +script: +- ./autogen.sh +- ./configure --target=$TARGET --host=$HOST +- make -j32 +- sudo bash -c 'echo core.%p.%p > /proc/sys/kernel/core_pattern' +- ulimit -c unlimited +- if [ $TARGET == 'x86_64-linux-gnu' ]; then make check -j32; fi diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/AUTHORS b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/AUTHORS new file mode 100644 index 0000000..719eee5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/AUTHORS @@ -0,0 +1 @@ +David Mosberger diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/CMakeLists.txt new file mode 100644 index 0000000..5c66b90 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/CMakeLists.txt @@ -0,0 +1,22 @@ +add_subdirectory(src) + +# define variables for the configure_file below + +if (CLR_CMAKE_HOST_ARCH_AMD64) + set(arch x86_64) +elseif(CLR_CMAKE_HOST_ARCH_ARM64) + set(arch aarch64) +elseif(CLR_CMAKE_PLATFROM_ARCH_ARM) + set(arch arm) +elseif(CLR_CMAKE_HOST_ARCH_I386) + set(arch x86) +endif() + +set(PKG_MAJOR "1") +set(PKG_MINOR "3") +set(PKG_EXTRA "-rc1") + +configure_file(include/libunwind-common.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/libunwind-common.h) +configure_file(include/libunwind.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/libunwind.h) +configure_file(include/tdep/libunwind_i.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/tdep/libunwind_i.h) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/COPYING b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/COPYING new file mode 100644 index 0000000..41e7d8a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/COPYING @@ -0,0 +1,20 @@ +Copyright (c) 2002 Hewlett-Packard Co. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/ChangeLog b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/ChangeLog new file mode 100644 index 0000000..dfa24b9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/ChangeLog @@ -0,0 +1,55 @@ +*********************************************************** + + Discontinued. See git log instead at + + http://www.kernel.org/git/gitweb.cgi?p=libs/libunwind/libunwind.git;a=log + +*********************************************************** + +2002-11-08 David Mosberger-Tang + + * src/ia64/unwind_i.h (ia64_getfp): Change from macro to inline + function. Check "loc" argument for being NULL before dereferencing it. + (ia64_putfp): Ditto. + (ia64_get): Ditto. + (ia64_put): Ditto. + +2002-01-18 David Mosberger-Tang + + * src/ia64/parser.c (__ia64_unw_create_state_record): Set + IA64_FLAG_HAS_HANDLER if the unwind info descriptors indicate that + there a handler. + + * src/ia64/regs.c (__ia64_access_reg): Return zero for UNW_REG_HANDLER + in frames that don't have a personality routine. + + * src/ia64/unwind_i.h (IA64_FLAG_HAS_HANDLER): New flag. + + * src/ia64/regs.c (__ia64_access_reg): When reading UNW_REG_HANDLER, + account for the fact that the personality address is gp-relative. + + * src/ia64/parser.c (__ia64_unw_create_state_record): Fix + initialization of segbase and len. + +2002-01-17 David Mosberger-Tang + + * include/unwind-ia64.h: Include via "unwind.h" to ensure + the file is picked up from same directory. + +2002-01-16 David Mosberger-Tang + + * include/unwind.h: Define UNW_ESTOPUNWIND. This error code may + be returned by acquire_unwind_info() to force termination of + unwinding. An application may want to do this when encountering a + call frame for dynamically generated code, for example. + + * unwind.h: Pass opaque argument pointer to acquire_unwind_info() + and release_unwind_info() like we do for access_mem() etc. + +2002-01-14 David Mosberger-Tang + + * Version 0.0 released. + +2002-01-11 David Mosberger-Tang + + * ChangeLog created. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/LICENSE b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/LICENSE new file mode 100644 index 0000000..c9b44cb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/LICENSE @@ -0,0 +1,18 @@ +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/Makefile.am b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/Makefile.am new file mode 100644 index 0000000..711d910 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/Makefile.am @@ -0,0 +1,106 @@ +include_HEADERS = include/libunwind-dynamic.h + +if BUILD_PTRACE +include_HEADERS += include/libunwind-ptrace.h +endif BUILD_PTRACE + +if BUILD_COREDUMP +include_HEADERS += include/libunwind-coredump.h +endif BUILD_COREDUMP + +if ARCH_AARCH64 +include_HEADERS += include/libunwind-aarch64.h +endif +if ARCH_ARM +include_HEADERS += include/libunwind-arm.h +endif +if ARCH_IA64 +include_HEADERS += include/libunwind-ia64.h +endif +if ARCH_HPPA +include_HEADERS += include/libunwind-hppa.h +endif +if ARCH_MIPS +include_HEADERS += include/libunwind-mips.h +endif +if ARCH_TILEGX +include_HEADERS += include/libunwind-tilegx.h +endif +if ARCH_X86 +include_HEADERS += include/libunwind-x86.h +endif +if ARCH_X86_64 +include_HEADERS += include/libunwind-x86_64.h +endif +if ARCH_PPC32 +include_HEADERS += include/libunwind-ppc32.h +endif +if ARCH_PPC64 +include_HEADERS += include/libunwind-ppc64.h +endif +if ARCH_SH +include_HEADERS += include/libunwind-sh.h +endif + +if !REMOTE_ONLY +include_HEADERS += include/libunwind.h include/unwind.h +endif + +nodist_include_HEADERS = include/libunwind-common.h + +SUBDIRS = src + +if CONFIG_TESTS +SUBDIRS += tests +endif + +if CONFIG_DOCS +SUBDIRS += doc +endif + +noinst_HEADERS = include/dwarf.h include/dwarf_i.h include/dwarf-eh.h \ + include/compiler.h include/libunwind_i.h include/mempool.h \ + include/remote.h \ + include/tdep-aarch64/dwarf-config.h \ + include/tdep-aarch64/jmpbuf.h \ + include/tdep-aarch64/libunwind_i.h \ + include/tdep-arm/dwarf-config.h include/tdep-arm/ex_tables.h \ + include/tdep-arm/jmpbuf.h include/tdep-arm/libunwind_i.h \ + include/tdep-ia64/jmpbuf.h include/tdep-ia64/rse.h \ + include/tdep-ia64/libunwind_i.h include/tdep-ia64/script.h \ + include/tdep-hppa/libunwind_i.h \ + include/tdep-hppa/jmpbuf.h include/tdep-hppa/dwarf-config.h \ + include/tdep-mips/libunwind_i.h \ + include/tdep-mips/jmpbuf.h include/tdep-mips/dwarf-config.h \ + include/tdep-tilegx/libunwind_i.h \ + include/tdep-tilegx/jmpbuf.h include/tdep-tilegx/dwarf-config.h \ + include/tdep-x86/libunwind_i.h \ + include/tdep-x86/jmpbuf.h include/tdep-x86/dwarf-config.h \ + include/tdep-x86_64/libunwind_i.h \ + include/tdep-x86_64/jmpbuf.h include/tdep-x86_64/dwarf-config.h \ + include/tdep-ppc32/dwarf-config.h \ + include/tdep-ppc32/jmpbuf.h include/tdep-ppc32/libunwind_i.h \ + include/tdep-ppc64/dwarf-config.h \ + include/tdep-ppc64/jmpbuf.h include/tdep-ppc64/libunwind_i.h \ + include/tdep-sh/dwarf-config.h \ + include/tdep-sh/jmpbuf.h include/tdep-sh/libunwind_i.h \ + include/tdep/libunwind_i.h \ + include/tdep/jmpbuf.h include/tdep/dwarf-config.h + +EXTRA_DIST = include/libunwind-common.h.in + +MAINTAINERCLEANFILES = \ + Makefile.in \ + INSTALL \ + aclocal.m4 \ + configure \ + config/compile \ + config/config.guess \ + config/config.sub \ + config/depcomp \ + config/install-sh \ + config/ltmain.sh \ + config/missing \ + include/config.h.in \ + include/config.h.in~ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/NEWS b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/NEWS new file mode 100644 index 0000000..ae6cbcf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/NEWS @@ -0,0 +1,247 @@ +-*-Mode: outline-*- + +* News for v1.3: + +** Iteration of unwind register states support + Doug Moore +** Freebsd/Armv6 support + Konstantin Belousov +** Many, many dwarf bugfixes +** Mips remote unwind support +** aarch64 ptrace support + +* News for v1.2: + +** aarch64 port +** dwarf parsing improvements +** Fast stacktraces for aarch64 & arm +** tilegx port +** powerpc64 port + +* News for v1.1: + +** coredump unwind support +** New arch: SuperH +** Improved support for PowerPC, ARM +** Lots of cleanups, perf tweaks +** pkg-config support + +* News for v1.0: + +** Fast unwind (rbp, rsp, rip only) on x86_64 with a fallback to + slow code path (Lassi Tuura) +** Improved local and remote unwinding on ARM (Ken Werner) +** Testing, stability and many fixes on x86 (Paul Pluzhnikov) +** FreeBSD port and clean separation of OS specific bits + (Konstantin Belousov) +** Thanks for all the bug reports, contributions and testing! + +* News for v0.99: + +** Greatly improved x86-64 support thanks to Arun Sharma. +** Support for PPC64 added by Jose Flavio Aguilar Paulino. + +* News for v0.98.6: + +** Fix address-leak triggered by invalid byte-order. Fixed by Andreas Schwab. +** On ia64, get_static_proc_name() no longer uses a weak reference to + _Uelf64_get_proc_name(), since that was causing problems with archive + libraries and no longer served any apparent purpose. Fixed by + Curt Wohlgemuth. + +* News for v0.98.5: + +** Fix a typo in the man-page of unw_create_addr_space(). +** Fix an off-by-1 bug in the handling of the dynamic ALIAS directive + for ia64. Reported by Todd L. Miller. +** Fix a bug in libunwind-ptrace which could cause crash due to extraneous + munmap() calls. + +* News for v0.98.4: + +** Fix a typo in _ReadSLEB.c which caused hangs when throwing exceptions + from Intel ICC-compiled programs. Reported by Tommy Hoffner. + +* News for v0.98.3: + +** Make it possible to link against libunwind-ia64.a only (i.e., without + requiring libunwind.a as well). This keeps apps which need only + remote unwinding cleaner, since they logically have no dependency + on libunwind.a. +** Dont link against libatomic_ops for now. Due to a packaging bug on + Debian, linking against this library causes libunwind.so to get + a dependency on libatomic_ops.so, which is not at all what we want. + Fortunately, we don't have to link against that library on x86 or + ia64 since the library is strictly needed only for platforms with + poor atomic operation support. Once the libatomic_ops package is fixed, + we can re-enable linking against libatomic_ops. + +* News for v0.98.2: + +** Fixed bug which caused _UPT_get_dyn_info_list_addr() to sometimes fail + needlessly. Found by Todd L. Miller. + +** When using GCC to build libunwind on ia64, libunwind.so had an + unresolved reference to __divdi3. This is undesirable since it + creates an implicit dependency on libgcc. This problem has been + fixed in the 0.98.2 release by explicitly linking against libgcc.a + when building libunwind. + +* News for v0.98.1: + +** Fixed a bug which caused "make install" to install libunwind-common.h.in + instead of libunwind-common.h. +** Fixed a bug in the ia64 {sig,}longjmp() which showed on + SuSE Linux 9 because it's using a newer compiler & the EPC-based system + call stubs. +** Fixed incorrect offsets in tests/ia64-test-nat-asm.S. + Warning: you'll need a GNU assembler dated later than 21-Sep-2004 to + get this file translated correctly. With an old assembler, "make check" + will get lots of failures when running Gia64-test-nat or Lia64-test-nat! +** Convert tests/bt into a full-blown test-case. It's designed to + trigger a (rarely-encountered) bug in the GNU assembler on ia64. + The assembler has been fixed and once the libraries (libc etc) + have been rebuilt, this test will pass. +** Added test-case tests/run-ptrace-misc which, on ia64, triggers a bug in + current GCC (including v3.4.2) which causes bad unwind info. + +* News for v0.98: + +** Update libunwind to be compliant with the updated/expanded + ia64 unwind specificiation by HJ Lu [1]. This is needed for + GCC 3.4 compatibility. + + [1] http://www.kernel.org/pub/linux/devel/gcc/unwind/ + +** Initial support for x86-64 has been added courtesy of Max Asbock. + Along with this came a bunch of DWARF2 unwinder fixes. + +** A new rountine unw_strerror() has been added courtesy of + Thomas Hallgren. + +** Including now defines 4 macros that can be used + to determine the version number of libunwind. Specifically, + UNW_VERSION_MAJOR, UNW_VERSION_MINOR, UNW_VERSION, and + UNW_VERSION_CODE are defined by the header now. + +** Bug fixes +*** Fix a memory-leak in _UPT_get_dyn_info_list_addr() courtesy of Ed Connell. +*** Fix a crash in libunwind-ptrace courtesy of Mark Young. +*** Fix a bug in ia64-version of unw_init_remote() which prevented + it from working correctly for the local address space. Reported by + Troy Heber. +*** Many other small and not so small fixes. + +* News for v0.97: + +** unw_get_proc_name() may now be called from signal-handler. + +** The ptrace-helper routines are now declared in libunwind-ptrace.h. + Applications which use ptrace-based unwinding should include + to get the _UPT_*() routines declared. + +** libunwind has been split into a "local-only" and a "generic" versions. + The former is optimized for local unwinding (within a process) and + is called libunwind.so (shared version) or libunwind.a (archive + version). The generic version is not limited to unwinding within a + process and is called libunwind-generic.so (shared version) + libunwind-generic.a (archive version). Similarly, the ptrace() + support has been separated out into a convenience library called + libunwind-ptrace.a. For the most part, backwards-compatibility + is retained. However, when building an application which uses + libunwind, it may be necessary to change the linker command-line + as shown in the table below: + + Application which does: Before v0.97: With v0.97: + ----------------------- ------------- ----------- + local unwinding only: -lunwind -lunwind + remote unwinding: -lunwind -lunwind-generic + cross unwinding: -lunwind-PLAT -lunwind-PLAT + ptrace-based unwinding: -lunwind -lunwind-ptrace -lunwind-generic + + The motivation for this splitting is to keep libunwind.so as minimal + as possible. This library will eventually be loaded by most (if not + all) executables and hence it is important to ensure that it can + be loaded as quickly as possible. + +** unw_getcontext() tuned on IA-64. + + The unw_getcontext() routine used to be provided by (GNU) libc + (getcontext()). This caused unnecessary overhead (e.g., an + unnecessary system-call to sigprocmask()). The new + unw_getcontext() only does the work really needed for libunwind and + hence performs much better. However, this change implies that + programs linked against libunwind v0.97 won't be + backwards-compatible with earlier versions (there would be an + unresolved symbol for _Uia64_getcontext()). + +** Fix NaT-bit handling on IA-64. + + New test-cases have been added to test the handling of the NaT bit + (and floating-point NaT values) and all discovered/known bugs have + been fixed. + +** Initial DWARF-based unwinder for x86. + + There is a beginning for a DWARF-based unwinder for x86. Work for + x86-64-support based on this DWARF unwinder is currently underway + at IBM and it is expected that this support will be merged into the + official tree soon. + + +* News for v0.96: + +** _Unwind_*() routines defined by the C++ ABI are now included in + libunwind. + + +* News for v0.95: + +** Bigger, better, faster, or so the theory goes. + + +* News for v0.93: + +** More bug-fixes & improved HP-UX support. + + +* News for v0.92: + +** Bug-fix release. IA-64 unwinder can now be built with Intel compiler (ECC). + + +* News for v0.91: + +** Lots of documentation updates +** Some portability fixes. + + +* News for v0.9: + +** The libunwind API is mostly feature-complete at this point (hence the + version jump from v0.2 to v0.9). + + +* News for v0.2: + +** Automated configuration/build with autoconf and automake. +** Added support for building libunwind as a shared library. +** Added support for remote unwinding. +** Added support for cross-building. +** Added two new routines to the API: + - unw_is_fpreg() + - unw_get_save_loc() +** Added multi-architecture supports (lets a single application use + the unwind libraries for multiple target architectures; this is useful, + e.g., useful for building a debugger that can support multiple targets + such as x86, ia64, etc.) + + +* News for v0.1: + +** Added support for exception handling. + + +* News for v0.0: + +** It's a brand new package. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/README b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/README new file mode 100644 index 0000000..694f600 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/README @@ -0,0 +1,207 @@ +-*- mode: Outline -*- + +[![Build Status](https://travis-ci.org/libunwind/libunwind.svg?branch=master)](https://travis-ci.org/libunwind/libunwind) + +This is version 1.3 of the unwind library. This library supports +several architecture/operating-system combinations: + + Linux/x86-64: Works well. + Linux/x86: Works well. + Linux/ARM: Works well. + Linux/IA-64: Works well. + Linux/PARISC: Works well, but C library missing unwind-info. + HP-UX/IA-64: Mostly works but known to have some serious limitations. + MIPS: Newly added. + Linux/AArch64: Works well. + Linux/PPC64: Newly added. + Linux/SuperH: Newly added. + FreeBSD/i386: Works well. + FreeBSD/x86-64: Newly added (FreeBSD architecture is known as amd64). + Linux/Tilegx: Newly added (64-bit mode only). + +* General Build Instructions + +In general, this library can be built and installed with the following +commands: + + $ ./autogen.sh # Needed only for building from git. Depends on libtool. + $ ./configure + $ make + $ make install prefix=PREFIX + +where PREFIX is the installation prefix. By default, a prefix of +/usr/local is used, such that libunwind.a is installed in +/usr/local/lib and unwind.h is installed in /usr/local/include. For +testing, you may want to use a prefix of /usr/local instead. + + +* Building with Intel compiler + +** Version 8 and later + +Starting with version 8, the preferred name for the IA-64 Intel +compiler is "icc" (same name as on x86). Thus, the configure-line +should look like this: + + $ ./configure CC=icc CFLAGS="-g -O3 -ip" CXX=icc CCAS=gcc CCASFLAGS=-g \ + LDFLAGS="-L$PWD/src/.libs" + + +* Building on HP-UX + +For the time being, libunwind must be built with GCC on HP-UX. + +libunwind should be configured and installed on HP-UX like this: + + $ ./configure CFLAGS="-g -O2 -mlp64" CXXFLAGS="-g -O2 -mlp64" + +Caveat: Unwinding of 32-bit (ILP32) binaries is not supported + at the moment. + +** Workaround for older versions of GCC + +GCC v3.0 and GCC v3.2 ship with a bad version of sys/types.h. The +workaround is to issue the following commands before running +"configure": + + $ mkdir $top_dir/include/sys + $ cp /usr/include/sys/types.h $top_dir/include/sys + +GCC v3.3.2 or later have been fixed and do not require this +workaround. + +* Building for PowerPC64 / Linux + +For building for power64 you should use: + + $ ./configure CFLAGS="-g -O2 -m64" CXXFLAGS="-g -O2 -m64" + +If your power support altivec registers: + $ ./configure CFLAGS="-g -O2 -m64 -maltivec" CXXFLAGS="-g -O2 -m64 -maltivec" + +To check if your processor has support for vector registers (altivec): + cat /proc/cpuinfo | grep altivec +and should have something like this: + cpu : PPC970, altivec supported + +If libunwind seems to not work (backtracing failing), try to compile +it with -O0, without optimizations. There are some compiler problems +depending on the version of your gcc. + +* Building on FreeBSD + +General building instructions apply. To build and execute several tests, +you need libexecinfo library available in ports as devel/libexecinfo. + +Development of the port was done of FreeBSD 8.0-STABLE. The library +was build with the system compiler that is modified version of gcc 4.2.1, +as well as the gcc 4.4.3. + +* Regression Testing + +After building the library, you can run a set of regression tests with: + + $ make check + +** Expected results on IA-64 Linux + +Unless you have a very recent C library and compiler installed, it is +currently expected to have the following tests fail on IA-64 Linux: + + Gtest-init (should pass starting with glibc-2.3.x/gcc-3.4) + Ltest-init (should pass starting with glibc-2.3.x/gcc-3.4) + test-ptrace (should pass starting with glibc-2.3.x/gcc-3.4) + run-ia64-test-dyn1 (should pass starting with glibc-2.3.x) + +This does not mean that libunwind cannot be used with older compilers +or C libraries, it just means that for certain corner cases, unwinding +will fail. Since they're corner cases, it is not likely for +applications to trigger them. + +Note: If you get lots of errors in Gia64-test-nat and Lia64-test-nat, it's + almost certainly a sign of an old assembler. The GNU assembler used + to encode previous-stack-pointer-relative offsets incorrectly. + This bug was fixed on 21-Sep-2004 so any later assembler will be + fine. + +** Expected results on x86 Linux + +The following tests are expected to fail on x86 Linux: + + test-ptrace + +** Expected results on x86-64 Linux + +The following tests are expected to fail on x86-64 Linux: + + run-ptrace-misc (see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18748 + and http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18749) + +** Expected results on PARISC Linux + +Caveat: GCC v3.4 or newer is needed on PA-RISC Linux. Earlier +versions of the compiler failed to generate the exception-handling +program header (GNU_EH_FRAME) needed for unwinding. + +The following tests are expected to fail on x86-64 Linux: + + Gtest-bt (backtrace truncated at kill() due to lack of unwind-info) + Ltest-bt (likewise) + Gtest-resume-sig (Gresume.c:my_rt_sigreturn() is wrong somehow) + Ltest-resume-sig (likewise) + Gtest-init (likewise) + Ltest-init (likewise) + Gtest-dyn1 (no dynamic unwind info support yet) + Ltest-dyn1 (no dynamic unwind info support yet) + test-setjmp (longjmp() not implemented yet) + run-check-namespace (toolchain doesn't support HIDDEN yet) + +** Expected results on HP-UX + +"make check" is currently unsupported for HP-UX. You can try to run +it, but most tests will fail (and some may fail to terminate). The +only test programs that are known to work at this time are: + + tests/bt + tests/Gperf-simple + tests/test-proc-info + tests/test-static-link + tests/Gtest-init + tests/Ltest-init + tests/Gtest-resume-sig + tests/Ltest-resume-sig + +** Expected results on PPC64 Linux + +"make check" should run with no more than 10 out of 24 tests failed. + + +* Performance Testing + +This distribution includes a few simple performance tests which give +some idea of the basic cost of various libunwind operations. After +building the library, you can run these tests with the following +commands: + + $ cd tests + $ make perf + +* Contacting the Developers + +Please direct all questions regarding this library to: + + libunwind-devel@nongnu.org + +You can do this by sending a mail to libunwind-request@nongnu.org with +a body of: + + subscribe libunwind-devel + +or you can subscribe and manage your subscription via the +web-interface at: + + https://savannah.nongnu.org/mail/?group=libunwind + +Or interact at the gihub page: + + https://github.com/libunwind/libunwind diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/README.md b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/README.md new file mode 100644 index 0000000..100b938 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/README.md @@ -0,0 +1 @@ +README \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/TODO b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/TODO new file mode 100644 index 0000000..8b2e026 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/TODO @@ -0,0 +1,97 @@ +- Update the libunwind man page for the new/fixed cache-flushing behavior. + Effectively, that unw_flush_cache() doesn't have to be called by + applications except for extraordinary circumstances (e.g., if application + implements its own runtime loader). +- document split local-only/generic libraries and separate libunwind-ptrace.a + convenience-library +- document new "tdep" member in unw_proc_info_t structure +- for DWARF 2, use a dummy CIE entry with an augmentation that + provides the dyn-info-list-address + +=== taken care of: + +Testing: + + ensure that saving r4-r7 in a stacked register properly preserves + the NaT bit, even in the face of register-rotation + + ensure that IA64_INSN_MOVE_STACKED works correctly in the face of + register rotation + + on Linux, test access to f32-f127 in a signal handler (e.g., verify + that fph partition gets initialized properly) ++ According to Nicholas S. Wourms , adding this to the + Makefile.am: + AUTOMAKE_OPTIONS = 1.6 subdir-objects + ensures that object-files are build in separate subdirectories and that + in turn makes it possible for source files in different directories to + have the same filename, thus avoiding the need for those ugly -x86, -ia64, + etc., postfixes. ++ Switch ia64 (and rest over) to using Debug() instead of debug() ++ implement non-local versions of dwarf_readXX() ++ consolidate mostly architecture-independent code such as + unw_get_accessors() into shared files ++ caching is pretty fundamentally broken, what should happen is this: + o On unw_init_local()/unw_init_remote(), libunwind should validate + that the cached information is still valid and, if not, flush the + cache on its own. Rationale: once unw_init_local() has been + called, it is clear that the unwind info for the calling thread + cannot change (otherwise the program would be buggy anyhow) and + hence it is sufficient to validate the cache at this point. + Similarly, once unw_init_remote() has been called, the target + address space must have been stopped, because the unwinding would + otherwise be unreliable anyhow. + o glibc currently lacks a feature for dl_iterate_phdr() to support + safe caching; I proposed on 12/16/2003 that glibc maintain two + atomic counters which get inremented whenever something is added + to/removed from the dl_iterate_phdr-list. Once we have such counters, + we can use them in libunwind to implement an efficient version of a + cache-validation routine. + Once this has been fixed, update the libunwind man page accordingly. + Effectively, what this means is that unw_flush_cache() doesn't have + to be called by applications except for extraordinary circumstances + (e.g., if application implements its own runtime loader). ++ man-page for unw_is_fpreg() ++ man-page for _U_dyn_cancel() ++ man-page for _U_dyn_register() ++ global data is not protected by a lock; causes problems if two threads + call ia64_init() at almost the same time ++ cache the value of *cfm_loc; each rotate_FOO() call needs it! ++ implement the remote-lookup of the dynamic registration list ++ when doing sigreturn, must restore fp regs (and perhaps other regs) the same + way as the (user-level) gate.S sigreturn path does! ++ unw_resume() must at least restore gp (r1)! consider restoring all + scratch regs (but what's the performance impact on exception handling?); + alternative: restore scratch regs that may be used during procedure + call/return (e.g., r8-r11, f8-f11) ++ implement unw_resume() for the case where the current register frame is split + across multiple backing stores ++ document restricions on using unw_resume(): ++ implement remote cases of unw_resume() ++ test both with UNW_LOCAL_ONLY and without where this makes sense ++ allow region-length (insn_count) in unw_dyn_region_info_t to be negative + to indicate counting from the end of the procedure (to make it possible + for differently-sized procedures to share the same region list if they + share the same prologue/epilogue). ++ it appears that it is currently not possible to read register UNW_IA64_TP; + fix that => no, attempts to access r13 will result in access_reg() callbacks, + as desired; for local-case, access to r13 will fail though (since + getcontext() doesn't, and shouldn't, capture r13) ++ document the special nature of UNW_IA64_GP: read-only, but adjusted + automatically if the IP is changed ++ use pthread-mutexes where necessary, atomic ops where possible ++ man-page for unw_init_local() ++ man-page for unw_init_remote() ++ man-page for unw_create_addr_space() ++ man-page for unw_destroy_addr_space() ++ man-page for unw_get_proc_info() ++ man-page for unw_get_proc_name() ++ man-page for unw_get_accessors() ++ man-page for unw_regname() ++ man-page for unw_flush_cache() ++ man-page for unw_set_caching_policy() ++ man-page for unw_getcontext() ++ man-page for unw_is_signal_frame() ++ man-page for unw_step() ++ man-page for unw_get_reg() ++ man-page for unw_set_reg() ++ man-page for unw_get_fpreg() ++ man-page for unw_set_fpreg() ++ test with Intel compiler diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/acinclude.m4 b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/acinclude.m4 new file mode 100644 index 0000000..497f7c2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/acinclude.m4 @@ -0,0 +1,32 @@ +AC_DEFUN([LIBUNWIND___THREAD], +[dnl Check whether the compiler supports the __thread keyword. +if test "x$enable___thread" != xno; then + AC_CACHE_CHECK([for __thread], libc_cv_gcc___thread, + [cat > conftest.c <<\EOF + __thread int a = 42; +EOF + if AC_TRY_COMMAND([${CC-cc} $CFLAGS -c conftest.c >&AS_MESSAGE_LOG_FD]); then + libc_cv_gcc___thread=yes + else + libc_cv_gcc___thread=no + fi + rm -f conftest*]) + if test "$libc_cv_gcc___thread" = yes; then + AC_DEFINE(HAVE___THREAD, 1, + [Define to 1 if __thread keyword is supported by the C compiler.]) + fi +else + libc_cv_gcc___thread=no +fi]) + +AC_DEFUN([CHECK_ATOMIC_OPS], +[dnl Check whether the system has the atomic_ops package installed. + AC_CHECK_HEADERS(atomic_ops.h) +# +# Don't link against libatomic_ops for now. We don't want libunwind +# to depend on libatomic_ops.so. Fortunately, none of the platforms +# we care about so far need libatomic_ops.a (everything is done via +# inline macros). +# +# AC_CHECK_LIB(atomic_ops, main) +]) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/autogen.sh b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/autogen.sh new file mode 100644 index 0000000..aad9de6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/autogen.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +test -n "$srcdir" || srcdir=`dirname "${BASH_SOURCE[0]}"` +test -n "$srcdir" || srcdir=. +( + cd "$srcdir" && + autoreconf --force -v --install +) || exit +test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/aux_/config.guess b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/aux_/config.guess new file mode 100644 index 0000000..ed2e03b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/aux_/config.guess @@ -0,0 +1,1321 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-03-20' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int dummy(){}" > $dummy.c ; + for c in cc gcc c89 c99 ; do + ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; + if test $? = 0 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + rm -f $dummy.c $dummy.o $dummy.rel ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + eval $set_cc_for_build + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + 2-1307) + UNAME_MACHINE="alphaev68" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy` + if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi + rm -f $dummy.c $dummy + fi ;; + esac + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3D:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:3*) + echo i386-pc-interix3 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + rm -f $dummy.c + test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + rm -f $dummy.c + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit 0 ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/aux_/config.sub b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/aux_/config.sub new file mode 100644 index 0000000..f365797 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/aux_/config.sub @@ -0,0 +1,1443 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-03-07' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | c4x | clipper \ + | d10v | d30v | dsp16xx \ + | fr30 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | m32r | m68000 | m68k | m88k | mcore \ + | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el | mips64vr4300 \ + | mips64vr4300el | mips64vr5000 | mips64vr5000el \ + | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ + | mipsisa32 | mipsisa64 \ + | mn10200 | mn10300 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armv*-* \ + | avr-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c54x-* \ + | clipper-* | cydra-* \ + | d10v-* | d30v-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | m32r-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ + | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ + | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i686-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3d) + basic_machine=alpha-cray + os=-unicos + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + windows32) + basic_machine=i386-pc + os=-windows32-msvcrt + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh3eb | sh4eb) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/aux_/ltmain.sh b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/aux_/ltmain.sh new file mode 100644 index 0000000..6fc6900 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/aux_/ltmain.sh @@ -0,0 +1,5107 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun configure. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Check that we have a working $echo. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell, and then maybe $echo will work. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +# Parse our command line options once, thoroughly. +while test $# -gt 0 +do + arg="$1" + shift + + case $arg in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + execute_dlfiles) + execute_dlfiles="$execute_dlfiles $arg" + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case $arg in + --help) + show_help=yes + ;; + + --version) + echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + exit 0 + ;; + + --config) + ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0 + exit 0 + ;; + + --debug) + echo "$progname: enabling shell trace mode" + set -x + ;; + + --dry-run | -n) + run=: + ;; + + --features) + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + exit 0 + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --preserve-dup-deps) duplicate_deps="yes" ;; + + --quiet | --silent) + show=: + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 +fi + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + case $nonopt in + *cc | *++ | gcc* | *-gcc* | g++* | xlc*) + mode=link + for arg + do + case $arg in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case $mode in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + prev= + lastarg= + srcfile="$nonopt" + suppress_output= + + user_target=no + for arg + do + case $prev in + "") ;; + xcompiler) + # Aesthetically quote the previous argument. + prev= + lastarg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + + case $arg in + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + + # Add the previous argument to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + continue + ;; + esac + + # Accept any command-line options. + case $arg in + -o) + if test "$user_target" != "no"; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit 1 + fi + user_target=next + ;; + + -static) + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + lastarg="$lastarg $arg" + done + IFS="$save_ifs" + lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` + + # Add the arguments to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + continue + ;; + esac + + case $user_target in + next) + # The next one is the -o target name + user_target=yes + continue + ;; + yes) + # We got the output file + user_target=set + libobj="$arg" + continue + ;; + esac + + # Accept the current argument as the source file. + lastarg="$srcfile" + srcfile="$arg" + + # Aesthetically quote the previous argument. + + # Backslashify any backslashes, double quotes, and dollar signs. + # These are the only characters that are still specially + # interpreted inside of double-quoted scrings. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $lastarg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + lastarg="\"$lastarg\"" + ;; + esac + + # Add the previous argument to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + done + + case $user_target in + set) + ;; + no) + # Get the name of the library object. + libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + *) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit 1 + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSfmso]' + case $libobj in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case $libobj in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit 1 + ;; + esac + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $libobj" + else + removelist="$libobj" + fi + + $run $rm $removelist + trap "$run $rm $removelist; exit 1" 1 2 15 + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit 1" 1 2 15 + else + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $run ln "$0" "$lockfile" 2>/dev/null; do + $show "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + echo "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + echo $srcfile > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + # All platforms use -DPIC, to notify preprocessed assembler code. + command="$base_compile $srcfile $pic_flag -DPIC" + else + # Don't build PIC code + command="$base_compile $srcfile" + fi + if test "$build_old_libs" = yes; then + lo_libobj="$libobj" + dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$libobj"; then + dir="$objdir" + else + dir="$dir/$objdir" + fi + libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` + + if test -d "$dir"; then + $show "$rm $libobj" + $run $rm $libobj + else + $show "$mkdir $dir" + $run $mkdir $dir + status=$? + if test $status -ne 0 && test ! -d $dir; then + exit $status + fi + fi + fi + if test "$compiler_o_lo" = yes; then + output_obj="$libobj" + command="$command -o $output_obj" + elif test "$compiler_c_o" = yes; then + output_obj="$obj" + command="$command -o $output_obj" + fi + + $run $rm "$output_obj" + $show "$command" + if $run eval "$command"; then : + else + test -n "$output_obj" && $run $rm $removelist + exit 1 + fi + + if test "$need_locks" = warn && + test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then + echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + + # Just move the object if needed, then go on to compile the next one + if test x"$output_obj" != x"$libobj"; then + $show "$mv $output_obj $libobj" + if $run $mv $output_obj $libobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # If we have no pic_flag, then copy the object into place and finish. + if (test -z "$pic_flag" || test "$pic_mode" != default) && + test "$build_old_libs" = yes; then + # Rename the .lo from within objdir to obj + if test -f $obj; then + $show $rm $obj + $run $rm $obj + fi + + $show "$mv $libobj $obj" + if $run $mv $libobj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"` + libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` + # Now arrange that obj and lo_libobj become the same file + $show "(cd $xdir && $LN_S $baseobj $libobj)" + if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + $run $rm "$lockfile" + fi + exit 0 + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Allow error messages only from the first compilation. + suppress_output=' >/dev/null 2>&1' + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $srcfile" + else + # All platforms use -DPIC, to notify preprocessed assembler code. + command="$base_compile $srcfile $pic_flag -DPIC" + fi + if test "$compiler_c_o" = yes; then + command="$command -o $obj" + output_obj="$obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + command="$command$suppress_output" + $run $rm "$output_obj" + $show "$command" + if $run eval "$command"; then : + else + $run $rm $removelist + exit 1 + fi + + if test "$need_locks" = warn && + test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then + echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + + # Just move the object if needed + if test x"$output_obj" != x"$obj"; then + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Create an invalid libtool object if no PIC, so that we do not + # accidentally link it into a program. + if test "$build_libtool_libs" != yes; then + $show "echo timestamp > $libobj" + $run eval "echo timestamp > \$libobj" || exit $? + else + # Move the .lo from within objdir + $show "$mv $libobj $lo_libobj" + if $run $mv $libobj $lo_libobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + fi + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + $run $rm "$lockfile" + fi + + exit 0 + ;; + + # libtool link mode + link | relink) + modename="$modename: link" + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invokation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args="$nonopt" + compile_command="$nonopt" + finalize_command="$nonopt" + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + + avoid_version=no + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -all-static | -static) + if test "X$arg" = "X-all-static"; then + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + fi + build_libtool_libs=no + build_old_libs=yes + prefer_static_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test $# -gt 0; do + arg="$1" + shift + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test + ;; + *) qarg=$arg ;; + esac + libtool_args="$libtool_args $qarg" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit 1 + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit 1 + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + compile_command="$compile_command $wl$qarg" + finalize_command="$finalize_command $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n $prev + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: more than one -exported-symbols argument is not allowed" + exit 1 + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | no/*-*-nonstopux*) + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + ;; + esac + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + exit 1 + fi + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + case :$dllsearchpath: in + *":$dir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-pw32* | *-*-beos*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-mingw* | *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # The PATH hackery in wrapper scripts is required on Windows + # in order for the loader to find any dlls it needs. + $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 + $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -o) prev=output ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit 1 + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Wl,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $wl$flag" + linker_flags="$linker_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + + *.lo | *.$objext) + # A library or standard object. + if test "$prev" = dlfiles; then + # This file was specified with -dlopen. + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $arg" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"` + prev= + else + case $arg in + *.lo) libobjs="$libobjs $arg" ;; + *) objs="$objs $arg" ;; + esac + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done # argument parsing loop + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + # Create the object directory. + if test ! -d $output_objdir; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + status=$? + if test $status -ne 0 && test ! -d $output_objdir; then + exit $status + fi + fi + + # Determine the type of output + case $output in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if test "X$duplicate_deps" = "Xyes" ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + case $linkmode in + lib) + passes="conv link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 + exit 1 + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + for pass in $passes; do + if test $linkmode = prog; then + # Determine which files to process + case $pass in + dlopen) + libs="$dlfiles" + save_deplibs="$deplibs" # Collect dlpreopened libraries + deplibs= + ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + for deplib in $libs; do + lib= + found=no + case $deplib in + -l*) + if test $linkmode = oldlib && test $linkmode = obj; then + $echo "$modename: warning: \`-l' is ignored for archives/objects: $deplib" 1>&2 + continue + fi + if test $pass = conv; then + deplibs="$deplib $deplibs" + continue + fi + name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` + for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do + # Search the libtool library + lib="$searchdir/lib${name}.la" + if test -f "$lib"; then + found=yes + break + fi + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test $linkmode = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test $pass = conv && continue + newdependency_libs="$deplib $newdependency_libs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + prog) + if test $pass = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test $pass = scan; then + deplibs="$deplib $deplibs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + ;; + *) + $echo "$modename: warning: \`-L' is ignored for archives/objects: $deplib" 1>&2 + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test $pass = link; then + dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test $pass = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + if test "$deplibs_check_method" != pass_all; then + echo + echo "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not used here." + else + echo + echo "*** Warning: Linking the shared library $output against the" + echo "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + continue + ;; + prog) + if test $pass != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test $pass = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + if test $found = yes || test -f "$lib"; then : + else + $echo "$modename: cannot find the library \`$lib'" 1>&2 + exit 1 + fi + + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $lib | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit 1 + fi + + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + # If the library was installed with an old release of libtool, + # it will not redefine variable installed. + installed=yes + + # Read the .la file + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test $linkmode = oldlib && test $linkmode = obj; }; then + # Add dl[pre]opened files of deplib + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test $pass = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit 1 + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test $linkmode != prog && test $linkmode != lib; then + $echo "$modename: \`$lib' is not a convenience library" 1>&2 + exit 1 + fi + continue + fi # $pass = conv + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit 1 + fi + + # This library was specified with -dlopen. + if test $pass = dlopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 + exit 1 + fi + if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. + dlprefiles="$dlprefiles $lib" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + abs_ladir="$ladir" + fi + ;; + esac + laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + $echo "$modename: warning: library \`$lib' was moved." 1>&2 + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi # $installed = yes + name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + + # This library was specified with -dlpreopen. + if test $pass = dlpreopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 + exit 1 + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test $linkmode = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" + fi + continue + fi + + if test $linkmode = prog && test $pass != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test + esac + # Need to link against all dependency_libs? + if test $linkalldeplibs = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + link_static=no # Whether the deplib will be linked statically + if test -n "$library_names" && + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + # Link against this shared library + + if test "$linkmode,$pass" = "prog,link" || + { test $linkmode = lib && test $hardcode_into_libs = yes; }; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + if test $linkmode = prog; then + # We need to hardcode the library path + if test -n "$shlibpath_var"; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *" $absdir "*) ;; + *) temp_rpath="$temp_rpath $dir" ;; + esac + fi + fi + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + realname="$2" + shift; shift + libname=`eval \\$echo \"$libname_spec\"` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin*) + major=`expr $current - $age` + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + soname=`echo $soroot | ${SED} -e 's/^.*\///'` + newlib="libimp-`echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + $show "extracting exported symbol list from \`$soname'" + save_ifs="$IFS"; IFS='~' + eval cmds=\"$extract_expsyms_cmds\" + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + $show "generating import library for \`$soname'" + save_ifs="$IFS"; IFS='~' + eval cmds=\"$old_archive_from_expsyms_cmds\" + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n $old_archive_from_expsyms_cmds + + if test $linkmode = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case "$libdir" in + [\/]*) + add_dir="-L$inst_prefix_dir$libdir $add_dir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + $echo "$modename: configuration error: unsupported hardcode properties" + exit 1 + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test $linkmode = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test $linkmode = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case "$libdir" in + [\/]*) + add_dir="-L$inst_prefix_dir$libdir $add_dir" + ;; + esac + fi + add="-l$name" + fi + + if test $linkmode = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test $linkmode = prog; then + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + + # Try to link the static library + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + echo "*** Warning: This system can not link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + convenience="$convenience $dir/$old_library" + old_convenience="$old_convenience $dir/$old_library" + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test $linkmode = lib; then + if test -n "$dependency_libs" && + { test $hardcode_into_libs != yes || test $build_old_libs = yes || + test $link_static = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test $link_all_deplibs != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$deplib" && dir="." + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + fi + ;; + esac + if grep "^installed=no" $deplib > /dev/null; then + path="-L$absdir/$objdir" + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit 1 + fi + if test "$absdir" != "$libdir"; then + $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 + fi + path="-L$absdir" + fi + ;; + *) continue ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$deplibs $path" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test $pass = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test $pass != dlopen; then + test $pass != scan && dependency_libs="$newdependency_libs" + if test $pass != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + *) + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + if test "$pass" = "conv" && + { test "$linkmode" = "lib" || test "$linkmode" = "prog"; }; then + libs="$deplibs" # reset libs + deplibs= + fi + done # for pass + if test $linkmode = prog; then + dlfiles="$newdlfiles" + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 + exit 1 + else + echo + echo "*** Warning: Linking the shared library $output against the non-libtool" + echo "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + if test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test $# -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + libext=al + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + current="$2" + revision="$3" + age="$4" + + # Check that each of the things are valid numbers. + case $current in + 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; + *) + $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case $revision in + 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; + *) + $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case $age in + 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; + *) + $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + if test $age -gt $current; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + minor_current=`expr $current + 1` + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + irix | nonstopux) + major=`expr $current - $age + 1` + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test $loop != 0; do + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=.`expr $current - $age` + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test $loop != 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + major=`expr $current - $age` + versuffix="-$major" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + verstring="0.0" + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring="" + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + fi + + if test "$mode" != relink; then + # Remove our outputs. + $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*" + $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.* + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + for path in $notinst_path; do + lib_search_path=`echo "$lib_search_path " | ${SED} -e 's% $path % %g'` + deplibs=`echo "$deplibs " | ${SED} -e 's% -L$path % %g'` + dependency_libs=`echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'` + done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test $hardcode_into_libs != yes || test $build_old_libs = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs -framework System" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd*) + # Do not include libc due to us having libc/libc_r. + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test $build_libtool_need_lc = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behaviour. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $rm conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null \ + | grep " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | ${SED} 10q \ + | egrep "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + echo "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + echo "*** with $libname but no candidates were found. (...for file magic test)" + else + echo "*** with $libname and none of the candidates passed a file format test" + echo "*** using a file magic. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name="`expr $a_deplib : '-l\(.*\)'`" + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + libname=`eval \\$echo \"$libname_spec\"` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check below in file_magic test + if eval echo \"$potent_lib\" 2>/dev/null \ + | ${SED} 10q \ + | egrep "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + echo "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + echo "*** with $libname but no candidates were found. (...for regex pattern test)" + else + echo "*** with $libname and none of the candidates passed a file format test" + echo "*** using a regex pattern. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' | + grep . >/dev/null; then + echo + if test "X$deplibs_check_method" = "Xnone"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + echo "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test $allow_undefined = no; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test $hardcode_into_libs = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + test -z "$dlname" && dlname=$soname + + lib="$output_objdir/$realname" + for link + do + linknames="$linknames $link" + done + + # Ensure that we have .o objects for linkers which dislike .lo + # (e.g. aix) in case we are running --disable-static + for obj in $libobjs; do + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` + if test ! -f $xdir/$oldobj; then + $show "(cd $xdir && ${LN_S} $baseobj $oldobj)" + $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $? + fi + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + eval cmds=\"$export_symbols_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + for xlib in $convenience; do + # Extract the objects. + case $xlib in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` + done + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval cmds=\"$archive_expsym_cmds\" + else + save_deplibs="$deplibs" + for conv in $convenience; do + tmp_deplibs= + for test_deplib in $deplibs; do + if test "$test_deplib" != "$conv"; then + tmp_deplibs="$tmp_deplibs $test_deplib" + fi + done + deplibs="$tmp_deplibs" + done + eval cmds=\"$archive_cmds\" + deplibs="$save_deplibs" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? + exit 0 + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case $output in + *.lo) + if test -n "$objs$old_deplibs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit 1 + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + for xlib in $convenience; do + # Extract the objects. + case $xlib in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` + done + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + eval cmds=\"$reload_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit 0 + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + $show "echo timestamp > $libobj" + $run eval "echo timestamp > $libobj" || exit $? + exit 0 + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + eval cmds=\"$reload_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + else + # Just create a symlink. + $show $rm $libobj + $run $rm $libobj + xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$libobj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` + oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` + $show "(cd $xdir && $LN_S $oldobj $baseobj)" + $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $? + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit 0 + ;; + + prog) + case $host in + *cygwin*) output=`echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; + esac + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + case $host in + *darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + ;; + esac + ;; + esac + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + case :$dllsearchpath: in + *":$libdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case $dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$output.exp" + $run $rm $export_symbols + $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + else + $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' + $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`echo "$arg" | ${SED} -e 's%^.*/%%'` + $run eval 'echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if grep -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + grep -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr void * +#else +# define lt_ptr char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr address; +} +lt_preloaded_symbols[] = +{\ +" + + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DPIC";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit 1 + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test $need_relink = no || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $run $rm $output + # Link the executable and exit + $show "$link_command" + $run eval "$link_command" || exit $? + exit 0 + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $0 --fallback-echo"; then + case $0 in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; + *) qecho="$SHELL `pwd`/$0 --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`echo $output|${SED} 's,.exe$,,'` ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) exeext=.exe ;; + *) exeext= ;; + esac + $rm $output + trap "$rm $output; exit 1" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variable: + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + echo >> $output "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $mkdir \"\$progdir\" + else + $rm \"\$progdir/\$file\" + fi" + + echo >> $output "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $echo \"\$relink_command_output\" >&2 + $rm \"\$progdir/\$file\" + exit 1 + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + echo >> $output "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 ${SED} + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # win32 systems need to use the prog path for dll + # lookup to work + *-*-cygwin* | *-*-pw32*) + $echo >> $output "\ + exec \$progdir/\$program \${1+\"\$@\"} +" + ;; + + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2*) + $echo >> $output "\ + exec \$progdir\\\\\$program \${1+\"\$@\"} +" + ;; + + *) + $echo >> $output "\ + # Export the path to the program. + PATH=\"\$progdir:\$PATH\" + export PATH + + exec \$program \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit 1 + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" + chmod +x $output + fi + exit 0 + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$objs$old_deplibs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP` + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + # Add in members from convenience archives. + for xlib in $addlibs; do + # Extract the objects. + case $xlib in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` + done + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + eval cmds=\"$old_archive_from_new_cmds\" + else + # Ensure that we have .o objects in place in case we decided + # not to build a shared library, and have fallen back to building + # static libs even though --disable-static was passed! + for oldobj in $oldobjs; do + if test ! -f $oldobj; then + xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$oldobj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'` + obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` + $show "(cd $xdir && ${LN_S} $obj $baseobj)" + $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $? + fi + done + + eval cmds=\"$old_archive_cmds\" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + + # Only create the output if not a dry run. + if test -z "$run"; then + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit 1 + fi + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + for lib in $dlfiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit 1 + fi + newdlfiles="$newdlfiles $libdir/$name" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit 1 + fi + newdlprefiles="$newdlprefiles $libdir/$name" + done + dlprefiles="$newdlprefiles" + fi + $rm $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test $need_relink = yes; then + $echo >> $output "\ +relink_command=\"$relink_command\"" + fi + done + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? + ;; + esac + exit 0 + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg="$nonopt" + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest="$arg" + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) prev="-f" ;; + -g) prev="-g" ;; + -m) prev="-m" ;; + -o) prev="-o" ;; + -s) + stripme=" -s" + continue + ;; + -*) ;; + + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest="$arg" + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit 1 + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test $# -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + library_names= + old_library= + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$echo "$destdir" | sed "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + if test "$inst_prefix_dir" = "$destdir"; then + $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 + exit 1 + fi + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$echo "$relink_command" | sed "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$echo "$relink_command" | sed "s%@inst_prefix_dir@%%"` + fi + + $echo "$modename: warning: relinking \`$file'" 1>&2 + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + exit 1 + fi + fi + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$srcname $destdir/$realname" + $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? + if test -n "$stripme" && test -n "$striplib"; then + $show "$striplib $destdir/$realname" + $run eval "$striplib $destdir/$realname" || exit $? + fi + + if test $# -gt 0; then + # Delete the old symlinks, and create new ones. + for linkname + do + if test "$linkname" != "$realname"; then + $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + eval cmds=\"$postinstall_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit 0 + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin*|*mingw*) + wrapper=`echo $file | ${SED} -e 's,.exe$,,'` + ;; + *) + wrapper=$file + ;; + esac + if (${SED} -e '4q' $wrapper | egrep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then + notinst_deplibs= + relink_command= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $wrapper ;; + *) . ./$wrapper ;; + esac + + # Check the variables that should have been set. + if test -z "$notinst_deplibs"; then + $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 + exit 1 + fi + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $wrapper ;; + *) . ./$wrapper ;; + esac + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir="/tmp" + test -n "$TMPDIR" && tmpdir="$TMPDIR" + tmpdir="$tmpdir/libtool-$$" + if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : + else + $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 + continue + fi + file=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyways + case $install_prog,$host in + /usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + destfile=`echo $destfile | ${SED} -e 's,.exe$,,'` + ;; + esac + ;; + esac + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + if test -n "$stripme" && test -n "$striplib"; then + $show "$old_striplib $oldlib" + $run eval "$old_striplib $oldlib" || exit $? + fi + + # Do each command in the postinstall commands. + eval cmds=\"$old_postinstall_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $0 --finish$current_libdirs' + else + exit 0 + fi + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + eval cmds=\"$finish_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = ":" && exit 0 + + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + echo " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + echo " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + echo " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + echo "See any operating system documentation about shared libraries for" + echo "more information, such as the ld(1) and ld.so(8) manual pages." + echo "----------------------------------------------------------------------" + exit 0 + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit 1 + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit 1 + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (${SED} -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved enviroment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + fi + $echo "$cmd$args" + exit 0 + fi + ;; + + # libtool clean and uninstall mode + clean | uninstall) + modename="$modename: $mode" + rm="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) rm="$rm $arg"; rmforce=yes ;; + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + rmdirs= + + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$file"; then + dir=. + objdir="$objdir" + else + objdir="$dir/$objdir" + fi + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + test $mode = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test $mode = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if (test -L "$file") >/dev/null 2>&1 \ + || (test -h "$file") >/dev/null 2>&1 \ + || test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + test $mode = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + + if test $mode = uninstall; then + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + eval cmds=\"$postuninstall_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + if test $? != 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + eval cmds=\"$old_postuninstall_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + if test $? != 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + # FIXME: should reinstall the best remaining shared library. + fi + fi + ;; + + *.lo) + if test "$build_old_libs" = yes; then + oldobj=`$echo "X$name" | $Xsed -e "$lo2o"` + rmfiles="$rmfiles $dir/$oldobj" + fi + ;; + + *) + # Do a test to see if this is a libtool program. + if test $mode = clean && + (${SED} -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + relink_command= + . $dir/$file + + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + fi + ;; + esac + $show "$rm $rmfiles" + $run $rm $rmfiles || exit_status=1 + done + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + $show "rmdir $dir" + $run rmdir $dir >/dev/null 2>&1 + fi + done + + exit $exit_status + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 + ;; + esac + + if test -z "$exec_cmd"; then + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 + fi +fi # test -z "$show_help" + +if test -n "$exec_cmd"; then + eval exec $exec_cmd + exit 1 +fi + +# We need to display help for each of the modes. +case $mode in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + + --config show all configuration variables + --debug enable verbose shell tracing +-n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --version print version information + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE." + exit 0 + ;; + +clean) + $echo \ +"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -static always build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + +uninstall) + $echo \ +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; +esac + +echo +$echo "Try \`$modename --help' for more information about other modes." + +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/configure.ac b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/configure.ac new file mode 100644 index 0000000..0c51259 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/configure.ac @@ -0,0 +1,445 @@ +define(pkg_major, 1) +define(pkg_minor, 3) +define(pkg_extra, -rc1) +define(pkg_maintainer, libunwind-devel@nongnu.org) +define(mkvers, $1.$2$3) +dnl Process this file with autoconf to produce a configure script. +AC_INIT([libunwind],[mkvers(pkg_major, pkg_minor, pkg_extra)],[pkg_maintainer]) +AC_CONFIG_SRCDIR(src/mi/backtrace.c) +AC_CONFIG_AUX_DIR(config) +AC_CANONICAL_TARGET +AM_INIT_AUTOMAKE([1.6 subdir-objects]) +AM_MAINTAINER_MODE +AC_CONFIG_HEADERS([include/config.h]) + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CXX +AC_PROG_INSTALL +AC_PROG_MAKE_SET +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) +LT_INIT +AM_PROG_AS +AM_PROG_CC_C_O + +dnl Checks for libraries. +AC_CHECK_LIB(uca, __uc_get_grs) +OLD_LIBS=${LIBS} +AC_SEARCH_LIBS(dlopen, dl) +LIBS=${OLD_LIBS} +case "$ac_cv_search_dlopen" in + -l*) DLLIB=$ac_cv_search_dlopen;; + *) DLLIB="";; +esac + +CHECK_ATOMIC_OPS + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(asm/ptrace_offsets.h endian.h sys/endian.h execinfo.h \ + ia64intrin.h sys/uc_access.h unistd.h signal.h sys/types.h \ + sys/procfs.h sys/ptrace.h byteswap.h elf.h sys/elf.h link.h sys/link.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +AC_TYPE_SIZE_T +AC_CHECK_SIZEOF(off_t) + +CPPFLAGS="${CPPFLAGS} -D_GNU_SOURCE" + +AC_CHECK_MEMBERS([struct dl_phdr_info.dlpi_subs],,,[#include ]) +AC_CHECK_TYPES([struct elf_prstatus, struct prstatus], [], [], +[$ac_includes_default +#if HAVE_SYS_PROCFS_H +# include +#endif +]) + +AC_CHECK_DECLS([PTRACE_POKEUSER, PTRACE_POKEDATA, PTRACE_SETREGSET, +PTRACE_TRACEME, PTRACE_CONT, PTRACE_SINGLESTEP, +PTRACE_SYSCALL, PT_IO, PT_GETREGS, +PT_GETFPREGS, PT_CONTINUE, PT_TRACE_ME, +PT_STEP, PT_SYSCALL], [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) + +dnl Checks for library functions. +AC_CHECK_FUNCS(dl_iterate_phdr dl_phdr_removals_counter dlmodinfo getunwind \ + ttrace mincore) + +AC_MSG_CHECKING([if building with AltiVec]) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ +#ifndef __ALTIVEC__ +# error choke +#endif +]])], [use_altivec=yes],[use_altivec=no]) +AM_CONDITIONAL(USE_ALTIVEC, [test x$use_altivec = xyes]) +AC_MSG_RESULT([$use_altivec]) + +AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ +#ifndef __powerpc64__ +# error choke +#endif +]])], [ppc_bits=64], [ppc_bits=32]) + +AC_DEFUN([SET_ARCH],[ + AS_CASE([$1], + [aarch64*],[$2=aarch64], + [arm*],[$2=arm], + [i?86],[$2=x86], + [hppa*],[$2=hppa], + [mips*],[$2=mips], + [powerpc*],[$2=ppc$ppc_bits], + [sh*],[$2=sh], + [amd64],[$2=x86_64], + [tile*],[$2=tilegx], + [$2=$1]) +]) dnl SET_ARCH + +SET_ARCH([$build_cpu],[build_arch]) +SET_ARCH([$host_cpu],[host_arch]) +SET_ARCH([$target_cpu],[target_arch]) + +# Check for Android +AC_MSG_CHECKING([for Android]) +android="no" +case "$host_os" in + *android*) + android="yes" + AC_MSG_RESULT([yes]) + ;; + *) + AC_MSG_RESULT([no]) + ;; +esac + +AC_ARG_ENABLE(coredump, + AS_HELP_STRING([--enable-coredump],[building libunwind-coredump library]),, + [AS_CASE([$host_arch], [aarch64*|arm*|mips*|sh*|x86*|tile*], [enable_coredump=yes], [enable_coredump=no])] +) + +AC_MSG_CHECKING([if we should build libunwind-coredump]) +AC_MSG_RESULT([$enable_coredump]) + +AC_ARG_ENABLE(ptrace, + AS_HELP_STRING([--enable-ptrace],[building libunwind-ptrace library]),, + [AC_CHECK_HEADER([sys/ptrace.h], [enable_ptrace=yes], [enable_ptrace=no])] +) + +AC_MSG_CHECKING([if we should build libunwind-ptrace]) +AC_MSG_RESULT([$enable_ptrace]) + +AC_ARG_ENABLE(setjmp, + AS_HELP_STRING([--enable-setjmp],[building libunwind-setjmp library]),, + [AS_IF([test x$target_arch == x$host_arch], [enable_setjmp=yes], [enable_setjmp=no])] +) + +AC_ARG_ENABLE(documentation, + AS_HELP_STRING([--disable-documentation],[Disable generating the man pages]),, + [enable_documentation=yes]) + +AC_ARG_ENABLE(tests, + AS_HELP_STRING([--disable-tests],[Disable tests build]),, + [enable_tests=yes]) + +AC_MSG_CHECKING([if we should build libunwind-setjmp]) +AC_MSG_RESULT([$enable_setjmp]) + +AC_MSG_CHECKING([for build architecture]) +AC_MSG_RESULT([$build_arch]) +AC_MSG_CHECKING([for host architecture]) +AC_MSG_RESULT([$host_arch]) +AC_MSG_CHECKING([for target architecture]) +AC_MSG_RESULT([$target_arch]) +AC_MSG_CHECKING([for target operating system]) +AC_MSG_RESULT([$target_os]) + +AM_CONDITIONAL(BUILD_COREDUMP, test x$enable_coredump = xyes) +AM_CONDITIONAL(BUILD_PTRACE, test x$enable_ptrace = xyes) +AM_CONDITIONAL(BUILD_SETJMP, test x$enable_setjmp = xyes) +AM_CONDITIONAL(NO_PTRACE_TEST, test x$build_arch != x$host_arch) +AM_CONDITIONAL(REMOTE_ONLY, test x$target_arch != x$host_arch) +AM_CONDITIONAL(ARCH_AARCH64, test x$target_arch = xaarch64) +AM_CONDITIONAL(ARCH_ARM, test x$target_arch = xarm) +AM_CONDITIONAL(ARCH_IA64, test x$target_arch = xia64) +AM_CONDITIONAL(ARCH_HPPA, test x$target_arch = xhppa) +AM_CONDITIONAL(ARCH_MIPS, test x$target_arch = xmips) +AM_CONDITIONAL(ARCH_X86, test x$target_arch = xx86) +AM_CONDITIONAL(ARCH_X86_64, test x$target_arch = xx86_64) +AM_CONDITIONAL(ARCH_PPC32, test x$target_arch = xppc32) +AM_CONDITIONAL(ARCH_PPC64, test x$target_arch = xppc64) +AM_CONDITIONAL(ARCH_SH, test x$target_arch = xsh) +AM_CONDITIONAL(ARCH_TILEGX, test x$target_arch = xtilegx) +AM_CONDITIONAL(OS_LINUX, expr x$target_os : xlinux >/dev/null) +AM_CONDITIONAL(OS_HPUX, expr x$target_os : xhpux >/dev/null) +AM_CONDITIONAL(OS_FREEBSD, expr x$target_os : xfreebsd >/dev/null) +AM_CONDITIONAL(OS_QNX, expr x$target_os : xnto-qnx >/dev/null) + +AC_MSG_CHECKING([for ELF helper width]) +case "${target_arch}" in +(arm|hppa|ppc32|x86|sh) use_elf32=yes; AC_MSG_RESULT([32]);; +(aarch64|ia64|ppc64|x86_64|tilegx) use_elf64=yes; AC_MSG_RESULT([64]);; +(mips) use_elfxx=yes; AC_MSG_RESULT([xx]);; +*) AC_MSG_ERROR([Unknown ELF target: ${target_arch}]) +esac +AM_CONDITIONAL(USE_ELF32, [test x$use_elf32 = xyes]) +AM_CONDITIONAL(USE_ELF64, [test x$use_elf64 = xyes]) +AM_CONDITIONAL(USE_ELFXX, [test x$use_elfxx = xyes]) + +AC_MSG_CHECKING([whether to include DWARF support]) +if test x$target_arch != xia64; then + use_dwarf=yes +else + use_dwarf=no +fi +AM_CONDITIONAL(USE_DWARF, [test x$use_dwarf = xyes]) +AC_MSG_RESULT([$use_dwarf]) + +if test x$target_arch = xppc64; then + libdir='${exec_prefix}/lib64' + AC_MSG_NOTICE([PowerPC64 detected, lib will be installed ${libdir}]); + AC_SUBST([libdir]) +fi + +AC_MSG_CHECKING([whether to restrict build to remote support]) +if test x$target_arch != x$host_arch; then + CPPFLAGS="${CPPFLAGS} -DUNW_REMOTE_ONLY" + remote_only=yes +else + remote_only=no +fi +AC_MSG_RESULT([$remote_only]) + +AC_MSG_CHECKING([whether to enable debug support]) +AC_ARG_ENABLE(debug, +AS_HELP_STRING([--enable-debug],[turn on debug support (slows down execution)])) +if test x$enable_debug = xyes; then + CPPFLAGS="${CPPFLAGS} -DDEBUG" +else + CPPFLAGS="${CPPFLAGS} -DNDEBUG" +fi +AC_MSG_RESULT([$enable_debug]) + +AC_MSG_CHECKING([whether to enable C++ exception support]) +AC_ARG_ENABLE(cxx_exceptions, +AS_HELP_STRING([--enable-cxx-exceptions],[use libunwind to handle C++ exceptions]),, +[ +# C++ exception handling doesn't work too well on x86 +case $target_arch in + x86*) enable_cxx_exceptions=no;; + aarch64*) enable_cxx_exceptions=no;; + arm*) enable_cxx_exceptions=no;; + mips*) enable_cxx_exceptions=no;; + tile*) enable_cxx_exceptions=no;; + *) enable_cxx_exceptions=yes;; +esac +]) + +AM_CONDITIONAL([SUPPORT_CXX_EXCEPTIONS], [test x$enable_cxx_exceptions = xyes]) +AC_MSG_RESULT([$enable_cxx_exceptions]) + +AC_MSG_CHECKING([whether to load .debug_frame sections]) +AC_ARG_ENABLE(debug_frame, +AS_HELP_STRING([--enable-debug-frame],[Load the ".debug_frame" section if available]),, [ +case "${target_arch}" in + (arm) enable_debug_frame=yes;; + (aarch64) enable_debug_frame=yes;; + (*) enable_debug_frame=no;; +esac]) +if test x$enable_debug_frame = xyes; then + AC_DEFINE([CONFIG_DEBUG_FRAME], [], [Enable Debug Frame]) +fi +AC_MSG_RESULT([$enable_debug_frame]) + +AC_MSG_CHECKING([whether to block signals during mutex ops]) +AC_ARG_ENABLE(block_signals, +AS_HELP_STRING([--enable-block-signals],[Block signals before performing mutex operations]),, +[enable_block_signals=yes]) +if test x$enable_block_signals = xyes; then + AC_DEFINE([CONFIG_BLOCK_SIGNALS], [], [Block signals before mutex operations]) +fi +AC_MSG_RESULT([$enable_block_signals]) + +AC_MSG_CHECKING([whether to validate memory addresses before use]) +AC_ARG_ENABLE(conservative_checks, +AS_HELP_STRING([--enable-conservative-checks],[Validate all memory addresses before use]),, +[enable_conservative_checks=yes]) +if test x$enable_conservative_checks = xyes; then + AC_DEFINE(CONSERVATIVE_CHECKS, 1, + [Define to 1 if you want every memory access validated]) +fi +AC_MSG_RESULT([$enable_conservative_checks]) + +AC_MSG_CHECKING([whether to enable msabi support]) +AC_ARG_ENABLE(msabi_support, +AS_HELP_STRING([--enable-msabi-support],[Enables support for Microsoft ABI extensions])) +if test x$enable_msabi_support = xyes; then + AC_DEFINE([CONFIG_MSABI_SUPPORT], [], [Support for Microsoft ABI extensions]) +fi +AC_MSG_RESULT([$enable_msabi_support]) + +LIBLZMA= +AC_MSG_CHECKING([whether to support LZMA-compressed symbol tables]) +AC_ARG_ENABLE(minidebuginfo, +AS_HELP_STRING([--enable-minidebuginfo], [Enables support for LZMA-compressed symbol tables]),, [enable_minidebuginfo=auto]) +AC_MSG_RESULT([$enable_minidebuginfo]) +if test x$enable_minidebuginfo != xno; then + AC_CHECK_LIB([lzma], [lzma_mf_is_supported], + [LIBLZMA=-llzma + AC_DEFINE([HAVE_LZMA], [1], [Define if you have liblzma]) + enable_minidebuginfo=yes], + [if test x$enable_minidebuginfo = xyes; then + AC_MSG_FAILURE([liblzma not found]) + fi]) +fi +AC_SUBST([LIBLZMA]) +AM_CONDITIONAL(HAVE_LZMA, test x$enable_minidebuginfo = xyes) + +AC_MSG_CHECKING([whether to support UNW_CACHE_PER_THREAD]) +AC_ARG_ENABLE([per-thread-cache], +AS_HELP_STRING([--enable-per-thread-cache], [build with support for UNW_CACHE_PER_THREAD (which imposes a hight TLS memory usage) (default: disabled)])) +AC_MSG_RESULT([$enable_per_thread_cache]) +AS_IF([test x$enable_per_thread_cache = xyes], [ + LIBUNWIND___THREAD + AS_IF([test x$libc_cv_gcc___thread = xno], [ + AC_MSG_FAILURE([UNW_CACHE_PER_THREAD requires __thread]) + ]) +]) + +AC_MSG_CHECKING([for Intel compiler]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[#ifndef __INTEL_COMPILER +#error choke me +#endif]])],[intel_compiler=yes],[intel_compiler=no]) + +if test x$GCC = xyes -a x$intel_compiler != xyes; then + CFLAGS="${CFLAGS} -fexceptions -Wall -Wsign-compare" +fi +AC_MSG_RESULT([$intel_compiler]) + +AC_MSG_CHECKING([for QCC compiler]) +AS_CASE([$CC], [qcc*|QCC*], [qcc_compiler=yes], [qcc_compiler=no]) +AC_MSG_RESULT([$qcc_compiler]) + +if test x$intel_compiler = xyes; then + AC_MSG_CHECKING([if linker supports -static-libcxa]) + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -static-libcxa" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[have_static_libcxa=yes],[have_static_libcxa=no]) + LDFLAGS="$save_LDFLAGS" + if test "x$have_static_libcxa" = xyes; then + LDFLAGS_STATIC_LIBCXA="-XCClinker -static-libcxa" + fi + AC_MSG_RESULT([$have_static_libcxa]) +fi + +if test x$qcc_compiler = xyes; then + LDFLAGS_NOSTARTFILES="-XCClinker -Wc,-nostartfiles" +else + LDFLAGS_NOSTARTFILES="-XCClinker -nostartfiles" +fi + +if test x$GCC = xyes -a x$intel_compiler != xyes -a x$qcc_compiler != xyes -a x$android != xyes; then + LIBCRTS="-lgcc_s" +fi + +AC_MSG_CHECKING([for __builtin___clear_cache]) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[]], [[__builtin___clear_cache(0, 0)]])], + [have__builtin___clear_cache=yes], + [have__builtin___clear_cache=no]) +if test x$have__builtin___clear_cache = xyes; then + AC_DEFINE([HAVE__BUILTIN___CLEAR_CACHE], [1], + [Defined if __builtin___clear_cache() is available]) +fi +AC_MSG_RESULT([$have__builtin___clear_cache]) + +AC_MSG_CHECKING([for __builtin_unreachable]) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[]], [[__builtin_unreachable()]])], + [have__builtin_unreachable=yes], + [have__builtin_unreachable=no]) +if test x$have__builtin_unreachable = xyes; then + AC_DEFINE([HAVE__BUILTIN_UNREACHABLE], [1], + [Defined if __builtin_unreachable() is available]) +fi +AC_MSG_RESULT([$have__builtin_unreachable]) + +AC_MSG_CHECKING([for __sync atomics]) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[]], [[ + __sync_bool_compare_and_swap((int *)0, 0, 1); + __sync_fetch_and_add((int *)0, 1); + ]])], + [have_sync_atomics=yes], + [have_sync_atomics=no]) +if test x$have_sync_atomics = xyes; then + AC_DEFINE([HAVE_SYNC_ATOMICS], [1], + [Defined if __sync atomics are available]) +fi +AC_MSG_RESULT([$have_sync_atomics]) + +CCASFLAGS="${CCASFLAGS} ${CPPFLAGS}" + +arch="$target_arch" +ARCH=`echo $target_arch | tr [a-z] [A-Z]` + +dnl create shell variables from the M4 macros: +PKG_MAJOR=pkg_major +PKG_MINOR=pkg_minor +PKG_EXTRA=pkg_extra +PKG_MAINTAINER=pkg_maintainer + +old_LIBS="$LIBS" +LIBS="" +AC_SEARCH_LIBS(backtrace, execinfo) +LIBS="$old_LIBS" +case "$ac_cv_search_backtrace" in + -l*) BACKTRACELIB=$ac_cv_search_backtrace;; + *) BACKTRACELIB="";; +esac + + +AC_SUBST(build_arch) +AC_SUBST(target_os) +AC_SUBST(arch) +AC_SUBST(ARCH) +AC_SUBST(LDFLAGS_STATIC_LIBCXA) +AC_SUBST(LDFLAGS_NOSTARTFILES) +AC_SUBST(LIBCRTS) +AC_SUBST(PKG_MAJOR) +AC_SUBST(PKG_MINOR) +AC_SUBST(PKG_EXTRA) +AC_SUBST(PKG_MAINTAINER) +AC_SUBST(enable_cxx_exceptions) +AC_SUBST(enable_debug_frame) +AC_SUBST(DLLIB) +AC_SUBST(BACKTRACELIB) + +AC_PATH_PROG([LATEX2MAN],[latex2man]) +if test "x$LATEX2MAN" = "x"; then + AC_MSG_WARN([latex2man not found. Install latex2man. Disabling docs.]) + enable_documentation="no"; +fi + +AM_CONDITIONAL([CONFIG_DOCS], [test x$enable_documentation = xyes]) +if test "x$enable_documentation" = "xyes"; then + AC_CONFIG_FILES(doc/Makefile doc/common.tex) +fi + +AM_CONDITIONAL([CONFIG_TESTS], [test x$enable_tests = xyes]) +if test "x$enable_tests" = "xyes"; then + AC_CONFIG_FILES(tests/Makefile tests/check-namespace.sh) +fi + +AC_CONFIG_FILES(Makefile src/Makefile + include/libunwind-common.h + include/libunwind.h include/tdep/libunwind_i.h) +AC_CONFIG_FILES(src/unwind/libunwind.pc src/coredump/libunwind-coredump.pc + src/ptrace/libunwind-ptrace.pc src/setjmp/libunwind-setjmp.pc + src/libunwind-generic.pc) +AC_OUTPUT diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/Makefile.am b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/Makefile.am new file mode 100644 index 0000000..bfe4669 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/Makefile.am @@ -0,0 +1,80 @@ +# man pages that go into section 3: +man3_MANS = libunwind.man libunwind-dynamic.man libunwind-ia64.man \ + libunwind-ptrace.man libunwind-setjmp.man \ + unw_apply_reg_state.man \ + unw_backtrace.man \ + unw_flush_cache.man \ + unw_get_accessors.man \ + unw_get_proc_info.man \ + unw_get_proc_info_by_ip.man \ + unw_get_proc_name.man \ + unw_get_fpreg.man \ + unw_get_reg.man \ + unw_getcontext.man \ + unw_init_local.man unw_init_remote.man \ + unw_init_local2.man \ + unw_is_fpreg.man \ + unw_is_signal_frame.man \ + unw_create_addr_space.man \ + unw_destroy_addr_space.man \ + unw_regname.man unw_resume.man \ + unw_reg_states_iterate.man \ + unw_set_caching_policy.man \ + unw_set_cache_size.man \ + unw_set_fpreg.man \ + unw_set_reg.man \ + unw_step.man \ + unw_strerror.man \ + _U_dyn_register.man \ + _U_dyn_cancel.man + +EXTRA_DIST = NOTES libunwind.trans \ + libunwind.tex libunwind-dynamic.tex libunwind-ia64.tex \ + libunwind-ptrace.tex libunwind-setjmp.tex \ + unw_apply_reg_state.tex \ + unw_backtrace.tex \ + unw_flush_cache.tex \ + unw_get_accessors.tex \ + unw_get_proc_info.tex \ + unw_get_proc_info_by_ip.tex \ + unw_get_proc_name.tex \ + unw_get_fpreg.tex \ + unw_get_reg.tex \ + unw_getcontext.tex \ + unw_init_local.tex unw_init_remote.tex \ + unw_is_fpreg.tex \ + unw_is_signal_frame.tex \ + unw_create_addr_space.tex unw_destroy_addr_space.tex \ + unw_regname.tex unw_resume.tex unw_set_caching_policy.tex \ + unw_reg_states_iterate.tex \ + unw_set_cache_size.tex \ + unw_set_fpreg.tex \ + unw_set_reg.tex \ + unw_step.tex \ + unw_strerror.tex \ + _U_dyn_register.tex \ + _U_dyn_cancel.tex \ + $(man3_MANS) + +L2M = latex2man +L2P = pdflatex +L2M_CMD = $(L2M) -t $(srcdir)/libunwind.trans +L2H_CMD = $(L2M) -H -t $(srcdir)/libunwind.trans + +.tex.man: + $(L2M_CMD) $< $@ + -cp $@ $(srcdir)/$@ + +html: + for n in $(man3_MANS); do \ + page=`basename $$n .man`; \ + $(L2H_CMD) $(srcdir)/$$page.tex "$$page(3).raw"; \ + done + +pdf: + for n in $(man3_MANS); do \ + page=`basename $$n .man`; \ + $(L2P) $(srcdir)/$$page.tex "$$page(3).pdf"; \ + done + +MAINTAINERCLEANFILES = Makefile.in diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/NOTES b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/NOTES new file mode 100644 index 0000000..3f3caa9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/NOTES @@ -0,0 +1,127 @@ +The central data structure of the unwind API is the unwind cursor. +This structure tracks the register contents. The unwind API defines a +handful of well-known frame "registers": + + - ip: the instruction pointer (pc) + - rp: the return pointer (rp, aka "return address" or "return link") + - sp: the stack pointer (memory stack pointer, in the case of ia64) + - fp: the frame pointer + - first_ip: the starting address of the current "procedure" + - handler: a pointer to an architecture & language-specific + "personality" routine + - lsda: a pointer to an architecture & language-specific + data-area + +The API defines no well-known preserved registers. Each architecture +can define additional registers as needed. Of course, a portable +application may only rely on well-known registers. The names for +preserved registers are defined in the architecture-specific header +file . For example, to get the IA-64-specific register +names, an application would do: + + #include + +The API is designed to handle two primary cases: unwinding within the +current (local) process and unwinding of another ("remote") process +(e.g., through ptrace()). In the local case, the initial machine +state is captured by an unwind context (currently the same as +ucontext_t). In the remote case, the initial machine state is +captured by an unwind accessor structure, which provides callback +routines for reading/writing memory and registers and for obtaining +unwind information. + +Once a cursor has been initialized, you can step through the call +chain with the unw_step() routine. The frame registers and the +preserved state can then be accessed with unw_get_reg() or modified +with unw_set_reg(). For floating-point registers, there are separate +unw_get_fpreg() and unw_set_fpreg() routines (on some arches, e.g., +Alpha, these could be just aliases for unw_{g,s}et_reg()). The +unw_resume() routine can be used to resume execution at an arbitrary +point in the call-chain (as identified by an unwind cursor). This is +intended for exception handling and, at least for now, the intention +is to support this routine only for the local case. Kevin, if you +feel gdb could benefit from such a routine, I'd be interested to hear +about it. + +Note that it is perfectly legal to make copies of the unwind cursor. +This makes it possible, e.g., to obtain an unwind context, modify the +state in an earlier call frame, and then resume execution at the point +at which the unwind context was captured. + +Here is a quick example of how to use the unwind API to do a simple +stack trace: + + unw_cursor_t cursor; + unw_word_t ip, sp; + unw_context_t uc; + + unw_getcontext(&uc); + unw_init_local(&cursor, &uc); + do + { + unw_get_reg(&cursor, UNW_REG_IP, &ip); + unw_get_reg(&cursor, UNW_REG_SP, &sp); + printf ("ip=%016lx sp=%016lx\n", ip, sp); + } + while (unw_step (&cursor) > 0); + +Note that this particular example should work on pretty much any +architecture, as it doesn't rely on any arch-specific registers. + +* Multiarchitecture support + +If libunwind is configured for a target other than the local (native) +host, the library is installed as libunwind-$ARCH, where $ARCH is +the target architecture name (e.g., ia32, ia64, or alpha). Similarly, +the header file is installed as libunwind-$ARCH. + +With this setup, an application should: + + - include , and + - link against -lunwind + +if the application needs to use the unwinder of the host. An +application wanting to use the unwinder for a different target (e.g., +a cross-debugger) should: + + - include , and + - link against -lunwind-$ARCH + +The global symbols exported by -lunwind-$ARCH are unique such that the +same application can be linked against the separate unwind libraries +of multiple targets. However, a single compilation unit can include +the header file for only one target. For example, foo.c might include + and bar.c might include and the +entire application would have to be linked against both -lunwind and +-lunwind-ia64. + +Note: the unwind header files of all targets have a common dependency +on libunwind-common.h. To avoid version conflicts, it is necessary to +ensure that the unwind libraries for all targets were derived from the +same release of libunwind. That is, if the unwind library for one +target is upgraded to a newer version, the libraries for all other +targets also need to be upgraded. + +Note 2: The assumption is that a cross-unwinder can handle all +interesting flavors of a target. For example, the unwinder for the +ia64 target is expected to be able to handle both Linux and HP-UX. + +* IA-64 Specific Information + +Apart from the normal frame-registers, the IA-64 implementation of +libunwind provides the means to access the current value of the +register backing store pointer (bsp). One quirk with this +frame-register is that it corresponds to the address that would be in +register ar.bsp after flushing the current register stack to the +backing store (i.e., as if a "flushrs" instruction had been executed). +Of course, given this value and the contents of the current frame +marker (CFM), it's easy to calculate the original value of ar.bsp: + + unw_word_t cfm, bsp, bsp_after_flushrs, sof; + + unw_get_reg (&cursor, UNW_IA64_BSP, &bsp_after_flushrs); + unw_get_reg (&cursor, UNW_IA64_CFM, &cfm); + bsp = ia64_rse_skip_regs (bsp_after_flushrs, -(cfm & 0x7f)); + +** Dynamic Unwind Info + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_cancel.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_cancel.man new file mode 100644 index 0000000..a420a6d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_cancel.man @@ -0,0 +1,66 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "\\_U\\_DYN\\_CANCEL" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +_U_dyn_cancel +\-\- cancel unwind\-info for dynamically generated code +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +void +_U_dyn_cancel(unw_dyn_info_t *di); +.br +.PP +.SH DESCRIPTION + +.PP +The _U_dyn_cancel() +routine cancels the registration of the +unwind\-info for a dynamically generated procedure. Argument di +is the pointer to the unw_dyn_info_t +structure that +describes the procedure\&'s unwind\-info. +.PP +The _U_dyn_cancel() +routine is guaranteed to execute in +constant time (in the absence of contention from concurrent calls to +_U_dyn_register() +or _U_dyn_cancel()). +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +_U_dyn_cancel() +is thread\-safe but \fInot\fP +safe to use +from a signal handler. +.PP +.SH SEE ALSO + +.PP +libunwind\-dynamic(3), +_U_dyn_register(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_cancel.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_cancel.tex new file mode 100644 index 0000000..ca5a12a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_cancel.tex @@ -0,0 +1,46 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{\_U\_dyn\_cancel}{David Mosberger-Tang}{Programming Library}{\_U\_dyn\_cancel}\_U\_dyn\_cancel -- cancel unwind-info for dynamically generated code +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{void} \Func{\_U\_dyn\_cancel}(\Type{unw\_dyn\_info\_t~*}\Var{di});\\ + +\section{Description} + +The \Func{\_U\_dyn\_cancel}() routine cancels the registration of the +unwind-info for a dynamically generated procedure. Argument \Var{di} +is the pointer to the \Type{unw\_dyn\_info\_t} structure that +describes the procedure's unwind-info. + +The \Func{\_U\_dyn\_cancel}() routine is guaranteed to execute in +constant time (in the absence of contention from concurrent calls to +\Func{\_U\_dyn\_register}() or \Func{\_U\_dyn\_cancel}()). + + +\section{Thread and Signal Safety} + +\Func{\_U\_dyn\_cancel}() is thread-safe but \emph{not} safe to use +from a signal handler. + +\section{See Also} + +\SeeAlso{libunwind-dynamic(3)}, \SeeAlso{\_U\_dyn\_register(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_register.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_register.man new file mode 100644 index 0000000..107e5fd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_register.man @@ -0,0 +1,68 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "\\_U\\_DYN\\_REGISTER" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +_U_dyn_register +\-\- register unwind\-info for dynamically generated code +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +void +_U_dyn_register(unw_dyn_info_t *di); +.br +.PP +.SH DESCRIPTION + +.PP +The _U_dyn_register() +routine registers unwind\-info for a +dynamically generated procedure. The procedure\&'s unwind\-info is +described by a structure of type unw_dyn_info_t +(see +libunwind\-dynamic(3)). +A pointer to this structure is +passed in argument di\&. +.PP +The _U_dyn_register() +routine is guaranteed to execute in +constant time (in the absence of contention from concurrent calls to +_U_dyn_register() +or _U_dyn_cancel()). +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +_U_dyn_register() +is thread\-safe but \fInot\fP +safe to use +from a signal handler. +.PP +.SH SEE ALSO + +.PP +libunwind\-dynamic(3), +_U_dyn_cancel(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_register.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_register.tex new file mode 100644 index 0000000..ab23b5c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/_U_dyn_register.tex @@ -0,0 +1,47 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{\_U\_dyn\_register}{David Mosberger-Tang}{Programming Library}{\_U\_dyn\_register}\_U\_dyn\_register -- register unwind-info for dynamically generated code +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{void} \Func{\_U\_dyn\_register}(\Type{unw\_dyn\_info\_t~*}\Var{di});\\ + +\section{Description} + +The \Func{\_U\_dyn\_register}() routine registers unwind-info for a +dynamically generated procedure. The procedure's unwind-info is +described by a structure of type \Type{unw\_dyn\_info\_t} (see +\SeeAlso{libunwind-dynamic(3)}). A pointer to this structure is +passed in argument \Var{di}. + +The \Func{\_U\_dyn\_register}() routine is guaranteed to execute in +constant time (in the absence of contention from concurrent calls to +\Func{\_U\_dyn\_register}() or \Func{\_U\_dyn\_cancel}()). + + +\section{Thread and Signal Safety} + +\Func{\_U\_dyn\_register}() is thread-safe but \emph{not} safe to use +from a signal handler. + +\section{See Also} + +\SeeAlso{libunwind-dynamic(3)}, \SeeAlso{\_U\_dyn\_cancel(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/common.tex.in b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/common.tex.in new file mode 100644 index 0000000..91c96a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/common.tex.in @@ -0,0 +1,11 @@ +\setVersion{@VERSION@} + +\sloppy + +\newcommand{\Lt}{\symbol{"3C}} +\newcommand{\Gt}{\symbol{"3E}} +\newcommand{\Type}[1]{\File{#1}} % see libunwind.trans +\newcommand{\Func}[1]{\Prog{#1}} % see libunwind.trans +\newcommand{\Var}[1]{\Prog{#1}} % see libunwind.trans +\newcommand{\Const}[1]{\File{#1}} % see libunwind.trans +\newcommand{\SeeAlso}[2]{\File{#1}} % see libunwind.trans diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-dynamic.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-dynamic.man new file mode 100644 index 0000000..7c7507c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-dynamic.man @@ -0,0 +1,538 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "LIBUNWIND\-DYNAMIC" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +libunwind\-dynamic +\-\- libunwind\-support for runtime\-generated code +.PP +.SH INTRODUCTION + +.PP +For libunwind +to do its job, it needs to be able to reconstruct +the \fIframe state\fP +of each frame in a call\-chain. The frame state +describes the subset of the machine\-state that consists of the +\fIframe registers\fP +(typically the instruction\-pointer and the +stack\-pointer) and all callee\-saved registers (preserved registers). +The frame state describes each register either by providing its +current value (for frame registers) or by providing the location at +which the current value is stored (callee\-saved registers). +.PP +For statically generated code, the compiler normally takes care of +emitting \fIunwind\-info\fP +which provides the minimum amount of +information needed to reconstruct the frame\-state for each instruction +in a procedure. For dynamically generated code, the runtime code +generator must use the dynamic unwind\-info interface provided by +libunwind +to supply the equivalent information. This manual +page describes the format of this information in detail. +.PP +For the purpose of this discussion, a \fIprocedure\fP +is defined to +be an arbitrary piece of \fIcontiguous\fP +code. Normally, each +procedure directly corresponds to a function in the source\-language +but this is not strictly required. For example, a runtime +code\-generator could translate a given function into two separate +(discontiguous) procedures: one for frequently\-executed (hot) code and +one for rarely\-executed (cold) code. Similarly, simple +source\-language functions (usually leaf functions) may get translated +into code for which the default unwind\-conventions apply and for such +code, it is not strictly necessary to register dynamic unwind\-info. +.PP +A procedure logically consists of a sequence of \fIregions\fP\&. +Regions are nested in the sense that the frame state at the end of one +region is, by default, assumed to be the frame state for the next +region. Each region is thought of as being divided into a +\fIprologue\fP, +a \fIbody\fP, +and an \fIepilogue\fP\&. +Each of them +can be empty. If non\-empty, the prologue sets up the frame state for +the body. For example, the prologue may need to allocate some space +on the stack and save certain callee\-saved registers. The body +performs the actual work of the procedure but does not change the +frame state in any way. If non\-empty, the epilogue restores the +previous frame state and as such it undoes or cancels the effect of +the prologue. In fact, a single epilogue may undo the effect of the +prologues of several (nested) regions. +.PP +We should point out that even though the prologue, body, and epilogue +are logically separate entities, optimizing code\-generators will +generally interleave instructions from all three entities. For this +reason, the dynamic unwind\-info interface of libunwind +makes no +distinction whatsoever between prologue and body. Similarly, the +exact set of instructions that make up an epilogue is also irrelevant. +The only point in the epilogue that needs to be described explicitly +by the dynamic unwind\-info is the point at which the stack\-pointer +gets restored. The reason this point needs to be described is that +once the stack\-pointer is restored, all values saved in the +deallocated portion of the stack frame become invalid and hence +libunwind +needs to know about it. The portion of the frame +state not saved on the stack is assume to remain valid through the end +of the region. For this reason, there is usually no need to describe +instructions which restore the contents of callee\-saved registers. +.PP +Within a region, each instruction that affects the frame state in some +fashion needs to be described with an operation descriptor. For this +purpose, each instruction in the region is assigned a unique index. +Exactly how this index is derived depends on the architecture. For +example, on RISC and EPIC\-style architecture, instructions have a +fixed size so it\&'s possible to simply number the instructions. In +contrast, most CISC use variable\-length instruction encodings, so it +is usually necessary to use a byte\-offset as the index. Given the +instruction index, the operation descriptor specifies the effect of +the instruction in an abstract manner. For example, it might express +that the instruction stores calle\-saved register r1 +at offset 16 +in the stack frame. +.PP +.SH PROCEDURES + +.PP +A runtime code\-generator registers the dynamic unwind\-info of a +procedure by setting up a structure of type unw_dyn_info_t +and calling _U_dyn_register(), +passing the address of the +structure as the sole argument. The members of the +unw_dyn_info_t +structure are described below: +.TP +void *next + Private to libunwind\&. +Must not be used +by the application. +.TP +void *prev + Private to libunwind\&. +Must not be used +by the application. +.TP +unw_word_t start_ip + The start\-address of the +instructions of the procedure (remember: procedure are defined to be +contiguous pieces of code, so a single code\-range is sufficient). +.TP +unw_word_t end_ip + The end\-address of the +instructions of the procedure (non\-inclusive, that is, +end_ip\-start_ip +is the size of the procedure in +bytes). +.TP +unw_word_t gp + The global\-pointer value in use +for this procedure. The exact meaing of the global\-pointer is +architecture\-specific and on some architecture, it is not used at +all. +.TP +int32_t format + The format of the unwind\-info. +This member can be one of UNW_INFO_FORMAT_DYNAMIC, +UNW_INFO_FORMAT_TABLE, +or +UNW_INFO_FORMAT_REMOTE_TABLE\&. +.TP +union u + This union contains one sub\-member +structure for every possible unwind\-info format: +.RS +.TP +unw_dyn_proc_info_t pi + This member is used +for format UNW_INFO_FORMAT_DYNAMIC\&. +.TP +unw_dyn_table_info_t ti + This member is used +for format UNW_INFO_FORMAT_TABLE\&. +.TP +unw_dyn_remote_table_info_t rti + This member +is used for format UNW_INFO_FORMAT_REMOTE_TABLE\&. +.RE +.RS +.PP +The format of these sub\-members is described in detail below. +.RE +.PP +.SS PROC\-INFO FORMAT +.PP +This is the preferred dynamic unwind\-info format and it is generally +the one used by full\-blown runtime code\-generators. In this format, +the details of a procedure are described by a structure of type +unw_dyn_proc_info_t\&. +This structure contains the following +members: +.PP +.RE +.TP +unw_word_t name_ptr + The address of a +(human\-readable) name of the procedure or 0 if no such name is +available. If non\-zero, The string stored at this address must be +ASCII NUL terminated. For source languages that use name\-mangling +(such as C++ or Java) the string stored at this address should be +the \fIdemangled\fP +version of the name. +.PP +.TP +unw_word_t handler + The address of the +personality\-routine for this procedure. Personality\-routines are +used in conjunction with exception handling. See the C++ ABI draft +(http://www.codesourcery.com/cxx\-abi/) for an overview and a +description of the personality routine. If the procedure has no +personality routine, handler +must be set to 0. +.PP +.TP +uint32_t flags + A bitmask of flags. At the +moment, no flags have been defined and this member must be +set to 0. +.PP +.TP +unw_dyn_region_info_t *regions + A NULL\-terminated +linked list of region\-descriptors. See section ``Region +descriptors\&'' below for more details. +.PP +.SS TABLE\-INFO FORMAT +.PP +This format is generally used when the dynamically generated code was +derived from static code and the unwind\-info for the dynamic and the +static versions is identical. For example, this format can be useful +when loading statically\-generated code into an address\-space in a +non\-standard fashion (i.e., through some means other than +dlopen()). +In this format, the details of a group of procedures +is described by a structure of type unw_dyn_table_info\&. +This structure contains the following members: +.PP +.TP +unw_word_t name_ptr + The address of a +(human\-readable) name of the procedure or 0 if no such name is +available. If non\-zero, The string stored at this address must be +ASCII NUL terminated. For source languages that use name\-mangling +(such as C++ or Java) the string stored at this address should be +the \fIdemangled\fP +version of the name. +.PP +.TP +unw_word_t segbase + The segment\-base value +that needs to be added to the segment\-relative values stored in the +unwind\-info. The exact meaning of this value is +architecture\-specific. +.PP +.TP +unw_word_t table_len + The length of the +unwind\-info (table_data) +counted in units of words +(unw_word_t). +.PP +.TP +unw_word_t table_data + A pointer to the actual +data encoding the unwind\-info. The exact format is +architecture\-specific (see architecture\-specific sections below). +.PP +.SS REMOTE TABLE\-INFO FORMAT +.PP +The remote table\-info format has the same basic purpose as the regular +table\-info format. The only difference is that when libunwind +uses the unwind\-info, it will keep the table data in the target +address\-space (which may be remote). Consequently, the type of the +table_data +member is unw_word_t +rather than a pointer. +This implies that libunwind +will have to access the table\-data +via the address\-space\&'s access_mem() +call\-back, rather than +through a direct memory reference. +.PP +From the point of view of a runtime\-code generator, the remote +table\-info format offers no advantage and it is expected that such +generators will describe their procedures either with the proc\-info +format or the normal table\-info format. The main reason that the +remote table\-info format exists is to enable the +address\-space\-specific find_proc_info() +callback (see +unw_create_addr_space(3)) +to return unwind tables whose +data remains in remote memory. This can speed up unwinding (e.g., for +a debugger) because it reduces the amount of data that needs to be +loaded from remote memory. +.PP +.SH REGIONS DESCRIPTORS + +.PP +A region descriptor is a variable length structure that describes how +each instruction in the region affects the frame state. Of course, +most instructions in a region usualy do not change the frame state and +for those, nothing needs to be recorded in the region descriptor. A +region descriptor is a structure of type +unw_dyn_region_info_t +and has the following members: +.TP +unw_dyn_region_info_t *next + A pointer to the +next region. If this is the last region, next +is NULL\&. +.TP +int32_t insn_count + The length of the region in +instructions. Each instruction is assumed to have a fixed size (see +architecture\-specific sections for details). The value of +insn_count +may be negative in the last region of a procedure +(i.e., it may be negative only if next +is NULL). +A +negative value indicates that the region covers the last \fIN\fP +instructions of the procedure, where \fIN\fP +is the absolute value +of insn_count\&. +.TP +uint32_t op_count + The (allocated) length of +the op_count +array. +.TP +unw_dyn_op_t op + An array of dynamic unwind +directives. See Section ``Dynamic unwind directives\&'' for a +description of the directives. +.PP +A region descriptor with an insn_count +of zero is an +\fIempty region\fP +and such regions are perfectly legal. In fact, +empty regions can be useful to establish a particular frame state +before the start of another region. +.PP +A single region list can be shared across multiple procedures provided +those procedures share a common prologue and epilogue (their bodies +may differ, of course). Normally, such procedures consist of a canned +prologue, the body, and a canned epilogue. This could be described by +two regions: one covering the prologue and one covering the epilogue. +Since the body length is variable, the latter region would need to +specify a negative value in insn_count +such that +libunwind +knows that the region covers the end of the procedure +(up to the address specified by end_ip). +.PP +The region descriptor is a variable length structure to make it +possible to allocate all the necessary memory with a single +memory\-allocation request. To facilitate the allocation of a region +descriptors libunwind +provides a helper routine with the +following synopsis: +.PP +size_t +_U_dyn_region_size(int +op_count); +.PP +This routine returns the number of bytes needed to hold a region +descriptor with space for op_count +unwind directives. Note +that the length of the op +array does not have to match exactly +with the number of directives in a region. Instead, it is sufficient +if the op +array contains at least as many entries as there are +directives, since the end of the directives can always be indicated +with the UNW_DYN_STOP +directive. +.PP +.SH DYNAMIC UNWIND DIRECTIVES + +.PP +A dynamic unwind directive describes how the frame state changes +at a particular point within a region. The description is in +the form of a structure of type unw_dyn_op_t\&. +This +structure has the following members: +.TP +int8_t tag + The operation tag. Must be one +of the unw_dyn_operation_t +values described below. +.TP +int8_t qp + The qualifying predicate that controls +whether or not this directive is active. This is useful for +predicated architecturs such as IA\-64 or ARM, where the contents of +another (callee\-saved) register determines whether or not an +instruction is executed (takes effect). If the directive is always +active, this member should be set to the manifest constant +_U_QP_TRUE +(this constant is defined for all +architectures, predicated or not). +.TP +int16_t reg + The number of the register affected +by the instruction. +.TP +int32_t when + The region\-relative number of +the instruction to which this directive applies. For example, +a value of 0 means that the effect described by this directive +has taken place once the first instruction in the region has +executed. +.TP +unw_word_t val + The value to be applied by the +operation tag. The exact meaning of this value varies by tag. See +Section ``Operation tags\&'' below. +.PP +It is perfectly legitimate to specify multiple dynamic unwind +directives with the same when +value, if a particular instruction +has a complex effect on the frame state. +.PP +Empty regions by definition contain no actual instructions and as such +the directives are not tied to a particular instruction. By +convention, the when +member should be set to 0, however. +.PP +There is no need for the dynamic unwind directives to appear +in order of increasing when +values. If the directives happen to +be sorted in that order, it may result in slightly faster execution, +but a runtime code\-generator should not go to extra lengths just to +ensure that the directives are sorted. +.PP +IMPLEMENTATION NOTE: should libunwind +implementations for +certain architectures prefer the list of unwind directives to be +sorted, it is recommended that such implementations first check +whether the list happens to be sorted already and, if not, sort the +directives explicitly before the first use. With this approach, the +overhead of explicit sorting is only paid when there is a real benefit +and if the runtime code\-generator happens to generated sorted lists +naturally, the performance penalty is limited to a simple O(N) check. +.PP +.SS OPERATIONS TAGS +.PP +The possible operation tags are defined by enumeration type +unw_dyn_operation_t +which defines the following +values: +.PP +.TP +UNW_DYN_STOP + Marks the end of the dynamic unwind +directive list. All remaining entries in the op +array of the +region\-descriptor are ignored. This tag is guaranteed to have a +value of 0. +.PP +.TP +UNW_DYN_SAVE_REG + Marks an instruction which saves +register reg +to register val\&. +.PP +.TP +UNW_DYN_SPILL_FP_REL + Marks an instruction which +spills register reg +to a frame\-pointer\-relative location. The +frame\-pointer\-relative offset is given by the value stored in member +val\&. +See the architecture\-specific sections for a description +of the stack frame layout. +.PP +.TP +UNW_DYN_SPILL_SP_REL + Marks an instruction which +spills register reg +to a stack\-pointer\-relative location. The +stack\-pointer\-relative offset is given by the value stored in member +val\&. +See the architecture\-specific sections for a description +of the stack frame layout. +.PP +.TP +UNW_DYN_ADD + Marks an instruction which adds +the constant value val +to register reg\&. +To add subtract +a constant value, store the two\&'s\-complement of the value in +val\&. +The set of registers that can be specified for this tag +is described in the architecture\-specific sections below. +.PP +.TP +UNW_DYN_POP_FRAMES + .PP +.TP +UNW_DYN_LABEL_STATE + .PP +.TP +UNW_DYN_COPY_STATE + .PP +.TP +UNW_DYN_ALIAS + .PP +unw_dyn_op_t +.PP +_U_dyn_op_save_reg(); +_U_dyn_op_spill_fp_rel(); +_U_dyn_op_spill_sp_rel(); +_U_dyn_op_add(); +_U_dyn_op_pop_frames(); +_U_dyn_op_label_state(); +_U_dyn_op_copy_state(); +_U_dyn_op_alias(); +_U_dyn_op_stop(); +.PP +.SH IA\-64 SPECIFICS + +.PP +\- meaning of segbase member in table\-info/table\-remote\-info format +\- format of table_data in table\-info/table\-remote\-info format +\- instruction size: each bundle is counted as 3 instructions, regardless +of template (MLX) +\- describe stack\-frame layout, especially with regards to sp\-relative +and fp\-relative addressing +\- UNW_DYN_ADD can only add to ``sp\&'' (always a negative value); use +POP_FRAMES otherwise +.PP +.SH SEE ALSO + +.PP +libunwind(3), +_U_dyn_register(3), +_U_dyn_cancel(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-dynamic.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-dynamic.tex new file mode 100644 index 0000000..21e895a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-dynamic.tex @@ -0,0 +1,401 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{libunwind-dynamic}{David Mosberger-Tang}{Programming Library}{Introduction to dynamic unwind-info}libunwind-dynamic -- libunwind-support for runtime-generated code +\end{Name} + +\section{Introduction} + +For \Prog{libunwind} to do its job, it needs to be able to reconstruct +the \emph{frame state} of each frame in a call-chain. The frame state +describes the subset of the machine-state that consists of the +\emph{frame registers} (typically the instruction-pointer and the +stack-pointer) and all callee-saved registers (preserved registers). +The frame state describes each register either by providing its +current value (for frame registers) or by providing the location at +which the current value is stored (callee-saved registers). + +For statically generated code, the compiler normally takes care of +emitting \emph{unwind-info} which provides the minimum amount of +information needed to reconstruct the frame-state for each instruction +in a procedure. For dynamically generated code, the runtime code +generator must use the dynamic unwind-info interface provided by +\Prog{libunwind} to supply the equivalent information. This manual +page describes the format of this information in detail. + +For the purpose of this discussion, a \emph{procedure} is defined to +be an arbitrary piece of \emph{contiguous} code. Normally, each +procedure directly corresponds to a function in the source-language +but this is not strictly required. For example, a runtime +code-generator could translate a given function into two separate +(discontiguous) procedures: one for frequently-executed (hot) code and +one for rarely-executed (cold) code. Similarly, simple +source-language functions (usually leaf functions) may get translated +into code for which the default unwind-conventions apply and for such +code, it is not strictly necessary to register dynamic unwind-info. + +A procedure logically consists of a sequence of \emph{regions}. +Regions are nested in the sense that the frame state at the end of one +region is, by default, assumed to be the frame state for the next +region. Each region is thought of as being divided into a +\emph{prologue}, a \emph{body}, and an \emph{epilogue}. Each of them +can be empty. If non-empty, the prologue sets up the frame state for +the body. For example, the prologue may need to allocate some space +on the stack and save certain callee-saved registers. The body +performs the actual work of the procedure but does not change the +frame state in any way. If non-empty, the epilogue restores the +previous frame state and as such it undoes or cancels the effect of +the prologue. In fact, a single epilogue may undo the effect of the +prologues of several (nested) regions. + +We should point out that even though the prologue, body, and epilogue +are logically separate entities, optimizing code-generators will +generally interleave instructions from all three entities. For this +reason, the dynamic unwind-info interface of \Prog{libunwind} makes no +distinction whatsoever between prologue and body. Similarly, the +exact set of instructions that make up an epilogue is also irrelevant. +The only point in the epilogue that needs to be described explicitly +by the dynamic unwind-info is the point at which the stack-pointer +gets restored. The reason this point needs to be described is that +once the stack-pointer is restored, all values saved in the +deallocated portion of the stack frame become invalid and hence +\Prog{libunwind} needs to know about it. The portion of the frame +state not saved on the stack is assume to remain valid through the end +of the region. For this reason, there is usually no need to describe +instructions which restore the contents of callee-saved registers. + +Within a region, each instruction that affects the frame state in some +fashion needs to be described with an operation descriptor. For this +purpose, each instruction in the region is assigned a unique index. +Exactly how this index is derived depends on the architecture. For +example, on RISC and EPIC-style architecture, instructions have a +fixed size so it's possible to simply number the instructions. In +contrast, most CISC use variable-length instruction encodings, so it +is usually necessary to use a byte-offset as the index. Given the +instruction index, the operation descriptor specifies the effect of +the instruction in an abstract manner. For example, it might express +that the instruction stores calle-saved register \Var{r1} at offset 16 +in the stack frame. + +\section{Procedures} + +A runtime code-generator registers the dynamic unwind-info of a +procedure by setting up a structure of type \Type{unw\_dyn\_info\_t} +and calling \Func{\_U\_dyn\_register}(), passing the address of the +structure as the sole argument. The members of the +\Type{unw\_dyn\_info\_t} structure are described below: +\begin{itemize} +\item[\Type{void~*}next] Private to \Prog{libunwind}. Must not be used + by the application. +\item[\Type{void~*}prev] Private to \Prog{libunwind}. Must not be used + by the application. +\item[\Type{unw\_word\_t} \Var{start\_ip}] The start-address of the + instructions of the procedure (remember: procedure are defined to be + contiguous pieces of code, so a single code-range is sufficient). +\item[\Type{unw\_word\_t} \Var{end\_ip}] The end-address of the + instructions of the procedure (non-inclusive, that is, + \Var{end\_ip}-\Var{start\_ip} is the size of the procedure in + bytes). +\item[\Type{unw\_word\_t} \Var{gp}] The global-pointer value in use + for this procedure. The exact meaing of the global-pointer is + architecture-specific and on some architecture, it is not used at + all. +\item[\Type{int32\_t} \Var{format}] The format of the unwind-info. + This member can be one of \Const{UNW\_INFO\_FORMAT\_DYNAMIC}, + \Const{UNW\_INFO\_FORMAT\_TABLE}, or + \Const{UNW\_INFO\_FORMAT\_REMOTE\_TABLE}. +\item[\Type{union} \Var{u}] This union contains one sub-member + structure for every possible unwind-info format: + \begin{description} + \item[\Type{unw\_dyn\_proc\_info\_t} \Var{pi}] This member is used + for format \Const{UNW\_INFO\_FORMAT\_DYNAMIC}. + \item[\Type{unw\_dyn\_table\_info\_t} \Var{ti}] This member is used + for format \Const{UNW\_INFO\_FORMAT\_TABLE}. + \item[\Type{unw\_dyn\_remote\_table\_info\_t} \Var{rti}] This member + is used for format \Const{UNW\_INFO\_FORMAT\_REMOTE\_TABLE}. + \end{description}\ + The format of these sub-members is described in detail below. +\end{itemize} + +\subsection{Proc-info format} + +This is the preferred dynamic unwind-info format and it is generally +the one used by full-blown runtime code-generators. In this format, +the details of a procedure are described by a structure of type +\Type{unw\_dyn\_proc\_info\_t}. This structure contains the following +members: +\begin{description} + +\item[\Type{unw\_word\_t} \Var{name\_ptr}] The address of a + (human-readable) name of the procedure or 0 if no such name is + available. If non-zero, The string stored at this address must be + ASCII NUL terminated. For source languages that use name-mangling + (such as C++ or Java) the string stored at this address should be + the \emph{demangled} version of the name. + +\item[\Type{unw\_word\_t} \Var{handler}] The address of the + personality-routine for this procedure. Personality-routines are + used in conjunction with exception handling. See the C++ ABI draft + (http://www.codesourcery.com/cxx-abi/) for an overview and a + description of the personality routine. If the procedure has no + personality routine, \Var{handler} must be set to 0. + +\item[\Type{uint32\_t} \Var{flags}] A bitmask of flags. At the + moment, no flags have been defined and this member must be + set to 0. + +\item[\Type{unw\_dyn\_region\_info\_t~*}\Var{regions}] A NULL-terminated + linked list of region-descriptors. See section ``Region + descriptors'' below for more details. + +\end{description} + +\subsection{Table-info format} + +This format is generally used when the dynamically generated code was +derived from static code and the unwind-info for the dynamic and the +static versions is identical. For example, this format can be useful +when loading statically-generated code into an address-space in a +non-standard fashion (i.e., through some means other than +\Func{dlopen}()). In this format, the details of a group of procedures +is described by a structure of type \Type{unw\_dyn\_table\_info}. +This structure contains the following members: +\begin{description} + +\item[\Type{unw\_word\_t} \Var{name\_ptr}] The address of a + (human-readable) name of the procedure or 0 if no such name is + available. If non-zero, The string stored at this address must be + ASCII NUL terminated. For source languages that use name-mangling + (such as C++ or Java) the string stored at this address should be + the \emph{demangled} version of the name. + +\item[\Type{unw\_word\_t} \Var{segbase}] The segment-base value + that needs to be added to the segment-relative values stored in the + unwind-info. The exact meaning of this value is + architecture-specific. + +\item[\Type{unw\_word\_t} \Var{table\_len}] The length of the + unwind-info (\Var{table\_data}) counted in units of words + (\Type{unw\_word\_t}). + +\item[\Type{unw\_word\_t} \Var{table\_data}] A pointer to the actual + data encoding the unwind-info. The exact format is + architecture-specific (see architecture-specific sections below). + +\end{description} + +\subsection{Remote table-info format} + +The remote table-info format has the same basic purpose as the regular +table-info format. The only difference is that when \Prog{libunwind} +uses the unwind-info, it will keep the table data in the target +address-space (which may be remote). Consequently, the type of the +\Var{table\_data} member is \Type{unw\_word\_t} rather than a pointer. +This implies that \Prog{libunwind} will have to access the table-data +via the address-space's \Func{access\_mem}() call-back, rather than +through a direct memory reference. + +From the point of view of a runtime-code generator, the remote +table-info format offers no advantage and it is expected that such +generators will describe their procedures either with the proc-info +format or the normal table-info format. The main reason that the +remote table-info format exists is to enable the +address-space-specific \Func{find\_proc\_info}() callback (see +\SeeAlso{unw\_create\_addr\_space}(3)) to return unwind tables whose +data remains in remote memory. This can speed up unwinding (e.g., for +a debugger) because it reduces the amount of data that needs to be +loaded from remote memory. + +\section{Regions descriptors} + +A region descriptor is a variable length structure that describes how +each instruction in the region affects the frame state. Of course, +most instructions in a region usualy do not change the frame state and +for those, nothing needs to be recorded in the region descriptor. A +region descriptor is a structure of type +\Type{unw\_dyn\_region\_info\_t} and has the following members: +\begin{description} +\item[\Type{unw\_dyn\_region\_info\_t~*}\Var{next}] A pointer to the + next region. If this is the last region, \Var{next} is \Const{NULL}. +\item[\Type{int32\_t} \Var{insn\_count}] The length of the region in + instructions. Each instruction is assumed to have a fixed size (see + architecture-specific sections for details). The value of + \Var{insn\_count} may be negative in the last region of a procedure + (i.e., it may be negative only if \Var{next} is \Const{NULL}). A + negative value indicates that the region covers the last \emph{N} + instructions of the procedure, where \emph{N} is the absolute value + of \Var{insn\_count}. +\item[\Type{uint32\_t} \Var{op\_count}] The (allocated) length of + the \Var{op\_count} array. +\item[\Type{unw\_dyn\_op\_t} \Var{op}] An array of dynamic unwind + directives. See Section ``Dynamic unwind directives'' for a + description of the directives. +\end{description} +A region descriptor with an \Var{insn\_count} of zero is an +\emph{empty region} and such regions are perfectly legal. In fact, +empty regions can be useful to establish a particular frame state +before the start of another region. + +A single region list can be shared across multiple procedures provided +those procedures share a common prologue and epilogue (their bodies +may differ, of course). Normally, such procedures consist of a canned +prologue, the body, and a canned epilogue. This could be described by +two regions: one covering the prologue and one covering the epilogue. +Since the body length is variable, the latter region would need to +specify a negative value in \Var{insn\_count} such that +\Prog{libunwind} knows that the region covers the end of the procedure +(up to the address specified by \Var{end\_ip}). + +The region descriptor is a variable length structure to make it +possible to allocate all the necessary memory with a single +memory-allocation request. To facilitate the allocation of a region +descriptors \Prog{libunwind} provides a helper routine with the +following synopsis: + +\noindent +\Type{size\_t} \Func{\_U\_dyn\_region\_size}(\Type{int} \Var{op\_count}); + +This routine returns the number of bytes needed to hold a region +descriptor with space for \Var{op\_count} unwind directives. Note +that the length of the \Var{op} array does not have to match exactly +with the number of directives in a region. Instead, it is sufficient +if the \Var{op} array contains at least as many entries as there are +directives, since the end of the directives can always be indicated +with the \Const{UNW\_DYN\_STOP} directive. + +\section{Dynamic unwind directives} + +A dynamic unwind directive describes how the frame state changes +at a particular point within a region. The description is in +the form of a structure of type \Type{unw\_dyn\_op\_t}. This +structure has the following members: +\begin{description} +\item[\Type{int8\_t} \Var{tag}] The operation tag. Must be one + of the \Type{unw\_dyn\_operation\_t} values described below. +\item[\Type{int8\_t} \Var{qp}] The qualifying predicate that controls + whether or not this directive is active. This is useful for + predicated architecturs such as IA-64 or ARM, where the contents of + another (callee-saved) register determines whether or not an + instruction is executed (takes effect). If the directive is always + active, this member should be set to the manifest constant + \Const{\_U\_QP\_TRUE} (this constant is defined for all + architectures, predicated or not). +\item[\Type{int16\_t} \Var{reg}] The number of the register affected + by the instruction. +\item[\Type{int32\_t} \Var{when}] The region-relative number of + the instruction to which this directive applies. For example, + a value of 0 means that the effect described by this directive + has taken place once the first instruction in the region has + executed. +\item[\Type{unw\_word\_t} \Var{val}] The value to be applied by the + operation tag. The exact meaning of this value varies by tag. See + Section ``Operation tags'' below. +\end{description} +It is perfectly legitimate to specify multiple dynamic unwind +directives with the same \Var{when} value, if a particular instruction +has a complex effect on the frame state. + +Empty regions by definition contain no actual instructions and as such +the directives are not tied to a particular instruction. By +convention, the \Var{when} member should be set to 0, however. + +There is no need for the dynamic unwind directives to appear +in order of increasing \Var{when} values. If the directives happen to +be sorted in that order, it may result in slightly faster execution, +but a runtime code-generator should not go to extra lengths just to +ensure that the directives are sorted. + +IMPLEMENTATION NOTE: should \Prog{libunwind} implementations for +certain architectures prefer the list of unwind directives to be +sorted, it is recommended that such implementations first check +whether the list happens to be sorted already and, if not, sort the +directives explicitly before the first use. With this approach, the +overhead of explicit sorting is only paid when there is a real benefit +and if the runtime code-generator happens to generated sorted lists +naturally, the performance penalty is limited to a simple O(N) check. + +\subsection{Operations tags} + +The possible operation tags are defined by enumeration type +\Type{unw\_dyn\_operation\_t} which defines the following +values: +\begin{description} + +\item[\Const{UNW\_DYN\_STOP}] Marks the end of the dynamic unwind + directive list. All remaining entries in the \Var{op} array of the + region-descriptor are ignored. This tag is guaranteed to have a + value of 0. + +\item[\Const{UNW\_DYN\_SAVE\_REG}] Marks an instruction which saves + register \Var{reg} to register \Var{val}. + +\item[\Const{UNW\_DYN\_SPILL\_FP\_REL}] Marks an instruction which + spills register \Var{reg} to a frame-pointer-relative location. The + frame-pointer-relative offset is given by the value stored in member + \Var{val}. See the architecture-specific sections for a description + of the stack frame layout. + +\item[\Const{UNW\_DYN\_SPILL\_SP\_REL}] Marks an instruction which + spills register \Var{reg} to a stack-pointer-relative location. The + stack-pointer-relative offset is given by the value stored in member + \Var{val}. See the architecture-specific sections for a description + of the stack frame layout. + +\item[\Const{UNW\_DYN\_ADD}] Marks an instruction which adds + the constant value \Var{val} to register \Var{reg}. To add subtract + a constant value, store the two's-complement of the value in + \Var{val}. The set of registers that can be specified for this tag + is described in the architecture-specific sections below. + +\item[\Const{UNW\_DYN\_POP\_FRAMES}] + +\item[\Const{UNW\_DYN\_LABEL\_STATE}] + +\item[\Const{UNW\_DYN\_COPY\_STATE}] + +\item[\Const{UNW\_DYN\_ALIAS}] + +\end{description} + +unw\_dyn\_op\_t + +\_U\_dyn\_op\_save\_reg(); +\_U\_dyn\_op\_spill\_fp\_rel(); +\_U\_dyn\_op\_spill\_sp\_rel(); +\_U\_dyn\_op\_add(); +\_U\_dyn\_op\_pop\_frames(); +\_U\_dyn\_op\_label\_state(); +\_U\_dyn\_op\_copy\_state(); +\_U\_dyn\_op\_alias(); +\_U\_dyn\_op\_stop(); + +\section{IA-64 specifics} + +- meaning of segbase member in table-info/table-remote-info format +- format of table\_data in table-info/table-remote-info format +- instruction size: each bundle is counted as 3 instructions, regardless + of template (MLX) +- describe stack-frame layout, especially with regards to sp-relative + and fp-relative addressing +- UNW\_DYN\_ADD can only add to ``sp'' (always a negative value); use + POP\_FRAMES otherwise + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{\_U\_dyn\_register(3)}, +\SeeAlso{\_U\_dyn\_cancel(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ia64.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ia64.man new file mode 100644 index 0000000..06b141e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ia64.man @@ -0,0 +1,314 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "LIBUNWIND\-IA64" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +libunwind\-ia64 +\-\- IA\-64\-specific support in libunwind +.PP +.SH INTRODUCTION + +.PP +The IA\-64 version of libunwind +uses a platform\-string of +ia64 +and, at least in theory, should be able to support all +operating systems adhering to the processor\-specific ABI defined for +the Itanium Processor Family. This includes both little\-endian Linux +and big\-endian HP\-UX. Furthermore, to make it possible for a single +library to unwind both 32\- and 64\-bit targets, the type +unw_word_t +is always defined to be 64 bits wide (independent +of the natural word\-size of the host). Having said that, the current +implementation has been tested only with IA\-64 Linux. +.PP +When targeting IA\-64, the libunwind +header file defines the +macro UNW_TARGET_IA64 +as 1 and the macro UNW_TARGET +as ``ia64\&'' (without the quotation marks). The former makes it +possible for platform\-dependent unwind code to use +conditional\-compilation to select an appropriate implementation. The +latter is useful for stringification purposes and to construct +target\-platform\-specific symbols. +.PP +One special feature of IA\-64 is the use of NaT bits to support +speculative execution. Often, NaT bits are thought of as the ``65\-th +bit\&'' of a general register. However, to make everything fit into +64\-bit wide unw_word_t +values, libunwind +treats the +NaT\-bits like separate boolean registers, whose 64\-bit value is either +TRUE (non\-zero) or FALSE (zero). +.PP +.SH MACHINE\-STATE + +.PP +The machine\-state (set of registers) that is accessible through +libunwind +depends on the type of stack frame that a cursor +points to. For normal frames, all ``preserved\&'' (callee\-saved) +registers are accessible. For signal\-trampoline frames, all registers +(including ``scratch\&'' (caller\-saved) registers) are accessible. Most +applications do not have to worry a\-priori about which registers are +accessible when. In case of doubt, it is always safe to \fItry\fP +to +access a register (via unw_get_reg() +or +unw_get_fpreg()) +and if the register isn\&'t accessible, the +call will fail with a return\-value of \-UNW_EBADREG\&. +.PP +As a special exception to the above general rule, scratch registers +r15\-r18 +are always accessible, even in normal +frames. This makes it possible to pass arguments, e.g., to exception +handlers. +.PP +For a detailed description of the IA\-64 register usage convention, +please see the ``Itanium Software Conventions and Runtime Architecture +Guide\&'', available at: +.ce 100 +\fBhttp://www.intel.com/design/itanium/downloads/245358.htm\fP +.ce 0 + +.PP +.SH REGISTER NAMES + +.PP +The IA\-64\-version of libunwind +defines three kinds of register +name macros: frame\-register macros, normal register macros, and +convenience macros. Below, we describe each kind in turn: +.PP +.SS FRAME\-REGISTER MACROS +.PP +Frame\-registers are special (pseudo) registers because they always +have a valid value, even though sometimes they do not get saved +explicitly (e.g., if a memory stack frame is 16 bytes in size, the +previous stack\-pointer value can be calculated simply as +sp+16, +so there is no need to save the stack\-pointer +explicitly). Moreover, the set of frame register values uniquely +identifies a stack frame. The IA\-64 architecture defines two stacks +(a memory and a register stack). Including the instruction\-pointer +(IP), this means there are three frame registers: +.TP +UNW_IA64_IP: + Contains the instruction pointer (IP, or +``program counter\&'') of the current stack frame. Given this value, +the remaining machine\-state corresponds to the register\-values that +were present in the CPU when it was just about to execute the +instruction pointed to by UNW_IA64_IP\&. +Bits 0 and 1 of +this frame\-register encode the slot number of the instruction. +\fBNote:\fP +Due to the way the call instruction works on IA\-64, +the slot number is usually zero, but can be non\-zero, e.g., in the +stack\-frame of a signal\-handler trampoline. +.TP +UNW_IA64_SP: + Contains the (memory) stack\-pointer +value (SP). +.TP +UNW_IA64_BSP: + Contains the register backing\-store +pointer (BSP). \fBNote:\fP +the value in this register is equal +to the contents of register ar.bsp +at the time the +instruction at UNW_IA64_IP +was about to begin execution. +.PP +.SS NORMAL REGISTER MACROS +.PP +The following normal register name macros are available: +.TP +UNW_IA64_GR: + The base\-index for general (integer) +registers. Add an index in the range from 0..127 to get a +particular general register. For example, to access r4, +the index UNW_IA64_GR+4 +should be used. +Registers r0 +and r1 +(gp) +are read\-only, +and any attempt to write them will result in an error +(\-UNW_EREADONLYREG). +Even though r1 +is +read\-only, libunwind +will automatically adjust its value if +the instruction\-pointer (UNW_IA64_IP) +is modified. For +example, if UNW_IA64_IP +is set to a value inside a +function func(), +then reading +UNW_IA64_GR+1 +will return the global\-pointer +value for this function. +.TP +UNW_IA64_NAT: + The base\-index for the NaT bits of the +general (integer) registers. A non\-zero value in these registers +corresponds to a set NaT\-bit. Add an index in the range from 0..127 +to get a particular NaT\-bit register. For example, to access the +NaT bit of r4, +the index UNW_IA64_NAT+4 +should be used. +.TP +UNW_IA64_FR: + The base\-index for floating\-point +registers. Add an index in the range from 0..127 to get a +particular floating\-point register. For example, to access +f2, +the index UNW_IA64_FR+2 +should be +used. Registers f0 +and f1 +are read\-only, and any +attempt to write to indices UNW_IA64_FR+0 +or +UNW_IA64_FR+1 +will result in an error +(\-UNW_EREADONLYREG). +.TP +UNW_IA64_AR: + The base\-index for application +registers. Add an index in the range from 0..127 to get a +particular application register. For example, to access +ar40, +the index UNW_IA64_AR+40 +should be +used. The IA\-64 architecture defines several application registers +as ``reserved for future use\&''\&. Attempting to access such registers +results in an error (\-UNW_EBADREG). +.TP +UNW_IA64_BR: + The base\-index for branch registers. +Add an index in the range from 0..7 to get a particular branch +register. For example, to access b6, +the index +UNW_IA64_BR+6 +should be used. +.TP +UNW_IA64_PR: + Contains the set of predicate registers. +This 64\-bit wide register contains registers p0 +through +p63 +in the ``broad\-side\&'' format. Just like with the +``move predicates\&'' instruction, the registers are mapped as if +CFM.rrb.pr +were set to 0. Thus, in general the value of +predicate register pN +with N>=16 can be found +in bit 16 + ((N\-16)+CFM.rrb.pr) % 48\&. +.TP +UNW_IA64_CFM: + Contains the current\-frame\-mask +register. +.PP +.SS CONVENIENCE MACROS +.PP +Convenience macros are simply aliases for certain frequently used +registers: +.TP +UNW_IA64_GP: + Alias for UNW_IA64_GR+1, +the global\-pointer register. +.TP +UNW_IA64_TP: + Alias for UNW_IA64_GR+13, +the thread\-pointer register. +.TP +UNW_IA64_AR_RSC: + Alias for UNW_IA64_GR+16, +the register\-stack configuration register. +.TP +UNW_IA64_AR_BSP: + Alias for +UNW_IA64_GR+17\&. +This register index accesses the +value of register ar.bsp +as of the time it was last saved +explicitly. This is rarely what you want. Normally, you\&'ll want to +use UNW_IA64_BSP +instead. +.TP +UNW_IA64_AR_BSPSTORE: + Alias for UNW_IA64_GR+18, +the register\-backing store write pointer. +.TP +UNW_IA64_AR_RNAT: + Alias for UNW_IA64_GR+19, +the register\-backing store NaT\-collection register. +.TP +UNW_IA64_AR_CCV: + Alias for UNW_IA64_GR+32, +the compare\-and\-swap value register. +.TP +UNW_IA64_AR_CSD: + Alias for UNW_IA64_GR+25, +the compare\-and\-swap\-data register (used by 16\-byte atomic operations). +.TP +UNW_IA64_AR_UNAT: + Alias for UNW_IA64_GR+36, +the user NaT\-collection register. +.TP +UNW_IA64_AR_FPSR: + Alias for UNW_IA64_GR+40, +the floating\-point status (and control) register. +.TP +UNW_IA64_AR_PFS: + Alias for UNW_IA64_GR+64, +the previous frame\-state register. +.TP +UNW_IA64_AR_LC: + Alias for UNW_IA64_GR+65 +the loop\-count register. +.TP +UNW_IA64_AR_EC: + Alias for UNW_IA64_GR+66, +the epilogue\-count register. +.PP +.SH THE UNWIND\-CONTEXT TYPE + +.PP +On IA\-64, unw_context_t +is simply an alias for +ucontext_t +(as defined by the Single UNIX Spec). This implies +that it is possible to initialize a value of this type not just with +unw_getcontext(), +but also with getcontext(), +for +example. However, since this is an IA\-64\-specific extension to +libunwind, +portable code should not rely on this equivalence. +.PP +.SH SEE ALSO + +.PP +libunwind(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ia64.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ia64.tex new file mode 100644 index 0000000..c08946d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ia64.tex @@ -0,0 +1,216 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{libunwind-ia64}{David Mosberger-Tang}{Programming Library}{IA-64-specific support in libunwind}libunwind-ia64 -- IA-64-specific support in libunwind +\end{Name} + + +\section{Introduction} + +The IA-64 version of \Prog{libunwind} uses a platform-string of +\texttt{ia64} and, at least in theory, should be able to support all +operating systems adhering to the processor-specific ABI defined for +the Itanium Processor Family. This includes both little-endian Linux +and big-endian HP-UX. Furthermore, to make it possible for a single +library to unwind both 32- and 64-bit targets, the type +\Type{unw\_word\_t} is always defined to be 64 bits wide (independent +of the natural word-size of the host). Having said that, the current +implementation has been tested only with IA-64 Linux. + +When targeting IA-64, the \Prog{libunwind} header file defines the +macro \Const{UNW\_TARGET\_IA64} as 1 and the macro \Const{UNW\_TARGET} +as ``ia64'' (without the quotation marks). The former makes it +possible for platform-dependent unwind code to use +conditional-compilation to select an appropriate implementation. The +latter is useful for stringification purposes and to construct +target-platform-specific symbols. + +One special feature of IA-64 is the use of NaT bits to support +speculative execution. Often, NaT bits are thought of as the ``65-th +bit'' of a general register. However, to make everything fit into +64-bit wide \Type{unw\_word\_t} values, \Prog{libunwind} treats the +NaT-bits like separate boolean registers, whose 64-bit value is either +TRUE (non-zero) or FALSE (zero). + + +\section{Machine-State} + +The machine-state (set of registers) that is accessible through +\Prog{libunwind} depends on the type of stack frame that a cursor +points to. For normal frames, all ``preserved'' (callee-saved) +registers are accessible. For signal-trampoline frames, all registers +(including ``scratch'' (caller-saved) registers) are accessible. Most +applications do not have to worry a-priori about which registers are +accessible when. In case of doubt, it is always safe to \emph{try} to +access a register (via \Func{unw\_get\_reg}() or +\Func{unw\_get\_fpreg}()) and if the register isn't accessible, the +call will fail with a return-value of \texttt{-}\Const{UNW\_EBADREG}. + +As a special exception to the above general rule, scratch registers +\texttt{r15}-\texttt{r18} are always accessible, even in normal +frames. This makes it possible to pass arguments, e.g., to exception +handlers. + +For a detailed description of the IA-64 register usage convention, +please see the ``Itanium Software Conventions and Runtime Architecture +Guide'', available at: +\begin{center} + \URL{http://www.intel.com/design/itanium/downloads/245358.htm} +\end{center} + + +\section{Register Names} + +The IA-64-version of \Prog{libunwind} defines three kinds of register +name macros: frame-register macros, normal register macros, and +convenience macros. Below, we describe each kind in turn: + + +\subsection{Frame-register Macros} + +Frame-registers are special (pseudo) registers because they always +have a valid value, even though sometimes they do not get saved +explicitly (e.g., if a memory stack frame is 16 bytes in size, the +previous stack-pointer value can be calculated simply as +\texttt{sp+16}, so there is no need to save the stack-pointer +explicitly). Moreover, the set of frame register values uniquely +identifies a stack frame. The IA-64 architecture defines two stacks +(a memory and a register stack). Including the instruction-pointer +(IP), this means there are three frame registers: +\begin{Description} +\item[\Const{UNW\_IA64\_IP}:] Contains the instruction pointer (IP, or + ``program counter'') of the current stack frame. Given this value, + the remaining machine-state corresponds to the register-values that + were present in the CPU when it was just about to execute the + instruction pointed to by \Const{UNW\_IA64\_IP}. Bits 0 and 1 of + this frame-register encode the slot number of the instruction. + \textbf{Note:} Due to the way the call instruction works on IA-64, + the slot number is usually zero, but can be non-zero, e.g., in the + stack-frame of a signal-handler trampoline. +\item[\Const{UNW\_IA64\_SP}:] Contains the (memory) stack-pointer + value (SP). +\item[\Const{UNW\_IA64\_BSP}:] Contains the register backing-store + pointer (BSP). \textbf{Note:} the value in this register is equal + to the contents of register \texttt{ar.bsp} at the time the + instruction at \Const{UNW\_IA64\_IP} was about to begin execution. +\end{Description} + + +\subsection{Normal Register Macros} + +The following normal register name macros are available: +\begin{Description} +\item[\Const{UNW\_IA64\_GR}:] The base-index for general (integer) + registers. Add an index in the range from 0..127 to get a + particular general register. For example, to access \texttt{r4}, + the index \Const{UNW\_IA64\_GR}\texttt{+4} should be used. + Registers \texttt{r0} and \texttt{r1} (\texttt{gp}) are read-only, + and any attempt to write them will result in an error + (\texttt{-}\Const{UNW\_EREADONLYREG}). Even though \texttt{r1} is + read-only, \Prog{libunwind} will automatically adjust its value if + the instruction-pointer (\Const{UNW\_IA64\_IP}) is modified. For + example, if \Const{UNW\_IA64\_IP} is set to a value inside a + function \Func{func}(), then reading + \Const{UNW\_IA64\_GR}\texttt{+1} will return the global-pointer + value for this function. +\item[\Const{UNW\_IA64\_NAT}:] The base-index for the NaT bits of the + general (integer) registers. A non-zero value in these registers + corresponds to a set NaT-bit. Add an index in the range from 0..127 + to get a particular NaT-bit register. For example, to access the + NaT bit of \texttt{r4}, the index \Const{UNW\_IA64\_NAT}\texttt{+4} + should be used. +\item[\Const{UNW\_IA64\_FR}:] The base-index for floating-point + registers. Add an index in the range from 0..127 to get a + particular floating-point register. For example, to access + \texttt{f2}, the index \Const{UNW\_IA64\_FR}\texttt{+2} should be + used. Registers \texttt{f0} and \texttt{f1} are read-only, and any + attempt to write to indices \Const{UNW\_IA64\_FR}\texttt{+0} or + \Const{UNW\_IA64\_FR}\texttt{+1} will result in an error + (\texttt{-}\Const{UNW\_EREADONLYREG}). +\item[\Const{UNW\_IA64\_AR}:] The base-index for application + registers. Add an index in the range from 0..127 to get a + particular application register. For example, to access + \texttt{ar40}, the index \Const{UNW\_IA64\_AR}\texttt{+40} should be + used. The IA-64 architecture defines several application registers + as ``reserved for future use''. Attempting to access such registers + results in an error (\texttt{-}\Const{UNW\_EBADREG}). +\item[\Const{UNW\_IA64\_BR}:] The base-index for branch registers. + Add an index in the range from 0..7 to get a particular branch + register. For example, to access \texttt{b6}, the index + \Const{UNW\_IA64\_BR}\texttt{+6} should be used. +\item[\Const{UNW\_IA64\_PR}:] Contains the set of predicate registers. + This 64-bit wide register contains registers \texttt{p0} through + \texttt{p63} in the ``broad-side'' format. Just like with the + ``move predicates'' instruction, the registers are mapped as if + \texttt{CFM.rrb.pr} were set to 0. Thus, in general the value of + predicate register \texttt{p}$N$ with $N$>=16 can be found + in bit \texttt{16 + (($N$-16)+CFM.rrb.pr) \% 48}. +\item[\Const{UNW\_IA64\_CFM}:] Contains the current-frame-mask + register. +\end{Description} + + +\subsection{Convenience Macros} + +Convenience macros are simply aliases for certain frequently used +registers: +\begin{Description} +\item[\Const{UNW\_IA64\_GP}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+1}, + the global-pointer register. +\item[\Const{UNW\_IA64\_TP}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+13}, + the thread-pointer register. +\item[\Const{UNW\_IA64\_AR\_RSC}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+16}, + the register-stack configuration register. +\item[\Const{UNW\_IA64\_AR\_BSP}:] Alias for + \Const{UNW\_IA64\_GR}\texttt{+17}. This register index accesses the + value of register \texttt{ar.bsp} as of the time it was last saved + explicitly. This is rarely what you want. Normally, you'll want to + use \Const{UNW\_IA64\_BSP} instead. +\item[\Const{UNW\_IA64\_AR\_BSPSTORE}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+18}, + the register-backing store write pointer. +\item[\Const{UNW\_IA64\_AR\_RNAT}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+19}, + the register-backing store NaT-collection register. +\item[\Const{UNW\_IA64\_AR\_CCV}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+32}, + the compare-and-swap value register. +\item[\Const{UNW\_IA64\_AR\_CSD}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+25}, + the compare-and-swap-data register (used by 16-byte atomic operations). +\item[\Const{UNW\_IA64\_AR\_UNAT}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+36}, + the user NaT-collection register. +\item[\Const{UNW\_IA64\_AR\_FPSR}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+40}, + the floating-point status (and control) register. +\item[\Const{UNW\_IA64\_AR\_PFS}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+64}, + the previous frame-state register. +\item[\Const{UNW\_IA64\_AR\_LC}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+65} + the loop-count register. +\item[\Const{UNW\_IA64\_AR\_EC}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+66}, + the epilogue-count register. +\end{Description} + + +\section{The Unwind-Context Type} + +On IA-64, \Type{unw\_context\_t} is simply an alias for +\Type{ucontext\_t} (as defined by the Single UNIX Spec). This implies +that it is possible to initialize a value of this type not just with +\Func{unw\_getcontext}(), but also with \Func{getcontext}(), for +example. However, since this is an IA-64-specific extension to +\Prog{libunwind}, portable code should not rely on this equivalence. + + +\section{See Also} + +\SeeAlso{libunwind(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ptrace.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ptrace.man new file mode 100644 index 0000000..985fcae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ptrace.man @@ -0,0 +1,220 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "LIBUNWIND\-PTRACE" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +libunwind\-ptrace +\-\- ptrace() support in libunwind +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +unw_accessors_t +_UPT_accessors; +.br +.PP +void *_UPT_create(pid_t); +.br +void +_UPT_destroy(void *); +.br +.PP +int +_UPT_find_proc_info(unw_addr_space_t, +unw_word_t, +unw_proc_info_t *, +int, +void *); +.br +void +_UPT_put_unwind_info(unw_addr_space_t, +unw_proc_info_t *, +void *); +.br +int +_UPT_get_dyn_info_list_addr(unw_addr_space_t, +unw_word_t *, +void *); +.br +int +_UPT_access_mem(unw_addr_space_t, +unw_word_t, +unw_word_t *, +int, +void *); +.br +int +_UPT_access_reg(unw_addr_space_t, +unw_regnum_t, +unw_word_t *, +int, +void *); +.br +int +_UPT_access_fpreg(unw_addr_space_t, +unw_regnum_t, +unw_fpreg_t *, +int, +void *); +.br +int +_UPT_get_proc_name(unw_addr_space_t, +unw_word_t, +char *, +size_t, +unw_word_t *, +void *); +.br +int +_UPT_resume(unw_addr_space_t, +unw_cursor_t *, +void *); +.br +.PP +.SH DESCRIPTION + +.PP +The ptrace(2) +system\-call makes it possible for a process to +gain access to the machine\-state and virtual memory of \fIanother\fP +process. With the right set of call\-back routines, it is therefore +possible to hook up libunwind +to another process via +ptrace(2). +While it\&'s not very difficult to do so directly, +libunwind +further facilitates this task by providing +ready\-to\-use callbacks for this purpose. The routines and variables +implementing this facility use a name\-prefix of _UPT, +which is +stands for ``unwind\-via\-ptrace\&''\&. +.PP +An application that wants to use the _UPT\-facility +first needs +to create a new libunwind +address\-space that represents the +target process. This is done by calling +unw_create_addr_space(). +In many cases, the application +will simply want to pass the address of _UPT_accessors +as the +first argument to this routine. Doing so will ensure that +libunwind +will be able to properly unwind the target process. +However, in special circumstances, an application may prefer to use +only portions of the _UPT\-facility. +For this reason, the +individual callback routines (_UPT_find_proc_info(), +_UPT_put_unwind_info(), +etc.) are also available for direct +use. Of course, the addresses of these routines could also be picked +up from _UPT_accessors, +but doing so would prevent static +initialization. Also, when using _UPT_accessors, +\fIall\fP +the callback routines will be linked into the application, even if +they are never actually called. +.PP +Next, the application can turn on ptrace\-mode on the target process, +either by forking a new process, invoking PTRACE_TRACEME, +and +then starting the target program (via execve(2)), +or by +directly attaching to an already running process (via +PTRACE_ATTACH). +Either way, once the process\-ID (pid) of the +target process is known, a _UPT\-info\-structure +can be created +by calling _UPT_create(), +passing the pid of the target process +as the only argument. The returned void\-pointer then needs to be +passed as the ``argument\&'' pointer (third argument) to +unw_init_remote(). +.PP +The _UPT_resume() +routine can be used to resume execution of +the target process. It simply invokes ptrace(2) +with a command +value of PTRACE_CONT\&. +.PP +When the application is done using libunwind +on the target +process, _UPT_destroy() +needs to be called, passing it the +void\-pointer that was returned by the corresponding call to +_UPT_create(). +This ensures that all memory and other +resources are freed up. +.PP +.SH AVAILABILITY + +.PP +Since ptrace(2) +works within a single machine only, the +_UPT\-facility +by definition is not available in +libunwind\-versions +configured for cross\-unwinding. +.PP +.SH THREAD SAFETY + +.PP +The _UPT\-facility +assumes that a single _UPT\-info +structure is never shared between threads. Because of this, no +explicit locking is used. As long as only one thread uses +a _UPT\-info +structure at any given time, this facility +is thread\-safe. +.PP +.SH RETURN VALUE + +.PP +_UPT_create() +may return a NULL +pointer if it fails +to create the _UPT\-info\-structure +for any reason. For the +current implementation, the only reason this call may fail is when the +system is out of memory. +.PP +.SH FILES + +.PP +.TP +libunwind\-ptrace.h + Headerfile to include when using the +interface defined by this library. +.TP +\fB\-l\fPunwind\-ptrace \fB\-l\fPunwind\-generic + Linker\-switches to add when building a program that uses the +functions defined by this library. +.PP +.SH SEE ALSO + +.PP +execve(2), +libunwind(3), +ptrace(2) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ptrace.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ptrace.tex new file mode 100644 index 0000000..fe074d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-ptrace.tex @@ -0,0 +1,134 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{libunwind-ptrace}{David Mosberger-Tang}{Programming Library}{ptrace() support in libunwind}libunwind-ptrace -- ptrace() support in libunwind +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind-ptrace.h$>$}\\ + +\noindent +\Type{unw\_accessors\_t} \Var{\_UPT\_accessors};\\ + +\Type{void~*}\Func{\_UPT\_create}(\Type{pid\_t});\\ +\noindent +\Type{void} \Func{\_UPT\_destroy}(\Type{void~*});\\ + +\noindent +\Type{int} \Func{\_UPT\_find\_proc\_info}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t}, \Type{unw\_proc\_info\_t~*}, \Type{int}, \Type{void~*});\\ +\noindent +\Type{void} \Func{\_UPT\_put\_unwind\_info}(\Type{unw\_addr\_space\_t}, \Type{unw\_proc\_info\_t~*}, \Type{void~*});\\ +\noindent +\Type{int} \Func{\_UPT\_get\_dyn\_info\_list\_addr}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t~*}, \Type{void~*});\\ +\noindent +\Type{int} \Func{\_UPT\_access\_mem}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t}, \Type{unw\_word\_t~*}, \Type{int}, \Type{void~*});\\ +\noindent +\Type{int} \Func{\_UPT\_access\_reg}(\Type{unw\_addr\_space\_t}, \Type{unw\_regnum\_t}, \Type{unw\_word\_t~*}, \Type{int}, \Type{void~*});\\ +\noindent +\Type{int} \Func{\_UPT\_access\_fpreg}(\Type{unw\_addr\_space\_t}, \Type{unw\_regnum\_t}, \Type{unw\_fpreg\_t~*}, \Type{int}, \Type{void~*});\\ +\noindent +\Type{int} \Func{\_UPT\_get\_proc\_name}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t}, \Type{char~*}, \Type{size\_t}, \Type{unw\_word\_t~*}, \Type{void~*});\\ +\noindent +\Type{int} \Func{\_UPT\_resume}(\Type{unw\_addr\_space\_t}, \Type{unw\_cursor\_t~*}, \Type{void~*});\\ + +\section{Description} + +The \Func{ptrace}(2) system-call makes it possible for a process to +gain access to the machine-state and virtual memory of \emph{another} +process. With the right set of call-back routines, it is therefore +possible to hook up \Prog{libunwind} to another process via +\Func{ptrace}(2). While it's not very difficult to do so directly, +\Prog{libunwind} further facilitates this task by providing +ready-to-use callbacks for this purpose. The routines and variables +implementing this facility use a name-prefix of \Func{\_UPT}, which is +stands for ``unwind-via-ptrace''. + +An application that wants to use the \Func{\_UPT}-facility first needs +to create a new \Prog{libunwind} address-space that represents the +target process. This is done by calling +\Func{unw\_create\_addr\_space}(). In many cases, the application +will simply want to pass the address of \Var{\_UPT\_accessors} as the +first argument to this routine. Doing so will ensure that +\Prog{libunwind} will be able to properly unwind the target process. +However, in special circumstances, an application may prefer to use +only portions of the \Prog{\_UPT}-facility. For this reason, the +individual callback routines (\Func{\_UPT\_find\_proc\_info}(), +\Func{\_UPT\_put\_unwind\_info}(), etc.) are also available for direct +use. Of course, the addresses of these routines could also be picked +up from \Var{\_UPT\_accessors}, but doing so would prevent static +initialization. Also, when using \Var{\_UPT\_accessors}, \emph{all} +the callback routines will be linked into the application, even if +they are never actually called. + +Next, the application can turn on ptrace-mode on the target process, +either by forking a new process, invoking \Const{PTRACE\_TRACEME}, and +then starting the target program (via \Func{execve}(2)), or by +directly attaching to an already running process (via +\Const{PTRACE\_ATTACH}). Either way, once the process-ID (pid) of the +target process is known, a \Prog{\_UPT}-info-structure can be created +by calling \Func{\_UPT\_create}(), passing the pid of the target process +as the only argument. The returned void-pointer then needs to be +passed as the ``argument'' pointer (third argument) to +\Func{unw\_init\_remote}(). + +The \Func{\_UPT\_resume}() routine can be used to resume execution of +the target process. It simply invokes \Func{ptrace}(2) with a command +value of \Const{PTRACE\_CONT}. + +When the application is done using \Prog{libunwind} on the target +process, \Func{\_UPT\_destroy}() needs to be called, passing it the +void-pointer that was returned by the corresponding call to +\Func{\_UPT\_create}(). This ensures that all memory and other +resources are freed up. + +\section{Availability} + +Since \Func{ptrace}(2) works within a single machine only, the +\Prog{\_UPT}-facility by definition is not available in +\Prog{libunwind}-versions configured for cross-unwinding. + +\section{Thread Safety} + +The \Prog{\_UPT}-facility assumes that a single \Prog{\_UPT}-info +structure is never shared between threads. Because of this, no +explicit locking is used. As long as only one thread uses +a \Prog{\_UPT}-info structure at any given time, this facility +is thread-safe. + +\section{Return Value} + +\Func{\_UPT\_create}() may return a \Const{NULL} pointer if it fails +to create the \Prog{\_UPT}-info-structure for any reason. For the +current implementation, the only reason this call may fail is when the +system is out of memory. + +\section{Files} + +\begin{Description} +\item[\File{libunwind-ptrace.h}] Headerfile to include when using the + interface defined by this library. +\item[\Opt{-l}\File{unwind-ptrace} \Opt{-l}\File{unwind-generic}] + Linker-switches to add when building a program that uses the + functions defined by this library. +\end{Description} + +\section{See Also} + +execve(2), +\SeeAlso{libunwind(3)}, +ptrace(2) + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-setjmp.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-setjmp.man new file mode 100644 index 0000000..1faa38e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-setjmp.man @@ -0,0 +1,132 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "LIBUNWIND\-SETJMP" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +libunwind\-setjmp +\-\- libunwind\-based non\-local gotos +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +setjmp(jmp_buf env); +.br +void +longjmp(jmp_buf env, +int val); +.br +int +_setjmp(jmp_buf env); +.br +void +_longjmp(jmp_buf env, +int val); +.br +int +sigsetjmp(sigjmp_buf env, +int savemask); +.br +void +siglongjmp(sigjmp_buf env, +int val); +.br +.PP +.SH DESCRIPTION + +.PP +The unwind\-setjmp +library offers a libunwind\-based +implementation of non\-local gotos. This implementation is intended to +be a drop\-in replacement for the normal, system\-provided routines of +the same name. The main advantage of using the unwind\-setjmp +library is that setting up a non\-local goto via one of the +setjmp() +routines is very fast. Typically, just 2 or 3 words +need to be saved in the jump\-buffer (plus one call to +sigprocmask(2), +in the case of sigsetjmp). +On the +other hand, executing a non\-local goto by calling one of the +longjmp() +routines tends to be much slower than with the +system\-provided routines. In fact, the time spent on a +longjmp() +will be proportional to the number of call frames +that exist between the points where setjmp() +and +longjmp() +were called. For this reason, the +unwind\-setjmp +library is beneficial primarily in applications +that frequently call setjmp() +but only rarely call +longjmp(). +.PP +.SH CAVEATS + +.PP +.TP +.B * +The correct operation of this library depends on the presence of +correct unwind information. On newer platforms, this is rarely an +issue. On older platforms, care needs to be taken to +ensure that each of the functions whose stack frames may have to be +unwound during a longjmp() +have correct unwind information +(on those platforms, there is usually a compiler\-switch, such as +\fB\-funwind\-tables\fP, +to request the generation of unwind +information). +.TP +.B * +The contents of jmp_buf and sigjmp_buf as setup +and used by these routines is completely different from the ones +used by the system\-provided routines. Thus, a jump\-buffer created +by the libunwind\-based setjmp()/_setjmp +may only be +used in a call to the libunwind\-based +longjmp()/_longjmp(). +The analogous applies for +sigjmp_buf +with sigsetjmp() +and siglongjmp(). +.PP +.SH FILES + +.PP +.TP +\fB\-l\fPunwind\-setjmp + The library an application should +be linked against to ensure it uses the libunwind\-based non\-local +goto routines. +.PP +.SH SEE ALSO + +.PP +libunwind(3), +setjmp(3), longjmp(3), +_setjmp(3), _longjmp(3), +sigsetjmp(3), siglongjmp(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-setjmp.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-setjmp.tex new file mode 100644 index 0000000..17ce073 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind-setjmp.tex @@ -0,0 +1,87 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{libunwind-setjmp}{David Mosberger-Tang}{Programming Library}{libunwind-based non-local gotos}libunwind-setjmp -- libunwind-based non-local gotos +\end{Name} + +\section{Synopsis} + +\File{\#include $<$setjmp.h$>$}\\ + +\noindent +\Type{int} \Func{setjmp}(\Type{jmp\_buf}~\Var{env});\\ +\Type{void} \Func{longjmp}(\Type{jmp\_buf}~\Var{env}, \Type{int}~\Var{val});\\ +\Type{int} \Func{\_setjmp}(\Type{jmp\_buf}~\Var{env});\\ +\Type{void} \Func{\_longjmp}(\Type{jmp\_buf}~\Var{env}, \Type{int}~\Var{val});\\ +\Type{int} \Func{sigsetjmp}(\Type{sigjmp\_buf}~\Var{env}, \Type{int}~\Var{savemask});\\ +\Type{void} \Func{siglongjmp}(\Type{sigjmp\_buf}~\Var{env}, \Type{int}~\Var{val});\\ + +\section{Description} + +The \Prog{unwind-setjmp} library offers a \Prog{libunwind}-based +implementation of non-local gotos. This implementation is intended to +be a drop-in replacement for the normal, system-provided routines of +the same name. The main advantage of using the \Prog{unwind-setjmp} +library is that setting up a non-local goto via one of the +\Func{setjmp}() routines is very fast. Typically, just 2 or 3 words +need to be saved in the jump-buffer (plus one call to +\Func{sigprocmask}(2), in the case of \Func{sigsetjmp}). On the +other hand, executing a non-local goto by calling one of the +\Func{longjmp}() routines tends to be much slower than with the +system-provided routines. In fact, the time spent on a +\Func{longjmp}() will be proportional to the number of call frames +that exist between the points where \Func{setjmp}() and +\Func{longjmp}() were called. For this reason, the +\Prog{unwind-setjmp} library is beneficial primarily in applications +that frequently call \Func{setjmp}() but only rarely call +\Func{longjmp}(). + +\section{Caveats} + +\begin{itemize} +\item The correct operation of this library depends on the presence of + correct unwind information. On newer platforms, this is rarely an + issue. On older platforms, care needs to be taken to + ensure that each of the functions whose stack frames may have to be + unwound during a \Func{longjmp}() have correct unwind information + (on those platforms, there is usually a compiler-switch, such as + \Opt{-funwind-tables}, to request the generation of unwind + information). +\item The contents of \Type{jmp\_buf} and \Type{sigjmp\_buf} as setup + and used by these routines is completely different from the ones + used by the system-provided routines. Thus, a jump-buffer created + by the libunwind-based \Func{setjmp}()/\Func{\_setjmp} may only be + used in a call to the libunwind-based + \Func{longjmp}()/\Func{\_longjmp}(). The analogous applies for + \Type{sigjmp\_buf} with \Func{sigsetjmp}() and \Func{siglongjmp}(). +\end{itemize} + +\section{Files} + +\begin{Description} +\item[\Opt{-l}\File{unwind-setjmp}] The library an application should + be linked against to ensure it uses the libunwind-based non-local + goto routines. +\end{Description} + + +\section{See Also} + +\SeeAlso{libunwind(3)}, +setjmp(3), longjmp(3), +\_setjmp(3), \_longjmp(3), +sigsetjmp(3), siglongjmp(3) + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind.man new file mode 100644 index 0000000..02ab6b8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind.man @@ -0,0 +1,508 @@ +'\" t +.\" Manual page created with latex2man on Thu Jan 12 06:50:29 PST 2017 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "LIBUNWIND" "3" "12 January 2017" "Programming Library " "Programming Library " +.SH NAME +libunwind +\-\- a (mostly) platform\-independent unwind API +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_getcontext(unw_context_t *); +.br +int +unw_init_local(unw_cursor_t *, +unw_context_t *); +.br +int +unw_init_remote(unw_cursor_t *, +unw_addr_space_t, +void *); +.br +int +unw_step(unw_cursor_t *); +.br +int +unw_get_reg(unw_cursor_t *, +unw_regnum_t, +unw_word_t *); +.br +int +unw_get_fpreg(unw_cursor_t *, +unw_regnum_t, +unw_fpreg_t *); +.br +int +unw_set_reg(unw_cursor_t *, +unw_regnum_t, +unw_word_t); +.br +int +unw_set_fpreg(unw_cursor_t *, +unw_regnum_t, +unw_fpreg_t); +.br +int +unw_resume(unw_cursor_t *); +.br +.PP +unw_addr_space_t +unw_local_addr_space; +.br +unw_addr_space_t +unw_create_addr_space(unw_accessors_t, +int); +.br +void +unw_destroy_addr_space(unw_addr_space_t); +.br +unw_accessors_t +unw_get_accessors(unw_addr_space_t); +.br +void +unw_flush_cache(unw_addr_space_t, +unw_word_t, +unw_word_t); +.br +int +unw_set_caching_policy(unw_addr_space_t, +unw_caching_policy_t); +.br +int +unw_set_cache_size(unw_addr_space_t, +size_t, +int); +.br +.PP +const char *unw_regname(unw_regnum_t); +.br +int +unw_get_proc_info(unw_cursor_t *, +unw_proc_info_t *); +.br +int +unw_get_save_loc(unw_cursor_t *, +int, +unw_save_loc_t *); +.br +int +unw_is_fpreg(unw_regnum_t); +.br +int +unw_is_signal_frame(unw_cursor_t *); +.br +int +unw_get_proc_name(unw_cursor_t *, +char *, +size_t, +unw_word_t *); +.br +.PP +void +_U_dyn_register(unw_dyn_info_t *); +.br +void +_U_dyn_cancel(unw_dyn_info_t *); +.br +.PP +.SH LOCAL UNWINDING + +.PP +Libunwind +is very easy to use when unwinding a stack from +within a running program. This is called \fIlocal\fP +unwinding. Say +you want to unwind the stack while executing in some function +F(). +In this function, you would call unw_getcontext() +to get a snapshot of the CPU registers (machine\-state). Then you +initialize an \fIunwind cursor\fP +based on this snapshot. This is +done with a call to unw_init_local(). +The cursor now points +to the current frame, that is, the stack frame that corresponds to the +current activation of function F(). +The unwind cursor can then +be moved ``up\&'' (towards earlier stack frames) by calling +unw_step(). +By repeatedly calling this routine, you can +uncover the entire call\-chain that led to the activation of function +F(). +A positive return value from unw_step() +indicates +that there are more frames in the chain, zero indicates that the end +of the chain has been reached, and any negative value indicates that +some sort of error has occurred. +.PP +While it is not possible to directly move the unwind cursor in the +``down\&'' direction (towards newer stack frames), this effect can be +achieved by making copies of an unwind cursor. For example, a program +that sometimes has to move ``down\&'' by one stack frame could maintain +two cursor variables: ``curr\&'' +and ``prev\&''\&. +The former +would be used as the current cursor and prev +would be maintained +as the ``previous frame\&'' cursor by copying the contents of curr +to prev +right before calling unw_step(). +With this +approach, the program could move one step ``down\&'' simply by copying +back prev +to curr +whenever that is necessary. In the most +extreme case, a program could maintain a separate cursor for each call +frame and that way it could move up and down the callframe\-chain at +will. +.PP +Given an unwind cursor, it is possible to read and write the CPU +registers that were preserved for the current stack frame (as +identified by the cursor). Libunwind +provides several routines +for this purpose: unw_get_reg() +reads an integer (general) +register, unw_get_fpreg() +reads a floating\-point register, +unw_set_reg() +writes an integer register, and +unw_set_fpreg() +writes a floating\-point register. Note that, +by definition, only the \fIpreserved\fP +machine state can be accessed +during an unwind operation. Normally, this state consists of the +\fIcallee\-saved\fP +(``preserved\&'') registers. However, in some +special circumstances (e.g., in a signal handler trampoline), even the +\fIcaller\-saved\fP +(``scratch\&'') registers are preserved in the stack +frame and, in those cases, libunwind +will grant access to them +as well. The exact set of registers that can be accessed via the +cursor depends, of course, on the platform. However, there are two +registers that can be read on all platforms: the instruction pointer +(IP), sometimes also known as the ``program counter\&'', and the stack +pointer (SP). In libunwind, +these registers are identified by +the macros UNW_REG_IP +and UNW_REG_SP, +respectively. +.PP +Besides just moving the unwind cursor and reading/writing saved +registers, libunwind +also provides the ability to resume +execution at an arbitrary stack frame. As you might guess, this is +useful for implementing non\-local gotos and the exception handling +needed by some high\-level languages such as Java. Resuming execution +with a particular stack frame simply requires calling +unw_resume() +and passing the cursor identifying the target +frame as the only argument. +.PP +Normally, libunwind +supports both local and remote unwinding +(the latter will be explained in the next section). However, if you +tell libunwind that your program only needs local unwinding, then a +special implementation can be selected which may run much faster than +the generic implementation which supports both kinds of unwinding. To +select this optimized version, simply define the macro +UNW_LOCAL_ONLY +before including the headerfile +\&. +It is perfectly OK for a single program to +employ both local\-only and generic unwinding. That is, whether or not +UNW_LOCAL_ONLY +is defined is a choice that each source\-file +(compilation\-unit) can make on its own. Independent of the setting(s) +of UNW_LOCAL_ONLY, +you\&'ll always link the same library into +the program (normally \fB\-l\fPunwind). +Furthermore, the +portion of libunwind +that manages unwind\-info for dynamically +generated code is not affected by the setting of +UNW_LOCAL_ONLY\&. +.PP +If we put all of the above together, here is how we could use +libunwind +to write a function ``show_backtrace()\&'' +which prints a classic stack trace: +.PP +.Vb +#define UNW_LOCAL_ONLY +#include + +void show_backtrace (void) { + unw_cursor_t cursor; unw_context_t uc; + unw_word_t ip, sp; + + unw_getcontext(&uc); + unw_init_local(&cursor, &uc); + while (unw_step(&cursor) > 0) { + unw_get_reg(&cursor, UNW_REG_IP, &ip); + unw_get_reg(&cursor, UNW_REG_SP, &sp); + printf ("ip = %lx, sp = %lx\\n", (long) ip, (long) sp); + } +} +.Ve +.PP +.SH REMOTE UNWINDING + +.PP +Libunwind +can also be used to unwind a stack in a ``remote\&'' +process. Here, ``remote\&'' may mean another process on the same +machine or even a process on a completely different machine from the +one that is running libunwind\&. +Remote unwinding is typically +used by debuggers and instruction\-set simulators, for example. +.PP +Before you can unwind a remote process, you need to create a new +address\-space object for that process. This is achieved with the +unw_create_addr_space() +routine. The routine takes two +arguments: a pointer to a set of \fIaccessor\fP +routines and an +integer that specifies the byte\-order of the target process. The +accessor routines provide libunwind +with the means to +communicate with the remote process. In particular, there are +callbacks to read and write the process\&'s memory, its registers, and +to access unwind information which may be needed by libunwind\&. +.PP +With the address space created, unwinding can be initiated by a call +to unw_init_remote(). +This routine is very similar to +unw_init_local(), +except that it takes an address\-space +object and an opaque pointer as arguments. The routine uses these +arguments to fetch the initial machine state. Libunwind +never +uses the opaque pointer on its own, but instead just passes it on to +the accessor (callback) routines. Typically, this pointer is used to +select, e.g., the thread within a process that is to be unwound. +.PP +Once a cursor has been initialized with unw_init_remote(), +unwinding works exactly like in the local case. That is, you can use +unw_step() +to move ``up\&'' in the call\-chain, read and write +registers, or resume execution at a particular stack frame by calling +unw_resume\&. +.PP +.SH CROSS\-PLATFORM AND MULTI\-PLATFORM UNWINDING + +.PP +Libunwind +has been designed to enable unwinding across +platforms (architectures). Indeed, a single program can use +libunwind +to unwind an arbitrary number of target platforms, +all at the same time! +.PP +We call the machine that is running libunwind +the \fIhost\fP +and the machine that is running the process being unwound the +\fItarget\fP\&. +If the host and the target platform are the same, we +call it \fInative\fP +unwinding. If they differ, we call it +\fIcross\-platform\fP +unwinding. +.PP +The principle behind supporting native, cross\-platform, and +multi\-platform unwinding is very simple: for native unwinding, a +program includes +and uses the linker switch +\fB\-l\fPunwind\&. +For cross\-platform unwinding, a program +includes +and uses the linker +switch \fB\-l\fPunwind\-PLAT, +where PLAT +is the name +of the target platform (e.g., ia64 +for IA\-64, hppa\-elf +for ELF\-based HP PA\-RISC, or x86 +for 80386). Multi\-platform +unwinding works exactly like cross\-platform unwinding, the only +limitation is that a single source file (compilation unit) can include +at most one libunwind +header file. In other words, the +platform\-specific support for each supported target needs to be +isolated in separate source files\-\-\-a limitation that shouldn\&'t be an +issue in practice. +.PP +Note that, by definition, local unwinding is possible only for the +native case. Attempting to call, e.g., unw_local_init() +when +targeting a cross\-platform will result in a link\-time error +(unresolved references). +.PP +.SH THREAD\- AND SIGNAL\-SAFETY + +.PP +All libunwind +routines are thread\-safe. What this means is +that multiple threads may use libunwind +simulatenously. +However, any given cursor may be accessed by only one thread at +any given time. +.PP +To ensure thread\-safety, some libunwind +routines may have to +use locking. Such routines \fImust not\fP +be called from signal +handlers (directly or indirectly) and are therefore \fInot\fP +signal\-safe. The manual page for each libunwind +routine +identifies whether or not it is signal\-safe, but as a general rule, +any routine that may be needed for \fIlocal\fP +unwinding is +signal\-safe (e.g., unw_step() +for local unwinding is +signal\-safe). For remote\-unwinding, \fInone\fP +of the +libunwind +routines are guaranteed to be signal\-safe. +.PP +.SH UNWINDING THROUGH DYNAMICALLY GENERATED CODE + +.PP +Libunwind +provides the routines _U_dyn_register() +and +_U_dyn_cancel() +to register/cancel the information required to +unwind through code that has been generated at runtime (e.g., by a +just\-in\-time (JIT) compiler). It is important to register the +information for \fIall\fP +dynamically generated code because +otherwise, a debugger may not be able to function properly or +high\-level language exception handling may not work as expected. +.PP +The interface for registering and canceling dynamic unwind info has +been designed for maximum efficiency, so as to minimize the +performance impact on JIT\-compilers. In particular, both routines are +guaranteed to execute in ``constant time\&'' (O(1)) and the +data\-structure encapsulating the dynamic unwind info has been designed +to facilitate sharing, such that similar procedures can share much of +the underlying information. +.PP +For more information on the libunwind +support for dynamically +generated code, see libunwind\-dynamic(3)\&. +.PP +.SH CACHING OF UNWIND INFO + +.PP +To speed up execution, libunwind +may aggressively cache the +information it needs to perform unwinding. If a process changes +during its lifetime, this creates a risk of libunwind +using +stale data. For example, this would happen if libunwind +were +to cache information about a shared library which later on gets +unloaded (e.g., via \fIdlclose\fP(3)). +.PP +To prevent the risk of using stale data, libunwind +provides two +facilities: first, it is possible to flush the cached information +associated with a specific address range in the target process (or the +entire address space, if desired). This functionality is provided by +unw_flush_cache(). +The second facility is provided by +unw_set_caching_policy(), +which lets a program +select the exact caching policy in use for a given address\-space +object. In particular, by selecting the policy +UNW_CACHE_NONE, +it is possible to turn off caching +completely, therefore eliminating the risk of stale data alltogether +(at the cost of slower execution). By default, caching is enabled for +local unwinding only. The cache size can be dynamically changed with +unw_set_cache_size(), +which also fluches the current cache. +.PP +.SH FILES + +.PP +.TP +libunwind.h + Headerfile to include for native (same +platform) unwinding. +.TP +libunwind\-PLAT\&.h + Headerfile to include when +the unwind target runs on platform PLAT\&. +For example, to unwind +an IA\-64 program, the header file libunwind\-ia64.h +should be +included. +.TP +\fB\-l\fPunwind + Linker\-switch to add when building a +program that does native (same platform) unwinding. +.TP +\fB\-l\fPunwind\-PLAT + Linker\-switch to add when +building a program that unwinds a program on platform PLAT\&. +For example, to (cross\-)unwind an IA\-64 program, the linker switch +\-lunwind\-ia64 +should be added. Note: multiple such switches +may need to be specified for programs that can unwind programs on +multiple platforms. +.PP +.SH SEE ALSO + +.PP +libunwind\-dynamic(3), +libunwind\-ia64(3), +libunwind\-ptrace(3), +libunwind\-setjmp(3), +unw_create_addr_space(3), +unw_destroy_addr_space(3), +unw_flush_cache(3), +unw_get_accessors(3), +unw_get_fpreg(3), +unw_get_proc_info(3), +unw_get_proc_name(3), +unw_get_reg(3), +unw_getcontext(3), +unw_init_local(3), +unw_init_remote(3), +unw_is_fpreg(3), +unw_is_signal_frame(3), +unw_regname(3), +unw_resume(3), +unw_set_caching_policy(3), +unw_set_cache_size(3), +unw_set_fpreg(3), +unw_set_reg(3), +unw_step(3), +unw_strerror(3), +_U_dyn_register(3), +_U_dyn_cancel(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind.tex new file mode 100644 index 0000000..6cbb476 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind.tex @@ -0,0 +1,359 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{libunwind}{David Mosberger-Tang}{Programming Library}{Introduction to libunwind}libunwind -- a (mostly) platform-independent unwind API +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\noindent +\Type{int} \Func{unw\_getcontext}(\Type{unw\_context\_t~*});\\ +\noindent +\Type{int} \Func{unw\_init\_local}(\Type{unw\_cursor\_t~*}, \Type{unw\_context\_t~*});\\ +\noindent +\Type{int} \Func{unw\_init\_remote}(\Type{unw\_cursor\_t~*}, \Type{unw\_addr\_space\_t}, \Type{void~*});\\ +\noindent +\Type{int} \Func{unw\_step}(\Type{unw\_cursor\_t~*});\\ +\noindent +\Type{int} \Func{unw\_get\_reg}(\Type{unw\_cursor\_t~*}, \Type{unw\_regnum\_t}, \Type{unw\_word\_t~*});\\ +\noindent +\Type{int} \Func{unw\_get\_fpreg}(\Type{unw\_cursor\_t~*}, \Type{unw\_regnum\_t}, \Type{unw\_fpreg\_t~*});\\ +\noindent +\Type{int} \Func{unw\_set\_reg}(\Type{unw\_cursor\_t~*}, \Type{unw\_regnum\_t}, \Type{unw\_word\_t});\\ +\noindent +\Type{int} \Func{unw\_set\_fpreg}(\Type{unw\_cursor\_t~*}, \Type{unw\_regnum\_t}, \Type{unw\_fpreg\_t});\\ +\noindent +\Type{int} \Func{unw\_resume}(\Type{unw\_cursor\_t~*});\\ + +\noindent +\Type{unw\_addr\_space\_t} \Var{unw\_local\_addr\_space};\\ +\noindent +\Type{unw\_addr\_space\_t} \Func{unw\_create\_addr\_space}(\Type{unw\_accessors\_t}, \Type{int});\\ +\noindent +\Type{void} \Func{unw\_destroy\_addr\_space}(\Type{unw\_addr\_space\_t});\\ +\noindent +\Type{unw\_accessors\_t} \Func{unw\_get\_accessors}(\Type{unw\_addr\_space\_t});\\ +\noindent +\Type{void} \Func{unw\_flush\_cache}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t}, \Type{unw\_word\_t});\\ +\noindent +\Type{int} \Func{unw\_set\_caching\_policy}(\Type{unw\_addr\_space\_t}, \Type{unw\_caching\_policy\_t});\\ +\noindent +\Type{int} \Func{unw\_set\_cache\_size}(\Type{unw\_addr\_space\_t}, \Type{size\_t}, \Type{int});\\ + +\noindent +\Type{const char *}\Func{unw\_regname}(\Type{unw\_regnum\_t});\\ +\noindent +\Type{int} \Func{unw\_get\_proc\_info}(\Type{unw\_cursor\_t~*}, \Type{unw\_proc\_info\_t~*});\\ +\noindent +\Type{int} \Func{unw\_get\_save\_loc}(\Type{unw\_cursor\_t~*}, \Type{int}, \Type{unw\_save\_loc\_t~*});\\ +\noindent +\Type{int} \Func{unw\_is\_fpreg}(\Type{unw\_regnum\_t});\\ +\Type{int} \Func{unw\_is\_signal\_frame}(\Type{unw\_cursor\_t~*});\\ +\noindent +\Type{int} \Func{unw\_get\_proc\_name}(\Type{unw\_cursor\_t~*}, \Type{char~*}, \Type{size\_t}, \Type{unw\_word\_t~*});\\ + +\noindent +\Type{void} \Func{\_U\_dyn\_register}(\Type{unw\_dyn\_info\_t~*});\\ +\noindent +\Type{void} \Func{\_U\_dyn\_cancel}(\Type{unw\_dyn\_info\_t~*});\\ + +\section{Local Unwinding} + +\Prog{Libunwind} is very easy to use when unwinding a stack from +within a running program. This is called \emph{local} unwinding. Say +you want to unwind the stack while executing in some function +\Func{F}(). In this function, you would call \Func{unw\_getcontext}() +to get a snapshot of the CPU registers (machine-state). Then you +initialize an \emph{unwind~cursor} based on this snapshot. This is +done with a call to \Func{unw\_init\_local}(). The cursor now points +to the current frame, that is, the stack frame that corresponds to the +current activation of function \Func{F}(). The unwind cursor can then +be moved ``up'' (towards earlier stack frames) by calling +\Func{unw\_step}(). By repeatedly calling this routine, you can +uncover the entire call-chain that led to the activation of function +\Func{F}(). A positive return value from \Func{unw\_step}() indicates +that there are more frames in the chain, zero indicates that the end +of the chain has been reached, and any negative value indicates that +some sort of error has occurred. + +While it is not possible to directly move the unwind cursor in the +``down'' direction (towards newer stack frames), this effect can be +achieved by making copies of an unwind cursor. For example, a program +that sometimes has to move ``down'' by one stack frame could maintain +two cursor variables: ``\Var{curr}'' and ``\Var{prev}''. The former +would be used as the current cursor and \Var{prev} would be maintained +as the ``previous frame'' cursor by copying the contents of \Var{curr} +to \Var{prev} right before calling \Func{unw\_step}(). With this +approach, the program could move one step ``down'' simply by copying +back \Var{prev} to \Var{curr} whenever that is necessary. In the most +extreme case, a program could maintain a separate cursor for each call +frame and that way it could move up and down the callframe-chain at +will. + +Given an unwind cursor, it is possible to read and write the CPU +registers that were preserved for the current stack frame (as +identified by the cursor). \Prog{Libunwind} provides several routines +for this purpose: \Func{unw\_get\_reg}() reads an integer (general) +register, \Func{unw\_get\_fpreg}() reads a floating-point register, +\Func{unw\_set\_reg}() writes an integer register, and +\Func{unw\_set\_fpreg}() writes a floating-point register. Note that, +by definition, only the \emph{preserved} machine state can be accessed +during an unwind operation. Normally, this state consists of the +\emph{callee-saved} (``preserved'') registers. However, in some +special circumstances (e.g., in a signal handler trampoline), even the +\emph{caller-saved} (``scratch'') registers are preserved in the stack +frame and, in those cases, \Prog{libunwind} will grant access to them +as well. The exact set of registers that can be accessed via the +cursor depends, of course, on the platform. However, there are two +registers that can be read on all platforms: the instruction pointer +(IP), sometimes also known as the ``program counter'', and the stack +pointer (SP). In \Prog{libunwind}, these registers are identified by +the macros \Const{UNW\_REG\_IP} and \Const{UNW\_REG\_SP}, +respectively. + +Besides just moving the unwind cursor and reading/writing saved +registers, \Prog{libunwind} also provides the ability to resume +execution at an arbitrary stack frame. As you might guess, this is +useful for implementing non-local gotos and the exception handling +needed by some high-level languages such as Java. Resuming execution +with a particular stack frame simply requires calling +\Func{unw\_resume}() and passing the cursor identifying the target +frame as the only argument. + +Normally, \Prog{libunwind} supports both local and remote unwinding +(the latter will be explained in the next section). However, if you +tell libunwind that your program only needs local unwinding, then a +special implementation can be selected which may run much faster than +the generic implementation which supports both kinds of unwinding. To +select this optimized version, simply define the macro +\Const{UNW\_LOCAL\_ONLY} before including the headerfile +\File{$<$libunwind.h$>$}. It is perfectly OK for a single program to +employ both local-only and generic unwinding. That is, whether or not +\Const{UNW\_LOCAL\_ONLY} is defined is a choice that each source-file +(compilation-unit) can make on its own. Independent of the setting(s) +of \Const{UNW\_LOCAL\_ONLY}, you'll always link the same library into +the program (normally \Opt{-l}\File{unwind}). Furthermore, the +portion of \Prog{libunwind} that manages unwind-info for dynamically +generated code is not affected by the setting of +\Const{UNW\_LOCAL\_ONLY}. + +If we put all of the above together, here is how we could use +\Prog{libunwind} to write a function ``\Func{show\_backtrace}()'' +which prints a classic stack trace: + +\begin{verbatim} +#define UNW_LOCAL_ONLY +#include + +void show_backtrace (void) { + unw_cursor_t cursor; unw_context_t uc; + unw_word_t ip, sp; + + unw_getcontext(&uc); + unw_init_local(&cursor, &uc); + while (unw_step(&cursor) > 0) { + unw_get_reg(&cursor, UNW_REG_IP, &ip); + unw_get_reg(&cursor, UNW_REG_SP, &sp); + printf ("ip = %lx, sp = %lx\n", (long) ip, (long) sp); + } +} +\end{verbatim} + + +\section{Remote Unwinding} + +\Prog{Libunwind} can also be used to unwind a stack in a ``remote'' +process. Here, ``remote'' may mean another process on the same +machine or even a process on a completely different machine from the +one that is running \Prog{libunwind}. Remote unwinding is typically +used by debuggers and instruction-set simulators, for example. + +Before you can unwind a remote process, you need to create a new +address-space object for that process. This is achieved with the +\Func{unw\_create\_addr\_space}() routine. The routine takes two +arguments: a pointer to a set of \emph{accessor} routines and an +integer that specifies the byte-order of the target process. The +accessor routines provide \Func{libunwind} with the means to +communicate with the remote process. In particular, there are +callbacks to read and write the process's memory, its registers, and +to access unwind information which may be needed by \Func{libunwind}. + +With the address space created, unwinding can be initiated by a call +to \Func{unw\_init\_remote}(). This routine is very similar to +\Func{unw\_init\_local}(), except that it takes an address-space +object and an opaque pointer as arguments. The routine uses these +arguments to fetch the initial machine state. \Prog{Libunwind} never +uses the opaque pointer on its own, but instead just passes it on to +the accessor (callback) routines. Typically, this pointer is used to +select, e.g., the thread within a process that is to be unwound. + +Once a cursor has been initialized with \Func{unw\_init\_remote}(), +unwinding works exactly like in the local case. That is, you can use +\Func{unw\_step}() to move ``up'' in the call-chain, read and write +registers, or resume execution at a particular stack frame by calling +\Func{unw\_resume}. + + +\section{Cross-platform and Multi-platform Unwinding} + +\Prog{Libunwind} has been designed to enable unwinding across +platforms (architectures). Indeed, a single program can use +\Prog{libunwind} to unwind an arbitrary number of target platforms, +all at the same time! + +We call the machine that is running \Prog{libunwind} the \emph{host} +and the machine that is running the process being unwound the +\emph{target}. If the host and the target platform are the same, we +call it \emph{native} unwinding. If they differ, we call it +\emph{cross-platform} unwinding. + +The principle behind supporting native, cross-platform, and +multi-platform unwinding is very simple: for native unwinding, a +program includes \File{$<$libunwind.h$>$} and uses the linker switch +\Opt{-l}\File{unwind}. For cross-platform unwinding, a program +includes \File{$<$libunwind-}\Var{PLAT}\File{.h$>$} and uses the linker +switch \Opt{-l}\File{unwind-}\Var{PLAT}, where \Var{PLAT} is the name +of the target platform (e.g., \File{ia64} for IA-64, \File{hppa-elf} +for ELF-based HP PA-RISC, or \File{x86} for 80386). Multi-platform +unwinding works exactly like cross-platform unwinding, the only +limitation is that a single source file (compilation unit) can include +at most one \Prog{libunwind} header file. In other words, the +platform-specific support for each supported target needs to be +isolated in separate source files---a limitation that shouldn't be an +issue in practice. + +Note that, by definition, local unwinding is possible only for the +native case. Attempting to call, e.g., \Func{unw\_local\_init}() when +targeting a cross-platform will result in a link-time error +(unresolved references). + + +\section{Thread- and Signal-Safety} + + +All \Prog{libunwind} routines are thread-safe. What this means is +that multiple threads may use \Prog{libunwind} simulatenously. +However, any given cursor may be accessed by only one thread at +any given time. + +To ensure thread-safety, some \Prog{libunwind} routines may have to +use locking. Such routines \emph{must~not} be called from signal +handlers (directly or indirectly) and are therefore \emph{not} +signal-safe. The manual page for each \Prog{libunwind} routine +identifies whether or not it is signal-safe, but as a general rule, +any routine that may be needed for \emph{local} unwinding is +signal-safe (e.g., \Func{unw\_step}() for local unwinding is +signal-safe). For remote-unwinding, \emph{none} of the +\Prog{libunwind} routines are guaranteed to be signal-safe. + + +\section{Unwinding Through Dynamically Generated Code} + +\Func{Libunwind} provides the routines \Func{\_U\_dyn\_register}() and +\Func{\_U\_dyn\_cancel}() to register/cancel the information required to +unwind through code that has been generated at runtime (e.g., by a +just-in-time (JIT) compiler). It is important to register the +information for \emph{all} dynamically generated code because +otherwise, a debugger may not be able to function properly or +high-level language exception handling may not work as expected. + +The interface for registering and canceling dynamic unwind info has +been designed for maximum efficiency, so as to minimize the +performance impact on JIT-compilers. In particular, both routines are +guaranteed to execute in ``constant time'' (O(1)) and the +data-structure encapsulating the dynamic unwind info has been designed +to facilitate sharing, such that similar procedures can share much of +the underlying information. + +For more information on the \Prog{libunwind} support for dynamically +generated code, see \SeeAlso{libunwind-dynamic(3)}. + + +\section{Caching of Unwind Info} + +To speed up execution, \Prog{libunwind} may aggressively cache the +information it needs to perform unwinding. If a process changes +during its lifetime, this creates a risk of \Prog{libunwind} using +stale data. For example, this would happen if \Prog{libunwind} were +to cache information about a shared library which later on gets +unloaded (e.g., via \Cmd{dlclose}{3}). + +To prevent the risk of using stale data, \Prog{libunwind} provides two +facilities: first, it is possible to flush the cached information +associated with a specific address range in the target process (or the +entire address space, if desired). This functionality is provided by +\Func{unw\_flush\_cache}(). The second facility is provided by +\Func{unw\_set\_caching\_policy}(), which lets a program +select the exact caching policy in use for a given address-space +object. In particular, by selecting the policy +\Const{UNW\_CACHE\_NONE}, it is possible to turn off caching +completely, therefore eliminating the risk of stale data alltogether +(at the cost of slower execution). By default, caching is enabled for +local unwinding only. The cache size can be dynamically changed with +\Func{unw\_set\_cache\_size}(), which also fluches the current cache. + + +\section{Files} + +\begin{Description} +\item[\File{libunwind.h}] Headerfile to include for native (same + platform) unwinding. +\item[\File{libunwind-}\Var{PLAT}\File{.h}] Headerfile to include when + the unwind target runs on platform \Var{PLAT}. For example, to unwind + an IA-64 program, the header file \File{libunwind-ia64.h} should be + included. +\item[\Opt{-l}\File{unwind}] Linker-switch to add when building a + program that does native (same platform) unwinding. +\item[\Opt{-l}\File{unwind-}\Var{PLAT}] Linker-switch to add when + building a program that unwinds a program on platform \Var{PLAT}. + For example, to (cross-)unwind an IA-64 program, the linker switch + \File{-lunwind-ia64} should be added. Note: multiple such switches + may need to be specified for programs that can unwind programs on + multiple platforms. +\end{Description} + +\section{See Also} + +\SeeAlso{libunwind-dynamic(3)}, +\SeeAlso{libunwind-ia64(3)}, +\SeeAlso{libunwind-ptrace(3)}, +\SeeAlso{libunwind-setjmp(3)}, +\SeeAlso{unw\_create\_addr\_space(3)}, +\SeeAlso{unw\_destroy\_addr\_space(3)}, +\SeeAlso{unw\_flush\_cache(3)}, +\SeeAlso{unw\_get\_accessors(3)}, +\SeeAlso{unw\_get\_fpreg(3)}, +\SeeAlso{unw\_get\_proc\_info(3)}, +\SeeAlso{unw\_get\_proc\_name(3)}, +\SeeAlso{unw\_get\_reg(3)}, +\SeeAlso{unw\_getcontext(3)}, +\SeeAlso{unw\_init\_local(3)}, +\SeeAlso{unw\_init\_remote(3)}, +\SeeAlso{unw\_is\_fpreg(3)}, +\SeeAlso{unw\_is\_signal\_frame(3)}, +\SeeAlso{unw\_regname(3)}, +\SeeAlso{unw\_resume(3)}, +\SeeAlso{unw\_set\_caching\_policy(3)}, +\SeeAlso{unw\_set\_cache\_size(3)}, +\SeeAlso{unw\_set\_fpreg(3)}, +\SeeAlso{unw\_set\_reg(3)}, +\SeeAlso{unw\_step(3)}, +\SeeAlso{unw\_strerror(3)}, +\SeeAlso{\_U\_dyn\_register(3)}, +\SeeAlso{\_U\_dyn\_cancel(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind.trans b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind.trans new file mode 100644 index 0000000..a514e5a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/libunwind.trans @@ -0,0 +1,34 @@ +$manMacro1a{'Type'} = $manMacro1a{File}; + $manMacro1b{'Type'} = $manMacro1b{File}; +$htmlMacro1a{'Type'} = $htmlMacro1a{File}; + $htmlMacro1b{'Type'} = $htmlMacro1b{File}; +$texiMacro1a{'Type'} = $texiMacro1a{File}; + $texiMacro1b{'Type'} = $texiMacro1b{File}; +$manMacro1a{'Func'} = $manMacro1a{Prog}; + $manMacro1b{'Func'} = $manMacro1b{Prog}; +$htmlMacro1a{'Func'} = $htmlMacro1a{Arg}; + $htmlMacro1b{'Func'} = $htmlMacro1b{Arg}; +$texiMacro1a{'Func'} = $texiMacro1a{Prog}; + $texiMacro1b{'Func'} = $texiMacro1b{Prog}; +$manMacro1a{'Var'} = $manMacro1a{Prog}; + $manMacro1b{'Var'} = $manMacro1b{Prog}; +$htmlMacro1a{'Var'} = $htmlMacro1a{Prog}; + $htmlMacro1b{'Var'} = $htmlMacro1b{Prog}; +$texiMacro1a{'Var'} = $texiMacro1a{Prog}; + $texiMacro1b{'Var'} = $texiMacro1b{Prog}; +$manMacro1a{'Const'} = $manMacro1a{File}; + $manMacro1b{'Const'} = $manMacro1b{File}; +$htmlMacro1a{'Const'} = $htmlMacro1a{File}; + $htmlMacro1b{'Const'} = $htmlMacro1b{File}; +$texiMacro1a{'Const'} = $texiMacro1a{File}; + $texiMacro1b{'Const'} = $texiMacro1b{File}; + +$manMacro1a{'SeeAlso'} = $manMacro1a{File}; + $manMacro1b{'SeeAlso'} = $manMacro1b{File}; +# special handling of SeeAlso in latex2man, so that argument gets doubled: +$htmlMacro2a{'SeeAlso'} = "$htmlMacro1a{File}"; + $htmlMacro2c{'SeeAlso'} = "$htmlMacro1b{File}"; +$texiMacro1a{'SeeAlso'} = $texiMacro1a{File}; + $texiMacro1b{'SeeAlso'} = $texiMacro1b{File}; + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_apply_reg_state.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_apply_reg_state.man new file mode 100644 index 0000000..457f0c4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_apply_reg_state.man @@ -0,0 +1,90 @@ +'\" t +.\" Manual page created with latex2man on Wed Aug 16 11:09:44 PDT 2017 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_APPLY\\_REG\\_STATE" "3" "16 August 2017" "Programming Library " "Programming Library " +.SH NAME +unw_apply_reg_state +\-\- apply a register state update to a cursor +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_apply_reg_state(unw_cursor_t *cp, +void *reg_states_data); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_apply_reg_state() +routine updates the register values +of a cursor according to the instructions in reg_states_data, +which have been obtained by calling unw_reg_states_iterate\&. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_apply_reg_state() +returns 0. +Otherwise the negative value of one of the error\-codes below is +returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_apply_reg_state() +is thread\-safe. If cursor cp +is +in the local address\-space, this routine is also safe to use from a +signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_EUNSPEC + An unspecified error occurred. +.TP +UNW_ENOINFO + Libunwind +was unable to locate +unwind\-info for the procedure. +.TP +UNW_EBADVERSION + The unwind\-info for the procedure has +version or format that is not understood by libunwind\&. +.PP +In addition, unw_apply_reg_state() +may return any error +returned by the access_mem() +call\-back (see +unw_create_addr_space(3)). +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_reg_states_iterate(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_apply_reg_state.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_apply_reg_state.tex new file mode 100644 index 0000000..c67cc3e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_apply_reg_state.tex @@ -0,0 +1,63 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_apply\_reg\_state}{David Mosberger-Tang}{Programming Library}{unw\_apply\_reg\_state}unw\_apply\_reg\_state -- apply a register state update to a cursor +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} +\Func{unw\_apply\_reg\_state}(\Type{unw\_cursor\_t~*}\Var{cp}, +\Type{void~*}\Var{reg\_states\_data});\\ + +\section{Description} + +The \Func{unw\_apply\_reg\_state}() routine updates the register values +of a cursor according to the instructions in \Var{reg\_states\_data}, +which have been obtained by calling \Var{unw\_reg\_states\_iterate}. + +\section{Return Value} + +On successful completion, \Func{unw\_apply\_reg\_state}() returns 0. +Otherwise the negative value of one of the error-codes below is +returned. + +\section{Thread and Signal Safety} + +\Func{unw\_apply\_reg\_state}() is thread-safe. If cursor \Var{cp} is +in the local address-space, this routine is also safe to use from a +signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred. +\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to locate + unwind-info for the procedure. +\item[\Const{UNW\_EBADVERSION}] The unwind-info for the procedure has + version or format that is not understood by \Prog{libunwind}. +\end{Description} +In addition, \Func{unw\_apply\_reg\_state}() may return any error +returned by the \Func{access\_mem}() call-back (see +\Func{unw\_create\_addr\_space}(3)). + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_reg\_states\_iterate(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_backtrace.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_backtrace.man new file mode 100644 index 0000000..5699bbf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_backtrace.man @@ -0,0 +1,86 @@ +'\" t +.\" Manual page created with latex2man on Fri Aug 31 13:39:04 EEST 2012 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_BACKTRACE" "3" "31 August 2012" "Programming Library " "Programming Library " +.SH NAME +unw_backtrace +\-\- return backtrace for the calling program +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_backtrace(void **buffer, +int size); +.br +.PP +#include +.br +.PP +int +backtrace(void **buffer, +int size); +.br +.PP +.SH DESCRIPTION + +.PP +unw_backtrace() +is a convenient routine for obtaining the backtrace for +the calling program. The routine fills up to size +addresses in the array +pointed by buffer\&. +The routine is only available for local unwinding. +.PP +Note that many (but not all) systems provide practically identical function +called backtrace(). +The prototype for this function is usually obtained +by including the +header file \-\- a prototype for +backtrace() +is not provided by libunwind\&. +libunwind +weakly +aliases backtrace() +to unw_backtrace(), +so when a program +calling backtrace() +is linked against libunwind, +it may end up +calling unw_backtrace(). +.PP +.SH RETURN VALUE + +.PP +The routine returns the number of addresses stored in the array pointed by +buffer\&. +The return value may be zero to indicate that no addresses were +stored. +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_step(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_backtrace.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_backtrace.tex new file mode 100644 index 0000000..c383eeb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_backtrace.tex @@ -0,0 +1,54 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_backtrace}{David Mosberger-Tang}{Programming Library}{unw\_backtrace}unw\_backtrace -- return backtrace for the calling program +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_backtrace}(\Type{void~**}\Var{buffer}, \Type{int}~\Var{size});\\ + +\File{\#include $<$execinfo.h$>$}\\ + +\Type{int} \Func{backtrace}(\Type{void~**}\Var{buffer}, \Type{int}~\Var{size});\\ + +\section{Description} + +\Func{unw\_backtrace}() is a convenient routine for obtaining the backtrace for +the calling program. The routine fills up to \Var{size} addresses in the array +pointed by \Var{buffer}. The routine is only available for local unwinding. + +Note that many (but not all) systems provide practically identical function +called \Func{backtrace}(). The prototype for this function is usually obtained +by including the \File{$<$execinfo.h$>$} header file -- a prototype for +\Func{backtrace}() is not provided by \Prog{libunwind}. \Prog{libunwind} weakly +aliases \Func{backtrace}() to \Func{unw\_backtrace}(), so when a program +calling \Func{backtrace}() is linked against \Prog{libunwind}, it may end up +calling \Func{unw\_backtrace}(). + +\section{Return Value} + +The routine returns the number of addresses stored in the array pointed by +\Var{buffer}. The return value may be zero to indicate that no addresses were +stored. + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_step(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_create_addr_space.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_create_addr_space.man new file mode 100644 index 0000000..4aca13e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_create_addr_space.man @@ -0,0 +1,457 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_CREATE\\_ADDR\\_SPACE" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_create_addr_space +\-\- create address space for remote unwinding +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +unw_addr_space_t +unw_create_addr_space(unw_accessors_t *ap, +int +byteorder); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_create_addr_space() +routine creates a new unwind +address\-space and initializes it based on the call\-back routines +passed via the ap +pointer and the specified byteorder\&. +The call\-back routines are described in detail below. The +byteorder +can be set to 0 to request the default byte\-order of +the unwind target. To request a particular byte\-order, +byteorder +can be set to any constant defined by +\&. +In particular, __LITTLE_ENDIAN +would +request little\-endian byte\-order and __BIG_ENDIAN +would +request big\-endian byte\-order. Whether or not a particular byte\-order +is supported depends on the target platform. +.PP +.SH CALL\-BACK ROUTINES + +.PP +Libunwind +uses a set of call\-back routines to access the +information it needs to unwind a chain of stack\-frames. These +routines are specified via the ap +argument, which points to a +variable of type unw_accessors_t\&. +The contents of this +variable is copied into the newly\-created address space, so the +variable must remain valid only for the duration of the call to +unw_create_addr_space(). +.PP +The first argument to every call\-back routine is an address\-space +identifier (as) +and the last argument is an arbitrary, +application\-specified void\-pointer (arg). +When invoking a +call\-back routine, libunwind +sets the as +argument to the +address\-space on whose behalf the invocation is made and the arg +argument to the value that was specified when +unw_init_remote(3) +was called. +.PP +The synopsis and a detailed description of every call\-back routine +follows below. +.PP +.SS CALL\-BACK ROUTINE SYNOPSIS +.PP +int +find_proc_info(unw_addr_space_t +as, +.br +\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_word_t +ip, +unw_proc_info_t *pip, +.br +\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPint +need_unwind_info, +void *arg); +.br +void +put_unwind_info(unw_addr_space_t +as, +.br +\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_proc_info_t *pip, +void *arg); +.br +int +get_dyn_info_list_addr(unw_addr_space_t +as, +.br +\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_word_t *dilap, +void *arg); +.br +int +access_mem(unw_addr_space_t +as, +.br +\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_word_t +addr, +unw_word_t *valp, +.br +\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPint +write, +void *arg); +.br +int +access_reg(unw_addr_space_t +as, +.br +\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_regnum_t +regnum, +unw_word_t *valp, +.br +\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPint +write, +void *arg); +.br +int +access_fpreg(unw_addr_space_t +as, +.br +\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_regnum_t +regnum, +unw_fpreg_t *fpvalp, +.br +\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPint +write, +void *arg); +.br +int +resume(unw_addr_space_t +as, +.br +\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_cursor_t *cp, +void *arg); +.br +int +get_proc_name(unw_addr_space_t +as, +.br +\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_word_t +addr, +char *bufp, +.br +\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPsize_t +buf_len, +unw_word_t *offp, +.br +\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPvoid *arg); +.br +.PP +.SS FIND_PROC_INFO +.PP +Libunwind +invokes the find_proc_info() +call\-back to +locate the information need to unwind a particular procedure. The +ip +argument is an instruction\-address inside the procedure whose +information is needed. The pip +argument is a pointer to the +variable used to return the desired information. The type of this +variable is unw_proc_info_t\&. +See +unw_get_proc_info(3) +for details. Argument +need_unwind_info +is zero if the call\-back does not need to +provide values for the following members in the +unw_proc_info_t +structure: format, +unwind_info_size, +and unwind_info\&. +If +need_unwind_info +is non\-zero, valid values need to be returned +in these members. Furthermore, the contents of the memory addressed +by the unwind_info +member must remain valid until the info is +released via the put_unwind_info +call\-back (see below). +.PP +On successful completion, the find_proc_info() +call\-back must +return zero. Otherwise, the negative value of one of the +unw_error_t +error\-codes may be returned. In particular, this +call\-back may return \-UNW_ESTOPUNWIND +to signal the end of +the frame\-chain. +.PP +.SS PUT_UNWIND_INFO +.PP +Libunwind +invokes the put_unwind_info() +call\-back to +release the resources (such as memory) allocated by a previous call to +find_proc_info() +with the need_unwind_info +argument +set to a non\-zero value. The pip +argument has the same value as +the argument of the same name in the previous matching call to +find_proc_info(). +Note that libunwind +does \fInot\fP +invoke put_unwind_info +for calls to find_proc_info() +with a zero need_unwind_info +argument. +.PP +.SS GET_DYN_INFO_LIST_ADDR +.PP +Libunwind +invokes the get_dyn_info_list_addr() +call\-back to obtain the address of the head of the dynamic unwind\-info +registration list. The variable stored at the returned address must +have a type of unw_dyn_info_list_t +(see +_U_dyn_register(3)). +The dliap +argument is a pointer +to a variable of type unw_word_t +which is used to return the +address of the dynamic unwind\-info registration list. If no dynamic +unwind\-info registration list exist, the value pointed to by +dliap +must be cleared to zero. Libunwind +will cache the +value returned by get_dyn_info_list_addr() +if caching is +enabled for the given address\-space. The cache can be cleared with a +call to unw_flush_cache(). +.PP +On successful completion, the get_dyn_info_list_addr() +call\-back must return zero. Otherwise, the negative value of one of +the unw_error_t +error\-codes may be returned. +.PP +.SS ACCESS_MEM +.PP +Libunwind +invokes the access_mem() +call\-back to read +from or write to a word of memory in the target address\-space. The +address of the word to be accessed is passed in argument addr\&. +To read memory, libunwind +sets argument write +to zero and +valp +to point to the word that receives the read value. To +write memory, libunwind +sets argument write +to a non\-zero +value and valp +to point to the word that contains the value to +be written. The word that valp +points to is always in the +byte\-order of the host\-platform, regardless of the byte\-order of the +target. In other words, it is the responsibility of the call\-back +routine to convert between the target\&'s and the host\&'s byte\-order, if +necessary. +.PP +On successful completion, the access_mem() +call\-back must return zero. Otherwise, the negative value of one of +the unw_error_t +error\-codes may be returned. +.PP +.SS ACCESS_REG +.PP +Libunwind +invokes the access_reg() +call\-back to read +from or write to a scalar (non\-floating\-point) CPU register. The +index of the register to be accessed is passed in argument +regnum\&. +To read a register, libunwind +sets argument +write +to zero and valp +to point to the word that receives +the read value. To write a register, libunwind +sets argument +write +to a non\-zero value and valp +to point to the word +that contains the value to be written. The word that valp +points to is always in the byte\-order of the host\-platform, regardless +of the byte\-order of the target. In other words, it is the +responsibility of the call\-back routine to convert between the +target\&'s and the host\&'s byte\-order, if necessary. +.PP +On successful completion, the access_reg() +call\-back must +return zero. Otherwise, the negative value of one of the +unw_error_t +error\-codes may be returned. +.PP +.SS ACCESS_FPREG +.PP +Libunwind +invokes the access_fpreg() +call\-back to read +from or write to a floating\-point CPU register. The index of the +register to be accessed is passed in argument regnum\&. +To read a +register, libunwind +sets argument write +to zero and +fpvalp +to point to a variable of type unw_fpreg_t +that +receives the read value. To write a register, libunwind +sets +argument write +to a non\-zero value and fpvalp +to point to +the variable of type unw_fpreg_t +that contains the value to +be written. The word that fpvalp +points to is always in the +byte\-order of the host\-platform, regardless of the byte\-order of the +target. In other words, it is the responsibility of the call\-back +routine to convert between the target\&'s and the host\&'s byte\-order, if +necessary. +.PP +On successful completion, the access_fpreg() +call\-back must +return zero. Otherwise, the negative value of one of the +unw_error_t +error\-codes may be returned. +.PP +.SS RESUME +.PP +Libunwind +invokes the resume() +call\-back to resume +execution in the target address space. Argument cp +is the +unwind\-cursor that identifies the stack\-frame in which execution +should resume. By the time libunwind +invokes the resume +call\-back, it has already established the desired machine\- and +memory\-state via calls to the access_reg(), +access_fpreg, +and access_mem() +call\-backs. Thus, all +the call\-back needs to do is perform whatever action is needed to +actually resume execution. +.PP +The resume +call\-back is invoked only in response to a call to +unw_resume(3), +so applications which never invoke +unw_resume(3) +need not define the resume +callback. +.PP +On successful completion, the resume() +call\-back must return +zero. Otherwise, the negative value of one of the +unw_error_t +error\-codes may be returned. As a special case, +when resuming execution in the local address space, the call\-back will +not return on success. +.PP +.SS GET_PROC_NAME +.PP +Libunwind +invokes the get_proc_name() +call\-back to +obtain the procedure\-name of a static (not dynamically generated) +procedure. Argument addr +is an instruction\-address within the +procedure whose name is to be obtained. The bufp +argument is a +pointer to a character\-buffer used to return the procedure name. The +size of this buffer is specified in argument buf_len\&. +The +returned name must be terminated by a NUL character. If the +procedure\&'s name is longer than buf_len +bytes, it must be +truncated to buf_len\-1 +bytes, with the last byte in the +buffer set to the NUL character and \-UNW_ENOMEM +must be +returned. Argument offp +is a pointer to a word which is used to +return the byte\-offset relative to the start of the procedure whose +name is being returned. For example, if procedure foo() +starts +at address 0x40003000, then invoking get_proc_name() +with +addr +set to 0x40003080 should return a value of 0x80 in the word +pointed to by offp +(assuming the procedure is at least 0x80 +bytes long). +.PP +On successful completion, the get_proc_name() +call\-back must +return zero. Otherwise, the negative value of one of the +unw_error_t +error\-codes may be returned. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_create_addr_space() +returns a +non\-NULL +value that represents the newly created +address\-space. Otherwise, NULL +is returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_create_addr_space() +is thread\-safe but \fInot\fP +safe to use from a signal handler. +.PP +.SH SEE ALSO + +.PP +_U_dyn_register(3), +libunwind(3), +unw_destroy_addr_space(3), +unw_get_proc_info(3), +unw_init_remote(3), +unw_resume(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_create_addr_space.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_create_addr_space.tex new file mode 100644 index 0000000..8de0691 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_create_addr_space.tex @@ -0,0 +1,265 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_create\_addr\_space}{David Mosberger-Tang}{Programming Library}{unw\_create\_addr\_space}unw\_create\_addr\_space -- create address space for remote unwinding +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{unw\_addr\_space\_t} \Func{unw\_create\_addr\_space}(\Type{unw\_accessors\_t~*}\Var{ap}, \Type{int} \Var{byteorder});\\ + +\section{Description} + +The \Func{unw\_create\_addr\_space}() routine creates a new unwind +address-space and initializes it based on the call-back routines +passed via the \Var{ap} pointer and the specified \Var{byteorder}. +The call-back routines are described in detail below. The +\Var{byteorder} can be set to 0 to request the default byte-order of +the unwind target. To request a particular byte-order, +\Var{byteorder} can be set to any constant defined by +\File{$<$endian.h$>$}. In particular, \Const{\_\_LITTLE\_ENDIAN} would +request little-endian byte-order and \Const{\_\_BIG\_ENDIAN} would +request big-endian byte-order. Whether or not a particular byte-order +is supported depends on the target platform. + +\section{Call-back Routines} + +\Prog{Libunwind} uses a set of call-back routines to access the +information it needs to unwind a chain of stack-frames. These +routines are specified via the \Var{ap} argument, which points to a +variable of type \Type{unw\_accessors\_t}. The contents of this +variable is copied into the newly-created address space, so the +variable must remain valid only for the duration of the call to +\Func{unw\_create\_addr\_space}(). + +The first argument to every call-back routine is an address-space +identifier (\Var{as}) and the last argument is an arbitrary, +application-specified void-pointer (\Var{arg}). When invoking a +call-back routine, \Prog{libunwind} sets the \Var{as} argument to the +address-space on whose behalf the invocation is made and the \Var{arg} +argument to the value that was specified when +\Func{unw\_init\_remote}(3) was called. + +The synopsis and a detailed description of every call-back routine +follows below. + +\subsection{Call-back Routine Synopsis} + +\Type{int} \Func{find\_proc\_info}(\Type{unw\_addr\_space\_t} \Var{as},\\ +\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_word\_t} \Var{ip}, \Type{unw\_proc\_info\_t~*}\Var{pip},\\ +\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{int} \Var{need\_unwind\_info}, \Type{void~*}arg);\\ +\Type{void} \Func{put\_unwind\_info}(\Type{unw\_addr\_space\_t} \Var{as},\\ +\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_proc\_info\_t~*}pip, \Type{void~*}\Var{arg});\\ +\Type{int} \Func{get\_dyn\_info\_list\_addr}(\Type{unw\_addr\_space\_t} \Var{as},\\ +\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_word\_t~*}\Var{dilap}, \Type{void~*}\Var{arg});\\ +\Type{int} \Func{access\_mem}(\Var{unw\_addr\_space\_t} \Var{as},\\ +\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_word\_t} \Var{addr}, \Type{unw\_word\_t~*}\Var{valp},\\ +\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{int} \Var{write}, \Type{void~*}\Var{arg});\\ +\Type{int} \Func{access\_reg}(\Var{unw\_addr\_space\_t} \Var{as},\\ +\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_regnum\_t} \Var{regnum}, \Type{unw\_word\_t~*}\Var{valp},\\ +\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{int} \Var{write}, \Type{void~*}\Var{arg});\\ +\Type{int} \Func{access\_fpreg}(\Var{unw\_addr\_space\_t} \Var{as},\\ +\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_regnum\_t} \Var{regnum}, \Type{unw\_fpreg\_t~*}\Var{fpvalp},\\ +\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{int} \Var{write}, \Type{void~*}\Var{arg});\\ +\Type{int} \Func{resume}(\Var{unw\_addr\_space\_t} \Var{as},\\ +\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_cursor\_t~*}\Var{cp}, \Type{void~*}\Var{arg});\\ +\Type{int} \Func{get\_proc\_name}(\Type{unw\_addr\_space\_t} \Var{as},\\ +\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_word\_t} \Var{addr}, \Type{char~*}\Var{bufp},\\ +\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{size\_t} \Var{buf\_len}, \Type{unw\_word\_t~*}\Var{offp},\\ +\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{void~*}\Var{arg});\\ + +\subsection{find\_proc\_info} + +\Prog{Libunwind} invokes the \Func{find\_proc\_info}() call-back to +locate the information need to unwind a particular procedure. The +\Var{ip} argument is an instruction-address inside the procedure whose +information is needed. The \Var{pip} argument is a pointer to the +variable used to return the desired information. The type of this +variable is \Type{unw\_proc\_info\_t}. See +\Func{unw\_get\_proc\_info(3)} for details. Argument +\Var{need\_unwind\_info} is zero if the call-back does not need to +provide values for the following members in the +\Type{unw\_proc\_info\_t} structure: \Var{format}, +\Var{unwind\_info\_size}, and \Var{unwind\_info}. If +\Var{need\_unwind\_info} is non-zero, valid values need to be returned +in these members. Furthermore, the contents of the memory addressed +by the \Var{unwind\_info} member must remain valid until the info is +released via the \Func{put\_unwind\_info} call-back (see below). + +On successful completion, the \Func{find\_proc\_info}() call-back must +return zero. Otherwise, the negative value of one of the +\Type{unw\_error\_t} error-codes may be returned. In particular, this +call-back may return -\Const{UNW\_ESTOPUNWIND} to signal the end of +the frame-chain. + +\subsection{put\_unwind\_info} + +\Prog{Libunwind} invokes the \Func{put\_unwind\_info}() call-back to +release the resources (such as memory) allocated by a previous call to +\Func{find\_proc\_info}() with the \Var{need\_unwind\_info} argument +set to a non-zero value. The \Var{pip} argument has the same value as +the argument of the same name in the previous matching call to +\Func{find\_proc\_info}(). Note that \Prog{libunwind} does \emph{not} +invoke \Func{put\_unwind\_info} for calls to \Func{find\_proc\_info}() +with a zero \Var{need\_unwind\_info} argument. + + +\subsection{get\_dyn\_info\_list\_addr} + +\Prog{Libunwind} invokes the \Func{get\_dyn\_info\_list\_addr}() +call-back to obtain the address of the head of the dynamic unwind-info +registration list. The variable stored at the returned address must +have a type of \Type{unw\_dyn\_info\_list\_t} (see +\Func{\_U\_dyn\_register}(3)). The \Var{dliap} argument is a pointer +to a variable of type \Type{unw\_word\_t} which is used to return the +address of the dynamic unwind-info registration list. If no dynamic +unwind-info registration list exist, the value pointed to by +\Var{dliap} must be cleared to zero. \Prog{Libunwind} will cache the +value returned by \Func{get\_dyn\_info\_list\_addr}() if caching is +enabled for the given address-space. The cache can be cleared with a +call to \Func{unw\_flush\_cache}(). + +On successful completion, the \Func{get\_dyn\_info\_list\_addr}() +call-back must return zero. Otherwise, the negative value of one of +the \Type{unw\_error\_t} error-codes may be returned. + +\subsection{access\_mem} + +\Prog{Libunwind} invokes the \Func{access\_mem}() call-back to read +from or write to a word of memory in the target address-space. The +address of the word to be accessed is passed in argument \Var{addr}. +To read memory, \Prog{libunwind} sets argument \Var{write} to zero and +\Var{valp} to point to the word that receives the read value. To +write memory, \Prog{libunwind} sets argument \Var{write} to a non-zero +value and \Var{valp} to point to the word that contains the value to +be written. The word that \Var{valp} points to is always in the +byte-order of the host-platform, regardless of the byte-order of the +target. In other words, it is the responsibility of the call-back +routine to convert between the target's and the host's byte-order, if +necessary. + +On successful completion, the \Func{access\_mem}() +call-back must return zero. Otherwise, the negative value of one of +the \Type{unw\_error\_t} error-codes may be returned. + +\subsection{access\_reg} + +\Prog{Libunwind} invokes the \Func{access\_reg}() call-back to read +from or write to a scalar (non-floating-point) CPU register. The +index of the register to be accessed is passed in argument +\Var{regnum}. To read a register, \Prog{libunwind} sets argument +\Var{write} to zero and \Var{valp} to point to the word that receives +the read value. To write a register, \Prog{libunwind} sets argument +\Var{write} to a non-zero value and \Var{valp} to point to the word +that contains the value to be written. The word that \Var{valp} +points to is always in the byte-order of the host-platform, regardless +of the byte-order of the target. In other words, it is the +responsibility of the call-back routine to convert between the +target's and the host's byte-order, if necessary. + +On successful completion, the \Func{access\_reg}() call-back must +return zero. Otherwise, the negative value of one of the +\Type{unw\_error\_t} error-codes may be returned. + +\subsection{access\_fpreg} + +\Prog{Libunwind} invokes the \Func{access\_fpreg}() call-back to read +from or write to a floating-point CPU register. The index of the +register to be accessed is passed in argument \Var{regnum}. To read a +register, \Prog{libunwind} sets argument \Var{write} to zero and +\Var{fpvalp} to point to a variable of type \Type{unw\_fpreg\_t} that +receives the read value. To write a register, \Prog{libunwind} sets +argument \Var{write} to a non-zero value and \Var{fpvalp} to point to +the variable of type \Type{unw\_fpreg\_t} that contains the value to +be written. The word that \Var{fpvalp} points to is always in the +byte-order of the host-platform, regardless of the byte-order of the +target. In other words, it is the responsibility of the call-back +routine to convert between the target's and the host's byte-order, if +necessary. + +On successful completion, the \Func{access\_fpreg}() call-back must +return zero. Otherwise, the negative value of one of the +\Type{unw\_error\_t} error-codes may be returned. + +\subsection{resume} + +\Prog{Libunwind} invokes the \Func{resume}() call-back to resume +execution in the target address space. Argument \Var{cp} is the +unwind-cursor that identifies the stack-frame in which execution +should resume. By the time \Prog{libunwind} invokes the \Func{resume} +call-back, it has already established the desired machine- and +memory-state via calls to the \Func{access\_reg}(), +\Func{access\_fpreg}, and \Func{access\_mem}() call-backs. Thus, all +the call-back needs to do is perform whatever action is needed to +actually resume execution. + +The \Func{resume} call-back is invoked only in response to a call to +\Func{unw\_resume}(3), so applications which never invoke +\Func{unw\_resume}(3) need not define the \Func{resume} callback. + +On successful completion, the \Func{resume}() call-back must return +zero. Otherwise, the negative value of one of the +\Type{unw\_error\_t} error-codes may be returned. As a special case, +when resuming execution in the local address space, the call-back will +not return on success. + +\subsection{get\_proc\_name} + +\Prog{Libunwind} invokes the \Func{get\_proc\_name}() call-back to +obtain the procedure-name of a static (not dynamically generated) +procedure. Argument \Var{addr} is an instruction-address within the +procedure whose name is to be obtained. The \Var{bufp} argument is a +pointer to a character-buffer used to return the procedure name. The +size of this buffer is specified in argument \Var{buf\_len}. The +returned name must be terminated by a NUL character. If the +procedure's name is longer than \Var{buf\_len} bytes, it must be +truncated to \Var{buf\_len}\Prog{-1} bytes, with the last byte in the +buffer set to the NUL character and -\Const{UNW\_ENOMEM} must be +returned. Argument \Var{offp} is a pointer to a word which is used to +return the byte-offset relative to the start of the procedure whose +name is being returned. For example, if procedure \Func{foo}() starts +at address 0x40003000, then invoking \Func{get\_proc\_name}() with +\Var{addr} set to 0x40003080 should return a value of 0x80 in the word +pointed to by \Var{offp} (assuming the procedure is at least 0x80 +bytes long). + +On successful completion, the \Func{get\_proc\_name}() call-back must +return zero. Otherwise, the negative value of one of the +\Type{unw\_error\_t} error-codes may be returned. + + +\section{Return Value} + +On successful completion, \Func{unw\_create\_addr\_space}() returns a +non-\Const{NULL} value that represents the newly created +address-space. Otherwise, \Const{NULL} is returned. + +\section{Thread and Signal Safety} + +\Func{unw\_create\_addr\_space}() is thread-safe but \emph{not} +safe to use from a signal handler. + +\section{See Also} + +\SeeAlso{\_U\_dyn\_register(3)}, +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_destroy\_addr\_space(3)}, +\SeeAlso{unw\_get\_proc\_info(3)}, +\SeeAlso{unw\_init\_remote(3)}, +\SeeAlso{unw\_resume(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_destroy_addr_space.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_destroy_addr_space.man new file mode 100644 index 0000000..90c9777 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_destroy_addr_space.man @@ -0,0 +1,57 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_DESTROY\\_ADDR\\_SPACE" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_destroy_addr_space +\-\- destroy unwind address space +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +void +unw_destroy_addr_space(unw_addr_space_t +as); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_destroy_addr_space() +routine destroys the +address space specified by argument as +and thereby releases +all associated resources (such as memory). +.PP +Applications must not destroy the local address space +unw_local_addr_space\&. +Attempting to do so results in +undefined behavior (e.g., the application may crash). +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_create_addr_space(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_destroy_addr_space.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_destroy_addr_space.tex new file mode 100644 index 0000000..a66b10b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_destroy_addr_space.tex @@ -0,0 +1,40 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_destroy\_addr\_space}{David Mosberger-Tang}{Programming Library}{unw\_destroy\_addr\_space}unw\_destroy\_addr\_space -- destroy unwind address space +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{void} \Func{unw\_destroy\_addr\_space}(\Type{unw\_addr\_space\_t} \Var{as});\\ + +\section{Description} + +The \Func{unw\_destroy\_addr\_space}() routine destroys the +address space specified by argument \Var{as} and thereby releases +all associated resources (such as memory). + +Applications must not destroy the local address space +\Var{unw\_local\_addr\_space}. Attempting to do so results in +undefined behavior (e.g., the application may crash). + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_create\_addr\_space(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_flush_cache.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_flush_cache.man new file mode 100644 index 0000000..627449e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_flush_cache.man @@ -0,0 +1,93 @@ +'\" t +.\" Manual page created with latex2man on Fri Dec 2 16:09:33 PST 2016 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_FLUSH\\_CACHE" "3" "02 December 2016" "Programming Library " "Programming Library " +.SH NAME +unw_flush_cache +\-\- flush cached info +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +void +unw_flush_cache(unw_addr_space_t +as, +unw_word_t +lo, +unw_word_t +hi); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_flush_cache() +routine flushes all cached info as it +relates to address\-range lo +to hi +(non\-inclusive) in the +target address\-space as\&. +In addition, all info cached for +address\-space as +that is not tied to a particular code\-range is +also flushed. For example, the address of the dynamic registration +list is not tied to a code\-range and its cached value (if any) is +flushed by a call to this routine. The address range specified by +lo +and hi +should be understood as a hint: +unw_flush_cache() +may flush more information than requested, +but \fInever\fP +less. In other words, unw_flush_cache() +may +overflush, but not underflush. +.PP +As a special case, if arguments lo +and hi +are both 0, all +information cached on behalf of address space as +is flushed. +.PP +.SH RETURN VALUE + +.PP +The unw_flush_cache() +routine cannot fail and does not +return a value. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +The unw_flush_cache() +routine is thread\-safe as well as safe to +use from a signal handler. +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_set_caching_policy(3) +unw_set_cache_size(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_flush_cache.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_flush_cache.tex new file mode 100644 index 0000000..32319db --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_flush_cache.tex @@ -0,0 +1,58 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_flush\_cache}{David Mosberger-Tang}{Programming Library}{unw\_flush\_cache}unw\_flush\_cache -- flush cached info +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{void} \Func{unw\_flush\_cache}(\Type{unw\_addr\_space\_t} \Var{as}, \Type{unw\_word\_t} \Var{lo}, \Type{unw\_word\_t} \Var{hi});\\ + +\section{Description} + +The \Func{unw\_flush\_cache}() routine flushes all cached info as it +relates to address-range \Var{lo} to \Var{hi} (non-inclusive) in the +target address-space \Var{as}. In addition, all info cached for +address-space \Var{as} that is not tied to a particular code-range is +also flushed. For example, the address of the dynamic registration +list is not tied to a code-range and its cached value (if any) is +flushed by a call to this routine. The address range specified by +\Var{lo} and \Var{hi} should be understood as a hint: +\Func{unw\_flush\_cache}() may flush more information than requested, +but \emph{never} less. In other words, \Func{unw\_flush\_cache}() may +overflush, but not underflush. + +As a special case, if arguments \Var{lo} and \Var{hi} are both 0, all +information cached on behalf of address space \Var{as} is flushed. + +\section{Return Value} + +The \Func{unw\_flush\_cache}() routine cannot fail and does not +return a value. + +\section{Thread and Signal Safety} + +The \Func{unw\_flush\_cache}() routine is thread-safe as well as safe to +use from a signal handler. + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_set\_caching\_policy(3)} +\SeeAlso{unw\_set\_cache\_size(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_accessors.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_accessors.man new file mode 100644 index 0000000..83fe4fc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_accessors.man @@ -0,0 +1,79 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_GET\\_ACCESSORS" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_get_accessors +\-\- get pointer to accessor call\-backs +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +unw_accessors_t *unw_get_accessors(unw_addr_space_t as); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_get_accessors() +routine returns a pointer to a +unw_accessors_t +structure, which contains the call\-back +routines that were specified when address space as +was created +(see unw_create_addr_space(3)). +The returned pointer is +guaranteed to remain valid until address space as +is destroyed +by a call to unw_destroy_addr_space(3). +.PP +Note that unw_get_accessors() +can be used to retrieve the +call\-back routines for the local address space +unw_local_addr_space\&. +.PP +.SH RETURN VALUE + +.PP +The unw_get_accessors() +routine cannot fail and always +returns a valid (non\-NULL) +pointer to an +unw_accessors_t +structure. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +The unw_get_accessors() +routine is thread\-safe as well as +safe to use from a signal handler. +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_create_addr_space(3), +unw_destroy_addr_space(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_accessors.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_accessors.tex new file mode 100644 index 0000000..bf344a3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_accessors.tex @@ -0,0 +1,55 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_get\_accessors}{David Mosberger-Tang}{Programming Library}{unw\_get\_accessors}unw\_get\_accessors -- get pointer to accessor call-backs +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{unw\_accessors\_t~*}\Func{unw\_get\_accessors}(\Type{unw\_addr\_space\_t~}\Var{as});\\ + +\section{Description} + +The \Func{unw\_get\_accessors}() routine returns a pointer to a +\Type{unw\_accessors\_t} structure, which contains the call-back +routines that were specified when address space \Var{as} was created +(see \Func{unw\_create\_addr\_space}(3)). The returned pointer is +guaranteed to remain valid until address space \Var{as} is destroyed +by a call to \Func{unw\_destroy\_addr\_space}(3). + +Note that \Func{unw\_get\_accessors}() can be used to retrieve the +call-back routines for the local address space +\Var{unw\_local\_addr\_space}. + +\section{Return Value} + +The \Func{unw\_get\_accessors}() routine cannot fail and always +returns a valid (non-\Const{NULL}) pointer to an +\Type{unw\_accessors\_t} structure. + +\section{Thread and Signal Safety} + +The \Func{unw\_get\_accessors}() routine is thread-safe as well as +safe to use from a signal handler. + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_create\_addr\_space(3)}, +\SeeAlso{unw\_destroy\_addr\_space(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_fpreg.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_fpreg.man new file mode 100644 index 0000000..5e54ca1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_fpreg.man @@ -0,0 +1,111 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_GET\\_FPREG" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_get_fpreg +\-\- get contents of floating\-point register +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_get_fpreg(unw_cursor_t *cp, +unw_regnum_t +reg, +unw_fpreg_t *valp); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_get_fpreg() +routine reads the value of floating\-point +register reg +in the stack frame identified by cursor cp +and stores the value in the variable pointed to by valp\&. +.PP +The register numbering is target\-dependent and described in separate +manual pages (e.g., libunwind\-ia64(3) for the IA\-64 target). +Furthermore, the exact set of accessible registers may depend on the +type of frame that cp +is referring to. For ordinary stack +frames, it is normally possible to access only the preserved +(``callee\-saved\&'') registers and frame\-related registers (such as the +stack\-pointer). However, for signal frames (see +unw_is_signal_frame(3)), +it is usually possible to access +all registers. +.PP +Note that unw_get_fpreg() +can only read the contents of +floating\-point registers. See unw_get_fpreg(3) +for a way to +read registers which fit in a single word. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_get_fpreg() +returns 0. +Otherwise the negative value of one of the error\-codes below is +returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_get_fpreg() +is thread\-safe as well as safe to use +from a signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_EUNSPEC + An unspecified error occurred. +.TP +UNW_EBADREG + An attempt was made to read a register +that is either invalid or not accessible in the current frame. +.PP +In addition, unw_get_fpreg() +may return any error returned by +the access_mem(), +access_reg(), +and +access_fpreg() +call\-backs (see +unw_create_addr_space(3)). +.PP +.SH SEE ALSO + +.PP +libunwind(3), +libunwind\-ia64(3), +unw_get_reg(3), +unw_is_fpreg(3), +unw_is_signal_frame(3), +unw_set_fpreg(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_fpreg.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_fpreg.tex new file mode 100644 index 0000000..dd679ad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_fpreg.tex @@ -0,0 +1,77 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_get\_fpreg}{David Mosberger-Tang}{Programming Library}{unw\_get\_fpreg}unw\_get\_fpreg -- get contents of floating-point register +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_get\_fpreg}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{unw\_regnum\_t} \Var{reg}, \Type{unw\_fpreg\_t~*}\Var{valp});\\ + +\section{Description} + +The \Func{unw\_get\_fpreg}() routine reads the value of floating-point +register \Var{reg} in the stack frame identified by cursor \Var{cp} +and stores the value in the variable pointed to by \Var{valp}. + +The register numbering is target-dependent and described in separate +manual pages (e.g., libunwind-ia64(3) for the IA-64 target). +Furthermore, the exact set of accessible registers may depend on the +type of frame that \Var{cp} is referring to. For ordinary stack +frames, it is normally possible to access only the preserved +(``callee-saved'') registers and frame-related registers (such as the +stack-pointer). However, for signal frames (see +\Func{unw\_is\_signal\_frame}(3)), it is usually possible to access +all registers. + +Note that \Func{unw\_get\_fpreg}() can only read the contents of +floating-point registers. See \Func{unw\_get\_fpreg}(3) for a way to +read registers which fit in a single word. + +\section{Return Value} + +On successful completion, \Func{unw\_get\_fpreg}() returns 0. +Otherwise the negative value of one of the error-codes below is +returned. + +\section{Thread and Signal Safety} + +\Func{unw\_get\_fpreg}() is thread-safe as well as safe to use +from a signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred. +\item[\Const{UNW\_EBADREG}] An attempt was made to read a register + that is either invalid or not accessible in the current frame. +\end{Description} +In addition, \Func{unw\_get\_fpreg}() may return any error returned by +the \Func{access\_mem}(), \Func{access\_reg}(), and +\Func{access\_fpreg}() call-backs (see +\Func{unw\_create\_addr\_space}(3)). + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{libunwind-ia64(3)}, +\SeeAlso{unw\_get\_reg(3)}, +\SeeAlso{unw\_is\_fpreg(3)}, +\SeeAlso{unw\_is\_signal\_frame(3)}, +\SeeAlso{unw\_set\_fpreg(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info.man new file mode 100644 index 0000000..09eadee --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info.man @@ -0,0 +1,203 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_GET\\_PROC\\_INFO" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_get_proc_info +\-\- get info on current procedure +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_get_proc_info(unw_cursor_t *cp, +unw_proc_info_t *pip); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_get_proc_info() +routine returns auxiliary +information about the procedure that created the stack frame +identified by argument cp\&. +The pip +argument is a pointer +to a structure of type unw_proc_info_t +which is used to +return the information. The unw_proc_info_t +has the +following members: +.TP +unw_word_t start_ip + The address of the first +instruction of the procedure. If this address cannot be determined +(e.g., due to lack of unwind information), the start_ip +member is cleared to 0. +.br +.TP +unw_word_t end_ip + The address of the first +instruction \fIbeyond\fP +the end of the procedure. If this address +cannot be determined (e.g., due to lack of unwind information), +the end_ip +member is cleared to 0. +.br +.TP +unw_word_t lsda + The address of the +language\-specific data\-area (LSDA). This area normally contains +language\-specific information needed during exception handling. If +the procedure has no such area, this member is cleared to 0. +.br +.TP +unw_word_t handler + The address of the exception +handler routine. This is sometimes called the \fIpersonality\fP +routine. If the procedure does not define +a personality routine, the handler +member is cleared to 0. +.br +.TP +unw_word_t gp + The global\-pointer of the +procedure. On platforms that do not use a global pointer, this +member may contain an undefined value. On all other platforms, it +must be set either to the correct global\-pointer value of the +procedure or to 0 if the proper global\-pointer cannot be +obtained for some reason. +.br +.TP +unw_word_t flags + A set of flags. There are +currently no target\-independent flags. For the IA\-64 target, the +flag UNW_PI_FLAG_IA64_RBS_SWITCH +is set if the +procedure may switch the register\-backing store. +.br +.TP +int format + The format of the unwind\-info for this +procedure. If the unwind\-info consists of dynamic procedure info, +format +is equal to UNW_INFO_FORMAT_DYNAMIC\&. +If the +unwind\-info consists of a (target\-specific) unwind table, it is +equal to to UNW_INFO_FORMAT_TABLE\&. +All other values are +reserved for future use by libunwind\&. +This member exists +for use by the find_proc_info() +call\-back (see +unw_create_addr_space(3)). +The +unw_get_proc_info() +routine +may return an undefined value in this member. +.br +.TP +int unwind_info_size + The size of the unwind\-info +in bytes. This member exists for use by the +find_proc_info() +call\-back (see +unw_create_addr_space(3)). +The +unw_get_proc_info() +routine +may return an undefined value in this member. +.br +.TP +void *unwind_info + The pointer to the unwind\-info. +If no unwind info is available, this member must be set to +NULL\&. +This member exists for use by the +find_proc_info() +call\-back (see +unw_create_addr_space(3)). +The +unw_get_proc_info() +routine +may return an undefined value in this member. +.br +.PP +Note that for the purposes of libunwind, +the code of a +procedure is assumed to occupy a single, contiguous range of +addresses. For this reason, it is alwas possible to describe the +extent of a procedure with the start_ip +and end_ip +members. If a single function/routine is split into multiple, +discontiguous pieces, libunwind +will treat each piece as a +separate procedure. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_get_proc_info() +returns 0. +Otherwise the negative value of one of the error\-codes below is +returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_get_proc_info() +is thread\-safe. If cursor cp +is +in the local address\-space, this routine is also safe to use from a +signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_EUNSPEC + An unspecified error occurred. +.TP +UNW_ENOINFO + Libunwind +was unable to locate +unwind\-info for the procedure. +.TP +UNW_EBADVERSION + The unwind\-info for the procedure has +version or format that is not understood by libunwind\&. +.PP +In addition, unw_get_proc_info() +may return any error +returned by the access_mem() +call\-back (see +unw_create_addr_space(3)). +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_create_addr_space(3), +unw_get_proc_name(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info.tex new file mode 100644 index 0000000..72621f1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info.tex @@ -0,0 +1,123 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_get\_proc\_info}{David Mosberger-Tang}{Programming Library}{unw\_get\_proc\_info}unw\_get\_proc\_info -- get info on current procedure +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_get\_proc\_info}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{unw\_proc\_info\_t~*}\Var{pip});\\ + +\section{Description} + +The \Func{unw\_get\_proc\_info}() routine returns auxiliary +information about the procedure that created the stack frame +identified by argument \Var{cp}. The \Var{pip} argument is a pointer +to a structure of type \Type{unw\_proc\_info\_t} which is used to +return the information. The \Type{unw\_proc\_info\_t} has the +following members: +\begin{description} +\item[\Type{unw\_word\_t} \Var{start\_ip}] The address of the first + instruction of the procedure. If this address cannot be determined + (e.g., due to lack of unwind information), the \Var{start\_ip} + member is cleared to 0. \\ +\item[\Type{unw\_word\_t} \Var{end\_ip}] The address of the first + instruction \emph{beyond} the end of the procedure. If this address + cannot be determined (e.g., due to lack of unwind information), + the \Var{end\_ip} member is cleared to 0. \\ +\item[\Type{unw\_word\_t} \Var{lsda}] The address of the + language-specific data-area (LSDA). This area normally contains + language-specific information needed during exception handling. If + the procedure has no such area, this member is cleared to 0. \\ +\item[\Type{unw\_word\_t} \Var{handler}] The address of the exception + handler routine. This is sometimes called the \emph{personality} + routine. If the procedure does not define + a personality routine, the \Var{handler} member is cleared to 0. \\ +\item[\Type{unw\_word\_t} \Var{gp}] The global-pointer of the + procedure. On platforms that do not use a global pointer, this + member may contain an undefined value. On all other platforms, it + must be set either to the correct global-pointer value of the + procedure or to 0 if the proper global-pointer cannot be + obtained for some reason. \\ +\item[\Type{unw\_word\_t} \Var{flags}] A set of flags. There are + currently no target-independent flags. For the IA-64 target, the + flag \Const{UNW\_PI\_FLAG\_IA64\_RBS\_SWITCH} is set if the + procedure may switch the register-backing store.\\ +\item[\Type{int} \Var{format}] The format of the unwind-info for this + procedure. If the unwind-info consists of dynamic procedure info, + \Var{format} is equal to \Const{UNW\_INFO\_FORMAT\_DYNAMIC}. If the + unwind-info consists of a (target-specific) unwind table, it is + equal to to \Const{UNW\_INFO\_FORMAT\_TABLE}. All other values are + reserved for future use by \Prog{libunwind}. This member exists + for use by the \Func{find\_proc\_info}() call-back (see + \Func{unw\_create\_addr\_space}(3)). The + \Func{unw\_get\_proc\_info}() routine + may return an undefined value in this member. \\ +\item[\Type{int} \Var{unwind\_info\_size}] The size of the unwind-info + in bytes. This member exists for use by the + \Func{find\_proc\_info}() call-back (see + \Func{unw\_create\_addr\_space}(3)). The + \Func{unw\_get\_proc\_info}() routine + may return an undefined value in this member.\\ +\item[\Type{void~*}\Var{unwind\_info}] The pointer to the unwind-info. + If no unwind info is available, this member must be set to + \Const{NULL}. This member exists for use by the + \Func{find\_proc\_info}() call-back (see + \Func{unw\_create\_addr\_space}(3)). The + \Func{unw\_get\_proc\_info}() routine + may return an undefined value in this member.\\ +\end{description} +Note that for the purposes of \Prog{libunwind}, the code of a +procedure is assumed to occupy a single, contiguous range of +addresses. For this reason, it is alwas possible to describe the +extent of a procedure with the \Var{start\_ip} and \Var{end\_ip} +members. If a single function/routine is split into multiple, +discontiguous pieces, \Prog{libunwind} will treat each piece as a +separate procedure. + +\section{Return Value} + +On successful completion, \Func{unw\_get\_proc\_info}() returns 0. +Otherwise the negative value of one of the error-codes below is +returned. + +\section{Thread and Signal Safety} + +\Func{unw\_get\_proc\_info}() is thread-safe. If cursor \Var{cp} is +in the local address-space, this routine is also safe to use from a +signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred. +\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to locate + unwind-info for the procedure. +\item[\Const{UNW\_EBADVERSION}] The unwind-info for the procedure has + version or format that is not understood by \Prog{libunwind}. +\end{Description} +In addition, \Func{unw\_get\_proc\_info}() may return any error +returned by the \Func{access\_mem}() call-back (see +\Func{unw\_create\_addr\_space}(3)). + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_create\_addr\_space(3)}, +\SeeAlso{unw\_get\_proc\_name(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.man new file mode 100644 index 0000000..a347a1d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.man @@ -0,0 +1,134 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_GET\\_PROC\\_INFO\\_BY\\_IP" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_get_proc_info_by_ip +\-\- get procedure info by IP +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_get_proc_info_by_ip(unw_addr_space_t as, +unw_word_t ip, +unw_proc_info_t *pip, +void *arg); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_get_proc_info_by_ip() +routine returns the same +kind of auxiliary information about a procedure as +unw_get_proc_info(), +except that the info is looked up by +instruction\-pointer (IP) instead of a cursor. This is more flexible +because it is possible to look up the info for an arbitrary procedure, +even if it is not part of the current call\-chain. However, since it +is more flexible, it also tends to run slower (and often much slower) +than unw_get_proc_info(). +.PP +The routine expects the followins arguments: as +is the +address\-space in which the instruction\-pointer should be looked up. +For a look\-up in the local address\-space, +unw_local_addr_space +can be passed for this argument. +Argument ip +is the instruction\-pointer for which the procedure +info should be looked up and pip +is a pointer to a structure of +type unw_proc_info_t +which is used to return the info. +Lastly, arg +is the address\-space argument that should be used +when accessing the address\-space. It has the same purpose as the +argument of the same name for unw_init_remote(). +When +accessing the local address\-space (first argument is +unw_local_addr_space), +NULL +must be passed for this +argument. +.PP +Note that for the purposes of libunwind, +the code of a +procedure is assumed to occupy a single, contiguous range of +addresses. For this reason, it is alwas possible to describe the +extent of a procedure with the start_ip +and end_ip +members. If a single function/routine is split into multiple, +discontiguous pieces, libunwind +will treat each piece as a +separate procedure. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_get_proc_info_by_ip() +returns 0. Otherwise the negative value of one of the error\-codes +below is returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_get_proc_info() +is thread\-safe. If the local +address\-space is passed in argument as, +this routine is also +safe to use from a signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_EUNSPEC + An unspecified error occurred. +.TP +UNW_ENOINFO + Libunwind +was unable to locate +unwind\-info for the procedure. +.TP +UNW_EBADVERSION + The unwind\-info for the procedure has +version or format that is not understood by libunwind\&. +.PP +In addition, unw_get_proc_info() +may return any error +returned by the access_mem() +call\-back (see +unw_create_addr_space(3)). +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_create_addr_space(3), +unw_get_proc_name(3), +unw_get_proc_info(3), +unw_init_remote(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.tex new file mode 100644 index 0000000..5e1d5d2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.tex @@ -0,0 +1,91 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_get\_proc\_info\_by\_ip}{David Mosberger-Tang}{Programming Library}{unw\_get\_proc\_info\_by\_ip}unw\_get\_proc\_info\_by\_ip -- get procedure info by IP +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_get\_proc\_info\_by\_ip}(\Type{unw\_addr\_space\_t~}\Var{as}, \Type{unw\_word\_t~}\Var{ip}, \Type{unw\_proc\_info\_t~*}\Var{pip}, \Type{void~*}\Var{arg});\\ + +\section{Description} + +The \Func{unw\_get\_proc\_info\_by\_ip}() routine returns the same +kind of auxiliary information about a procedure as +\Func{unw\_get\_proc\_info}(), except that the info is looked up by +instruction-pointer (IP) instead of a cursor. This is more flexible +because it is possible to look up the info for an arbitrary procedure, +even if it is not part of the current call-chain. However, since it +is more flexible, it also tends to run slower (and often much slower) +than \Func{unw\_get\_proc\_info}(). + +The routine expects the followins arguments: \Var{as} is the +address-space in which the instruction-pointer should be looked up. +For a look-up in the local address-space, +\Var{unw\_local\_addr\_space} can be passed for this argument. +Argument \Var{ip} is the instruction-pointer for which the procedure +info should be looked up and \Var{pip} is a pointer to a structure of +type \Type{unw\_proc\_info\_t} which is used to return the info. +Lastly, \Var{arg} is the address-space argument that should be used +when accessing the address-space. It has the same purpose as the +argument of the same name for \Func{unw\_init\_remote}(). When +accessing the local address-space (first argument is +\Var{unw\_local\_addr\_space}), \Const{NULL} must be passed for this +argument. + +Note that for the purposes of \Prog{libunwind}, the code of a +procedure is assumed to occupy a single, contiguous range of +addresses. For this reason, it is alwas possible to describe the +extent of a procedure with the \Var{start\_ip} and \Var{end\_ip} +members. If a single function/routine is split into multiple, +discontiguous pieces, \Prog{libunwind} will treat each piece as a +separate procedure. + +\section{Return Value} + +On successful completion, \Func{unw\_get\_proc\_info\_by\_ip}() +returns 0. Otherwise the negative value of one of the error-codes +below is returned. + +\section{Thread and Signal Safety} + +\Func{unw\_get\_proc\_info}() is thread-safe. If the local +address-space is passed in argument \Var{as}, this routine is also +safe to use from a signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred. +\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to locate + unwind-info for the procedure. +\item[\Const{UNW\_EBADVERSION}] The unwind-info for the procedure has + version or format that is not understood by \Prog{libunwind}. +\end{Description} +In addition, \Func{unw\_get\_proc\_info}() may return any error +returned by the \Func{access\_mem}() call-back (see +\Func{unw\_create\_addr\_space}(3)). + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_create\_addr\_space(3)}, +\SeeAlso{unw\_get\_proc\_name(3)}, +\SeeAlso{unw\_get\_proc\_info(3)}, +\SeeAlso{unw\_init\_remote(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_name.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_name.man new file mode 100644 index 0000000..8b2bd06 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_name.man @@ -0,0 +1,123 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_GET\\_PROC\\_NAME" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_get_proc_name +\-\- get name of current procedure +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_get_proc_name(unw_cursor_t *cp, +char *bufp, +size_t +len, +unw_word_t *offp); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_get_proc_name() +routine returns the name of the +procedure that created the stack frame identified by argument +cp\&. +The bufp +argument is a pointer to a character buffer +that is at least len +bytes long. This buffer is used to return +the name of the procedure. The offp +argument is a pointer to a +word that is used to return the byte\-offset of the instruction\-pointer +saved in the stack frame identified by cp, +relative to the start +of the procedure. For example, if procedure foo() +starts at +address 0x40003000, then invoking unw_get_proc_name() +on a +stack frame with an instruction\-pointer value of 0x40003080 would +return a value of 0x80 in the word pointed to by offp +(assuming +the procedure is at least 0x80 bytes long). +.PP +Note that on some platforms there is no reliable way to distinguish +between procedure names and ordinary labels. Furthermore, if symbol +information has been stripped from a program, procedure names may be +completely unavailable or may be limited to those exported via a +dynamic symbol table. In such cases, unw_get_proc_name() +may return the name of a label or a preceeding (nearby) procedure. +However, the offset returned through offp +is always relative to +the returned name, which ensures that the value (address) of the +returned name plus the returned offset will always be equal to the +instruction\-pointer of the stack frame identified by cp\&. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_get_proc_name() +returns 0. +Otherwise the negative value of one of the error\-codes below is +returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_get_proc_name() +is thread\-safe. If cursor cp +is +in the local address\-space, this routine is also safe to use from a +signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_EUNSPEC + An unspecified error occurred. +.TP +UNW_ENOINFO + Libunwind +was unable to determine +the name of the procedure. +.TP +UNW_ENOMEM + The procedure name is too long to fit +in the buffer provided. A truncated version of the name has been +returned. +.PP +In addition, unw_get_proc_name() +may return any error +returned by the access_mem() +call\-back (see +unw_create_addr_space(3)). +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_get_proc_info(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_name.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_name.tex new file mode 100644 index 0000000..c413990 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_proc_name.tex @@ -0,0 +1,82 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_get\_proc\_name}{David Mosberger-Tang}{Programming Library}{unw\_get\_proc\_name}unw\_get\_proc\_name -- get name of current procedure +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_get\_proc\_name}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{char~*}\Var{bufp}, \Type{size\_t} \Var{len}, \Type{unw\_word\_t~*}\Var{offp});\\ + +\section{Description} + +The \Func{unw\_get\_proc\_name}() routine returns the name of the +procedure that created the stack frame identified by argument +\Var{cp}. The \Var{bufp} argument is a pointer to a character buffer +that is at least \Var{len} bytes long. This buffer is used to return +the name of the procedure. The \Var{offp} argument is a pointer to a +word that is used to return the byte-offset of the instruction-pointer +saved in the stack frame identified by \Var{cp}, relative to the start +of the procedure. For example, if procedure \Func{foo}() starts at +address 0x40003000, then invoking \Func{unw\_get\_proc\_name}() on a +stack frame with an instruction-pointer value of 0x40003080 would +return a value of 0x80 in the word pointed to by \Var{offp} (assuming +the procedure is at least 0x80 bytes long). + +Note that on some platforms there is no reliable way to distinguish +between procedure names and ordinary labels. Furthermore, if symbol +information has been stripped from a program, procedure names may be +completely unavailable or may be limited to those exported via a +dynamic symbol table. In such cases, \Func{unw\_get\_proc\_name}() +may return the name of a label or a preceeding (nearby) procedure. +However, the offset returned through \Var{offp} is always relative to +the returned name, which ensures that the value (address) of the +returned name plus the returned offset will always be equal to the +instruction-pointer of the stack frame identified by \Var{cp}. + +\section{Return Value} + +On successful completion, \Func{unw\_get\_proc\_name}() returns 0. +Otherwise the negative value of one of the error-codes below is +returned. + +\section{Thread and Signal Safety} + +\Func{unw\_get\_proc\_name}() is thread-safe. If cursor \Var{cp} is +in the local address-space, this routine is also safe to use from a +signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred. +\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to determine + the name of the procedure. +\item[\Const{UNW\_ENOMEM}] The procedure name is too long to fit + in the buffer provided. A truncated version of the name has been + returned. +\end{Description} +In addition, \Func{unw\_get\_proc\_name}() may return any error +returned by the \Func{access\_mem}() call-back (see +\Func{unw\_create\_addr\_space}(3)). + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_get\_proc\_info(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_reg.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_reg.man new file mode 100644 index 0000000..83e8bb4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_reg.man @@ -0,0 +1,112 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_GET\\_REG" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_get_reg +\-\- get register contents +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_get_reg(unw_cursor_t *cp, +unw_regnum_t +reg, +unw_word_t *valp); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_get_reg() +routine reads the value of register +reg +in the stack frame identified by cursor cp +and stores +the value in the word pointed to by valp\&. +.PP +The register numbering is target\-dependent and described in separate +manual pages (e.g., libunwind\-ia64(3) for the IA\-64 target). +Furthermore, the exact set of accessible registers may depend on the +type of frame that cp +is referring to. For ordinary stack +frames, it is normally possible to access only the preserved +(``callee\-saved\&'') registers and frame\-related registers (such as the +stack\-pointer). However, for signal frames (see +unw_is_signal_frame(3)), +it is usually possible to access +all registers. +.PP +Note that unw_get_reg() +can only read the contents of +registers whose values fit in a single word. See +unw_get_fpreg(3) +for a way to read registers which do not fit +this constraint. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_get_reg() +returns 0. +Otherwise the negative value of one of the error\-codes below is +returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_get_reg() +is thread\-safe as well as safe to use +from a signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_EUNSPEC + An unspecified error occurred. +.TP +UNW_EBADREG + An attempt was made to read a register +that is either invalid or not accessible in the current frame. +.PP +In addition, unw_get_reg() +may return any error returned by +the access_mem(), +access_reg(), +and +access_fpreg() +call\-backs (see +unw_create_addr_space(3)). +.PP +.SH SEE ALSO + +.PP +libunwind(3), +libunwind\-ia64(3), +unw_get_fpreg(3), +unw_is_signal_frame(3), +unw_set_reg(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_reg.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_reg.tex new file mode 100644 index 0000000..b66e8c0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_get_reg.tex @@ -0,0 +1,77 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_get\_reg}{David Mosberger-Tang}{Programming Library}{unw\_get\_reg}unw\_get\_reg -- get register contents +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_get\_reg}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{unw\_regnum\_t} \Var{reg}, \Type{unw\_word\_t~*}\Var{valp});\\ + +\section{Description} + +The \Func{unw\_get\_reg}() routine reads the value of register +\Var{reg} in the stack frame identified by cursor \Var{cp} and stores +the value in the word pointed to by \Var{valp}. + +The register numbering is target-dependent and described in separate +manual pages (e.g., libunwind-ia64(3) for the IA-64 target). +Furthermore, the exact set of accessible registers may depend on the +type of frame that \Var{cp} is referring to. For ordinary stack +frames, it is normally possible to access only the preserved +(``callee-saved'') registers and frame-related registers (such as the +stack-pointer). However, for signal frames (see +\Func{unw\_is\_signal\_frame}(3)), it is usually possible to access +all registers. + +Note that \Func{unw\_get\_reg}() can only read the contents of +registers whose values fit in a single word. See +\Func{unw\_get\_fpreg}(3) for a way to read registers which do not fit +this constraint. + +\section{Return Value} + +On successful completion, \Func{unw\_get\_reg}() returns 0. +Otherwise the negative value of one of the error-codes below is +returned. + +\section{Thread and Signal Safety} + +\Func{unw\_get\_reg}() is thread-safe as well as safe to use +from a signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred. +\item[\Const{UNW\_EBADREG}] An attempt was made to read a register + that is either invalid or not accessible in the current frame. +\end{Description} +In addition, \Func{unw\_get\_reg}() may return any error returned by +the \Func{access\_mem}(), \Func{access\_reg}(), and +\Func{access\_fpreg}() call-backs (see +\Func{unw\_create\_addr\_space}(3)). + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{libunwind-ia64(3)}, +\SeeAlso{unw\_get\_fpreg(3)}, +\SeeAlso{unw\_is\_signal\_frame(3)}, +\SeeAlso{unw\_set\_reg(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_getcontext.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_getcontext.man new file mode 100644 index 0000000..13725df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_getcontext.man @@ -0,0 +1,93 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_GETCONTEXT" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_getcontext +\-\- get initial machine\-state +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_getcontext(unw_context_t *ucp); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_getcontext() +routine initializes the context structure +pointed to by ucp +with the machine\-state of the call\-site. The +exact set of registers stored by unw_getcontext() +is +platform\-specific, but, in general, at least all preserved +(``callee\-saved\&'') and all frame\-related registers, such as the +stack\-pointer, will be stored. +.PP +This routine is normally implemented as a macro and applications +should not attempt to take its address. +.PP +.SH PLATFORM\-SPECIFIC NOTES + +.PP +On IA\-64, unw_context_t +has a layout that is compatible with +that of ucontext_t +and such structures can be initialized with +getcontext() +instead of unw_getcontext(). +However, the +reverse is \fInot\fP +true and it is \fInot\fP +safe to use structures +initialized by unw_getcontext() +in places where a structure +initialized by getcontext() +is expected. The reason for this +asymmetry is that unw_getcontext() +is optimized for maximum +performance and does not, for example, save the signal mask. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_getcontext() +returns 0. +Otherwise, a value of \-1 is returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_getcontext() +is thread\-safe as well as safe to use +from a signal handler. +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_init_local(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_getcontext.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_getcontext.tex new file mode 100644 index 0000000..fa3eb81 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_getcontext.tex @@ -0,0 +1,63 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_getcontext}{David Mosberger-Tang}{Programming Library}{unw\_getcontext}unw\_getcontext -- get initial machine-state +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_getcontext}(\Type{unw\_context\_t~*}\Var{ucp});\\ + +\section{Description} + +The \Func{unw\_getcontext}() routine initializes the context structure +pointed to by \Var{ucp} with the machine-state of the call-site. The +exact set of registers stored by \Func{unw\_getcontext}() is +platform-specific, but, in general, at least all preserved +(``callee-saved'') and all frame-related registers, such as the +stack-pointer, will be stored. + +This routine is normally implemented as a macro and applications +should not attempt to take its address. + +\section{Platform-specific Notes} + +On IA-64, \Type{unw\_context\_t} has a layout that is compatible with +that of \Type{ucontext\_t} and such structures can be initialized with +\Func{getcontext}() instead of \Func{unw\_getcontext}(). However, the +reverse is \emph{not} true and it is \emph{not} safe to use structures +initialized by \Func{unw\_getcontext()} in places where a structure +initialized by \Func{getcontext()} is expected. The reason for this +asymmetry is that \Func{unw\_getcontext()} is optimized for maximum +performance and does not, for example, save the signal mask. + +\section{Return Value} + +On successful completion, \Func{unw\_getcontext}() returns 0. +Otherwise, a value of -1 is returned. + +\section{Thread and Signal Safety} + +\Func{unw\_getcontext}() is thread-safe as well as safe to use +from a signal handler. + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_init\_local(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_local.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_local.man new file mode 100644 index 0000000..301dd6f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_local.man @@ -0,0 +1,124 @@ +'\" t +.\" Manual page created with latex2man on Wed Aug 16 12:11:05 PDT 2017 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_INIT\\_LOCAL" "3" "16 August 2017" "Programming Library " "Programming Library " +.SH NAME +unw_init_local +\-\- initialize cursor for local unwinding +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_init_local(unw_cursor_t *c, +unw_context_t *ctxt); +.br +int +unw_init_local2(unw_cursor_t *c, +unw_context_t *ctxt, +int +flag); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_init_local() +routine initializes the unwind cursor +pointed to by c +with the machine\-state in the context structure +pointed to by ctxt\&. +As such, the machine\-state pointed to by +ctxt +identifies the initial stack frame at which unwinding +starts. The machine\-state is expected to be one provided by a call to +unw_getcontext; as such, the instruction pointer may point to the +instruction after the last instruction of a function, and libunwind +will back\-up the instruction pointer before beginning a walk up the +call stack. The machine\-state must remain valid for the duration for +which the cursor c +is in use. +.PP +The unw_init_local() +routine can be used only for unwinding in +the address space of the current process (i.e., for local unwinding). +For all other cases, unw_init_remote() +must be used instead. +However, unwind performance may be better when using +unw_init_local(). +Also, unw_init_local() +is +available even when UNW_LOCAL_ONLY +has been defined before +including , +whereas unw_init_remote() +is not. +.PP +If the unw_context_t is known to be a signal frame (i.e., from the +third argument in a sigaction handler on linux), +unw_init_local2() +should be used for correct initialization +on some platforms, passing the UNW_INIT_SIGNAL_FRAME flag. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_init_local() +returns 0. +Otherwise the negative value of one of the error\-codes below is +returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_init_local() +is thread\-safe as well as safe to use from a +signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_EINVAL + unw_init_local() +was called in a +version of libunwind +which supports remote unwinding only +(this normally happens when calling unw_init_local() +for a +cross\-platform version of libunwind). +.TP +UNW_EUNSPEC + An unspecified error occurred. +.TP +UNW_EBADREG + A register needed by unw_init_local() +wasn\&'t accessible. +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_init_remote(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_local.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_local.tex new file mode 100644 index 0000000..ff0d03b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_local.tex @@ -0,0 +1,80 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_init\_local}{David Mosberger-Tang}{Programming Library}{unw\_init\_local}unw\_init\_local -- initialize cursor for local unwinding +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_init\_local}(\Type{unw\_cursor\_t~*}\Var{c}, \Type{unw\_context\_t~*}\Var{ctxt});\\ +\Type{int} \Func{unw\_init\_local2}(\Type{unw\_cursor\_t~*}\Var{c}, \Type{unw\_context\_t~*}\Var{ctxt}, \Type{int} \Var{flag});\\ + +\section{Description} + +The \Func{unw\_init\_local}() routine initializes the unwind cursor +pointed to by \Var{c} with the machine-state in the context structure +pointed to by \Var{ctxt}. As such, the machine-state pointed to by +\Var{ctxt} identifies the initial stack frame at which unwinding +starts. The machine-state is expected to be one provided by a call to +unw_getcontext; as such, the instruction pointer may point to the +instruction after the last instruction of a function, and libunwind +will back-up the instruction pointer before beginning a walk up the +call stack. The machine-state must remain valid for the duration for +which the cursor \Var{c} is in use. + +The \Func{unw\_init\_local}() routine can be used only for unwinding in +the address space of the current process (i.e., for local unwinding). +For all other cases, \Func{unw\_init\_remote}() must be used instead. +However, unwind performance may be better when using +\Func{unw\_init\_local}(). Also, \Func{unw\_init\_local}() is +available even when \Const{UNW\_LOCAL\_ONLY} has been defined before +including \File{$<$libunwind.h$>$}, whereas \Func{unw\_init\_remote}() +is not. + +If the unw_context_t is known to be a signal frame (i.e., from the +third argument in a sigaction handler on linux), +\Func{unw\_init\_local2}() should be used for correct initialization +on some platforms, passing the UNW_INIT_SIGNAL_FRAME flag. + +\section{Return Value} + +On successful completion, \Func{unw\_init\_local}() returns 0. +Otherwise the negative value of one of the error-codes below is +returned. + +\section{Thread and Signal Safety} + +\Func{unw\_init\_local}() is thread-safe as well as safe to use from a +signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_EINVAL}] \Func{unw\_init\_local}() was called in a + version of \Prog{libunwind} which supports remote unwinding only + (this normally happens when calling \Func{unw\_init\_local}() for a + cross-platform version of \Prog{libunwind}). +\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred. +\item[\Const{UNW\_EBADREG}] A register needed by \Func{unw\_init\_local}() + wasn't accessible. +\end{Description} + +\section{See Also} + +\SeeAlso{libunwind(3)}, \SeeAlso{unw\_init\_remote(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_local2.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_local2.man new file mode 100644 index 0000000..6cbbf00 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_local2.man @@ -0,0 +1 @@ +.so man3/unw_init_local.3 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_remote.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_remote.man new file mode 100644 index 0000000..0acdac9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_remote.man @@ -0,0 +1,123 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_INIT\\_REMOTE" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_init_remote +\-\- initialize cursor for remote unwinding +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_init_remote(unw_cursor_t *c, +unw_addr_space_t as, +void *arg); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_init_remote() +routine initializes the unwind cursor +pointed to by c +for unwinding in the address space identified by +as\&. +The as +argument can either be set to +unw_local_addr_space +(local address space) or to an arbitrary +address space created with unw_create_addr_space(). +.PP +The arg +void\-pointer tells the address space exactly what entity +should be unwound. For example, if unw_local_addr_space +is +passed in as, +then arg +needs to be a pointer to a context +structure containing the machine\-state of the initial stack frame. +However, other address\-spaces may instead expect a process\-id, a +thread\-id, or a pointer to an arbitrary structure which identifies the +stack\-frame chain to be unwound. In other words, the interpretation +of arg +is entirely dependent on the address\-space in use; +libunwind +never interprets the argument in any way on its own. +.PP +Note that unw_init_remote() +can be used to initiate unwinding +in \fIany\fP +process, including the local process in which the +unwinder itself is running. However, for local unwinding, it is +generally preferable to use unw_init_local() +instead, because +it is easier to use and because it may perform better. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_init_remote() +returns 0. +Otherwise the negative value of one of the error\-codes below is +returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_init_remote() +is thread\-safe. If the local address\-space +is passed in argument as, +this routine is also safe to use from +a signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_EINVAL + unw_init_remote() +was called in a +version of libunwind +which supports local unwinding only +(this normally happens when defining UNW_LOCAL_ONLY +before +including +and then calling +unw_init_remote()). +.TP +UNW_EUNSPEC + An unspecified error occurred. +.TP +UNW_EBADREG + A register needed by unw_init_remote() +wasn\&'t accessible. +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_create_addr_space(3), +unw_init_local(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_remote.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_remote.tex new file mode 100644 index 0000000..9b4dc79 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_init_remote.tex @@ -0,0 +1,79 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_init\_remote}{David Mosberger-Tang}{Programming Library}{unw\_init\_remote}unw\_init\_remote -- initialize cursor for remote unwinding +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_init\_remote}(\Type{unw\_cursor\_t~*}\Var{c}, \Type{unw\_addr\_space\_t~}\Var{as}, \Type{void~*}\Var{arg});\\ + +\section{Description} + +The \Func{unw\_init\_remote}() routine initializes the unwind cursor +pointed to by \Var{c} for unwinding in the address space identified by +\Var{as}. The \Var{as} argument can either be set to +\Var{unw\_local\_addr\_space} (local address space) or to an arbitrary +address space created with \Func{unw\_create\_addr\_space}(). + +The \Var{arg} void-pointer tells the address space exactly what entity +should be unwound. For example, if \Var{unw\_local\_addr\_space} is +passed in \Var{as}, then \Var{arg} needs to be a pointer to a context +structure containing the machine-state of the initial stack frame. +However, other address-spaces may instead expect a process-id, a +thread-id, or a pointer to an arbitrary structure which identifies the +stack-frame chain to be unwound. In other words, the interpretation +of \Var{arg} is entirely dependent on the address-space in use; +\Prog{libunwind} never interprets the argument in any way on its own. + +Note that \Func{unw\_init\_remote}() can be used to initiate unwinding +in \emph{any} process, including the local process in which the +unwinder itself is running. However, for local unwinding, it is +generally preferable to use \Func{unw\_init\_local}() instead, because +it is easier to use and because it may perform better. + +\section{Return Value} + +On successful completion, \Func{unw\_init\_remote}() returns 0. +Otherwise the negative value of one of the error-codes below is +returned. + +\section{Thread and Signal Safety} + +\Func{unw\_init\_remote}() is thread-safe. If the local address-space +is passed in argument \Var{as}, this routine is also safe to use from +a signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_EINVAL}] \Func{unw\_init\_remote}() was called in a + version of \Prog{libunwind} which supports local unwinding only + (this normally happens when defining \Const{UNW\_LOCAL\_ONLY} before + including \File{$<$libunwind.h$>$} and then calling + \Func{unw\_init\_remote}()). +\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred. +\item[\Const{UNW\_EBADREG}] A register needed by \Func{unw\_init\_remote}() + wasn't accessible. +\end{Description} + +\section{See Also} + +\SeeAlso{libunwind(3)}, \SeeAlso{unw\_create\_addr\_space(3)}, +\SeeAlso{unw\_init\_local(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_fpreg.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_fpreg.man new file mode 100644 index 0000000..0c26ec1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_fpreg.man @@ -0,0 +1,73 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_IS\\_FPREG" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_is_fpreg +\-\- check if a register is a floating\-point register +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_is_fpreg(unw_regnum_t +reg); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_is_fpreg() +routine checks whether register number +reg +is a floating\-point register. +.PP +This routine is normally implemented as a macro and applications +should not attempt to take its address. +.PP +.SH RETURN VALUE + +.PP +The unw_is_fpreg() +routine returns a non\-zero value if +reg +is a floating\-point register. Otherwise, it returns a value +of 0. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_is_fpreg() +is thread\-safe as well as safe to use +from a signal handler. +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_get_reg(3), +unw_set_reg(3), +unw_get_fpreg(3), +unw_set_fpreg(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_fpreg.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_fpreg.tex new file mode 100644 index 0000000..c28cdc9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_fpreg.tex @@ -0,0 +1,52 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_is\_fpreg}{David Mosberger-Tang}{Programming Library}{unw\_is\_fpreg}unw\_is\_fpreg -- check if a register is a floating-point register +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_is\_fpreg}(\Type{unw\_regnum\_t} \Var{reg});\\ + +\section{Description} + +The \Func{unw\_is\_fpreg}() routine checks whether register number +\Var{reg} is a floating-point register. + +This routine is normally implemented as a macro and applications +should not attempt to take its address. + +\section{Return Value} + +The \Func{unw\_is\_fpreg}() routine returns a non-zero value if +\Var{reg} is a floating-point register. Otherwise, it returns a value +of 0. + +\section{Thread and Signal Safety} + +\Func{unw\_is\_fpreg}() is thread-safe as well as safe to use +from a signal handler. + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_get\_reg(3)}, +\SeeAlso{unw\_set\_reg(3)}, +\SeeAlso{unw\_get\_fpreg(3)}, +\SeeAlso{unw\_set\_fpreg(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_signal_frame.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_signal_frame.man new file mode 100644 index 0000000..d9a7cda --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_signal_frame.man @@ -0,0 +1,88 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_IS\\_SIGNAL\\_FRAME" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_is_signal_frame +\-\- check if current frame is a signal frame +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_is_signal_frame(unw_cursor_t *cp); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_is_signal_frame() +routine returns a positive value +if the current frame identified by cp +is a signal frame, and a +value of 0 otherwise. For the purpose of this discussion, a signal +frame is a frame that was created in response to a potentially +asynchronous interruption. For UNIX and UNIX\-like platforms, such +frames are normally created by the kernel when delivering a signal. +In a kernel\-environment, a signal frame might, for example, correspond +to a frame created in response to a device interrupt. +.PP +Signal frames are somewhat unusual because the asynchronous nature of +the events that create them require storing the contents of registers +that are normally treated as scratch (``caller\-saved\&'') registers. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_is_signal_frame() +returns a +positive value if the current frame is a signal frame, or 0 if it is +not. Otherwise, a negative value of one of the error\-codes below is +returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_is_signal_frame() +is thread\-safe as well as safe to use +from a signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_ENOINFO + Libunwind +is unable to determine +whether or not the current frame is a signal frame. +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_get_reg(3), +unw_set_reg(3), +unw_get_fpreg(3), +unw_set_fpreg(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_signal_frame.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_signal_frame.tex new file mode 100644 index 0000000..f262e56 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_is_signal_frame.tex @@ -0,0 +1,67 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_is\_signal\_frame}{David Mosberger-Tang}{Programming Library}{unw\_is\_signal\_frame}unw\_is\_signal\_frame -- check if current frame is a signal frame +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_is\_signal\_frame}(\Type{unw\_cursor\_t~*}\Var{cp});\\ + +\section{Description} + +The \Func{unw\_is\_signal\_frame}() routine returns a positive value +if the current frame identified by \Var{cp} is a signal frame, and a +value of 0 otherwise. For the purpose of this discussion, a signal +frame is a frame that was created in response to a potentially +asynchronous interruption. For UNIX and UNIX-like platforms, such +frames are normally created by the kernel when delivering a signal. +In a kernel-environment, a signal frame might, for example, correspond +to a frame created in response to a device interrupt. + +Signal frames are somewhat unusual because the asynchronous nature of +the events that create them require storing the contents of registers +that are normally treated as scratch (``caller-saved'') registers. + +\section{Return Value} + +On successful completion, \Func{unw\_is\_signal\_frame}() returns a +positive value if the current frame is a signal frame, or 0 if it is +not. Otherwise, a negative value of one of the error-codes below is +returned. + +\section{Thread and Signal Safety} + +\Func{unw\_is\_signal\_frame}() is thread-safe as well as safe to use +from a signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} is unable to determine + whether or not the current frame is a signal frame. +\end{Description} + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_get\_reg(3)}, +\SeeAlso{unw\_set\_reg(3)}, +\SeeAlso{unw\_get\_fpreg(3)}, +\SeeAlso{unw\_set\_fpreg(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_reg_states_iterate.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_reg_states_iterate.man new file mode 100644 index 0000000..e328ad2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_reg_states_iterate.man @@ -0,0 +1,137 @@ +'\" t +.\" Manual page created with latex2man on Wed Aug 16 11:09:44 PDT 2017 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_REG\\_STATES\\_ITERATE" "3" "16 August 2017" "Programming Library " "Programming Library " +.SH NAME +unw_reg_states_iterate +\-\- get register state info on current procedure +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_reg_states_iterate(unw_cursor_t *cp, +unw_reg_states_callbackcb, +void *token); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_reg_states_iterate() +routine provides +information about the procedure that created the stack frame +identified by argument cp\&. +The cb +argument is a pointer +to a function of type unw_reg_states_callback +which is used to +return the information. The function unw_reg_states_callback +has the +following definition: +.PP +int +( *unw_reg_states_callback)(void *token, +void *reg_states_data, +size_t +reg_states_data_size, +unw_word_t +start_ip, +unw_word_t +end_ip); +.PP +The callback function may be invoked several times for each call of unw_reg_states_iterate\&. +Each call is associcated with a instruction address range and a set of instructions on how to update register values when returning from the procedure in that address range. For each invocation, the arguments to the callback function are: +.TP +void * token + The token value passed to unw_reg_states_callback\&. +.br +.TP +void * reg_states_data + A pointer to data about +updating register values. This data, or a copy of it, can be passed +to unw_apply_reg_state\&. +.br +.TP +int reg_states_data_size + The size of the register update data. +.br +.TP +unw_word_t start_ip + The address of the first +instruction of the address range. +.br +.TP +unw_word_t end_ip + The address of the first +instruction \fIbeyond\fP +the end of the address range. +.br +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_reg_states_iterate() +returns +0. If the callback function returns a nonzero value, that indicates +failure and the function returns immediately. Otherwise the negative +value of one of the error\-codes below is returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_reg_states_iterate() +is thread\-safe. If cursor cp +is +in the local address\-space, this routine is also safe to use from a +signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_EUNSPEC + An unspecified error occurred. +.TP +UNW_ENOINFO + Libunwind +was unable to locate +unwind\-info for the procedure. +.TP +UNW_EBADVERSION + The unwind\-info for the procedure has +version or format that is not understood by libunwind\&. +.PP +In addition, unw_reg_states_iterate() +may return any error +returned by the access_mem() +call\-back (see +unw_create_addr_space(3)). +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_apply_reg_state(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_reg_states_iterate.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_reg_states_iterate.tex new file mode 100644 index 0000000..36c9b54 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_reg_states_iterate.tex @@ -0,0 +1,83 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_reg\_states\_iterate}{David Mosberger-Tang}{Programming Library}{unw\_reg\_states\_iterate}unw\_reg\_states\_iterate -- get register state info on current procedure +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_reg\_states\_iterate}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{unw\_reg\_states\_callback}\Var{cb}, \Type{void~*}\Var{token});\\ + +\section{Description} + +The \Func{unw\_reg\_states\_iterate}() routine provides +information about the procedure that created the stack frame +identified by argument \Var{cp}. The \Var{cb} argument is a pointer +to a function of type \Type{unw\_reg\_states\_callback} which is used to +return the information. The function \Type{unw\_reg\_states\_callback} has the +following definition: + +\Type{int} (~*\Var{unw\_reg\_states\_callback})(\Type{void~*}\Var{token}, + \Type{void~*}\Var{reg\_states\_data}, + \Type{size\_t} \Var{reg\_states\_data\_size}, + \Type{unw\_word\_t} \Var{start\_ip}, \Type{unw\_word\_t} \Var{end\_ip}); + +The callback function may be invoked several times for each call of \Func{unw\_reg\_states\_iterate}. Each call is associcated with a instruction address range and a set of instructions on how to update register values when returning from the procedure in that address range. For each invocation, the arguments to the callback function are: +\begin{description} +\item[\Type{void~*} \Var{token}] The token value passed to \Var{unw\_reg\_states\_callback}. \\ +\item[\Type{void~*} \Var{reg\_states\_data}] A pointer to data about + updating register values. This data, or a copy of it, can be passed + to \Var{unw\_apply\_reg\_state}.\\ +\item[\Type{int} \Var{reg\_states\_data\_size}] The size of the register update data. \\ +\item[\Type{unw\_word\_t} \Var{start\_ip}] The address of the first + instruction of the address range. \\ +\item[\Type{unw\_word\_t} \Var{end\_ip}] The address of the first + instruction \emph{beyond} the end of the address range. \\ +\end{description} + +\section{Return Value} + +On successful completion, \Func{unw\_reg\_states\_iterate}() returns +0. If the callback function returns a nonzero value, that indicates +failure and the function returns immediately. Otherwise the negative +value of one of the error-codes below is returned. + +\section{Thread and Signal Safety} + +\Func{unw\_reg\_states\_iterate}() is thread-safe. If cursor \Var{cp} is +in the local address-space, this routine is also safe to use from a +signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred. +\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to locate + unwind-info for the procedure. +\item[\Const{UNW\_EBADVERSION}] The unwind-info for the procedure has + version or format that is not understood by \Prog{libunwind}. +\end{Description} +In addition, \Func{unw\_reg\_states\_iterate}() may return any error +returned by the \Func{access\_mem}() call-back (see +\Func{unw\_create\_addr\_space}(3)). + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_apply\_reg\_state(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_regname.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_regname.man new file mode 100644 index 0000000..1e3e2db --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_regname.man @@ -0,0 +1,68 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_REGNAME" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_regname +\-\- get register name +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +const char *unw_regname(unw_regnum_t +regnum); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_regname() +routine returns a printable name for +register regnum\&. +If regnum +is an invalid or otherwise +unrecognized register number, a string consisting of three question +marks is returned. The returned string is statically allocated and +therefore guaranteed to remain valid until the application terminates. +.PP +.SH RETURN VALUE + +.PP +The unw_regname() +routine cannot fail and always returns a +valid (non\-NULL) +string. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +The unw_regname() +routine is thread\-safe as well as safe to +use from a signal handler. +.PP +.SH SEE ALSO + +.PP +libunwind(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_regname.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_regname.tex new file mode 100644 index 0000000..94b6434 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_regname.tex @@ -0,0 +1,47 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_regname}{David Mosberger-Tang}{Programming Library}{unw\_regname}unw\_regname -- get register name +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{const char~*}\Func{unw\_regname}(\Type{unw\_regnum\_t} \Var{regnum});\\ + +\section{Description} + +The \Func{unw\_regname}() routine returns a printable name for +register \Var{regnum}. If \Var{regnum} is an invalid or otherwise +unrecognized register number, a string consisting of three question +marks is returned. The returned string is statically allocated and +therefore guaranteed to remain valid until the application terminates. + +\section{Return Value} + +The \Func{unw\_regname}() routine cannot fail and always returns a +valid (non-\Const{NULL}) string. + +\section{Thread and Signal Safety} + +The \Func{unw\_regname}() routine is thread-safe as well as safe to +use from a signal handler. + +\section{See Also} + +\SeeAlso{libunwind(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_resume.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_resume.man new file mode 100644 index 0000000..1bf3832 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_resume.man @@ -0,0 +1,146 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_RESUME" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_resume +\-\- resume execution in a particular stack frame +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_resume(unw_cursor_t *cp); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_resume() +routine resumes execution at the stack frame +identified by cp\&. +The behavior of this routine differs +slightly for local and remote unwinding. +.PP +For local unwinding, unw_resume() +restores the machine state +and then directly resumes execution in the target stack frame. Thus +unw_resume() +does not return in this case. Restoring the +machine state normally involves restoring the ``preserved\&'' +(callee\-saved) registers. However, if execution in any of the stack +frames younger (more deeply nested) than the one identified by +cp +was interrupted by a signal, then unw_resume() +will +restore all registers as well as the signal mask. Attempting to call +unw_resume() +on a cursor which identifies the stack frame of +another thread results in undefined behavior (e.g., the program may +crash). +.PP +For remote unwinding, unw_resume() +installs the machine state +identified by the cursor by calling the access_reg +and +access_fpreg +accessor callbacks as needed. Once that is +accomplished, the resume +accessor callback is invoked. The +unw_resume +routine then returns normally (that is, unlikely +for local unwinding, unw_resume +will always return for remote +unwinding). +.PP +Most platforms reserve some registers to pass arguments to exception +handlers (e.g., IA\-64 uses r15\-r18 +for this +purpose). These registers are normally treated like ``scratch\&'' +registers. However, if libunwind +is used to set an exception +argument register to a particular value (e.g., via +unw_set_reg()), +then unw_resume() +will install this +value as the contents of the register. In other words, the exception +handling arguments are installed even in cases where normally only the +``preserved\&'' registers are restored. +.PP +Note that unw_resume() +does \fInot\fP +invoke any unwind +handlers (aka, ``personality routines\&''). If a program needs this, it +will have to do so on its own by obtaining the unw_proc_info_t +of each unwound frame and appropriately processing its unwind handler +and language\-specific data area (lsda). These steps are generally +dependent on the target\-platform and are regulated by the +processor\-specific ABI (application\-binary interface). +.PP +.SH RETURN VALUE + +.PP +For local unwinding, unw_resume() +does not return on success. +For remote unwinding, it returns 0 on success. On failure, the +negative value of one of the errors below is returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_resume() +is thread\-safe. If cursor cp +is in the +local address\-space, this routine is also safe to use from a signal +handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_EUNSPEC + An unspecified error occurred. +.TP +UNW_EBADREG + A register needed by unw_resume() +wasn\&'t +accessible. +.TP +UNW_EINVALIDIP + The instruction pointer identified by +cp +is not valid. +.TP +UNW_BADFRAME + The stack frame identified by +cp +is not valid. +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_set_reg(3), +sigprocmask(2) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_resume.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_resume.tex new file mode 100644 index 0000000..38b1824 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_resume.tex @@ -0,0 +1,99 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_resume}{David Mosberger-Tang}{Programming Library}{unw\_resume}unw\_resume -- resume execution in a particular stack frame +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_resume}(\Type{unw\_cursor\_t~*}\Var{cp});\\ + +\section{Description} + +The \Func{unw\_resume}() routine resumes execution at the stack frame +identified by \Var{cp}. The behavior of this routine differs +slightly for local and remote unwinding. + +For local unwinding, \Func{unw\_resume}() restores the machine state +and then directly resumes execution in the target stack frame. Thus +\Func{unw\_resume}() does not return in this case. Restoring the +machine state normally involves restoring the ``preserved'' +(callee-saved) registers. However, if execution in any of the stack +frames younger (more deeply nested) than the one identified by +\Var{cp} was interrupted by a signal, then \Func{unw\_resume}() will +restore all registers as well as the signal mask. Attempting to call +\Func{unw\_resume}() on a cursor which identifies the stack frame of +another thread results in undefined behavior (e.g., the program may +crash). + +For remote unwinding, \Func{unw\_resume}() installs the machine state +identified by the cursor by calling the \Func{access\_reg} and +\Func{access\_fpreg} accessor callbacks as needed. Once that is +accomplished, the \Func{resume} accessor callback is invoked. The +\Func{unw\_resume} routine then returns normally (that is, unlikely +for local unwinding, \Func{unw\_resume} will always return for remote +unwinding). + +Most platforms reserve some registers to pass arguments to exception +handlers (e.g., IA-64 uses \texttt{r15}-\texttt{r18} for this +purpose). These registers are normally treated like ``scratch'' +registers. However, if \Prog{libunwind} is used to set an exception +argument register to a particular value (e.g., via +\Func{unw\_set\_reg}()), then \Func{unw\_resume}() will install this +value as the contents of the register. In other words, the exception +handling arguments are installed even in cases where normally only the +``preserved'' registers are restored. + +Note that \Func{unw\_resume}() does \emph{not} invoke any unwind +handlers (aka, ``personality routines''). If a program needs this, it +will have to do so on its own by obtaining the \Type{unw\_proc\_info\_t} +of each unwound frame and appropriately processing its unwind handler +and language-specific data area (lsda). These steps are generally +dependent on the target-platform and are regulated by the +processor-specific ABI (application-binary interface). + +\section{Return Value} + +For local unwinding, \Func{unw\_resume}() does not return on success. +For remote unwinding, it returns 0 on success. On failure, the +negative value of one of the errors below is returned. + +\section{Thread and Signal Safety} + +\Func{unw\_resume}() is thread-safe. If cursor \Var{cp} is in the +local address-space, this routine is also safe to use from a signal +handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred. +\item[\Const{UNW\_EBADREG}] A register needed by \Func{unw\_resume}() wasn't + accessible. +\item[\Const{UNW\_EINVALIDIP}] The instruction pointer identified by + \Var{cp} is not valid. +\item[\Const{UNW\_BADFRAME}] The stack frame identified by + \Var{cp} is not valid. +\end{Description} + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_set\_reg(3)}, +sigprocmask(2) + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_cache_size.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_cache_size.man new file mode 100644 index 0000000..34bbc53 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_cache_size.man @@ -0,0 +1,88 @@ +'\" t +.\" Manual page created with latex2man on Fri Jan 13 08:33:21 PST 2017 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_SET\\_CACHE\\_SIZE" "3" "13 January 2017" "Programming Library " "Programming Library " +.SH NAME +unw_set_cache_size +\-\- set unwind cache size +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_set_cache_size(unw_addr_space_t +as, +size_t +size, +int +flag); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_set_cache_size() +routine sets the cache size of +address space as +to hold at least as many items as given by +argument size\&. +It may hold more items as determined by the +implementation. To disable caching, call +unw_set_caching_policy) +with a policy of +UNW_CACHE_NONE\&. +Flag is currently unused and must be 0. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_set_cache_size() +returns 0. +Otherwise the negative value of one of the error\-codes below is +returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_set_cache_size() +is thread\-safe but \fInot\fP +safe +to use from a signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_ENOMEM + The desired cache size could not be +established because the application is out of memory. +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_create_addr_space(3), +unw_set_caching_policy(3), +unw_flush_cache(3) +.PP +.SH AUTHOR + +.PP +Dave Watson +.br +Email: \fBdade.watson@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_cache_size.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_cache_size.tex new file mode 100644 index 0000000..1bd7e00 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_cache_size.tex @@ -0,0 +1,59 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_set\_cache\_size}{Dave Watson}{Programming Library}{unw\_set\_cache\_size}unw\_set\_cache\_size -- set unwind cache size +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_set\_cache\_size}(\Type{unw\_addr\_space\_t} \Var{as}, \Type{size\_t} \Var{size}, \Type{int} \Var{flag});\\ + +\section{Description} + +The \Func{unw\_set\_cache\_size}() routine sets the cache size of +address space \Var{as} to hold at least as many items as given by +argument \Var{size}. It may hold more items as determined by the +implementation. To disable caching, call +\Func{unw\_set\_caching\_policy}) with a policy of +\Const{UNW\_CACHE\_NONE}. Flag is currently unused and must be 0. + +\section{Return Value} + +On successful completion, \Func{unw\_set\_cache\_size}() returns 0. +Otherwise the negative value of one of the error-codes below is +returned. + +\section{Thread and Signal Safety} + +\Func{unw\_set\_cache\_size}() is thread-safe but \emph{not} safe +to use from a signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_ENOMEM}] The desired cache size could not be + established because the application is out of memory. +\end{Description} + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_create\_addr\_space(3)}, +\SeeAlso{unw\_set\_caching\_policy(3)}, +\SeeAlso{unw\_flush\_cache(3)} + +\section{Author} + +\noindent +Dave Watson\\ +Email: \Email{dade.watson@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_caching_policy.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_caching_policy.man new file mode 100644 index 0000000..4862ea5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_caching_policy.man @@ -0,0 +1,119 @@ +'\" t +.\" Manual page created with latex2man on Fri Dec 2 16:09:33 PST 2016 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_SET\\_CACHING\\_POLICY" "3" "02 December 2016" "Programming Library " "Programming Library " +.SH NAME +unw_set_caching_policy +\-\- set unwind caching policy +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_set_caching_policy(unw_addr_space_t +as, +unw_caching_policy_t +policy); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_set_caching_policy() +routine sets the caching policy +of address space as +to the policy specified by argument +policy\&. +The policy +argument can take one of three +possible values: +.TP +UNW_CACHE_NONE + Turns off caching completely. This +also implicitly flushes the contents of all caches as if +unw_flush_cache() +had been called. +.TP +UNW_CACHE_GLOBAL + Enables caching using a global cache +that is shared by all threads. If global caching is unavailable or +unsupported, libunwind +may fall back on using a per\-thread +cache, as if UNW_CACHE_PER_THREAD +had been specified. +.TP +UNW_CACHE_PER_THREAD + Enables caching using +thread\-local caches. If a thread\-local caching are unavailable or +unsupported, libunwind +may fall back on using a global cache, +as if UNW_CACHE_GLOBAL +had been specified. +.PP +If caching is enabled, an application must be prepared to make +appropriate calls to unw_flush_cache() +whenever the target +changes in a way that could affect the validity of cached information. +For example, after unloading (removing) a shared library, +unw_flush_cache() +would have to be called (at least) for the +address\-range that was covered by the shared library. +.PP +For address spaces created via unw_create_addr_space(3), +caching is turned off by default. For the local address space +unw_local_addr_space, +caching is turned on by default. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_set_caching_policy() +returns 0. +Otherwise the negative value of one of the error\-codes below is +returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_set_caching_policy() +is thread\-safe but \fInot\fP +safe +to use from a signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_ENOMEM + The desired caching policy could not be +established because the application is out of memory. +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_create_addr_space(3), +unw_set_cache_size(3), +unw_flush_cache(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_caching_policy.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_caching_policy.tex new file mode 100644 index 0000000..3a4b07e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_caching_policy.tex @@ -0,0 +1,81 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_set\_caching\_policy}{David Mosberger-Tang}{Programming Library}{unw\_set\_caching\_policy}unw\_set\_caching\_policy -- set unwind caching policy +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_set\_caching\_policy}(\Type{unw\_addr\_space\_t} \Var{as}, \Type{unw\_caching\_policy\_t} \Var{policy});\\ + +\section{Description} + +The \Func{unw\_set\_caching\_policy}() routine sets the caching policy +of address space \Var{as} to the policy specified by argument +\Var{policy}. The \Var{policy} argument can take one of three +possible values: +\begin{description} +\item[\Const{UNW\_CACHE\_NONE}] Turns off caching completely. This + also implicitly flushes the contents of all caches as if + \Func{unw\_flush\_cache}() had been called. +\item[\Const{UNW\_CACHE\_GLOBAL}] Enables caching using a global cache + that is shared by all threads. If global caching is unavailable or + unsupported, \Prog{libunwind} may fall back on using a per-thread + cache, as if \Const{UNW\_CACHE\_PER\_THREAD} had been specified. +\item[\Const{UNW\_CACHE\_PER\_THREAD}] Enables caching using + thread-local caches. If a thread-local caching are unavailable or + unsupported, \Prog{libunwind} may fall back on using a global cache, + as if \Const{UNW\_CACHE\_GLOBAL} had been specified. +\end{description} + +If caching is enabled, an application must be prepared to make +appropriate calls to \Func{unw\_flush\_cache}() whenever the target +changes in a way that could affect the validity of cached information. +For example, after unloading (removing) a shared library, +\Func{unw\_flush\_cache}() would have to be called (at least) for the +address-range that was covered by the shared library. + +For address spaces created via \Func{unw\_create\_addr\_space}(3), +caching is turned off by default. For the local address space +\Func{unw\_local\_addr\_space}, caching is turned on by default. + +\section{Return Value} + +On successful completion, \Func{unw\_set\_caching\_policy}() returns 0. +Otherwise the negative value of one of the error-codes below is +returned. + +\section{Thread and Signal Safety} + +\Func{unw\_set\_caching\_policy}() is thread-safe but \emph{not} safe +to use from a signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_ENOMEM}] The desired caching policy could not be + established because the application is out of memory. +\end{Description} + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_create\_addr\_space(3)}, +\SeeAlso{unw\_set\_cache\_size(3)}, +\SeeAlso{unw\_flush\_cache(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_fpreg.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_fpreg.man new file mode 100644 index 0000000..6cefa54 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_fpreg.man @@ -0,0 +1,117 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_SET\\_FPREG" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_set_fpreg +\-\- set contents of floating\-point register +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_set_fpreg(unw_cursor_t *cp, +unw_regnum_t +reg, +unw_fpreg_t +val); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_set_fpreg() +routine sets the value of register +reg +in the stack frame identified by cursor cp +to the +value passed in val\&. +.PP +The register numbering is target\-dependent and described in separate +manual pages (e.g., libunwind\-ia64(3) for the IA\-64 target). +Furthermore, the exact set of accessible registers may depend on the +type of frame that cp +is referring to. For ordinary stack +frames, it is normally possible to access only the preserved +(``callee\-saved\&'') registers and frame\-related registers (such as the +stack\-pointer). However, for signal frames (see +unw_is_signal_frame(3)), +it is usually possible to access +all registers. +.PP +Note that unw_set_fpreg() +can only write the contents of +floating\-point registers. See unw_set_reg(3) +for a way to +write registers which fit in a single word. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_set_fpreg() +returns 0. +Otherwise the negative value of one of the error\-codes below is +returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_set_fpreg() +is thread\-safe as well as safe to use +from a signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_EUNSPEC + An unspecified error occurred. +.TP +UNW_EBADREG + An attempt was made to write a register +that is either invalid or not accessible in the current frame. +.TP +UNW_EREADONLY + An attempt was made to write to a +read\-only register. +.PP +In addition, unw_set_fpreg() +may return any error returned by +the access_mem(), +access_reg(), +and +access_fpreg() +call\-backs (see +unw_create_addr_space(3)). +.PP +.SH SEE ALSO + +.PP +libunwind(3), +libunwind\-ia64(3), +unw_get_fpreg(3), +unw_is_fpreg(3), +unw_is_signal_frame(3), +unw_set_reg(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_fpreg.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_fpreg.tex new file mode 100644 index 0000000..aaf7fb2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_fpreg.tex @@ -0,0 +1,79 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_set\_fpreg}{David Mosberger-Tang}{Programming Library}{unw\_set\_fpreg}unw\_set\_fpreg -- set contents of floating-point register +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_set\_fpreg}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{unw\_regnum\_t} \Var{reg}, \Type{unw\_fpreg\_t} \Var{val});\\ + +\section{Description} + +The \Func{unw\_set\_fpreg}() routine sets the value of register +\Var{reg} in the stack frame identified by cursor \Var{cp} to the +value passed in \Var{val}. + +The register numbering is target-dependent and described in separate +manual pages (e.g., libunwind-ia64(3) for the IA-64 target). +Furthermore, the exact set of accessible registers may depend on the +type of frame that \Var{cp} is referring to. For ordinary stack +frames, it is normally possible to access only the preserved +(``callee-saved'') registers and frame-related registers (such as the +stack-pointer). However, for signal frames (see +\Func{unw\_is\_signal\_frame}(3)), it is usually possible to access +all registers. + +Note that \Func{unw\_set\_fpreg}() can only write the contents of +floating-point registers. See \Func{unw\_set\_reg}(3) for a way to +write registers which fit in a single word. + +\section{Return Value} + +On successful completion, \Func{unw\_set\_fpreg}() returns 0. +Otherwise the negative value of one of the error-codes below is +returned. + +\section{Thread and Signal Safety} + +\Func{unw\_set\_fpreg}() is thread-safe as well as safe to use +from a signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred. +\item[\Const{UNW\_EBADREG}] An attempt was made to write a register + that is either invalid or not accessible in the current frame. +\item[\Const{UNW\_EREADONLY}] An attempt was made to write to a + read-only register. +\end{Description} +In addition, \Func{unw\_set\_fpreg}() may return any error returned by +the \Func{access\_mem}(), \Func{access\_reg}(), and +\Func{access\_fpreg}() call-backs (see +\Func{unw\_create\_addr\_space}(3)). + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{libunwind-ia64(3)}, +\SeeAlso{unw\_get\_fpreg(3)}, +\SeeAlso{unw\_is\_fpreg(3)}, +\SeeAlso{unw\_is\_signal\_frame(3)}, +\SeeAlso{unw\_set\_reg(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_reg.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_reg.man new file mode 100644 index 0000000..5d57045 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_reg.man @@ -0,0 +1,117 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_SET\\_REG" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_set_reg +\-\- set register contents +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_set_reg(unw_cursor_t *cp, +unw_regnum_t +reg, +unw_word_t +val); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_set_reg() +routine sets the value of register +reg +in the stack frame identified by cursor cp +to the +value passed in val\&. +.PP +The register numbering is target\-dependent and described in separate +manual pages (e.g., libunwind\-ia64(3) for the IA\-64 target). +Furthermore, the exact set of accessible registers may depend on the +type of frame that cp +is referring to. For ordinary stack +frames, it is normally possible to access only the preserved +(``callee\-saved\&'') registers and frame\-related registers (such as the +stack\-pointer). However, for signal frames (see +unw_is_signal_frame(3)), +it is usually possible to access +all registers. +.PP +Note that unw_set_reg() +can only write the contents of +registers whose values fit in a single word. See +unw_set_fpreg(3) +for a way to write registers which do not +fit this constraint. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_set_reg() +returns 0. +Otherwise the negative value of one of the error\-codes below is +returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_set_reg() +is thread\-safe as well as safe to use +from a signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_EUNSPEC + An unspecified error occurred. +.TP +UNW_EBADREG + An attempt was made to write a register +that is either invalid or not accessible in the current frame. +.TP +UNW_EREADONLY + An attempt was made to write to a +read\-only register. +.PP +In addition, unw_set_reg() +may return any error returned by +the access_mem(), +access_reg(), +and +access_fpreg() +call\-backs (see +unw_create_addr_space(3)). +.PP +.SH SEE ALSO + +.PP +libunwind(3), +libunwind\-ia64(3), +unw_get_reg(3), +unw_is_signal_frame(3), +unw_set_fpreg(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_reg.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_reg.tex new file mode 100644 index 0000000..2421846 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_set_reg.tex @@ -0,0 +1,79 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_set\_reg}{David Mosberger-Tang}{Programming Library}{unw\_set\_reg}unw\_set\_reg -- set register contents +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_set\_reg}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{unw\_regnum\_t} \Var{reg}, \Type{unw\_word\_t} \Var{val});\\ + +\section{Description} + +The \Func{unw\_set\_reg}() routine sets the value of register +\Var{reg} in the stack frame identified by cursor \Var{cp} to the +value passed in \Var{val}. + +The register numbering is target-dependent and described in separate +manual pages (e.g., libunwind-ia64(3) for the IA-64 target). +Furthermore, the exact set of accessible registers may depend on the +type of frame that \Var{cp} is referring to. For ordinary stack +frames, it is normally possible to access only the preserved +(``callee-saved'') registers and frame-related registers (such as the +stack-pointer). However, for signal frames (see +\Func{unw\_is\_signal\_frame}(3)), it is usually possible to access +all registers. + +Note that \Func{unw\_set\_reg}() can only write the contents of +registers whose values fit in a single word. See +\Func{unw\_set\_fpreg}(3) for a way to write registers which do not +fit this constraint. + +\section{Return Value} + +On successful completion, \Func{unw\_set\_reg}() returns 0. +Otherwise the negative value of one of the error-codes below is +returned. + +\section{Thread and Signal Safety} + +\Func{unw\_set\_reg}() is thread-safe as well as safe to use +from a signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred. +\item[\Const{UNW\_EBADREG}] An attempt was made to write a register + that is either invalid or not accessible in the current frame. +\item[\Const{UNW\_EREADONLY}] An attempt was made to write to a + read-only register. +\end{Description} +In addition, \Func{unw\_set\_reg}() may return any error returned by +the \Func{access\_mem}(), \Func{access\_reg}(), and +\Func{access\_fpreg}() call-backs (see +\Func{unw\_create\_addr\_space}(3)). + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{libunwind-ia64(3)}, +\SeeAlso{unw\_get\_reg(3)}, +\SeeAlso{unw\_is\_signal\_frame(3)}, +\SeeAlso{unw\_set\_fpreg(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_step.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_step.man new file mode 100644 index 0000000..54da1b2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_step.man @@ -0,0 +1,106 @@ +'\" t +.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_STEP" "3" "16 August 2007" "Programming Library " "Programming Library " +.SH NAME +unw_step +\-\- advance to next stack frame +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +int +unw_step(unw_cursor_t *cp); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_step() +routine advances the unwind cursor cp +to +the next older, less deeply nested stack frame. +.PP +.SH RETURN VALUE + +.PP +On successful completion, unw_step() +returns a positive value +if the updated cursor refers to a valid stack frame, or 0 if the +previous stack frame was the last frame in the chain. On error, the +negative value of one of the error\-codes below is returned. +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_step() +is thread\-safe. If cursor cp +is in the local +address\-space, this routine is also safe to use from a signal handler. +.PP +.SH ERRORS + +.PP +.TP +UNW_EUNSPEC + An unspecified error occurred. +.TP +UNW_ENOINFO + Libunwind +was unable to locate the +unwind\-info needed to complete the operation. +.TP +UNW_EBADVERSION + The unwind\-info needed to complete the +operation has a version or a format that is not understood by +libunwind\&. +.TP +UNW_EINVALIDIP + The instruction\-pointer +(``program\-counter\&'') of the next stack frame is invalid (e.g., not +properly aligned). +.TP +UNW_EBADFRAME + The next stack frame is invalid. +.TP +UNW_ESTOPUNWIND + Returned if a call to +find_proc_info() +returned \-UNW_ESTOPUNWIND\&. +.PP +In addition, unw_step() +may return any error returned by the +find_proc_info(), +get_dyn_info_list_addr(), +access_mem(), +access_reg(), +or access_fpreg() +call\-backs (see unw_create_addr_space(3)). +.PP +.SH SEE ALSO + +.PP +libunwind(3), +unw_create_addr_space(3) +.PP +.SH AUTHOR + +.PP +David Mosberger\-Tang +.br +Email: \fBdmosberger@gmail.com\fP +.br +WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&. +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_step.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_step.tex new file mode 100644 index 0000000..106bd9b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_step.tex @@ -0,0 +1,68 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_step}{David Mosberger-Tang}{Programming Library}{unw\_step}unw\_step -- advance to next stack frame +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{int} \Func{unw\_step}(\Type{unw\_cursor\_t~*}\Var{cp});\\ + +\section{Description} + +The \Func{unw\_step}() routine advances the unwind cursor \Var{cp} to +the next older, less deeply nested stack frame. + +\section{Return Value} + +On successful completion, \Func{unw\_step}() returns a positive value +if the updated cursor refers to a valid stack frame, or 0 if the +previous stack frame was the last frame in the chain. On error, the +negative value of one of the error-codes below is returned. + +\section{Thread and Signal Safety} + +\Func{unw\_step}() is thread-safe. If cursor \Var{cp} is in the local +address-space, this routine is also safe to use from a signal handler. + +\section{Errors} + +\begin{Description} +\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred. +\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to locate the + unwind-info needed to complete the operation. +\item[\Const{UNW\_EBADVERSION}] The unwind-info needed to complete the + operation has a version or a format that is not understood by + \Prog{libunwind}. +\item[\Const{UNW\_EINVALIDIP}] The instruction-pointer + (``program-counter'') of the next stack frame is invalid (e.g., not + properly aligned). +\item[\Const{UNW\_EBADFRAME}] The next stack frame is invalid. +\item[\Const{UNW\_ESTOPUNWIND}] Returned if a call to + \Func{find\_proc\_info}() returned -\Const{UNW\_ESTOPUNWIND}. +\end{Description} +In addition, \Func{unw\_step}() may return any error returned by the +\Func{find\_proc\_info}(), \Func{get\_dyn\_info\_list\_addr}(), +\Func{access\_mem}(), \Func{access\_reg}(), or \Func{access\_fpreg}() +call-backs (see \Func{unw\_create\_addr\_space}(3)). + +\section{See Also} + +\SeeAlso{libunwind(3)}, +\SeeAlso{unw\_create\_addr\_space(3)} + +\section{Author} + +\noindent +David Mosberger-Tang\\ +Email: \Email{dmosberger@gmail.com}\\ +WWW: \URL{http://www.nongnu.org/libunwind/}. +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_strerror.man b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_strerror.man new file mode 100644 index 0000000..467c44d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_strerror.man @@ -0,0 +1,63 @@ +'\" t +.\" Manual page created with latex2man on Wed Aug 18 16:51:29 CEST 2004 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "UNW\\_STRERROR" "3" "18 August 2004" "Programming Library " "Programming Library " +.SH NAME +unw_strerror +\-\- get text corresponding to error code +.PP +.SH SYNOPSIS + +.PP +#include +.br +.PP +const char * +unw_strerror(int +err_code); +.br +.PP +.SH DESCRIPTION + +.PP +The unw_strerror() +routine maps the (negative) err_code +to a corresponding text message and returns it. +.PP +.SH RETURN VALUE + +.PP +The message that corresponds to err_code +or, if the +err_code +has no corresponding message, the text "invalid error +code". +.PP +.SH THREAD AND SIGNAL SAFETY + +.PP +unw_strerror() +is thread\-safe as well as safe to use +from a signal handler. +.PP +.SH AUTHOR + +.PP +Thomas Hallgren +.br +BEA Systems +.br +Stockholm, Sweden +.br +Email: \fBthallgre@bea.com\fP +.br +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_strerror.tex b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_strerror.tex new file mode 100644 index 0000000..7cad011 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/doc/unw_strerror.tex @@ -0,0 +1,42 @@ +\documentclass{article} +\usepackage[fancyhdr,pdf]{latex2man} + +\input{common.tex} + +\begin{document} + +\begin{Name}{3}{unw\_strerror}{Thomas Hallgren}{Programming Library}{unw\_strerror}unw\_strerror -- get text corresponding to error code +\end{Name} + +\section{Synopsis} + +\File{\#include $<$libunwind.h$>$}\\ + +\Type{const char *} \Func{unw\_strerror}(\Type{int} \Var{err\_code});\\ + +\section{Description} + +The \Func{unw\_strerror}() routine maps the (negative) \Var{err\_code} +to a corresponding text message and returns it. + +\section{Return Value} + +The message that corresponds to \Var{err\_code} or, if the +\Var{err\_code} has no corresponding message, the text "invalid error +code". + +\section{Thread and Signal Safety} + +\Func{unw\_strerror}() is thread-safe as well as safe to use +from a signal handler. + +\section{Author} + +\noindent +Thomas Hallgren\\ +BEA Systems\\ +Stockholm, Sweden\\ +Email: \Email{thallgre@bea.com}\\ +\LatexManEnd + +\end{document} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/compiler.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/compiler.h new file mode 100644 index 0000000..2fa59ef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/compiler.h @@ -0,0 +1,72 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2005 Hewlett-Packard Co + Copyright (C) 2007 David Mosberger-Tang + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Compiler specific useful bits that are used in libunwind, and also in the + * tests. */ + +#ifndef COMPILER_H +#define COMPILER_H + +#ifdef __GNUC__ +# define ALIGNED(x) __attribute__((aligned(x))) +# define CONST_ATTR __attribute__((__const__)) +# define UNUSED __attribute__((unused)) +# define NOINLINE __attribute__((noinline)) +# define NORETURN __attribute__((noreturn)) +# define ALIAS2(name) #name +# define ALIAS(name) __attribute__((alias (ALIAS2(name)))) +# if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 2) +# define ALWAYS_INLINE inline __attribute__((always_inline)) +# define HIDDEN __attribute__((visibility ("hidden"))) +# else +# define ALWAYS_INLINE +# define HIDDEN +# endif +# define WEAK __attribute__((weak)) +# if (__GNUC__ >= 3) +# define likely(x) __builtin_expect ((x), 1) +# define unlikely(x) __builtin_expect ((x), 0) +# else +# define likely(x) (x) +# define unlikely(x) (x) +# endif +#else +# define ALIGNED(x) +# define ALWAYS_INLINE +# define CONST_ATTR +# define UNUSED +# define NOINLINE +# define NORETURN +# define ALIAS(name) +# define HIDDEN +# define WEAK +# define likely(x) (x) +# define unlikely(x) (x) +#endif + +#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) + +#endif /* COMPILER_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/dwarf-eh.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/dwarf-eh.h new file mode 100644 index 0000000..e037507 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/dwarf-eh.h @@ -0,0 +1,128 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef dwarf_eh_h +#define dwarf_eh_h + +#include "dwarf.h" + +/* This header file defines the format of a DWARF exception-header + section (.eh_frame_hdr, pointed to by program-header + PT_GNU_EH_FRAME). The exception-header is self-describing in the + sense that the format of the addresses contained in it is expressed + as a one-byte type-descriptor called a "pointer-encoding" (PE). + + The exception header encodes the address of the .eh_frame section + and optionally contains a binary search table for the + Frame Descriptor Entries (FDEs) in the .eh_frame. The contents of + .eh_frame has the format described by the DWARF v3 standard + (http://www.eagercon.com/dwarf/dwarf3std.htm), except that code + addresses may be encoded in different ways. Also, .eh_frame has + augmentations that allow encoding a language-specific data-area + (LSDA) pointer and a pointer to a personality-routine. + + Details: + + The Common Information Entry (CIE) associated with an FDE may + contain an augmentation string. Each character in this string has + a specific meaning and either one or two associated operands. The + operands are stored in an augmentation body which appears right + after the "return_address_register" member and before the + "initial_instructions" member. The operands appear in the order + in which the characters appear in the string. For example, if the + augmentation string is "zL", the operand for 'z' would be first in + the augmentation body and the operand for 'L' would be second. + The following characters are supported for the CIE augmentation + string: + + 'z': The operand for this character is a uleb128 value that gives the + length of the CIE augmentation body, not counting the length + of the uleb128 operand itself. If present, this code must + appear as the first character in the augmentation body. + + 'L': Indicates that the FDE's augmentation body contains an LSDA + pointer. The operand for this character is a single byte + that specifies the pointer-encoding (PE) that is used for + the LSDA pointer. + + 'R': Indicates that the code-pointers (FDE members + "initial_location" and "address_range" and the operand for + DW_CFA_set_loc) in the FDE have a non-default encoding. The + operand for this character is a single byte that specifies + the pointer-encoding (PE) that is used for the + code-pointers. Note: the "address_range" member is always + encoded as an absolute value. Apart from that, the specified + FDE pointer-encoding applies. + + 'P': Indicates the presence of a personality routine (handler). + The first operand for this character specifies the + pointer-encoding (PE) that is used for the second operand, + which specifies the address of the personality routine. + + If the augmentation string contains any other characters, the + remainder of the augmentation string should be ignored. + Furthermore, if the size of the augmentation body is unknown + (i.e., 'z' is not the first character of the augmentation string), + then the entire CIE as well all associated FDEs must be ignored. + + A Frame Descriptor Entries (FDE) may contain an augmentation body + which, if present, appears right after the "address_range" member + and before the "instructions" member. The contents of this body + is implicitly defined by the augmentation string of the associated + CIE. The meaning of the characters in the CIE's augmentation + string as far as FDEs are concerned is as follows: + + 'z': The first operand in the FDE's augmentation body specifies + the total length of the augmentation body as a uleb128 (not + counting the length of the uleb128 operand itself). + + 'L': The operand for this character is an LSDA pointer, encoded + in the format specified by the corresponding operand in the + CIE's augmentation body. + +*/ + +#define DW_EH_VERSION 1 /* The version we're implementing */ + +struct __attribute__((packed)) dwarf_eh_frame_hdr + { + unsigned char version; + unsigned char eh_frame_ptr_enc; + unsigned char fde_count_enc; + unsigned char table_enc; + Elf_W (Addr) eh_frame; + /* The rest of the header is variable-length and consists of the + following members: + + encoded_t fde_count; + struct + { + encoded_t start_ip; // first address covered by this FDE + encoded_t fde_addr; // address of the FDE + } + binary_search_table[fde_count]; */ + }; + +#endif /* dwarf_eh_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/dwarf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/dwarf.h new file mode 100644 index 0000000..fab93c6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/dwarf.h @@ -0,0 +1,450 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef dwarf_h +#define dwarf_h + +#include + +struct dwarf_cursor; /* forward-declaration */ +struct elf_dyn_info; + +#include "dwarf-config.h" + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef UNW_REMOTE_ONLY + #if defined(HAVE_LINK_H) + #include + #elif defined(HAVE_SYS_LINK_H) + #include + #else + #error Could not find + #endif +#endif + +#include + +/* DWARF expression opcodes. */ + +typedef enum + { + DW_OP_addr = 0x03, + DW_OP_deref = 0x06, + DW_OP_const1u = 0x08, + DW_OP_const1s = 0x09, + DW_OP_const2u = 0x0a, + DW_OP_const2s = 0x0b, + DW_OP_const4u = 0x0c, + DW_OP_const4s = 0x0d, + DW_OP_const8u = 0x0e, + DW_OP_const8s = 0x0f, + DW_OP_constu = 0x10, + DW_OP_consts = 0x11, + DW_OP_dup = 0x12, + DW_OP_drop = 0x13, + DW_OP_over = 0x14, + DW_OP_pick = 0x15, + DW_OP_swap = 0x16, + DW_OP_rot = 0x17, + DW_OP_xderef = 0x18, + DW_OP_abs = 0x19, + DW_OP_and = 0x1a, + DW_OP_div = 0x1b, + DW_OP_minus = 0x1c, + DW_OP_mod = 0x1d, + DW_OP_mul = 0x1e, + DW_OP_neg = 0x1f, + DW_OP_not = 0x20, + DW_OP_or = 0x21, + DW_OP_plus = 0x22, + DW_OP_plus_uconst = 0x23, + DW_OP_shl = 0x24, + DW_OP_shr = 0x25, + DW_OP_shra = 0x26, + DW_OP_xor = 0x27, + DW_OP_skip = 0x2f, + DW_OP_bra = 0x28, + DW_OP_eq = 0x29, + DW_OP_ge = 0x2a, + DW_OP_gt = 0x2b, + DW_OP_le = 0x2c, + DW_OP_lt = 0x2d, + DW_OP_ne = 0x2e, + DW_OP_lit0 = 0x30, + DW_OP_lit1, DW_OP_lit2, DW_OP_lit3, DW_OP_lit4, DW_OP_lit5, + DW_OP_lit6, DW_OP_lit7, DW_OP_lit8, DW_OP_lit9, DW_OP_lit10, + DW_OP_lit11, DW_OP_lit12, DW_OP_lit13, DW_OP_lit14, DW_OP_lit15, + DW_OP_lit16, DW_OP_lit17, DW_OP_lit18, DW_OP_lit19, DW_OP_lit20, + DW_OP_lit21, DW_OP_lit22, DW_OP_lit23, DW_OP_lit24, DW_OP_lit25, + DW_OP_lit26, DW_OP_lit27, DW_OP_lit28, DW_OP_lit29, DW_OP_lit30, + DW_OP_lit31, + DW_OP_reg0 = 0x50, + DW_OP_reg1, DW_OP_reg2, DW_OP_reg3, DW_OP_reg4, DW_OP_reg5, + DW_OP_reg6, DW_OP_reg7, DW_OP_reg8, DW_OP_reg9, DW_OP_reg10, + DW_OP_reg11, DW_OP_reg12, DW_OP_reg13, DW_OP_reg14, DW_OP_reg15, + DW_OP_reg16, DW_OP_reg17, DW_OP_reg18, DW_OP_reg19, DW_OP_reg20, + DW_OP_reg21, DW_OP_reg22, DW_OP_reg23, DW_OP_reg24, DW_OP_reg25, + DW_OP_reg26, DW_OP_reg27, DW_OP_reg28, DW_OP_reg29, DW_OP_reg30, + DW_OP_reg31, + DW_OP_breg0 = 0x70, + DW_OP_breg1, DW_OP_breg2, DW_OP_breg3, DW_OP_breg4, DW_OP_breg5, + DW_OP_breg6, DW_OP_breg7, DW_OP_breg8, DW_OP_breg9, DW_OP_breg10, + DW_OP_breg11, DW_OP_breg12, DW_OP_breg13, DW_OP_breg14, DW_OP_breg15, + DW_OP_breg16, DW_OP_breg17, DW_OP_breg18, DW_OP_breg19, DW_OP_breg20, + DW_OP_breg21, DW_OP_breg22, DW_OP_breg23, DW_OP_breg24, DW_OP_breg25, + DW_OP_breg26, DW_OP_breg27, DW_OP_breg28, DW_OP_breg29, DW_OP_breg30, + DW_OP_breg31, + DW_OP_regx = 0x90, + DW_OP_fbreg = 0x91, + DW_OP_bregx = 0x92, + DW_OP_piece = 0x93, + DW_OP_deref_size = 0x94, + DW_OP_xderef_size = 0x95, + DW_OP_nop = 0x96, + DW_OP_push_object_address = 0x97, + DW_OP_call2 = 0x98, + DW_OP_call4 = 0x99, + DW_OP_call_ref = 0x9a, + DW_OP_lo_user = 0xe0, + DW_OP_hi_user = 0xff + } +dwarf_expr_op_t; + +#define DWARF_CIE_VERSION 3 +#define DWARF_CIE_VERSION_MAX 4 + +#define DWARF_CFA_OPCODE_MASK 0xc0 +#define DWARF_CFA_OPERAND_MASK 0x3f + +typedef enum + { + DW_CFA_advance_loc = 0x40, + DW_CFA_offset = 0x80, + DW_CFA_restore = 0xc0, + DW_CFA_nop = 0x00, + DW_CFA_set_loc = 0x01, + DW_CFA_advance_loc1 = 0x02, + DW_CFA_advance_loc2 = 0x03, + DW_CFA_advance_loc4 = 0x04, + DW_CFA_offset_extended = 0x05, + DW_CFA_restore_extended = 0x06, + DW_CFA_undefined = 0x07, + DW_CFA_same_value = 0x08, + DW_CFA_register = 0x09, + DW_CFA_remember_state = 0x0a, + DW_CFA_restore_state = 0x0b, + DW_CFA_def_cfa = 0x0c, + DW_CFA_def_cfa_register = 0x0d, + DW_CFA_def_cfa_offset = 0x0e, + DW_CFA_def_cfa_expression = 0x0f, + DW_CFA_expression = 0x10, + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + DW_CFA_val_expression = 0x16, + DW_CFA_lo_user = 0x1c, + DW_CFA_MIPS_advance_loc8 = 0x1d, + DW_CFA_GNU_window_save = 0x2d, + DW_CFA_GNU_args_size = 0x2e, + DW_CFA_GNU_negative_offset_extended = 0x2f, + DW_CFA_hi_user = 0x3c + } +dwarf_cfa_t; + +/* DWARF Pointer-Encoding (PEs). + + Pointer-Encodings were invented for the GCC exception-handling + support for C++, but they represent a rather generic way of + describing the format in which an address/pointer is stored and + hence we include the definitions here, in the main dwarf.h file. + The Pointer-Encoding format is partially documented in Linux Base + Spec v1.3 (http://www.linuxbase.org/spec/). The rest is reverse + engineered from GCC. + +*/ +#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */ +#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */ +/* Flag bit. If set, the resulting pointer is the address of the word + that contains the final address. */ +#define DW_EH_PE_indirect 0x80 + +/* Pointer-encoding formats: */ +#define DW_EH_PE_omit 0xff +#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */ +#define DW_EH_PE_uleb128 0x01 /* unsigned LE base-128 value */ +#define DW_EH_PE_udata2 0x02 /* unsigned 16-bit value */ +#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */ +#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */ +#define DW_EH_PE_sleb128 0x09 /* signed LE base-128 value */ +#define DW_EH_PE_sdata2 0x0a /* signed 16-bit value */ +#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */ +#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */ + +/* Pointer-encoding application: */ +#define DW_EH_PE_absptr 0x00 /* absolute value */ +#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */ +#define DW_EH_PE_textrel 0x20 /* text-relative (GCC-specific???) */ +#define DW_EH_PE_datarel 0x30 /* data-relative */ +/* The following are not documented by LSB v1.3, yet they are used by + GCC, presumably they aren't documented by LSB since they aren't + used on Linux: */ +#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */ +#define DW_EH_PE_aligned 0x50 /* aligned pointer */ + +extern struct mempool dwarf_reg_state_pool; +extern struct mempool dwarf_cie_info_pool; + +typedef enum + { + DWARF_WHERE_UNDEF, /* register isn't saved at all */ + DWARF_WHERE_SAME, /* register has same value as in prev. frame */ + DWARF_WHERE_CFAREL, /* register saved at CFA-relative address */ + DWARF_WHERE_REG, /* register saved in another register */ + DWARF_WHERE_EXPR, /* register saved */ + DWARF_WHERE_VAL_EXPR, /* register has computed value */ + } +dwarf_where_t; + +/* For uniformity, we'd like to treat the CFA save-location like any + other register save-location, but this doesn't quite work, because + the CFA can be expressed as a (REGISTER,OFFSET) pair. To handle + this, we use two dwarf_save_loc structures to describe the CFA. + The first one (CFA_REG_COLUMN), tells us where the CFA is saved. + In the case of DWARF_WHERE_EXPR, the CFA is defined by a DWARF + location expression whose address is given by member "val". In the + case of DWARF_WHERE_REG, member "val" gives the number of the + base-register and the "val" member of DWARF_CFA_OFF_COLUMN gives + the offset value. */ +#define DWARF_CFA_REG_COLUMN DWARF_NUM_PRESERVED_REGS +#define DWARF_CFA_OFF_COLUMN (DWARF_NUM_PRESERVED_REGS + 1) + +typedef struct dwarf_reg_only_state + { + char where[DWARF_NUM_PRESERVED_REGS + 2]; /* how is the register saved? */ + unw_word_t val[DWARF_NUM_PRESERVED_REGS + 2]; /* where it's saved */ + } +dwarf_reg_only_state_t; + +typedef struct dwarf_reg_state + { + unw_word_t ret_addr_column; /* which column in rule table represents return address */ + dwarf_reg_only_state_t reg; + } +dwarf_reg_state_t; + +typedef struct dwarf_stackable_reg_state + { + struct dwarf_stackable_reg_state *next; /* for rs_stack */ + dwarf_reg_state_t state; + } +dwarf_stackable_reg_state_t; + +typedef struct dwarf_reg_cache_entry + { + unw_word_t ip; /* ip this rs is for */ + unsigned short coll_chain; /* used for hash collisions */ + unsigned short hint; /* hint for next rs to try (or -1) */ + unsigned short valid : 1; /* optional machine-dependent signal info */ + unsigned short signal_frame : 1; /* optional machine-dependent signal info */ + } +dwarf_reg_cache_entry_t; + +typedef struct dwarf_cie_info + { + unw_word_t cie_instr_start; /* start addr. of CIE "initial_instructions" */ + unw_word_t cie_instr_end; /* end addr. of CIE "initial_instructions" */ + unw_word_t fde_instr_start; /* start addr. of FDE "instructions" */ + unw_word_t fde_instr_end; /* end addr. of FDE "instructions" */ + unw_word_t code_align; /* code-alignment factor */ + unw_word_t data_align; /* data-alignment factor */ + unw_word_t ret_addr_column; /* column of return-address register */ + unw_word_t handler; /* address of personality-routine */ + uint16_t abi; + uint16_t tag; + uint8_t fde_encoding; + uint8_t lsda_encoding; + unsigned int sized_augmentation : 1; + unsigned int have_abi_marker : 1; + unsigned int signal_frame : 1; + } +dwarf_cie_info_t; + +typedef struct dwarf_state_record + { + unsigned char fde_encoding; + unw_word_t args_size; + + dwarf_reg_state_t rs_initial; /* reg-state after CIE instructions */ + dwarf_reg_state_t rs_current; /* current reg-state */ + } +dwarf_state_record_t; + +typedef struct dwarf_cursor + { + void *as_arg; /* argument to address-space callbacks */ + unw_addr_space_t as; /* reference to per-address-space info */ + + unw_word_t cfa; /* canonical frame address; aka frame-/stack-pointer */ + unw_word_t ip; /* instruction pointer */ + unw_word_t args_size; /* size of arguments */ + unw_word_t eh_args[UNW_TDEP_NUM_EH_REGS]; + unsigned int eh_valid_mask; + + dwarf_loc_t loc[DWARF_NUM_PRESERVED_REGS]; + + unsigned int stash_frames :1; /* stash frames for fast lookup */ + unsigned int use_prev_instr :1; /* use previous (= call) or current (= signal) instruction? */ + unsigned int pi_valid :1; /* is proc_info valid? */ + unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */ + unw_proc_info_t pi; /* info about current procedure */ + + short hint; /* faster lookup of the rs cache */ + short prev_rs; + } +dwarf_cursor_t; + +#define DWARF_DEFAULT_LOG_UNW_CACHE_SIZE 7 +#define DWARF_DEFAULT_UNW_CACHE_SIZE (1 << DWARF_DEFAULT_LOG_UNW_CACHE_SIZE) + +#define DWARF_DEFAULT_LOG_UNW_HASH_SIZE (DWARF_DEFAULT_LOG_UNW_CACHE_SIZE + 1) +#define DWARF_DEFAULT_UNW_HASH_SIZE (1 << DWARF_DEFAULT_LOG_UNW_HASH_SIZE) + +typedef unsigned char unw_hash_index_t; + +struct dwarf_rs_cache + { + pthread_mutex_t lock; + unsigned short rr_head; /* index of least-recently allocated rs */ + + unsigned short log_size; + unsigned short prev_log_size; + + /* hash table that maps instruction pointer to rs index: */ + unsigned short *hash; + + uint32_t generation; /* generation number */ + + /* rs cache: */ + dwarf_reg_state_t *buckets; + dwarf_reg_cache_entry_t *links; + + /* default memory, loaded in BSS segment */ + unsigned short default_hash[DWARF_DEFAULT_UNW_HASH_SIZE]; + dwarf_reg_state_t default_buckets[DWARF_DEFAULT_UNW_CACHE_SIZE]; + dwarf_reg_cache_entry_t default_links[DWARF_DEFAULT_UNW_CACHE_SIZE]; + }; + +/* A list of descriptors for loaded .debug_frame sections. */ + +struct unw_debug_frame_list + { + /* The start (inclusive) and end (exclusive) of the described region. */ + unw_word_t start; + unw_word_t end; + /* The debug frame itself. */ + char *debug_frame; + size_t debug_frame_size; + /* Index (for binary search). */ + struct table_entry *index; + size_t index_size; + /* Pointer to next descriptor. */ + struct unw_debug_frame_list *next; + }; + +/* Convenience macros: */ +#define dwarf_init UNW_ARCH_OBJ (dwarf_init) +#define dwarf_callback UNW_OBJ (dwarf_callback) +#define dwarf_find_proc_info UNW_OBJ (dwarf_find_proc_info) +#define dwarf_find_debug_frame UNW_OBJ (dwarf_find_debug_frame) +#define dwarf_search_unwind_table UNW_OBJ (dwarf_search_unwind_table) +#define dwarf_find_unwind_table UNW_OBJ (dwarf_find_unwind_table) +#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info) +#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info) +#define dwarf_eval_expr UNW_OBJ (dwarf_eval_expr) +#define dwarf_stack_aligned UNW_OBJ (dwarf_stack_aligned) +#define dwarf_extract_proc_info_from_fde \ + UNW_OBJ (dwarf_extract_proc_info_from_fde) +#define dwarf_find_save_locs UNW_OBJ (dwarf_find_save_locs) +#define dwarf_make_proc_info UNW_OBJ (dwarf_make_proc_info) +#define dwarf_apply_reg_state UNW_OBJ (dwarf_apply_reg_state) +#define dwarf_reg_states_iterate UNW_OBJ (dwarf_reg_states_iterate) +#define dwarf_read_encoded_pointer UNW_OBJ (dwarf_read_encoded_pointer) +#define dwarf_step UNW_OBJ (dwarf_step) +#define dwarf_flush_rs_cache UNW_OBJ (dwarf_flush_rs_cache) + +extern int dwarf_init (void); +#ifndef UNW_REMOTE_ONLY +extern int dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr); +extern int dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); +#endif /* !UNW_REMOTE_ONLY */ +extern int dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, + unw_word_t ip, unw_word_t segbase, + const char* obj_name, unw_word_t start, + unw_word_t end); +extern int dwarf_search_unwind_table (unw_addr_space_t as, + unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); + +extern int dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as, + char *path, unw_word_t segbase, unw_word_t mapoff, + unw_word_t ip); +extern void dwarf_put_unwind_info (unw_addr_space_t as, + unw_proc_info_t *pi, void *arg); +extern int dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr, + unw_word_t len, unw_word_t *valp, + int *is_register); +extern int +dwarf_stack_aligned(struct dwarf_cursor *c, unw_word_t cfa_addr, + unw_word_t rbp_addr, unw_word_t *offset); + +extern int dwarf_extract_proc_info_from_fde (unw_addr_space_t as, + unw_accessors_t *a, + unw_word_t *fde_addr, + unw_proc_info_t *pi, + unw_word_t base, + int need_unwind_info, + int is_debug_frame, + void *arg); +extern int dwarf_find_save_locs (struct dwarf_cursor *c); +extern int dwarf_make_proc_info (struct dwarf_cursor *c); +extern int dwarf_apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs); +extern int dwarf_reg_states_iterate (struct dwarf_cursor *c, unw_reg_states_callback cb, void *token); +extern int dwarf_read_encoded_pointer (unw_addr_space_t as, + unw_accessors_t *a, + unw_word_t *addr, + unsigned char encoding, + const unw_proc_info_t *pi, + unw_word_t *valp, void *arg); +extern int dwarf_step (struct dwarf_cursor *c); +extern int dwarf_flush_rs_cache (struct dwarf_rs_cache *cache); + +#endif /* dwarf_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-aarch64.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-aarch64.h new file mode 100644 index 0000000..85812e1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-aarch64.h @@ -0,0 +1,210 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + Copyright (C) 2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef LIBUNWIND_H +#define LIBUNWIND_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include +#include +#include + +#define UNW_TARGET aarch64 +#define UNW_TARGET_AARCH64 1 + +#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ + +/* This needs to be big enough to accommodate "struct cursor", while + leaving some slack for future expansion. Changing this value will + require recompiling all users of this library. Stack allocation is + relatively cheap and unwind-state copying is relatively rare, so we + want to err on making it rather too big than too small. */ + +#define UNW_TDEP_CURSOR_LEN 512 + +typedef uint64_t unw_word_t; +typedef int64_t unw_sword_t; + +typedef long double unw_tdep_fpreg_t; + +typedef struct + { + /* no aarch64-specific auxiliary proc-info */ + } +unw_tdep_proc_info_t; + +typedef enum + { + /* 64-bit general registers. */ + UNW_AARCH64_X0, + UNW_AARCH64_X1, + UNW_AARCH64_X2, + UNW_AARCH64_X3, + UNW_AARCH64_X4, + UNW_AARCH64_X5, + UNW_AARCH64_X6, + UNW_AARCH64_X7, + UNW_AARCH64_X8, + + /* Temporary registers. */ + UNW_AARCH64_X9, + UNW_AARCH64_X10, + UNW_AARCH64_X11, + UNW_AARCH64_X12, + UNW_AARCH64_X13, + UNW_AARCH64_X14, + UNW_AARCH64_X15, + + /* Intra-procedure-call temporary registers. */ + UNW_AARCH64_X16, + UNW_AARCH64_X17, + + /* Callee-saved registers. */ + UNW_AARCH64_X18, + UNW_AARCH64_X19, + UNW_AARCH64_X20, + UNW_AARCH64_X21, + UNW_AARCH64_X22, + UNW_AARCH64_X23, + UNW_AARCH64_X24, + UNW_AARCH64_X25, + UNW_AARCH64_X26, + UNW_AARCH64_X27, + UNW_AARCH64_X28, + + /* 64-bit frame pointer. */ + UNW_AARCH64_X29, + + /* 64-bit link register. */ + UNW_AARCH64_X30, + + /* 64-bit stack pointer. */ + UNW_AARCH64_SP = 31, + UNW_AARCH64_PC, + UNW_AARCH64_PSTATE, + + /* 128-bit FP/Advanced SIMD registers. */ + UNW_AARCH64_V0 = 64, + UNW_AARCH64_V1, + UNW_AARCH64_V2, + UNW_AARCH64_V3, + UNW_AARCH64_V4, + UNW_AARCH64_V5, + UNW_AARCH64_V6, + UNW_AARCH64_V7, + UNW_AARCH64_V8, + UNW_AARCH64_V9, + UNW_AARCH64_V10, + UNW_AARCH64_V11, + UNW_AARCH64_V12, + UNW_AARCH64_V13, + UNW_AARCH64_V14, + UNW_AARCH64_V15, + UNW_AARCH64_V16, + UNW_AARCH64_V17, + UNW_AARCH64_V18, + UNW_AARCH64_V19, + UNW_AARCH64_V20, + UNW_AARCH64_V21, + UNW_AARCH64_V22, + UNW_AARCH64_V23, + UNW_AARCH64_V24, + UNW_AARCH64_V25, + UNW_AARCH64_V26, + UNW_AARCH64_V27, + UNW_AARCH64_V28, + UNW_AARCH64_V29, + UNW_AARCH64_V30, + UNW_AARCH64_V31, + + UNW_AARCH64_FPSR, + UNW_AARCH64_FPCR, + + /* For AArch64, the CFA is the value of SP (x31) at the call site of the + previous frame. */ + UNW_AARCH64_CFA = UNW_AARCH64_SP, + + UNW_TDEP_LAST_REG = UNW_AARCH64_FPCR, + + UNW_TDEP_IP = UNW_AARCH64_X30, + UNW_TDEP_SP = UNW_AARCH64_SP, + UNW_TDEP_EH = UNW_AARCH64_X0, + + } +aarch64_regnum_t; + +/* Use R0 through R3 to pass exception handling information. */ +#define UNW_TDEP_NUM_EH_REGS 4 + +typedef struct unw_tdep_save_loc + { + /* Additional target-dependent info on a save location. */ + } +unw_tdep_save_loc_t; + + +/* On AArch64, we can directly use ucontext_t as the unwind context. */ +typedef ucontext_t unw_tdep_context_t; + +#include "libunwind-common.h" +#include "libunwind-dynamic.h" + +#define unw_tdep_getcontext(uc) (({ \ + unw_tdep_context_t *unw_ctx = (uc); \ + register uint64_t *unw_base asm ("x0") = (uint64_t*) unw_ctx->uc_mcontext.regs; \ + __asm__ __volatile__ ( \ + "stp x0, x1, [%[base], #0]\n" \ + "stp x2, x3, [%[base], #16]\n" \ + "stp x4, x5, [%[base], #32]\n" \ + "stp x6, x7, [%[base], #48]\n" \ + "stp x8, x9, [%[base], #64]\n" \ + "stp x10, x11, [%[base], #80]\n" \ + "stp x12, x13, [%[base], #96]\n" \ + "stp x14, x13, [%[base], #112]\n" \ + "stp x16, x17, [%[base], #128]\n" \ + "stp x18, x19, [%[base], #144]\n" \ + "stp x20, x21, [%[base], #160]\n" \ + "stp x22, x23, [%[base], #176]\n" \ + "stp x24, x25, [%[base], #192]\n" \ + "stp x26, x27, [%[base], #208]\n" \ + "stp x28, x29, [%[base], #224]\n" \ + "str x30, [%[base], #240]\n" \ + "mov x1, sp\n" \ + "stp x1, x30, [%[base], #248]\n" \ + : [base] "+r" (unw_base) : : "x1", "memory"); \ + }), 0) +#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) + +extern int unw_tdep_is_fpreg (int); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* LIBUNWIND_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-arm.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-arm.h new file mode 100644 index 0000000..6709b7a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-arm.h @@ -0,0 +1,303 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef LIBUNWIND_H +#define LIBUNWIND_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include +#include + +#define UNW_TARGET arm +#define UNW_TARGET_ARM 1 + +#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ + +/* This needs to be big enough to accommodate "struct cursor", while + leaving some slack for future expansion. Changing this value will + require recompiling all users of this library. Stack allocation is + relatively cheap and unwind-state copying is relatively rare, so we + want to err on making it rather too big than too small. */ + +/* FIXME for ARM. Too big? What do other things use for similar tasks? */ +#define UNW_TDEP_CURSOR_LEN 4096 + +typedef uint32_t unw_word_t; +typedef int32_t unw_sword_t; + +typedef long double unw_tdep_fpreg_t; + +typedef enum + { + UNW_ARM_R0, + UNW_ARM_R1, + UNW_ARM_R2, + UNW_ARM_R3, + UNW_ARM_R4, + UNW_ARM_R5, + UNW_ARM_R6, + UNW_ARM_R7, + UNW_ARM_R8, + UNW_ARM_R9, + UNW_ARM_R10, + UNW_ARM_R11, + UNW_ARM_R12, + UNW_ARM_R13, + UNW_ARM_R14, + UNW_ARM_R15, + + /* VFPv2 s0-s31 (obsolescent numberings). */ + UNW_ARM_S0 = 64, + UNW_ARM_S1, + UNW_ARM_S2, + UNW_ARM_S3, + UNW_ARM_S4, + UNW_ARM_S5, + UNW_ARM_S6, + UNW_ARM_S7, + UNW_ARM_S8, + UNW_ARM_S9, + UNW_ARM_S10, + UNW_ARM_S11, + UNW_ARM_S12, + UNW_ARM_S13, + UNW_ARM_S14, + UNW_ARM_S15, + UNW_ARM_S16, + UNW_ARM_S17, + UNW_ARM_S18, + UNW_ARM_S19, + UNW_ARM_S20, + UNW_ARM_S21, + UNW_ARM_S22, + UNW_ARM_S23, + UNW_ARM_S24, + UNW_ARM_S25, + UNW_ARM_S26, + UNW_ARM_S27, + UNW_ARM_S28, + UNW_ARM_S29, + UNW_ARM_S30, + UNW_ARM_S31, + + /* FPA register numberings. */ + UNW_ARM_F0 = 96, + UNW_ARM_F1, + UNW_ARM_F2, + UNW_ARM_F3, + UNW_ARM_F4, + UNW_ARM_F5, + UNW_ARM_F6, + UNW_ARM_F7, + + /* iWMMXt GR register numberings. */ + UNW_ARM_wCGR0 = 104, + UNW_ARM_wCGR1, + UNW_ARM_wCGR2, + UNW_ARM_wCGR3, + UNW_ARM_wCGR4, + UNW_ARM_wCGR5, + UNW_ARM_wCGR6, + UNW_ARM_wCGR7, + + /* iWMMXt register numberings. */ + UNW_ARM_wR0 = 112, + UNW_ARM_wR1, + UNW_ARM_wR2, + UNW_ARM_wR3, + UNW_ARM_wR4, + UNW_ARM_wR5, + UNW_ARM_wR6, + UNW_ARM_wR7, + UNW_ARM_wR8, + UNW_ARM_wR9, + UNW_ARM_wR10, + UNW_ARM_wR11, + UNW_ARM_wR12, + UNW_ARM_wR13, + UNW_ARM_wR14, + UNW_ARM_wR15, + + /* Two-byte encodings from here on. */ + + /* SPSR. */ + UNW_ARM_SPSR = 128, + UNW_ARM_SPSR_FIQ, + UNW_ARM_SPSR_IRQ, + UNW_ARM_SPSR_ABT, + UNW_ARM_SPSR_UND, + UNW_ARM_SPSR_SVC, + + /* User mode registers. */ + UNW_ARM_R8_USR = 144, + UNW_ARM_R9_USR, + UNW_ARM_R10_USR, + UNW_ARM_R11_USR, + UNW_ARM_R12_USR, + UNW_ARM_R13_USR, + UNW_ARM_R14_USR, + + /* FIQ registers. */ + UNW_ARM_R8_FIQ = 151, + UNW_ARM_R9_FIQ, + UNW_ARM_R10_FIQ, + UNW_ARM_R11_FIQ, + UNW_ARM_R12_FIQ, + UNW_ARM_R13_FIQ, + UNW_ARM_R14_FIQ, + + /* IRQ registers. */ + UNW_ARM_R13_IRQ = 158, + UNW_ARM_R14_IRQ, + + /* ABT registers. */ + UNW_ARM_R13_ABT = 160, + UNW_ARM_R14_ABT, + + /* UND registers. */ + UNW_ARM_R13_UND = 162, + UNW_ARM_R14_UND, + + /* SVC registers. */ + UNW_ARM_R13_SVC = 164, + UNW_ARM_R14_SVC, + + /* iWMMXt control registers. */ + UNW_ARM_wC0 = 192, + UNW_ARM_wC1, + UNW_ARM_wC2, + UNW_ARM_wC3, + UNW_ARM_wC4, + UNW_ARM_wC5, + UNW_ARM_wC6, + UNW_ARM_wC7, + + /* VFPv3/Neon 64-bit registers. */ + UNW_ARM_D0 = 256, + UNW_ARM_D1, + UNW_ARM_D2, + UNW_ARM_D3, + UNW_ARM_D4, + UNW_ARM_D5, + UNW_ARM_D6, + UNW_ARM_D7, + UNW_ARM_D8, + UNW_ARM_D9, + UNW_ARM_D10, + UNW_ARM_D11, + UNW_ARM_D12, + UNW_ARM_D13, + UNW_ARM_D14, + UNW_ARM_D15, + UNW_ARM_D16, + UNW_ARM_D17, + UNW_ARM_D18, + UNW_ARM_D19, + UNW_ARM_D20, + UNW_ARM_D21, + UNW_ARM_D22, + UNW_ARM_D23, + UNW_ARM_D24, + UNW_ARM_D25, + UNW_ARM_D26, + UNW_ARM_D27, + UNW_ARM_D28, + UNW_ARM_D29, + UNW_ARM_D30, + UNW_ARM_D31, + + /* For ARM, the CFA is the value of SP (r13) at the call site in the + previous frame. */ + UNW_ARM_CFA, + + UNW_TDEP_LAST_REG = UNW_ARM_D31, + + UNW_TDEP_IP = UNW_ARM_R14, /* A little white lie. */ + UNW_TDEP_SP = UNW_ARM_R13, + UNW_TDEP_EH = UNW_ARM_R0 /* FIXME. */ + } +arm_regnum_t; + +#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for ARM. */ + +typedef struct unw_tdep_save_loc + { + /* Additional target-dependent info on a save location. */ + } +unw_tdep_save_loc_t; + +/* On ARM, we define our own unw_tdep_context instead of using ucontext_t. + This allows us to support systems that don't support getcontext and + therefore do not define ucontext_t. */ +typedef struct unw_tdep_context + { + unsigned long regs[16]; + } +unw_tdep_context_t; + +/* There is no getcontext() on ARM. Use a stub version which only saves GP + registers. FIXME: Not ideal, may not be sufficient for all libunwind + use cases. Stores pc+8, which is only approximately correct, really. */ +#ifndef __thumb__ +#define unw_tdep_getcontext(uc) (({ \ + unw_tdep_context_t *unw_ctx = (uc); \ + register unsigned long *unw_base __asm__ ("r0") = unw_ctx->regs; \ + __asm__ __volatile__ ( \ + "stmia %[base], {r0-r15}" \ + : : [base] "r" (unw_base) : "memory"); \ + }), 0) +#else /* __thumb__ */ +#define unw_tdep_getcontext(uc) (({ \ + unw_tdep_context_t *unw_ctx = (uc); \ + register unsigned long *unw_base __asm__ ("r0") = unw_ctx->regs; \ + __asm__ __volatile__ ( \ + ".align 2\nbx pc\nnop\n.code 32\n" \ + "stmia %[base], {r0-r15}\n" \ + "orr %[base], pc, #1\nbx %[base]\n" \ + ".code 16\n" \ + : [base] "+r" (unw_base) : : "memory", "cc"); \ + }), 0) +#endif + +#include "libunwind-dynamic.h" + +typedef struct + { + /* no arm-specific auxiliary proc-info */ + } +unw_tdep_proc_info_t; + +#include "libunwind-common.h" + +#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) +extern int unw_tdep_is_fpreg (int); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* LIBUNWIND_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-common.h.in b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-common.h.in new file mode 100644 index 0000000..8d96ddc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-common.h.in @@ -0,0 +1,281 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#define UNW_VERSION_MAJOR @PKG_MAJOR@ +#define UNW_VERSION_MINOR @PKG_MINOR@ +#define UNW_VERSION_EXTRA @PKG_EXTRA@ + +#define UNW_VERSION_CODE(maj,min) (((maj) << 16) | (min)) +#define UNW_VERSION UNW_VERSION_CODE(UNW_VERSION_MAJOR, UNW_VERSION_MINOR) + +#define UNW_PASTE2(x,y) x##y +#define UNW_PASTE(x,y) UNW_PASTE2(x,y) +#define UNW_OBJ(fn) UNW_PASTE(UNW_PREFIX, fn) +#define UNW_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_), fn) + +#ifdef UNW_LOCAL_ONLY +# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_UL,UNW_TARGET),_) +#else /* !UNW_LOCAL_ONLY */ +# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_) +#endif /* !UNW_LOCAL_ONLY */ + +/* Error codes. The unwind routines return the *negated* values of + these error codes on error and a non-negative value on success. */ +typedef enum + { + UNW_ESUCCESS = 0, /* no error */ + UNW_EUNSPEC, /* unspecified (general) error */ + UNW_ENOMEM, /* out of memory */ + UNW_EBADREG, /* bad register number */ + UNW_EREADONLYREG, /* attempt to write read-only register */ + UNW_ESTOPUNWIND, /* stop unwinding */ + UNW_EINVALIDIP, /* invalid IP */ + UNW_EBADFRAME, /* bad frame */ + UNW_EINVAL, /* unsupported operation or bad value */ + UNW_EBADVERSION, /* unwind info has unsupported version */ + UNW_ENOINFO /* no unwind info found */ + } +unw_error_t; + +/* The following enum defines the indices for a couple of + (pseudo-)registers which have the same meaning across all + platforms. (RO) means read-only. (RW) means read-write. General + registers (aka "integer registers") are expected to start with + index 0. The number of such registers is architecture-dependent. + The remaining indices can be used as an architecture sees fit. The + last valid register index is given by UNW_REG_LAST. */ +typedef enum + { + UNW_REG_IP = UNW_TDEP_IP, /* (rw) instruction pointer (pc) */ + UNW_REG_SP = UNW_TDEP_SP, /* (ro) stack pointer */ + UNW_REG_EH = UNW_TDEP_EH, /* (rw) exception-handling reg base */ + UNW_REG_LAST = UNW_TDEP_LAST_REG + } +unw_frame_regnum_t; + +/* Number of exception-handler argument registers: */ +#define UNW_NUM_EH_REGS UNW_TDEP_NUM_EH_REGS + +typedef enum + { + UNW_CACHE_NONE, /* no caching */ + UNW_CACHE_GLOBAL, /* shared global cache */ + UNW_CACHE_PER_THREAD /* per-thread caching */ + } +unw_caching_policy_t; + +typedef enum + { + UNW_INIT_SIGNAL_FRAME = 1, /* We know this is a signal frame */ + } +unw_init_local2_flags_t; + +typedef int unw_regnum_t; + +/* The unwind cursor starts at the youngest (most deeply nested) frame + and is used to track the frame state as the unwinder steps from + frame to frame. It is safe to make (shallow) copies of variables + of this type. */ +typedef struct unw_cursor + { + unw_word_t opaque[UNW_TDEP_CURSOR_LEN]; + } +unw_cursor_t; + +/* This type encapsulates the entire (preserved) machine-state. */ +typedef unw_tdep_context_t unw_context_t; + +/* unw_getcontext() fills the unw_context_t pointed to by UC with the + machine state as it exists at the call-site. For implementation + reasons, this needs to be a target-dependent macro. It's easiest + to think of unw_getcontext() as being identical to getcontext(). */ +#define unw_getcontext(uc) unw_tdep_getcontext(uc) + +/* Return 1 if register number R is a floating-point register, zero + otherwise. + This routine is signal-safe. */ +#define unw_is_fpreg(r) unw_tdep_is_fpreg(r) + +typedef unw_tdep_fpreg_t unw_fpreg_t; + +typedef struct unw_addr_space *unw_addr_space_t; + +/* Each target may define it's own set of flags, but bits 0-15 are + reserved for general libunwind-use. */ +#define UNW_PI_FLAG_FIRST_TDEP_BIT 16 +/* The information comes from a .debug_frame section. */ +#define UNW_PI_FLAG_DEBUG_FRAME 32 + +typedef struct unw_proc_info + { + unw_word_t start_ip; /* first IP covered by this procedure */ + unw_word_t end_ip; /* first IP NOT covered by this procedure */ +#if defined(NEED_LAST_IP) + unw_word_t last_ip; /* first IP that could begin another procedure */ +#endif + unw_word_t lsda; /* address of lang.-spec. data area (if any) */ + unw_word_t handler; /* optional personality routine */ + unw_word_t gp; /* global-pointer value for this procedure */ + unw_word_t flags; /* misc. flags */ + + int format; /* unwind-info format (arch-specific) */ + int unwind_info_size; /* size of the information (if applicable) */ + void *unwind_info; /* unwind-info (arch-specific) */ + unw_tdep_proc_info_t extra; /* target-dependent auxiliary proc-info */ + } +unw_proc_info_t; + +typedef int (*unw_reg_states_callback)(void *token, + void *reg_states_data, + size_t reg_states_data_size, + unw_word_t start_ip, unw_word_t end_ip); + +/* These are backend callback routines that provide access to the + state of a "remote" process. This can be used, for example, to + unwind another process through the ptrace() interface. */ +typedef struct unw_accessors + { + /* Look up the unwind info associated with instruction-pointer IP. + On success, the routine fills in the PROC_INFO structure. */ + int (*find_proc_info) (unw_addr_space_t, unw_word_t, unw_proc_info_t *, + int, void *); + + /* Release any resources (e.g., memory) that were allocated for + the unwind info returned in by a previous call to + find_proc_info() with NEED_UNWIND_INFO set to 1. */ + void (*put_unwind_info) (unw_addr_space_t, unw_proc_info_t *, void *); + + /* Return the list-head of the dynamically registered unwind + info. */ + int (*get_dyn_info_list_addr) (unw_addr_space_t, unw_word_t *, void *); + + /* Access aligned word at address ADDR. The value is returned + according to the endianness of the host (e.g., if the host is + little-endian and the target is big-endian, access_mem() needs + to byte-swap the value before returning it). */ + int (*access_mem) (unw_addr_space_t, unw_word_t, unw_word_t *, int, + void *); + + /* Access register number REG at address ADDR. */ + int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, int, + void *); + + /* Access register number REG at address ADDR. */ + int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, + unw_fpreg_t *, int, void *); + + int (*resume) (unw_addr_space_t, unw_cursor_t *, void *); + + /* Optional call back to obtain the name of a (static) procedure. + Dynamically generated procedures are handled automatically by + libunwind. This callback is optional and may be set to + NULL. */ + int (*get_proc_name) (unw_addr_space_t, unw_word_t, char *, size_t, + unw_word_t *, void *); + } +unw_accessors_t; + +typedef enum unw_save_loc_type + { + UNW_SLT_NONE, /* register is not saved ("not an l-value") */ + UNW_SLT_MEMORY, /* register has been saved in memory */ + UNW_SLT_REG /* register has been saved in (another) register */ + } +unw_save_loc_type_t; + +typedef struct unw_save_loc + { + unw_save_loc_type_t type; + union + { + unw_word_t addr; /* valid if type==UNW_SLT_MEMORY */ + unw_regnum_t regnum; /* valid if type==UNW_SLT_REG */ + } + u; + unw_tdep_save_loc_t extra; /* target-dependent additional information */ + } +unw_save_loc_t; + +/* These routines work both for local and remote unwinding. */ + +#define unw_local_addr_space UNW_OBJ(local_addr_space) +#define unw_create_addr_space UNW_OBJ(create_addr_space) +#define unw_destroy_addr_space UNW_OBJ(destroy_addr_space) +#define unw_get_accessors UNW_ARCH_OBJ(get_accessors) +#define unw_get_accessors_int UNW_ARCH_OBJ(get_accessors_int) +#define unw_init_local UNW_OBJ(init_local) +#define unw_init_local2 UNW_OBJ(init_local2) +#define unw_init_remote UNW_OBJ(init_remote) +#define unw_step UNW_OBJ(step) +#define unw_resume UNW_OBJ(resume) +#define unw_get_proc_info UNW_OBJ(get_proc_info) +#define unw_get_proc_info_by_ip UNW_OBJ(get_proc_info_by_ip) +#define unw_reg_states_iterate UNW_OBJ(reg_states_iterate) +#define unw_apply_reg_state UNW_OBJ(apply_reg_state) +#define unw_get_reg UNW_OBJ(get_reg) +#define unw_set_reg UNW_OBJ(set_reg) +#define unw_get_fpreg UNW_OBJ(get_fpreg) +#define unw_set_fpreg UNW_OBJ(set_fpreg) +#define unw_get_save_loc UNW_OBJ(get_save_loc) +#define unw_is_signal_frame UNW_OBJ(is_signal_frame) +#define unw_handle_signal_frame UNW_OBJ(handle_signal_frame) +#define unw_get_proc_name UNW_OBJ(get_proc_name) +#define unw_set_caching_policy UNW_OBJ(set_caching_policy) +#define unw_set_cache_size UNW_OBJ(set_cache_size) +#define unw_regname UNW_ARCH_OBJ(regname) +#define unw_flush_cache UNW_ARCH_OBJ(flush_cache) +#define unw_strerror UNW_ARCH_OBJ(strerror) + +extern unw_addr_space_t unw_create_addr_space (unw_accessors_t *, int); +extern void unw_destroy_addr_space (unw_addr_space_t); +extern unw_accessors_t *unw_get_accessors (unw_addr_space_t); +extern unw_accessors_t *unw_get_accessors_int (unw_addr_space_t); +extern void unw_flush_cache (unw_addr_space_t, unw_word_t, unw_word_t); +extern int unw_set_caching_policy (unw_addr_space_t, unw_caching_policy_t); +extern int unw_set_cache_size (unw_addr_space_t, size_t, int); +extern const char *unw_regname (unw_regnum_t); + +extern int unw_init_local (unw_cursor_t *, unw_context_t *); +extern int unw_init_local2 (unw_cursor_t *, unw_context_t *, int); +extern int unw_init_remote (unw_cursor_t *, unw_addr_space_t, void *); +extern int unw_step (unw_cursor_t *); +extern int unw_resume (unw_cursor_t *); +extern int unw_get_proc_info (unw_cursor_t *, unw_proc_info_t *); +extern int unw_get_proc_info_by_ip (unw_addr_space_t, unw_word_t, + unw_proc_info_t *, void *); +extern int unw_reg_states_iterate (unw_cursor_t *, unw_reg_states_callback, void *); +extern int unw_apply_reg_state (unw_cursor_t *, void *); +extern int unw_get_reg (unw_cursor_t *, int, unw_word_t *); +extern int unw_set_reg (unw_cursor_t *, int, unw_word_t); +extern int unw_get_fpreg (unw_cursor_t *, int, unw_fpreg_t *); +extern int unw_set_fpreg (unw_cursor_t *, int, unw_fpreg_t); +extern int unw_get_save_loc (unw_cursor_t *, int, unw_save_loc_t *); +extern int unw_is_signal_frame (unw_cursor_t *); +extern int unw_handle_signal_frame (unw_cursor_t *); +extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *); +extern const char *unw_strerror (int); +extern int unw_backtrace (void **, int); + +extern unw_addr_space_t unw_local_addr_space; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-coredump.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-coredump.h new file mode 100644 index 0000000..3c78141 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-coredump.h @@ -0,0 +1,73 @@ +/* libunwind - a platform-independent unwind library + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef libunwind_coredump_h +#define libunwind_coredump_h + +#include + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +/* Helper routines which make it easy to use libunwind on a coredump. + They're available only if UNW_REMOTE_ONLY is _not_ defined and they + aren't really part of the libunwind API. They are implemented in a + archive library called libunwind-coredump.a. */ + +struct UCD_info; + +extern struct UCD_info *_UCD_create(const char *filename); +extern void _UCD_destroy(struct UCD_info *); + +extern int _UCD_get_num_threads(struct UCD_info *); +extern void _UCD_select_thread(struct UCD_info *, int); +extern pid_t _UCD_get_pid(struct UCD_info *); +extern int _UCD_get_cursig(struct UCD_info *); +extern int _UCD_add_backing_file_at_segment(struct UCD_info *, int phdr_no, const char *filename); +extern int _UCD_add_backing_file_at_vaddr(struct UCD_info *, + unsigned long vaddr, + const char *filename); + +extern int _UCD_find_proc_info (unw_addr_space_t, unw_word_t, + unw_proc_info_t *, int, void *); +extern void _UCD_put_unwind_info (unw_addr_space_t, unw_proc_info_t *, void *); +extern int _UCD_get_dyn_info_list_addr (unw_addr_space_t, unw_word_t *, + void *); +extern int _UCD_access_mem (unw_addr_space_t, unw_word_t, unw_word_t *, int, + void *); +extern int _UCD_access_reg (unw_addr_space_t, unw_regnum_t, unw_word_t *, + int, void *); +extern int _UCD_access_fpreg (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *, + int, void *); +extern int _UCD_get_proc_name (unw_addr_space_t, unw_word_t, char *, size_t, + unw_word_t *, void *); +extern int _UCD_resume (unw_addr_space_t, unw_cursor_t *, void *); +extern unw_accessors_t _UCD_accessors; + + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* libunwind_coredump_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-dynamic.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-dynamic.h new file mode 100644 index 0000000..edb0bbd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-dynamic.h @@ -0,0 +1,214 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* This file defines the runtime-support routines for dynamically +generated code. Even though it is implemented as part of libunwind, +it is logically separate from the interface to perform the actual +unwinding. In particular, this interface is always used in the +context of the unwind target, whereas the rest of the unwind API is +used in context of the process that is doing the unwind (which may be +a debugger running on another machine, for example). + +Note that the data-structures declared here server a dual purpose: +when a program registers a dynamically generated procedure, it uses +these structures directly. On the other hand, with remote-unwinding, +the data-structures are read from the remote process's memory and +translated into internalized versions. To facilitate remote-access, +the following rules should be followed in declaring these structures: + + (1) Declare a member as a pointer only if the the information the + member points to needs to be internalized as well (e.g., a + string representing a procedure name should be declared as + "const char *", but the instruction pointer should be declared + as unw_word_t). + + (2) Provide sufficient padding to ensure that no implicit padding + will be needed on any of the supported target architectures. For + the time being, padding data structures with the assumption that + sizeof (unw_word_t) == 8 should be sufficient. (Note: it's not + impossible to internalize structures with internal padding, but + it does make the process a bit harder). + + (3) Don't declare members that contain bitfields or floating-point + values. + + (4) Don't declare members with enumeration types. Declare them as + int32_t instead. */ + +typedef enum + { + UNW_DYN_STOP = 0, /* end-of-unwind-info marker */ + UNW_DYN_SAVE_REG, /* save register to another register */ + UNW_DYN_SPILL_FP_REL, /* frame-pointer-relative register spill */ + UNW_DYN_SPILL_SP_REL, /* stack-pointer-relative register spill */ + UNW_DYN_ADD, /* add constant value to a register */ + UNW_DYN_POP_FRAMES, /* drop one or more stack frames */ + UNW_DYN_LABEL_STATE, /* name the current state */ + UNW_DYN_COPY_STATE, /* set the region's entry-state */ + UNW_DYN_ALIAS /* get unwind info from an alias */ + } +unw_dyn_operation_t; + +typedef enum + { + UNW_INFO_FORMAT_DYNAMIC, /* unw_dyn_proc_info_t */ + UNW_INFO_FORMAT_TABLE, /* unw_dyn_table_t */ + UNW_INFO_FORMAT_REMOTE_TABLE, /* unw_dyn_remote_table_t */ + UNW_INFO_FORMAT_ARM_EXIDX, /* ARM specific unwind info */ + UNW_INFO_FORMAT_IP_OFFSET, /* Like UNW_INFO_FORMAT_REMOTE_TABLE, but + table entries are considered + relative to di->start_ip, rather + than di->segbase */ + } +unw_dyn_info_format_t; + +typedef struct unw_dyn_op + { + int8_t tag; /* what operation? */ + int8_t qp; /* qualifying predicate register */ + int16_t reg; /* what register */ + int32_t when; /* when does it take effect? */ + unw_word_t val; /* auxiliary value */ + } +unw_dyn_op_t; + +typedef struct unw_dyn_region_info + { + struct unw_dyn_region_info *next; /* linked list of regions */ + int32_t insn_count; /* region length (# of instructions) */ + uint32_t op_count; /* length of op-array */ + unw_dyn_op_t op[1]; /* variable-length op-array */ + } +unw_dyn_region_info_t; + +typedef struct unw_dyn_proc_info + { + unw_word_t name_ptr; /* address of human-readable procedure name */ + unw_word_t handler; /* address of personality routine */ + uint32_t flags; + int32_t pad0; + unw_dyn_region_info_t *regions; + } +unw_dyn_proc_info_t; + +typedef struct unw_dyn_table_info + { + unw_word_t name_ptr; /* addr. of table name (e.g., library name) */ + unw_word_t segbase; /* segment base */ + unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */ + unw_word_t *table_data; + } +unw_dyn_table_info_t; + +typedef struct unw_dyn_remote_table_info + { + unw_word_t name_ptr; /* addr. of table name (e.g., library name) */ + unw_word_t segbase; /* segment base */ + unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */ + unw_word_t table_data; + } +unw_dyn_remote_table_info_t; + +typedef struct unw_dyn_info + { + /* doubly-linked list of dyn-info structures: */ + struct unw_dyn_info *next; + struct unw_dyn_info *prev; + unw_word_t start_ip; /* first IP covered by this entry */ + unw_word_t end_ip; /* first IP NOT covered by this entry */ + unw_word_t gp; /* global-pointer in effect for this entry */ + int32_t format; /* real type: unw_dyn_info_format_t */ + int32_t pad; + union + { + unw_dyn_proc_info_t pi; + unw_dyn_table_info_t ti; + unw_dyn_remote_table_info_t rti; + } + u; + } +unw_dyn_info_t; + +typedef struct unw_dyn_info_list + { + uint32_t version; + uint32_t generation; + unw_dyn_info_t *first; + } +unw_dyn_info_list_t; + +/* Return the size (in bytes) of an unw_dyn_region_info_t structure that can + hold OP_COUNT ops. */ +#define _U_dyn_region_info_size(op_count) \ + ((char *) (((unw_dyn_region_info_t *) NULL)->op + (op_count)) \ + - (char *) NULL) + +/* Register the unwind info for a single procedure. + This routine is NOT signal-safe. */ +extern void _U_dyn_register (unw_dyn_info_t *); + +/* Cancel the unwind info for a single procedure. + This routine is NOT signal-safe. */ +extern void _U_dyn_cancel (unw_dyn_info_t *); + + +/* Convenience routines. */ + +#define _U_dyn_op(_tag, _qp, _when, _reg, _val) \ + ((unw_dyn_op_t) { (_tag), (_qp), (_reg), (_when), (_val) }) + +#define _U_dyn_op_save_reg(op, qp, when, reg, dst) \ + (*(op) = _U_dyn_op (UNW_DYN_SAVE_REG, (qp), (when), (reg), (dst))) + +#define _U_dyn_op_spill_fp_rel(op, qp, when, reg, offset) \ + (*(op) = _U_dyn_op (UNW_DYN_SPILL_FP_REL, (qp), (when), (reg), \ + (offset))) + +#define _U_dyn_op_spill_sp_rel(op, qp, when, reg, offset) \ + (*(op) = _U_dyn_op (UNW_DYN_SPILL_SP_REL, (qp), (when), (reg), \ + (offset))) + +#define _U_dyn_op_add(op, qp, when, reg, value) \ + (*(op) = _U_dyn_op (UNW_DYN_ADD, (qp), (when), (reg), (value))) + +#define _U_dyn_op_pop_frames(op, qp, when, num_frames) \ + (*(op) = _U_dyn_op (UNW_DYN_POP_FRAMES, (qp), (when), 0, (num_frames))) + +#define _U_dyn_op_label_state(op, label) \ + (*(op) = _U_dyn_op (UNW_DYN_LABEL_STATE, _U_QP_TRUE, -1, 0, (label))) + +#define _U_dyn_op_copy_state(op, label) \ + (*(op) = _U_dyn_op (UNW_DYN_COPY_STATE, _U_QP_TRUE, -1, 0, (label))) + +#define _U_dyn_op_alias(op, qp, when, addr) \ + (*(op) = _U_dyn_op (UNW_DYN_ALIAS, (qp), (when), 0, (addr))) + +#define _U_dyn_op_stop(op) \ + (*(op) = _U_dyn_op (UNW_DYN_STOP, _U_QP_TRUE, -1, 0, 0)) + +/* The target-dependent qualifying predicate which is always TRUE. On + IA-64, that's p0 (0), on non-predicated architectures, the value is + ignored. */ +#define _U_QP_TRUE _U_TDEP_QP_TRUE diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-hppa.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-hppa.h new file mode 100644 index 0000000..7013aa7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-hppa.h @@ -0,0 +1,125 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef LIBUNWIND_H +#define LIBUNWIND_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include +#include + +#define UNW_TARGET hppa +#define UNW_TARGET_HPPA 1 + +#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ + +/* This needs to be big enough to accommodate "struct cursor", while + leaving some slack for future expansion. Changing this value will + require recompiling all users of this library. Stack allocation is + relatively cheap and unwind-state copying is relatively rare, so we + want to err on making it rather too big than too small. */ +#define UNW_TDEP_CURSOR_LEN 511 + +typedef uint32_t unw_word_t; +typedef int32_t unw_sword_t; + +typedef union + { + struct { unw_word_t bits[2]; } raw; + double val; + } +unw_tdep_fpreg_t; + +typedef enum + { + /* Note: general registers are expected to start with index 0. + This convention facilitates architecture-independent + implementation of the C++ exception handling ABI. See + _Unwind_SetGR() and _Unwind_GetGR() for details. */ + UNW_HPPA_GR = 0, + UNW_HPPA_RP = 2, /* return pointer */ + UNW_HPPA_FP = 3, /* frame pointer */ + UNW_HPPA_SP = UNW_HPPA_GR + 30, + + UNW_HPPA_FR = UNW_HPPA_GR + 32, + + UNW_HPPA_IP = UNW_HPPA_FR + 32, /* instruction pointer */ + + /* other "preserved" registers (fpsr etc.)... */ + + /* PA-RISC has 4 exception-argument registers but they're not + contiguous. To deal with this, we define 4 pseudo + exception-handling registers which we then alias to the actual + physical register. */ + + UNW_HPPA_EH0 = UNW_HPPA_IP + 1, /* alias for UNW_HPPA_GR + 20 */ + UNW_HPPA_EH1 = UNW_HPPA_EH0 + 1, /* alias for UNW_HPPA_GR + 21 */ + UNW_HPPA_EH2 = UNW_HPPA_EH1 + 1, /* alias for UNW_HPPA_GR + 22 */ + UNW_HPPA_EH3 = UNW_HPPA_EH2 + 1, /* alias for UNW_HPPA_GR + 31 */ + + /* frame info (read-only) */ + UNW_HPPA_CFA, + + UNW_TDEP_LAST_REG = UNW_HPPA_IP, + + UNW_TDEP_IP = UNW_HPPA_IP, + UNW_TDEP_SP = UNW_HPPA_SP, + UNW_TDEP_EH = UNW_HPPA_EH0 + } +hppa_regnum_t; + +#define UNW_TDEP_NUM_EH_REGS 4 + +typedef struct unw_tdep_save_loc + { + /* Additional target-dependent info on a save location. */ + } +unw_tdep_save_loc_t; + +/* On PA-RISC, we can directly use ucontext_t as the unwind context. */ +typedef ucontext_t unw_tdep_context_t; + +#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_HPPA_FR) < 32) + +#include "libunwind-dynamic.h" + +typedef struct + { + /* no PA-RISC-specific auxiliary proc-info */ + } +unw_tdep_proc_info_t; + +#include "libunwind-common.h" + +#define unw_tdep_getcontext UNW_ARCH_OBJ (getcontext) +extern int unw_tdep_getcontext (unw_tdep_context_t *); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* LIBUNWIND_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ia64.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ia64.h new file mode 100644 index 0000000..0cc4f39 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ia64.h @@ -0,0 +1,194 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef LIBUNWIND_H +#define LIBUNWIND_H + +#include +#include + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#ifdef ia64 + /* This works around a bug in Intel's ECC v7.0 which defines "ia64" + as "1". */ +# undef ia64 +#endif + +#ifdef __hpux + /* On HP-UX, there is no hope of supporting UNW_LOCAL_ONLY, because + it's impossible to obtain the address of the members in the + sigcontext structure. */ +# undef UNW_LOCAL_ONLY +# define UNW_GENERIC_ONLY +#endif + +#define UNW_TARGET ia64 +#define UNW_TARGET_IA64 1 + +#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ + +/* This needs to be big enough to accommodate "struct cursor", while + leaving some slack for future expansion. Changing this value will + require recompiling all users of this library. Stack allocation is + relatively cheap and unwind-state copying is relatively rare, so we + want to err on making it rather too big than too small. */ +#define UNW_TDEP_CURSOR_LEN 511 + +/* If this bit is it indicates that the procedure saved all of ar.bsp, + ar.bspstore, and ar.rnat. If, additionally, ar.bsp != saved ar.bsp, + then this procedure has performed a register-backing-store switch. */ +#define UNW_PI_FLAG_IA64_RBS_SWITCH_BIT (UNW_PI_FLAG_FIRST_TDEP_BIT + 0) + +#define UNW_PI_FLAG_IA64_RBS_SWITCH (1 << UNW_PI_FLAG_IA64_RBS_SWITCH_BIT) + +typedef uint64_t unw_word_t; +typedef int64_t unw_sword_t; + +/* On IA-64, we want to access the contents of floating-point + registers as a pair of "words", but to ensure 16-byte alignment, we + make it a union that contains a "long double". This will do the + Right Thing on all known IA-64 platforms, including HP-UX. */ +typedef union + { + struct { unw_word_t bits[2]; } raw; + long double dummy; /* dummy to force 16-byte alignment */ + } +unw_tdep_fpreg_t; + +typedef struct + { + /* no ia64-specific auxiliary proc-info */ + } +unw_tdep_proc_info_t; + +typedef enum + { + /* Note: general registers are excepted to start with index 0. + This convention facilitates architecture-independent + implementation of the C++ exception handling ABI. See + _Unwind_SetGR() and _Unwind_GetGR() for details. */ + UNW_IA64_GR = 0, /* general registers (r0..r127) */ + UNW_IA64_GP = UNW_IA64_GR + 1, + UNW_IA64_TP = UNW_IA64_GR + 13, + + UNW_IA64_NAT = UNW_IA64_GR + 128, /* NaT registers (nat0..nat127) */ + + UNW_IA64_FR = UNW_IA64_NAT + 128, /* fp registers (f0..f127) */ + + UNW_IA64_AR = UNW_IA64_FR + 128, /* application registers (ar0..r127) */ + UNW_IA64_AR_RSC = UNW_IA64_AR + 16, + UNW_IA64_AR_BSP = UNW_IA64_AR + 17, + UNW_IA64_AR_BSPSTORE = UNW_IA64_AR + 18, + UNW_IA64_AR_RNAT = UNW_IA64_AR + 19, + UNW_IA64_AR_CSD = UNW_IA64_AR + 25, + UNW_IA64_AR_26 = UNW_IA64_AR + 26, + UNW_IA64_AR_SSD = UNW_IA64_AR_26, + UNW_IA64_AR_CCV = UNW_IA64_AR + 32, + UNW_IA64_AR_UNAT = UNW_IA64_AR + 36, + UNW_IA64_AR_FPSR = UNW_IA64_AR + 40, + UNW_IA64_AR_PFS = UNW_IA64_AR + 64, + UNW_IA64_AR_LC = UNW_IA64_AR + 65, + UNW_IA64_AR_EC = UNW_IA64_AR + 66, + + UNW_IA64_BR = UNW_IA64_AR + 128, /* branch registers (b0..p7) */ + UNW_IA64_RP = UNW_IA64_BR + 0, /* return pointer (rp) */ + UNW_IA64_PR = UNW_IA64_BR + 8, /* predicate registers (p0..p63) */ + UNW_IA64_CFM, + + /* frame info: */ + UNW_IA64_BSP, + UNW_IA64_IP, + UNW_IA64_SP, + + UNW_TDEP_LAST_REG = UNW_IA64_SP, + + UNW_TDEP_IP = UNW_IA64_IP, + UNW_TDEP_SP = UNW_IA64_SP, + UNW_TDEP_EH = UNW_IA64_GR + 15 + } +ia64_regnum_t; + +#define UNW_TDEP_NUM_EH_REGS 4 /* r15-r18 are exception args */ + +typedef struct unw_tdep_save_loc + { + /* Additional target-dependent info on a save location. On IA-64, + we use this to provide the bit number in which a NaT bit gets + saved. */ + uint8_t nat_bitnr; + + /* Padding reserved for future use. */ + uint8_t reserved[7]; + } +unw_tdep_save_loc_t; + +/* On IA-64, we can directly use ucontext_t as the unwind context. */ +typedef ucontext_t unw_tdep_context_t; + +#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_IA64_FR) < 128) + +#include "libunwind-dynamic.h" +#include "libunwind-common.h" + +#ifdef __hpux + /* In theory, we could use _Uia64_getcontext() on HP-UX as well, but + the benefit of doing so would be marginal given that it can't + support UNW_LOCAL_ONLY. */ +# define unw_tdep_getcontext getcontext +#else +# define unw_tdep_getcontext UNW_ARCH_OBJ (getcontext) + extern int unw_tdep_getcontext (unw_tdep_context_t *); +#endif + +/* This is a helper routine to search an ia64 unwind table. If the + address-space argument AS points to something other than the local + address-space, the memory for the unwind-info will be allocated + with malloc(), and should be free()d during the put_unwind_info() + callback. This routine is signal-safe for the local-address-space + case ONLY. */ +#define unw_search_ia64_unwind_table UNW_OBJ(search_unwind_table) +extern int unw_search_ia64_unwind_table (unw_addr_space_t, unw_word_t, + unw_dyn_info_t *, unw_proc_info_t *, + int, void *); + +/* This is a helper routine which the get_dyn_info_list_addr() + callback can use to locate the special dynamic-info list entry in + an IA-64 unwind table. If the entry exists in the table, the + list-address is returned. In all other cases, 0 is returned. */ +extern unw_word_t _Uia64_find_dyn_list (unw_addr_space_t, unw_dyn_info_t *, + void *); + +/* This is a helper routine to obtain the kernel-unwind info. It is + signal-safe. */ +extern int _Uia64_get_kernel_table (unw_dyn_info_t *); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* LIBUNWIND_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-mips.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-mips.h new file mode 100644 index 0000000..97c95e2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-mips.h @@ -0,0 +1,160 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef LIBUNWIND_H +#define LIBUNWIND_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include +#include + +#ifdef mips +# undef mips +#endif + +#define UNW_TARGET mips +#define UNW_TARGET_MIPS 1 + +#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ + +/* This needs to be big enough to accommodate "struct cursor", while + leaving some slack for future expansion. Changing this value will + require recompiling all users of this library. Stack allocation is + relatively cheap and unwind-state copying is relatively rare, so we + want to err on making it rather too big than too small. */ + +/* FIXME for MIPS. Too big? What do other things use for similar tasks? */ +#define UNW_TDEP_CURSOR_LEN 4096 + +/* The size of a "word" varies on MIPS. This type is used for memory + addresses and register values, which are 32-bit wide for O32 and N32 + ABIs, and 64-bit wide for N64 ABI. */ +#if _MIPS_SIM == _ABI64 +typedef uint64_t unw_word_t; +#else +typedef uint32_t unw_word_t; +#endif +typedef int32_t unw_sword_t; + +/* FIXME: MIPS ABIs. */ +typedef long double unw_tdep_fpreg_t; + +typedef enum + { + UNW_MIPS_R0, + UNW_MIPS_R1, + UNW_MIPS_R2, + UNW_MIPS_R3, + UNW_MIPS_R4, + UNW_MIPS_R5, + UNW_MIPS_R6, + UNW_MIPS_R7, + UNW_MIPS_R8, + UNW_MIPS_R9, + UNW_MIPS_R10, + UNW_MIPS_R11, + UNW_MIPS_R12, + UNW_MIPS_R13, + UNW_MIPS_R14, + UNW_MIPS_R15, + UNW_MIPS_R16, + UNW_MIPS_R17, + UNW_MIPS_R18, + UNW_MIPS_R19, + UNW_MIPS_R20, + UNW_MIPS_R21, + UNW_MIPS_R22, + UNW_MIPS_R23, + UNW_MIPS_R24, + UNW_MIPS_R25, + UNW_MIPS_R26, + UNW_MIPS_R27, + UNW_MIPS_R28, + UNW_MIPS_R29, + UNW_MIPS_R30, + UNW_MIPS_R31, + + UNW_MIPS_PC = 34, + + /* FIXME: Other registers! */ + + /* For MIPS, the CFA is the value of SP (r29) at the call site in the + previous frame. */ + UNW_MIPS_CFA, + + UNW_TDEP_LAST_REG = UNW_MIPS_PC, + + UNW_TDEP_IP = UNW_MIPS_R31, + UNW_TDEP_SP = UNW_MIPS_R29, + UNW_TDEP_EH = UNW_MIPS_R0 /* FIXME. */ + } +mips_regnum_t; + +typedef enum + { + UNW_MIPS_ABI_O32, + UNW_MIPS_ABI_N32, + UNW_MIPS_ABI_N64 + } +mips_abi_t; + +#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for MIPS. */ + +typedef struct unw_tdep_save_loc + { + /* Additional target-dependent info on a save location. */ + } +unw_tdep_save_loc_t; + +/* On x86, we can directly use ucontext_t as the unwind context. FIXME for + MIPS. */ +typedef ucontext_t unw_tdep_context_t; + +#include "libunwind-dynamic.h" + +typedef struct + { + /* no mips-specific auxiliary proc-info */ + } +unw_tdep_proc_info_t; + +#include "libunwind-common.h" + +/* There is no getcontext() on MIPS. Use a stub version which only saves GP + registers. FIXME: Not ideal, may not be sufficient for all libunwind + use cases. */ +#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext) +extern int unw_tdep_getcontext (ucontext_t *uc); + +#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) +extern int unw_tdep_is_fpreg (int); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* LIBUNWIND_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ppc32.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ppc32.h new file mode 100644 index 0000000..47ebfde --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ppc32.h @@ -0,0 +1,207 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + + Copied from libunwind-x86_64.h, modified slightly for building + frysk successfully on ppc64, by Wu Zhou + Will be replaced when libunwind is ready on ppc64 platform. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef LIBUNWIND_H +#define LIBUNWIND_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include +#include + +#define UNW_TARGET ppc32 +#define UNW_TARGET_PPC32 1 + +#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ + +/* + * This needs to be big enough to accommodate "struct cursor", while + * leaving some slack for future expansion. Changing this value will + * require recompiling all users of this library. Stack allocation is + * relatively cheap and unwind-state copying is relatively rare, so we want + * to err on making it rather too big than too small. + * + * To simplify this whole process, we are at least initially taking the + * tack that UNW_PPC32_* map straight across to the .eh_frame column register + * numbers. These register numbers come from gcc's source in + * gcc/config/rs6000/rs6000.h + * + * UNW_TDEP_CURSOR_LEN is in terms of unw_word_t size. Since we have 115 + * elements in the loc array, each sized 2 * unw_word_t, plus the rest of + * the cursor struct, this puts us at about 2 * 115 + 40 = 270. Let's + * round that up to 280. + */ + +#define UNW_TDEP_CURSOR_LEN 280 + +#if __WORDSIZE==32 +typedef uint32_t unw_word_t; +typedef int32_t unw_sword_t; +#else +typedef uint64_t unw_word_t; +typedef int64_t unw_sword_t; +#endif + +typedef long double unw_tdep_fpreg_t; + +typedef enum + { + UNW_PPC32_R0, + UNW_PPC32_R1, /* called STACK_POINTER in gcc */ + UNW_PPC32_R2, + UNW_PPC32_R3, + UNW_PPC32_R4, + UNW_PPC32_R5, + UNW_PPC32_R6, + UNW_PPC32_R7, + UNW_PPC32_R8, + UNW_PPC32_R9, + UNW_PPC32_R10, + UNW_PPC32_R11, /* called STATIC_CHAIN in gcc */ + UNW_PPC32_R12, + UNW_PPC32_R13, + UNW_PPC32_R14, + UNW_PPC32_R15, + UNW_PPC32_R16, + UNW_PPC32_R17, + UNW_PPC32_R18, + UNW_PPC32_R19, + UNW_PPC32_R20, + UNW_PPC32_R21, + UNW_PPC32_R22, + UNW_PPC32_R23, + UNW_PPC32_R24, + UNW_PPC32_R25, + UNW_PPC32_R26, + UNW_PPC32_R27, + UNW_PPC32_R28, + UNW_PPC32_R29, + UNW_PPC32_R30, + UNW_PPC32_R31, /* called HARD_FRAME_POINTER in gcc */ + + /* Count Register */ + UNW_PPC32_CTR = 32, + /* Fixed-Point Status and Control Register */ + UNW_PPC32_XER = 33, + /* Condition Register */ + UNW_PPC32_CCR = 34, + /* Machine State Register */ + //UNW_PPC32_MSR = 35, + /* MQ or SPR0, not part of generic Power, part of MPC601 */ + //UNW_PPC32_MQ = 36, + /* Link Register */ + UNW_PPC32_LR = 36, + /* Floating Pointer Status and Control Register */ + UNW_PPC32_FPSCR = 37, + + UNW_PPC32_F0 = 48, + UNW_PPC32_F1, + UNW_PPC32_F2, + UNW_PPC32_F3, + UNW_PPC32_F4, + UNW_PPC32_F5, + UNW_PPC32_F6, + UNW_PPC32_F7, + UNW_PPC32_F8, + UNW_PPC32_F9, + UNW_PPC32_F10, + UNW_PPC32_F11, + UNW_PPC32_F12, + UNW_PPC32_F13, + UNW_PPC32_F14, + UNW_PPC32_F15, + UNW_PPC32_F16, + UNW_PPC32_F17, + UNW_PPC32_F18, + UNW_PPC32_F19, + UNW_PPC32_F20, + UNW_PPC32_F21, + UNW_PPC32_F22, + UNW_PPC32_F23, + UNW_PPC32_F24, + UNW_PPC32_F25, + UNW_PPC32_F26, + UNW_PPC32_F27, + UNW_PPC32_F28, + UNW_PPC32_F29, + UNW_PPC32_F30, + UNW_PPC32_F31, + + UNW_TDEP_LAST_REG = UNW_PPC32_F31, + + UNW_TDEP_IP = UNW_PPC32_LR, + UNW_TDEP_SP = UNW_PPC32_R1, + UNW_TDEP_EH = UNW_PPC32_R12 + } +ppc32_regnum_t; + +/* + * According to David Edelsohn, GNU gcc uses R3, R4, R5, and maybe R6 for + * passing parameters to exception handlers. + */ + +#define UNW_TDEP_NUM_EH_REGS 4 + +typedef struct unw_tdep_save_loc + { + /* Additional target-dependent info on a save location. */ + } +unw_tdep_save_loc_t; + +/* On ppc, we can directly use ucontext_t as the unwind context. */ +typedef ucontext_t unw_tdep_context_t; + +/* XXX this is not ideal: an application should not be prevented from + using the "getcontext" name just because it's using libunwind. We + can't just use __getcontext() either, because that isn't exported + by glibc... */ +#define unw_tdep_getcontext(uc) (getcontext (uc), 0) + +#include "libunwind-dynamic.h" + +typedef struct + { + /* no ppc32-specific auxiliary proc-info */ + } +unw_tdep_proc_info_t; + +#include "libunwind-common.h" + +#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) +extern int unw_tdep_is_fpreg (int); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* LIBUNWIND_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ppc64.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ppc64.h new file mode 100644 index 0000000..9944628 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ppc64.h @@ -0,0 +1,271 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + + Copied from libunwind-x86_64.h, modified slightly for building + frysk successfully on ppc64, by Wu Zhou + Will be replaced when libunwind is ready on ppc64 platform. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef LIBUNWIND_H +#define LIBUNWIND_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include +#include + +#define UNW_TARGET ppc64 +#define UNW_TARGET_PPC64 1 + +#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ + +/* + * This needs to be big enough to accommodate "struct cursor", while + * leaving some slack for future expansion. Changing this value will + * require recompiling all users of this library. Stack allocation is + * relatively cheap and unwind-state copying is relatively rare, so we want + * to err on making it rather too big than too small. + * + * To simplify this whole process, we are at least initially taking the + * tack that UNW_PPC64_* map straight across to the .eh_frame column register + * numbers. These register numbers come from gcc's source in + * gcc/config/rs6000/rs6000.h + * + * UNW_TDEP_CURSOR_LEN is in terms of unw_word_t size. Since we have 115 + * elements in the loc array, each sized 2 * unw_word_t, plus the rest of + * the cursor struct, this puts us at about 2 * 115 + 40 = 270. Let's + * round that up to 280. + */ + +#define UNW_TDEP_CURSOR_LEN 280 + +#if __WORDSIZE==32 +typedef uint32_t unw_word_t; +typedef int32_t unw_sword_t; +#else +typedef uint64_t unw_word_t; +typedef int64_t unw_sword_t; +#endif + +typedef long double unw_tdep_fpreg_t; + +/* + * Vector register (in PowerPC64 used for AltiVec registers) + */ +typedef struct { + uint64_t halves[2]; +} unw_tdep_vreg_t; + +typedef enum + { + UNW_PPC64_R0, + UNW_PPC64_R1, /* called STACK_POINTER in gcc */ + UNW_PPC64_R2, + UNW_PPC64_R3, + UNW_PPC64_R4, + UNW_PPC64_R5, + UNW_PPC64_R6, + UNW_PPC64_R7, + UNW_PPC64_R8, + UNW_PPC64_R9, + UNW_PPC64_R10, + UNW_PPC64_R11, /* called STATIC_CHAIN in gcc */ + UNW_PPC64_R12, + UNW_PPC64_R13, + UNW_PPC64_R14, + UNW_PPC64_R15, + UNW_PPC64_R16, + UNW_PPC64_R17, + UNW_PPC64_R18, + UNW_PPC64_R19, + UNW_PPC64_R20, + UNW_PPC64_R21, + UNW_PPC64_R22, + UNW_PPC64_R23, + UNW_PPC64_R24, + UNW_PPC64_R25, + UNW_PPC64_R26, + UNW_PPC64_R27, + UNW_PPC64_R28, + UNW_PPC64_R29, + UNW_PPC64_R30, + UNW_PPC64_R31, /* called HARD_FRAME_POINTER in gcc */ + + UNW_PPC64_F0 = 32, + UNW_PPC64_F1, + UNW_PPC64_F2, + UNW_PPC64_F3, + UNW_PPC64_F4, + UNW_PPC64_F5, + UNW_PPC64_F6, + UNW_PPC64_F7, + UNW_PPC64_F8, + UNW_PPC64_F9, + UNW_PPC64_F10, + UNW_PPC64_F11, + UNW_PPC64_F12, + UNW_PPC64_F13, + UNW_PPC64_F14, + UNW_PPC64_F15, + UNW_PPC64_F16, + UNW_PPC64_F17, + UNW_PPC64_F18, + UNW_PPC64_F19, + UNW_PPC64_F20, + UNW_PPC64_F21, + UNW_PPC64_F22, + UNW_PPC64_F23, + UNW_PPC64_F24, + UNW_PPC64_F25, + UNW_PPC64_F26, + UNW_PPC64_F27, + UNW_PPC64_F28, + UNW_PPC64_F29, + UNW_PPC64_F30, + UNW_PPC64_F31, + /* Note that there doesn't appear to be an .eh_frame register column + for the FPSCR register. I don't know why this is. Since .eh_frame + info is what this implementation uses for unwinding, we have no way + to unwind this register, and so we will not expose an FPSCR register + number in the libunwind API. + */ + + UNW_PPC64_LR = 65, + UNW_PPC64_CTR = 66, + UNW_PPC64_ARG_POINTER = 67, + + UNW_PPC64_CR0 = 68, + UNW_PPC64_CR1, + UNW_PPC64_CR2, + UNW_PPC64_CR3, + UNW_PPC64_CR4, + /* CR5 .. CR7 are currently unused */ + UNW_PPC64_CR5, + UNW_PPC64_CR6, + UNW_PPC64_CR7, + + UNW_PPC64_XER = 76, + + UNW_PPC64_V0 = 77, + UNW_PPC64_V1, + UNW_PPC64_V2, + UNW_PPC64_V3, + UNW_PPC64_V4, + UNW_PPC64_V5, + UNW_PPC64_V6, + UNW_PPC64_V7, + UNW_PPC64_V8, + UNW_PPC64_V9, + UNW_PPC64_V10, + UNW_PPC64_V11, + UNW_PPC64_V12, + UNW_PPC64_V13, + UNW_PPC64_V14, + UNW_PPC64_V15, + UNW_PPC64_V16, + UNW_PPC64_V17, + UNW_PPC64_V18, + UNW_PPC64_V19, + UNW_PPC64_V20, + UNW_PPC64_V21, + UNW_PPC64_V22, + UNW_PPC64_V23, + UNW_PPC64_V24, + UNW_PPC64_V25, + UNW_PPC64_V26, + UNW_PPC64_V27, + UNW_PPC64_V28, + UNW_PPC64_V29, + UNW_PPC64_V30, + UNW_PPC64_V31, + + UNW_PPC64_VRSAVE = 109, + UNW_PPC64_VSCR = 110, + UNW_PPC64_SPE_ACC = 111, + UNW_PPC64_SPEFSCR = 112, + + /* frame info (read-only) */ + UNW_PPC64_FRAME_POINTER, + UNW_PPC64_NIP, + + + UNW_TDEP_LAST_REG = UNW_PPC64_NIP, + + UNW_TDEP_IP = UNW_PPC64_NIP, + UNW_TDEP_SP = UNW_PPC64_R1, + UNW_TDEP_EH = UNW_PPC64_R12 + } +ppc64_regnum_t; + +typedef enum + { + UNW_PPC64_ABI_ELFv1, + UNW_PPC64_ABI_ELFv2 + } +ppc64_abi_t; + +/* + * According to David Edelsohn, GNU gcc uses R3, R4, R5, and maybe R6 for + * passing parameters to exception handlers. + */ + +#define UNW_TDEP_NUM_EH_REGS 4 + +typedef struct unw_tdep_save_loc + { + /* Additional target-dependent info on a save location. */ + } +unw_tdep_save_loc_t; + +/* On ppc64, we can directly use ucontext_t as the unwind context. */ +typedef ucontext_t unw_tdep_context_t; + +/* XXX this is not ideal: an application should not be prevented from + using the "getcontext" name just because it's using libunwind. We + can't just use __getcontext() either, because that isn't exported + by glibc... */ +#define unw_tdep_getcontext(uc) (getcontext (uc), 0) + +#include "libunwind-dynamic.h" + +typedef struct + { + /* no ppc64-specific auxiliary proc-info */ + } +unw_tdep_proc_info_t; + +#include "libunwind-common.h" + +#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) +extern int unw_tdep_is_fpreg (int); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* LIBUNWIND_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ptrace.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ptrace.h new file mode 100644 index 0000000..801325c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-ptrace.h @@ -0,0 +1,63 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef libunwind_ptrace_h +#define libunwind_ptrace_h + +#include + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +/* Helper routines which make it easy to use libunwind via ptrace(). + They're available only if UNW_REMOTE_ONLY is _not_ defined and they + aren't really part of the libunwind API. They are implemented in a + archive library called libunwind-ptrace.a. */ + +extern void *_UPT_create (pid_t); +extern void _UPT_destroy (void *); +extern int _UPT_find_proc_info (unw_addr_space_t, unw_word_t, + unw_proc_info_t *, int, void *); +extern void _UPT_put_unwind_info (unw_addr_space_t, unw_proc_info_t *, void *); +extern int _UPT_get_dyn_info_list_addr (unw_addr_space_t, unw_word_t *, + void *); +extern int _UPT_access_mem (unw_addr_space_t, unw_word_t, unw_word_t *, int, + void *); +extern int _UPT_access_reg (unw_addr_space_t, unw_regnum_t, unw_word_t *, + int, void *); +extern int _UPT_access_fpreg (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *, + int, void *); +extern int _UPT_get_proc_name (unw_addr_space_t, unw_word_t, char *, size_t, + unw_word_t *, void *); +extern int _UPT_resume (unw_addr_space_t, unw_cursor_t *, void *); +extern unw_accessors_t _UPT_accessors; + + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* libunwind_ptrace_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-sh.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-sh.h new file mode 100644 index 0000000..927f61f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-sh.h @@ -0,0 +1,114 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef LIBUNWIND_H +#define LIBUNWIND_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include +#include +#include + +#define UNW_TARGET sh +#define UNW_TARGET_SH 1 + +#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ + +/* This needs to be big enough to accommodate "struct cursor", while + leaving some slack for future expansion. Changing this value will + require recompiling all users of this library. Stack allocation is + relatively cheap and unwind-state copying is relatively rare, so we + want to err on making it rather too big than too small. */ + +#define UNW_TDEP_CURSOR_LEN 4096 + +typedef uint32_t unw_word_t; +typedef int32_t unw_sword_t; + +typedef long double unw_tdep_fpreg_t; + +typedef enum + { + UNW_SH_R0, + UNW_SH_R1, + UNW_SH_R2, + UNW_SH_R3, + UNW_SH_R4, + UNW_SH_R5, + UNW_SH_R6, + UNW_SH_R7, + UNW_SH_R8, + UNW_SH_R9, + UNW_SH_R10, + UNW_SH_R11, + UNW_SH_R12, + UNW_SH_R13, + UNW_SH_R14, + UNW_SH_R15, + + UNW_SH_PC, + UNW_SH_PR, + + UNW_TDEP_LAST_REG = UNW_SH_PR, + + UNW_TDEP_IP = UNW_SH_PR, + UNW_TDEP_SP = UNW_SH_R15, + UNW_TDEP_EH = UNW_SH_R0 + } +sh_regnum_t; + +#define UNW_TDEP_NUM_EH_REGS 2 + +typedef ucontext_t unw_tdep_context_t; + +#define unw_tdep_getcontext(uc) (getcontext (uc), 0) + +typedef struct unw_tdep_save_loc + { + /* Additional target-dependent info on a save location. */ + } +unw_tdep_save_loc_t; + +#include "libunwind-dynamic.h" + +typedef struct + { + /* no sh-specific auxiliary proc-info */ + } +unw_tdep_proc_info_t; + +#include "libunwind-common.h" + +#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) +extern int unw_tdep_is_fpreg (int); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* LIBUNWIND_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-tilegx.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-tilegx.h new file mode 100644 index 0000000..0f84ea6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-tilegx.h @@ -0,0 +1,161 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef LIBUNWIND_H +#define LIBUNWIND_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include +#include + +#define UNW_TARGET tilegx +#define UNW_TARGET_TILEGX 1 + +#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ + +/* This needs to be big enough to accommodate "struct cursor", while + leaving some slack for future expansion. Changing this value will + require recompiling all users of this library. Stack allocation is + relatively cheap and unwind-state copying is relatively rare, so we + want to err on making it rather too big than too small. */ + +#define UNW_TDEP_CURSOR_LEN 4096 + +/* The size of a "word" varies on TILEGX. This type is used for memory + addresses and register values. */ +typedef uint64_t unw_word_t; +typedef int64_t unw_sword_t; + +typedef long double unw_tdep_fpreg_t; + +typedef enum +{ + UNW_TILEGX_R0, + UNW_TILEGX_R1, + UNW_TILEGX_R2, + UNW_TILEGX_R3, + UNW_TILEGX_R4, + UNW_TILEGX_R5, + UNW_TILEGX_R6, + UNW_TILEGX_R7, + UNW_TILEGX_R8, + UNW_TILEGX_R9, + UNW_TILEGX_R10, + UNW_TILEGX_R11, + UNW_TILEGX_R12, + UNW_TILEGX_R13, + UNW_TILEGX_R14, + UNW_TILEGX_R15, + UNW_TILEGX_R16, + UNW_TILEGX_R17, + UNW_TILEGX_R18, + UNW_TILEGX_R19, + UNW_TILEGX_R20, + UNW_TILEGX_R21, + UNW_TILEGX_R22, + UNW_TILEGX_R23, + UNW_TILEGX_R24, + UNW_TILEGX_R25, + UNW_TILEGX_R26, + UNW_TILEGX_R27, + UNW_TILEGX_R28, + UNW_TILEGX_R29, + UNW_TILEGX_R30, + UNW_TILEGX_R31, + UNW_TILEGX_R32, + UNW_TILEGX_R33, + UNW_TILEGX_R34, + UNW_TILEGX_R35, + UNW_TILEGX_R36, + UNW_TILEGX_R37, + UNW_TILEGX_R38, + UNW_TILEGX_R39, + UNW_TILEGX_R40, + UNW_TILEGX_R41, + UNW_TILEGX_R42, + UNW_TILEGX_R43, + UNW_TILEGX_R44, + UNW_TILEGX_R45, + UNW_TILEGX_R46, + UNW_TILEGX_R47, + UNW_TILEGX_R48, + UNW_TILEGX_R49, + UNW_TILEGX_R50, + UNW_TILEGX_R51, + UNW_TILEGX_R52, + UNW_TILEGX_R53, + UNW_TILEGX_R54, + UNW_TILEGX_R55, + + /* FIXME: Other registers! */ + + UNW_TILEGX_PC, + /* For TILEGX, the CFA is the value of SP (r54) at the call site in the + previous frame. */ + UNW_TILEGX_CFA, + + UNW_TDEP_LAST_REG = UNW_TILEGX_PC, + + UNW_TDEP_IP = UNW_TILEGX_R55, /* R55 is link register for Tilegx */ + UNW_TDEP_SP = UNW_TILEGX_R54, + UNW_TDEP_EH = UNW_TILEGX_R0 /* FIXME. */ +} tilegx_regnum_t; + +typedef enum +{ + UNW_TILEGX_ABI_N64 = 2 +} tilegx_abi_t; + +#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for TILEGX. */ + +typedef struct unw_tdep_save_loc +{ + /* Additional target-dependent info on a save location. */ +} unw_tdep_save_loc_t; + +typedef ucontext_t unw_tdep_context_t; + +#include "libunwind-dynamic.h" + +typedef struct +{ + /* no tilegx-specific auxiliary proc-info */ +} unw_tdep_proc_info_t; + +#include "libunwind-common.h" + +#define unw_tdep_getcontext getcontext + +#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) +extern int unw_tdep_is_fpreg (int); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* LIBUNWIND_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-x86.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-x86.h new file mode 100644 index 0000000..40fe046 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-x86.h @@ -0,0 +1,187 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef LIBUNWIND_H +#define LIBUNWIND_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include +#include +#include + +#define UNW_TARGET x86 +#define UNW_TARGET_X86 1 + +#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ + +/* This needs to be big enough to accommodate "struct cursor", while + leaving some slack for future expansion. Changing this value will + require recompiling all users of this library. Stack allocation is + relatively cheap and unwind-state copying is relatively rare, so we + want to err on making it rather too big than too small. */ +#define UNW_TDEP_CURSOR_LEN 127 + +typedef uint32_t unw_word_t; +typedef int32_t unw_sword_t; + +typedef union { + struct { uint8_t b[4]; } val32; + struct { uint8_t b[10]; } val80; + struct { uint8_t b[16]; } val128; +} unw_tdep_fpreg_t; + +typedef enum + { + /* Note: general registers are expected to start with index 0. + This convention facilitates architecture-independent + implementation of the C++ exception handling ABI. See + _Unwind_SetGR() and _Unwind_GetGR() for details. + + The described register usage convention is based on "System V + Application Binary Interface, Intel386 Architecture Processor + Supplement, Fourth Edition" at + + http://www.linuxbase.org/spec/refspecs/elf/abi386-4.pdf + + It would have been nice to use the same register numbering as + DWARF, but that doesn't work because the libunwind requires + that the exception argument registers be consecutive, which the + wouldn't be with the DWARF numbering. */ + UNW_X86_EAX, /* scratch (exception argument 1) */ + UNW_X86_EDX, /* scratch (exception argument 2) */ + UNW_X86_ECX, /* scratch */ + UNW_X86_EBX, /* preserved */ + UNW_X86_ESI, /* preserved */ + UNW_X86_EDI, /* preserved */ + UNW_X86_EBP, /* (optional) frame-register */ + UNW_X86_ESP, /* (optional) frame-register */ + UNW_X86_EIP, /* frame-register */ + UNW_X86_EFLAGS, /* scratch (except for "direction", which is fixed */ + UNW_X86_TRAPNO, /* scratch */ + + /* MMX/stacked-fp registers */ + UNW_X86_ST0, /* fp return value */ + UNW_X86_ST1, /* scratch */ + UNW_X86_ST2, /* scratch */ + UNW_X86_ST3, /* scratch */ + UNW_X86_ST4, /* scratch */ + UNW_X86_ST5, /* scratch */ + UNW_X86_ST6, /* scratch */ + UNW_X86_ST7, /* scratch */ + + UNW_X86_FCW, /* scratch */ + UNW_X86_FSW, /* scratch */ + UNW_X86_FTW, /* scratch */ + UNW_X86_FOP, /* scratch */ + UNW_X86_FCS, /* scratch */ + UNW_X86_FIP, /* scratch */ + UNW_X86_FEA, /* scratch */ + UNW_X86_FDS, /* scratch */ + + /* SSE registers */ + UNW_X86_XMM0_lo, /* scratch */ + UNW_X86_XMM0_hi, /* scratch */ + UNW_X86_XMM1_lo, /* scratch */ + UNW_X86_XMM1_hi, /* scratch */ + UNW_X86_XMM2_lo, /* scratch */ + UNW_X86_XMM2_hi, /* scratch */ + UNW_X86_XMM3_lo, /* scratch */ + UNW_X86_XMM3_hi, /* scratch */ + UNW_X86_XMM4_lo, /* scratch */ + UNW_X86_XMM4_hi, /* scratch */ + UNW_X86_XMM5_lo, /* scratch */ + UNW_X86_XMM5_hi, /* scratch */ + UNW_X86_XMM6_lo, /* scratch */ + UNW_X86_XMM6_hi, /* scratch */ + UNW_X86_XMM7_lo, /* scratch */ + UNW_X86_XMM7_hi, /* scratch */ + + UNW_X86_MXCSR, /* scratch */ + + /* segment registers */ + UNW_X86_GS, /* special */ + UNW_X86_FS, /* special */ + UNW_X86_ES, /* special */ + UNW_X86_DS, /* special */ + UNW_X86_SS, /* special */ + UNW_X86_CS, /* special */ + UNW_X86_TSS, /* special */ + UNW_X86_LDT, /* special */ + + /* frame info (read-only) */ + UNW_X86_CFA, + + UNW_X86_XMM0, /* scratch */ + UNW_X86_XMM1, /* scratch */ + UNW_X86_XMM2, /* scratch */ + UNW_X86_XMM3, /* scratch */ + UNW_X86_XMM4, /* scratch */ + UNW_X86_XMM5, /* scratch */ + UNW_X86_XMM6, /* scratch */ + UNW_X86_XMM7, /* scratch */ + + UNW_TDEP_LAST_REG = UNW_X86_XMM7, + + UNW_TDEP_IP = UNW_X86_EIP, + UNW_TDEP_SP = UNW_X86_ESP, + UNW_TDEP_EH = UNW_X86_EAX + } +x86_regnum_t; + +#define UNW_TDEP_NUM_EH_REGS 2 /* eax and edx are exception args */ + +typedef struct unw_tdep_save_loc + { + /* Additional target-dependent info on a save location. */ + } +unw_tdep_save_loc_t; + +/* On x86, we can directly use ucontext_t as the unwind context. */ +typedef ucontext_t unw_tdep_context_t; + +#include "libunwind-dynamic.h" + +typedef struct + { + /* no x86-specific auxiliary proc-info */ + } +unw_tdep_proc_info_t; + +#include "libunwind-common.h" + +#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext) +extern int unw_tdep_getcontext (unw_tdep_context_t *); + +#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) +extern int unw_tdep_is_fpreg (int); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* LIBUNWIND_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-x86_64.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-x86_64.h new file mode 100644 index 0000000..78eb541 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind-x86_64.h @@ -0,0 +1,141 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef LIBUNWIND_H +#define LIBUNWIND_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include +#include +#include + +#define UNW_TARGET x86_64 +#define UNW_TARGET_X86_64 1 + +#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ + +/* This needs to be big enough to accommodate "struct cursor", while + leaving some slack for future expansion. Changing this value will + require recompiling all users of this library. Stack allocation is + relatively cheap and unwind-state copying is relatively rare, so we + want to err on making it rather too big than too small. */ +#define UNW_TDEP_CURSOR_LEN 127 + +typedef uint64_t unw_word_t; +typedef int64_t unw_sword_t; + +typedef long double unw_tdep_fpreg_t; + +typedef enum + { + UNW_X86_64_RAX, + UNW_X86_64_RDX, + UNW_X86_64_RCX, + UNW_X86_64_RBX, + UNW_X86_64_RSI, + UNW_X86_64_RDI, + UNW_X86_64_RBP, + UNW_X86_64_RSP, + UNW_X86_64_R8, + UNW_X86_64_R9, + UNW_X86_64_R10, + UNW_X86_64_R11, + UNW_X86_64_R12, + UNW_X86_64_R13, + UNW_X86_64_R14, + UNW_X86_64_R15, + UNW_X86_64_RIP, +#ifdef CONFIG_MSABI_SUPPORT + UNW_X86_64_XMM0, + UNW_X86_64_XMM1, + UNW_X86_64_XMM2, + UNW_X86_64_XMM3, + UNW_X86_64_XMM4, + UNW_X86_64_XMM5, + UNW_X86_64_XMM6, + UNW_X86_64_XMM7, + UNW_X86_64_XMM8, + UNW_X86_64_XMM9, + UNW_X86_64_XMM10, + UNW_X86_64_XMM11, + UNW_X86_64_XMM12, + UNW_X86_64_XMM13, + UNW_X86_64_XMM14, + UNW_X86_64_XMM15, + UNW_TDEP_LAST_REG = UNW_X86_64_XMM15, +#else + UNW_TDEP_LAST_REG = UNW_X86_64_RIP, +#endif + + /* XXX Add other regs here */ + + /* frame info (read-only) */ + UNW_X86_64_CFA, + + UNW_TDEP_IP = UNW_X86_64_RIP, + UNW_TDEP_SP = UNW_X86_64_RSP, + UNW_TDEP_BP = UNW_X86_64_RBP, + UNW_TDEP_EH = UNW_X86_64_RAX + } +x86_64_regnum_t; + +#define UNW_TDEP_NUM_EH_REGS 2 /* XXX Not sure what this means */ + +typedef struct unw_tdep_save_loc + { + /* Additional target-dependent info on a save location. */ + char unused; + } +unw_tdep_save_loc_t; + +/* On x86_64, we can directly use ucontext_t as the unwind context. */ +typedef ucontext_t unw_tdep_context_t; + +typedef struct + { + /* no x86-64-specific auxiliary proc-info */ + char unused; + } +unw_tdep_proc_info_t; + +#include "libunwind-dynamic.h" +#include "libunwind-common.h" + +#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext) +#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) + +extern int unw_tdep_getcontext (unw_tdep_context_t *); +extern int unw_tdep_is_fpreg (int); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* LIBUNWIND_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind.h.in b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind.h.in new file mode 100644 index 0000000..7a56168 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/libunwind.h.in @@ -0,0 +1,36 @@ +/* Provide a real file - not a symlink - as it would cause multiarch conflicts + when multiple different arch releases are installed simultaneously. */ + +#ifndef UNW_REMOTE_ONLY + +#if defined __aarch64__ +#include "libunwind-aarch64.h" +#elif defined __arm__ +# include "libunwind-arm.h" +#elif defined __hppa__ +# include "libunwind-hppa.h" +#elif defined __ia64__ +# include "libunwind-ia64.h" +#elif defined __mips__ +# include "libunwind-mips.h" +#elif defined __powerpc__ && !defined __powerpc64__ +# include "libunwind-ppc32.h" +#elif defined __powerpc64__ +# include "libunwind-ppc64.h" +#elif defined __sh__ +# include "libunwind-sh.h" +#elif defined __i386__ +# include "libunwind-x86.h" +#elif defined __x86_64__ +# include "libunwind-x86_64.h" +#elif defined __tilegx__ +# include "libunwind-tilegx.h" +#else +# error "Unsupported arch" +#endif + +#else /* UNW_REMOTE_ONLY */ + +# include "libunwind-@arch@.h" + +#endif /* UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/mempool.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/mempool.h new file mode 100644 index 0000000..1f1c770 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/mempool.h @@ -0,0 +1,89 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef mempool_h +#define mempool_h + +/* Memory pools provide simple memory management of fixed-size + objects. Memory pools are used for two purposes: + + o To ensure a stack can be unwound even when a process + is out of memory. + + o To ensure a stack can be unwound at any time in a + multi-threaded process (e.g., even at a time when the normal + malloc-lock is taken, possibly by the very thread that is + being unwind). + + + To achieve the second objective, memory pools allocate memory + directly via mmap() system call (or an equivalent facility). + + The first objective is accomplished by reserving memory ahead of + time. Since the memory requirements of stack unwinding generally + depends on the complexity of the procedures being unwind, there is + no absolute guarantee that unwinding will always work, but in + practice, this should not be a serious problem. */ + +#include + +#include "libunwind_i.h" + +#define sos_alloc(s) UNWI_ARCH_OBJ(_sos_alloc)(s) +#define mempool_init(p,s,r) UNWI_ARCH_OBJ(_mempool_init)(p,s,r) +#define mempool_alloc(p) UNWI_ARCH_OBJ(_mempool_alloc)(p) +#define mempool_free(p,o) UNWI_ARCH_OBJ(_mempool_free)(p,o) + +/* The mempool structure should be treated as an opaque object. It's + declared here only to enable static allocation of mempools. */ +struct mempool + { + pthread_mutex_t lock; + size_t obj_size; /* object size (rounded up for alignment) */ + size_t chunk_size; /* allocation granularity */ + unsigned int reserve; /* minimum (desired) size of the free-list */ + unsigned int num_free; /* number of objects on the free-list */ + struct object + { + struct object *next; + } + *free_list; + }; + +/* Emergency allocation for one-time stuff that doesn't fit the memory + pool model. A limited amount of memory is available in this + fashion and once allocated, there is no way to free it. */ +extern void *sos_alloc (size_t size); + +/* Initialize POOL for an object size of OBJECT_SIZE bytes. RESERVE + is the number of objects that should be reserved for use under + tight memory situations. If it is zero, mempool attempts to pick a + reasonable default value. */ +extern void mempool_init (struct mempool *pool, + size_t obj_size, size_t reserve); +extern void *mempool_alloc (struct mempool *pool); +extern void mempool_free (struct mempool *pool, void *object); + +#endif /* mempool_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/remote.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/remote.h new file mode 100644 index 0000000..064d630 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/remote.h @@ -0,0 +1,129 @@ +#ifndef REMOTE_H +#define REMOTE_H + +/* Helper functions for accessing (remote) memory. These functions + assume that all addresses are naturally aligned (e.g., 32-bit + quantity is stored at a 32-bit-aligned address. */ + +#ifdef UNW_LOCAL_ONLY + +static inline int +fetch8 (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, int8_t *valp, void *arg) +{ + *valp = *(int8_t *) (uintptr_t) *addr; + *addr += 1; + return 0; +} + +static inline int +fetch16 (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, int16_t *valp, void *arg) +{ + *valp = *(int16_t *) (uintptr_t) *addr; + *addr += 2; + return 0; +} + +static inline int +fetch32 (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, int32_t *valp, void *arg) +{ + *valp = *(int32_t *) (uintptr_t) *addr; + *addr += 4; + return 0; +} + +static inline int +fetchw (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, unw_word_t *valp, void *arg) +{ + *valp = *(unw_word_t *) (uintptr_t) *addr; + *addr += sizeof (unw_word_t); + return 0; +} + +#else /* !UNW_LOCAL_ONLY */ + +#define WSIZE (sizeof (unw_word_t)) + +static inline int +fetch8 (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, int8_t *valp, void *arg) +{ + unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr; + int ret; + + *addr += 1; + + ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg); + +#if __BYTE_ORDER == __LITTLE_ENDIAN + val >>= 8*off; +#else + val >>= 8*(WSIZE - 1 - off); +#endif + *valp = val & 0xff; + return ret; +} + +static inline int +fetch16 (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, int16_t *valp, void *arg) +{ + unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr; + int ret; + + if ((off & 0x1) != 0) + return -UNW_EINVAL; + + *addr += 2; + + ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg); + +#if __BYTE_ORDER == __LITTLE_ENDIAN + val >>= 8*off; +#else + val >>= 8*(WSIZE - 2 - off); +#endif + *valp = val & 0xffff; + return ret; +} + +static inline int +fetch32 (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, int32_t *valp, void *arg) +{ + unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr; + int ret; + + if ((off & 0x3) != 0) + return -UNW_EINVAL; + + *addr += 4; + + ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg); + +#if __BYTE_ORDER == __LITTLE_ENDIAN + val >>= 8*off; +#else + val >>= 8*(WSIZE - 4 - off); +#endif + *valp = val & 0xffffffff; + return ret; +} + +static inline int +fetchw (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, unw_word_t *valp, void *arg) +{ + int ret; + + ret = (*a->access_mem) (as, *addr, valp, 0, arg); + *addr += WSIZE; + return ret; +} + +#endif /* !UNW_LOCAL_ONLY */ + +#endif /* REMOTE_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-aarch64/dwarf-config.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-aarch64/dwarf-config.h new file mode 100644 index 0000000..f65db17 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-aarch64/dwarf-config.h @@ -0,0 +1,52 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + Copyright (C) 2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef dwarf_config_h +#define dwarf_config_h + +/* This matches the value udes by GCC (see + gcc/config/aarch64/aarch64.h:DWARF_FRAME_REGISTERS. */ +#define DWARF_NUM_PRESERVED_REGS 97 + +/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ +#define dwarf_is_big_endian(addr_space) 0 + +#define dwarf_to_unw_regnum(reg) (((reg) <= UNW_AARCH64_V31) ? (reg) : 0) + +/* Convert a pointer to a dwarf_cursor structure to a pointer to + unw_cursor_t. */ +#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) + +typedef struct dwarf_loc + { + unw_word_t val; +#ifndef UNW_LOCAL_ONLY + unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */ +#endif + } +dwarf_loc_t; + +#endif /* dwarf_config_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-aarch64/jmpbuf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-aarch64/jmpbuf.h new file mode 100644 index 0000000..3f01a44 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-aarch64/jmpbuf.h @@ -0,0 +1,33 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ + +/* FIXME for AArch64 */ + +#define JB_SP 13 +#define JB_RP 14 +#define JB_MASK_SAVED 15 +#define JB_MASK 16 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-arm/dwarf-config.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-arm/dwarf-config.h new file mode 100644 index 0000000..f502289 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-arm/dwarf-config.h @@ -0,0 +1,51 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef dwarf_config_h +#define dwarf_config_h + +/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not + explicitly defined. */ +#define DWARF_NUM_PRESERVED_REGS 128 + +#define dwarf_to_unw_regnum(reg) (((reg) < 16) ? (reg) : 0) + +/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ +#define dwarf_is_big_endian(addr_space) 0 + +/* Convert a pointer to a dwarf_cursor structure to a pointer to + unw_cursor_t. */ +#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) + +typedef struct dwarf_loc + { + unw_word_t val; +#ifndef UNW_LOCAL_ONLY + unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */ +#endif + } +dwarf_loc_t; + +#endif /* dwarf_config_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-arm/ex_tables.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-arm/ex_tables.h new file mode 100644 index 0000000..9df5e0a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-arm/ex_tables.h @@ -0,0 +1,55 @@ +/* libunwind - a platform-independent unwind library + Copyright 2011 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef ARM_EX_TABLES_H +#define ARM_EX_TABLES_H + +typedef enum arm_exbuf_cmd { + ARM_EXIDX_CMD_FINISH, + ARM_EXIDX_CMD_DATA_PUSH, + ARM_EXIDX_CMD_DATA_POP, + ARM_EXIDX_CMD_REG_POP, + ARM_EXIDX_CMD_REG_TO_SP, + ARM_EXIDX_CMD_VFP_POP, + ARM_EXIDX_CMD_WREG_POP, + ARM_EXIDX_CMD_WCGR_POP, + ARM_EXIDX_CMD_RESERVED, + ARM_EXIDX_CMD_REFUSED, +} arm_exbuf_cmd_t; + +struct arm_exbuf_data +{ + arm_exbuf_cmd_t cmd; + uint32_t data; +}; + +#define arm_exidx_extract UNW_OBJ(arm_exidx_extract) +#define arm_exidx_decode UNW_OBJ(arm_exidx_decode) +#define arm_exidx_apply_cmd UNW_OBJ(arm_exidx_apply_cmd) + +int arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf); +int arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c); +int arm_exidx_apply_cmd (struct arm_exbuf_data *edata, struct dwarf_cursor *c); + +#endif // ARM_EX_TABLES_H diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-arm/jmpbuf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-arm/jmpbuf.h new file mode 100644 index 0000000..008e77f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-arm/jmpbuf.h @@ -0,0 +1,32 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ + +/* FIXME for ARM! */ + +#define JB_SP 4 +#define JB_RP 5 +#define JB_MASK_SAVED 6 +#define JB_MASK 7 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-hppa/dwarf-config.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-hppa/dwarf-config.h new file mode 100644 index 0000000..fb963c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-hppa/dwarf-config.h @@ -0,0 +1,54 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2004 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef dwarf_config_h +#define dwarf_config_h + +/* See DWARF_FRAME_REGNUM() macro in gcc/config/pa/pa32-regs.h: */ +#define dwarf_to_unw_regnum(reg) \ + (((reg) < DWARF_NUM_PRESERVED_REGS) ? (reg) : 0) + +/* This matches the value used by GCC (see + gcc/config/pa/pa32-regs.h:FIRST_PSEUDO_REGISTER), which leaves + plenty of room for expansion. */ +#define DWARF_NUM_PRESERVED_REGS 89 + +/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ +#define dwarf_is_big_endian(addr_space) 1 + +/* Convert a pointer to a dwarf_cursor structure to a pointer to + unw_cursor_t. */ +#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) + +typedef struct dwarf_loc + { + unw_word_t val; +#ifndef UNW_LOCAL_ONLY + unw_word_t type; /* see X86_LOC_TYPE_* macros. */ +#endif + } +dwarf_loc_t; + +#endif /* dwarf_config_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-hppa/jmpbuf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-hppa/jmpbuf.h new file mode 100644 index 0000000..91f062f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-hppa/jmpbuf.h @@ -0,0 +1,33 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ + +#ifndef JB_SP +# define JB_SP 19 +#endif +#define JB_RP 20 +#define JB_MASK_SAVED 21 +#define JB_MASK 22 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ia64/jmpbuf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ia64/jmpbuf.h new file mode 100644 index 0000000..d642af2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ia64/jmpbuf.h @@ -0,0 +1,32 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Use glibc's jump-buffer indices; NPTL peeks at SP and BSP: */ + +#define JB_SP 0 +#define JB_RP 8 +#define JB_BSP 17 +#define JB_MASK_SAVED 70 +#define JB_MASK 71 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ia64/rse.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ia64/rse.h new file mode 100644 index 0000000..ee521a5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ia64/rse.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 1998, 1999, 2002, 2003, 2005 Hewlett-Packard Co + * David Mosberger-Tang + * + * Register stack engine related helper functions. This file may be + * used in applications, so be careful about the name-space and give + * some consideration to non-GNU C compilers (though __inline__ is + * fine). + */ +#ifndef RSE_H +#define RSE_H + +#include + +static inline uint64_t +rse_slot_num (uint64_t addr) +{ + return (addr >> 3) & 0x3f; +} + +/* + * Return TRUE if ADDR is the address of an RNAT slot. + */ +static inline uint64_t +rse_is_rnat_slot (uint64_t addr) +{ + return rse_slot_num (addr) == 0x3f; +} + +/* + * Returns the address of the RNAT slot that covers the slot at + * address SLOT_ADDR. + */ +static inline uint64_t +rse_rnat_addr (uint64_t slot_addr) +{ + return slot_addr | (0x3f << 3); +} + +/* + * Calculate the number of registers in the dirty partition starting at + * BSPSTORE and ending at BSP. This isn't simply (BSP-BSPSTORE)/8 + * because every 64th slot stores ar.rnat. + */ +static inline uint64_t +rse_num_regs (uint64_t bspstore, uint64_t bsp) +{ + uint64_t slots = (bsp - bspstore) >> 3; + + return slots - (rse_slot_num(bspstore) + slots)/0x40; +} + +/* + * The inverse of the above: given bspstore and the number of + * registers, calculate ar.bsp. + */ +static inline uint64_t +rse_skip_regs (uint64_t addr, long num_regs) +{ + long delta = rse_slot_num(addr) + num_regs; + + if (num_regs < 0) + delta -= 0x3e; + return addr + ((num_regs + delta/0x3f) << 3); +} + +#endif /* RSE_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ia64/script.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ia64/script.h new file mode 100644 index 0000000..fe3360b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ia64/script.h @@ -0,0 +1,85 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#define IA64_LOG_UNW_CACHE_SIZE 7 +#define IA64_UNW_CACHE_SIZE (1 << IA64_LOG_UNW_CACHE_SIZE) + +#define IA64_LOG_UNW_HASH_SIZE (IA64_LOG_UNW_CACHE_SIZE + 1) +#define IA64_UNW_HASH_SIZE (1 << IA64_LOG_UNW_HASH_SIZE) + +typedef unsigned char unw_hash_index_t; + +struct ia64_script_insn + { + unsigned int opc; /* see enum ia64_script_insn_opcode */ + unsigned int dst; + unw_word_t val; + }; + +/* Updating each preserved register may result in one script + instruction each. At the end of the script, psp gets popped, + accounting for one more instruction. */ +#define IA64_MAX_SCRIPT_LEN (IA64_NUM_PREGS + 1) + +struct ia64_script + { + unw_word_t ip; /* ip this script is for */ + unw_word_t pr_mask; /* mask of predicates script depends on */ + unw_word_t pr_val; /* predicate values this script is for */ + unw_proc_info_t pi; /* info about underlying procedure */ + unsigned short lru_chain; /* used for least-recently-used chain */ + unsigned short coll_chain; /* used for hash collisions */ + unsigned short hint; /* hint for next script to try (or -1) */ + unsigned short count; /* number of instructions in script */ + unsigned short abi_marker; + struct ia64_script_insn insn[IA64_MAX_SCRIPT_LEN]; + }; + +struct ia64_script_cache + { +#ifdef HAVE_ATOMIC_OPS_H + AO_TS_t busy; /* is the script-cache busy? */ +#else + pthread_mutex_t lock; +#endif + unsigned short lru_head; /* index of lead-recently used script */ + unsigned short lru_tail; /* index of most-recently used script */ + + /* hash table that maps instruction pointer to script index: */ + unsigned short hash[IA64_UNW_HASH_SIZE]; + + uint32_t generation; /* generation number */ + + /* script cache: */ + struct ia64_script buckets[IA64_UNW_CACHE_SIZE]; + }; + +#define ia64_cache_proc_info UNW_OBJ(cache_proc_info) +#define ia64_get_cached_proc_info UNW_OBJ(get_cached_proc_info) + +struct cursor; /* forward declaration */ + +extern int ia64_cache_proc_info (struct cursor *c); +extern int ia64_get_cached_proc_info (struct cursor *c); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-mips/dwarf-config.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-mips/dwarf-config.h new file mode 100644 index 0000000..8006d0b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-mips/dwarf-config.h @@ -0,0 +1,54 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef dwarf_config_h +#define dwarf_config_h + +/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not + explicitly defined. */ +#define DWARF_NUM_PRESERVED_REGS 188 + +#define dwarf_to_unw_regnum(reg) (((reg) < 32) ? (reg) : 0) + +/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ +#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian) + +/* Return the size of an address, for DWARF purposes. */ +#define dwarf_addr_size(addr_space) ((addr_space)->addr_size) + +/* Convert a pointer to a dwarf_cursor structure to a pointer to + unw_cursor_t. */ +#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) + +typedef struct dwarf_loc + { + unw_word_t val; +#ifndef UNW_LOCAL_ONLY + unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */ +#endif + } +dwarf_loc_t; + +#endif /* dwarf_config_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-mips/jmpbuf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-mips/jmpbuf.h new file mode 100644 index 0000000..c099f92 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-mips/jmpbuf.h @@ -0,0 +1,32 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ + +/* FIXME for MIPS! */ + +#define JB_SP 4 +#define JB_RP 5 +#define JB_MASK_SAVED 6 +#define JB_MASK 7 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc32/dwarf-config.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc32/dwarf-config.h new file mode 100644 index 0000000..bf6886b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc32/dwarf-config.h @@ -0,0 +1,56 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + + Copied from libunwind-x86_64.h, modified slightly for building + frysk successfully on ppc64, by Wu Zhou + Will be replaced when libunwind is ready on ppc64 platform. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef dwarf_config_h +#define dwarf_config_h + +/* For PPC64, 48 GPRs + 33 FPRs + 33 AltiVec + 1 SPE */ +#define DWARF_NUM_PRESERVED_REGS 115 + +#define DWARF_REGNUM_MAP_LENGTH 115 + +/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ +#define dwarf_is_big_endian(addr_space) 1 + +/* Convert a pointer to a dwarf_cursor structure to a pointer to + unw_cursor_t. */ +#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) + +typedef struct dwarf_loc + { + unw_word_t val; +#ifndef UNW_LOCAL_ONLY + unw_word_t type; /* see X86_LOC_TYPE_* macros. */ +#endif + } +dwarf_loc_t; + +#endif /* dwarf_config_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc32/jmpbuf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc32/jmpbuf.h new file mode 100644 index 0000000..861e94d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc32/jmpbuf.h @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + + Copied from libunwind-x86_64.h, modified slightly for building + frysk successfully on ppc64, by Wu Zhou + Will be replaced when libunwind is ready on ppc64 platform. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ + +#define JB_SP 6 +#define JB_RP 7 +#define JB_MASK_SAVED 8 +#define JB_MASK 9 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc64/dwarf-config.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc64/dwarf-config.h new file mode 100644 index 0000000..6d8ef0a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc64/dwarf-config.h @@ -0,0 +1,56 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + + Copied from libunwind-x86_64.h, modified slightly for building + frysk successfully on ppc64, by Wu Zhou + Will be replaced when libunwind is ready on ppc64 platform. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef dwarf_config_h +#define dwarf_config_h + +/* For PPC64, 48 GPRs + 33 FPRs + 33 AltiVec + 1 SPE */ +#define DWARF_NUM_PRESERVED_REGS 115 + +#define DWARF_REGNUM_MAP_LENGTH 115 + +/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ +#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian) + +/* Convert a pointer to a dwarf_cursor structure to a pointer to + unw_cursor_t. */ +#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) + +typedef struct dwarf_loc + { + unw_word_t val; +#ifndef UNW_LOCAL_ONLY + unw_word_t type; /* see X86_LOC_TYPE_* macros. */ +#endif + } +dwarf_loc_t; + +#endif /* dwarf_config_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc64/jmpbuf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc64/jmpbuf.h new file mode 100644 index 0000000..861e94d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-ppc64/jmpbuf.h @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + + Copied from libunwind-x86_64.h, modified slightly for building + frysk successfully on ppc64, by Wu Zhou + Will be replaced when libunwind is ready on ppc64 platform. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ + +#define JB_SP 6 +#define JB_RP 7 +#define JB_MASK_SAVED 8 +#define JB_MASK 9 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-sh/dwarf-config.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-sh/dwarf-config.h new file mode 100644 index 0000000..2f76f5b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-sh/dwarf-config.h @@ -0,0 +1,49 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef dwarf_config_h +#define dwarf_config_h + +#define DWARF_NUM_PRESERVED_REGS 18 + +#define dwarf_to_unw_regnum(reg) (((reg) <= UNW_SH_PR) ? (reg) : 0) + +/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ +#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian) + +/* Convert a pointer to a dwarf_cursor structure to a pointer to + unw_cursor_t. */ +#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) + +typedef struct dwarf_loc + { + unw_word_t val; +#ifndef UNW_LOCAL_ONLY + unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */ +#endif + } +dwarf_loc_t; + +#endif /* dwarf_config_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-sh/jmpbuf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-sh/jmpbuf.h new file mode 100644 index 0000000..8b44b5b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-sh/jmpbuf.h @@ -0,0 +1,48 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ + +/* SH4 glibc jump buffer contents: + * 0. r8 + * 1. r9 + * 2. r10 + * 3. r11 + * 4. r12 + * 5. r13 + * 6. r14 + * 7. r15 + * 8. pr/pc + * 9. gbr + * 10. fpscr + * 11. fr12 + * 12. fr13 + * 13. fr14 + * 14. fr15 + */ + +#define JB_SP 7 +#define JB_RP 8 +#define JB_MASK_SAVED 15 +#define JB_MASK 16 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-tilegx/dwarf-config.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-tilegx/dwarf-config.h new file mode 100644 index 0000000..93bc6aa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-tilegx/dwarf-config.h @@ -0,0 +1,50 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef dwarf_config_h +#define dwarf_config_h + +/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not + explicitly defined. */ +#define DWARF_NUM_PRESERVED_REGS 188 + +#define DWARF_REGNUM_MAP_LENGTH (56 + 2) + +/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ +#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian) + +/* Convert a pointer to a dwarf_cursor structure to a pointer to + unw_cursor_t. */ +#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) + +typedef struct dwarf_loc +{ + unw_word_t val; +#ifndef UNW_LOCAL_ONLY + unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */ +#endif +} dwarf_loc_t; + +#endif /* dwarf_config_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-tilegx/jmpbuf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-tilegx/jmpbuf.h new file mode 100644 index 0000000..3afe9e4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-tilegx/jmpbuf.h @@ -0,0 +1,33 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ + +/* FIXME for Tilegx! */ + +#define JB_SP 4 +#define JB_RP 5 +#define JB_MASK_SAVED 6 +#define JB_MASK 7 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86/dwarf-config.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86/dwarf-config.h new file mode 100644 index 0000000..f76f9c1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86/dwarf-config.h @@ -0,0 +1,52 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef dwarf_config_h +#define dwarf_config_h + +/* This matches the value used by GCC (see + gcc/config/i386.h:DWARF_FRAME_REGISTERS), which leaves plenty of + room for expansion. */ +#define DWARF_NUM_PRESERVED_REGS 17 + +#define DWARF_REGNUM_MAP_LENGTH 19 + +/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ +#define dwarf_is_big_endian(addr_space) 0 + +/* Convert a pointer to a dwarf_cursor structure to a pointer to + unw_cursor_t. */ +#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) + +typedef struct dwarf_loc + { + unw_word_t val; +#ifndef UNW_LOCAL_ONLY + unw_word_t type; /* see X86_LOC_TYPE_* macros. */ +#endif + } +dwarf_loc_t; + +#endif /* dwarf_config_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86/jmpbuf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86/jmpbuf.h new file mode 100644 index 0000000..521dfa6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86/jmpbuf.h @@ -0,0 +1,42 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ + +#if defined __linux__ + +#define JB_SP 4 +#define JB_RP 5 +#define JB_MASK_SAVED 6 +#define JB_MASK 7 + +#elif defined __FreeBSD__ + +#define JB_SP 2 +#define JB_RP 0 +#define JB_MASK_SAVED 11 +#define JB_MASK 7 + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86_64/dwarf-config.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86_64/dwarf-config.h new file mode 100644 index 0000000..ff77808 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86_64/dwarf-config.h @@ -0,0 +1,57 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* copy of include/tdep-x86/dwarf-config.h, modified slightly for x86-64 + some consolidation is possible here */ + +#ifndef dwarf_config_h +#define dwarf_config_h + +/* XXX need to verify if this value is correct */ +#ifdef CONFIG_MSABI_SUPPORT +#define DWARF_NUM_PRESERVED_REGS 33 +#else +#define DWARF_NUM_PRESERVED_REGS 17 +#endif + +#define DWARF_REGNUM_MAP_LENGTH DWARF_NUM_PRESERVED_REGS + +/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ +#define dwarf_is_big_endian(addr_space) 0 + +/* Convert a pointer to a dwarf_cursor structure to a pointer to + unw_cursor_t. */ +#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) + +typedef struct dwarf_loc + { + unw_word_t val; + unw_word_t type; /* see X86_LOC_TYPE_* macros. */ + } +dwarf_loc_t; + +#endif /* dwarf_config_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86_64/jmpbuf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86_64/jmpbuf.h new file mode 100644 index 0000000..d571966 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep-x86_64/jmpbuf.h @@ -0,0 +1,43 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#if defined __linux__ + +/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ + +#define JB_SP 6 +#define JB_RP 7 +#define JB_MASK_SAVED 8 +#define JB_MASK 9 + +#elif defined __FreeBSD__ + +#define JB_SP 2 +#define JB_RP 0 +/* Pretend the ip cannot be 0 and mask is always saved */ +#define JB_MASK_SAVED 0 +#define JB_MASK 9 + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep/dwarf-config.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep/dwarf-config.h new file mode 100644 index 0000000..c759a46 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep/dwarf-config.h @@ -0,0 +1,28 @@ +/* Provide a real file - not a symlink - as it would cause multiarch conflicts + when multiple different arch releases are installed simultaneously. */ + +#if defined __aarch64__ +# include "tdep-aarch64/dwarf-config.h" +#elif defined __arm__ +# include "tdep-arm/dwarf-config.h" +#elif defined __hppa__ +# include "tdep-hppa/dwarf-config.h" +#elif defined __ia64__ +# include "tdep-ia64/dwarf-config.h" +#elif defined __mips__ +# include "tdep-mips/dwarf-config.h" +#elif defined __powerpc__ && !defined __powerpc64__ +# include "tdep-ppc32/dwarf-config.h" +#elif defined __powerpc64__ +# include "tdep-ppc64/dwarf-config.h" +#elif defined __sh__ +# include "tdep-sh/dwarf-config.h" +#elif defined __i386__ +# include "tdep-x86/dwarf-config.h" +#elif defined __x86_64__ || defined __amd64__ +# include "tdep-x86_64/dwarf-config.h" +#elif defined __tilegx__ +# include "tdep-tilegx/dwarf-config.h" +#else +# error "Unsupported arch" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep/jmpbuf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep/jmpbuf.h new file mode 100644 index 0000000..13093a0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep/jmpbuf.h @@ -0,0 +1,30 @@ +/* Provide a real file - not a symlink - as it would cause multiarch conflicts + when multiple different arch releases are installed simultaneously. */ + +#ifndef UNW_REMOTE_ONLY + +#if defined __aarch64__ +# include "tdep-aarch64/jmpbuf.h" +#elif defined __arm__ +# include "tdep-arm/jmpbuf.h" +#elif defined __hppa__ +# include "tdep-hppa/jmpbuf.h" +#elif defined __ia64__ +# include "tdep-ia64/jmpbuf.h" +#elif defined __mips__ +# include "tdep-mips/jmpbuf.h" +#elif defined __powerpc__ && !defined __powerpc64__ +# include "tdep-ppc32/jmpbuf.h" +#elif defined __powerpc64__ +# include "tdep-ppc64/jmpbuf.h" +#elif defined __i386__ +# include "tdep-x86/jmpbuf.h" +#elif defined __x86_64__ +# include "tdep-x86_64/jmpbuf.h" +#elif defined __tilegx__ +# include "tdep-tilegx/jmpbuf.h" +#else +# error "Unsupported arch" +#endif + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep/libunwind_i.h.in b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep/libunwind_i.h.in new file mode 100644 index 0000000..af05a7f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/tdep/libunwind_i.h.in @@ -0,0 +1,37 @@ +/* Provide a real file - not a symlink - as it would cause multiarch conflicts + when multiple different arch releases are installed simultaneously. */ + +#ifndef UNW_REMOTE_ONLY + +#if defined __aarch64__ +# include "tdep-aarch64/libunwind_i.h" +#elif defined __arm__ +# include "tdep-arm/libunwind_i.h" +#elif defined __hppa__ +# include "tdep-hppa/libunwind_i.h" +#elif defined __ia64__ +# include "tdep-ia64/libunwind_i.h" +#elif defined __mips__ +# include "tdep-mips/libunwind_i.h" +#elif defined __powerpc__ && !defined __powerpc64__ +# include "tdep-ppc32/libunwind_i.h" +#elif defined __powerpc64__ +# include "tdep-ppc64/libunwind_i.h" +#elif defined __sh__ +# include "tdep-sh/libunwind_i.h" +#elif defined __i386__ +# include "tdep-x86/libunwind_i.h" +#elif defined __x86_64__ +# include "tdep-x86_64/libunwind_i.h" +#elif defined __tilegx__ +# include "tdep-tilegx/libunwind_i.h" +#else +# error "Unsupported arch" +#endif + + +#else /* UNW_REMOTE_ONLY */ + +# include "tdep-@arch@/libunwind_i.h" + +#endif /* UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/unwind.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/unwind.h new file mode 100644 index 0000000..7cf128d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/include/unwind.h @@ -0,0 +1,154 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _UNWIND_H +#define _UNWIND_H + +/* For uint64_t */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Minimal interface as per C++ ABI draft standard: + + http://www.codesourcery.com/cxx-abi/abi-eh.html */ + +typedef enum + { + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8 + } +_Unwind_Reason_Code; + +typedef int _Unwind_Action; + +#define _UA_SEARCH_PHASE 1 +#define _UA_CLEANUP_PHASE 2 +#define _UA_HANDLER_FRAME 4 +#define _UA_FORCE_UNWIND 8 + +struct _Unwind_Context; /* opaque data-structure */ +struct _Unwind_Exception; /* forward-declaration */ + +typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code, + struct _Unwind_Exception *); + +typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) (int, _Unwind_Action, + uint64_t, + struct _Unwind_Exception *, + struct _Unwind_Context *, + void *); + +/* The C++ ABI requires exception_class, private_1, and private_2 to + be of type uint64 and the entire structure to be + double-word-aligned. Please note that exception_class stays 64-bit + even on 32-bit machines for gcc compatibility. */ +struct _Unwind_Exception + { + uint64_t exception_class; + _Unwind_Exception_Cleanup_Fn exception_cleanup; + unsigned long private_1; + unsigned long private_2; + } __attribute__((__aligned__)); + +extern _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *); +extern _Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *, + _Unwind_Stop_Fn, void *); +extern void _Unwind_Resume (struct _Unwind_Exception *); +extern void _Unwind_DeleteException (struct _Unwind_Exception *); +extern unsigned long _Unwind_GetGR (struct _Unwind_Context *, int); +extern void _Unwind_SetGR (struct _Unwind_Context *, int, unsigned long); +extern unsigned long _Unwind_GetIP (struct _Unwind_Context *); +extern unsigned long _Unwind_GetIPInfo (struct _Unwind_Context *, int *); +extern void _Unwind_SetIP (struct _Unwind_Context *, unsigned long); +extern unsigned long _Unwind_GetLanguageSpecificData (struct _Unwind_Context*); +extern unsigned long _Unwind_GetRegionStart (struct _Unwind_Context *); + +#ifdef _GNU_SOURCE + +/* Callback for _Unwind_Backtrace(). The backtrace stops immediately + if the callback returns any value other than _URC_NO_REASON. */ +typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (struct _Unwind_Context *, + void *); + +/* See http://gcc.gnu.org/ml/gcc-patches/2001-09/msg00082.html for why + _UA_END_OF_STACK exists. */ +# define _UA_END_OF_STACK 16 + +/* If the unwind was initiated due to a forced unwind, resume that + operation, else re-raise the exception. This is used by + __cxa_rethrow(). */ +extern _Unwind_Reason_Code + _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *); + +/* See http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00154.html for why + _Unwind_GetBSP() exists. */ +extern unsigned long _Unwind_GetBSP (struct _Unwind_Context *); + +/* Return the "canonical frame address" for the given context. + This is used by NPTL... */ +extern unsigned long _Unwind_GetCFA (struct _Unwind_Context *); + +/* Return the base-address for data references. */ +extern unsigned long _Unwind_GetDataRelBase (struct _Unwind_Context *); + +/* Return the base-address for text references. */ +extern unsigned long _Unwind_GetTextRelBase (struct _Unwind_Context *); + +/* Call _Unwind_Trace_Fn once for each stack-frame, without doing any + cleanup. The first frame for which the callback is invoked is the + one for the caller of _Unwind_Backtrace(). _Unwind_Backtrace() + returns _URC_END_OF_STACK when the backtrace stopped due to + reaching the end of the call-chain or _URC_FATAL_PHASE1_ERROR if it + stops for any other reason. */ +extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *); + +/* Find the start-address of the procedure containing the specified IP + or NULL if it cannot be found (e.g., because the function has no + unwind info). Note: there is not necessarily a one-to-one + correspondence between source-level functions and procedures: some + functions don't have unwind-info and others are split into multiple + procedures. */ +extern void *_Unwind_FindEnclosingFunction (void *); + +/* See also Linux Standard Base Spec: + http://www.linuxbase.org/spec/refspecs/LSB_1.3.0/gLSB/gLSB/libgcc-s.html */ + +#endif /* _GNU_SOURCE */ + +#ifdef __cplusplus +}; +#endif + +#endif /* _UNWIND_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/scripts/kernel-diff.sh b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/scripts/kernel-diff.sh new file mode 100644 index 0000000..459194e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/scripts/kernel-diff.sh @@ -0,0 +1,10 @@ +kdir=${1:-../kernel} +scriptdir=$(dirname $0) +udir=$(dirname $scriptdir) +cat $scriptdir/kernel-files.txt | \ +(while read l r; do + left=$(eval echo $l) + right=$(eval echo $r) +# echo $left $right + diff -up $left $right +done) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/scripts/kernel-files.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/scripts/kernel-files.txt new file mode 100644 index 0000000..d79e453 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/scripts/kernel-files.txt @@ -0,0 +1,19 @@ +$udir/include/tdep-ia64/rse.h $kdir/arch/ia64/unwind/rse.h +$udir/src/ia64/Ginit_local.c $kdir/arch/ia64/unwind/init_local.c +$udir/src/ia64/Gis_signal_frame.c $kdir/arch/ia64/unwind/is_signal_frame.c +$udir/src/ia64/Gparser.c $kdir/arch/ia64/unwind/parser.c +$udir/src/ia64/Grbs.c $kdir/arch/ia64/unwind/rbs.c +$udir/src/ia64/Gregs.c $kdir/arch/ia64/unwind/regs.c +$udir/src/ia64/Gscript.c $kdir/arch/ia64/unwind/script.c +$udir/src/ia64/Gstep.c $kdir/arch/ia64/unwind/step.c +$udir/src/ia64/init.h $kdir/arch/ia64/unwind/init.h +$udir/src/ia64/offsets.h $kdir/arch/ia64/unwind/offsets.h +$udir/src/ia64/regname.c $kdir/arch/ia64/unwind/regname.c +$udir/src/ia64/regs.h $kdir/arch/ia64/unwind/regs.h +$udir/src/ia64/unwind_decoder.h $kdir/arch/ia64/unwind/unwind_decoder.h +$udir/src/mi/Gget_fpreg.c $kdir/unwind/get_fpreg.c +$udir/src/mi/Gget_reg.c $kdir/unwind/get_reg.c +$udir/src/mi/Gset_fpreg.c $kdir/unwind/set_fpreg.c +$udir/src/mi/Gset_reg.c $kdir/unwind/set_reg.c +$udir/src/mi/flush_cache.c $kdir/unwind/flush_cache.c +$udir/src/mi/mempool.c $kdir/unwind/mempool.c diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/scripts/make-L-files b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/scripts/make-L-files new file mode 100644 index 0000000..8280e3d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/scripts/make-L-files @@ -0,0 +1,30 @@ +#!/bin/sh +cwd=`pwd` +dir=`basename ${cwd}` +# +# When compiling a file that goes into libunwind, we only +# need to compile it when we really do support UNW_LOCAL_ONLY. +# In contrast, libunwind-tests should always get compiled. +# +if test $dir = "tests"; then + local_only_test="" +else + local_only_test="defined(UNW_LOCAL_ONLY) && " +fi +for gname in `ls G*.c G*.cxx G*.S 2>/dev/null`; do + lname="L$(expr $gname : '.\(.*\)')" + bk edit $lname >/dev/null 2>&1 + ext=$(expr $gname : '[^.]*[.]\(.*\)') + if [ "$ext" = "S" ]; then + include="" + else + include="#include " + fi + echo -e "\ +#define UNW_LOCAL_ONLY\n\ +$include\n\ +#if ${local_only_test}!defined(UNW_REMOTE_ONLY)\n\ +#include \"$gname\"\n\ +#endif" > $lname + echo created $lname +done diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/CMakeLists.txt new file mode 100644 index 0000000..891eadd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/CMakeLists.txt @@ -0,0 +1,354 @@ +project(unwind) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + + +include(configure.cmake) + +# The HAVE___THREAD set to 1 causes creation of thread local variable with tls_model("initial-exec") +# which is incompatible with usage of the unwind code in a shared library. +add_definitions(-DHAVE___THREAD=0) +add_definitions(-DHAVE_CONFIG_H=1) + +add_definitions(-DPACKAGE_STRING="") +add_definitions(-DPACKAGE_BUGREPORT="") + +add_definitions(-D_GNU_SOURCE) +# Ensure that the remote and local unwind code can reside in the same binary without name clashing +add_definitions("-Ddwarf_search_unwind_table_int=UNW_OBJ(dwarf_search_unwind_table_int)") + +# Disable warning due to incorrect format specifier in debugging printf via the Debug macro +add_compile_options(-Wno-format -Wno-format-security) + +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wno-header-guard) +else() + add_compile_options(-Wno-unused-value) + add_compile_options(-Wno-unused-result) +endif() + +if(CLR_CMAKE_HOST_ARCH_ARM) + # Ensure that the remote and local unwind code can reside in the same binary without name clashing + add_definitions("-Darm_search_unwind_table=UNW_OBJ(arm_search_unwind_table)") + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # Disable warning due to labs function called on unsigned argument + add_compile_options(-Wno-absolute-value) + # Disable warning in asm: use of SP or PC in the list is deprecated + add_compile_options(-Wno-inline-asm) + endif() + # Disable warning for a bug in the libunwind source src/arm/Gtrace.c:529, but not in code that we exercise + add_compile_options(-Wno-implicit-function-declaration) + # Disable warning due to an unused function prel31_read + add_compile_options(-Wno-unused-function) + # We compile code with -std=c99 and the asm keyword is not recognized as it is a gnu extension + add_definitions(-Dasm=__asm__) + # The arm sources include ex_tables.h from include/tdep-arm without going through a redirection + # in include/tdep like it works for similar files on other architectures. So we need to add + # the include/tdep-arm to include directories + include_directories(../include/tdep-arm) +elseif(CLR_CMAKE_HOST_ARCH_ARM64) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # Disable warning due to labs function called on unsigned argument + add_compile_options(-Wno-absolute-value) + endif() + # We compile code with -std=c99 and the asm keyword is not recognized as it is a gnu extension + add_definitions(-Dasm=__asm__) +elseif(CLR_CMAKE_HOST_ARCH_I386) + # Disable warning for a bug in the libunwind source src/x86/Gos-linux.c, but not in code that we exercise + add_compile_options(-Wno-incompatible-pointer-types) +endif() + +SET(libunwind_ptrace_la_SOURCES + ptrace/_UPT_elf.c + ptrace/_UPT_accessors.c ptrace/_UPT_access_fpreg.c + ptrace/_UPT_access_mem.c ptrace/_UPT_access_reg.c + ptrace/_UPT_create.c ptrace/_UPT_destroy.c + ptrace/_UPT_find_proc_info.c ptrace/_UPT_get_dyn_info_list_addr.c + ptrace/_UPT_put_unwind_info.c ptrace/_UPT_get_proc_name.c + ptrace/_UPT_reg_offset.c ptrace/_UPT_resume.c +) + +SET(libunwind_coredump_la_SOURCES + coredump/_UCD_accessors.c + coredump/_UCD_create.c + coredump/_UCD_destroy.c + coredump/_UCD_access_mem.c + coredump/_UCD_elf_map_image.c + coredump/_UCD_find_proc_info.c + coredump/_UCD_get_proc_name.c + + coredump/_UPT_elf.c + coredump/_UPT_access_fpreg.c + coredump/_UPT_get_dyn_info_list_addr.c + coredump/_UPT_put_unwind_info.c + coredump/_UPT_resume.c +) + +# List of arch-independent files needed by generic library (libunwind-$ARCH): +SET(libunwind_la_SOURCES_generic + mi/Gdyn-extract.c mi/Gdyn-remote.c mi/Gfind_dynamic_proc_info.c + # The Gget_accessors.c implements the same function as Lget_accessors.c, so + # the source is excluded here to prevent name clash + #mi/Gget_accessors.c + mi/Gget_proc_info_by_ip.c mi/Gget_proc_name.c + mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c + mi/Gget_reg.c mi/Gset_reg.c + mi/Gget_fpreg.c mi/Gset_fpreg.c + mi/Gset_caching_policy.c + mi/Gset_cache_size.c + oop/_OOP_find_proc_info.c +) + +SET(libunwind_la_SOURCES_os_linux + os-linux.c +) + +SET(libunwind_la_SOURCES_os_linux_local +# Nothing when we don't want to support CXX exceptions +) + +SET(libunwind_la_SOURCES_os_freebsd + os-freebsd.c +) + +SET(libunwind_la_SOURCES_os_freebsd_local +# Nothing +) + +if(CLR_CMAKE_HOST_LINUX) + SET(libunwind_la_SOURCES_os ${libunwind_la_SOURCES_os_linux}) + SET(libunwind_la_SOURCES_os_local ${libunwind_la_SOURCES_os_linux_local}) + SET(libunwind_la_SOURCES_x86_os x86/Gos-linux.c) + SET(libunwind_x86_la_SOURCES_os x86/getcontext-linux.S) + SET(libunwind_la_SOURCES_x86_os_local x86/Los-linux.c) + SET(libunwind_la_SOURCES_x86_64_os x86_64/Gos-linux.c) + SET(libunwind_la_SOURCES_x86_64_os_local x86_64/Los-linux.c) + SET(libunwind_la_SOURCES_arm_os arm/Gos-linux.c) + SET(libunwind_la_SOURCES_arm_os_local arm/Los-linux.c) + list(APPEND libunwind_coredump_la_SOURCES coredump/_UCD_access_reg_linux.c) +elseif(CLR_CMAKE_HOST_FREEBSD) + SET(libunwind_la_SOURCES_os ${libunwind_la_SOURCES_os_freebsd}) + SET(libunwind_la_SOURCES_os_local ${libunwind_la_SOURCES_os_freebsd_local}) + SET(libunwind_la_SOURCES_x86_os x86/Gos-freebsd.c) + SET(libunwind_x86_la_SOURCES_os x86/getcontext-freebsd.S) + SET(libunwind_la_SOURCES_x86_os_local x86/Los-freebsd.c) + SET(libunwind_la_SOURCES_x86_64_os x86_64/Gos-freebsd.c) + SET(libunwind_la_SOURCES_x86_64_os_local x86_64/Los-freebsd.c) + SET(libunwind_la_SOURCES_arm_os arm/Gos-freebsd.c) + SET(libunwind_la_SOURCES_arm_os_local arm/Los-freebsd.c) + list(APPEND libunwind_coredump_la_SOURCES coredump/_UCD_access_reg_freebsd.c) +endif() + +# List of arch-independent files needed by both local-only and generic +# libraries: +SET(libunwind_la_SOURCES_common + ${libunwind_la_SOURCES_os} + mi/init.c mi/flush_cache.c mi/mempool.c mi/strerror.c +) + +SET(libunwind_la_SOURCES_local_unwind +# Nothing when we don't want to support CXX exceptions +) + +# List of arch-independent files needed by local-only library (libunwind): +SET(libunwind_la_SOURCES_local_nounwind + ${libunwind_la_SOURCES_os_local} + mi/backtrace.c + mi/dyn-cancel.c mi/dyn-info-list.c mi/dyn-register.c + mi/Ldyn-extract.c mi/Lfind_dynamic_proc_info.c + mi/Lget_accessors.c + mi/Lget_proc_info_by_ip.c mi/Lget_proc_name.c + mi/Lput_dynamic_unwind_info.c mi/Ldestroy_addr_space.c + mi/Lget_reg.c mi/Lset_reg.c + mi/Lget_fpreg.c mi/Lset_fpreg.c + mi/Lset_caching_policy.c + mi/Lset_cache_size.c +) + +SET(libunwind_la_SOURCES_local + ${libunwind_la_SOURCES_local_nounwind} + ${libunwind_la_SOURCES_local_unwind} +) + +SET(libunwind_dwarf_common_la_SOURCES + dwarf/global.c +) + +SET(libunwind_dwarf_local_la_SOURCES + dwarf/Lexpr.c dwarf/Lfde.c dwarf/Lparser.c dwarf/Lpe.c + dwarf/Lfind_proc_info-lsb.c + dwarf/Lfind_unwind_table.c +) + +SET(libunwind_dwarf_generic_la_SOURCES + dwarf/Gexpr.c dwarf/Gfde.c dwarf/Gparser.c dwarf/Gpe.c + dwarf/Gfind_proc_info-lsb.c + dwarf/Gfind_unwind_table.c +) + +SET(libunwind_elf32_la_SOURCES + elf32.c +) + +SET(libunwind_elf64_la_SOURCES + elf64.c +) +SET(libunwind_elfxx_la_SOURCES + elfxx.c +) + +# The list of files that go into libunwind and libunwind-aarch64: +SET(libunwind_la_SOURCES_aarch64_common + ${libunwind_la_SOURCES_common} + aarch64/is_fpreg.c + aarch64/regname.c +) + +# The list of files that go into libunwind: +SET(libunwind_la_SOURCES_aarch64 + ${libunwind_la_SOURCES_aarch64_common} + ${libunwind_la_SOURCES_local} + aarch64/Lapply_reg_state.c aarch64/Lreg_states_iterate.c + aarch64/Lcreate_addr_space.c aarch64/Lget_proc_info.c + aarch64/Lget_save_loc.c aarch64/Lglobal.c aarch64/Linit.c + aarch64/Linit_local.c aarch64/Linit_remote.c + aarch64/Lis_signal_frame.c aarch64/Lregs.c aarch64/Lresume.c + aarch64/Lstash_frame.c aarch64/Lstep.c aarch64/Ltrace.c + aarch64/getcontext.S +) + +SET(libunwind_aarch64_la_SOURCES_aarch64 + ${libunwind_la_SOURCES_aarch64_common} + ${libunwind_la_SOURCES_generic} + aarch64/Gapply_reg_state.c aarch64/Greg_states_iterate.c + aarch64/Gcreate_addr_space.c aarch64/Gget_proc_info.c + aarch64/Gget_save_loc.c aarch64/Gglobal.c aarch64/Ginit.c + aarch64/Ginit_local.c aarch64/Ginit_remote.c + aarch64/Gis_signal_frame.c aarch64/Gregs.c aarch64/Gresume.c + aarch64/Gstash_frame.c aarch64/Gstep.c aarch64/Gtrace.c +) + +# The list of files that go into libunwind and libunwind-arm: +SET(libunwind_la_SOURCES_arm_common + ${libunwind_la_SOURCES_common} + arm/is_fpreg.c arm/regname.c +) + +# The list of files that go into libunwind: +SET(libunwind_la_SOURCES_arm + ${libunwind_la_SOURCES_arm_common} + ${libunwind_la_SOURCES_arm_os_local} + ${libunwind_la_SOURCES_local} + arm/getcontext.S + arm/Lapply_reg_state.c arm/Lreg_states_iterate.c + arm/Lcreate_addr_space.c arm/Lget_proc_info.c arm/Lget_save_loc.c + arm/Lglobal.c arm/Linit.c arm/Linit_local.c arm/Linit_remote.c + arm/Lregs.c arm/Lresume.c arm/Lstep.c + arm/Lex_tables.c arm/Lstash_frame.c arm/Ltrace.c +) + +# The list of files that go into libunwind-arm: +SET(libunwind_arm_la_SOURCES_arm + ${libunwind_la_SOURCES_arm_common} + ${libunwind_la_SOURCES_arm_os} + ${libunwind_la_SOURCES_generic} + arm/Gapply_reg_state.c arm/Greg_states_iterate.c + arm/Gcreate_addr_space.c arm/Gget_proc_info.c arm/Gget_save_loc.c + arm/Gglobal.c arm/Ginit.c arm/Ginit_local.c arm/Ginit_remote.c + arm/Gregs.c arm/Gresume.c arm/Gstep.c + arm/Gex_tables.c arm/Gstash_frame.c arm/Gtrace.c +) + +# The list of files that go both into libunwind and libunwind-x86: +SET(libunwind_la_SOURCES_x86_common + ${libunwind_la_SOURCES_common} + x86/is_fpreg.c x86/regname.c +) + +# The list of files that go into libunwind: +SET(libunwind_la_SOURCES_x86 + ${libunwind_la_SOURCES_x86_common} + ${libunwind_la_SOURCES_x86_os_local} + ${libunwind_la_SOURCES_local} + x86/Lapply_reg_state.c x86/Lreg_states_iterate.c + x86/Lcreate_addr_space.c x86/Lget_save_loc.c x86/Lglobal.c + x86/Linit.c x86/Linit_local.c x86/Linit_remote.c + x86/Lget_proc_info.c x86/Lregs.c + x86/Lresume.c x86/Lstep.c +) + +# The list of files that go into libunwind-x86: +SET(libunwind_x86_la_SOURCES_x86 + ${libunwind_la_SOURCES_x86_common} + ${libunwind_la_SOURCES_x86_os} + ${libunwind_la_SOURCES_generic} + x86/Gapply_reg_state.c x86/Greg_states_iterate.c + x86/Gcreate_addr_space.c x86/Gget_save_loc.c x86/Gglobal.c + x86/Ginit.c x86/Ginit_local.c x86/Ginit_remote.c + x86/Gget_proc_info.c x86/Gregs.c + x86/Gresume.c x86/Gstep.c +) + +# The list of files that go both into libunwind and libunwind-x86_64: +SET(libunwind_la_SOURCES_x86_64_common + ${libunwind_la_SOURCES_common} + x86_64/is_fpreg.c x86_64/regname.c +) + +# The list of files that go into libunwind: +SET(libunwind_la_SOURCES_x86_64 + ${libunwind_la_SOURCES_x86_64_common} + ${libunwind_la_SOURCES_x86_64_os_local} + ${libunwind_la_SOURCES_local} + x86_64/setcontext.S + x86_64/Lapply_reg_state.c x86_64/Lreg_states_iterate.c + x86_64/Lcreate_addr_space.c x86_64/Lget_save_loc.c x86_64/Lglobal.c + x86_64/Linit.c x86_64/Linit_local.c x86_64/Linit_remote.c + x86_64/Lget_proc_info.c x86_64/Lregs.c x86_64/Lresume.c + x86_64/Lstash_frame.c x86_64/Lstep.c x86_64/Ltrace.c x86_64/getcontext.S +) + +# The list of files that go into libunwind-x86_64: +SET(libunwind_x86_64_la_SOURCES_x86_64 + ${libunwind_la_SOURCES_x86_64_common} + ${libunwind_la_SOURCES_x86_64_os} + ${libunwind_la_SOURCES_generic} + x86_64/Gapply_reg_state.c x86_64/Greg_states_iterate.c + x86_64/Gcreate_addr_space.c x86_64/Gget_save_loc.c x86_64/Gglobal.c + x86_64/Ginit.c x86_64/Ginit_local.c x86_64/Ginit_remote.c + x86_64/Gget_proc_info.c x86_64/Gregs.c x86_64/Gresume.c + x86_64/Gstash_frame.c x86_64/Gstep.c x86_64/Gtrace.c +) + +if(CLR_CMAKE_HOST_ARCH_ARM64) + SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_aarch64}) + SET(libunwind_remote_la_SOURCES ${libunwind_aarch64_la_SOURCES_aarch64}) + SET(libunwind_elf_la_SOURCES ${libunwind_elf64_la_SOURCES}) + list(APPEND libunwind_setjmp_la_SOURCES aarch64/siglongjmp.S) +elseif(CLR_CMAKE_HOST_ARCH_ARM) + SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_arm}) + SET(libunwind_remote_la_SOURCES ${libunwind_arm_la_SOURCES_arm}) + SET(libunwind_elf_la_SOURCES ${libunwind_elf32_la_SOURCES}) + list(APPEND libunwind_setjmp_la_SOURCES arm/siglongjmp.S) +elseif(CLR_CMAKE_HOST_ARCH_I386) + SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_x86} ${libunwind_x86_la_SOURCES_os}) + SET(libunwind_remote_la_SOURCES ${libunwind_x86_la_SOURCES_x86}) + SET(libunwind_elf_la_SOURCES ${libunwind_elf32_la_SOURCES}) + list(APPEND libunwind_setjmp_la_SOURCES x86/longjmp.S x86/siglongjmp.S) +elseif(CLR_CMAKE_HOST_ARCH_AMD64) + SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_x86_64}) + SET(libunwind_remote_la_SOURCES ${libunwind_x86_64_la_SOURCES_x86_64}) + SET(libunwind_elf_la_SOURCES ${libunwind_elf64_la_SOURCES}) + list(APPEND libunwind_setjmp_la_SOURCES x86_64/longjmp.S x86_64/siglongjmp.SA) +endif() + +add_library(libunwind + OBJECT + ${libunwind_la_SOURCES} + ${libunwind_remote_la_SOURCES} + ${libunwind_dwarf_local_la_SOURCES} + ${libunwind_dwarf_common_la_SOURCES} + ${libunwind_dwarf_generic_la_SOURCES} + ${libunwind_elf_la_SOURCES} +) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/Makefile.am b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/Makefile.am new file mode 100644 index 0000000..a557d8d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/Makefile.am @@ -0,0 +1,750 @@ +SOVERSION=8:1:0 # See comments at end of file. +SETJMP_SO_VERSION=0:0:0 +COREDUMP_SO_VERSION=0:0:0 +# +# Don't link with start-files since we don't use any constructors/destructors: +# +COMMON_SO_LDFLAGS = $(LDFLAGS_NOSTARTFILES) + +lib_LIBRARIES = +lib_LTLIBRARIES = +if !REMOTE_ONLY +lib_LTLIBRARIES += libunwind.la +if BUILD_PTRACE +lib_LTLIBRARIES += libunwind-ptrace.la +endif +if BUILD_COREDUMP +lib_LTLIBRARIES += libunwind-coredump.la +endif +endif + +noinst_HEADERS = +noinst_LTLIBRARIES = + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libunwind-generic.pc + +if !REMOTE_ONLY +pkgconfig_DATA += unwind/libunwind.pc +endif + +if BUILD_PTRACE +pkgconfig_DATA += ptrace/libunwind-ptrace.pc +endif + +if BUILD_SETJMP +pkgconfig_DATA += setjmp/libunwind-setjmp.pc +endif + +if BUILD_COREDUMP +pkgconfig_DATA += coredump/libunwind-coredump.pc +endif + +### libunwind-ptrace: +libunwind_ptrace_la_SOURCES = \ + ptrace/_UPT_elf.c \ + ptrace/_UPT_accessors.c ptrace/_UPT_access_fpreg.c \ + ptrace/_UPT_access_mem.c ptrace/_UPT_access_reg.c \ + ptrace/_UPT_create.c ptrace/_UPT_destroy.c \ + ptrace/_UPT_find_proc_info.c ptrace/_UPT_get_dyn_info_list_addr.c \ + ptrace/_UPT_put_unwind_info.c ptrace/_UPT_get_proc_name.c \ + ptrace/_UPT_reg_offset.c ptrace/_UPT_resume.c +noinst_HEADERS += ptrace/_UPT_internal.h + +### libunwind-coredump: +libunwind_coredump_la_SOURCES = \ + coredump/_UCD_accessors.c \ + coredump/_UCD_create.c \ + coredump/_UCD_destroy.c \ + coredump/_UCD_access_mem.c \ + coredump/_UCD_elf_map_image.c \ + coredump/_UCD_find_proc_info.c \ + coredump/_UCD_get_proc_name.c \ + \ + coredump/_UPT_elf.c \ + coredump/_UPT_access_fpreg.c \ + coredump/_UPT_get_dyn_info_list_addr.c \ + coredump/_UPT_put_unwind_info.c \ + coredump/_UPT_resume.c +libunwind_coredump_la_LDFLAGS = $(COMMON_SO_LDFLAGS) \ + -version-info $(COREDUMP_SO_VERSION) +libunwind_coredump_la_LIBADD = $(LIBLZMA) +noinst_HEADERS += coredump/_UCD_internal.h coredump/_UCD_lib.h + +### libunwind-setjmp: +libunwind_setjmp_la_LDFLAGS = $(COMMON_SO_LDFLAGS) \ + -version-info $(SETJMP_SO_VERSION) + +if USE_ELF32 +LIBUNWIND_ELF = libunwind-elf32.la +endif +if USE_ELF64 +LIBUNWIND_ELF = libunwind-elf64.la +endif +if USE_ELFXX +LIBUNWIND_ELF = libunwind-elfxx.la +endif + +libunwind_setjmp_la_LIBADD = $(LIBUNWIND_ELF) \ + libunwind-$(arch).la \ + libunwind.la -lc +libunwind_setjmp_la_SOURCES = setjmp/longjmp.c \ + setjmp/siglongjmp.c +noinst_HEADERS += setjmp/setjmp_i.h + +### libunwind: +libunwind_la_LIBADD = + +# List of arch-independent files needed by both local-only and generic +# libraries: +libunwind_la_SOURCES_common = \ + $(libunwind_la_SOURCES_os) \ + mi/init.c mi/flush_cache.c mi/mempool.c mi/strerror.c + +# List of arch-independent files needed by generic library (libunwind-$ARCH): +libunwind_la_SOURCES_generic = \ + mi/Gdyn-extract.c mi/Gdyn-remote.c mi/Gfind_dynamic_proc_info.c \ + mi/Gget_accessors.c \ + mi/Gget_proc_info_by_ip.c mi/Gget_proc_name.c \ + mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c \ + mi/Gget_reg.c mi/Gset_reg.c \ + mi/Gget_fpreg.c mi/Gset_fpreg.c \ + mi/Gset_caching_policy.c \ + mi/Gset_cache_size.c + +if SUPPORT_CXX_EXCEPTIONS +libunwind_la_SOURCES_local_unwind = \ + unwind/Backtrace.c unwind/DeleteException.c \ + unwind/FindEnclosingFunction.c unwind/ForcedUnwind.c \ + unwind/GetBSP.c unwind/GetCFA.c unwind/GetDataRelBase.c \ + unwind/GetGR.c unwind/GetIP.c unwind/GetLanguageSpecificData.c \ + unwind/GetRegionStart.c unwind/GetTextRelBase.c \ + unwind/RaiseException.c unwind/Resume.c \ + unwind/Resume_or_Rethrow.c unwind/SetGR.c unwind/SetIP.c \ + unwind/GetIPInfo.c + +# _ReadULEB()/_ReadSLEB() are needed for Intel C++ 8.0 compatibility +libunwind_la_SOURCES_os_linux_local = mi/_ReadULEB.c mi/_ReadSLEB.c +endif + +# List of arch-independent files needed by local-only library (libunwind): +libunwind_la_SOURCES_local_nounwind = \ + $(libunwind_la_SOURCES_os_local) \ + mi/backtrace.c \ + mi/dyn-cancel.c mi/dyn-info-list.c mi/dyn-register.c \ + mi/Ldyn-extract.c mi/Lfind_dynamic_proc_info.c \ + mi/Lget_accessors.c \ + mi/Lget_proc_info_by_ip.c mi/Lget_proc_name.c \ + mi/Lput_dynamic_unwind_info.c mi/Ldestroy_addr_space.c \ + mi/Lget_reg.c mi/Lset_reg.c \ + mi/Lget_fpreg.c mi/Lset_fpreg.c \ + mi/Lset_caching_policy.c \ + mi/Lset_cache_size.c + +libunwind_la_SOURCES_local = \ + $(libunwind_la_SOURCES_local_nounwind) \ + $(libunwind_la_SOURCES_local_unwind) + +noinst_HEADERS += os-linux.h +libunwind_la_SOURCES_os_linux = os-linux.c + +libunwind_la_SOURCES_os_hpux = os-hpux.c + +libunwind_la_SOURCES_os_freebsd = os-freebsd.c + +libunwind_la_SOURCES_os_qnx = os-qnx.c + +libunwind_dwarf_common_la_SOURCES = dwarf/global.c + +libunwind_dwarf_local_la_SOURCES = \ + dwarf/Lexpr.c dwarf/Lfde.c dwarf/Lparser.c dwarf/Lpe.c \ + dwarf/Lfind_proc_info-lsb.c \ + dwarf/Lfind_unwind_table.c +libunwind_dwarf_local_la_LIBADD = libunwind-dwarf-common.la + +libunwind_dwarf_generic_la_SOURCES = \ + dwarf/Gexpr.c dwarf/Gfde.c dwarf/Gparser.c dwarf/Gpe.c \ + dwarf/Gfind_proc_info-lsb.c \ + dwarf/Gfind_unwind_table.c +libunwind_dwarf_generic_la_LIBADD = libunwind-dwarf-common.la + +if USE_DWARF + noinst_LTLIBRARIES += libunwind-dwarf-common.la libunwind-dwarf-generic.la +if !REMOTE_ONLY + noinst_LTLIBRARIES += libunwind-dwarf-local.la +endif + libunwind_la_LIBADD += libunwind-dwarf-local.la +endif + +noinst_HEADERS += elf32.h elf64.h elfxx.h + +libunwind_elf32_la_SOURCES = elf32.c +libunwind_elf64_la_SOURCES = elf64.c +libunwind_elfxx_la_SOURCES = elfxx.c +libunwind_elf32_la_LIBADD = $(LIBLZMA) +libunwind_elf64_la_LIBADD = $(LIBLZMA) +libunwind_elfxx_la_LIBADD = $(LIBLZMA) + +noinst_LTLIBRARIES += $(LIBUNWIND_ELF) +libunwind_la_LIBADD += $(LIBUNWIND_ELF) + +# The list of files that go into libunwind and libunwind-aarch64: +noinst_HEADERS += aarch64/init.h aarch64/offsets.h aarch64/unwind_i.h +libunwind_la_SOURCES_aarch64_common = $(libunwind_la_SOURCES_common) \ + aarch64/is_fpreg.c aarch64/regname.c + +# The list of files that go into libunwind: +libunwind_la_SOURCES_aarch64 = $(libunwind_la_SOURCES_aarch64_common) \ + $(libunwind_la_SOURCES_local) \ + aarch64/Lapply_reg_state.c aarch64/Lreg_states_iterate.c \ + aarch64/Lcreate_addr_space.c aarch64/Lget_proc_info.c \ + aarch64/Lget_save_loc.c aarch64/Lglobal.c aarch64/Linit.c \ + aarch64/Linit_local.c aarch64/Linit_remote.c \ + aarch64/Lis_signal_frame.c aarch64/Lregs.c aarch64/Lresume.c \ + aarch64/Lstash_frame.c aarch64/Lstep.c aarch64/Ltrace.c \ + aarch64/getcontext.S + +libunwind_aarch64_la_SOURCES_aarch64 = $(libunwind_la_SOURCES_aarch64_common) \ + $(libunwind_la_SOURCES_generic) \ + aarch64/Gapply_reg_state.c aarch64/Greg_states_iterate.c \ + aarch64/Gcreate_addr_space.c aarch64/Gget_proc_info.c \ + aarch64/Gget_save_loc.c aarch64/Gglobal.c aarch64/Ginit.c \ + aarch64/Ginit_local.c aarch64/Ginit_remote.c \ + aarch64/Gis_signal_frame.c aarch64/Gregs.c aarch64/Gresume.c \ + aarch64/Gstash_frame.c aarch64/Gstep.c aarch64/Gtrace.c + +# The list of files that go into libunwind and libunwind-arm: +noinst_HEADERS += arm/init.h arm/offsets.h arm/unwind_i.h +libunwind_la_SOURCES_arm_common = $(libunwind_la_SOURCES_common) \ + arm/is_fpreg.c arm/regname.c + +# The list of files that go into libunwind: +libunwind_la_SOURCES_arm = $(libunwind_la_SOURCES_arm_common) \ + $(libunwind_la_SOURCES_arm_os_local) \ + $(libunwind_la_SOURCES_local) \ + arm/getcontext.S \ + arm/Lapply_reg_state.c arm/Lreg_states_iterate.c \ + arm/Lcreate_addr_space.c arm/Lget_proc_info.c arm/Lget_save_loc.c \ + arm/Lglobal.c arm/Linit.c arm/Linit_local.c arm/Linit_remote.c \ + arm/Lregs.c arm/Lresume.c arm/Lstep.c \ + arm/Lex_tables.c arm/Lstash_frame.c arm/Ltrace.c + +# The list of files that go into libunwind-arm: +libunwind_arm_la_SOURCES_arm = $(libunwind_la_SOURCES_arm_common) \ + $(libunwind_la_SOURCES_arm_os) \ + $(libunwind_la_SOURCES_generic) \ + arm/Gapply_reg_state.c arm/Greg_states_iterate.c \ + arm/Gcreate_addr_space.c arm/Gget_proc_info.c arm/Gget_save_loc.c \ + arm/Gglobal.c arm/Ginit.c arm/Ginit_local.c arm/Ginit_remote.c \ + arm/Gregs.c arm/Gresume.c arm/Gstep.c \ + arm/Gex_tables.c arm/Gstash_frame.c arm/Gtrace.c + +# The list of files that go both into libunwind and libunwind-ia64: +noinst_HEADERS += ia64/init.h ia64/offsets.h ia64/regs.h \ + ia64/ucontext_i.h ia64/unwind_decoder.h ia64/unwind_i.h +libunwind_la_SOURCES_ia64_common = $(libunwind_la_SOURCES_common) \ + ia64/regname.c + +# The list of files that go into libunwind: +libunwind_la_SOURCES_ia64 = $(libunwind_la_SOURCES_ia64_common) \ + $(libunwind_la_SOURCES_local) \ + \ + ia64/dyn_info_list.S ia64/getcontext.S \ + \ + ia64/Lapply_reg_state.c ia64/Lreg_states_iterate.c \ + ia64/Lcreate_addr_space.c ia64/Lget_proc_info.c ia64/Lget_save_loc.c \ + ia64/Lglobal.c ia64/Linit.c ia64/Linit_local.c ia64/Linit_remote.c \ + ia64/Linstall_cursor.S ia64/Lis_signal_frame.c ia64/Lparser.c \ + ia64/Lrbs.c ia64/Lregs.c ia64/Lresume.c ia64/Lscript.c ia64/Lstep.c \ + ia64/Ltables.c ia64/Lfind_unwind_table.c + +# The list of files that go into libunwind-ia64: +libunwind_ia64_la_SOURCES_ia64 = $(libunwind_la_SOURCES_ia64_common) \ + $(libunwind_la_SOURCES_generic) \ + ia64/Gapply_reg_state.c ia64/Greg_states_iterate.c \ + ia64/Gcreate_addr_space.c ia64/Gget_proc_info.c ia64/Gget_save_loc.c \ + ia64/Gglobal.c ia64/Ginit.c ia64/Ginit_local.c ia64/Ginit_remote.c \ + ia64/Ginstall_cursor.S ia64/Gis_signal_frame.c ia64/Gparser.c \ + ia64/Grbs.c ia64/Gregs.c ia64/Gresume.c ia64/Gscript.c ia64/Gstep.c \ + ia64/Gtables.c ia64/Gfind_unwind_table.c + +# The list of files that go both into libunwind and libunwind-hppa: +noinst_HEADERS += hppa/init.h hppa/offsets.h hppa/unwind_i.h +libunwind_la_SOURCES_hppa_common = $(libunwind_la_SOURCES_common) \ + hppa/regname.c + +# The list of files that go into libunwind: +libunwind_la_SOURCES_hppa = $(libunwind_la_SOURCES_hppa_common) \ + $(libunwind_la_SOURCES_local) \ + hppa/getcontext.S hppa/setcontext.S \ + hppa/Lapply_reg_state.c hppa/Lreg_states_iterate.c \ + hppa/Lcreate_addr_space.c hppa/Lget_save_loc.c hppa/Lglobal.c \ + hppa/Linit.c hppa/Linit_local.c hppa/Linit_remote.c \ + hppa/Lis_signal_frame.c hppa/Lget_proc_info.c hppa/Lregs.c \ + hppa/Lresume.c hppa/Lstep.c + +# The list of files that go into libunwind-hppa: +libunwind_hppa_la_SOURCES_hppa = $(libunwind_la_SOURCES_hppa_common) \ + $(libunwind_la_SOURCES_generic) \ + hppa/Gapply_reg_state.c hppa/Greg_states_iterate.c \ + hppa/Gcreate_addr_space.c hppa/Gget_save_loc.c hppa/Gglobal.c \ + hppa/Ginit.c hppa/Ginit_local.c hppa/Ginit_remote.c \ + hppa/Gis_signal_frame.c hppa/Gget_proc_info.c hppa/Gregs.c \ + hppa/Gresume.c hppa/Gstep.c + +# The list of files that go info libunwind and libunwind-mips: +noinst_HEADERS += mips/init.h mips/offsets.h mips/unwind_i.h +libunwind_la_SOURCES_mips_common = $(libunwind_la_SOURCES_common) \ + mips/is_fpreg.c mips/regname.c + +# The list of files that go into libunwind: +libunwind_la_SOURCES_mips = $(libunwind_la_SOURCES_mips_common) \ + $(libunwind_la_SOURCES_local) \ + mips/getcontext.S \ + mips/Lapply_reg_state.c mips/Lreg_states_iterate.c \ + mips/Lcreate_addr_space.c mips/Lget_proc_info.c mips/Lget_save_loc.c \ + mips/Lglobal.c mips/Linit.c mips/Linit_local.c mips/Linit_remote.c \ + mips/Lis_signal_frame.c mips/Lregs.c mips/Lresume.c mips/Lstep.c + +libunwind_mips_la_SOURCES_mips = $(libunwind_la_SOURCES_mips_common) \ + $(libunwind_la_SOURCES_generic) \ + mips/Gapply_reg_state.c mips/Greg_states_iterate.c \ + mips/Gcreate_addr_space.c mips/Gget_proc_info.c mips/Gget_save_loc.c \ + mips/Gglobal.c mips/Ginit.c mips/Ginit_local.c mips/Ginit_remote.c \ + mips/Gis_signal_frame.c mips/Gregs.c mips/Gresume.c mips/Gstep.c + +# The list of files that go info libunwind and libunwind-tilegx: +noinst_HEADERS += tilegx/init.h tilegx/offsets.h tilegx/unwind_i.h +libunwind_la_SOURCES_tilegx_common = $(libunwind_la_SOURCES_common) \ + tilegx/is_fpreg.c tilegx/regname.c + +# The list of files that go into libunwind: +libunwind_la_SOURCES_tilegx = $(libunwind_la_SOURCES_tilegx_common) \ + $(libunwind_la_SOURCES_local) \ + tilegx/getcontext.S \ + tilegx/Lapply_reg_state.c tilegx/Lreg_states_iterate.c \ + tilegx/Lcreate_addr_space.c tilegx/Lget_proc_info.c tilegx/Lget_save_loc.c \ + tilegx/Lglobal.c tilegx/Linit.c tilegx/Linit_local.c tilegx/Linit_remote.c \ + tilegx/Lis_signal_frame.c tilegx/Lregs.c tilegx/Lresume.c tilegx/Lstep.c + +libunwind_tilegx_la_SOURCES_tilegx = $(libunwind_la_SOURCES_tilegx_common) \ + $(libunwind_la_SOURCES_generic) \ + tilegx/Gapply_reg_state.c tilegx/Greg_states_iterate.c \ + tilegx/Gcreate_addr_space.c tilegx/Gget_proc_info.c tilegx/Gget_save_loc.c \ + tilegx/Gglobal.c tilegx/Ginit.c tilegx/Ginit_local.c tilegx/Ginit_remote.c \ + tilegx/Gis_signal_frame.c tilegx/Gregs.c tilegx/Gresume.c tilegx/Gstep.c + + +# The list of files that go both into libunwind and libunwind-x86: +noinst_HEADERS += x86/init.h x86/offsets.h x86/unwind_i.h +libunwind_la_SOURCES_x86_common = $(libunwind_la_SOURCES_common) \ + x86/is_fpreg.c x86/regname.c + +# The list of files that go into libunwind: +libunwind_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ + $(libunwind_la_SOURCES_x86_os_local) \ + $(libunwind_la_SOURCES_local) \ + x86/Lapply_reg_state.c x86/Lreg_states_iterate.c \ + x86/Lcreate_addr_space.c x86/Lget_save_loc.c x86/Lglobal.c \ + x86/Linit.c x86/Linit_local.c x86/Linit_remote.c \ + x86/Lget_proc_info.c x86/Lregs.c \ + x86/Lresume.c x86/Lstep.c + +# The list of files that go into libunwind-x86: +libunwind_x86_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ + $(libunwind_la_SOURCES_x86_os) \ + $(libunwind_la_SOURCES_generic) \ + x86/Gapply_reg_state.c x86/Greg_states_iterate.c \ + x86/Gcreate_addr_space.c x86/Gget_save_loc.c x86/Gglobal.c \ + x86/Ginit.c x86/Ginit_local.c x86/Ginit_remote.c \ + x86/Gget_proc_info.c x86/Gregs.c \ + x86/Gresume.c x86/Gstep.c + +# The list of files that go both into libunwind and libunwind-x86_64: +noinst_HEADERS += x86_64/offsets.h \ + x86_64/init.h x86_64/unwind_i.h x86_64/ucontext_i.h +libunwind_la_SOURCES_x86_64_common = $(libunwind_la_SOURCES_common) \ + x86_64/is_fpreg.c x86_64/regname.c + +# The list of files that go into libunwind: +libunwind_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \ + $(libunwind_la_SOURCES_x86_64_os_local) \ + $(libunwind_la_SOURCES_local) \ + x86_64/setcontext.S \ + x86_64/Lapply_reg_state.c x86_64/Lreg_states_iterate.c \ + x86_64/Lcreate_addr_space.c x86_64/Lget_save_loc.c x86_64/Lglobal.c \ + x86_64/Linit.c x86_64/Linit_local.c x86_64/Linit_remote.c \ + x86_64/Lget_proc_info.c x86_64/Lregs.c x86_64/Lresume.c \ + x86_64/Lstash_frame.c x86_64/Lstep.c x86_64/Ltrace.c x86_64/getcontext.S + +# The list of files that go into libunwind-x86_64: +libunwind_x86_64_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \ + $(libunwind_la_SOURCES_x86_64_os) \ + $(libunwind_la_SOURCES_generic) \ + x86_64/Gapply_reg_state.c x86_64/Greg_states_iterate.c \ + x86_64/Gcreate_addr_space.c x86_64/Gget_save_loc.c x86_64/Gglobal.c \ + x86_64/Ginit.c x86_64/Ginit_local.c x86_64/Ginit_remote.c \ + x86_64/Gget_proc_info.c x86_64/Gregs.c x86_64/Gresume.c \ + x86_64/Gstash_frame.c x86_64/Gstep.c x86_64/Gtrace.c + +# The list of local files that go to Power 64 and 32: +libunwind_la_SOURCES_ppc = \ + ppc/Lget_proc_info.c ppc/Lget_save_loc.c ppc/Linit_local.c \ + ppc/Linit_remote.c ppc/Lis_signal_frame.c + +# The list of generic files that go to Power 64 and 32: +libunwind_ppc_la_SOURCES_ppc_generic = \ + ppc/Gget_proc_info.c ppc/Gget_save_loc.c ppc/Ginit_local.c \ + ppc/Ginit_remote.c ppc/Gis_signal_frame.c + +# The list of files that go both into libunwind and libunwind-ppc32: +noinst_HEADERS += ppc32/init.h ppc32/unwind_i.h ppc32/ucontext_i.h +libunwind_la_SOURCES_ppc32_common = $(libunwind_la_SOURCES_common) \ + ppc32/is_fpreg.c ppc32/regname.c ppc32/get_func_addr.c + +# The list of files that go into libunwind: +libunwind_la_SOURCES_ppc32 = $(libunwind_la_SOURCES_ppc32_common) \ + $(libunwind_la_SOURCES_local) \ + $(libunwind_la_SOURCES_ppc) \ + ppc32/Lapply_reg_state.c ppc32/Lreg_states_iterate.c \ + ppc32/Lcreate_addr_space.c \ + ppc32/Lglobal.c ppc32/Linit.c \ + ppc32/Lregs.c ppc32/Lresume.c ppc32/Lstep.c + +# The list of files that go into libunwind-ppc32: +libunwind_ppc32_la_SOURCES_ppc32 = $(libunwind_la_SOURCES_ppc32_common) \ + $(libunwind_la_SOURCES_generic) \ + $(libunwind_ppc_la_SOURCES_ppc_generic) \ + ppc32/Gapply_reg_state.c ppc32/Greg_states_iterate.c \ + ppc32/Gcreate_addr_space.c \ + ppc32/Gglobal.c ppc32/Ginit.c \ + ppc32/Gregs.c ppc32/Gresume.c ppc32/Gstep.c + +# The list of files that go both into libunwind and libunwind-ppc64: +noinst_HEADERS += ppc64/init.h ppc64/unwind_i.h ppc64/ucontext_i.h +libunwind_la_SOURCES_ppc64_common = $(libunwind_la_SOURCES_common) \ + ppc64/is_fpreg.c ppc64/regname.c ppc64/get_func_addr.c + +# The list of files that go into libunwind: +libunwind_la_SOURCES_ppc64 = $(libunwind_la_SOURCES_ppc64_common) \ + $(libunwind_la_SOURCES_local) \ + $(libunwind_la_SOURCES_ppc) \ + ppc64/Lapply_reg_state.c ppc64/Lreg_states_iterate.c \ + ppc64/Lcreate_addr_space.c \ + ppc64/Lglobal.c ppc64/Linit.c \ + ppc64/Lregs.c ppc64/Lresume.c ppc64/Lstep.c + +# The list of files that go into libunwind-ppc64: +libunwind_ppc64_la_SOURCES_ppc64 = $(libunwind_la_SOURCES_ppc64_common) \ + $(libunwind_la_SOURCES_generic) \ + $(libunwind_ppc_la_SOURCES_ppc_generic) \ + ppc64/Gapply_reg_state.c ppc64/Greg_states_iterate.c \ + ppc64/Gcreate_addr_space.c \ + ppc64/Gglobal.c ppc64/Ginit.c \ + ppc64/Gregs.c ppc64/Gresume.c ppc64/Gstep.c + +# The list of files that go into libunwind and libunwind-sh: +noinst_HEADERS += sh/init.h sh/offsets.h sh/unwind_i.h +libunwind_la_SOURCES_sh_common = $(libunwind_la_SOURCES_common) \ + sh/is_fpreg.c sh/regname.c + +# The list of files that go into libunwind: +libunwind_la_SOURCES_sh = $(libunwind_la_SOURCES_sh_common) \ + $(libunwind_la_SOURCES_local) \ + sh/Lapply_reg_state.c sh/Lreg_states_iterate.c \ + sh/Lcreate_addr_space.c sh/Lget_proc_info.c sh/Lget_save_loc.c \ + sh/Lglobal.c sh/Linit.c sh/Linit_local.c sh/Linit_remote.c \ + sh/Lis_signal_frame.c sh/Lregs.c sh/Lresume.c sh/Lstep.c + +libunwind_sh_la_SOURCES_sh = $(libunwind_la_SOURCES_sh_common) \ + $(libunwind_la_SOURCES_generic) \ + sh/Gapply_reg_state.c sh/Greg_states_iterate.c \ + sh/Gcreate_addr_space.c sh/Gget_proc_info.c sh/Gget_save_loc.c \ + sh/Gglobal.c sh/Ginit.c sh/Ginit_local.c sh/Ginit_remote.c \ + sh/Gis_signal_frame.c sh/Gregs.c sh/Gresume.c sh/Gstep.c + +if REMOTE_ONLY +install-exec-hook: +# Nothing to do here.... +else +# +# This is not ideal, but I know of no other way to install an +# alias for a library. For the shared version, we have to do +# a file check before creating the link, because it isn't going +# to be there if the user configured with --disable-shared. +# +install-exec-hook: + if test -f $(DESTDIR)$(libdir)/libunwind-$(arch).a; then \ + cd $(DESTDIR)$(libdir) && $(LN_S) -f libunwind-$(arch).a libunwind-generic.a; \ + fi + if test -f $(DESTDIR)$(libdir)/libunwind-$(arch).so; then \ + cd $(DESTDIR)$(libdir) && $(LN_S) -f libunwind-$(arch).so \ + libunwind-generic.so; \ + fi +endif + +if OS_LINUX + libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_linux) + libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_linux_local) + libunwind_la_SOURCES_x86_os = x86/Gos-linux.c + libunwind_x86_la_SOURCES_os = x86/getcontext-linux.S + libunwind_la_SOURCES_x86_os_local = x86/Los-linux.c + libunwind_la_SOURCES_x86_64_os = x86_64/Gos-linux.c + libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-linux.c + libunwind_la_SOURCES_arm_os = arm/Gos-linux.c + libunwind_la_SOURCES_arm_os_local = arm/Los-linux.c + libunwind_coredump_la_SOURCES += coredump/_UCD_access_reg_linux.c +endif + +if OS_HPUX + libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_hpux) + libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_hpux_local) +endif + +if OS_FREEBSD + libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_freebsd) + libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_freebsd_local) + libunwind_la_SOURCES_x86_os = x86/Gos-freebsd.c + libunwind_x86_la_SOURCES_os = x86/getcontext-freebsd.S + libunwind_la_SOURCES_x86_os_local = x86/Los-freebsd.c + libunwind_la_SOURCES_x86_64_os = x86_64/Gos-freebsd.c + libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-freebsd.c + libunwind_la_SOURCES_arm_os = arm/Gos-freebsd.c + libunwind_la_SOURCES_arm_os_local = arm/Los-freebsd.c + libunwind_coredump_la_SOURCES += coredump/_UCD_access_reg_freebsd.c +endif + +if OS_QNX + libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_qnx) + libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_qnx_local) + libunwind_la_SOURCES_arm_os = arm/Gos-other.c + libunwind_la_SOURCES_arm_os_local = arm/Los-other.c +endif + +if ARCH_AARCH64 + lib_LTLIBRARIES += libunwind-aarch64.la + libunwind_la_SOURCES = $(libunwind_la_SOURCES_aarch64) + libunwind_aarch64_la_SOURCES = $(libunwind_aarch64_la_SOURCES_aarch64) + libunwind_aarch64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) + libunwind_aarch64_la_LIBADD = libunwind-dwarf-generic.la + libunwind_aarch64_la_LIBADD += libunwind-elf64.la +if !REMOTE_ONLY + libunwind_aarch64_la_LIBADD += libunwind.la -lc +endif + libunwind_setjmp_la_SOURCES += aarch64/siglongjmp.S +else +if ARCH_ARM + lib_LTLIBRARIES += libunwind-arm.la + libunwind_la_SOURCES = $(libunwind_la_SOURCES_arm) + libunwind_arm_la_SOURCES = $(libunwind_arm_la_SOURCES_arm) + libunwind_arm_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) + libunwind_arm_la_LIBADD = libunwind-dwarf-generic.la + libunwind_arm_la_LIBADD += libunwind-elf32.la +if !REMOTE_ONLY + libunwind_arm_la_LIBADD += libunwind.la -lc +endif + libunwind_setjmp_la_SOURCES += arm/siglongjmp.S +else +if ARCH_IA64 + BUILT_SOURCES = Gcursor_i.h Lcursor_i.h +mk_Gcursor_i.s: $(srcdir)/ia64/mk_Gcursor_i.c + $(COMPILE) -S "$(srcdir)/ia64/mk_Gcursor_i.c" -o mk_Gcursor_i.s +mk_Lcursor_i.s: $(srcdir)/ia64/mk_Lcursor_i.c + $(COMPILE) -S "$(srcdir)/ia64/mk_Lcursor_i.c" -o mk_Lcursor_i.s +Gcursor_i.h: mk_Gcursor_i.s + "$(srcdir)/ia64/mk_cursor_i" mk_Gcursor_i.s > Gcursor_i.h +Lcursor_i.h: mk_Lcursor_i.s + "$(srcdir)/ia64/mk_cursor_i" mk_Lcursor_i.s > Lcursor_i.h + + lib_LTLIBRARIES += libunwind-ia64.la + libunwind_la_SOURCES = $(libunwind_la_SOURCES_ia64) + libunwind_ia64_la_SOURCES = $(libunwind_ia64_la_SOURCES_ia64) + libunwind_ia64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) + libunwind_ia64_la_LIBADD = libunwind-elf64.la +if !REMOTE_ONLY + libunwind_ia64_la_LIBADD += libunwind.la -lc +endif + libunwind_setjmp_la_SOURCES += ia64/setjmp.S ia64/sigsetjmp.S \ + ia64/longjmp.S ia64/siglongjmp.S +else +if ARCH_HPPA + lib_LTLIBRARIES += libunwind-hppa.la + libunwind_la_SOURCES = $(libunwind_la_SOURCES_hppa) + libunwind_hppa_la_SOURCES = $(libunwind_hppa_la_SOURCES_hppa) + libunwind_hppa_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) + libunwind_hppa_la_LIBADD = libunwind-dwarf-generic.la + libunwind_hppa_la_LIBADD += libunwind-elf32.la +if !REMOTE_ONLY + libunwind_hppa_la_LIBADD += libunwind.la -lc +endif + libunwind_setjmp_la_SOURCES += hppa/siglongjmp.S +else +if ARCH_MIPS + lib_LTLIBRARIES += libunwind-mips.la + libunwind_la_SOURCES = $(libunwind_la_SOURCES_mips) + libunwind_mips_la_SOURCES = $(libunwind_mips_la_SOURCES_mips) + libunwind_mips_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) + libunwind_mips_la_LIBADD = libunwind-dwarf-generic.la + libunwind_mips_la_LIBADD += libunwind-elfxx.la +if !REMOTE_ONLY + libunwind_mips_la_LIBADD += libunwind.la -lc +endif + libunwind_setjmp_la_SOURCES += mips/siglongjmp.S +else +if ARCH_TILEGX + lib_LTLIBRARIES += libunwind-tilegx.la + libunwind_la_SOURCES = $(libunwind_la_SOURCES_tilegx) + libunwind_tilegx_la_SOURCES = $(libunwind_tilegx_la_SOURCES_tilegx) + libunwind_tilegx_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) + libunwind_tilegx_la_LIBADD = libunwind-dwarf-generic.la + libunwind_tilegx_la_LIBADD += libunwind-elfxx.la +if !REMOTE_ONLY + libunwind_tilegx_la_LIBADD += libunwind.la -lc +endif + libunwind_setjmp_la_SOURCES += tilegx/siglongjmp.S +else +if ARCH_X86 + lib_LTLIBRARIES += libunwind-x86.la + libunwind_la_SOURCES = $(libunwind_la_SOURCES_x86) $(libunwind_x86_la_SOURCES_os) + libunwind_x86_la_SOURCES = $(libunwind_x86_la_SOURCES_x86) + libunwind_x86_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) + libunwind_x86_la_LIBADD = libunwind-dwarf-generic.la + libunwind_x86_la_LIBADD += libunwind-elf32.la +if !REMOTE_ONLY + libunwind_x86_la_LIBADD += libunwind.la -lc +endif + libunwind_setjmp_la_SOURCES += x86/longjmp.S x86/siglongjmp.S +else +if ARCH_X86_64 + lib_LTLIBRARIES += libunwind-x86_64.la + libunwind_la_SOURCES = $(libunwind_la_SOURCES_x86_64) + libunwind_x86_64_la_SOURCES = $(libunwind_x86_64_la_SOURCES_x86_64) + libunwind_x86_64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) + libunwind_x86_64_la_LIBADD = libunwind-dwarf-generic.la + libunwind_x86_64_la_LIBADD += libunwind-elf64.la +if !REMOTE_ONLY + libunwind_x86_64_la_LIBADD += libunwind.la -lc +endif + libunwind_setjmp_la_SOURCES += x86_64/longjmp.S x86_64/siglongjmp.S +else +if ARCH_PPC32 + lib_LTLIBRARIES += libunwind-ppc32.la + libunwind_la_SOURCES = $(libunwind_la_SOURCES_ppc32) + libunwind_ppc32_la_SOURCES = $(libunwind_ppc32_la_SOURCES_ppc32) + libunwind_ppc32_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) + libunwind_ppc32_la_LIBADD = libunwind-dwarf-generic.la + libunwind_ppc32_la_LIBADD += libunwind-elf32.la +if !REMOTE_ONLY + libunwind_ppc32_la_LIBADD += libunwind.la -lc +endif + libunwind_setjmp_la_SOURCES += ppc/longjmp.S ppc/siglongjmp.S +else +if ARCH_PPC64 + lib_LTLIBRARIES += libunwind-ppc64.la + libunwind_la_SOURCES = $(libunwind_la_SOURCES_ppc64) + libunwind_ppc64_la_SOURCES = $(libunwind_ppc64_la_SOURCES_ppc64) + libunwind_ppc64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) + libunwind_ppc64_la_LIBADD = libunwind-dwarf-generic.la + libunwind_ppc64_la_LIBADD += libunwind-elf64.la +if !REMOTE_ONLY + libunwind_ppc64_la_LIBADD += libunwind.la -lc +endif + libunwind_setjmp_la_SOURCES += ppc/longjmp.S ppc/siglongjmp.S +else +if ARCH_SH + lib_LTLIBRARIES += libunwind-sh.la + libunwind_la_SOURCES = $(libunwind_la_SOURCES_sh) + libunwind_sh_la_SOURCES = $(libunwind_sh_la_SOURCES_sh) + libunwind_sh_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) + libunwind_sh_la_LIBADD = libunwind-dwarf-generic.la + libunwind_sh_la_LIBADD += libunwind-elf32.la +if !REMOTE_ONLY + libunwind_sh_la_LIBADD += libunwind.la -lc +endif + libunwind_setjmp_la_SOURCES += sh/siglongjmp.S + +endif # ARCH_SH +endif # ARCH_PPC64 +endif # ARCH_PPC32 +endif # ARCH_X86_64 +endif # ARCH_X86 +endif # ARCH_TILEGX +endif # ARCH_MIPS +endif # ARCH_HPPA +endif # ARCH_IA64 +endif # ARCH_ARM +endif # ARCH_AARCH64 + +# libunwind-setjmp depends on libunwind-$(arch). Therefore must be added +# at the end. +if BUILD_SETJMP +lib_LTLIBRARIES += libunwind-setjmp.la +endif + +# +# Don't link with standard libraries, because those may mention +# libunwind already. +# +libunwind_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -XCClinker -nostdlib \ + $(LDFLAGS_STATIC_LIBCXA) -version-info $(SOVERSION) +libunwind_la_LIBADD += -lc $(LIBCRTS) +libunwind_la_LIBADD += $(LIBLZMA) + +AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/tdep-$(arch) -I. +AM_CCASFLAGS = $(AM_CPPFLAGS) +noinst_HEADERS += unwind/unwind-internal.h + +EXTRA_DIST = $(libunwind_la_SOURCES_aarch64) \ + $(libunwind_la_SOURCES_arm) \ + $(libunwind_la_SOURCES_hppa) \ + $(libunwind_la_SOURCES_ia64) \ + $(libunwind_la_SOURCES_mips) \ + $(libunwind_la_SOURCES_sh) \ + $(libunwind_la_SOURCES_x86) \ + $(libunwind_la_SOURCES_os_freebsd) \ + $(libunwind_la_SOURCES_os_linux) \ + $(libunwind_la_SOURCES_os_hpux) \ + $(libunwind_la_SOURCES_os_qnx) \ + $(libunwind_la_SOURCES_common) \ + $(libunwind_la_SOURCES_local) \ + $(libunwind_la_SOURCES_generic) \ + $(libunwind_aarch64_la_SOURCES_aarch64) \ + $(libunwind_arm_la_SOURCES_arm) \ + $(libunwind_hppa_la_SOURCES_hppa) \ + $(libunwind_ia64_la_SOURCES_ia64) \ + $(libunwind_mips_la_SOURCES_mips) \ + $(libunwind_sh_la_SOURCES_sh) \ + $(libunwind_x86_la_SOURCES_x86) \ + $(libunwind_x86_64_la_SOURCES_x86_64) + +MAINTAINERCLEANFILES = Makefile.in + +# The -version-info flag accepts an argument of the form +# `current[:revision[:age]]'. So, passing `-version-info 3:12:1' sets +# current to 3, revision to 12, and age to 1. + +# If either revision or age are omitted, they default to 0. Also note +# that age must be less than or equal to the current interface number. + +# Here are a set of rules to help you update your library version +# information: + +# 1. Start with version information of `0:0:0' for each libtool +# library. + +# 2. Update the version information only immediately before a public +# release of your software. More frequent updates are unnecessary, +# and only guarantee that the current interface number gets larger +# faster. + +# 3. If the library source code has changed at all since the last +# update, then increment revision (`c:r:a' becomes `c:r+1:a'). + +# 4. If any interfaces have been added, removed, or changed since the +# last update, increment current, and set revision to 0. + +# 5. If any interfaces have been added since the last public release, +# then increment age. + +# 6. If any interfaces have been removed since the last public +# release, then set age to 0. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gapply_reg_state.c new file mode 100644 index 0000000..82f056d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gapply_reg_state.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_apply_reg_state (unw_cursor_t *cursor, + void *reg_states_data) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gcreate_addr_space.c new file mode 100644 index 0000000..f217adc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gcreate_addr_space.c @@ -0,0 +1,60 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2012 Tommi Rantala + Copyright (C) 2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#include "unwind_i.h" + +unw_addr_space_t +unw_create_addr_space (unw_accessors_t *a, int byte_order) +{ +#ifdef UNW_LOCAL_ONLY + return NULL; +#else + unw_addr_space_t as; + + /* AArch64 supports little-endian and big-endian. */ + if (byte_order != 0 && byte_order != __LITTLE_ENDIAN + && byte_order != __BIG_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); + if (!as) + return NULL; + + memset (as, 0, sizeof (*as)); + + as->acc = *a; + + /* Default to little-endian for AArch64. */ + if (byte_order == 0 || byte_order == __LITTLE_ENDIAN) + as->big_endian = 0; + else + as->big_endian = 1; + + return as; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gget_proc_info.c new file mode 100644 index 0000000..c363d24 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gget_proc_info.c @@ -0,0 +1,39 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + ret = dwarf_make_proc_info (&c->dwarf); + if (ret < 0) + return ret; + + *pi = c->dwarf.pi; + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gget_save_loc.c new file mode 100644 index 0000000..86bbbd0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gget_save_loc.c @@ -0,0 +1,100 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + Copyright (C) 2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) +{ + struct cursor *c = (struct cursor *) cursor; + dwarf_loc_t loc; + + switch (reg) + { + case UNW_AARCH64_X0: + case UNW_AARCH64_X1: + case UNW_AARCH64_X2: + case UNW_AARCH64_X3: + case UNW_AARCH64_X4: + case UNW_AARCH64_X5: + case UNW_AARCH64_X6: + case UNW_AARCH64_X7: + case UNW_AARCH64_X8: + case UNW_AARCH64_X9: + case UNW_AARCH64_X10: + case UNW_AARCH64_X11: + case UNW_AARCH64_X12: + case UNW_AARCH64_X13: + case UNW_AARCH64_X14: + case UNW_AARCH64_X15: + case UNW_AARCH64_X16: + case UNW_AARCH64_X17: + case UNW_AARCH64_X18: + case UNW_AARCH64_X19: + case UNW_AARCH64_X20: + case UNW_AARCH64_X21: + case UNW_AARCH64_X22: + case UNW_AARCH64_X23: + case UNW_AARCH64_X24: + case UNW_AARCH64_X25: + case UNW_AARCH64_X26: + case UNW_AARCH64_X27: + case UNW_AARCH64_X28: + case UNW_AARCH64_X29: + case UNW_AARCH64_X30: + case UNW_AARCH64_SP: + case UNW_AARCH64_PC: + case UNW_AARCH64_PSTATE: + loc = c->dwarf.loc[reg]; + break; + + default: + loc = DWARF_NULL_LOC; /* default to "not saved" */ + break; + } + + memset (sloc, 0, sizeof (*sloc)); + + if (DWARF_IS_NULL_LOC (loc)) + { + sloc->type = UNW_SLT_NONE; + return 0; + } + +#if !defined(UNW_LOCAL_ONLY) + if (DWARF_IS_REG_LOC (loc)) + { + sloc->type = UNW_SLT_REG; + sloc->u.regnum = DWARF_GET_LOC (loc); + } + else +#endif + { + sloc->type = UNW_SLT_MEMORY; + sloc->u.addr = DWARF_GET_LOC (loc); + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gglobal.c new file mode 100644 index 0000000..72e36b2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gglobal.c @@ -0,0 +1,57 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + Copyright (C) 2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "dwarf_i.h" + +HIDDEN define_lock (aarch64_lock); +HIDDEN int tdep_init_done; + +HIDDEN void +tdep_init (void) +{ + intrmask_t saved_mask; + + sigfillset (&unwi_full_mask); + + lock_acquire (&aarch64_lock, saved_mask); + { + if (tdep_init_done) + /* another thread else beat us to it... */ + goto out; + + mi_init (); + + dwarf_init (); + +#ifndef UNW_REMOTE_ONLY + aarch64_local_addr_space_init (); +#endif + tdep_init_done = 1; /* signal that we're initialized... */ + } + out: + lock_release (&aarch64_lock, saved_mask); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ginit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ginit.c new file mode 100644 index 0000000..9c4eae8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ginit.c @@ -0,0 +1,190 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + Copyright (C) 2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#include "unwind_i.h" + +#ifdef UNW_REMOTE_ONLY + +/* unw_local_addr_space is a NULL pointer in this case. */ +unw_addr_space_t unw_local_addr_space; + +#else /* !UNW_REMOTE_ONLY */ + +static struct unw_addr_space local_addr_space; + +unw_addr_space_t unw_local_addr_space = &local_addr_space; + +static inline void * +uc_addr (ucontext_t *uc, int reg) +{ + if (reg >= UNW_AARCH64_X0 && reg < UNW_AARCH64_V0) + return &uc->uc_mcontext.regs[reg]; + else if (reg >= UNW_AARCH64_V0 && reg <= UNW_AARCH64_V31) + return &GET_FPCTX(uc)->vregs[reg - UNW_AARCH64_V0]; + else + return NULL; +} + +# ifdef UNW_LOCAL_ONLY + +HIDDEN void * +tdep_uc_addr (ucontext_t *uc, int reg) +{ + return uc_addr (uc, reg); +} + +# endif /* UNW_LOCAL_ONLY */ + +HIDDEN unw_dyn_info_list_t _U_dyn_info_list; + +/* XXX fix me: there is currently no way to locate the dyn-info list + by a remote unwinder. On ia64, this is done via a special + unwind-table entry. Perhaps something similar can be done with + DWARF2 unwind info. */ + +static void +put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) +{ + /* it's a no-op */ +} + +static int +get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, + void *arg) +{ + *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; + return 0; +} + +static int +access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, + void *arg) +{ + if (write) + { + Debug (16, "mem[%lx] <- %lx\n", addr, *val); + *(unw_word_t *) addr = *val; + } + else + { + *val = *(unw_word_t *) addr; + Debug (16, "mem[%lx] -> %lx\n", addr, *val); + } + return 0; +} + +static int +access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, + void *arg) +{ + unw_word_t *addr; + ucontext_t *uc = arg; + + if (unw_is_fpreg (reg)) + goto badreg; + + if (!(addr = uc_addr (uc, reg))) + goto badreg; + + if (write) + { + *(unw_word_t *) addr = *val; + Debug (12, "%s <- %lx\n", unw_regname (reg), *val); + } + else + { + *val = *(unw_word_t *) addr; + Debug (12, "%s -> %lx\n", unw_regname (reg), *val); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} + +static int +access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + ucontext_t *uc = arg; + unw_fpreg_t *addr; + + if (!unw_is_fpreg (reg)) + goto badreg; + + if (!(addr = uc_addr (uc, reg))) + goto badreg; + + if (write) + { + Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg), + ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); + *(unw_fpreg_t *) addr = *val; + } + else + { + *val = *(unw_fpreg_t *) addr; + Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg), + ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + /* attempt to access a non-preserved register */ + return -UNW_EBADREG; +} + +static int +get_static_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, + void *arg) +{ + return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp); +} + +HIDDEN void +aarch64_local_addr_space_init (void) +{ + memset (&local_addr_space, 0, sizeof (local_addr_space)); + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; + local_addr_space.acc.find_proc_info = dwarf_find_proc_info; + local_addr_space.acc.put_unwind_info = put_unwind_info; + local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; + local_addr_space.acc.access_mem = access_mem; + local_addr_space.acc.access_reg = access_reg; + local_addr_space.acc.access_fpreg = access_fpreg; + local_addr_space.acc.resume = aarch64_local_resume; + local_addr_space.acc.get_proc_name = get_static_proc_name; + local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN); + unw_flush_cache (&local_addr_space, 0, 0); +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ginit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ginit_local.c new file mode 100644 index 0000000..cd60ca8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ginit_local.c @@ -0,0 +1,78 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2011-2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "init.h" + +#ifdef UNW_REMOTE_ONLY + +int +unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) +{ + return -UNW_EINVAL; +} + +#else /* !UNW_REMOTE_ONLY */ + +static int +unw_init_local_common (unw_cursor_t *cursor, unw_context_t *uc, unsigned use_prev_instr) +{ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = unw_local_addr_space; + c->dwarf.as_arg = uc; + + return common_init (c, use_prev_instr); +} + +int +unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) +{ + return unw_init_local_common(cursor, uc, 1); +} + +int +unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) +{ + if (!flag) + { + return unw_init_local_common(cursor, uc, 1); + } + else if (flag == UNW_INIT_SIGNAL_FRAME) + { + return unw_init_local_common(cursor, uc, 0); + } + else + { + return -UNW_EINVAL; + } +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ginit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ginit_remote.c new file mode 100644 index 0000000..9b8ba5b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ginit_remote.c @@ -0,0 +1,45 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "init.h" +#include "unwind_i.h" + +int +unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) +{ +#ifdef UNW_LOCAL_ONLY + return -UNW_EINVAL; +#else /* !UNW_LOCAL_ONLY */ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = as; + c->dwarf.as_arg = as_arg; + return common_init (c, 0); +#endif /* !UNW_LOCAL_ONLY */ +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gis_signal_frame.c new file mode 100644 index 0000000..67159d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gis_signal_frame.c @@ -0,0 +1,64 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2012 Tommi Rantala + Copyright (C) 2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +/* The restorer stub will always have the form: + + d2801168 movz x8, #0x8b + d4000001 svc #0x0 +*/ + +int +unw_is_signal_frame (unw_cursor_t *cursor) +{ +#ifdef __linux__ + struct cursor *c = (struct cursor *) cursor; + unw_word_t w0, ip; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + int ret; + + as = c->dwarf.as; + a = unw_get_accessors_int (as); + arg = c->dwarf.as_arg; + + ip = c->dwarf.ip; + + ret = (*a->access_mem) (as, ip, &w0, 0, arg); + if (ret < 0) + return ret; + + /* FIXME: distinguish 32bit insn vs 64bit registers. */ + if (w0 != 0xd4000001d2801168) + return 0; + + return 1; + +#else + return -UNW_ENOINFO; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Greg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Greg_states_iterate.c new file mode 100644 index 0000000..a17dc1b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Greg_states_iterate.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_reg_states_iterate (unw_cursor_t *cursor, + unw_reg_states_callback cb, void *token) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_reg_states_iterate (&c->dwarf, cb, token); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gregs.c new file mode 100644 index 0000000..a884373 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gregs.c @@ -0,0 +1,118 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + Copyright (C) 2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +HIDDEN int +tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + int write) +{ + dwarf_loc_t loc = DWARF_NULL_LOC; + unsigned int mask; + + switch (reg) + { + case UNW_AARCH64_X0: + case UNW_AARCH64_X1: + case UNW_AARCH64_X2: + case UNW_AARCH64_X3: + mask = 1 << reg; + if (write) + { + c->dwarf.eh_args[reg] = *valp; + c->dwarf.eh_valid_mask |= mask; + return 0; + } + else if ((c->dwarf.eh_valid_mask & mask) != 0) + { + *valp = c->dwarf.eh_args[reg]; + return 0; + } + else + loc = c->dwarf.loc[reg]; + break; + + case UNW_AARCH64_X30: + if (write) + c->dwarf.ip = *valp; /* update the IP cache */ + case UNW_AARCH64_X4: + case UNW_AARCH64_X5: + case UNW_AARCH64_X6: + case UNW_AARCH64_X7: + case UNW_AARCH64_X8: + case UNW_AARCH64_X9: + case UNW_AARCH64_X10: + case UNW_AARCH64_X11: + case UNW_AARCH64_X12: + case UNW_AARCH64_X13: + case UNW_AARCH64_X14: + case UNW_AARCH64_X15: + case UNW_AARCH64_X16: + case UNW_AARCH64_X17: + case UNW_AARCH64_X18: + case UNW_AARCH64_X19: + case UNW_AARCH64_X20: + case UNW_AARCH64_X21: + case UNW_AARCH64_X22: + case UNW_AARCH64_X23: + case UNW_AARCH64_X24: + case UNW_AARCH64_X25: + case UNW_AARCH64_X26: + case UNW_AARCH64_X27: + case UNW_AARCH64_X28: + case UNW_AARCH64_X29: + case UNW_AARCH64_PC: + case UNW_AARCH64_PSTATE: + loc = c->dwarf.loc[reg]; + break; + + case UNW_AARCH64_SP: + if (write) + return -UNW_EREADONLYREG; + *valp = c->dwarf.cfa; + return 0; + + default: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; + } + + if (write) + return dwarf_put (&c->dwarf, loc, *valp); + else + return dwarf_get (&c->dwarf, loc, valp); +} + +HIDDEN int +tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, + int write) +{ + dwarf_loc_t loc = c->dwarf.loc[reg]; + if (write) + return dwarf_putfp (&c->dwarf, loc, *valp); + else + return dwarf_getfp (&c->dwarf, loc, valp); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gresume.c new file mode 100644 index 0000000..3d82739 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gresume.c @@ -0,0 +1,198 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2011-2013 Linaro Limited + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "offsets.h" + +#ifndef UNW_REMOTE_ONLY + +HIDDEN inline int +aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ +#ifdef __linux__ + struct cursor *c = (struct cursor *) cursor; + unw_tdep_context_t *uc = c->dwarf.as_arg; + + if (c->sigcontext_format == AARCH64_SCF_NONE) + { + /* Since there are no signals involved here we restore EH and non scratch + registers only. */ + unsigned long regs[24]; + regs[0] = uc->uc_mcontext.regs[0]; + regs[1] = uc->uc_mcontext.regs[1]; + regs[2] = uc->uc_mcontext.regs[2]; + regs[3] = uc->uc_mcontext.regs[3]; + regs[4] = uc->uc_mcontext.regs[19]; + regs[5] = uc->uc_mcontext.regs[20]; + regs[6] = uc->uc_mcontext.regs[21]; + regs[7] = uc->uc_mcontext.regs[22]; + regs[8] = uc->uc_mcontext.regs[23]; + regs[9] = uc->uc_mcontext.regs[24]; + regs[10] = uc->uc_mcontext.regs[25]; + regs[11] = uc->uc_mcontext.regs[26]; + regs[12] = uc->uc_mcontext.regs[27]; + regs[13] = uc->uc_mcontext.regs[28]; + regs[14] = uc->uc_mcontext.regs[29]; /* FP */ + regs[15] = uc->uc_mcontext.regs[30]; /* LR */ + regs[16] = GET_FPCTX(uc)->vregs[8]; + regs[17] = GET_FPCTX(uc)->vregs[9]; + regs[18] = GET_FPCTX(uc)->vregs[10]; + regs[19] = GET_FPCTX(uc)->vregs[11]; + regs[20] = GET_FPCTX(uc)->vregs[12]; + regs[21] = GET_FPCTX(uc)->vregs[13]; + regs[22] = GET_FPCTX(uc)->vregs[14]; + regs[23] = GET_FPCTX(uc)->vregs[15]; + unsigned long sp = uc->uc_mcontext.sp; + + struct regs_overlay { + char x[sizeof(regs)]; + }; + + asm volatile ( + "mov x4, %0\n" + "mov x5, %1\n" + "ldp x0, x1, [x4]\n" + "ldp x2, x3, [x4,16]\n" + "ldp x19, x20, [x4,32]\n" + "ldp x21, x22, [x4,48]\n" + "ldp x23, x24, [x4,64]\n" + "ldp x25, x26, [x4,80]\n" + "ldp x27, x28, [x4,96]\n" + "ldp x29, x30, [x4,112]\n" + "ldp d8, d9, [x4,128]\n" + "ldp d10, d11, [x4,144]\n" + "ldp d12, d13, [x4,160]\n" + "ldp d14, d15, [x4,176]\n" + "mov sp, x5\n" + "ret \n" + : + : "r" (regs), + "r" (sp), + "m" (*(struct regs_overlay *)regs) + ); + } + else + { + struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; + + if (c->dwarf.eh_valid_mask & 0x1) sc->regs[0] = c->dwarf.eh_args[0]; + if (c->dwarf.eh_valid_mask & 0x2) sc->regs[1] = c->dwarf.eh_args[1]; + if (c->dwarf.eh_valid_mask & 0x4) sc->regs[2] = c->dwarf.eh_args[2]; + if (c->dwarf.eh_valid_mask & 0x8) sc->regs[3] = c->dwarf.eh_args[3]; + + sc->regs[4] = uc->uc_mcontext.regs[4]; + sc->regs[5] = uc->uc_mcontext.regs[5]; + sc->regs[6] = uc->uc_mcontext.regs[6]; + sc->regs[7] = uc->uc_mcontext.regs[7]; + sc->regs[8] = uc->uc_mcontext.regs[8]; + sc->regs[9] = uc->uc_mcontext.regs[9]; + sc->regs[10] = uc->uc_mcontext.regs[10]; + sc->regs[11] = uc->uc_mcontext.regs[11]; + sc->regs[12] = uc->uc_mcontext.regs[12]; + sc->regs[13] = uc->uc_mcontext.regs[13]; + sc->regs[14] = uc->uc_mcontext.regs[14]; + sc->regs[15] = uc->uc_mcontext.regs[15]; + sc->regs[16] = uc->uc_mcontext.regs[16]; + sc->regs[17] = uc->uc_mcontext.regs[17]; + sc->regs[18] = uc->uc_mcontext.regs[18]; + sc->regs[19] = uc->uc_mcontext.regs[19]; + sc->regs[20] = uc->uc_mcontext.regs[20]; + sc->regs[21] = uc->uc_mcontext.regs[21]; + sc->regs[22] = uc->uc_mcontext.regs[22]; + sc->regs[23] = uc->uc_mcontext.regs[23]; + sc->regs[24] = uc->uc_mcontext.regs[24]; + sc->regs[25] = uc->uc_mcontext.regs[25]; + sc->regs[26] = uc->uc_mcontext.regs[26]; + sc->regs[27] = uc->uc_mcontext.regs[27]; + sc->regs[28] = uc->uc_mcontext.regs[28]; + sc->regs[29] = uc->uc_mcontext.regs[29]; + sc->regs[30] = uc->uc_mcontext.regs[30]; + sc->sp = uc->uc_mcontext.sp; + sc->pc = uc->uc_mcontext.pc; + sc->pstate = uc->uc_mcontext.pstate; + + asm volatile ( + "mov sp, %0\n" + "ret %1\n" + : : "r" (c->sigcontext_sp), "r" (c->sigcontext_pc) + ); + } + unreachable(); +#else + printf ("%s: implement me\n", __FUNCTION__); +#endif + return -UNW_EINVAL; +} + +#endif /* !UNW_REMOTE_ONLY */ + +static inline void +establish_machine_state (struct cursor *c) +{ + unw_addr_space_t as = c->dwarf.as; + void *arg = c->dwarf.as_arg; + unw_fpreg_t fpval; + unw_word_t val; + int reg; + + Debug (8, "copying out cursor state\n"); + + for (reg = 0; reg <= UNW_AARCH64_V31; ++reg) + { + Debug (16, "copying %s %d\n", unw_regname (reg), reg); + if (unw_is_fpreg (reg)) + { + if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) + as->acc.access_fpreg (as, reg, &fpval, 1, arg); + } + else + { + if (tdep_access_reg (c, reg, &val, 0) >= 0) + as->acc.access_reg (as, reg, &val, 1, arg); + } + } +} + +int +unw_resume (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + + Debug (1, "(cursor=%p)\n", c); + + if (!c->dwarf.ip) + { + /* This can happen easily when the frame-chain gets truncated + due to bad or missing unwind-info. */ + Debug (1, "refusing to resume execution at address 0\n"); + return -UNW_EINVAL; + } + + establish_machine_state (c); + + return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, + c->dwarf.as_arg); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gstash_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gstash_frame.c new file mode 100644 index 0000000..6689af1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gstash_frame.c @@ -0,0 +1,89 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY + Copyright (C) 2014 CERN and Aalto University + Contributed by Filip Nyback + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +HIDDEN void +tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs) +{ + struct cursor *c = (struct cursor *) dwarf_to_cursor (d); + unw_tdep_frame_t *f = &c->frame_info; + + Debug (4, "ip=0x%lx cfa=0x%lx type %d cfa [where=%d val=%ld] cfaoff=%ld" + " ra=0x%lx fp [where=%d val=%ld @0x%lx] lr [where=%d val=%ld @0x%lx] " + "sp [where=%d val=%ld @0x%lx]\n", + d->ip, d->cfa, f->frame_type, + rs->reg.where[DWARF_CFA_REG_COLUMN], + rs->reg.val[DWARF_CFA_REG_COLUMN], + rs->reg.val[DWARF_CFA_OFF_COLUMN], + DWARF_GET_LOC(d->loc[rs->ret_addr_column]), + rs->reg.where[FP], rs->reg.val[FP], DWARF_GET_LOC(d->loc[FP]), + rs->reg.where[LR], rs->reg.val[LR], DWARF_GET_LOC(d->loc[LR]), + rs->reg.where[SP], rs->reg.val[SP], DWARF_GET_LOC(d->loc[SP])); + + /* A standard frame is defined as: + - CFA is register-relative offset off FP or SP; + - Return address is saved in LR; + - FP is unsaved or saved at CFA+offset, offset != -1; + - LR is unsaved or saved at CFA+offset, offset != -1; + - SP is unsaved or saved at CFA+offset, offset != -1. */ + if (f->frame_type == UNW_AARCH64_FRAME_OTHER + && (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG) + && (rs->reg.val[DWARF_CFA_REG_COLUMN] == FP + || rs->reg.val[DWARF_CFA_REG_COLUMN] == SP) + && labs(rs->reg.val[DWARF_CFA_OFF_COLUMN]) < (1 << 29) + && rs->ret_addr_column == LR + && (rs->reg.where[FP] == DWARF_WHERE_UNDEF + || rs->reg.where[FP] == DWARF_WHERE_SAME + || (rs->reg.where[FP] == DWARF_WHERE_CFAREL + && labs(rs->reg.val[FP]) < (1 << 29) + && rs->reg.val[FP]+1 != 0)) + && (rs->reg.where[LR] == DWARF_WHERE_UNDEF + || rs->reg.where[LR] == DWARF_WHERE_SAME + || (rs->reg.where[LR] == DWARF_WHERE_CFAREL + && labs(rs->reg.val[LR]) < (1 << 29) + && rs->reg.val[LR]+1 != 0)) + && (rs->reg.where[SP] == DWARF_WHERE_UNDEF + || rs->reg.where[SP] == DWARF_WHERE_SAME + || (rs->reg.where[SP] == DWARF_WHERE_CFAREL + && labs(rs->reg.val[SP]) < (1 << 29) + && rs->reg.val[SP]+1 != 0))) + { + /* Save information for a standard frame. */ + f->frame_type = UNW_AARCH64_FRAME_STANDARD; + f->cfa_reg_sp = (rs->reg.val[DWARF_CFA_REG_COLUMN] == SP); + f->cfa_reg_offset = rs->reg.val[DWARF_CFA_OFF_COLUMN]; + if (rs->reg.where[FP] == DWARF_WHERE_CFAREL) + f->fp_cfa_offset = rs->reg.val[FP]; + if (rs->reg.where[LR] == DWARF_WHERE_CFAREL) + f->lr_cfa_offset = rs->reg.val[LR]; + if (rs->reg.where[SP] == DWARF_WHERE_CFAREL) + f->sp_cfa_offset = rs->reg.val[SP]; + Debug (4, " standard frame\n"); + } + else + Debug (4, " unusual frame\n"); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gstep.c new file mode 100644 index 0000000..fdf64a7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gstep.c @@ -0,0 +1,189 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2011-2013 Linaro Limited + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "offsets.h" + +/* Recognise PLT entries such as: + 40ddf0: b0000570 adrp x16, 4ba000 <_GLOBAL_OFFSET_TABLE_+0x2a8> + 40ddf4: f9433611 ldr x17, [x16,#1640] + 40ddf8: 9119a210 add x16, x16, #0x668 + 40ddfc: d61f0220 br x17 */ +static int +is_plt_entry (struct dwarf_cursor *c) +{ + unw_word_t w0, w1; + unw_accessors_t *a; + int ret; + + a = unw_get_accessors_int (c->as); + if ((ret = (*a->access_mem) (c->as, c->ip, &w0, 0, c->as_arg)) < 0 + || (ret = (*a->access_mem) (c->as, c->ip + 8, &w1, 0, c->as_arg)) < 0) + return 0; + + ret = (((w0 & 0xff0000009f000000) == 0xf900000090000000) + && ((w1 & 0xffffffffff000000) == 0xd61f022091000000)); + + Debug (14, "ip=0x%lx => 0x%016lx 0x%016lx, ret = %d\n", c->ip, w0, w1, ret); + return ret; +} + +static int +aarch64_handle_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; + struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); + + if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) + return -UNW_EUNSPEC; + + ret = unw_is_signal_frame (cursor); + Debug(1, "unw_is_signal_frame()=%d\n", ret); + + /* Save the SP and PC to be able to return execution at this point + later in time (unw_resume). */ + c->sigcontext_sp = c->dwarf.cfa; + c->sigcontext_pc = c->dwarf.ip; + + if (ret) + { + c->sigcontext_format = AARCH64_SCF_LINUX_RT_SIGFRAME; + sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF; + } + else + return -UNW_EUNSPEC; + + c->sigcontext_addr = sc_addr; + c->frame_info.frame_type = UNW_AARCH64_FRAME_SIGRETURN; + c->frame_info.cfa_reg_offset = sc_addr - sp_addr; + + /* Update the dwarf cursor. + Set the location of the registers to the corresponding addresses of the + uc_mcontext / sigcontext structure contents. */ + c->dwarf.loc[UNW_AARCH64_X0] = DWARF_LOC (sc_addr + LINUX_SC_X0_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X1] = DWARF_LOC (sc_addr + LINUX_SC_X1_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X2] = DWARF_LOC (sc_addr + LINUX_SC_X2_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X3] = DWARF_LOC (sc_addr + LINUX_SC_X3_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X4] = DWARF_LOC (sc_addr + LINUX_SC_X4_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X5] = DWARF_LOC (sc_addr + LINUX_SC_X5_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X6] = DWARF_LOC (sc_addr + LINUX_SC_X6_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X7] = DWARF_LOC (sc_addr + LINUX_SC_X7_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X8] = DWARF_LOC (sc_addr + LINUX_SC_X8_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X9] = DWARF_LOC (sc_addr + LINUX_SC_X9_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X10] = DWARF_LOC (sc_addr + LINUX_SC_X10_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X11] = DWARF_LOC (sc_addr + LINUX_SC_X11_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X12] = DWARF_LOC (sc_addr + LINUX_SC_X12_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X13] = DWARF_LOC (sc_addr + LINUX_SC_X13_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X14] = DWARF_LOC (sc_addr + LINUX_SC_X14_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X15] = DWARF_LOC (sc_addr + LINUX_SC_X15_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X16] = DWARF_LOC (sc_addr + LINUX_SC_X16_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X17] = DWARF_LOC (sc_addr + LINUX_SC_X17_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X18] = DWARF_LOC (sc_addr + LINUX_SC_X18_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X19] = DWARF_LOC (sc_addr + LINUX_SC_X19_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X20] = DWARF_LOC (sc_addr + LINUX_SC_X20_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X21] = DWARF_LOC (sc_addr + LINUX_SC_X21_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X22] = DWARF_LOC (sc_addr + LINUX_SC_X22_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X23] = DWARF_LOC (sc_addr + LINUX_SC_X23_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X24] = DWARF_LOC (sc_addr + LINUX_SC_X24_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X25] = DWARF_LOC (sc_addr + LINUX_SC_X25_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X26] = DWARF_LOC (sc_addr + LINUX_SC_X26_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X27] = DWARF_LOC (sc_addr + LINUX_SC_X27_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X28] = DWARF_LOC (sc_addr + LINUX_SC_X28_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X29] = DWARF_LOC (sc_addr + LINUX_SC_X29_OFF, 0); + c->dwarf.loc[UNW_AARCH64_X30] = DWARF_LOC (sc_addr + LINUX_SC_X30_OFF, 0); + c->dwarf.loc[UNW_AARCH64_SP] = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0); + c->dwarf.loc[UNW_AARCH64_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); + c->dwarf.loc[UNW_AARCH64_PSTATE] = DWARF_LOC (sc_addr + LINUX_SC_PSTATE_OFF, 0); + + /* Set SP/CFA and PC/IP. */ + dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_SP], &c->dwarf.cfa); + dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip); + + c->dwarf.pi_valid = 0; + c->dwarf.use_prev_instr = 0; + + return 1; +} + +int +unw_step (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx))\n", + c, c->dwarf.ip, c->dwarf.cfa); + + /* Check if this is a signal frame. */ + if (unw_is_signal_frame (cursor) > 0) + return aarch64_handle_signal_frame (cursor); + + ret = dwarf_step (&c->dwarf); + Debug(1, "dwarf_step()=%d\n", ret); + + if (unlikely (ret == -UNW_ESTOPUNWIND)) + return ret; + + if (unlikely (ret < 0)) + { + /* DWARF failed. */ + if (is_plt_entry (&c->dwarf)) + { + Debug (2, "found plt entry\n"); + c->frame_info.frame_type = UNW_AARCH64_FRAME_STANDARD; + } + else + { + Debug (2, "fallback\n"); + c->frame_info.frame_type = UNW_AARCH64_FRAME_GUESSED; + } + /* Use link register (X30). */ + c->frame_info.cfa_reg_offset = 0; + c->frame_info.cfa_reg_sp = 0; + c->frame_info.fp_cfa_offset = -1; + c->frame_info.lr_cfa_offset = -1; + c->frame_info.sp_cfa_offset = -1; + c->dwarf.loc[UNW_AARCH64_PC] = c->dwarf.loc[UNW_AARCH64_X30]; + c->dwarf.loc[UNW_AARCH64_X30] = DWARF_NULL_LOC; + if (!DWARF_IS_NULL_LOC (c->dwarf.loc[UNW_AARCH64_PC])) + { + ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip); + if (ret < 0) + { + Debug (2, "failed to get pc from link register: %d\n", ret); + return ret; + } + Debug (2, "link register (x30) = 0x%016lx\n", c->dwarf.ip); + ret = 1; + } + else + c->dwarf.ip = 0; + } + + return (c->dwarf.ip == 0) ? 0 : 1; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gtrace.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gtrace.c new file mode 100644 index 0000000..c67faf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Gtrace.c @@ -0,0 +1,548 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY + Copyright (C) 2014 CERN and Aalto University + Contributed by Filip Nyback + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "offsets.h" +#include +#include + +#pragma weak pthread_once +#pragma weak pthread_key_create +#pragma weak pthread_getspecific +#pragma weak pthread_setspecific + +/* Initial hash table size. Table expands by 2 bits (times four). */ +#define HASH_MIN_BITS 14 + +typedef struct +{ + unw_tdep_frame_t *frames; + size_t log_size; + size_t used; + size_t dtor_count; /* Counts how many times our destructor has already + been called. */ +} unw_trace_cache_t; + +static const unw_tdep_frame_t empty_frame = { 0, UNW_AARCH64_FRAME_OTHER, -1, -1, 0, -1, -1, -1 }; +static define_lock (trace_init_lock); +static pthread_once_t trace_cache_once = PTHREAD_ONCE_INIT; +static sig_atomic_t trace_cache_once_happen; +static pthread_key_t trace_cache_key; +static struct mempool trace_cache_pool; +static __thread unw_trace_cache_t *tls_cache; +static __thread int tls_cache_destroyed; + +/* Free memory for a thread's trace cache. */ +static void +trace_cache_free (void *arg) +{ + unw_trace_cache_t *cache = arg; + if (++cache->dtor_count < PTHREAD_DESTRUCTOR_ITERATIONS) + { + /* Not yet our turn to get destroyed. Re-install ourselves into the key. */ + pthread_setspecific(trace_cache_key, cache); + Debug(5, "delayed freeing cache %p (%zx to go)\n", cache, + PTHREAD_DESTRUCTOR_ITERATIONS - cache->dtor_count); + return; + } + tls_cache_destroyed = 1; + tls_cache = NULL; + munmap (cache->frames, (1u << cache->log_size) * sizeof(unw_tdep_frame_t)); + mempool_free (&trace_cache_pool, cache); + Debug(5, "freed cache %p\n", cache); +} + +/* Initialise frame tracing for threaded use. */ +static void +trace_cache_init_once (void) +{ + pthread_key_create (&trace_cache_key, &trace_cache_free); + mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0); + trace_cache_once_happen = 1; +} + +static unw_tdep_frame_t * +trace_cache_buckets (size_t n) +{ + unw_tdep_frame_t *frames; + size_t i; + + GET_MEMORY(frames, n * sizeof (unw_tdep_frame_t)); + if (likely(frames != NULL)) + for (i = 0; i < n; ++i) + frames[i] = empty_frame; + + return frames; +} + +/* Allocate and initialise hash table for frame cache lookups. + Returns the cache initialised with (1u << HASH_LOW_BITS) hash + buckets, or NULL if there was a memory allocation problem. */ +static unw_trace_cache_t * +trace_cache_create (void) +{ + unw_trace_cache_t *cache; + + if (tls_cache_destroyed) + { + /* The current thread is in the process of exiting. Don't recreate + cache, as we wouldn't have another chance to free it. */ + Debug(5, "refusing to reallocate cache: " + "thread-locals are being deallocated\n"); + return NULL; + } + + if (! (cache = mempool_alloc(&trace_cache_pool))) + { + Debug(5, "failed to allocate cache\n"); + return NULL; + } + + if (! (cache->frames = trace_cache_buckets(1u << HASH_MIN_BITS))) + { + Debug(5, "failed to allocate buckets\n"); + mempool_free(&trace_cache_pool, cache); + return NULL; + } + + cache->log_size = HASH_MIN_BITS; + cache->used = 0; + cache->dtor_count = 0; + tls_cache_destroyed = 0; /* Paranoia: should already be 0. */ + Debug(5, "allocated cache %p\n", cache); + return cache; +} + +/* Expand the hash table in the frame cache if possible. This always + quadruples the hash size, and clears all previous frame entries. */ +static int +trace_cache_expand (unw_trace_cache_t *cache) +{ + size_t old_size = (1u << cache->log_size); + size_t new_log_size = cache->log_size + 2; + unw_tdep_frame_t *new_frames = trace_cache_buckets (1u << new_log_size); + + if (unlikely(! new_frames)) + { + Debug(5, "failed to expand cache to 2^%lu buckets\n", new_log_size); + return -UNW_ENOMEM; + } + + Debug(5, "expanded cache from 2^%lu to 2^%lu buckets\n", cache->log_size, new_log_size); + munmap(cache->frames, old_size * sizeof(unw_tdep_frame_t)); + cache->frames = new_frames; + cache->log_size = new_log_size; + cache->used = 0; + return 0; +} + +static unw_trace_cache_t * +trace_cache_get_unthreaded (void) +{ + unw_trace_cache_t *cache; + intrmask_t saved_mask; + static unw_trace_cache_t *global_cache = NULL; + lock_acquire (&trace_init_lock, saved_mask); + if (! global_cache) + { + mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0); + global_cache = trace_cache_create (); + } + cache = global_cache; + lock_release (&trace_init_lock, saved_mask); + Debug(5, "using cache %p\n", cache); + return cache; +} + +/* Get the frame cache for the current thread. Create it if there is none. */ +static unw_trace_cache_t * +trace_cache_get (void) +{ + unw_trace_cache_t *cache; + if (likely (pthread_once != NULL)) + { + pthread_once(&trace_cache_once, &trace_cache_init_once); + if (!trace_cache_once_happen) + { + return trace_cache_get_unthreaded(); + } + if (! (cache = tls_cache)) + { + cache = trace_cache_create(); + pthread_setspecific(trace_cache_key, cache); + tls_cache = cache; + } + Debug(5, "using cache %p\n", cache); + return cache; + } + else + { + return trace_cache_get_unthreaded(); + } +} + +/* Initialise frame properties for address cache slot F at address + PC using current CFA, FP and SP values. Modifies CURSOR to + that location, performs one unw_step(), and fills F with what + was discovered about the location. Returns F. + + FIXME: This probably should tell DWARF handling to never evaluate + or use registers other than FP, SP and PC in case there is + highly unusual unwind info which uses these creatively. */ +static unw_tdep_frame_t * +trace_init_addr (unw_tdep_frame_t *f, + unw_cursor_t *cursor, + unw_word_t cfa, + unw_word_t pc, + unw_word_t fp, + unw_word_t sp) +{ + struct cursor *c = (struct cursor *) cursor; + struct dwarf_cursor *d = &c->dwarf; + int ret = -UNW_EINVAL; + + /* Initialise frame properties: unknown, not last. */ + f->virtual_address = pc; + f->frame_type = UNW_AARCH64_FRAME_OTHER; + f->last_frame = 0; + f->cfa_reg_sp = -1; + f->cfa_reg_offset = 0; + f->fp_cfa_offset = -1; + f->lr_cfa_offset = -1; + f->sp_cfa_offset = -1; + + /* Reinitialise cursor to this instruction - but undo next/prev PC + adjustment because unw_step will redo it - and force PC, FP and + SP into register locations (=~ ucontext we keep), then set + their desired values. Then perform the step. */ + d->ip = pc + d->use_prev_instr; + d->cfa = cfa; + d->loc[UNW_AARCH64_X29] = DWARF_REG_LOC (d, UNW_AARCH64_X29); + d->loc[UNW_AARCH64_SP] = DWARF_REG_LOC (d, UNW_AARCH64_SP); + d->loc[UNW_AARCH64_PC] = DWARF_REG_LOC (d, UNW_AARCH64_PC); + c->frame_info = *f; + + if (likely(dwarf_put (d, d->loc[UNW_AARCH64_X29], fp) >= 0) + && likely(dwarf_put (d, d->loc[UNW_AARCH64_SP], sp) >= 0) + && likely(dwarf_put (d, d->loc[UNW_AARCH64_PC], pc) >= 0) + && likely((ret = unw_step (cursor)) >= 0)) + *f = c->frame_info; + + /* If unw_step() stopped voluntarily, remember that, even if it + otherwise could not determine anything useful. This avoids + failing trace if we hit frames without unwind info, which is + common for the outermost frame (CRT stuff) on many systems. + This avoids failing trace in very common circumstances; failing + to unw_step() loop wouldn't produce any better result. */ + if (ret == 0) + f->last_frame = -1; + + Debug (3, "frame va %lx type %d last %d cfa %s+%d fp @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n", + f->virtual_address, f->frame_type, f->last_frame, + f->cfa_reg_sp ? "sp" : "fp", f->cfa_reg_offset, + f->fp_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset); + + return f; +} + +/* Look up and if necessary fill in frame attributes for address PC + in CACHE using current CFA, FP and SP values. Uses CURSOR to + perform any unwind steps necessary to fill the cache. Returns the + frame cache slot which describes RIP. */ +static unw_tdep_frame_t * +trace_lookup (unw_cursor_t *cursor, + unw_trace_cache_t *cache, + unw_word_t cfa, + unw_word_t pc, + unw_word_t fp, + unw_word_t sp) +{ + /* First look up for previously cached information using cache as + linear probing hash table with probe step of 1. Majority of + lookups should be completed within few steps, but it is very + important the hash table does not fill up, or performance falls + off the cliff. */ + uint64_t i, addr; + uint64_t cache_size = 1u << cache->log_size; + uint64_t slot = ((pc * 0x9e3779b97f4a7c16) >> 43) & (cache_size-1); + unw_tdep_frame_t *frame; + + for (i = 0; i < 16; ++i) + { + frame = &cache->frames[slot]; + addr = frame->virtual_address; + + /* Return if we found the address. */ + if (likely(addr == pc)) + { + Debug (4, "found address after %ld steps\n", i); + return frame; + } + + /* If slot is empty, reuse it. */ + if (likely(! addr)) + break; + + /* Linear probe to next slot candidate, step = 1. */ + if (++slot >= cache_size) + slot -= cache_size; + } + + /* If we collided after 16 steps, or if the hash is more than half + full, force the hash to expand. Fill the selected slot, whether + it's free or collides. Note that hash expansion drops previous + contents; further lookups will refill the hash. */ + Debug (4, "updating slot %lu after %ld steps, replacing 0x%lx\n", slot, i, addr); + if (unlikely(addr || cache->used >= cache_size / 2)) + { + if (unlikely(trace_cache_expand (cache) < 0)) + return NULL; + + cache_size = 1u << cache->log_size; + slot = ((pc * 0x9e3779b97f4a7c16) >> 43) & (cache_size-1); + frame = &cache->frames[slot]; + addr = frame->virtual_address; + } + + if (! addr) + ++cache->used; + + return trace_init_addr (frame, cursor, cfa, pc, fp, sp); +} + +/* Fast stack backtrace for AArch64. + + This is used by backtrace() implementation to accelerate frequent + queries for current stack, without any desire to unwind. It fills + BUFFER with the call tree from CURSOR upwards for at most SIZE + stack levels. The first frame, backtrace itself, is omitted. When + called, SIZE should give the maximum number of entries that can be + stored into BUFFER. Uses an internal thread-specific cache to + accelerate queries. + + The caller should fall back to a unw_step() loop if this function + fails by returning -UNW_ESTOPUNWIND, meaning the routine hit a + stack frame that is too complex to be traced in the fast path. + + This function is tuned for clients which only need to walk the + stack to get the call tree as fast as possible but without any + other details, for example profilers sampling the stack thousands + to millions of times per second. The routine handles the most + common AArch64 ABI stack layouts: CFA is FP or SP plus/minus + constant offset, return address is in LR, and FP, LR and SP are + either unchanged or saved on stack at constant offset from the CFA; + the signal return frame; and frames without unwind info provided + they are at the outermost (final) frame or can conservatively be + assumed to be frame-pointer based. + + Any other stack layout will cause the routine to give up. There + are only a handful of relatively rarely used functions which do + not have a stack in the standard form: vfork, longjmp, setcontext + and _dl_runtime_profile on common linux systems for example. + + On success BUFFER and *SIZE reflect the trace progress up to *SIZE + stack levels or the outermost frame, which ever is less. It may + stop short of outermost frame if unw_step() loop would also do so, + e.g. if there is no more unwind information; this is not reported + as an error. + + The function returns a negative value for errors, -UNW_ESTOPUNWIND + if tracing stopped because of an unusual frame unwind info. The + BUFFER and *SIZE reflect tracing progress up to the error frame. + + Callers of this function would normally look like this: + + unw_cursor_t cur; + unw_context_t ctx; + void addrs[128]; + int depth = 128; + int ret; + + unw_getcontext(&ctx); + unw_init_local(&cur, &ctx); + if ((ret = unw_tdep_trace(&cur, addrs, &depth)) < 0) + { + depth = 0; + unw_getcontext(&ctx); + unw_init_local(&cur, &ctx); + while ((ret = unw_step(&cur)) > 0 && depth < 128) + { + unw_word_t ip; + unw_get_reg(&cur, UNW_REG_IP, &ip); + addresses[depth++] = (void *) ip; + } + } +*/ +HIDDEN int +tdep_trace (unw_cursor_t *cursor, void **buffer, int *size) +{ + struct cursor *c = (struct cursor *) cursor; + struct dwarf_cursor *d = &c->dwarf; + unw_trace_cache_t *cache; + unw_word_t fp, sp, pc, cfa, lr; + int maxdepth = 0; + int depth = 0; + int ret; + + /* Check input parametres. */ + if (unlikely(! cursor || ! buffer || ! size || (maxdepth = *size) <= 0)) + return -UNW_EINVAL; + + Debug (1, "begin ip 0x%lx cfa 0x%lx\n", d->ip, d->cfa); + + /* Tell core dwarf routines to call back to us. */ + d->stash_frames = 1; + + /* Determine initial register values. These are direct access safe + because we know they come from the initial machine context. */ + pc = d->ip; + sp = cfa = d->cfa; + ACCESS_MEM_FAST(ret, 0, d, DWARF_GET_LOC(d->loc[UNW_AARCH64_X29]), fp); + assert(ret == 0); + lr = 0; + + /* Get frame cache. */ + if (unlikely(! (cache = trace_cache_get()))) + { + Debug (1, "returning %d, cannot get trace cache\n", -UNW_ENOMEM); + *size = 0; + d->stash_frames = 0; + return -UNW_ENOMEM; + } + + /* Trace the stack upwards, starting from current RIP. Adjust + the RIP address for previous/next instruction as the main + unwinding logic would also do. We undo this before calling + back into unw_step(). */ + while (depth < maxdepth) + { + pc -= d->use_prev_instr; + Debug (2, "depth %d cfa 0x%lx pc 0x%lx sp 0x%lx fp 0x%lx\n", + depth, cfa, pc, sp, fp); + + /* See if we have this address cached. If not, evaluate enough of + the dwarf unwind information to fill the cache line data, or to + decide this frame cannot be handled in fast trace mode. We + cache negative results too to prevent unnecessary dwarf parsing + for common failures. */ + unw_tdep_frame_t *f = trace_lookup (cursor, cache, cfa, pc, fp, sp); + + /* If we don't have information for this frame, give up. */ + if (unlikely(! f)) + { + ret = -UNW_ENOINFO; + break; + } + + Debug (3, "frame va %lx type %d last %d cfa %s+%d fp @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n", + f->virtual_address, f->frame_type, f->last_frame, + f->cfa_reg_sp ? "sp" : "fp", f->cfa_reg_offset, + f->fp_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset); + + assert (f->virtual_address == pc); + + /* Stop if this was the last frame. In particular don't evaluate + new register values as it may not be safe - we don't normally + run with full validation on, and do not want to - and there's + enough bad unwind info floating around that we need to trust + what unw_step() previously said, in potentially bogus frames. */ + if (f->last_frame) + break; + + /* Evaluate CFA and registers for the next frame. */ + switch (f->frame_type) + { + case UNW_AARCH64_FRAME_GUESSED: + /* Fall thru to standard processing after forcing validation. */ + c->validate = 1; + + case UNW_AARCH64_FRAME_STANDARD: + /* Advance standard traceable frame. */ + cfa = (f->cfa_reg_sp ? sp : fp) + f->cfa_reg_offset; + if (likely(f->lr_cfa_offset != -1)) + ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->lr_cfa_offset, pc); + else if (lr != 0) + { + /* Use the saved link register as the new pc. */ + pc = lr; + lr = 0; + } + if (likely(ret >= 0) && likely(f->fp_cfa_offset != -1)) + ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->fp_cfa_offset, fp); + + /* Don't bother reading SP from DWARF, CFA becomes new SP. */ + sp = cfa; + + /* Next frame needs to back up for unwind info lookup. */ + d->use_prev_instr = 1; + break; + + case UNW_AARCH64_FRAME_SIGRETURN: + cfa = cfa + f->cfa_reg_offset; /* cfa now points to ucontext_t. */ + + ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_PC_OFF, pc); + if (likely(ret >= 0)) + ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_X29_OFF, fp); + if (likely(ret >= 0)) + ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_SP_OFF, sp); + /* Save the link register here in case we end up in a function that + doesn't save the link register in the prologue, e.g. kill. */ + if (likely(ret >= 0)) + ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_X30_OFF, lr); + + /* Resume stack at signal restoration point. The stack is not + necessarily continuous here, especially with sigaltstack(). */ + cfa = sp; + + /* Next frame should not back up. */ + d->use_prev_instr = 0; + break; + + default: + /* We cannot trace through this frame, give up and tell the + caller we had to stop. Data collected so far may still be + useful to the caller, so let it know how far we got. */ + ret = -UNW_ESTOPUNWIND; + break; + } + + Debug (4, "new cfa 0x%lx pc 0x%lx sp 0x%lx fp 0x%lx\n", + cfa, pc, sp, fp); + + /* If we failed or ended up somewhere bogus, stop. */ + if (unlikely(ret < 0 || pc < 0x4000)) + break; + + /* Record this address in stack trace. We skipped the first address. */ + buffer[depth++] = (void *) (pc - d->use_prev_instr); + } + +#if UNW_DEBUG + Debug (1, "returning %d, depth %d\n", ret, depth); +#endif + *size = depth; + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lapply_reg_state.c new file mode 100644 index 0000000..7ebada4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lapply_reg_state.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gapply_reg_state.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lcreate_addr_space.c new file mode 100644 index 0000000..0f2dc6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lcreate_addr_space.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gcreate_addr_space.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lget_proc_info.c new file mode 100644 index 0000000..69028b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lget_proc_info.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_proc_info.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lget_save_loc.c new file mode 100644 index 0000000..9ea048a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lget_save_loc.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_save_loc.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lglobal.c new file mode 100644 index 0000000..6d7b489 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lglobal.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gglobal.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Linit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Linit.c new file mode 100644 index 0000000..e9abfdd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Linit.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Linit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Linit_local.c new file mode 100644 index 0000000..68a1687 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Linit_local.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_local.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Linit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Linit_remote.c new file mode 100644 index 0000000..58cb04a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Linit_remote.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_remote.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lis_signal_frame.c new file mode 100644 index 0000000..b9a7c4f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lis_signal_frame.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gis_signal_frame.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lreg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lreg_states_iterate.c new file mode 100644 index 0000000..f1eb1e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lreg_states_iterate.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Greg_states_iterate.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lregs.c new file mode 100644 index 0000000..2c9c75c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lregs.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gregs.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lresume.c new file mode 100644 index 0000000..41a8cf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lresume.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gresume.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lstash_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lstash_frame.c new file mode 100644 index 0000000..7758780 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lstash_frame.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gstash_frame.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lstep.c new file mode 100644 index 0000000..c1ac3c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Lstep.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gstep.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ltrace.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ltrace.c new file mode 100644 index 0000000..fcd3f23 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/Ltrace.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gtrace.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/gen-offsets.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/gen-offsets.c new file mode 100644 index 0000000..eadc237 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/gen-offsets.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include + +#define UC(N,X) \ + printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X)) + +#define SC(N,X) \ + printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X)) + +int +main (void) +{ + printf ( +"/* Linux-specific definitions: */\n\n" + +"/* Define various structure offsets to simplify cross-compilation. */\n\n" + +"/* Offsets for AArch64 Linux \"ucontext_t\": */\n\n"); + + UC ("FLAGS", uc_flags); + UC ("LINK", uc_link); + UC ("STACK", uc_stack); + UC ("MCONTEXT", uc_mcontext); + UC ("SIGMASK", uc_sigmask); + + printf ("\n/* Offsets for AArch64 Linux \"struct sigcontext\": */\n\n"); + + SC ("R0", regs[0]); + SC ("R1", regs[1]); + SC ("R2", regs[2]); + SC ("R3", regs[3]); + SC ("R4", regs[4]); + SC ("R5", regs[5]); + SC ("R6", regs[6]); + SC ("R7", regs[7]); + SC ("R8", regs[8]); + SC ("R9", regs[9]); + SC ("R10", regs[10]); + SC ("R11", regs[11]); + SC ("R12", regs[12]); + SC ("R13", regs[13]); + SC ("R14", regs[14]); + SC ("R15", regs[15]); + SC ("R16", regs[16]); + SC ("R17", regs[17]); + SC ("R18", regs[18]); + SC ("R19", regs[19]); + SC ("R20", regs[20]); + SC ("R21", regs[21]); + SC ("R22", regs[22]); + SC ("R23", regs[23]); + SC ("R24", regs[24]); + SC ("R25", regs[25]); + SC ("R26", regs[26]); + SC ("R27", regs[27]); + SC ("R28", regs[28]); + SC ("R29", regs[29]); + SC ("R30", regs[30]); + SC ("R31", regs[31]); + + SC ("PC", pc); + SC ("SP", sp); + SC ("Fault", fault_address); + SC ("state", pstate); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/getcontext.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/getcontext.S new file mode 100644 index 0000000..25ed5b6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/getcontext.S @@ -0,0 +1,52 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 Google, Inc + Contributed by Paul Pluzhnikov + Copyright (C) 2010 Konstantin Belousov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "offsets.h" + +/* int _Uaarch64_getcontext_trace (unw_tdep_context_t *ucp) + + Saves limited machine context in UCP necessary for fast trace. If fast trace + fails, caller will have to get the full context. +*/ + + .global _Uaarch64_getcontext_trace + .hidden _Uaarch64_getcontext_trace + .type _Uaarch64_getcontext_trace, @function +_Uaarch64_getcontext_trace: + .cfi_startproc + + /* Save only FP, SP, PC - exclude this call. */ + str x29, [x0, #(LINUX_UC_MCONTEXT_OFF + LINUX_SC_X29_OFF)] + mov x9, sp + str x9, [x0, #(LINUX_UC_MCONTEXT_OFF + LINUX_SC_SP_OFF)] + str x30, [x0, #(LINUX_UC_MCONTEXT_OFF + LINUX_SC_PC_OFF)] + + ret + .cfi_endproc + .size _Uaarch64_getcontext_trace, . - _Uaarch64_getcontext_trace + + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/init.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/init.h new file mode 100644 index 0000000..5dab60b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/init.h @@ -0,0 +1,126 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2012 Tommi Rantala + Copyright (C) 2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static inline int +common_init (struct cursor *c, unsigned use_prev_instr) +{ + int ret, i; + + c->dwarf.loc[UNW_AARCH64_X0] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X0); + c->dwarf.loc[UNW_AARCH64_X1] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X1); + c->dwarf.loc[UNW_AARCH64_X2] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X2); + c->dwarf.loc[UNW_AARCH64_X3] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X3); + c->dwarf.loc[UNW_AARCH64_X4] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X4); + c->dwarf.loc[UNW_AARCH64_X5] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X5); + c->dwarf.loc[UNW_AARCH64_X6] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X6); + c->dwarf.loc[UNW_AARCH64_X7] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X7); + c->dwarf.loc[UNW_AARCH64_X8] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X8); + c->dwarf.loc[UNW_AARCH64_X9] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X9); + c->dwarf.loc[UNW_AARCH64_X10] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X10); + c->dwarf.loc[UNW_AARCH64_X11] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X11); + c->dwarf.loc[UNW_AARCH64_X12] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X12); + c->dwarf.loc[UNW_AARCH64_X13] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X13); + c->dwarf.loc[UNW_AARCH64_X14] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X14); + c->dwarf.loc[UNW_AARCH64_X15] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X15); + c->dwarf.loc[UNW_AARCH64_X16] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X16); + c->dwarf.loc[UNW_AARCH64_X17] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X17); + c->dwarf.loc[UNW_AARCH64_X18] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X18); + c->dwarf.loc[UNW_AARCH64_X19] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X19); + c->dwarf.loc[UNW_AARCH64_X20] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X20); + c->dwarf.loc[UNW_AARCH64_X21] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X21); + c->dwarf.loc[UNW_AARCH64_X22] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X22); + c->dwarf.loc[UNW_AARCH64_X23] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X23); + c->dwarf.loc[UNW_AARCH64_X24] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X24); + c->dwarf.loc[UNW_AARCH64_X25] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X25); + c->dwarf.loc[UNW_AARCH64_X26] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X26); + c->dwarf.loc[UNW_AARCH64_X27] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X27); + c->dwarf.loc[UNW_AARCH64_X28] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X28); + c->dwarf.loc[UNW_AARCH64_X29] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X29); + c->dwarf.loc[UNW_AARCH64_X30] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X30); + c->dwarf.loc[UNW_AARCH64_SP] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_SP); + c->dwarf.loc[UNW_AARCH64_PC] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_PC); + c->dwarf.loc[UNW_AARCH64_PSTATE] = DWARF_REG_LOC (&c->dwarf, + UNW_AARCH64_PSTATE); + c->dwarf.loc[UNW_AARCH64_V0] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V0); + c->dwarf.loc[UNW_AARCH64_V1] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V1); + c->dwarf.loc[UNW_AARCH64_V2] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V2); + c->dwarf.loc[UNW_AARCH64_V3] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V3); + c->dwarf.loc[UNW_AARCH64_V4] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V4); + c->dwarf.loc[UNW_AARCH64_V5] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V5); + c->dwarf.loc[UNW_AARCH64_V6] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V6); + c->dwarf.loc[UNW_AARCH64_V7] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V7); + c->dwarf.loc[UNW_AARCH64_V8] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V8); + c->dwarf.loc[UNW_AARCH64_V9] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V9); + c->dwarf.loc[UNW_AARCH64_V10] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V10); + c->dwarf.loc[UNW_AARCH64_V11] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V11); + c->dwarf.loc[UNW_AARCH64_V12] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V12); + c->dwarf.loc[UNW_AARCH64_V13] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V13); + c->dwarf.loc[UNW_AARCH64_V14] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V14); + c->dwarf.loc[UNW_AARCH64_V15] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V15); + c->dwarf.loc[UNW_AARCH64_V16] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V16); + c->dwarf.loc[UNW_AARCH64_V17] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V17); + c->dwarf.loc[UNW_AARCH64_V18] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V18); + c->dwarf.loc[UNW_AARCH64_V19] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V19); + c->dwarf.loc[UNW_AARCH64_V20] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V20); + c->dwarf.loc[UNW_AARCH64_V21] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V21); + c->dwarf.loc[UNW_AARCH64_V22] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V22); + c->dwarf.loc[UNW_AARCH64_V23] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V23); + c->dwarf.loc[UNW_AARCH64_V24] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V24); + c->dwarf.loc[UNW_AARCH64_V25] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V25); + c->dwarf.loc[UNW_AARCH64_V26] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V26); + c->dwarf.loc[UNW_AARCH64_V27] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V27); + c->dwarf.loc[UNW_AARCH64_V28] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V28); + c->dwarf.loc[UNW_AARCH64_V29] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V29); + c->dwarf.loc[UNW_AARCH64_V30] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V30); + c->dwarf.loc[UNW_AARCH64_V31] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V31); + + for (i = UNW_AARCH64_PSTATE + 1; i < UNW_AARCH64_V0; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + + ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip); + if (ret < 0) + return ret; + + ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_SP], &c->dwarf.cfa); + if (ret < 0) + return ret; + + c->sigcontext_format = AARCH64_SCF_NONE; + c->sigcontext_addr = 0; + c->sigcontext_sp = 0; + c->sigcontext_pc = 0; + + c->dwarf.args_size = 0; + c->dwarf.stash_frames = 0; + c->dwarf.use_prev_instr = use_prev_instr; + c->dwarf.pi_valid = 0; + c->dwarf.pi_is_dynamic = 0; + c->dwarf.hint = 0; + c->dwarf.prev_rs = 0; + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/is_fpreg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/is_fpreg.c new file mode 100644 index 0000000..2981d27 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/is_fpreg.c @@ -0,0 +1,32 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +int +unw_is_fpreg (int regnum) +{ + return (regnum >= UNW_AARCH64_V0 && regnum <= UNW_AARCH64_V31); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/offsets.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/offsets.h new file mode 100644 index 0000000..e78251d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/offsets.h @@ -0,0 +1,49 @@ +/* Linux-specific definitions: */ + +/* Define various structure offsets to simplify cross-compilation. */ + +/* Offsets for AArch64 Linux "ucontext_t": */ + +#define LINUX_UC_FLAGS_OFF 0x0 +#define LINUX_UC_LINK_OFF 0x8 +#define LINUX_UC_STACK_OFF 0x10 +#define LINUX_UC_SIGMASK_OFF 0x28 +#define LINUX_UC_MCONTEXT_OFF 0xb0 + +/* Offsets for AArch64 Linux "struct sigcontext": */ + +#define LINUX_SC_FAULTADDRESS_OFF 0x00 +#define LINUX_SC_X0_OFF 0x008 +#define LINUX_SC_X1_OFF 0x010 +#define LINUX_SC_X2_OFF 0x018 +#define LINUX_SC_X3_OFF 0x020 +#define LINUX_SC_X4_OFF 0x028 +#define LINUX_SC_X5_OFF 0x030 +#define LINUX_SC_X6_OFF 0x038 +#define LINUX_SC_X7_OFF 0x040 +#define LINUX_SC_X8_OFF 0x048 +#define LINUX_SC_X9_OFF 0x050 +#define LINUX_SC_X10_OFF 0x058 +#define LINUX_SC_X11_OFF 0x060 +#define LINUX_SC_X12_OFF 0x068 +#define LINUX_SC_X13_OFF 0x070 +#define LINUX_SC_X14_OFF 0x078 +#define LINUX_SC_X15_OFF 0x080 +#define LINUX_SC_X16_OFF 0x088 +#define LINUX_SC_X17_OFF 0x090 +#define LINUX_SC_X18_OFF 0x098 +#define LINUX_SC_X19_OFF 0x0a0 +#define LINUX_SC_X20_OFF 0x0a8 +#define LINUX_SC_X21_OFF 0x0b0 +#define LINUX_SC_X22_OFF 0x0b8 +#define LINUX_SC_X23_OFF 0x0c0 +#define LINUX_SC_X24_OFF 0x0c8 +#define LINUX_SC_X25_OFF 0x0d0 +#define LINUX_SC_X26_OFF 0x0d8 +#define LINUX_SC_X27_OFF 0x0e0 +#define LINUX_SC_X28_OFF 0x0e8 +#define LINUX_SC_X29_OFF 0x0f0 +#define LINUX_SC_X30_OFF 0x0f8 +#define LINUX_SC_SP_OFF 0x100 +#define LINUX_SC_PC_OFF 0x108 +#define LINUX_SC_PSTATE_OFF 0x110 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/regname.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/regname.c new file mode 100644 index 0000000..0f7a8bd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/regname.c @@ -0,0 +1,106 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2012 Tommi Rantala + Copyright (C) 2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static const char *const regname[] = + { + [UNW_AARCH64_X0] = "x0", + [UNW_AARCH64_X1] = "x1", + [UNW_AARCH64_X2] = "x2", + [UNW_AARCH64_X3] = "x3", + [UNW_AARCH64_X4] = "x4", + [UNW_AARCH64_X5] = "x5", + [UNW_AARCH64_X6] = "x6", + [UNW_AARCH64_X7] = "x7", + [UNW_AARCH64_X8] = "x8", + [UNW_AARCH64_X9] = "x9", + [UNW_AARCH64_X10] = "x10", + [UNW_AARCH64_X11] = "x11", + [UNW_AARCH64_X12] = "x12", + [UNW_AARCH64_X13] = "x13", + [UNW_AARCH64_X14] = "x14", + [UNW_AARCH64_X15] = "x15", + [UNW_AARCH64_X16] = "ip0", + [UNW_AARCH64_X17] = "ip1", + [UNW_AARCH64_X18] = "x18", + [UNW_AARCH64_X19] = "x19", + [UNW_AARCH64_X20] = "x20", + [UNW_AARCH64_X21] = "x21", + [UNW_AARCH64_X22] = "x22", + [UNW_AARCH64_X23] = "x23", + [UNW_AARCH64_X24] = "x24", + [UNW_AARCH64_X25] = "x25", + [UNW_AARCH64_X26] = "x26", + [UNW_AARCH64_X27] = "x27", + [UNW_AARCH64_X28] = "x28", + [UNW_AARCH64_X29] = "fp", + [UNW_AARCH64_X30] = "lr", + [UNW_AARCH64_SP] = "sp", + [UNW_AARCH64_PC] = "pc", + [UNW_AARCH64_V0] = "v0", + [UNW_AARCH64_V1] = "v1", + [UNW_AARCH64_V2] = "v2", + [UNW_AARCH64_V3] = "v3", + [UNW_AARCH64_V4] = "v4", + [UNW_AARCH64_V5] = "v5", + [UNW_AARCH64_V6] = "v6", + [UNW_AARCH64_V7] = "v7", + [UNW_AARCH64_V8] = "v8", + [UNW_AARCH64_V9] = "v9", + [UNW_AARCH64_V10] = "v10", + [UNW_AARCH64_V11] = "v11", + [UNW_AARCH64_V12] = "v12", + [UNW_AARCH64_V13] = "v13", + [UNW_AARCH64_V14] = "v14", + [UNW_AARCH64_V15] = "v15", + [UNW_AARCH64_V16] = "v16", + [UNW_AARCH64_V17] = "v17", + [UNW_AARCH64_V18] = "v18", + [UNW_AARCH64_V19] = "v19", + [UNW_AARCH64_V20] = "v20", + [UNW_AARCH64_V21] = "v21", + [UNW_AARCH64_V22] = "v22", + [UNW_AARCH64_V23] = "v23", + [UNW_AARCH64_V24] = "v24", + [UNW_AARCH64_V25] = "v25", + [UNW_AARCH64_V26] = "v26", + [UNW_AARCH64_V27] = "v27", + [UNW_AARCH64_V28] = "v28", + [UNW_AARCH64_V29] = "v29", + [UNW_AARCH64_V30] = "v30", + [UNW_AARCH64_V31] = "v31", + [UNW_AARCH64_FPSR] = "fpsr", + [UNW_AARCH64_FPCR] = "fpcr", + }; + +const char * +unw_regname (unw_regnum_t reg) +{ + if (reg < (unw_regnum_t) ARRAY_SIZE (regname) && regname[reg] != NULL) + return regname[reg]; + else + return "???"; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/siglongjmp.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/siglongjmp.S new file mode 100644 index 0000000..9985c4b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/aarch64/siglongjmp.S @@ -0,0 +1,12 @@ + /* Dummy implementation for now. */ + + .global _UI_siglongjmp_cont + .global _UI_longjmp_cont + +_UI_siglongjmp_cont: +_UI_longjmp_cont: + ret +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",%progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gapply_reg_state.c new file mode 100644 index 0000000..82f056d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gapply_reg_state.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_apply_reg_state (unw_cursor_t *cursor, + void *reg_states_data) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gcreate_addr_space.c new file mode 100644 index 0000000..7b2d6ba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gcreate_addr_space.c @@ -0,0 +1,60 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "unwind_i.h" + +unw_addr_space_t +unw_create_addr_space (unw_accessors_t *a, int byte_order) +{ +#ifdef UNW_LOCAL_ONLY + return NULL; +#else + unw_addr_space_t as; + + /* + * ARM supports little-endian and big-endian. + */ + if (byte_order != 0 && byte_order != __LITTLE_ENDIAN + && byte_order != __BIG_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); + if (!as) + return NULL; + + memset (as, 0, sizeof (*as)); + + as->acc = *a; + + /* Default to little-endian for ARM. */ + if (byte_order == 0 || byte_order == __LITTLE_ENDIAN) + as->big_endian = 0; + else + as->big_endian = 1; + + return as; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gex_tables.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gex_tables.c new file mode 100644 index 0000000..e79903c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gex_tables.c @@ -0,0 +1,548 @@ +/* libunwind - a platform-independent unwind library + Copyright 2011 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* This file contains functionality for parsing and interpreting the ARM +specific unwind information. Documentation about the exception handling +ABI for the ARM architecture can be found at: +http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf +*/ + +#include "libunwind_i.h" + +#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f) +#define ARM_EXBUF_COUNT(x) ((x) & 0x0f) +#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x)) + +#define ARM_EXIDX_CANT_UNWIND 0x00000001 +#define ARM_EXIDX_COMPACT 0x80000000 + +#define ARM_EXTBL_OP_FINISH 0xb0 + +enum arm_exbuf_cmd_flags { + ARM_EXIDX_VFP_SHIFT_16 = 1 << 16, + ARM_EXIDX_VFP_DOUBLE = 1 << 17, +}; + +struct arm_cb_data + { + /* in: */ + unw_word_t ip; /* instruction-pointer we're looking for */ + unw_proc_info_t *pi; /* proc-info pointer */ + /* out: */ + unw_dyn_info_t di; /* info about the ARM exidx segment */ + }; + +static inline uint32_t CONST_ATTR +prel31_read (uint32_t prel31) +{ + return ((int32_t)prel31 << 1) >> 1; +} + +static inline int +prel31_to_addr (unw_addr_space_t as, void *arg, unw_word_t prel31, + unw_word_t *val) +{ + unw_word_t offset; + + if ((*as->acc.access_mem)(as, prel31, &offset, 0, arg) < 0) + return -UNW_EINVAL; + + offset = ((long)offset << 1) >> 1; + *val = prel31 + offset; + + return 0; +} + +/** + * Applies the given command onto the new state to the given dwarf_cursor. + */ +HIDDEN int +arm_exidx_apply_cmd (struct arm_exbuf_data *edata, struct dwarf_cursor *c) +{ + int ret = 0; + unsigned i; + + switch (edata->cmd) + { + case ARM_EXIDX_CMD_FINISH: + /* Set LR to PC if not set already. */ + if (DWARF_IS_NULL_LOC (c->loc[UNW_ARM_R15])) + c->loc[UNW_ARM_R15] = c->loc[UNW_ARM_R14]; + /* Set IP. */ + dwarf_get (c, c->loc[UNW_ARM_R15], &c->ip); + break; + case ARM_EXIDX_CMD_DATA_PUSH: + Debug (2, "vsp = vsp - %d\n", edata->data); + c->cfa -= edata->data; + break; + case ARM_EXIDX_CMD_DATA_POP: + Debug (2, "vsp = vsp + %d\n", edata->data); + c->cfa += edata->data; + break; + case ARM_EXIDX_CMD_REG_POP: + for (i = 0; i < 16; i++) + if (edata->data & (1 << i)) + { + Debug (2, "pop {r%d}\n", i); + c->loc[UNW_ARM_R0 + i] = DWARF_LOC (c->cfa, 0); + c->cfa += 4; + } + /* Set cfa in case the SP got popped. */ + if (edata->data & (1 << 13)) + dwarf_get (c, c->loc[UNW_ARM_R13], &c->cfa); + break; + case ARM_EXIDX_CMD_REG_TO_SP: + assert (edata->data < 16); + Debug (2, "vsp = r%d\n", edata->data); + c->loc[UNW_ARM_R13] = c->loc[UNW_ARM_R0 + edata->data]; + dwarf_get (c, c->loc[UNW_ARM_R13], &c->cfa); + break; + case ARM_EXIDX_CMD_VFP_POP: + /* Skip VFP registers, but be sure to adjust stack */ + for (i = ARM_EXBUF_START (edata->data); i <= ARM_EXBUF_END (edata->data); + i++) + c->cfa += 8; + if (!(edata->data & ARM_EXIDX_VFP_DOUBLE)) + c->cfa += 4; + break; + case ARM_EXIDX_CMD_WREG_POP: + for (i = ARM_EXBUF_START (edata->data); i <= ARM_EXBUF_END (edata->data); + i++) + c->cfa += 8; + break; + case ARM_EXIDX_CMD_WCGR_POP: + for (i = 0; i < 4; i++) + if (edata->data & (1 << i)) + c->cfa += 4; + break; + case ARM_EXIDX_CMD_REFUSED: + case ARM_EXIDX_CMD_RESERVED: + ret = -1; + break; + } + return ret; +} + +/** + * Decodes the given unwind instructions into arm_exbuf_data and calls + * arm_exidx_apply_cmd that applies the command onto the dwarf_cursor. + */ +HIDDEN int +arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c) +{ +#define READ_OP() *buf++ + assert(buf != NULL); + assert(len > 0); + const uint8_t *end = buf + len; + int ret; + struct arm_exbuf_data edata; + + while (buf < end) + { + uint8_t op = READ_OP (); + if ((op & 0xc0) == 0x00) + { + edata.cmd = ARM_EXIDX_CMD_DATA_POP; + edata.data = (((int)op & 0x3f) << 2) + 4; + } + else if ((op & 0xc0) == 0x40) + { + edata.cmd = ARM_EXIDX_CMD_DATA_PUSH; + edata.data = (((int)op & 0x3f) << 2) + 4; + } + else if ((op & 0xf0) == 0x80) + { + uint8_t op2 = READ_OP (); + if (op == 0x80 && op2 == 0x00) + edata.cmd = ARM_EXIDX_CMD_REFUSED; + else + { + edata.cmd = ARM_EXIDX_CMD_REG_POP; + edata.data = ((op & 0xf) << 8) | op2; + edata.data = edata.data << 4; + } + } + else if ((op & 0xf0) == 0x90) + { + if (op == 0x9d || op == 0x9f) + edata.cmd = ARM_EXIDX_CMD_RESERVED; + else + { + edata.cmd = ARM_EXIDX_CMD_REG_TO_SP; + edata.data = op & 0x0f; + } + } + else if ((op & 0xf0) == 0xa0) + { + unsigned end = (op & 0x07); + edata.data = (1 << (end + 1)) - 1; + edata.data = edata.data << 4; + if (op & 0x08) + edata.data |= 1 << 14; + edata.cmd = ARM_EXIDX_CMD_REG_POP; + } + else if (op == ARM_EXTBL_OP_FINISH) + { + edata.cmd = ARM_EXIDX_CMD_FINISH; + buf = end; + } + else if (op == 0xb1) + { + uint8_t op2 = READ_OP (); + if (op2 == 0 || (op2 & 0xf0)) + edata.cmd = ARM_EXIDX_CMD_RESERVED; + else + { + edata.cmd = ARM_EXIDX_CMD_REG_POP; + edata.data = op2 & 0x0f; + } + } + else if (op == 0xb2) + { + uint32_t offset = 0; + uint8_t byte, shift = 0; + do + { + byte = READ_OP (); + offset |= (byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + edata.data = offset * 4 + 0x204; + edata.cmd = ARM_EXIDX_CMD_DATA_POP; + } + else if (op == 0xb3 || op == 0xc8 || op == 0xc9) + { + edata.cmd = ARM_EXIDX_CMD_VFP_POP; + edata.data = READ_OP (); + if (op == 0xc8) + edata.data |= ARM_EXIDX_VFP_SHIFT_16; + if (op != 0xb3) + edata.data |= ARM_EXIDX_VFP_DOUBLE; + } + else if ((op & 0xf8) == 0xb8 || (op & 0xf8) == 0xd0) + { + edata.cmd = ARM_EXIDX_CMD_VFP_POP; + edata.data = 0x80 | (op & 0x07); + if ((op & 0xf8) == 0xd0) + edata.data |= ARM_EXIDX_VFP_DOUBLE; + } + else if (op >= 0xc0 && op <= 0xc5) + { + edata.cmd = ARM_EXIDX_CMD_WREG_POP; + edata.data = 0xa0 | (op & 0x07); + } + else if (op == 0xc6) + { + edata.cmd = ARM_EXIDX_CMD_WREG_POP; + edata.data = READ_OP (); + } + else if (op == 0xc7) + { + uint8_t op2 = READ_OP (); + if (op2 == 0 || (op2 & 0xf0)) + edata.cmd = ARM_EXIDX_CMD_RESERVED; + else + { + edata.cmd = ARM_EXIDX_CMD_WCGR_POP; + edata.data = op2 & 0x0f; + } + } + else + edata.cmd = ARM_EXIDX_CMD_RESERVED; + + ret = arm_exidx_apply_cmd (&edata, c); + if (ret < 0) + return ret; + } + return 0; +} + +/** + * Reads the entry from the given cursor and extracts the unwind instructions + * into buf. Returns the number of the extracted unwind insns or + * -UNW_ESTOPUNWIND if the special bit pattern ARM_EXIDX_CANT_UNWIND (0x1) was + * found. + */ +HIDDEN int +arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf) +{ + int nbuf = 0; + unw_word_t entry = (unw_word_t) c->pi.unwind_info; + unw_word_t addr; + uint32_t data; + + /* An ARM unwind entry consists of a prel31 offset to the start of a + function followed by 31bits of data: + * if set to 0x1: the function cannot be unwound (EXIDX_CANTUNWIND) + * if bit 31 is one: this is a table entry itself (ARM_EXIDX_COMPACT) + * if bit 31 is zero: this is a prel31 offset of the start of the + table entry for this function */ + if (prel31_to_addr(c->as, c->as_arg, entry, &addr) < 0) + return -UNW_EINVAL; + + if ((*c->as->acc.access_mem)(c->as, entry + 4, &data, 0, c->as_arg) < 0) + return -UNW_EINVAL; + + if (data == ARM_EXIDX_CANT_UNWIND) + { + Debug (2, "0x1 [can't unwind]\n"); + nbuf = -UNW_ESTOPUNWIND; + } + else if (data & ARM_EXIDX_COMPACT) + { + Debug (2, "%p compact model %d [%8.8x]\n", (void *)addr, + (data >> 24) & 0x7f, data); + buf[nbuf++] = data >> 16; + buf[nbuf++] = data >> 8; + buf[nbuf++] = data; + } + else + { + unw_word_t extbl_data; + unsigned int n_table_words = 0; + + if (prel31_to_addr(c->as, c->as_arg, entry + 4, &extbl_data) < 0) + return -UNW_EINVAL; + + if ((*c->as->acc.access_mem)(c->as, extbl_data, &data, 0, c->as_arg) < 0) + return -UNW_EINVAL; + + if (data & ARM_EXIDX_COMPACT) + { + int pers = (data >> 24) & 0x0f; + Debug (2, "%p compact model %d [%8.8x]\n", (void *)addr, pers, data); + if (pers == 1 || pers == 2) + { + n_table_words = (data >> 16) & 0xff; + extbl_data += 4; + } + else + buf[nbuf++] = data >> 16; + buf[nbuf++] = data >> 8; + buf[nbuf++] = data; + } + else + { + unw_word_t pers; + if (prel31_to_addr (c->as, c->as_arg, extbl_data, &pers) < 0) + return -UNW_EINVAL; + Debug (2, "%p Personality routine: %8p\n", (void *)addr, + (void *)pers); + if ((*c->as->acc.access_mem)(c->as, extbl_data + 4, &data, 0, + c->as_arg) < 0) + return -UNW_EINVAL; + n_table_words = data >> 24; + buf[nbuf++] = data >> 16; + buf[nbuf++] = data >> 8; + buf[nbuf++] = data; + extbl_data += 8; + } + assert (n_table_words <= 5); + unsigned j; + for (j = 0; j < n_table_words; j++) + { + if ((*c->as->acc.access_mem)(c->as, extbl_data, &data, 0, + c->as_arg) < 0) + return -UNW_EINVAL; + extbl_data += 4; + buf[nbuf++] = data >> 24; + buf[nbuf++] = data >> 16; + buf[nbuf++] = data >> 8; + buf[nbuf++] = data >> 0; + } + } + + if (nbuf > 0 && buf[nbuf - 1] != ARM_EXTBL_OP_FINISH) + buf[nbuf++] = ARM_EXTBL_OP_FINISH; + + return nbuf; +} + +int +arm_search_unwind_table (unw_addr_space_t as, unw_word_t ip, + unw_dyn_info_t *di, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + /* The .ARM.exidx section contains a sorted list of key-value pairs - + the unwind entries. The 'key' is a prel31 offset to the start of a + function. We binary search this section in order to find the + appropriate unwind entry. */ + unw_word_t first = di->u.rti.table_data; + unw_word_t last = di->u.rti.table_data + di->u.rti.table_len - 8; + unw_word_t entry, val; + + if (prel31_to_addr (as, arg, first, &val) < 0 || ip < val) + return -UNW_ENOINFO; + + if (prel31_to_addr (as, arg, last, &val) < 0) + return -UNW_EINVAL; + + if (ip >= val) + { + entry = last; + + if (prel31_to_addr (as, arg, last, &pi->start_ip) < 0) + return -UNW_EINVAL; + + pi->end_ip = di->end_ip -1; + } + else + { + while (first < last - 8) + { + entry = first + (((last - first) / 8 + 1) >> 1) * 8; + + if (prel31_to_addr (as, arg, entry, &val) < 0) + return -UNW_EINVAL; + + if (ip < val) + last = entry; + else + first = entry; + } + + entry = first; + + if (prel31_to_addr (as, arg, entry, &pi->start_ip) < 0) + return -UNW_EINVAL; + + if (prel31_to_addr (as, arg, entry + 8, &pi->end_ip) < 0) + return -UNW_EINVAL; + + pi->end_ip--; + } + + if (need_unwind_info) + { + pi->unwind_info_size = 8; + pi->unwind_info = (void *) entry; + pi->format = UNW_INFO_FORMAT_ARM_EXIDX; + } + return 0; +} + +int +tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, + unw_dyn_info_t *di, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX) + && di->format == UNW_INFO_FORMAT_ARM_EXIDX) + return arm_search_unwind_table (as, ip, di, pi, need_unwind_info, arg); + else if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF) + && di->format != UNW_INFO_FORMAT_ARM_EXIDX) + return dwarf_search_unwind_table (as, ip, di, pi, need_unwind_info, arg); + + return -UNW_ENOINFO; +} + +#ifndef UNW_REMOTE_ONLY +/** + * Callback to dl_iterate_phdr to find infos about the ARM exidx segment. + */ +static int +arm_phdr_cb (struct dl_phdr_info *info, size_t size, void *data) +{ + struct arm_cb_data *cb_data = data; + const Elf_W(Phdr) *p_text = NULL; + const Elf_W(Phdr) *p_arm_exidx = NULL; + const Elf_W(Phdr) *phdr = info->dlpi_phdr; + long n; + + for (n = info->dlpi_phnum; --n >= 0; phdr++) + { + switch (phdr->p_type) + { + case PT_LOAD: + if (cb_data->ip >= phdr->p_vaddr + info->dlpi_addr && + cb_data->ip < phdr->p_vaddr + info->dlpi_addr + phdr->p_memsz) + p_text = phdr; + break; + + case PT_ARM_EXIDX: + p_arm_exidx = phdr; + break; + + default: + break; + } + } + + if (p_text && p_arm_exidx) + { + cb_data->di.format = UNW_INFO_FORMAT_ARM_EXIDX; + cb_data->di.start_ip = p_text->p_vaddr + info->dlpi_addr; + cb_data->di.end_ip = cb_data->di.start_ip + p_text->p_memsz; + cb_data->di.u.rti.name_ptr = (unw_word_t) info->dlpi_name; + cb_data->di.u.rti.table_data = p_arm_exidx->p_vaddr + info->dlpi_addr; + cb_data->di.u.rti.table_len = p_arm_exidx->p_memsz; + return 1; + } + + return 0; +} + +HIDDEN int +arm_find_proc_info (unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, int need_unwind_info, void *arg) +{ + int ret = -1; + intrmask_t saved_mask; + + Debug (14, "looking for IP=0x%lx\n", (long) ip); + + if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)) + ret = dwarf_find_proc_info (as, ip, pi, need_unwind_info, arg); + + if (ret < 0 && UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)) + { + struct arm_cb_data cb_data; + + memset (&cb_data, 0, sizeof (cb_data)); + cb_data.ip = ip; + cb_data.pi = pi; + cb_data.di.format = -1; + + SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask); + ret = dl_iterate_phdr (arm_phdr_cb, &cb_data); + SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); + + if (cb_data.di.format != -1) + ret = arm_search_unwind_table (as, ip, &cb_data.di, pi, + need_unwind_info, arg); + else + ret = -UNW_ENOINFO; + } + + return ret; +} + +HIDDEN void +arm_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) +{ + /* it's a no-op */ +} +#endif /* !UNW_REMOTE_ONLY */ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gget_proc_info.c new file mode 100644 index 0000000..4051a10 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gget_proc_info.c @@ -0,0 +1,41 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + /* We can only unwind using Dwarf into on ARM: return failure code + if it's not present. */ + ret = dwarf_make_proc_info (&c->dwarf); + if (ret < 0) + return ret; + + *pi = c->dwarf.pi; + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gget_save_loc.c new file mode 100644 index 0000000..9fb0704 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gget_save_loc.c @@ -0,0 +1,81 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) +{ + struct cursor *c = (struct cursor *) cursor; + dwarf_loc_t loc; + + loc = DWARF_NULL_LOC; /* default to "not saved" */ + + switch (reg) + { + case UNW_ARM_R0: + case UNW_ARM_R1: + case UNW_ARM_R2: + case UNW_ARM_R3: + case UNW_ARM_R4: + case UNW_ARM_R5: + case UNW_ARM_R6: + case UNW_ARM_R7: + case UNW_ARM_R8: + case UNW_ARM_R9: + case UNW_ARM_R10: + case UNW_ARM_R11: + case UNW_ARM_R12: + case UNW_ARM_R13: + case UNW_ARM_R14: + case UNW_ARM_R15: + loc = c->dwarf.loc[reg - UNW_ARM_R0]; + break; + + default: + break; + } + + memset (sloc, 0, sizeof (*sloc)); + + if (DWARF_IS_NULL_LOC (loc)) + { + sloc->type = UNW_SLT_NONE; + return 0; + } + +#if !defined(UNW_LOCAL_ONLY) + if (DWARF_IS_REG_LOC (loc)) + { + sloc->type = UNW_SLT_REG; + sloc->u.regnum = DWARF_GET_LOC (loc); + } + else +#endif + { + sloc->type = UNW_SLT_MEMORY; + sloc->u.addr = DWARF_GET_LOC (loc); + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gglobal.c new file mode 100644 index 0000000..7b93fbd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gglobal.c @@ -0,0 +1,65 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "dwarf_i.h" + +HIDDEN define_lock (arm_lock); +HIDDEN int tdep_init_done; + +/* Unwinding methods to use. See UNW_METHOD_ enums */ +HIDDEN int unwi_unwind_method = UNW_ARM_METHOD_ALL; + +HIDDEN void +tdep_init (void) +{ + intrmask_t saved_mask; + + sigfillset (&unwi_full_mask); + + lock_acquire (&arm_lock, saved_mask); + { + if (tdep_init_done) + /* another thread else beat us to it... */ + goto out; + + /* read ARM unwind method setting */ + const char* str = getenv ("UNW_ARM_UNWIND_METHOD"); + if (str) + { + unwi_unwind_method = atoi (str); + } + + mi_init (); + + dwarf_init (); + +#ifndef UNW_REMOTE_ONLY + arm_local_addr_space_init (); +#endif + tdep_init_done = 1; /* signal that we're initialized... */ + } + out: + lock_release (&arm_lock, saved_mask); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ginit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ginit.c new file mode 100644 index 0000000..2720d06 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ginit.c @@ -0,0 +1,235 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#include "unwind_i.h" + +#ifdef UNW_REMOTE_ONLY + +/* unw_local_addr_space is a NULL pointer in this case. */ +unw_addr_space_t unw_local_addr_space; + +#else /* !UNW_REMOTE_ONLY */ + +static struct unw_addr_space local_addr_space; + +unw_addr_space_t unw_local_addr_space = &local_addr_space; + +static inline void * +uc_addr (unw_tdep_context_t *uc, int reg) +{ + if (reg >= UNW_ARM_R0 && reg < UNW_ARM_R0 + 16) + return &uc->regs[reg - UNW_ARM_R0]; + else + return NULL; +} + +# ifdef UNW_LOCAL_ONLY + +HIDDEN void * +tdep_uc_addr (unw_tdep_context_t *uc, int reg) +{ + return uc_addr (uc, reg); +} + +# endif /* UNW_LOCAL_ONLY */ + +HIDDEN unw_dyn_info_list_t _U_dyn_info_list; + +/* XXX fix me: there is currently no way to locate the dyn-info list + by a remote unwinder. On ia64, this is done via a special + unwind-table entry. Perhaps something similar can be done with + DWARF2 unwind info. */ + +static int +get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, + void *arg) +{ + *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; + return 0; +} + +#define PAGE_SIZE 4096 +#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1)) + +/* Cache of already validated addresses */ +#define NLGA 4 +static unw_word_t last_good_addr[NLGA]; +static int lga_victim; + +static int +validate_mem (unw_word_t addr) +{ + int i, victim; + size_t len; + + if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr)) + len = PAGE_SIZE; + else + len = PAGE_SIZE * 2; + + addr = PAGE_START(addr); + + if (addr == 0) + return -1; + + for (i = 0; i < NLGA; i++) + { + if (last_good_addr[i] && (addr == last_good_addr[i])) + return 0; + } + + if (msync ((void *) addr, len, MS_ASYNC) == -1) + return -1; + + victim = lga_victim; + for (i = 0; i < NLGA; i++) { + if (!last_good_addr[victim]) { + last_good_addr[victim++] = addr; + return 0; + } + victim = (victim + 1) % NLGA; + } + + /* All slots full. Evict the victim. */ + last_good_addr[victim] = addr; + victim = (victim + 1) % NLGA; + lga_victim = victim; + + return 0; +} + +static int +access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, + void *arg) +{ + /* validate address */ + const struct cursor *c = (const struct cursor *) arg; + if (c && validate_mem(addr)) + return -1; + + if (write) + { + Debug (16, "mem[%x] <- %x\n", addr, *val); + *(unw_word_t *) addr = *val; + } + else + { + *val = *(unw_word_t *) addr; + Debug (16, "mem[%x] -> %x\n", addr, *val); + } + return 0; +} + +static int +access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, + void *arg) +{ + unw_word_t *addr; + unw_tdep_context_t *uc = arg; + + if (unw_is_fpreg (reg)) + goto badreg; + +Debug (16, "reg = %s\n", unw_regname (reg)); + if (!(addr = uc_addr (uc, reg))) + goto badreg; + + if (write) + { + *(unw_word_t *) addr = *val; + Debug (12, "%s <- %x\n", unw_regname (reg), *val); + } + else + { + *val = *(unw_word_t *) addr; + Debug (12, "%s -> %x\n", unw_regname (reg), *val); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} + +static int +access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + unw_tdep_context_t *uc = arg; + unw_fpreg_t *addr; + + if (!unw_is_fpreg (reg)) + goto badreg; + + if (!(addr = uc_addr (uc, reg))) + goto badreg; + + if (write) + { + Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg), + ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); + *(unw_fpreg_t *) addr = *val; + } + else + { + *val = *(unw_fpreg_t *) addr; + Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg), + ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + /* attempt to access a non-preserved register */ + return -UNW_EBADREG; +} + +static int +get_static_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, + void *arg) +{ + return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp); +} + +HIDDEN void +arm_local_addr_space_init (void) +{ + memset (&local_addr_space, 0, sizeof (local_addr_space)); + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; + local_addr_space.acc.find_proc_info = arm_find_proc_info; + local_addr_space.acc.put_unwind_info = arm_put_unwind_info; + local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; + local_addr_space.acc.access_mem = access_mem; + local_addr_space.acc.access_reg = access_reg; + local_addr_space.acc.access_fpreg = access_fpreg; + local_addr_space.acc.resume = arm_local_resume; + local_addr_space.acc.get_proc_name = get_static_proc_name; + unw_flush_cache (&local_addr_space, 0, 0); +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ginit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ginit_local.c new file mode 100644 index 0000000..e13519b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ginit_local.c @@ -0,0 +1,78 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright 2011 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "init.h" + +#ifdef UNW_REMOTE_ONLY + +int +unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) +{ + return -UNW_EINVAL; +} + +#else /* !UNW_REMOTE_ONLY */ + +static int +unw_init_local_common (unw_cursor_t *cursor, unw_context_t *uc, unsigned use_prev_instr) +{ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = unw_local_addr_space; + c->dwarf.as_arg = uc; + + return common_init (c, use_prev_instr); +} + +int +unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) +{ + return unw_init_local_common(cursor, uc, 1); +} + +int +unw_init_local2 (unw_cursor_t *cursor, unw_context_t *uc, int flag) +{ + if (!flag) + { + return unw_init_local_common(cursor, uc, 1); + } + else if (flag == UNW_INIT_SIGNAL_FRAME) + { + return unw_init_local_common(cursor, uc, 0); + } + else + { + return -UNW_EINVAL; + } +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ginit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ginit_remote.c new file mode 100644 index 0000000..9b8ba5b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ginit_remote.c @@ -0,0 +1,45 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "init.h" +#include "unwind_i.h" + +int +unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) +{ +#ifdef UNW_LOCAL_ONLY + return -UNW_EINVAL; +#else /* !UNW_LOCAL_ONLY */ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = as; + c->dwarf.as_arg = as_arg; + return common_init (c, 0); +#endif /* !UNW_LOCAL_ONLY */ +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gos-freebsd.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gos-freebsd.c new file mode 100644 index 0000000..a106922 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gos-freebsd.c @@ -0,0 +1,129 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright 2011 Linaro Limited + Copyright (C) 2012 Tommi Rantala + Copyright 2015 The FreeBSD Foundation + + Portions of this software were developed by Konstantin Belousov + under sponsorship from the FreeBSD Foundation. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include "unwind_i.h" +#include "offsets.h" +#include "ex_tables.h" + +HIDDEN int +arm_handle_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret, fmt; + unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; + struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); + + if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) + return -UNW_EUNSPEC; + fmt = unw_is_signal_frame(cursor); + + c->dwarf.pi_valid = 0; + + if (fmt == UNW_ARM_FRAME_SYSCALL) + { + c->sigcontext_format = ARM_SCF_FREEBSD_SYSCALL; + c->frame_info.frame_type = UNW_ARM_FRAME_SYSCALL; + c->frame_info.cfa_reg_offset = 0; + c->dwarf.loc[UNW_ARM_R7] = c->dwarf.loc[UNW_ARM_R12]; + dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R14], &c->dwarf.ip); + return 1; + } + + c->sigcontext_format = ARM_SCF_FREEBSD_SIGFRAME; + sc_addr = sp_addr; + + /* Save the SP and PC to be able to return execution at this point + later in time (unw_resume). */ + c->sigcontext_sp = c->dwarf.cfa; + c->sigcontext_pc = c->dwarf.ip; + + c->sigcontext_addr = sc_addr; + c->frame_info.frame_type = UNW_ARM_FRAME_SIGRETURN; + c->frame_info.cfa_reg_offset = sc_addr - sp_addr; + + /* Update the dwarf cursor. + Set the location of the registers to the corresponding addresses of the + uc_mcontext / sigcontext structure contents. */ +#define ROFF(n) (FREEBSD_SC_UCONTEXT_OFF + FREEBSD_UC_MCONTEXT_OFF + \ + FREEBSD_MC_R0_OFF + (n) * 4) +#define SL(n) \ + c->dwarf.loc[UNW_ARM_R ## n] = DWARF_LOC (sc_addr + ROFF(n), 0); + SL(0); SL(1); SL(2); SL(3); SL(4); SL(5); SL(6); SL(7); + SL(8); SL(9); SL(10); SL(11); SL(12); SL(13); SL(14); SL(15); +#undef SL +#undef ROFF + + /* Set SP/CFA and PC/IP. */ + dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R13], &c->dwarf.cfa); + dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip); + + return 1; +} + +/* Returns 1 in case of a non-RT signal frame and 2 in case of a RT signal + frame. */ +int +unw_is_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + unw_word_t w0, w1, w2, w3, ip; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + int ret; + + as = c->dwarf.as; + a = unw_get_accessors_int (as); + arg = c->dwarf.as_arg; + + ip = c->dwarf.ip; + + if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0) + return ret; + if ((ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0) + return ret; + if ((ret = (*a->access_mem) (as, ip + 8, &w2, 0, arg)) < 0) + return ret; + if ((ret = (*a->access_mem) (as, ip + 12, &w3, 0, arg)) < 0) + return ret; + + if (w0 == 0xe1a0000d && w1 == 0xe2800040 && w2 == 0xe59f700c && + w3 == 0xef0001a1) + return UNW_ARM_FRAME_SIGRETURN; + + if ((ret = (*a->access_mem) (as, ip - 4, &w0, 0, arg)) < 0) + return ret; + if (w0 == 0xef000000) + return UNW_ARM_FRAME_SYSCALL; + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gos-linux.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gos-linux.c new file mode 100644 index 0000000..260e086 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gos-linux.c @@ -0,0 +1,182 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright 2011 Linaro Limited + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include "unwind_i.h" +#include "offsets.h" + +HIDDEN int +arm_handle_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; + struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); + + if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) + return -UNW_EUNSPEC; + + /* Obtain signal frame type (non-RT or RT). */ + ret = unw_is_signal_frame (cursor); + + /* Save the SP and PC to be able to return execution at this point + later in time (unw_resume). */ + c->sigcontext_sp = c->dwarf.cfa; + c->sigcontext_pc = c->dwarf.ip; + + /* Since kernel version 2.6.18 the non-RT signal frame starts with a + ucontext while the RT signal frame starts with a siginfo, followed + by a sigframe whose first element is an ucontext. + Prior 2.6.18 the non-RT signal frame starts with a sigcontext while + the RT signal frame starts with two pointers followed by a siginfo + and an ucontext. The first pointer points to the start of the siginfo + structure and the second one to the ucontext structure. */ + + if (ret == 1) + { + /* Handle non-RT signal frames. Check if the first word on the stack + is the magic number. */ + if (sp == 0x5ac3c35a) + { + c->sigcontext_format = ARM_SCF_LINUX_SIGFRAME; + sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF; + } + else + { + c->sigcontext_format = ARM_SCF_LINUX_OLD_SIGFRAME; + sc_addr = sp_addr; + } + } + else if (ret == 2) + { + /* Handle RT signal frames. Check if the first word on the stack is a + pointer to the siginfo structure. */ + if (sp == sp_addr + 8) + { + c->sigcontext_format = ARM_SCF_LINUX_OLD_RT_SIGFRAME; + sc_addr = sp_addr + 8 + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF; + } + else + { + c->sigcontext_format = ARM_SCF_LINUX_RT_SIGFRAME; + sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF; + } + } + else + return -UNW_EUNSPEC; + + c->sigcontext_addr = sc_addr; + c->frame_info.frame_type = UNW_ARM_FRAME_SIGRETURN; + c->frame_info.cfa_reg_offset = sc_addr - sp_addr; + + /* Update the dwarf cursor. + Set the location of the registers to the corresponding addresses of the + uc_mcontext / sigcontext structure contents. */ + c->dwarf.loc[UNW_ARM_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); + c->dwarf.loc[UNW_ARM_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); + c->dwarf.loc[UNW_ARM_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0); + c->dwarf.loc[UNW_ARM_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0); + c->dwarf.loc[UNW_ARM_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0); + c->dwarf.loc[UNW_ARM_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0); + c->dwarf.loc[UNW_ARM_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0); + c->dwarf.loc[UNW_ARM_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0); + c->dwarf.loc[UNW_ARM_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0); + c->dwarf.loc[UNW_ARM_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0); + c->dwarf.loc[UNW_ARM_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0); + c->dwarf.loc[UNW_ARM_R11] = DWARF_LOC (sc_addr + LINUX_SC_FP_OFF, 0); + c->dwarf.loc[UNW_ARM_R12] = DWARF_LOC (sc_addr + LINUX_SC_IP_OFF, 0); + c->dwarf.loc[UNW_ARM_R13] = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0); + c->dwarf.loc[UNW_ARM_R14] = DWARF_LOC (sc_addr + LINUX_SC_LR_OFF, 0); + c->dwarf.loc[UNW_ARM_R15] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); + + /* Set SP/CFA and PC/IP. */ + dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R13], &c->dwarf.cfa); + dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip); + + c->dwarf.pi_valid = 0; + + return 1; +} + +#define ARM_NR_sigreturn 119 +#define ARM_NR_rt_sigreturn 173 +#define ARM_NR_OABI_SYSCALL_BASE 0x900000 + +/* ARM EABI sigreturn (the syscall number is loaded into r7) */ +#define MOV_R7_SIGRETURN (0xe3a07000UL | ARM_NR_sigreturn) +#define MOV_R7_RT_SIGRETURN (0xe3a07000UL | ARM_NR_rt_sigreturn) + +/* ARM OABI sigreturn (using SWI) */ +#define ARM_SIGRETURN \ + (0xef000000UL | ARM_NR_sigreturn | ARM_NR_OABI_SYSCALL_BASE) +#define ARM_RT_SIGRETURN \ + (0xef000000UL | ARM_NR_rt_sigreturn | ARM_NR_OABI_SYSCALL_BASE) + +/* Thumb sigreturn (two insns, syscall number is loaded into r7) */ +#define THUMB_SIGRETURN (0xdf00UL << 16 | 0x2700 | ARM_NR_sigreturn) +#define THUMB_RT_SIGRETURN (0xdf00UL << 16 | 0x2700 | ARM_NR_rt_sigreturn) + +/* Thumb2 sigreturn (mov.w r7, $SYS_ify(rt_sigreturn/sigreturn)) */ +#define THUMB2_SIGRETURN (((0x0700 | ARM_NR_sigreturn) << 16) | \ + 0xf04f) +#define THUMB2_RT_SIGRETURN (((0x0700 | ARM_NR_rt_sigreturn) << 16) | \ + 0xf04f) +/* TODO: with different toolchains, there are a lot more possibilities */ + +/* Returns 1 in case of a non-RT signal frame and 2 in case of a RT signal + frame. */ +int +unw_is_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + unw_word_t w0, ip; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + int ret; + + as = c->dwarf.as; + a = unw_get_accessors_int (as); + arg = c->dwarf.as_arg; + + /* The least bit denotes thumb/arm mode. Do not read there. */ + ip = c->dwarf.ip & ~0x1; + + if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0) + return ret; + + /* Return 1 if the IP points to a non-RT sigreturn sequence. */ + if (w0 == MOV_R7_SIGRETURN || w0 == ARM_SIGRETURN || w0 == THUMB_SIGRETURN + || w0 == THUMB2_SIGRETURN) + return 1; + /* Return 2 if the IP points to a RT sigreturn sequence. */ + else if (w0 == MOV_R7_RT_SIGRETURN || w0 == ARM_RT_SIGRETURN + || w0 == THUMB_RT_SIGRETURN || w0 == THUMB2_RT_SIGRETURN) + return 2; + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gos-other.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gos-other.c new file mode 100644 index 0000000..73c102c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gos-other.c @@ -0,0 +1,48 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright 2011 Linaro Limited + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include "unwind_i.h" +#include "offsets.h" + +HIDDEN int +arm_handle_signal_frame (unw_cursor_t *cursor) +{ + return -UNW_EUNSPEC; +} + +int +unw_is_signal_frame (unw_cursor_t *cursor) +{ +#if defined(__QNX__) + /* Not supported yet */ + return 0; +#else + printf ("%s: implement me\n", __FUNCTION__); + return -UNW_ENOINFO; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Greg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Greg_states_iterate.c new file mode 100644 index 0000000..a17dc1b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Greg_states_iterate.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_reg_states_iterate (unw_cursor_t *cursor, + unw_reg_states_callback cb, void *token) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_reg_states_iterate (&c->dwarf, cb, token); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gregs.c new file mode 100644 index 0000000..0d52f0b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gregs.c @@ -0,0 +1,83 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +HIDDEN int +tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + int write) +{ + dwarf_loc_t loc = DWARF_NULL_LOC; + + switch (reg) + { + case UNW_ARM_R15: + if (write) + c->dwarf.ip = *valp; /* update the IP cache */ + case UNW_ARM_R0: + case UNW_ARM_R1: + case UNW_ARM_R2: + case UNW_ARM_R3: + case UNW_ARM_R4: + case UNW_ARM_R5: + case UNW_ARM_R6: + case UNW_ARM_R7: + case UNW_ARM_R8: + case UNW_ARM_R9: + case UNW_ARM_R10: + case UNW_ARM_R11: + case UNW_ARM_R12: + case UNW_ARM_R14: + loc = c->dwarf.loc[reg - UNW_ARM_R0]; + break; + + case UNW_ARM_R13: + case UNW_ARM_CFA: + if (write) + return -UNW_EREADONLYREG; + *valp = c->dwarf.cfa; + return 0; + + /* FIXME: Initialise coprocessor & shadow registers? */ + + default: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; + } + + if (write) + return dwarf_put (&c->dwarf, loc, *valp); + else + return dwarf_get (&c->dwarf, loc, valp); +} + +/* FIXME for ARM. */ + +HIDDEN int +tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, + int write) +{ + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gresume.c new file mode 100644 index 0000000..a828862 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gresume.c @@ -0,0 +1,154 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright 2011 Linaro Limited + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "offsets.h" + +#ifndef UNW_REMOTE_ONLY + +HIDDEN inline int +arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ +#ifdef __linux__ + struct cursor *c = (struct cursor *) cursor; + unw_tdep_context_t *uc = c->dwarf.as_arg; + + if (c->sigcontext_format == ARM_SCF_NONE) + { + /* Since there are no signals involved here we restore the non scratch + registers only. */ + unsigned long regs[10]; + regs[0] = uc->regs[4]; + regs[1] = uc->regs[5]; + regs[2] = uc->regs[6]; + regs[3] = uc->regs[7]; + regs[4] = uc->regs[8]; + regs[5] = uc->regs[9]; + regs[6] = uc->regs[10]; + regs[7] = uc->regs[11]; /* FP */ + regs[8] = uc->regs[13]; /* SP */ + regs[9] = uc->regs[14]; /* LR */ + + struct regs_overlay { + char x[sizeof(regs)]; + }; + + asm __volatile__ ( + "ldmia %0, {r4-r12, lr}\n" + "mov sp, r12\n" + "bx lr\n" + : : "r" (regs), + "m" (*(struct regs_overlay *)regs) + ); + } + else + { + /* In case a signal frame is involved, we're using its trampoline which + calls sigreturn. */ + struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; + sc->arm_r0 = uc->regs[0]; + sc->arm_r1 = uc->regs[1]; + sc->arm_r2 = uc->regs[2]; + sc->arm_r3 = uc->regs[3]; + sc->arm_r4 = uc->regs[4]; + sc->arm_r5 = uc->regs[5]; + sc->arm_r6 = uc->regs[6]; + sc->arm_r7 = uc->regs[7]; + sc->arm_r8 = uc->regs[8]; + sc->arm_r9 = uc->regs[9]; + sc->arm_r10 = uc->regs[10]; + sc->arm_fp = uc->regs[11]; /* FP */ + sc->arm_ip = uc->regs[12]; /* IP */ + sc->arm_sp = uc->regs[13]; /* SP */ + sc->arm_lr = uc->regs[14]; /* LR */ + sc->arm_pc = uc->regs[15]; /* PC */ + /* clear the ITSTATE bits. */ + sc->arm_cpsr &= 0xf9ff03ffUL; + + /* Set the SP and the PC in order to continue execution at the modified + trampoline which restores the signal mask and the registers. */ + asm __volatile__ ( + "mov sp, %0\n" + "bx %1\n" + : : "r" (c->sigcontext_sp), "r" (c->sigcontext_pc) + ); + } + unreachable(); +#else + printf ("%s: implement me\n", __FUNCTION__); +#endif + return -UNW_EINVAL; +} + +#endif /* !UNW_REMOTE_ONLY */ + +static inline void +establish_machine_state (struct cursor *c) +{ + unw_addr_space_t as = c->dwarf.as; + void *arg = c->dwarf.as_arg; + unw_fpreg_t fpval; + unw_word_t val; + int reg; + + Debug (8, "copying out cursor state\n"); + + for (reg = 0; reg <= UNW_REG_LAST; ++reg) + { + Debug (16, "copying %s %d\n", unw_regname (reg), reg); + if (unw_is_fpreg (reg)) + { + if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) + as->acc.access_fpreg (as, reg, &fpval, 1, arg); + } + else + { + if (tdep_access_reg (c, reg, &val, 0) >= 0) + as->acc.access_reg (as, reg, &val, 1, arg); + } + } +} + +int +unw_resume (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + + Debug (1, "(cursor=%p)\n", c); + + if (!c->dwarf.ip) + { + /* This can happen easily when the frame-chain gets truncated + due to bad or missing unwind-info. */ + Debug (1, "refusing to resume execution at address 0\n"); + return -UNW_EINVAL; + } + + establish_machine_state (c); + + return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, + c->dwarf.as_arg); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gstash_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gstash_frame.c new file mode 100644 index 0000000..c5a76b8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gstash_frame.c @@ -0,0 +1,90 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY + Copyright (C) 2014 CERN and Aalto University + Contributed by Filip Nyback + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +HIDDEN void +tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs) +{ + struct cursor *c = (struct cursor *) dwarf_to_cursor (d); + unw_tdep_frame_t *f = &c->frame_info; + + Debug (4, "ip=0x%x cfa=0x%x type %d cfa [where=%d val=%d] cfaoff=%d" + " ra=0x%x r7 [where=%d val=%d @0x%x] lr [where=%d val=%d @0x%x] " + "sp [where=%d val=%d @0x%x]\n", + d->ip, d->cfa, f->frame_type, + rs->reg.where[DWARF_CFA_REG_COLUMN], + rs->reg.val[DWARF_CFA_REG_COLUMN], + rs->reg.val[DWARF_CFA_OFF_COLUMN], + DWARF_GET_LOC(d->loc[rs->ret_addr_column]), + rs->reg.where[R7], rs->reg.val[R7], DWARF_GET_LOC(d->loc[R7]), + rs->reg.where[LR], rs->reg.val[LR], DWARF_GET_LOC(d->loc[LR]), + rs->reg.where[SP], rs->reg.val[SP], DWARF_GET_LOC(d->loc[SP])); + + /* A standard frame is defined as: + - CFA is register-relative offset off R7 or SP; + - Return address is saved in LR; + - R7 is unsaved or saved at CFA+offset, offset != -1; + - LR is unsaved or saved at CFA+offset, offset != -1; + - SP is unsaved or saved at CFA+offset, offset != -1. */ + if (f->frame_type == UNW_ARM_FRAME_OTHER + && (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG) + && (rs->reg.val[DWARF_CFA_REG_COLUMN] == R7 + || rs->reg.val[DWARF_CFA_REG_COLUMN] == SP) + && labs(rs->reg.val[DWARF_CFA_OFF_COLUMN]) < (1 << 29) + && rs->ret_addr_column == LR + && (rs->reg.where[R7] == DWARF_WHERE_UNDEF + || rs->reg.where[R7] == DWARF_WHERE_SAME + || (rs->reg.where[R7] == DWARF_WHERE_CFAREL + && labs(rs->reg.val[R7]) < (1 << 29) + && rs->reg.val[R7]+1 != 0)) + && (rs->reg.where[LR] == DWARF_WHERE_UNDEF + || rs->reg.where[LR] == DWARF_WHERE_SAME + || (rs->reg.where[LR] == DWARF_WHERE_CFAREL + && labs(rs->reg.val[LR]) < (1 << 29) + && rs->reg.val[LR]+1 != 0)) + && (rs->reg.where[SP] == DWARF_WHERE_UNDEF + || rs->reg.where[SP] == DWARF_WHERE_SAME + || (rs->reg.where[SP] == DWARF_WHERE_CFAREL + && labs(rs->reg.val[SP]) < (1 << 29) + && rs->reg.val[SP]+1 != 0))) + { + /* Save information for a standard frame. */ + f->frame_type = UNW_ARM_FRAME_STANDARD; + f->cfa_reg_sp = (rs->reg.val[DWARF_CFA_REG_COLUMN] == SP); + f->cfa_reg_offset = rs->reg.val[DWARF_CFA_OFF_COLUMN]; + if (rs->reg.where[R7] == DWARF_WHERE_CFAREL) + f->r7_cfa_offset = rs->reg.val[R7]; + if (rs->reg.where[LR] == DWARF_WHERE_CFAREL) + f->lr_cfa_offset = rs->reg.val[LR]; + if (rs->reg.where[SP] == DWARF_WHERE_CFAREL) + f->sp_cfa_offset = rs->reg.val[SP]; + Debug (4, " standard frame\n"); + } + else + Debug (4, " unusual frame\n"); +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gstep.c new file mode 100644 index 0000000..516c9f4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gstep.c @@ -0,0 +1,192 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright 2011 Linaro Limited + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "offsets.h" +#include "ex_tables.h" + +#include + +#define arm_exidx_step UNW_OBJ(arm_exidx_step) + +static inline int +arm_exidx_step (struct cursor *c) +{ + unw_word_t old_ip, old_cfa; + uint8_t buf[32]; + int ret; + + old_ip = c->dwarf.ip; + old_cfa = c->dwarf.cfa; + + /* mark PC unsaved */ + c->dwarf.loc[UNW_ARM_R15] = DWARF_NULL_LOC; + unw_word_t ip = c->dwarf.ip; + if (c->dwarf.use_prev_instr) + --ip; + + /* check dynamic info first --- it overrides everything else */ + ret = unwi_find_dynamic_proc_info (c->dwarf.as, ip, &c->dwarf.pi, 1, + c->dwarf.as_arg); + if (ret == -UNW_ENOINFO) + { + if ((ret = tdep_find_proc_info (&c->dwarf, ip, 1)) < 0) + return ret; + } + + if (c->dwarf.pi.format != UNW_INFO_FORMAT_ARM_EXIDX) + return -UNW_ENOINFO; + + ret = arm_exidx_extract (&c->dwarf, buf); + if (ret == -UNW_ESTOPUNWIND) + return 0; + else if (ret < 0) + return ret; + + ret = arm_exidx_decode (buf, ret, &c->dwarf); + if (ret < 0) + return ret; + + if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa) + { + Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n", + __FUNCTION__, (long) c->dwarf.ip); + return -UNW_EBADFRAME; + } + + c->dwarf.pi_valid = 0; + + return (c->dwarf.ip == 0) ? 0 : 1; +} + +int +unw_step (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret = -UNW_EUNSPEC; + + Debug (1, "(cursor=%p)\n", c); + + /* Check if this is a signal frame. */ + if (unw_is_signal_frame (cursor) > 0) + return arm_handle_signal_frame (cursor); + +#ifdef CONFIG_DEBUG_FRAME + /* First, try DWARF-based unwinding. */ + if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)) + { + ret = dwarf_step (&c->dwarf); + Debug(1, "dwarf_step()=%d\n", ret); + + if (likely (ret > 0)) + return 1; + else if (unlikely (ret == -UNW_ESTOPUNWIND)) + return ret; + + if (ret < 0 && ret != -UNW_ENOINFO) + { + Debug (2, "returning %d\n", ret); + return ret; + } + } +#endif /* CONFIG_DEBUG_FRAME */ + + /* Next, try extbl-based unwinding. */ + if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)) + { + ret = arm_exidx_step (c); + if (ret > 0) + return 1; + if (ret == -UNW_ESTOPUNWIND || ret == 0) + return ret; + } + + /* Fall back on APCS frame parsing. + Note: This won't work in case the ARM EABI is used. */ +#ifdef __FreeBSD__ + if (0) +#else + if (unlikely (ret < 0)) +#endif + { + if (UNW_TRY_METHOD(UNW_ARM_METHOD_FRAME)) + { + Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); + ret = UNW_ESUCCESS; + /* DWARF unwinding failed, try to follow APCS/optimized APCS frame chain */ + unw_word_t instr, i; + dwarf_loc_t ip_loc, fp_loc; + unw_word_t frame; + /* Mark all registers unsaved, since we don't know where + they are saved (if at all), except for the EBP and + EIP. */ + if (dwarf_get(&c->dwarf, c->dwarf.loc[UNW_ARM_R11], &frame) < 0) + { + return 0; + } + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) { + c->dwarf.loc[i] = DWARF_NULL_LOC; + } + if (frame) + { + if (dwarf_get(&c->dwarf, DWARF_LOC(frame, 0), &instr) < 0) + { + return 0; + } + instr -= 8; + if (dwarf_get(&c->dwarf, DWARF_LOC(instr, 0), &instr) < 0) + { + return 0; + } + if ((instr & 0xFFFFD800) == 0xE92DD800) + { + /* Standard APCS frame. */ + ip_loc = DWARF_LOC(frame - 4, 0); + fp_loc = DWARF_LOC(frame - 12, 0); + } + else + { + /* Codesourcery optimized normal frame. */ + ip_loc = DWARF_LOC(frame, 0); + fp_loc = DWARF_LOC(frame - 4, 0); + } + if (dwarf_get(&c->dwarf, ip_loc, &c->dwarf.ip) < 0) + { + return 0; + } + c->dwarf.loc[UNW_ARM_R12] = ip_loc; + c->dwarf.loc[UNW_ARM_R11] = fp_loc; + c->dwarf.pi_valid = 0; + Debug(15, "ip=%x\n", c->dwarf.ip); + } + else + { + ret = -UNW_ENOINFO; + } + } + } + return ret == -UNW_ENOINFO ? 0 : ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gtrace.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gtrace.c new file mode 100644 index 0000000..2f27752 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Gtrace.c @@ -0,0 +1,557 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY + Copyright (C) 2014 CERN and Aalto University + Contributed by Filip Nyback + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "offsets.h" +#include +#include + +#pragma weak pthread_once +#pragma weak pthread_key_create +#pragma weak pthread_getspecific +#pragma weak pthread_setspecific + +/* Initial hash table size. Table expands by 2 bits (times four). */ +#define HASH_MIN_BITS 14 + +typedef struct +{ + unw_tdep_frame_t *frames; + size_t log_size; + size_t used; + size_t dtor_count; /* Counts how many times our destructor has already + been called. */ +} unw_trace_cache_t; + +static const unw_tdep_frame_t empty_frame = { 0, UNW_ARM_FRAME_OTHER, -1, -1, 0, -1, -1, -1 }; +static define_lock (trace_init_lock); +static pthread_once_t trace_cache_once = PTHREAD_ONCE_INIT; +static sig_atomic_t trace_cache_once_happen; +static pthread_key_t trace_cache_key; +static struct mempool trace_cache_pool; +static __thread unw_trace_cache_t *tls_cache; +static __thread int tls_cache_destroyed; + +/* Free memory for a thread's trace cache. */ +static void +trace_cache_free (void *arg) +{ + unw_trace_cache_t *cache = arg; + if (++cache->dtor_count < PTHREAD_DESTRUCTOR_ITERATIONS) + { + /* Not yet our turn to get destroyed. Re-install ourselves into the key. */ + pthread_setspecific(trace_cache_key, cache); + Debug(5, "delayed freeing cache %p (%zx to go)\n", cache, + PTHREAD_DESTRUCTOR_ITERATIONS - cache->dtor_count); + return; + } + tls_cache_destroyed = 1; + tls_cache = NULL; + munmap (cache->frames, (1u << cache->log_size) * sizeof(unw_tdep_frame_t)); + mempool_free (&trace_cache_pool, cache); + Debug(5, "freed cache %p\n", cache); +} + +/* Initialise frame tracing for threaded use. */ +static void +trace_cache_init_once (void) +{ + pthread_key_create (&trace_cache_key, &trace_cache_free); + mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0); + trace_cache_once_happen = 1; +} + +static unw_tdep_frame_t * +trace_cache_buckets (size_t n) +{ + unw_tdep_frame_t *frames; + size_t i; + + GET_MEMORY(frames, n * sizeof (unw_tdep_frame_t)); + if (likely(frames != NULL)) + for (i = 0; i < n; ++i) + frames[i] = empty_frame; + + return frames; +} + +/* Allocate and initialise hash table for frame cache lookups. + Returns the cache initialised with (1u << HASH_LOW_BITS) hash + buckets, or NULL if there was a memory allocation problem. */ +static unw_trace_cache_t * +trace_cache_create (void) +{ + unw_trace_cache_t *cache; + + if (tls_cache_destroyed) + { + /* The current thread is in the process of exiting. Don't recreate + cache, as we wouldn't have another chance to free it. */ + Debug(5, "refusing to reallocate cache: " + "thread-locals are being deallocated\n"); + return NULL; + } + + if (! (cache = mempool_alloc(&trace_cache_pool))) + { + Debug(5, "failed to allocate cache\n"); + return NULL; + } + + if (! (cache->frames = trace_cache_buckets(1u << HASH_MIN_BITS))) + { + Debug(5, "failed to allocate buckets\n"); + mempool_free(&trace_cache_pool, cache); + return NULL; + } + + cache->log_size = HASH_MIN_BITS; + cache->used = 0; + cache->dtor_count = 0; + tls_cache_destroyed = 0; /* Paranoia: should already be 0. */ + Debug(5, "allocated cache %p\n", cache); + return cache; +} + +/* Expand the hash table in the frame cache if possible. This always + quadruples the hash size, and clears all previous frame entries. */ +static int +trace_cache_expand (unw_trace_cache_t *cache) +{ + size_t old_size = (1u << cache->log_size); + size_t new_log_size = cache->log_size + 2; + unw_tdep_frame_t *new_frames = trace_cache_buckets (1u << new_log_size); + + if (unlikely(! new_frames)) + { + Debug(5, "failed to expand cache to 2^%u buckets\n", new_log_size); + return -UNW_ENOMEM; + } + + Debug(5, "expanded cache from 2^%u to 2^%u buckets\n", cache->log_size, + new_log_size); + munmap(cache->frames, old_size * sizeof(unw_tdep_frame_t)); + cache->frames = new_frames; + cache->log_size = new_log_size; + cache->used = 0; + return 0; +} + +static unw_trace_cache_t * +trace_cache_get_unthreaded (void) +{ + unw_trace_cache_t *cache; + intrmask_t saved_mask; + static unw_trace_cache_t *global_cache = NULL; + lock_acquire (&trace_init_lock, saved_mask); + if (! global_cache) + { + mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0); + global_cache = trace_cache_create (); + } + cache = global_cache; + lock_release (&trace_init_lock, saved_mask); + Debug(5, "using cache %p\n", cache); + return cache; +} + +/* Get the frame cache for the current thread. Create it if there is none. */ +static unw_trace_cache_t * +trace_cache_get (void) +{ + unw_trace_cache_t *cache; + if (likely (pthread_once != NULL)) + { + pthread_once(&trace_cache_once, &trace_cache_init_once); + if (!trace_cache_once_happen) + { + return trace_cache_get_unthreaded(); + } + if (! (cache = tls_cache)) + { + cache = trace_cache_create(); + pthread_setspecific(trace_cache_key, cache); + tls_cache = cache; + } + Debug(5, "using cache %p\n", cache); + return cache; + } + else + { + return trace_cache_get_unthreaded(); + } +} + +/* Initialise frame properties for address cache slot F at address + PC using current CFA, R7 and SP values. Modifies CURSOR to + that location, performs one unw_step(), and fills F with what + was discovered about the location. Returns F. + + FIXME: This probably should tell DWARF handling to never evaluate + or use registers other than R7, SP and PC in case there is + highly unusual unwind info which uses these creatively. */ +static unw_tdep_frame_t * +trace_init_addr (unw_tdep_frame_t *f, + unw_cursor_t *cursor, + unw_word_t cfa, + unw_word_t pc, + unw_word_t r7, + unw_word_t sp) +{ + struct cursor *c = (struct cursor *) cursor; + struct dwarf_cursor *d = &c->dwarf; + int ret = -UNW_EINVAL; + + /* Initialise frame properties: unknown, not last. */ + f->virtual_address = pc; + f->frame_type = UNW_ARM_FRAME_OTHER; + f->last_frame = 0; + f->cfa_reg_sp = -1; + f->cfa_reg_offset = 0; + f->r7_cfa_offset = -1; + f->lr_cfa_offset = -1; + f->sp_cfa_offset = -1; + + /* Reinitialise cursor to this instruction - but undo next/prev RIP + adjustment because unw_step will redo it - and force PC, R7 and + SP into register locations (=~ ucontext we keep), then set + their desired values. Then perform the step. */ + d->ip = pc + d->use_prev_instr; + d->cfa = cfa; + d->loc[UNW_ARM_R7] = DWARF_REG_LOC (d, UNW_ARM_R7); + d->loc[UNW_ARM_R13] = DWARF_REG_LOC (d, UNW_ARM_R13); + d->loc[UNW_ARM_R15] = DWARF_REG_LOC (d, UNW_ARM_R15); + c->frame_info = *f; + + if (likely(dwarf_put (d, d->loc[UNW_ARM_R7], r7) >= 0) + && likely(dwarf_put (d, d->loc[UNW_ARM_R13], sp) >= 0) + && likely(dwarf_put (d, d->loc[UNW_ARM_R15], pc) >= 0) + && likely((ret = unw_step (cursor)) >= 0)) + *f = c->frame_info; + + /* If unw_step() stopped voluntarily, remember that, even if it + otherwise could not determine anything useful. This avoids + failing trace if we hit frames without unwind info, which is + common for the outermost frame (CRT stuff) on many systems. + This avoids failing trace in very common circumstances; failing + to unw_step() loop wouldn't produce any better result. */ + if (ret == 0) + f->last_frame = -1; + + Debug (3, "frame va %x type %d last %d cfa %s+%d r7 @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n", + f->virtual_address, f->frame_type, f->last_frame, + f->cfa_reg_sp ? "sp" : "r7", f->cfa_reg_offset, + f->r7_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset); + + return f; +} + +/* Look up and if necessary fill in frame attributes for address PC + in CACHE using current CFA, R7 and SP values. Uses CURSOR to + perform any unwind steps necessary to fill the cache. Returns the + frame cache slot which describes RIP. */ +static unw_tdep_frame_t * +trace_lookup (unw_cursor_t *cursor, + unw_trace_cache_t *cache, + unw_word_t cfa, + unw_word_t pc, + unw_word_t r7, + unw_word_t sp) +{ + /* First look up for previously cached information using cache as + linear probing hash table with probe step of 1. Majority of + lookups should be completed within few steps, but it is very + important the hash table does not fill up, or performance falls + off the cliff. */ + uint32_t i, addr; + uint32_t cache_size = 1u << cache->log_size; + uint32_t slot = ((pc * 0x9e3779b9) >> 11) & (cache_size-1); + unw_tdep_frame_t *frame; + + for (i = 0; i < 16; ++i) + { + frame = &cache->frames[slot]; + addr = frame->virtual_address; + + /* Return if we found the address. */ + if (likely(addr == pc)) + { + Debug (4, "found address after %d steps\n", i); + return frame; + } + + /* If slot is empty, reuse it. */ + if (likely(! addr)) + break; + + /* Linear probe to next slot candidate, step = 1. */ + if (++slot >= cache_size) + slot -= cache_size; + } + + /* If we collided after 16 steps, or if the hash is more than half + full, force the hash to expand. Fill the selected slot, whether + it's free or collides. Note that hash expansion drops previous + contents; further lookups will refill the hash. */ + Debug (4, "updating slot %u after %d steps, replacing 0x%x\n", slot, i, addr); + if (unlikely(addr || cache->used >= cache_size / 2)) + { + if (unlikely(trace_cache_expand (cache) < 0)) + return NULL; + + cache_size = 1u << cache->log_size; + slot = ((pc * 0x9e3779b9) >> 11) & (cache_size-1); + frame = &cache->frames[slot]; + addr = frame->virtual_address; + } + + if (! addr) + ++cache->used; + + return trace_init_addr (frame, cursor, cfa, pc, r7, sp); +} + +/* Fast stack backtrace for ARM. + + This is used by backtrace() implementation to accelerate frequent + queries for current stack, without any desire to unwind. It fills + BUFFER with the call tree from CURSOR upwards for at most SIZE + stack levels. The first frame, backtrace itself, is omitted. When + called, SIZE should give the maximum number of entries that can be + stored into BUFFER. Uses an internal thread-specific cache to + accelerate queries. + + The caller should fall back to a unw_step() loop if this function + fails by returning -UNW_ESTOPUNWIND, meaning the routine hit a + stack frame that is too complex to be traced in the fast path. + + This function is tuned for clients which only need to walk the + stack to get the call tree as fast as possible but without any + other details, for example profilers sampling the stack thousands + to millions of times per second. The routine handles the most + common ARM ABI stack layouts: CFA is R7 or SP plus/minus + constant offset, return address is in LR, and R7, LR and SP are + either unchanged or saved on stack at constant offset from the CFA; + the signal return frame; and frames without unwind info provided + they are at the outermost (final) frame or can conservatively be + assumed to be frame-pointer based. + + Any other stack layout will cause the routine to give up. There + are only a handful of relatively rarely used functions which do + not have a stack in the standard form: vfork, longjmp, setcontext + and _dl_runtime_profile on common linux systems for example. + + On success BUFFER and *SIZE reflect the trace progress up to *SIZE + stack levels or the outermost frame, which ever is less. It may + stop short of outermost frame if unw_step() loop would also do so, + e.g. if there is no more unwind information; this is not reported + as an error. + + The function returns a negative value for errors, -UNW_ESTOPUNWIND + if tracing stopped because of an unusual frame unwind info. The + BUFFER and *SIZE reflect tracing progress up to the error frame. + + Callers of this function would normally look like this: + + unw_cursor_t cur; + unw_context_t ctx; + void addrs[128]; + int depth = 128; + int ret; + + unw_getcontext(&ctx); + unw_init_local(&cur, &ctx); + if ((ret = unw_tdep_trace(&cur, addrs, &depth)) < 0) + { + depth = 0; + unw_getcontext(&ctx); + unw_init_local(&cur, &ctx); + while ((ret = unw_step(&cur)) > 0 && depth < 128) + { + unw_word_t ip; + unw_get_reg(&cur, UNW_REG_IP, &ip); + addresses[depth++] = (void *) ip; + } + } +*/ +HIDDEN int +tdep_trace (unw_cursor_t *cursor, void **buffer, int *size) +{ + struct cursor *c = (struct cursor *) cursor; + struct dwarf_cursor *d = &c->dwarf; + unw_trace_cache_t *cache; + unw_word_t sp, pc, cfa, r7, lr; + int maxdepth = 0; + int depth = 0; + int ret; + + /* Check input parametres. */ + if (unlikely(! cursor || ! buffer || ! size || (maxdepth = *size) <= 0)) + return -UNW_EINVAL; + + Debug (1, "begin ip 0x%x cfa 0x%x\n", d->ip, d->cfa); + + /* Tell core dwarf routines to call back to us. */ + d->stash_frames = 1; + + /* Determine initial register values. These are direct access safe + because we know they come from the initial machine context. */ + pc = d->ip; + sp = cfa = d->cfa; + ACCESS_MEM_FAST(ret, 0, d, DWARF_GET_LOC(d->loc[UNW_ARM_R7]), r7); + assert(ret == 0); + lr = 0; + + /* Get frame cache. */ + if (unlikely(! (cache = trace_cache_get()))) + { + Debug (1, "returning %d, cannot get trace cache\n", -UNW_ENOMEM); + *size = 0; + d->stash_frames = 0; + return -UNW_ENOMEM; + } + + /* Trace the stack upwards, starting from current PC. Adjust + the PC address for previous/next instruction as the main + unwinding logic would also do. We undo this before calling + back into unw_step(). */ + while (depth < maxdepth) + { + pc -= d->use_prev_instr; + Debug (2, "depth %d cfa 0x%x pc 0x%x sp 0x%x r7 0x%x\n", + depth, cfa, pc, sp, r7); + + /* See if we have this address cached. If not, evaluate enough of + the dwarf unwind information to fill the cache line data, or to + decide this frame cannot be handled in fast trace mode. We + cache negative results too to prevent unnecessary dwarf parsing + for common failures. */ + unw_tdep_frame_t *f = trace_lookup (cursor, cache, cfa, pc, r7, sp); + + /* If we don't have information for this frame, give up. */ + if (unlikely(! f)) + { + ret = -UNW_ENOINFO; + break; + } + + Debug (3, "frame va %x type %d last %d cfa %s+%d r7 @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n", + f->virtual_address, f->frame_type, f->last_frame, + f->cfa_reg_sp ? "sp" : "r7", f->cfa_reg_offset, + f->r7_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset); + + assert (f->virtual_address == pc); + + /* Stop if this was the last frame. In particular don't evaluate + new register values as it may not be safe - we don't normally + run with full validation on, and do not want to - and there's + enough bad unwind info floating around that we need to trust + what unw_step() previously said, in potentially bogus frames. */ + if (f->last_frame) + break; + + /* Evaluate CFA and registers for the next frame. */ + switch (f->frame_type) + { + case UNW_ARM_FRAME_GUESSED: + /* Fall thru to standard processing after forcing validation. */ + c->validate = 1; + + case UNW_ARM_FRAME_STANDARD: + /* Advance standard traceable frame. */ + cfa = (f->cfa_reg_sp ? sp : r7) + f->cfa_reg_offset; + if (likely(f->lr_cfa_offset != -1)) + ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->lr_cfa_offset, pc); + else if (lr != 0) + { + /* Use the saved link register as the new pc. */ + pc = lr; + lr = 0; + } + if (likely(ret >= 0) && likely(f->r7_cfa_offset != -1)) + ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->r7_cfa_offset, r7); + + /* Don't bother reading SP from DWARF, CFA becomes new SP. */ + sp = cfa; + + /* Next frame needs to back up for unwind info lookup. */ + d->use_prev_instr = 1; + break; + + case UNW_ARM_FRAME_SIGRETURN: + cfa = cfa + f->cfa_reg_offset; /* cfa now points to ucontext_t. */ +#if defined(__linux__) + ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_PC_OFF, pc); + if (likely(ret >= 0)) + ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_R7_OFF, r7); + if (likely(ret >= 0)) + ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_SP_OFF, sp); + /* Save the link register here in case we end up in a function that + doesn't save the link register in the prologue, e.g. kill. */ + if (likely(ret >= 0)) + ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_LR_OFF, lr); +#elif defined(__FreeBSD__) + printf("XXX\n"); +#endif + + /* Resume stack at signal restoration point. The stack is not + necessarily continuous here, especially with sigaltstack(). */ + cfa = sp; + + /* Next frame should not back up. */ + d->use_prev_instr = 0; + break; + + case UNW_ARM_FRAME_SYSCALL: + printf("XXX1\n"); + break; + + default: + /* We cannot trace through this frame, give up and tell the + caller we had to stop. Data collected so far may still be + useful to the caller, so let it know how far we got. */ + ret = -UNW_ESTOPUNWIND; + break; + } + + Debug (4, "new cfa 0x%x pc 0x%x sp 0x%x r7 0x%x\n", + cfa, pc, sp, r7); + + /* If we failed or ended up somewhere bogus, stop. */ + if (unlikely(ret < 0 || pc < 0x4000)) + break; + + /* Record this address in stack trace. We skipped the first address. */ + buffer[depth++] = (void *) (pc - d->use_prev_instr); + } + +#if UNW_DEBUG + Debug (1, "returning %d, depth %d\n", ret, depth); +#endif + *size = depth; + return ret; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lapply_reg_state.c new file mode 100644 index 0000000..7ebada4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lapply_reg_state.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gapply_reg_state.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lcreate_addr_space.c new file mode 100644 index 0000000..0f2dc6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lcreate_addr_space.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gcreate_addr_space.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lex_tables.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lex_tables.c new file mode 100644 index 0000000..4a4f925 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lex_tables.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gex_tables.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lget_proc_info.c new file mode 100644 index 0000000..69028b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lget_proc_info.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_proc_info.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lget_save_loc.c new file mode 100644 index 0000000..9ea048a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lget_save_loc.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_save_loc.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lglobal.c new file mode 100644 index 0000000..6d7b489 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lglobal.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gglobal.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Linit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Linit.c new file mode 100644 index 0000000..e9abfdd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Linit.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Linit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Linit_local.c new file mode 100644 index 0000000..68a1687 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Linit_local.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_local.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Linit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Linit_remote.c new file mode 100644 index 0000000..58cb04a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Linit_remote.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_remote.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lis_signal_frame.c new file mode 100644 index 0000000..b9a7c4f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lis_signal_frame.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gis_signal_frame.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Los-freebsd.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Los-freebsd.c new file mode 100644 index 0000000..a75a205 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Los-freebsd.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gos-freebsd.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Los-linux.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Los-linux.c new file mode 100644 index 0000000..3cc18aa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Los-linux.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gos-linux.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Los-other.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Los-other.c new file mode 100644 index 0000000..a75a205 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Los-other.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gos-freebsd.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lreg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lreg_states_iterate.c new file mode 100644 index 0000000..f1eb1e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lreg_states_iterate.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Greg_states_iterate.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lregs.c new file mode 100644 index 0000000..2c9c75c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lregs.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gregs.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lresume.c new file mode 100644 index 0000000..41a8cf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lresume.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gresume.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lstash_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lstash_frame.c new file mode 100644 index 0000000..7758780 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lstash_frame.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gstash_frame.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lstep.c new file mode 100644 index 0000000..c1ac3c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Lstep.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gstep.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ltrace.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ltrace.c new file mode 100644 index 0000000..24b7b3c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/Ltrace.c @@ -0,0 +1,6 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gtrace.c" +#endif + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/gen-offsets.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/gen-offsets.c new file mode 100644 index 0000000..7d6bf2f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/gen-offsets.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include + +#define UC(N,X) \ + printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X)) + +#define SC(N,X) \ + printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X)) + +int +main (void) +{ + printf ( +"/* Linux-specific definitions: */\n\n" + +"/* Define various structure offsets to simplify cross-compilation. */\n\n" + +"/* Offsets for ARM Linux \"ucontext_t\": */\n\n"); + + UC ("FLAGS", uc_flags); + UC ("LINK", uc_link); + UC ("STACK", uc_stack); + UC ("MCONTEXT", uc_mcontext); + UC ("SIGMASK", uc_sigmask); + UC ("REGSPACE", uc_regspace); + + printf ("\n/* Offsets for ARM Linux \"struct sigcontext\": */\n\n"); + + SC ("TRAPNO", trap_no); + SC ("ERRORCODE", error_code); + SC ("OLDMASK", oldmask); + SC ("R0", arm_r0); + SC ("R1", arm_r1); + SC ("R2", arm_r2); + SC ("R3", arm_r3); + SC ("R4", arm_r4); + SC ("R5", arm_r5); + SC ("R6", arm_r6); + SC ("R7", arm_r7); + SC ("R8", arm_r8); + SC ("R9", arm_r9); + SC ("R10", arm_r10); + SC ("FP", arm_fp); + SC ("IP", arm_ip); + SC ("SP", arm_sp); + SC ("LR", arm_lr); + SC ("PC", arm_pc); + SC ("CPSR", arm_cpsr); + SC ("FAULTADDR", fault_address); + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/getcontext.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/getcontext.S new file mode 100644 index 0000000..7e18784 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/getcontext.S @@ -0,0 +1,63 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "offsets.h" + + .text + .arm + + .global _Uarm_getcontext + .type _Uarm_getcontext, %function + @ This is a stub version of getcontext() for ARM which only stores core + @ registers. It must be called in a special way, not as a regular + @ function -- see also the libunwind-arm.h:unw_tdep_getcontext macro. +_Uarm_getcontext: + stmfd sp!, {r0, r1} + @ store r0 +#if defined(__linux__) + str r0, [r0, #LINUX_UC_MCONTEXT_OFF + LINUX_SC_R0_OFF] + add r0, r0, #LINUX_UC_MCONTEXT_OFF + LINUX_SC_R0_OFF +#elif defined(__FreeBSD__) + str r0, [r0, #FREEBSD_UC_MCONTEXT_OFF + FREEBSD_MC_R0_OFF] + add r0, r0, #FREEBSD_UC_MCONTEXT_OFF + FREEBSD_MC_R0_OFF +#else +#error Fix me +#endif + @ store r1 to r12 + stmib r0, {r1-r12} + @ reconstruct r13 at call site, then store + add r1, sp, #12 + str r1, [r0, #13 * 4] + @ retrieve r14 from call site, then store + ldr r1, [sp, #8] + str r1, [r0, #14 * 4] + @ point lr to instruction after call site's stack adjustment + add r1, lr, #4 + str r1, [r0, #15 * 4] + ldmfd sp!, {r0, r1} + bx lr +#if defined(__linux__) || defined(__FreeBSD__) + /* We do not need executable stack. */ + .section .note.GNU-stack,"",%progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/init.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/init.h new file mode 100644 index 0000000..7d765ec --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/init.h @@ -0,0 +1,77 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static inline int +common_init (struct cursor *c, unsigned use_prev_instr) +{ + int ret, i; + + c->dwarf.loc[UNW_ARM_R0] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R0); + c->dwarf.loc[UNW_ARM_R1] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R1); + c->dwarf.loc[UNW_ARM_R2] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R2); + c->dwarf.loc[UNW_ARM_R3] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R3); + c->dwarf.loc[UNW_ARM_R4] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R4); + c->dwarf.loc[UNW_ARM_R5] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R5); + c->dwarf.loc[UNW_ARM_R6] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R6); + c->dwarf.loc[UNW_ARM_R7] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R7); + c->dwarf.loc[UNW_ARM_R8] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R8); + c->dwarf.loc[UNW_ARM_R9] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R9); + c->dwarf.loc[UNW_ARM_R10] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R10); + c->dwarf.loc[UNW_ARM_R11] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R11); + c->dwarf.loc[UNW_ARM_R12] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R12); + c->dwarf.loc[UNW_ARM_R13] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R13); + c->dwarf.loc[UNW_ARM_R14] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R14); + c->dwarf.loc[UNW_ARM_R15] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R15); + for (i = UNW_ARM_R15 + 1; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + + ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip); + if (ret < 0) + return ret; + + /* FIXME: correct for ARM? */ + ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_ARM_R13), + &c->dwarf.cfa); + if (ret < 0) + return ret; + + c->sigcontext_format = ARM_SCF_NONE; + c->sigcontext_addr = 0; + c->sigcontext_sp = 0; + c->sigcontext_pc = 0; + + /* FIXME: Initialisation for other registers. */ + + c->dwarf.args_size = 0; + c->dwarf.stash_frames = 0; + c->dwarf.use_prev_instr = use_prev_instr; + c->dwarf.pi_valid = 0; + c->dwarf.pi_is_dynamic = 0; + c->dwarf.hint = 0; + c->dwarf.prev_rs = 0; + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/is_fpreg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/is_fpreg.c new file mode 100644 index 0000000..e55bcff --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/is_fpreg.c @@ -0,0 +1,39 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +/* FIXME: I'm not sure if libunwind's GP/FP register distinction is very useful + on ARM. Count all the FP or coprocessor registers we know about for now. */ + +int +unw_is_fpreg (int regnum) +{ + return ((regnum >= UNW_ARM_S0 && regnum <= UNW_ARM_S31) + || (regnum >= UNW_ARM_F0 && regnum <= UNW_ARM_F7) + || (regnum >= UNW_ARM_wCGR0 && regnum <= UNW_ARM_wCGR7) + || (regnum >= UNW_ARM_wR0 && regnum <= UNW_ARM_wR15) + || (regnum >= UNW_ARM_wC0 && regnum <= UNW_ARM_wC7) + || (regnum >= UNW_ARM_D0 && regnum <= UNW_ARM_D31)); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/offsets.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/offsets.h new file mode 100644 index 0000000..6217011 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/offsets.h @@ -0,0 +1,42 @@ +/* Linux-specific definitions: */ + +/* Define various structure offsets to simplify cross-compilation. */ + +/* Offsets for ARM Linux "ucontext_t": */ + +#define LINUX_UC_FLAGS_OFF 0x00 +#define LINUX_UC_LINK_OFF 0x04 +#define LINUX_UC_STACK_OFF 0x08 +#define LINUX_UC_MCONTEXT_OFF 0x14 +#define LINUX_UC_SIGMASK_OFF 0x68 +#define LINUX_UC_REGSPACE_OFF 0xE8 + +/* Offsets for ARM Linux "struct sigcontext": */ + +#define LINUX_SC_TRAPNO_OFF 0x00 +#define LINUX_SC_ERRORCODE_OFF 0x04 +#define LINUX_SC_OLDMASK_OFF 0x08 +#define LINUX_SC_R0_OFF 0x0C +#define LINUX_SC_R1_OFF 0x10 +#define LINUX_SC_R2_OFF 0x14 +#define LINUX_SC_R3_OFF 0x18 +#define LINUX_SC_R4_OFF 0x1C +#define LINUX_SC_R5_OFF 0x20 +#define LINUX_SC_R6_OFF 0x24 +#define LINUX_SC_R7_OFF 0x28 +#define LINUX_SC_R8_OFF 0x2C +#define LINUX_SC_R9_OFF 0x30 +#define LINUX_SC_R10_OFF 0x34 +#define LINUX_SC_FP_OFF 0x38 +#define LINUX_SC_IP_OFF 0x3C +#define LINUX_SC_SP_OFF 0x40 +#define LINUX_SC_LR_OFF 0x44 +#define LINUX_SC_PC_OFF 0x48 +#define LINUX_SC_CPSR_OFF 0x4C +#define LINUX_SC_FAULTADDR_OFF 0x50 + +/* FreeBSD-specific definitions: */ + +#define FREEBSD_SC_UCONTEXT_OFF 0x40 +#define FREEBSD_UC_MCONTEXT_OFF 0x10 +#define FREEBSD_MC_R0_OFF 0 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/regname.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/regname.c new file mode 100644 index 0000000..7cac630 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/regname.c @@ -0,0 +1,90 @@ +#include "unwind_i.h" + +static const char *regname[] = + { + /* 0. */ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + /* 8. */ + "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc", + /* 16. Obsolete FPA names. */ + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + /* 24. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 32. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 40. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 48. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 56. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 64. */ + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + /* 72. */ + "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", + /* 80. */ + "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", + /* 88. */ + "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", + /* 96. */ + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + /* 104. */ + "wCGR0", "wCGR1", "wCGR2", "wCGR3", "wCGR4", "wCGR5", "wCGR6", "wCGR7", + /* 112. */ + "wR0", "wR1", "wR2", "wR3", "wR4", "wR5", "wR6", "wR7", + /* 128. */ + "spsr", "spsr_fiq", "spsr_irq", "spsr_abt", "spsr_und", "spsr_svc", 0, 0, + /* 136. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 144. */ + "r8_usr", "r9_usr", "r10_usr", "r11_usr", "r12_usr", "r13_usr", "r14_usr", + /* 151. */ + "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "r14_fiq", + /* 158. */ + "r13_irq", "r14_irq", + /* 160. */ + "r13_abt", "r14_abt", + /* 162. */ + "r13_und", "r14_und", + /* 164. */ + "r13_svc", "r14_svc", 0, 0, + /* 168. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 176. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 184. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 192. */ + "wC0", "wC1", "wC2", "wC3", "wC4", "wC5", "wC6", "wC7", + /* 200. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 208. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 216. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 224. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 232. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 240. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 248. */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 256. */ + "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", + /* 264. */ + "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", + /* 272. */ + "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", + /* 280. */ + "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", + }; + +const char * +unw_regname (unw_regnum_t reg) +{ + if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) + return regname[reg]; + else + return "???"; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/siglongjmp.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/siglongjmp.S new file mode 100644 index 0000000..4df0736 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/arm/siglongjmp.S @@ -0,0 +1,12 @@ + /* Dummy implementation for now. */ + + .globl _UI_siglongjmp_cont + .globl _UI_longjmp_cont + +_UI_siglongjmp_cont: +_UI_longjmp_cont: + bx lr +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",%progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/config.h.in b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/config.h.in new file mode 100644 index 0000000..1bc7c93 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/config.h.in @@ -0,0 +1,18 @@ +#ifndef __LIBUNWIND_CONFIG_H__ +#define __LIBUNWIND_CONFIG_H__ + +#cmakedefine HAVE_ELF_H +#cmakedefine HAVE_SYS_ELF_H + +#cmakedefine HAVE_ENDIAN_H +#cmakedefine HAVE_SYS_ENDIAN_H + +#cmakedefine HAVE_LINK_H +#cmakedefine HAVE_SYS_LINK_H + +#cmakedefine HAVE__BUILTIN_UNREACHABLE +#cmakedefine HAVE_SYNC_ATOMICS + +#cmakedefine HAVE_ATOMIC_OPS_H + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/configure.cmake b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/configure.cmake new file mode 100644 index 0000000..a6d37b5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/configure.cmake @@ -0,0 +1,33 @@ +include(CheckCXXSourceCompiles) +include(CheckIncludeFiles) + +check_include_files(elf.h HAVE_ELF_H) +check_include_files(sys/elf.h HAVE_SYS_ELF_H) + +check_include_files(endian.h HAVE_ENDIAN_H) +check_include_files(sys/endian.h HAVE_SYS_ENDIAN_H) + +check_include_files(link.h HAVE_LINK_H) +check_include_files(sys/link.h HAVE_SYS_LINK_H) + +check_include_files(atomic_ops.h HAVE_ATOMIC_OPS_H) + +check_cxx_source_compiles(" +int main(int argc, char **argv) +{ + __sync_bool_compare_and_swap((int *)0, 0, 1); + __sync_fetch_and_add((int *)0, 1); + + return 0; +}" HAVE_SYNC_ATOMICS) + + +check_cxx_source_compiles(" +int main(int argc, char **argv) +{ + __builtin_unreachable(); + + return 0; +}" HAVE__BUILTIN_UNREACHABLE) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/README b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/README new file mode 100644 index 0000000..204493c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/README @@ -0,0 +1,8 @@ +This code is based on "unwinding via ptrace" code from ptrace/ +directory. + +Files with names starting with _UCD_ are substantially changed +from their ptrace/_UPT_... progenitors. + +Files which still have _UPT_... names are either verbiatim copies +from ptrace/, or unimplemented stubs. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_access_mem.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_access_mem.c new file mode 100644 index 0000000..1fdbd12 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_access_mem.c @@ -0,0 +1,98 @@ +/* libunwind - a platform-independent unwind library + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UCD_lib.h" +#include "_UCD_internal.h" + +int +_UCD_access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *val, + int write, void *arg) +{ + if (write) + { + Debug(0, "write is not supported\n"); + return -UNW_EINVAL; + } + + struct UCD_info *ui = arg; + + unw_word_t addr_last = addr + sizeof(*val)-1; + coredump_phdr_t *phdr; + unsigned i; + for (i = 0; i < ui->phdrs_count; i++) + { + phdr = &ui->phdrs[i]; + if (phdr->p_vaddr <= addr && addr_last < phdr->p_vaddr + phdr->p_memsz) + { + goto found; + } + } + Debug(1, "addr 0x%llx is unmapped\n", (unsigned long long)addr); + return -UNW_EINVAL; + + found: ; + + const char *filename UNUSED; + off_t fileofs; + int fd; + if (addr_last >= phdr->p_vaddr + phdr->p_filesz) + { + /* This part of mapped address space is not present in coredump file */ + /* Do we have it in the backup file? */ + if (phdr->backing_fd < 0) + { + Debug(1, "access to not-present data in phdr[%d]: addr:0x%llx\n", + i, (unsigned long long)addr + ); + return -UNW_EINVAL; + } + filename = phdr->backing_filename; + fileofs = addr - phdr->p_vaddr; + fd = phdr->backing_fd; + goto read; + } + + filename = ui->coredump_filename; + fileofs = phdr->p_offset + (addr - phdr->p_vaddr); + fd = ui->coredump_fd; + read: + if (lseek(fd, fileofs, SEEK_SET) != fileofs) + goto read_error; + if (read(fd, val, sizeof(*val)) != sizeof(*val)) + goto read_error; + + Debug(1, "0x%llx <- [addr:0x%llx fileofs:0x%llx]\n", + (unsigned long long)(*val), + (unsigned long long)addr, + (unsigned long long)fileofs + ); + return 0; + + read_error: + Debug(1, "access out of file: addr:0x%llx fileofs:%llx file:'%s'\n", + (unsigned long long)addr, + (unsigned long long)fileofs, + filename + ); + return -UNW_EINVAL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_access_reg_freebsd.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_access_reg_freebsd.c new file mode 100644 index 0000000..0e3a83b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_access_reg_freebsd.c @@ -0,0 +1,137 @@ +/* libunwind - a platform-independent unwind library + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UCD_lib.h" + +#include "_UCD_internal.h" + +int +_UCD_access_reg (unw_addr_space_t as, + unw_regnum_t regnum, unw_word_t *valp, + int write, void *arg) +{ + if (write) + { + Debug(0, "write is not supported\n"); + return -UNW_EINVAL; + } + + struct UCD_info *ui = arg; + +#if defined(UNW_TARGET_X86) + switch (regnum) { + case UNW_X86_EAX: + *valp = ui->prstatus->pr_reg.r_eax; + break; + case UNW_X86_EDX: + *valp = ui->prstatus->pr_reg.r_edx; + break; + case UNW_X86_ECX: + *valp = ui->prstatus->pr_reg.r_ecx; + break; + case UNW_X86_EBX: + *valp = ui->prstatus->pr_reg.r_ebx; + break; + case UNW_X86_ESI: + *valp = ui->prstatus->pr_reg.r_esi; + break; + case UNW_X86_EDI: + *valp = ui->prstatus->pr_reg.r_edi; + break; + case UNW_X86_EBP: + *valp = ui->prstatus->pr_reg.r_ebp; + break; + case UNW_X86_ESP: + *valp = ui->prstatus->pr_reg.r_esp; + break; + case UNW_X86_EIP: + *valp = ui->prstatus->pr_reg.r_eip; + break; + case UNW_X86_EFLAGS: + *valp = ui->prstatus->pr_reg.r_eflags; + break; + case UNW_X86_TRAPNO: + *valp = ui->prstatus->pr_reg.r_trapno; + break; + default: + Debug(0, "bad regnum:%d\n", regnum); + return -UNW_EINVAL; + } +#elif defined(UNW_TARGET_X86_64) + switch (regnum) { + case UNW_X86_64_RAX: + *valp = ui->prstatus->pr_reg.r_rax; + break; + case UNW_X86_64_RDX: + *valp = ui->prstatus->pr_reg.r_rdx; + break; + case UNW_X86_64_RCX: + *valp = ui->prstatus->pr_reg.r_rcx; + break; + case UNW_X86_64_RBX: + *valp = ui->prstatus->pr_reg.r_rbx; + break; + case UNW_X86_64_RSI: + *valp = ui->prstatus->pr_reg.r_rsi; + break; + case UNW_X86_64_RDI: + *valp = ui->prstatus->pr_reg.r_rdi; + break; + case UNW_X86_64_RBP: + *valp = ui->prstatus->pr_reg.r_rbp; + break; + case UNW_X86_64_RSP: + *valp = ui->prstatus->pr_reg.r_rsp; + break; + case UNW_X86_64_RIP: + *valp = ui->prstatus->pr_reg.r_rip; + break; + default: + Debug(0, "bad regnum:%d\n", regnum); + return -UNW_EINVAL; + } +#elif defined(UNW_TARGET_ARM) + if (regnum >= UNW_ARM_R0 && regnum <= UNW_ARM_R12) { + *valp = ui->prstatus->pr_reg.r[regnum]; + } else { + switch (regnum) { + case UNW_ARM_R13: + *valp = ui->prstatus->pr_reg.r_sp; + break; + case UNW_ARM_R14: + *valp = ui->prstatus->pr_reg.r_lr; + break; + case UNW_ARM_R15: + *valp = ui->prstatus->pr_reg.r_pc; + break; + default: + Debug(0, "bad regnum:%d\n", regnum); + return -UNW_EINVAL; + } + } +#else +#error Port me +#endif + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c new file mode 100644 index 0000000..208d8d2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c @@ -0,0 +1,146 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UCD_lib.h" + +#include "_UCD_internal.h" + +int +_UCD_access_reg (unw_addr_space_t as, + unw_regnum_t regnum, unw_word_t *valp, + int write, void *arg) +{ + struct UCD_info *ui = arg; + + if (write) + { + Debug(0, "write is not supported\n"); + return -UNW_EINVAL; + } + + if (regnum < 0) + goto badreg; + +#if defined(UNW_TARGET_AARCH64) + if (regnum >= UNW_AARCH64_FPCR) + goto badreg; +#elif defined(UNW_TARGET_ARM) + if (regnum >= 16) + goto badreg; +#elif defined(UNW_TARGET_SH) + if (regnum > UNW_SH_PR) + goto badreg; +#elif defined(UNW_TARGET_TILEGX) + if (regnum > UNW_TILEGX_CFA) + goto badreg; +#else +#if defined(UNW_TARGET_MIPS) + static const uint8_t remap_regs[] = + { + [UNW_MIPS_R0] = EF_REG0, + [UNW_MIPS_R1] = EF_REG1, + [UNW_MIPS_R2] = EF_REG2, + [UNW_MIPS_R3] = EF_REG3, + [UNW_MIPS_R4] = EF_REG4, + [UNW_MIPS_R5] = EF_REG5, + [UNW_MIPS_R6] = EF_REG6, + [UNW_MIPS_R7] = EF_REG7, + [UNW_MIPS_R8] = EF_REG8, + [UNW_MIPS_R9] = EF_REG9, + [UNW_MIPS_R10] = EF_REG10, + [UNW_MIPS_R11] = EF_REG11, + [UNW_MIPS_R12] = EF_REG12, + [UNW_MIPS_R13] = EF_REG13, + [UNW_MIPS_R14] = EF_REG14, + [UNW_MIPS_R15] = EF_REG15, + [UNW_MIPS_R16] = EF_REG16, + [UNW_MIPS_R17] = EF_REG17, + [UNW_MIPS_R18] = EF_REG18, + [UNW_MIPS_R19] = EF_REG19, + [UNW_MIPS_R20] = EF_REG20, + [UNW_MIPS_R21] = EF_REG21, + [UNW_MIPS_R22] = EF_REG22, + [UNW_MIPS_R23] = EF_REG23, + [UNW_MIPS_R24] = EF_REG24, + [UNW_MIPS_R25] = EF_REG25, + [UNW_MIPS_R28] = EF_REG28, + [UNW_MIPS_R29] = EF_REG29, + [UNW_MIPS_R30] = EF_REG30, + [UNW_MIPS_R31] = EF_REG31, + [UNW_MIPS_PC] = EF_CP0_EPC, + }; +#elif defined(UNW_TARGET_X86) + static const uint8_t remap_regs[] = + { + /* names from libunwind-x86.h */ + [UNW_X86_EAX] = offsetof(struct user_regs_struct, eax) / sizeof(long), + [UNW_X86_EDX] = offsetof(struct user_regs_struct, edx) / sizeof(long), + [UNW_X86_ECX] = offsetof(struct user_regs_struct, ecx) / sizeof(long), + [UNW_X86_EBX] = offsetof(struct user_regs_struct, ebx) / sizeof(long), + [UNW_X86_ESI] = offsetof(struct user_regs_struct, esi) / sizeof(long), + [UNW_X86_EDI] = offsetof(struct user_regs_struct, edi) / sizeof(long), + [UNW_X86_EBP] = offsetof(struct user_regs_struct, ebp) / sizeof(long), + [UNW_X86_ESP] = offsetof(struct user_regs_struct, esp) / sizeof(long), + [UNW_X86_EIP] = offsetof(struct user_regs_struct, eip) / sizeof(long), + [UNW_X86_EFLAGS] = offsetof(struct user_regs_struct, eflags) / sizeof(long), + [UNW_X86_TRAPNO] = offsetof(struct user_regs_struct, orig_eax) / sizeof(long), + }; +#elif defined(UNW_TARGET_X86_64) + static const int8_t remap_regs[] = + { + [UNW_X86_64_RAX] = offsetof(struct user_regs_struct, rax) / sizeof(long), + [UNW_X86_64_RDX] = offsetof(struct user_regs_struct, rdx) / sizeof(long), + [UNW_X86_64_RCX] = offsetof(struct user_regs_struct, rcx) / sizeof(long), + [UNW_X86_64_RBX] = offsetof(struct user_regs_struct, rbx) / sizeof(long), + [UNW_X86_64_RSI] = offsetof(struct user_regs_struct, rsi) / sizeof(long), + [UNW_X86_64_RDI] = offsetof(struct user_regs_struct, rdi) / sizeof(long), + [UNW_X86_64_RBP] = offsetof(struct user_regs_struct, rbp) / sizeof(long), + [UNW_X86_64_RSP] = offsetof(struct user_regs_struct, rsp) / sizeof(long), + [UNW_X86_64_RIP] = offsetof(struct user_regs_struct, rip) / sizeof(long), + }; +#else +#error Port me +#endif + + if (regnum >= (unw_regnum_t)ARRAY_SIZE(remap_regs)) + goto badreg; + + regnum = remap_regs[regnum]; +#endif + + /* pr_reg is a long[] array, but it contains struct user_regs_struct's + * image. + */ + Debug(1, "pr_reg[%d]:%ld (0x%lx)\n", regnum, + (long)ui->prstatus->pr_reg[regnum], + (long)ui->prstatus->pr_reg[regnum] + ); + *valp = ui->prstatus->pr_reg[regnum]; + + return 0; + +badreg: + Debug(0, "bad regnum:%d\n", regnum); + return -UNW_EINVAL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_accessors.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_accessors.c new file mode 100644 index 0000000..ae5c23d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_accessors.c @@ -0,0 +1,36 @@ +/* libunwind - a platform-independent unwind library + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UCD_internal.h" + +unw_accessors_t _UCD_accessors = + { + .find_proc_info = _UCD_find_proc_info, + .put_unwind_info = _UCD_put_unwind_info, + .get_dyn_info_list_addr = _UCD_get_dyn_info_list_addr, + .access_mem = _UCD_access_mem, + .access_reg = _UCD_access_reg, + .access_fpreg = _UCD_access_fpreg, + .resume = _UCD_resume, + .get_proc_name = _UCD_get_proc_name + }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_create.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_create.c new file mode 100644 index 0000000..62f6ee0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_create.c @@ -0,0 +1,417 @@ +/* libunwind - a platform-independent unwind library + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +/* Endian detection */ +#include +#if defined(HAVE_BYTESWAP_H) +#include +#endif +#if defined(HAVE_ENDIAN_H) +# include +#elif defined(HAVE_SYS_ENDIAN_H) +# include +#endif +#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN +# define WE_ARE_BIG_ENDIAN 1 +# define WE_ARE_LITTLE_ENDIAN 0 +#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN +# define WE_ARE_BIG_ENDIAN 0 +# define WE_ARE_LITTLE_ENDIAN 1 +#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN +# define WE_ARE_BIG_ENDIAN 1 +# define WE_ARE_LITTLE_ENDIAN 0 +#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN +# define WE_ARE_BIG_ENDIAN 0 +# define WE_ARE_LITTLE_ENDIAN 1 +#elif defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN +# define WE_ARE_BIG_ENDIAN 1 +# define WE_ARE_LITTLE_ENDIAN 0 +#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN +# define WE_ARE_BIG_ENDIAN 0 +# define WE_ARE_LITTLE_ENDIAN 1 +#elif defined(__386__) +# define WE_ARE_BIG_ENDIAN 0 +# define WE_ARE_LITTLE_ENDIAN 1 +#else +# error "Can't determine endianness" +#endif + +#include +#include /* struct elf_prstatus */ + +#include "_UCD_lib.h" +#include "_UCD_internal.h" + +#define NOTE_DATA(_hdr) STRUCT_MEMBER_P((_hdr), sizeof (Elf32_Nhdr) + UNW_ALIGN((_hdr)->n_namesz, 4)) +#define NOTE_SIZE(_hdr) (sizeof (Elf32_Nhdr) + UNW_ALIGN((_hdr)->n_namesz, 4) + UNW_ALIGN((_hdr)->n_descsz, 4)) +#define NOTE_NEXT(_hdr) STRUCT_MEMBER_P((_hdr), NOTE_SIZE(_hdr)) +#define NOTE_FITS_IN(_hdr, _size) ((_size) >= sizeof (Elf32_Nhdr) && (_size) >= NOTE_SIZE (_hdr)) +#define NOTE_FITS(_hdr, _end) NOTE_FITS_IN((_hdr), (unsigned long)((char *)(_end) - (char *)(_hdr))) + +struct UCD_info * +_UCD_create(const char *filename) +{ + union + { + Elf32_Ehdr h32; + Elf64_Ehdr h64; + } elf_header; +#define elf_header32 elf_header.h32 +#define elf_header64 elf_header.h64 + bool _64bits; + + struct UCD_info *ui = memset(malloc(sizeof(*ui)), 0, sizeof(*ui)); + ui->edi.di_cache.format = -1; + ui->edi.di_debug.format = -1; +#if UNW_TARGET_IA64 + ui->edi.ktab.format = -1; +#endif + + int fd = ui->coredump_fd = open(filename, O_RDONLY); + if (fd < 0) + goto err; + ui->coredump_filename = strdup(filename); + + /* No sane ELF32 file is going to be smaller then ELF64 _header_, + * so let's just read 64-bit sized one. + */ + if (read(fd, &elf_header64, sizeof(elf_header64)) != sizeof(elf_header64)) + { + Debug(0, "'%s' is not an ELF file\n", filename); + goto err; + } + + if (memcmp(&elf_header32, ELFMAG, SELFMAG) != 0) + { + Debug(0, "'%s' is not an ELF file\n", filename); + goto err; + } + + if (elf_header32.e_ident[EI_CLASS] != ELFCLASS32 + && elf_header32.e_ident[EI_CLASS] != ELFCLASS64) + { + Debug(0, "'%s' is not a 32/64 bit ELF file\n", filename); + goto err; + } + + if (WE_ARE_LITTLE_ENDIAN != (elf_header32.e_ident[EI_DATA] == ELFDATA2LSB)) + { + Debug(0, "'%s' is endian-incompatible\n", filename); + goto err; + } + + _64bits = (elf_header32.e_ident[EI_CLASS] == ELFCLASS64); + if (_64bits && sizeof(elf_header64.e_entry) > sizeof(off_t)) + { + Debug(0, "Can't process '%s': 64-bit file " + "while only %ld bits are supported", + filename, 8L * sizeof(off_t)); + goto err; + } + + /* paranoia check */ + if (_64bits + ? 0 /* todo: (elf_header64.e_ehsize != NN || elf_header64.e_phentsize != NN) */ + : (elf_header32.e_ehsize != 52 || elf_header32.e_phentsize != 32) + ) + { + Debug(0, "'%s' has wrong e_ehsize or e_phentsize\n", filename); + goto err; + } + + off_t ofs = (_64bits ? elf_header64.e_phoff : elf_header32.e_phoff); + if (lseek(fd, ofs, SEEK_SET) != ofs) + { + Debug(0, "Can't read phdrs from '%s'\n", filename); + goto err; + } + unsigned size = ui->phdrs_count = (_64bits ? elf_header64.e_phnum : elf_header32.e_phnum); + coredump_phdr_t *phdrs = ui->phdrs = memset(malloc(size * sizeof(phdrs[0])), 0, size * sizeof(phdrs[0])); + if (_64bits) + { + coredump_phdr_t *cur = phdrs; + unsigned i = 0; + while (i < size) + { + Elf64_Phdr hdr64; + if (read(fd, &hdr64, sizeof(hdr64)) != sizeof(hdr64)) + { + Debug(0, "Can't read phdrs from '%s'\n", filename); + goto err; + } + cur->p_type = hdr64.p_type ; + cur->p_flags = hdr64.p_flags ; + cur->p_offset = hdr64.p_offset; + cur->p_vaddr = hdr64.p_vaddr ; + /*cur->p_paddr = hdr32.p_paddr ; always 0 */ +//TODO: check that and abort if it isn't? + cur->p_filesz = hdr64.p_filesz; + cur->p_memsz = hdr64.p_memsz ; + cur->p_align = hdr64.p_align ; + /* cur->backing_filename = NULL; - done by memset */ + cur->backing_fd = -1; + cur->backing_filesize = hdr64.p_filesz; + i++; + cur++; + } + } else { + coredump_phdr_t *cur = phdrs; + unsigned i = 0; + while (i < size) + { + Elf32_Phdr hdr32; + if (read(fd, &hdr32, sizeof(hdr32)) != sizeof(hdr32)) + { + Debug(0, "Can't read phdrs from '%s'\n", filename); + goto err; + } + cur->p_type = hdr32.p_type ; + cur->p_flags = hdr32.p_flags ; + cur->p_offset = hdr32.p_offset; + cur->p_vaddr = hdr32.p_vaddr ; + /*cur->p_paddr = hdr32.p_paddr ; always 0 */ + cur->p_filesz = hdr32.p_filesz; + cur->p_memsz = hdr32.p_memsz ; + cur->p_align = hdr32.p_align ; + /* cur->backing_filename = NULL; - done by memset */ + cur->backing_fd = -1; + cur->backing_filesize = hdr32.p_memsz; + i++; + cur++; + } + } + + unsigned i = 0; + coredump_phdr_t *cur = phdrs; + while (i < size) + { + Debug(2, "phdr[%03d]: type:%d", i, cur->p_type); + if (cur->p_type == PT_NOTE) + { + Elf32_Nhdr *note_hdr, *note_end; + unsigned n_threads; + + ui->note_phdr = malloc(cur->p_filesz); + if (lseek(fd, cur->p_offset, SEEK_SET) != (off_t)cur->p_offset + || (uoff_t)read(fd, ui->note_phdr, cur->p_filesz) != cur->p_filesz) + { + Debug(0, "Can't read PT_NOTE from '%s'\n", filename); + goto err; + } + + note_end = STRUCT_MEMBER_P (ui->note_phdr, cur->p_filesz); + + /* Count number of threads */ + n_threads = 0; + note_hdr = (Elf32_Nhdr *)ui->note_phdr; + while (NOTE_FITS (note_hdr, note_end)) + { + if (note_hdr->n_type == NT_PRSTATUS) + n_threads++; + + note_hdr = NOTE_NEXT (note_hdr); + } + + ui->n_threads = n_threads; + ui->threads = malloc(sizeof (void *) * n_threads); + + n_threads = 0; + note_hdr = (Elf32_Nhdr *)ui->note_phdr; + while (NOTE_FITS (note_hdr, note_end)) + { + if (note_hdr->n_type == NT_PRSTATUS) + ui->threads[n_threads++] = NOTE_DATA (note_hdr); + + note_hdr = NOTE_NEXT (note_hdr); + } + } + if (cur->p_type == PT_LOAD) + { + Debug(2, " ofs:%08llx va:%08llx filesize:%08llx memsize:%08llx flg:%x", + (unsigned long long) cur->p_offset, + (unsigned long long) cur->p_vaddr, + (unsigned long long) cur->p_filesz, + (unsigned long long) cur->p_memsz, + cur->p_flags + ); + if (cur->p_filesz < cur->p_memsz) + Debug(2, " partial"); + if (cur->p_flags & PF_X) + Debug(2, " executable"); + } + Debug(2, "\n"); + i++; + cur++; + } + + if (ui->n_threads == 0) + { + Debug(0, "No NT_PRSTATUS note found in '%s'\n", filename); + goto err; + } + + ui->prstatus = ui->threads[0]; + + return ui; + + err: + _UCD_destroy(ui); + return NULL; +} + +int _UCD_get_num_threads(struct UCD_info *ui) +{ + return ui->n_threads; +} + +void _UCD_select_thread(struct UCD_info *ui, int n) +{ + if (n >= 0 && n < ui->n_threads) + ui->prstatus = ui->threads[n]; +} + +pid_t _UCD_get_pid(struct UCD_info *ui) +{ + return ui->prstatus->pr_pid; +} + +int _UCD_get_cursig(struct UCD_info *ui) +{ + return ui->prstatus->pr_cursig; +} + +int _UCD_add_backing_file_at_segment(struct UCD_info *ui, int phdr_no, const char *filename) +{ + if ((unsigned)phdr_no >= ui->phdrs_count) + { + Debug(0, "There is no segment %d in this coredump\n", phdr_no); + return -1; + } + + struct coredump_phdr *phdr = &ui->phdrs[phdr_no]; + if (phdr->backing_filename) + { + Debug(0, "Backing file already added to segment %d\n", phdr_no); + return -1; + } + + int fd = open(filename, O_RDONLY); + if (fd < 0) + { + Debug(0, "Can't open '%s'\n", filename); + return -1; + } + + phdr->backing_fd = fd; + phdr->backing_filename = strdup(filename); + + struct stat statbuf; + if (fstat(fd, &statbuf) != 0) + { + Debug(0, "Can't stat '%s'\n", filename); + goto err; + } + phdr->backing_filesize = (uoff_t)statbuf.st_size; + + if (phdr->p_flags != (PF_X | PF_R)) + Debug(1, "Note: phdr[%u] is not r-x: flags are 0x%x\n", phdr_no, phdr->p_flags); + + if (phdr->backing_filesize > phdr->p_memsz) + { + /* This is expected */ + Debug(2, "Note: phdr[%u] is %lld bytes, file is larger: %lld bytes\n", + phdr_no, + (unsigned long long)phdr->p_memsz, + (unsigned long long)phdr->backing_filesize + ); + } +//TODO: else loudly complain? Maybe even fail? + + if (phdr->p_filesz != 0) + { +//TODO: loop and compare in smaller blocks + char *core_buf = malloc(phdr->p_filesz); + char *file_buf = malloc(phdr->p_filesz); + if (lseek(ui->coredump_fd, phdr->p_offset, SEEK_SET) != (off_t)phdr->p_offset + || (uoff_t)read(ui->coredump_fd, core_buf, phdr->p_filesz) != phdr->p_filesz + ) + { + Debug(0, "Error reading from coredump file\n"); + err_read: + free(core_buf); + free(file_buf); + goto err; + } + if ((uoff_t)read(fd, file_buf, phdr->p_filesz) != phdr->p_filesz) + { + Debug(0, "Error reading from '%s'\n", filename); + goto err_read; + } + int r = memcmp(core_buf, file_buf, phdr->p_filesz); + free(core_buf); + free(file_buf); + if (r != 0) + { + Debug(1, "Note: phdr[%u] first %lld bytes in core dump and in file do not match\n", + phdr_no, (unsigned long long)phdr->p_filesz + ); + } else { + Debug(1, "Note: phdr[%u] first %lld bytes in core dump and in file match\n", + phdr_no, (unsigned long long)phdr->p_filesz + ); + } + } + + /* Success */ + return 0; + + err: + if (phdr->backing_fd >= 0) + { + close(phdr->backing_fd); + phdr->backing_fd = -1; + } + free(phdr->backing_filename); + phdr->backing_filename = NULL; + return -1; +} + +int _UCD_add_backing_file_at_vaddr(struct UCD_info *ui, + unsigned long vaddr, + const char *filename) +{ + unsigned i; + for (i = 0; i < ui->phdrs_count; i++) + { + struct coredump_phdr *phdr = &ui->phdrs[i]; + if (phdr->p_vaddr != vaddr) + continue; + /* It seems to match. Add it. */ + return _UCD_add_backing_file_at_segment(ui, i, filename); + } + return -1; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_destroy.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_destroy.c new file mode 100644 index 0000000..ddc36ec --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_destroy.c @@ -0,0 +1,52 @@ +/* libunwind - a platform-independent unwind library + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UCD_internal.h" + +void +_UCD_destroy (struct UCD_info *ui) +{ + if (!ui) + return; + + if (ui->coredump_fd >= 0) + close(ui->coredump_fd); + free(ui->coredump_filename); + + invalidate_edi (&ui->edi); + + unsigned i; + for (i = 0; i < ui->phdrs_count; i++) + { + struct coredump_phdr *phdr = &ui->phdrs[i]; + free(phdr->backing_filename); + if (phdr->backing_fd >= 0) + close(phdr->backing_fd); + } + + free(ui->phdrs); + free(ui->note_phdr); + free(ui->threads); + + free(ui); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_elf_map_image.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_elf_map_image.c new file mode 100644 index 0000000..4b3db0b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_elf_map_image.c @@ -0,0 +1,98 @@ +/* libunwind - a platform-independent unwind library + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "_UCD_lib.h" +#include "_UCD_internal.h" + +static coredump_phdr_t * +CD_elf_map_image(struct UCD_info *ui, coredump_phdr_t *phdr) +{ + struct elf_image *ei = &ui->edi.ei; + + if (phdr->backing_fd < 0) + { + /* Note: coredump file contains only phdr->p_filesz bytes. + * We want to map bigger area (phdr->p_memsz bytes) to make sure + * these pages are allocated, but non-accessible. + */ + /* addr, length, prot, flags, fd, fd_offset */ + ei->image = mmap(NULL, phdr->p_memsz, PROT_READ, MAP_PRIVATE, ui->coredump_fd, phdr->p_offset); + if (ei->image == MAP_FAILED) + { + ei->image = NULL; + return NULL; + } + ei->size = phdr->p_filesz; + size_t remainder_len = phdr->p_memsz - phdr->p_filesz; + if (remainder_len > 0) + { + void *remainder_base = (char*) ei->image + phdr->p_filesz; + munmap(remainder_base, remainder_len); + } + } else { + /* We have a backing file for this segment. + * This file is always longer than phdr->p_memsz, + * and if phdr->p_filesz !=0, first phdr->p_filesz bytes in coredump + * are the same as first bytes in the file. (Thus no need to map coredump) + * We map the entire file: + * unwinding may need data which is past phdr->p_memsz bytes. + */ + /* addr, length, prot, flags, fd, fd_offset */ + ei->image = mmap(NULL, phdr->backing_filesize, PROT_READ, MAP_PRIVATE, phdr->backing_fd, 0); + if (ei->image == MAP_FAILED) + { + ei->image = NULL; + return NULL; + } + ei->size = phdr->backing_filesize; + } + + /* Check ELF header for sanity */ + if (!elf_w(valid_object)(ei)) + { + munmap(ei->image, ei->size); + ei->image = NULL; + ei->size = 0; + return NULL; + } + + return phdr; +} + +HIDDEN coredump_phdr_t * +_UCD_get_elf_image(struct UCD_info *ui, unw_word_t ip) +{ + unsigned i; + for (i = 0; i < ui->phdrs_count; i++) + { + coredump_phdr_t *phdr = &ui->phdrs[i]; + if (phdr->p_vaddr <= ip && ip < phdr->p_vaddr + phdr->p_memsz) + { + phdr = CD_elf_map_image(ui, phdr); + return phdr; + } + } + return NULL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_find_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_find_proc_info.c new file mode 100644 index 0000000..33b66c8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_find_proc_info.c @@ -0,0 +1,163 @@ +/* libunwind - a platform-independent unwind library + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "_UCD_lib.h" +#include "_UCD_internal.h" + +static int +get_unwind_info(struct UCD_info *ui, unw_addr_space_t as, unw_word_t ip) +{ + unsigned long segbase, mapoff; + +#if UNW_TARGET_IA64 && defined(__linux) + if (!ui->edi.ktab.start_ip && _Uia64_get_kernel_table (&ui->edi.ktab) < 0) + return -UNW_ENOINFO; + + if (ui->edi.ktab.format != -1 && ip >= ui->edi.ktab.start_ip && ip < ui->edi.ktab.end_ip) + return 0; +#endif + + if ((ui->edi.di_cache.format != -1 + && ip >= ui->edi.di_cache.start_ip && ip < ui->edi.di_cache.end_ip) +#if UNW_TARGET_ARM + || (ui->edi.di_debug.format != -1 + && ip >= ui->edi.di_arm.start_ip && ip < ui->edi.di_arm.end_ip) +#endif + || (ui->edi.di_debug.format != -1 + && ip >= ui->edi.di_debug.start_ip && ip < ui->edi.di_debug.end_ip)) + return 0; + + invalidate_edi (&ui->edi); + + /* Used to be tdep_get_elf_image() in ptrace unwinding code */ + coredump_phdr_t *phdr = _UCD_get_elf_image(ui, ip); + if (!phdr) + { + Debug(1, "returns error: _UCD_get_elf_image failed\n"); + return -UNW_ENOINFO; + } + /* segbase: where it is mapped in virtual memory */ + /* mapoff: offset in the file */ + segbase = phdr->p_vaddr; + /*mapoff = phdr->p_offset; WRONG! phdr->p_offset is the offset in COREDUMP file */ + mapoff = 0; +///FIXME. text segment is USUALLY, not always, at offset 0 in the binary/.so file. +// ensure that at initialization. + + /* Here, SEGBASE is the starting-address of the (mmap'ped) segment + which covers the IP we're looking for. */ + if (tdep_find_unwind_table(&ui->edi, as, phdr->backing_filename, segbase, mapoff, ip) < 0) + { + Debug(1, "returns error: tdep_find_unwind_table failed\n"); + return -UNW_ENOINFO; + } + + /* This can happen in corner cases where dynamically generated + code falls into the same page that contains the data-segment + and the page-offset of the code is within the first page of + the executable. */ + if (ui->edi.di_cache.format != -1 + && (ip < ui->edi.di_cache.start_ip || ip >= ui->edi.di_cache.end_ip)) + ui->edi.di_cache.format = -1; + + if (ui->edi.di_debug.format != -1 + && (ip < ui->edi.di_debug.start_ip || ip >= ui->edi.di_debug.end_ip)) + ui->edi.di_debug.format = -1; + + if (ui->edi.di_cache.format == -1 +#if UNW_TARGET_ARM + && ui->edi.di_arm.format == -1 +#endif + && ui->edi.di_debug.format == -1) + { + Debug(1, "returns error: all formats are -1\n"); + return -UNW_ENOINFO; + } + + Debug(1, "returns success\n"); + return 0; +} + +int +_UCD_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + struct UCD_info *ui = arg; + + Debug(1, "entering\n"); + + int ret = -UNW_ENOINFO; + + if (get_unwind_info(ui, as, ip) < 0) { + Debug(1, "returns error: get_unwind_info failed\n"); + return -UNW_ENOINFO; + } + +#if UNW_TARGET_IA64 + if (ui->edi.ktab.format != -1) + { + /* The kernel unwind table resides in local memory, so we have + to use the local address space to search it. Since + _UCD_put_unwind_info() has no easy way of detecting this + case, we simply make a copy of the unwind-info, so + _UCD_put_unwind_info() can always free() the unwind-info + without ill effects. */ + ret = tdep_search_unwind_table (unw_local_addr_space, ip, &ui->edi.ktab, pi, + need_unwind_info, arg); + if (ret >= 0) + { + if (!need_unwind_info) + pi->unwind_info = NULL; + else + { + void *mem = malloc (pi->unwind_info_size); + + if (!mem) + return -UNW_ENOMEM; + memcpy (mem, pi->unwind_info, pi->unwind_info_size); + pi->unwind_info = mem; + } + } + } +#endif + + if (ret == -UNW_ENOINFO && ui->edi.di_cache.format != -1) + ret = tdep_search_unwind_table (as, ip, &ui->edi.di_cache, + pi, need_unwind_info, arg); + +#if UNW_TARGET_ARM + if (ret == -UNW_ENOINFO && ui->edi.di_arm.format != -1) + ret = tdep_search_unwind_table (as, ip, &ui->edi.di_arm, pi, + need_unwind_info, arg); +#endif + + if (ret == -UNW_ENOINFO && ui->edi.di_debug.format != -1) + ret = tdep_search_unwind_table (as, ip, &ui->edi.di_debug, pi, + need_unwind_info, arg); + + Debug(1, "returns %d\n", ret); + + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_get_proc_name.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_get_proc_name.c new file mode 100644 index 0000000..00096c4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_get_proc_name.c @@ -0,0 +1,70 @@ +/* libunwind - a platform-independent unwind library + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UCD_lib.h" +#include "_UCD_internal.h" + + +/* Find the ELF image that contains IP and return the "closest" + procedure name, if there is one. With some caching, this could be + sped up greatly, but until an application materializes that's + sensitive to the performance of this routine, why bother... */ +static int +elf_w (CD_get_proc_name) (struct UCD_info *ui, unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp) +{ + unsigned long segbase, mapoff; + int ret; + + /* Used to be tdep_get_elf_image() in ptrace unwinding code */ + coredump_phdr_t *cphdr = _UCD_get_elf_image(ui, ip); + if (!cphdr) + { + Debug(1, "returns error: _UCD_get_elf_image failed\n"); + return -UNW_ENOINFO; + } + /* segbase: where it is mapped in virtual memory */ + /* mapoff: offset in the file */ + segbase = cphdr->p_vaddr; + /*mapoff = phdr->p_offset; WRONG! phdr->p_offset is the offset in COREDUMP file */ + mapoff = 0; + + ret = elf_w (get_proc_name_in_image) (as, &ui->edi.ei, segbase, mapoff, ip, buf, buf_len, offp); + + return ret; +} + +int +_UCD_get_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, void *arg) +{ + struct UCD_info *ui = arg; + +#if ELF_CLASS == ELFCLASS64 + return _Uelf64_CD_get_proc_name (ui, as, ip, buf, buf_len, offp); +#elif ELF_CLASS == ELFCLASS32 + return _Uelf32_CD_get_proc_name (ui, as, ip, buf, buf_len, offp); +#else + return -UNW_ENOINFO; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_internal.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_internal.h new file mode 100644 index 0000000..3c95a2a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_internal.h @@ -0,0 +1,105 @@ +/* libunwind - a platform-independent unwind library + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _UCD_internal_h +#define _UCD_internal_h + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_PROCFS_H +#include /* struct elf_prstatus */ +#endif +#include +#include +#include +#include +#include + +#include + +#include "libunwind_i.h" + + +#if SIZEOF_OFF_T == 4 +typedef uint32_t uoff_t; +#elif SIZEOF_OFF_T == 8 +typedef uint64_t uoff_t; +#else +# error Unknown size of off_t! +#endif + + +/* Similar to ELF phdrs. p_paddr element is absent, + * since it's always 0 in coredumps. + */ +struct coredump_phdr + { + uint32_t p_type; + uint32_t p_flags; + uoff_t p_offset; + uoff_t p_vaddr; + uoff_t p_filesz; + uoff_t p_memsz; + uoff_t p_align; + /* Data for backing file. If backing_fd < 0, there is no file */ + uoff_t backing_filesize; + char *backing_filename; /* for error meesages only */ + int backing_fd; + }; + +typedef struct coredump_phdr coredump_phdr_t; + +#if defined(HAVE_STRUCT_ELF_PRSTATUS) +#define PRSTATUS_STRUCT elf_prstatus +#elif defined(HAVE_STRUCT_PRSTATUS) +#define PRSTATUS_STRUCT prstatus +#else +#define PRSTATUS_STRUCT non_existent +#endif + +struct UCD_info + { + int big_endian; /* bool */ + int coredump_fd; + char *coredump_filename; /* for error meesages only */ + coredump_phdr_t *phdrs; /* array, allocated */ + unsigned phdrs_count; + void *note_phdr; /* allocated or NULL */ + struct PRSTATUS_STRUCT *prstatus; /* points inside note_phdr */ + int n_threads; + struct PRSTATUS_STRUCT **threads; + + struct elf_dyn_info edi; + }; + +extern coredump_phdr_t * _UCD_get_elf_image(struct UCD_info *ui, unw_word_t ip); + +#define STRUCT_MEMBER_P(struct_p, struct_offset) ((void *) ((char*) (struct_p) + (long) (struct_offset))) +#define STRUCT_MEMBER(member_type, struct_p, struct_offset) (*(member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset))) + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_lib.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_lib.h new file mode 100644 index 0000000..22be32e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UCD_lib.h @@ -0,0 +1,57 @@ +/* libunwind - a platform-independent unwind library + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _UCD_lib_h +#define _UCD_lib_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_access_fpreg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_access_fpreg.c new file mode 100644 index 0000000..0b8b86a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_access_fpreg.c @@ -0,0 +1,34 @@ +/* libunwind - a platform-independent unwind library + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UCD_lib.h" +#include "_UCD_internal.h" + +int +_UCD_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + print_error (__func__); + print_error (" not implemented\n"); + return -UNW_EINVAL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_elf.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_elf.c new file mode 100644 index 0000000..fb7b19a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_elf.c @@ -0,0 +1,5 @@ +/* We need to get a separate copy of the ELF-code into + libunwind-coredump since it cannot (and must not) have any ELF + dependencies on libunwind. */ +#include "libunwind_i.h" /* get ELFCLASS defined */ +#include "../elfxx.c" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_get_dyn_info_list_addr.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_get_dyn_info_list_addr.c new file mode 100644 index 0000000..0d11905 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_get_dyn_info_list_addr.c @@ -0,0 +1,108 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UCD_lib.h" +#include "_UCD_internal.h" + +#if UNW_TARGET_IA64 && defined(__linux) +# include "elf64.h" +# include "os-linux.h" + +static inline int +get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg, + int *countp) +{ + unsigned long lo, hi, off; + struct UPT_info *ui = arg; + struct map_iterator mi; + char path[PATH_MAX]; + unw_dyn_info_t *di; + unw_word_t res; + int count = 0; + + maps_init (&mi, ui->pid); + while (maps_next (&mi, &lo, &hi, &off)) + { + if (off) + continue; + + invalidate_edi (&ui->edi); + + if (elf_map_image (&ui->ei, path) < 0) + /* ignore unmappable stuff like "/SYSV00001b58 (deleted)" */ + continue; + + Debug (16, "checking object %s\n", path); + + di = tdep_find_unwind_table (&ui->edi, as, path, lo, off); + if (di) + { + res = _Uia64_find_dyn_list (as, di, arg); + if (res && count++ == 0) + { + Debug (12, "dyn_info_list_addr = 0x%lx\n", (long) res); + *dil_addr = res; + } + } + } + maps_close (&mi); + *countp = count; + return 0; +} + +#else + +static inline int +get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg, + int *countp) +{ +# warning Implement get_list_addr(), please. + *countp = 0; + return 0; +} + +#endif + +int +_UCD_get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, + void *arg) +{ + int count, ret; + + Debug (12, "looking for dyn_info list\n"); + + if ((ret = get_list_addr (as, dil_addr, arg, &count)) < 0) + return ret; + + /* If multiple dynamic-info list addresses are found, we would have + to determine which was is the one actually in use (since the + dynamic name resolution algorithm will pick one "winner"). + Perhaps we'd have to track them all until we find one that's + non-empty. Hopefully, this case simply will never arise, since + only libunwind defines the dynamic info list head. */ + assert (count <= 1); + + return (count > 0) ? 0 : -UNW_ENOINFO; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_put_unwind_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_put_unwind_info.c new file mode 100644 index 0000000..462e1d0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_put_unwind_info.c @@ -0,0 +1,36 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UCD_lib.h" +#include "_UCD_internal.h" + +void +_UCD_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg) +{ + if (!pi->unwind_info) + return; + free (pi->unwind_info); + pi->unwind_info = NULL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_resume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_resume.c new file mode 100644 index 0000000..a729c90 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/_UPT_resume.c @@ -0,0 +1,35 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UCD_lib.h" +#include "_UCD_internal.h" + +int +_UCD_resume (unw_addr_space_t as, unw_cursor_t *c, void *arg) +{ + print_error (__func__); + print_error (" not implemented\n"); + return -UNW_EINVAL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/libunwind-coredump.pc.in b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/libunwind-coredump.pc.in new file mode 100644 index 0000000..9cb62c0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/coredump/libunwind-coredump.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libunwind-coredump +Description: libunwind coredump library +Version: @VERSION@ +Requires: libunwind-generic libunwind +Libs: -L${libdir} -lunwind-coredump +Cflags: -I${includedir} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gexpr.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gexpr.c new file mode 100644 index 0000000..f63c3d2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gexpr.c @@ -0,0 +1,696 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "dwarf_i.h" +#include "libunwind_i.h" + +/* The "pick" operator provides an index range of 0..255 indicating + that the stack could at least have a depth of up to 256 elements, + but the GCC unwinder restricts the depth to 64, which seems + reasonable so we use the same value here. */ +#define MAX_EXPR_STACK_SIZE 64 + +#define NUM_OPERANDS(signature) (((signature) >> 6) & 0x3) +#define OPND1_TYPE(signature) (((signature) >> 3) & 0x7) +#define OPND2_TYPE(signature) (((signature) >> 0) & 0x7) + +#define OPND_SIGNATURE(n, t1, t2) (((n) << 6) | ((t1) << 3) | ((t2) << 0)) +#define OPND1(t1) OPND_SIGNATURE(1, t1, 0) +#define OPND2(t1, t2) OPND_SIGNATURE(2, t1, t2) + +#define VAL8 0x0 +#define VAL16 0x1 +#define VAL32 0x2 +#define VAL64 0x3 +#define ULEB128 0x4 +#define SLEB128 0x5 +#define OFFSET 0x6 /* 32-bit offset for 32-bit DWARF, 64-bit otherwise */ +#define ADDR 0x7 /* Machine address. */ + +static const uint8_t operands[256] = + { + [DW_OP_addr] = OPND1 (ADDR), + [DW_OP_const1u] = OPND1 (VAL8), + [DW_OP_const1s] = OPND1 (VAL8), + [DW_OP_const2u] = OPND1 (VAL16), + [DW_OP_const2s] = OPND1 (VAL16), + [DW_OP_const4u] = OPND1 (VAL32), + [DW_OP_const4s] = OPND1 (VAL32), + [DW_OP_const8u] = OPND1 (VAL64), + [DW_OP_const8s] = OPND1 (VAL64), + [DW_OP_pick] = OPND1 (VAL8), + [DW_OP_plus_uconst] = OPND1 (ULEB128), + [DW_OP_skip] = OPND1 (VAL16), + [DW_OP_bra] = OPND1 (VAL16), + [DW_OP_breg0 + 0] = OPND1 (SLEB128), + [DW_OP_breg0 + 1] = OPND1 (SLEB128), + [DW_OP_breg0 + 2] = OPND1 (SLEB128), + [DW_OP_breg0 + 3] = OPND1 (SLEB128), + [DW_OP_breg0 + 4] = OPND1 (SLEB128), + [DW_OP_breg0 + 5] = OPND1 (SLEB128), + [DW_OP_breg0 + 6] = OPND1 (SLEB128), + [DW_OP_breg0 + 7] = OPND1 (SLEB128), + [DW_OP_breg0 + 8] = OPND1 (SLEB128), + [DW_OP_breg0 + 9] = OPND1 (SLEB128), + [DW_OP_breg0 + 10] = OPND1 (SLEB128), + [DW_OP_breg0 + 11] = OPND1 (SLEB128), + [DW_OP_breg0 + 12] = OPND1 (SLEB128), + [DW_OP_breg0 + 13] = OPND1 (SLEB128), + [DW_OP_breg0 + 14] = OPND1 (SLEB128), + [DW_OP_breg0 + 15] = OPND1 (SLEB128), + [DW_OP_breg0 + 16] = OPND1 (SLEB128), + [DW_OP_breg0 + 17] = OPND1 (SLEB128), + [DW_OP_breg0 + 18] = OPND1 (SLEB128), + [DW_OP_breg0 + 19] = OPND1 (SLEB128), + [DW_OP_breg0 + 20] = OPND1 (SLEB128), + [DW_OP_breg0 + 21] = OPND1 (SLEB128), + [DW_OP_breg0 + 22] = OPND1 (SLEB128), + [DW_OP_breg0 + 23] = OPND1 (SLEB128), + [DW_OP_breg0 + 24] = OPND1 (SLEB128), + [DW_OP_breg0 + 25] = OPND1 (SLEB128), + [DW_OP_breg0 + 26] = OPND1 (SLEB128), + [DW_OP_breg0 + 27] = OPND1 (SLEB128), + [DW_OP_breg0 + 28] = OPND1 (SLEB128), + [DW_OP_breg0 + 29] = OPND1 (SLEB128), + [DW_OP_breg0 + 30] = OPND1 (SLEB128), + [DW_OP_breg0 + 31] = OPND1 (SLEB128), + [DW_OP_regx] = OPND1 (ULEB128), + [DW_OP_fbreg] = OPND1 (SLEB128), + [DW_OP_bregx] = OPND2 (ULEB128, SLEB128), + [DW_OP_piece] = OPND1 (ULEB128), + [DW_OP_deref_size] = OPND1 (VAL8), + [DW_OP_xderef_size] = OPND1 (VAL8), + [DW_OP_call2] = OPND1 (VAL16), + [DW_OP_call4] = OPND1 (VAL32), + [DW_OP_call_ref] = OPND1 (OFFSET) + }; + +static inline unw_sword_t +sword (unw_addr_space_t as, unw_word_t val) +{ + switch (dwarf_addr_size (as)) + { + case 1: return (int8_t) val; + case 2: return (int16_t) val; + case 4: return (int32_t) val; + case 8: return (int64_t) val; + default: abort (); + } +} + +static inline unw_word_t +read_operand (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, int operand_type, unw_word_t *val, void *arg) +{ + uint8_t u8; + uint16_t u16; + uint32_t u32; + uint64_t u64; + int ret; + + if (operand_type == ADDR) + switch (dwarf_addr_size (as)) + { + case 1: operand_type = VAL8; break; + case 2: operand_type = VAL16; break; + case 4: operand_type = VAL32; break; + case 8: operand_type = VAL64; break; + default: abort (); + } + + switch (operand_type) + { + case VAL8: + ret = dwarf_readu8 (as, a, addr, &u8, arg); + if (ret < 0) + return ret; + *val = u8; + break; + + case VAL16: + ret = dwarf_readu16 (as, a, addr, &u16, arg); + if (ret < 0) + return ret; + *val = u16; + break; + + case VAL32: + ret = dwarf_readu32 (as, a, addr, &u32, arg); + if (ret < 0) + return ret; + *val = u32; + break; + + case VAL64: + ret = dwarf_readu64 (as, a, addr, &u64, arg); + if (ret < 0) + return ret; + *val = u64; + break; + + case ULEB128: + ret = dwarf_read_uleb128 (as, a, addr, val, arg); + break; + + case SLEB128: + ret = dwarf_read_sleb128 (as, a, addr, val, arg); + break; + + case OFFSET: /* only used by DW_OP_call_ref, which we don't implement */ + default: + Debug (1, "Unexpected operand type %d\n", operand_type); + ret = -UNW_EINVAL; + } + return ret; +} + +HIDDEN int +dwarf_stack_aligned(struct dwarf_cursor *c, unw_word_t cfa_addr, + unw_word_t rbp_addr, unw_word_t *cfa_offset) { + unw_accessors_t *a; + int ret; + void *arg; + unw_word_t len; + uint8_t opcode; + unw_word_t operand1; + + a = unw_get_accessors_int (c->as); + arg = c->as_arg; + + ret = dwarf_read_uleb128(c->as, a, &rbp_addr, &len, arg); + if (len != 2 || ret < 0) + return 0; + + ret = dwarf_readu8(c->as, a, &rbp_addr, &opcode, arg); + if (ret < 0 || opcode != DW_OP_breg6) + return 0; + + ret = read_operand(c->as, a, &rbp_addr, + OPND1_TYPE(operands[opcode]), &operand1, arg); + + if (ret < 0 || operand1 != 0) + return 0; + + ret = dwarf_read_uleb128(c->as, a, &cfa_addr, &len, arg); + if (ret < 0 || len != 3) + return 0; + + ret = dwarf_readu8(c->as, a, &cfa_addr, &opcode, arg); + if (ret < 0 || opcode != DW_OP_breg6) + return 0; + + ret = read_operand(c->as, a, &cfa_addr, + OPND1_TYPE(operands[opcode]), &operand1, arg); + if (ret < 0) + return 0; + + ret = dwarf_readu8(c->as, a, &cfa_addr, &opcode, arg); + if (ret < 0 || opcode != DW_OP_deref) + return 0; + + *cfa_offset = operand1; + return 1; +} + +HIDDEN int +dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr, unw_word_t len, + unw_word_t *valp, int *is_register) +{ + unw_word_t operand1 = 0, operand2 = 0, tmp1, tmp2 = 0, tmp3, end_addr; + uint8_t opcode, operands_signature, u8; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + unw_word_t stack[MAX_EXPR_STACK_SIZE]; + unsigned int tos = 0; + uint16_t u16; + uint32_t u32; + uint64_t u64; + int ret; +# define pop() \ +({ \ + if ((tos - 1) >= MAX_EXPR_STACK_SIZE) \ + { \ + Debug (1, "Stack underflow\n"); \ + return -UNW_EINVAL; \ + } \ + stack[--tos]; \ +}) +# define push(x) \ +do { \ + unw_word_t _x = (x); \ + if (tos >= MAX_EXPR_STACK_SIZE) \ + { \ + Debug (1, "Stack overflow\n"); \ + return -UNW_EINVAL; \ + } \ + stack[tos++] = _x; \ +} while (0) +# define pick(n) \ +({ \ + unsigned int _index = tos - 1 - (n); \ + if (_index >= MAX_EXPR_STACK_SIZE) \ + { \ + Debug (1, "Out-of-stack pick\n"); \ + return -UNW_EINVAL; \ + } \ + stack[_index]; \ +}) + + as = c->as; + arg = c->as_arg; + a = unw_get_accessors_int (as); + end_addr = *addr + len; + *is_register = 0; + + Debug (14, "len=%lu, pushing cfa=0x%lx\n", + (unsigned long) len, (unsigned long) c->cfa); + + push (c->cfa); /* push current CFA as required by DWARF spec */ + + while (*addr < end_addr) + { + if ((ret = dwarf_readu8 (as, a, addr, &opcode, arg)) < 0) + return ret; + + operands_signature = operands[opcode]; + + if (unlikely (NUM_OPERANDS (operands_signature) > 0)) + { + if ((ret = read_operand (as, a, addr, + OPND1_TYPE (operands_signature), + &operand1, arg)) < 0) + return ret; + if (NUM_OPERANDS (operands_signature) > 1) + if ((ret = read_operand (as, a, addr, + OPND2_TYPE (operands_signature), + &operand2, arg)) < 0) + return ret; + } + + switch ((dwarf_expr_op_t) opcode) + { + case DW_OP_lit0: case DW_OP_lit1: case DW_OP_lit2: + case DW_OP_lit3: case DW_OP_lit4: case DW_OP_lit5: + case DW_OP_lit6: case DW_OP_lit7: case DW_OP_lit8: + case DW_OP_lit9: case DW_OP_lit10: case DW_OP_lit11: + case DW_OP_lit12: case DW_OP_lit13: case DW_OP_lit14: + case DW_OP_lit15: case DW_OP_lit16: case DW_OP_lit17: + case DW_OP_lit18: case DW_OP_lit19: case DW_OP_lit20: + case DW_OP_lit21: case DW_OP_lit22: case DW_OP_lit23: + case DW_OP_lit24: case DW_OP_lit25: case DW_OP_lit26: + case DW_OP_lit27: case DW_OP_lit28: case DW_OP_lit29: + case DW_OP_lit30: case DW_OP_lit31: + Debug (15, "OP_lit(%d)\n", (int) opcode - DW_OP_lit0); + push (opcode - DW_OP_lit0); + break; + + case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: + case DW_OP_breg3: case DW_OP_breg4: case DW_OP_breg5: + case DW_OP_breg6: case DW_OP_breg7: case DW_OP_breg8: + case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11: + case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: + case DW_OP_breg15: case DW_OP_breg16: case DW_OP_breg17: + case DW_OP_breg18: case DW_OP_breg19: case DW_OP_breg20: + case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23: + case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: + case DW_OP_breg27: case DW_OP_breg28: case DW_OP_breg29: + case DW_OP_breg30: case DW_OP_breg31: + Debug (15, "OP_breg(r%d,0x%lx)\n", + (int) opcode - DW_OP_breg0, (unsigned long) operand1); + if ((ret = unw_get_reg (dwarf_to_cursor (c), + dwarf_to_unw_regnum (opcode - DW_OP_breg0), + &tmp1)) < 0) + return ret; + push (tmp1 + operand1); + break; + + case DW_OP_bregx: + Debug (15, "OP_bregx(r%d,0x%lx)\n", + (int) operand1, (unsigned long) operand2); + if ((ret = unw_get_reg (dwarf_to_cursor (c), + dwarf_to_unw_regnum (operand1), &tmp1)) < 0) + return ret; + push (tmp1 + operand2); + break; + + case DW_OP_reg0: case DW_OP_reg1: case DW_OP_reg2: + case DW_OP_reg3: case DW_OP_reg4: case DW_OP_reg5: + case DW_OP_reg6: case DW_OP_reg7: case DW_OP_reg8: + case DW_OP_reg9: case DW_OP_reg10: case DW_OP_reg11: + case DW_OP_reg12: case DW_OP_reg13: case DW_OP_reg14: + case DW_OP_reg15: case DW_OP_reg16: case DW_OP_reg17: + case DW_OP_reg18: case DW_OP_reg19: case DW_OP_reg20: + case DW_OP_reg21: case DW_OP_reg22: case DW_OP_reg23: + case DW_OP_reg24: case DW_OP_reg25: case DW_OP_reg26: + case DW_OP_reg27: case DW_OP_reg28: case DW_OP_reg29: + case DW_OP_reg30: case DW_OP_reg31: + Debug (15, "OP_reg(r%d)\n", (int) opcode - DW_OP_reg0); + *valp = dwarf_to_unw_regnum (opcode - DW_OP_reg0); + *is_register = 1; + return 0; + + case DW_OP_regx: + Debug (15, "OP_regx(r%d)\n", (int) operand1); + *valp = dwarf_to_unw_regnum (operand1); + *is_register = 1; + return 0; + + case DW_OP_addr: + case DW_OP_const1u: + case DW_OP_const2u: + case DW_OP_const4u: + case DW_OP_const8u: + case DW_OP_constu: + case DW_OP_const8s: + case DW_OP_consts: + Debug (15, "OP_const(0x%lx)\n", (unsigned long) operand1); + push (operand1); + break; + + case DW_OP_const1s: + if (operand1 & 0x80) + operand1 |= ((unw_word_t) -1) << 8; + Debug (15, "OP_const1s(%ld)\n", (long) operand1); + push (operand1); + break; + + case DW_OP_const2s: + if (operand1 & 0x8000) + operand1 |= ((unw_word_t) -1) << 16; + Debug (15, "OP_const2s(%ld)\n", (long) operand1); + push (operand1); + break; + + case DW_OP_const4s: + if (operand1 & 0x80000000) + operand1 |= (((unw_word_t) -1) << 16) << 16; + Debug (15, "OP_const4s(%ld)\n", (long) operand1); + push (operand1); + break; + + case DW_OP_deref: + Debug (15, "OP_deref\n"); + tmp1 = pop (); + if ((ret = dwarf_readw (as, a, &tmp1, &tmp2, arg)) < 0) + return ret; + push (tmp2); + break; + + case DW_OP_deref_size: + Debug (15, "OP_deref_size(%d)\n", (int) operand1); + tmp1 = pop (); + switch (operand1) + { + default: + Debug (1, "Unexpected DW_OP_deref_size size %d\n", + (int) operand1); + return -UNW_EINVAL; + + case 1: + if ((ret = dwarf_readu8 (as, a, &tmp1, &u8, arg)) < 0) + return ret; + tmp2 = u8; + break; + + case 2: + if ((ret = dwarf_readu16 (as, a, &tmp1, &u16, arg)) < 0) + return ret; + tmp2 = u16; + break; + + case 3: + case 4: + if ((ret = dwarf_readu32 (as, a, &tmp1, &u32, arg)) < 0) + return ret; + tmp2 = u32; + if (operand1 == 3) + { + if (dwarf_is_big_endian (as)) + tmp2 >>= 8; + else + tmp2 &= 0xffffff; + } + break; + case 5: + case 6: + case 7: + case 8: + if ((ret = dwarf_readu64 (as, a, &tmp1, &u64, arg)) < 0) + return ret; + tmp2 = u64; + if (operand1 != 8) + { + if (dwarf_is_big_endian (as)) + tmp2 >>= 64 - 8 * operand1; + else + tmp2 &= (~ (unw_word_t) 0) << (8 * operand1); + } + break; + } + push (tmp2); + break; + + case DW_OP_dup: + Debug (15, "OP_dup\n"); + push (pick (0)); + break; + + case DW_OP_drop: + Debug (15, "OP_drop\n"); + (void) pop (); + break; + + case DW_OP_pick: + Debug (15, "OP_pick(%d)\n", (int) operand1); + push (pick (operand1)); + break; + + case DW_OP_over: + Debug (15, "OP_over\n"); + push (pick (1)); + break; + + case DW_OP_swap: + Debug (15, "OP_swap\n"); + tmp1 = pop (); + tmp2 = pop (); + push (tmp1); + push (tmp2); + break; + + case DW_OP_rot: + Debug (15, "OP_rot\n"); + tmp1 = pop (); + tmp2 = pop (); + tmp3 = pop (); + push (tmp1); + push (tmp3); + push (tmp2); + break; + + case DW_OP_abs: + Debug (15, "OP_abs\n"); + tmp1 = pop (); + if (tmp1 & ((unw_word_t) 1 << (8 * dwarf_addr_size (as) - 1))) + tmp1 = -tmp1; + push (tmp1); + break; + + case DW_OP_and: + Debug (15, "OP_and\n"); + tmp1 = pop (); + tmp2 = pop (); + push (tmp1 & tmp2); + break; + + case DW_OP_div: + Debug (15, "OP_div\n"); + tmp1 = pop (); + tmp2 = pop (); + if (tmp1) + tmp1 = sword (as, tmp2) / sword (as, tmp1); + push (tmp1); + break; + + case DW_OP_minus: + Debug (15, "OP_minus\n"); + tmp1 = pop (); + tmp2 = pop (); + tmp1 = tmp2 - tmp1; + push (tmp1); + break; + + case DW_OP_mod: + Debug (15, "OP_mod\n"); + tmp1 = pop (); + tmp2 = pop (); + if (tmp1) + tmp1 = tmp2 % tmp1; + push (tmp1); + break; + + case DW_OP_mul: + Debug (15, "OP_mul\n"); + tmp1 = pop (); + tmp2 = pop (); + if (tmp1) + tmp1 = tmp2 * tmp1; + push (tmp1); + break; + + case DW_OP_neg: + Debug (15, "OP_neg\n"); + push (-pop ()); + break; + + case DW_OP_not: + Debug (15, "OP_not\n"); + push (~pop ()); + break; + + case DW_OP_or: + Debug (15, "OP_or\n"); + tmp1 = pop (); + tmp2 = pop (); + push (tmp1 | tmp2); + break; + + case DW_OP_plus: + Debug (15, "OP_plus\n"); + tmp1 = pop (); + tmp2 = pop (); + push (tmp1 + tmp2); + break; + + case DW_OP_plus_uconst: + Debug (15, "OP_plus_uconst(%lu)\n", (unsigned long) operand1); + tmp1 = pop (); + push (tmp1 + operand1); + break; + + case DW_OP_shl: + Debug (15, "OP_shl\n"); + tmp1 = pop (); + tmp2 = pop (); + push (tmp2 << tmp1); + break; + + case DW_OP_shr: + Debug (15, "OP_shr\n"); + tmp1 = pop (); + tmp2 = pop (); + push (tmp2 >> tmp1); + break; + + case DW_OP_shra: + Debug (15, "OP_shra\n"); + tmp1 = pop (); + tmp2 = pop (); + push (sword (as, tmp2) >> tmp1); + break; + + case DW_OP_xor: + Debug (15, "OP_xor\n"); + tmp1 = pop (); + tmp2 = pop (); + push (tmp1 ^ tmp2); + break; + + case DW_OP_le: + Debug (15, "OP_le\n"); + tmp1 = pop (); + tmp2 = pop (); + push (sword (as, tmp2) <= sword (as, tmp1)); + break; + + case DW_OP_ge: + Debug (15, "OP_ge\n"); + tmp1 = pop (); + tmp2 = pop (); + push (sword (as, tmp2) >= sword (as, tmp1)); + break; + + case DW_OP_eq: + Debug (15, "OP_eq\n"); + tmp1 = pop (); + tmp2 = pop (); + push (sword (as, tmp2) == sword (as, tmp1)); + break; + + case DW_OP_lt: + Debug (15, "OP_lt\n"); + tmp1 = pop (); + tmp2 = pop (); + push (sword (as, tmp2) < sword (as, tmp1)); + break; + + case DW_OP_gt: + Debug (15, "OP_gt\n"); + tmp1 = pop (); + tmp2 = pop (); + push (sword (as, tmp2) > sword (as, tmp1)); + break; + + case DW_OP_ne: + Debug (15, "OP_ne\n"); + tmp1 = pop (); + tmp2 = pop (); + push (sword (as, tmp2) != sword (as, tmp1)); + break; + + case DW_OP_skip: + Debug (15, "OP_skip(%d)\n", (int16_t) operand1); + *addr += (int16_t) operand1; + break; + + case DW_OP_bra: + Debug (15, "OP_skip(%d)\n", (int16_t) operand1); + tmp1 = pop (); + if (tmp1) + *addr += (int16_t) operand1; + break; + + case DW_OP_nop: + Debug (15, "OP_nop\n"); + break; + + case DW_OP_call2: + case DW_OP_call4: + case DW_OP_call_ref: + case DW_OP_fbreg: + case DW_OP_piece: + case DW_OP_push_object_address: + case DW_OP_xderef: + case DW_OP_xderef_size: + default: + Debug (1, "Unexpected opcode 0x%x\n", opcode); + return -UNW_EINVAL; + } + } + *valp = pop (); + Debug (14, "final value = 0x%lx\n", (unsigned long) *valp); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gfde.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gfde.c new file mode 100644 index 0000000..9250b89 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gfde.c @@ -0,0 +1,359 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "dwarf_i.h" + +static inline int +is_cie_id (unw_word_t val, int is_debug_frame) +{ + /* The CIE ID is normally 0xffffffff (for 32-bit ELF) or + 0xffffffffffffffff (for 64-bit ELF). However, .eh_frame + uses 0. */ + if (is_debug_frame) + return (val == (uint32_t)(-1) || val == (uint64_t)(-1)); + else + return (val == 0); +} + +/* Note: we don't need to keep track of more than the first four + characters of the augmentation string, because we (a) ignore any + augmentation string contents once we find an unrecognized character + and (b) those characters that we do recognize, can't be + repeated. */ +static inline int +parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr, + const unw_proc_info_t *pi, struct dwarf_cie_info *dci, + int is_debug_frame, void *arg) +{ + uint8_t version, ch, augstr[5], fde_encoding, handler_encoding; + unw_word_t len, cie_end_addr, aug_size; + uint32_t u32val; + uint64_t u64val; + size_t i; + int ret; +# define STR2(x) #x +# define STR(x) STR2(x) + + /* Pick appropriate default for FDE-encoding. DWARF spec says + start-IP (initial_location) and the code-size (address_range) are + "address-unit sized constants". The `R' augmentation can be used + to override this, but by default, we pick an address-sized unit + for fde_encoding. */ + switch (dwarf_addr_size (as)) + { + case 4: fde_encoding = DW_EH_PE_udata4; break; + case 8: fde_encoding = DW_EH_PE_udata8; break; + default: fde_encoding = DW_EH_PE_omit; break; + } + + dci->lsda_encoding = DW_EH_PE_omit; + dci->handler = 0; + + if ((ret = dwarf_readu32 (as, a, &addr, &u32val, arg)) < 0) + return ret; + + if (u32val != 0xffffffff) + { + /* the CIE is in the 32-bit DWARF format */ + uint32_t cie_id; + /* DWARF says CIE id should be 0xffffffff, but in .eh_frame, it's 0 */ + const uint32_t expected_id = (is_debug_frame) ? 0xffffffff : 0; + + len = u32val; + cie_end_addr = addr + len; + if ((ret = dwarf_readu32 (as, a, &addr, &cie_id, arg)) < 0) + return ret; + if (cie_id != expected_id) + { + Debug (1, "Unexpected CIE id %x\n", cie_id); + return -UNW_EINVAL; + } + } + else + { + /* the CIE is in the 64-bit DWARF format */ + uint64_t cie_id; + /* DWARF says CIE id should be 0xffffffffffffffff, but in + .eh_frame, it's 0 */ + const uint64_t expected_id = (is_debug_frame) ? 0xffffffffffffffffull : 0; + + if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0) + return ret; + len = u64val; + cie_end_addr = addr + len; + if ((ret = dwarf_readu64 (as, a, &addr, &cie_id, arg)) < 0) + return ret; + if (cie_id != expected_id) + { + Debug (1, "Unexpected CIE id %llx\n", (long long) cie_id); + return -UNW_EINVAL; + } + } + dci->cie_instr_end = cie_end_addr; + + if ((ret = dwarf_readu8 (as, a, &addr, &version, arg)) < 0) + return ret; + + /* GCC emits version 1??? */ + if (version != 1 && (version < DWARF_CIE_VERSION || version > DWARF_CIE_VERSION_MAX)) + { + Debug (1, "Got CIE version %u, expected version 1 or between " + STR (DWARF_CIE_VERSION) " and " STR (DWARF_CIE_VERSION_MAX) "\n", version); + return -UNW_EBADVERSION; + } + + /* read and parse the augmentation string: */ + memset (augstr, 0, sizeof (augstr)); + for (i = 0;;) + { + if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0) + return ret; + + if (!ch) + break; /* end of augmentation string */ + + if (i < sizeof (augstr) - 1) + augstr[i++] = ch; + } + + if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->code_align, arg)) < 0 + || (ret = dwarf_read_sleb128 (as, a, &addr, &dci->data_align, arg)) < 0) + return ret; + + /* Read the return-address column either as a u8 or as a uleb128. */ + if (version == 1) + { + if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0) + return ret; + dci->ret_addr_column = ch; + } + else if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->ret_addr_column, + arg)) < 0) + return ret; + + i = 0; + if (augstr[0] == 'z') + { + dci->sized_augmentation = 1; + if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0) + return ret; + i++; + } + + for (; i < sizeof (augstr) && augstr[i]; ++i) + switch (augstr[i]) + { + case 'L': + /* read the LSDA pointer-encoding format. */ + if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0) + return ret; + dci->lsda_encoding = ch; + break; + + case 'R': + /* read the FDE pointer-encoding format. */ + if ((ret = dwarf_readu8 (as, a, &addr, &fde_encoding, arg)) < 0) + return ret; + break; + + case 'P': + /* read the personality-routine pointer-encoding format. */ + if ((ret = dwarf_readu8 (as, a, &addr, &handler_encoding, arg)) < 0) + return ret; + if ((ret = dwarf_read_encoded_pointer (as, a, &addr, handler_encoding, + pi, &dci->handler, arg)) < 0) + return ret; + break; + + case 'S': + /* This is a signal frame. */ + dci->signal_frame = 1; + + /* Temporarily set it to one so dwarf_parse_fde() knows that + it should fetch the actual ABI/TAG pair from the FDE. */ + dci->have_abi_marker = 1; + break; + + default: + Debug (1, "Unexpected augmentation string `%s'\n", augstr); + if (dci->sized_augmentation) + /* If we have the size of the augmentation body, we can skip + over the parts that we don't understand, so we're OK. */ + goto done; + else + return -UNW_EINVAL; + } + done: + dci->fde_encoding = fde_encoding; + dci->cie_instr_start = addr; + Debug (15, "CIE parsed OK, augmentation = \"%s\", handler=0x%lx\n", + augstr, (long) dci->handler); + return 0; +} + +/* Extract proc-info from the FDE starting at adress ADDR. + + Pass BASE as zero for eh_frame behaviour, or a pointer to + debug_frame base for debug_frame behaviour. */ + +HIDDEN int +dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addrp, unw_proc_info_t *pi, + unw_word_t base, + int need_unwind_info, int is_debug_frame, + void *arg) +{ + unw_word_t fde_end_addr, cie_addr, cie_offset_addr, aug_end_addr = 0; + unw_word_t start_ip, ip_range, aug_size, addr = *addrp; + int ret, ip_range_encoding; + struct dwarf_cie_info dci; + uint64_t u64val; + uint32_t u32val; + + Debug (12, "FDE @ 0x%lx\n", (long) addr); + + memset (&dci, 0, sizeof (dci)); + + if ((ret = dwarf_readu32 (as, a, &addr, &u32val, arg)) < 0) + return ret; + + if (u32val != 0xffffffff) + { + int32_t cie_offset = 0; + + /* In some configurations, an FDE with a 0 length indicates the + end of the FDE-table. */ + if (u32val == 0) + return -UNW_ENOINFO; + + /* the FDE is in the 32-bit DWARF format */ + + *addrp = fde_end_addr = addr + u32val; + cie_offset_addr = addr; + + if ((ret = dwarf_reads32 (as, a, &addr, &cie_offset, arg)) < 0) + return ret; + + if (is_cie_id (cie_offset, is_debug_frame)) + /* ignore CIEs (happens during linear searches) */ + return 0; + + if (is_debug_frame) + cie_addr = base + cie_offset; + else + /* DWARF says that the CIE_pointer in the FDE is a + .debug_frame-relative offset, but the GCC-generated .eh_frame + sections instead store a "pcrelative" offset, which is just + as fine as it's self-contained. */ + cie_addr = cie_offset_addr - cie_offset; + } + else + { + int64_t cie_offset = 0; + + /* the FDE is in the 64-bit DWARF format */ + + if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0) + return ret; + + *addrp = fde_end_addr = addr + u64val; + cie_offset_addr = addr; + + if ((ret = dwarf_reads64 (as, a, &addr, &cie_offset, arg)) < 0) + return ret; + + if (is_cie_id (cie_offset, is_debug_frame)) + /* ignore CIEs (happens during linear searches) */ + return 0; + + if (is_debug_frame) + cie_addr = base + cie_offset; + else + /* DWARF says that the CIE_pointer in the FDE is a + .debug_frame-relative offset, but the GCC-generated .eh_frame + sections instead store a "pcrelative" offset, which is just + as fine as it's self-contained. */ + cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset); + } + + Debug (15, "looking for CIE at address %lx\n", (long) cie_addr); + + if ((ret = parse_cie (as, a, cie_addr, pi, &dci, is_debug_frame, arg)) < 0) + return ret; + + /* IP-range has same encoding as FDE pointers, except that it's + always an absolute value: */ + ip_range_encoding = dci.fde_encoding & DW_EH_PE_FORMAT_MASK; + + if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.fde_encoding, + pi, &start_ip, arg)) < 0 + || (ret = dwarf_read_encoded_pointer (as, a, &addr, ip_range_encoding, + pi, &ip_range, arg)) < 0) + return ret; + pi->start_ip = start_ip; + pi->end_ip = start_ip + ip_range; + pi->handler = dci.handler; + + if (dci.sized_augmentation) + { + if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0) + return ret; + aug_end_addr = addr + aug_size; + } + + if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.lsda_encoding, + pi, &pi->lsda, arg)) < 0) + return ret; + + Debug (15, "FDE covers IP 0x%lx-0x%lx, LSDA=0x%lx\n", + (long) pi->start_ip, (long) pi->end_ip, (long) pi->lsda); + + if (need_unwind_info) + { + pi->format = UNW_INFO_FORMAT_TABLE; + pi->unwind_info_size = sizeof (dci); + pi->unwind_info = mempool_alloc (&dwarf_cie_info_pool); + if (!pi->unwind_info) + return -UNW_ENOMEM; + + if (dci.have_abi_marker) + { + if ((ret = dwarf_readu16 (as, a, &addr, &dci.abi, arg)) < 0 + || (ret = dwarf_readu16 (as, a, &addr, &dci.tag, arg)) < 0) + return ret; + Debug (13, "Found ABI marker = (abi=%u, tag=%u)\n", + dci.abi, dci.tag); + } + + if (dci.sized_augmentation) + dci.fde_instr_start = aug_end_addr; + else + dci.fde_instr_start = addr; + dci.fde_instr_end = fde_end_addr; + + memcpy (pi->unwind_info, &dci, sizeof (dci)); + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gfind_proc_info-lsb.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gfind_proc_info-lsb.c new file mode 100644 index 0000000..509ceff --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gfind_proc_info-lsb.c @@ -0,0 +1,935 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Locate an FDE via the ELF data-structures defined by LSB v1.3 + (http://www.linuxbase.org/spec/). */ + +#include +#include +#include + +#include "dwarf_i.h" +#include "dwarf-eh.h" +#include "libunwind_i.h" + +struct table_entry + { + int32_t start_ip_offset; + int32_t fde_offset; + }; + +#ifndef UNW_REMOTE_ONLY + +#ifdef __linux +#include "os-linux.h" +#endif + +static ALIAS(dwarf_search_unwind_table) int +dwarf_search_unwind_table_int (unw_addr_space_t as, + unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); +static int +linear_search (unw_addr_space_t as, unw_word_t ip, + unw_word_t eh_frame_start, unw_word_t eh_frame_end, + unw_word_t fde_count, + unw_proc_info_t *pi, int need_unwind_info, void *arg) +{ + unw_accessors_t *a = unw_get_accessors_int (unw_local_addr_space); + unw_word_t i = 0, fde_addr, addr = eh_frame_start; + int ret; + + while (i++ < fde_count && addr < eh_frame_end) + { + fde_addr = addr; + if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, + eh_frame_start, + 0, 0, arg)) < 0) + return ret; + + if (ip >= pi->start_ip && ip < pi->end_ip) + { + if (!need_unwind_info) + return 1; + addr = fde_addr; + if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, + eh_frame_start, + need_unwind_info, 0, + arg)) + < 0) + return ret; + return 1; + } + } + return -UNW_ENOINFO; +} +#endif /* !UNW_REMOTE_ONLY */ + +#ifdef CONFIG_DEBUG_FRAME +/* Load .debug_frame section from FILE. Allocates and returns space + in *BUF, and sets *BUFSIZE to its size. IS_LOCAL is 1 if using the + local process, in which case we can search the system debug file + directory; 0 for other address spaces, in which case we do + not. Returns 0 on success, 1 on error. Succeeds even if the file + contains no .debug_frame. */ +/* XXX: Could use mmap; but elf_map_image keeps tons mapped in. */ + +static int +load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local) +{ + struct elf_image ei; + Elf_W (Shdr) *shdr; + int ret; + + ei.image = NULL; + + ret = elf_w (load_debuglink) (file, &ei, is_local); + if (ret != 0) + return ret; + + shdr = elf_w (find_section) (&ei, ".debug_frame"); + if (!shdr || + (shdr->sh_offset + shdr->sh_size > ei.size)) + { + munmap(ei.image, ei.size); + return 1; + } + + *bufsize = shdr->sh_size; + *buf = malloc (*bufsize); + + memcpy(*buf, shdr->sh_offset + ei.image, *bufsize); + + Debug (4, "read %zd bytes of .debug_frame from offset %zd\n", + *bufsize, shdr->sh_offset); + + munmap(ei.image, ei.size); + return 0; +} + +/* Locate the binary which originated the contents of address ADDR. Return + the name of the binary in *name (space is allocated by the caller) + Returns 0 if a binary is successfully found, or 1 if an error occurs. */ + +static int +find_binary_for_address (unw_word_t ip, char *name, size_t name_size) +{ +#if defined(__linux) && (!UNW_REMOTE_ONLY) + struct map_iterator mi; + int found = 0; + int pid = getpid (); + unsigned long segbase, mapoff, hi; + + if (maps_init (&mi, pid) != 0) + return 1; + + while (maps_next (&mi, &segbase, &hi, &mapoff)) + if (ip >= segbase && ip < hi) + { + size_t len = strlen (mi.path); + + if (len + 1 <= name_size) + { + memcpy (name, mi.path, len + 1); + found = 1; + } + break; + } + maps_close (&mi); + return !found; +#endif + + return 1; +} + +/* Locate and/or try to load a debug_frame section for address ADDR. Return + pointer to debug frame descriptor, or zero if not found. */ + +static struct unw_debug_frame_list * +locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname, + unw_word_t start, unw_word_t end) +{ + struct unw_debug_frame_list *w, *fdesc = 0; + char path[PATH_MAX]; + char *name = path; + int err; + char *buf; + size_t bufsize; + + /* First, see if we loaded this frame already. */ + + for (w = as->debug_frames; w; w = w->next) + { + Debug (4, "checking %p: %lx-%lx\n", w, (long)w->start, (long)w->end); + if (addr >= w->start && addr < w->end) + return w; + } + + /* If the object name we receive is blank, there's still a chance of locating + the file by parsing /proc/self/maps. */ + + if (strcmp (dlname, "") == 0) + { + err = find_binary_for_address (addr, name, sizeof(path)); + if (err) + { + Debug (15, "tried to locate binary for 0x%" PRIx64 ", but no luck\n", + (uint64_t) addr); + return 0; + } + } + else + name = (char*) dlname; + + err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space); + + if (!err) + { + fdesc = malloc (sizeof (struct unw_debug_frame_list)); + + fdesc->start = start; + fdesc->end = end; + fdesc->debug_frame = buf; + fdesc->debug_frame_size = bufsize; + fdesc->index = NULL; + fdesc->next = as->debug_frames; + + as->debug_frames = fdesc; + } + + return fdesc; +} + +struct debug_frame_tab + { + struct table_entry *tab; + uint32_t length; + uint32_t size; + }; + +static void +debug_frame_tab_append (struct debug_frame_tab *tab, + unw_word_t fde_offset, unw_word_t start_ip) +{ + unsigned int length = tab->length; + + if (length == tab->size) + { + tab->size *= 2; + tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->size); + } + + tab->tab[length].fde_offset = fde_offset; + tab->tab[length].start_ip_offset = start_ip; + + tab->length = length + 1; +} + +static void +debug_frame_tab_shrink (struct debug_frame_tab *tab) +{ + if (tab->size > tab->length) + { + tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->length); + tab->size = tab->length; + } +} + +static int +debug_frame_tab_compare (const void *a, const void *b) +{ + const struct table_entry *fa = a, *fb = b; + + if (fa->start_ip_offset > fb->start_ip_offset) + return 1; + else if (fa->start_ip_offset < fb->start_ip_offset) + return -1; + else + return 0; +} + +HIDDEN int +dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip, + unw_word_t segbase, const char* obj_name, + unw_word_t start, unw_word_t end) +{ + unw_dyn_info_t *di; + struct unw_debug_frame_list *fdesc = 0; + unw_accessors_t *a; + unw_word_t addr; + + Debug (15, "Trying to find .debug_frame for %s\n", obj_name); + di = di_debug; + + fdesc = locate_debug_info (unw_local_addr_space, ip, obj_name, start, end); + + if (!fdesc) + { + Debug (15, "couldn't load .debug_frame\n"); + return found; + } + else + { + char *buf; + size_t bufsize; + unw_word_t item_start, item_end = 0; + uint32_t u32val = 0; + uint64_t cie_id = 0; + struct debug_frame_tab tab; + + Debug (15, "loaded .debug_frame\n"); + + buf = fdesc->debug_frame; + bufsize = fdesc->debug_frame_size; + + if (bufsize == 0) + { + Debug (15, "zero-length .debug_frame\n"); + return found; + } + + /* Now create a binary-search table, if it does not already exist. */ + if (!fdesc->index) + { + addr = (unw_word_t) (uintptr_t) buf; + + a = unw_get_accessors_int (unw_local_addr_space); + + /* Find all FDE entries in debug_frame, and make into a sorted + index. */ + + tab.length = 0; + tab.size = 16; + tab.tab = calloc (tab.size, sizeof (struct table_entry)); + + while (addr < (unw_word_t) (uintptr_t) (buf + bufsize)) + { + uint64_t id_for_cie; + item_start = addr; + + dwarf_readu32 (unw_local_addr_space, a, &addr, &u32val, NULL); + + if (u32val == 0) + break; + else if (u32val != 0xffffffff) + { + uint32_t cie_id32 = 0; + item_end = addr + u32val; + dwarf_readu32 (unw_local_addr_space, a, &addr, &cie_id32, + NULL); + cie_id = cie_id32; + id_for_cie = 0xffffffff; + } + else + { + uint64_t u64val = 0; + /* Extended length. */ + dwarf_readu64 (unw_local_addr_space, a, &addr, &u64val, NULL); + item_end = addr + u64val; + + dwarf_readu64 (unw_local_addr_space, a, &addr, &cie_id, NULL); + id_for_cie = 0xffffffffffffffffull; + } + + /*Debug (1, "CIE/FDE id = %.8x\n", (int) cie_id);*/ + + if (cie_id == id_for_cie) + ; + /*Debug (1, "Found CIE at %.8x.\n", item_start);*/ + else + { + unw_word_t fde_addr = item_start; + unw_proc_info_t this_pi; + int err; + + /*Debug (1, "Found FDE at %.8x\n", item_start);*/ + + err = dwarf_extract_proc_info_from_fde (unw_local_addr_space, + a, &fde_addr, + &this_pi, + (uintptr_t) buf, 0, 1, + NULL); + if (err == 0) + { + Debug (15, "start_ip = %lx, end_ip = %lx\n", + (long) this_pi.start_ip, (long) this_pi.end_ip); + debug_frame_tab_append (&tab, + item_start - (unw_word_t) (uintptr_t) buf, + this_pi.start_ip); + } + /*else + Debug (1, "FDE parse failed\n");*/ + } + + addr = item_end; + } + + debug_frame_tab_shrink (&tab); + qsort (tab.tab, tab.length, sizeof (struct table_entry), + debug_frame_tab_compare); + /* for (i = 0; i < tab.length; i++) + { + fprintf (stderr, "ip %x, fde offset %x\n", + (int) tab.tab[i].start_ip_offset, + (int) tab.tab[i].fde_offset); + }*/ + fdesc->index = tab.tab; + fdesc->index_size = tab.length; + } + + di->format = UNW_INFO_FORMAT_TABLE; + di->start_ip = fdesc->start; + di->end_ip = fdesc->end; + di->u.ti.name_ptr = (unw_word_t) (uintptr_t) obj_name; + di->u.ti.table_data = (unw_word_t *) fdesc; + di->u.ti.table_len = sizeof (*fdesc) / sizeof (unw_word_t); + di->u.ti.segbase = segbase; + + found = 1; + Debug (15, "found debug_frame table `%s': segbase=0x%lx, len=%lu, " + "gp=0x%lx, table_data=0x%lx\n", + (char *) (uintptr_t) di->u.ti.name_ptr, + (long) di->u.ti.segbase, (long) di->u.ti.table_len, + (long) di->gp, (long) di->u.ti.table_data); + } + return found; +} + +#endif /* CONFIG_DEBUG_FRAME */ + +#ifndef UNW_REMOTE_ONLY + +static Elf_W (Addr) +dwarf_find_eh_frame_section(struct dl_phdr_info *info) +{ + int rc; + struct elf_image ei; + Elf_W (Addr) eh_frame = 0; + Elf_W (Shdr)* shdr; + const char *file = info->dlpi_name; + char exepath[PATH_MAX]; + + if (strlen(file) == 0) + { + tdep_get_exe_image_path(exepath); + file = exepath; + } + + Debug (1, "looking for .eh_frame section in %s\n", + file); + + rc = elf_map_image (&ei, file); + if (rc != 0) + return 0; + + shdr = elf_w (find_section) (&ei, ".eh_frame"); + if (!shdr) + goto out; + + eh_frame = shdr->sh_addr + info->dlpi_addr; + Debug (4, "found .eh_frame at address %lx\n", + eh_frame); + +out: + munmap (ei.image, ei.size); + + return eh_frame; +} + +struct dwarf_callback_data + { + /* in: */ + unw_word_t ip; /* instruction-pointer we're looking for */ + unw_proc_info_t *pi; /* proc-info pointer */ + int need_unwind_info; + /* out: */ + int single_fde; /* did we find a single FDE? (vs. a table) */ + unw_dyn_info_t di; /* table info (if single_fde is false) */ + unw_dyn_info_t di_debug; /* additional table info for .debug_frame */ + }; + +/* ptr is a pointer to a dwarf_callback_data structure and, on entry, + member ip contains the instruction-pointer we're looking + for. */ +HIDDEN int +dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr) +{ + struct dwarf_callback_data *cb_data = ptr; + unw_dyn_info_t *di = &cb_data->di; + const Elf_W(Phdr) *phdr, *p_eh_hdr, *p_dynamic, *p_text; + unw_word_t addr, eh_frame_start, eh_frame_end, fde_count, ip; + Elf_W(Addr) load_base, max_load_addr = 0; + int ret, need_unwind_info = cb_data->need_unwind_info; + unw_proc_info_t *pi = cb_data->pi; + struct dwarf_eh_frame_hdr *hdr = NULL; + unw_accessors_t *a; + long n; + int found = 0; + struct dwarf_eh_frame_hdr synth_eh_frame_hdr; +#ifdef CONFIG_DEBUG_FRAME + unw_word_t start, end; +#endif /* CONFIG_DEBUG_FRAME*/ + + ip = cb_data->ip; + + /* Make sure struct dl_phdr_info is at least as big as we need. */ + if (size < offsetof (struct dl_phdr_info, dlpi_phnum) + + sizeof (info->dlpi_phnum)) + return -1; + + Debug (15, "checking %s, base=0x%lx)\n", + info->dlpi_name, (long) info->dlpi_addr); + + phdr = info->dlpi_phdr; + load_base = info->dlpi_addr; + p_text = NULL; + p_eh_hdr = NULL; + p_dynamic = NULL; + + /* See if PC falls into one of the loaded segments. Find the + eh-header segment at the same time. */ + for (n = info->dlpi_phnum; --n >= 0; phdr++) + { + if (phdr->p_type == PT_LOAD) + { + Elf_W(Addr) vaddr = phdr->p_vaddr + load_base; + + if (ip >= vaddr && ip < vaddr + phdr->p_memsz) + p_text = phdr; + + if (vaddr + phdr->p_filesz > max_load_addr) + max_load_addr = vaddr + phdr->p_filesz; + } + else if (phdr->p_type == PT_GNU_EH_FRAME) + p_eh_hdr = phdr; + else if (phdr->p_type == PT_DYNAMIC) + p_dynamic = phdr; + } + + if (!p_text) + return 0; + + if (p_eh_hdr) + { + hdr = (struct dwarf_eh_frame_hdr *) (p_eh_hdr->p_vaddr + load_base); + } + else + { + Elf_W (Addr) eh_frame; + Debug (1, "no .eh_frame_hdr section found\n"); + eh_frame = dwarf_find_eh_frame_section (info); + if (eh_frame) + { + Debug (1, "using synthetic .eh_frame_hdr section for %s\n", + info->dlpi_name); + synth_eh_frame_hdr.version = DW_EH_VERSION; + synth_eh_frame_hdr.eh_frame_ptr_enc = DW_EH_PE_absptr | + ((sizeof(Elf_W (Addr)) == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8); + synth_eh_frame_hdr.fde_count_enc = DW_EH_PE_omit; + synth_eh_frame_hdr.table_enc = DW_EH_PE_omit; + synth_eh_frame_hdr.eh_frame = eh_frame; + hdr = &synth_eh_frame_hdr; + } + } + + if (hdr) + { + if (p_dynamic) + { + /* For dynamicly linked executables and shared libraries, + DT_PLTGOT is the value that data-relative addresses are + relative to for that object. We call this the "gp". */ + Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(p_dynamic->p_vaddr + load_base); + for (; dyn->d_tag != DT_NULL; ++dyn) + if (dyn->d_tag == DT_PLTGOT) + { + /* Assume that _DYNAMIC is writable and GLIBC has + relocated it (true for x86 at least). */ + di->gp = dyn->d_un.d_ptr; + break; + } + } + else + /* Otherwise this is a static executable with no _DYNAMIC. Assume + that data-relative addresses are relative to 0, i.e., + absolute. */ + di->gp = 0; + pi->gp = di->gp; + + if (hdr->version != DW_EH_VERSION) + { + Debug (1, "table `%s' has unexpected version %d\n", + info->dlpi_name, hdr->version); + return 0; + } + + a = unw_get_accessors_int (unw_local_addr_space); + addr = (unw_word_t) (uintptr_t) (&hdr->eh_frame); + + /* (Optionally) read eh_frame_ptr: */ + if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a, + &addr, hdr->eh_frame_ptr_enc, pi, + &eh_frame_start, NULL)) < 0) + return ret; + + /* (Optionally) read fde_count: */ + if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a, + &addr, hdr->fde_count_enc, pi, + &fde_count, NULL)) < 0) + return ret; + + if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) + { + /* If there is no search table or it has an unsupported + encoding, fall back on linear search. */ + if (hdr->table_enc == DW_EH_PE_omit) + Debug (4, "table `%s' lacks search table; doing linear search\n", + info->dlpi_name); + else + Debug (4, "table `%s' has encoding 0x%x; doing linear search\n", + info->dlpi_name, hdr->table_enc); + + eh_frame_end = max_load_addr; /* XXX can we do better? */ + + if (hdr->fde_count_enc == DW_EH_PE_omit) + fde_count = ~0UL; + if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit) + abort (); + + Debug (1, "eh_frame_start = %lx eh_frame_end = %lx\n", + eh_frame_start, eh_frame_end); + + /* XXX we know how to build a local binary search table for + .debug_frame, so we could do that here too. */ + found = linear_search (unw_local_addr_space, ip, + eh_frame_start, eh_frame_end, fde_count, + pi, need_unwind_info, NULL); + if (found != 1) + found = 0; + else + cb_data->single_fde = 1; + } + else + { + di->format = UNW_INFO_FORMAT_REMOTE_TABLE; + di->start_ip = p_text->p_vaddr + load_base; + di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz; + di->u.rti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name; + di->u.rti.table_data = addr; + assert (sizeof (struct table_entry) % sizeof (unw_word_t) == 0); + di->u.rti.table_len = (fde_count * sizeof (struct table_entry) + / sizeof (unw_word_t)); + /* For the binary-search table in the eh_frame_hdr, data-relative + means relative to the start of that section... */ + di->u.rti.segbase = (unw_word_t) (uintptr_t) hdr; + + found = 1; + Debug (15, "found table `%s': segbase=0x%lx, len=%lu, gp=0x%lx, " + "table_data=0x%lx\n", (char *) (uintptr_t) di->u.rti.name_ptr, + (long) di->u.rti.segbase, (long) di->u.rti.table_len, + (long) di->gp, (long) di->u.rti.table_data); + } + } + +#ifdef CONFIG_DEBUG_FRAME + /* Find the start/end of the described region by parsing the phdr_info + structure. */ + start = (unw_word_t) -1; + end = 0; + + for (n = 0; n < info->dlpi_phnum; n++) + { + if (info->dlpi_phdr[n].p_type == PT_LOAD) + { + unw_word_t seg_start = info->dlpi_addr + info->dlpi_phdr[n].p_vaddr; + unw_word_t seg_end = seg_start + info->dlpi_phdr[n].p_memsz; + + if (seg_start < start) + start = seg_start; + + if (seg_end > end) + end = seg_end; + } + } + + found = dwarf_find_debug_frame (found, &cb_data->di_debug, ip, + info->dlpi_addr, info->dlpi_name, start, + end); +#endif /* CONFIG_DEBUG_FRAME */ + + return found; +} + +HIDDEN int +dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, int need_unwind_info, void *arg) +{ + struct dwarf_callback_data cb_data; + intrmask_t saved_mask; + int ret; + + Debug (14, "looking for IP=0x%lx\n", (long) ip); + + memset (&cb_data, 0, sizeof (cb_data)); + cb_data.ip = ip; + cb_data.pi = pi; + cb_data.need_unwind_info = need_unwind_info; + cb_data.di.format = -1; + cb_data.di_debug.format = -1; + + SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask); + ret = dl_iterate_phdr (dwarf_callback, &cb_data); + SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); + + if (ret > 0) + { + if (cb_data.single_fde) + /* already got the result in *pi */ + return 0; + + /* search the table: */ + if (cb_data.di.format != -1) + ret = dwarf_search_unwind_table_int (as, ip, &cb_data.di, + pi, need_unwind_info, arg); + else + ret = -UNW_ENOINFO; + + if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1) + ret = dwarf_search_unwind_table_int (as, ip, &cb_data.di_debug, pi, + need_unwind_info, arg); + } + else + ret = -UNW_ENOINFO; + + return ret; +} + +static inline const struct table_entry * +lookup (const struct table_entry *table, size_t table_size, int32_t rel_ip) +{ + unsigned long table_len = table_size / sizeof (struct table_entry); + const struct table_entry *e = NULL; + unsigned long lo, hi, mid; + + /* do a binary search for right entry: */ + for (lo = 0, hi = table_len; lo < hi;) + { + mid = (lo + hi) / 2; + e = table + mid; + Debug (15, "e->start_ip_offset = %lx\n", (long) e->start_ip_offset); + if (rel_ip < e->start_ip_offset) + hi = mid; + else + lo = mid + 1; + } + if (hi <= 0) + return NULL; + e = table + hi - 1; + return e; +} + +#endif /* !UNW_REMOTE_ONLY */ + +#ifndef UNW_LOCAL_ONLY + +/* Lookup an unwind-table entry in remote memory. Returns 1 if an + entry is found, 0 if no entry is found, negative if an error + occurred reading remote memory. */ +static int +remote_lookup (unw_addr_space_t as, + unw_word_t table, size_t table_size, int32_t rel_ip, + struct table_entry *e, int32_t *last_ip_offset, void *arg) +{ + unsigned long table_len = table_size / sizeof (struct table_entry); + unw_accessors_t *a = unw_get_accessors_int (as); + unsigned long lo, hi, mid; + unw_word_t e_addr = 0; + int32_t start = 0; + int ret; + + /* do a binary search for right entry: */ + for (lo = 0, hi = table_len; lo < hi;) + { + mid = (lo + hi) / 2; + e_addr = table + mid * sizeof (struct table_entry); + if ((ret = dwarf_reads32 (as, a, &e_addr, &start, arg)) < 0) + return ret; + + if (rel_ip < start) + hi = mid; + else + lo = mid + 1; + } + if (hi <= 0) + return 0; + e_addr = table + (hi - 1) * sizeof (struct table_entry); + if ((ret = dwarf_reads32 (as, a, &e_addr, &e->start_ip_offset, arg)) < 0 + || (ret = dwarf_reads32 (as, a, &e_addr, &e->fde_offset, arg)) < 0 + || (hi < table_len && + (ret = dwarf_reads32 (as, a, &e_addr, last_ip_offset, arg)) < 0)) + return ret; + return 1; +} + +#endif /* !UNW_LOCAL_ONLY */ + +static int is_remote_table(int format) +{ + return (format == UNW_INFO_FORMAT_REMOTE_TABLE || + format == UNW_INFO_FORMAT_IP_OFFSET); +} + +int +dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip, + unw_dyn_info_t *di, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + const struct table_entry *e = NULL, *table; + unw_word_t ip_base = 0, segbase = 0, last_ip, fde_addr; + unw_accessors_t *a; +#ifndef UNW_LOCAL_ONLY + struct table_entry ent; +#endif + int ret; + unw_word_t debug_frame_base; + size_t table_len; + +#ifdef UNW_REMOTE_ONLY + assert (is_remote_table(di->format)); +#else + assert (is_remote_table(di->format) + || di->format == UNW_INFO_FORMAT_TABLE); +#endif + assert (ip >= di->start_ip && ip < di->end_ip); + + if (is_remote_table(di->format)) + { + table = (const struct table_entry *) (uintptr_t) di->u.rti.table_data; + table_len = di->u.rti.table_len * sizeof (unw_word_t); + debug_frame_base = 0; + } + else + { + assert(di->format == UNW_INFO_FORMAT_TABLE); +#ifndef UNW_REMOTE_ONLY + struct unw_debug_frame_list *fdesc = (void *) di->u.ti.table_data; + + /* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is read from local address + space. Both the index and the unwind tables live in local memory, but + the address space to check for properties like the address size and + endianness is the target one. */ + as = unw_local_addr_space; + table = fdesc->index; + table_len = fdesc->index_size * sizeof (struct table_entry); + debug_frame_base = (uintptr_t) fdesc->debug_frame; +#endif + } + + a = unw_get_accessors_int (as); + + segbase = di->u.rti.segbase; + if (di->format == UNW_INFO_FORMAT_IP_OFFSET) { + ip_base = di->start_ip; + } else { + ip_base = segbase; + } + +#ifndef UNW_REMOTE_ONLY + if (as == unw_local_addr_space) + { + e = lookup (table, table_len, ip - ip_base); + if (e && &e[1] < &table[table_len]) + last_ip = e[1].start_ip_offset + ip_base; + else + last_ip = di->end_ip; + } + else +#endif + { +#ifndef UNW_LOCAL_ONLY + int32_t last_ip_offset = di->end_ip - ip_base; + segbase = di->u.rti.segbase; + if ((ret = remote_lookup (as, (uintptr_t) table, table_len, + ip - ip_base, &ent, &last_ip_offset, arg)) < 0) + return ret; + if (ret) + { + e = &ent; + last_ip = last_ip_offset + ip_base; + } + else + e = NULL; /* no info found */ +#endif + } + if (!e) + { + Debug (1, "IP %lx inside range %lx-%lx, but no explicit unwind info found\n", + (long) ip, (long) di->start_ip, (long) di->end_ip); + /* IP is inside this table's range, but there is no explicit + unwind info. */ + return -UNW_ENOINFO; + } + Debug (15, "ip=0x%lx, start_ip=0x%lx\n", + (long) ip, (long) (e->start_ip_offset)); + if (debug_frame_base) + fde_addr = e->fde_offset + debug_frame_base; + else + fde_addr = e->fde_offset + segbase; + Debug (1, "e->fde_offset = %lx, segbase = %lx, debug_frame_base = %lx, " + "fde_addr = %lx\n", (long) e->fde_offset, (long) segbase, + (long) debug_frame_base, (long) fde_addr); + if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi, + debug_frame_base ? + debug_frame_base : segbase, + need_unwind_info, + debug_frame_base != 0, arg)) < 0) + return ret; + + /* .debug_frame uses an absolute encoding that does not know about any + shared library relocation. */ + if (di->format == UNW_INFO_FORMAT_TABLE) + { + pi->start_ip += segbase; + pi->end_ip += segbase; + pi->flags = UNW_PI_FLAG_DEBUG_FRAME; + } + +#if defined(NEED_LAST_IP) + pi->last_ip = last_ip; +#else + (void)last_ip; +#endif + if (ip < pi->start_ip || ip >= pi->end_ip) + return -UNW_ENOINFO; + + return 0; +} + +HIDDEN void +dwarf_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg) +{ + return; /* always a nop */ +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gfind_unwind_table.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gfind_unwind_table.c new file mode 100644 index 0000000..6a2ad50 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gfind_unwind_table.c @@ -0,0 +1,230 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include + +#include + +#include "libunwind_i.h" +#include "dwarf-eh.h" +#include "dwarf_i.h" + +#define to_unw_word(p) ((unw_word_t) (uintptr_t) (p)) + +int +dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as, + char *path, unw_word_t segbase, unw_word_t mapoff, + unw_word_t ip) +{ + Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL; + unw_word_t addr, eh_frame_start, fde_count, load_base; + unw_word_t max_load_addr = 0; + unw_word_t start_ip = to_unw_word (-1); + unw_word_t end_ip = 0; + struct dwarf_eh_frame_hdr *hdr; + unw_proc_info_t pi; + unw_accessors_t *a; + Elf_W(Ehdr) *ehdr; +#if UNW_TARGET_ARM + const Elf_W(Phdr) *parm_exidx = NULL; +#endif + int i, ret, found = 0; + + /* XXX: Much of this code is Linux/LSB-specific. */ + + if (!elf_w(valid_object) (&edi->ei)) + return -UNW_ENOINFO; + + ehdr = edi->ei.image; + phdr = (Elf_W(Phdr) *) ((char *) edi->ei.image + ehdr->e_phoff); + + for (i = 0; i < ehdr->e_phnum; ++i) + { + switch (phdr[i].p_type) + { + case PT_LOAD: + if (phdr[i].p_vaddr < start_ip) + start_ip = phdr[i].p_vaddr; + + if (phdr[i].p_vaddr + phdr[i].p_memsz > end_ip) + end_ip = phdr[i].p_vaddr + phdr[i].p_memsz; + + if (phdr[i].p_offset == mapoff) + ptxt = phdr + i; + if ((uintptr_t) edi->ei.image + phdr->p_filesz > max_load_addr) + max_load_addr = (uintptr_t) edi->ei.image + phdr->p_filesz; + break; + + case PT_GNU_EH_FRAME: + peh_hdr = phdr + i; + break; + + case PT_DYNAMIC: + pdyn = phdr + i; + break; + +#if UNW_TARGET_ARM + case PT_ARM_EXIDX: + parm_exidx = phdr + i; + break; +#endif + + default: + break; + } + } + + if (!ptxt) + return 0; + + load_base = segbase - ptxt->p_vaddr; + start_ip += load_base; + end_ip += load_base; + + if (peh_hdr) + { + if (pdyn) + { + /* For dynamicly linked executables and shared libraries, + DT_PLTGOT is the value that data-relative addresses are + relative to for that object. We call this the "gp". */ + Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(pdyn->p_offset + + (char *) edi->ei.image); + for (; dyn->d_tag != DT_NULL; ++dyn) + if (dyn->d_tag == DT_PLTGOT) + { + /* Assume that _DYNAMIC is writable and GLIBC has + relocated it (true for x86 at least). */ + edi->di_cache.gp = dyn->d_un.d_ptr; + break; + } + } + else + /* Otherwise this is a static executable with no _DYNAMIC. Assume + that data-relative addresses are relative to 0, i.e., + absolute. */ + edi->di_cache.gp = 0; + + hdr = (struct dwarf_eh_frame_hdr *) (peh_hdr->p_offset + + (char *) edi->ei.image); + if (hdr->version != DW_EH_VERSION) + { + Debug (1, "table `%s' has unexpected version %d\n", + path, hdr->version); + return -UNW_ENOINFO; + } + + a = unw_get_accessors_int (unw_local_addr_space); + addr = to_unw_word (&hdr->eh_frame); + + /* Fill in a dummy proc_info structure. We just need to fill in + enough to ensure that dwarf_read_encoded_pointer() can do it's + job. Since we don't have a procedure-context at this point, all + we have to do is fill in the global-pointer. */ + memset (&pi, 0, sizeof (pi)); + pi.gp = edi->di_cache.gp; + + /* (Optionally) read eh_frame_ptr: */ + if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a, + &addr, hdr->eh_frame_ptr_enc, &pi, + &eh_frame_start, NULL)) < 0) + return -UNW_ENOINFO; + + /* (Optionally) read fde_count: */ + if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a, + &addr, hdr->fde_count_enc, &pi, + &fde_count, NULL)) < 0) + return -UNW_ENOINFO; + + if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) + { + #if 1 + abort (); + #else + unw_word_t eh_frame_end; + + /* If there is no search table or it has an unsupported + encoding, fall back on linear search. */ + if (hdr->table_enc == DW_EH_PE_omit) + Debug (4, "EH lacks search table; doing linear search\n"); + else + Debug (4, "EH table has encoding 0x%x; doing linear search\n", + hdr->table_enc); + + eh_frame_end = max_load_addr; /* XXX can we do better? */ + + if (hdr->fde_count_enc == DW_EH_PE_omit) + fde_count = ~0UL; + if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit) + abort (); + + return linear_search (unw_local_addr_space, ip, + eh_frame_start, eh_frame_end, fde_count, + pi, need_unwind_info, NULL); + #endif + } + + edi->di_cache.start_ip = start_ip; + edi->di_cache.end_ip = end_ip; + edi->di_cache.format = UNW_INFO_FORMAT_REMOTE_TABLE; + edi->di_cache.u.rti.name_ptr = 0; + /* two 32-bit values (ip_offset/fde_offset) per table-entry: */ + edi->di_cache.u.rti.table_len = (fde_count * 8) / sizeof (unw_word_t); + edi->di_cache.u.rti.table_data = ((load_base + peh_hdr->p_vaddr) + + (addr - to_unw_word (edi->ei.image) + - peh_hdr->p_offset)); + + /* For the binary-search table in the eh_frame_hdr, data-relative + means relative to the start of that section... */ + edi->di_cache.u.rti.segbase = ((load_base + peh_hdr->p_vaddr) + + (to_unw_word (hdr) - + to_unw_word (edi->ei.image) + - peh_hdr->p_offset)); + found = 1; + } + +#if UNW_TARGET_ARM + if (parm_exidx) + { + edi->di_arm.format = UNW_INFO_FORMAT_ARM_EXIDX; + edi->di_arm.start_ip = start_ip; + edi->di_arm.end_ip = end_ip; + edi->di_arm.u.rti.name_ptr = to_unw_word (path); + edi->di_arm.u.rti.table_data = load_base + parm_exidx->p_vaddr; + edi->di_arm.u.rti.table_len = parm_exidx->p_memsz; + found = 1; + } +#endif + +#ifdef CONFIG_DEBUG_FRAME + /* Try .debug_frame. */ + found = dwarf_find_debug_frame (found, &edi->di_debug, ip, load_base, path, + start_ip, end_ip); +#endif + + return found; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gparser.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gparser.c new file mode 100644 index 0000000..7d255ae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gparser.c @@ -0,0 +1,1059 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "dwarf_i.h" +#include "libunwind_i.h" +#include +#include + +#define alloc_reg_state() (mempool_alloc (&dwarf_reg_state_pool)) +#define free_reg_state(rs) (mempool_free (&dwarf_reg_state_pool, rs)) + +#define DWARF_UNW_CACHE_SIZE(log_size) (1 << log_size) +#define DWARF_UNW_HASH_SIZE(log_size) (1 << (log_size + 1)) + +static inline int +read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + unw_word_t *valp, void *arg) +{ + int ret; + + if ((ret = dwarf_read_uleb128 (as, a, addr, valp, arg)) < 0) + return ret; + + if (*valp >= DWARF_NUM_PRESERVED_REGS) + { + Debug (1, "Invalid register number %u\n", (unsigned int) *valp); + return -UNW_EBADREG; + } + return 0; +} + +static inline void +set_reg (dwarf_state_record_t *sr, unw_word_t regnum, dwarf_where_t where, + unw_word_t val) +{ + sr->rs_current.reg.where[regnum] = where; + sr->rs_current.reg.val[regnum] = val; +} + +static inline int +push_rstate_stack(dwarf_stackable_reg_state_t **rs_stack) +{ + dwarf_stackable_reg_state_t *old_rs = *rs_stack; + if (NULL == (*rs_stack = alloc_reg_state ())) + { + *rs_stack = old_rs; + return -1; + } + (*rs_stack)->next = old_rs; + return 0; +} + +static inline void +pop_rstate_stack(dwarf_stackable_reg_state_t **rs_stack) +{ + dwarf_stackable_reg_state_t *old_rs = *rs_stack; + *rs_stack = old_rs->next; + free_reg_state (old_rs); +} + +static inline void +empty_rstate_stack(dwarf_stackable_reg_state_t **rs_stack) +{ + while (*rs_stack) + pop_rstate_stack(rs_stack); +} + +/* Run a CFI program to update the register state. */ +static int +run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr, + unw_word_t *ip, unw_word_t end_ip, + unw_word_t *addr, unw_word_t end_addr, + dwarf_stackable_reg_state_t **rs_stack, + struct dwarf_cie_info *dci) +{ + unw_addr_space_t as; + void *arg; + + if (c->pi.flags & UNW_PI_FLAG_DEBUG_FRAME) + { + /* .debug_frame CFI is stored in local address space. */ + as = unw_local_addr_space; + arg = NULL; + } + else + { + as = c->as; + arg = c->as_arg; + } + unw_accessors_t *a = unw_get_accessors_int (as); + int ret = 0; + + while (*ip <= end_ip && *addr < end_addr && ret >= 0) + { + unw_word_t operand = 0, regnum, val, len; + uint8_t u8, op; + uint16_t u16; + uint32_t u32; + + if ((ret = dwarf_readu8 (as, a, addr, &op, arg)) < 0) + break; + + if (op & DWARF_CFA_OPCODE_MASK) + { + operand = op & DWARF_CFA_OPERAND_MASK; + op &= ~DWARF_CFA_OPERAND_MASK; + } + switch ((dwarf_cfa_t) op) + { + case DW_CFA_advance_loc: + *ip += operand * dci->code_align; + Debug (15, "CFA_advance_loc to 0x%lx\n", (long) *ip); + break; + + case DW_CFA_advance_loc1: + if ((ret = dwarf_readu8 (as, a, addr, &u8, arg)) < 0) + break; + *ip += u8 * dci->code_align; + Debug (15, "CFA_advance_loc1 to 0x%lx\n", (long) *ip); + break; + + case DW_CFA_advance_loc2: + if ((ret = dwarf_readu16 (as, a, addr, &u16, arg)) < 0) + break; + *ip += u16 * dci->code_align; + Debug (15, "CFA_advance_loc2 to 0x%lx\n", (long) *ip); + break; + + case DW_CFA_advance_loc4: + if ((ret = dwarf_readu32 (as, a, addr, &u32, arg)) < 0) + break; + *ip += u32 * dci->code_align; + Debug (15, "CFA_advance_loc4 to 0x%lx\n", (long) *ip); + break; + + case DW_CFA_MIPS_advance_loc8: +#ifdef UNW_TARGET_MIPS + { + uint64_t u64 = 0; + + if ((ret = dwarf_readu64 (as, a, addr, &u64, arg)) < 0) + break; + *ip += u64 * dci->code_align; + Debug (15, "CFA_MIPS_advance_loc8\n"); + break; + } +#else + Debug (1, "DW_CFA_MIPS_advance_loc8 on non-MIPS target\n"); + ret = -UNW_EINVAL; + break; +#endif + + case DW_CFA_offset: + regnum = operand; + if (regnum >= DWARF_NUM_PRESERVED_REGS) + { + Debug (1, "Invalid register number %u in DW_cfa_OFFSET\n", + (unsigned int) regnum); + ret = -UNW_EBADREG; + break; + } + if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) + break; + set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align); + Debug (15, "CFA_offset r%lu at cfa+0x%lx\n", + (long) regnum, (long) (val * dci->data_align)); + break; + + case DW_CFA_offset_extended: + if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) + || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) + break; + set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align); + Debug (15, "CFA_offset_extended r%lu at cf+0x%lx\n", + (long) regnum, (long) (val * dci->data_align)); + break; + + case DW_CFA_offset_extended_sf: + if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) + || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)) + break; + set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align); + Debug (15, "CFA_offset_extended_sf r%lu at cf+0x%lx\n", + (long) regnum, (long) (val * dci->data_align)); + break; + + case DW_CFA_restore: + regnum = operand; + if (regnum >= DWARF_NUM_PRESERVED_REGS) + { + Debug (1, "Invalid register number %u in DW_CFA_restore\n", + (unsigned int) regnum); + ret = -UNW_EINVAL; + break; + } + sr->rs_current.reg.where[regnum] = sr->rs_initial.reg.where[regnum]; + sr->rs_current.reg.val[regnum] = sr->rs_initial.reg.val[regnum]; + Debug (15, "CFA_restore r%lu\n", (long) regnum); + break; + + case DW_CFA_restore_extended: + if ((ret = dwarf_read_uleb128 (as, a, addr, ®num, arg)) < 0) + break; + if (regnum >= DWARF_NUM_PRESERVED_REGS) + { + Debug (1, "Invalid register number %u in " + "DW_CFA_restore_extended\n", (unsigned int) regnum); + ret = -UNW_EINVAL; + break; + } + sr->rs_current.reg.where[regnum] = sr->rs_initial.reg.where[regnum]; + sr->rs_current.reg.val[regnum] = sr->rs_initial.reg.val[regnum]; + Debug (15, "CFA_restore_extended r%lu\n", (long) regnum); + break; + + case DW_CFA_nop: + break; + + case DW_CFA_set_loc: + if ((ret = dwarf_read_encoded_pointer (as, a, addr, dci->fde_encoding, + &c->pi, ip, + arg)) < 0) + break; + Debug (15, "CFA_set_loc to 0x%lx\n", (long) *ip); + break; + + case DW_CFA_undefined: + if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) + break; + set_reg (sr, regnum, DWARF_WHERE_UNDEF, 0); + Debug (15, "CFA_undefined r%lu\n", (long) regnum); + break; + + case DW_CFA_same_value: + if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) + break; + set_reg (sr, regnum, DWARF_WHERE_SAME, 0); + Debug (15, "CFA_same_value r%lu\n", (long) regnum); + break; + + case DW_CFA_register: + if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) + || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) + break; + set_reg (sr, regnum, DWARF_WHERE_REG, val); + Debug (15, "CFA_register r%lu to r%lu\n", (long) regnum, (long) val); + break; + + case DW_CFA_remember_state: + if (push_rstate_stack(rs_stack) < 0) + { + Debug (1, "Out of memory in DW_CFA_remember_state\n"); + ret = -UNW_ENOMEM; + break; + } + (*rs_stack)->state = sr->rs_current; + Debug (15, "CFA_remember_state\n"); + break; + + case DW_CFA_restore_state: + if (!*rs_stack) + { + Debug (1, "register-state stack underflow\n"); + ret = -UNW_EINVAL; + break; + } + sr->rs_current = (*rs_stack)->state; + pop_rstate_stack(rs_stack); + Debug (15, "CFA_restore_state\n"); + break; + + case DW_CFA_def_cfa: + if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) + || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) + break; + set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum); + set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */ + Debug (15, "CFA_def_cfa r%lu+0x%lx\n", (long) regnum, (long) val); + break; + + case DW_CFA_def_cfa_sf: + if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) + || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)) + break; + set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum); + set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, + val * dci->data_align); /* factored! */ + Debug (15, "CFA_def_cfa_sf r%lu+0x%lx\n", + (long) regnum, (long) (val * dci->data_align)); + break; + + case DW_CFA_def_cfa_register: + if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) + break; + set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum); + Debug (15, "CFA_def_cfa_register r%lu\n", (long) regnum); + break; + + case DW_CFA_def_cfa_offset: + if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) + break; + set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */ + Debug (15, "CFA_def_cfa_offset 0x%lx\n", (long) val); + break; + + case DW_CFA_def_cfa_offset_sf: + if ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0) + break; + set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, + val * dci->data_align); /* factored! */ + Debug (15, "CFA_def_cfa_offset_sf 0x%lx\n", + (long) (val * dci->data_align)); + break; + + case DW_CFA_def_cfa_expression: + /* Save the address of the DW_FORM_block for later evaluation. */ + set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_EXPR, *addr); + + if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0) + break; + + Debug (15, "CFA_def_cfa_expr @ 0x%lx [%lu bytes]\n", + (long) *addr, (long) len); + *addr += len; + break; + + case DW_CFA_expression: + if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) + break; + + /* Save the address of the DW_FORM_block for later evaluation. */ + set_reg (sr, regnum, DWARF_WHERE_EXPR, *addr); + + if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0) + break; + + Debug (15, "CFA_expression r%lu @ 0x%lx [%lu bytes]\n", + (long) regnum, (long) addr, (long) len); + *addr += len; + break; + + case DW_CFA_val_expression: + if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) + break; + + /* Save the address of the DW_FORM_block for later evaluation. */ + set_reg (sr, regnum, DWARF_WHERE_VAL_EXPR, *addr); + + if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0) + break; + + Debug (15, "CFA_val_expression r%lu @ 0x%lx [%lu bytes]\n", + (long) regnum, (long) addr, (long) len); + *addr += len; + break; + + case DW_CFA_GNU_args_size: + if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) + break; + sr->args_size = val; + Debug (15, "CFA_GNU_args_size %lu\n", (long) val); + break; + + case DW_CFA_GNU_negative_offset_extended: + /* A comment in GCC says that this is obsoleted by + DW_CFA_offset_extended_sf, but that it's used by older + PowerPC code. */ + if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) + || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) + break; + set_reg (sr, regnum, DWARF_WHERE_CFAREL, -(val * dci->data_align)); + Debug (15, "CFA_GNU_negative_offset_extended cfa+0x%lx\n", + (long) -(val * dci->data_align)); + break; + + case DW_CFA_GNU_window_save: +#ifdef UNW_TARGET_SPARC + /* This is a special CFA to handle all 16 windowed registers + on SPARC. */ + for (regnum = 16; regnum < 32; ++regnum) + set_reg (sr, regnum, DWARF_WHERE_CFAREL, + (regnum - 16) * sizeof (unw_word_t)); + Debug (15, "CFA_GNU_window_save\n"); + break; +#else + /* FALL THROUGH */ +#endif + case DW_CFA_lo_user: + case DW_CFA_hi_user: + Debug (1, "Unexpected CFA opcode 0x%x\n", op); + ret = -UNW_EINVAL; + break; + } + } + + if (ret > 0) + ret = 0; + return ret; +} + +static int +fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip) +{ + int ret, dynamic = 1; + + /* The 'ip' can point either to the previous or next instruction + depending on what type of frame we have: normal call or a place + to resume execution (e.g. after signal frame). + + For a normal call frame we need to back up so we point within the + call itself; this is important because a) the call might be the + very last instruction of the function and the edge of the FDE, + and b) so that run_cfi_program() runs locations up to the call + but not more. + + For signal frame, we need to do the exact opposite and look + up using the current 'ip' value. That is where execution will + continue, and it's important we get this right, as 'ip' could be + right at the function entry and hence FDE edge, or at instruction + that manipulates CFA (push/pop). */ + if (c->use_prev_instr) + --ip; + + memset (&c->pi, 0, sizeof (c->pi)); + + /* check dynamic info first --- it overrides everything else */ + ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, 1, + c->as_arg); + if (ret == -UNW_ENOINFO) + { + dynamic = 0; + if ((ret = tdep_find_proc_info (c, ip, 1)) < 0) + return ret; + } + + if (c->pi.format != UNW_INFO_FORMAT_DYNAMIC + && c->pi.format != UNW_INFO_FORMAT_TABLE + && c->pi.format != UNW_INFO_FORMAT_REMOTE_TABLE) + return -UNW_ENOINFO; + + c->pi_valid = 1; + c->pi_is_dynamic = dynamic; + + /* Let system/machine-dependent code determine frame-specific attributes. */ + if (ret >= 0) + tdep_fetch_frame (c, ip, 1); + + return ret; +} + +static int +parse_dynamic (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr) +{ + Debug (1, "Not yet implemented\n"); + return -UNW_ENOINFO; +} + +static inline void +put_unwind_info (struct dwarf_cursor *c, unw_proc_info_t *pi) +{ + if (c->pi_is_dynamic) + unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg); + else if (pi->unwind_info && pi->format == UNW_INFO_FORMAT_TABLE) + { + mempool_free (&dwarf_cie_info_pool, pi->unwind_info); + pi->unwind_info = NULL; + } + c->pi_valid = 0; +} + +static inline int +setup_fde (struct dwarf_cursor *c, dwarf_state_record_t *sr) +{ + int i, ret; + + assert (c->pi_valid); + + memset (sr, 0, sizeof (*sr)); + for (i = 0; i < DWARF_NUM_PRESERVED_REGS + 2; ++i) + set_reg (sr, i, DWARF_WHERE_SAME, 0); + + struct dwarf_cie_info *dci = c->pi.unwind_info; + sr->rs_current.ret_addr_column = dci->ret_addr_column; + unw_word_t addr = dci->cie_instr_start; + unw_word_t curr_ip = 0; + dwarf_stackable_reg_state_t *rs_stack = NULL; + ret = run_cfi_program (c, sr, &curr_ip, ~(unw_word_t) 0, &addr, + dci->cie_instr_end, + &rs_stack, dci); + empty_rstate_stack(&rs_stack); + if (ret < 0) + return ret; + + memcpy (&sr->rs_initial, &sr->rs_current, sizeof (sr->rs_initial)); + return 0; +} + +static inline int +parse_fde (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr) +{ + int ret; + struct dwarf_cie_info *dci = c->pi.unwind_info; + unw_word_t addr = dci->fde_instr_start; + unw_word_t curr_ip = c->pi.start_ip; + dwarf_stackable_reg_state_t *rs_stack = NULL; + /* Process up to current `ip` for signal frame and `ip - 1` for normal call frame + See `c->use_prev_instr` use in `fetch_proc_info` for details. */ + ret = run_cfi_program (c, sr, &curr_ip, ip - c->use_prev_instr, &addr, dci->fde_instr_end, + &rs_stack, dci); + empty_rstate_stack(&rs_stack); + if (ret < 0) + return ret; + + return 0; +} + +HIDDEN int +dwarf_flush_rs_cache (struct dwarf_rs_cache *cache) +{ + int i; + + if (cache->log_size == DWARF_DEFAULT_LOG_UNW_CACHE_SIZE + || !cache->hash) { + cache->hash = cache->default_hash; + cache->buckets = cache->default_buckets; + cache->links = cache->default_links; + cache->log_size = DWARF_DEFAULT_LOG_UNW_CACHE_SIZE; + } else { + if (cache->hash && cache->hash != cache->default_hash) + munmap(cache->hash, DWARF_UNW_HASH_SIZE(cache->prev_log_size) + * sizeof (cache->hash[0])); + if (cache->buckets && cache->buckets != cache->default_buckets) + munmap(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->prev_log_size) + * sizeof (cache->buckets[0])); + if (cache->links && cache->links != cache->default_links) + munmap(cache->links, DWARF_UNW_CACHE_SIZE(cache->prev_log_size) + * sizeof (cache->links[0])); + GET_MEMORY(cache->hash, DWARF_UNW_HASH_SIZE(cache->log_size) + * sizeof (cache->hash[0])); + GET_MEMORY(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->log_size) + * sizeof (cache->buckets[0])); + GET_MEMORY(cache->links, DWARF_UNW_CACHE_SIZE(cache->log_size) + * sizeof (cache->links[0])); + if (!cache->hash || !cache->buckets || !cache->links) + { + Debug (1, "Unable to allocate cache memory"); + return -UNW_ENOMEM; + } + cache->prev_log_size = cache->log_size; + } + + cache->rr_head = 0; + + for (i = 0; i < DWARF_UNW_CACHE_SIZE(cache->log_size); ++i) + { + cache->links[i].coll_chain = -1; + cache->links[i].ip = 0; + cache->links[i].valid = 0; + } + for (i = 0; i< DWARF_UNW_HASH_SIZE(cache->log_size); ++i) + cache->hash[i] = -1; + + return 0; +} + +static inline struct dwarf_rs_cache * +get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp) +{ + struct dwarf_rs_cache *cache = &as->global_cache; + unw_caching_policy_t caching = as->caching_policy; + + if (caching == UNW_CACHE_NONE) + return NULL; + +#if defined(HAVE___THREAD) && HAVE___THREAD + if (likely (caching == UNW_CACHE_PER_THREAD)) + { + static __thread struct dwarf_rs_cache tls_cache __attribute__((tls_model("initial-exec"))); + Debug (16, "using TLS cache\n"); + cache = &tls_cache; + } + else +#else + if (likely (caching == UNW_CACHE_GLOBAL)) +#endif + { + Debug (16, "acquiring lock\n"); + lock_acquire (&cache->lock, *saved_maskp); + } + + if ((atomic_read (&as->cache_generation) != atomic_read (&cache->generation)) + || !cache->hash) + { + /* cache_size is only set in the global_cache, copy it over before flushing */ + cache->log_size = as->global_cache.log_size; + if (dwarf_flush_rs_cache (cache) < 0) + return NULL; + cache->generation = as->cache_generation; + } + + return cache; +} + +static inline void +put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache, + intrmask_t *saved_maskp) +{ + assert (as->caching_policy != UNW_CACHE_NONE); + + Debug (16, "unmasking signals/interrupts and releasing lock\n"); + if (likely (as->caching_policy == UNW_CACHE_GLOBAL)) + lock_release (&cache->lock, *saved_maskp); +} + +static inline unw_hash_index_t CONST_ATTR +hash (unw_word_t ip, unsigned short log_size) +{ + /* based on (sqrt(5)/2-1)*2^64 */ +# define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL) + + return ip * magic >> ((sizeof(unw_word_t) * 8) - (log_size + 1)); +} + +static inline long +cache_match (struct dwarf_rs_cache *cache, unsigned short index, unw_word_t ip) +{ + return (cache->links[index].valid && (ip == cache->links[index].ip)); +} + +static dwarf_reg_state_t * +rs_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c) +{ + unsigned short index; + unw_word_t ip = c->ip; + + if (c->hint > 0) + { + index = c->hint - 1; + if (cache_match (cache, index, ip)) + return &cache->buckets[index]; + } + + for (index = cache->hash[hash (ip, cache->log_size)]; + index < DWARF_UNW_CACHE_SIZE(cache->log_size); + index = cache->links[index].coll_chain) + { + if (cache_match (cache, index, ip)) + return &cache->buckets[index]; + } + return NULL; +} + +static inline dwarf_reg_state_t * +rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c) +{ + unw_hash_index_t index; + unsigned short head; + + head = cache->rr_head; + cache->rr_head = (head + 1) & (DWARF_UNW_CACHE_SIZE(cache->log_size) - 1); + + /* remove the old rs from the hash table (if it's there): */ + if (cache->links[head].ip) + { + unsigned short *pindex; + for (pindex = &cache->hash[hash (cache->links[head].ip, cache->log_size)]; + *pindex < DWARF_UNW_CACHE_SIZE(cache->log_size); + pindex = &cache->links[*pindex].coll_chain) + { + if (*pindex == head) + { + *pindex = cache->links[*pindex].coll_chain; + break; + } + } + } + + /* enter new rs in the hash table */ + index = hash (c->ip, cache->log_size); + cache->links[head].coll_chain = cache->hash[index]; + cache->hash[index] = head; + + cache->links[head].ip = c->ip; + cache->links[head].valid = 1; + cache->links[head].signal_frame = tdep_cache_frame(c); + return cache->buckets + head; +} + +static int +create_state_record_for (struct dwarf_cursor *c, dwarf_state_record_t *sr, + unw_word_t ip) +{ + int ret; + switch (c->pi.format) + { + case UNW_INFO_FORMAT_TABLE: + case UNW_INFO_FORMAT_REMOTE_TABLE: + if ((ret = setup_fde(c, sr)) < 0) + return ret; + ret = parse_fde (c, ip, sr); + break; + + case UNW_INFO_FORMAT_DYNAMIC: + ret = parse_dynamic (c, ip, sr); + break; + + default: + Debug (1, "Unexpected unwind-info format %d\n", c->pi.format); + ret = -UNW_EINVAL; + } + return ret; +} + +static inline int +eval_location_expr (struct dwarf_cursor *c, unw_addr_space_t as, + unw_accessors_t *a, unw_word_t addr, + dwarf_loc_t *locp, void *arg) +{ + int ret, is_register; + unw_word_t len, val; + + /* read the length of the expression: */ + if ((ret = dwarf_read_uleb128 (as, a, &addr, &len, arg)) < 0) + return ret; + + /* evaluate the expression: */ + if ((ret = dwarf_eval_expr (c, &addr, len, &val, &is_register)) < 0) + return ret; + + if (is_register) + *locp = DWARF_REG_LOC (c, dwarf_to_unw_regnum (val)); + else + *locp = DWARF_MEM_LOC (c, val); + + return 0; +} + +static int +apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) +{ + unw_word_t regnum, addr, cfa, ip; + unw_word_t prev_ip, prev_cfa; + unw_addr_space_t as; + dwarf_loc_t cfa_loc; + unw_accessors_t *a; + int i, ret; + void *arg; + + prev_ip = c->ip; + prev_cfa = c->cfa; + + as = c->as; + arg = c->as_arg; + a = unw_get_accessors_int (as); + + /* Evaluate the CFA first, because it may be referred to by other + expressions. */ + + if (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG) + { + /* CFA is equal to [reg] + offset: */ + + /* As a special-case, if the stack-pointer is the CFA and the + stack-pointer wasn't saved, popping the CFA implicitly pops + the stack-pointer as well. */ + if ((rs->reg.val[DWARF_CFA_REG_COLUMN] == UNW_TDEP_SP) + && (UNW_TDEP_SP < ARRAY_SIZE(rs->reg.val)) + && (rs->reg.where[UNW_TDEP_SP] == DWARF_WHERE_SAME)) + cfa = c->cfa; + else + { + regnum = dwarf_to_unw_regnum (rs->reg.val[DWARF_CFA_REG_COLUMN]); + if ((ret = unw_get_reg ((unw_cursor_t *) c, regnum, &cfa)) < 0) + return ret; + } + cfa += rs->reg.val[DWARF_CFA_OFF_COLUMN]; + } + else + { + /* CFA is equal to EXPR: */ + + assert (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_EXPR); + + addr = rs->reg.val[DWARF_CFA_REG_COLUMN]; + if ((ret = eval_location_expr (c, as, a, addr, &cfa_loc, arg)) < 0) + return ret; + /* the returned location better be a memory location... */ + if (DWARF_IS_REG_LOC (cfa_loc)) + return -UNW_EBADFRAME; + cfa = DWARF_GET_LOC (cfa_loc); + } + + dwarf_loc_t new_loc[DWARF_NUM_PRESERVED_REGS]; + memcpy(new_loc, c->loc, sizeof(new_loc)); + + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + { + switch ((dwarf_where_t) rs->reg.where[i]) + { + case DWARF_WHERE_UNDEF: + new_loc[i] = DWARF_NULL_LOC; + break; + + case DWARF_WHERE_SAME: + break; + + case DWARF_WHERE_CFAREL: + new_loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg.val[i]); + break; + + case DWARF_WHERE_REG: + new_loc[i] = DWARF_REG_LOC (c, dwarf_to_unw_regnum (rs->reg.val[i])); + break; + + case DWARF_WHERE_EXPR: + addr = rs->reg.val[i]; + if ((ret = eval_location_expr (c, as, a, addr, new_loc + i, arg)) < 0) + return ret; + break; + + case DWARF_WHERE_VAL_EXPR: + addr = rs->reg.val[i]; + if ((ret = eval_location_expr (c, as, a, addr, new_loc + i, arg)) < 0) + return ret; + new_loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (new_loc[i])); + break; + } + } + + memcpy(c->loc, new_loc, sizeof(new_loc)); + + c->cfa = cfa; + /* DWARF spec says undefined return address location means end of stack. */ + if (DWARF_IS_NULL_LOC (c->loc[rs->ret_addr_column])) + { + c->ip = 0; + ret = 0; + } + else + { + ret = dwarf_get (c, c->loc[rs->ret_addr_column], &ip); + if (ret < 0) + return ret; + c->ip = ip; + ret = 1; + } + + /* XXX: check for ip to be code_aligned */ + if (c->ip == prev_ip && c->cfa == prev_cfa) + { + Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n", + __FUNCTION__, (long) c->ip); + return -UNW_EBADFRAME; + } + + if (c->stash_frames) + tdep_stash_frame (c, rs); + + return ret; +} + +/* Find the saved locations. */ +static int +find_reg_state (struct dwarf_cursor *c, dwarf_state_record_t *sr) +{ + dwarf_reg_state_t *rs; + struct dwarf_rs_cache *cache; + int ret = 0; + intrmask_t saved_mask; + + if ((cache = get_rs_cache(c->as, &saved_mask)) && + (rs = rs_lookup(cache, c))) + { + /* update hint; no locking needed: single-word writes are atomic */ + unsigned short index = rs - cache->buckets; + c->use_prev_instr = ! cache->links[index].signal_frame; + memcpy (&sr->rs_current, rs, sizeof (*rs)); + } + else + { + ret = fetch_proc_info (c, c->ip); + int next_use_prev_instr = c->use_prev_instr; + if (ret >= 0) + { + /* Update use_prev_instr for the next frame. */ + assert(c->pi.unwind_info); + struct dwarf_cie_info *dci = c->pi.unwind_info; + next_use_prev_instr = ! dci->signal_frame; + ret = create_state_record_for (c, sr, c->ip); + } + put_unwind_info (c, &c->pi); + c->use_prev_instr = next_use_prev_instr; + + if (cache && ret >= 0) + { + rs = rs_new (cache, c); + cache->links[rs - cache->buckets].hint = 0; + memcpy(rs, &sr->rs_current, sizeof(*rs)); + } + } + + unsigned short index = -1; + if (cache) + { + put_rs_cache (c->as, cache, &saved_mask); + if (rs) + { + index = rs - cache->buckets; + c->hint = cache->links[index].hint; + cache->links[c->prev_rs].hint = index + 1; + c->prev_rs = index; + } + } + if (ret < 0) + return ret; + if (cache) + tdep_reuse_frame (c, cache->links[index].signal_frame); + return 0; +} + +/* The function finds the saved locations and applies the register + state as well. */ +HIDDEN int +dwarf_step (struct dwarf_cursor *c) +{ + int ret; + dwarf_state_record_t sr; + if ((ret = find_reg_state (c, &sr)) < 0) + return ret; + return apply_reg_state (c, &sr.rs_current); +} + +HIDDEN int +dwarf_make_proc_info (struct dwarf_cursor *c) +{ +#if 0 + if (c->as->caching_policy == UNW_CACHE_NONE + || get_cached_proc_info (c) < 0) +#endif + /* Need to check if current frame contains + args_size, and set cursor appropriately. Only + needed for unw_resume */ + dwarf_state_record_t sr; + int ret; + + /* Lookup it up the slow way... */ + ret = fetch_proc_info (c, c->ip); + if (ret >= 0) + ret = create_state_record_for (c, &sr, c->ip); + put_unwind_info (c, &c->pi); + if (ret < 0) + return ret; + c->args_size = sr.args_size; + + return 0; +} + +static int +dwarf_reg_states_dynamic_iterate(struct dwarf_cursor *c, + unw_reg_states_callback cb, + void *token) +{ + Debug (1, "Not yet implemented\n"); + return -UNW_ENOINFO; +} + +static int +dwarf_reg_states_table_iterate(struct dwarf_cursor *c, + unw_reg_states_callback cb, + void *token) +{ + dwarf_state_record_t sr; + int ret = setup_fde(c, &sr); + struct dwarf_cie_info *dci = c->pi.unwind_info; + unw_word_t addr = dci->fde_instr_start; + unw_word_t curr_ip = c->pi.start_ip; + dwarf_stackable_reg_state_t *rs_stack = NULL; + while (ret >= 0 && curr_ip < c->pi.end_ip && addr < dci->fde_instr_end) + { + unw_word_t prev_ip = curr_ip; + ret = run_cfi_program (c, &sr, &curr_ip, prev_ip, &addr, dci->fde_instr_end, + &rs_stack, dci); + if (ret >= 0 && prev_ip < curr_ip) + ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), prev_ip, curr_ip); + } + empty_rstate_stack(&rs_stack); +#if defined(NEED_LAST_IP) + if (ret >= 0 && curr_ip < c->pi.last_ip) + /* report the dead zone after the procedure ends */ + ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), curr_ip, c->pi.last_ip); +#else + if (ret >= 0 && curr_ip < c->pi.end_ip) + /* report for whatever is left before procedure end */ + ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), curr_ip, c->pi.end_ip); +#endif + return ret; +} + +HIDDEN int +dwarf_reg_states_iterate(struct dwarf_cursor *c, + unw_reg_states_callback cb, + void *token) +{ + int ret = fetch_proc_info (c, c->ip); + int next_use_prev_instr = c->use_prev_instr; + if (ret >= 0) + { + /* Update use_prev_instr for the next frame. */ + assert(c->pi.unwind_info); + struct dwarf_cie_info *dci = c->pi.unwind_info; + next_use_prev_instr = ! dci->signal_frame; + switch (c->pi.format) + { + case UNW_INFO_FORMAT_TABLE: + case UNW_INFO_FORMAT_REMOTE_TABLE: + ret = dwarf_reg_states_table_iterate(c, cb, token); + break; + + case UNW_INFO_FORMAT_DYNAMIC: + ret = dwarf_reg_states_dynamic_iterate (c, cb, token); + break; + + default: + Debug (1, "Unexpected unwind-info format %d\n", c->pi.format); + ret = -UNW_EINVAL; + } + } + put_unwind_info (c, &c->pi); + c->use_prev_instr = next_use_prev_instr; + return ret; +} + +HIDDEN int +dwarf_apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) +{ + return apply_reg_state(c, rs); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gpe.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gpe.c new file mode 100644 index 0000000..a0e37ba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Gpe.c @@ -0,0 +1,39 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "dwarf_i.h" +#include "libunwind_i.h" + +#include + +HIDDEN int +dwarf_read_encoded_pointer (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, unsigned char encoding, + const unw_proc_info_t *pi, + unw_word_t *valp, void *arg) +{ + return dwarf_read_encoded_pointer_inlined (as, a, addr, encoding, + pi, valp, arg); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lexpr.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lexpr.c new file mode 100644 index 0000000..245970c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lexpr.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gexpr.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lfde.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lfde.c new file mode 100644 index 0000000..e779e8f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lfde.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gfde.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lfind_proc_info-lsb.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lfind_proc_info-lsb.c new file mode 100644 index 0000000..27a5eea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lfind_proc_info-lsb.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gfind_proc_info-lsb.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lfind_unwind_table.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lfind_unwind_table.c new file mode 100644 index 0000000..68e269f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lfind_unwind_table.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gfind_unwind_table.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lparser.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lparser.c new file mode 100644 index 0000000..f23aaf4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lparser.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gparser.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lpe.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lpe.c new file mode 100644 index 0000000..a672358 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/Lpe.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gpe.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/global.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/global.c new file mode 100644 index 0000000..7098507 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/dwarf/global.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2003-2004 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "dwarf_i.h" + +HIDDEN struct mempool dwarf_reg_state_pool; +HIDDEN struct mempool dwarf_cie_info_pool; + +HIDDEN int +dwarf_init (void) +{ + mempool_init (&dwarf_reg_state_pool, sizeof (dwarf_stackable_reg_state_t), 0); + mempool_init (&dwarf_cie_info_pool, sizeof (struct dwarf_cie_info), 0); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf32.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf32.c new file mode 100644 index 0000000..a70bb58 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf32.c @@ -0,0 +1,4 @@ +#ifndef UNW_REMOTE_ONLY +# include "elf32.h" +# include "elfxx.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf32.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf32.h new file mode 100644 index 0000000..2c7bca4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf32.h @@ -0,0 +1,9 @@ +#ifndef elf32_h +#define elf32_h + +#ifndef ELF_CLASS +#define ELF_CLASS ELFCLASS32 +#endif +#include "elfxx.h" + +#endif /* elf32_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf64.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf64.c new file mode 100644 index 0000000..195b887 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf64.c @@ -0,0 +1,4 @@ +#ifndef UNW_REMOTE_ONLY +# include "elf64.h" +# include "elfxx.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf64.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf64.h new file mode 100644 index 0000000..091fba8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elf64.h @@ -0,0 +1,9 @@ +#ifndef elf64_h +#define elf64_h + +#ifndef ELF_CLASS +#define ELF_CLASS ELFCLASS64 +#endif +#include "elfxx.h" + +#endif /* elf64_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elfxx.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elfxx.c new file mode 100644 index 0000000..b03dfcb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elfxx.c @@ -0,0 +1,481 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2005 Hewlett-Packard Co + Copyright (C) 2007 David Mosberger-Tang + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +#include +#include + +#ifdef HAVE_LZMA +#include +#endif /* HAVE_LZMA */ + +static Elf_W (Shdr)* +elf_w (section_table) (struct elf_image *ei) +{ + Elf_W (Ehdr) *ehdr = ei->image; + Elf_W (Off) soff; + + soff = ehdr->e_shoff; + if (soff + ehdr->e_shnum * ehdr->e_shentsize > ei->size) + { + Debug (1, "section table outside of image? (%lu > %lu)\n", + (unsigned long) (soff + ehdr->e_shnum * ehdr->e_shentsize), + (unsigned long) ei->size); + return NULL; + } + + return (Elf_W (Shdr) *) ((char *) ei->image + soff); +} + +static char* +elf_w (string_table) (struct elf_image *ei, int section) +{ + Elf_W (Ehdr) *ehdr = ei->image; + Elf_W (Off) soff, str_soff; + Elf_W (Shdr) *str_shdr; + + /* this offset is assumed to be OK */ + soff = ehdr->e_shoff; + + str_soff = soff + (section * ehdr->e_shentsize); + if (str_soff + ehdr->e_shentsize > ei->size) + { + Debug (1, "string shdr table outside of image? (%lu > %lu)\n", + (unsigned long) (str_soff + ehdr->e_shentsize), + (unsigned long) ei->size); + return NULL; + } + str_shdr = (Elf_W (Shdr) *) ((char *) ei->image + str_soff); + + if (str_shdr->sh_offset + str_shdr->sh_size > ei->size) + { + Debug (1, "string table outside of image? (%lu > %lu)\n", + (unsigned long) (str_shdr->sh_offset + str_shdr->sh_size), + (unsigned long) ei->size); + return NULL; + } + + Debug (16, "strtab=0x%lx\n", (long) str_shdr->sh_offset); + return ei->image + str_shdr->sh_offset; +} + +static int +elf_w (lookup_symbol) (unw_addr_space_t as, + unw_word_t ip, struct elf_image *ei, + Elf_W (Addr) load_offset, + char *buf, size_t buf_len, Elf_W (Addr) *min_dist) +{ + size_t syment_size; + Elf_W (Ehdr) *ehdr = ei->image; + Elf_W (Sym) *sym, *symtab, *symtab_end; + Elf_W (Shdr) *shdr; + Elf_W (Addr) val; + int i, ret = -UNW_ENOINFO; + char *strtab; + + if (!elf_w (valid_object) (ei)) + return -UNW_ENOINFO; + + shdr = elf_w (section_table) (ei); + if (!shdr) + return -UNW_ENOINFO; + + for (i = 0; i < ehdr->e_shnum; ++i) + { + switch (shdr->sh_type) + { + case SHT_SYMTAB: + case SHT_DYNSYM: + symtab = (Elf_W (Sym) *) ((char *) ei->image + shdr->sh_offset); + symtab_end = (Elf_W (Sym) *) ((char *) symtab + shdr->sh_size); + syment_size = shdr->sh_entsize; + + strtab = elf_w (string_table) (ei, shdr->sh_link); + if (!strtab) + break; + + Debug (16, "symtab=0x%lx[%d]\n", + (long) shdr->sh_offset, shdr->sh_type); + + for (sym = symtab; + sym < symtab_end; + sym = (Elf_W (Sym) *) ((char *) sym + syment_size)) + { + if (ELF_W (ST_TYPE) (sym->st_info) == STT_FUNC + && sym->st_shndx != SHN_UNDEF) + { + val = sym->st_value; + if (sym->st_shndx != SHN_ABS) + val += load_offset; + if (tdep_get_func_addr (as, val, &val) < 0) + continue; + Debug (16, "0x%016lx info=0x%02x %s\n", + (long) val, sym->st_info, strtab + sym->st_name); + + if ((Elf_W (Addr)) (ip - val) < *min_dist) + { + *min_dist = (Elf_W (Addr)) (ip - val); + strncpy (buf, strtab + sym->st_name, buf_len); + buf[buf_len - 1] = '\0'; + ret = (strlen (strtab + sym->st_name) >= buf_len + ? -UNW_ENOMEM : 0); + } + } + } + break; + + default: + break; + } + shdr = (Elf_W (Shdr) *) (((char *) shdr) + ehdr->e_shentsize); + } + return ret; +} + +static Elf_W (Addr) +elf_w (get_load_offset) (struct elf_image *ei, unsigned long segbase, + unsigned long mapoff) +{ + Elf_W (Addr) offset = 0; + Elf_W (Ehdr) *ehdr; + Elf_W (Phdr) *phdr; + int i; + + ehdr = ei->image; + phdr = (Elf_W (Phdr) *) ((char *) ei->image + ehdr->e_phoff); + + for (i = 0; i < ehdr->e_phnum; ++i) + if (phdr[i].p_type == PT_LOAD && phdr[i].p_offset == mapoff) + { + offset = segbase - phdr[i].p_vaddr; + break; + } + + return offset; +} + +#if HAVE_LZMA +static size_t +xz_uncompressed_size (uint8_t *compressed, size_t length) +{ + uint64_t memlimit = UINT64_MAX; + size_t ret = 0, pos = 0; + lzma_stream_flags options; + lzma_index *index; + + if (length < LZMA_STREAM_HEADER_SIZE) + return 0; + + uint8_t *footer = compressed + length - LZMA_STREAM_HEADER_SIZE; + if (lzma_stream_footer_decode (&options, footer) != LZMA_OK) + return 0; + + if (length < LZMA_STREAM_HEADER_SIZE + options.backward_size) + return 0; + + uint8_t *indexdata = footer - options.backward_size; + if (lzma_index_buffer_decode (&index, &memlimit, NULL, indexdata, + &pos, options.backward_size) != LZMA_OK) + return 0; + + if (lzma_index_size (index) == options.backward_size) + { + ret = lzma_index_uncompressed_size (index); + } + + lzma_index_end (index, NULL); + return ret; +} + +static int +elf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi) +{ + Elf_W (Shdr) *shdr; + uint8_t *compressed = NULL; + uint64_t memlimit = UINT64_MAX; /* no memory limit */ + size_t compressed_len, uncompressed_len; + + shdr = elf_w (find_section) (ei, ".gnu_debugdata"); + if (!shdr) + return 0; + + compressed = ((uint8_t *) ei->image) + shdr->sh_offset; + compressed_len = shdr->sh_size; + + uncompressed_len = xz_uncompressed_size (compressed, compressed_len); + if (uncompressed_len == 0) + { + Debug (1, "invalid .gnu_debugdata contents\n"); + return 0; + } + + mdi->size = uncompressed_len; + mdi->image = mmap (NULL, uncompressed_len, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + + if (mdi->image == MAP_FAILED) + return 0; + + size_t in_pos = 0, out_pos = 0; + lzma_ret lret; + lret = lzma_stream_buffer_decode (&memlimit, 0, NULL, + compressed, &in_pos, compressed_len, + mdi->image, &out_pos, mdi->size); + if (lret != LZMA_OK) + { + Debug (1, "LZMA decompression failed: %d\n", lret); + munmap (mdi->image, mdi->size); + return 0; + } + + return 1; +} +#else +static int +elf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi) +{ + return 0; +} +#endif /* !HAVE_LZMA */ + +/* Find the ELF image that contains IP and return the "closest" + procedure name, if there is one. With some caching, this could be + sped up greatly, but until an application materializes that's + sensitive to the performance of this routine, why bother... */ + +HIDDEN int +elf_w (get_proc_name_in_image) (unw_addr_space_t as, struct elf_image *ei, + unsigned long segbase, + unsigned long mapoff, + unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp) +{ + Elf_W (Addr) load_offset; + Elf_W (Addr) min_dist = ~(Elf_W (Addr))0; + int ret; + + load_offset = elf_w (get_load_offset) (ei, segbase, mapoff); + ret = elf_w (lookup_symbol) (as, ip, ei, load_offset, buf, buf_len, &min_dist); + + /* If the ELF image has MiniDebugInfo embedded in it, look up the symbol in + there as well and replace the previously found if it is closer. */ + struct elf_image mdi; + if (elf_w (extract_minidebuginfo) (ei, &mdi)) + { + int ret_mdi = elf_w (lookup_symbol) (as, ip, &mdi, load_offset, buf, + buf_len, &min_dist); + + /* Closer symbol was found (possibly truncated). */ + if (ret_mdi == 0 || ret_mdi == -UNW_ENOMEM) + { + ret = ret_mdi; + } + + munmap (mdi.image, mdi.size); + } + + if (min_dist >= ei->size) + return -UNW_ENOINFO; /* not found */ + if (offp) + *offp = min_dist; + return ret; +} + +HIDDEN int +elf_w (get_proc_name) (unw_addr_space_t as, pid_t pid, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp) +{ + unsigned long segbase, mapoff; + struct elf_image ei; + int ret; + char file[PATH_MAX]; + + ret = tdep_get_elf_image (&ei, pid, ip, &segbase, &mapoff, file, PATH_MAX); + if (ret < 0) + return ret; + + ret = elf_w (load_debuglink) (file, &ei, 1); + if (ret < 0) + return ret; + + ret = elf_w (get_proc_name_in_image) (as, &ei, segbase, mapoff, ip, buf, buf_len, offp); + + munmap (ei.image, ei.size); + ei.image = NULL; + + return ret; +} + +HIDDEN Elf_W (Shdr)* +elf_w (find_section) (struct elf_image *ei, const char* secname) +{ + Elf_W (Ehdr) *ehdr = ei->image; + Elf_W (Shdr) *shdr; + char *strtab; + int i; + + if (!elf_w (valid_object) (ei)) + return 0; + + shdr = elf_w (section_table) (ei); + if (!shdr) + return 0; + + strtab = elf_w (string_table) (ei, ehdr->e_shstrndx); + if (!strtab) + return 0; + + for (i = 0; i < ehdr->e_shnum; ++i) + { + if (strcmp (strtab + shdr->sh_name, secname) == 0) + { + if (shdr->sh_offset + shdr->sh_size > ei->size) + { + Debug (1, "section \"%s\" outside image? (0x%lu > 0x%lu)\n", + secname, + (unsigned long) shdr->sh_offset + shdr->sh_size, + (unsigned long) ei->size); + return 0; + } + + Debug (16, "found section \"%s\" at 0x%lx\n", + secname, (unsigned long) shdr->sh_offset); + return shdr; + } + + shdr = (Elf_W (Shdr) *) (((char *) shdr) + ehdr->e_shentsize); + } + + /* section not found */ + return 0; +} + +/* Load a debug section, following .gnu_debuglink if appropriate + * Loads ei from file if not already mapped. + * If is_local, will also search sys directories /usr/local/dbg + * + * Returns 0 on success, failure otherwise. + * ei will be mapped to file or the located .gnu_debuglink from file + */ +HIDDEN int +elf_w (load_debuglink) (const char* file, struct elf_image *ei, int is_local) +{ + int ret; + Elf_W (Shdr) *shdr; + Elf_W (Ehdr) *prev_image; + off_t prev_size; + + if (!ei->image) + { + ret = elf_map_image(ei, file); + if (ret) + return ret; + } + + prev_image = ei->image; + prev_size = ei->size; + + /* Ignore separate debug files which contain a .gnu_debuglink section. */ + if (is_local == -1) { + return 0; + } + + shdr = elf_w (find_section) (ei, ".gnu_debuglink"); + if (shdr) { + if (shdr->sh_size >= PATH_MAX || + (shdr->sh_offset + shdr->sh_size > ei->size)) + { + return 0; + } + + { + char linkbuf[shdr->sh_size]; + char *link = ((char *) ei->image) + shdr->sh_offset; + char *p; + static const char *debugdir = "/usr/lib/debug"; + char basedir[strlen(file) + 1]; + char newname[shdr->sh_size + strlen (debugdir) + strlen (file) + 9]; + + memcpy(linkbuf, link, shdr->sh_size); + + if (memchr (linkbuf, 0, shdr->sh_size) == NULL) + return 0; + + ei->image = NULL; + + Debug(1, "Found debuglink section, following %s\n", linkbuf); + + p = strrchr (file, '/'); + if (p != NULL) + { + memcpy (basedir, file, p - file); + basedir[p - file] = '\0'; + } + else + basedir[0] = 0; + + strcpy (newname, basedir); + strcat (newname, "/"); + strcat (newname, linkbuf); + ret = elf_w (load_debuglink) (newname, ei, -1); + + if (ret == -1) + { + strcpy (newname, basedir); + strcat (newname, "/.debug/"); + strcat (newname, linkbuf); + ret = elf_w (load_debuglink) (newname, ei, -1); + } + + if (ret == -1 && is_local == 1) + { + strcpy (newname, debugdir); + strcat (newname, basedir); + strcat (newname, "/"); + strcat (newname, linkbuf); + ret = elf_w (load_debuglink) (newname, ei, -1); + } + + if (ret == -1) + { + /* No debuglink file found even though .gnu_debuglink existed */ + ei->image = prev_image; + ei->size = prev_size; + + return 0; + } + else + { + munmap (prev_image, prev_size); + } + + return ret; + } + } + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elfxx.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elfxx.h new file mode 100644 index 0000000..830432c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/elfxx.h @@ -0,0 +1,101 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003, 2005 Hewlett-Packard Co + Copyright (C) 2007 David Mosberger-Tang + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#include +#include + +#include "libunwind_i.h" + +#if ELF_CLASS == ELFCLASS32 +# define ELF_W(x) ELF32_##x +# define Elf_W(x) Elf32_##x +# define elf_w(x) _Uelf32_##x +#else +# define ELF_W(x) ELF64_##x +# define Elf_W(x) Elf64_##x +# define elf_w(x) _Uelf64_##x +#endif + +extern int elf_w (get_proc_name) (unw_addr_space_t as, + pid_t pid, unw_word_t ip, + char *buf, size_t len, + unw_word_t *offp); + +extern int elf_w (get_proc_name_in_image) (unw_addr_space_t as, + struct elf_image *ei, + unsigned long segbase, + unsigned long mapoff, + unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp); + +extern Elf_W (Shdr)* elf_w (find_section) (struct elf_image *ei, const char* secname); +extern int elf_w (load_debuglink) (const char* file, struct elf_image *ei, int is_local); + +static inline int +elf_w (valid_object) (struct elf_image *ei) +{ + if (ei->size <= EI_VERSION) + return 0; + + return (memcmp (ei->image, ELFMAG, SELFMAG) == 0 + && ((uint8_t *) ei->image)[EI_CLASS] == ELF_CLASS + && ((uint8_t *) ei->image)[EI_VERSION] != EV_NONE + && ((uint8_t *) ei->image)[EI_VERSION] <= EV_CURRENT); +} + +static inline int +elf_map_image (struct elf_image *ei, const char *path) +{ + struct stat stat; + int fd; + + fd = open (path, O_RDONLY); + if (fd < 0) + return -1; + + if (fstat (fd, &stat) < 0) + { + close (fd); + return -1; + } + + ei->size = stat.st_size; + ei->image = mmap (NULL, ei->size, PROT_READ, MAP_PRIVATE, fd, 0); + close (fd); + if (ei->image == MAP_FAILED) + return -1; + + if (!elf_w (valid_object) (ei)) + { + munmap(ei->image, ei->size); + return -1; + } + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gapply_reg_state.c new file mode 100644 index 0000000..82f056d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gapply_reg_state.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_apply_reg_state (unw_cursor_t *cursor, + void *reg_states_data) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gcreate_addr_space.c new file mode 100644 index 0000000..8a6cb8b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gcreate_addr_space.c @@ -0,0 +1,54 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "unwind_i.h" + +unw_addr_space_t +unw_create_addr_space (unw_accessors_t *a, int byte_order) +{ +#ifdef UNW_LOCAL_ONLY + return NULL; +#else + unw_addr_space_t as; + + /* + * hppa supports only big-endian. + */ + if (byte_order != 0 && byte_order != __BIG_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); + if (!as) + return NULL; + + memset (as, 0, sizeof (*as)); + + as->acc = *a; + + return as; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gget_proc_info.c new file mode 100644 index 0000000..e10efcf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gget_proc_info.c @@ -0,0 +1,46 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) +{ + struct cursor *c = (struct cursor *) cursor; + + if (dwarf_make_proc_info (&c->dwarf) < 0) + { + /* On hppa, some key routines such as _start() and _dl_start() + are missing DWARF unwind info. We don't want to fail in that + case, because those frames are uninteresting and just mark + the end of the frame-chain anyhow. */ + memset (pi, 0, sizeof (*pi)); + pi->start_ip = c->dwarf.ip; + pi->end_ip = c->dwarf.ip + 4; + return 0; + } + *pi = c->dwarf.pi; + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gget_save_loc.c new file mode 100644 index 0000000..02dfa30 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gget_save_loc.c @@ -0,0 +1,59 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) +{ + /* struct cursor *c = (struct cursor *) cursor; */ + dwarf_loc_t loc; + + loc = DWARF_NULL_LOC; /* default to "not saved" */ + +#warning FIX ME! + + memset (sloc, 0, sizeof (*sloc)); + + if (DWARF_IS_NULL_LOC (loc)) + { + sloc->type = UNW_SLT_NONE; + return 0; + } + +#if !defined(UNW_LOCAL_ONLY) + if (DWARF_IS_REG_LOC (loc)) + { + sloc->type = UNW_SLT_REG; + sloc->u.regnum = DWARF_GET_LOC (loc); + } + else +#endif + { + sloc->type = UNW_SLT_MEMORY; + sloc->u.addr = DWARF_GET_LOC (loc); + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gglobal.c new file mode 100644 index 0000000..351a501 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gglobal.c @@ -0,0 +1,55 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2004-2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +HIDDEN define_lock (hppa_lock); +HIDDEN int tdep_init_done; + +HIDDEN void +tdep_init (void) +{ + intrmask_t saved_mask; + + sigfillset (&unwi_full_mask); + + lock_acquire (&hppa_lock, saved_mask); + { + if (tdep_init_done) + /* another thread else beat us to it... */ + goto out; + + mi_init (); + + dwarf_init (); + +#ifndef UNW_REMOTE_ONLY + hppa_local_addr_space_init (); +#endif + tdep_init_done = 1; /* signal that we're initialized... */ + } + out: + lock_release (&hppa_lock, saved_mask); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Ginit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Ginit.c new file mode 100644 index 0000000..461e4b9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Ginit.c @@ -0,0 +1,194 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002, 2004 Hewlett-Packard Co + Copyright (C) 2007 David Mosberger-Tang + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#include "unwind_i.h" + +#ifdef UNW_REMOTE_ONLY + +/* unw_local_addr_space is a NULL pointer in this case. */ +unw_addr_space_t unw_local_addr_space; + +#else /* !UNW_REMOTE_ONLY */ + +static struct unw_addr_space local_addr_space; + +unw_addr_space_t unw_local_addr_space = &local_addr_space; + +static inline void * +uc_addr (ucontext_t *uc, int reg) +{ + void *addr; + + if ((unsigned) (reg - UNW_HPPA_GR) < 32) + addr = &uc->uc_mcontext.sc_gr[reg - UNW_HPPA_GR]; + else if ((unsigned) (reg - UNW_HPPA_FR) < 32) + addr = &uc->uc_mcontext.sc_fr[reg - UNW_HPPA_FR]; + else + addr = NULL; + return addr; +} + +# ifdef UNW_LOCAL_ONLY + +void * +_Uhppa_uc_addr (ucontext_t *uc, int reg) +{ + return uc_addr (uc, reg); +} + +# endif /* UNW_LOCAL_ONLY */ + +HIDDEN unw_dyn_info_list_t _U_dyn_info_list; + +/* XXX fix me: there is currently no way to locate the dyn-info list + by a remote unwinder. On ia64, this is done via a special + unwind-table entry. Perhaps something similar can be done with + DWARF2 unwind info. */ + +static void +put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) +{ + /* it's a no-op */ +} + +static int +get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, + void *arg) +{ + *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; + return 0; +} + +static int +access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, + void *arg) +{ + if (write) + { + Debug (12, "mem[%x] <- %x\n", addr, *val); + *(unw_word_t *) addr = *val; + } + else + { + *val = *(unw_word_t *) addr; + Debug (12, "mem[%x] -> %x\n", addr, *val); + } + return 0; +} + +static int +access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, + void *arg) +{ + unw_word_t *addr; + ucontext_t *uc = arg; + + if ((unsigned int) (reg - UNW_HPPA_FR) < 32) + goto badreg; + + addr = uc_addr (uc, reg); + if (!addr) + goto badreg; + + if (write) + { + *(unw_word_t *) addr = *val; + Debug (12, "%s <- %x\n", unw_regname (reg), *val); + } + else + { + *val = *(unw_word_t *) addr; + Debug (12, "%s -> %x\n", unw_regname (reg), *val); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} + +static int +access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + ucontext_t *uc = arg; + unw_fpreg_t *addr; + + if ((unsigned) (reg - UNW_HPPA_FR) > 32) + goto badreg; + + addr = uc_addr (uc, reg); + if (!addr) + goto badreg; + + if (write) + { + Debug (12, "%s <- %08x.%08x\n", + unw_regname (reg), val->raw.bits[1], val->raw.bits[0]); + *(unw_fpreg_t *) addr = *val; + } + else + { + *val = *(unw_fpreg_t *) addr; + Debug (12, "%s -> %08x.%08x\n", + unw_regname (reg), val->raw.bits[1], val->raw.bits[0]); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + /* attempt to access a non-preserved register */ + return -UNW_EBADREG; +} + +static int +get_static_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, + void *arg) +{ + return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp); +} + +HIDDEN void +hppa_local_addr_space_init (void) +{ + memset (&local_addr_space, 0, sizeof (local_addr_space)); + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; + local_addr_space.acc.find_proc_info = dwarf_find_proc_info; + local_addr_space.acc.put_unwind_info = put_unwind_info; + local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; + local_addr_space.acc.access_mem = access_mem; + local_addr_space.acc.access_reg = access_reg; + local_addr_space.acc.access_fpreg = access_fpreg; + local_addr_space.acc.resume = hppa_local_resume; + local_addr_space.acc.get_proc_name = get_static_proc_name; + unw_flush_cache (&local_addr_space, 0, 0); +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Ginit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Ginit_local.c new file mode 100644 index 0000000..1fdc771 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Ginit_local.c @@ -0,0 +1,77 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by ... + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "init.h" + +#ifdef UNW_REMOTE_ONLY + +int +unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) +{ + return -UNW_EINVAL; +} + +#else /* !UNW_REMOTE_ONLY */ + +static int +unw_init_local_common (unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr) +{ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = unw_local_addr_space; + c->dwarf.as_arg = uc; + return common_init (c, use_prev_instr); +} + +int +unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) +{ + return unw_init_local_common(cursor, uc, 1); +} + +int +unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) +{ + if (!flag) + { + return unw_init_local_common(cursor, uc, 1); + } + else if (flag == UNW_INIT_SIGNAL_FRAME) + { + return unw_init_local_common(cursor, uc, 0); + } + else + { + return -UNW_EINVAL; + } +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Ginit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Ginit_remote.c new file mode 100644 index 0000000..71096ce --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Ginit_remote.c @@ -0,0 +1,46 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2004 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "init.h" +#include "unwind_i.h" + +int +unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) +{ +#ifdef UNW_LOCAL_ONLY + return -UNW_EINVAL; +#else /* !UNW_LOCAL_ONLY */ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = as; + c->dwarf.as_arg = as_arg; + return common_init (c, 0); +#endif /* !UNW_LOCAL_ONLY */ +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gis_signal_frame.c new file mode 100644 index 0000000..addb551 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gis_signal_frame.c @@ -0,0 +1,74 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_is_signal_frame (unw_cursor_t *cursor) +{ +#ifdef __linux__ + struct cursor *c = (struct cursor *) cursor; + unw_word_t w0, w1, w2, w3, ip; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + int ret; + + as = c->dwarf.as; + a = unw_get_accessors_int (as); + arg = c->dwarf.as_arg; + + /* Check if IP points at sigreturn() sequence. On Linux, this normally is: + + rt_sigreturn: + 0x34190000 ldi 0, %r25 + 0x3414015a ldi __NR_rt_sigreturn,%r20 + 0xe4008200 be,l 0x100(%sr2,%r0),%sr0,%r31 + 0x08000240 nop + + When a signal interrupts a system call, the first word is instead: + + 0x34190002 ldi 1, %r25 + */ + ip = c->dwarf.ip; + if (!ip) + return 0; + if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0 + || (ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0 + || (ret = (*a->access_mem) (as, ip + 8, &w2, 0, arg)) < 0 + || (ret = (*a->access_mem) (as, ip + 12, &w3, 0, arg)) < 0) + { + Debug (1, "failed to read sigreturn code (ret=%d)\n", ret); + return ret; + } + ret = ((w0 == 0x34190000 || w0 == 0x34190002) + && w1 == 0x3414015a && w2 == 0xe4008200 && w3 == 0x08000240); + Debug (1, "(cursor=%p, ip=0x%08lx) -> %d\n", c, (unsigned) ip, ret); + return ret; +#else + printf ("%s: implement me\n", __FUNCTION__); +#endif + return -UNW_ENOINFO; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Greg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Greg_states_iterate.c new file mode 100644 index 0000000..a17dc1b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Greg_states_iterate.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_reg_states_iterate (unw_cursor_t *cursor, + unw_reg_states_callback cb, void *token) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_reg_states_iterate (&c->dwarf, cb, token); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gregs.c new file mode 100644 index 0000000..da0542c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gregs.c @@ -0,0 +1,87 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +HIDDEN int +tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + int write) +{ + struct dwarf_loc loc; + + switch (reg) + { + case UNW_HPPA_IP: + if (write) + c->dwarf.ip = *valp; /* update the IP cache */ + if (c->dwarf.pi_valid && (*valp < c->dwarf.pi.start_ip + || *valp >= c->dwarf.pi.end_ip)) + c->dwarf.pi_valid = 0; /* new IP outside of current proc */ + break; + + case UNW_HPPA_CFA: + case UNW_HPPA_SP: + if (write) + return -UNW_EREADONLYREG; + *valp = c->dwarf.cfa; + return 0; + + /* Do the exception-handling register remapping: */ + case UNW_HPPA_EH0: reg = UNW_HPPA_GR + 20; break; + case UNW_HPPA_EH1: reg = UNW_HPPA_GR + 21; break; + case UNW_HPPA_EH2: reg = UNW_HPPA_GR + 22; break; + case UNW_HPPA_EH3: reg = UNW_HPPA_GR + 31; break; + + default: + break; + } + + if ((unsigned) (reg - UNW_HPPA_GR) >= 32) + return -UNW_EBADREG; + + loc = c->dwarf.loc[reg]; + + if (write) + return dwarf_put (&c->dwarf, loc, *valp); + else + return dwarf_get (&c->dwarf, loc, valp); +} + +HIDDEN int +tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, + int write) +{ + struct dwarf_loc loc; + + if ((unsigned) (reg - UNW_HPPA_FR) >= 32) + return -UNW_EBADREG; + + loc = c->dwarf.loc[reg]; + + if (write) + return dwarf_putfp (&c->dwarf, loc, *valp); + else + return dwarf_getfp (&c->dwarf, loc, valp); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gresume.c new file mode 100644 index 0000000..6c11f14 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gresume.c @@ -0,0 +1,145 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2004 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "unwind_i.h" + +#ifndef UNW_REMOTE_ONLY + +#if defined(__linux) + +# include + +static NORETURN inline long +my_rt_sigreturn (void *new_sp, int in_syscall) +{ + register unsigned long r25 __asm__ ("r25") = (in_syscall != 0); + register unsigned long r20 __asm__ ("r20") = SYS_rt_sigreturn; + + __asm__ __volatile__ ("copy %0, %%sp\n" + "be,l 0x100(%%sr2,%%r0),%%sr0,%%r31\n" + "nop" + : + : "r"(new_sp), "r"(r20), "r"(r25) + : "memory"); + abort (); +} + +#endif /* __linux */ + +HIDDEN inline int +hppa_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ +#if defined(__linux) + struct cursor *c = (struct cursor *) cursor; + ucontext_t *uc = c->dwarf.as_arg; + + /* Ensure c->pi is up-to-date. On PA-RISC, it's relatively common to be + missing DWARF unwind info. We don't want to fail in that case, + because the frame-chain still would let us do a backtrace at + least. */ + dwarf_make_proc_info (&c->dwarf); + + if (unlikely (c->sigcontext_format != HPPA_SCF_NONE)) + { + struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; + + Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); + my_rt_sigreturn (sc, (sc->sc_flags & PARISC_SC_FLAG_IN_SYSCALL) != 0); + } + else + { + Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip); + setcontext (uc); + } +#else +# warning Implement me! +#endif + return -UNW_EINVAL; +} + +#endif /* !UNW_REMOTE_ONLY */ + +/* This routine is responsible for copying the register values in + cursor C and establishing them as the current machine state. */ + +static inline int +establish_machine_state (struct cursor *c) +{ + int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, + int write, void *); + int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *, + int write, void *); + unw_addr_space_t as = c->dwarf.as; + void *arg = c->dwarf.as_arg; + unw_fpreg_t fpval; + unw_word_t val; + int reg; + + access_reg = as->acc.access_reg; + access_fpreg = as->acc.access_fpreg; + + Debug (8, "copying out cursor state\n"); + + for (reg = 0; reg <= UNW_REG_LAST; ++reg) + { + Debug (16, "copying %s %d\n", unw_regname (reg), reg); + if (unw_is_fpreg (reg)) + { + if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) + (*access_fpreg) (as, reg, &fpval, 1, arg); + } + else + { + if (tdep_access_reg (c, reg, &val, 0) >= 0) + (*access_reg) (as, reg, &val, 1, arg); + } + } + return 0; +} + +int +unw_resume (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + Debug (1, "(cursor=%p)\n", c); + + if (!c->dwarf.ip) + { + /* This can happen easily when the frame-chain gets truncated + due to bad or missing unwind-info. */ + Debug (1, "refusing to resume execution at address 0\n"); + return -UNW_EINVAL; + } + + if ((ret = establish_machine_state (c)) < 0) + return ret; + + return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, + c->dwarf.as_arg); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gstep.c new file mode 100644 index 0000000..4fc8a87 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Gstep.c @@ -0,0 +1,95 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "offsets.h" + +int +unw_step (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret, i; + + Debug (1, "(cursor=%p, ip=0x%08x)\n", c, (unsigned) c->dwarf.ip); + + /* Try DWARF-based unwinding... */ + ret = dwarf_step (&c->dwarf); + + if (ret < 0 && ret != -UNW_ENOINFO) + { + Debug (2, "returning %d\n", ret); + return ret; + } + + if (unlikely (ret < 0)) + { + /* DWARF failed, let's see if we can follow the frame-chain + or skip over the signal trampoline. */ + + Debug (13, "dwarf_step() failed (ret=%d), trying fallback\n", ret); + + if (unw_is_signal_frame (cursor)) + { +#ifdef __linux__ + /* Assume that the trampoline is at the beginning of the + sigframe. */ + unw_word_t ip, sc_addr = c->dwarf.ip + LINUX_RT_SIGFRAME_UC_OFF; + dwarf_loc_t iaoq_loc = DWARF_LOC (sc_addr + LINUX_SC_IAOQ_OFF, 0); + + c->sigcontext_format = HPPA_SCF_LINUX_RT_SIGFRAME; + c->sigcontext_addr = sc_addr; + + if ((ret = dwarf_get (&c->dwarf, iaoq_loc, &ip)) < 0) + { + Debug (2, "failed to read IAOQ[1] (ret=%d)\n", ret); + return ret; + } + c->dwarf.ip = ip & ~0x3; /* mask out the privilege level */ + + for (i = 0; i < 32; ++i) + { + c->dwarf.loc[UNW_HPPA_GR + i] + = DWARF_LOC (sc_addr + LINUX_SC_GR_OFF + 4*i, 0); + c->dwarf.loc[UNW_HPPA_FR + i] + = DWARF_LOC (sc_addr + LINUX_SC_FR_OFF + 4*i, 0); + } + + if ((ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_HPPA_SP], + &c->dwarf.cfa)) < 0) + { + Debug (2, "failed to read SP (ret=%d)\n", ret); + return ret; + } +#else +# error Implement me! +#endif + } + else + c->dwarf.ip = 0; + } + ret = (c->dwarf.ip == 0) ? 0 : 1; + Debug (2, "returning %d\n", ret); + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lapply_reg_state.c new file mode 100644 index 0000000..7ebada4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lapply_reg_state.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gapply_reg_state.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lcreate_addr_space.c new file mode 100644 index 0000000..0f2dc6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lcreate_addr_space.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gcreate_addr_space.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lget_proc_info.c new file mode 100644 index 0000000..69028b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lget_proc_info.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_proc_info.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lget_save_loc.c new file mode 100644 index 0000000..9ea048a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lget_save_loc.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_save_loc.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lglobal.c new file mode 100644 index 0000000..6d7b489 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lglobal.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gglobal.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Linit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Linit.c new file mode 100644 index 0000000..e9abfdd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Linit.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Linit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Linit_local.c new file mode 100644 index 0000000..68a1687 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Linit_local.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_local.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Linit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Linit_remote.c new file mode 100644 index 0000000..58cb04a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Linit_remote.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_remote.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lis_signal_frame.c new file mode 100644 index 0000000..b9a7c4f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lis_signal_frame.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gis_signal_frame.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lreg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lreg_states_iterate.c new file mode 100644 index 0000000..f1eb1e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lreg_states_iterate.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Greg_states_iterate.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lregs.c new file mode 100644 index 0000000..2c9c75c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lregs.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gregs.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lresume.c new file mode 100644 index 0000000..41a8cf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lresume.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gresume.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lstep.c new file mode 100644 index 0000000..c1ac3c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/Lstep.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gstep.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/get_accessors.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/get_accessors.c new file mode 100644 index 0000000..2479580 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/get_accessors.c @@ -0,0 +1,38 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by ... + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +HIDDEN ALIAS(unw_get_accessors) unw_accessors_t * +unw_get_accessors_int (unw_addr_space_t as); + +unw_accessors_t * +unw_get_accessors (unw_addr_space_t as) +{ + if (!tdep_init_done) + tdep_init (); + + return &as->acc; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/getcontext.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/getcontext.S new file mode 100644 index 0000000..ec7554a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/getcontext.S @@ -0,0 +1,74 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#define SPILL(n) stw %r##n, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_GR_OFF+4*(n))(%r26) + +#include "offsets.h" + + .align 4 + .protected _Uhppa_getcontext + .global _Uhppa_getcontext + .proc + .callinfo +_Uhppa_getcontext: + SPILL (2) /* return-pointer */ + SPILL (3) /* frame pointer */ + SPILL (4) /* 2nd-ary frame pointer */ + SPILL (5) /* preserved register */ + SPILL (6) /* preserved register */ + SPILL (7) /* preserved register */ + SPILL (8) /* preserved register */ + SPILL (9) /* preserved register */ + SPILL (10) /* preserved register */ + SPILL (11) /* preserved register */ + SPILL (12) /* preserved register */ + SPILL (13) /* preserved register */ + SPILL (14) /* preserved register */ + SPILL (15) /* preserved register */ + SPILL (16) /* preserved register */ + SPILL (17) /* preserved register */ + SPILL (18) /* preserved register */ + SPILL (19) /* linkage-table register */ + SPILL (27) /* global-data pointer */ + SPILL (30) /* stack pointer */ + + ldo (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FR_OFF)(%r26), %r29 + fstds,ma %fr12, 8(%r29) + fstds,ma %fr13, 8(%r29) + fstds,ma %fr14, 8(%r29) + fstds,ma %fr15, 8(%r29) + fstds,ma %fr16, 8(%r29) + fstds,ma %fr17, 8(%r29) + fstds,ma %fr18, 8(%r29) + fstds,ma %fr19, 8(%r29) + fstds,ma %fr20, 8(%r29) + fstds %fr21, 8(%r29) + + bv,n %r0(%rp) + .procend +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/init.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/init.h new file mode 100644 index 0000000..4e23b86 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/init.h @@ -0,0 +1,47 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by ... + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static inline int +common_init (struct cursor *c, unsigned use_prev_instr) +{ + int ret; + + c->dwarf.loc[UNW_HPPA_IP] = DWARF_REG_LOC (&c->dwarf, UNW_HPPA_IP); + c->dwarf.loc[UNW_HPPA_SP] = DWARF_REG_LOC (&c->dwarf, UNW_HPPA_SP); + + ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_HPPA_IP], &c->dwarf.ip); + if (ret < 0) + return ret; + + ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_HPPA_SP], &c->dwarf.cfa); + if (ret < 0) + return ret; + + c->dwarf.stash_frames = 0; + c->dwarf.use_prev_instr = use_prev_instr; + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/offsets.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/offsets.h new file mode 100644 index 0000000..24e6453 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/offsets.h @@ -0,0 +1,17 @@ +#define LINUX_UC_FLAGS_OFF 0x000 +#define LINUX_UC_LINK_OFF 0x004 +#define LINUX_UC_STACK_OFF 0x008 +#define LINUX_UC_MCONTEXT_OFF 0x018 +#define LINUX_UC_SIGMASK_OFF 0x1b8 + +#define LINUX_SC_FLAGS_OFF 0x000 +#define LINUX_SC_GR_OFF 0x004 +#define LINUX_SC_FR_OFF 0x088 +#define LINUX_SC_IASQ_OFF 0x188 +#define LINUX_SC_IAOQ_OFF 0x190 +#define LINUX_SC_SAR_OFF 0x198 + +/* The signal frame contains 4 words of space for the sigreturn + trampoline, the siginfo structure, and then the sigcontext + structure. See include/asm-parisc/compat_rt_sigframe.h. */ +#define LINUX_RT_SIGFRAME_UC_OFF 0xac diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/regname.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/regname.c new file mode 100644 index 0000000..5698a58 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/regname.c @@ -0,0 +1,50 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2004-2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static const char *regname[] = + { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", + "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7", + "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15", + "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23", + "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31", + "ip", + "eh0", "eh1", "eh2", "eh3", + "cfa" + }; + +const char * +unw_regname (unw_regnum_t reg) +{ + if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) + return regname[reg]; + else + return "???"; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/setcontext.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/setcontext.S new file mode 100644 index 0000000..a36ea35 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/setcontext.S @@ -0,0 +1,77 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* The setcontext() in glibc is a no-op (as of 4 Dec 2004), so we have + to implement something useful on our own here. */ + +#define FILL(n) ldw (LINUX_UC_MCONTEXT_OFF+LINUX_SC_GR_OFF+4*(n))(%r26),%r##n + +#include "offsets.h" + + .align 4 + .global _Uhppa_setcontext + .protected _Uhppa_setcontext + .proc + .callinfo +_Uhppa_setcontext: + FILL (2) /* return-pointer */ + FILL (3) /* frame pointer */ + FILL (4) /* 2nd-ary frame pointer */ + FILL (5) /* preserved register */ + FILL (6) /* preserved register */ + FILL (7) /* preserved register */ + FILL (8) /* preserved register */ + FILL (9) /* preserved register */ + FILL (10) /* preserved register */ + FILL (11) /* preserved register */ + FILL (12) /* preserved register */ + FILL (13) /* preserved register */ + FILL (14) /* preserved register */ + FILL (15) /* preserved register */ + FILL (16) /* preserved register */ + FILL (17) /* preserved register */ + FILL (18) /* preserved register */ + FILL (19) /* linkage-table register */ + FILL (27) /* global-data pointer */ + FILL (30) /* stack pointer */ + + ldo (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FR_OFF)(%r26), %r29 + fldds,ma 8(%r29), %fr12 + fldds,ma 8(%r29), %fr13 + fldds,ma 8(%r29), %fr14 + fldds,ma 8(%r29), %fr15 + fldds,ma 8(%r29), %fr16 + fldds,ma 8(%r29), %fr17 + fldds,ma 8(%r29), %fr18 + fldds,ma 8(%r29), %fr19 + fldds,ma 8(%r29), %fr20 + fldds 8(%r29), %fr21 + + bv,n %r0(%rp) + .procend +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/siglongjmp.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/siglongjmp.S new file mode 100644 index 0000000..34878db --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/siglongjmp.S @@ -0,0 +1,16 @@ + /* Dummy implementation for now. */ + + .globl _UI_siglongjmp_cont + .globl _UI_longjmp_cont + +_UI_siglongjmp_cont: +_UI_longjmp_cont: + .proc + .callinfo +#warning fix me + bv %r0(%rp) + .procend +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/tables.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/tables.c new file mode 100644 index 0000000..5104d4d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/hppa/tables.c @@ -0,0 +1,43 @@ +#include "unwind_i.h" + +static inline int +is_local_addr_space (unw_addr_space_t as) +{ + extern unw_addr_space_t _ULhppa_local_addr_space; + + return (as == _Uhppa_local_addr_space +#ifndef UNW_REMOTE_ONLY + || as == _ULhppa_local_addr_space +#endif + ); +} + +HIDDEN int +tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, int need_unwind_info, void *arg) +{ + printf ("%s: begging to get implemented...\n", __FUNCTION__); + return 0; +} + +HIDDEN int +tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, int need_unwind_info, void *arg) +{ + printf ("%s: the biggest beggar of them all...\n", __FUNCTION__); + return 0; +} + +HIDDEN void +tdep_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg) +{ + if (!pi->unwind_info) + return; + + if (!is_local_addr_space (as)) + { + free (pi->unwind_info); + pi->unwind_info = NULL; + } +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gapply_reg_state.c new file mode 100644 index 0000000..b45d1b5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gapply_reg_state.c @@ -0,0 +1,39 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_apply_reg_state (unw_cursor_t *cursor, + void *reg_states_data) +{ + struct cursor *c = (struct cursor *) cursor; + + // Needs dwarf support on ia64 + // return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); + return -UNW_EINVAL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gcreate_addr_space.c new file mode 100644 index 0000000..7ad29cb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gcreate_addr_space.c @@ -0,0 +1,63 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "unwind_i.h" + +unw_addr_space_t +unw_create_addr_space (unw_accessors_t *a, int byte_order) +{ +#ifdef UNW_LOCAL_ONLY + return NULL; +#else + unw_addr_space_t as; + + /* + * IA-64 supports only big or little-endian, not weird stuff like + * PDP_ENDIAN. + */ + if (byte_order != 0 + && byte_order != __LITTLE_ENDIAN + && byte_order != __BIG_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); + + if (!as) + return NULL; + + memset (as, 0, sizeof (*as)); + + as->acc = *a; + + if (byte_order == 0) + /* use host default: */ + as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN); + else + as->big_endian = (byte_order == __BIG_ENDIAN); + return as; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gfind_unwind_table.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gfind_unwind_table.c new file mode 100644 index 0000000..9fd2707 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gfind_unwind_table.c @@ -0,0 +1,143 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include +#include +#include +#include + +#include + +#include "libunwind_i.h" +#include "elf64.h" + +static unw_word_t +find_gp (struct elf_dyn_info *edi, Elf64_Phdr *pdyn, Elf64_Addr load_base) +{ + Elf64_Off soff, str_soff; + Elf64_Ehdr *ehdr = edi->ei.image; + Elf64_Shdr *shdr; + Elf64_Shdr *str_shdr; + Elf64_Addr gp = 0; + char *strtab; + int i; + + if (pdyn) + { + /* If we have a PT_DYNAMIC program header, fetch the gp-value + from the DT_PLTGOT entry. */ + Elf64_Dyn *dyn = (Elf64_Dyn *) (pdyn->p_offset + (char *) edi->ei.image); + for (; dyn->d_tag != DT_NULL; ++dyn) + if (dyn->d_tag == DT_PLTGOT) + { + gp = (Elf64_Addr) dyn->d_un.d_ptr + load_base; + goto done; + } + } + + /* Without a PT_DYAMIC header, lets try to look for a non-empty .opd + section. If there is such a section, we know it's full of + function descriptors, and we can simply pick up the gp from the + second word of the first entry in this table. */ + + soff = ehdr->e_shoff; + str_soff = soff + (ehdr->e_shstrndx * ehdr->e_shentsize); + + if (soff + ehdr->e_shnum * ehdr->e_shentsize > edi->ei.size) + { + Debug (1, "section table outside of image? (%lu > %lu)", + soff + ehdr->e_shnum * ehdr->e_shentsize, + edi->ei.size); + goto done; + } + + shdr = (Elf64_Shdr *) ((char *) edi->ei.image + soff); + str_shdr = (Elf64_Shdr *) ((char *) edi->ei.image + str_soff); + strtab = (char *) edi->ei.image + str_shdr->sh_offset; + for (i = 0; i < ehdr->e_shnum; ++i) + { + if (strcmp (strtab + shdr->sh_name, ".opd") == 0 + && shdr->sh_size >= 16) + { + gp = ((Elf64_Addr *) ((char *) edi->ei.image + shdr->sh_offset))[1]; + goto done; + } + shdr = (Elf64_Shdr *) (((char *) shdr) + ehdr->e_shentsize); + } + + done: + Debug (16, "image at %p, gp = %lx\n", edi->ei.image, gp); + return gp; +} + +int +ia64_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as, + char *path, unw_word_t segbase, unw_word_t mapoff, + unw_word_t ip) +{ + Elf64_Phdr *phdr, *ptxt = NULL, *punw = NULL, *pdyn = NULL; + Elf64_Ehdr *ehdr; + int i; + + if (!_Uelf64_valid_object (&edi->ei)) + return -UNW_ENOINFO; + + ehdr = edi->ei.image; + phdr = (Elf64_Phdr *) ((char *) edi->ei.image + ehdr->e_phoff); + + for (i = 0; i < ehdr->e_phnum; ++i) + { + switch (phdr[i].p_type) + { + case PT_LOAD: + if (phdr[i].p_offset == mapoff) + ptxt = phdr + i; + break; + + case PT_IA_64_UNWIND: + punw = phdr + i; + break; + + case PT_DYNAMIC: + pdyn = phdr + i; + break; + + default: + break; + } + } + if (!ptxt || !punw) + return 0; + + edi->di_cache.start_ip = segbase; + edi->di_cache.end_ip = edi->di_cache.start_ip + ptxt->p_memsz; + edi->di_cache.gp = find_gp (edi, pdyn, segbase - ptxt->p_vaddr); + edi->di_cache.format = UNW_INFO_FORMAT_TABLE; + edi->di_cache.u.ti.name_ptr = 0; + edi->di_cache.u.ti.segbase = segbase; + edi->di_cache.u.ti.table_len = punw->p_memsz / sizeof (unw_word_t); + edi->di_cache.u.ti.table_data = (unw_word_t *) + ((char *) edi->ei.image + (punw->p_vaddr - ptxt->p_vaddr)); + return 1; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gget_proc_info.c new file mode 100644 index 0000000..3ec82b9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gget_proc_info.c @@ -0,0 +1,38 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + if ((ret = ia64_make_proc_info (c)) < 0) + return ret; + *pi = c->pi; + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gget_save_loc.c new file mode 100644 index 0000000..34efe99 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gget_save_loc.c @@ -0,0 +1,168 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2003, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "rse.h" + +#include "offsets.h" +#include "regs.h" + +int +unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) +{ + struct cursor *c = (struct cursor *) cursor; + ia64_loc_t loc, reg_loc; + uint8_t nat_bitnr; + int ret; + + loc = IA64_NULL_LOC; /* default to "not saved" */ + + switch (reg) + { + /* frame registers */ + case UNW_IA64_BSP: + case UNW_REG_SP: + default: + break; + + case UNW_REG_IP: + loc = c->loc[IA64_REG_IP]; + break; + + /* preserved registers: */ + case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7: + loc = c->loc[IA64_REG_R4 + (reg - (UNW_IA64_GR + 4))]; + break; + + case UNW_IA64_NAT + 4 ... UNW_IA64_NAT + 7: + loc = c->loc[IA64_REG_NAT4 + (reg - (UNW_IA64_NAT + 4))]; + reg_loc = c->loc[IA64_REG_R4 + (reg - (UNW_IA64_NAT + 4))]; + nat_bitnr = c->nat_bitnr[reg - (UNW_IA64_NAT + 4)]; + if (IA64_IS_FP_LOC (reg_loc)) + /* NaT bit saved as a NaTVal. */ + loc = reg_loc; + break; + + case UNW_IA64_FR + 2: loc = c->loc[IA64_REG_F2]; break; + case UNW_IA64_FR + 3: loc = c->loc[IA64_REG_F3]; break; + case UNW_IA64_FR + 4: loc = c->loc[IA64_REG_F4]; break; + case UNW_IA64_FR + 5: loc = c->loc[IA64_REG_F5]; break; + case UNW_IA64_FR + 16 ... UNW_IA64_FR + 31: + loc = c->loc[IA64_REG_F16 + (reg - (UNW_IA64_FR + 16))]; + break; + + case UNW_IA64_AR_BSP: loc = c->loc[IA64_REG_BSP]; break; + case UNW_IA64_AR_BSPSTORE: loc = c->loc[IA64_REG_BSPSTORE]; break; + case UNW_IA64_AR_PFS: loc = c->loc[IA64_REG_PFS]; break; + case UNW_IA64_AR_RNAT: loc = c->loc[IA64_REG_RNAT]; break; + case UNW_IA64_AR_UNAT: loc = c->loc[IA64_REG_UNAT]; break; + case UNW_IA64_AR_LC: loc = c->loc[IA64_REG_LC]; break; + case UNW_IA64_AR_FPSR: loc = c->loc[IA64_REG_FPSR]; break; + case UNW_IA64_BR + 1: loc = c->loc[IA64_REG_B1]; break; + case UNW_IA64_BR + 2: loc = c->loc[IA64_REG_B2]; break; + case UNW_IA64_BR + 3: loc = c->loc[IA64_REG_B3]; break; + case UNW_IA64_BR + 4: loc = c->loc[IA64_REG_B4]; break; + case UNW_IA64_BR + 5: loc = c->loc[IA64_REG_B5]; break; + case UNW_IA64_CFM: loc = c->cfm_loc; break; + case UNW_IA64_PR: loc = c->loc[IA64_REG_PR]; break; + + case UNW_IA64_GR + 32 ... UNW_IA64_GR + 127: /* stacked reg */ + reg = rotate_gr (c, reg - UNW_IA64_GR); + ret = ia64_get_stacked (c, reg, &loc, NULL); + if (ret < 0) + return ret; + break; + + case UNW_IA64_NAT + 32 ... UNW_IA64_NAT + 127: /* stacked reg */ + reg = rotate_gr (c, reg - UNW_IA64_NAT); + ret = ia64_get_stacked (c, reg, NULL, &loc); + break; + + case UNW_IA64_AR_EC: + loc = c->cfm_loc; + break; + + /* scratch & special registers: */ + + case UNW_IA64_GR + 0: + case UNW_IA64_GR + 1: /* global pointer */ + case UNW_IA64_NAT + 0: + case UNW_IA64_NAT + 1: /* global pointer */ + case UNW_IA64_FR + 0: + case UNW_IA64_FR + 1: + break; + + case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3: + case UNW_IA64_NAT + 8 ... UNW_IA64_NAT + 31: + loc = ia64_scratch_loc (c, reg, &nat_bitnr); + break; + + case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3: + case UNW_IA64_GR + 8 ... UNW_IA64_GR + 31: + case UNW_IA64_BR + 0: + case UNW_IA64_BR + 6: + case UNW_IA64_BR + 7: + case UNW_IA64_AR_RSC: + case UNW_IA64_AR_CSD: + case UNW_IA64_AR_SSD: + case UNW_IA64_AR_CCV: + loc = ia64_scratch_loc (c, reg, NULL); + break; + + case UNW_IA64_FR + 6 ... UNW_IA64_FR + 15: + loc = ia64_scratch_loc (c, reg, NULL); + break; + + case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127: + reg = rotate_fr (c, reg - UNW_IA64_FR) + UNW_IA64_FR; + loc = ia64_scratch_loc (c, reg, NULL); + break; + } + + memset (sloc, 0, sizeof (*sloc)); + + if (IA64_IS_NULL_LOC (loc)) + { + sloc->type = UNW_SLT_NONE; + return 0; + } + +#if !defined(UNW_LOCAL_ONLY) + if (IA64_IS_REG_LOC (loc)) + { + sloc->type = UNW_SLT_REG; + sloc->u.regnum = IA64_GET_REG (loc); + sloc->extra.nat_bitnr = nat_bitnr; + } + else +#endif + { + sloc->type = UNW_SLT_MEMORY; + sloc->u.addr = IA64_GET_ADDR (loc); + sloc->extra.nat_bitnr = nat_bitnr; + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gglobal.c new file mode 100644 index 0000000..5c6156f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gglobal.c @@ -0,0 +1,122 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "unwind_i.h" + +HIDDEN struct ia64_global_unwind_state unw = + { + .lock = PTHREAD_MUTEX_INITIALIZER, + .save_order = { + IA64_REG_IP, IA64_REG_PFS, IA64_REG_PSP, IA64_REG_PR, + IA64_REG_UNAT, IA64_REG_LC, IA64_REG_FPSR, IA64_REG_PRI_UNAT_GR + }, +#if UNW_DEBUG + .preg_name = { + "pri_unat_gr", "pri_unat_mem", "psp", "bsp", "bspstore", + "ar.pfs", "ar.rnat", "rp", + "r4", "r5", "r6", "r7", + "nat4", "nat5", "nat6", "nat7", + "ar.unat", "pr", "ar.lc", "ar.fpsr", + "b1", "b2", "b3", "b4", "b5", + "f2", "f3", "f4", "f5", + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31" + } +#endif +}; + +HIDDEN void +tdep_init (void) +{ + const uint8_t f1_bytes[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + const uint8_t nat_val_bytes[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + const uint8_t int_val_bytes[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + intrmask_t saved_mask; + uint8_t *lep, *bep; + long i; + + sigfillset (&unwi_full_mask); + + lock_acquire (&unw.lock, saved_mask); + { + if (tdep_init_done) + /* another thread else beat us to it... */ + goto out; + + mi_init (); + + mempool_init (&unw.reg_state_pool, sizeof (struct ia64_reg_state), 0); + mempool_init (&unw.labeled_state_pool, + sizeof (struct ia64_labeled_state), 0); + + unw.read_only.r0 = 0; + unw.read_only.f0.raw.bits[0] = 0; + unw.read_only.f0.raw.bits[1] = 0; + + lep = (uint8_t *) &unw.read_only.f1_le + 16; + bep = (uint8_t *) &unw.read_only.f1_be; + for (i = 0; i < 16; ++i) + { + *--lep = f1_bytes[i]; + *bep++ = f1_bytes[i]; + } + + lep = (uint8_t *) &unw.nat_val_le + 16; + bep = (uint8_t *) &unw.nat_val_be; + for (i = 0; i < 16; ++i) + { + *--lep = nat_val_bytes[i]; + *bep++ = nat_val_bytes[i]; + } + + lep = (uint8_t *) &unw.int_val_le + 16; + bep = (uint8_t *) &unw.int_val_be; + for (i = 0; i < 16; ++i) + { + *--lep = int_val_bytes[i]; + *bep++ = int_val_bytes[i]; + } + + assert (8*sizeof(unw_hash_index_t) >= IA64_LOG_UNW_HASH_SIZE); + +#ifndef UNW_REMOTE_ONLY + ia64_local_addr_space_init (); +#endif + tdep_init_done = 1; /* signal that we're initialized... */ + } + out: + lock_release (&unw.lock, saved_mask); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginit.c new file mode 100644 index 0000000..b09a2ad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginit.c @@ -0,0 +1,505 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2005 Hewlett-Packard Co + Copyright (C) 2007 David Mosberger-Tang + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +#ifdef HAVE_SYS_UC_ACCESS_H +# include +#endif + +#ifdef UNW_REMOTE_ONLY + +/* unw_local_addr_space is a NULL pointer in this case. */ +unw_addr_space_t unw_local_addr_space; + +#else /* !UNW_REMOTE_ONLY */ + +static struct unw_addr_space local_addr_space; + +unw_addr_space_t unw_local_addr_space = &local_addr_space; + +#ifdef HAVE_SYS_UC_ACCESS_H + +#else /* !HAVE_SYS_UC_ACCESS_H */ + +HIDDEN void * +tdep_uc_addr (ucontext_t *uc, int reg, uint8_t *nat_bitnr) +{ + return inlined_uc_addr (uc, reg, nat_bitnr); +} + +#endif /* !HAVE_SYS_UC_ACCESS_H */ + +static void +put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) +{ + /* it's a no-op */ +} + +static int +get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, + void *arg) +{ +#ifndef UNW_LOCAL_ONLY +# pragma weak _U_dyn_info_list_addr + if (!_U_dyn_info_list_addr) + return -UNW_ENOINFO; +#endif + *dyn_info_list_addr = _U_dyn_info_list_addr (); + return 0; +} + +static int +access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, + void *arg) +{ + if (write) + { + Debug (12, "mem[%lx] <- %lx\n", addr, *val); + *(unw_word_t *) addr = *val; + } + else + { + *val = *(unw_word_t *) addr; + Debug (12, "mem[%lx] -> %lx\n", addr, *val); + } + return 0; +} + +#ifdef HAVE_SYS_UC_ACCESS_H + +#define SYSCALL_CFM_SAVE_REG 11 /* on a syscall, ar.pfs is saved in r11 */ +#define REASON_SYSCALL 0 + +static int +access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, + void *arg) +{ + ucontext_t *uc = arg; + unsigned int nat, mask; + uint64_t value; + uint16_t reason; + int ret; + + __uc_get_reason (uc, &reason); + + switch (reg) + { + case UNW_IA64_GR ... UNW_IA64_GR + 31: + if ((ret = __uc_get_grs (uc, (reg - UNW_IA64_GR), 1, &value, &nat))) + break; + + if (write) + ret = __uc_set_grs (uc, (reg - UNW_IA64_GR), 1, val, nat); + else + *val = value; + break; + + case UNW_IA64_NAT ... UNW_IA64_NAT + 31: + if ((ret = __uc_get_grs (uc, (reg - UNW_IA64_GR), 1, &value, &nat))) + break; + + mask = 1 << (reg - UNW_IA64_GR); + + if (write) + { + if (*val) + nat |= mask; + else + nat &= ~mask; + ret = __uc_set_grs (uc, (reg - UNW_IA64_GR), 1, &value, nat); + } + else + *val = (nat & mask) != 0; + break; + + case UNW_IA64_AR ... UNW_IA64_AR + 127: + if (reg == UNW_IA64_AR_BSP) + { + if (write) + ret = __uc_set_ar (uc, (reg - UNW_IA64_AR), *val); + else + ret = __uc_get_ar (uc, (reg - UNW_IA64_AR), val); + } + else if (reg == UNW_IA64_AR_PFS && reason == REASON_SYSCALL) + { + /* As of HP-UX 11.22, getcontext() does not have unwind info + and because of that, we need to hack thins manually here. + Hopefully, this is OK because the HP-UX kernel also needs + to know where AR.PFS has been saved, so the use of + register r11 for this purpose is pretty much nailed + down. */ + if (write) + ret = __uc_set_grs (uc, SYSCALL_CFM_SAVE_REG, 1, val, 0); + else + ret = __uc_get_grs (uc, SYSCALL_CFM_SAVE_REG, 1, val, &nat); + } + else + { + if (write) + ret = __uc_set_ar (uc, (reg - UNW_IA64_AR), *val); + else + ret = __uc_get_ar (uc, (reg - UNW_IA64_AR), val); + } + break; + + case UNW_IA64_BR ... UNW_IA64_BR + 7: + if (write) + ret = __uc_set_brs (uc, (reg - UNW_IA64_BR), 1, val); + else + ret = __uc_get_brs (uc, (reg - UNW_IA64_BR), 1, val); + break; + + case UNW_IA64_PR: + if (write) + ret = __uc_set_prs (uc, *val); + else + ret = __uc_get_prs (uc, val); + break; + + case UNW_IA64_IP: + if (write) + ret = __uc_set_ip (uc, *val); + else + ret = __uc_get_ip (uc, val); + break; + + case UNW_IA64_CFM: + if (write) + ret = __uc_set_cfm (uc, *val); + else + ret = __uc_get_cfm (uc, val); + break; + + case UNW_IA64_FR ... UNW_IA64_FR + 127: + default: + ret = EINVAL; + break; + } + + if (ret != 0) + { + Debug (1, "failed to %s %s (ret = %d)\n", + write ? "write" : "read", unw_regname (reg), ret); + return -UNW_EBADREG; + } + + if (write) + Debug (12, "%s <- %lx\n", unw_regname (reg), *val); + else + Debug (12, "%s -> %lx\n", unw_regname (reg), *val); + return 0; +} + +static int +access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + ucontext_t *uc = arg; + fp_regval_t fp_regval; + int ret; + + switch (reg) + { + case UNW_IA64_FR ... UNW_IA64_FR + 127: + if (write) + { + memcpy (&fp_regval, val, sizeof (fp_regval)); + ret = __uc_set_frs (uc, (reg - UNW_IA64_FR), 1, &fp_regval); + } + else + { + ret = __uc_get_frs (uc, (reg - UNW_IA64_FR), 1, &fp_regval); + memcpy (val, &fp_regval, sizeof (*val)); + } + break; + + default: + ret = EINVAL; + break; + } + if (ret != 0) + return -UNW_EBADREG; + + return 0; +} + +#else /* !HAVE_SYS_UC_ACCESS_H */ + +static int +access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, + void *arg) +{ + unw_word_t *addr, mask; + ucontext_t *uc = arg; + + if (reg >= UNW_IA64_NAT + 4 && reg <= UNW_IA64_NAT + 7) + { + mask = ((unw_word_t) 1) << (reg - UNW_IA64_NAT); + if (write) + { + if (*val) + uc->uc_mcontext.sc_nat |= mask; + else + uc->uc_mcontext.sc_nat &= ~mask; + } + else + *val = (uc->uc_mcontext.sc_nat & mask) != 0; + + if (write) + Debug (12, "%s <- %lx\n", unw_regname (reg), *val); + else + Debug (12, "%s -> %lx\n", unw_regname (reg), *val); + return 0; + } + + addr = tdep_uc_addr (uc, reg, NULL); + if (!addr) + goto badreg; + + if (write) + { + if (ia64_read_only_reg (addr)) + { + Debug (16, "attempt to write read-only register\n"); + return -UNW_EREADONLYREG; + } + *addr = *val; + Debug (12, "%s <- %lx\n", unw_regname (reg), *val); + } + else + { + *val = *(unw_word_t *) addr; + Debug (12, "%s -> %lx\n", unw_regname (reg), *val); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} + +static int +access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + ucontext_t *uc = arg; + unw_fpreg_t *addr; + + if (reg < UNW_IA64_FR || reg >= UNW_IA64_FR + 128) + goto badreg; + + addr = tdep_uc_addr (uc, reg, NULL); + if (!addr) + goto badreg; + + if (write) + { + if (ia64_read_only_reg (addr)) + { + Debug (16, "attempt to write read-only register\n"); + return -UNW_EREADONLYREG; + } + *addr = *val; + Debug (12, "%s <- %016lx.%016lx\n", + unw_regname (reg), val->raw.bits[1], val->raw.bits[0]); + } + else + { + *val = *(unw_fpreg_t *) addr; + Debug (12, "%s -> %016lx.%016lx\n", + unw_regname (reg), val->raw.bits[1], val->raw.bits[0]); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + /* attempt to access a non-preserved register */ + return -UNW_EBADREG; +} + +#endif /* !HAVE_SYS_UC_ACCESS_H */ + +static int +get_static_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, + void *arg) +{ + return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp); +} + +HIDDEN void +ia64_local_addr_space_init (void) +{ + memset (&local_addr_space, 0, sizeof (local_addr_space)); + local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN); +#if defined(__linux) + local_addr_space.abi = ABI_LINUX; +#elif defined(__hpux) + local_addr_space.abi = ABI_HPUX; +#endif + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; + local_addr_space.acc.find_proc_info = tdep_find_proc_info; + local_addr_space.acc.put_unwind_info = put_unwind_info; + local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; + local_addr_space.acc.access_mem = access_mem; + local_addr_space.acc.access_reg = access_reg; + local_addr_space.acc.access_fpreg = access_fpreg; + local_addr_space.acc.resume = ia64_local_resume; + local_addr_space.acc.get_proc_name = get_static_proc_name; + unw_flush_cache (&local_addr_space, 0, 0); +} + +#endif /* !UNW_REMOTE_ONLY */ + +#ifndef UNW_LOCAL_ONLY + +HIDDEN int +ia64_uc_access_reg (struct cursor *c, ia64_loc_t loc, unw_word_t *valp, + int write) +{ +#ifdef HAVE_SYS_UC_ACCESS_H + unw_word_t uc_addr = IA64_GET_AUX_ADDR (loc); + ucontext_t *ucp; + int ret; + + Debug (16, "%s location %s\n", + write ? "writing" : "reading", ia64_strloc (loc)); + + if (c->as == unw_local_addr_space) + ucp = (ucontext_t *) uc_addr; + else + { + unw_word_t *dst, src; + + /* Need to copy-in ucontext_t first. */ + ucp = alloca (sizeof (ucontext_t)); + if (!ucp) + return -UNW_ENOMEM; + + /* For now, there is no non-HP-UX implementation of the + uc_access(3) interface. Because of that, we cannot, e.g., + unwind an HP-UX program from a Linux program. Should that + become possible at some point in the future, the + copy-in/copy-out needs to be adjusted to do byte-swapping if + necessary. */ + assert (c->as->big_endian == (__BYTE_ORDER == __BIG_ENDIAN)); + + dst = (unw_word_t *) ucp; + for (src = uc_addr; src < uc_addr + sizeof (ucontext_t); src += 8) + if ((ret = (*c->as->acc.access_mem) (c->as, src, dst++, 0, c->as_arg)) + < 0) + return ret; + } + + if (IA64_IS_REG_LOC (loc)) + ret = access_reg (unw_local_addr_space, IA64_GET_REG (loc), valp, write, + ucp); + else + { + /* Must be an access to the RSE backing store in ucontext_t. */ + unw_word_t addr = IA64_GET_ADDR (loc); + + if (write) + ret = __uc_set_rsebs (ucp, (uint64_t *) addr, 1, valp); + else + ret = __uc_get_rsebs (ucp, (uint64_t *) addr, 1, valp); + if (ret != 0) + ret = -UNW_EBADREG; + } + if (ret < 0) + return ret; + + if (write && c->as != unw_local_addr_space) + { + /* need to copy-out ucontext_t: */ + unw_word_t dst, *src = (unw_word_t *) ucp; + for (dst = uc_addr; dst < uc_addr + sizeof (ucontext_t); dst += 8) + if ((ret = (*c->as->acc.access_mem) (c->as, dst, src++, 1, c->as_arg)) + < 0) + return ret; + } + return 0; +#else /* !HAVE_SYS_UC_ACCESS_H */ + return -UNW_EINVAL; +#endif /* !HAVE_SYS_UC_ACCESS_H */ +} + +HIDDEN int +ia64_uc_access_fpreg (struct cursor *c, ia64_loc_t loc, unw_fpreg_t *valp, + int write) +{ +#ifdef HAVE_SYS_UC_ACCESS_H + unw_word_t uc_addr = IA64_GET_AUX_ADDR (loc); + ucontext_t *ucp; + int ret; + + if (c->as == unw_local_addr_space) + ucp = (ucontext_t *) uc_addr; + else + { + unw_word_t *dst, src; + + /* Need to copy-in ucontext_t first. */ + ucp = alloca (sizeof (ucontext_t)); + if (!ucp) + return -UNW_ENOMEM; + + /* For now, there is no non-HP-UX implementation of the + uc_access(3) interface. Because of that, we cannot, e.g., + unwind an HP-UX program from a Linux program. Should that + become possible at some point in the future, the + copy-in/copy-out needs to be adjusted to do byte-swapping if + necessary. */ + assert (c->as->big_endian == (__BYTE_ORDER == __BIG_ENDIAN)); + + dst = (unw_word_t *) ucp; + for (src = uc_addr; src < uc_addr + sizeof (ucontext_t); src += 8) + if ((ret = (*c->as->acc.access_mem) (c->as, src, dst++, 0, c->as_arg)) + < 0) + return ret; + } + + if ((ret = access_fpreg (unw_local_addr_space, IA64_GET_REG (loc), valp, + write, ucp)) < 0) + return ret; + + if (write && c->as != unw_local_addr_space) + { + /* need to copy-out ucontext_t: */ + unw_word_t dst, *src = (unw_word_t *) ucp; + for (dst = uc_addr; dst < uc_addr + sizeof (ucontext_t); dst += 8) + if ((ret = (*c->as->acc.access_mem) (c->as, dst, src++, 1, c->as_arg)) + < 0) + return ret; + } + return 0; +#else /* !HAVE_SYS_UC_ACCESS_H */ + return -UNW_EINVAL; +#endif /* !HAVE_SYS_UC_ACCESS_H */ +} + +#endif /* UNW_LOCAL_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginit_local.c new file mode 100644 index 0000000..8fe1c67 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginit_local.c @@ -0,0 +1,110 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2003, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "init.h" +#include "unwind_i.h" + +#ifdef UNW_REMOTE_ONLY + +int +unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) +{ + return -UNW_EINVAL; +} + +#else /* !UNW_REMOTE_ONLY */ + +static inline void +set_as_arg (struct cursor *c, unw_context_t *uc) +{ +#if defined(__linux) && defined(__KERNEL__) + c->task = current; + c->as_arg = &uc->sw; +#else + c->as_arg = uc; +#endif +} + +static inline int +get_initial_stack_pointers (struct cursor *c, unw_context_t *uc, + unw_word_t *sp, unw_word_t *bsp) +{ +#if defined(__linux) + unw_word_t sol, bspstore; + +#ifdef __KERNEL__ + sol = (uc->sw.ar_pfs >> 7) & 0x7f; + bspstore = uc->sw.ar_bspstore; + *sp = uc->ksp; +# else + sol = (uc->uc_mcontext.sc_ar_pfs >> 7) & 0x7f; + bspstore = uc->uc_mcontext.sc_ar_bsp; + *sp = uc->uc_mcontext.sc_gr[12]; +# endif + *bsp = rse_skip_regs (bspstore, -sol); +#elif defined(__hpux) + int ret; + + if ((ret = ia64_get (c, IA64_REG_LOC (c, UNW_IA64_GR + 12), sp)) < 0 + || (ret = ia64_get (c, IA64_REG_LOC (c, UNW_IA64_AR_BSP), bsp)) < 0) + return ret; +#else +# error Fix me. +#endif + return 0; +} + +int +unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) +{ + struct cursor *c = (struct cursor *) cursor; + unw_word_t sp, bsp; + int ret; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->as = unw_local_addr_space; + set_as_arg (c, uc); + + if ((ret = get_initial_stack_pointers (c, uc, &sp, &bsp)) < 0) + return ret; + + Debug (4, "initial bsp=%lx, sp=%lx\n", bsp, sp); + + if ((ret = common_init (c, sp, bsp)) < 0) + return ret; + +#ifdef __hpux + /* On HP-UX, the context created by getcontext() points to the + getcontext() system call stub. Step over it: */ + ret = unw_step (cursor); +#endif + return ret; +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginit_remote.c new file mode 100644 index 0000000..b570c7e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginit_remote.c @@ -0,0 +1,61 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002, 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "init.h" +#include "unwind_i.h" + +int +unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) +{ +#ifdef UNW_LOCAL_ONLY + return -UNW_EINVAL; +#else /* !UNW_LOCAL_ONLY */ + struct cursor *c = (struct cursor *) cursor; + unw_word_t sp, bsp; + int ret; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + if (as == unw_local_addr_space) + /* This special-casing is unfortunate and shouldn't be needed; + however, both Linux and HP-UX need to adjust the context a bit + before it's usable. Try to think of a cleaner way of doing + this. Not sure it's possible though, as long as we want to be + able to use the context returned by getcontext() et al. */ + return unw_init_local (cursor, as_arg); + + c->as = as; + c->as_arg = as_arg; + + if ((ret = ia64_get (c, IA64_REG_LOC (c, UNW_IA64_GR + 12), &sp)) < 0 + || (ret = ia64_get (c, IA64_REG_LOC (c, UNW_IA64_AR_BSP), &bsp)) < 0) + return ret; + + return common_init (c, sp, bsp); +#endif /* !UNW_LOCAL_ONLY */ +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginstall_cursor.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginstall_cursor.S new file mode 100644 index 0000000..6fb4401 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ginstall_cursor.S @@ -0,0 +1,348 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "ucontext_i.h" + +#ifdef UNW_LOCAL_ONLY +# include "Lcursor_i.h" +# define ia64_install_cursor _ULia64_install_cursor +#else +# include "Gcursor_i.h" +# define ia64_install_cursor _Uia64_install_cursor +#endif + +#define SYS_sigreturn 1181 + +#ifndef UNW_REMOTE_ONLY + +/* ia64_install_cursor (const cursor *c, long pri_unat, long *extra, + long bspstore, long dirty_size, long *dirty_partition, + long dirty_rnat) + + Restores the machine-state represented by C and thereby resumes execution + in that frame. If the frame or one of its descendants was interrupted + by a signal, all registers are restored (including the signal mask). + Otherwise, only the preserved registers, the global-pointer (r1), and + the exception-arguments (r15-r18) are restored. */ + +#define pRet p6 +#define pSig p7 + + .align 32 + .hidden ia64_install_cursor + .global ia64_install_cursor + .proc ia64_install_cursor +ia64_install_cursor: + alloc r3 = ar.pfs, 7, 0, 0, 0 + invala + add r2 = FR_LOC_OFF, in0 + ;; + + ld8 r16 = [r2], LOC_SIZE // r16 = loc[IA64_REG_FR16] + mov.m r10 = ar.rsc // (ar.rsc: ~ 12 cycle latency) + add r3 = FR_LOC_OFF + 16, in0 + ;; + + ld8 r17 = [r2], 2*LOC_SIZE // r17 = loc[IA64_REG_FR17] + ld8 r18 = [r3], 2*LOC_SIZE // r18 = loc[IA64_REG_FR18] + and r16 = -4, r16 + ;; + + ld8 r19 = [r2], 2*LOC_SIZE // r19 = loc[IA64_REG_FR19] + ld8 r20 = [r3], 2*LOC_SIZE // r20 = loc[IA64_REG_FR20] + and r17 = -4, r17 + ;; + + ldf.fill f16 = [r16] // f16 restored (don't touch no more) + ldf.fill f17 = [r17] // f17 restored (don't touch no more) + and r18 = -4, r18 + + ld8 r21 = [r2], 2*LOC_SIZE // r21 = loc[IA64_REG_FR21] + ld8 r22 = [r3], 2*LOC_SIZE // r22 = loc[IA64_REG_FR22] + and r19 = -4, r19 + ;; + + ldf.fill f18 = [r18] // f18 restored (don't touch no more) + ldf.fill f19 = [r19] // f19 restored (don't touch no more) + and r20 = -4, r20 + + ld8 r23 = [r2], 2*LOC_SIZE // r23 = loc[IA64_REG_FR23] + ld8 r24 = [r3], 2*LOC_SIZE // r24 = loc[IA64_REG_FR24] + and r21 = -4, r21 + ;; + + ldf.fill f20 = [r20] // f20 restored (don't touch no more) + ldf.fill f21 = [r21] // f21 restored (don't touch no more) + and r22 = -4, r22 + + ld8 r25 = [r2], 2*LOC_SIZE // r25 = loc[IA64_REG_FR25] + ld8 r26 = [r3], 2*LOC_SIZE // r26 = loc[IA64_REG_FR26] + and r23 = -4, r23 + ;; + + ldf.fill f22 = [r22] // f22 restored (don't touch no more) + ldf.fill f23 = [r23] // f23 restored (don't touch no more) + and r24 = -4, r24 + + ld8 r27 = [r2], 2*LOC_SIZE // r27 = loc[IA64_REG_FR27] + ld8 r28 = [r3], 2*LOC_SIZE // r28 = loc[IA64_REG_FR28] + and r25 = -4, r25 + ;; + + ldf.fill f24 = [r24] // f24 restored (don't touch no more) + ldf.fill f25 = [r25] // f25 restored (don't touch no more) + and r26 = -4, r26 + + ld8 r29 = [r2], 2*LOC_SIZE // r29 = loc[IA64_REG_FR29] + ld8 r30 = [r3], 2*LOC_SIZE // r30 = loc[IA64_REG_FR30] + and r27 = -4, r27 + ;; + + ldf.fill f26 = [r26] // f26 restored (don't touch no more) + ldf.fill f27 = [r27] // f27 restored (don't touch no more) + and r28 = -4, r28 + + ld8 r31 = [r2] // r31 = loc[IA64_REG_FR31] + mov.m ar.unat = in1 + and r29 = -4, r29 + ;; + + ldf.fill f28 = [r28] // f28 restored (don't touch no more) + ldf.fill f29 = [r29] // f29 restored (don't touch no more) + and r30 = -4, r30 + + ld8 r1 = [in2], 8 // gp restored (don't touch no more) + add r8 = SIGCONTEXT_ADDR_OFF, in0 + and r31 = -4, r31 + ;; + + ld8 r8 = [r8] // r8 = sigcontext_addr + and r11 = 0x1c, r10 // clear all but rsc.be and rsc.pl + add r2 = PFS_LOC_OFF, in0 + + ldf.fill f30 = [r30] // f30 restored (don't touch no more) + ldf.fill f31 = [r31] // f31 restored (don't touch no more) + add r3 = 8, in2 + ;; + + ld8.fill r4 = [in2], 16 // r4 restored (don't touch no more) + ld8.fill r5 = [r3], 16 // r5 restored (don't touch no more) + cmp.eq pRet, pSig = r0, r8 // sigcontext_addr == NULL? + ;; + ld8.fill r6 = [in2], 16 // r6 restored (don't touch no more) + ld8.fill r7 = [r3] // r7 restored (don't touch no more) + add r3 = IP_OFF, in0 + ;; + + ld8 r14 = [r2], (B1_LOC_OFF - PFS_LOC_OFF) // r14 = pfs_loc + ld8 r15 = [r3] // r15 = ip + add r3 = (B2_LOC_OFF - IP_OFF), r3 + ;; + + ld8 r16 = [r2], (B3_LOC_OFF - B1_LOC_OFF) // r16 = b1_loc + ld8 r17= [r3], (B4_LOC_OFF - B2_LOC_OFF) // r17 = b2_loc + and r14 = -4, r14 + ;; + + ld8 r18 = [r2], (B5_LOC_OFF - B3_LOC_OFF) // r18 = b3_loc + ld8 r19 = [r3], (F2_LOC_OFF - B4_LOC_OFF) // r19 = b4_loc + and r16 = -4, r16 + ;; + + ld8 r20 = [r2], (F3_LOC_OFF - B5_LOC_OFF) // r20 = b5_loc + ld8 r21 = [r3], (F4_LOC_OFF - F2_LOC_OFF) // r21 = f2_loc + and r17 = -4, r17 + ;; + + ld8 r16 = [r16] // r16 = *b1_loc + ld8 r17 = [r17] // r17 = *b2_loc + and r18 = -4, r18 + + ld8 r22 = [r2], (F5_LOC_OFF - F3_LOC_OFF) // r21 = f3_loc + ld8 r23 = [r3], (UNAT_LOC_OFF - F4_LOC_OFF) // r22 = f4_loc + and r19 = -4, r19 + ;; + + ld8 r18 = [r18] // r18 = *b3_loc + ld8 r19 = [r19] // r19 = *b4_loc + and r20 = -4, r20 + + ld8 r24 = [r2], (LC_LOC_OFF - F5_LOC_OFF) // r24 = f5_loc + ld8 r25 = [r3], (FPSR_LOC_OFF - UNAT_LOC_OFF) // r25 = unat_loc + and r21 = -4, r21 + ;; + + and r22 = -4, r22 + and r23 = -4, r23 + and r24 = -4, r24 + + ld8 r20 = [r20] // r20 = *b5_loc + ldf.fill f2 = [r21] // f2 restored (don't touch no more) + mov b1 = r16 // b1 restored (don't touch no more) + ;; + + ldf.fill f3 = [r22] // f3 restored (don't touch no more) + ldf.fill f4 = [r23] // f4 restored (don't touch no more) + mov b2 = r17 // b2 restored (don't touch no more) + + ld8 r26 = [r2], (RNAT_LOC_OFF - LC_LOC_OFF) // r26 = lc_loc + ld8 r27 = [r3] // r27 = fpsr_loc + and r25 = -4, r25 + + add r3 = (PSP_OFF - FPSR_LOC_OFF), r3 + nop 0 + nop 0 + ;; + + ldf.fill f5 = [r24] // f5 restored (don't touch no more) +(pRet) ld8 r25 = [r25] // r25 = *unat_loc + mov b3 = r18 // b3 restored (don't touch no more) + + ld8 r28 = [r2], (BSP_OFF - RNAT_LOC_OFF) // r28 = rnat_loc + ld8 r29 = [r3], (PR_OFF - PSP_OFF) // r29 = sp + mov b4 = r19 // b4 restored (don't touch no more) + + and r26 = -4, r26 + and r27 = -4, r27 + mov b5 = r20 // b5 restored (don't touch no more) + ;; + + ld8 r26 = [r26] // r26 = *lc_loc + ld8 r27 = [r27] // r27 = *fpsr_loc + and r28 = -4, r28 + + mov r30 = in3 // make backup-copy of new bsp + ld8 r31 = [r3] // r31 = pr + mov rp = r15 + ;; + + ld8 r28 = [r28] // r28 = rnat + mov.m ar.rsc = r11 // put RSE into enforced lazy mode + mov.i ar.lc = r26 // lc restored (don't touch no more) + ;; + + loadrs // drop dirty partition + mov r9 = in2 // make backup-copy of &extra[r16] + cmp.eq p8, p0 = in4, r0 // dirty-size == 0? +(p8) br.cond.dpnt.many .skip_load_dirty + + mov r2 = in4 // make backup-copy of dirty_size + mov r15 = in5 // make backup-copy of dirty_partition + mov r16 = in6 // make backup-copy of dirty_rnat + ;; + + alloc r3 = ar.pfs, 0, 0, 0, 0 // drop register frame + dep r11 = r2, r11, 16, 16 + ;; + mov.m ar.bspstore = r15 + ;; + mov.m ar.rnat = r16 + mov.m ar.rsc = r11 // 14 cycles latency to loadrs + ;; + loadrs // loadup new dirty partition + ;; + +.skip_load_dirty: + mov.m ar.bspstore = r30 // restore register backing-store + add r3 = 8, r9 // r3 = &extra[r16] + ;; + +(pRet) mov.m ar.fpsr = r27 // fpsr restored (don't touch no more) + mov.m ar.rnat = r28 +(pSig) br.cond.dpnt.many .next + +/****** Return via br.ret: */ + + ld8 r14 = [r14] // r14 = *pfs_loc + ld8 r15 = [r9], 16 // r15 restored (don't touch no more) + mov pr = r31, -1 // pr restored (don't touch no more) + ;; + + ld8 r16 = [r3], 16 // r16 restored (don't touch no more) + ld8 r17 = [r9] // r17 restored (don't touch no more) + nop.i 0 + ;; + + ld8 r18 = [r3] // r18 restored (don't touch no more) + mov.m ar.rsc = r10 // restore original ar.rsc + mov sp = r29 + + mov.m ar.unat = r25 // unat restored (don't touch no more) + mov.i ar.pfs = r14 + br.ret.sptk.many rp + ;; + +/****** Return via sigreturn(): */ + +.next: mov.m ar.rsc = r10 // restore original ar.rsc + add r2 = (SC_FR + 6*16), r8 + add r3 = (SC_FR + 7*16), r8 + ;; + + ldf.fill f6 = [r2], 32 + ldf.fill f7 = [r3], 32 + nop 0 + ;; + + ldf.fill f8 = [r2], 32 + ldf.fill f9 = [r3], 32 + nop 0 + ;; + + ldf.fill f10 = [r2], 32 + ldf.fill f11 = [r3], 32 + nop 0 + ;; + + ldf.fill f12 = [r2], 32 + ldf.fill f13 = [r3], 32 + nop 0 + ;; + + ldf.fill f14 = [r2], 32 + ldf.fill f15 = [r3], 32 + mov sp = r29 + ;; + +#if NEW_SYSCALL + add r2 = 8, tp;; + ld8 r2 = [r2] + mov r15 = SYS_sigreturn + mov b7 = r2 + br.call.sptk.many b6 = b7 + ;; +#else + mov r15 = SYS_sigreturn + break 0x100000 +#endif + break 0 // bug out if sigreturn() returns + + .endp ia64_install_cursor + +#endif /* !UNW_REMOTE_ONLY */ +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gis_signal_frame.c new file mode 100644 index 0000000..e268a06 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gis_signal_frame.c @@ -0,0 +1,54 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_is_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + struct ia64_state_record sr; + int ret; + + /* Crude and slow, but we need to peek ahead into the unwind + descriptors to find out if the current IP is inside the signal + trampoline. */ + ret = ia64_fetch_proc_info (c, c->ip, 1); + if (ret < 0) + return ret; + + ret = ia64_create_state_record (c, &sr); + if (ret < 0) + return ret; + + /* For now, we assume that any non-zero abi marker implies a signal frame. + This should get us pretty far. */ + ret = (sr.abi_marker != 0); + + ia64_free_state_record (&sr); + + Debug (1, "(cursor=%p, ip=0x%016lx) -> %d\n", c, c->ip, ret); + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gparser.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gparser.c new file mode 100644 index 0000000..b1f0f4a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gparser.c @@ -0,0 +1,1131 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +/* forward declaration: */ +static int create_state_record_for (struct cursor *c, + struct ia64_state_record *sr, + unw_word_t ip); + +typedef unsigned long unw_word; + +#define alloc_reg_state() (mempool_alloc (&unw.reg_state_pool)) +#define free_reg_state(rs) (mempool_free (&unw.reg_state_pool, rs)) +#define alloc_labeled_state() (mempool_alloc (&unw.labeled_state_pool)) +#define free_labeled_state(s) (mempool_free (&unw.labeled_state_pool, s)) + +/* Routines to manipulate the state stack. */ + +static inline void +push (struct ia64_state_record *sr) +{ + struct ia64_reg_state *rs; + + rs = alloc_reg_state (); + if (!rs) + { + print_error ("libunwind: cannot stack reg state!\n"); + return; + } + memcpy (rs, &sr->curr, sizeof (*rs)); + sr->curr.next = rs; +} + +static void +pop (struct ia64_state_record *sr) +{ + struct ia64_reg_state *rs = sr->curr.next; + + if (!rs) + { + print_error ("libunwind: stack underflow!\n"); + return; + } + memcpy (&sr->curr, rs, sizeof (*rs)); + free_reg_state (rs); +} + +/* Make a copy of the state stack. Non-recursive to avoid stack overflows. */ +static struct ia64_reg_state * +dup_state_stack (struct ia64_reg_state *rs) +{ + struct ia64_reg_state *copy, *prev = NULL, *first = NULL; + + while (rs) + { + copy = alloc_reg_state (); + if (!copy) + { + print_error ("unwind.dup_state_stack: out of memory\n"); + return NULL; + } + memcpy (copy, rs, sizeof (*copy)); + if (first) + prev->next = copy; + else + first = copy; + rs = rs->next; + prev = copy; + } + return first; +} + +/* Free all stacked register states (but not RS itself). */ +static void +free_state_stack (struct ia64_reg_state *rs) +{ + struct ia64_reg_state *p, *next; + + for (p = rs->next; p != NULL; p = next) + { + next = p->next; + free_reg_state (p); + } + rs->next = NULL; +} + +/* Unwind decoder routines */ + +static enum ia64_pregnum CONST_ATTR +decode_abreg (unsigned char abreg, int memory) +{ + switch (abreg) + { + case 0x04 ... 0x07: + return IA64_REG_R4 + (abreg - 0x04); + case 0x22 ... 0x25: + return IA64_REG_F2 + (abreg - 0x22); + case 0x30 ... 0x3f: + return IA64_REG_F16 + (abreg - 0x30); + case 0x41 ... 0x45: + return IA64_REG_B1 + (abreg - 0x41); + case 0x60: + return IA64_REG_PR; + case 0x61: + return IA64_REG_PSP; + case 0x62: + return memory ? IA64_REG_PRI_UNAT_MEM : IA64_REG_PRI_UNAT_GR; + case 0x63: + return IA64_REG_IP; + case 0x64: + return IA64_REG_BSP; + case 0x65: + return IA64_REG_BSPSTORE; + case 0x66: + return IA64_REG_RNAT; + case 0x67: + return IA64_REG_UNAT; + case 0x68: + return IA64_REG_FPSR; + case 0x69: + return IA64_REG_PFS; + case 0x6a: + return IA64_REG_LC; + default: + break; + } + Dprintf ("libunwind: bad abreg=0x%x\n", abreg); + return IA64_REG_LC; +} + +static void +set_reg (struct ia64_reg_info *reg, enum ia64_where where, int when, + unsigned long val) +{ + reg->val = val; + reg->where = where; + if (reg->when == IA64_WHEN_NEVER) + reg->when = when; +} + +static void +alloc_spill_area (unsigned long *offp, unsigned long regsize, + struct ia64_reg_info *lo, struct ia64_reg_info *hi) +{ + struct ia64_reg_info *reg; + + for (reg = hi; reg >= lo; --reg) + { + if (reg->where == IA64_WHERE_SPILL_HOME) + { + reg->where = IA64_WHERE_PSPREL; + *offp -= regsize; + reg->val = *offp; + } + } +} + +static inline void +spill_next_when (struct ia64_reg_info **regp, struct ia64_reg_info *lim, + unw_word t) +{ + struct ia64_reg_info *reg; + + for (reg = *regp; reg <= lim; ++reg) + { + if (reg->where == IA64_WHERE_SPILL_HOME) + { + reg->when = t; + *regp = reg + 1; + return; + } + } + Dprintf ("libunwind: excess spill!\n"); +} + +static inline void +finish_prologue (struct ia64_state_record *sr) +{ + struct ia64_reg_info *reg; + unsigned long off; + int i; + + /* First, resolve implicit register save locations (see Section + "11.4.2.3 Rules for Using Unwind Descriptors", rule 3). */ + for (i = 0; i < (int) ARRAY_SIZE (unw.save_order); ++i) + { + reg = sr->curr.reg + unw.save_order[i]; + if (reg->where == IA64_WHERE_GR_SAVE) + { + reg->where = IA64_WHERE_GR; + reg->val = sr->gr_save_loc++; + } + } + + /* Next, compute when the fp, general, and branch registers get + saved. This must come before alloc_spill_area() because we need + to know which registers are spilled to their home locations. */ + + if (sr->imask) + { + unsigned char kind, mask = 0, *cp = sr->imask; + unsigned long t; + static const unsigned char limit[3] = + { + IA64_REG_F31, IA64_REG_R7, IA64_REG_B5 + }; + struct ia64_reg_info *(regs[3]); + + regs[0] = sr->curr.reg + IA64_REG_F2; + regs[1] = sr->curr.reg + IA64_REG_R4; + regs[2] = sr->curr.reg + IA64_REG_B1; + + for (t = 0; (int) t < sr->region_len; ++t) + { + if ((t & 3) == 0) + mask = *cp++; + kind = (mask >> 2 * (3 - (t & 3))) & 3; + if (kind > 0) + spill_next_when (®s[kind - 1], sr->curr.reg + limit[kind - 1], + sr->region_start + t); + } + } + + /* Next, lay out the memory stack spill area. */ + + if (sr->any_spills) + { + off = sr->spill_offset; + alloc_spill_area (&off, 16, sr->curr.reg + IA64_REG_F2, + sr->curr.reg + IA64_REG_F31); + alloc_spill_area (&off, 8, sr->curr.reg + IA64_REG_B1, + sr->curr.reg + IA64_REG_B5); + alloc_spill_area (&off, 8, sr->curr.reg + IA64_REG_R4, + sr->curr.reg + IA64_REG_R7); + } +} + +/* Region header descriptors. */ + +static void +desc_prologue (int body, unw_word rlen, unsigned char mask, + unsigned char grsave, struct ia64_state_record *sr) +{ + int i, region_start; + + if (!(sr->in_body || sr->first_region)) + finish_prologue (sr); + sr->first_region = 0; + + /* check if we're done: */ + if (sr->when_target < sr->region_start + sr->region_len) + { + sr->done = 1; + return; + } + + region_start = sr->region_start + sr->region_len; + + for (i = 0; i < sr->epilogue_count; ++i) + pop (sr); + sr->epilogue_count = 0; + sr->when_sp_restored = IA64_WHEN_NEVER; + + sr->region_start = region_start; + sr->region_len = rlen; + sr->in_body = body; + + if (!body) + { + push (sr); + + if (mask) + for (i = 0; i < 4; ++i) + { + if (mask & 0x8) + set_reg (sr->curr.reg + unw.save_order[i], IA64_WHERE_GR, + sr->region_start + sr->region_len - 1, grsave++); + mask <<= 1; + } + sr->gr_save_loc = grsave; + sr->any_spills = 0; + sr->imask = 0; + sr->spill_offset = 0x10; /* default to psp+16 */ + } +} + +/* Prologue descriptors. */ + +static inline void +desc_abi (unsigned char abi, unsigned char context, + struct ia64_state_record *sr) +{ + sr->abi_marker = (abi << 8) | context; +} + +static inline void +desc_br_gr (unsigned char brmask, unsigned char gr, + struct ia64_state_record *sr) +{ + int i; + + for (i = 0; i < 5; ++i) + { + if (brmask & 1) + set_reg (sr->curr.reg + IA64_REG_B1 + i, IA64_WHERE_GR, + sr->region_start + sr->region_len - 1, gr++); + brmask >>= 1; + } +} + +static inline void +desc_br_mem (unsigned char brmask, struct ia64_state_record *sr) +{ + int i; + + for (i = 0; i < 5; ++i) + { + if (brmask & 1) + { + set_reg (sr->curr.reg + IA64_REG_B1 + i, IA64_WHERE_SPILL_HOME, + sr->region_start + sr->region_len - 1, 0); + sr->any_spills = 1; + } + brmask >>= 1; + } +} + +static inline void +desc_frgr_mem (unsigned char grmask, unw_word frmask, + struct ia64_state_record *sr) +{ + int i; + + for (i = 0; i < 4; ++i) + { + if ((grmask & 1) != 0) + { + set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_SPILL_HOME, + sr->region_start + sr->region_len - 1, 0); + sr->any_spills = 1; + } + grmask >>= 1; + } + for (i = 0; i < 20; ++i) + { + if ((frmask & 1) != 0) + { + int base = (i < 4) ? IA64_REG_F2 : IA64_REG_F16 - 4; + set_reg (sr->curr.reg + base + i, IA64_WHERE_SPILL_HOME, + sr->region_start + sr->region_len - 1, 0); + sr->any_spills = 1; + } + frmask >>= 1; + } +} + +static inline void +desc_fr_mem (unsigned char frmask, struct ia64_state_record *sr) +{ + int i; + + for (i = 0; i < 4; ++i) + { + if ((frmask & 1) != 0) + { + set_reg (sr->curr.reg + IA64_REG_F2 + i, IA64_WHERE_SPILL_HOME, + sr->region_start + sr->region_len - 1, 0); + sr->any_spills = 1; + } + frmask >>= 1; + } +} + +static inline void +desc_gr_gr (unsigned char grmask, unsigned char gr, + struct ia64_state_record *sr) +{ + int i; + + for (i = 0; i < 4; ++i) + { + if ((grmask & 1) != 0) + set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_GR, + sr->region_start + sr->region_len - 1, gr++); + grmask >>= 1; + } +} + +static inline void +desc_gr_mem (unsigned char grmask, struct ia64_state_record *sr) +{ + int i; + + for (i = 0; i < 4; ++i) + { + if ((grmask & 1) != 0) + { + set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_SPILL_HOME, + sr->region_start + sr->region_len - 1, 0); + sr->any_spills = 1; + } + grmask >>= 1; + } +} + +static inline void +desc_mem_stack_f (unw_word t, unw_word size, struct ia64_state_record *sr) +{ + set_reg (sr->curr.reg + IA64_REG_PSP, IA64_WHERE_NONE, + sr->region_start + MIN ((int) t, sr->region_len - 1), 16 * size); +} + +static inline void +desc_mem_stack_v (unw_word t, struct ia64_state_record *sr) +{ + sr->curr.reg[IA64_REG_PSP].when = + sr->region_start + MIN ((int) t, sr->region_len - 1); +} + +static inline void +desc_reg_gr (unsigned char reg, unsigned char dst, + struct ia64_state_record *sr) +{ + set_reg (sr->curr.reg + reg, IA64_WHERE_GR, + sr->region_start + sr->region_len - 1, dst); +} + +static inline void +desc_reg_psprel (unsigned char reg, unw_word pspoff, + struct ia64_state_record *sr) +{ + set_reg (sr->curr.reg + reg, IA64_WHERE_PSPREL, + sr->region_start + sr->region_len - 1, 0x10 - 4 * pspoff); +} + +static inline void +desc_reg_sprel (unsigned char reg, unw_word spoff, + struct ia64_state_record *sr) +{ + set_reg (sr->curr.reg + reg, IA64_WHERE_SPREL, + sr->region_start + sr->region_len - 1, 4 * spoff); +} + +static inline void +desc_rp_br (unsigned char dst, struct ia64_state_record *sr) +{ + sr->return_link_reg = dst; +} + +static inline void +desc_reg_when (unsigned char regnum, unw_word t, struct ia64_state_record *sr) +{ + struct ia64_reg_info *reg = sr->curr.reg + regnum; + + if (reg->where == IA64_WHERE_NONE) + reg->where = IA64_WHERE_GR_SAVE; + reg->when = sr->region_start + MIN ((int) t, sr->region_len - 1); +} + +static inline void +desc_spill_base (unw_word pspoff, struct ia64_state_record *sr) +{ + sr->spill_offset = 0x10 - 4 * pspoff; +} + +static inline unsigned char * +desc_spill_mask (unsigned char *imaskp, struct ia64_state_record *sr) +{ + sr->imask = imaskp; + return imaskp + (2 * sr->region_len + 7) / 8; +} + +/* Body descriptors. */ + +static inline void +desc_epilogue (unw_word t, unw_word ecount, struct ia64_state_record *sr) +{ + sr->when_sp_restored = sr->region_start + sr->region_len - 1 - t; + sr->epilogue_count = ecount + 1; +} + +static inline void +desc_copy_state (unw_word label, struct ia64_state_record *sr) +{ + struct ia64_labeled_state *ls; + + for (ls = sr->labeled_states; ls; ls = ls->next) + { + if (ls->label == label) + { + free_state_stack (&sr->curr); + memcpy (&sr->curr, &ls->saved_state, sizeof (sr->curr)); + sr->curr.next = dup_state_stack (ls->saved_state.next); + return; + } + } + print_error ("libunwind: failed to find labeled state\n"); +} + +static inline void +desc_label_state (unw_word label, struct ia64_state_record *sr) +{ + struct ia64_labeled_state *ls; + + ls = alloc_labeled_state (); + if (!ls) + { + print_error ("unwind.desc_label_state(): out of memory\n"); + return; + } + ls->label = label; + memcpy (&ls->saved_state, &sr->curr, sizeof (ls->saved_state)); + ls->saved_state.next = dup_state_stack (sr->curr.next); + + /* insert into list of labeled states: */ + ls->next = sr->labeled_states; + sr->labeled_states = ls; +} + +/* General descriptors. */ + +static inline int +desc_is_active (unsigned char qp, unw_word t, struct ia64_state_record *sr) +{ + if (sr->when_target <= sr->region_start + MIN ((int) t, sr->region_len - 1)) + return 0; + if (qp > 0) + { + if ((sr->pr_val & ((unw_word_t) 1 << qp)) == 0) + return 0; + sr->pr_mask |= ((unw_word_t) 1 << qp); + } + return 1; +} + +static inline void +desc_restore_p (unsigned char qp, unw_word t, unsigned char abreg, + struct ia64_state_record *sr) +{ + struct ia64_reg_info *r; + + if (!desc_is_active (qp, t, sr)) + return; + + r = sr->curr.reg + decode_abreg (abreg, 0); + r->where = IA64_WHERE_NONE; + r->when = IA64_WHEN_NEVER; + r->val = 0; +} + +static inline void +desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg, + unsigned char x, unsigned char ytreg, + struct ia64_state_record *sr) +{ + enum ia64_where where = IA64_WHERE_GR; + struct ia64_reg_info *r; + + if (!desc_is_active (qp, t, sr)) + return; + + if (x) + where = IA64_WHERE_BR; + else if (ytreg & 0x80) + where = IA64_WHERE_FR; + + r = sr->curr.reg + decode_abreg (abreg, 0); + r->where = where; + r->when = sr->region_start + MIN ((int) t, sr->region_len - 1); + r->val = (ytreg & 0x7f); +} + +static inline void +desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg, + unw_word pspoff, struct ia64_state_record *sr) +{ + struct ia64_reg_info *r; + + if (!desc_is_active (qp, t, sr)) + return; + + r = sr->curr.reg + decode_abreg (abreg, 1); + r->where = IA64_WHERE_PSPREL; + r->when = sr->region_start + MIN ((int) t, sr->region_len - 1); + r->val = 0x10 - 4 * pspoff; +} + +static inline void +desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, + unw_word spoff, struct ia64_state_record *sr) +{ + struct ia64_reg_info *r; + + if (!desc_is_active (qp, t, sr)) + return; + + r = sr->curr.reg + decode_abreg (abreg, 1); + r->where = IA64_WHERE_SPREL; + r->when = sr->region_start + MIN ((int) t, sr->region_len - 1); + r->val = 4 * spoff; +} + +#define UNW_DEC_BAD_CODE(code) \ + print_error ("libunwind: unknown code encountered\n") + +/* Register names. */ +#define UNW_REG_BSP IA64_REG_BSP +#define UNW_REG_BSPSTORE IA64_REG_BSPSTORE +#define UNW_REG_FPSR IA64_REG_FPSR +#define UNW_REG_LC IA64_REG_LC +#define UNW_REG_PFS IA64_REG_PFS +#define UNW_REG_PR IA64_REG_PR +#define UNW_REG_RNAT IA64_REG_RNAT +#define UNW_REG_PSP IA64_REG_PSP +#define UNW_REG_RP IA64_REG_IP +#define UNW_REG_UNAT IA64_REG_UNAT + +/* Region headers. */ +#define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg) desc_prologue(0,r,m,gr,arg) +#define UNW_DEC_PROLOGUE(fmt,b,r,arg) desc_prologue(b,r,0,32,arg) + +/* Prologue descriptors. */ +#define UNW_DEC_ABI(fmt,a,c,arg) desc_abi(a,c,arg) +#define UNW_DEC_BR_GR(fmt,b,g,arg) desc_br_gr(b,g,arg) +#define UNW_DEC_BR_MEM(fmt,b,arg) desc_br_mem(b,arg) +#define UNW_DEC_FRGR_MEM(fmt,g,f,arg) desc_frgr_mem(g,f,arg) +#define UNW_DEC_FR_MEM(fmt,f,arg) desc_fr_mem(f,arg) +#define UNW_DEC_GR_GR(fmt,m,g,arg) desc_gr_gr(m,g,arg) +#define UNW_DEC_GR_MEM(fmt,m,arg) desc_gr_mem(m,arg) +#define UNW_DEC_MEM_STACK_F(fmt,t,s,arg) desc_mem_stack_f(t,s,arg) +#define UNW_DEC_MEM_STACK_V(fmt,t,arg) desc_mem_stack_v(t,arg) +#define UNW_DEC_REG_GR(fmt,r,d,arg) desc_reg_gr(r,d,arg) +#define UNW_DEC_REG_PSPREL(fmt,r,o,arg) desc_reg_psprel(r,o,arg) +#define UNW_DEC_REG_SPREL(fmt,r,o,arg) desc_reg_sprel(r,o,arg) +#define UNW_DEC_REG_WHEN(fmt,r,t,arg) desc_reg_when(r,t,arg) +#define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) \ + desc_reg_when(IA64_REG_PRI_UNAT_GR,t,arg) +#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) \ + desc_reg_when(IA64_REG_PRI_UNAT_MEM,t,arg) +#define UNW_DEC_PRIUNAT_GR(fmt,r,arg) \ + desc_reg_gr(IA64_REG_PRI_UNAT_GR,r,arg) +#define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg) \ + desc_reg_psprel(IA64_REG_PRI_UNAT_MEM,o,arg) +#define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg) \ + desc_reg_sprel(IA64_REG_PRI_UNAT_MEM,o,arg) +#define UNW_DEC_RP_BR(fmt,d,arg) desc_rp_br(d,arg) +#define UNW_DEC_SPILL_BASE(fmt,o,arg) desc_spill_base(o,arg) +#define UNW_DEC_SPILL_MASK(fmt,m,arg) (m = desc_spill_mask(m,arg)) + +/* Body descriptors. */ +#define UNW_DEC_EPILOGUE(fmt,t,c,arg) desc_epilogue(t,c,arg) +#define UNW_DEC_COPY_STATE(fmt,l,arg) desc_copy_state(l,arg) +#define UNW_DEC_LABEL_STATE(fmt,l,arg) desc_label_state(l,arg) + +/* General unwind descriptors. */ +#define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg) desc_spill_reg_p(p,t,a,x,y,arg) +#define UNW_DEC_SPILL_REG(f,t,a,x,y,arg) desc_spill_reg_p(0,t,a,x,y,arg) +#define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg) \ + desc_spill_psprel_p(p,t,a,o,arg) +#define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg) \ + desc_spill_psprel_p(0,t,a,o,arg) +#define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg) desc_spill_sprel_p(p,t,a,o,arg) +#define UNW_DEC_SPILL_SPREL(f,t,a,o,arg) desc_spill_sprel_p(0,t,a,o,arg) +#define UNW_DEC_RESTORE_P(f,p,t,a,arg) desc_restore_p(p,t,a,arg) +#define UNW_DEC_RESTORE(f,t,a,arg) desc_restore_p(0,t,a,arg) + +#include "unwind_decoder.h" + +#ifdef _U_dyn_op + +/* parse dynamic unwind info */ + +static struct ia64_reg_info * +lookup_preg (int regnum, int memory, struct ia64_state_record *sr) +{ + int preg; + + switch (regnum) + { + case UNW_IA64_AR_BSP: preg = IA64_REG_BSP; break; + case UNW_IA64_AR_BSPSTORE: preg = IA64_REG_BSPSTORE; break; + case UNW_IA64_AR_FPSR: preg = IA64_REG_FPSR; break; + case UNW_IA64_AR_LC: preg = IA64_REG_LC; break; + case UNW_IA64_AR_PFS: preg = IA64_REG_PFS; break; + case UNW_IA64_AR_RNAT: preg = IA64_REG_RNAT; break; + case UNW_IA64_AR_UNAT: preg = IA64_REG_UNAT; break; + case UNW_IA64_BR + 0: preg = IA64_REG_IP; break; + case UNW_IA64_PR: preg = IA64_REG_PR; break; + case UNW_IA64_SP: preg = IA64_REG_PSP; break; + + case UNW_IA64_NAT: + if (memory) + preg = IA64_REG_PRI_UNAT_MEM; + else + preg = IA64_REG_PRI_UNAT_GR; + break; + + case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7: + preg = IA64_REG_R4 + (regnum - (UNW_IA64_GR + 4)); + break; + + case UNW_IA64_BR + 1 ... UNW_IA64_BR + 5: + preg = IA64_REG_B1 + (regnum - UNW_IA64_BR); + break; + + case UNW_IA64_FR + 2 ... UNW_IA64_FR + 5: + preg = IA64_REG_F2 + (regnum - (UNW_IA64_FR + 2)); + break; + + case UNW_IA64_FR + 16 ... UNW_IA64_FR + 31: + preg = IA64_REG_F16 + (regnum - (UNW_IA64_FR + 16)); + break; + + default: + Dprintf ("%s: invalid register number %d\n", __FUNCTION__, regnum); + return NULL; + } + return sr->curr.reg + preg; +} + +/* An alias directive inside a region of length RLEN is interpreted to + mean that the region behaves exactly like the first RLEN + instructions at the aliased IP. RLEN=0 implies that the current + state matches exactly that of before the instruction at the aliased + IP is executed. */ + +static int +desc_alias (unw_dyn_op_t *op, struct cursor *c, struct ia64_state_record *sr) +{ + struct ia64_state_record orig_sr = *sr; + int i, ret, when, rlen = sr->region_len; + unw_word_t new_ip; + + when = MIN (sr->when_target, rlen); + new_ip = op->val + ((when / 3) * 16 + (when % 3)); + + if ((ret = ia64_fetch_proc_info (c, new_ip, 1)) < 0) + return ret; + + if ((ret = create_state_record_for (c, sr, new_ip)) < 0) + return ret; + + sr->first_region = orig_sr.first_region; + sr->done = 0; + sr->any_spills |= orig_sr.any_spills; + sr->in_body = orig_sr.in_body; + sr->region_start = orig_sr.region_start; + sr->region_len = orig_sr.region_len; + if (sr->when_sp_restored != IA64_WHEN_NEVER) + sr->when_sp_restored = op->when + MIN (orig_sr.when_sp_restored, rlen); + sr->epilogue_count = orig_sr.epilogue_count; + sr->when_target = orig_sr.when_target; + + for (i = 0; i < IA64_NUM_PREGS; ++i) + if (sr->curr.reg[i].when != IA64_WHEN_NEVER) + sr->curr.reg[i].when = op->when + MIN (sr->curr.reg[i].when, rlen); + + ia64_free_state_record (sr); + sr->labeled_states = orig_sr.labeled_states; + sr->curr.next = orig_sr.curr.next; + return 0; +} + +static inline int +parse_dynamic (struct cursor *c, struct ia64_state_record *sr) +{ + unw_dyn_info_t *di = c->pi.unwind_info; + unw_dyn_proc_info_t *proc = &di->u.pi; + unw_dyn_region_info_t *r; + struct ia64_reg_info *ri; + enum ia64_where where; + int32_t when, len; + unw_dyn_op_t *op; + unw_word_t val; + int memory, ret; + int8_t qp; + + for (r = proc->regions; r; r = r->next) + { + len = r->insn_count; + if (len < 0) + { + if (r->next) + { + Debug (1, "negative region length allowed in last region only!"); + return -UNW_EINVAL; + } + len = -len; + /* hack old region info to set the start where we need it: */ + sr->region_start = (di->end_ip - di->start_ip) / 0x10 * 3 - len; + sr->region_len = 0; + } + /* all regions are treated as prologue regions: */ + desc_prologue (0, len, 0, 0, sr); + + if (sr->done) + return 0; + + for (op = r->op; op < r->op + r->op_count; ++op) + { + when = op->when; + val = op->val; + qp = op->qp; + + if (!desc_is_active (qp, when, sr)) + continue; + + when = sr->region_start + MIN ((int) when, sr->region_len - 1); + + switch (op->tag) + { + case UNW_DYN_SAVE_REG: + memory = 0; + if ((unsigned) (val - UNW_IA64_GR) < 128) + where = IA64_WHERE_GR; + else if ((unsigned) (val - UNW_IA64_FR) < 128) + where = IA64_WHERE_FR; + else if ((unsigned) (val - UNW_IA64_BR) < 8) + where = IA64_WHERE_BR; + else + { + Dprintf ("%s: can't save to register number %d\n", + __FUNCTION__, (int) op->reg); + return -UNW_EBADREG; + } + /* fall through */ + update_reg_info: + ri = lookup_preg (op->reg, memory, sr); + if (!ri) + return -UNW_EBADREG; + ri->where = where; + ri->when = when; + ri->val = val; + break; + + case UNW_DYN_SPILL_FP_REL: + memory = 1; + where = IA64_WHERE_PSPREL; + val = 0x10 - val; + goto update_reg_info; + + case UNW_DYN_SPILL_SP_REL: + memory = 1; + where = IA64_WHERE_SPREL; + goto update_reg_info; + + case UNW_DYN_ADD: + if (op->reg == UNW_IA64_SP) + { + if (val & 0xf) + { + Dprintf ("%s: frame-size %ld not an integer " + "multiple of 16\n", + __FUNCTION__, (long) op->val); + return -UNW_EINVAL; + } + desc_mem_stack_f (when, -((int64_t) val / 16), sr); + } + else + { + Dprintf ("%s: can only ADD to stack-pointer\n", + __FUNCTION__); + return -UNW_EBADREG; + } + break; + + case UNW_DYN_POP_FRAMES: + sr->when_sp_restored = when; + sr->epilogue_count = op->val; + break; + + case UNW_DYN_LABEL_STATE: + desc_label_state (op->val, sr); + break; + + case UNW_DYN_COPY_STATE: + desc_copy_state (op->val, sr); + break; + + case UNW_DYN_ALIAS: + if ((ret = desc_alias (op, c, sr)) < 0) + return ret; + + case UNW_DYN_STOP: + goto end_of_ops; + } + } + end_of_ops: + ; + } + return 0; +} +#else +# define parse_dynamic(c,sr) (-UNW_EINVAL) +#endif /* _U_dyn_op */ + + +HIDDEN int +ia64_fetch_proc_info (struct cursor *c, unw_word_t ip, int need_unwind_info) +{ + int ret, dynamic = 1; + + if (c->pi_valid && !need_unwind_info) + return 0; + + /* check dynamic info first --- it overrides everything else */ + ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, need_unwind_info, + c->as_arg); + if (ret == -UNW_ENOINFO) + { + dynamic = 0; + ret = ia64_find_proc_info (c, ip, need_unwind_info); + } + + c->pi_valid = 1; + c->pi_is_dynamic = dynamic; + return ret; +} + +static inline void +put_unwind_info (struct cursor *c, unw_proc_info_t *pi) +{ + if (!c->pi_valid) + return; + + if (c->pi_is_dynamic) + unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg); + else + ia64_put_unwind_info (c, pi); +} + +static int +create_state_record_for (struct cursor *c, struct ia64_state_record *sr, + unw_word_t ip) +{ + unw_word_t predicates = c->pr; + struct ia64_reg_info *r; + uint8_t *dp, *desc_end; + int ret; + + assert (c->pi_valid); + + /* build state record */ + memset (sr, 0, sizeof (*sr)); + for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r) + r->when = IA64_WHEN_NEVER; + sr->pr_val = predicates; + sr->first_region = 1; + + if (!c->pi.unwind_info) + { + /* No info, return default unwinder (leaf proc, no mem stack, no + saved regs), rp in b0, pfs in ar.pfs. */ + Debug (1, "no unwind info for ip=0x%lx (gp=%lx)\n", + (long) ip, (long) c->pi.gp); + sr->curr.reg[IA64_REG_IP].where = IA64_WHERE_BR; + sr->curr.reg[IA64_REG_IP].when = -1; + sr->curr.reg[IA64_REG_IP].val = 0; + goto out; + } + + sr->when_target = (3 * ((ip & ~(unw_word_t) 0xf) - c->pi.start_ip) / 16 + + (ip & 0xf)); + + switch (c->pi.format) + { + case UNW_INFO_FORMAT_TABLE: + case UNW_INFO_FORMAT_REMOTE_TABLE: + dp = c->pi.unwind_info; + desc_end = dp + c->pi.unwind_info_size; + while (!sr->done && dp < desc_end) + dp = unw_decode (dp, sr->in_body, sr); + ret = 0; + break; + + case UNW_INFO_FORMAT_DYNAMIC: + ret = parse_dynamic (c, sr); + break; + + default: + ret = -UNW_EINVAL; + } + + put_unwind_info (c, &c->pi); + + if (ret < 0) + return ret; + + if (sr->when_target > sr->when_sp_restored) + { + /* sp has been restored and all values on the memory stack below + psp also have been restored. */ + sr->curr.reg[IA64_REG_PSP].val = 0; + sr->curr.reg[IA64_REG_PSP].where = IA64_WHERE_NONE; + sr->curr.reg[IA64_REG_PSP].when = IA64_WHEN_NEVER; + for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r) + if ((r->where == IA64_WHERE_PSPREL && r->val <= 0x10) + || r->where == IA64_WHERE_SPREL) + { + r->val = 0; + r->where = IA64_WHERE_NONE; + r->when = IA64_WHEN_NEVER; + } + } + + /* If RP did't get saved, generate entry for the return link + register. */ + if (sr->curr.reg[IA64_REG_IP].when >= sr->when_target) + { + sr->curr.reg[IA64_REG_IP].where = IA64_WHERE_BR; + sr->curr.reg[IA64_REG_IP].when = -1; + sr->curr.reg[IA64_REG_IP].val = sr->return_link_reg; + } + + if (sr->when_target > sr->curr.reg[IA64_REG_BSP].when + && sr->when_target > sr->curr.reg[IA64_REG_BSPSTORE].when + && sr->when_target > sr->curr.reg[IA64_REG_RNAT].when) + { + Debug (8, "func 0x%lx may switch the register-backing-store\n", + c->pi.start_ip); + c->pi.flags |= UNW_PI_FLAG_IA64_RBS_SWITCH; + } + out: +#if UNW_DEBUG + if (unwi_debug_level > 2) + { + Dprintf ("%s: state record for func 0x%lx, t=%u (flags=0x%lx):\n", + __FUNCTION__, + (long) c->pi.start_ip, sr->when_target, (long) c->pi.flags); + for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r) + { + if (r->where != IA64_WHERE_NONE || r->when != IA64_WHEN_NEVER) + { + Dprintf (" %s <- ", unw.preg_name[r - sr->curr.reg]); + switch (r->where) + { + case IA64_WHERE_GR: + Dprintf ("r%lu", (long) r->val); + break; + case IA64_WHERE_FR: + Dprintf ("f%lu", (long) r->val); + break; + case IA64_WHERE_BR: + Dprintf ("b%lu", (long) r->val); + break; + case IA64_WHERE_SPREL: + Dprintf ("[sp+0x%lx]", (long) r->val); + break; + case IA64_WHERE_PSPREL: + Dprintf ("[psp+0x%lx]", (long) r->val); + break; + case IA64_WHERE_NONE: + Dprintf ("%s+0x%lx", + unw.preg_name[r - sr->curr.reg], (long) r->val); + break; + default: + Dprintf ("BADWHERE(%d)", r->where); + break; + } + Dprintf ("\t\t%d\n", r->when); + } + } + } +#endif + return 0; +} + +/* The proc-info must be valid for IP before this routine can be + called. */ +HIDDEN int +ia64_create_state_record (struct cursor *c, struct ia64_state_record *sr) +{ + return create_state_record_for (c, sr, c->ip); +} + +HIDDEN int +ia64_free_state_record (struct ia64_state_record *sr) +{ + struct ia64_labeled_state *ls, *next; + + /* free labeled register states & stack: */ + + for (ls = sr->labeled_states; ls; ls = next) + { + next = ls->next; + free_state_stack (&ls->saved_state); + free_labeled_state (ls); + } + free_state_stack (&sr->curr); + + return 0; +} + +HIDDEN int +ia64_make_proc_info (struct cursor *c) +{ + int ret, caching = c->as->caching_policy != UNW_CACHE_NONE; + + if (!caching || ia64_get_cached_proc_info (c) < 0) + { + /* Lookup it up the slow way... */ + if ((ret = ia64_fetch_proc_info (c, c->ip, 0)) < 0) + return ret; + if (caching) + ia64_cache_proc_info (c); + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Grbs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Grbs.c new file mode 100644 index 0000000..e7c01fe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Grbs.c @@ -0,0 +1,319 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Logically, we like to think of the stack as a contiguous region of +memory. Unfortunately, this logical view doesn't work for the +register backing store, because the RSE is an asynchronous engine and +because UNIX/Linux allow for stack-switching via sigaltstack(2). +Specifically, this means that any given stacked register may or may +not be backed up by memory in the current stack. If not, then the +backing memory may be found in any of the "more inner" (younger) +stacks. The routines in this file help manage the discontiguous +nature of the register backing store. The routines are completely +independent of UNIX/Linux, but each stack frame that switches the +backing store is expected to reserve 4 words for use by libunwind. For +example, in the Linux sigcontext, sc_fr[0] and sc_fr[1] serve this +purpose. */ + +#include "unwind_i.h" + +#if UNW_DEBUG + +HIDDEN const char * +ia64_strloc (ia64_loc_t loc) +{ + static char buf[128]; + + if (IA64_IS_NULL_LOC (loc)) + return ""; + + buf[0] = '\0'; + + if (IA64_IS_MEMSTK_NAT (loc)) + strcat (buf, "memstk_nat("); + if (IA64_IS_UC_LOC (loc)) + strcat (buf, "uc("); + if (IA64_IS_FP_LOC (loc)) + strcat (buf, "fp("); + + if (IA64_IS_REG_LOC (loc)) + sprintf (buf + strlen (buf), "%s", unw_regname (IA64_GET_REG (loc))); + else + sprintf (buf + strlen (buf), "0x%llx", + (unsigned long long) IA64_GET_ADDR (loc)); + + if (IA64_IS_FP_LOC (loc)) + strcat (buf, ")"); + if (IA64_IS_UC_LOC (loc)) + strcat (buf, ")"); + if (IA64_IS_MEMSTK_NAT (loc)) + strcat (buf, ")"); + + return buf; +} + +#endif /* UNW_DEBUG */ + +HIDDEN int +rbs_switch (struct cursor *c, + unw_word_t saved_bsp, unw_word_t saved_bspstore, + ia64_loc_t saved_rnat_loc) +{ + struct rbs_area *rbs = &c->rbs_area[c->rbs_curr]; + unw_word_t lo, ndirty, rbs_base; + int ret; + + Debug (10, "(left=%u, curr=%u)\n", c->rbs_left_edge, c->rbs_curr); + + /* Calculate address "lo" at which the backing store starts: */ + ndirty = rse_num_regs (saved_bspstore, saved_bsp); + lo = rse_skip_regs (c->bsp, -ndirty); + + rbs->size = (rbs->end - lo); + + /* If the previously-recorded rbs-area is empty we don't need to + track it and we can simply overwrite it... */ + if (rbs->size) + { + Debug (10, "inner=[0x%lx-0x%lx)\n", + (long) (rbs->end - rbs->size), (long) rbs->end); + + c->rbs_curr = (c->rbs_curr + 1) % ARRAY_SIZE (c->rbs_area); + rbs = c->rbs_area + c->rbs_curr; + + if (c->rbs_curr == c->rbs_left_edge) + c->rbs_left_edge = (c->rbs_left_edge + 1) % ARRAY_SIZE (c->rbs_area); + } + + if ((ret = rbs_get_base (c, saved_bspstore, &rbs_base)) < 0) + return ret; + + rbs->end = saved_bspstore; + rbs->size = saved_bspstore - rbs_base; + rbs->rnat_loc = saved_rnat_loc; + + c->bsp = saved_bsp; + + Debug (10, "outer=[0x%llx-0x%llx), rnat@%s\n", (long long) rbs_base, + (long long) rbs->end, ia64_strloc (rbs->rnat_loc)); + return 0; +} + +HIDDEN int +rbs_find_stacked (struct cursor *c, unw_word_t regs_to_skip, + ia64_loc_t *locp, ia64_loc_t *rnat_locp) +{ + unw_word_t nregs, bsp = c->bsp, curr = c->rbs_curr, n; + unw_word_t left_edge = c->rbs_left_edge; +#if UNW_DEBUG + int reg = 32 + regs_to_skip; +#endif + + while (!rbs_contains (&c->rbs_area[curr], bsp)) + { + if (curr == left_edge) + { + Debug (1, "could not find register r%d!\n", reg); + return -UNW_EBADREG; + } + + n = rse_num_regs (c->rbs_area[curr].end, bsp); + curr = (curr + ARRAY_SIZE (c->rbs_area) - 1) % ARRAY_SIZE (c->rbs_area); + bsp = rse_skip_regs (c->rbs_area[curr].end - c->rbs_area[curr].size, n); + } + + while (1) + { + nregs = rse_num_regs (bsp, c->rbs_area[curr].end); + + if (regs_to_skip < nregs) + { + /* found it: */ + unw_word_t addr; + + addr = rse_skip_regs (bsp, regs_to_skip); + if (locp) + *locp = rbs_loc (c->rbs_area + curr, addr); + if (rnat_locp) + *rnat_locp = rbs_get_rnat_loc (c->rbs_area + curr, addr); + return 0; + } + + if (curr == left_edge) + { + Debug (1, "could not find register r%d!\n", reg); + return -UNW_EBADREG; + } + + regs_to_skip -= nregs; + + curr = (curr + ARRAY_SIZE (c->rbs_area) - 1) % ARRAY_SIZE (c->rbs_area); + bsp = c->rbs_area[curr].end - c->rbs_area[curr].size; + } +} + +#ifdef NEED_RBS_COVER_AND_FLUSH + +static inline int +get_rnat (struct cursor *c, struct rbs_area *rbs, unw_word_t bsp, + unw_word_t *__restrict rnatp) +{ + ia64_loc_t rnat_locp = rbs_get_rnat_loc (rbs, bsp); + + return ia64_get (c, rnat_locp, rnatp); +} + +/* Simulate the effect of "cover" followed by a "flushrs" for the + target-frame. However, since the target-frame's backing store + may not have space for the registers that got spilled onto other + rbs-areas, we save those registers to DIRTY_PARTITION where + we can then load them via a single "loadrs". + + This function returns the size of the dirty-partition that was + created or a negative error-code in case of error. + + Note: This does not modify the rbs_area[] structure in any way. */ +HIDDEN int +rbs_cover_and_flush (struct cursor *c, unw_word_t nregs, + unw_word_t *dirty_partition, unw_word_t *dirty_rnat, + unw_word_t *bspstore) +{ + unw_word_t n, src_mask, dst_mask, bsp, *dst, src_rnat, dst_rnat = 0; + unw_word_t curr = c->rbs_curr, left_edge = c->rbs_left_edge; + struct rbs_area *rbs = c->rbs_area + curr; + int ret; + + bsp = c->bsp; + c->bsp = rse_skip_regs (bsp, nregs); + + if (likely (rbs_contains (rbs, bsp))) + { + /* at least _some_ registers are on rbs... */ + n = rse_num_regs (bsp, rbs->end); + if (likely (n >= nregs)) + { + /* common case #1: all registers are on current rbs... */ + /* got lucky: _all_ registers are on rbs... */ + ia64_loc_t rnat_loc = rbs_get_rnat_loc (rbs, c->bsp); + + *bspstore = c->bsp; + + if (IA64_IS_REG_LOC (rnat_loc)) + { + unw_word_t rnat_addr = (unw_word_t) + tdep_uc_addr (c->as_arg, UNW_IA64_AR_RNAT, NULL); + rnat_loc = IA64_LOC_ADDR (rnat_addr, 0); + } + c->loc[IA64_REG_RNAT] = rnat_loc; + return 0; /* all done */ + } + nregs -= n; /* account for registers already on the rbs */ + + assert (rse_skip_regs (c->bsp, -nregs) == rse_skip_regs (rbs->end, 0)); + } + else + /* Earlier frames also didn't get spilled; need to "loadrs" those, + too... */ + nregs += rse_num_regs (rbs->end, bsp); + + /* OK, we need to copy NREGS registers to the dirty partition. */ + + *bspstore = bsp = rbs->end; + c->loc[IA64_REG_RNAT] = rbs->rnat_loc; + assert (!IA64_IS_REG_LOC (rbs->rnat_loc)); + + dst = dirty_partition; + + while (nregs > 0) + { + if (unlikely (!rbs_contains (rbs, bsp))) + { + /* switch to next non-empty rbs-area: */ + do + { + if (curr == left_edge) + { + Debug (0, "rbs-underflow while flushing %lu regs, " + "bsp=0x%lx, dst=0x%p\n", (unsigned long) nregs, + (unsigned long) bsp, dst); + return -UNW_EBADREG; + } + + assert (rse_num_regs (rbs->end, bsp) == 0); + + curr = (curr + ARRAY_SIZE (c->rbs_area) - 1) + % ARRAY_SIZE (c->rbs_area); + rbs = c->rbs_area + curr; + bsp = rbs->end - rbs->size; + } + while (rbs->size == 0); + + if ((ret = get_rnat (c, rbs, bsp, &src_rnat)) < 0) + return ret; + } + + if (unlikely (rse_is_rnat_slot (bsp))) + { + bsp += 8; + if ((ret = get_rnat (c, rbs, bsp, &src_rnat)) < 0) + return ret; + } + if (unlikely (rse_is_rnat_slot ((unw_word_t) dst))) + { + *dst++ = dst_rnat; + dst_rnat = 0; + } + + src_mask = ((unw_word_t) 1) << rse_slot_num (bsp); + dst_mask = ((unw_word_t) 1) << rse_slot_num ((unw_word_t) dst); + + if (src_rnat & src_mask) + dst_rnat |= dst_mask; + else + dst_rnat &= ~dst_mask; + + /* copy one slot: */ + if ((ret = ia64_get (c, rbs_loc (rbs, bsp), dst)) < 0) + return ret; + + /* advance to next slot: */ + --nregs; + bsp += 8; + ++dst; + } + if (unlikely (rse_is_rnat_slot ((unw_word_t) dst))) + { + /* The LOADRS instruction loads "the N bytes below the current + BSP" but BSP can never point to an RNaT slot so if the last + destination word happens to be an RNaT slot, we need to write + that slot now. */ + *dst++ = dst_rnat; + dst_rnat = 0; + } + *dirty_rnat = dst_rnat; + return (char *) dst - (char *) dirty_partition; +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Greg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Greg_states_iterate.c new file mode 100644 index 0000000..3570740 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Greg_states_iterate.c @@ -0,0 +1,39 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_reg_states_iterate (unw_cursor_t *cursor, + unw_reg_states_callback cb, void *token) +{ + struct cursor *c = (struct cursor *) cursor; + + // Needs dwarf support on ia64 + // return dwarf_reg_states_iterate (&c->dwarf, cb, token); + return -UNW_EINVAL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gregs.c new file mode 100644 index 0000000..ac6f738 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gregs.c @@ -0,0 +1,612 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "offsets.h" +#include "regs.h" +#include "unwind_i.h" + +static inline ia64_loc_t +linux_scratch_loc (struct cursor *c, unw_regnum_t reg, uint8_t *nat_bitnr) +{ +#if !defined(UNW_LOCAL_ONLY) || defined(__linux) + unw_word_t addr = c->sigcontext_addr, flags, tmp_addr; + int i; + + if (ia64_get_abi_marker (c) == ABI_MARKER_LINUX_SIGTRAMP + || ia64_get_abi_marker (c) == ABI_MARKER_OLD_LINUX_SIGTRAMP) + { + switch (reg) + { + case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3: + case UNW_IA64_NAT + 8 ... UNW_IA64_NAT + 31: + /* Linux sigcontext contains the NaT bit of scratch register + N in bit position N of the sc_nat member. */ + *nat_bitnr = (reg - UNW_IA64_NAT); + addr += LINUX_SC_NAT_OFF; + break; + + case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3: + case UNW_IA64_GR + 8 ... UNW_IA64_GR + 31: + addr += LINUX_SC_GR_OFF + 8 * (reg - UNW_IA64_GR); + break; + + case UNW_IA64_FR + 6 ... UNW_IA64_FR + 15: + addr += LINUX_SC_FR_OFF + 16 * (reg - UNW_IA64_FR); + return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP); + + case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127: + if (ia64_get (c, IA64_LOC_ADDR (addr + LINUX_SC_FLAGS_OFF, 0), + &flags) < 0) + return IA64_NULL_LOC; + + if (!(flags & IA64_SC_FLAG_FPH_VALID)) + { + /* initialize fph partition: */ + tmp_addr = addr + LINUX_SC_FR_OFF + 32*16; + for (i = 32; i < 128; ++i, tmp_addr += 16) + if (ia64_putfp (c, IA64_LOC_ADDR (tmp_addr, 0), + unw.read_only.f0) < 0) + return IA64_NULL_LOC; + /* mark fph partition as valid: */ + if (ia64_put (c, IA64_LOC_ADDR (addr + LINUX_SC_FLAGS_OFF, 0), + flags | IA64_SC_FLAG_FPH_VALID) < 0) + return IA64_NULL_LOC; + } + + addr += LINUX_SC_FR_OFF + 16 * (reg - UNW_IA64_FR); + return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP); + + case UNW_IA64_BR + 0: addr += LINUX_SC_BR_OFF + 0; break; + case UNW_IA64_BR + 6: addr += LINUX_SC_BR_OFF + 6*8; break; + case UNW_IA64_BR + 7: addr += LINUX_SC_BR_OFF + 7*8; break; + case UNW_IA64_AR_RSC: addr += LINUX_SC_AR_RSC_OFF; break; + case UNW_IA64_AR_CSD: addr += LINUX_SC_AR_CSD_OFF; break; + case UNW_IA64_AR_SSD: addr += LINUX_SC_AR_SSD_OFF; break; + case UNW_IA64_AR_CCV: addr += LINUX_SC_AR_CCV; break; + + default: + if (unw_is_fpreg (reg)) + return IA64_FPREG_LOC (c, reg); + else + return IA64_REG_LOC (c, reg); + } + return IA64_LOC_ADDR (addr, 0); + } + else + { + int is_nat = 0; + + if ((unsigned) (reg - UNW_IA64_NAT) < 128) + { + is_nat = 1; + reg -= (UNW_IA64_NAT - UNW_IA64_GR); + } + if (ia64_get_abi_marker (c) == ABI_MARKER_LINUX_INTERRUPT) + { + switch (reg) + { + case UNW_IA64_BR + 6 ... UNW_IA64_BR + 7: + addr += LINUX_PT_B6_OFF + 8 * (reg - (UNW_IA64_BR + 6)); + break; + + case UNW_IA64_AR_CSD: addr += LINUX_PT_CSD_OFF; break; + case UNW_IA64_AR_SSD: addr += LINUX_PT_SSD_OFF; break; + + case UNW_IA64_GR + 8 ... UNW_IA64_GR + 11: + addr += LINUX_PT_R8_OFF + 8 * (reg - (UNW_IA64_GR + 8)); + break; + + case UNW_IA64_IP: addr += LINUX_PT_IIP_OFF; break; + case UNW_IA64_CFM: addr += LINUX_PT_IFS_OFF; break; + case UNW_IA64_AR_UNAT: addr += LINUX_PT_UNAT_OFF; break; + case UNW_IA64_AR_PFS: addr += LINUX_PT_PFS_OFF; break; + case UNW_IA64_AR_RSC: addr += LINUX_PT_RSC_OFF; break; + case UNW_IA64_AR_RNAT: addr += LINUX_PT_RNAT_OFF; break; + case UNW_IA64_AR_BSPSTORE: addr += LINUX_PT_BSPSTORE_OFF; break; + case UNW_IA64_PR: addr += LINUX_PT_PR_OFF; break; + case UNW_IA64_BR + 0: addr += LINUX_PT_B0_OFF; break; + + case UNW_IA64_GR + 1: + /* The saved r1 value is valid only in the frame in which + it was saved; for everything else we need to look up + the appropriate gp value. */ + if (c->sigcontext_addr != c->sp + 0x10) + return IA64_NULL_LOC; + addr += LINUX_PT_R1_OFF; + break; + + case UNW_IA64_GR + 12: addr += LINUX_PT_R12_OFF; break; + case UNW_IA64_GR + 13: addr += LINUX_PT_R13_OFF; break; + case UNW_IA64_AR_FPSR: addr += LINUX_PT_FPSR_OFF; break; + case UNW_IA64_GR + 15: addr += LINUX_PT_R15_OFF; break; + case UNW_IA64_GR + 14: addr += LINUX_PT_R14_OFF; break; + case UNW_IA64_GR + 2: addr += LINUX_PT_R2_OFF; break; + case UNW_IA64_GR + 3: addr += LINUX_PT_R3_OFF; break; + + case UNW_IA64_GR + 16 ... UNW_IA64_GR + 31: + addr += LINUX_PT_R16_OFF + 8 * (reg - (UNW_IA64_GR + 16)); + break; + + case UNW_IA64_AR_CCV: addr += LINUX_PT_CCV_OFF; break; + + case UNW_IA64_FR + 6 ... UNW_IA64_FR + 11: + addr += LINUX_PT_F6_OFF + 16 * (reg - (UNW_IA64_FR + 6)); + return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP); + + default: + if (unw_is_fpreg (reg)) + return IA64_FPREG_LOC (c, reg); + else + return IA64_REG_LOC (c, reg); + } + } + else if (ia64_get_abi_marker (c) == ABI_MARKER_OLD_LINUX_INTERRUPT) + { + switch (reg) + { + case UNW_IA64_GR + 1: + /* The saved r1 value is valid only in the frame in which + it was saved; for everything else we need to look up + the appropriate gp value. */ + if (c->sigcontext_addr != c->sp + 0x10) + return IA64_NULL_LOC; + addr += LINUX_OLD_PT_R1_OFF; + break; + + case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3: + addr += LINUX_OLD_PT_R2_OFF + 8 * (reg - (UNW_IA64_GR + 2)); + break; + + case UNW_IA64_GR + 8 ... UNW_IA64_GR + 11: + addr += LINUX_OLD_PT_R8_OFF + 8 * (reg - (UNW_IA64_GR + 8)); + break; + + case UNW_IA64_GR + 16 ... UNW_IA64_GR + 31: + addr += LINUX_OLD_PT_R16_OFF + 8 * (reg - (UNW_IA64_GR + 16)); + break; + + case UNW_IA64_FR + 6 ... UNW_IA64_FR + 9: + addr += LINUX_OLD_PT_F6_OFF + 16 * (reg - (UNW_IA64_FR + 6)); + return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP); + + case UNW_IA64_BR + 0: addr += LINUX_OLD_PT_B0_OFF; break; + case UNW_IA64_BR + 6: addr += LINUX_OLD_PT_B6_OFF; break; + case UNW_IA64_BR + 7: addr += LINUX_OLD_PT_B7_OFF; break; + + case UNW_IA64_AR_RSC: addr += LINUX_OLD_PT_RSC_OFF; break; + case UNW_IA64_AR_CCV: addr += LINUX_OLD_PT_CCV_OFF; break; + + default: + if (unw_is_fpreg (reg)) + return IA64_FPREG_LOC (c, reg); + else + return IA64_REG_LOC (c, reg); + } + } + if (is_nat) + { + /* For Linux pt-regs structure, bit number is determined by + the UNaT slot number (as determined by st8.spill) and the + bits are saved wherever the (primary) UNaT was saved. */ + *nat_bitnr = ia64_unat_slot_num (addr); + return c->loc[IA64_REG_PRI_UNAT_MEM]; + } + return IA64_LOC_ADDR (addr, 0); + } +#endif + return IA64_NULL_LOC; +} + +static inline ia64_loc_t +hpux_scratch_loc (struct cursor *c, unw_regnum_t reg, uint8_t *nat_bitnr) +{ +#if !defined(UNW_LOCAL_ONLY) || defined(__hpux) + return IA64_LOC_UC_REG (reg, c->sigcontext_addr); +#else + return IA64_NULL_LOC; +#endif +} + +HIDDEN ia64_loc_t +ia64_scratch_loc (struct cursor *c, unw_regnum_t reg, uint8_t *nat_bitnr) +{ + if (c->sigcontext_addr) + { + if (ia64_get_abi (c) == ABI_LINUX) + return linux_scratch_loc (c, reg, nat_bitnr); + else if (ia64_get_abi (c) == ABI_HPUX) + return hpux_scratch_loc (c, reg, nat_bitnr); + else + return IA64_NULL_LOC; + } + else + return IA64_REG_LOC (c, reg); +} + +static inline int +update_nat (struct cursor *c, ia64_loc_t nat_loc, unw_word_t mask, + unw_word_t *valp, int write) +{ + unw_word_t nat_word; + int ret; + + ret = ia64_get (c, nat_loc, &nat_word); + if (ret < 0) + return ret; + + if (write) + { + if (*valp) + nat_word |= mask; + else + nat_word &= ~mask; + ret = ia64_put (c, nat_loc, nat_word); + } + else + *valp = (nat_word & mask) != 0; + return ret; +} + +static int +access_nat (struct cursor *c, + ia64_loc_t nat_loc, ia64_loc_t reg_loc, uint8_t nat_bitnr, + unw_word_t *valp, int write) +{ + unw_word_t mask = 0; + unw_fpreg_t tmp; + int ret; + + if (IA64_IS_FP_LOC (reg_loc)) + { + /* NaT bit is saved as a NaTVal. This happens when a general + register is saved to a floating-point register. */ + if (write) + { + if (*valp) + { + if (ia64_is_big_endian (c)) + ret = ia64_putfp (c, reg_loc, unw.nat_val_be); + else + ret = ia64_putfp (c, reg_loc, unw.nat_val_le); + } + else + { + unw_word_t *src, *dst; + unw_fpreg_t tmp; + + ret = ia64_getfp (c, reg_loc, &tmp); + if (ret < 0) + return ret; + + /* Reset the exponent to 0x1003e so that the significand + will be interpreted as an integer value. */ + src = (unw_word_t *) &unw.int_val_be; + dst = (unw_word_t *) &tmp; + if (!ia64_is_big_endian (c)) + ++src, ++dst; + *dst = *src; + + ret = ia64_putfp (c, reg_loc, tmp); + } + } + else + { + ret = ia64_getfp (c, reg_loc, &tmp); + if (ret < 0) + return ret; + + if (ia64_is_big_endian (c)) + *valp = (memcmp (&tmp, &unw.nat_val_be, sizeof (tmp)) == 0); + else + *valp = (memcmp (&tmp, &unw.nat_val_le, sizeof (tmp)) == 0); + } + return ret; + } + + if ((IA64_IS_REG_LOC (nat_loc) + && (unsigned) (IA64_GET_REG (nat_loc) - UNW_IA64_NAT) < 128) + || IA64_IS_UC_LOC (reg_loc)) + { + if (write) + return ia64_put (c, nat_loc, *valp); + else + return ia64_get (c, nat_loc, valp); + } + + if (IA64_IS_NULL_LOC (nat_loc)) + { + /* NaT bit is not saved. This happens if a general register is + saved to a branch register. Since the NaT bit gets lost, we + need to drop it here, too. Note that if the NaT bit had been + set when the save occurred, it would have caused a NaT + consumption fault. */ + if (write) + { + if (*valp) + return -UNW_EBADREG; /* can't set NaT bit */ + } + else + *valp = 0; + return 0; + } + + mask = (unw_word_t) 1 << nat_bitnr; + return update_nat (c, nat_loc, mask, valp, write); +} + +HIDDEN int +tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + int write) +{ + ia64_loc_t loc, reg_loc, nat_loc; + unw_word_t mask, val; + uint8_t nat_bitnr; + int ret; + + switch (reg) + { + /* frame registers: */ + + case UNW_IA64_BSP: + if (write) + c->bsp = *valp; + else + *valp = c->bsp; + return 0; + + case UNW_REG_SP: + if (write) + c->sp = *valp; + else + *valp = c->sp; + return 0; + + case UNW_REG_IP: + if (write) + { + c->ip = *valp; /* also update the IP cache */ + if (c->pi_valid && (*valp < c->pi.start_ip || *valp >= c->pi.end_ip)) + c->pi_valid = 0; /* new IP outside of current proc */ + } + loc = c->loc[IA64_REG_IP]; + break; + + /* preserved registers: */ + + case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7: + loc = c->loc[IA64_REG_R4 + (reg - (UNW_IA64_GR + 4))]; + break; + + case UNW_IA64_NAT + 4 ... UNW_IA64_NAT + 7: + loc = c->loc[IA64_REG_NAT4 + (reg - (UNW_IA64_NAT + 4))]; + reg_loc = c->loc[IA64_REG_R4 + (reg - (UNW_IA64_NAT + 4))]; + nat_bitnr = c->nat_bitnr[reg - (UNW_IA64_NAT + 4)]; + return access_nat (c, loc, reg_loc, nat_bitnr, valp, write); + + case UNW_IA64_AR_BSP: loc = c->loc[IA64_REG_BSP]; break; + case UNW_IA64_AR_BSPSTORE: loc = c->loc[IA64_REG_BSPSTORE]; break; + case UNW_IA64_AR_PFS: loc = c->loc[IA64_REG_PFS]; break; + case UNW_IA64_AR_RNAT: loc = c->loc[IA64_REG_RNAT]; break; + case UNW_IA64_AR_UNAT: loc = c->loc[IA64_REG_UNAT]; break; + case UNW_IA64_AR_LC: loc = c->loc[IA64_REG_LC]; break; + case UNW_IA64_AR_FPSR: loc = c->loc[IA64_REG_FPSR]; break; + case UNW_IA64_BR + 1: loc = c->loc[IA64_REG_B1]; break; + case UNW_IA64_BR + 2: loc = c->loc[IA64_REG_B2]; break; + case UNW_IA64_BR + 3: loc = c->loc[IA64_REG_B3]; break; + case UNW_IA64_BR + 4: loc = c->loc[IA64_REG_B4]; break; + case UNW_IA64_BR + 5: loc = c->loc[IA64_REG_B5]; break; + + case UNW_IA64_CFM: + if (write) + c->cfm = *valp; /* also update the CFM cache */ + loc = c->cfm_loc; + break; + + case UNW_IA64_PR: + /* + * Note: broad-side access to the predicates is NOT rotated + * (i.e., it is done as if CFM.rrb.pr == 0. + */ + if (write) + { + c->pr = *valp; /* update the predicate cache */ + return ia64_put (c, c->loc[IA64_REG_PR], *valp); + } + else + return ia64_get (c, c->loc[IA64_REG_PR], valp); + + case UNW_IA64_GR + 32 ... UNW_IA64_GR + 127: /* stacked reg */ + reg = rotate_gr (c, reg - UNW_IA64_GR); + if (reg < 0) + return -UNW_EBADREG; + ret = ia64_get_stacked (c, reg, &loc, NULL); + if (ret < 0) + return ret; + break; + + case UNW_IA64_NAT + 32 ... UNW_IA64_NAT + 127: /* stacked reg */ + reg = rotate_gr (c, reg - UNW_IA64_NAT); + if (reg < 0) + return -UNW_EBADREG; + ret = ia64_get_stacked (c, reg, &loc, &nat_loc); + if (ret < 0) + return ret; + assert (!IA64_IS_REG_LOC (loc)); + mask = (unw_word_t) 1 << rse_slot_num (IA64_GET_ADDR (loc)); + return update_nat (c, nat_loc, mask, valp, write); + + case UNW_IA64_AR_EC: + if ((ret = ia64_get (c, c->ec_loc, &val)) < 0) + return ret; + + if (write) + { + val = ((val & ~((unw_word_t) 0x3f << 52)) | ((*valp & 0x3f) << 52)); + return ia64_put (c, c->ec_loc, val); + } + else + { + *valp = (val >> 52) & 0x3f; + return 0; + } + + /* scratch & special registers: */ + + case UNW_IA64_GR + 0: + if (write) + return -UNW_EREADONLYREG; + *valp = 0; + return 0; + + case UNW_IA64_NAT + 0: + if (write) + return -UNW_EREADONLYREG; + *valp = 0; + return 0; + + case UNW_IA64_NAT + 1: + case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3: + case UNW_IA64_NAT + 8 ... UNW_IA64_NAT + 31: + loc = ia64_scratch_loc (c, reg, &nat_bitnr); + if (IA64_IS_NULL_LOC (loc) && reg == UNW_IA64_NAT + 1) + { + /* access to GP */ + if (write) + return -UNW_EREADONLYREG; + *valp = 0; + return 0; + } + if (!(IA64_IS_REG_LOC (loc) || IA64_IS_UC_LOC (loc) + || IA64_IS_FP_LOC (loc))) + /* We're dealing with a NaT bit stored in memory. */ + return update_nat(c, loc, (unw_word_t) 1 << nat_bitnr, valp, write); + break; + + case UNW_IA64_GR + 15 ... UNW_IA64_GR + 18: + mask = 1 << (reg - (UNW_IA64_GR + 15)); + if (write) + { + c->eh_args[reg - (UNW_IA64_GR + 15)] = *valp; + c->eh_valid_mask |= mask; + return 0; + } + else if ((c->eh_valid_mask & mask) != 0) + { + *valp = c->eh_args[reg - (UNW_IA64_GR + 15)]; + return 0; + } + else + loc = ia64_scratch_loc (c, reg, NULL); + break; + + case UNW_IA64_GR + 1: /* global pointer */ + case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3: + case UNW_IA64_GR + 8 ... UNW_IA64_GR + 14: + case UNW_IA64_GR + 19 ... UNW_IA64_GR + 31: + case UNW_IA64_BR + 0: + case UNW_IA64_BR + 6: + case UNW_IA64_BR + 7: + case UNW_IA64_AR_RSC: + case UNW_IA64_AR_CSD: + case UNW_IA64_AR_SSD: + case UNW_IA64_AR_CCV: + loc = ia64_scratch_loc (c, reg, NULL); + if (IA64_IS_NULL_LOC (loc) && reg == UNW_IA64_GR + 1) + { + /* access to GP */ + if (write) + return -UNW_EREADONLYREG; + + /* ensure c->pi is up-to-date: */ + if ((ret = ia64_make_proc_info (c)) < 0) + return ret; + *valp = c->pi.gp; + return 0; + } + break; + + default: + Debug (1, "bad register number %d\n", reg); + return -UNW_EBADREG; + } + + if (write) + return ia64_put (c, loc, *valp); + else + return ia64_get (c, loc, valp); +} + +HIDDEN int +tdep_access_fpreg (struct cursor *c, int reg, unw_fpreg_t *valp, + int write) +{ + ia64_loc_t loc; + + switch (reg) + { + case UNW_IA64_FR + 0: + if (write) + return -UNW_EREADONLYREG; + *valp = unw.read_only.f0; + return 0; + + case UNW_IA64_FR + 1: + if (write) + return -UNW_EREADONLYREG; + + if (ia64_is_big_endian (c)) + *valp = unw.read_only.f1_be; + else + *valp = unw.read_only.f1_le; + return 0; + + case UNW_IA64_FR + 2: loc = c->loc[IA64_REG_F2]; break; + case UNW_IA64_FR + 3: loc = c->loc[IA64_REG_F3]; break; + case UNW_IA64_FR + 4: loc = c->loc[IA64_REG_F4]; break; + case UNW_IA64_FR + 5: loc = c->loc[IA64_REG_F5]; break; + + case UNW_IA64_FR + 16 ... UNW_IA64_FR + 31: + loc = c->loc[IA64_REG_F16 + (reg - (UNW_IA64_FR + 16))]; + break; + + case UNW_IA64_FR + 6 ... UNW_IA64_FR + 15: + loc = ia64_scratch_loc (c, reg, NULL); + break; + + case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127: + reg = rotate_fr (c, reg - UNW_IA64_FR) + UNW_IA64_FR; + loc = ia64_scratch_loc (c, reg, NULL); + break; + + default: + Debug (1, "bad register number %d\n", reg); + return -UNW_EBADREG; + } + + if (write) + return ia64_putfp (c, loc, *valp); + else + return ia64_getfp (c, loc, valp); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gresume.c new file mode 100644 index 0000000..68fe8a6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gresume.c @@ -0,0 +1,274 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "unwind_i.h" +#include "offsets.h" + +#ifndef UNW_REMOTE_ONLY + +static inline int +local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ +#if defined(__linux) + unw_word_t dirty_partition[2048]; /* AR.RSC.LOADRS is a 14-bit field */ + unw_word_t val, sol, sof, pri_unat, n, pfs, bspstore, dirty_rnat; + struct cursor *c = (struct cursor *) cursor; + struct + { + unw_word_t r1; + unw_word_t r4; + unw_word_t r5; + unw_word_t r6; + unw_word_t r7; + unw_word_t r15; + unw_word_t r16; + unw_word_t r17; + unw_word_t r18; + } + extra; + int ret, dirty_size; +# define GET_NAT(n) \ + do \ + { \ + ret = tdep_access_reg (c, UNW_IA64_NAT + (n), &val, 0); \ + if (ret < 0) \ + return ret; \ + if (val) \ + pri_unat |= (unw_word_t) 1 << n; \ + } \ + while (0) + + /* ensure c->pi is up-to-date: */ + if ((ret = ia64_make_proc_info (c)) < 0) + return ret; + + /* Copy contents of r4-r7 into "extra", so that their values end up + contiguous, so we can use a single (primary-) UNaT value. */ + if ((ret = ia64_get (c, c->loc[IA64_REG_R4], &extra.r4)) < 0 + || (ret = ia64_get (c, c->loc[IA64_REG_R5], &extra.r5)) < 0 + || (ret = ia64_get (c, c->loc[IA64_REG_R6], &extra.r6)) < 0 + || (ret = ia64_get (c, c->loc[IA64_REG_R7], &extra.r7)) < 0) + return ret; + + /* Form the primary UNaT value: */ + pri_unat = 0; + GET_NAT (4); GET_NAT(5); + GET_NAT (6); GET_NAT(7); + n = (((uintptr_t) &extra.r4) / 8 - 4) % 64; + pri_unat = (pri_unat << n) | (pri_unat >> (64 - n)); + + if (unlikely (c->sigcontext_addr)) + { + struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; +# define PR_SCRATCH 0xffc0 /* p6-p15 are scratch */ +# define PR_PRESERVED (~(PR_SCRATCH | 1)) + + /* We're returning to a frame that was (either directly or + indirectly) interrupted by a signal. We have to restore + _both_ "preserved" and "scratch" registers. That doesn't + leave us any registers to work with, and the only way we can + achieve this is by doing a sigreturn(). + + Note: it might be tempting to think that we don't have to + restore the scratch registers when returning to a frame that + was indirectly interrupted by a signal. However, that is not + safe because that frame and its descendants could have been + using a special convention that stores "preserved" state in + scratch registers. For example, the Linux fsyscall + convention does this with r11 (to save ar.pfs) and b6 (to + save "rp"). */ + + sc->sc_gr[12] = c->psp; + c->psp = c->sigcontext_addr - c->sigcontext_off; + + sof = (c->cfm & 0x7f); + if ((dirty_size = rbs_cover_and_flush (c, sof, dirty_partition, + &dirty_rnat, &bspstore)) < 0) + return dirty_size; + + /* Clear the "in-syscall" flag, because in general we won't be + returning to the interruption-point and we need all registers + restored. */ + sc->sc_flags &= ~IA64_SC_FLAG_IN_SYSCALL; + sc->sc_ip = c->ip; + sc->sc_cfm = c->cfm & (((unw_word_t) 1 << 38) - 1); + sc->sc_pr = (c->pr & ~PR_SCRATCH) | (sc->sc_pr & ~PR_PRESERVED); + if ((ret = ia64_get (c, c->loc[IA64_REG_PFS], &sc->sc_ar_pfs)) < 0 + || (ret = ia64_get (c, c->loc[IA64_REG_FPSR], &sc->sc_ar_fpsr)) < 0 + || (ret = ia64_get (c, c->loc[IA64_REG_UNAT], &sc->sc_ar_unat)) < 0) + return ret; + + sc->sc_gr[1] = c->pi.gp; + if (c->eh_valid_mask & 0x1) sc->sc_gr[15] = c->eh_args[0]; + if (c->eh_valid_mask & 0x2) sc->sc_gr[16] = c->eh_args[1]; + if (c->eh_valid_mask & 0x4) sc->sc_gr[17] = c->eh_args[2]; + if (c->eh_valid_mask & 0x8) sc->sc_gr[18] = c->eh_args[3]; + Debug (9, "sc: r15=%lx,r16=%lx,r17=%lx,r18=%lx\n", + (long) sc->sc_gr[15], (long) sc->sc_gr[16], + (long) sc->sc_gr[17], (long) sc->sc_gr[18]); + } + else + { + /* Account for the fact that _Uia64_install_context() will + return via br.ret, which will decrement bsp by size-of-locals. */ + if ((ret = ia64_get (c, c->loc[IA64_REG_PFS], &pfs)) < 0) + return ret; + sol = (pfs >> 7) & 0x7f; + if ((dirty_size = rbs_cover_and_flush (c, sol, dirty_partition, + &dirty_rnat, &bspstore)) < 0) + return dirty_size; + + extra.r1 = c->pi.gp; + extra.r15 = c->eh_args[0]; + extra.r16 = c->eh_args[1]; + extra.r17 = c->eh_args[2]; + extra.r18 = c->eh_args[3]; + Debug (9, "extra: r15=%lx,r16=%lx,r17=%lx,r18=%lx\n", + (long) extra.r15, (long) extra.r16, + (long) extra.r17, (long) extra.r18); + } + Debug (8, "resuming at ip=%lx\n", (long) c->ip); + ia64_install_cursor (c, pri_unat, (unw_word_t *) &extra, + bspstore, dirty_size, dirty_partition + dirty_size/8, + dirty_rnat); +#elif defined(__hpux) + struct cursor *c = (struct cursor *) cursor; + + setcontext (c->as_arg); /* should not return */ +#endif + return -UNW_EINVAL; +} + +HIDDEN int +ia64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ + return local_resume (as, cursor, arg); +} + +#endif /* !UNW_REMOTE_ONLY */ + +#ifndef UNW_LOCAL_ONLY + +static inline int +remote_install_cursor (struct cursor *c) +{ + int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, + int write, void *); + int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *, + int write, void *); + unw_fpreg_t fpval; + unw_word_t val; + int reg; + +#if defined(__linux) && !defined(UNW_REMOTE_ONLY) + if (c->as == unw_local_addr_space) + { + /* Take a short-cut: we directly resume out of the cursor and + all we need to do is make sure that all locations point to + memory, not registers. Furthermore, R4-R7 and NAT4-NAT7 are + taken care of by ia64_local_resume() so they don't need to be + handled here. */ +# define MEMIFY(preg, reg) \ + do { \ + if (IA64_IS_REG_LOC (c->loc[(preg)])) \ + c->loc[(preg)] = IA64_LOC_ADDR ((unw_word_t) \ + tdep_uc_addr(c->as_arg, (reg), \ + NULL), 0); \ + } while (0) + MEMIFY (IA64_REG_PR, UNW_IA64_PR); + MEMIFY (IA64_REG_PFS, UNW_IA64_AR_PFS); + MEMIFY (IA64_REG_RNAT, UNW_IA64_AR_RNAT); + MEMIFY (IA64_REG_UNAT, UNW_IA64_AR_UNAT); + MEMIFY (IA64_REG_LC, UNW_IA64_AR_LC); + MEMIFY (IA64_REG_FPSR, UNW_IA64_AR_FPSR); + MEMIFY (IA64_REG_IP, UNW_IA64_BR + 0); + MEMIFY (IA64_REG_B1, UNW_IA64_BR + 1); + MEMIFY (IA64_REG_B2, UNW_IA64_BR + 2); + MEMIFY (IA64_REG_B3, UNW_IA64_BR + 3); + MEMIFY (IA64_REG_B4, UNW_IA64_BR + 4); + MEMIFY (IA64_REG_B5, UNW_IA64_BR + 5); + MEMIFY (IA64_REG_F2, UNW_IA64_FR + 2); + MEMIFY (IA64_REG_F3, UNW_IA64_FR + 3); + MEMIFY (IA64_REG_F4, UNW_IA64_FR + 4); + MEMIFY (IA64_REG_F5, UNW_IA64_FR + 5); + MEMIFY (IA64_REG_F16, UNW_IA64_FR + 16); + MEMIFY (IA64_REG_F17, UNW_IA64_FR + 17); + MEMIFY (IA64_REG_F18, UNW_IA64_FR + 18); + MEMIFY (IA64_REG_F19, UNW_IA64_FR + 19); + MEMIFY (IA64_REG_F20, UNW_IA64_FR + 20); + MEMIFY (IA64_REG_F21, UNW_IA64_FR + 21); + MEMIFY (IA64_REG_F22, UNW_IA64_FR + 22); + MEMIFY (IA64_REG_F23, UNW_IA64_FR + 23); + MEMIFY (IA64_REG_F24, UNW_IA64_FR + 24); + MEMIFY (IA64_REG_F25, UNW_IA64_FR + 25); + MEMIFY (IA64_REG_F26, UNW_IA64_FR + 26); + MEMIFY (IA64_REG_F27, UNW_IA64_FR + 27); + MEMIFY (IA64_REG_F28, UNW_IA64_FR + 28); + MEMIFY (IA64_REG_F29, UNW_IA64_FR + 29); + MEMIFY (IA64_REG_F30, UNW_IA64_FR + 30); + MEMIFY (IA64_REG_F31, UNW_IA64_FR + 31); + } + else +#endif /* __linux && !UNW_REMOTE_ONLY */ + { + access_reg = c->as->acc.access_reg; + access_fpreg = c->as->acc.access_fpreg; + + Debug (8, "copying out cursor state\n"); + + for (reg = 0; reg <= UNW_REG_LAST; ++reg) + { + if (unw_is_fpreg (reg)) + { + if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) + (*access_fpreg) (c->as, reg, &fpval, 1, c->as_arg); + } + else + { + if (tdep_access_reg (c, reg, &val, 0) >= 0) + (*access_reg) (c->as, reg, &val, 1, c->as_arg); + } + } + } + return (*c->as->acc.resume) (c->as, (unw_cursor_t *) c, c->as_arg); +} + +#endif /* !UNW_LOCAL_ONLY */ + +int +unw_resume (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + + Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->ip); + +#ifdef UNW_LOCAL_ONLY + return local_resume (c->as, cursor, c->as_arg); +#else + return remote_install_cursor (c); +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gscript.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gscript.c new file mode 100644 index 0000000..526aeaf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gscript.c @@ -0,0 +1,765 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "offsets.h" +#include "regs.h" +#include "unwind_i.h" + +enum ia64_script_insn_opcode + { + IA64_INSN_INC_PSP, /* psp += val */ + IA64_INSN_LOAD_PSP, /* psp = *psp_loc */ + IA64_INSN_ADD_PSP, /* s[dst] = (s.psp + val) */ + IA64_INSN_ADD_PSP_NAT, /* like above, but with NaT info */ + IA64_INSN_ADD_SP, /* s[dst] = (s.sp + val) */ + IA64_INSN_ADD_SP_NAT, /* like above, but with NaT info */ + IA64_INSN_MOVE, /* s[dst] = s[val] */ + IA64_INSN_MOVE_NAT, /* like above, but with NaT info */ + IA64_INSN_MOVE_NO_NAT, /* like above, but clear NaT info */ + IA64_INSN_MOVE_STACKED, /* s[dst] = rse_skip(*s.bsp_loc, val) */ + IA64_INSN_MOVE_STACKED_NAT, /* like above, but with NaT info */ + IA64_INSN_MOVE_SCRATCH, /* s[dst] = scratch reg "val" */ + IA64_INSN_MOVE_SCRATCH_NAT, /* like above, but with NaT info */ + IA64_INSN_MOVE_SCRATCH_NO_NAT /* like above, but clear NaT info */ + }; + +#if defined(HAVE___THREAD) && HAVE___THREAD +static __thread struct ia64_script_cache ia64_per_thread_cache = + { +#ifdef HAVE_ATOMIC_OPS_H + .busy = AO_TS_INITIALIZER +#else + .lock = PTHREAD_MUTEX_INITIALIZER +#endif + }; +#endif + +static inline unw_hash_index_t CONST_ATTR +hash (unw_word_t ip) +{ + /* based on (sqrt(5)/2-1)*2^64 */ +# define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL) + + return (ip >> 4) * magic >> (64 - IA64_LOG_UNW_HASH_SIZE); +} + +static inline long +cache_match (struct ia64_script *script, unw_word_t ip, unw_word_t pr) +{ + if (ip == script->ip && ((pr ^ script->pr_val) & script->pr_mask) == 0) + return 1; + return 0; +} + +static inline void +flush_script_cache (struct ia64_script_cache *cache) +{ + int i; + + cache->lru_head = IA64_UNW_CACHE_SIZE - 1; + cache->lru_tail = 0; + + for (i = 0; i < IA64_UNW_CACHE_SIZE; ++i) + { + if (i > 0) + cache->buckets[i].lru_chain = (i - 1); + cache->buckets[i].coll_chain = -1; + cache->buckets[i].ip = 0; + } + for (i = 0; ihash[i] = -1; +} + +static inline struct ia64_script_cache * +get_script_cache (unw_addr_space_t as, intrmask_t *saved_maskp) +{ + struct ia64_script_cache *cache = &as->global_cache; + unw_caching_policy_t caching = as->caching_policy; + + if (caching == UNW_CACHE_NONE) + return NULL; + +#ifdef HAVE_ATOMIC_H + if (!spin_trylock_irqsave (&cache->busy, *saved_maskp)) + return NULL; +#else +# if defined(HAVE___THREAD) && HAVE___THREAD + if (as->caching_policy == UNW_CACHE_PER_THREAD) + cache = &ia64_per_thread_cache; +# endif +# ifdef HAVE_ATOMIC_OPS_H + if (AO_test_and_set (&cache->busy) == AO_TS_SET) + return NULL; +# else + if (likely (caching == UNW_CACHE_GLOBAL)) + { + Debug (16, "acquiring lock\n"); + lock_acquire (&cache->lock, *saved_maskp); + } +# endif +#endif + + if (atomic_read (&as->cache_generation) != atomic_read (&cache->generation)) + { + flush_script_cache (cache); + cache->generation = as->cache_generation; + } + return cache; +} + +static inline void +put_script_cache (unw_addr_space_t as, struct ia64_script_cache *cache, + intrmask_t *saved_maskp) +{ + assert (as->caching_policy != UNW_CACHE_NONE); + + Debug (16, "unmasking signals/interrupts and releasing lock\n"); +#ifdef HAVE_ATOMIC_H + spin_unlock_irqrestore (&cache->busy, *saved_maskp); +#else +# ifdef HAVE_ATOMIC_OPS_H + AO_CLEAR (&cache->busy); +# else + if (likely (as->caching_policy == UNW_CACHE_GLOBAL)) + lock_release (&cache->lock, *saved_maskp); +# endif +#endif +} + +static struct ia64_script * +script_lookup (struct ia64_script_cache *cache, struct cursor *c) +{ + struct ia64_script *script = cache->buckets + c->hint; + unsigned short index; + unw_word_t ip, pr; + + ip = c->ip; + pr = c->pr; + + if (cache_match (script, ip, pr)) + return script; + + index = cache->hash[hash (ip)]; + if (index >= IA64_UNW_CACHE_SIZE) + return 0; + + script = cache->buckets + index; + while (1) + { + if (cache_match (script, ip, pr)) + { + /* update hint; no locking needed: single-word writes are atomic */ + c->hint = cache->buckets[c->prev_script].hint = + (script - cache->buckets); + return script; + } + if (script->coll_chain >= IA64_UNW_HASH_SIZE) + return 0; + script = cache->buckets + script->coll_chain; + } +} + +static inline void +script_init (struct ia64_script *script, unw_word_t ip) +{ + script->ip = ip; + script->hint = 0; + script->count = 0; + script->abi_marker = 0; +} + +static inline struct ia64_script * +script_new (struct ia64_script_cache *cache, unw_word_t ip) +{ + struct ia64_script *script, *prev, *tmp; + unw_hash_index_t index; + unsigned short head; + + head = cache->lru_head; + script = cache->buckets + head; + cache->lru_head = script->lru_chain; + + /* re-insert script at the tail of the LRU chain: */ + cache->buckets[cache->lru_tail].lru_chain = head; + cache->lru_tail = head; + + /* remove the old script from the hash table (if it's there): */ + if (script->ip) + { + index = hash (script->ip); + tmp = cache->buckets + cache->hash[index]; + prev = 0; + while (1) + { + if (tmp == script) + { + if (prev) + prev->coll_chain = tmp->coll_chain; + else + cache->hash[index] = tmp->coll_chain; + break; + } + else + prev = tmp; + if (tmp->coll_chain >= IA64_UNW_CACHE_SIZE) + /* old script wasn't in the hash-table */ + break; + tmp = cache->buckets + tmp->coll_chain; + } + } + + /* enter new script in the hash table */ + index = hash (ip); + script->coll_chain = cache->hash[index]; + cache->hash[index] = script - cache->buckets; + + script_init (script, ip); + return script; +} + +static inline void +script_finalize (struct ia64_script *script, struct cursor *c, + struct ia64_state_record *sr) +{ + script->pr_mask = sr->pr_mask; + script->pr_val = sr->pr_val; + script->pi = c->pi; +} + +static inline void +script_emit (struct ia64_script *script, struct ia64_script_insn insn) +{ + if (script->count >= IA64_MAX_SCRIPT_LEN) + { + Dprintf ("%s: script exceeds maximum size of %u instructions!\n", + __FUNCTION__, IA64_MAX_SCRIPT_LEN); + return; + } + script->insn[script->count++] = insn; +} + +static void +compile_reg (struct ia64_state_record *sr, int i, struct ia64_reg_info *r, + struct ia64_script *script) +{ + enum ia64_script_insn_opcode opc; + unsigned long val, rval; + struct ia64_script_insn insn; + long is_preserved_gr; + + if (r->where == IA64_WHERE_NONE || r->when >= sr->when_target) + return; + + opc = IA64_INSN_MOVE; + val = rval = r->val; + is_preserved_gr = (i >= IA64_REG_R4 && i <= IA64_REG_R7); + + if (r->where == IA64_WHERE_GR) + { + /* Handle most common case first... */ + if (rval >= 32) + { + /* register got spilled to a stacked register */ + if (is_preserved_gr) + opc = IA64_INSN_MOVE_STACKED_NAT; + else + opc = IA64_INSN_MOVE_STACKED; + val = rval; + } + else if (rval >= 4 && rval <= 7) + { + /* register got spilled to a preserved register */ + val = IA64_REG_R4 + (rval - 4); + if (is_preserved_gr) + opc = IA64_INSN_MOVE_NAT; + } + else + { + /* register got spilled to a scratch register */ + if (is_preserved_gr) + opc = IA64_INSN_MOVE_SCRATCH_NAT; + else + opc = IA64_INSN_MOVE_SCRATCH; + val = UNW_IA64_GR + rval; + } + } + else + { + switch (r->where) + { + case IA64_WHERE_FR: + /* Note: There is no need to handle NaT-bit info here + (indepent of is_preserved_gr), because for floating-point + NaTs are represented as NaTVal, so the NaT-info never + needs to be consulated. */ + if (rval >= 2 && rval <= 5) + val = IA64_REG_F2 + (rval - 2); + else if (rval >= 16 && rval <= 31) + val = IA64_REG_F16 + (rval - 16); + else + { + opc = IA64_INSN_MOVE_SCRATCH; + val = UNW_IA64_FR + rval; + } + break; + + case IA64_WHERE_BR: + if (rval >= 1 && rval <= 5) + { + val = IA64_REG_B1 + (rval - 1); + if (is_preserved_gr) + opc = IA64_INSN_MOVE_NO_NAT; + } + else + { + opc = IA64_INSN_MOVE_SCRATCH; + if (is_preserved_gr) + opc = IA64_INSN_MOVE_SCRATCH_NO_NAT; + val = UNW_IA64_BR + rval; + } + break; + + case IA64_WHERE_SPREL: + if (is_preserved_gr) + opc = IA64_INSN_ADD_SP_NAT; + else + { + opc = IA64_INSN_ADD_SP; + if (i >= IA64_REG_F2 && i <= IA64_REG_F31) + val |= IA64_LOC_TYPE_FP; + } + break; + + case IA64_WHERE_PSPREL: + if (is_preserved_gr) + opc = IA64_INSN_ADD_PSP_NAT; + else + { + opc = IA64_INSN_ADD_PSP; + if (i >= IA64_REG_F2 && i <= IA64_REG_F31) + val |= IA64_LOC_TYPE_FP; + } + break; + + default: + Dprintf ("%s: register %u has unexpected `where' value of %u\n", + __FUNCTION__, i, r->where); + break; + } + } + insn.opc = opc; + insn.dst = i; + insn.val = val; + script_emit (script, insn); + + if (i == IA64_REG_PSP) + { + /* c->psp must contain the _value_ of the previous sp, not it's + save-location. We get this by dereferencing the value we + just stored in loc[IA64_REG_PSP]: */ + insn.opc = IA64_INSN_LOAD_PSP; + script_emit (script, insn); + } +} + +/* Sort the registers which got saved in decreasing order of WHEN + value. This is needed to ensure that the save-locations are + updated in the proper order. For example, suppose r4 gets spilled + to memory and then r5 gets saved in r4. In this case, we need to + update the save location of r5 before the one of r4. */ + +static inline int +sort_regs (struct ia64_state_record *sr, int regorder[]) +{ + int r, i, j, max, max_reg, max_when, num_regs = 0; + + assert (IA64_REG_BSP == 3); + + for (r = IA64_REG_BSP; r < IA64_NUM_PREGS; ++r) + { + if (sr->curr.reg[r].where == IA64_WHERE_NONE + || sr->curr.reg[r].when >= sr->when_target) + continue; + + regorder[num_regs++] = r; + } + + /* Simple insertion-sort. Involves about N^2/2 comparisons and N + exchanges. N is often small (say, 2-5) so a fancier sorting + algorithm may not be worthwhile. */ + + for (i = max = 0; i < num_regs - 1; ++i) + { + max_reg = regorder[max]; + max_when = sr->curr.reg[max_reg].when; + + for (j = i + 1; j < num_regs; ++j) + if (sr->curr.reg[regorder[j]].when > max_when) + { + max = j; + max_reg = regorder[j]; + max_when = sr->curr.reg[max_reg].when; + } + if (i != max) + { + regorder[max] = regorder[i]; + regorder[i] = max_reg; + } + } + return num_regs; +} + +/* Build an unwind script that unwinds from state OLD_STATE to the + entrypoint of the function that called OLD_STATE. */ + +static inline int +build_script (struct cursor *c, struct ia64_script *script) +{ + int num_regs, i, ret, regorder[IA64_NUM_PREGS - 3]; + struct ia64_reg_info *pri_unat; + struct ia64_state_record sr; + struct ia64_script_insn insn; + + ret = ia64_create_state_record (c, &sr); + if (ret < 0) + return ret; + + /* First, compile the update for IA64_REG_PSP. This is important + because later save-locations may depend on it's correct (updated) + value. Fixed-size frames are handled specially and variable-size + frames get handled via the normal compile_reg(). */ + + if (sr.when_target > sr.curr.reg[IA64_REG_PSP].when + && (sr.curr.reg[IA64_REG_PSP].where == IA64_WHERE_NONE) + && sr.curr.reg[IA64_REG_PSP].val != 0) + { + /* new psp is psp plus frame size */ + insn.opc = IA64_INSN_INC_PSP; + insn.val = sr.curr.reg[IA64_REG_PSP].val; /* frame size */ + script_emit (script, insn); + } + else + compile_reg (&sr, IA64_REG_PSP, sr.curr.reg + IA64_REG_PSP, script); + + /* Second, compile the update for the primary UNaT, if any: */ + + if (sr.when_target >= sr.curr.reg[IA64_REG_PRI_UNAT_GR].when + || sr.when_target >= sr.curr.reg[IA64_REG_PRI_UNAT_MEM].when) + { + if (sr.when_target < sr.curr.reg[IA64_REG_PRI_UNAT_GR].when) + /* (primary) NaT bits were saved to memory only */ + pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_MEM; + else if (sr.when_target < sr.curr.reg[IA64_REG_PRI_UNAT_MEM].when) + /* (primary) NaT bits were saved to a register only */ + pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_GR; + else if (sr.curr.reg[IA64_REG_PRI_UNAT_MEM].when > + sr.curr.reg[IA64_REG_PRI_UNAT_GR].when) + /* (primary) NaT bits were last saved to memory */ + pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_MEM; + else + /* (primary) NaT bits were last saved to a register */ + pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_GR; + + /* Note: we always store the final primary-UNaT location in UNAT_MEM. */ + compile_reg (&sr, IA64_REG_PRI_UNAT_MEM, pri_unat, script); + } + + /* Third, compile the other register in decreasing order of WHEN values. */ + + num_regs = sort_regs (&sr, regorder); + for (i = 0; i < num_regs; ++i) + compile_reg (&sr, regorder[i], sr.curr.reg + regorder[i], script); + + script->abi_marker = sr.abi_marker; + script_finalize (script, c, &sr); + + ia64_free_state_record (&sr); + return 0; +} + +static inline void +set_nat_info (struct cursor *c, unsigned long dst, + ia64_loc_t nat_loc, uint8_t bitnr) +{ + assert (dst >= IA64_REG_R4 && dst <= IA64_REG_R7); + + c->loc[dst - IA64_REG_R4 + IA64_REG_NAT4] = nat_loc; + c->nat_bitnr[dst - IA64_REG_R4] = bitnr; +} + +/* Apply the unwinding actions represented by OPS and update SR to + reflect the state that existed upon entry to the function that this + unwinder represents. */ + +static inline int +run_script (struct ia64_script *script, struct cursor *c) +{ + struct ia64_script_insn *ip, *limit, next_insn; + ia64_loc_t loc, nat_loc; + unsigned long opc, dst; + uint8_t nat_bitnr; + unw_word_t val; + int ret; + + c->pi = script->pi; + ip = script->insn; + limit = script->insn + script->count; + next_insn = *ip; + c->abi_marker = script->abi_marker; + + while (ip++ < limit) + { + opc = next_insn.opc; + dst = next_insn.dst; + val = next_insn.val; + next_insn = *ip; + + /* This is by far the most common operation: */ + if (likely (opc == IA64_INSN_MOVE_STACKED)) + { + if ((ret = ia64_get_stacked (c, val, &loc, NULL)) < 0) + return ret; + } + else + switch (opc) + { + case IA64_INSN_INC_PSP: + c->psp += val; + continue; + + case IA64_INSN_LOAD_PSP: + if ((ret = ia64_get (c, c->loc[IA64_REG_PSP], &c->psp)) < 0) + return ret; + continue; + + case IA64_INSN_ADD_PSP: + loc = IA64_LOC_ADDR (c->psp + val, (val & IA64_LOC_TYPE_FP)); + break; + + case IA64_INSN_ADD_SP: + loc = IA64_LOC_ADDR (c->sp + val, (val & IA64_LOC_TYPE_FP)); + break; + + case IA64_INSN_MOVE_NO_NAT: + set_nat_info (c, dst, IA64_NULL_LOC, 0); + case IA64_INSN_MOVE: + loc = c->loc[val]; + break; + + case IA64_INSN_MOVE_SCRATCH_NO_NAT: + set_nat_info (c, dst, IA64_NULL_LOC, 0); + case IA64_INSN_MOVE_SCRATCH: + loc = ia64_scratch_loc (c, val, NULL); + break; + + case IA64_INSN_ADD_PSP_NAT: + loc = IA64_LOC_ADDR (c->psp + val, 0); + assert (!IA64_IS_REG_LOC (loc)); + set_nat_info (c, dst, + c->loc[IA64_REG_PRI_UNAT_MEM], + ia64_unat_slot_num (IA64_GET_ADDR (loc))); + break; + + case IA64_INSN_ADD_SP_NAT: + loc = IA64_LOC_ADDR (c->sp + val, 0); + assert (!IA64_IS_REG_LOC (loc)); + set_nat_info (c, dst, + c->loc[IA64_REG_PRI_UNAT_MEM], + ia64_unat_slot_num (IA64_GET_ADDR (loc))); + break; + + case IA64_INSN_MOVE_NAT: + loc = c->loc[val]; + set_nat_info (c, dst, + c->loc[val - IA64_REG_R4 + IA64_REG_NAT4], + c->nat_bitnr[val - IA64_REG_R4]); + break; + + case IA64_INSN_MOVE_STACKED_NAT: + if ((ret = ia64_get_stacked (c, val, &loc, &nat_loc)) < 0) + return ret; + assert (!IA64_IS_REG_LOC (loc)); + set_nat_info (c, dst, nat_loc, rse_slot_num (IA64_GET_ADDR (loc))); + break; + + case IA64_INSN_MOVE_SCRATCH_NAT: + loc = ia64_scratch_loc (c, val, NULL); + nat_loc = ia64_scratch_loc (c, val + (UNW_IA64_NAT - UNW_IA64_GR), + &nat_bitnr); + set_nat_info (c, dst, nat_loc, nat_bitnr); + break; + } + c->loc[dst] = loc; + } + return 0; +} + +static int +uncached_find_save_locs (struct cursor *c) +{ + struct ia64_script script; + int ret = 0; + + if ((ret = ia64_fetch_proc_info (c, c->ip, 1)) < 0) + return ret; + + script_init (&script, c->ip); + if ((ret = build_script (c, &script)) < 0) + { + if (ret != -UNW_ESTOPUNWIND) + Dprintf ("%s: failed to build unwind script for ip %lx\n", + __FUNCTION__, (long) c->ip); + return ret; + } + return run_script (&script, c); +} + +HIDDEN int +ia64_find_save_locs (struct cursor *c) +{ + struct ia64_script_cache *cache = NULL; + struct ia64_script *script = NULL; + intrmask_t saved_mask; + int ret = 0; + + if (c->as->caching_policy == UNW_CACHE_NONE) + return uncached_find_save_locs (c); + + cache = get_script_cache (c->as, &saved_mask); + if (!cache) + { + Debug (1, "contention on script-cache; doing uncached lookup\n"); + return uncached_find_save_locs (c); + } + { + script = script_lookup (cache, c); + Debug (8, "ip %lx %s in script cache\n", (long) c->ip, + script ? "hit" : "missed"); + + if (!script || (script->count == 0 && !script->pi.unwind_info)) + { + if ((ret = ia64_fetch_proc_info (c, c->ip, 1)) < 0) + goto out; + } + + if (!script) + { + script = script_new (cache, c->ip); + if (!script) + { + Dprintf ("%s: failed to create unwind script\n", __FUNCTION__); + ret = -UNW_EUNSPEC; + goto out; + } + } + cache->buckets[c->prev_script].hint = script - cache->buckets; + + if (script->count == 0) + ret = build_script (c, script); + + assert (script->count > 0); + + c->hint = script->hint; + c->prev_script = script - cache->buckets; + + if (ret < 0) + { + if (ret != -UNW_ESTOPUNWIND) + Dprintf ("%s: failed to locate/build unwind script for ip %lx\n", + __FUNCTION__, (long) c->ip); + goto out; + } + + ret = run_script (script, c); + } + out: + put_script_cache (c->as, cache, &saved_mask); + return ret; +} + +HIDDEN void +ia64_validate_cache (unw_addr_space_t as, void *arg) +{ +#ifndef UNW_REMOTE_ONLY + if (as == unw_local_addr_space && ia64_local_validate_cache (as, arg) == 1) + return; +#endif + +#ifndef UNW_LOCAL_ONLY + /* local info is up-to-date, check dynamic info. */ + unwi_dyn_validate_cache (as, arg); +#endif +} + +HIDDEN int +ia64_cache_proc_info (struct cursor *c) +{ + struct ia64_script_cache *cache; + struct ia64_script *script; + intrmask_t saved_mask; + int ret = 0; + + cache = get_script_cache (c->as, &saved_mask); + if (!cache) + return ret; /* cache is busy */ + + /* Re-check to see if a cache entry has been added in the meantime: */ + script = script_lookup (cache, c); + if (script) + goto out; + + script = script_new (cache, c->ip); + if (!script) + { + Dprintf ("%s: failed to create unwind script\n", __FUNCTION__); + ret = -UNW_EUNSPEC; + goto out; + } + + script->pi = c->pi; + + out: + put_script_cache (c->as, cache, &saved_mask); + return ret; +} + +HIDDEN int +ia64_get_cached_proc_info (struct cursor *c) +{ + struct ia64_script_cache *cache; + struct ia64_script *script; + intrmask_t saved_mask; + + cache = get_script_cache (c->as, &saved_mask); + if (!cache) + return -UNW_ENOINFO; /* cache is busy */ + { + script = script_lookup (cache, c); + if (script) + c->pi = script->pi; + } + put_script_cache (c->as, cache, &saved_mask); + return script ? 0 : -UNW_ENOINFO; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gstep.c new file mode 100644 index 0000000..df4ecb8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gstep.c @@ -0,0 +1,359 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "offsets.h" +#include "unwind_i.h" + +static inline int +linux_sigtramp (struct cursor *c, ia64_loc_t prev_cfm_loc, + unw_word_t *num_regsp) +{ +#if defined(UNW_LOCAL_ONLY) && !defined(__linux) + return -UNW_EINVAL; +#else + unw_word_t sc_addr; + int ret; + + if ((ret = ia64_get (c, IA64_LOC_ADDR (c->sp + 0x10 + + LINUX_SIGFRAME_ARG2_OFF, 0), + &sc_addr)) < 0) + return ret; + + c->sigcontext_addr = sc_addr; + + if (!IA64_IS_REG_LOC (c->loc[IA64_REG_IP]) + && IA64_GET_ADDR (c->loc[IA64_REG_IP]) == sc_addr + LINUX_SC_BR_OFF + 8) + { + /* Linux kernels before 2.4.19 and 2.5.10 had buggy + unwind info for sigtramp. Fix it up here. */ + c->loc[IA64_REG_IP] = IA64_LOC_ADDR (sc_addr + LINUX_SC_IP_OFF, 0); + c->cfm_loc = IA64_LOC_ADDR (sc_addr + LINUX_SC_CFM_OFF, 0); + } + + /* do what can't be described by unwind directives: */ + c->loc[IA64_REG_PFS] = IA64_LOC_ADDR (sc_addr + LINUX_SC_AR_PFS_OFF, 0); + c->ec_loc = prev_cfm_loc; + *num_regsp = c->cfm & 0x7f; /* size of frame */ + return 0; +#endif +} + +static inline int +linux_interrupt (struct cursor *c, ia64_loc_t prev_cfm_loc, + unw_word_t *num_regsp, int marker) +{ +#if defined(UNW_LOCAL_ONLY) && !(defined(__linux) && defined(__KERNEL__)) + return -UNW_EINVAL; +#else + unw_word_t sc_addr, num_regs; + ia64_loc_t pfs_loc; + + sc_addr = c->sigcontext_addr = c->sp + 0x10; + + if ((c->pr & (1UL << LINUX_PT_P_NONSYS)) != 0) + num_regs = c->cfm & 0x7f; + else + num_regs = 0; + + /* do what can't be described by unwind directives: */ + if (marker == ABI_MARKER_OLD_LINUX_INTERRUPT) + pfs_loc = IA64_LOC_ADDR (sc_addr + LINUX_OLD_PT_PFS_OFF, 0); + else + pfs_loc = IA64_LOC_ADDR (sc_addr + LINUX_PT_PFS_OFF, 0); + c->loc[IA64_REG_PFS] = pfs_loc; + c->ec_loc = prev_cfm_loc; + *num_regsp = num_regs; /* size of frame */ + return 0; +#endif +} + +static inline int +hpux_sigtramp (struct cursor *c, ia64_loc_t prev_cfm_loc, + unw_word_t *num_regsp) +{ +#if defined(UNW_LOCAL_ONLY) && !defined(__hpux) + return -UNW_EINVAL; +#else + unw_word_t sc_addr, bsp, bspstore; + ia64_loc_t sc_loc; + int ret, i; + + /* HP-UX passes the address of ucontext_t in r32: */ + if ((ret = ia64_get_stacked (c, 32, &sc_loc, NULL)) < 0) + return ret; + if ((ret = ia64_get (c, sc_loc, &sc_addr)) < 0) + return ret; + + c->sigcontext_addr = sc_addr; + + /* Now mark all (preserved) registers as coming from the + signal context: */ + c->cfm_loc = IA64_LOC_UC_REG (UNW_IA64_CFM, sc_addr); + c->loc[IA64_REG_PRI_UNAT_MEM] = IA64_NULL_LOC; + c->loc[IA64_REG_PSP] = IA64_LOC_UC_REG (UNW_IA64_GR + 12, sc_addr); + c->loc[IA64_REG_BSP] = IA64_LOC_UC_REG (UNW_IA64_AR_BSP, sc_addr); + c->loc[IA64_REG_BSPSTORE] = IA64_LOC_UC_REG (UNW_IA64_AR_BSPSTORE, sc_addr); + c->loc[IA64_REG_PFS] = IA64_LOC_UC_REG (UNW_IA64_AR_PFS, sc_addr); + c->loc[IA64_REG_RNAT] = IA64_LOC_UC_REG (UNW_IA64_AR_RNAT, sc_addr); + c->loc[IA64_REG_IP] = IA64_LOC_UC_REG (UNW_IA64_IP, sc_addr); + c->loc[IA64_REG_R4] = IA64_LOC_UC_REG (UNW_IA64_GR + 4, sc_addr); + c->loc[IA64_REG_R5] = IA64_LOC_UC_REG (UNW_IA64_GR + 5, sc_addr); + c->loc[IA64_REG_R6] = IA64_LOC_UC_REG (UNW_IA64_GR + 6, sc_addr); + c->loc[IA64_REG_R7] = IA64_LOC_UC_REG (UNW_IA64_GR + 7, sc_addr); + c->loc[IA64_REG_NAT4] = IA64_LOC_UC_REG (UNW_IA64_NAT + 4, sc_addr); + c->loc[IA64_REG_NAT5] = IA64_LOC_UC_REG (UNW_IA64_NAT + 5, sc_addr); + c->loc[IA64_REG_NAT6] = IA64_LOC_UC_REG (UNW_IA64_NAT + 6, sc_addr); + c->loc[IA64_REG_NAT7] = IA64_LOC_UC_REG (UNW_IA64_NAT + 7, sc_addr); + c->loc[IA64_REG_UNAT] = IA64_LOC_UC_REG (UNW_IA64_AR_UNAT, sc_addr); + c->loc[IA64_REG_PR] = IA64_LOC_UC_REG (UNW_IA64_PR, sc_addr); + c->loc[IA64_REG_LC] = IA64_LOC_UC_REG (UNW_IA64_AR_LC, sc_addr); + c->loc[IA64_REG_FPSR] = IA64_LOC_UC_REG (UNW_IA64_AR_FPSR, sc_addr); + c->loc[IA64_REG_B1] = IA64_LOC_UC_REG (UNW_IA64_BR + 1, sc_addr); + c->loc[IA64_REG_B2] = IA64_LOC_UC_REG (UNW_IA64_BR + 2, sc_addr); + c->loc[IA64_REG_B3] = IA64_LOC_UC_REG (UNW_IA64_BR + 3, sc_addr); + c->loc[IA64_REG_B4] = IA64_LOC_UC_REG (UNW_IA64_BR + 4, sc_addr); + c->loc[IA64_REG_B5] = IA64_LOC_UC_REG (UNW_IA64_BR + 5, sc_addr); + c->loc[IA64_REG_F2] = IA64_LOC_UC_REG (UNW_IA64_FR + 2, sc_addr); + c->loc[IA64_REG_F3] = IA64_LOC_UC_REG (UNW_IA64_FR + 3, sc_addr); + c->loc[IA64_REG_F4] = IA64_LOC_UC_REG (UNW_IA64_FR + 4, sc_addr); + c->loc[IA64_REG_F5] = IA64_LOC_UC_REG (UNW_IA64_FR + 5, sc_addr); + for (i = 0; i < 16; ++i) + c->loc[IA64_REG_F16 + i] = IA64_LOC_UC_REG (UNW_IA64_FR + 16 + i, sc_addr); + + c->pi.flags |= UNW_PI_FLAG_IA64_RBS_SWITCH; + + /* update the CFM cache: */ + if ((ret = ia64_get (c, c->cfm_loc, &c->cfm)) < 0) + return ret; + /* update the PSP cache: */ + if ((ret = ia64_get (c, c->loc[IA64_REG_PSP], &c->psp)) < 0) + return ret; + + if ((ret = ia64_get (c, c->loc[IA64_REG_BSP], &bsp)) < 0 + || (ret = ia64_get (c, c->loc[IA64_REG_BSPSTORE], &bspstore)) < 0) + return ret; + if (bspstore < bsp) + /* Dirty partition got spilled into the ucontext_t structure + itself. We'll need to access it via uc_access(3). */ + rbs_switch (c, bsp, bspstore, IA64_LOC_UC_ADDR (bsp | 0x1f8, 0)); + + c->ec_loc = prev_cfm_loc; + + *num_regsp = 0; + return 0; +#endif +} + + +static inline int +check_rbs_switch (struct cursor *c) +{ + unw_word_t saved_bsp, saved_bspstore, loadrs, ndirty; + int ret = 0; + + saved_bsp = c->bsp; + if (c->pi.flags & UNW_PI_FLAG_IA64_RBS_SWITCH) + { + /* Got ourselves a frame that has saved ar.bspstore, ar.bsp, + and ar.rnat, so we're all set for rbs-switching: */ + if ((ret = ia64_get (c, c->loc[IA64_REG_BSP], &saved_bsp)) < 0 + || (ret = ia64_get (c, c->loc[IA64_REG_BSPSTORE], &saved_bspstore))) + return ret; + } + else if ((c->abi_marker == ABI_MARKER_LINUX_SIGTRAMP + || c->abi_marker == ABI_MARKER_OLD_LINUX_SIGTRAMP) + && !IA64_IS_REG_LOC (c->loc[IA64_REG_BSP]) + && (IA64_GET_ADDR (c->loc[IA64_REG_BSP]) + == c->sigcontext_addr + LINUX_SC_AR_BSP_OFF)) + { + /* When Linux delivers a signal on an alternate stack, it + does things a bit differently from what the unwind + conventions allow us to describe: instead of saving + ar.rnat, ar.bsp, and ar.bspstore, it saves the former two + plus the "loadrs" value. Because of this, we need to + detect & record a potential rbs-area switch + manually... */ + + /* If ar.bsp has been saved already AND the current bsp is + not equal to the saved value, then we know for sure that + we're past the point where the backing store has been + switched (and before the point where it's restored). */ + if ((ret = ia64_get (c, IA64_LOC_ADDR (c->sigcontext_addr + + LINUX_SC_AR_BSP_OFF, 0), + &saved_bsp) < 0) + || (ret = ia64_get (c, IA64_LOC_ADDR (c->sigcontext_addr + + LINUX_SC_LOADRS_OFF, 0), + &loadrs) < 0)) + return ret; + loadrs >>= 16; + ndirty = rse_num_regs (c->bsp - loadrs, c->bsp); + saved_bspstore = rse_skip_regs (saved_bsp, -ndirty); + } + + if (saved_bsp == c->bsp) + return 0; + + return rbs_switch (c, saved_bsp, saved_bspstore, c->loc[IA64_REG_RNAT]); +} + +static inline int +update_frame_state (struct cursor *c) +{ + unw_word_t prev_ip, prev_sp, prev_bsp, ip, num_regs; + ia64_loc_t prev_cfm_loc; + int ret; + + prev_cfm_loc = c->cfm_loc; + prev_ip = c->ip; + prev_sp = c->sp; + prev_bsp = c->bsp; + + /* Update the IP cache (do this first: if we reach the end of the + frame-chain, the rest of the info may not be valid/useful + anymore. */ + ret = ia64_get (c, c->loc[IA64_REG_IP], &ip); + if (ret < 0) + return ret; + c->ip = ip; + + if ((ip & 0xc) != 0) + { + /* don't let obviously bad addresses pollute the cache */ + Debug (1, "rejecting bad ip=0x%lx\n", (long) c->ip); + return -UNW_EINVALIDIP; + } + + c->cfm_loc = c->loc[IA64_REG_PFS]; + /* update the CFM cache: */ + ret = ia64_get (c, c->cfm_loc, &c->cfm); + if (ret < 0) + return ret; + + /* Normally, AR.EC is stored in the CFM save-location. That + save-location contains the full function-state as defined by + AR.PFS. However, interruptions only save the frame-marker, not + any other info in CFM. Instead, AR.EC gets saved on the first + call by the interruption-handler. Thus, interruption-related + frames need to track the _previous_ CFM save-location since + that's were AR.EC is saved. We support this by setting ec_loc to + cfm_loc by default and giving frames marked with an ABI-marker + the chance to override this value with prev_cfm_loc. */ + c->ec_loc = c->cfm_loc; + + num_regs = 0; + if (unlikely (c->abi_marker)) + { + c->last_abi_marker = c->abi_marker; + switch (ia64_get_abi_marker (c)) + { + case ABI_MARKER_LINUX_SIGTRAMP: + case ABI_MARKER_OLD_LINUX_SIGTRAMP: + ia64_set_abi (c, ABI_LINUX); + if ((ret = linux_sigtramp (c, prev_cfm_loc, &num_regs)) < 0) + return ret; + break; + + case ABI_MARKER_OLD_LINUX_INTERRUPT: + case ABI_MARKER_LINUX_INTERRUPT: + ia64_set_abi (c, ABI_LINUX); + if ((ret = linux_interrupt (c, prev_cfm_loc, &num_regs, + c->abi_marker)) < 0) + return ret; + break; + + case ABI_MARKER_HP_UX_SIGTRAMP: + ia64_set_abi (c, ABI_HPUX); + if ((ret = hpux_sigtramp (c, prev_cfm_loc, &num_regs)) < 0) + return ret; + break; + + default: + Debug (1, "unknown ABI marker: ABI=%u, context=%u\n", + c->abi_marker >> 8, c->abi_marker & 0xff); + return -UNW_EINVAL; + } + Debug (12, "sigcontext_addr=%lx (ret=%d)\n", + (unsigned long) c->sigcontext_addr, ret); + + c->sigcontext_off = c->sigcontext_addr - c->sp; + + /* update the IP cache: */ + if ((ret = ia64_get (c, c->loc[IA64_REG_IP], &ip)) < 0) + return ret; + c->ip = ip; + if (ip == 0) + /* end of frame-chain reached */ + return 0; + } + else + num_regs = (c->cfm >> 7) & 0x7f; /* size of locals */ + + if (!IA64_IS_NULL_LOC (c->loc[IA64_REG_BSP])) + { + ret = check_rbs_switch (c); + if (ret < 0) + return ret; + } + + c->bsp = rse_skip_regs (c->bsp, -num_regs); + + c->sp = c->psp; + c->abi_marker = 0; + + if (c->ip == prev_ip && c->sp == prev_sp && c->bsp == prev_bsp) + { + Dprintf ("%s: ip, sp, and bsp unchanged; stopping here (ip=0x%lx)\n", + __FUNCTION__, (long) ip); + return -UNW_EBADFRAME; + } + + /* as we unwind, the saved ar.unat becomes the primary unat: */ + c->loc[IA64_REG_PRI_UNAT_MEM] = c->loc[IA64_REG_UNAT]; + + /* restore the predicates: */ + ret = ia64_get (c, c->loc[IA64_REG_PR], &c->pr); + if (ret < 0) + return ret; + + c->pi_valid = 0; + return 0; +} + + +int +unw_step (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->ip); + + if ((ret = ia64_find_save_locs (c)) >= 0 + && (ret = update_frame_state (c)) >= 0) + ret = (c->ip == 0) ? 0 : 1; + + Debug (2, "returning %d (ip=0x%016lx)\n", ret, (unsigned long) c->ip); + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gtables.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gtables.c new file mode 100644 index 0000000..f5e8f2d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Gtables.c @@ -0,0 +1,731 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2001-2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include + +#include "unwind_i.h" + +#ifdef HAVE_IA64INTRIN_H +# include +#endif + +extern unw_addr_space_t _ULia64_local_addr_space; + +struct ia64_table_entry + { + uint64_t start_offset; + uint64_t end_offset; + uint64_t info_offset; + }; + +#ifdef UNW_LOCAL_ONLY + +static inline int +is_local_addr_space (unw_addr_space_t as) +{ + return 1; +} + +static inline int +read_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, void *arg) +{ + *valp = *(unw_word_t *) addr; + return 0; +} + +#else /* !UNW_LOCAL_ONLY */ + +static inline int +is_local_addr_space (unw_addr_space_t as) +{ + return as == unw_local_addr_space; +} + +static inline int +read_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, void *arg) +{ + unw_accessors_t *a = unw_get_accessors_int (as); + + return (*a->access_mem) (as, addr, valp, 0, arg); +} + +/* Helper macro for reading an ia64_table_entry from remote memory. */ +#define remote_read(addr, member) \ + (*a->access_mem) (as, (addr) + offsetof (struct ia64_table_entry, \ + member), &member, 0, arg) + +/* Lookup an unwind-table entry in remote memory. Returns 1 if an + entry is found, 0 if no entry is found, negative if an error + occurred reading remote memory. */ +static int +remote_lookup (unw_addr_space_t as, + unw_word_t table, size_t table_size, unw_word_t rel_ip, + struct ia64_table_entry *e, void *arg) +{ + unw_word_t e_addr = 0, start_offset, end_offset, info_offset; + unw_accessors_t *a = unw_get_accessors_int (as); + unsigned long lo, hi, mid; + int ret; + + /* do a binary search for right entry: */ + for (lo = 0, hi = table_size / sizeof (struct ia64_table_entry); lo < hi;) + { + mid = (lo + hi) / 2; + e_addr = table + mid * sizeof (struct ia64_table_entry); + if ((ret = remote_read (e_addr, start_offset)) < 0) + return ret; + + if (rel_ip < start_offset) + hi = mid; + else + { + if ((ret = remote_read (e_addr, end_offset)) < 0) + return ret; + + if (rel_ip >= end_offset) + lo = mid + 1; + else + break; + } + } + if (rel_ip < start_offset || rel_ip >= end_offset) + return 0; + e->start_offset = start_offset; + e->end_offset = end_offset; + + if ((ret = remote_read (e_addr, info_offset)) < 0) + return ret; + e->info_offset = info_offset; + return 1; +} + +HIDDEN void +tdep_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg) +{ + if (!pi->unwind_info) + return; + + if (is_local_addr_space (as)) + { + free (pi->unwind_info); + pi->unwind_info = NULL; + } +} + +unw_word_t +_Uia64_find_dyn_list (unw_addr_space_t as, unw_dyn_info_t *di, void *arg) +{ + unw_word_t hdr_addr, info_addr, hdr, directives, pers, cookie, off; + unw_word_t start_offset, end_offset, info_offset, segbase; + struct ia64_table_entry *e; + size_t table_size; + unw_word_t gp = di->gp; + int ret; + + switch (di->format) + { + case UNW_INFO_FORMAT_DYNAMIC: + default: + return 0; + + case UNW_INFO_FORMAT_TABLE: + e = (struct ia64_table_entry *) di->u.ti.table_data; + table_size = di->u.ti.table_len * sizeof (di->u.ti.table_data[0]); + segbase = di->u.ti.segbase; + if (table_size < sizeof (struct ia64_table_entry)) + return 0; + start_offset = e[0].start_offset; + end_offset = e[0].end_offset; + info_offset = e[0].info_offset; + break; + + case UNW_INFO_FORMAT_REMOTE_TABLE: + { + unw_accessors_t *a = unw_get_accessors_int (as); + unw_word_t e_addr = di->u.rti.table_data; + + table_size = di->u.rti.table_len * sizeof (unw_word_t); + segbase = di->u.rti.segbase; + if (table_size < sizeof (struct ia64_table_entry)) + return 0; + + if ( (ret = remote_read (e_addr, start_offset) < 0) + || (ret = remote_read (e_addr, end_offset) < 0) + || (ret = remote_read (e_addr, info_offset) < 0)) + return ret; + } + break; + } + + if (start_offset != end_offset) + /* dyn-list entry cover a zero-length "procedure" and should be + first entry (note: technically a binary could contain code + below the segment base, but this doesn't happen for normal + binaries and certainly doesn't happen when libunwind is a + separate shared object. For weird cases, the application may + have to provide its own (slower) version of this routine. */ + return 0; + + hdr_addr = info_offset + segbase; + info_addr = hdr_addr + 8; + + /* read the header word: */ + if ((ret = read_mem (as, hdr_addr, &hdr, arg)) < 0) + return ret; + + if (IA64_UNW_VER (hdr) != 1 + || IA64_UNW_FLAG_EHANDLER (hdr) || IA64_UNW_FLAG_UHANDLER (hdr)) + /* dyn-list entry must be version 1 and doesn't have ehandler + or uhandler */ + return 0; + + if (IA64_UNW_LENGTH (hdr) != 1) + /* dyn-list entry must consist of a single word of NOP directives */ + return 0; + + if ( ((ret = read_mem (as, info_addr, &directives, arg)) < 0) + || ((ret = read_mem (as, info_addr + 0x08, &pers, arg)) < 0) + || ((ret = read_mem (as, info_addr + 0x10, &cookie, arg)) < 0) + || ((ret = read_mem (as, info_addr + 0x18, &off, arg)) < 0)) + return 0; + + if (directives != 0 || pers != 0 + || (!as->big_endian && cookie != 0x7473696c2d6e7964ULL) + || ( as->big_endian && cookie != 0x64796e2d6c697374ULL)) + return 0; + + /* OK, we ran the gauntlet and found it: */ + return off + gp; +} + +#endif /* !UNW_LOCAL_ONLY */ + +static inline const struct ia64_table_entry * +lookup (struct ia64_table_entry *table, size_t table_size, unw_word_t rel_ip) +{ + const struct ia64_table_entry *e = 0; + unsigned long lo, hi, mid; + + /* do a binary search for right entry: */ + for (lo = 0, hi = table_size / sizeof (struct ia64_table_entry); lo < hi;) + { + mid = (lo + hi) / 2; + e = table + mid; + if (rel_ip < e->start_offset) + hi = mid; + else if (rel_ip >= e->end_offset) + lo = mid + 1; + else + break; + } + if (rel_ip < e->start_offset || rel_ip >= e->end_offset) + return NULL; + return e; +} + +int +unw_search_ia64_unwind_table (unw_addr_space_t as, unw_word_t ip, + unw_dyn_info_t *di, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + unw_word_t addr, hdr_addr, info_addr, info_end_addr, hdr, *wp; + const struct ia64_table_entry *e = NULL; + unw_word_t handler_offset, segbase = 0; + int ret, is_local; +#ifndef UNW_LOCAL_ONLY + struct ia64_table_entry ent; +#endif + + assert ((di->format == UNW_INFO_FORMAT_TABLE + || di->format == UNW_INFO_FORMAT_REMOTE_TABLE) + && (ip >= di->start_ip && ip < di->end_ip)); + + pi->flags = 0; + pi->unwind_info = 0; + pi->handler = 0; + + if (likely (di->format == UNW_INFO_FORMAT_TABLE)) + { + segbase = di->u.ti.segbase; + e = lookup ((struct ia64_table_entry *) di->u.ti.table_data, + di->u.ti.table_len * sizeof (unw_word_t), + ip - segbase); + } +#ifndef UNW_LOCAL_ONLY + else + { + segbase = di->u.rti.segbase; + if ((ret = remote_lookup (as, di->u.rti.table_data, + di->u.rti.table_len * sizeof (unw_word_t), + ip - segbase, &ent, arg)) < 0) + return ret; + if (ret) + e = &ent; + } +#endif + if (!e) + { + /* IP is inside this table's range, but there is no explicit + unwind info => use default conventions (i.e., this is NOT an + error). */ + memset (pi, 0, sizeof (*pi)); + pi->start_ip = 0; + pi->end_ip = 0; + pi->gp = di->gp; + pi->lsda = 0; + return 0; + } + + pi->start_ip = e->start_offset + segbase; + pi->end_ip = e->end_offset + segbase; + + hdr_addr = e->info_offset + segbase; + info_addr = hdr_addr + 8; + + /* Read the header word. Note: the actual unwind-info is always + assumed to reside in memory, independent of whether di->format is + UNW_INFO_FORMAT_TABLE or UNW_INFO_FORMAT_REMOTE_TABLE. */ + + if ((ret = read_mem (as, hdr_addr, &hdr, arg)) < 0) + return ret; + + if (IA64_UNW_VER (hdr) != 1) + { + Debug (1, "Unknown header version %ld (hdr word=0x%lx @ 0x%lx)\n", + IA64_UNW_VER (hdr), (unsigned long) hdr, + (unsigned long) hdr_addr); + return -UNW_EBADVERSION; + } + + info_end_addr = info_addr + 8 * IA64_UNW_LENGTH (hdr); + + is_local = is_local_addr_space (as); + + /* If we must have the unwind-info, return it. Also, if we are in + the local address-space, return the unwind-info because it's so + cheap to do so and it may come in handy later on. */ + if (need_unwind_info || is_local) + { + pi->unwind_info_size = 8 * IA64_UNW_LENGTH (hdr); + + if (is_local) + pi->unwind_info = (void *) (uintptr_t) info_addr; + else + { + /* Internalize unwind info. Note: since we're doing this + only for non-local address spaces, there is no + signal-safety issue and it is OK to use malloc()/free(). */ + pi->unwind_info = malloc (8 * IA64_UNW_LENGTH (hdr)); + if (!pi->unwind_info) + return -UNW_ENOMEM; + + wp = (unw_word_t *) pi->unwind_info; + for (addr = info_addr; addr < info_end_addr; addr += 8, ++wp) + { + if ((ret = read_mem (as, addr, wp, arg)) < 0) + { + free (pi->unwind_info); + return ret; + } + } + } + } + + if (IA64_UNW_FLAG_EHANDLER (hdr) || IA64_UNW_FLAG_UHANDLER (hdr)) + { + /* read the personality routine address (address is gp-relative): */ + if ((ret = read_mem (as, info_end_addr, &handler_offset, arg)) < 0) + return ret; + Debug (4, "handler ptr @ offset=%lx, gp=%lx\n", handler_offset, di->gp); + if ((read_mem (as, handler_offset + di->gp, &pi->handler, arg)) < 0) + return ret; + } + pi->lsda = info_end_addr + 8; + pi->gp = di->gp; + pi->format = di->format; + return 0; +} + +#ifndef UNW_REMOTE_ONLY + +# if defined(HAVE_DL_ITERATE_PHDR) +# include +# include + +# if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2) \ + || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && !defined(DT_CONFIG)) +# error You need GLIBC 2.2.4 or later on IA-64 Linux +# endif + +# if defined(HAVE_GETUNWIND) + extern unsigned long getunwind (void *buf, size_t len); +# else /* HAVE_GETUNWIND */ +# include +# include +# ifndef __NR_getunwind +# define __NR_getunwind 1215 +# endif + +static unsigned long +getunwind (void *buf, size_t len) +{ + return syscall (SYS_getunwind, buf, len); +} + +# endif /* HAVE_GETUNWIND */ + +static unw_dyn_info_t kernel_table; + +static int +get_kernel_table (unw_dyn_info_t *di) +{ + struct ia64_table_entry *ktab, *etab; + size_t size; + + Debug (16, "getting kernel table"); + + size = getunwind (NULL, 0); + ktab = sos_alloc (size); + if (!ktab) + { + Dprintf (__FILE__".%s: failed to allocate %zu bytes", + __FUNCTION__, size); + return -UNW_ENOMEM; + } + getunwind (ktab, size); + + /* Determine length of kernel's unwind table & relocate its entries. */ + for (etab = ktab; etab->start_offset; ++etab) + etab->info_offset += (uint64_t) ktab; + + di->format = UNW_INFO_FORMAT_TABLE; + di->gp = 0; + di->start_ip = ktab[0].start_offset; + di->end_ip = etab[-1].end_offset; + di->u.ti.name_ptr = (unw_word_t) ""; + di->u.ti.segbase = 0; + di->u.ti.table_len = ((char *) etab - (char *) ktab) / sizeof (unw_word_t); + di->u.ti.table_data = (unw_word_t *) ktab; + + Debug (16, "found table `%s': [%lx-%lx) segbase=%lx len=%lu\n", + (char *) di->u.ti.name_ptr, di->start_ip, di->end_ip, + di->u.ti.segbase, di->u.ti.table_len); + return 0; +} + +# ifndef UNW_LOCAL_ONLY + +/* This is exported for the benefit of libunwind-ptrace.a. */ +int +_Uia64_get_kernel_table (unw_dyn_info_t *di) +{ + int ret; + + if (!kernel_table.u.ti.table_data) + if ((ret = get_kernel_table (&kernel_table)) < 0) + return ret; + + memcpy (di, &kernel_table, sizeof (*di)); + return 0; +} + +# endif /* !UNW_LOCAL_ONLY */ + +static inline unsigned long +current_gp (void) +{ +# if defined(__GNUC__) && !defined(__INTEL_COMPILER) + register unsigned long gp __asm__("gp"); + return gp; +# elif HAVE_IA64INTRIN_H + return __getReg (_IA64_REG_GP); +# else +# error Implement me. +# endif +} + +static int +callback (struct dl_phdr_info *info, size_t size, void *ptr) +{ + unw_dyn_info_t *di = ptr; + const Elf64_Phdr *phdr, *p_unwind, *p_dynamic, *p_text; + long n; + Elf64_Addr load_base, segbase = 0; + + /* Make sure struct dl_phdr_info is at least as big as we need. */ + if (size < offsetof (struct dl_phdr_info, dlpi_phnum) + + sizeof (info->dlpi_phnum)) + return -1; + + Debug (16, "checking `%s' (load_base=%lx)\n", + info->dlpi_name, info->dlpi_addr); + + phdr = info->dlpi_phdr; + load_base = info->dlpi_addr; + p_text = NULL; + p_unwind = NULL; + p_dynamic = NULL; + + /* See if PC falls into one of the loaded segments. Find the unwind + segment at the same time. */ + for (n = info->dlpi_phnum; --n >= 0; phdr++) + { + if (phdr->p_type == PT_LOAD) + { + Elf64_Addr vaddr = phdr->p_vaddr + load_base; + if (di->u.ti.segbase >= vaddr + && di->u.ti.segbase < vaddr + phdr->p_memsz) + p_text = phdr; + } + else if (phdr->p_type == PT_IA_64_UNWIND) + p_unwind = phdr; + else if (phdr->p_type == PT_DYNAMIC) + p_dynamic = phdr; + } + if (!p_text || !p_unwind) + return 0; + + if (likely (p_unwind->p_vaddr >= p_text->p_vaddr + && p_unwind->p_vaddr < p_text->p_vaddr + p_text->p_memsz)) + /* normal case: unwind table is inside text segment */ + segbase = p_text->p_vaddr + load_base; + else + { + /* Special case: unwind table is in some other segment; this + happens for the Linux kernel's gate DSO, for example. */ + phdr = info->dlpi_phdr; + for (n = info->dlpi_phnum; --n >= 0; phdr++) + { + if (phdr->p_type == PT_LOAD && p_unwind->p_vaddr >= phdr->p_vaddr + && p_unwind->p_vaddr < phdr->p_vaddr + phdr->p_memsz) + { + segbase = phdr->p_vaddr + load_base; + break; + } + } + } + + if (p_dynamic) + { + /* For dynamicly linked executables and shared libraries, + DT_PLTGOT is the gp value for that object. */ + Elf64_Dyn *dyn = (Elf64_Dyn *)(p_dynamic->p_vaddr + load_base); + for (; dyn->d_tag != DT_NULL; ++dyn) + if (dyn->d_tag == DT_PLTGOT) + { + /* On IA-64, _DYNAMIC is writable and GLIBC has relocated it. */ + di->gp = dyn->d_un.d_ptr; + break; + } + } + else + /* Otherwise this is a static executable with no _DYNAMIC. + The gp is constant program-wide. */ + di->gp = current_gp(); + di->format = UNW_INFO_FORMAT_TABLE; + di->start_ip = p_text->p_vaddr + load_base; + di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz; + di->u.ti.name_ptr = (unw_word_t) info->dlpi_name; + di->u.ti.table_data = (void *) (p_unwind->p_vaddr + load_base); + di->u.ti.table_len = p_unwind->p_memsz / sizeof (unw_word_t); + di->u.ti.segbase = segbase; + + Debug (16, "found table `%s': segbase=%lx, len=%lu, gp=%lx, " + "table_data=%p\n", (char *) di->u.ti.name_ptr, di->u.ti.segbase, + di->u.ti.table_len, di->gp, di->u.ti.table_data); + return 1; +} + +# ifdef HAVE_DL_PHDR_REMOVALS_COUNTER + +static inline int +validate_cache (unw_addr_space_t as) +{ + /* Note: we don't need to serialize here with respect to + dl_iterate_phdr() because if somebody were to remove an object + that is required to complete the unwind on whose behalf we're + validating the cache here, we'd be hosed anyhow. What we're + guarding against here is the case where library FOO gets mapped, + unwind info for FOO gets cached, FOO gets unmapped, BAR gets + mapped in the place where FOO was and then we unwind across a + function in FOO. Since no thread can execute in BAR before FOO + has been removed, we are guaranteed that + dl_phdr_removals_counter() would have been incremented before we + get here. */ + unsigned long long removals = dl_phdr_removals_counter (); + + if (removals == as->shared_object_removals) + return 1; + + as->shared_object_removals = removals; + unw_flush_cache (as, 0, 0); + return -1; +} + +# else /* !HAVE_DL_PHDR_REMOVALS_COUNTER */ + +/* Check whether any phdrs have been removed since we last flushed the + cache. If so we flush the cache and return -1, if not, we do + nothing and return 1. */ + +static int +check_callback (struct dl_phdr_info *info, size_t size, void *ptr) +{ +# ifdef HAVE_STRUCT_DL_PHDR_INFO_DLPI_SUBS + unw_addr_space_t as = ptr; + + if (size < + offsetof (struct dl_phdr_info, dlpi_subs) + sizeof (info->dlpi_subs)) + /* It would be safer to flush the cache here, but that would + disable caching for older libc's which would be incompatible + with the behavior of older versions of libunwind so we return 1 + instead and hope nobody runs into stale cache info... */ + return 1; + + if (info->dlpi_subs == as->shared_object_removals) + return 1; + + as->shared_object_removals = info->dlpi_subs; + unw_flush_cache (as, 0, 0); + return -1; /* indicate that there were removals */ +# else + return 1; +# endif +} + +static inline int +validate_cache (unw_addr_space_t as) +{ + intrmask_t saved_mask; + int ret; + + SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask); + ret = dl_iterate_phdr (check_callback, as); + SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); + return ret; +} + +# endif /* HAVE_DL_PHDR_REMOVALS_COUNTER */ + +# elif defined(HAVE_DLMODINFO) + /* Support for HP-UX-style dlmodinfo() */ +# include + +static inline int +validate_cache (unw_addr_space_t as) +{ + return 1; +} + +# endif /* !HAVE_DLMODINFO */ + +HIDDEN int +tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, int need_unwind_info, void *arg) +{ +# if defined(HAVE_DL_ITERATE_PHDR) + unw_dyn_info_t di, *dip = &di; + intrmask_t saved_mask; + int ret; + + di.u.ti.segbase = ip; /* this is cheap... */ + + SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask); + ret = dl_iterate_phdr (callback, &di); + SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); + + if (ret <= 0) + { + if (!kernel_table.u.ti.table_data) + { + if ((ret = get_kernel_table (&kernel_table)) < 0) + return ret; + } + if (ip < kernel_table.start_ip || ip >= kernel_table.end_ip) + return -UNW_ENOINFO; + dip = &kernel_table; + } +# elif defined(HAVE_DLMODINFO) +# define UNWIND_TBL_32BIT 0x8000000000000000 + struct load_module_desc lmd; + unw_dyn_info_t di, *dip = &di; + struct unwind_header + { + uint64_t header_version; + uint64_t start_offset; + uint64_t end_offset; + } + *uhdr; + + if (!dlmodinfo (ip, &lmd, sizeof (lmd), NULL, 0, 0)) + return -UNW_ENOINFO; + + di.format = UNW_INFO_FORMAT_TABLE; + di.start_ip = lmd.text_base; + di.end_ip = lmd.text_base + lmd.text_size; + di.gp = lmd.linkage_ptr; + di.u.ti.name_ptr = 0; /* no obvious table-name available */ + di.u.ti.segbase = lmd.text_base; + + uhdr = (struct unwind_header *) lmd.unwind_base; + + if ((uhdr->header_version & ~UNWIND_TBL_32BIT) != 1 + && (uhdr->header_version & ~UNWIND_TBL_32BIT) != 2) + { + Debug (1, "encountered unknown unwind header version %ld\n", + (long) (uhdr->header_version & ~UNWIND_TBL_32BIT)); + return -UNW_EBADVERSION; + } + if (uhdr->header_version & UNWIND_TBL_32BIT) + { + Debug (1, "32-bit unwind tables are not supported yet\n"); + return -UNW_EINVAL; + } + + di.u.ti.table_data = (unw_word_t *) (di.u.ti.segbase + uhdr->start_offset); + di.u.ti.table_len = ((uhdr->end_offset - uhdr->start_offset) + / sizeof (unw_word_t)); + + Debug (16, "found table `%s': segbase=%lx, len=%lu, gp=%lx, " + "table_data=%p\n", (char *) di.u.ti.name_ptr, di.u.ti.segbase, + di.u.ti.table_len, di.gp, di.u.ti.table_data); +# endif + + /* now search the table: */ + return tdep_search_unwind_table (as, ip, dip, pi, need_unwind_info, arg); +} + +/* Returns 1 if the cache is up-to-date or -1 if the cache contained + stale data and had to be flushed. */ + +HIDDEN int +ia64_local_validate_cache (unw_addr_space_t as, void *arg) +{ + return validate_cache (as); +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lapply_reg_state.c new file mode 100644 index 0000000..7ebada4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lapply_reg_state.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gapply_reg_state.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lcreate_addr_space.c new file mode 100644 index 0000000..0f2dc6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lcreate_addr_space.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gcreate_addr_space.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lfind_unwind_table.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lfind_unwind_table.c new file mode 100644 index 0000000..68e269f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lfind_unwind_table.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gfind_unwind_table.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lget_proc_info.c new file mode 100644 index 0000000..69028b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lget_proc_info.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_proc_info.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lget_save_loc.c new file mode 100644 index 0000000..9ea048a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lget_save_loc.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_save_loc.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lglobal.c new file mode 100644 index 0000000..6d7b489 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lglobal.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gglobal.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linit.c new file mode 100644 index 0000000..e9abfdd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linit.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linit_local.c new file mode 100644 index 0000000..68a1687 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linit_local.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_local.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linit_remote.c new file mode 100644 index 0000000..58cb04a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linit_remote.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_remote.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linstall_cursor.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linstall_cursor.S new file mode 100644 index 0000000..8c72339 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Linstall_cursor.S @@ -0,0 +1,6 @@ +#define UNW_LOCAL_ONLY +#include "Ginstall_cursor.S" +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lis_signal_frame.c new file mode 100644 index 0000000..b9a7c4f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lis_signal_frame.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gis_signal_frame.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lparser.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lparser.c new file mode 100644 index 0000000..f23aaf4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lparser.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gparser.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lrbs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lrbs.c new file mode 100644 index 0000000..a91b5f2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lrbs.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Grbs.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lreg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lreg_states_iterate.c new file mode 100644 index 0000000..f1eb1e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lreg_states_iterate.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Greg_states_iterate.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lregs.c new file mode 100644 index 0000000..2c9c75c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lregs.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gregs.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lresume.c new file mode 100644 index 0000000..41a8cf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lresume.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gresume.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lscript.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lscript.c new file mode 100644 index 0000000..57b926b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lscript.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gscript.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lstep.c new file mode 100644 index 0000000..c1ac3c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Lstep.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gstep.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ltables.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ltables.c new file mode 100644 index 0000000..876b0aa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/Ltables.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gtables.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/NOTES b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/NOTES new file mode 100644 index 0000000..a5805e8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/NOTES @@ -0,0 +1,65 @@ +- the frame state consists of the following: + + - ip current instruction pointer + - sp current stack pointer value + - bsp current backing store pointer + - cfm current frame mask + + these are derived from the next younger (more deeply nested) frame + as follows: + + - ip == saved return-link (may be b0 or an alternate branch-reg) + - sp == if younger frame has a fixed-sized frame, sp + size-of-frame, + else saved sp + - cfm == saved ar.pfs + - bsp == if ar.bsp has been saved, saved ar.bsp, otherwise, + ar.bsp \ominus saved ar.pfs.pfm.sol + +The unwind cursor should represent the machine state as it existed at +the address contained in register ip. This state consists of the +*current* frame state and the save locations in the next younger +frame. + +An unwind script current takes the old save locations and updates them +for the next older frame. With the new setup, we need to update the +frame state first, without updating the other save locations. For this +to work, we need the following info: + + - save location of return-link + - save location of ar.pfs + - save location of bsp (if it has been saved) + - size of stack frame (fixed case) or save location of sp + + +setup: + + func: ... + ... + ... + br.call foo <-- call site + ... <-- ip + ... + +initial state: + + The unwind cursor represents the (preserved) machine state + as it existed at "ip". + + Evaluating the unwind descriptors for "ip" yields the following + info: + + - frame size at call site (or previous sp) + - what registers where saved where by func before + the call site was reached + + + Note that there is some procedure info that needs to be obtained + for the new "ip" which is contained in the unwind descriptors. + Specifically, the following is needed: + + - procedure's start address + - personality address + - pointer to language-specific data area + + This info is stored in a separate proc_info structure and needs + to be obtained right after running the unwind script for func. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/dyn_info_list.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/dyn_info_list.S new file mode 100644 index 0000000..31265f6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/dyn_info_list.S @@ -0,0 +1,26 @@ +#ifndef UNW_REMOTE_ONLY + +/* + * Create a special unwind-table entry which makes it easy for an + * unwinder to locate the dynamic registration list. The special + * entry covers address range [0-0) and is therefore guaranteed to be + * the first in the unwind-table. + */ + .global _U_dyn_info_list + .hidden _U_dyn_info_list + + .section .IA_64.unwind_info,"a","progbits" +.info: data8 (1<<48) | 1 /* v1, length==1 (8-byte word) */ + data8 0 /* 8 empty .prologue directives (nops) */ + data8 0 /* personality routine (ignored) */ + string "dyn-list" /* lsda */ + data8 @gprel(_U_dyn_info_list) + + .section .IA_64.unwind, "a", "progbits" + data8 0, 0, @segrel(.info) + +#endif +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/getcontext.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/getcontext.S new file mode 100644 index 0000000..d8da732 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/getcontext.S @@ -0,0 +1,177 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "ucontext_i.h" + +#define GR(n) (SC_GR + (n)*8) +#define BR(n) (SC_BR + (n)*8) +#define FR(n) (SC_FR + (n)*16) + +/* This should be compatible to the libc's getcontext(), except that + the sc->sc_mask field is always cleared and that the name is + prefixed with _Uia64_ so we don't step on the application's + name-space. */ + + .align 32 + .protected _Uia64_getcontext + .global _Uia64_getcontext + .proc _Uia64_getcontext +_Uia64_getcontext: + .prologue + alloc rPFS = ar.pfs, 1, 0, 0, 0 // M2 + mov rPR = pr // I0, 2 cycles + add r2 = GR(1), in0 // I1 + ;; + + .save ar.unat, rUNAT + mov.m rUNAT = ar.unat // M2, 5 cycles + .body + st8.spill [r2] = r1, (SC_FLAGS - GR(1)) // M3 + dep.z rFLAGS = -1, IA64_SC_FLAG_SYNCHRONOUS_BIT, 1 // I0, 1 cycle + ;; + + mov.m rRSC = ar.rsc // M2, 12 cyc. + st8 [r2] = rFLAGS, (SC_PR - SC_FLAGS) // M3 + add r3 = FR(2), in0 + ;; + + mov.m rBSP = ar.bsp // M2, 12 cyc. + st8 [r2] = rPR, (GR(12) - SC_PR) // M3 + add r8 = FR(16), in0 + ;; + + mov.m rFPSR = ar.fpsr // M2, 12 cyc. + st8.spill [r2] = r12, (GR(4) - GR(12)) // M3 + add r9 = FR(24), in0 + ;; + + stf.spill [r3] = f2 // M2 + stf.spill [r8] = f16 // M3 + add r3 = GR(7), in0 + ;; + + flushrs // M0 + stf.spill [r9] = f24, (FR(31) - FR(24)) // M2 + mov rB0 = b0 // I0, 2 cycles + ;; + + stf.spill [r9] = f31 // M2 + st8.spill [r2] = r4, (GR(5) - GR(4)) // M3, bank 1 + mov rB1 = b1 // I0, 2 cycles + ;; + +.mem.offset 0,0; st8.spill [r2] = r5, (GR(6) - GR(5)) // M4, bank 0 +.mem.offset 8,0; st8.spill [r3] = r7, (BR(0) - GR(7)) // M3, bank 0 + mov rB2 = b2 // I0, 2 cycles + ;; + + st8.spill [r2] = r6, (BR(1) - GR(6)) // M2, bank 1 + st8 [r3] = rB0, (BR(4) - BR(0)) // M3, bank 1 + mov rB4 = b4 // I0, 2 cycles + ;; + + mov.m rNAT = ar.unat // M2, 5 cycles + st8 [r2] = rB1, (BR(2) - BR(1)) // M3, bank 0 + mov rB3 = b3 + ;; + + st8 [r2] = rB2, (BR(3) - BR(2)) // M2, bank 1 + st8 [r3] = rB4, (SC_LC - BR(4)) // M3, bank 1 + mov rB5 = b5 // I0, 2 cycles + ;; + + and rTMP = ~0x3, rRSC // M0 + add rPOS = GR(0), in0 // rPOS <- &sc_gr[0] // M1 + mov.i rLC = ar.lc // I0, 2 cycles + ;; + + mov.m ar.rsc = rTMP // put RSE into lazy mode // M2, ? cycles + st8 [r2] = rB3, (BR(5) - BR(3)) // M3, bank 0 + extr.u rPOS = rPOS, 3, 6 // get NaT bitnr for r0 // I0 + ;; + + mov.m rRNAT = ar.rnat // M2, 5 cycles + st8 [r2] = rB5, (SC_PFS - BR(5)) // M3, bank 0 + sub rCPOS = 64, rPOS // I0 + ;; + + st8 [r2] = rPFS, (SC_UNAT - SC_PFS) // M2 + st8 [r3] = rLC, (SC_BSP - SC_LC) // M3 + shr.u rTMP = rNAT, rPOS // I0, 3 cycles + ;; + + st8 [r2] = rUNAT, (SC_FPSR - SC_UNAT) // M2 + st8 [r3] = rBSP // M3 + add r8 = FR(3), in0 + ;; + + st8 [r2] = rFPSR, (SC_RNAT - SC_FPSR) // M2 + stf.spill [r8] = f3, (FR(4) - FR(3)) // M3 + add r9 = FR(5), in0 + ;; + + stf.spill [r8] = f4, (FR(17) - FR(4)) // M2 + stf.spill [r9] = f5, (FR(19) - FR(5)) // M3 + shl rNAT = rNAT, rCPOS // I0, 3 cycles + ;; + + st8 [r2] = rRNAT, (SC_NAT - SC_RNAT) // M2 + stf.spill [r8] = f17, (FR(18) - FR(17)) // M3 + nop.i 0 + ;; + + stf.spill [r8] = f18, (FR(20) - FR(18)) // M2 + stf.spill [r9] = f19, (FR(21) - FR(19)) // M3 + nop.i 0 + ;; + + stf.spill [r8] = f20, (FR(22) - FR(20)) // M2 + stf.spill [r9] = f21, (FR(23) - FR(21)) // M3 + or rNAT = rNAT, rTMP // I0 + ;; + + st8 [r2] = rNAT // M2 + stf.spill [r8] = f22, (FR(25) - FR(22)) // M3 + ;; + stf.spill [r9] = f23, (FR(26) - FR(23)) // M2 + stf.spill [r8] = f25, (FR(27) - FR(25)) // M3 + ;; + stf.spill [r9] = f26, (FR(28) - FR(26)) // M2 + stf.spill [r8] = f27, (FR(29) - FR(27)) // M3 + ;; + mov.m ar.rsc = rRSC // restore RSE mode // M2 + stf.spill [r9] = f28, (FR(30) - FR(28)) // M3 + ;; + mov.m ar.unat = rUNAT // restore caller's UNaT // M2 + stf.spill [r8] = f29 // M3 + ;; + stf.spill [r9] = f30 // M2 + mov r8 = 0 + br.ret.sptk.many rp + .endp _Uia64_getcontext +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/init.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/init.h new file mode 100644 index 0000000..6628a1d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/init.h @@ -0,0 +1,132 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static ALWAYS_INLINE int +common_init (struct cursor *c, unw_word_t sp, unw_word_t bsp) +{ + unw_word_t bspstore, rbs_base; + int ret; + + if (c->as->caching_policy != UNW_CACHE_NONE) + /* ensure cache doesn't have any stale contents: */ + ia64_validate_cache (c->as, c->as_arg); + + c->cfm_loc = IA64_REG_LOC (c, UNW_IA64_CFM); + c->loc[IA64_REG_BSP] = IA64_NULL_LOC; + c->loc[IA64_REG_BSPSTORE] = IA64_REG_LOC (c, UNW_IA64_AR_BSPSTORE); + c->loc[IA64_REG_PFS] = IA64_REG_LOC (c, UNW_IA64_AR_PFS); + c->loc[IA64_REG_RNAT] = IA64_REG_LOC (c, UNW_IA64_AR_RNAT); + c->loc[IA64_REG_IP] = IA64_REG_LOC (c, UNW_IA64_IP); + c->loc[IA64_REG_PRI_UNAT_MEM] = IA64_NULL_LOC; /* no primary UNaT location */ + c->loc[IA64_REG_UNAT] = IA64_REG_LOC (c, UNW_IA64_AR_UNAT); + c->loc[IA64_REG_PR] = IA64_REG_LOC (c, UNW_IA64_PR); + c->loc[IA64_REG_LC] = IA64_REG_LOC (c, UNW_IA64_AR_LC); + c->loc[IA64_REG_FPSR] = IA64_REG_LOC (c, UNW_IA64_AR_FPSR); + + c->loc[IA64_REG_R4] = IA64_REG_LOC (c, UNW_IA64_GR + 4); + c->loc[IA64_REG_R5] = IA64_REG_LOC (c, UNW_IA64_GR + 5); + c->loc[IA64_REG_R6] = IA64_REG_LOC (c, UNW_IA64_GR + 6); + c->loc[IA64_REG_R7] = IA64_REG_LOC (c, UNW_IA64_GR + 7); + + c->loc[IA64_REG_NAT4] = IA64_REG_NAT_LOC (c, UNW_IA64_NAT + 4, &c->nat_bitnr[0]); + c->loc[IA64_REG_NAT5] = IA64_REG_NAT_LOC (c, UNW_IA64_NAT + 5, &c->nat_bitnr[1]); + c->loc[IA64_REG_NAT6] = IA64_REG_NAT_LOC (c, UNW_IA64_NAT + 6, &c->nat_bitnr[2]); + c->loc[IA64_REG_NAT7] = IA64_REG_NAT_LOC (c, UNW_IA64_NAT + 7, &c->nat_bitnr[3]); + + c->loc[IA64_REG_B1] = IA64_REG_LOC (c, UNW_IA64_BR + 1); + c->loc[IA64_REG_B2] = IA64_REG_LOC (c, UNW_IA64_BR + 2); + c->loc[IA64_REG_B3] = IA64_REG_LOC (c, UNW_IA64_BR + 3); + c->loc[IA64_REG_B4] = IA64_REG_LOC (c, UNW_IA64_BR + 4); + c->loc[IA64_REG_B5] = IA64_REG_LOC (c, UNW_IA64_BR + 5); + + c->loc[IA64_REG_F2] = IA64_FPREG_LOC (c, UNW_IA64_FR + 2); + c->loc[IA64_REG_F3] = IA64_FPREG_LOC (c, UNW_IA64_FR + 3); + c->loc[IA64_REG_F4] = IA64_FPREG_LOC (c, UNW_IA64_FR + 4); + c->loc[IA64_REG_F5] = IA64_FPREG_LOC (c, UNW_IA64_FR + 5); + c->loc[IA64_REG_F16] = IA64_FPREG_LOC (c, UNW_IA64_FR + 16); + c->loc[IA64_REG_F17] = IA64_FPREG_LOC (c, UNW_IA64_FR + 17); + c->loc[IA64_REG_F18] = IA64_FPREG_LOC (c, UNW_IA64_FR + 18); + c->loc[IA64_REG_F19] = IA64_FPREG_LOC (c, UNW_IA64_FR + 19); + c->loc[IA64_REG_F20] = IA64_FPREG_LOC (c, UNW_IA64_FR + 20); + c->loc[IA64_REG_F21] = IA64_FPREG_LOC (c, UNW_IA64_FR + 21); + c->loc[IA64_REG_F22] = IA64_FPREG_LOC (c, UNW_IA64_FR + 22); + c->loc[IA64_REG_F23] = IA64_FPREG_LOC (c, UNW_IA64_FR + 23); + c->loc[IA64_REG_F24] = IA64_FPREG_LOC (c, UNW_IA64_FR + 24); + c->loc[IA64_REG_F25] = IA64_FPREG_LOC (c, UNW_IA64_FR + 25); + c->loc[IA64_REG_F26] = IA64_FPREG_LOC (c, UNW_IA64_FR + 26); + c->loc[IA64_REG_F27] = IA64_FPREG_LOC (c, UNW_IA64_FR + 27); + c->loc[IA64_REG_F28] = IA64_FPREG_LOC (c, UNW_IA64_FR + 28); + c->loc[IA64_REG_F29] = IA64_FPREG_LOC (c, UNW_IA64_FR + 29); + c->loc[IA64_REG_F30] = IA64_FPREG_LOC (c, UNW_IA64_FR + 30); + c->loc[IA64_REG_F31] = IA64_FPREG_LOC (c, UNW_IA64_FR + 31); + + ret = ia64_get (c, c->loc[IA64_REG_IP], &c->ip); + if (ret < 0) + return ret; + + ret = ia64_get (c, c->cfm_loc, &c->cfm); + if (ret < 0) + return ret; + + ret = ia64_get (c, c->loc[IA64_REG_PR], &c->pr); + if (ret < 0) + return ret; + + c->sp = c->psp = sp; + c->bsp = bsp; + + ret = ia64_get (c, c->loc[IA64_REG_BSPSTORE], &bspstore); + if (ret < 0) + return ret; + + c->rbs_curr = c->rbs_left_edge = 0; + + /* Try to find a base of the register backing-store. We may default + to a reasonable value (e.g., half the address-space down from + bspstore). If the BSPSTORE looks corrupt, we fail. */ + if ((ret = rbs_get_base (c, bspstore, &rbs_base)) < 0) + return ret; + + c->rbs_area[0].end = bspstore; + c->rbs_area[0].size = bspstore - rbs_base; + c->rbs_area[0].rnat_loc = IA64_REG_LOC (c, UNW_IA64_AR_RNAT); + Debug (10, "initial rbs-area: [0x%llx-0x%llx), rnat@%s\n", + (long long) rbs_base, (long long) c->rbs_area[0].end, + ia64_strloc (c->rbs_area[0].rnat_loc)); + + c->pi.flags = 0; + + c->sigcontext_addr = 0; + c->abi_marker = 0; + c->last_abi_marker = 0; + + c->hint = 0; + c->prev_script = 0; + c->eh_valid_mask = 0; + c->pi_valid = 0; + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/longjmp.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/longjmp.S new file mode 100644 index 0000000..2a2f286 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/longjmp.S @@ -0,0 +1,42 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + .global _UI_longjmp_cont + + .align 32 + .proc longjmp_continuation +longjmp_continuation: +_UI_longjmp_cont: // non-function label for {sig,}longjmp.c + .prologue + .save rp, r15 + .body + mov rp = r15 + mov r8 = r16 + br.sptk.many rp + .endp longjmp_continuation +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/mk_cursor_i b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/mk_cursor_i new file mode 100644 index 0000000..9211f91 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/mk_cursor_i @@ -0,0 +1,7 @@ +#!/bin/sh +test -z "$1" && exit 1 +echo "/* GENERATED */" +echo "#ifndef cursor_i_h" +echo "#define cursor_i_h" +sed -ne 's/^->"\(\S*\)" \(\d*\)/#define \1 \2/p' < $1 || exit $? +echo "#endif" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/offsets.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/offsets.h new file mode 100644 index 0000000..5ab7f8b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/offsets.h @@ -0,0 +1,137 @@ +/* Linux-specific definitions: */ + +/* Define various structure offsets to simplify cross-compilation. */ + +/* The first three 64-bit words in a signal frame contain the signal + number, siginfo pointer, and sigcontext pointer passed to the + signal handler. We use this to locate the sigcontext pointer. */ + +#define LINUX_SIGFRAME_ARG2_OFF 0x10 + +#define LINUX_SC_FLAGS_OFF 0x000 +#define LINUX_SC_NAT_OFF 0x008 +#define LINUX_SC_STACK_OFF 0x010 +#define LINUX_SC_IP_OFF 0x028 +#define LINUX_SC_CFM_OFF 0x030 +#define LINUX_SC_UM_OFF 0x038 +#define LINUX_SC_AR_RSC_OFF 0x040 +#define LINUX_SC_AR_BSP_OFF 0x048 +#define LINUX_SC_AR_RNAT_OFF 0x050 +#define LINUX_SC_AR_CCV 0x058 +#define LINUX_SC_AR_UNAT_OFF 0x060 +#define LINUX_SC_AR_FPSR_OFF 0x068 +#define LINUX_SC_AR_PFS_OFF 0x070 +#define LINUX_SC_AR_LC_OFF 0x078 +#define LINUX_SC_PR_OFF 0x080 +#define LINUX_SC_BR_OFF 0x088 +#define LINUX_SC_GR_OFF 0x0c8 +#define LINUX_SC_FR_OFF 0x1d0 +#define LINUX_SC_RBS_BASE_OFF 0x9d0 +#define LINUX_SC_LOADRS_OFF 0x9d8 +#define LINUX_SC_AR_CSD_OFF 0x9e0 +#define LINUX_SC_AR_SSD_OFF 0x9e8 +#define LINUX_SC_MASK 0xa50 + +/* Layout of old Linux kernel interrupt frame (struct pt_regs). */ + +#define LINUX_OLD_PT_IPSR_OFF 0x000 +#define LINUX_OLD_PT_IIP_OFF 0x008 +#define LINUX_OLD_PT_IFS_OFF 0x010 +#define LINUX_OLD_PT_UNAT_OFF 0x018 +#define LINUX_OLD_PT_PFS_OFF 0x020 +#define LINUX_OLD_PT_RSC_OFF 0x028 +#define LINUX_OLD_PT_RNAT_OFF 0x030 +#define LINUX_OLD_PT_BSPSTORE_OFF 0x038 +#define LINUX_OLD_PT_PR_OFF 0x040 +#define LINUX_OLD_PT_B6_OFF 0x048 +#define LINUX_OLD_PT_LOADRS_OFF 0x050 +#define LINUX_OLD_PT_R1_OFF 0x058 +#define LINUX_OLD_PT_R2_OFF 0x060 +#define LINUX_OLD_PT_R3_OFF 0x068 +#define LINUX_OLD_PT_R12_OFF 0x070 +#define LINUX_OLD_PT_R13_OFF 0x078 +#define LINUX_OLD_PT_R14_OFF 0x080 +#define LINUX_OLD_PT_R15_OFF 0x088 +#define LINUX_OLD_PT_R8_OFF 0x090 +#define LINUX_OLD_PT_R9_OFF 0x098 +#define LINUX_OLD_PT_R10_OFF 0x0a0 +#define LINUX_OLD_PT_R11_OFF 0x0a8 +#define LINUX_OLD_PT_R16_OFF 0x0b0 +#define LINUX_OLD_PT_R17_OFF 0x0b8 +#define LINUX_OLD_PT_R18_OFF 0x0c0 +#define LINUX_OLD_PT_R19_OFF 0x0c8 +#define LINUX_OLD_PT_R20_OFF 0x0d0 +#define LINUX_OLD_PT_R21_OFF 0x0d8 +#define LINUX_OLD_PT_R22_OFF 0x0e0 +#define LINUX_OLD_PT_R23_OFF 0x0e8 +#define LINUX_OLD_PT_R24_OFF 0x0f0 +#define LINUX_OLD_PT_R25_OFF 0x0f8 +#define LINUX_OLD_PT_R26_OFF 0x100 +#define LINUX_OLD_PT_R27_OFF 0x108 +#define LINUX_OLD_PT_R28_OFF 0x110 +#define LINUX_OLD_PT_R29_OFF 0x118 +#define LINUX_OLD_PT_R30_OFF 0x120 +#define LINUX_OLD_PT_R31_OFF 0x128 +#define LINUX_OLD_PT_CCV_OFF 0x130 +#define LINUX_OLD_PT_FPSR_OFF 0x138 +#define LINUX_OLD_PT_B0_OFF 0x140 +#define LINUX_OLD_PT_B7_OFF 0x148 +#define LINUX_OLD_PT_F6_OFF 0x150 +#define LINUX_OLD_PT_F7_OFF 0x160 +#define LINUX_OLD_PT_F8_OFF 0x170 +#define LINUX_OLD_PT_F9_OFF 0x180 + +/* Layout of new Linux kernel interrupt frame (struct pt_regs). */ + +#define LINUX_PT_B6_OFF 0 +#define LINUX_PT_B7_OFF 8 +#define LINUX_PT_CSD_OFF 16 +#define LINUX_PT_SSD_OFF 24 +#define LINUX_PT_R8_OFF 32 +#define LINUX_PT_R9_OFF 40 +#define LINUX_PT_R10_OFF 48 +#define LINUX_PT_R11_OFF 56 +#define LINUX_PT_IPSR_OFF 64 +#define LINUX_PT_IIP_OFF 72 +#define LINUX_PT_IFS_OFF 80 +#define LINUX_PT_UNAT_OFF 88 +#define LINUX_PT_PFS_OFF 96 +#define LINUX_PT_RSC_OFF 104 +#define LINUX_PT_RNAT_OFF 112 +#define LINUX_PT_BSPSTORE_OFF 120 +#define LINUX_PT_PR_OFF 128 +#define LINUX_PT_B0_OFF 136 +#define LINUX_PT_LOADRS_OFF 144 +#define LINUX_PT_R1_OFF 152 +#define LINUX_PT_R12_OFF 160 +#define LINUX_PT_R13_OFF 168 +#define LINUX_PT_FPSR_OFF 176 +#define LINUX_PT_R15_OFF 184 +#define LINUX_PT_R14_OFF 192 +#define LINUX_PT_R2_OFF 200 +#define LINUX_PT_R3_OFF 208 +#define LINUX_PT_R16_OFF 216 +#define LINUX_PT_R17_OFF 224 +#define LINUX_PT_R18_OFF 232 +#define LINUX_PT_R19_OFF 240 +#define LINUX_PT_R20_OFF 248 +#define LINUX_PT_R21_OFF 256 +#define LINUX_PT_R22_OFF 264 +#define LINUX_PT_R23_OFF 272 +#define LINUX_PT_R24_OFF 280 +#define LINUX_PT_R25_OFF 288 +#define LINUX_PT_R26_OFF 296 +#define LINUX_PT_R27_OFF 304 +#define LINUX_PT_R28_OFF 312 +#define LINUX_PT_R29_OFF 320 +#define LINUX_PT_R30_OFF 328 +#define LINUX_PT_R31_OFF 336 +#define LINUX_PT_CCV_OFF 344 +#define LINUX_PT_F6_OFF 352 +#define LINUX_PT_F7_OFF 368 +#define LINUX_PT_F8_OFF 384 +#define LINUX_PT_F9_OFF 400 +#define LINUX_PT_F10_OFF 416 +#define LINUX_PT_F11_OFF 432 + +#define LINUX_PT_P_NONSYS 5 /* must match pNonSys in entry.h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/regname.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/regname.c new file mode 100644 index 0000000..3636df8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/regname.c @@ -0,0 +1,189 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Logically, we like to think of the stack as a contiguous region of +memory. Unfortunately, this logical view doesn't work for the +register backing store, because the RSE is an asynchronous engine and +because UNIX/Linux allow for stack-switching via sigaltstack(2). +Specifically, this means that any given stacked register may or may +not be backed up by memory in the current stack. If not, then the +backing memory may be found in any of the "more inner" (younger) +stacks. The routines in this file help manage the discontiguous +nature of the register backing store. The routines are completely +independent of UNIX/Linux, but each stack frame that switches the +backing store is expected to reserve 4 words for use by libunwind. For +example, in the Linux sigcontext, sc_fr[0] and sc_fr[1] serve this +purpose. */ + +#include "libunwind_i.h" + +/* Maintain the register names as a single string to keep the number + of dynamic relocations in the shared object to a minimum. */ + +#define regname_len 9 +#define regname_str \ + "r0\0\0\0\0\0\0\0r1\0\0\0\0\0\0\0r2\0\0\0\0\0\0\0r3\0\0\0\0\0\0\0" \ + "r4\0\0\0\0\0\0\0r5\0\0\0\0\0\0\0r6\0\0\0\0\0\0\0r7\0\0\0\0\0\0\0" \ + "r8\0\0\0\0\0\0\0r9\0\0\0\0\0\0\0r10\0\0\0\0\0\0r11\0\0\0\0\0\0" \ + "r12\0\0\0\0\0\0r13\0\0\0\0\0\0r14\0\0\0\0\0\0r15\0\0\0\0\0\0" \ + "r16\0\0\0\0\0\0r17\0\0\0\0\0\0r18\0\0\0\0\0\0r19\0\0\0\0\0\0" \ + "r20\0\0\0\0\0\0r21\0\0\0\0\0\0r22\0\0\0\0\0\0r23\0\0\0\0\0\0" \ + "r24\0\0\0\0\0\0r25\0\0\0\0\0\0r26\0\0\0\0\0\0r27\0\0\0\0\0\0" \ + "r28\0\0\0\0\0\0r29\0\0\0\0\0\0r30\0\0\0\0\0\0r31\0\0\0\0\0\0" \ + "r32\0\0\0\0\0\0r33\0\0\0\0\0\0r34\0\0\0\0\0\0r35\0\0\0\0\0\0" \ + "r36\0\0\0\0\0\0r37\0\0\0\0\0\0r38\0\0\0\0\0\0r39\0\0\0\0\0\0" \ + "r40\0\0\0\0\0\0r41\0\0\0\0\0\0r42\0\0\0\0\0\0r43\0\0\0\0\0\0" \ + "r44\0\0\0\0\0\0r45\0\0\0\0\0\0r46\0\0\0\0\0\0r47\0\0\0\0\0\0" \ + "r48\0\0\0\0\0\0r49\0\0\0\0\0\0r50\0\0\0\0\0\0r51\0\0\0\0\0\0" \ + "r52\0\0\0\0\0\0r53\0\0\0\0\0\0r54\0\0\0\0\0\0r55\0\0\0\0\0\0" \ + "r56\0\0\0\0\0\0r57\0\0\0\0\0\0r58\0\0\0\0\0\0r59\0\0\0\0\0\0" \ + "r60\0\0\0\0\0\0r61\0\0\0\0\0\0r62\0\0\0\0\0\0r63\0\0\0\0\0\0" \ + "r64\0\0\0\0\0\0r65\0\0\0\0\0\0r66\0\0\0\0\0\0r67\0\0\0\0\0\0" \ + "r68\0\0\0\0\0\0r69\0\0\0\0\0\0r70\0\0\0\0\0\0r71\0\0\0\0\0\0" \ + "r72\0\0\0\0\0\0r73\0\0\0\0\0\0r74\0\0\0\0\0\0r75\0\0\0\0\0\0" \ + "r76\0\0\0\0\0\0r77\0\0\0\0\0\0r78\0\0\0\0\0\0r79\0\0\0\0\0\0" \ + "r80\0\0\0\0\0\0r81\0\0\0\0\0\0r82\0\0\0\0\0\0r83\0\0\0\0\0\0" \ + "r84\0\0\0\0\0\0r85\0\0\0\0\0\0r86\0\0\0\0\0\0r87\0\0\0\0\0\0" \ + "r88\0\0\0\0\0\0r89\0\0\0\0\0\0r90\0\0\0\0\0\0r91\0\0\0\0\0\0" \ + "r92\0\0\0\0\0\0r93\0\0\0\0\0\0r94\0\0\0\0\0\0r95\0\0\0\0\0\0" \ + "r96\0\0\0\0\0\0r97\0\0\0\0\0\0r98\0\0\0\0\0\0r99\0\0\0\0\0\0" \ + "r100\0\0\0\0\0r101\0\0\0\0\0r102\0\0\0\0\0r103\0\0\0\0\0" \ + "r104\0\0\0\0\0r105\0\0\0\0\0r106\0\0\0\0\0r107\0\0\0\0\0" \ + "r108\0\0\0\0\0r109\0\0\0\0\0r110\0\0\0\0\0r111\0\0\0\0\0" \ + "r112\0\0\0\0\0r113\0\0\0\0\0r114\0\0\0\0\0r115\0\0\0\0\0" \ + "r116\0\0\0\0\0r117\0\0\0\0\0r118\0\0\0\0\0r119\0\0\0\0\0" \ + "r120\0\0\0\0\0r121\0\0\0\0\0r122\0\0\0\0\0r123\0\0\0\0\0" \ + "r124\0\0\0\0\0r125\0\0\0\0\0r126\0\0\0\0\0r127\0\0\0\0\0" \ + "nat0\0\0\0\0\0nat1\0\0\0\0\0nat2\0\0\0\0\0nat3\0\0\0\0\0" \ + "nat4\0\0\0\0\0nat5\0\0\0\0\0nat6\0\0\0\0\0nat7\0\0\0\0\0" \ + "nat8\0\0\0\0\0nat9\0\0\0\0\0nat10\0\0\0\0nat11\0\0\0\0" \ + "nat12\0\0\0\0nat13\0\0\0\0nat14\0\0\0\0nat15\0\0\0\0" \ + "nat16\0\0\0\0nat17\0\0\0\0nat18\0\0\0\0nat19\0\0\0\0" \ + "nat20\0\0\0\0nat21\0\0\0\0nat22\0\0\0\0nat23\0\0\0\0" \ + "nat24\0\0\0\0nat25\0\0\0\0nat26\0\0\0\0nat27\0\0\0\0" \ + "nat28\0\0\0\0nat29\0\0\0\0nat30\0\0\0\0nat31\0\0\0\0" \ + "nat32\0\0\0\0nat33\0\0\0\0nat34\0\0\0\0nat35\0\0\0\0" \ + "nat36\0\0\0\0nat37\0\0\0\0nat38\0\0\0\0nat39\0\0\0\0" \ + "nat40\0\0\0\0nat41\0\0\0\0nat42\0\0\0\0nat43\0\0\0\0" \ + "nat44\0\0\0\0nat45\0\0\0\0nat46\0\0\0\0nat47\0\0\0\0" \ + "nat48\0\0\0\0nat49\0\0\0\0nat50\0\0\0\0nat51\0\0\0\0" \ + "nat52\0\0\0\0nat53\0\0\0\0nat54\0\0\0\0nat55\0\0\0\0" \ + "nat56\0\0\0\0nat57\0\0\0\0nat58\0\0\0\0nat59\0\0\0\0" \ + "nat60\0\0\0\0nat61\0\0\0\0nat62\0\0\0\0nat63\0\0\0\0" \ + "nat64\0\0\0\0nat65\0\0\0\0nat66\0\0\0\0nat67\0\0\0\0" \ + "nat68\0\0\0\0nat69\0\0\0\0nat70\0\0\0\0nat71\0\0\0\0" \ + "nat72\0\0\0\0nat73\0\0\0\0nat74\0\0\0\0nat75\0\0\0\0" \ + "nat76\0\0\0\0nat77\0\0\0\0nat78\0\0\0\0nat79\0\0\0\0" \ + "nat80\0\0\0\0nat81\0\0\0\0nat82\0\0\0\0nat83\0\0\0\0" \ + "nat84\0\0\0\0nat85\0\0\0\0nat86\0\0\0\0nat87\0\0\0\0" \ + "nat88\0\0\0\0nat89\0\0\0\0nat90\0\0\0\0nat91\0\0\0\0" \ + "nat92\0\0\0\0nat93\0\0\0\0nat94\0\0\0\0nat95\0\0\0\0" \ + "nat96\0\0\0\0nat97\0\0\0\0nat98\0\0\0\0nat99\0\0\0\0" \ + "nat100\0\0\0nat101\0\0\0nat102\0\0\0nat103\0\0\0" \ + "nat104\0\0\0nat105\0\0\0nat106\0\0\0nat107\0\0\0" \ + "nat108\0\0\0nat109\0\0\0nat110\0\0\0nat111\0\0\0" \ + "nat112\0\0\0nat113\0\0\0nat114\0\0\0nat115\0\0\0" \ + "nat116\0\0\0nat117\0\0\0nat118\0\0\0nat119\0\0\0" \ + "nat120\0\0\0nat121\0\0\0nat122\0\0\0nat123\0\0\0" \ + "nat124\0\0\0nat125\0\0\0nat126\0\0\0nat127\0\0\0" \ + "f0\0\0\0\0\0\0\0f1\0\0\0\0\0\0\0f2\0\0\0\0\0\0\0f3\0\0\0\0\0\0\0" \ + "f4\0\0\0\0\0\0\0f5\0\0\0\0\0\0\0f6\0\0\0\0\0\0\0f7\0\0\0\0\0\0\0" \ + "f8\0\0\0\0\0\0\0f9\0\0\0\0\0\0\0f10\0\0\0\0\0\0f11\0\0\0\0\0\0" \ + "f12\0\0\0\0\0\0f13\0\0\0\0\0\0f14\0\0\0\0\0\0f15\0\0\0\0\0\0" \ + "f16\0\0\0\0\0\0f17\0\0\0\0\0\0f18\0\0\0\0\0\0f19\0\0\0\0\0\0" \ + "f20\0\0\0\0\0\0f21\0\0\0\0\0\0f22\0\0\0\0\0\0f23\0\0\0\0\0\0" \ + "f24\0\0\0\0\0\0f25\0\0\0\0\0\0f26\0\0\0\0\0\0f27\0\0\0\0\0\0" \ + "f28\0\0\0\0\0\0f29\0\0\0\0\0\0f30\0\0\0\0\0\0f31\0\0\0\0\0\0" \ + "f32\0\0\0\0\0\0f33\0\0\0\0\0\0f34\0\0\0\0\0\0f35\0\0\0\0\0\0" \ + "f36\0\0\0\0\0\0f37\0\0\0\0\0\0f38\0\0\0\0\0\0f39\0\0\0\0\0\0" \ + "f40\0\0\0\0\0\0f41\0\0\0\0\0\0f42\0\0\0\0\0\0f43\0\0\0\0\0\0" \ + "f44\0\0\0\0\0\0f45\0\0\0\0\0\0f46\0\0\0\0\0\0f47\0\0\0\0\0\0" \ + "f48\0\0\0\0\0\0f49\0\0\0\0\0\0f50\0\0\0\0\0\0f51\0\0\0\0\0\0" \ + "f52\0\0\0\0\0\0f53\0\0\0\0\0\0f54\0\0\0\0\0\0f55\0\0\0\0\0\0" \ + "f56\0\0\0\0\0\0f57\0\0\0\0\0\0f58\0\0\0\0\0\0f59\0\0\0\0\0\0" \ + "f60\0\0\0\0\0\0f61\0\0\0\0\0\0f62\0\0\0\0\0\0f63\0\0\0\0\0\0" \ + "f64\0\0\0\0\0\0f65\0\0\0\0\0\0f66\0\0\0\0\0\0f67\0\0\0\0\0\0" \ + "f68\0\0\0\0\0\0f69\0\0\0\0\0\0f70\0\0\0\0\0\0f71\0\0\0\0\0\0" \ + "f72\0\0\0\0\0\0f73\0\0\0\0\0\0f74\0\0\0\0\0\0f75\0\0\0\0\0\0" \ + "f76\0\0\0\0\0\0f77\0\0\0\0\0\0f78\0\0\0\0\0\0f79\0\0\0\0\0\0" \ + "f80\0\0\0\0\0\0f81\0\0\0\0\0\0f82\0\0\0\0\0\0f83\0\0\0\0\0\0" \ + "f84\0\0\0\0\0\0f85\0\0\0\0\0\0f86\0\0\0\0\0\0f87\0\0\0\0\0\0" \ + "f88\0\0\0\0\0\0f89\0\0\0\0\0\0f90\0\0\0\0\0\0f91\0\0\0\0\0\0" \ + "f92\0\0\0\0\0\0f93\0\0\0\0\0\0f94\0\0\0\0\0\0f95\0\0\0\0\0\0" \ + "f96\0\0\0\0\0\0f97\0\0\0\0\0\0f98\0\0\0\0\0\0f99\0\0\0\0\0\0" \ + "f100\0\0\0\0\0f101\0\0\0\0\0f102\0\0\0\0\0f103\0\0\0\0\0" \ + "f104\0\0\0\0\0f105\0\0\0\0\0f106\0\0\0\0\0f107\0\0\0\0\0" \ + "f108\0\0\0\0\0f109\0\0\0\0\0f110\0\0\0\0\0f111\0\0\0\0\0" \ + "f112\0\0\0\0\0f113\0\0\0\0\0f114\0\0\0\0\0f115\0\0\0\0\0" \ + "f116\0\0\0\0\0f117\0\0\0\0\0f118\0\0\0\0\0f119\0\0\0\0\0" \ + "f120\0\0\0\0\0f121\0\0\0\0\0f122\0\0\0\0\0f123\0\0\0\0\0" \ + "f124\0\0\0\0\0f125\0\0\0\0\0f126\0\0\0\0\0f127\0\0\0\0\0" \ + "ar0\0\0\0\0\0\0ar1\0\0\0\0\0\0ar2\0\0\0\0\0\0ar3\0\0\0\0\0\0" \ + "ar4\0\0\0\0\0\0ar5\0\0\0\0\0\0ar6\0\0\0\0\0\0ar7\0\0\0\0\0\0" \ + "ar8\0\0\0\0\0\0ar9\0\0\0\0\0\0ar10\0\0\0\0\0ar11\0\0\0\0\0" \ + "ar12\0\0\0\0\0ar13\0\0\0\0\0ar14\0\0\0\0\0ar15\0\0\0\0\0" \ + "rsc\0\0\0\0\0\0bsp\0\0\0\0\0\0bspstore\0rnat\0\0\0\0\0" \ + "ar20\0\0\0\0\0ar21\0\0\0\0\0ar22\0\0\0\0\0ar23\0\0\0\0\0" \ + "ar24\0\0\0\0\0ar25\0\0\0\0\0ar26\0\0\0\0\0ar27\0\0\0\0\0" \ + "ar28\0\0\0\0\0ar29\0\0\0\0\0ar30\0\0\0\0\0ar31\0\0\0\0\0" \ + "ccv\0\0\0\0\0\0ar33\0\0\0\0\0ar34\0\0\0\0\0ar35\0\0\0\0\0" \ + "unat\0\0\0\0\0ar37\0\0\0\0\0ar38\0\0\0\0\0ar39\0\0\0\0\0" \ + "fpsr\0\0\0\0\0ar41\0\0\0\0\0ar42\0\0\0\0\0ar43\0\0\0\0\0" \ + "ar44\0\0\0\0\0ar45\0\0\0\0\0ar46\0\0\0\0\0ar47\0\0\0\0\0" \ + "ar48\0\0\0\0\0ar49\0\0\0\0\0ar50\0\0\0\0\0ar51\0\0\0\0\0" \ + "ar52\0\0\0\0\0ar53\0\0\0\0\0ar54\0\0\0\0\0ar55\0\0\0\0\0" \ + "ar56\0\0\0\0\0ar57\0\0\0\0\0ar58\0\0\0\0\0ar59\0\0\0\0\0" \ + "ar60\0\0\0\0\0ar61\0\0\0\0\0ar62\0\0\0\0\0ar63\0\0\0\0\0" \ + "pfs\0\0\0\0\0\0lc\0\0\0\0\0\0\0ec\0\0\0\0\0\0\0ar67\0\0\0\0\0" \ + "ar68\0\0\0\0\0ar69\0\0\0\0\0ar70\0\0\0\0\0ar71\0\0\0\0\0" \ + "ar72\0\0\0\0\0ar73\0\0\0\0\0ar74\0\0\0\0\0ar75\0\0\0\0\0" \ + "ar76\0\0\0\0\0ar77\0\0\0\0\0ar78\0\0\0\0\0ar79\0\0\0\0\0" \ + "ar80\0\0\0\0\0ar81\0\0\0\0\0ar82\0\0\0\0\0ar83\0\0\0\0\0" \ + "ar84\0\0\0\0\0ar85\0\0\0\0\0ar86\0\0\0\0\0ar87\0\0\0\0\0" \ + "ar88\0\0\0\0\0ar89\0\0\0\0\0ar90\0\0\0\0\0ar91\0\0\0\0\0" \ + "ar92\0\0\0\0\0ar93\0\0\0\0\0ar94\0\0\0\0\0ar95\0\0\0\0\0" \ + "ar96\0\0\0\0\0ar97\0\0\0\0\0ar98\0\0\0\0\0ar99\0\0\0\0\0" \ + "ar100\0\0\0\0ar101\0\0\0\0ar102\0\0\0\0ar103\0\0\0\0" \ + "ar104\0\0\0\0ar105\0\0\0\0ar106\0\0\0\0ar107\0\0\0\0" \ + "ar108\0\0\0\0ar109\0\0\0\0ar110\0\0\0\0ar111\0\0\0\0" \ + "ar112\0\0\0\0ar113\0\0\0\0ar114\0\0\0\0ar115\0\0\0\0" \ + "ar116\0\0\0\0ar117\0\0\0\0ar118\0\0\0\0ar119\0\0\0\0" \ + "ar120\0\0\0\0ar121\0\0\0\0ar122\0\0\0\0ar123\0\0\0\0" \ + "ar124\0\0\0\0ar125\0\0\0\0ar126\0\0\0\0ar127\0\0\0\0" \ + "rp\0\0\0\0\0\0\0b1\0\0\0\0\0\0\0b2\0\0\0\0\0\0\0b3\0\0\0\0\0\0\0" \ + "b4\0\0\0\0\0\0\0b5\0\0\0\0\0\0\0b6\0\0\0\0\0\0\0b7\0\0\0\0\0\0\0" \ + "pr\0\0\0\0\0\0\0cfm\0\0\0\0\0\0bsp\0\0\0\0\0\0ip\0\0\0\0\0\0\0" \ + "sp\0\0\0\0\0\0\0" + +#define NREGS ((int) (sizeof (regname_str) - 1) / regname_len) + +const char * +unw_regname (unw_regnum_t reg) +{ + if (reg < NREGS) + return regname_str + reg * regname_len; + else + return "???"; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/regs.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/regs.h new file mode 100644 index 0000000..a22a818 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/regs.h @@ -0,0 +1,73 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +/* Apply rotation to a general register. REG must be in the range 0-127. */ + +static inline int +rotate_gr (struct cursor *c, int reg) +{ + unsigned int rrb_gr, sor; + int preg; + + sor = 8 * ((c->cfm >> 14) & 0xf); + rrb_gr = (c->cfm >> 18) & 0x7f; + + if ((unsigned) (reg - 32) >= sor) + preg = reg; + else + { + preg = reg + rrb_gr; /* apply rotation */ + if ((unsigned) (preg - 32) >= sor) + preg -= sor; /* wrap around */ + } + if (sor) + Debug (15, "sor=%u rrb.gr=%u, r%d -> r%d\n", sor, rrb_gr, reg, preg); + return preg; +} + +/* Apply rotation to a floating-point register. The number REG must + be in the range of 0-127. */ + +static inline int +rotate_fr (struct cursor *c, int reg) +{ + unsigned int rrb_fr; + int preg; + + rrb_fr = (c->cfm >> 25) & 0x7f; + if (reg < 32) + preg = reg; /* register not part of the rotating partition */ + else + { + preg = reg + rrb_fr; /* apply rotation */ + if (preg > 127) + preg -= 96; /* wrap around */ + } + if (rrb_fr) + Debug (15, "rrb.fr=%u, f%d -> f%d\n", rrb_fr, reg, preg); + return preg; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/setjmp.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/setjmp.S new file mode 100644 index 0000000..384615b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/setjmp.S @@ -0,0 +1,51 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "jmpbuf.h" + + .align 32 + + .global _setjmp + + .proc _setjmp + +_setjmp: + mov r2 = ar.bsp + st8 [r32] = r12 // jmp_buf[JB_SP] = sp + mov r3 = rp + + adds r16 = JB_RP*8, r32 + adds r17 = JB_BSP*8, r32 + mov r8 = 0 + ;; + st8 [r16] = r3 // jmp_buf[JB_RP] = rp + st8 [r17] = r2 // jmp_buf[JB_BSP] = bsp + br.ret.sptk.many rp + + .endp _setjmp +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/siglongjmp.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/siglongjmp.S new file mode 100644 index 0000000..d77b437 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/siglongjmp.S @@ -0,0 +1,69 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#define SIG_SETMASK 2 + + .global _UI_siglongjmp_cont + .global sigprocmask + + .align 32 + .proc siglongjmp_continuation +siglongjmp_continuation: +_UI_siglongjmp_cont: // non-function label for siglongjmp.c + .prologue + .save rp, r15 + .body + nop 0 + nop 0 + br.call.sptk.many b6 = .next + ;; + .prologue + .save ar.pfs, r33 +.next: alloc loc1 = ar.pfs, 0, 3, 3, 0 + /* + * Note: we can use the scratch stack are because the caller + * of sigsetjmp() by definition is not a leaf-procedure. + */ + st8 [sp] = r17 // store signal mask + .save rp, loc0 + mov loc0 = r15 // final continuation point + ;; + .body + mov loc2 = r16 // value to return in r8 + + mov out0 = SIG_SETMASK + mov out1 = sp + mov out2 = r0 + br.call.sptk.many rp = sigprocmask + ;; + mov rp = loc0 + mov ar.pfs = loc1 + mov r8 = loc2 + br.ret.sptk.many rp + .endp siglongjmp_continuation +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/sigsetjmp.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/sigsetjmp.S new file mode 100644 index 0000000..02f7af4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/sigsetjmp.S @@ -0,0 +1,69 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "jmpbuf.h" + +#define SIG_BLOCK 0 + + .align 32 + + .global __sigsetjmp + .global sigprocmask + + .proc __sigsetjmp + +__sigsetjmp: + .prologue + .save ar.pfs, r35 + alloc loc1 = ar.pfs, 2, 3, 3, 0 + add out2 = JB_MASK*8, in0 + .save rp, loc0 + mov loc0 = rp + mov out0 = SIG_BLOCK + .body + ;; + cmp.ne p6, p0 = in1, r0 + mov out1 = r0 + mov loc2 = ar.bsp +(p6) br.call.sptk.many rp = sigprocmask // sigjmp_buf[JB_MASK] = sigmask + ;; + + add r16 = JB_MASK_SAVED*8, in0 + st8 [in0] = sp, (JB_RP-JB_SP)*8 // sigjmp_buf[JB_SP] = sp + mov r8 = 0 + ;; + st8 [in0] = loc0, (JB_BSP-JB_RP)*8 // sigjmp_buf[JB_RP] = rp + st8 [r16] = in1 // sigjmp_buf[JB_MASK_SAVED] = savemask + mov rp = loc0 + ;; + st8 [in0] = loc2 // sigjmp_buf[JB_BSP] = bsp + mov.i ar.pfs = loc1 + br.ret.sptk.many rp + + .endp __sigsetjmp +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/unwind_decoder.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/unwind_decoder.h new file mode 100644 index 0000000..7fd4174 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ia64/unwind_decoder.h @@ -0,0 +1,477 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* + * Generic IA-64 unwind info decoder. + * + * This file is used both by the Linux kernel and objdump. Please keep + * the two copies of this file in sync. + * + * You need to customize the decoder by defining the following + * macros/constants before including this file: + * + * Types: + * unw_word Unsigned integer type with at least 64 bits + * + * Register names: + * UNW_REG_BSP + * UNW_REG_BSPSTORE + * UNW_REG_FPSR + * UNW_REG_LC + * UNW_REG_PFS + * UNW_REG_PR + * UNW_REG_RNAT + * UNW_REG_PSP + * UNW_REG_RP + * UNW_REG_UNAT + * + * Decoder action macros: + * UNW_DEC_BAD_CODE(code) + * UNW_DEC_ABI(fmt,abi,context,arg) + * UNW_DEC_BR_GR(fmt,brmask,gr,arg) + * UNW_DEC_BR_MEM(fmt,brmask,arg) + * UNW_DEC_COPY_STATE(fmt,label,arg) + * UNW_DEC_EPILOGUE(fmt,t,ecount,arg) + * UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg) + * UNW_DEC_FR_MEM(fmt,frmask,arg) + * UNW_DEC_GR_GR(fmt,grmask,gr,arg) + * UNW_DEC_GR_MEM(fmt,grmask,arg) + * UNW_DEC_LABEL_STATE(fmt,label,arg) + * UNW_DEC_MEM_STACK_F(fmt,t,size,arg) + * UNW_DEC_MEM_STACK_V(fmt,t,arg) + * UNW_DEC_PRIUNAT_GR(fmt,r,arg) + * UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) + * UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) + * UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg) + * UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg) + * UNW_DEC_PROLOGUE(fmt,body,rlen,arg) + * UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg) + * UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg) + * UNW_DEC_REG_REG(fmt,src,dst,arg) + * UNW_DEC_REG_SPREL(fmt,reg,spoff,arg) + * UNW_DEC_REG_WHEN(fmt,reg,t,arg) + * UNW_DEC_RESTORE(fmt,t,abreg,arg) + * UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg) + * UNW_DEC_SPILL_BASE(fmt,pspoff,arg) + * UNW_DEC_SPILL_MASK(fmt,imaskp,arg) + * UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg) + * UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg) + * UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg) + * UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg) + * UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg) + * UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg) + */ + +static unw_word +unw_decode_uleb128 (unsigned char **dpp) +{ + unsigned shift = 0; + unw_word byte, result = 0; + unsigned char *bp = *dpp; + + while (1) + { + byte = *bp++; + result |= (byte & 0x7f) << shift; + if ((byte & 0x80) == 0) + break; + shift += 7; + } + *dpp = bp; + return result; +} + +static unsigned char * +unw_decode_x1 (unsigned char *dp, unsigned char code, void *arg) +{ + unsigned char byte1, abreg; + unw_word t, off; + + byte1 = *dp++; + t = unw_decode_uleb128 (&dp); + off = unw_decode_uleb128 (&dp); + abreg = (byte1 & 0x7f); + if (byte1 & 0x80) + UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg); + else + UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg); + return dp; +} + +static unsigned char * +unw_decode_x2 (unsigned char *dp, unsigned char code, void *arg) +{ + unsigned char byte1, byte2, abreg, x, ytreg; + unw_word t; + + byte1 = *dp++; byte2 = *dp++; + t = unw_decode_uleb128 (&dp); + abreg = (byte1 & 0x7f); + ytreg = byte2; + x = (byte1 >> 7) & 1; + if ((byte1 & 0x80) == 0 && ytreg == 0) + UNW_DEC_RESTORE(X2, t, abreg, arg); + else + UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg); + return dp; +} + +static unsigned char * +unw_decode_x3 (unsigned char *dp, unsigned char code, void *arg) +{ + unsigned char byte1, byte2, abreg, qp; + unw_word t, off; + + byte1 = *dp++; byte2 = *dp++; + t = unw_decode_uleb128 (&dp); + off = unw_decode_uleb128 (&dp); + + qp = (byte1 & 0x3f); + abreg = (byte2 & 0x7f); + + if (byte1 & 0x80) + UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg); + else + UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg); + return dp; +} + +static unsigned char * +unw_decode_x4 (unsigned char *dp, unsigned char code, void *arg) +{ + unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg; + unw_word t; + + byte1 = *dp++; byte2 = *dp++; byte3 = *dp++; + t = unw_decode_uleb128 (&dp); + + qp = (byte1 & 0x3f); + abreg = (byte2 & 0x7f); + x = (byte2 >> 7) & 1; + ytreg = byte3; + + if ((byte2 & 0x80) == 0 && byte3 == 0) + UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg); + else + UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg); + return dp; +} + +static inline unsigned char * +unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg) +{ + int body = (code & 0x20) != 0; + unw_word rlen; + + rlen = (code & 0x1f); + UNW_DEC_PROLOGUE(R1, body, rlen, arg); + return dp; +} + +static inline unsigned char * +unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg) +{ + unsigned char byte1, mask, grsave; + unw_word rlen; + + byte1 = *dp++; + + mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1); + grsave = (byte1 & 0x7f); + rlen = unw_decode_uleb128 (&dp); + UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg); + return dp; +} + +static inline unsigned char * +unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg) +{ + unw_word rlen; + + rlen = unw_decode_uleb128 (&dp); + UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg); + return dp; +} + +static inline unsigned char * +unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg) +{ + unsigned char brmask = (code & 0x1f); + + UNW_DEC_BR_MEM(P1, brmask, arg); + return dp; +} + +static inline unsigned char * +unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg) +{ + if ((code & 0x10) == 0) + { + unsigned char byte1 = *dp++; + + UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1), + (byte1 & 0x7f), arg); + } + else if ((code & 0x08) == 0) + { + unsigned char byte1 = *dp++, r, dst; + + r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1); + dst = (byte1 & 0x7f); + switch (r) + { + case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break; + case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break; + case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break; + case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break; + case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break; + case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break; + case 6: UNW_DEC_RP_BR(P3, dst, arg); break; + case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break; + case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break; + case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break; + case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break; + case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break; + default: UNW_DEC_BAD_CODE(r); break; + } + } + else if ((code & 0x7) == 0) + UNW_DEC_SPILL_MASK(P4, dp, arg); + else if ((code & 0x7) == 1) + { + unw_word grmask, frmask, byte1, byte2, byte3; + + byte1 = *dp++; byte2 = *dp++; byte3 = *dp++; + grmask = ((byte1 >> 4) & 0xf); + frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3; + UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg); + } + else + UNW_DEC_BAD_CODE(code); + return dp; +} + +static inline unsigned char * +unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg) +{ + int gregs = (code & 0x10) != 0; + unsigned char mask = (code & 0x0f); + + if (gregs) + UNW_DEC_GR_MEM(P6, mask, arg); + else + UNW_DEC_FR_MEM(P6, mask, arg); + return dp; +} + +static inline unsigned char * +unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg) +{ + unsigned char r, byte1, byte2; + unw_word t, size; + + if ((code & 0x10) == 0) + { + r = (code & 0xf); + t = unw_decode_uleb128 (&dp); + switch (r) + { + case 0: + size = unw_decode_uleb128 (&dp); + UNW_DEC_MEM_STACK_F(P7, t, size, arg); + break; + + case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break; + case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break; + case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break; + case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break; + case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break; + case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break; + case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break; + case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break; + case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break; + case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break; + case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break; + case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break; + case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break; + case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break; + case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break; + default: UNW_DEC_BAD_CODE(r); break; + } + } + else + { + switch (code & 0xf) + { + case 0x0: /* p8 */ + { + r = *dp++; + t = unw_decode_uleb128 (&dp); + switch (r) + { + case 1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break; + case 2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break; + case 3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break; + case 4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break; + case 5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break; + case 6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break; + case 7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break; + case 8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break; + case 9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break; + case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break; + case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break; + case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break; + case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break; + case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break; + case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break; + case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break; + case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break; + case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break; + case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break; + default: UNW_DEC_BAD_CODE(r); break; + } + } + break; + + case 0x1: + byte1 = *dp++; byte2 = *dp++; + UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg); + break; + + case 0xf: /* p10 */ + byte1 = *dp++; byte2 = *dp++; + UNW_DEC_ABI(P10, byte1, byte2, arg); + break; + + case 0x9: + return unw_decode_x1 (dp, code, arg); + + case 0xa: + return unw_decode_x2 (dp, code, arg); + + case 0xb: + return unw_decode_x3 (dp, code, arg); + + case 0xc: + return unw_decode_x4 (dp, code, arg); + + default: + UNW_DEC_BAD_CODE(code); + break; + } + } + return dp; +} + +static inline unsigned char * +unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg) +{ + unw_word label = (code & 0x1f); + + if ((code & 0x20) != 0) + UNW_DEC_COPY_STATE(B1, label, arg); + else + UNW_DEC_LABEL_STATE(B1, label, arg); + return dp; +} + +static inline unsigned char * +unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg) +{ + unw_word t; + + t = unw_decode_uleb128 (&dp); + UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg); + return dp; +} + +static inline unsigned char * +unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg) +{ + unw_word t, ecount, label; + + if ((code & 0x10) == 0) + { + t = unw_decode_uleb128 (&dp); + ecount = unw_decode_uleb128 (&dp); + UNW_DEC_EPILOGUE(B3, t, ecount, arg); + } + else if ((code & 0x07) == 0) + { + label = unw_decode_uleb128 (&dp); + if ((code & 0x08) != 0) + UNW_DEC_COPY_STATE(B4, label, arg); + else + UNW_DEC_LABEL_STATE(B4, label, arg); + } + else + switch (code & 0x7) + { + case 1: return unw_decode_x1 (dp, code, arg); + case 2: return unw_decode_x2 (dp, code, arg); + case 3: return unw_decode_x3 (dp, code, arg); + case 4: return unw_decode_x4 (dp, code, arg); + default: UNW_DEC_BAD_CODE(code); break; + } + return dp; +} + +typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *); + +/* + * Decode one descriptor and return address of next descriptor. + */ +static inline unsigned char * +unw_decode (unsigned char *dp, int inside_body, void *arg) +{ + unsigned char code, primary; + + code = *dp++; + primary = code >> 5; + + if (primary < 2) + dp = unw_decode_r1 (dp, code, arg); + else if (primary == 2) + dp = unw_decode_r2 (dp, code, arg); + else if (primary == 3) + dp = unw_decode_r3 (dp, code, arg); + else if (inside_body) + switch (primary) + { + case 4: + case 5: dp = unw_decode_b1 (dp, code, arg); break; + case 6: dp = unw_decode_b2 (dp, code, arg); break; + case 7: dp = unw_decode_b3_x4 (dp, code, arg); break; + } + else + switch (primary) + { + case 4: dp = unw_decode_p1 (dp, code, arg); break; + case 5: dp = unw_decode_p2_p5 (dp, code, arg); break; + case 6: dp = unw_decode_p6 (dp, code, arg); break; + case 7: dp = unw_decode_p7_p10 (dp, code, arg); break; + } + return dp; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/libunwind-generic.pc.in b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/libunwind-generic.pc.in new file mode 100644 index 0000000..1f3baff --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/libunwind-generic.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libunwind-generic +Description: libunwind generic library +Version: @VERSION@ +Requires: libunwind +Libs: -L${libdir} -lunwind-generic +Cflags: -I${includedir} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gdestroy_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gdestroy_addr_space.c new file mode 100644 index 0000000..504558e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gdestroy_addr_space.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +void +unw_destroy_addr_space (unw_addr_space_t as) +{ +#ifndef UNW_LOCAL_ONLY +# if UNW_DEBUG + memset (as, 0, sizeof (*as)); +# endif + free (as); +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gdyn-extract.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gdyn-extract.c new file mode 100644 index 0000000..5f7682e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gdyn-extract.c @@ -0,0 +1,64 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +HIDDEN int +unwi_extract_dynamic_proc_info (unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, unw_dyn_info_t *di, + int need_unwind_info, void *arg) +{ + pi->start_ip = di->start_ip; + pi->end_ip = di->end_ip; + pi->gp = di->gp; + pi->format = di->format; + switch (di->format) + { + case UNW_INFO_FORMAT_DYNAMIC: + pi->handler = di->u.pi.handler; + pi->lsda = 0; + pi->flags = di->u.pi.flags; + pi->unwind_info_size = 0; + if (need_unwind_info) + pi->unwind_info = di; + else + pi->unwind_info = NULL; + return 0; + + case UNW_INFO_FORMAT_TABLE: + case UNW_INFO_FORMAT_REMOTE_TABLE: + case UNW_INFO_FORMAT_ARM_EXIDX: + case UNW_INFO_FORMAT_IP_OFFSET: +#ifdef tdep_search_unwind_table + /* call platform-specific search routine: */ + return tdep_search_unwind_table (as, ip, di, pi, need_unwind_info, arg); +#else + /* fall through */ +#endif + default: + break; + } + return -UNW_EINVAL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gdyn-remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gdyn-remote.c new file mode 100644 index 0000000..40a5ad8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gdyn-remote.c @@ -0,0 +1,326 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "libunwind_i.h" +#include "remote.h" + +static void +free_regions (unw_dyn_region_info_t *region) +{ + if (region->next) + free_regions (region->next); + free (region); +} + +static int +intern_op (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + unw_dyn_op_t *op, void *arg) +{ + int ret; + + if ((ret = fetch8 (as, a, addr, &op->tag, arg)) < 0 + || (ret = fetch8 (as, a, addr, &op->qp, arg)) < 0 + || (ret = fetch16 (as, a, addr, &op->reg, arg)) < 0 + || (ret = fetch32 (as, a, addr, &op->when, arg)) < 0 + || (ret = fetchw (as, a, addr, &op->val, arg)) < 0) + return ret; + return 0; +} + +static int +intern_regions (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, unw_dyn_region_info_t **regionp, void *arg) +{ + uint32_t insn_count, op_count, i; + unw_dyn_region_info_t *region; + unw_word_t next_addr; + int ret; + + *regionp = NULL; + + if (!*addr) + return 0; /* NULL region-list */ + + if ((ret = fetchw (as, a, addr, &next_addr, arg)) < 0 + || (ret = fetch32 (as, a, addr, (int32_t *) &insn_count, arg)) < 0 + || (ret = fetch32 (as, a, addr, (int32_t *) &op_count, arg)) < 0) + return ret; + + region = calloc (1, _U_dyn_region_info_size (op_count)); + if (!region) + { + ret = -UNW_ENOMEM; + goto out; + } + + region->insn_count = insn_count; + region->op_count = op_count; + for (i = 0; i < op_count; ++i) + if ((ret = intern_op (as, a, addr, region->op + i, arg)) < 0) + goto out; + + if (next_addr) + if ((ret = intern_regions (as, a, &next_addr, ®ion->next, arg)) < 0) + goto out; + + *regionp = region; + return 0; + + out: + if (region) + free_regions (region); + return ret; +} + +static int +intern_array (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, unw_word_t table_len, unw_word_t **table_data, + void *arg) +{ + unw_word_t i, *data = calloc (table_len, WSIZE); + int ret = 0; + + if (!data) + { + ret = -UNW_ENOMEM; + goto out; + } + + for (i = 0; i < table_len; ++i) + if (fetchw (as, a, addr, data + i, arg) < 0) + goto out; + + *table_data = data; + return 0; + + out: + if (data) + free (data); + return ret; +} + +static void +free_dyn_info (unw_dyn_info_t *di) +{ + switch (di->format) + { + case UNW_INFO_FORMAT_DYNAMIC: + if (di->u.pi.regions) + { + free_regions (di->u.pi.regions); + di->u.pi.regions = NULL; + } + break; + + case UNW_INFO_FORMAT_TABLE: + if (di->u.ti.table_data) + { + free (di->u.ti.table_data); + di->u.ti.table_data = NULL; + } + break; + + case UNW_INFO_FORMAT_REMOTE_TABLE: + default: + break; + } +} + +static int +intern_dyn_info (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, unw_dyn_info_t *di, void *arg) +{ + unw_word_t first_region; + int ret; + + switch (di->format) + { + case UNW_INFO_FORMAT_DYNAMIC: + if ((ret = fetchw (as, a, addr, &di->u.pi.name_ptr, arg)) < 0 + || (ret = fetchw (as, a, addr, &di->u.pi.handler, arg)) < 0 + || (ret = fetch32 (as, a, addr, + (int32_t *) &di->u.pi.flags, arg)) < 0) + goto out; + *addr += 4; /* skip over pad0 */ + if ((ret = fetchw (as, a, addr, &first_region, arg)) < 0 + || (ret = intern_regions (as, a, &first_region, &di->u.pi.regions, + arg)) < 0) + goto out; + break; + + case UNW_INFO_FORMAT_TABLE: + if ((ret = fetchw (as, a, addr, &di->u.ti.name_ptr, arg)) < 0 + || (ret = fetchw (as, a, addr, &di->u.ti.segbase, arg)) < 0 + || (ret = fetchw (as, a, addr, &di->u.ti.table_len, arg)) < 0 + || (ret = intern_array (as, a, addr, di->u.ti.table_len, + &di->u.ti.table_data, arg)) < 0) + goto out; + break; + + case UNW_INFO_FORMAT_REMOTE_TABLE: + if ((ret = fetchw (as, a, addr, &di->u.rti.name_ptr, arg)) < 0 + || (ret = fetchw (as, a, addr, &di->u.rti.segbase, arg)) < 0 + || (ret = fetchw (as, a, addr, &di->u.rti.table_len, arg)) < 0 + || (ret = fetchw (as, a, addr, &di->u.rti.table_data, arg)) < 0) + goto out; + break; + + default: + ret = -UNW_ENOINFO; + goto out; + } + return 0; + + out: + free_dyn_info (di); + return ret; +} + +HIDDEN int +unwi_dyn_remote_find_proc_info (unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + unw_accessors_t *a = unw_get_accessors_int (as); + unw_word_t dyn_list_addr, addr, next_addr, gen1, gen2, start_ip, end_ip; + unw_dyn_info_t *di = NULL; + int ret; + + if (as->dyn_info_list_addr) + dyn_list_addr = as->dyn_info_list_addr; + else + { + if ((*a->get_dyn_info_list_addr) (as, &dyn_list_addr, arg) < 0) + return -UNW_ENOINFO; + if (as->caching_policy != UNW_CACHE_NONE) + as->dyn_info_list_addr = dyn_list_addr; + } + + do + { + addr = dyn_list_addr; + + ret = -UNW_ENOINFO; + + if (fetchw (as, a, &addr, &gen1, arg) < 0 + || fetchw (as, a, &addr, &next_addr, arg) < 0) + return ret; + + for (addr = next_addr; addr != 0; addr = next_addr) + { + if (fetchw (as, a, &addr, &next_addr, arg) < 0) + goto recheck; /* only fail if generation # didn't change */ + + addr += WSIZE; /* skip over prev_addr */ + + if (fetchw (as, a, &addr, &start_ip, arg) < 0 + || fetchw (as, a, &addr, &end_ip, arg) < 0) + goto recheck; /* only fail if generation # didn't change */ + + if (ip >= start_ip && ip < end_ip) + { + if (!di) + di = calloc (1, sizeof (*di)); + + di->start_ip = start_ip; + di->end_ip = end_ip; + + if (fetchw (as, a, &addr, &di->gp, arg) < 0 + || fetch32 (as, a, &addr, &di->format, arg) < 0) + goto recheck; /* only fail if generation # didn't change */ + + addr += 4; /* skip over padding */ + + if (need_unwind_info + && intern_dyn_info (as, a, &addr, di, arg) < 0) + goto recheck; /* only fail if generation # didn't change */ + + if (unwi_extract_dynamic_proc_info (as, ip, pi, di, + need_unwind_info, arg) < 0) + { + free_dyn_info (di); + goto recheck; /* only fail if generation # didn't change */ + } + ret = 0; /* OK, found it */ + break; + } + } + + /* Re-check generation number to ensure the data we have is + consistent. */ + recheck: + addr = dyn_list_addr; + if (fetchw (as, a, &addr, &gen2, arg) < 0) + return ret; + } + while (gen1 != gen2); + + if (ret < 0 && di) + free (di); + + return ret; +} + +HIDDEN void +unwi_dyn_remote_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, + void *arg) +{ + if (!pi->unwind_info) + return; + + free_dyn_info (pi->unwind_info); + free (pi->unwind_info); + pi->unwind_info = NULL; +} + +/* Returns 1 if the cache is up-to-date or -1 if the cache contained + stale data and had to be flushed. */ + +HIDDEN int +unwi_dyn_validate_cache (unw_addr_space_t as, void *arg) +{ + unw_word_t addr, gen; + unw_accessors_t *a; + + if (!as->dyn_info_list_addr) + /* If we don't have the dyn_info_list_addr, we don't have anything + in the cache. */ + return 0; + + a = unw_get_accessors_int (as); + addr = as->dyn_info_list_addr; + + if (fetchw (as, a, &addr, &gen, arg) < 0) + return 1; + + if (gen == as->dyn_generation) + return 1; + + unw_flush_cache (as, 0, 0); + as->dyn_generation = gen; + return -1; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gfind_dynamic_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gfind_dynamic_proc_info.c new file mode 100644 index 0000000..98d3501 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gfind_dynamic_proc_info.c @@ -0,0 +1,91 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +#ifdef UNW_REMOTE_ONLY + +static inline int +local_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + return -UNW_ENOINFO; +} + +#else /* !UNW_REMOTE_ONLY */ + +static inline int +local_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + unw_dyn_info_list_t *list; + unw_dyn_info_t *di; + +#ifndef UNW_LOCAL_ONLY +# pragma weak _U_dyn_info_list_addr + if (!_U_dyn_info_list_addr) + return -UNW_ENOINFO; +#endif + + list = (unw_dyn_info_list_t *) (uintptr_t) _U_dyn_info_list_addr (); + for (di = list->first; di; di = di->next) + if (ip >= di->start_ip && ip < di->end_ip) + return unwi_extract_dynamic_proc_info (as, ip, pi, di, need_unwind_info, + arg); + return -UNW_ENOINFO; +} + +#endif /* !UNW_REMOTE_ONLY */ + +#ifdef UNW_LOCAL_ONLY + +static inline int +remote_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + return -UNW_ENOINFO; +} + +#else /* !UNW_LOCAL_ONLY */ + +static inline int +remote_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + return unwi_dyn_remote_find_proc_info (as, ip, pi, need_unwind_info, arg); +} + +#endif /* !UNW_LOCAL_ONLY */ + +HIDDEN int +unwi_find_dynamic_proc_info (unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, int need_unwind_info, + void *arg) +{ + if (as == unw_local_addr_space) + return local_find_proc_info (as, ip, pi, need_unwind_info, arg); + else + return remote_find_proc_info (as, ip, pi, need_unwind_info, arg); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_accessors.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_accessors.c new file mode 100644 index 0000000..31a6fba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_accessors.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002, 2004-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +HIDDEN ALIAS(unw_get_accessors) unw_accessors_t * +unw_get_accessors_int (unw_addr_space_t as); + +unw_accessors_t * +unw_get_accessors (unw_addr_space_t as) +{ + if (!tdep_init_done) + tdep_init (); + return &as->acc; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_fpreg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_fpreg.c new file mode 100644 index 0000000..f32b128 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_fpreg.c @@ -0,0 +1,34 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +int +unw_get_fpreg (unw_cursor_t *cursor, int regnum, unw_fpreg_t *valp) +{ + struct cursor *c = (struct cursor *) cursor; + + return tdep_access_fpreg (c, regnum, valp, 0); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_proc_info_by_ip.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_proc_info_by_ip.c new file mode 100644 index 0000000..2697ff8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_proc_info_by_ip.c @@ -0,0 +1,39 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +int +unw_get_proc_info_by_ip (unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, void *as_arg) +{ + unw_accessors_t *a = unw_get_accessors_int (as); + int ret; + + ret = unwi_find_dynamic_proc_info (as, ip, pi, 0, as_arg); + if (ret == -UNW_ENOINFO) + ret = (*a->find_proc_info) (as, ip, pi, 0, as_arg); + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_proc_name.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_proc_name.c new file mode 100644 index 0000000..840d900 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_proc_name.c @@ -0,0 +1,118 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" +#include "remote.h" + +static inline int +intern_string (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t addr, char *buf, size_t buf_len, void *arg) +{ + size_t i; + int ret; + + for (i = 0; i < buf_len; ++i) + { + if ((ret = fetch8 (as, a, &addr, (int8_t *) buf + i, arg)) < 0) + return ret; + + if (buf[i] == '\0') + return 0; /* copied full string; return success */ + } + buf[buf_len - 1] = '\0'; /* ensure string is NUL terminated */ + return -UNW_ENOMEM; +} + +static inline int +get_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, void *arg) +{ + unw_accessors_t *a = unw_get_accessors_int (as); + unw_proc_info_t pi; + int ret; + + buf[0] = '\0'; /* always return a valid string, even if it's empty */ + + ret = unwi_find_dynamic_proc_info (as, ip, &pi, 1, arg); + if (ret == 0) + { + unw_dyn_info_t *di = pi.unwind_info; + + if (offp) + *offp = ip - pi.start_ip; + + switch (di->format) + { + case UNW_INFO_FORMAT_DYNAMIC: + ret = intern_string (as, a, di->u.pi.name_ptr, buf, buf_len, arg); + break; + + case UNW_INFO_FORMAT_TABLE: + case UNW_INFO_FORMAT_REMOTE_TABLE: + /* XXX should we create a fake name, e.g.: "tablenameN", + where N is the index of the function in the table??? */ + ret = -UNW_ENOINFO; + break; + + default: + ret = -UNW_EINVAL; + break; + } + unwi_put_dynamic_unwind_info (as, &pi, arg); + return ret; + } + + if (ret != -UNW_ENOINFO) + return ret; + + /* not a dynamic procedure, try to lookup static procedure name: */ + + if (a->get_proc_name) + return (*a->get_proc_name) (as, ip, buf, buf_len, offp, arg); + + return -UNW_ENOINFO; +} + +int +unw_get_proc_name (unw_cursor_t *cursor, char *buf, size_t buf_len, + unw_word_t *offp) +{ + struct cursor *c = (struct cursor *) cursor; + unw_word_t ip; + int error; + + ip = tdep_get_ip (c); +#if !defined(__ia64__) + if (c->dwarf.use_prev_instr) + --ip; +#endif + error = get_proc_name (tdep_get_as (c), ip, buf, buf_len, offp, + tdep_get_as_arg (c)); +#if !defined(__ia64__) + if (c->dwarf.use_prev_instr && offp != NULL && error == 0) + *offp += 1; +#endif + return error; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_reg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_reg.c new file mode 100644 index 0000000..9fc725c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gget_reg.c @@ -0,0 +1,41 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +int +unw_get_reg (unw_cursor_t *cursor, int regnum, unw_word_t *valp) +{ + struct cursor *c = (struct cursor *) cursor; + + // We can get the IP value directly without needing a lookup. + if (regnum == UNW_REG_IP) + { + *valp = tdep_get_ip (c); + return 0; + } + + return tdep_access_reg (c, regnum, valp, 0); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gput_dynamic_unwind_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gput_dynamic_unwind_info.c new file mode 100644 index 0000000..ca377c9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gput_dynamic_unwind_info.c @@ -0,0 +1,55 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +HIDDEN void +unwi_put_dynamic_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, + void *arg) +{ + switch (pi->format) + { + case UNW_INFO_FORMAT_DYNAMIC: +#ifndef UNW_LOCAL_ONLY +# ifdef UNW_REMOTE_ONLY + unwi_dyn_remote_put_unwind_info (as, pi, arg); +# else + if (as != unw_local_addr_space) + unwi_dyn_remote_put_unwind_info (as, pi, arg); +# endif +#endif + break; + + case UNW_INFO_FORMAT_TABLE: + case UNW_INFO_FORMAT_REMOTE_TABLE: +#ifdef tdep_put_unwind_info + tdep_put_unwind_info (as, pi, arg); + break; +#endif + /* fall through */ + default: + break; + } +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_cache_size.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_cache_size.c new file mode 100644 index 0000000..07b282e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_cache_size.c @@ -0,0 +1,72 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2014 + Contributed by Milian Wolff + and Dave Watson + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +int +unw_set_cache_size (unw_addr_space_t as, size_t size, int flag) +{ + size_t power = 1; + unsigned short log_size = 0; + + if (!tdep_init_done) + tdep_init (); + + if (flag != 0) + return -1; + + /* Currently not supported for per-thread cache due to memory leak */ + /* A pthread-key destructor would work, but is not signal safe */ +#if defined(HAVE___THREAD) && HAVE___THREAD + return -1; +#endif + + /* Round up to next power of two, slowly but portably */ + while(power < size) + { + power *= 2; + log_size++; + /* Largest size currently supported by rs_cache */ + if (log_size >= 15) + break; + } + +#if !defined(__ia64__) + if (log_size == as->global_cache.log_size) + return 0; /* no change */ + + as->global_cache.log_size = log_size; +#endif + + /* Ensure caches are empty (and initialized). */ + unw_flush_cache (as, 0, 0); +#ifdef __ia64__ + return 0; +#else + /* Synchronously purge cache, to ensure memory is allocated */ + return dwarf_flush_rs_cache(&as->global_cache); +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_caching_policy.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_caching_policy.c new file mode 100644 index 0000000..aa3d237 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_caching_policy.c @@ -0,0 +1,46 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +int +unw_set_caching_policy (unw_addr_space_t as, unw_caching_policy_t policy) +{ + if (!tdep_init_done) + tdep_init (); + +#if !(defined(HAVE___THREAD) && HAVE___THREAD) + if (policy == UNW_CACHE_PER_THREAD) + policy = UNW_CACHE_GLOBAL; +#endif + + if (policy == as->caching_policy) + return 0; /* no change */ + + as->caching_policy = policy; + /* Ensure caches are empty (and initialized). */ + unw_flush_cache (as, 0, 0); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_fpreg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_fpreg.c new file mode 100644 index 0000000..8c37afd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_fpreg.c @@ -0,0 +1,34 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +int +unw_set_fpreg (unw_cursor_t *cursor, int regnum, unw_fpreg_t val) +{ + struct cursor *c = (struct cursor *) cursor; + + return tdep_access_fpreg (c, regnum, &val, 1); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_reg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_reg.c new file mode 100644 index 0000000..b1b1770 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Gset_reg.c @@ -0,0 +1,34 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +int +unw_set_reg (unw_cursor_t *cursor, int regnum, unw_word_t valp) +{ + struct cursor *c = (struct cursor *) cursor; + + return tdep_access_reg (c, regnum, &valp, 1); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Ldestroy_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Ldestroy_addr_space.c new file mode 100644 index 0000000..5bf9364 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Ldestroy_addr_space.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gdestroy_addr_space.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Ldyn-extract.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Ldyn-extract.c new file mode 100644 index 0000000..1802f86 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Ldyn-extract.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gdyn-extract.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Ldyn-remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Ldyn-remote.c new file mode 100644 index 0000000..260722a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Ldyn-remote.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gdyn-remote.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lfind_dynamic_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lfind_dynamic_proc_info.c new file mode 100644 index 0000000..bc88e1c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lfind_dynamic_proc_info.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gfind_dynamic_proc_info.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_accessors.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_accessors.c new file mode 100644 index 0000000..555e37f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_accessors.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_accessors.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_fpreg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_fpreg.c new file mode 100644 index 0000000..e3be441 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_fpreg.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_fpreg.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_proc_info_by_ip.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_proc_info_by_ip.c new file mode 100644 index 0000000..96910d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_proc_info_by_ip.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_proc_info_by_ip.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_proc_name.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_proc_name.c new file mode 100644 index 0000000..378097b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_proc_name.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_proc_name.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_reg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_reg.c new file mode 100644 index 0000000..effe8a8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lget_reg.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_reg.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lput_dynamic_unwind_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lput_dynamic_unwind_info.c new file mode 100644 index 0000000..99597cd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lput_dynamic_unwind_info.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gput_dynamic_unwind_info.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_cache_size.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_cache_size.c new file mode 100644 index 0000000..670f64d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_cache_size.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gset_cache_size.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_caching_policy.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_caching_policy.c new file mode 100644 index 0000000..cc18816 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_caching_policy.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gset_caching_policy.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_fpreg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_fpreg.c new file mode 100644 index 0000000..2497d40 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_fpreg.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gset_fpreg.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_reg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_reg.c new file mode 100644 index 0000000..c7a872b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/Lset_reg.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gset_reg.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/_ReadSLEB.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/_ReadSLEB.c new file mode 100644 index 0000000..c041e37 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/_ReadSLEB.c @@ -0,0 +1,25 @@ +#include + +unw_word_t +_ReadSLEB (unsigned char **dpp) +{ + unsigned shift = 0; + unw_word_t byte, result = 0; + unsigned char *bp = *dpp; + + while (1) + { + byte = *bp++; + result |= (byte & 0x7f) << shift; + shift += 7; + if ((byte & 0x80) == 0) + break; + } + + if (shift < 8 * sizeof (unw_word_t) && (byte & 0x40) != 0) + /* sign-extend negative value */ + result |= ((unw_word_t) -1) << shift; + + *dpp = bp; + return result; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/_ReadULEB.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/_ReadULEB.c new file mode 100644 index 0000000..116f3e1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/_ReadULEB.c @@ -0,0 +1,20 @@ +#include + +unw_word_t +_ReadULEB (unsigned char **dpp) +{ + unsigned shift = 0; + unw_word_t byte, result = 0; + unsigned char *bp = *dpp; + + while (1) + { + byte = *bp++; + result |= (byte & 0x7f) << shift; + if ((byte & 0x80) == 0) + break; + shift += 7; + } + *dpp = bp; + return result; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/backtrace.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/backtrace.c new file mode 100644 index 0000000..c7aa2bd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/backtrace.c @@ -0,0 +1,81 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef UNW_REMOTE_ONLY + +#define UNW_LOCAL_ONLY +#include +#include +#include + +/* See glibc manual for a description of this function. */ + +static ALWAYS_INLINE int +slow_backtrace (void **buffer, int size, unw_context_t *uc) +{ + unw_cursor_t cursor; + unw_word_t ip; + int n = 0; + + if (unlikely (unw_init_local (&cursor, uc) < 0)) + return 0; + + while (unw_step (&cursor) > 0) + { + if (n >= size) + return n; + + if (unw_get_reg (&cursor, UNW_REG_IP, &ip) < 0) + return n; + buffer[n++] = (void *) (uintptr_t) ip; + } + return n; +} + +int +unw_backtrace (void **buffer, int size) +{ + unw_cursor_t cursor; + unw_context_t uc; + int n = size; + + tdep_getcontext_trace (&uc); + + if (unlikely (unw_init_local (&cursor, &uc) < 0)) + return 0; + + if (unlikely (tdep_trace (&cursor, buffer, &n) < 0)) + { + unw_getcontext (&uc); + return slow_backtrace (buffer, size, &uc); + } + + return n; +} + +extern int backtrace (void **buffer, int size) + WEAK ALIAS(unw_backtrace); + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/dyn-cancel.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/dyn-cancel.c new file mode 100644 index 0000000..9d7472d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/dyn-cancel.c @@ -0,0 +1,46 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +void +_U_dyn_cancel (unw_dyn_info_t *di) +{ + mutex_lock (&_U_dyn_info_list_lock); + { + ++_U_dyn_info_list.generation; + + if (di->prev) + di->prev->next = di->next; + else + _U_dyn_info_list.first = di->next; + + if (di->next) + di->next->prev = di->prev; + } + mutex_unlock (&_U_dyn_info_list_lock); + + di->next = di->prev = NULL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/dyn-info-list.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/dyn-info-list.c new file mode 100644 index 0000000..1c7c550 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/dyn-info-list.c @@ -0,0 +1,34 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +HIDDEN unw_dyn_info_list_t _U_dyn_info_list; + +unw_word_t +_U_dyn_info_list_addr (void) +{ + return (unw_word_t) (uintptr_t) &_U_dyn_info_list; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/dyn-register.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/dyn-register.c new file mode 100644 index 0000000..efdad3d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/dyn-register.c @@ -0,0 +1,44 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +HIDDEN define_lock (_U_dyn_info_list_lock); + +void +_U_dyn_register (unw_dyn_info_t *di) +{ + mutex_lock (&_U_dyn_info_list_lock); + { + ++_U_dyn_info_list.generation; + + di->next = _U_dyn_info_list.first; + di->prev = NULL; + if (di->next) + di->next->prev = di; + _U_dyn_info_list.first = di; + } + mutex_unlock (&_U_dyn_info_list_lock); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/flush_cache.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/flush_cache.c new file mode 100644 index 0000000..cbd93e1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/flush_cache.c @@ -0,0 +1,59 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +void +unw_flush_cache (unw_addr_space_t as, unw_word_t lo, unw_word_t hi) +{ +#if !UNW_TARGET_IA64 + struct unw_debug_frame_list *w = as->debug_frames; +#endif + + /* clear dyn_info_list_addr cache: */ + as->dyn_info_list_addr = 0; + +#if !UNW_TARGET_IA64 + for (; w; w = w->next) + { + if (w->index) + free (w->index); + free (w->debug_frame); + } + as->debug_frames = NULL; +#endif + + /* This lets us flush caches lazily. The implementation currently + ignores the flush range arguments (lo-hi). This is OK because + unw_flush_cache() is allowed to flush more than the requested + range. */ + +#ifdef HAVE_FETCH_AND_ADD + fetch_and_add1 (&as->cache_generation); +#else +# warning unw_flush_cache(): need a way to atomically increment an integer. + ++as->cache_generation; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/init.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/init.c new file mode 100644 index 0000000..60a48c5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/init.c @@ -0,0 +1,60 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +HIDDEN intrmask_t unwi_full_mask; + +static const char rcsid[] UNUSED = + "$Id: " PACKAGE_STRING " --- report bugs to " PACKAGE_BUGREPORT " $"; + +#if UNW_DEBUG + +/* Must not be declared HIDDEN because libunwind.so and + libunwind-PLATFORM.so will both define their own copies of this + variable and we want to use only one or the other when both + libraries are loaded. */ +long unwi_debug_level; + +#endif /* UNW_DEBUG */ + +HIDDEN void +mi_init (void) +{ +#if UNW_DEBUG + const char *str = getenv ("UNW_DEBUG_LEVEL"); + + if (str) + unwi_debug_level = atoi (str); + + if (unwi_debug_level > 0) + { + setbuf (stdout, NULL); + setbuf (stderr, NULL); + } +#endif + + assert (sizeof (struct cursor) <= sizeof (unw_cursor_t)); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/mempool.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/mempool.c new file mode 100644 index 0000000..536b64e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/mempool.c @@ -0,0 +1,184 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2003, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +/* From GCC docs: ``Gcc also provides a target specific macro + * __BIGGEST_ALIGNMENT__, which is the largest alignment ever used for any data + * type on the target machine you are compiling for.'' */ +#ifdef __BIGGEST_ALIGNMENT__ +# define MAX_ALIGN __BIGGEST_ALIGNMENT__ +#else +/* Crude hack to check that MAX_ALIGN is power-of-two. + * sizeof(long double) = 12 on i386. */ +# define MAX_ALIGN_(n) (n < 8 ? 8 : \ + n < 16 ? 16 : n) +# define MAX_ALIGN MAX_ALIGN_(sizeof (long double)) +#endif + +static char sos_memory[SOS_MEMORY_SIZE] ALIGNED(MAX_ALIGN); +static size_t sos_memory_freepos; +static size_t pg_size; + +HIDDEN void * +sos_alloc (size_t size) +{ + size_t pos; + + size = UNW_ALIGN(size, MAX_ALIGN); + +#if defined(__GNUC__) && defined(HAVE_FETCH_AND_ADD) + /* Assume `sos_memory' is suitably aligned. */ + assert(((uintptr_t) &sos_memory[0] & (MAX_ALIGN-1)) == 0); + + pos = fetch_and_add (&sos_memory_freepos, size); +#else + static define_lock (sos_lock); + intrmask_t saved_mask; + + lock_acquire (&sos_lock, saved_mask); + { + /* No assumptions about `sos_memory' alignment. */ + if (sos_memory_freepos == 0) + { + unsigned align = UNW_ALIGN((uintptr_t) &sos_memory[0], MAX_ALIGN) + - (uintptr_t) &sos_memory[0]; + sos_memory_freepos = align; + } + pos = sos_memory_freepos; + sos_memory_freepos += size; + } + lock_release (&sos_lock, saved_mask); +#endif + + assert (((uintptr_t) &sos_memory[pos] & (MAX_ALIGN-1)) == 0); + assert ((pos+size) <= SOS_MEMORY_SIZE); + + return &sos_memory[pos]; +} + +/* Must be called while holding the mempool lock. */ + +static void +free_object (struct mempool *pool, void *object) +{ + struct object *obj = object; + + obj->next = pool->free_list; + pool->free_list = obj; + ++pool->num_free; +} + +static void +add_memory (struct mempool *pool, char *mem, size_t size, size_t obj_size) +{ + char *obj; + + for (obj = mem; obj <= mem + size - obj_size; obj += obj_size) + free_object (pool, obj); +} + +static void +expand (struct mempool *pool) +{ + size_t size; + char *mem; + + size = pool->chunk_size; + GET_MEMORY (mem, size); + if (!mem) + { + size = UNW_ALIGN(pool->obj_size, pg_size); + GET_MEMORY (mem, size); + if (!mem) + { + /* last chance: try to allocate one object from the SOS memory */ + size = pool->obj_size; + mem = sos_alloc (size); + } + } + add_memory (pool, mem, size, pool->obj_size); +} + +HIDDEN void +mempool_init (struct mempool *pool, size_t obj_size, size_t reserve) +{ + if (pg_size == 0) + pg_size = getpagesize (); + + memset (pool, 0, sizeof (*pool)); + + lock_init (&pool->lock); + + /* round object-size up to integer multiple of MAX_ALIGN */ + obj_size = UNW_ALIGN(obj_size, MAX_ALIGN); + + if (!reserve) + { + reserve = pg_size / obj_size / 4; + if (!reserve) + reserve = 16; + } + + pool->obj_size = obj_size; + pool->reserve = reserve; + pool->chunk_size = UNW_ALIGN(2*reserve*obj_size, pg_size); + + expand (pool); +} + +HIDDEN void * +mempool_alloc (struct mempool *pool) +{ + intrmask_t saved_mask; + struct object *obj; + + lock_acquire (&pool->lock, saved_mask); + { + if (pool->num_free <= pool->reserve) + expand (pool); + + assert (pool->num_free > 0); + + --pool->num_free; + obj = pool->free_list; + pool->free_list = obj->next; + } + lock_release (&pool->lock, saved_mask); + return obj; +} + +HIDDEN void +mempool_free (struct mempool *pool, void *object) +{ + intrmask_t saved_mask; + + lock_acquire (&pool->lock, saved_mask); + { + free_object (pool, object); + } + lock_release (&pool->lock, saved_mask); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/strerror.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/strerror.c new file mode 100644 index 0000000..2cec73d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mi/strerror.c @@ -0,0 +1,51 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 BEA Systems + Contributed by Thomas Hallgren + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +/* Returns the text corresponding to the given err_code or the + text "invalid error code" if the err_code is invalid. */ +const char * +unw_strerror (int err_code) +{ + const char *cp; + unw_error_t error = (unw_error_t)-err_code; + switch (error) + { + case UNW_ESUCCESS: cp = "no error"; break; + case UNW_EUNSPEC: cp = "unspecified (general) error"; break; + case UNW_ENOMEM: cp = "out of memory"; break; + case UNW_EBADREG: cp = "bad register number"; break; + case UNW_EREADONLYREG: cp = "attempt to write read-only register"; break; + case UNW_ESTOPUNWIND: cp = "stop unwinding"; break; + case UNW_EINVALIDIP: cp = "invalid IP"; break; + case UNW_EBADFRAME: cp = "bad frame"; break; + case UNW_EINVAL: cp = "unsupported operation or bad value"; break; + case UNW_EBADVERSION: cp = "unwind info has unsupported version"; break; + case UNW_ENOINFO: cp = "no unwind info found"; break; + default: cp = "invalid error code"; + } + return cp; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gapply_reg_state.c new file mode 100644 index 0000000..82f056d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gapply_reg_state.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_apply_reg_state (unw_cursor_t *cursor, + void *reg_states_data) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gcreate_addr_space.c new file mode 100644 index 0000000..493d03d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gcreate_addr_space.c @@ -0,0 +1,66 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "unwind_i.h" + +unw_addr_space_t +unw_create_addr_space (unw_accessors_t *a, int byte_order) +{ +#ifdef UNW_LOCAL_ONLY + return NULL; +#else + unw_addr_space_t as; + + /* + * MIPS supports only big or little-endian, not weird stuff like + * PDP_ENDIAN. + */ + if (byte_order != 0 + && byte_order != __LITTLE_ENDIAN + && byte_order != __BIG_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); + if (!as) + return NULL; + + memset (as, 0, sizeof (*as)); + + as->acc = *a; + + if (byte_order == 0) + /* use host default: */ + as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN); + else + as->big_endian = (byte_order == __BIG_ENDIAN); + + /* FIXME! There is no way to specify the ABI. */ + as->abi = UNW_MIPS_ABI_O32; + as->addr_size = 4; + + return as; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gget_proc_info.c new file mode 100644 index 0000000..7b84be8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gget_proc_info.c @@ -0,0 +1,41 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + /* We can only unwind using Dwarf into on MIPS: return failure code + if it's not present. */ + ret = dwarf_make_proc_info (&c->dwarf); + if (ret < 0) + return ret; + + *pi = c->dwarf.pi; + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gget_save_loc.c new file mode 100644 index 0000000..c21f9b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gget_save_loc.c @@ -0,0 +1,100 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +/* FIXME for MIPS. */ + +int +unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) +{ + struct cursor *c = (struct cursor *) cursor; + dwarf_loc_t loc; + + loc = DWARF_NULL_LOC; /* default to "not saved" */ + + switch (reg) + { + case UNW_MIPS_R0: + case UNW_MIPS_R1: + case UNW_MIPS_R2: + case UNW_MIPS_R3: + case UNW_MIPS_R4: + case UNW_MIPS_R5: + case UNW_MIPS_R6: + case UNW_MIPS_R7: + case UNW_MIPS_R8: + case UNW_MIPS_R9: + case UNW_MIPS_R10: + case UNW_MIPS_R11: + case UNW_MIPS_R12: + case UNW_MIPS_R13: + case UNW_MIPS_R14: + case UNW_MIPS_R15: + case UNW_MIPS_R16: + case UNW_MIPS_R17: + case UNW_MIPS_R18: + case UNW_MIPS_R19: + case UNW_MIPS_R20: + case UNW_MIPS_R21: + case UNW_MIPS_R22: + case UNW_MIPS_R23: + case UNW_MIPS_R24: + case UNW_MIPS_R25: + case UNW_MIPS_R26: + case UNW_MIPS_R27: + case UNW_MIPS_R28: + case UNW_MIPS_R29: + case UNW_MIPS_R30: + case UNW_MIPS_R31: + case UNW_MIPS_PC: + loc = c->dwarf.loc[reg - UNW_MIPS_R0]; + break; + + default: + break; + } + + memset (sloc, 0, sizeof (*sloc)); + + if (DWARF_IS_NULL_LOC (loc)) + { + sloc->type = UNW_SLT_NONE; + return 0; + } + +#if !defined(UNW_LOCAL_ONLY) + if (DWARF_IS_REG_LOC (loc)) + { + sloc->type = UNW_SLT_REG; + sloc->u.regnum = DWARF_GET_LOC (loc); + } + else +#endif + { + sloc->type = UNW_SLT_MEMORY; + sloc->u.addr = DWARF_GET_LOC (loc); + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gglobal.c new file mode 100644 index 0000000..fa9478e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gglobal.c @@ -0,0 +1,55 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "dwarf_i.h" + +HIDDEN define_lock (mips_lock); +HIDDEN int tdep_init_done; + +HIDDEN void +tdep_init (void) +{ + intrmask_t saved_mask; + + sigfillset (&unwi_full_mask); + + lock_acquire (&mips_lock, saved_mask); + { + if (tdep_init_done) + /* another thread else beat us to it... */ + goto out; + + mi_init (); + + dwarf_init (); + +#ifndef UNW_REMOTE_ONLY + mips_local_addr_space_init (); +#endif + tdep_init_done = 1; /* signal that we're initialized... */ + } + out: + lock_release (&mips_lock, saved_mask); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Ginit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Ginit.c new file mode 100644 index 0000000..3df170c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Ginit.c @@ -0,0 +1,210 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#include "unwind_i.h" + +#ifdef UNW_REMOTE_ONLY + +/* unw_local_addr_space is a NULL pointer in this case. */ +unw_addr_space_t unw_local_addr_space; + +#else /* !UNW_REMOTE_ONLY */ + +static struct unw_addr_space local_addr_space; + +unw_addr_space_t unw_local_addr_space = &local_addr_space; + +/* Return the address of the 64-bit slot in UC for REG (even for o32, + where registers are 32-bit, the slots are still 64-bit). */ + +static inline void * +uc_addr (ucontext_t *uc, int reg) +{ + if (reg >= UNW_MIPS_R0 && reg < UNW_MIPS_R0 + 32) + return &uc->uc_mcontext.gregs[reg - UNW_MIPS_R0]; + else if (reg == UNW_MIPS_PC) + return &uc->uc_mcontext.pc; + else + return NULL; +} + +# ifdef UNW_LOCAL_ONLY + +HIDDEN void * +tdep_uc_addr (ucontext_t *uc, int reg) +{ + char *addr = uc_addr (uc, reg); + + if (((reg >= UNW_MIPS_R0 && reg <= UNW_MIPS_R31) || reg == UNW_MIPS_PC) + && tdep_big_endian (unw_local_addr_space) + && unw_local_addr_space->abi == UNW_MIPS_ABI_O32) + addr += 4; + + return addr; +} + +# endif /* UNW_LOCAL_ONLY */ + +HIDDEN unw_dyn_info_list_t _U_dyn_info_list; + +/* XXX fix me: there is currently no way to locate the dyn-info list + by a remote unwinder. On ia64, this is done via a special + unwind-table entry. Perhaps something similar can be done with + DWARF2 unwind info. */ + +static void +put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) +{ + /* it's a no-op */ +} + +static int +get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, + void *arg) +{ + *dyn_info_list_addr = (unw_word_t) (intptr_t) &_U_dyn_info_list; + return 0; +} + +static int +access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, + void *arg) +{ + if (write) + { + Debug (16, "mem[%llx] <- %llx\n", (long long) addr, (long long) *val); + *(unw_word_t *) (intptr_t) addr = *val; + } + else + { + *val = *(unw_word_t *) (intptr_t) addr; + Debug (16, "mem[%llx] -> %llx\n", (long long) addr, (long long) *val); + } + return 0; +} + +static int +access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, + void *arg) +{ + unw_word_t *addr; + ucontext_t *uc = arg; + + if (unw_is_fpreg (reg)) + goto badreg; + + Debug (16, "reg = %s\n", unw_regname (reg)); + if (!(addr = uc_addr (uc, reg))) + goto badreg; + + if (write) + { + *(unw_word_t *) (intptr_t) addr = (mips_reg_t) *val; + Debug (12, "%s <- %llx\n", unw_regname (reg), (long long) *val); + } + else + { + *val = (mips_reg_t) *(unw_word_t *) (intptr_t) addr; + Debug (12, "%s -> %llx\n", unw_regname (reg), (long long) *val); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} + +static int +access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + ucontext_t *uc = arg; + unw_fpreg_t *addr; + + if (!unw_is_fpreg (reg)) + goto badreg; + + if (!(addr = uc_addr (uc, reg))) + goto badreg; + + if (write) + { + Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg), + ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); + *(unw_fpreg_t *) (intptr_t) addr = *val; + } + else + { + *val = *(unw_fpreg_t *) (intptr_t) addr; + Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg), + ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + /* attempt to access a non-preserved register */ + return -UNW_EBADREG; +} + +static int +get_static_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, + void *arg) +{ + + return elf_w (get_proc_name) (as, getpid (), ip, buf, buf_len, offp); +} + +HIDDEN void +mips_local_addr_space_init (void) +{ + memset (&local_addr_space, 0, sizeof (local_addr_space)); + local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN); +#if _MIPS_SIM == _ABIO32 + local_addr_space.abi = UNW_MIPS_ABI_O32; +#elif _MIPS_SIM == _ABIN32 + local_addr_space.abi = UNW_MIPS_ABI_N32; +#elif _MIPS_SIM == _ABI64 + local_addr_space.abi = UNW_MIPS_ABI_N64; +#else +# error Unsupported ABI +#endif + local_addr_space.addr_size = sizeof (void *); + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; + local_addr_space.acc.find_proc_info = dwarf_find_proc_info; + local_addr_space.acc.put_unwind_info = put_unwind_info; + local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; + local_addr_space.acc.access_mem = access_mem; + local_addr_space.acc.access_reg = access_reg; + local_addr_space.acc.access_fpreg = access_fpreg; + local_addr_space.acc.resume = NULL; /* mips_local_resume? FIXME! */ + local_addr_space.acc.get_proc_name = get_static_proc_name; + unw_flush_cache (&local_addr_space, 0, 0); +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Ginit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Ginit_local.c new file mode 100644 index 0000000..f3153b5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Ginit_local.c @@ -0,0 +1,76 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "init.h" + +#ifdef UNW_REMOTE_ONLY + +int +unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) +{ + return -UNW_EINVAL; +} + +#else /* !UNW_REMOTE_ONLY */ + +static int +unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr) +{ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = unw_local_addr_space; + c->dwarf.as_arg = uc; + return common_init (c, use_prev_instr); +} + +int +unw_init_local(unw_cursor_t *cursor, ucontext_t *uc) +{ + return unw_init_local_common(cursor, uc, 1); +} + +int +unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) +{ + if (!flag) + { + return unw_init_local_common(cursor, uc, 1); + } + else if (flag == UNW_INIT_SIGNAL_FRAME) + { + return unw_init_local_common(cursor, uc, 0); + } + else + { + return -UNW_EINVAL; + } +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Ginit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Ginit_remote.c new file mode 100644 index 0000000..9b8ba5b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Ginit_remote.c @@ -0,0 +1,45 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "init.h" +#include "unwind_i.h" + +int +unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) +{ +#ifdef UNW_LOCAL_ONLY + return -UNW_EINVAL; +#else /* !UNW_LOCAL_ONLY */ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = as; + c->dwarf.as_arg = as_arg; + return common_init (c, 0); +#endif /* !UNW_LOCAL_ONLY */ +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gis_signal_frame.c new file mode 100644 index 0000000..c0e3b98 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gis_signal_frame.c @@ -0,0 +1,78 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2015 Imagination Technologies Limited + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include + +int +unw_is_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + unw_word_t w0, w1, ip; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + int ret; + + as = c->dwarf.as; + a = unw_get_accessors_int (as); + arg = c->dwarf.as_arg; + + ip = c->dwarf.ip; + + /* syscall */ + if ((ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0) + return 0; + if ((w1 & 0xffffffff) != 0x0c) + return 0; + + /* li v0, 0x1061 (rt) or li v0, 0x1017 */ + if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0) + return 0; + + switch (c->dwarf.as->abi) + { + case UNW_MIPS_ABI_O32: + switch (w0 & 0xffffffff) + { + case 0x24021061: + return 1; + case 0x24021017: + return 2; + default: + return 0; + } + case UNW_MIPS_ABI_N64: + switch (w0 & 0xffffffff) + { + case 0x2402145b: + return 1; + default: + return 0; + } + default: + return 0; + } +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Greg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Greg_states_iterate.c new file mode 100644 index 0000000..a17dc1b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Greg_states_iterate.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_reg_states_iterate (unw_cursor_t *cursor, + unw_reg_states_callback cb, void *token) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_reg_states_iterate (&c->dwarf, cb, token); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gregs.c new file mode 100644 index 0000000..9519402 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gregs.c @@ -0,0 +1,105 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +/* FIXME: The following is probably unfinished and/or at least partly bogus. */ + +HIDDEN int +tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + int write) +{ + dwarf_loc_t loc = DWARF_NULL_LOC; + + switch (reg) + { + case UNW_MIPS_R0: + case UNW_MIPS_R1: + case UNW_MIPS_R2: + case UNW_MIPS_R3: + case UNW_MIPS_R4: + case UNW_MIPS_R5: + case UNW_MIPS_R6: + case UNW_MIPS_R7: + case UNW_MIPS_R8: + case UNW_MIPS_R9: + case UNW_MIPS_R10: + case UNW_MIPS_R11: + case UNW_MIPS_R12: + case UNW_MIPS_R13: + case UNW_MIPS_R14: + case UNW_MIPS_R15: + case UNW_MIPS_R16: + case UNW_MIPS_R17: + case UNW_MIPS_R18: + case UNW_MIPS_R19: + case UNW_MIPS_R20: + case UNW_MIPS_R21: + case UNW_MIPS_R22: + case UNW_MIPS_R23: + case UNW_MIPS_R24: + case UNW_MIPS_R25: + case UNW_MIPS_R26: + case UNW_MIPS_R27: + case UNW_MIPS_R28: + case UNW_MIPS_R29: + case UNW_MIPS_R30: + case UNW_MIPS_R31: + loc = c->dwarf.loc[reg - UNW_MIPS_R0]; + break; + + case UNW_MIPS_PC: + if (write) + c->dwarf.ip = *valp; /* update the IP cache */ + loc = c->dwarf.loc[reg]; + break; + + case UNW_MIPS_CFA: + if (write) + return -UNW_EREADONLYREG; + *valp = c->dwarf.cfa; + return 0; + + /* FIXME: IP? Copro & shadow registers? */ + + default: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; + } + + if (write) + return dwarf_put (&c->dwarf, loc, *valp); + else + return dwarf_get (&c->dwarf, loc, valp); +} + +/* FIXME for MIPS. */ + +HIDDEN int +tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, + int write) +{ + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gresume.c new file mode 100644 index 0000000..cb70abc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gresume.c @@ -0,0 +1,45 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* FIXME for MIPS. */ + +#include + +#include "unwind_i.h" + +#ifndef UNW_REMOTE_ONLY + +HIDDEN inline int +mips_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ + return -UNW_EINVAL; +} + +#endif /* !UNW_REMOTE_ONLY */ + +int +unw_resume (unw_cursor_t *cursor) +{ + return -UNW_EINVAL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gstep.c new file mode 100644 index 0000000..937136a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Gstep.c @@ -0,0 +1,132 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2015 Imagination Technologies Limited + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "offsets.h" + +static int +mips_handle_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + unw_word_t sc_addr, sp_addr = c->dwarf.cfa; + unw_word_t ra, fp; + int ret; + + switch (unw_is_signal_frame (cursor)) { + case 1: + sc_addr = sp_addr + LINUX_SF_TRAMP_SIZE + sizeof (siginfo_t) + + LINUX_UC_MCONTEXT_OFF; + break; + case 2: + sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF; + break; + default: + return -UNW_EUNSPEC; + } + + if (tdep_big_endian(c->dwarf.as)) + sc_addr += 4; + + c->sigcontext_addr = sc_addr; + + /* Update the dwarf cursor. */ + c->dwarf.loc[UNW_MIPS_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); + c->dwarf.loc[UNW_MIPS_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); + c->dwarf.loc[UNW_MIPS_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0); + c->dwarf.loc[UNW_MIPS_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0); + c->dwarf.loc[UNW_MIPS_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0); + c->dwarf.loc[UNW_MIPS_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0); + c->dwarf.loc[UNW_MIPS_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0); + c->dwarf.loc[UNW_MIPS_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0); + c->dwarf.loc[UNW_MIPS_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0); + c->dwarf.loc[UNW_MIPS_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0); + c->dwarf.loc[UNW_MIPS_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0); + c->dwarf.loc[UNW_MIPS_R11] = DWARF_LOC (sc_addr + LINUX_SC_R11_OFF, 0); + c->dwarf.loc[UNW_MIPS_R12] = DWARF_LOC (sc_addr + LINUX_SC_R12_OFF, 0); + c->dwarf.loc[UNW_MIPS_R13] = DWARF_LOC (sc_addr + LINUX_SC_R13_OFF, 0); + c->dwarf.loc[UNW_MIPS_R14] = DWARF_LOC (sc_addr + LINUX_SC_R14_OFF, 0); + c->dwarf.loc[UNW_MIPS_R15] = DWARF_LOC (sc_addr + LINUX_SC_R15_OFF, 0); + c->dwarf.loc[UNW_MIPS_R16] = DWARF_LOC (sc_addr + LINUX_SC_R16_OFF, 0); + c->dwarf.loc[UNW_MIPS_R17] = DWARF_LOC (sc_addr + LINUX_SC_R17_OFF, 0); + c->dwarf.loc[UNW_MIPS_R18] = DWARF_LOC (sc_addr + LINUX_SC_R18_OFF, 0); + c->dwarf.loc[UNW_MIPS_R19] = DWARF_LOC (sc_addr + LINUX_SC_R19_OFF, 0); + c->dwarf.loc[UNW_MIPS_R20] = DWARF_LOC (sc_addr + LINUX_SC_R20_OFF, 0); + c->dwarf.loc[UNW_MIPS_R21] = DWARF_LOC (sc_addr + LINUX_SC_R21_OFF, 0); + c->dwarf.loc[UNW_MIPS_R22] = DWARF_LOC (sc_addr + LINUX_SC_R22_OFF, 0); + c->dwarf.loc[UNW_MIPS_R23] = DWARF_LOC (sc_addr + LINUX_SC_R23_OFF, 0); + c->dwarf.loc[UNW_MIPS_R24] = DWARF_LOC (sc_addr + LINUX_SC_R24_OFF, 0); + c->dwarf.loc[UNW_MIPS_R25] = DWARF_LOC (sc_addr + LINUX_SC_R25_OFF, 0); + c->dwarf.loc[UNW_MIPS_R26] = DWARF_LOC (sc_addr + LINUX_SC_R26_OFF, 0); + c->dwarf.loc[UNW_MIPS_R27] = DWARF_LOC (sc_addr + LINUX_SC_R27_OFF, 0); + c->dwarf.loc[UNW_MIPS_R28] = DWARF_LOC (sc_addr + LINUX_SC_R28_OFF, 0); + c->dwarf.loc[UNW_MIPS_R29] = DWARF_LOC (sc_addr + LINUX_SC_R29_OFF, 0); + c->dwarf.loc[UNW_MIPS_R30] = DWARF_LOC (sc_addr + LINUX_SC_R30_OFF, 0); + c->dwarf.loc[UNW_MIPS_R31] = DWARF_LOC (sc_addr + LINUX_SC_R31_OFF, 0); + c->dwarf.loc[UNW_MIPS_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); + + /* Set SP/CFA and PC/IP. */ + dwarf_get (&c->dwarf, c->dwarf.loc[UNW_MIPS_R29], &c->dwarf.cfa); + + if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_PC_OFF, 0), + &c->dwarf.ip)) < 0) + return ret; + + if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R31_OFF, 0), + &ra)) < 0) + return ret; + if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R30_OFF, 0), + &fp)) < 0) + return ret; + + Debug (2, "SH (ip=0x%016llx, ra=0x%016llx, sp=0x%016llx, fp=0x%016llx)\n", + (unsigned long long)c->dwarf.ip, (unsigned long long)ra, + (unsigned long long)c->dwarf.cfa, (unsigned long long)fp); + + c->dwarf.pi_valid = 0; + c->dwarf.use_prev_instr = 0; + + return 1; +} + +int +unw_step (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + ret = mips_handle_signal_frame (cursor); + if (ret < 0) + /* Not a signal frame, try DWARF-based unwinding. */ + ret = dwarf_step (&c->dwarf); + + if (unlikely (ret == -UNW_ESTOPUNWIND)) + return ret; + + /* Dwarf unwinding didn't work, stop. */ + if (unlikely (ret < 0)) + return 0; + + return (c->dwarf.ip == 0) ? 0 : 1; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lapply_reg_state.c new file mode 100644 index 0000000..7ebada4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lapply_reg_state.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gapply_reg_state.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lcreate_addr_space.c new file mode 100644 index 0000000..0f2dc6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lcreate_addr_space.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gcreate_addr_space.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lget_proc_info.c new file mode 100644 index 0000000..69028b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lget_proc_info.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_proc_info.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lget_save_loc.c new file mode 100644 index 0000000..9ea048a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lget_save_loc.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_save_loc.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lglobal.c new file mode 100644 index 0000000..6d7b489 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lglobal.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gglobal.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Linit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Linit.c new file mode 100644 index 0000000..e9abfdd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Linit.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Linit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Linit_local.c new file mode 100644 index 0000000..68a1687 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Linit_local.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_local.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Linit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Linit_remote.c new file mode 100644 index 0000000..58cb04a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Linit_remote.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_remote.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lis_signal_frame.c new file mode 100644 index 0000000..b9a7c4f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lis_signal_frame.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gis_signal_frame.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lreg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lreg_states_iterate.c new file mode 100644 index 0000000..f1eb1e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lreg_states_iterate.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Greg_states_iterate.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lregs.c new file mode 100644 index 0000000..2c9c75c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lregs.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gregs.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lresume.c new file mode 100644 index 0000000..41a8cf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lresume.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gresume.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lstep.c new file mode 100644 index 0000000..c1ac3c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/Lstep.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gstep.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/elfxx.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/elfxx.c new file mode 100644 index 0000000..07d3d12 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/elfxx.c @@ -0,0 +1,27 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +#include "../src/elfxx.c" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/gen-offsets.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/gen-offsets.c new file mode 100644 index 0000000..448f694 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/gen-offsets.c @@ -0,0 +1,30 @@ +#include +#include +#include + +#define UC(N,X) \ + printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X)) + +#define SC(N,X) \ + printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X)) + +int +main (void) +{ + printf ( +"/* Linux-specific definitions: */\n\n" + +"/* Define various structure offsets to simplify cross-compilation. */\n\n" + +"/* Offsets for MIPS Linux \"ucontext_t\": */\n\n"); + + UC ("FLAGS", uc_flags); + UC ("LINK", uc_link); + UC ("STACK", uc_stack); + UC ("MCONTEXT", uc_mcontext); + UC ("SIGMASK", uc_sigmask); + + UC ("MCONTEXT_GREGS", uc_mcontext.gregs); + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/getcontext.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/getcontext.S new file mode 100644 index 0000000..d1dbd57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/getcontext.S @@ -0,0 +1,93 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "offsets.h" +#include + + .text + +#if _MIPS_SIM == _ABIO32 +# if __BYTE_ORDER == __BIG_ENDIAN +# define OFFSET 4 +# else +# define OFFSET 0 +# endif +# define SREG(X) \ + sw $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X + OFFSET) ($4); \ + sra $1, $X, 31; \ + sw $1, (LINUX_UC_MCONTEXT_GREGS + 8 * X + 4 - OFFSET) ($4) +/* Yes, we save the return address to PC. */ +# define SPC \ + sw $31, (LINUX_UC_MCONTEXT_PC + OFFSET) ($4); \ + sra $1, $31, 31; \ + sw $1, (LINUX_UC_MCONTEXT_PC + 4 - OFFSET) ($4) +#else +# define SREG(X) sd $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X) ($4) +# define SPC sd $31, (LINUX_UC_MCONTEXT_PC) ($4) +#endif + + .global _Umips_getcontext + .type _Umips_getcontext, %function + # This is a stub version of getcontext() for MIPS which only stores core + # registers. +_Umips_getcontext: + .set noat + SREG (1) + SREG (0) + SREG (2) + SREG (3) + SREG (4) + SREG (5) + SREG (6) + SREG (7) + SREG (8) + SREG (9) + SREG (10) + SREG (11) + SREG (12) + SREG (13) + SREG (14) + SREG (15) + SREG (16) + SREG (17) + SREG (18) + SREG (19) + SREG (20) + SREG (21) + SREG (22) + SREG (23) + SREG (24) + SREG (25) + SREG (26) + SREG (27) + SREG (28) + SREG (29) + SREG (30) + SREG (31) + SPC + li $2, 0 + j $31 + + .size _Umips_getcontext, .-_Umips_getcontext diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/init.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/init.h new file mode 100644 index 0000000..30c193a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/init.h @@ -0,0 +1,59 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static inline int +common_init (struct cursor *c, unsigned use_prev_instr) +{ + int ret, i; + + for (i = 0; i < 32; i++) + c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, UNW_MIPS_R0 + i); + for (i = 32; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + + c->dwarf.loc[UNW_MIPS_PC] = DWARF_REG_LOC (&c->dwarf, UNW_MIPS_PC); + + ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_MIPS_PC], &c->dwarf.ip); + if (ret < 0) + return ret; + + ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_MIPS_R29), + &c->dwarf.cfa); + if (ret < 0) + return ret; + + /* FIXME: Initialisation for other registers. */ + + c->dwarf.args_size = 0; + c->dwarf.stash_frames = 0; + c->dwarf.use_prev_instr = use_prev_instr; + c->dwarf.pi_valid = 0; + c->dwarf.pi_is_dynamic = 0; + c->dwarf.hint = 0; + c->dwarf.prev_rs = 0; + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/is_fpreg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/is_fpreg.c new file mode 100644 index 0000000..a92dd5e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/is_fpreg.c @@ -0,0 +1,35 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +/* FIXME: I'm not sure if libunwind's GP/FP register distinction is very useful + on MIPS. */ + +int +unw_is_fpreg (int regnum) +{ + /* FIXME: Support FP. */ + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/offsets.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/offsets.h new file mode 100644 index 0000000..b506051 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/offsets.h @@ -0,0 +1,86 @@ +/* Linux-specific definitions: */ + +/* Define various structure offsets to simplify cross-compilation. */ + +/* FIXME: Currently these are only used in getcontext.S, which is only used + for a local unwinder, so we can use the compile-time ABI. At a later date + we will want all three here, to use for signal handlers. Also, because + of the three ABIs, gen-offsets.c can not quite generate this file. */ + +/* Offsets for MIPS Linux "ucontext_t": */ + +/* First 24 bytes in sigframe are argument save space and padding for +what used to be signal trampolines. Ref: arch/mips/kernel/signal.c */ +#define LINUX_SF_TRAMP_SIZE 0x18 + +#if _MIPS_SIM == _ABIO32 + +# define LINUX_UC_FLAGS_OFF 0x0 +# define LINUX_UC_LINK_OFF 0x4 +# define LINUX_UC_STACK_OFF 0x8 +# define LINUX_UC_MCONTEXT_OFF 0x18 +# define LINUX_UC_SIGMASK_OFF 0x268 +# define LINUX_UC_MCONTEXT_PC 0x20 +# define LINUX_UC_MCONTEXT_GREGS 0x28 + +#elif _MIPS_SIM == _ABIN32 + +# define LINUX_UC_FLAGS_OFF 0x0 +# define LINUX_UC_LINK_OFF 0x4 +# define LINUX_UC_STACK_OFF 0x8 +# define LINUX_UC_MCONTEXT_OFF 0x18 +# define LINUX_UC_SIGMASK_OFF 0x270 +# define LINUX_UC_MCONTEXT_PC 0x258 +# define LINUX_UC_MCONTEXT_GREGS 0x18 + +#elif _MIPS_SIM == _ABI64 + +# define LINUX_UC_FLAGS_OFF 0x0 +# define LINUX_UC_LINK_OFF 0x8 +# define LINUX_UC_STACK_OFF 0x10 +# define LINUX_UC_MCONTEXT_OFF 0x28 +# define LINUX_UC_SIGMASK_OFF 0x280 +# define LINUX_UC_MCONTEXT_PC 0x268 +# define LINUX_UC_MCONTEXT_GREGS 0x28 + +#else + +#error Unsupported ABI + +#endif + +#define LINUX_SC_R0_OFF (LINUX_UC_MCONTEXT_GREGS - LINUX_UC_MCONTEXT_OFF) +#define LINUX_SC_R1_OFF (LINUX_SC_R0_OFF + 1*8) +#define LINUX_SC_R2_OFF (LINUX_SC_R0_OFF + 2*8) +#define LINUX_SC_R3_OFF (LINUX_SC_R0_OFF + 3*8) +#define LINUX_SC_R4_OFF (LINUX_SC_R0_OFF + 4*8) +#define LINUX_SC_R5_OFF (LINUX_SC_R0_OFF + 5*8) +#define LINUX_SC_R6_OFF (LINUX_SC_R0_OFF + 6*8) +#define LINUX_SC_R7_OFF (LINUX_SC_R0_OFF + 7*8) +#define LINUX_SC_R8_OFF (LINUX_SC_R0_OFF + 8*8) +#define LINUX_SC_R9_OFF (LINUX_SC_R0_OFF + 9*8) +#define LINUX_SC_R10_OFF (LINUX_SC_R0_OFF + 10*8) +#define LINUX_SC_R11_OFF (LINUX_SC_R0_OFF + 11*8) +#define LINUX_SC_R12_OFF (LINUX_SC_R0_OFF + 12*8) +#define LINUX_SC_R13_OFF (LINUX_SC_R0_OFF + 13*8) +#define LINUX_SC_R14_OFF (LINUX_SC_R0_OFF + 14*8) +#define LINUX_SC_R15_OFF (LINUX_SC_R0_OFF + 15*8) +#define LINUX_SC_R16_OFF (LINUX_SC_R0_OFF + 16*8) +#define LINUX_SC_R17_OFF (LINUX_SC_R0_OFF + 17*8) +#define LINUX_SC_R18_OFF (LINUX_SC_R0_OFF + 18*8) +#define LINUX_SC_R19_OFF (LINUX_SC_R0_OFF + 19*8) +#define LINUX_SC_R20_OFF (LINUX_SC_R0_OFF + 20*8) +#define LINUX_SC_R21_OFF (LINUX_SC_R0_OFF + 21*8) +#define LINUX_SC_R22_OFF (LINUX_SC_R0_OFF + 22*8) +#define LINUX_SC_R23_OFF (LINUX_SC_R0_OFF + 23*8) +#define LINUX_SC_R24_OFF (LINUX_SC_R0_OFF + 24*8) +#define LINUX_SC_R25_OFF (LINUX_SC_R0_OFF + 25*8) +#define LINUX_SC_R26_OFF (LINUX_SC_R0_OFF + 26*8) +#define LINUX_SC_R27_OFF (LINUX_SC_R0_OFF + 27*8) +#define LINUX_SC_R28_OFF (LINUX_SC_R0_OFF + 28*8) +#define LINUX_SC_R29_OFF (LINUX_SC_R0_OFF + 29*8) +#define LINUX_SC_R30_OFF (LINUX_SC_R0_OFF + 30*8) +#define LINUX_SC_R31_OFF (LINUX_SC_R0_OFF + 31*8) + +#define LINUX_SC_SP_OFF LINUX_SC_R29_OFF +#define LINUX_SC_PC_OFF (LINUX_UC_MCONTEXT_PC - LINUX_UC_MCONTEXT_OFF) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/regname.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/regname.c new file mode 100644 index 0000000..b137b97 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/regname.c @@ -0,0 +1,48 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static const char *regname[] = + { + /* 0. */ + "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", + /* 8. */ + "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", + /* 16. */ + "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", + /* 24. */ + "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31", + }; + +const char * +unw_regname (unw_regnum_t reg) +{ + if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) + return regname[reg]; + else if (reg == UNW_MIPS_PC) + return "pc"; + else + return "???"; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/siglongjmp.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/siglongjmp.S new file mode 100644 index 0000000..9cbcf3d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/mips/siglongjmp.S @@ -0,0 +1,8 @@ + /* Dummy implementation for now. */ + + .globl _UI_siglongjmp_cont + .globl _UI_longjmp_cont + +_UI_siglongjmp_cont: +_UI_longjmp_cont: + j $31 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/oop/_OOP_find_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/oop/_OOP_find_proc_info.c new file mode 100644 index 0000000..71c54a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/oop/_OOP_find_proc_info.c @@ -0,0 +1,104 @@ +// 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. + +#include +#include +#include +#include +#include + +#include + +#include "_OOP_internal.h" + +int +_OOP_find_proc_info ( + unw_word_t start_ip, + unw_word_t end_ip, + unw_word_t eh_frame_table, + unw_word_t eh_frame_table_len, + unw_word_t exidx_frame_table, + unw_word_t exidx_frame_table_len, + unw_addr_space_t as, + unw_word_t ip, + unw_proc_info_t *pi, + int need_unwind_info, + void *arg) +{ + int ret = 0; + + unw_dyn_info_t di; + di.start_ip = start_ip; + di.end_ip = end_ip; + di.gp = pi->gp; + di.u.rti.name_ptr = 0; + +#if UNW_TARGET_ARM + if (exidx_frame_table != 0) { + di.format = UNW_INFO_FORMAT_ARM_EXIDX; + di.u.rti.table_data = exidx_frame_table; + di.u.rti.table_len = exidx_frame_table_len; + di.u.rti.segbase = 0; + } + else +#endif + if (eh_frame_table != 0) { + unw_accessors_t *a = unw_get_accessors_int (as); + + unw_word_t hdr; + if ((*a->access_mem)(as, eh_frame_table, &hdr, 0, arg) < 0) { + return -UNW_EINVAL; + } + struct dwarf_eh_frame_hdr* exhdr = (struct dwarf_eh_frame_hdr*)&hdr; + + if (exhdr->version != DW_EH_VERSION) { + Debug (1, "Unexpected version %d\n", exhdr->version); + return -UNW_EBADVERSION; + } + unw_word_t addr = eh_frame_table + offsetof(struct dwarf_eh_frame_hdr, eh_frame); + unw_word_t eh_frame_start; + unw_word_t fde_count; + + /* read eh_frame_ptr */ + if ((ret = dwarf_read_encoded_pointer(as, a, &addr, exhdr->eh_frame_ptr_enc, pi, &eh_frame_start, arg)) < 0) { + return ret; + } + + /* read fde_count */ + if ((ret = dwarf_read_encoded_pointer(as, a, &addr, exhdr->fde_count_enc, pi, &fde_count, arg)) < 0) { + return ret; + } + + // If there are no frame table entries + if (fde_count == 0) { + Debug(1, "No frame table entries\n"); + return -UNW_ENOINFO; + } + + if (exhdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) { + Debug (1, "Table encoding not supported %x\n", exhdr->table_enc); + return -UNW_EINVAL; + } + + di.format = UNW_INFO_FORMAT_REMOTE_TABLE; + di.u.rti.table_data = addr; + di.u.rti.table_len = (fde_count * 8) / sizeof (unw_word_t); + di.u.rti.segbase = eh_frame_table; + } + else { + Debug (1, "No frame table data\n"); + return -UNW_ENOINFO; + } + + ret = tdep_search_unwind_table(as, ip, &di, pi, need_unwind_info, arg); + if (ret < 0) { + return ret; + } + + if (ip < pi->start_ip || ip >= pi->end_ip) { + Debug (1, "ip %p not in range start_ip %p end_ip %p\n", ip, pi->start_ip, pi->end_ip); + return -UNW_ENOINFO; + } + return UNW_ESUCCESS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/oop/_OOP_internal.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/oop/_OOP_internal.h new file mode 100644 index 0000000..6e41104 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/oop/_OOP_internal.h @@ -0,0 +1,25 @@ +// 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. + +#ifndef _OOP_internal_h +#define _OOP_internal_h + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#include +#include +#include +#include + +#include "libunwind_i.h" +#include "dwarf-eh.h" +#include "dwarf_i.h" + +#endif /* _OOP_internal_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-freebsd.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-freebsd.c new file mode 100644 index 0000000..753e819 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-freebsd.c @@ -0,0 +1,166 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2010 Konstantin Belousov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include +#include +#include +#include +#include + +#include "libunwind_i.h" + +static void * +get_mem(size_t sz) +{ + void *res; + + res = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + if (res == MAP_FAILED) + return (NULL); + return (res); +} + +static void +free_mem(void *ptr, size_t sz) +{ + munmap(ptr, sz); +} + +static int +get_pid_by_tid(int tid) +{ + int mib[3], error; + size_t len, len1; + char *buf; + struct kinfo_proc *kv; + unsigned i, pid; + + len = 0; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_ALL; + + error = sysctl(mib, 3, NULL, &len, NULL, 0); + if (error == -1) + return (-1); + len1 = len * 4 / 3; + buf = get_mem(len1); + if (buf == NULL) + return (-1); + len = len1; + error = sysctl(mib, 3, buf, &len, NULL, 0); + if (error == -1) { + free_mem(buf, len1); + return (-1); + } + pid = -1; + for (i = 0, kv = (struct kinfo_proc *)buf; i < len / sizeof(*kv); + i++, kv++) { + if (kv->ki_tid == tid) { + pid = kv->ki_pid; + break; + } + } + free_mem(buf, len1); + return (pid); +} + +int +tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, + unsigned long *segbase, unsigned long *mapoff, char *path, size_t pathlen) +{ + int mib[4], error, ret; + size_t len, len1; + char *buf, *bp, *eb; + struct kinfo_vmentry *kv; + + len = 0; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_VMMAP; + mib[3] = pid; + + error = sysctl(mib, 4, NULL, &len, NULL, 0); + if (error == -1) { + if (errno == ESRCH) { + mib[3] = get_pid_by_tid(pid); + if (mib[3] != -1) + error = sysctl(mib, 4, NULL, &len, NULL, 0); + if (error == -1) + return (-UNW_EUNSPEC); + } else + return (-UNW_EUNSPEC); + } + len1 = len * 4 / 3; + buf = get_mem(len1); + if (buf == NULL) + return (-UNW_EUNSPEC); + len = len1; + error = sysctl(mib, 4, buf, &len, NULL, 0); + if (error == -1) { + free_mem(buf, len1); + return (-UNW_EUNSPEC); + } + ret = -UNW_EUNSPEC; + for (bp = buf, eb = buf + len; bp < eb; bp += kv->kve_structsize) { + kv = (struct kinfo_vmentry *)(uintptr_t)bp; + if (ip < kv->kve_start || ip >= kv->kve_end) + continue; + if (kv->kve_type != KVME_TYPE_VNODE) + continue; + *segbase = kv->kve_start; + *mapoff = kv->kve_offset; + if (path) + { + strncpy(path, kv->kve_path, pathlen); + } + ret = elf_map_image (ei, kv->kve_path); + break; + } + free_mem(buf, len1); + return (ret); +} + +#ifndef UNW_REMOTE_ONLY + +void +tdep_get_exe_image_path (char *path) +{ + int mib[4], error; + size_t len; + + len = 0; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = getpid(); + + error = sysctl(mib, 4, path, &len, NULL, 0); + if (error == -1) + path[0] = 0; +} + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-hpux.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-hpux.c new file mode 100644 index 0000000..48bfb05 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-hpux.c @@ -0,0 +1,78 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include + +#include "libunwind_i.h" + +#include "elf64.h" + +HIDDEN int +tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, + unsigned long *segbase, unsigned long *mapoff, + char *path, size_t pathlen) +{ + struct load_module_desc lmd; + const char *path2; + + if (pid != getpid ()) + { + printf ("%s: remote case not implemented yet\n", __FUNCTION__); + return -UNW_ENOINFO; + } + + if (!dlmodinfo (ip, &lmd, sizeof (lmd), NULL, 0, 0)) + return -UNW_ENOINFO; + + *segbase = lmd.text_base; + *mapoff = 0; /* XXX fix me? */ + + path2 = dlgetname (&lmd, sizeof (lmd), NULL, 0, 0); + if (!path2) + return -UNW_ENOINFO; + if (path) + { + strncpy(path, path2, pathlen); + path[pathlen - 1] = '\0'; + if (strcmp(path, path2) != 0) + Debug(1, "buffer size (%d) not big enough to hold path\n", pathlen); + } + Debug(1, "segbase=%lx, mapoff=%lx, path=%s\n", *segbase, *mapoff, path); + + return elf_map_image (ei, path); +} + +#ifndef UNW_REMOTE_ONLY + +void +tdep_get_exe_image_path (char *path) +{ + path[0] = 0; /* XXX */ +} + +#endif + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-linux.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-linux.c new file mode 100644 index 0000000..8a00669 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-linux.c @@ -0,0 +1,73 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#include "libunwind_i.h" +#include "os-linux.h" + +int +tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, + unsigned long *segbase, unsigned long *mapoff, + char *path, size_t pathlen) +{ + struct map_iterator mi; + int found = 0, rc; + unsigned long hi; + + if (maps_init (&mi, pid) < 0) + return -1; + + while (maps_next (&mi, segbase, &hi, mapoff)) + if (ip >= *segbase && ip < hi) + { + found = 1; + break; + } + + if (!found) + { + maps_close (&mi); + return -1; + } + if (path) + { + strncpy(path, mi.path, pathlen); + } + rc = elf_map_image (ei, mi.path); + maps_close (&mi); + return rc; +} + +#ifndef UNW_REMOTE_ONLY + +void +tdep_get_exe_image_path (char *path) +{ + strcpy(path, "/proc/self/exe"); +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-linux.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-linux.h new file mode 100644 index 0000000..3976b38 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-linux.h @@ -0,0 +1,297 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Copyright (C) 2007 David Mosberger-Tang + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef os_linux_h +#define os_linux_h + +struct map_iterator + { + off_t offset; + int fd; + size_t buf_size; + char *buf; + char *buf_end; + char *path; + }; + +static inline char * +ltoa (char *buf, long val) +{ + char *cp = buf, tmp; + ssize_t i, len; + + do + { + *cp++ = '0' + (val % 10); + val /= 10; + } + while (val); + + /* reverse the order of the digits: */ + len = cp - buf; + --cp; + for (i = 0; i < len / 2; ++i) + { + tmp = buf[i]; + buf[i] = cp[-i]; + cp[-i] = tmp; + } + return buf + len; +} + +static inline int +maps_init (struct map_iterator *mi, pid_t pid) +{ + char path[sizeof ("/proc/0123456789/maps")], *cp; + + memcpy (path, "/proc/", 6); + cp = ltoa (path + 6, pid); + assert (cp + 6 < path + sizeof (path)); + memcpy (cp, "/maps", 6); + + mi->fd = open (path, O_RDONLY); + if (mi->fd >= 0) + { + /* Try to allocate a page-sized buffer. */ + mi->buf_size = getpagesize (); + cp = mmap (NULL, mi->buf_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (cp == MAP_FAILED) + { + close(mi->fd); + mi->fd = -1; + return -1; + } + else + { + mi->offset = 0; + mi->buf = mi->buf_end = cp + mi->buf_size; + return 0; + } + } + return -1; +} + +static inline char * +skip_whitespace (char *cp) +{ + if (!cp) + return NULL; + + while (*cp == ' ' || *cp == '\t') + ++cp; + return cp; +} + +static inline char * +scan_hex (char *cp, unsigned long *valp) +{ + unsigned long num_digits = 0, digit, val = 0; + + cp = skip_whitespace (cp); + if (!cp) + return NULL; + + while (1) + { + digit = *cp; + if ((digit - '0') <= 9) + digit -= '0'; + else if ((digit - 'a') < 6) + digit -= 'a' - 10; + else if ((digit - 'A') < 6) + digit -= 'A' - 10; + else + break; + val = (val << 4) | digit; + ++num_digits; + ++cp; + } + if (!num_digits) + return NULL; + *valp = val; + return cp; +} + +static inline char * +scan_dec (char *cp, unsigned long *valp) +{ + unsigned long num_digits = 0, digit, val = 0; + + if (!(cp = skip_whitespace (cp))) + return NULL; + + while (1) + { + digit = *cp; + if ((digit - '0') <= 9) + { + digit -= '0'; + ++cp; + } + else + break; + val = (10 * val) + digit; + ++num_digits; + } + if (!num_digits) + return NULL; + *valp = val; + return cp; +} + +static inline char * +scan_char (char *cp, char *valp) +{ + if (!cp) + return NULL; + + *valp = *cp; + + /* don't step over NUL terminator */ + if (*cp) + ++cp; + return cp; +} + +/* Scan a string delimited by white-space. Fails on empty string or + if string is doesn't fit in the specified buffer. */ +static inline char * +scan_string (char *cp, char *valp, size_t buf_size) +{ + size_t i = 0; + + if (!(cp = skip_whitespace (cp))) + return NULL; + + while (*cp != ' ' && *cp != '\t' && *cp != '\0') + { + if ((valp != NULL) && (i < buf_size - 1)) + valp[i++] = *cp; + ++cp; + } + if (i == 0 || i >= buf_size) + return NULL; + valp[i] = '\0'; + return cp; +} + +static inline int +maps_next (struct map_iterator *mi, + unsigned long *low, unsigned long *high, unsigned long *offset) +{ + char perm[16], dash = 0, colon = 0, *cp; + unsigned long major, minor, inum; + ssize_t i, nread; + + if (mi->fd < 0) + return 0; + + while (1) + { + ssize_t bytes_left = mi->buf_end - mi->buf; + char *eol = NULL; + + for (i = 0; i < bytes_left; ++i) + { + if (mi->buf[i] == '\n') + { + eol = mi->buf + i; + break; + } + else if (mi->buf[i] == '\0') + break; + } + if (!eol) + { + /* copy down the remaining bytes, if any */ + if (bytes_left > 0) + memmove (mi->buf_end - mi->buf_size, mi->buf, bytes_left); + + mi->buf = mi->buf_end - mi->buf_size; + nread = read (mi->fd, mi->buf + bytes_left, + mi->buf_size - bytes_left); + if (nread <= 0) + return 0; + else if ((size_t) (nread + bytes_left) < mi->buf_size) + { + /* Move contents to the end of the buffer so we + maintain the invariant that all bytes between + mi->buf and mi->buf_end are valid. */ + memmove (mi->buf_end - nread - bytes_left, mi->buf, + nread + bytes_left); + mi->buf = mi->buf_end - nread - bytes_left; + } + + eol = mi->buf + bytes_left + nread - 1; + + for (i = bytes_left; i < bytes_left + nread; ++i) + if (mi->buf[i] == '\n') + { + eol = mi->buf + i; + break; + } + } + cp = mi->buf; + mi->buf = eol + 1; + *eol = '\0'; + + /* scan: "LOW-HIGH PERM OFFSET MAJOR:MINOR INUM PATH" */ + cp = scan_hex (cp, low); + cp = scan_char (cp, &dash); + cp = scan_hex (cp, high); + cp = scan_string (cp, perm, sizeof (perm)); + cp = scan_hex (cp, offset); + cp = scan_hex (cp, &major); + cp = scan_char (cp, &colon); + cp = scan_hex (cp, &minor); + cp = scan_dec (cp, &inum); + cp = mi->path = skip_whitespace (cp); + if (!cp) + continue; + cp = scan_string (cp, NULL, 0); + if (dash != '-' || colon != ':') + continue; /* skip line with unknown or bad format */ + return 1; + } + return 0; +} + +static inline void +maps_close (struct map_iterator *mi) +{ + if (mi->fd < 0) + return; + close (mi->fd); + mi->fd = -1; + if (mi->buf) + { + munmap (mi->buf_end - mi->buf_size, mi->buf_size); + mi->buf = mi->buf_end = NULL; + } +} + +#endif /* os_linux_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-qnx.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-qnx.c new file mode 100644 index 0000000..4a76c7c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/os-qnx.c @@ -0,0 +1,117 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2013 Garmin International + Contributed by Matt Fischer + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "libunwind_i.h" + +struct cb_info +{ + unw_word_t ip; + unsigned long segbase; + unsigned long offset; + const char *path; +}; + +static int callback(const struct dl_phdr_info *info, size_t size, void *data) +{ + int i; + struct cb_info *cbi = (struct cb_info*)data; + for(i=0; idlpi_phnum; i++) { + int segbase = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr; + if(cbi->ip >= segbase && cbi->ip < segbase + info->dlpi_phdr[i].p_memsz) + { + cbi->path = info->dlpi_name; + cbi->offset = info->dlpi_phdr[i].p_offset; + cbi->segbase = segbase; + return 1; + } + } + + return 0; +} + +int +tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, + unsigned long *segbase, unsigned long *mapoff, + char *path, size_t pathlen) +{ + struct cb_info cbi; + int ret = -1; + cbi.ip = ip; + cbi.segbase = 0; + cbi.offset = 0; + cbi.path = NULL; + + /* QNX's support for accessing symbol maps is severely broken. There is + a devctl() call that can be made on a proc node (DCMD_PROC_MAPDEBUG) + which returns information similar to Linux's /proc//maps + node, however the filename that is returned by this call is not an + absolute path, and there is no foolproof way to map the filename + back to the file that it came from. + + Therefore, the normal approach for implementing this function, + which works equally well for both local and remote unwinding, + will not work here. The only type of image lookup which works + reliably is locally, using dl_iterate_phdr(). However, the only + time that this function is required to look up a remote image is for + ptrace support, which doesn't work on QNX anyway. Local unwinding, + which is the main case that makes use of this function, will work + fine with dl_iterate_phdr(). Therefore, in lieu of any better + platform support for remote image lookup, this function has just + been implemented in terms of dl_iterate_phdr(). + */ + + if (pid != getpid()) + { + /* Return an error if an attempt is made to perform remote image lookup */ + return -1; + } + + if (dl_iterate_phdr (callback, &cbi) != 0) + { + if (path) + { + strncpy (path, cbi.path, pathlen); + } + + *mapoff = cbi.offset; + *segbase = cbi.segbase; + + ret = elf_map_image (ei, cbi.path); + } + + return ret; +} + +#ifndef UNW_REMOTE_ONLY + +void +tdep_get_exe_image_path (char *path) +{ + path[0] = 0; /* XXX */ +} + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gapply_reg_state.c new file mode 100644 index 0000000..82f056d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gapply_reg_state.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_apply_reg_state (unw_cursor_t *cursor, + void *reg_states_data) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gget_proc_info.c new file mode 100644 index 0000000..7dfb6d4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gget_proc_info.c @@ -0,0 +1,41 @@ +/* libunwind - a platform-independent unwind library + + Copied from src/x86_64/, modified slightly (or made empty stubs) for + building frysk successfully on ppc64, by Wu Zhou + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +int +unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + ret = dwarf_make_proc_info (&c->dwarf); + if (ret < 0) + return ret; + + *pi = c->dwarf.pi; + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gget_save_loc.c new file mode 100644 index 0000000..5343fa4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gget_save_loc.c @@ -0,0 +1,34 @@ +/* libunwind - a platform-independent unwind library + + Copied from src/x86_64/, modified slightly (or made empty stubs) for + building frysk successfully on ppc64, by Wu Zhou + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +int +unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) +{ + /* XXX: empty stub. */ + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Ginit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Ginit_local.c new file mode 100644 index 0000000..366cf5b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Ginit_local.c @@ -0,0 +1,88 @@ +/* libunwind - a platform-independent unwind library + + Copied from src/x86_64/, modified slightly (or made empty stubs) for + building frysk successfully on ppc64, by Wu Zhou + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#ifdef UNW_TARGET_PPC64 +#include "../ppc64/init.h" +#else +#include "../ppc32/init.h" +#endif + +#ifdef UNW_REMOTE_ONLY + +int +unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) +{ + /* XXX: empty stub. */ + return -UNW_EINVAL; +} + +#else /* !UNW_REMOTE_ONLY */ + +static int +unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr) +{ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = unw_local_addr_space; + c->dwarf.as_arg = uc; + #ifdef UNW_TARGET_PPC64 + return common_init_ppc64 (c, use_prev_instr); + #else + return common_init_ppc32 (c, use_prev_instr); + #endif +} + +int +unw_init_local(unw_cursor_t *cursor, ucontext_t *uc) +{ + return unw_init_local_common(cursor, uc, 1); +} + +int +unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) +{ + if (!flag) + { + return unw_init_local_common(cursor, uc, 1); + } + else if (flag == UNW_INIT_SIGNAL_FRAME) + { + return unw_init_local_common(cursor, uc, 0); + } + else + { + return -UNW_EINVAL; + } +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Ginit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Ginit_remote.c new file mode 100644 index 0000000..ed85be8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Ginit_remote.c @@ -0,0 +1,60 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#ifdef UNW_TARGET_PPC64 +#include "../ppc64/init.h" +#else +#include "../ppc32/init.h" +#endif + +int +unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) +{ +#ifdef UNW_LOCAL_ONLY + return -UNW_EINVAL; +#else /* !UNW_LOCAL_ONLY */ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = as; + c->dwarf.as_arg = as_arg; + + #ifdef UNW_TARGET_PPC64 + return common_init_ppc64 (c, 0); + #elif UNW_TARGET_PPC32 + return common_init_ppc32 (c, 0); + #else + #error init_remote :: NO VALID PPC ARCH! + #endif +#endif /* !UNW_LOCAL_ONLY */ +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gis_signal_frame.c new file mode 100644 index 0000000..6184dd5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Gis_signal_frame.c @@ -0,0 +1,78 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +int +unw_is_signal_frame (unw_cursor_t * cursor) +{ + struct cursor *c = (struct cursor *) cursor; + unw_word_t w0, w1, i0, i1, i2, ip; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + int ret; + + as = c->dwarf.as; + as->validate = 1; /* Don't trust the ip */ + arg = c->dwarf.as_arg; + + /* Check if return address points at sigreturn sequence. + on ppc64 Linux that is (see libc.so): + 0x38210080 addi r1, r1, 128 // pop the stack + 0x380000ac li r0, 172 // invoke system service 172 + 0x44000002 sc + */ + + ip = c->dwarf.ip; + if (ip == 0) + return 0; + + /* Read up two 8-byte words at the IP. We are only looking at 3 + consecutive 32-bit words, so the second 8-byte word needs to be + shifted right by 32 bits (think big-endian) */ + + a = unw_get_accessors_int (as); + if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0 + || (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0) + return 0; + + if (tdep_big_endian (as)) + { + i0 = w0 >> 32; + i1 = w0 & 0xffffffffUL; + i2 = w1 >> 32; + } + else + { + i0 = w0 & 0xffffffffUL; + i1 = w0 >> 32; + i2 = w1 & 0xffffffffUL; + } + + return (i0 == 0x38210080 && i1 == 0x380000ac && i2 == 0x44000002); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Greg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Greg_states_iterate.c new file mode 100644 index 0000000..a17dc1b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Greg_states_iterate.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_reg_states_iterate (unw_cursor_t *cursor, + unw_reg_states_callback cb, void *token) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_reg_states_iterate (&c->dwarf, cb, token); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lapply_reg_state.c new file mode 100644 index 0000000..7ebada4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lapply_reg_state.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gapply_reg_state.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lget_proc_info.c new file mode 100644 index 0000000..69028b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lget_proc_info.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_proc_info.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lget_save_loc.c new file mode 100644 index 0000000..9ea048a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lget_save_loc.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_save_loc.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Linit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Linit_local.c new file mode 100644 index 0000000..68a1687 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Linit_local.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_local.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Linit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Linit_remote.c new file mode 100644 index 0000000..58cb04a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Linit_remote.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_remote.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lis_signal_frame.c new file mode 100644 index 0000000..b9a7c4f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lis_signal_frame.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gis_signal_frame.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lreg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lreg_states_iterate.c new file mode 100644 index 0000000..f1eb1e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/Lreg_states_iterate.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Greg_states_iterate.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/longjmp.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/longjmp.S new file mode 100644 index 0000000..d363aef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/longjmp.S @@ -0,0 +1,36 @@ +/* libunwind - a platform-independent unwind library + + Copied from src/x86_64/, modified slightly (or made empty stubs) for + building frysk successfully on ppc64, by Wu Zhou + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + .globl _UI_longjmp_cont + + .type _UI_longjmp_cont, @function +_UI_longjmp_cont: + .size _UI_longjmp_cont, .-_UI_longjmp_cont + +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/siglongjmp.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/siglongjmp.S new file mode 100644 index 0000000..64be36c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc/siglongjmp.S @@ -0,0 +1,31 @@ +/* libunwind - a platform-independent unwind library + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + .globl _UI_siglongjmp_cont + + _UI_siglongjmp_cont: + +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gapply_reg_state.c new file mode 100644 index 0000000..82f056d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gapply_reg_state.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_apply_reg_state (unw_cursor_t *cursor, + void *reg_states_data) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gcreate_addr_space.c new file mode 100644 index 0000000..aaa68bb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gcreate_addr_space.c @@ -0,0 +1,56 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include + +unw_addr_space_t +unw_create_addr_space (unw_accessors_t *a, int byte_order) +{ +#ifdef UNW_LOCAL_ONLY + return NULL; +#else + unw_addr_space_t as; + + /* + * We support only big-endian on Linux ppc32. + */ + if (byte_order != 0 && byte_order != __BIG_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); + if (!as) + return NULL; + + memset (as, 0, sizeof (*as)); + + as->acc = *a; + + return as; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gglobal.c new file mode 100644 index 0000000..a0f80be --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gglobal.c @@ -0,0 +1,135 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "dwarf_i.h" + +HIDDEN define_lock (ppc32_lock); +HIDDEN int tdep_init_done; + +/* The API register numbers are exactly the same as the .eh_frame + registers, for now at least. */ +HIDDEN const uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH] = + { + [UNW_PPC32_R0]=UNW_PPC32_R0, + [UNW_PPC32_R1]=UNW_PPC32_R1, + [UNW_PPC32_R2]=UNW_PPC32_R2, + [UNW_PPC32_R3]=UNW_PPC32_R3, + [UNW_PPC32_R4]=UNW_PPC32_R4, + [UNW_PPC32_R5]=UNW_PPC32_R5, + [UNW_PPC32_R6]=UNW_PPC32_R6, + [UNW_PPC32_R7]=UNW_PPC32_R7, + [UNW_PPC32_R8]=UNW_PPC32_R8, + [UNW_PPC32_R9]=UNW_PPC32_R9, + [UNW_PPC32_R10]=UNW_PPC32_R10, + [UNW_PPC32_R11]=UNW_PPC32_R11, + [UNW_PPC32_R12]=UNW_PPC32_R12, + [UNW_PPC32_R13]=UNW_PPC32_R13, + [UNW_PPC32_R14]=UNW_PPC32_R14, + [UNW_PPC32_R15]=UNW_PPC32_R15, + [UNW_PPC32_R16]=UNW_PPC32_R16, + [UNW_PPC32_R17]=UNW_PPC32_R17, + [UNW_PPC32_R18]=UNW_PPC32_R18, + [UNW_PPC32_R19]=UNW_PPC32_R19, + [UNW_PPC32_R20]=UNW_PPC32_R20, + [UNW_PPC32_R21]=UNW_PPC32_R21, + [UNW_PPC32_R22]=UNW_PPC32_R22, + [UNW_PPC32_R23]=UNW_PPC32_R23, + [UNW_PPC32_R24]=UNW_PPC32_R24, + [UNW_PPC32_R25]=UNW_PPC32_R25, + [UNW_PPC32_R26]=UNW_PPC32_R26, + [UNW_PPC32_R27]=UNW_PPC32_R27, + [UNW_PPC32_R28]=UNW_PPC32_R28, + [UNW_PPC32_R29]=UNW_PPC32_R29, + [UNW_PPC32_R30]=UNW_PPC32_R30, + [UNW_PPC32_R31]=UNW_PPC32_R31, + + [UNW_PPC32_CTR]=UNW_PPC32_CTR, + [UNW_PPC32_XER]=UNW_PPC32_XER, + [UNW_PPC32_CCR]=UNW_PPC32_CCR, + [UNW_PPC32_LR]=UNW_PPC32_LR, + [UNW_PPC32_FPSCR]=UNW_PPC32_FPSCR, + + [UNW_PPC32_F0]=UNW_PPC32_F0, + [UNW_PPC32_F1]=UNW_PPC32_F1, + [UNW_PPC32_F2]=UNW_PPC32_F2, + [UNW_PPC32_F3]=UNW_PPC32_F3, + [UNW_PPC32_F4]=UNW_PPC32_F4, + [UNW_PPC32_F5]=UNW_PPC32_F5, + [UNW_PPC32_F6]=UNW_PPC32_F6, + [UNW_PPC32_F7]=UNW_PPC32_F7, + [UNW_PPC32_F8]=UNW_PPC32_F8, + [UNW_PPC32_F9]=UNW_PPC32_F9, + [UNW_PPC32_F10]=UNW_PPC32_F10, + [UNW_PPC32_F11]=UNW_PPC32_F11, + [UNW_PPC32_F12]=UNW_PPC32_F12, + [UNW_PPC32_F13]=UNW_PPC32_F13, + [UNW_PPC32_F14]=UNW_PPC32_F14, + [UNW_PPC32_F15]=UNW_PPC32_F15, + [UNW_PPC32_F16]=UNW_PPC32_F16, + [UNW_PPC32_F17]=UNW_PPC32_F17, + [UNW_PPC32_F18]=UNW_PPC32_F18, + [UNW_PPC32_F19]=UNW_PPC32_F19, + [UNW_PPC32_F20]=UNW_PPC32_F20, + [UNW_PPC32_F21]=UNW_PPC32_F21, + [UNW_PPC32_F22]=UNW_PPC32_F22, + [UNW_PPC32_F23]=UNW_PPC32_F23, + [UNW_PPC32_F24]=UNW_PPC32_F24, + [UNW_PPC32_F25]=UNW_PPC32_F25, + [UNW_PPC32_F26]=UNW_PPC32_F26, + [UNW_PPC32_F27]=UNW_PPC32_F27, + [UNW_PPC32_F28]=UNW_PPC32_F28, + [UNW_PPC32_F29]=UNW_PPC32_F29, + [UNW_PPC32_F30]=UNW_PPC32_F30, + [UNW_PPC32_F31]=UNW_PPC32_F31, +}; + +HIDDEN void +tdep_init (void) +{ + intrmask_t saved_mask; + + sigfillset (&unwi_full_mask); + + lock_acquire (&ppc32_lock, saved_mask); + { + if (tdep_init_done) + /* another thread else beat us to it... */ + goto out; + + mi_init (); + + dwarf_init (); + +#ifndef UNW_REMOTE_ONLY + ppc32_local_addr_space_init (); +#endif + tdep_init_done = 1; /* signal that we're initialized... */ + } + out: + lock_release (&ppc32_lock, saved_mask); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Ginit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Ginit.c new file mode 100644 index 0000000..ba30244 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Ginit.c @@ -0,0 +1,216 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#include "ucontext_i.h" +#include "unwind_i.h" + +#ifdef UNW_REMOTE_ONLY + +/* unw_local_addr_space is a NULL pointer in this case. */ +unw_addr_space_t unw_local_addr_space; + +#else /* !UNW_REMOTE_ONLY */ + +static struct unw_addr_space local_addr_space; + +unw_addr_space_t unw_local_addr_space = &local_addr_space; + +static void * +uc_addr (ucontext_t *uc, int reg) +{ + void *addr; + + if ((unsigned) (reg - UNW_PPC32_R0) < 32) + addr = &uc->uc_mcontext.uc_regs->gregs[reg - UNW_PPC32_R0]; + + else + if ( ((unsigned) (reg - UNW_PPC32_F0) < 32) && + ((unsigned) (reg - UNW_PPC32_F0) >= 0) ) + addr = &uc->uc_mcontext.uc_regs->fpregs.fpregs[reg - UNW_PPC32_F0]; + + else + { + unsigned gregs_idx; + + switch (reg) + { + case UNW_PPC32_CTR: + gregs_idx = CTR_IDX; + break; + case UNW_PPC32_LR: + gregs_idx = LINK_IDX; + break; + case UNW_PPC32_XER: + gregs_idx = XER_IDX; + break; + case UNW_PPC32_CCR: + gregs_idx = CCR_IDX; + break; + default: + return NULL; + } + addr = &uc->uc_mcontext.uc_regs->gregs[gregs_idx]; + } + return addr; +} + +# ifdef UNW_LOCAL_ONLY + +HIDDEN void * +tdep_uc_addr (ucontext_t *uc, int reg) +{ + return uc_addr (uc, reg); +} + +# endif /* UNW_LOCAL_ONLY */ + +HIDDEN unw_dyn_info_list_t _U_dyn_info_list; + + +static void +put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) +{ + /* it's a no-op */ +} + +static int +get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, + void *arg) +{ + *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; + return 0; +} + +static int +access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, + void *arg) +{ + if (write) + { + Debug (12, "mem[%lx] <- %lx\n", addr, *val); + *(unw_word_t *) addr = *val; + } + else + { + *val = *(unw_word_t *) addr; + Debug (12, "mem[%lx] -> %lx\n", addr, *val); + } + return 0; +} + +static int +access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, + int write, void *arg) +{ + unw_word_t *addr; + ucontext_t *uc = arg; + + if ( ((unsigned int) (reg - UNW_PPC32_F0) < 32) && + ((unsigned int) (reg - UNW_PPC32_F0) >= 0)) + goto badreg; + + addr = uc_addr (uc, reg); + if (!addr) + goto badreg; + + if (write) + { + *(unw_word_t *) addr = *val; + Debug (12, "%s <- %lx\n", unw_regname (reg), *val); + } + else + { + *val = *(unw_word_t *) addr; + Debug (12, "%s -> %lx\n", unw_regname (reg), *val); + } + return 0; + +badreg: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} + +static int +access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + ucontext_t *uc = arg; + unw_fpreg_t *addr; + + if ((unsigned) (reg - UNW_PPC32_F0) < 0) + goto badreg; + + addr = uc_addr (uc, reg); + if (!addr) + goto badreg; + + if (write) + { + Debug (12, "%s <- %016Lf\n", unw_regname (reg), *val); + *(unw_fpreg_t *) addr = *val; + } + else + { + *val = *(unw_fpreg_t *) addr; + Debug (12, "%s -> %016Lf\n", unw_regname (reg), *val); + } + return 0; + +badreg: + Debug (1, "bad register number %u\n", reg); + /* attempt to access a non-preserved register */ + return -UNW_EBADREG; +} + +static int +get_static_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, + void *arg) +{ + return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp); +} + +HIDDEN void +ppc32_local_addr_space_init (void) +{ + memset (&local_addr_space, 0, sizeof (local_addr_space)); + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; + local_addr_space.acc.find_proc_info = dwarf_find_proc_info; + local_addr_space.acc.put_unwind_info = put_unwind_info; + local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; + local_addr_space.acc.access_mem = access_mem; + local_addr_space.acc.access_reg = access_reg; + local_addr_space.acc.access_fpreg = access_fpreg; + local_addr_space.acc.resume = ppc32_local_resume; + local_addr_space.acc.get_proc_name = get_static_proc_name; + unw_flush_cache (&local_addr_space, 0, 0); +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Greg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Greg_states_iterate.c new file mode 100644 index 0000000..a17dc1b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Greg_states_iterate.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_reg_states_iterate (unw_cursor_t *cursor, + unw_reg_states_callback cb, void *token) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_reg_states_iterate (&c->dwarf, cb, token); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gregs.c new file mode 100644 index 0000000..9344455 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gregs.c @@ -0,0 +1,90 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +HIDDEN int +tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + int write) +{ + struct dwarf_loc loc; + + switch (reg) + { + case UNW_TDEP_IP: + if (write) + { + c->dwarf.ip = *valp; /* update the IP cache */ + if (c->dwarf.pi_valid && (*valp < c->dwarf.pi.start_ip + || *valp >= c->dwarf.pi.end_ip)) + c->dwarf.pi_valid = 0; /* new IP outside of current proc */ + } + else + *valp = c->dwarf.ip; + return 0; + + case UNW_TDEP_SP: + if (write) + return -UNW_EREADONLYREG; + *valp = c->dwarf.cfa; + return 0; + + + default: + break; + } + + /* make sure it's not an FP or VR register */ + if ((((unsigned) (reg - UNW_PPC32_F0)) <= 31)) + return -UNW_EBADREG; + + loc = c->dwarf.loc[reg]; + + if (write) + return dwarf_put (&c->dwarf, loc, *valp); + else + return dwarf_get (&c->dwarf, loc, valp); +} + +HIDDEN int +tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, + int write) +{ + struct dwarf_loc loc; + + if ((unsigned) (reg - UNW_PPC32_F0) < 32) + { + loc = c->dwarf.loc[reg]; + if (write) + return dwarf_putfp (&c->dwarf, loc, *valp); + else + return dwarf_getfp (&c->dwarf, loc, valp); + } + + return -UNW_EBADREG; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gresume.c new file mode 100644 index 0000000..c0f9583 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gresume.c @@ -0,0 +1,77 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford cjashfor@us.ibm.com + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "unwind_i.h" + +#ifndef UNW_REMOTE_ONLY + +#include + +/* sigreturn() is a no-op on x86_64 glibc. */ + +static NORETURN inline long +my_rt_sigreturn (void *new_sp) +{ + /* XXX: empty stub. */ + abort (); +} + +HIDDEN inline int +ppc32_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ + /* XXX: empty stub. */ + return -UNW_EINVAL; +} + +#endif /* !UNW_REMOTE_ONLY */ + +/* This routine is responsible for copying the register values in + cursor C and establishing them as the current machine state. */ + +static inline int +establish_machine_state (struct cursor *c) +{ + /* XXX: empty stub. */ + return 0; +} + +int +unw_resume (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + Debug (1, "(cursor=%p)\n", c); + + if ((ret = establish_machine_state (c)) < 0) + return ret; + + return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, + c->dwarf.as_arg); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gstep.c new file mode 100644 index 0000000..478d3a6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Gstep.c @@ -0,0 +1,309 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "ucontext_i.h" +#include + +/* This definition originates in /usr/include/asm-ppc64/ptrace.h, but is + defined there only when __KERNEL__ is defined. We reproduce it here for + our use at the user level in order to locate the ucontext record, which + appears to be at this offset relative to the stack pointer when in the + context of the signal handler return trampoline code - + __kernel_sigtramp_rt64. */ +#define __SIGNAL_FRAMESIZE 128 + +/* This definition comes from the document "64-bit PowerPC ELF Application + Binary Interface Supplement 1.9", section 3.2.2. + http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK */ + +typedef struct +{ + long unsigned back_chain; + long unsigned lr_save; + /* many more fields here, but they are unused by this code */ +} stack_frame_t; + + +int +unw_step (unw_cursor_t * cursor) +{ + struct cursor *c = (struct cursor *) cursor; + stack_frame_t dummy; + unw_word_t back_chain_offset, lr_save_offset; + struct dwarf_loc back_chain_loc, lr_save_loc, sp_loc, ip_loc; + int ret; + + Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->dwarf.ip); + + if (c->dwarf.ip == 0) + { + /* Unless the cursor or stack is corrupt or uninitialized, + we've most likely hit the top of the stack */ + return 0; + } + + /* Try DWARF-based unwinding... */ + + ret = dwarf_step (&c->dwarf); + + if (ret < 0 && ret != -UNW_ENOINFO) + { + Debug (2, "returning %d\n", ret); + return ret; + } + + if (unlikely (ret < 0)) + { + if (likely (unw_is_signal_frame (cursor) <= 0)) + { + /* DWARF unwinding failed. As of 09/26/2006, gcc in 64-bit mode + produces the mandatory level of traceback record in the code, but + I get the impression that this is transitory, that eventually gcc + will not produce any traceback records at all. So, for now, we + won't bother to try to find and use these records. + + We can, however, attempt to unwind the frame by using the callback + chain. This is very crude, however, and won't be able to unwind + any registers besides the IP, SP, and LR . */ + + back_chain_offset = ((void *) &dummy.back_chain - (void *) &dummy); + lr_save_offset = ((void *) &dummy.lr_save - (void *) &dummy); + + back_chain_loc = DWARF_LOC (c->dwarf.cfa + back_chain_offset, 0); + + if ((ret = + dwarf_get (&c->dwarf, back_chain_loc, &c->dwarf.cfa)) < 0) + { + Debug (2, + "Unable to retrieve CFA from back chain in stack frame - %d\n", + ret); + return ret; + } + if (c->dwarf.cfa == 0) + /* Unless the cursor or stack is corrupt or uninitialized we've most + likely hit the top of the stack */ + return 0; + + lr_save_loc = DWARF_LOC (c->dwarf.cfa + lr_save_offset, 0); + + if ((ret = dwarf_get (&c->dwarf, lr_save_loc, &c->dwarf.ip)) < 0) + { + Debug (2, + "Unable to retrieve IP from lr save in stack frame - %d\n", + ret); + return ret; + } + ret = 1; + } + else + { + /* Find the sigcontext record by taking the CFA and adjusting by + the dummy signal frame size. + + Note that there isn't any way to determined if SA_SIGINFO was + set in the sa_flags parameter to sigaction when the signal + handler was established. If it was not set, the ucontext + record is not required to be on the stack, in which case the + following code will likely cause a seg fault or other crash + condition. */ + + unw_word_t ucontext = c->dwarf.cfa + __SIGNAL_FRAMESIZE; + + Debug (1, "signal frame, skip over trampoline\n"); + + c->sigcontext_format = PPC_SCF_LINUX_RT_SIGFRAME; + c->sigcontext_addr = ucontext; + + sp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0); + ip_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0); + + ret = dwarf_get (&c->dwarf, sp_loc, &c->dwarf.cfa); + if (ret < 0) + { + Debug (2, "returning %d\n", ret); + return ret; + } + ret = dwarf_get (&c->dwarf, ip_loc, &c->dwarf.ip); + if (ret < 0) + { + Debug (2, "returning %d\n", ret); + return ret; + } + + /* Instead of just restoring the non-volatile registers, do all + of the registers for now. This will incur a performance hit, + but it's rare enough not to cause too much of a problem, and + might be useful in some cases. */ + c->dwarf.loc[UNW_PPC32_R0] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R0, 0); + c->dwarf.loc[UNW_PPC32_R1] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0); + c->dwarf.loc[UNW_PPC32_R2] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R2, 0); + c->dwarf.loc[UNW_PPC32_R3] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R3, 0); + c->dwarf.loc[UNW_PPC32_R4] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R4, 0); + c->dwarf.loc[UNW_PPC32_R5] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R5, 0); + c->dwarf.loc[UNW_PPC32_R6] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R6, 0); + c->dwarf.loc[UNW_PPC32_R7] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R7, 0); + c->dwarf.loc[UNW_PPC32_R8] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); + c->dwarf.loc[UNW_PPC32_R9] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); + c->dwarf.loc[UNW_PPC32_R10] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); + c->dwarf.loc[UNW_PPC32_R11] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); + c->dwarf.loc[UNW_PPC32_R12] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); + c->dwarf.loc[UNW_PPC32_R13] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); + c->dwarf.loc[UNW_PPC32_R14] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); + c->dwarf.loc[UNW_PPC32_R15] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); + c->dwarf.loc[UNW_PPC32_R16] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R16, 0); + c->dwarf.loc[UNW_PPC32_R17] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R17, 0); + c->dwarf.loc[UNW_PPC32_R18] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R18, 0); + c->dwarf.loc[UNW_PPC32_R19] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R19, 0); + c->dwarf.loc[UNW_PPC32_R20] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R20, 0); + c->dwarf.loc[UNW_PPC32_R21] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R21, 0); + c->dwarf.loc[UNW_PPC32_R22] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R22, 0); + c->dwarf.loc[UNW_PPC32_R23] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R23, 0); + c->dwarf.loc[UNW_PPC32_R24] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R24, 0); + c->dwarf.loc[UNW_PPC32_R25] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R25, 0); + c->dwarf.loc[UNW_PPC32_R26] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R26, 0); + c->dwarf.loc[UNW_PPC32_R27] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R27, 0); + c->dwarf.loc[UNW_PPC32_R28] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R28, 0); + c->dwarf.loc[UNW_PPC32_R29] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R29, 0); + c->dwarf.loc[UNW_PPC32_R30] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R30, 0); + c->dwarf.loc[UNW_PPC32_R31] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R31, 0); + + c->dwarf.loc[UNW_PPC32_LR] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0); + c->dwarf.loc[UNW_PPC32_CTR] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CTR, 0); + + /* This CR0 assignment is probably wrong. There are 8 dwarf columns + assigned to the CR registers, but only one CR register in the + mcontext structure */ + c->dwarf.loc[UNW_PPC32_CCR] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CCR, 0); + c->dwarf.loc[UNW_PPC32_XER] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_XER, 0); + + c->dwarf.loc[UNW_PPC32_F0] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R0, 0); + c->dwarf.loc[UNW_PPC32_F1] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R1, 0); + c->dwarf.loc[UNW_PPC32_F2] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R2, 0); + c->dwarf.loc[UNW_PPC32_F3] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R3, 0); + c->dwarf.loc[UNW_PPC32_F4] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R4, 0); + c->dwarf.loc[UNW_PPC32_F5] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R5, 0); + c->dwarf.loc[UNW_PPC32_F6] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R6, 0); + c->dwarf.loc[UNW_PPC32_F7] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R7, 0); + c->dwarf.loc[UNW_PPC32_F8] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R8, 0); + c->dwarf.loc[UNW_PPC32_F9] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R9, 0); + c->dwarf.loc[UNW_PPC32_F10] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R10, 0); + c->dwarf.loc[UNW_PPC32_F11] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R11, 0); + c->dwarf.loc[UNW_PPC32_F12] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R12, 0); + c->dwarf.loc[UNW_PPC32_F13] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R13, 0); + c->dwarf.loc[UNW_PPC32_F14] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R14, 0); + c->dwarf.loc[UNW_PPC32_F15] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R15, 0); + c->dwarf.loc[UNW_PPC32_F16] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R16, 0); + c->dwarf.loc[UNW_PPC32_F17] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R17, 0); + c->dwarf.loc[UNW_PPC32_F18] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R18, 0); + c->dwarf.loc[UNW_PPC32_F19] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R19, 0); + c->dwarf.loc[UNW_PPC32_F20] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R20, 0); + c->dwarf.loc[UNW_PPC32_F21] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R21, 0); + c->dwarf.loc[UNW_PPC32_F22] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R22, 0); + c->dwarf.loc[UNW_PPC32_F23] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R23, 0); + c->dwarf.loc[UNW_PPC32_F24] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R24, 0); + c->dwarf.loc[UNW_PPC32_F25] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R25, 0); + c->dwarf.loc[UNW_PPC32_F26] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R26, 0); + c->dwarf.loc[UNW_PPC32_F27] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R27, 0); + c->dwarf.loc[UNW_PPC32_F28] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R28, 0); + c->dwarf.loc[UNW_PPC32_F29] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R29, 0); + c->dwarf.loc[UNW_PPC32_F30] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R30, 0); + c->dwarf.loc[UNW_PPC32_F31] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R31, 0); + + ret = 1; + } + } + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lapply_reg_state.c new file mode 100644 index 0000000..7ebada4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lapply_reg_state.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gapply_reg_state.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lcreate_addr_space.c new file mode 100644 index 0000000..0f2dc6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lcreate_addr_space.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gcreate_addr_space.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lglobal.c new file mode 100644 index 0000000..6d7b489 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lglobal.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gglobal.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Linit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Linit.c new file mode 100644 index 0000000..e9abfdd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Linit.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lreg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lreg_states_iterate.c new file mode 100644 index 0000000..f1eb1e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lreg_states_iterate.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Greg_states_iterate.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lregs.c new file mode 100644 index 0000000..2c9c75c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lregs.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gregs.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lresume.c new file mode 100644 index 0000000..41a8cf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lresume.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gresume.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lstep.c new file mode 100644 index 0000000..c1ac3c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Lstep.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gstep.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Make-arch.in b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Make-arch.in new file mode 100644 index 0000000..947dd5f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/Make-arch.in @@ -0,0 +1,11 @@ +# Word size. +ELFW = 64 +# Does use dwarf2 unwind info. +dwarf_target = true + +libunwind_setjmp_OBJS += \ + $(arch)/longjmp.o \ + $(arch)/siglongjmp.o + +libunwind_OBJS_common += \ + $(arch)/is_fpreg.o diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/get_func_addr.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/get_func_addr.c new file mode 100644 index 0000000..66ff795 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/get_func_addr.c @@ -0,0 +1,36 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +tdep_get_func_addr (unw_addr_space_t as, unw_word_t symbol_val_addr, + unw_word_t *real_func_addr) +{ + *real_func_addr = symbol_val_addr; + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/init.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/init.h new file mode 100644 index 0000000..87a69b1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/init.h @@ -0,0 +1,72 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +/* Here is the "common" init, for remote and local debuging" */ + +static inline int +common_init_ppc32 (struct cursor *c, unsigned use_prev_instr) +{ + int ret; + int i; + + for (i = UNW_PPC32_R0; i <= UNW_PPC32_R31; i++) { + c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, i); + } + for (i = UNW_PPC32_F0; i <= UNW_PPC32_F31; i++) { + c->dwarf.loc[i] = DWARF_FPREG_LOC (&c->dwarf, i); + } + + c->dwarf.loc[UNW_PPC32_CTR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_CTR); + c->dwarf.loc[UNW_PPC32_XER] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_XER); + c->dwarf.loc[UNW_PPC32_CCR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_CCR); + c->dwarf.loc[UNW_PPC32_LR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_LR); + c->dwarf.loc[UNW_PPC32_FPSCR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_FPSCR); + + ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_PPC32_LR], &c->dwarf.ip); + if (ret < 0) + return ret; + + ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_PPC32_R1), + &c->dwarf.cfa); + if (ret < 0) + return ret; + + c->sigcontext_format = PPC_SCF_NONE; + c->sigcontext_addr = 0; + + c->dwarf.args_size = 0; + c->dwarf.stash_frames = 0; + c->dwarf.use_prev_instr = use_prev_instr; + c->dwarf.pi_valid = 0; + c->dwarf.pi_is_dynamic = 0; + c->dwarf.hint = 0; + c->dwarf.prev_rs = 0; + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/is_fpreg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/is_fpreg.c new file mode 100644 index 0000000..646ff23 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/is_fpreg.c @@ -0,0 +1,34 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +int +unw_is_fpreg (int regnum) +{ + return (regnum >= UNW_PPC32_F0 && regnum <= UNW_PPC32_F31); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/regname.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/regname.c new file mode 100644 index 0000000..459b83a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/regname.c @@ -0,0 +1,112 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static const char *regname[] = + { + [UNW_PPC32_R0]="GPR0", + [UNW_PPC32_R1]="GPR1", + [UNW_PPC32_R2]="GPR2", + [UNW_PPC32_R3]="GPR3", + [UNW_PPC32_R4]="GPR4", + [UNW_PPC32_R5]="GPR5", + [UNW_PPC32_R6]="GPR6", + [UNW_PPC32_R7]="GPR7", + [UNW_PPC32_R8]="GPR8", + [UNW_PPC32_R9]="GPR9", + [UNW_PPC32_R10]="GPR10", + [UNW_PPC32_R11]="GPR11", + [UNW_PPC32_R12]="GPR12", + [UNW_PPC32_R13]="GPR13", + [UNW_PPC32_R14]="GPR14", + [UNW_PPC32_R15]="GPR15", + [UNW_PPC32_R16]="GPR16", + [UNW_PPC32_R17]="GPR17", + [UNW_PPC32_R18]="GPR18", + [UNW_PPC32_R19]="GPR19", + [UNW_PPC32_R20]="GPR20", + [UNW_PPC32_R21]="GPR21", + [UNW_PPC32_R22]="GPR22", + [UNW_PPC32_R23]="GPR23", + [UNW_PPC32_R24]="GPR24", + [UNW_PPC32_R25]="GPR25", + [UNW_PPC32_R26]="GPR26", + [UNW_PPC32_R27]="GPR27", + [UNW_PPC32_R28]="GPR28", + [UNW_PPC32_R29]="GPR29", + [UNW_PPC32_R30]="GPR30", + [UNW_PPC32_R31]="GPR31", + + [UNW_PPC32_CTR]="CTR", + [UNW_PPC32_XER]="XER", + [UNW_PPC32_CCR]="CCR", + [UNW_PPC32_LR]="LR", + [UNW_PPC32_FPSCR]="FPSCR", + + [UNW_PPC32_F0]="FPR0", + [UNW_PPC32_F1]="FPR1", + [UNW_PPC32_F2]="FPR2", + [UNW_PPC32_F3]="FPR3", + [UNW_PPC32_F4]="FPR4", + [UNW_PPC32_F5]="FPR5", + [UNW_PPC32_F6]="FPR6", + [UNW_PPC32_F7]="FPR7", + [UNW_PPC32_F8]="FPR8", + [UNW_PPC32_F9]="FPR9", + [UNW_PPC32_F10]="FPR10", + [UNW_PPC32_F11]="FPR11", + [UNW_PPC32_F12]="FPR12", + [UNW_PPC32_F13]="FPR13", + [UNW_PPC32_F14]="FPR14", + [UNW_PPC32_F15]="FPR15", + [UNW_PPC32_F16]="FPR16", + [UNW_PPC32_F17]="FPR17", + [UNW_PPC32_F18]="FPR18", + [UNW_PPC32_F19]="FPR19", + [UNW_PPC32_F20]="FPR20", + [UNW_PPC32_F21]="FPR21", + [UNW_PPC32_F22]="FPR22", + [UNW_PPC32_F23]="FPR23", + [UNW_PPC32_F24]="FPR24", + [UNW_PPC32_F25]="FPR25", + [UNW_PPC32_F26]="FPR26", + [UNW_PPC32_F27]="FPR27", + [UNW_PPC32_F28]="FPR28", + [UNW_PPC32_F29]="FPR29", + [UNW_PPC32_F30]="FPR30", + [UNW_PPC32_F31]="FPR31" +}; + +const char * +unw_regname (unw_regnum_t reg) +{ + if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) + return regname[reg]; + else + return "???"; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/setcontext.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/setcontext.S new file mode 100644 index 0000000..b54378a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc32/setcontext.S @@ -0,0 +1,9 @@ + .global _UI_setcontext + +_UI_setcontext: + retq + +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gapply_reg_state.c new file mode 100644 index 0000000..82f056d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gapply_reg_state.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_apply_reg_state (unw_cursor_t *cursor, + void *reg_states_data) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gcreate_addr_space.c new file mode 100644 index 0000000..bd48555 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gcreate_addr_space.c @@ -0,0 +1,71 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include + +unw_addr_space_t +unw_create_addr_space (unw_accessors_t *a, int byte_order) +{ +#ifdef UNW_LOCAL_ONLY + return NULL; +#else + unw_addr_space_t as; + + /* + * We support both big- and little-endian on Linux ppc64. + */ + if (byte_order != 0 + && byte_order != __LITTLE_ENDIAN + && byte_order != __BIG_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); + if (!as) + return NULL; + + memset (as, 0, sizeof (*as)); + + as->acc = *a; + + if (byte_order == 0) + /* use host default: */ + as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN); + else + as->big_endian = (byte_order == __BIG_ENDIAN); + + /* FIXME! There is no way to specify the ABI. + Default to ELFv1 on big-endian and ELFv2 on little-endian. */ + if (as->big_endian) + as->abi = UNW_PPC64_ABI_ELFv1; + else + as->abi = UNW_PPC64_ABI_ELFv2; + + return as; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gglobal.c new file mode 100644 index 0000000..9d0b0f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gglobal.c @@ -0,0 +1,182 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "dwarf_i.h" + +HIDDEN define_lock (ppc64_lock); +HIDDEN int tdep_init_done; + +/* The API register numbers are exactly the same as the .eh_frame + registers, for now at least. */ +HIDDEN const uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH] = + { + [UNW_PPC64_R0]=UNW_PPC64_R0, + [UNW_PPC64_R1]=UNW_PPC64_R1, + [UNW_PPC64_R2]=UNW_PPC64_R2, + [UNW_PPC64_R3]=UNW_PPC64_R3, + [UNW_PPC64_R4]=UNW_PPC64_R4, + [UNW_PPC64_R5]=UNW_PPC64_R5, + [UNW_PPC64_R6]=UNW_PPC64_R6, + [UNW_PPC64_R7]=UNW_PPC64_R7, + [UNW_PPC64_R8]=UNW_PPC64_R8, + [UNW_PPC64_R9]=UNW_PPC64_R9, + [UNW_PPC64_R10]=UNW_PPC64_R10, + [UNW_PPC64_R11]=UNW_PPC64_R11, + [UNW_PPC64_R12]=UNW_PPC64_R12, + [UNW_PPC64_R13]=UNW_PPC64_R13, + [UNW_PPC64_R14]=UNW_PPC64_R14, + [UNW_PPC64_R15]=UNW_PPC64_R15, + [UNW_PPC64_R16]=UNW_PPC64_R16, + [UNW_PPC64_R17]=UNW_PPC64_R17, + [UNW_PPC64_R18]=UNW_PPC64_R18, + [UNW_PPC64_R19]=UNW_PPC64_R19, + [UNW_PPC64_R20]=UNW_PPC64_R20, + [UNW_PPC64_R21]=UNW_PPC64_R21, + [UNW_PPC64_R22]=UNW_PPC64_R22, + [UNW_PPC64_R23]=UNW_PPC64_R23, + [UNW_PPC64_R24]=UNW_PPC64_R24, + [UNW_PPC64_R25]=UNW_PPC64_R25, + [UNW_PPC64_R26]=UNW_PPC64_R26, + [UNW_PPC64_R27]=UNW_PPC64_R27, + [UNW_PPC64_R28]=UNW_PPC64_R28, + [UNW_PPC64_R29]=UNW_PPC64_R29, + [UNW_PPC64_R30]=UNW_PPC64_R30, + [UNW_PPC64_R31]=UNW_PPC64_R31, + + [UNW_PPC64_F0]=UNW_PPC64_F0, + [UNW_PPC64_F1]=UNW_PPC64_F1, + [UNW_PPC64_F2]=UNW_PPC64_F2, + [UNW_PPC64_F3]=UNW_PPC64_F3, + [UNW_PPC64_F4]=UNW_PPC64_F4, + [UNW_PPC64_F5]=UNW_PPC64_F5, + [UNW_PPC64_F6]=UNW_PPC64_F6, + [UNW_PPC64_F7]=UNW_PPC64_F7, + [UNW_PPC64_F8]=UNW_PPC64_F8, + [UNW_PPC64_F9]=UNW_PPC64_F9, + [UNW_PPC64_F10]=UNW_PPC64_F10, + [UNW_PPC64_F11]=UNW_PPC64_F11, + [UNW_PPC64_F12]=UNW_PPC64_F12, + [UNW_PPC64_F13]=UNW_PPC64_F13, + [UNW_PPC64_F14]=UNW_PPC64_F14, + [UNW_PPC64_F15]=UNW_PPC64_F15, + [UNW_PPC64_F16]=UNW_PPC64_F16, + [UNW_PPC64_F17]=UNW_PPC64_F17, + [UNW_PPC64_F18]=UNW_PPC64_F18, + [UNW_PPC64_F19]=UNW_PPC64_F19, + [UNW_PPC64_F20]=UNW_PPC64_F20, + [UNW_PPC64_F21]=UNW_PPC64_F21, + [UNW_PPC64_F22]=UNW_PPC64_F22, + [UNW_PPC64_F23]=UNW_PPC64_F23, + [UNW_PPC64_F24]=UNW_PPC64_F24, + [UNW_PPC64_F25]=UNW_PPC64_F25, + [UNW_PPC64_F26]=UNW_PPC64_F26, + [UNW_PPC64_F27]=UNW_PPC64_F27, + [UNW_PPC64_F28]=UNW_PPC64_F28, + [UNW_PPC64_F29]=UNW_PPC64_F29, + [UNW_PPC64_F30]=UNW_PPC64_F30, + [UNW_PPC64_F31]=UNW_PPC64_F31, + + [UNW_PPC64_LR]=UNW_PPC64_LR, + [UNW_PPC64_CTR]=UNW_PPC64_CTR, + [UNW_PPC64_ARG_POINTER]=UNW_PPC64_ARG_POINTER, + + [UNW_PPC64_CR0]=UNW_PPC64_CR0, + [UNW_PPC64_CR1]=UNW_PPC64_CR1, + [UNW_PPC64_CR2]=UNW_PPC64_CR2, + [UNW_PPC64_CR3]=UNW_PPC64_CR3, + [UNW_PPC64_CR4]=UNW_PPC64_CR4, + [UNW_PPC64_CR5]=UNW_PPC64_CR5, + [UNW_PPC64_CR6]=UNW_PPC64_CR6, + [UNW_PPC64_CR7]=UNW_PPC64_CR7, + + [UNW_PPC64_XER]=UNW_PPC64_XER, + + [UNW_PPC64_V0]=UNW_PPC64_V0, + [UNW_PPC64_V1]=UNW_PPC64_V1, + [UNW_PPC64_V2]=UNW_PPC64_V2, + [UNW_PPC64_V3]=UNW_PPC64_V3, + [UNW_PPC64_V4]=UNW_PPC64_V4, + [UNW_PPC64_V5]=UNW_PPC64_V5, + [UNW_PPC64_V6]=UNW_PPC64_V6, + [UNW_PPC64_V7]=UNW_PPC64_V7, + [UNW_PPC64_V8]=UNW_PPC64_V8, + [UNW_PPC64_V9]=UNW_PPC64_V9, + [UNW_PPC64_V10]=UNW_PPC64_V10, + [UNW_PPC64_V11]=UNW_PPC64_V11, + [UNW_PPC64_V12]=UNW_PPC64_V12, + [UNW_PPC64_V13]=UNW_PPC64_V13, + [UNW_PPC64_V14]=UNW_PPC64_V14, + [UNW_PPC64_V15]=UNW_PPC64_V15, + [UNW_PPC64_V16]=UNW_PPC64_V16, + [UNW_PPC64_V17]=UNW_PPC64_V17, + [UNW_PPC64_V18]=UNW_PPC64_V18, + [UNW_PPC64_V19]=UNW_PPC64_V19, + [UNW_PPC64_V20]=UNW_PPC64_V20, + [UNW_PPC64_V21]=UNW_PPC64_V21, + [UNW_PPC64_V22]=UNW_PPC64_V22, + [UNW_PPC64_V23]=UNW_PPC64_V23, + [UNW_PPC64_V24]=UNW_PPC64_V24, + [UNW_PPC64_V25]=UNW_PPC64_V25, + [UNW_PPC64_V26]=UNW_PPC64_V26, + [UNW_PPC64_V27]=UNW_PPC64_V27, + [UNW_PPC64_V28]=UNW_PPC64_V28, + [UNW_PPC64_V29]=UNW_PPC64_V29, + [UNW_PPC64_V30]=UNW_PPC64_V30, + [UNW_PPC64_V31]=UNW_PPC64_V31, + + [UNW_PPC64_VRSAVE]=UNW_PPC64_VRSAVE, + [UNW_PPC64_VSCR]=UNW_PPC64_VSCR, + [UNW_PPC64_SPE_ACC]=UNW_PPC64_SPE_ACC, + [UNW_PPC64_SPEFSCR]=UNW_PPC64_SPEFSCR, + }; + +HIDDEN void +tdep_init (void) +{ + intrmask_t saved_mask; + + sigfillset (&unwi_full_mask); + + lock_acquire (&ppc64_lock, saved_mask); + { + if (tdep_init_done) + /* another thread else beat us to it... */ + goto out; + + mi_init (); + + dwarf_init (); + +#ifndef UNW_REMOTE_ONLY + ppc64_local_addr_space_init (); +#endif + tdep_init_done = 1; /* signal that we're initialized... */ + } + out: + lock_release (&ppc64_lock, saved_mask); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Ginit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Ginit.c new file mode 100644 index 0000000..4c88cd6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Ginit.c @@ -0,0 +1,229 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#include "ucontext_i.h" +#include "unwind_i.h" + +#ifdef UNW_REMOTE_ONLY + +/* unw_local_addr_space is a NULL pointer in this case. */ +unw_addr_space_t unw_local_addr_space; + +#else /* !UNW_REMOTE_ONLY */ + +static struct unw_addr_space local_addr_space; + +unw_addr_space_t unw_local_addr_space = &local_addr_space; + +static void * +uc_addr (ucontext_t *uc, int reg) +{ + void *addr; + + if ((unsigned) (reg - UNW_PPC64_R0) < 32) + addr = &uc->uc_mcontext.gp_regs[reg - UNW_PPC64_R0]; + + else if ((unsigned) (reg - UNW_PPC64_F0) < 32) + addr = &uc->uc_mcontext.fp_regs[reg - UNW_PPC64_F0]; + + else if ((unsigned) (reg - UNW_PPC64_V0) < 32) + addr = (uc->uc_mcontext.v_regs == 0) ? NULL : &uc->uc_mcontext.v_regs->vrregs[reg - UNW_PPC64_V0][0]; + + else + { + unsigned gregs_idx; + + switch (reg) + { + case UNW_PPC64_NIP: + gregs_idx = NIP_IDX; + break; + case UNW_PPC64_CTR: + gregs_idx = CTR_IDX; + break; + case UNW_PPC64_LR: + gregs_idx = LINK_IDX; + break; + case UNW_PPC64_XER: + gregs_idx = XER_IDX; + break; + case UNW_PPC64_CR0: + gregs_idx = CCR_IDX; + break; + default: + return NULL; + } + addr = &uc->uc_mcontext.gp_regs[gregs_idx]; + } + return addr; +} + +# ifdef UNW_LOCAL_ONLY + +HIDDEN void * +tdep_uc_addr (ucontext_t *uc, int reg) +{ + return uc_addr (uc, reg); +} + +# endif /* UNW_LOCAL_ONLY */ + +HIDDEN unw_dyn_info_list_t _U_dyn_info_list; + + +static void +put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) +{ + /* it's a no-op */ +} + +static int +get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, + void *arg) +{ + *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; + return 0; +} + +static int +access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, + void *arg) +{ + if (write) + { + Debug (12, "mem[%lx] <- %lx\n", addr, *val); + *(unw_word_t *) addr = *val; + } + else + { + *val = *(unw_word_t *) addr; + Debug (12, "mem[%lx] -> %lx\n", addr, *val); + } + return 0; +} + +static int +access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, + int write, void *arg) +{ + unw_word_t *addr; + ucontext_t *uc = arg; + + if (UNW_PPC64_F0 <= reg && reg <= UNW_PPC64_F31) + goto badreg; + if (UNW_PPC64_V0 <= reg && reg <= UNW_PPC64_V31) + goto badreg; + + addr = uc_addr (uc, reg); + if (!addr) + goto badreg; + + if (write) + { + *(unw_word_t *) addr = *val; + Debug (12, "%s <- %lx\n", unw_regname (reg), *val); + } + else + { + *val = *(unw_word_t *) addr; + Debug (12, "%s -> %lx\n", unw_regname (reg), *val); + } + return 0; + +badreg: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} + +static int +access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + ucontext_t *uc = arg; + unw_fpreg_t *addr; + + /* Allow only 32 fregs and 32 vregs */ + if (!(((unsigned) (reg - UNW_PPC64_F0) < 32) + ||((unsigned) (reg - UNW_PPC64_V0) < 32))) + goto badreg; + + addr = uc_addr (uc, reg); + if (!addr) + goto badreg; + + if (write) + { + Debug (12, "%s <- %016Lf\n", unw_regname (reg), *val); + *(unw_fpreg_t *) addr = *val; + } + else + { + *val = *(unw_fpreg_t *) addr; + Debug (12, "%s -> %016Lf\n", unw_regname (reg), *val); + } + return 0; + +badreg: + Debug (1, "bad register number %u\n", reg); + /* attempt to access a non-preserved register */ + return -UNW_EBADREG; +} + +static int +get_static_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, + void *arg) +{ + return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp); +} + +HIDDEN void +ppc64_local_addr_space_init (void) +{ + memset (&local_addr_space, 0, sizeof (local_addr_space)); + local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN); +#if _CALL_ELF == 2 + local_addr_space.abi = UNW_PPC64_ABI_ELFv2; +#else + local_addr_space.abi = UNW_PPC64_ABI_ELFv1; +#endif + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; + local_addr_space.acc.find_proc_info = dwarf_find_proc_info; + local_addr_space.acc.put_unwind_info = put_unwind_info; + local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; + local_addr_space.acc.access_mem = access_mem; + local_addr_space.acc.access_reg = access_reg; + local_addr_space.acc.access_fpreg = access_fpreg; + local_addr_space.acc.resume = ppc64_local_resume; + local_addr_space.acc.get_proc_name = get_static_proc_name; + unw_flush_cache (&local_addr_space, 0, 0); +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Greg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Greg_states_iterate.c new file mode 100644 index 0000000..a17dc1b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Greg_states_iterate.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_reg_states_iterate (unw_cursor_t *cursor, + unw_reg_states_callback cb, void *token) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_reg_states_iterate (&c->dwarf, cb, token); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gregs.c new file mode 100644 index 0000000..1cb5d9d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gregs.c @@ -0,0 +1,141 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +HIDDEN int +tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + int write) +{ + struct dwarf_loc loc; + + switch (reg) + { + case UNW_PPC64_R0: + case UNW_PPC64_R2: + case UNW_PPC64_R3: + case UNW_PPC64_R4: + case UNW_PPC64_R5: + case UNW_PPC64_R6: + case UNW_PPC64_R7: + case UNW_PPC64_R8: + case UNW_PPC64_R9: + case UNW_PPC64_R10: + case UNW_PPC64_R11: + case UNW_PPC64_R12: + case UNW_PPC64_R13: + case UNW_PPC64_R14: + case UNW_PPC64_R15: + case UNW_PPC64_R16: + case UNW_PPC64_R17: + case UNW_PPC64_R18: + case UNW_PPC64_R19: + case UNW_PPC64_R20: + case UNW_PPC64_R21: + case UNW_PPC64_R22: + case UNW_PPC64_R23: + case UNW_PPC64_R24: + case UNW_PPC64_R25: + case UNW_PPC64_R26: + case UNW_PPC64_R27: + case UNW_PPC64_R28: + case UNW_PPC64_R29: + case UNW_PPC64_R30: + case UNW_PPC64_R31: + case UNW_PPC64_LR: + case UNW_PPC64_CTR: + case UNW_PPC64_CR0: + case UNW_PPC64_CR1: + case UNW_PPC64_CR2: + case UNW_PPC64_CR3: + case UNW_PPC64_CR4: + case UNW_PPC64_CR5: + case UNW_PPC64_CR6: + case UNW_PPC64_CR7: + case UNW_PPC64_VRSAVE: + case UNW_PPC64_VSCR: + case UNW_PPC64_SPE_ACC: + case UNW_PPC64_SPEFSCR: + loc = c->dwarf.loc[reg]; + break; + + case UNW_TDEP_IP: + if (write) + { + c->dwarf.ip = *valp; /* update the IP cache */ + if (c->dwarf.pi_valid && (*valp < c->dwarf.pi.start_ip + || *valp >= c->dwarf.pi.end_ip)) + c->dwarf.pi_valid = 0; /* new IP outside of current proc */ + } + else + *valp = c->dwarf.ip; + return 0; + + case UNW_TDEP_SP: + if (write) + return -UNW_EREADONLYREG; + *valp = c->dwarf.cfa; + return 0; + + default: + return -UNW_EBADREG; + break; + } + + if (write) + return dwarf_put (&c->dwarf, loc, *valp); + else + return dwarf_get (&c->dwarf, loc, valp); +} + +HIDDEN int +tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, + int write) +{ + struct dwarf_loc loc; + + if ((unsigned) (reg - UNW_PPC64_F0) < 32) + { + loc = c->dwarf.loc[reg]; + if (write) + return dwarf_putfp (&c->dwarf, loc, *valp); + else + return dwarf_getfp (&c->dwarf, loc, valp); + } + else + if ((unsigned) (reg - UNW_PPC64_V0) < 32) + { + loc = c->dwarf.loc[reg]; + if (write) + return dwarf_putvr (&c->dwarf, loc, *valp); + else + return dwarf_getvr (&c->dwarf, loc, valp); + } + + return -UNW_EBADREG; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gresume.c new file mode 100644 index 0000000..0d832d0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gresume.c @@ -0,0 +1,111 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford cjashfor@us.ibm.com + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "unwind_i.h" + +#ifndef UNW_REMOTE_ONLY + +#include + +/* sigreturn() is a no-op on x86_64 glibc. */ + +static NORETURN inline long +my_rt_sigreturn (void *new_sp) +{ + /* XXX: empty stub. */ + abort (); +} + +HIDDEN inline int +ppc64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ + struct cursor *c = (struct cursor *) cursor; + ucontext_t *uc = (ucontext_t *)c->dwarf.as_arg; + + if (unlikely (c->sigcontext_format != PPC_SCF_NONE)) + { + my_rt_sigreturn(cursor); + abort(); + } + else + { + Debug (8, "resuming at ip=%llx via setcontext()\n", + (unsigned long long) c->dwarf.ip); + setcontext (uc); + } + return -UNW_EINVAL; +} + +#endif /* !UNW_REMOTE_ONLY */ + +/* This routine is responsible for copying the register values in + cursor C and establishing them as the current machine state. */ + +static inline int +establish_machine_state (struct cursor *c) +{ + unw_addr_space_t as = c->dwarf.as; + void *arg = c->dwarf.as_arg; + unw_fpreg_t fpval; + unw_word_t val; + int reg; + + Debug (8, "copying out cursor state\n"); + + for (reg = 0; reg <= UNW_REG_LAST; ++reg) + { + Debug (16, "copying %s %d\n", unw_regname (reg), reg); + if (unw_is_fpreg (reg)) + { + if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) + as->acc.access_fpreg (as, reg, &fpval, 1, arg); + } + else + { + if (tdep_access_reg (c, reg, &val, 0) >= 0) + as->acc.access_reg (as, reg, &val, 1, arg); + } + } + return 0; +} + +int +unw_resume (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + Debug (1, "(cursor=%p)\n", c); + + if ((ret = establish_machine_state (c)) < 0) + return ret; + + return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, + c->dwarf.as_arg); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gstep.c new file mode 100644 index 0000000..f44e959 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Gstep.c @@ -0,0 +1,466 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "ucontext_i.h" +#include "remote.h" +#include + +/* This definition originates in /usr/include/asm-ppc64/ptrace.h, but is + defined there only when __KERNEL__ is defined. We reproduce it here for + our use at the user level in order to locate the ucontext record, which + appears to be at this offset relative to the stack pointer when in the + context of the signal handler return trampoline code - + __kernel_sigtramp_rt64. */ +#define __SIGNAL_FRAMESIZE 128 + +/* This definition comes from the document "64-bit PowerPC ELF Application + Binary Interface Supplement 1.9", section 3.2.2. + http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK */ + +typedef struct +{ + long unsigned back_chain; + long unsigned cr_save; + long unsigned lr_save; + /* many more fields here, but they are unused by this code */ +} stack_frame_t; + + +int +unw_step (unw_cursor_t * cursor) +{ + struct cursor *c = (struct cursor *) cursor; + stack_frame_t dummy; + unw_word_t back_chain_offset, lr_save_offset, v_regs_ptr; + struct dwarf_loc back_chain_loc, lr_save_loc, sp_loc, ip_loc, v_regs_loc; + int ret, i; + + Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->dwarf.ip); + + /* Try DWARF-based unwinding... */ + + ret = dwarf_step (&c->dwarf); + + if (ret < 0 && ret != -UNW_ENOINFO) + { + Debug (2, "returning %d\n", ret); + return ret; + } + + if (unlikely (ret < 0)) + { + if (likely (unw_is_signal_frame (cursor) <= 0)) + { + /* DWARF unwinding failed. As of 09/26/2006, gcc in 64-bit mode + produces the mandatory level of traceback record in the code, but + I get the impression that this is transitory, that eventually gcc + will not produce any traceback records at all. So, for now, we + won't bother to try to find and use these records. + + We can, however, attempt to unwind the frame by using the callback + chain. This is very crude, however, and won't be able to unwind + any registers besides the IP, SP, and LR . */ + + back_chain_offset = ((void *) &dummy.back_chain - (void *) &dummy); + lr_save_offset = ((void *) &dummy.lr_save - (void *) &dummy); + + back_chain_loc = DWARF_LOC (c->dwarf.cfa + back_chain_offset, 0); + + if ((ret = + dwarf_get (&c->dwarf, back_chain_loc, &c->dwarf.cfa)) < 0) + { + Debug (2, + "Unable to retrieve CFA from back chain in stack frame - %d\n", + ret); + return ret; + } + if (c->dwarf.cfa == 0) + /* Unless the cursor or stack is corrupt or uninitialized we've most + likely hit the top of the stack */ + return 0; + + lr_save_loc = DWARF_LOC (c->dwarf.cfa + lr_save_offset, 0); + + if ((ret = dwarf_get (&c->dwarf, lr_save_loc, &c->dwarf.ip)) < 0) + { + Debug (2, + "Unable to retrieve IP from lr save in stack frame - %d\n", + ret); + return ret; + } + + /* Mark all registers unsaved */ + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + + ret = 1; + } + else + { + /* Find the sigcontext record by taking the CFA and adjusting by + the dummy signal frame size. + + Note that there isn't any way to determined if SA_SIGINFO was + set in the sa_flags parameter to sigaction when the signal + handler was established. If it was not set, the ucontext + record is not required to be on the stack, in which case the + following code will likely cause a seg fault or other crash + condition. */ + + unw_word_t ucontext = c->dwarf.cfa + __SIGNAL_FRAMESIZE; + + Debug (1, "signal frame, skip over trampoline\n"); + + c->sigcontext_format = PPC_SCF_LINUX_RT_SIGFRAME; + c->sigcontext_addr = ucontext; + + sp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0); + ip_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_NIP, 0); + + ret = dwarf_get (&c->dwarf, sp_loc, &c->dwarf.cfa); + if (ret < 0) + { + Debug (2, "returning %d\n", ret); + return ret; + } + ret = dwarf_get (&c->dwarf, ip_loc, &c->dwarf.ip); + if (ret < 0) + { + Debug (2, "returning %d\n", ret); + return ret; + } + + /* Instead of just restoring the non-volatile registers, do all + of the registers for now. This will incur a performance hit, + but it's rare enough not to cause too much of a problem, and + might be useful in some cases. */ + c->dwarf.loc[UNW_PPC64_R0] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R0, 0); + c->dwarf.loc[UNW_PPC64_R1] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0); + c->dwarf.loc[UNW_PPC64_R2] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R2, 0); + c->dwarf.loc[UNW_PPC64_R3] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R3, 0); + c->dwarf.loc[UNW_PPC64_R4] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R4, 0); + c->dwarf.loc[UNW_PPC64_R5] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R5, 0); + c->dwarf.loc[UNW_PPC64_R6] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R6, 0); + c->dwarf.loc[UNW_PPC64_R7] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R7, 0); + c->dwarf.loc[UNW_PPC64_R8] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); + c->dwarf.loc[UNW_PPC64_R9] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); + c->dwarf.loc[UNW_PPC64_R10] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); + c->dwarf.loc[UNW_PPC64_R11] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); + c->dwarf.loc[UNW_PPC64_R12] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); + c->dwarf.loc[UNW_PPC64_R13] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); + c->dwarf.loc[UNW_PPC64_R14] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); + c->dwarf.loc[UNW_PPC64_R15] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); + c->dwarf.loc[UNW_PPC64_R16] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R16, 0); + c->dwarf.loc[UNW_PPC64_R17] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R17, 0); + c->dwarf.loc[UNW_PPC64_R18] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R18, 0); + c->dwarf.loc[UNW_PPC64_R19] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R19, 0); + c->dwarf.loc[UNW_PPC64_R20] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R20, 0); + c->dwarf.loc[UNW_PPC64_R21] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R21, 0); + c->dwarf.loc[UNW_PPC64_R22] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R22, 0); + c->dwarf.loc[UNW_PPC64_R23] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R23, 0); + c->dwarf.loc[UNW_PPC64_R24] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R24, 0); + c->dwarf.loc[UNW_PPC64_R25] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R25, 0); + c->dwarf.loc[UNW_PPC64_R26] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R26, 0); + c->dwarf.loc[UNW_PPC64_R27] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R27, 0); + c->dwarf.loc[UNW_PPC64_R28] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R28, 0); + c->dwarf.loc[UNW_PPC64_R29] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R29, 0); + c->dwarf.loc[UNW_PPC64_R30] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R30, 0); + c->dwarf.loc[UNW_PPC64_R31] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R31, 0); + + c->dwarf.loc[UNW_PPC64_LR] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0); + c->dwarf.loc[UNW_PPC64_CTR] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CTR, 0); + /* This CR0 assignment is probably wrong. There are 8 dwarf columns + assigned to the CR registers, but only one CR register in the + mcontext structure */ + c->dwarf.loc[UNW_PPC64_CR0] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CCR, 0); + c->dwarf.loc[UNW_PPC64_XER] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_XER, 0); + c->dwarf.loc[UNW_PPC64_NIP] = + DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_NIP, 0); + + /* TODO: Is there a way of obtaining the value of the + pseudo frame pointer (which is sp + some fixed offset, I + assume), based on the contents of the ucontext record + structure? For now, set this loc to null. */ + c->dwarf.loc[UNW_PPC64_FRAME_POINTER] = DWARF_NULL_LOC; + + c->dwarf.loc[UNW_PPC64_F0] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R0, 0); + c->dwarf.loc[UNW_PPC64_F1] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R1, 0); + c->dwarf.loc[UNW_PPC64_F2] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R2, 0); + c->dwarf.loc[UNW_PPC64_F3] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R3, 0); + c->dwarf.loc[UNW_PPC64_F4] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R4, 0); + c->dwarf.loc[UNW_PPC64_F5] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R5, 0); + c->dwarf.loc[UNW_PPC64_F6] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R6, 0); + c->dwarf.loc[UNW_PPC64_F7] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R7, 0); + c->dwarf.loc[UNW_PPC64_F8] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R8, 0); + c->dwarf.loc[UNW_PPC64_F9] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R9, 0); + c->dwarf.loc[UNW_PPC64_F10] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R10, 0); + c->dwarf.loc[UNW_PPC64_F11] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R11, 0); + c->dwarf.loc[UNW_PPC64_F12] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R12, 0); + c->dwarf.loc[UNW_PPC64_F13] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R13, 0); + c->dwarf.loc[UNW_PPC64_F14] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R14, 0); + c->dwarf.loc[UNW_PPC64_F15] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R15, 0); + c->dwarf.loc[UNW_PPC64_F16] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R16, 0); + c->dwarf.loc[UNW_PPC64_F17] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R17, 0); + c->dwarf.loc[UNW_PPC64_F18] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R18, 0); + c->dwarf.loc[UNW_PPC64_F19] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R19, 0); + c->dwarf.loc[UNW_PPC64_F20] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R20, 0); + c->dwarf.loc[UNW_PPC64_F21] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R21, 0); + c->dwarf.loc[UNW_PPC64_F22] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R22, 0); + c->dwarf.loc[UNW_PPC64_F23] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R23, 0); + c->dwarf.loc[UNW_PPC64_F24] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R24, 0); + c->dwarf.loc[UNW_PPC64_F25] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R25, 0); + c->dwarf.loc[UNW_PPC64_F26] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R26, 0); + c->dwarf.loc[UNW_PPC64_F27] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R27, 0); + c->dwarf.loc[UNW_PPC64_F28] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R28, 0); + c->dwarf.loc[UNW_PPC64_F29] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R29, 0); + c->dwarf.loc[UNW_PPC64_F30] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R30, 0); + c->dwarf.loc[UNW_PPC64_F31] = + DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R31, 0); + /* Note that there is no .eh_section register column for the + FPSCR register. I don't know why this is. */ + + v_regs_loc = DWARF_LOC (ucontext + UC_MCONTEXT_V_REGS, 0); + ret = dwarf_get (&c->dwarf, v_regs_loc, &v_regs_ptr); + if (ret < 0) + { + Debug (2, "returning %d\n", ret); + return ret; + } + if (v_regs_ptr != 0) + { + /* The v_regs_ptr is not null. Set all of the AltiVec locs */ + + c->dwarf.loc[UNW_PPC64_V0] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R0, 0); + c->dwarf.loc[UNW_PPC64_V1] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R1, 0); + c->dwarf.loc[UNW_PPC64_V2] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R2, 0); + c->dwarf.loc[UNW_PPC64_V3] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R3, 0); + c->dwarf.loc[UNW_PPC64_V4] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R4, 0); + c->dwarf.loc[UNW_PPC64_V5] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R5, 0); + c->dwarf.loc[UNW_PPC64_V6] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R6, 0); + c->dwarf.loc[UNW_PPC64_V7] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R7, 0); + c->dwarf.loc[UNW_PPC64_V8] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R8, 0); + c->dwarf.loc[UNW_PPC64_V9] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R9, 0); + c->dwarf.loc[UNW_PPC64_V10] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R10, 0); + c->dwarf.loc[UNW_PPC64_V11] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R11, 0); + c->dwarf.loc[UNW_PPC64_V12] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R12, 0); + c->dwarf.loc[UNW_PPC64_V13] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R13, 0); + c->dwarf.loc[UNW_PPC64_V14] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R14, 0); + c->dwarf.loc[UNW_PPC64_V15] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R15, 0); + c->dwarf.loc[UNW_PPC64_V16] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R16, 0); + c->dwarf.loc[UNW_PPC64_V17] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R17, 0); + c->dwarf.loc[UNW_PPC64_V18] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R18, 0); + c->dwarf.loc[UNW_PPC64_V19] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R19, 0); + c->dwarf.loc[UNW_PPC64_V20] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R20, 0); + c->dwarf.loc[UNW_PPC64_V21] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R21, 0); + c->dwarf.loc[UNW_PPC64_V22] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R22, 0); + c->dwarf.loc[UNW_PPC64_V23] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R23, 0); + c->dwarf.loc[UNW_PPC64_V24] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R24, 0); + c->dwarf.loc[UNW_PPC64_V25] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R25, 0); + c->dwarf.loc[UNW_PPC64_V26] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R26, 0); + c->dwarf.loc[UNW_PPC64_V27] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R27, 0); + c->dwarf.loc[UNW_PPC64_V28] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R28, 0); + c->dwarf.loc[UNW_PPC64_V29] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R29, 0); + c->dwarf.loc[UNW_PPC64_V30] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R30, 0); + c->dwarf.loc[UNW_PPC64_V31] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R31, 0); + c->dwarf.loc[UNW_PPC64_VRSAVE] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_VRSAVE, 0); + c->dwarf.loc[UNW_PPC64_VSCR] = + DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_VSCR, 0); + } + else + { + c->dwarf.loc[UNW_PPC64_V0] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V1] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V2] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V3] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V4] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V5] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V6] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V7] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V8] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V9] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V10] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V11] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V12] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V13] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V14] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V15] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V16] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V17] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V18] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V19] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V20] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V21] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V22] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V23] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V24] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V25] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V26] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V27] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V28] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V29] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V30] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_V31] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_VRSAVE] = DWARF_NULL_LOC; + c->dwarf.loc[UNW_PPC64_VSCR] = DWARF_NULL_LOC; + } + ret = 1; + } + } + + if (c->dwarf.ip == 0) + { + /* Unless the cursor or stack is corrupt or uninitialized, + we've most likely hit the top of the stack */ + Debug (2, "returning 0\n"); + return 0; + } + + // on ppc64, R2 register is used as pointer to TOC + // section which is used for symbol lookup in PIC code + // ppc64 linker generates "ld r2, 40(r1)" (ELFv1) or + // "ld r2, 24(r1)" (ELFv2) instruction after each + // @plt call. We need restore R2, but only for @plt calls + { + unw_word_t ip = c->dwarf.ip; + unw_addr_space_t as = c->dwarf.as; + unw_accessors_t *a = unw_get_accessors_int (as); + void *arg = c->dwarf.as_arg; + uint32_t toc_save = (as->abi == UNW_PPC64_ABI_ELFv2)? 24 : 40; + int32_t inst; + + if (fetch32 (as, a, &ip, &inst, arg) >= 0 + && (uint32_t)inst == (0xE8410000U + toc_save)) + { + // @plt call, restoring R2 from CFA+toc_save + c->dwarf.loc[UNW_PPC64_R2] = DWARF_LOC(c->dwarf.cfa + toc_save, 0); + } + } + + Debug (2, "returning %d with last return statement\n", ret); + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lapply_reg_state.c new file mode 100644 index 0000000..7ebada4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lapply_reg_state.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gapply_reg_state.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lcreate_addr_space.c new file mode 100644 index 0000000..0f2dc6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lcreate_addr_space.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gcreate_addr_space.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lglobal.c new file mode 100644 index 0000000..6d7b489 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lglobal.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gglobal.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Linit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Linit.c new file mode 100644 index 0000000..e9abfdd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Linit.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lreg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lreg_states_iterate.c new file mode 100644 index 0000000..f1eb1e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lreg_states_iterate.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Greg_states_iterate.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lregs.c new file mode 100644 index 0000000..2c9c75c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lregs.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gregs.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lresume.c new file mode 100644 index 0000000..41a8cf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lresume.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gresume.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lstep.c new file mode 100644 index 0000000..c1ac3c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/Lstep.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gstep.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/get_func_addr.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/get_func_addr.c new file mode 100644 index 0000000..80a58fa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/get_func_addr.c @@ -0,0 +1,51 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr, + unw_word_t *entry_point) +{ + if (as->abi == UNW_PPC64_ABI_ELFv1) + { + unw_accessors_t *a; + int ret; + + a = unw_get_accessors_int (as); + /* Entry-point is stored in the 1st word of the function descriptor. + In case that changes in the future, we'd have to update the line + below and read the word at addr + offset: */ + ret = (*a->access_mem) (as, addr, entry_point, 0, NULL); + if (ret < 0) + return ret; + } + else + *entry_point = addr; + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/init.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/init.h new file mode 100644 index 0000000..9b81393 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/init.h @@ -0,0 +1,82 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static inline int +common_init_ppc64 (struct cursor *c, unsigned use_prev_instr) +{ + int ret; + int i; + + for (i = UNW_PPC64_R0; i <= UNW_PPC64_R31; i++) { + c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, i); + } + for (i = UNW_PPC64_F0; i <= UNW_PPC64_F31; i++) { + c->dwarf.loc[i] = DWARF_FPREG_LOC (&c->dwarf, i); + } + for (i = UNW_PPC64_V0; i <= UNW_PPC64_V31; i++) { + c->dwarf.loc[i] = DWARF_VREG_LOC (&c->dwarf, i); + } + + for (i = UNW_PPC64_CR0; i <= UNW_PPC64_CR7; i++) { + c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, i); + } + c->dwarf.loc[UNW_PPC64_ARG_POINTER] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_ARG_POINTER); + c->dwarf.loc[UNW_PPC64_CTR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_CTR); + c->dwarf.loc[UNW_PPC64_VSCR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_VSCR); + + c->dwarf.loc[UNW_PPC64_XER] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_XER); + c->dwarf.loc[UNW_PPC64_LR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_LR); + c->dwarf.loc[UNW_PPC64_VRSAVE] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_VRSAVE); + c->dwarf.loc[UNW_PPC64_SPEFSCR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_SPEFSCR); + c->dwarf.loc[UNW_PPC64_SPE_ACC] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_SPE_ACC); + + c->dwarf.loc[UNW_PPC64_NIP] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_NIP); + + ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_PPC64_NIP], &c->dwarf.ip); + if (ret < 0) + return ret; + + ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_PPC64_R1), + &c->dwarf.cfa); + if (ret < 0) + return ret; + + c->sigcontext_format = PPC_SCF_NONE; + c->sigcontext_addr = 0; + + c->dwarf.args_size = 0; + c->dwarf.stash_frames = 0; + c->dwarf.use_prev_instr = use_prev_instr; + c->dwarf.pi_valid = 0; + c->dwarf.pi_is_dynamic = 0; + c->dwarf.hint = 0; + c->dwarf.prev_rs = 0; + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/is_fpreg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/is_fpreg.c new file mode 100644 index 0000000..653964a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/is_fpreg.c @@ -0,0 +1,34 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +int +unw_is_fpreg (int regnum) +{ + return (regnum >= UNW_PPC64_F0 && regnum <= UNW_PPC64_F31); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/regname.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/regname.c new file mode 100644 index 0000000..58c6fa6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/regname.c @@ -0,0 +1,164 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford + Jose Flavio Aguilar Paulino + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static const char *regname[] = + { + [UNW_PPC64_R0]="GPR0", + [UNW_PPC64_R1]="GPR1", + [UNW_PPC64_R2]="GPR2", + [UNW_PPC64_R3]="GPR3", + [UNW_PPC64_R4]="GPR4", + [UNW_PPC64_R5]="GPR5", + [UNW_PPC64_R6]="GPR6", + [UNW_PPC64_R7]="GPR7", + [UNW_PPC64_R8]="GPR8", + [UNW_PPC64_R9]="GPR9", + [UNW_PPC64_R10]="GPR10", + [UNW_PPC64_R11]="GPR11", + [UNW_PPC64_R12]="GPR12", + [UNW_PPC64_R13]="GPR13", + [UNW_PPC64_R14]="GPR14", + [UNW_PPC64_R15]="GPR15", + [UNW_PPC64_R16]="GPR16", + [UNW_PPC64_R17]="GPR17", + [UNW_PPC64_R18]="GPR18", + [UNW_PPC64_R19]="GPR19", + [UNW_PPC64_R20]="GPR20", + [UNW_PPC64_R21]="GPR21", + [UNW_PPC64_R22]="GPR22", + [UNW_PPC64_R23]="GPR23", + [UNW_PPC64_R24]="GPR24", + [UNW_PPC64_R25]="GPR25", + [UNW_PPC64_R26]="GPR26", + [UNW_PPC64_R27]="GPR27", + [UNW_PPC64_R28]="GPR28", + [UNW_PPC64_R29]="GPR29", + [UNW_PPC64_R30]="GPR30", + [UNW_PPC64_R31]="GPR31", + + [UNW_PPC64_F0]="FPR0", + [UNW_PPC64_F1]="FPR1", + [UNW_PPC64_F2]="FPR2", + [UNW_PPC64_F3]="FPR3", + [UNW_PPC64_F4]="FPR4", + [UNW_PPC64_F5]="FPR5", + [UNW_PPC64_F6]="FPR6", + [UNW_PPC64_F7]="FPR7", + [UNW_PPC64_F8]="FPR8", + [UNW_PPC64_F9]="FPR9", + [UNW_PPC64_F10]="FPR10", + [UNW_PPC64_F11]="FPR11", + [UNW_PPC64_F12]="FPR12", + [UNW_PPC64_F13]="FPR13", + [UNW_PPC64_F14]="FPR14", + [UNW_PPC64_F15]="FPR15", + [UNW_PPC64_F16]="FPR16", + [UNW_PPC64_F17]="FPR17", + [UNW_PPC64_F18]="FPR18", + [UNW_PPC64_F19]="FPR19", + [UNW_PPC64_F20]="FPR20", + [UNW_PPC64_F21]="FPR21", + [UNW_PPC64_F22]="FPR22", + [UNW_PPC64_F23]="FPR23", + [UNW_PPC64_F24]="FPR24", + [UNW_PPC64_F25]="FPR25", + [UNW_PPC64_F26]="FPR26", + [UNW_PPC64_F27]="FPR27", + [UNW_PPC64_F28]="FPR28", + [UNW_PPC64_F29]="FPR29", + [UNW_PPC64_F30]="FPR30", + [UNW_PPC64_F31]="FPR31", + + [UNW_PPC64_LR]="LR", + [UNW_PPC64_CTR]="CTR", + [UNW_PPC64_ARG_POINTER]="ARG_POINTER", + + [UNW_PPC64_CR0]="CR0", + [UNW_PPC64_CR1]="CR1", + [UNW_PPC64_CR2]="CR2", + [UNW_PPC64_CR3]="CR3", + [UNW_PPC64_CR4]="CR4", + [UNW_PPC64_CR5]="CR5", + [UNW_PPC64_CR6]="CR6", + [UNW_PPC64_CR7]="CR7", + + [UNW_PPC64_XER]="XER", + + [UNW_PPC64_V0]="VR0", + [UNW_PPC64_V1]="VR1", + [UNW_PPC64_V2]="VR2", + [UNW_PPC64_V3]="VR3", + [UNW_PPC64_V4]="VR4", + [UNW_PPC64_V5]="VR5", + [UNW_PPC64_V6]="VR6", + [UNW_PPC64_V7]="VR7", + [UNW_PPC64_V8]="VR8", + [UNW_PPC64_V9]="VR9", + [UNW_PPC64_V10]="VR10", + [UNW_PPC64_V11]="VR11", + [UNW_PPC64_V12]="VR12", + [UNW_PPC64_V13]="VR13", + [UNW_PPC64_V14]="VR14", + [UNW_PPC64_V15]="VR15", + [UNW_PPC64_V16]="VR16", + [UNW_PPC64_V17]="VR17", + [UNW_PPC64_V18]="VR18", + [UNW_PPC64_V19]="VR19", + [UNW_PPC64_V20]="VR20", + [UNW_PPC64_V21]="VR21", + [UNW_PPC64_V22]="VR22", + [UNW_PPC64_V23]="VR23", + [UNW_PPC64_V24]="VR24", + [UNW_PPC64_V25]="VR25", + [UNW_PPC64_V26]="VR26", + [UNW_PPC64_V27]="VR27", + [UNW_PPC64_V28]="VR28", + [UNW_PPC64_V29]="VR29", + [UNW_PPC64_V30]="VR30", + [UNW_PPC64_V31]="VR31", + + [UNW_PPC64_VSCR]="VSCR", + + [UNW_PPC64_VRSAVE]="VRSAVE", + [UNW_PPC64_SPE_ACC]="SPE_ACC", + [UNW_PPC64_SPEFSCR]="SPEFSCR", + + [UNW_PPC64_FRAME_POINTER]="FRAME_POINTER", + [UNW_PPC64_NIP]="NIP", + + }; + +const char * +unw_regname (unw_regnum_t reg) +{ + if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) + return regname[reg]; + else + return "???"; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/setcontext.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/setcontext.S new file mode 100644 index 0000000..ffc2500 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ppc64/setcontext.S @@ -0,0 +1,9 @@ + .global _UI_setcontext + +_UI_setcontext: + blr + +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_access_fpreg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_access_fpreg.c new file mode 100644 index 0000000..2b92462 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_access_fpreg.c @@ -0,0 +1,121 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + Copyright (C) 2010 Konstantin Belousov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +#if HAVE_DECL_PTRACE_POKEUSER || HAVE_TTRACE +int +_UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + unw_word_t *wp = (unw_word_t *) val; + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + int i; + + if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) + return -UNW_EBADREG; + + errno = 0; + if (write) + for (i = 0; i < (int) (sizeof (*val) / sizeof (wp[i])); ++i) + { +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + ptrace (PTRACE_POKEUSER, pid, _UPT_reg_offset[reg] + i * sizeof(wp[i]), + wp[i]); +#endif + if (errno) + return -UNW_EBADREG; + } + else + for (i = 0; i < (int) (sizeof (*val) / sizeof (wp[i])); ++i) + { +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + wp[i] = ptrace (PTRACE_PEEKUSER, pid, + _UPT_reg_offset[reg] + i * sizeof(wp[i]), 0); +#endif + if (errno) + return -UNW_EBADREG; + } + return 0; +} +#elif HAVE_DECL_PT_GETFPREGS +int +_UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + fpregset_t fpreg; + +#if defined(__amd64__) + if (1) /* XXXKIB */ + return -UNW_EBADREG; +#elif defined(__i386__) + if ((unsigned) reg < UNW_X86_ST0 || (unsigned) reg > UNW_X86_ST7) + return -UNW_EBADREG; +#elif defined(__arm__) + if ((unsigned) reg < UNW_ARM_F0 || (unsigned) reg > UNW_ARM_F7) + return -UNW_EBADREG; +#else +#error Fix me +#endif + if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) + return -UNW_EBADREG; + + if (ptrace(PT_GETFPREGS, pid, (caddr_t)&fpreg, 0) == -1) + return -UNW_EBADREG; + if (write) { +#if defined(__amd64__) + memcpy(&fpreg.fpr_xacc[reg], val, sizeof(unw_fpreg_t)); +#elif defined(__i386__) + memcpy(&fpreg.fpr_acc[reg], val, sizeof(unw_fpreg_t)); +#elif defined(__arm__) + memcpy(&fpreg.fpr[reg], val, sizeof(unw_fpreg_t)); +#else +#error Fix me +#endif + if (ptrace(PT_SETFPREGS, pid, (caddr_t)&fpreg, 0) == -1) + return -UNW_EBADREG; + } else +#if defined(__amd64__) + memcpy(val, &fpreg.fpr_xacc[reg], sizeof(unw_fpreg_t)); +#elif defined(__i386__) + memcpy(val, &fpreg.fpr_acc[reg], sizeof(unw_fpreg_t)); +#elif defined(__arm__) + memcpy(val, &fpreg.fpr[reg], sizeof(unw_fpreg_t)); +#else +#error Fix me +#endif + return 0; +} +#else +#error Fix me +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_access_mem.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_access_mem.c new file mode 100644 index 0000000..79bde25 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_access_mem.c @@ -0,0 +1,123 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + Copyright (C) 2010 Konstantin Belousov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +#if HAVE_DECL_PTRACE_POKEDATA || HAVE_TTRACE +int +_UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + int i, end; + unw_word_t tmp_val; + + if (!ui) + return -UNW_EINVAL; + + pid_t pid = ui->pid; + + // Some 32-bit archs have to define a 64-bit unw_word_t. + // Callers of this function therefore expect a 64-bit + // return value, but ptrace only returns a 32-bit value + // in such cases. + if (sizeof(long) == 4 && sizeof(unw_word_t) == 8) + end = 2; + else + end = 1; + + for (i = 0; i < end; i++) + { + unw_word_t tmp_addr = i == 0 ? addr : addr + 4; + + errno = 0; + if (write) + { +#if __BYTE_ORDER == __LITTLE_ENDIAN + tmp_val = i == 0 ? *val : *val >> 32; +#else + tmp_val = i == 0 && end == 2 ? *val >> 32 : *val; +#endif + + Debug (16, "mem[%lx] <- %lx\n", (long) tmp_addr, (long) tmp_val); +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + ptrace (PTRACE_POKEDATA, pid, tmp_addr, tmp_val); + if (errno) + return -UNW_EINVAL; +#endif + } + else + { +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + tmp_val = (unsigned long) ptrace (PTRACE_PEEKDATA, pid, tmp_addr, 0); + + if (i == 0) + *val = 0; + +#if __BYTE_ORDER == __LITTLE_ENDIAN + *val |= tmp_val << (i * 32); +#else + *val |= i == 0 && end == 2 ? tmp_val << 32 : tmp_val; +#endif + + if (errno) + return -UNW_EINVAL; +#endif + Debug (16, "mem[%lx] -> %lx\n", (long) tmp_addr, (long) tmp_val); + } + } + return 0; +} +#elif HAVE_DECL_PT_IO +int +_UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + if (!ui) + return -UNW_EINVAL; + pid_t pid = ui->pid; + struct ptrace_io_desc iod; + + iod.piod_offs = (void *)addr; + iod.piod_addr = val; + iod.piod_len = sizeof(*val); + iod.piod_op = write ? PIOD_WRITE_D : PIOD_READ_D; + if (write) + Debug (16, "mem[%lx] <- %lx\n", (long) addr, (long) *val); + if (ptrace(PT_IO, pid, (caddr_t)&iod, 0) == -1) + return -UNW_EINVAL; + if (!write) + Debug (16, "mem[%lx] -> %lx\n", (long) addr, (long) *val); + return 0; +} +#else +#error Fix me +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_access_reg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_access_reg.c new file mode 100644 index 0000000..ce25c78 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_access_reg.c @@ -0,0 +1,352 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + Copyright (C) 2010 Konstantin Belousov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +#if UNW_TARGET_IA64 +# include +# ifdef HAVE_ASM_PTRACE_OFFSETS_H +# include +# endif +# include "tdep-ia64/rse.h" +#endif + +#if HAVE_DECL_PTRACE_SETREGSET +#include +int +_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + gregset_t regs; + char *r; + struct iovec loc; + +#if UNW_DEBUG + Debug(16, "using getregset: reg: %s [%u], val: %lx, write: %u\n", + unw_regname(reg), (unsigned) reg, (long) val, write); + + if (write) + Debug (16, "%s [%u] <- %lx\n", unw_regname (reg), (unsigned) reg, (long) *val); +#endif + if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) + { + errno = EINVAL; + goto badreg; + } + + loc.iov_base = ®s; + loc.iov_len = sizeof(regs); + + r = (char *)®s + _UPT_reg_offset[reg]; + if (ptrace (PTRACE_GETREGSET, pid, NT_PRSTATUS, &loc) == -1) + goto badreg; + if (write) { + memcpy(r, val, sizeof(unw_word_t)); + if (ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &loc) == -1) + goto badreg; + } else + memcpy(val, r, sizeof(unw_word_t)); + return 0; + +badreg: + Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno)); + return -UNW_EBADREG; +} +#elif HAVE_DECL_PTRACE_POKEUSER || HAVE_TTRACE +int +_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + +#if UNW_DEBUG + Debug(16, "using pokeuser: reg: %s [%u], val: %lx, write: %d\n", unw_regname(reg), (unsigned) reg, (long) val, write); + + if (write) + Debug (16, "%s <- %lx\n", unw_regname (reg), (long) *val); +#endif + +#if UNW_TARGET_IA64 + if ((unsigned) reg - UNW_IA64_NAT < 32) + { + unsigned long nat_bits, mask; + + /* The Linux ptrace represents the statc NaT bits as a single word. */ + mask = ((unw_word_t) 1) << (reg - UNW_IA64_NAT); + errno = 0; +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + nat_bits = ptrace (PTRACE_PEEKUSER, pid, PT_NAT_BITS, 0); + if (errno) + goto badreg; +#endif + + if (write) + { + if (*val) + nat_bits |= mask; + else + nat_bits &= ~mask; +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + ptrace (PTRACE_POKEUSER, pid, PT_NAT_BITS, nat_bits); + if (errno) + goto badreg; +#endif + } + goto out; + } + else + switch (reg) + { + case UNW_IA64_GR + 0: + if (write) + goto badreg; + *val = 0; + return 0; + + case UNW_REG_IP: + { + unsigned long ip, psr; + + /* distribute bundle-addr. & slot-number across PT_IIP & PT_IPSR. */ +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + psr = ptrace (PTRACE_PEEKUSER, pid, PT_CR_IPSR, 0); + if (errno) + goto badreg; +#endif + if (write) + { + ip = *val & ~0xfUL; + psr = (psr & ~0x3UL << 41) | (*val & 0x3); +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + ptrace (PTRACE_POKEUSER, pid, PT_CR_IIP, ip); + ptrace (PTRACE_POKEUSER, pid, PT_CR_IPSR, psr); + if (errno) + goto badreg; +#endif + } + else + { +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + ip = ptrace (PTRACE_PEEKUSER, pid, PT_CR_IIP, 0); + if (errno) + goto badreg; +#endif + *val = ip + ((psr >> 41) & 0x3); + } + goto out; + } + + case UNW_IA64_AR_BSPSTORE: + reg = UNW_IA64_AR_BSP; + break; + + case UNW_IA64_AR_BSP: + case UNW_IA64_BSP: + { + unsigned long sof, cfm, bsp; + +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + /* Account for the fact that ptrace() expects bsp to point + _after_ the current register frame. */ + errno = 0; + cfm = ptrace (PTRACE_PEEKUSER, pid, PT_CFM, 0); + if (errno) + goto badreg; +#endif + sof = (cfm & 0x7f); + + if (write) + { + bsp = rse_skip_regs (*val, sof); +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + ptrace (PTRACE_POKEUSER, pid, PT_AR_BSP, bsp); + if (errno) + goto badreg; +#endif + } + else + { +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0); + if (errno) + goto badreg; +#endif + *val = rse_skip_regs (bsp, -sof); + } + goto out; + } + + case UNW_IA64_CFM: + /* If we change CFM, we need to adjust ptrace's notion of bsp + accordingly, so that the real bsp remains unchanged. */ + if (write) + { + unsigned long new_sof, old_sof, cfm, bsp; + +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0); + cfm = ptrace (PTRACE_PEEKUSER, pid, PT_CFM, 0); +#endif + if (errno) + goto badreg; + old_sof = (cfm & 0x7f); + new_sof = (*val & 0x7f); + if (old_sof != new_sof) + { + bsp = rse_skip_regs (bsp, -old_sof + new_sof); +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + ptrace (PTRACE_POKEUSER, pid, PT_AR_BSP, 0); + if (errno) + goto badreg; +#endif + } +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + ptrace (PTRACE_POKEUSER, pid, PT_CFM, *val); + if (errno) + goto badreg; +#endif + goto out; + } + break; + } +#endif /* End of IA64 */ + + if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) + { +#if UNW_DEBUG + Debug(2, "register out of range: >= %zu / %zu\n", sizeof(_UPT_reg_offset), sizeof(_UPT_reg_offset[0])); +#endif + errno = EINVAL; + goto badreg; + } + +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + if (write) + ptrace (PTRACE_POKEUSER, pid, _UPT_reg_offset[reg], *val); + else { +#if UNW_DEBUG + Debug(16, "ptrace PEEKUSER pid: %lu , reg: %lu , offs: %lu\n", (unsigned long)pid, (unsigned long)reg, + (unsigned long)_UPT_reg_offset[reg]); +#endif + *val = ptrace (PTRACE_PEEKUSER, pid, _UPT_reg_offset[reg], 0); + } + if (errno) { +#if UNW_DEBUG + Debug(2, "ptrace failure\n"); +#endif + goto badreg; + } +#endif + +#ifdef UNW_TARGET_IA64 + out: +#endif +#if UNW_DEBUG + if (!write) + Debug (16, "%s[%u] -> %lx\n", unw_regname (reg), (unsigned) reg, (long) *val); +#endif + return 0; + + badreg: + Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno)); + return -UNW_EBADREG; +} +#elif HAVE_DECL_PT_GETREGS +int +_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + gregset_t regs; + char *r; + +#if UNW_DEBUG + Debug(16, "using getregs: reg: %s [%u], val: %lx, write: %u\n", unw_regname(reg), (unsigned) reg, (long) val, write); + + if (write) + Debug (16, "%s [%u] <- %lx\n", unw_regname (reg), (unsigned) reg, (long) *val); +#endif + if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) + { + errno = EINVAL; + goto badreg; + } + r = (char *)®s + _UPT_reg_offset[reg]; + if (ptrace(PT_GETREGS, pid, (caddr_t)®s, 0) == -1) + goto badreg; + if (write) { + memcpy(r, val, sizeof(unw_word_t)); + if (ptrace(PT_SETREGS, pid, (caddr_t)®s, 0) == -1) + goto badreg; + } else + memcpy(val, r, sizeof(unw_word_t)); + return 0; + + badreg: + Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno)); + return -UNW_EBADREG; +} +#else +#error Port me +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_accessors.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_accessors.c new file mode 100644 index 0000000..4724360 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_accessors.c @@ -0,0 +1,38 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +unw_accessors_t _UPT_accessors = + { + .find_proc_info = _UPT_find_proc_info, + .put_unwind_info = _UPT_put_unwind_info, + .get_dyn_info_list_addr = _UPT_get_dyn_info_list_addr, + .access_mem = _UPT_access_mem, + .access_reg = _UPT_access_reg, + .access_fpreg = _UPT_access_fpreg, + .resume = _UPT_resume, + .get_proc_name = _UPT_get_proc_name + }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_create.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_create.c new file mode 100644 index 0000000..dd59e97 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_create.c @@ -0,0 +1,46 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "_UPT_internal.h" + +void * +_UPT_create (pid_t pid) +{ + struct UPT_info *ui = malloc (sizeof (struct UPT_info)); + + if (!ui) + return NULL; + + memset (ui, 0, sizeof (*ui)); + ui->pid = pid; + ui->edi.di_cache.format = -1; + ui->edi.di_debug.format = -1; +#if UNW_TARGET_IA64 + ui->edi.ktab.format = -1; +#endif + return ui; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_destroy.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_destroy.c new file mode 100644 index 0000000..edb664c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_destroy.c @@ -0,0 +1,34 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +void +_UPT_destroy (void *ptr) +{ + struct UPT_info *ui = (struct UPT_info *) ptr; + invalidate_edi (&ui->edi); + free (ptr); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_elf.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_elf.c new file mode 100644 index 0000000..efc43b5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_elf.c @@ -0,0 +1,5 @@ +/* We need to get a separate copy of the ELF-code into + libunwind-ptrace since it cannot (and must not) have any ELF + dependencies on libunwind. */ +#include "libunwind_i.h" /* get ELFCLASS defined */ +#include "../elfxx.c" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_find_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_find_proc_info.c new file mode 100644 index 0000000..b3209f4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_find_proc_info.c @@ -0,0 +1,145 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include +#include + +#include + +#include "_UPT_internal.h" + +static int +get_unwind_info (struct elf_dyn_info *edi, pid_t pid, unw_addr_space_t as, unw_word_t ip) +{ + unsigned long segbase, mapoff; + char path[PATH_MAX]; + +#if UNW_TARGET_IA64 && defined(__linux) + if (!edi->ktab.start_ip && _Uia64_get_kernel_table (&edi->ktab) < 0) + return -UNW_ENOINFO; + + if (edi->ktab.format != -1 && ip >= edi->ktab.start_ip && ip < edi->ktab.end_ip) + return 0; +#endif + + if ((edi->di_cache.format != -1 + && ip >= edi->di_cache.start_ip && ip < edi->di_cache.end_ip) +#if UNW_TARGET_ARM + || (edi->di_debug.format != -1 + && ip >= edi->di_arm.start_ip && ip < edi->di_arm.end_ip) +#endif + || (edi->di_debug.format != -1 + && ip >= edi->di_debug.start_ip && ip < edi->di_debug.end_ip)) + return 0; + + invalidate_edi(edi); + + if (tdep_get_elf_image (&edi->ei, pid, ip, &segbase, &mapoff, path, + sizeof(path)) < 0) + return -UNW_ENOINFO; + + /* Here, SEGBASE is the starting-address of the (mmap'ped) segment + which covers the IP we're looking for. */ + if (tdep_find_unwind_table (edi, as, path, segbase, mapoff, ip) < 0) + return -UNW_ENOINFO; + + /* This can happen in corner cases where dynamically generated + code falls into the same page that contains the data-segment + and the page-offset of the code is within the first page of + the executable. */ + if (edi->di_cache.format != -1 + && (ip < edi->di_cache.start_ip || ip >= edi->di_cache.end_ip)) + edi->di_cache.format = -1; + + if (edi->di_debug.format != -1 + && (ip < edi->di_debug.start_ip || ip >= edi->di_debug.end_ip)) + edi->di_debug.format = -1; + + if (edi->di_cache.format == -1 +#if UNW_TARGET_ARM + && edi->di_arm.format == -1 +#endif + && edi->di_debug.format == -1) + return -UNW_ENOINFO; + + return 0; +} + +int +_UPT_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + struct UPT_info *ui = arg; + int ret = -UNW_ENOINFO; + + if (get_unwind_info (&ui->edi, ui->pid, as, ip) < 0) + return -UNW_ENOINFO; + +#if UNW_TARGET_IA64 + if (ui->edi.ktab.format != -1) + { + /* The kernel unwind table resides in local memory, so we have + to use the local address space to search it. Since + _UPT_put_unwind_info() has no easy way of detecting this + case, we simply make a copy of the unwind-info, so + _UPT_put_unwind_info() can always free() the unwind-info + without ill effects. */ + ret = tdep_search_unwind_table (unw_local_addr_space, ip, &ui->edi.ktab, pi, + need_unwind_info, arg); + if (ret >= 0) + { + if (!need_unwind_info) + pi->unwind_info = NULL; + else + { + void *mem = malloc (pi->unwind_info_size); + + if (!mem) + return -UNW_ENOMEM; + memcpy (mem, pi->unwind_info, pi->unwind_info_size); + pi->unwind_info = mem; + } + } + } +#endif + + if (ret == -UNW_ENOINFO && ui->edi.di_cache.format != -1) + ret = tdep_search_unwind_table (as, ip, &ui->edi.di_cache, + pi, need_unwind_info, arg); + + if (ret == -UNW_ENOINFO && ui->edi.di_debug.format != -1) + ret = tdep_search_unwind_table (as, ip, &ui->edi.di_debug, pi, + need_unwind_info, arg); + +#if UNW_TARGET_ARM + if (ret == -UNW_ENOINFO && ui->edi.di_arm.format != -1) + ret = tdep_search_unwind_table (as, ip, &ui->edi.di_arm, pi, + need_unwind_info, arg); +#endif + + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_get_dyn_info_list_addr.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_get_dyn_info_list_addr.c new file mode 100644 index 0000000..cc5ed04 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_get_dyn_info_list_addr.c @@ -0,0 +1,105 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +#if UNW_TARGET_IA64 && defined(__linux) +# include "elf64.h" +# include "os-linux.h" + +static inline int +get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg, + int *countp) +{ + unsigned long lo, hi, off; + struct UPT_info *ui = arg; + struct map_iterator mi; + char path[PATH_MAX]; + unw_word_t res; + int count = 0; + + maps_init (&mi, ui->pid); + while (maps_next (&mi, &lo, &hi, &off)) + { + if (off) + continue; + + invalidate_edi(&ui->edi); + + if (elf_map_image (&ui->edi.ei, path) < 0) + /* ignore unmappable stuff like "/SYSV00001b58 (deleted)" */ + continue; + + Debug (16, "checking object %s\n", path); + + if (tdep_find_unwind_table (&ui->edi, as, path, lo, off, 0) > 0) + { + res = _Uia64_find_dyn_list (as, &ui->edi.di_cache, arg); + if (res && count++ == 0) + { + Debug (12, "dyn_info_list_addr = 0x%lx\n", (long) res); + *dil_addr = res; + } + } + } + maps_close (&mi); + *countp = count; + return 0; +} + +#else + +static inline int +get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg, + int *countp) +{ +# warning Implement get_list_addr(), please. + *countp = 0; + return 0; +} + +#endif + +int +_UPT_get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, + void *arg) +{ + int count, ret; + + Debug (12, "looking for dyn_info list\n"); + + if ((ret = get_list_addr (as, dil_addr, arg, &count)) < 0) + return ret; + + /* If multiple dynamic-info list addresses are found, we would have + to determine which was is the one actually in use (since the + dynamic name resolution algorithm will pick one "winner"). + Perhaps we'd have to track them all until we find one that's + non-empty. Hopefully, this case simply will never arise, since + only libunwind defines the dynamic info list head. */ + assert (count <= 1); + + return (count > 0) ? 0 : -UNW_ENOINFO; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_get_proc_name.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_get_proc_name.c new file mode 100644 index 0000000..79c1f38 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_get_proc_name.c @@ -0,0 +1,42 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Copyright (C) 2007 David Mosberger-Tang + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +int +_UPT_get_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, void *arg) +{ + struct UPT_info *ui = arg; + +#if ELF_CLASS == ELFCLASS64 + return _Uelf64_get_proc_name (as, ui->pid, ip, buf, buf_len, offp); +#elif ELF_CLASS == ELFCLASS32 + return _Uelf32_get_proc_name (as, ui->pid, ip, buf, buf_len, offp); +#else + return -UNW_ENOINFO; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_internal.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_internal.h new file mode 100644 index 0000000..5cef257 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_internal.h @@ -0,0 +1,59 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _UPT_internal_h +#define _UPT_internal_h + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_PTRACE_H +#include +#endif +#ifdef HAVE_SYS_PROCFS_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "libunwind_i.h" + +struct UPT_info + { + pid_t pid; /* the process-id of the child we're unwinding */ + struct elf_dyn_info edi; + }; + +extern const int _UPT_reg_offset[UNW_REG_LAST + 1]; + +#endif /* _UPT_internal_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_put_unwind_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_put_unwind_info.c new file mode 100644 index 0000000..d4b8463 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_put_unwind_info.c @@ -0,0 +1,35 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +void +_UPT_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg) +{ + if (!pi->unwind_info) + return; + free (pi->unwind_info); + pi->unwind_info = NULL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c new file mode 100644 index 0000000..c82d1c9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c @@ -0,0 +1,638 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + Copyright (C) 2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +#include + +#ifdef HAVE_ASM_PTRACE_OFFSETS_H +# include +#endif + +const int _UPT_reg_offset[UNW_REG_LAST + 1] = + { +#ifdef HAVE_ASM_PTRACE_OFFSETS_H +# ifndef PT_AR_CSD +# define PT_AR_CSD -1 /* this was introduced with rev 2.1 of ia64 */ +# endif + + [UNW_IA64_GR + 0] = -1, [UNW_IA64_GR + 1] = PT_R1, + [UNW_IA64_GR + 2] = PT_R2, [UNW_IA64_GR + 3] = PT_R3, + [UNW_IA64_GR + 4] = PT_R4, [UNW_IA64_GR + 5] = PT_R5, + [UNW_IA64_GR + 6] = PT_R6, [UNW_IA64_GR + 7] = PT_R7, + [UNW_IA64_GR + 8] = PT_R8, [UNW_IA64_GR + 9] = PT_R9, + [UNW_IA64_GR + 10] = PT_R10, [UNW_IA64_GR + 11] = PT_R11, + [UNW_IA64_GR + 12] = PT_R12, [UNW_IA64_GR + 13] = PT_R13, + [UNW_IA64_GR + 14] = PT_R14, [UNW_IA64_GR + 15] = PT_R15, + [UNW_IA64_GR + 16] = PT_R16, [UNW_IA64_GR + 17] = PT_R17, + [UNW_IA64_GR + 18] = PT_R18, [UNW_IA64_GR + 19] = PT_R19, + [UNW_IA64_GR + 20] = PT_R20, [UNW_IA64_GR + 21] = PT_R21, + [UNW_IA64_GR + 22] = PT_R22, [UNW_IA64_GR + 23] = PT_R23, + [UNW_IA64_GR + 24] = PT_R24, [UNW_IA64_GR + 25] = PT_R25, + [UNW_IA64_GR + 26] = PT_R26, [UNW_IA64_GR + 27] = PT_R27, + [UNW_IA64_GR + 28] = PT_R28, [UNW_IA64_GR + 29] = PT_R29, + [UNW_IA64_GR + 30] = PT_R30, [UNW_IA64_GR + 31] = PT_R31, + + [UNW_IA64_NAT+ 0] = -1, [UNW_IA64_NAT+ 1] = PT_NAT_BITS, + [UNW_IA64_NAT+ 2] = PT_NAT_BITS, [UNW_IA64_NAT+ 3] = PT_NAT_BITS, + [UNW_IA64_NAT+ 4] = PT_NAT_BITS, [UNW_IA64_NAT+ 5] = PT_NAT_BITS, + [UNW_IA64_NAT+ 6] = PT_NAT_BITS, [UNW_IA64_NAT+ 7] = PT_NAT_BITS, + [UNW_IA64_NAT+ 8] = PT_NAT_BITS, [UNW_IA64_NAT+ 9] = PT_NAT_BITS, + [UNW_IA64_NAT+ 10] = PT_NAT_BITS, [UNW_IA64_NAT+ 11] = PT_NAT_BITS, + [UNW_IA64_NAT+ 12] = PT_NAT_BITS, [UNW_IA64_NAT+ 13] = PT_NAT_BITS, + [UNW_IA64_NAT+ 14] = PT_NAT_BITS, [UNW_IA64_NAT+ 15] = PT_NAT_BITS, + [UNW_IA64_NAT+ 16] = PT_NAT_BITS, [UNW_IA64_NAT+ 17] = PT_NAT_BITS, + [UNW_IA64_NAT+ 18] = PT_NAT_BITS, [UNW_IA64_NAT+ 19] = PT_NAT_BITS, + [UNW_IA64_NAT+ 20] = PT_NAT_BITS, [UNW_IA64_NAT+ 21] = PT_NAT_BITS, + [UNW_IA64_NAT+ 22] = PT_NAT_BITS, [UNW_IA64_NAT+ 23] = PT_NAT_BITS, + [UNW_IA64_NAT+ 24] = PT_NAT_BITS, [UNW_IA64_NAT+ 25] = PT_NAT_BITS, + [UNW_IA64_NAT+ 26] = PT_NAT_BITS, [UNW_IA64_NAT+ 27] = PT_NAT_BITS, + [UNW_IA64_NAT+ 28] = PT_NAT_BITS, [UNW_IA64_NAT+ 29] = PT_NAT_BITS, + [UNW_IA64_NAT+ 30] = PT_NAT_BITS, [UNW_IA64_NAT+ 31] = PT_NAT_BITS, + + [UNW_IA64_FR + 0] = -1, [UNW_IA64_FR + 1] = -1, + [UNW_IA64_FR + 2] = PT_F2, [UNW_IA64_FR + 3] = PT_F3, + [UNW_IA64_FR + 4] = PT_F4, [UNW_IA64_FR + 5] = PT_F5, + [UNW_IA64_FR + 6] = PT_F6, [UNW_IA64_FR + 7] = PT_F7, + [UNW_IA64_FR + 8] = PT_F8, [UNW_IA64_FR + 9] = PT_F9, + [UNW_IA64_FR + 10] = PT_F10, [UNW_IA64_FR + 11] = PT_F11, + [UNW_IA64_FR + 12] = PT_F12, [UNW_IA64_FR + 13] = PT_F13, + [UNW_IA64_FR + 14] = PT_F14, [UNW_IA64_FR + 15] = PT_F15, + [UNW_IA64_FR + 16] = PT_F16, [UNW_IA64_FR + 17] = PT_F17, + [UNW_IA64_FR + 18] = PT_F18, [UNW_IA64_FR + 19] = PT_F19, + [UNW_IA64_FR + 20] = PT_F20, [UNW_IA64_FR + 21] = PT_F21, + [UNW_IA64_FR + 22] = PT_F22, [UNW_IA64_FR + 23] = PT_F23, + [UNW_IA64_FR + 24] = PT_F24, [UNW_IA64_FR + 25] = PT_F25, + [UNW_IA64_FR + 26] = PT_F26, [UNW_IA64_FR + 27] = PT_F27, + [UNW_IA64_FR + 28] = PT_F28, [UNW_IA64_FR + 29] = PT_F29, + [UNW_IA64_FR + 30] = PT_F30, [UNW_IA64_FR + 31] = PT_F31, + [UNW_IA64_FR + 32] = PT_F32, [UNW_IA64_FR + 33] = PT_F33, + [UNW_IA64_FR + 34] = PT_F34, [UNW_IA64_FR + 35] = PT_F35, + [UNW_IA64_FR + 36] = PT_F36, [UNW_IA64_FR + 37] = PT_F37, + [UNW_IA64_FR + 38] = PT_F38, [UNW_IA64_FR + 39] = PT_F39, + [UNW_IA64_FR + 40] = PT_F40, [UNW_IA64_FR + 41] = PT_F41, + [UNW_IA64_FR + 42] = PT_F42, [UNW_IA64_FR + 43] = PT_F43, + [UNW_IA64_FR + 44] = PT_F44, [UNW_IA64_FR + 45] = PT_F45, + [UNW_IA64_FR + 46] = PT_F46, [UNW_IA64_FR + 47] = PT_F47, + [UNW_IA64_FR + 48] = PT_F48, [UNW_IA64_FR + 49] = PT_F49, + [UNW_IA64_FR + 50] = PT_F50, [UNW_IA64_FR + 51] = PT_F51, + [UNW_IA64_FR + 52] = PT_F52, [UNW_IA64_FR + 53] = PT_F53, + [UNW_IA64_FR + 54] = PT_F54, [UNW_IA64_FR + 55] = PT_F55, + [UNW_IA64_FR + 56] = PT_F56, [UNW_IA64_FR + 57] = PT_F57, + [UNW_IA64_FR + 58] = PT_F58, [UNW_IA64_FR + 59] = PT_F59, + [UNW_IA64_FR + 60] = PT_F60, [UNW_IA64_FR + 61] = PT_F61, + [UNW_IA64_FR + 62] = PT_F62, [UNW_IA64_FR + 63] = PT_F63, + [UNW_IA64_FR + 64] = PT_F64, [UNW_IA64_FR + 65] = PT_F65, + [UNW_IA64_FR + 66] = PT_F66, [UNW_IA64_FR + 67] = PT_F67, + [UNW_IA64_FR + 68] = PT_F68, [UNW_IA64_FR + 69] = PT_F69, + [UNW_IA64_FR + 70] = PT_F70, [UNW_IA64_FR + 71] = PT_F71, + [UNW_IA64_FR + 72] = PT_F72, [UNW_IA64_FR + 73] = PT_F73, + [UNW_IA64_FR + 74] = PT_F74, [UNW_IA64_FR + 75] = PT_F75, + [UNW_IA64_FR + 76] = PT_F76, [UNW_IA64_FR + 77] = PT_F77, + [UNW_IA64_FR + 78] = PT_F78, [UNW_IA64_FR + 79] = PT_F79, + [UNW_IA64_FR + 80] = PT_F80, [UNW_IA64_FR + 81] = PT_F81, + [UNW_IA64_FR + 82] = PT_F82, [UNW_IA64_FR + 83] = PT_F83, + [UNW_IA64_FR + 84] = PT_F84, [UNW_IA64_FR + 85] = PT_F85, + [UNW_IA64_FR + 86] = PT_F86, [UNW_IA64_FR + 87] = PT_F87, + [UNW_IA64_FR + 88] = PT_F88, [UNW_IA64_FR + 89] = PT_F89, + [UNW_IA64_FR + 90] = PT_F90, [UNW_IA64_FR + 91] = PT_F91, + [UNW_IA64_FR + 92] = PT_F92, [UNW_IA64_FR + 93] = PT_F93, + [UNW_IA64_FR + 94] = PT_F94, [UNW_IA64_FR + 95] = PT_F95, + [UNW_IA64_FR + 96] = PT_F96, [UNW_IA64_FR + 97] = PT_F97, + [UNW_IA64_FR + 98] = PT_F98, [UNW_IA64_FR + 99] = PT_F99, + [UNW_IA64_FR +100] = PT_F100, [UNW_IA64_FR +101] = PT_F101, + [UNW_IA64_FR +102] = PT_F102, [UNW_IA64_FR +103] = PT_F103, + [UNW_IA64_FR +104] = PT_F104, [UNW_IA64_FR +105] = PT_F105, + [UNW_IA64_FR +106] = PT_F106, [UNW_IA64_FR +107] = PT_F107, + [UNW_IA64_FR +108] = PT_F108, [UNW_IA64_FR +109] = PT_F109, + [UNW_IA64_FR +110] = PT_F110, [UNW_IA64_FR +111] = PT_F111, + [UNW_IA64_FR +112] = PT_F112, [UNW_IA64_FR +113] = PT_F113, + [UNW_IA64_FR +114] = PT_F114, [UNW_IA64_FR +115] = PT_F115, + [UNW_IA64_FR +116] = PT_F116, [UNW_IA64_FR +117] = PT_F117, + [UNW_IA64_FR +118] = PT_F118, [UNW_IA64_FR +119] = PT_F119, + [UNW_IA64_FR +120] = PT_F120, [UNW_IA64_FR +121] = PT_F121, + [UNW_IA64_FR +122] = PT_F122, [UNW_IA64_FR +123] = PT_F123, + [UNW_IA64_FR +124] = PT_F124, [UNW_IA64_FR +125] = PT_F125, + [UNW_IA64_FR +126] = PT_F126, [UNW_IA64_FR +127] = PT_F127, + + [UNW_IA64_AR + 0] = -1, [UNW_IA64_AR + 1] = -1, + [UNW_IA64_AR + 2] = -1, [UNW_IA64_AR + 3] = -1, + [UNW_IA64_AR + 4] = -1, [UNW_IA64_AR + 5] = -1, + [UNW_IA64_AR + 6] = -1, [UNW_IA64_AR + 7] = -1, + [UNW_IA64_AR + 8] = -1, [UNW_IA64_AR + 9] = -1, + [UNW_IA64_AR + 10] = -1, [UNW_IA64_AR + 11] = -1, + [UNW_IA64_AR + 12] = -1, [UNW_IA64_AR + 13] = -1, + [UNW_IA64_AR + 14] = -1, [UNW_IA64_AR + 15] = -1, + [UNW_IA64_AR + 16] = PT_AR_RSC, [UNW_IA64_AR + 17] = PT_AR_BSP, + [UNW_IA64_AR + 18] = PT_AR_BSPSTORE,[UNW_IA64_AR + 19] = PT_AR_RNAT, + [UNW_IA64_AR + 20] = -1, [UNW_IA64_AR + 21] = -1, + [UNW_IA64_AR + 22] = -1, [UNW_IA64_AR + 23] = -1, + [UNW_IA64_AR + 24] = -1, [UNW_IA64_AR + 25] = PT_AR_CSD, + [UNW_IA64_AR + 26] = -1, [UNW_IA64_AR + 27] = -1, + [UNW_IA64_AR + 28] = -1, [UNW_IA64_AR + 29] = -1, + [UNW_IA64_AR + 30] = -1, [UNW_IA64_AR + 31] = -1, + [UNW_IA64_AR + 32] = PT_AR_CCV, [UNW_IA64_AR + 33] = -1, + [UNW_IA64_AR + 34] = -1, [UNW_IA64_AR + 35] = -1, + [UNW_IA64_AR + 36] = PT_AR_UNAT, [UNW_IA64_AR + 37] = -1, + [UNW_IA64_AR + 38] = -1, [UNW_IA64_AR + 39] = -1, + [UNW_IA64_AR + 40] = PT_AR_FPSR, [UNW_IA64_AR + 41] = -1, + [UNW_IA64_AR + 42] = -1, [UNW_IA64_AR + 43] = -1, + [UNW_IA64_AR + 44] = -1, [UNW_IA64_AR + 45] = -1, + [UNW_IA64_AR + 46] = -1, [UNW_IA64_AR + 47] = -1, + [UNW_IA64_AR + 48] = -1, [UNW_IA64_AR + 49] = -1, + [UNW_IA64_AR + 50] = -1, [UNW_IA64_AR + 51] = -1, + [UNW_IA64_AR + 52] = -1, [UNW_IA64_AR + 53] = -1, + [UNW_IA64_AR + 54] = -1, [UNW_IA64_AR + 55] = -1, + [UNW_IA64_AR + 56] = -1, [UNW_IA64_AR + 57] = -1, + [UNW_IA64_AR + 58] = -1, [UNW_IA64_AR + 59] = -1, + [UNW_IA64_AR + 60] = -1, [UNW_IA64_AR + 61] = -1, + [UNW_IA64_AR + 62] = -1, [UNW_IA64_AR + 63] = -1, + [UNW_IA64_AR + 64] = PT_AR_PFS, [UNW_IA64_AR + 65] = PT_AR_LC, + [UNW_IA64_AR + 66] = PT_AR_EC, [UNW_IA64_AR + 67] = -1, + [UNW_IA64_AR + 68] = -1, [UNW_IA64_AR + 69] = -1, + [UNW_IA64_AR + 70] = -1, [UNW_IA64_AR + 71] = -1, + [UNW_IA64_AR + 72] = -1, [UNW_IA64_AR + 73] = -1, + [UNW_IA64_AR + 74] = -1, [UNW_IA64_AR + 75] = -1, + [UNW_IA64_AR + 76] = -1, [UNW_IA64_AR + 77] = -1, + [UNW_IA64_AR + 78] = -1, [UNW_IA64_AR + 79] = -1, + [UNW_IA64_AR + 80] = -1, [UNW_IA64_AR + 81] = -1, + [UNW_IA64_AR + 82] = -1, [UNW_IA64_AR + 83] = -1, + [UNW_IA64_AR + 84] = -1, [UNW_IA64_AR + 85] = -1, + [UNW_IA64_AR + 86] = -1, [UNW_IA64_AR + 87] = -1, + [UNW_IA64_AR + 88] = -1, [UNW_IA64_AR + 89] = -1, + [UNW_IA64_AR + 90] = -1, [UNW_IA64_AR + 91] = -1, + [UNW_IA64_AR + 92] = -1, [UNW_IA64_AR + 93] = -1, + [UNW_IA64_AR + 94] = -1, [UNW_IA64_AR + 95] = -1, + [UNW_IA64_AR + 96] = -1, [UNW_IA64_AR + 97] = -1, + [UNW_IA64_AR + 98] = -1, [UNW_IA64_AR + 99] = -1, + [UNW_IA64_AR +100] = -1, [UNW_IA64_AR +101] = -1, + [UNW_IA64_AR +102] = -1, [UNW_IA64_AR +103] = -1, + [UNW_IA64_AR +104] = -1, [UNW_IA64_AR +105] = -1, + [UNW_IA64_AR +106] = -1, [UNW_IA64_AR +107] = -1, + [UNW_IA64_AR +108] = -1, [UNW_IA64_AR +109] = -1, + [UNW_IA64_AR +110] = -1, [UNW_IA64_AR +111] = -1, + [UNW_IA64_AR +112] = -1, [UNW_IA64_AR +113] = -1, + [UNW_IA64_AR +114] = -1, [UNW_IA64_AR +115] = -1, + [UNW_IA64_AR +116] = -1, [UNW_IA64_AR +117] = -1, + [UNW_IA64_AR +118] = -1, [UNW_IA64_AR +119] = -1, + [UNW_IA64_AR +120] = -1, [UNW_IA64_AR +121] = -1, + [UNW_IA64_AR +122] = -1, [UNW_IA64_AR +123] = -1, + [UNW_IA64_AR +124] = -1, [UNW_IA64_AR +125] = -1, + [UNW_IA64_AR +126] = -1, [UNW_IA64_AR +127] = -1, + + [UNW_IA64_BR + 0] = PT_B0, [UNW_IA64_BR + 1] = PT_B1, + [UNW_IA64_BR + 2] = PT_B2, [UNW_IA64_BR + 3] = PT_B3, + [UNW_IA64_BR + 4] = PT_B4, [UNW_IA64_BR + 5] = PT_B5, + [UNW_IA64_BR + 6] = PT_B6, [UNW_IA64_BR + 7] = PT_B7, + + [UNW_IA64_PR] = PT_PR, + [UNW_IA64_CFM] = PT_CFM, + [UNW_IA64_IP] = PT_CR_IIP +#elif defined(HAVE_TTRACE) +# warning No support for ttrace() yet. +#elif defined(UNW_TARGET_HPPA) + [UNW_HPPA_GR + 0] = 0x000, [UNW_HPPA_GR + 1] = 0x004, + [UNW_HPPA_GR + 2] = 0x008, [UNW_HPPA_GR + 3] = 0x00c, + [UNW_HPPA_GR + 4] = 0x010, [UNW_HPPA_GR + 5] = 0x014, + [UNW_HPPA_GR + 6] = 0x018, [UNW_HPPA_GR + 7] = 0x01c, + [UNW_HPPA_GR + 8] = 0x020, [UNW_HPPA_GR + 9] = 0x024, + [UNW_HPPA_GR + 10] = 0x028, [UNW_HPPA_GR + 11] = 0x02c, + [UNW_HPPA_GR + 12] = 0x030, [UNW_HPPA_GR + 13] = 0x034, + [UNW_HPPA_GR + 14] = 0x038, [UNW_HPPA_GR + 15] = 0x03c, + [UNW_HPPA_GR + 16] = 0x040, [UNW_HPPA_GR + 17] = 0x044, + [UNW_HPPA_GR + 18] = 0x048, [UNW_HPPA_GR + 19] = 0x04c, + [UNW_HPPA_GR + 20] = 0x050, [UNW_HPPA_GR + 21] = 0x054, + [UNW_HPPA_GR + 22] = 0x058, [UNW_HPPA_GR + 23] = 0x05c, + [UNW_HPPA_GR + 24] = 0x060, [UNW_HPPA_GR + 25] = 0x064, + [UNW_HPPA_GR + 26] = 0x068, [UNW_HPPA_GR + 27] = 0x06c, + [UNW_HPPA_GR + 28] = 0x070, [UNW_HPPA_GR + 29] = 0x074, + [UNW_HPPA_GR + 30] = 0x078, [UNW_HPPA_GR + 31] = 0x07c, + + [UNW_HPPA_FR + 0] = 0x080, [UNW_HPPA_FR + 1] = 0x088, + [UNW_HPPA_FR + 2] = 0x090, [UNW_HPPA_FR + 3] = 0x098, + [UNW_HPPA_FR + 4] = 0x0a0, [UNW_HPPA_FR + 5] = 0x0a8, + [UNW_HPPA_FR + 6] = 0x0b0, [UNW_HPPA_FR + 7] = 0x0b8, + [UNW_HPPA_FR + 8] = 0x0c0, [UNW_HPPA_FR + 9] = 0x0c8, + [UNW_HPPA_FR + 10] = 0x0d0, [UNW_HPPA_FR + 11] = 0x0d8, + [UNW_HPPA_FR + 12] = 0x0e0, [UNW_HPPA_FR + 13] = 0x0e8, + [UNW_HPPA_FR + 14] = 0x0f0, [UNW_HPPA_FR + 15] = 0x0f8, + [UNW_HPPA_FR + 16] = 0x100, [UNW_HPPA_FR + 17] = 0x108, + [UNW_HPPA_FR + 18] = 0x110, [UNW_HPPA_FR + 19] = 0x118, + [UNW_HPPA_FR + 20] = 0x120, [UNW_HPPA_FR + 21] = 0x128, + [UNW_HPPA_FR + 22] = 0x130, [UNW_HPPA_FR + 23] = 0x138, + [UNW_HPPA_FR + 24] = 0x140, [UNW_HPPA_FR + 25] = 0x148, + [UNW_HPPA_FR + 26] = 0x150, [UNW_HPPA_FR + 27] = 0x158, + [UNW_HPPA_FR + 28] = 0x160, [UNW_HPPA_FR + 29] = 0x168, + [UNW_HPPA_FR + 30] = 0x170, [UNW_HPPA_FR + 31] = 0x178, + + [UNW_HPPA_IP] = 0x1a8 /* IAOQ[0] */ +#elif defined(UNW_TARGET_X86) +#if defined __FreeBSD__ +#define UNW_R_OFF(R, r) \ + [UNW_X86_##R] = offsetof(gregset_t, r_##r), + UNW_R_OFF(EAX, eax) + UNW_R_OFF(EDX, edx) + UNW_R_OFF(ECX, ecx) + UNW_R_OFF(EBX, ebx) + UNW_R_OFF(ESI, esi) + UNW_R_OFF(EDI, edi) + UNW_R_OFF(EBP, ebp) + UNW_R_OFF(ESP, esp) + UNW_R_OFF(EIP, eip) +// UNW_R_OFF(CS, cs) +// UNW_R_OFF(EFLAGS, eflags) +// UNW_R_OFF(SS, ss) +#elif defined __linux__ + [UNW_X86_EAX] = 0x18, + [UNW_X86_EBX] = 0x00, + [UNW_X86_ECX] = 0x04, + [UNW_X86_EDX] = 0x08, + [UNW_X86_ESI] = 0x0c, + [UNW_X86_EDI] = 0x10, + [UNW_X86_EBP] = 0x14, + [UNW_X86_EIP] = 0x30, + [UNW_X86_ESP] = 0x3c +/* CS = 0x34, */ +/* DS = 0x1c, */ +/* ES = 0x20, */ +/* FS = 0x24, */ +/* GS = 0x28, */ +/* ORIG_EAX = 0x2c, */ +/* EFLAGS = 0x38, */ +/* SS = 0x40 */ +#else +#error Port me +#endif +#elif defined(UNW_TARGET_X86_64) +#if defined __FreeBSD__ +#define UNW_R_OFF(R, r) \ + [UNW_X86_64_##R] = offsetof(gregset_t, r_##r), + UNW_R_OFF(RAX, rax) + UNW_R_OFF(RDX, rdx) + UNW_R_OFF(RCX, rcx) + UNW_R_OFF(RBX, rbx) + UNW_R_OFF(RSI, rsi) + UNW_R_OFF(RDI, rdi) + UNW_R_OFF(RBP, rbp) + UNW_R_OFF(RSP, rsp) + UNW_R_OFF(R8, r8) + UNW_R_OFF(R9, r9) + UNW_R_OFF(R10, r10) + UNW_R_OFF(R11, r11) + UNW_R_OFF(R12, r12) + UNW_R_OFF(R13, r13) + UNW_R_OFF(R14, r14) + UNW_R_OFF(R15, r15) + UNW_R_OFF(RIP, rip) +// UNW_R_OFF(CS, cs) +// UNW_R_OFF(EFLAGS, rflags) +// UNW_R_OFF(SS, ss) +#undef UNW_R_OFF +#elif defined __linux__ + [UNW_X86_64_RAX] = 0x50, + [UNW_X86_64_RDX] = 0x60, + [UNW_X86_64_RCX] = 0x58, + [UNW_X86_64_RBX] = 0x28, + [UNW_X86_64_RSI] = 0x68, + [UNW_X86_64_RDI] = 0x70, + [UNW_X86_64_RBP] = 0x20, + [UNW_X86_64_RSP] = 0x98, + [UNW_X86_64_R8] = 0x48, + [UNW_X86_64_R9] = 0x40, + [UNW_X86_64_R10] = 0x38, + [UNW_X86_64_R11] = 0x30, + [UNW_X86_64_R12] = 0x18, + [UNW_X86_64_R13] = 0x10, + [UNW_X86_64_R14] = 0x08, + [UNW_X86_64_R15] = 0x00, + [UNW_X86_64_RIP] = 0x80 +// [UNW_X86_64_CS] = 0x88, +// [UNW_X86_64_EFLAGS] = 0x90, +// [UNW_X86_64_RSP] = 0x98, +// [UNW_X86_64_SS] = 0xa0 +#else +#error Port me +#endif +#elif defined(UNW_TARGET_PPC32) || defined(UNW_TARGET_PPC64) + +#define UNW_REG_SLOT_SIZE sizeof(unsigned long) +#define UNW_PPC_R(v) ((v) * UNW_REG_SLOT_SIZE) +#define UNW_PPC_PT(p) UNW_PPC_R(PT_##p) + +#define UNW_FP_OFF(b, i) \ + [UNW_PPC##b##_F##i] = UNW_PPC_R(PT_FPR0 + i * 8/UNW_REG_SLOT_SIZE) + +#define UNW_R_OFF(b, i) \ + [UNW_PPC##b##_R##i] = UNW_PPC_R(PT_R##i) + +#define UNW_PPC_REGS(b) \ + UNW_R_OFF(b, 0), \ + UNW_R_OFF(b, 1), \ + UNW_R_OFF(b, 2), \ + UNW_R_OFF(b, 3), \ + UNW_R_OFF(b, 4), \ + UNW_R_OFF(b, 5), \ + UNW_R_OFF(b, 6), \ + UNW_R_OFF(b, 7), \ + UNW_R_OFF(b, 8), \ + UNW_R_OFF(b, 9), \ + UNW_R_OFF(b, 10), \ + UNW_R_OFF(b, 11), \ + UNW_R_OFF(b, 12), \ + UNW_R_OFF(b, 13), \ + UNW_R_OFF(b, 14), \ + UNW_R_OFF(b, 15), \ + UNW_R_OFF(b, 16), \ + UNW_R_OFF(b, 17), \ + UNW_R_OFF(b, 18), \ + UNW_R_OFF(b, 19), \ + UNW_R_OFF(b, 20), \ + UNW_R_OFF(b, 21), \ + UNW_R_OFF(b, 22), \ + UNW_R_OFF(b, 23), \ + UNW_R_OFF(b, 24), \ + UNW_R_OFF(b, 25), \ + UNW_R_OFF(b, 26), \ + UNW_R_OFF(b, 27), \ + UNW_R_OFF(b, 28), \ + UNW_R_OFF(b, 29), \ + UNW_R_OFF(b, 30), \ + UNW_R_OFF(b, 31), \ + \ + [UNW_PPC##b##_CTR] = UNW_PPC_PT(CTR), \ + [UNW_PPC##b##_XER] = UNW_PPC_PT(XER), \ + [UNW_PPC##b##_LR] = UNW_PPC_PT(LNK), \ + \ + UNW_FP_OFF(b, 0), \ + UNW_FP_OFF(b, 1), \ + UNW_FP_OFF(b, 2), \ + UNW_FP_OFF(b, 3), \ + UNW_FP_OFF(b, 4), \ + UNW_FP_OFF(b, 5), \ + UNW_FP_OFF(b, 6), \ + UNW_FP_OFF(b, 7), \ + UNW_FP_OFF(b, 8), \ + UNW_FP_OFF(b, 9), \ + UNW_FP_OFF(b, 10), \ + UNW_FP_OFF(b, 11), \ + UNW_FP_OFF(b, 12), \ + UNW_FP_OFF(b, 13), \ + UNW_FP_OFF(b, 14), \ + UNW_FP_OFF(b, 15), \ + UNW_FP_OFF(b, 16), \ + UNW_FP_OFF(b, 17), \ + UNW_FP_OFF(b, 18), \ + UNW_FP_OFF(b, 19), \ + UNW_FP_OFF(b, 20), \ + UNW_FP_OFF(b, 21), \ + UNW_FP_OFF(b, 22), \ + UNW_FP_OFF(b, 23), \ + UNW_FP_OFF(b, 24), \ + UNW_FP_OFF(b, 25), \ + UNW_FP_OFF(b, 26), \ + UNW_FP_OFF(b, 27), \ + UNW_FP_OFF(b, 28), \ + UNW_FP_OFF(b, 29), \ + UNW_FP_OFF(b, 30), \ + UNW_FP_OFF(b, 31) + +#define UNW_PPC32_REGS \ + [UNW_PPC32_FPSCR] = UNW_PPC_PT(FPSCR), \ + [UNW_PPC32_CCR] = UNW_PPC_PT(CCR) + +#define UNW_VR_OFF(i) \ + [UNW_PPC64_V##i] = UNW_PPC_R(PT_VR0 + i * 2) + +#define UNW_PPC64_REGS \ + [UNW_PPC64_NIP] = UNW_PPC_PT(NIP), \ + [UNW_PPC64_FRAME_POINTER] = -1, \ + [UNW_PPC64_ARG_POINTER] = -1, \ + [UNW_PPC64_CR0] = -1, \ + [UNW_PPC64_CR1] = -1, \ + [UNW_PPC64_CR2] = -1, \ + [UNW_PPC64_CR3] = -1, \ + [UNW_PPC64_CR4] = -1, \ + [UNW_PPC64_CR5] = -1, \ + [UNW_PPC64_CR6] = -1, \ + [UNW_PPC64_CR7] = -1, \ + [UNW_PPC64_VRSAVE] = UNW_PPC_PT(VRSAVE), \ + [UNW_PPC64_VSCR] = UNW_PPC_PT(VSCR), \ + [UNW_PPC64_SPE_ACC] = -1, \ + [UNW_PPC64_SPEFSCR] = -1, \ + UNW_VR_OFF(0), \ + UNW_VR_OFF(1), \ + UNW_VR_OFF(2), \ + UNW_VR_OFF(3), \ + UNW_VR_OFF(4), \ + UNW_VR_OFF(5), \ + UNW_VR_OFF(6), \ + UNW_VR_OFF(7), \ + UNW_VR_OFF(8), \ + UNW_VR_OFF(9), \ + UNW_VR_OFF(10), \ + UNW_VR_OFF(11), \ + UNW_VR_OFF(12), \ + UNW_VR_OFF(13), \ + UNW_VR_OFF(14), \ + UNW_VR_OFF(15), \ + UNW_VR_OFF(16), \ + UNW_VR_OFF(17), \ + UNW_VR_OFF(18), \ + UNW_VR_OFF(19), \ + UNW_VR_OFF(20), \ + UNW_VR_OFF(21), \ + UNW_VR_OFF(22), \ + UNW_VR_OFF(23), \ + UNW_VR_OFF(24), \ + UNW_VR_OFF(25), \ + UNW_VR_OFF(26), \ + UNW_VR_OFF(27), \ + UNW_VR_OFF(28), \ + UNW_VR_OFF(29), \ + UNW_VR_OFF(30), \ + UNW_VR_OFF(31) + +#if defined(UNW_TARGET_PPC32) + UNW_PPC_REGS(32), + UNW_PPC32_REGS, +#else + UNW_PPC_REGS(64), + UNW_PPC64_REGS, +#endif + +#elif defined(UNW_TARGET_ARM) +#if defined(__linux__) || defined(__FreeBSD__) + [UNW_ARM_R0] = 0x00, + [UNW_ARM_R1] = 0x04, + [UNW_ARM_R2] = 0x08, + [UNW_ARM_R3] = 0x0c, + [UNW_ARM_R4] = 0x10, + [UNW_ARM_R5] = 0x14, + [UNW_ARM_R6] = 0x18, + [UNW_ARM_R7] = 0x1c, + [UNW_ARM_R8] = 0x20, + [UNW_ARM_R9] = 0x24, + [UNW_ARM_R10] = 0x28, + [UNW_ARM_R11] = 0x2c, + [UNW_ARM_R12] = 0x30, + [UNW_ARM_R13] = 0x34, + [UNW_ARM_R14] = 0x38, + [UNW_ARM_R15] = 0x3c, +#else +#error Fix me +#endif +#elif defined(UNW_TARGET_MIPS) + [UNW_MIPS_R0] = 0, + [UNW_MIPS_R1] = 1, + [UNW_MIPS_R2] = 2, + [UNW_MIPS_R3] = 3, + [UNW_MIPS_R4] = 4, + [UNW_MIPS_R5] = 5, + [UNW_MIPS_R6] = 6, + [UNW_MIPS_R7] = 7, + [UNW_MIPS_R8] = 8, + [UNW_MIPS_R9] = 9, + [UNW_MIPS_R10] = 10, + [UNW_MIPS_R11] = 11, + [UNW_MIPS_R12] = 12, + [UNW_MIPS_R13] = 13, + [UNW_MIPS_R14] = 14, + [UNW_MIPS_R15] = 15, + [UNW_MIPS_R16] = 16, + [UNW_MIPS_R17] = 17, + [UNW_MIPS_R18] = 18, + [UNW_MIPS_R19] = 19, + [UNW_MIPS_R20] = 20, + [UNW_MIPS_R21] = 21, + [UNW_MIPS_R22] = 22, + [UNW_MIPS_R23] = 23, + [UNW_MIPS_R24] = 24, + [UNW_MIPS_R25] = 25, + [UNW_MIPS_R26] = 26, + [UNW_MIPS_R27] = 27, + [UNW_MIPS_R28] = 28, + [UNW_MIPS_R29] = 29, + [UNW_MIPS_R30] = 30, + [UNW_MIPS_R31] = 31, + [UNW_MIPS_PC] = 64, +#elif defined(UNW_TARGET_SH) +#elif defined(UNW_TARGET_AARCH64) + [UNW_AARCH64_X0] = 0x00, + [UNW_AARCH64_X1] = 0x08, + [UNW_AARCH64_X2] = 0x10, + [UNW_AARCH64_X3] = 0x18, + [UNW_AARCH64_X4] = 0x20, + [UNW_AARCH64_X5] = 0x28, + [UNW_AARCH64_X6] = 0x30, + [UNW_AARCH64_X7] = 0x38, + [UNW_AARCH64_X8] = 0x40, + [UNW_AARCH64_X9] = 0x48, + [UNW_AARCH64_X10] = 0x50, + [UNW_AARCH64_X11] = 0x58, + [UNW_AARCH64_X12] = 0x60, + [UNW_AARCH64_X13] = 0x68, + [UNW_AARCH64_X14] = 0x70, + [UNW_AARCH64_X15] = 0x78, + [UNW_AARCH64_X16] = 0x80, + [UNW_AARCH64_X17] = 0x88, + [UNW_AARCH64_X18] = 0x90, + [UNW_AARCH64_X19] = 0x98, + [UNW_AARCH64_X20] = 0xa0, + [UNW_AARCH64_X21] = 0xa8, + [UNW_AARCH64_X22] = 0xb0, + [UNW_AARCH64_X23] = 0xb8, + [UNW_AARCH64_X24] = 0xc0, + [UNW_AARCH64_X25] = 0xc8, + [UNW_AARCH64_X26] = 0xd0, + [UNW_AARCH64_X27] = 0xd8, + [UNW_AARCH64_X28] = 0xe0, + [UNW_AARCH64_X29] = 0xe8, + [UNW_AARCH64_X30] = 0xf0, + [UNW_AARCH64_SP] = 0xf8, + [UNW_AARCH64_PC] = 0x100, + [UNW_AARCH64_PSTATE] = 0x108 +#elif defined(UNW_TARGET_TILEGX) + [UNW_TILEGX_R0] = 0x00, + [UNW_TILEGX_R1] = 0x08, + [UNW_TILEGX_R2] = 0x10, + [UNW_TILEGX_R3] = 0x08, + [UNW_TILEGX_R4] = 0x20, + [UNW_TILEGX_R5] = 0x28, + [UNW_TILEGX_R6] = 0x30, + [UNW_TILEGX_R7] = 0x38, + [UNW_TILEGX_R8] = 0x40, + [UNW_TILEGX_R9] = 0x48, + [UNW_TILEGX_R10] = 0x50, + [UNW_TILEGX_R11] = 0x58, + [UNW_TILEGX_R12] = 0x60, + [UNW_TILEGX_R13] = 0x68, + [UNW_TILEGX_R14] = 0x70, + [UNW_TILEGX_R15] = 0x78, + [UNW_TILEGX_R16] = 0x80, + [UNW_TILEGX_R17] = 0x88, + [UNW_TILEGX_R18] = 0x90, + [UNW_TILEGX_R19] = 0x98, + [UNW_TILEGX_R20] = 0xa0, + [UNW_TILEGX_R21] = 0xa8, + [UNW_TILEGX_R22] = 0xb0, + [UNW_TILEGX_R23] = 0xb8, + [UNW_TILEGX_R24] = 0xc0, + [UNW_TILEGX_R25] = 0xc8, + [UNW_TILEGX_R26] = 0xd0, + [UNW_TILEGX_R27] = 0xd8, + [UNW_TILEGX_R28] = 0xe0, + [UNW_TILEGX_R29] = 0xe8, + [UNW_TILEGX_R30] = 0xf0, + [UNW_TILEGX_R31] = 0xf8, + [UNW_TILEGX_R32] = 0x100, + [UNW_TILEGX_R33] = 0x108, + [UNW_TILEGX_R34] = 0x110, + [UNW_TILEGX_R35] = 0x118, + [UNW_TILEGX_R36] = 0x120, + [UNW_TILEGX_R37] = 0x128, + [UNW_TILEGX_R38] = 0x130, + [UNW_TILEGX_R39] = 0x138, + [UNW_TILEGX_R40] = 0x140, + [UNW_TILEGX_R41] = 0x148, + [UNW_TILEGX_R42] = 0x150, + [UNW_TILEGX_R43] = 0x158, + [UNW_TILEGX_R44] = 0x160, + [UNW_TILEGX_R45] = 0x168, + [UNW_TILEGX_R46] = 0x170, + [UNW_TILEGX_R47] = 0x178, + [UNW_TILEGX_R48] = 0x180, + [UNW_TILEGX_R49] = 0x188, + [UNW_TILEGX_R50] = 0x190, + [UNW_TILEGX_R51] = 0x198, + [UNW_TILEGX_R52] = 0x1a0, + [UNW_TILEGX_R53] = 0x1a8, + [UNW_TILEGX_R54] = 0x1b0, + [UNW_TILEGX_R55] = 0x1b8, + [UNW_TILEGX_PC] = 0x1a0 +#else +# error Fix me. +#endif + }; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_resume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_resume.c new file mode 100644 index 0000000..d70a0d4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/_UPT_resume.c @@ -0,0 +1,40 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +int +_UPT_resume (unw_addr_space_t as, unw_cursor_t *c, void *arg) +{ + struct UPT_info *ui = arg; + +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#elif HAVE_DECL_PTRACE_CONT + return ptrace (PTRACE_CONT, ui->pid, 0, 0); +#elif HAVE_DECL_PT_CONTINUE + return ptrace(PT_CONTINUE, ui->pid, (caddr_t)1, 0); +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/libunwind-ptrace.pc.in b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/libunwind-ptrace.pc.in new file mode 100644 index 0000000..673004b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/ptrace/libunwind-ptrace.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libunwind-ptrace +Description: libunwind ptrace library +Version: @VERSION@ +Requires: libunwind-generic libunwind +Libs: -L${libdir} -lunwind-ptrace +Cflags: -I${includedir} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/libunwind-setjmp.pc.in b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/libunwind-setjmp.pc.in new file mode 100644 index 0000000..7b71126 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/libunwind-setjmp.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libunwind-setjmp +Description: libunwind setjmp library +Version: @VERSION@ +Requires: libunwind +Libs: -L${libdir} -lunwind-setjmp +Cflags: -I${includedir} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/longjmp.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/longjmp.c new file mode 100644 index 0000000..8295a9b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/longjmp.c @@ -0,0 +1,115 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#define UNW_LOCAL_ONLY + +#undef _FORTIFY_SOURCE +#include +#include +#include +#include +#include + +#include "jmpbuf.h" +#include "setjmp_i.h" + +#if defined(__GLIBC__) +#if __GLIBC_PREREQ(2, 4) + +/* Starting with glibc-2.4, {sig,}setjmp in GLIBC obfuscates the + register values in jmp_buf by XORing them with a "random" + canary value. + + This makes it impossible to implement longjmp, as we + can never match wp[JB_SP], unless we decode the canary first. + + Doing so is possible, but doesn't appear to be worth the trouble, + so we simply defer to glibc longjmp here. */ +#define _longjmp __nonworking__longjmp +#define longjmp __nonworking_longjmp +static void _longjmp (jmp_buf env, int val); +static void longjmp (jmp_buf env, int val); +#endif +#endif /* __GLIBC__ */ + +void +_longjmp (jmp_buf env, int val) +{ + extern int _UI_longjmp_cont; + unw_context_t uc; + unw_cursor_t c; + unw_word_t sp; + unw_word_t *wp = (unw_word_t *) env; + + if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0) + abort (); + + do + { + if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0) + abort (); +#ifdef __FreeBSD__ + if (sp != wp[JB_SP] + sizeof(unw_word_t)) +#else + if (sp != wp[JB_SP]) +#endif + continue; + + if (!bsp_match (&c, wp)) + continue; + + /* found the right frame: */ + + assert (UNW_NUM_EH_REGS >= 2); + + if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0 + || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0 + || unw_set_reg (&c, UNW_REG_IP, + (unw_word_t) (uintptr_t) &_UI_longjmp_cont)) + abort (); + + unw_resume (&c); + + abort (); + } + while (unw_step (&c) > 0); + + abort (); +} + +#ifdef __GNUC__ +#define STRINGIFY1(x) #x +#define STRINGIFY(x) STRINGIFY1(x) +void longjmp (jmp_buf env, int val) + __attribute__ ((alias (STRINGIFY(_longjmp)))); +#else + +void +longjmp (jmp_buf env, int val) +{ + _longjmp (env, val); +} + +#endif /* __GNUC__ */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/setjmp.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/setjmp.c new file mode 100644 index 0000000..bec9fc7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/setjmp.c @@ -0,0 +1,49 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#include "jmpbuf.h" + +/* Why use K&R syntax here? setjmp() is often a macro and that + expands into a call to, say, __setjmp() and we need to define the + libunwind-version of setjmp() with the name of the actual function. + Using K&R syntax lets us keep the setjmp() macro while keeping the + syntax valid... This trick works provided setjmp() doesn't do + anything other than a function call. */ + +int +setjmp (env) + jmp_buf env; +{ + void **wp = (void **) env; + + /* this should work on most platforms, but may not be + performance-optimal; check the code! */ + wp[JB_SP] = __builtin_frame_address (0); + wp[JB_RP] = (void *) __builtin_return_address (0); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/siglongjmp.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/siglongjmp.c new file mode 100644 index 0000000..0e286f6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/siglongjmp.c @@ -0,0 +1,127 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#define UNW_LOCAL_ONLY + +#include + +#include "libunwind_i.h" +#include "jmpbuf.h" +#include "setjmp_i.h" + +#if !defined(_NSIG) && defined(_SIG_MAXSIG) +# define _NSIG (_SIG_MAXSIG - 1) +#endif + +#if defined(__GLIBC__) +#if __GLIBC_PREREQ(2, 4) + +/* Starting with glibc-2.4, {sig,}setjmp in GLIBC obfuscates the + register values in jmp_buf by XORing them with a "random" + canary value. + + This makes it impossible to implement longjmp, as we + can never match wp[JB_SP], unless we decode the canary first. + + Doing so is possible, but doesn't appear to be worth the trouble, + so we simply defer to glibc siglongjmp here. */ + +#define siglongjmp __nonworking_siglongjmp +static void siglongjmp (sigjmp_buf env, int val) UNUSED; +#endif +#endif /* __GLIBC_PREREQ */ + +void +siglongjmp (sigjmp_buf env, int val) +{ + unw_word_t *wp = (unw_word_t *) env; + extern int _UI_siglongjmp_cont; + extern int _UI_longjmp_cont; + unw_context_t uc; + unw_cursor_t c; + unw_word_t sp; + int *cont; + + if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0) + abort (); + + do + { + if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0) + abort (); +#ifdef __FreeBSD__ + if (sp != wp[JB_SP] + sizeof(unw_word_t)) +#else + if (sp != wp[JB_SP]) +#endif + continue; + + if (!bsp_match (&c, wp)) + continue; + + /* found the right frame: */ + + /* default to resuming without restoring signal-mask */ + cont = &_UI_longjmp_cont; + + /* Order of evaluation is important here: if unw_resume() + restores signal mask, we must set it up appropriately, even + if wp[JB_MASK_SAVED] is FALSE. */ + if (!resume_restores_sigmask (&c, wp) && wp[JB_MASK_SAVED]) + { + /* sigmask was saved */ +#if defined(__linux__) + if (UNW_NUM_EH_REGS < 4 || _NSIG > 16 * sizeof (unw_word_t)) + /* signal mask doesn't fit into EH arguments and we can't + put it on the stack without overwriting something + else... */ + abort (); + else + if (unw_set_reg (&c, UNW_REG_EH + 2, wp[JB_MASK]) < 0 + || (_NSIG > 8 * sizeof (unw_word_t) + && unw_set_reg (&c, UNW_REG_EH + 3, wp[JB_MASK + 1]) < 0)) + abort (); +#elif defined(__FreeBSD__) + if (unw_set_reg (&c, UNW_REG_EH + 2, &wp[JB_MASK]) < 0) + abort(); +#else +#error Port me +#endif + cont = &_UI_siglongjmp_cont; + } + + if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0 + || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0 + || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) (uintptr_t) cont)) + abort (); + + unw_resume (&c); + + abort (); + } + while (unw_step (&c) > 0); + + abort (); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/sigsetjmp.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/sigsetjmp.c new file mode 100644 index 0000000..f84935d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/setjmp/sigsetjmp.c @@ -0,0 +1,50 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include + +#include "jmpbuf.h" + +int +sigsetjmp (sigjmp_buf env, int savemask) +{ + unw_word_t *wp = (unw_word_t *) env; + + /* This should work on most platforms, but may not be + performance-optimal; check the code! */ + + wp[JB_SP] = (unw_word_t) __builtin_frame_address (0); + wp[JB_RP] = (unw_word_t) __builtin_return_address (0); + wp[JB_MASK_SAVED] = savemask; + + /* Note: we assume here that "wp" has same or better alignment as + sigset_t. */ + if (savemask + && sigprocmask (SIG_BLOCK, NULL, (sigset_t *) (wp + JB_MASK)) < 0) + abort (); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gapply_reg_state.c new file mode 100644 index 0000000..82f056d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gapply_reg_state.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_apply_reg_state (unw_cursor_t *cursor, + void *reg_states_data) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gcreate_addr_space.c new file mode 100644 index 0000000..6ca3a38 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gcreate_addr_space.c @@ -0,0 +1,59 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#include "unwind_i.h" + +unw_addr_space_t +unw_create_addr_space (unw_accessors_t *a, int byte_order) +{ +#ifdef UNW_LOCAL_ONLY + return NULL; +#else + unw_addr_space_t as; + + /* SH supports little-endian and big-endian. */ + if (byte_order != 0 && byte_order != __LITTLE_ENDIAN + && byte_order != __BIG_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); + if (!as) + return NULL; + + memset (as, 0, sizeof (*as)); + + as->acc = *a; + + /* Default to little-endian for SH. */ + if (byte_order == 0 || byte_order == __LITTLE_ENDIAN) + as->big_endian = 0; + else + as->big_endian = 1; + + return as; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gget_proc_info.c new file mode 100644 index 0000000..c363d24 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gget_proc_info.c @@ -0,0 +1,39 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + ret = dwarf_make_proc_info (&c->dwarf); + if (ret < 0) + return ret; + + *pi = c->dwarf.pi; + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gget_save_loc.c new file mode 100644 index 0000000..24d9f63 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gget_save_loc.c @@ -0,0 +1,83 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) +{ + struct cursor *c = (struct cursor *) cursor; + dwarf_loc_t loc; + + switch (reg) + { + case UNW_SH_R0: + case UNW_SH_R1: + case UNW_SH_R2: + case UNW_SH_R3: + case UNW_SH_R4: + case UNW_SH_R5: + case UNW_SH_R6: + case UNW_SH_R7: + case UNW_SH_R8: + case UNW_SH_R9: + case UNW_SH_R10: + case UNW_SH_R11: + case UNW_SH_R12: + case UNW_SH_R13: + case UNW_SH_R14: + case UNW_SH_R15: + case UNW_SH_PC: + case UNW_SH_PR: + loc = c->dwarf.loc[reg]; + break; + + default: + loc = DWARF_NULL_LOC; /* default to "not saved" */ + break; + } + + memset (sloc, 0, sizeof (*sloc)); + + if (DWARF_IS_NULL_LOC (loc)) + { + sloc->type = UNW_SLT_NONE; + return 0; + } + +#if !defined(UNW_LOCAL_ONLY) + if (DWARF_IS_REG_LOC (loc)) + { + sloc->type = UNW_SLT_REG; + sloc->u.regnum = DWARF_GET_LOC (loc); + } + else +#endif + { + sloc->type = UNW_SLT_MEMORY; + sloc->u.addr = DWARF_GET_LOC (loc); + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gglobal.c new file mode 100644 index 0000000..ed27333 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gglobal.c @@ -0,0 +1,56 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "dwarf_i.h" + +HIDDEN define_lock (sh_lock); +HIDDEN int tdep_init_done; + +HIDDEN void +tdep_init (void) +{ + intrmask_t saved_mask; + + sigfillset (&unwi_full_mask); + + lock_acquire (&sh_lock, saved_mask); + { + if (tdep_init_done) + /* another thread else beat us to it... */ + goto out; + + mi_init (); + + dwarf_init (); + +#ifndef UNW_REMOTE_ONLY + sh_local_addr_space_init (); +#endif + tdep_init_done = 1; /* signal that we're initialized... */ + } + out: + lock_release (&sh_lock, saved_mask); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Ginit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Ginit.c new file mode 100644 index 0000000..52988a7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Ginit.c @@ -0,0 +1,186 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#include "unwind_i.h" + +#ifdef UNW_REMOTE_ONLY + +/* unw_local_addr_space is a NULL pointer in this case. */ +unw_addr_space_t unw_local_addr_space; + +#else /* !UNW_REMOTE_ONLY */ + +static struct unw_addr_space local_addr_space; + +unw_addr_space_t unw_local_addr_space = &local_addr_space; + +static inline void * +uc_addr (ucontext_t *uc, int reg) +{ + if (reg >= UNW_SH_R0 && reg <= UNW_SH_PR) + return &uc->uc_mcontext.gregs[reg]; + else + return NULL; +} + +# ifdef UNW_LOCAL_ONLY + +HIDDEN void * +tdep_uc_addr (ucontext_t *uc, int reg) +{ + return uc_addr (uc, reg); +} + +# endif /* UNW_LOCAL_ONLY */ + +HIDDEN unw_dyn_info_list_t _U_dyn_info_list; + +/* XXX fix me: there is currently no way to locate the dyn-info list + by a remote unwinder. On ia64, this is done via a special + unwind-table entry. Perhaps something similar can be done with + DWARF2 unwind info. */ + +static void +put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) +{ + /* it's a no-op */ +} + +static int +get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, + void *arg) +{ + *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; + return 0; +} + +static int +access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, + void *arg) +{ + if (write) + { + Debug (16, "mem[%x] <- %x\n", addr, *val); + *(unw_word_t *) addr = *val; + } + else + { + *val = *(unw_word_t *) addr; + Debug (16, "mem[%x] -> %x\n", addr, *val); + } + return 0; +} + +static int +access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, + void *arg) +{ + unw_word_t *addr; + ucontext_t *uc = arg; + + if (unw_is_fpreg (reg)) + goto badreg; + + if (!(addr = uc_addr (uc, reg))) + goto badreg; + + if (write) + { + *(unw_word_t *) addr = *val; + Debug (12, "%s <- %x\n", unw_regname (reg), *val); + } + else + { + *val = *(unw_word_t *) addr; + Debug (12, "%s -> %x\n", unw_regname (reg), *val); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} + +static int +access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + ucontext_t *uc = arg; + unw_fpreg_t *addr; + + if (!unw_is_fpreg (reg)) + goto badreg; + + if (!(addr = uc_addr (uc, reg))) + goto badreg; + + if (write) + { + Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg), + ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); + *(unw_fpreg_t *) addr = *val; + } + else + { + *val = *(unw_fpreg_t *) addr; + Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg), + ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + /* attempt to access a non-preserved register */ + return -UNW_EBADREG; +} + +static int +get_static_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, + void *arg) +{ + return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp); +} + +HIDDEN void +sh_local_addr_space_init (void) +{ + memset (&local_addr_space, 0, sizeof (local_addr_space)); + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; + local_addr_space.acc.find_proc_info = dwarf_find_proc_info; + local_addr_space.acc.put_unwind_info = put_unwind_info; + local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; + local_addr_space.acc.access_mem = access_mem; + local_addr_space.acc.access_reg = access_reg; + local_addr_space.acc.access_fpreg = access_fpreg; + local_addr_space.acc.resume = sh_local_resume; + local_addr_space.acc.get_proc_name = get_static_proc_name; + unw_flush_cache (&local_addr_space, 0, 0); +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Ginit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Ginit_local.c new file mode 100644 index 0000000..99ddb36 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Ginit_local.c @@ -0,0 +1,78 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright 2011 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "init.h" + +#ifdef UNW_REMOTE_ONLY + +int +unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) +{ + return -UNW_EINVAL; +} + +#else /* !UNW_REMOTE_ONLY */ + +static int +unw_init_local (unw_cursor_t *cursor, unw_context_t *uc, unsigned use_prev_instr) +{ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = unw_local_addr_space; + c->dwarf.as_arg = uc; + + return common_init (c, use_prev_instr); +} + +int +unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) +{ + return unw_init_local_common(cursor, uc, 1); +} + +int +unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) +{ + if (!flag) + { + return unw_init_local_common(cursor, uc, 1); + } + else if (flag == UNW_INIT_SIGNAL_FRAME) + { + return unw_init_local_common(cursor, uc, 0); + } + else + { + return -UNW_EINVAL; + } +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Ginit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Ginit_remote.c new file mode 100644 index 0000000..9b8ba5b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Ginit_remote.c @@ -0,0 +1,45 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "init.h" +#include "unwind_i.h" + +int +unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) +{ +#ifdef UNW_LOCAL_ONLY + return -UNW_EINVAL; +#else /* !UNW_LOCAL_ONLY */ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = as; + c->dwarf.as_arg = as_arg; + return common_init (c, 0); +#endif /* !UNW_LOCAL_ONLY */ +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gis_signal_frame.c new file mode 100644 index 0000000..4481fe1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gis_signal_frame.c @@ -0,0 +1,119 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +/* Disassembly of the Linux VDSO sigreturn functions: + +00000000 <__kernel_sigreturn>: + 0: 05 93 mov.w e <__kernel_sigreturn+0xe>,r3 ! 77 + 2: 10 c3 trapa #16 + 4: 0b 20 or r0,r0 + 6: 0b 20 or r0,r0 + 8: 0b 20 or r0,r0 + a: 0b 20 or r0,r0 + c: 0b 20 or r0,r0 + e: 77 00 .word 0x0077 + 10: 09 00 nop + 12: 09 00 nop + 14: 09 00 nop + 16: 09 00 nop + 18: 09 00 nop + 1a: 09 00 nop + 1c: 09 00 nop + 1e: 09 00 nop + +00000020 <__kernel_rt_sigreturn>: + 20: 05 93 mov.w 2e <__kernel_rt_sigreturn+0xe>,r3 ! ad + 22: 10 c3 trapa #16 + 24: 0b 20 or r0,r0 + 26: 0b 20 or r0,r0 + 28: 0b 20 or r0,r0 + 2a: 0b 20 or r0,r0 + 2c: 0b 20 or r0,r0 + 2e: ad 00 mov.w @(r0,r10),r0 + 30: 09 00 nop + 32: 09 00 nop + 34: 09 00 nop + 36: 09 00 nop + 38: 09 00 nop + 3a: 09 00 nop + 3c: 09 00 nop + 3e: 09 00 nop +*/ + +int +unw_is_signal_frame (unw_cursor_t *cursor) +{ +#ifdef __linux__ + struct cursor *c = (struct cursor *) cursor; + unw_word_t w0, ip; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + int ret; + + as = c->dwarf.as; + a = unw_get_accessors_int (as); + arg = c->dwarf.as_arg; + + ip = c->dwarf.ip; + + ret = (*a->access_mem) (as, ip, &w0, 0, arg); + if (ret < 0) + return ret; + + if (w0 != 0xc3109305) + return 0; + + ret = (*a->access_mem) (as, ip+4, &w0, 0, arg); + if (ret < 0) + return ret; + + if (w0 != 0x200b200b) + return 0; + + ret = (*a->access_mem) (as, ip+8, &w0, 0, arg); + if (ret < 0) + return ret; + + if (w0 != 0x200b200b) + return 0; + + ret = (*a->access_mem) (as, ip+12, &w0, 0, arg); + if (ret < 0) + return ret; + + if (w0 == 0x0077200b) + return 1; /* non-RT */ + else if (w0 == 0x00ad200b) + return 2; /* RT */ + + /* does not look like a signal frame */ + return 0; + +#else + return -UNW_ENOINFO; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Greg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Greg_states_iterate.c new file mode 100644 index 0000000..a17dc1b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Greg_states_iterate.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_reg_states_iterate (unw_cursor_t *cursor, + unw_reg_states_callback cb, void *token) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_reg_states_iterate (&c->dwarf, cb, token); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gregs.c new file mode 100644 index 0000000..7d8e8e9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gregs.c @@ -0,0 +1,81 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +HIDDEN int +tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + int write) +{ + dwarf_loc_t loc = DWARF_NULL_LOC; + + switch (reg) + { + case UNW_SH_PC: + if (write) + c->dwarf.ip = *valp; /* update the IP cache */ + case UNW_SH_R0: + case UNW_SH_R1: + case UNW_SH_R2: + case UNW_SH_R3: + case UNW_SH_R4: + case UNW_SH_R5: + case UNW_SH_R6: + case UNW_SH_R7: + case UNW_SH_R8: + case UNW_SH_R9: + case UNW_SH_R10: + case UNW_SH_R11: + case UNW_SH_R12: + case UNW_SH_R13: + case UNW_SH_R14: + case UNW_SH_PR: + loc = c->dwarf.loc[reg]; + break; + + case UNW_SH_R15: + if (write) + return -UNW_EREADONLYREG; + *valp = c->dwarf.cfa; + return 0; + + default: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; + } + + if (write) + return dwarf_put (&c->dwarf, loc, *valp); + else + return dwarf_get (&c->dwarf, loc, valp); +} + +HIDDEN int +tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, + int write) +{ + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gresume.c new file mode 100644 index 0000000..a263c92 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gresume.c @@ -0,0 +1,165 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright 2011 Linaro Limited + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "offsets.h" + +#ifndef UNW_REMOTE_ONLY + +HIDDEN inline int +sh_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ +#ifdef __linux__ + struct cursor *c = (struct cursor *) cursor; + unw_tdep_context_t *uc = c->dwarf.as_arg; + + if (c->sigcontext_format == SH_SCF_NONE) + { + /* Since there are no signals involved here we restore the non scratch + registers only. */ + unsigned long regs[8]; + regs[0] = uc->uc_mcontext.gregs[8]; + regs[1] = uc->uc_mcontext.gregs[9]; + regs[2] = uc->uc_mcontext.gregs[10]; + regs[3] = uc->uc_mcontext.gregs[11]; + regs[4] = uc->uc_mcontext.gregs[12]; + regs[5] = uc->uc_mcontext.gregs[13]; + regs[6] = uc->uc_mcontext.gregs[14]; + regs[7] = uc->uc_mcontext.gregs[15]; + unsigned long pc = uc->uc_mcontext.pr; + + struct regs_overlay { + char x[sizeof(regs)]; + }; + + asm volatile ( + "mov.l @%0+, r8\n" + "mov.l @%0+, r9\n" + "mov.l @%0+, r10\n" + "mov.l @%0+, r11\n" + "mov.l @%0+, r12\n" + "mov.l @%0+, r13\n" + "mov.l @%0+, r14\n" + "mov.l @%0, r15\n" + "lds %1, pr\n" + "rts\n" + "nop\n" + : + : "r" (regs), + "r" (pc), + "m" (*(struct regs_overlay *)regs) + ); + } + else + { + /* In case a signal frame is involved, we're using its trampoline which + calls sigreturn. */ + struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; + sc->sc_regs[0] = uc->uc_mcontext.gregs[0]; + sc->sc_regs[1] = uc->uc_mcontext.gregs[1]; + sc->sc_regs[2] = uc->uc_mcontext.gregs[2]; + sc->sc_regs[3] = uc->uc_mcontext.gregs[3]; + sc->sc_regs[4] = uc->uc_mcontext.gregs[4]; + sc->sc_regs[5] = uc->uc_mcontext.gregs[5]; + sc->sc_regs[6] = uc->uc_mcontext.gregs[6]; + sc->sc_regs[7] = uc->uc_mcontext.gregs[7]; + sc->sc_regs[8] = uc->uc_mcontext.gregs[8]; + sc->sc_regs[9] = uc->uc_mcontext.gregs[9]; + sc->sc_regs[10] = uc->uc_mcontext.gregs[10]; + sc->sc_regs[11] = uc->uc_mcontext.gregs[11]; + sc->sc_regs[12] = uc->uc_mcontext.gregs[12]; + sc->sc_regs[13] = uc->uc_mcontext.gregs[13]; + sc->sc_regs[14] = uc->uc_mcontext.gregs[14]; + sc->sc_regs[15] = uc->uc_mcontext.gregs[15]; + sc->sc_pc = uc->uc_mcontext.pc; + sc->sc_pr = uc->uc_mcontext.pr; + + /* Set the SP and the PC in order to continue execution at the modified + trampoline which restores the signal mask and the registers. */ + asm __volatile__ ( + "mov %0, r15\n" + "lds %1, pr\n" + "rts\n" + "nop\n" + : + : "r" (c->sigcontext_sp), + "r" (c->sigcontext_pc) + ); + } + unreachable(); +#endif + return -UNW_EINVAL; +} + +#endif /* !UNW_REMOTE_ONLY */ + +static inline void +establish_machine_state (struct cursor *c) +{ + unw_addr_space_t as = c->dwarf.as; + void *arg = c->dwarf.as_arg; + unw_fpreg_t fpval; + unw_word_t val; + int reg; + + Debug (8, "copying out cursor state\n"); + + for (reg = 0; reg <= UNW_REG_LAST; ++reg) + { + Debug (16, "copying %s %d\n", unw_regname (reg), reg); + if (unw_is_fpreg (reg)) + { + if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) + as->acc.access_fpreg (as, reg, &fpval, 1, arg); + } + else + { + if (tdep_access_reg (c, reg, &val, 0) >= 0) + as->acc.access_reg (as, reg, &val, 1, arg); + } + } +} + +int +unw_resume (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + + Debug (1, "(cursor=%p)\n", c); + + if (!c->dwarf.ip) + { + /* This can happen easily when the frame-chain gets truncated + due to bad or missing unwind-info. */ + Debug (1, "refusing to resume execution at address 0\n"); + return -UNW_EINVAL; + } + + establish_machine_state (c); + + return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, + c->dwarf.as_arg); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gstep.c new file mode 100644 index 0000000..60d7ec2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Gstep.c @@ -0,0 +1,117 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright 2011 Linaro Limited + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "offsets.h" + +static int +sh_handle_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; + struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); + + if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) + return -UNW_EUNSPEC; + + ret = unw_is_signal_frame (cursor); + Debug(1, "unw_is_signal_frame()=%d\n", ret); + + /* Save the SP and PC to be able to return execution at this point + later in time (unw_resume). */ + c->sigcontext_sp = c->dwarf.cfa; + c->sigcontext_pc = c->dwarf.ip; + + if (ret == 1) + { + /* Handle non-RT signal frame. */ + c->sigcontext_format = SH_SCF_LINUX_SIGFRAME; + sc_addr = sp_addr; + } + else if (ret == 2) + { + /* Handle RT signal frame. */ + c->sigcontext_format = SH_SCF_LINUX_RT_SIGFRAME; + sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF; + } + else + return -UNW_EUNSPEC; + + c->sigcontext_addr = sc_addr; + + /* Update the dwarf cursor. + Set the location of the registers to the corresponding addresses of the + uc_mcontext / sigcontext structure contents. */ + c->dwarf.loc[UNW_SH_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); + c->dwarf.loc[UNW_SH_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); + c->dwarf.loc[UNW_SH_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0); + c->dwarf.loc[UNW_SH_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0); + c->dwarf.loc[UNW_SH_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0); + c->dwarf.loc[UNW_SH_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0); + c->dwarf.loc[UNW_SH_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0); + c->dwarf.loc[UNW_SH_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0); + c->dwarf.loc[UNW_SH_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0); + c->dwarf.loc[UNW_SH_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0); + c->dwarf.loc[UNW_SH_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0); + c->dwarf.loc[UNW_SH_R11] = DWARF_LOC (sc_addr + LINUX_SC_R11_OFF, 0); + c->dwarf.loc[UNW_SH_R12] = DWARF_LOC (sc_addr + LINUX_SC_R12_OFF, 0); + c->dwarf.loc[UNW_SH_R13] = DWARF_LOC (sc_addr + LINUX_SC_R13_OFF, 0); + c->dwarf.loc[UNW_SH_R14] = DWARF_LOC (sc_addr + LINUX_SC_R14_OFF, 0); + c->dwarf.loc[UNW_SH_R15] = DWARF_LOC (sc_addr + LINUX_SC_R15_OFF, 0); + c->dwarf.loc[UNW_SH_PR] = DWARF_LOC (sc_addr + LINUX_SC_PR_OFF, 0); + c->dwarf.loc[UNW_SH_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); + + /* Set SP/CFA and PC/IP. */ + dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SH_R15], &c->dwarf.cfa); + dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SH_PC], &c->dwarf.ip); + + c->dwarf.pi_valid = 0; + + return 1; +} + +int +unw_step (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + Debug (1, "(cursor=%p)\n", c); + + if (unw_is_signal_frame (cursor) > 0) + return sh_handle_signal_frame (cursor); + + ret = dwarf_step (&c->dwarf); + + if (unlikely (ret == -UNW_ESTOPUNWIND)) + return ret; + + if (unlikely (ret < 0)) + return 0; + + return (c->dwarf.ip == 0) ? 0 : 1; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lapply_reg_state.c new file mode 100644 index 0000000..7ebada4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lapply_reg_state.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gapply_reg_state.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lcreate_addr_space.c new file mode 100644 index 0000000..0f2dc6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lcreate_addr_space.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gcreate_addr_space.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lget_proc_info.c new file mode 100644 index 0000000..69028b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lget_proc_info.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_proc_info.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lget_save_loc.c new file mode 100644 index 0000000..9ea048a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lget_save_loc.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_save_loc.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lglobal.c new file mode 100644 index 0000000..6d7b489 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lglobal.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gglobal.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Linit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Linit.c new file mode 100644 index 0000000..e9abfdd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Linit.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Linit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Linit_local.c new file mode 100644 index 0000000..68a1687 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Linit_local.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_local.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Linit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Linit_remote.c new file mode 100644 index 0000000..58cb04a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Linit_remote.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_remote.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lis_signal_frame.c new file mode 100644 index 0000000..b9a7c4f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lis_signal_frame.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gis_signal_frame.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lreg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lreg_states_iterate.c new file mode 100644 index 0000000..f1eb1e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lreg_states_iterate.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Greg_states_iterate.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lregs.c new file mode 100644 index 0000000..2c9c75c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lregs.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gregs.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lresume.c new file mode 100644 index 0000000..41a8cf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lresume.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gresume.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lstep.c new file mode 100644 index 0000000..c1ac3c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/Lstep.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gstep.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/gen-offsets.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/gen-offsets.c new file mode 100644 index 0000000..16695a6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/gen-offsets.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include + +#define UC(N,X) \ + printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X)) + +#define SC(N,X) \ + printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X)) + +int +main (void) +{ + printf ( +"/* Linux-specific definitions: */\n\n" + +"/* Define various structure offsets to simplify cross-compilation. */\n\n" + +"/* Offsets for SH Linux \"ucontext_t\": */\n\n"); + + UC ("FLAGS", uc_flags); + UC ("LINK", uc_link); + UC ("STACK", uc_stack); + UC ("MCONTEXT", uc_mcontext); + UC ("SIGMASK", uc_sigmask); + + printf ("\n/* Offsets for SH Linux \"struct sigcontext\": */\n\n"); + + SC ("R0", sc_regs[0]); + SC ("R1", sc_regs[1]); + SC ("R2", sc_regs[2]); + SC ("R3", sc_regs[3]); + SC ("R4", sc_regs[4]); + SC ("R5", sc_regs[5]); + SC ("R6", sc_regs[6]); + SC ("R7", sc_regs[7]); + SC ("R8", sc_regs[8]); + SC ("R9", sc_regs[9]); + SC ("R10", sc_regs[10]); + SC ("R11", sc_regs[11]); + SC ("R12", sc_regs[12]); + SC ("R13", sc_regs[13]); + SC ("R14", sc_regs[14]); + SC ("R15", sc_regs[15]); + + SC ("PC", sc_pc); + SC ("PR", sc_pr); + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/init.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/init.h new file mode 100644 index 0000000..36713fe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/init.h @@ -0,0 +1,73 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static inline int +common_init (struct cursor *c, unsigned use_prev_instr) +{ + int ret; + + c->dwarf.loc[UNW_SH_R0] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R0); + c->dwarf.loc[UNW_SH_R1] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R1); + c->dwarf.loc[UNW_SH_R2] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R2); + c->dwarf.loc[UNW_SH_R3] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R3); + c->dwarf.loc[UNW_SH_R4] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R4); + c->dwarf.loc[UNW_SH_R5] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R5); + c->dwarf.loc[UNW_SH_R6] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R6); + c->dwarf.loc[UNW_SH_R7] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R7); + c->dwarf.loc[UNW_SH_R8] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R8); + c->dwarf.loc[UNW_SH_R9] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R9); + c->dwarf.loc[UNW_SH_R10] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R10); + c->dwarf.loc[UNW_SH_R11] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R11); + c->dwarf.loc[UNW_SH_R12] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R12); + c->dwarf.loc[UNW_SH_R13] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R13); + c->dwarf.loc[UNW_SH_R14] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R14); + c->dwarf.loc[UNW_SH_R15] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R15); + c->dwarf.loc[UNW_SH_PC] = DWARF_REG_LOC (&c->dwarf, UNW_SH_PC); + c->dwarf.loc[UNW_SH_PR] = DWARF_REG_LOC (&c->dwarf, UNW_SH_PR); + + ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SH_PC], &c->dwarf.ip); + if (ret < 0) + return ret; + + ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_TDEP_SP], &c->dwarf.cfa); + if (ret < 0) + return ret; + + c->sigcontext_format = SH_SCF_NONE; + c->sigcontext_addr = 0; + c->sigcontext_sp = 0; + c->sigcontext_pc = 0; + + c->dwarf.args_size = 0; + c->dwarf.stash_frames = 0; + c->dwarf.use_prev_instr = use_prev_instr; + c->dwarf.pi_valid = 0; + c->dwarf.pi_is_dynamic = 0; + c->dwarf.hint = 0; + c->dwarf.prev_rs = 0; + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/is_fpreg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/is_fpreg.c new file mode 100644 index 0000000..de09340 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/is_fpreg.c @@ -0,0 +1,32 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +int +unw_is_fpreg (int regnum) +{ + /* FIXME: Support FP. */ + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/offsets.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/offsets.h new file mode 100644 index 0000000..b02d8ae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/offsets.h @@ -0,0 +1,32 @@ +/* Linux-specific definitions: */ + +/* Define various structure offsets to simplify cross-compilation. */ + +/* Offsets for SH Linux "ucontext_t": */ + +#define LINUX_UC_FLAGS_OFF 0x0 +#define LINUX_UC_LINK_OFF 0x4 +#define LINUX_UC_STACK_OFF 0x8 +#define LINUX_UC_MCONTEXT_OFF 0x14 +#define LINUX_UC_SIGMASK_OFF 0xFC + +/* Offsets for SH Linux "struct sigcontext": */ + +#define LINUX_SC_R0_OFF 0x4 +#define LINUX_SC_R1_OFF 0x8 +#define LINUX_SC_R2_OFF 0xC +#define LINUX_SC_R3_OFF 0x10 +#define LINUX_SC_R4_OFF 0x14 +#define LINUX_SC_R5_OFF 0x18 +#define LINUX_SC_R6_OFF 0x1C +#define LINUX_SC_R7_OFF 0x20 +#define LINUX_SC_R8_OFF 0x24 +#define LINUX_SC_R9_OFF 0x28 +#define LINUX_SC_R10_OFF 0x2C +#define LINUX_SC_R11_OFF 0x30 +#define LINUX_SC_R12_OFF 0x34 +#define LINUX_SC_R13_OFF 0x38 +#define LINUX_SC_R14_OFF 0x3C +#define LINUX_SC_R15_OFF 0x40 +#define LINUX_SC_PC_OFF 0x44 +#define LINUX_SC_PR_OFF 0x48 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/regname.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/regname.c new file mode 100644 index 0000000..b52925b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/regname.c @@ -0,0 +1,56 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static const char *const regname[] = + { + [UNW_SH_R0] = "r0", + [UNW_SH_R1] = "r1", + [UNW_SH_R2] = "r2", + [UNW_SH_R3] = "r3", + [UNW_SH_R4] = "r4", + [UNW_SH_R5] = "r5", + [UNW_SH_R6] = "r6", + [UNW_SH_R7] = "r7", + [UNW_SH_R8] = "r8", + [UNW_SH_R9] = "r9", + [UNW_SH_R10] = "r10", + [UNW_SH_R11] = "r11", + [UNW_SH_R12] = "r12", + [UNW_SH_R13] = "r13", + [UNW_SH_R14] = "r14", + [UNW_SH_R15] = "r15", + [UNW_SH_PC] = "pc", + [UNW_SH_PR] = "pr", + }; + +const char * +unw_regname (unw_regnum_t reg) +{ + if (reg < (unw_regnum_t) ARRAY_SIZE (regname) && regname[reg] != NULL) + return regname[reg]; + else + return "???"; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/siglongjmp.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/siglongjmp.S new file mode 100644 index 0000000..9ca53d1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/sh/siglongjmp.S @@ -0,0 +1,8 @@ + /* Dummy implementation for now. */ + + .globl _UI_siglongjmp_cont + .globl _UI_longjmp_cont + +_UI_siglongjmp_cont: +_UI_longjmp_cont: + rts diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gapply_reg_state.c new file mode 100644 index 0000000..82f056d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gapply_reg_state.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_apply_reg_state (unw_cursor_t *cursor, + void *reg_states_data) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gcreate_addr_space.c new file mode 100644 index 0000000..39acdc2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gcreate_addr_space.c @@ -0,0 +1,65 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "unwind_i.h" + +unw_addr_space_t +unw_create_addr_space (unw_accessors_t *a, int byte_order) +{ +#ifdef UNW_LOCAL_ONLY + return NULL; +#else + unw_addr_space_t as = malloc (sizeof (*as)); + + if (!as) + return NULL; + + memset (as, 0, sizeof (*as)); + + as->acc = *a; + + /* + * Tilegx supports only big or little-endian, not weird stuff like + * PDP_ENDIAN. + */ + if (byte_order != 0 + && byte_order != __LITTLE_ENDIAN + && byte_order != __BIG_ENDIAN) + return NULL; + + if (byte_order == 0) + /* use host default: */ + as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN); + else + as->big_endian = (byte_order == __BIG_ENDIAN); + + as->abi = UNW_TILEGX_ABI_N64; + as->addr_size = 8; + + return as; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gget_proc_info.c new file mode 100644 index 0000000..3a158da --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gget_proc_info.c @@ -0,0 +1,48 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + ret = dwarf_make_proc_info (&c->dwarf); + + if (ret < 0) + { + /* On Tilegx, some routines i.e. _start() etc has no dwarf info. + Just simply mark the end of the frames. */ + memset (pi, 0, sizeof (*pi)); + pi->start_ip = c->dwarf.ip; + pi->end_ip = c->dwarf.ip + 1; + return 0; + } + + *pi = c->dwarf.pi; + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gget_save_loc.c new file mode 100644 index 0000000..fcf0697 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gget_save_loc.c @@ -0,0 +1,62 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) +{ + struct cursor *c = (struct cursor *) cursor; + dwarf_loc_t loc; + + loc = DWARF_NULL_LOC; /* default to "not saved" */ + + if (reg <= UNW_TILEGX_R55) + loc = c->dwarf.loc[reg - UNW_TILEGX_R0]; + else + printf("\nInvalid register!"); + + memset (sloc, 0, sizeof (*sloc)); + + if (DWARF_IS_NULL_LOC (loc)) + { + sloc->type = UNW_SLT_NONE; + return 0; + } + +#if !defined(UNW_LOCAL_ONLY) + if (DWARF_IS_REG_LOC (loc)) + { + sloc->type = UNW_SLT_REG; + sloc->u.regnum = DWARF_GET_LOC (loc); + } + else +#endif + { + sloc->type = UNW_SLT_MEMORY; + sloc->u.addr = DWARF_GET_LOC (loc); + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gglobal.c new file mode 100644 index 0000000..e18f50a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gglobal.c @@ -0,0 +1,64 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "dwarf_i.h" + +__attribute__((weak)) +pthread_mutex_t tilegx_lock = PTHREAD_MUTEX_INITIALIZER; +HIDDEN int tdep_init_done; + +HIDDEN const uint8_t dwarf_to_unw_regnum_map[] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55 + }; + +HIDDEN void +tdep_init (void) +{ + intrmask_t saved_mask; + + sigfillset (&unwi_full_mask); + + lock_acquire (&tilegx_lock, saved_mask); + + if (tdep_init_done) + /* another thread else beat us to it... */ + goto out; + + mi_init (); + dwarf_init (); + +#ifndef UNW_REMOTE_ONLY + tilegx_local_addr_space_init (); +#endif + tdep_init_done = 1; /* signal that we're initialized... */ + + out: + lock_release (&tilegx_lock, saved_mask); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Ginit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Ginit.c new file mode 100644 index 0000000..7564a55 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Ginit.c @@ -0,0 +1,167 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#include "unwind_i.h" + +#ifdef UNW_REMOTE_ONLY + +/* unw_local_addr_space is a NULL pointer in this case. */ +unw_addr_space_t unw_local_addr_space; + +#else /* !UNW_REMOTE_ONLY */ + +static struct unw_addr_space local_addr_space; + +unw_addr_space_t unw_local_addr_space = &local_addr_space; + +/* Return the address of the 64-bit slot in UC for REG (even for o32, + where registers are 32-bit, the slots are still 64-bit). */ + +static inline void * +uc_addr (ucontext_t *uc, int reg) +{ + if (reg >= UNW_TILEGX_R0 && reg < UNW_TILEGX_R0 + 56) + return &uc->uc_mcontext.gregs[reg - UNW_TILEGX_R0]; + else if (reg == UNW_TILEGX_PC) + return &uc->uc_mcontext.pc; + else + return NULL; +} + +# ifdef UNW_LOCAL_ONLY + +HIDDEN void * +tdep_uc_addr (ucontext_t *uc, int reg) +{ + char *addr = uc_addr (uc, reg); + return addr; +} + +# endif /* UNW_LOCAL_ONLY */ + +HIDDEN unw_dyn_info_list_t _U_dyn_info_list; + +/* XXX fix me: there is currently no way to locate the dyn-info list + by a remote unwinder. On ia64, this is done via a special + unwind-table entry. Perhaps something similar can be done with + DWARF2 unwind info. */ + +static void +put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) +{ + /* it's a no-op */ +} + +static int +get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, + void *arg) +{ + *dyn_info_list_addr = (unw_word_t) (intptr_t) &_U_dyn_info_list; + return 0; +} + +static int +access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, + void *arg) +{ + if ((long long)addr & (sizeof(unw_word_t) - 1)) + return 0; + + if (write) + { + Debug (16, "mem[%llx] <- %llx\n", (long long) addr, (long long) *val); + *(unw_word_t *) (intptr_t) addr = *val; + } + else + { + *val = *(unw_word_t *) (intptr_t) addr; + Debug (16, "mem[%llx] -> %llx\n", (long long) addr, (long long) *val); + } + return 0; +} + +static int +access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, + void *arg) +{ + unw_word_t *addr; + ucontext_t *uc = arg; + + if (unw_is_fpreg (reg)) + goto badreg; + + Debug (16, "reg = %s\n", unw_regname (reg)); + if (!(addr = uc_addr (uc, reg))) + goto badreg; + + if (write) + { + *(unw_word_t *) (intptr_t) addr = (tilegx_reg_t) *val; + Debug (12, "%s <- %llx\n", unw_regname (reg), (long long) *val); + } + else + { + *val = (tilegx_reg_t) *(unw_word_t *) (intptr_t) addr; + Debug (12, "%s -> %llx\n", unw_regname (reg), (long long) *val); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} + +static int +get_static_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, + void *arg) +{ + return elf_w (get_proc_name) (as, getpid (), ip, buf, buf_len, offp); +} + +__attribute__((weak)) void +tilegx_local_addr_space_init (void) +{ + memset (&local_addr_space, 0, sizeof (local_addr_space)); + local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN); + + local_addr_space.abi = UNW_TILEGX_ABI_N64; + local_addr_space.addr_size = sizeof (void *); + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; + local_addr_space.acc.find_proc_info = dwarf_find_proc_info; + local_addr_space.acc.put_unwind_info = put_unwind_info; + local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; + local_addr_space.acc.access_mem = access_mem; + local_addr_space.acc.access_reg = access_reg; + local_addr_space.acc.access_fpreg = NULL; + local_addr_space.acc.resume = tilegx_local_resume; + local_addr_space.acc.get_proc_name = get_static_proc_name; + unw_flush_cache (&local_addr_space, 0, 0); +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Ginit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Ginit_local.c new file mode 100644 index 0000000..31a716d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Ginit_local.c @@ -0,0 +1,80 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "init.h" + +#ifdef UNW_REMOTE_ONLY + +int +unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) +{ + return -UNW_EINVAL; +} + +#else /* !UNW_REMOTE_ONLY */ + +static int +unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr) +{ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + memset(c, 0, sizeof(unw_cursor_t)); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = unw_local_addr_space; + + c->dwarf.as_arg = uc; + return common_init (c, use_prev_instr); +} + +int +unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) +{ + return unw_init_local_common(cursor, uc, 1); +} + +int +unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) +{ + if (!flag) + { + return unw_init_local_common(cursor, uc, 1); + } + else if (flag == UNW_INIT_SIGNAL_FRAME) + { + return unw_init_local_common(cursor, uc, 0); + } + else + { + return -UNW_EINVAL; + } +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Ginit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Ginit_remote.c new file mode 100644 index 0000000..2a31b18 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Ginit_remote.c @@ -0,0 +1,47 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "init.h" +#include "unwind_i.h" + +int +unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) +{ +#ifdef UNW_LOCAL_ONLY + return -UNW_EINVAL; +#else /* !UNW_LOCAL_ONLY */ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = as; + c->dwarf.as_arg = as_arg; + + return common_init (c, 0); +#endif /* !UNW_LOCAL_ONLY */ +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gis_signal_frame.c new file mode 100644 index 0000000..5452c2c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gis_signal_frame.c @@ -0,0 +1,115 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include +#include "offsets.h" + +#ifdef __linux__ +#include +#include +#else +# error "Only support Linux!" +#endif + +#define MOVELI_R10_RT_SIGRETURN \ + ( 0x000007e051483000ULL | \ + ((unsigned long)__NR_rt_sigreturn << 43) | \ + ((unsigned long)TREG_SYSCALL_NR << 31) ) +#define SWINT1 0x286b180051485000ULL + +int +unw_is_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor*) cursor; + unw_word_t w0, w1, ip; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + int ret; + + as = c->dwarf.as; + a = unw_get_accessors_int (as); + arg = c->dwarf.as_arg; + + ip = c->dwarf.ip; + + if (!ip || !a->access_mem || (ip & (sizeof(unw_word_t) - 1))) + return 0; + + if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0) + return ret; + + if ((ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0) + return ret; + + /* Return 1 if the IP points to a RT sigreturn sequence. */ + if (w0 == MOVELI_R10_RT_SIGRETURN && + w1 == SWINT1) + { + return 1; + } + return 0; +} + + +HIDDEN int +tilegx_handle_signal_frame (unw_cursor_t *cursor) +{ + int i; + struct cursor *c = (struct cursor *) cursor; + unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; + struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); + int ret; + + if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) + return -UNW_EUNSPEC; + + /* Save the SP and PC to be able to return execution at this point + later in time (unw_resume). */ + c->sigcontext_sp = c->dwarf.cfa; + c->sigcontext_pc = c->dwarf.ip; + + c->sigcontext_addr = sp_addr + sizeof (siginfo_t) + + C_ABI_SAVE_AREA_SIZE; + sc_addr = c->sigcontext_addr + LINUX_UC_MCONTEXT_OFF; + + /* Update the dwarf cursor. + Set the location of the registers to the corresponding addresses of the + uc_mcontext / sigcontext structure contents. */ + +#define SC_REG_OFFSET(X) (8 * X) + + for (i = UNW_TILEGX_R0; i <= UNW_TILEGX_R55; i++) + { + c->dwarf.loc[i] = DWARF_LOC (sc_addr + SC_REG_OFFSET(i), 0); + } + + /* Set SP/CFA and PC/IP. */ + dwarf_get (&c->dwarf, c->dwarf.loc[UNW_TILEGX_R54], &c->dwarf.cfa); + dwarf_get (&c->dwarf, c->dwarf.loc[UNW_TILEGX_R55], &c->dwarf.ip); + + return 1; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Greg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Greg_states_iterate.c new file mode 100644 index 0000000..a17dc1b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Greg_states_iterate.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_reg_states_iterate (unw_cursor_t *cursor, + unw_reg_states_callback cb, void *token) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_reg_states_iterate (&c->dwarf, cb, token); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gregs.c new file mode 100644 index 0000000..565c6f4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gregs.c @@ -0,0 +1,76 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +HIDDEN int +tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + int write) +{ + dwarf_loc_t loc = DWARF_NULL_LOC; + + if (reg == UNW_TILEGX_R54 && !write) + { + reg = UNW_TILEGX_CFA; + } + + if (reg <= UNW_TILEGX_R55) + loc = c->dwarf.loc[reg - UNW_TILEGX_R0]; + else if (reg == UNW_TILEGX_CFA) + { + if (write) + return -UNW_EREADONLYREG; + *valp = c->dwarf.cfa; + return 0; + } + else + { + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; + } + + if (write) + { + if (ci->dwarf.use_prev_instr == 0) { + if (reg == UNW_TILEGX_PC) + c->dwarf.ip = *valp; /* update the IP cache */ + } + else { + if (reg == UNW_TILEGX_R55) + c->dwarf.ip = *valp; /* update the IP cache */ + } + return dwarf_put (&c->dwarf, loc, *valp); + } + else + return dwarf_get (&c->dwarf, loc, valp); +} + +HIDDEN int +tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, + int write) +{ + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gresume.c new file mode 100644 index 0000000..ece443a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gresume.c @@ -0,0 +1,94 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + +#include "unwind_i.h" +#include "offsets.h" +#include + +#ifndef UNW_REMOTE_ONLY + +HIDDEN inline int +tilegx_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ + int i; + struct cursor *c = (struct cursor *) cursor; + ucontext_t *uc = c->dwarf.as_arg; + + Debug (1, "(cursor=%p\n", c); + + return setcontext(uc); +} + +#endif /* !UNW_REMOTE_ONLY */ + +static inline void +establish_machine_state (struct cursor *c) +{ + unw_addr_space_t as = c->dwarf.as; + void *arg = c->dwarf.as_arg; + unw_fpreg_t fpval; + unw_word_t val; + int reg; + + Debug (8, "copying out cursor state\n"); + + for (reg = 0; reg <= UNW_REG_LAST; ++reg) + { + Debug (16, "copying %s %d\n", unw_regname (reg), reg); + + if (unw_is_fpreg (reg)) + { + Debug (1, "no fp!"); + abort (); + } + else + { + if (tdep_access_reg (c, reg, &val, 0) >= 0) + as->acc.access_reg (as, reg, &val, 1, arg); + } + } +} + +int +unw_resume (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + + Debug (1, "(cursor=%p) ip=0x%lx\n", c, c->dwarf.ip); + + if (!c->dwarf.ip) + { + /* This can happen easily when the frame-chain gets truncated + due to bad or missing unwind-info. */ + Debug (1, "refusing to resume execution at address 0\n"); + return -UNW_EINVAL; + } + + establish_machine_state (c); + + return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, + c->dwarf.as_arg); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gstep.c new file mode 100644 index 0000000..c748dbc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Gstep.c @@ -0,0 +1,53 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "offsets.h" + +int +unw_step (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + Debug (1, "(cursor=%p, ip=0x%016lx, sp=0x%016lx)\n", + c, c->dwarf.ip, c->dwarf.cfa); + + /* Special handling the singal frame. */ + if (unw_is_signal_frame (cursor) > 0) + return tilegx_handle_signal_frame (cursor); + + /* Try DWARF-based unwinding... */ + ret = dwarf_step (&c->dwarf); + + if (unlikely (ret == -UNW_ESTOPUNWIND)) + return ret; + + /* Dwarf unwinding didn't work, stop. */ + if (unlikely (ret < 0)) + return 0; + + return (c->dwarf.ip == 0) ? 0 : 1; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lapply_reg_state.c new file mode 100644 index 0000000..7ebada4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lapply_reg_state.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gapply_reg_state.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lcreate_addr_space.c new file mode 100644 index 0000000..0f2dc6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lcreate_addr_space.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gcreate_addr_space.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lget_proc_info.c new file mode 100644 index 0000000..69028b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lget_proc_info.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_proc_info.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lget_save_loc.c new file mode 100644 index 0000000..9ea048a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lget_save_loc.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_save_loc.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lglobal.c new file mode 100644 index 0000000..6d7b489 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lglobal.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gglobal.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Linit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Linit.c new file mode 100644 index 0000000..e9abfdd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Linit.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Linit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Linit_local.c new file mode 100644 index 0000000..68a1687 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Linit_local.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_local.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Linit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Linit_remote.c new file mode 100644 index 0000000..58cb04a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Linit_remote.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_remote.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lis_signal_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lis_signal_frame.c new file mode 100644 index 0000000..b9a7c4f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lis_signal_frame.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gis_signal_frame.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lreg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lreg_states_iterate.c new file mode 100644 index 0000000..f1eb1e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lreg_states_iterate.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Greg_states_iterate.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lregs.c new file mode 100644 index 0000000..2c9c75c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lregs.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gregs.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lresume.c new file mode 100644 index 0000000..41a8cf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lresume.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gresume.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lstep.c new file mode 100644 index 0000000..c1ac3c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/Lstep.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gstep.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/elfxx.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/elfxx.c new file mode 100644 index 0000000..07d3d12 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/elfxx.c @@ -0,0 +1,27 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +#include "../src/elfxx.c" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/gen-offsets.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/gen-offsets.c new file mode 100644 index 0000000..8704bb2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/gen-offsets.c @@ -0,0 +1,30 @@ +#include +#include +#include + +#define UC(N,X) \ + printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X)) + +#define SC(N,X) \ + printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X)) + +int +main (void) +{ + printf ( +"/* Linux-specific definitions: */\n\n" + +"/* Define various structure offsets to simplify cross-compilation. */\n\n" + +"/* Offsets for TILEGX Linux \"ucontext_t\": */\n\n"); + + UC ("FLAGS", uc_flags); + UC ("LINK", uc_link); + UC ("STACK", uc_stack); + UC ("MCONTEXT", uc_mcontext); + UC ("SIGMASK", uc_sigmask); + + UC ("MCONTEXT_GREGS", uc_mcontext.gregs); + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/getcontext.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/getcontext.S new file mode 100644 index 0000000..fbc8654 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/getcontext.S @@ -0,0 +1,36 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "offsets.h" +#include + + .text + # define REG(X) LINUX_UC_MCONTEXT_GREGS + 8 * (X) + .global _Utilegx_getcontext + .type _Utilegx_getcontext, %function + # This is a stub version of getcontext() for TILEGX. +_Utilegx_getcontext: + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/init.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/init.h new file mode 100644 index 0000000..0e0f7fd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/init.h @@ -0,0 +1,63 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static inline int +common_init (struct cursor *c, unsigned use_prev_instr) +{ + int ret, i; + + for (i = 0; i < 56; i++) + c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, UNW_TILEGX_R0 + i); + for (i = 56; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + + if (use_prev_instr == 0) + ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_TILEGX_PC), + &c->dwarf.ip); + else + ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_TILEGX_R55), + &c->dwarf.ip); + + if (ret < 0) + return ret; + + ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_TILEGX_R54), + &c->dwarf.cfa); + + if (ret < 0) + return ret; + + c->dwarf.args_size = 0; + c->dwarf.stash_frames = 0; + c->dwarf.use_prev_instr = use_prev_instr; + c->dwarf.pi_valid = 0; + c->dwarf.pi_is_dynamic = 0; + c->dwarf.hint = 0; + c->dwarf.prev_rs = 0; + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/is_fpreg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/is_fpreg.c new file mode 100644 index 0000000..d6d5896 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/is_fpreg.c @@ -0,0 +1,33 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +/* TILEGX has no FP. */ + +int +unw_is_fpreg (int regnum) +{ + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/offsets.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/offsets.h new file mode 100644 index 0000000..6d30f1e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/offsets.h @@ -0,0 +1,12 @@ +/* Linux-specific definitions: */ + +/* Define various structure offsets to simplify cross-compilation. */ + +/* Offsets for TILEGX Linux "ucontext_t": */ + +#define LINUX_UC_FLAGS_OFF 0x0 +#define LINUX_UC_LINK_OFF 0x8 +#define LINUX_UC_STACK_OFF 0x10 +#define LINUX_UC_MCONTEXT_OFF 0x28 +#define LINUX_UC_SIGMASK_OFF 0x228 +#define LINUX_UC_MCONTEXT_GREGS 0x28 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/regname.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/regname.c new file mode 100644 index 0000000..0ce47b9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/regname.c @@ -0,0 +1,55 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2014 Tilera Corp. + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static const char *regname[] = + { + /* 0. */ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + /* 8. */ + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + /* 16. */ + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + /* 24. */ + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", + /* 32. */ + "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", + /* 40. */ + "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", + /* 48. */ + "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", + /* pc, cfa */ + "pc", "cfa" + }; + +const char * +unw_regname (unw_regnum_t reg) +{ + if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) + return regname[reg]; + else + return "???"; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/siglongjmp.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/siglongjmp.S new file mode 100644 index 0000000..bccb1c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/tilegx/siglongjmp.S @@ -0,0 +1,7 @@ + /* Dummy implementation for now. */ + .globl _UI_siglongjmp_cont + .globl _UI_longjmp_cont + +_UI_siglongjmp_cont: +_UI_longjmp_cont: + jrp lr diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/Backtrace.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/Backtrace.c new file mode 100644 index 0000000..0b14df4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/Backtrace.c @@ -0,0 +1,56 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +_Unwind_Reason_Code +_Unwind_Backtrace (_Unwind_Trace_Fn trace, void *trace_parameter) +{ + struct _Unwind_Context context; + unw_context_t uc; + int ret; + + if (_Unwind_InitContext (&context, &uc) < 0) + return _URC_FATAL_PHASE1_ERROR; + + /* Phase 1 (search phase) */ + + while (1) + { + if ((ret = unw_step (&context.cursor)) <= 0) + { + if (ret == 0) + return _URC_END_OF_STACK; + else + return _URC_FATAL_PHASE1_ERROR; + } + + if ((*trace) (&context, trace_parameter) != _URC_NO_REASON) + return _URC_FATAL_PHASE1_ERROR; + } +} + +_Unwind_Reason_Code __libunwind_Unwind_Backtrace (_Unwind_Trace_Fn, void *) + ALIAS (_Unwind_Backtrace); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/DeleteException.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/DeleteException.c new file mode 100644 index 0000000..ad38eaf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/DeleteException.c @@ -0,0 +1,38 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +void +_Unwind_DeleteException (struct _Unwind_Exception *exception_object) +{ + _Unwind_Exception_Cleanup_Fn cleanup = exception_object->exception_cleanup; + + if (cleanup) + (*cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exception_object); +} + +void __libunwind_Unwind_DeleteException (struct _Unwind_Exception *) + ALIAS (_Unwind_DeleteException); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/FindEnclosingFunction.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/FindEnclosingFunction.c new file mode 100644 index 0000000..4f10666 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/FindEnclosingFunction.c @@ -0,0 +1,42 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +void * +_Unwind_FindEnclosingFunction (void *ip) +{ + unw_proc_info_t pi; + + if (unw_get_proc_info_by_ip (unw_local_addr_space, + (unw_word_t) (uintptr_t) ip, &pi, 0) + < 0) + return NULL; + + return (void *) (uintptr_t) pi.start_ip; +} + +void *__libunwind_Unwind_FindEnclosingFunction (void *) + ALIAS (_Unwind_FindEnclosingFunction); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/ForcedUnwind.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/ForcedUnwind.c new file mode 100644 index 0000000..905b31c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/ForcedUnwind.c @@ -0,0 +1,52 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +_Unwind_Reason_Code +_Unwind_ForcedUnwind (struct _Unwind_Exception *exception_object, + _Unwind_Stop_Fn stop, void *stop_parameter) +{ + struct _Unwind_Context context; + unw_context_t uc; + + /* We check "stop" here to tell the compiler's inliner that + exception_object->private_1 isn't NULL when calling + _Unwind_Phase2(). */ + if (!stop) + return _URC_FATAL_PHASE2_ERROR; + + if (_Unwind_InitContext (&context, &uc) < 0) + return _URC_FATAL_PHASE2_ERROR; + + exception_object->private_1 = (unsigned long) stop; + exception_object->private_2 = (unsigned long) stop_parameter; + + return _Unwind_Phase2 (exception_object, &context); +} + +_Unwind_Reason_Code __libunwind_Unwind_ForcedUnwind (struct _Unwind_Exception*, + _Unwind_Stop_Fn, void *) + ALIAS (_Unwind_ForcedUnwind); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetBSP.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetBSP.c new file mode 100644 index 0000000..d1bc84e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetBSP.c @@ -0,0 +1,42 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +unsigned long +_Unwind_GetBSP (struct _Unwind_Context *context) +{ +#ifdef UNW_TARGET_IA64 + unw_word_t val; + + unw_get_reg (&context->cursor, UNW_IA64_BSP, &val); + return val; +#else + return 0; +#endif +} + +unsigned long __libunwind_Unwind_GetBSP (struct _Unwind_Context *) + ALIAS (_Unwind_GetBSP); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetCFA.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetCFA.c new file mode 100644 index 0000000..5ca6390 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetCFA.c @@ -0,0 +1,38 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +unsigned long +_Unwind_GetCFA (struct _Unwind_Context *context) +{ + unw_word_t val; + + unw_get_reg (&context->cursor, UNW_REG_SP, &val); + return val; +} + +unsigned long __libunwind_Unwind_GetCFA (struct _Unwind_Context *) + ALIAS (_Unwind_GetCFA); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetDataRelBase.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetDataRelBase.c new file mode 100644 index 0000000..8e6914f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetDataRelBase.c @@ -0,0 +1,39 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +unsigned long +_Unwind_GetDataRelBase (struct _Unwind_Context *context) +{ + unw_proc_info_t pi; + + pi.gp = 0; + unw_get_proc_info (&context->cursor, &pi); + return pi.gp; +} + +unsigned long __libunwind_Unwind_GetDataRelBase (struct _Unwind_Context *) + ALIAS (_Unwind_GetDataRelBase); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetGR.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetGR.c new file mode 100644 index 0000000..fa70943 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetGR.c @@ -0,0 +1,43 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +unsigned long +_Unwind_GetGR (struct _Unwind_Context *context, int index) +{ + unw_word_t val; + + if (index == UNW_REG_SP && context->end_of_stack) + /* _Unwind_ForcedUnwind() requires us to return a NULL + stack-pointer after reaching the end of the stack. */ + return 0; + + unw_get_reg (&context->cursor, index, &val); + return val; +} + +unsigned long __libunwind_Unwind_GetGR (struct _Unwind_Context *, int) + ALIAS (_Unwind_GetGR); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetIP.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetIP.c new file mode 100644 index 0000000..e9fc494 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetIP.c @@ -0,0 +1,38 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +unsigned long +_Unwind_GetIP (struct _Unwind_Context *context) +{ + unw_word_t val; + + unw_get_reg (&context->cursor, UNW_REG_IP, &val); + return val; +} + +unsigned long __libunwind_Unwind_GetIP (struct _Unwind_Context *) + ALIAS (_Unwind_GetIP); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetIPInfo.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetIPInfo.c new file mode 100644 index 0000000..e8ee7fd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetIPInfo.c @@ -0,0 +1,42 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2009 Red Hat + Contributed by Jan Kratochvil + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +/* gcc/unwind-dw2.c: Retrieve the return address and flag whether that IP is + before or after first not yet fully executed instruction. */ + +unsigned long +_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn) +{ + unw_word_t val; + + unw_get_reg (&context->cursor, UNW_REG_IP, &val); + *ip_before_insn = unw_is_signal_frame (&context->cursor); + return val; +} + +unsigned long __libunwind_Unwind_GetIPInfo (struct _Unwind_Context *, int *) + ALIAS (_Unwind_GetIPInfo); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetLanguageSpecificData.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetLanguageSpecificData.c new file mode 100644 index 0000000..e7ca9b4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetLanguageSpecificData.c @@ -0,0 +1,40 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +unsigned long +_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context) +{ + unw_proc_info_t pi; + + pi.lsda = 0; + unw_get_proc_info (&context->cursor, &pi); + return pi.lsda; +} + +unsigned long +__libunwind_Unwind_GetLanguageSpecificData (struct _Unwind_Context *) + ALIAS (_Unwind_GetLanguageSpecificData); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetRegionStart.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetRegionStart.c new file mode 100644 index 0000000..f499581 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetRegionStart.c @@ -0,0 +1,39 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +unsigned long +_Unwind_GetRegionStart (struct _Unwind_Context *context) +{ + unw_proc_info_t pi; + + pi.start_ip = 0; + unw_get_proc_info (&context->cursor, &pi); + return pi.start_ip; +} + +unsigned long __libunwind_Unwind_GetRegionStart (struct _Unwind_Context *) + ALIAS (_Unwind_GetRegionStart); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetTextRelBase.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetTextRelBase.c new file mode 100644 index 0000000..ce65ae9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/GetTextRelBase.c @@ -0,0 +1,35 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +unsigned long +_Unwind_GetTextRelBase (struct _Unwind_Context *context) +{ + return 0; +} + +unsigned long __libunwind_Unwind_GetTextRelBase (struct _Unwind_Context *) + ALIAS (_Unwind_GetTextRelBase); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/RaiseException.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/RaiseException.c new file mode 100644 index 0000000..3c3ca19 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/RaiseException.c @@ -0,0 +1,103 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +_Unwind_Reason_Code +_Unwind_RaiseException (struct _Unwind_Exception *exception_object) +{ + uint64_t exception_class = exception_object->exception_class; + _Unwind_Personality_Fn personality; + struct _Unwind_Context context; + _Unwind_Reason_Code reason; + unw_proc_info_t pi; + unw_context_t uc; + unw_word_t ip; + int ret; + + Debug (1, "(exception_object=%p)\n", exception_object); + + if (_Unwind_InitContext (&context, &uc) < 0) + return _URC_FATAL_PHASE1_ERROR; + + /* Phase 1 (search phase) */ + + while (1) + { + if ((ret = unw_step (&context.cursor)) <= 0) + { + if (ret == 0) + { + Debug (1, "no handler found\n"); + return _URC_END_OF_STACK; + } + else + return _URC_FATAL_PHASE1_ERROR; + } + + if (unw_get_proc_info (&context.cursor, &pi) < 0) + return _URC_FATAL_PHASE1_ERROR; + + personality = (_Unwind_Personality_Fn) (uintptr_t) pi.handler; + if (personality) + { + reason = (*personality) (_U_VERSION, _UA_SEARCH_PHASE, + exception_class, exception_object, + &context); + if (reason != _URC_CONTINUE_UNWIND) + { + if (reason == _URC_HANDLER_FOUND) + break; + else + { + Debug (1, "personality returned %d\n", reason); + return _URC_FATAL_PHASE1_ERROR; + } + } + } + } + + /* Exceptions are associated with IP-ranges. If a given exception + is handled at a particular IP, it will _always_ be handled at + that IP. If this weren't true, we'd have to track the tuple + (IP,SP,BSP) to uniquely identify the stack frame that's handling + the exception. */ + if (unw_get_reg (&context.cursor, UNW_REG_IP, &ip) < 0) + return _URC_FATAL_PHASE1_ERROR; + exception_object->private_1 = 0; /* clear "stop" pointer */ + exception_object->private_2 = ip; /* save frame marker */ + + Debug (1, "found handler for IP=%lx; entering cleanup phase\n", (long) ip); + + /* Reset the cursor to the first frame: */ + if (unw_init_local (&context.cursor, &uc) < 0) + return _URC_FATAL_PHASE1_ERROR; + + return _Unwind_Phase2 (exception_object, &context); +} + +_Unwind_Reason_Code +__libunwind_Unwind_RaiseException (struct _Unwind_Exception *) + ALIAS (_Unwind_RaiseException); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/Resume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/Resume.c new file mode 100644 index 0000000..e23d6be --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/Resume.c @@ -0,0 +1,42 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +void +_Unwind_Resume (struct _Unwind_Exception *exception_object) +{ + struct _Unwind_Context context; + unw_context_t uc; + + if (_Unwind_InitContext (&context, &uc) < 0) + abort (); + + _Unwind_Phase2 (exception_object, &context); + abort (); +} + +void __libunwind_Unwind_Resume (struct _Unwind_Exception *) + ALIAS (_Unwind_Resume); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/Resume_or_Rethrow.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/Resume_or_Rethrow.c new file mode 100644 index 0000000..9c76443 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/Resume_or_Rethrow.c @@ -0,0 +1,47 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +_Unwind_Reason_Code +_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exception_object) +{ + struct _Unwind_Context context; + unw_context_t uc; + + if (exception_object->private_1) + { + if (_Unwind_InitContext (&context, &uc) < 0) + return _URC_FATAL_PHASE2_ERROR; + + return _Unwind_Phase2 (exception_object, &context); + } + else + return _Unwind_RaiseException (exception_object); +} + +_Unwind_Reason_Code +__libunwind_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *) + ALIAS (_Unwind_Resume_or_Rethrow); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/SetGR.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/SetGR.c new file mode 100644 index 0000000..ae77a8e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/SetGR.c @@ -0,0 +1,47 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" +#ifdef UNW_TARGET_X86 +#include "dwarf_i.h" +#endif + +void +_Unwind_SetGR (struct _Unwind_Context *context, int index, + unsigned long new_value) +{ +#ifdef UNW_TARGET_X86 + index = dwarf_to_unw_regnum(index); +#endif + unw_set_reg (&context->cursor, index, new_value); +#ifdef UNW_TARGET_IA64 + if (index >= UNW_IA64_GR && index <= UNW_IA64_GR + 127) + /* Clear the NaT bit. */ + unw_set_reg (&context->cursor, UNW_IA64_NAT + (index - UNW_IA64_GR), 0); +#endif +} + +void __libunwind_Unwind_SetGR (struct _Unwind_Context *, int, unsigned long) + ALIAS (_Unwind_SetGR); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/SetIP.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/SetIP.c new file mode 100644 index 0000000..fccc2f0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/SetIP.c @@ -0,0 +1,35 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind-internal.h" + +void +_Unwind_SetIP (struct _Unwind_Context *context, unsigned long new_value) +{ + unw_set_reg (&context->cursor, UNW_REG_IP, new_value); +} + +void __libunwind_Unwind_SetIP (struct _Unwind_Context *, unsigned long) + ALIAS (_Unwind_SetIP); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/libunwind.pc.in b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/libunwind.pc.in new file mode 100644 index 0000000..1505c5d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/libunwind.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libunwind +Description: libunwind base library +Version: @VERSION@ +Libs: -L${libdir} -lunwind +Libs.private: @LIBLZMA@ +Cflags: -I${includedir} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/unwind-internal.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/unwind-internal.h new file mode 100644 index 0000000..c68fc3c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/unwind/unwind-internal.h @@ -0,0 +1,140 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef unwind_internal_h +#define unwind_internal_h + +#define UNW_LOCAL_ONLY + +#include +#include +#include + +#include "libunwind_i.h" + +/* The version of the _Unwind_*() interface implemented by this code. */ +#define _U_VERSION 1 + +typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn) + (int, _Unwind_Action, uint64_t, struct _Unwind_Exception *, + struct _Unwind_Context *); + +struct _Unwind_Context { + unw_cursor_t cursor; + int end_of_stack; /* set to 1 if the end of stack was reached */ +}; + +/* This must be a macro because unw_getcontext() must be invoked from + the callee, even if optimization (and hence inlining) is turned + off. The macro arguments MUST NOT have any side-effects. */ +#define _Unwind_InitContext(context, uc) \ + ((context)->end_of_stack = 0, \ + ((unw_getcontext (uc) < 0 || unw_init_local (&(context)->cursor, uc) < 0) \ + ? -1 : 0)) + +static _Unwind_Reason_Code ALWAYS_INLINE +_Unwind_Phase2 (struct _Unwind_Exception *exception_object, + struct _Unwind_Context *context) +{ + _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) exception_object->private_1; + uint64_t exception_class = exception_object->exception_class; + void *stop_parameter = (void *) exception_object->private_2; + _Unwind_Personality_Fn personality; + _Unwind_Reason_Code reason; + _Unwind_Action actions; + unw_proc_info_t pi; + unw_word_t ip; + int ret; + + actions = _UA_CLEANUP_PHASE; + if (stop) + actions |= _UA_FORCE_UNWIND; + + while (1) + { + ret = unw_step (&context->cursor); + if (ret <= 0) + { + if (ret == 0) + { + actions |= _UA_END_OF_STACK; + context->end_of_stack = 1; + } + else + return _URC_FATAL_PHASE2_ERROR; + } + + if (stop) + { + reason = (*stop) (_U_VERSION, actions, exception_class, + exception_object, context, stop_parameter); + if (reason != _URC_NO_REASON) + /* Stop function may return _URC_FATAL_PHASE2_ERROR if + it's unable to handle end-of-stack condition or + _URC_FATAL_PHASE2_ERROR if something is wrong. Not + that it matters: the resulting state is indeterminate + anyhow so we must return _URC_FATAL_PHASE2_ERROR... */ + return _URC_FATAL_PHASE2_ERROR; + } + + if (context->end_of_stack + || unw_get_proc_info (&context->cursor, &pi) < 0) + return _URC_FATAL_PHASE2_ERROR; + + personality = (_Unwind_Personality_Fn) (uintptr_t) pi.handler; + if (personality) + { + if (!stop) + { + if (unw_get_reg (&context->cursor, UNW_REG_IP, &ip) < 0) + return _URC_FATAL_PHASE2_ERROR; + + if ((unsigned long) stop_parameter == ip) + actions |= _UA_HANDLER_FRAME; + } + + reason = (*personality) (_U_VERSION, actions, exception_class, + exception_object, context); + if (reason != _URC_CONTINUE_UNWIND) + { + if (reason == _URC_INSTALL_CONTEXT) + { + /* we may regain control via _Unwind_Resume() */ + unw_resume (&context->cursor); + abort (); + } + else + return _URC_FATAL_PHASE2_ERROR; + } + if (actions & _UA_HANDLER_FRAME) + /* The personality routine for the handler-frame changed + it's mind; that's a no-no... */ + abort (); + } + } + return _URC_FATAL_PHASE2_ERROR; /* shouldn't be reached */ +} + +#endif /* unwind_internal_h */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gapply_reg_state.c new file mode 100644 index 0000000..82f056d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gapply_reg_state.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_apply_reg_state (unw_cursor_t *cursor, + void *reg_states_data) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gcreate_addr_space.c new file mode 100644 index 0000000..9b2db98 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gcreate_addr_space.c @@ -0,0 +1,61 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "unwind_i.h" + +#if defined(_LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN) +#define __LITTLE_ENDIAN _LITTLE_ENDIAN +#endif + +unw_addr_space_t +unw_create_addr_space (unw_accessors_t *a, int byte_order) +{ +#ifdef UNW_LOCAL_ONLY + return NULL; +#else + unw_addr_space_t as; + + /* + * x86_64 supports only little-endian. + */ + if (byte_order != 0 && byte_order != __LITTLE_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); + if (!as) + return NULL; + + memset (as, 0, sizeof (*as)); + + as->acc = *a; + + return as; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gget_proc_info.c new file mode 100644 index 0000000..50de1e4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gget_proc_info.c @@ -0,0 +1,48 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) +{ + struct cursor *c = (struct cursor *) cursor; + + if (dwarf_make_proc_info (&c->dwarf) < 0) + { + /* On x86-64, some key routines such as _start() and _dl_start() + are missing DWARF unwind info. We don't want to fail in that + case, because those frames are uninteresting and just mark + the end of the frame-chain anyhow. */ + memset (pi, 0, sizeof (*pi)); + pi->start_ip = c->dwarf.ip; + pi->end_ip = c->dwarf.ip + 1; + return 0; + } + *pi = c->dwarf.pi; + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gget_save_loc.c new file mode 100644 index 0000000..0057c62 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gget_save_loc.c @@ -0,0 +1,73 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) +{ + struct cursor *c = (struct cursor *) cursor; + dwarf_loc_t loc; + + loc = DWARF_NULL_LOC; /* default to "not saved" */ + + switch (reg) + { + case UNW_X86_64_RBX: loc = c->dwarf.loc[RBX]; break; + case UNW_X86_64_RSP: loc = c->dwarf.loc[RSP]; break; + case UNW_X86_64_RBP: loc = c->dwarf.loc[RBP]; break; + case UNW_X86_64_R12: loc = c->dwarf.loc[R12]; break; + case UNW_X86_64_R13: loc = c->dwarf.loc[R13]; break; + case UNW_X86_64_R14: loc = c->dwarf.loc[R14]; break; + case UNW_X86_64_R15: loc = c->dwarf.loc[R15]; break; + + default: + break; + } + + memset (sloc, 0, sizeof (*sloc)); + + if (DWARF_IS_NULL_LOC (loc)) + { + sloc->type = UNW_SLT_NONE; + return 0; + } + +#if !defined(UNW_LOCAL_ONLY) + if (DWARF_IS_REG_LOC (loc)) + { + sloc->type = UNW_SLT_REG; + sloc->u.regnum = DWARF_GET_LOC (loc); + } + else +#endif + { + sloc->type = UNW_SLT_MEMORY; + sloc->u.addr = DWARF_GET_LOC (loc); + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gglobal.c new file mode 100644 index 0000000..8d1fbb4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gglobal.c @@ -0,0 +1,102 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "config.h" +#include "unwind_i.h" +#include "dwarf_i.h" + +HIDDEN define_lock (x86_64_lock); +HIDDEN int tdep_init_done; + +/* See comments for svr4_dbx_register_map[] in gcc/config/i386/i386.c. */ + +HIDDEN const uint8_t dwarf_to_unw_regnum_map[DWARF_NUM_PRESERVED_REGS] = + { + UNW_X86_64_RAX, + UNW_X86_64_RDX, + UNW_X86_64_RCX, + UNW_X86_64_RBX, + UNW_X86_64_RSI, + UNW_X86_64_RDI, + UNW_X86_64_RBP, + UNW_X86_64_RSP, + UNW_X86_64_R8, + UNW_X86_64_R9, + UNW_X86_64_R10, + UNW_X86_64_R11, + UNW_X86_64_R12, + UNW_X86_64_R13, + UNW_X86_64_R14, + UNW_X86_64_R15, + UNW_X86_64_RIP, +#ifdef CONFIG_MSABI_SUPPORT + UNW_X86_64_XMM0, + UNW_X86_64_XMM1, + UNW_X86_64_XMM2, + UNW_X86_64_XMM3, + UNW_X86_64_XMM4, + UNW_X86_64_XMM5, + UNW_X86_64_XMM6, + UNW_X86_64_XMM7, + UNW_X86_64_XMM8, + UNW_X86_64_XMM9, + UNW_X86_64_XMM10, + UNW_X86_64_XMM11, + UNW_X86_64_XMM12, + UNW_X86_64_XMM13, + UNW_X86_64_XMM14, + UNW_X86_64_XMM15 +#endif + }; + +HIDDEN void +tdep_init (void) +{ + intrmask_t saved_mask; + + sigfillset (&unwi_full_mask); + + lock_acquire (&x86_64_lock, saved_mask); + { + if (tdep_init_done) + /* another thread else beat us to it... */ + goto out; + + mi_init (); + + dwarf_init (); + + tdep_init_mem_validate (); + +#ifndef UNW_REMOTE_ONLY + x86_64_local_addr_space_init (); +#endif + tdep_init_done = 1; /* signal that we're initialized... */ + } + out: + lock_release (&x86_64_lock, saved_mask); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ginit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ginit.c new file mode 100644 index 0000000..2a84a1e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ginit.c @@ -0,0 +1,342 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002 Hewlett-Packard Co + Copyright (C) 2007 David Mosberger-Tang + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "unwind_i.h" + +#ifdef UNW_REMOTE_ONLY + +/* unw_local_addr_space is a NULL pointer in this case. */ +unw_addr_space_t unw_local_addr_space; + +#else /* !UNW_REMOTE_ONLY */ + +static struct unw_addr_space local_addr_space; + +unw_addr_space_t unw_local_addr_space = &local_addr_space; + +HIDDEN unw_dyn_info_list_t _U_dyn_info_list; + +/* XXX fix me: there is currently no way to locate the dyn-info list + by a remote unwinder. On ia64, this is done via a special + unwind-table entry. Perhaps something similar can be done with + DWARF2 unwind info. */ + +static void +put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) +{ + /* it's a no-op */ +} + +static int +get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, + void *arg) +{ + *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; + return 0; +} + +#define PAGE_SIZE 4096 +#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1)) + +static int mem_validate_pipe[2] = {-1, -1}; + +static inline void +open_pipe (void) +{ + /* ignore errors for closing invalid fd's */ + close (mem_validate_pipe[0]); + close (mem_validate_pipe[1]); + + pipe2 (mem_validate_pipe, O_CLOEXEC | O_NONBLOCK); +} + +ALWAYS_INLINE +static int +write_validate (void *addr) +{ + int ret = -1; + ssize_t bytes = 0; + + do + { + char buf; + bytes = read (mem_validate_pipe[0], &buf, 1); + } + while ( errno == EINTR ); + + int valid_read = (bytes > 0 || errno == EAGAIN || errno == EWOULDBLOCK); + if (!valid_read) + { + // re-open closed pipe + open_pipe (); + } + + do + { + /* use syscall insteadof write() so that ASAN does not complain */ + ret = syscall (SYS_write, mem_validate_pipe[1], addr, 1); + } + while ( errno == EINTR ); + + return ret; +} + +static int (*mem_validate_func) (void *addr, size_t len); +static int msync_validate (void *addr, size_t len) +{ + if (msync (addr, len, MS_ASYNC) != 0) + { + return -1; + } + + return write_validate (addr); +} + +#ifdef HAVE_MINCORE +static int mincore_validate (void *addr, size_t len) +{ + unsigned char mvec[2]; /* Unaligned access may cross page boundary */ + size_t i; + + /* mincore could fail with EAGAIN but we conservatively return -1 + instead of looping. */ + if (mincore (addr, len, mvec) != 0) + { + return -1; + } + + for (i = 0; i < (len + PAGE_SIZE - 1) / PAGE_SIZE; i++) + { + if (!(mvec[i] & 1)) return -1; + } + + return write_validate (addr); +} +#endif + +/* Initialise memory validation method. On linux kernels <2.6.21, + mincore() returns incorrect value for MAP_PRIVATE mappings, + such as stacks. If mincore() was available at compile time, + check if we can actually use it. If not, use msync() instead. */ +HIDDEN void +tdep_init_mem_validate (void) +{ + open_pipe (); + +#ifdef HAVE_MINCORE + unsigned char present = 1; + unw_word_t addr = PAGE_START((unw_word_t)&present); + unsigned char mvec[1]; + int ret; + while ((ret = mincore ((void*)addr, PAGE_SIZE, mvec)) == -1 && + errno == EAGAIN) {} + if (ret == 0 && (mvec[0] & 1)) + { + Debug(1, "using mincore to validate memory\n"); + mem_validate_func = mincore_validate; + } + else +#endif + { + Debug(1, "using msync to validate memory\n"); + mem_validate_func = msync_validate; + } +} + +/* Cache of already validated addresses */ +#define NLGA 4 +static unw_word_t last_good_addr[NLGA]; +static int lga_victim; + +static int +validate_mem (unw_word_t addr) +{ + int i, victim; + size_t len; + + if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr)) + len = PAGE_SIZE; + else + len = PAGE_SIZE * 2; + + addr = PAGE_START(addr); + + if (addr == 0) + return -1; + + for (i = 0; i < NLGA; i++) + { + if (last_good_addr[i] && (addr == last_good_addr[i])) + return 0; + } + + if (mem_validate_func ((void *) addr, len) == -1) + return -1; + + victim = lga_victim; + for (i = 0; i < NLGA; i++) { + if (!last_good_addr[victim]) { + last_good_addr[victim++] = addr; + return 0; + } + victim = (victim + 1) % NLGA; + } + + /* All slots full. Evict the victim. */ + last_good_addr[victim] = addr; + victim = (victim + 1) % NLGA; + lga_victim = victim; + + return 0; +} + +static int +access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, + void *arg) +{ + if (unlikely (write)) + { + Debug (16, "mem[%016lx] <- %lx\n", addr, *val); + *(unw_word_t *) addr = *val; + } + else + { + /* validate address */ + const struct cursor *c = (const struct cursor *)arg; + if (likely (c != NULL) && unlikely (c->validate) + && unlikely (validate_mem (addr))) { + Debug (16, "mem[%016lx] -> invalid\n", addr); + return -1; + } + *val = *(unw_word_t *) addr; + Debug (16, "mem[%016lx] -> %lx\n", addr, *val); + } + return 0; +} + +static int +access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, + void *arg) +{ + unw_word_t *addr; + ucontext_t *uc = ((struct cursor *)arg)->uc; + + if (unw_is_fpreg (reg)) + goto badreg; + + if (!(addr = x86_64_r_uc_addr (uc, reg))) + goto badreg; + + if (write) + { + *(unw_word_t *) addr = *val; + Debug (12, "%s <- 0x%016lx\n", unw_regname (reg), *val); + } + else + { + *val = *(unw_word_t *) addr; + Debug (12, "%s -> 0x%016lx\n", unw_regname (reg), *val); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} + +static int +access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + ucontext_t *uc = ((struct cursor *)arg)->uc; + unw_fpreg_t *addr; + + if (!unw_is_fpreg (reg)) + goto badreg; + + if (!(addr = x86_64_r_uc_addr (uc, reg))) + goto badreg; + + if (write) + { + Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg), + ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); + *(unw_fpreg_t *) addr = *val; + } + else + { + *val = *(unw_fpreg_t *) addr; + Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg), + ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + /* attempt to access a non-preserved register */ + return -UNW_EBADREG; +} + +static int +get_static_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, + void *arg) +{ + return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp); +} + +HIDDEN void +x86_64_local_addr_space_init (void) +{ + memset (&local_addr_space, 0, sizeof (local_addr_space)); + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; + local_addr_space.acc.find_proc_info = dwarf_find_proc_info; + local_addr_space.acc.put_unwind_info = put_unwind_info; + local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; + local_addr_space.acc.access_mem = access_mem; + local_addr_space.acc.access_reg = access_reg; + local_addr_space.acc.access_fpreg = access_fpreg; + local_addr_space.acc.resume = x86_64_local_resume; + local_addr_space.acc.get_proc_name = get_static_proc_name; + unw_flush_cache (&local_addr_space, 0, 0); + + memset (last_good_addr, 0, sizeof (unw_word_t) * NLGA); + lga_victim = 0; +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ginit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ginit_local.c new file mode 100644 index 0000000..5eaead0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ginit_local.c @@ -0,0 +1,81 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "init.h" + +#ifdef UNW_REMOTE_ONLY + +int +unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) +{ + return -UNW_EINVAL; +} + +#else /* !UNW_REMOTE_ONLY */ + +static int +unw_init_local_common (unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr) +{ + struct cursor *c = (struct cursor *) cursor; + + if (unlikely (!tdep_init_done)) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = unw_local_addr_space; + c->dwarf.as_arg = c; + c->uc = uc; + c->validate = 0; + return common_init (c, use_prev_instr); +} + +int +unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) +{ + return unw_init_local_common(cursor, uc, 1); +} + +int +unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) +{ + if (!flag) + { + return unw_init_local_common(cursor, uc, 1); + } + else if (flag == UNW_INIT_SIGNAL_FRAME) + { + return unw_init_local_common(cursor, uc, 0); + } + else + { + return -UNW_EINVAL; + } +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ginit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ginit_remote.c new file mode 100644 index 0000000..efd61d6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ginit_remote.c @@ -0,0 +1,57 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "init.h" +#include "unwind_i.h" + +int +unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) +{ +#ifdef UNW_LOCAL_ONLY + return -UNW_EINVAL; +#else /* !UNW_LOCAL_ONLY */ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = as; + if (as == unw_local_addr_space) + { + c->dwarf.as_arg = c; + c->uc = as_arg; + } + else + { + c->dwarf.as_arg = as_arg; + c->uc = NULL; + } + return common_init (c, 0); +#endif /* !UNW_LOCAL_ONLY */ +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gos-freebsd.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gos-freebsd.c new file mode 100644 index 0000000..883025c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gos-freebsd.c @@ -0,0 +1,218 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2010 Konstantin Belousov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include "unwind_i.h" +#include "ucontext_i.h" + +int +unw_is_signal_frame (unw_cursor_t *cursor) +{ + /* XXXKIB */ + struct cursor *c = (struct cursor *) cursor; + unw_word_t w0, w1, w2, b0, ip; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + int ret; + + as = c->dwarf.as; + a = unw_get_accessors_int (as); + arg = c->dwarf.as_arg; + + /* Check if RIP points at sigreturn sequence. +48 8d 7c 24 10 lea SIGF_UC(%rsp),%rdi +6a 00 pushq $0 +48 c7 c0 a1 01 00 00 movq $SYS_sigreturn,%rax +0f 05 syscall +f4 0: hlt +eb fd jmp 0b + */ + + ip = c->dwarf.ip; + c->sigcontext_format = X86_64_SCF_NONE; + if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0 + || (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0 + || (ret = (*a->access_mem) (as, ip + 16, &w2, 0, arg)) < 0) + return 0; + w2 &= 0xffffff; + if (w0 == 0x48006a10247c8d48 && + w1 == 0x050f000001a1c0c7 && + w2 == 0x0000000000fdebf4) + { + c->sigcontext_format = X86_64_SCF_FREEBSD_SIGFRAME; + return (c->sigcontext_format); + } + /* Check if RIP points at standard syscall sequence. +49 89 ca mov %rcx,%r10 +0f 05 syscall + */ + if ((ret = (*a->access_mem) (as, ip - 5, &b0, 0, arg)) < 0) + return (0); + Debug (12, "b0 0x%lx\n", b0); + if ((b0 & 0xffffffffffffff) == 0x050fca89490000 || + (b0 & 0xffffffffff) == 0x050fca8949) + { + c->sigcontext_format = X86_64_SCF_FREEBSD_SYSCALL; + return (c->sigcontext_format); + } + return (X86_64_SCF_NONE); +} + +HIDDEN int +x86_64_handle_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + unw_word_t ucontext; + int ret; + + if (c->sigcontext_format == X86_64_SCF_FREEBSD_SIGFRAME) + { + ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc); + c->sigcontext_addr = c->dwarf.cfa; + Debug(1, "signal frame, skip over trampoline\n"); + + struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); + ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa); + if (ret < 0) + { + Debug (2, "returning %d\n", ret); + return ret; + } + + c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0); + c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0); + c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0); + c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0); + c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0); + c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0); + c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0); + c->dwarf.loc[RSP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); + c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); + c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); + c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); + c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); + c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); + c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); + c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); + c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); + c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); + + return 0; + } + else if (c->sigcontext_format == X86_64_SCF_FREEBSD_SYSCALL) + { + c->dwarf.loc[RCX] = c->dwarf.loc[R10]; + /* rsp_loc = DWARF_LOC(c->dwarf.cfa - 8, 0); */ + /* rbp_loc = c->dwarf.loc[RBP]; */ + c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); + ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); + Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", + (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]), + (unsigned long long) c->dwarf.ip); + if (ret < 0) + { + Debug (2, "returning %d\n", ret); + return ret; + } + c->dwarf.cfa += 8; + c->dwarf.use_prev_instr = 1; + return 1; + } + else + return -UNW_EBADFRAME; + +} + +#ifndef UNW_REMOTE_ONLY +HIDDEN void * +x86_64_r_uc_addr (ucontext_t *uc, int reg) +{ + /* NOTE: common_init() in init.h inlines these for fast path access. */ + void *addr; + + switch (reg) + { + case UNW_X86_64_R8: addr = &uc->uc_mcontext.mc_r8; break; + case UNW_X86_64_R9: addr = &uc->uc_mcontext.mc_r9; break; + case UNW_X86_64_R10: addr = &uc->uc_mcontext.mc_r10; break; + case UNW_X86_64_R11: addr = &uc->uc_mcontext.mc_r11; break; + case UNW_X86_64_R12: addr = &uc->uc_mcontext.mc_r12; break; + case UNW_X86_64_R13: addr = &uc->uc_mcontext.mc_r13; break; + case UNW_X86_64_R14: addr = &uc->uc_mcontext.mc_r14; break; + case UNW_X86_64_R15: addr = &uc->uc_mcontext.mc_r15; break; + case UNW_X86_64_RDI: addr = &uc->uc_mcontext.mc_rdi; break; + case UNW_X86_64_RSI: addr = &uc->uc_mcontext.mc_rsi; break; + case UNW_X86_64_RBP: addr = &uc->uc_mcontext.mc_rbp; break; + case UNW_X86_64_RBX: addr = &uc->uc_mcontext.mc_rbx; break; + case UNW_X86_64_RDX: addr = &uc->uc_mcontext.mc_rdx; break; + case UNW_X86_64_RAX: addr = &uc->uc_mcontext.mc_rax; break; + case UNW_X86_64_RCX: addr = &uc->uc_mcontext.mc_rcx; break; + case UNW_X86_64_RSP: addr = &uc->uc_mcontext.mc_rsp; break; + case UNW_X86_64_RIP: addr = &uc->uc_mcontext.mc_rip; break; + + default: + addr = NULL; + } + return addr; +} + +HIDDEN NORETURN void +x86_64_sigreturn (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + ucontext_t *uc = (ucontext_t *)(c->sigcontext_addr + + offsetof(struct sigframe, sf_uc)); + + uc->uc_mcontext.mc_r8 = c->uc->uc_mcontext.mc_r8; + uc->uc_mcontext.mc_r9 = c->uc->uc_mcontext.mc_r9; + uc->uc_mcontext.mc_r10 = c->uc->uc_mcontext.mc_r10; + uc->uc_mcontext.mc_r11 = c->uc->uc_mcontext.mc_r11; + uc->uc_mcontext.mc_r12 = c->uc->uc_mcontext.mc_r12; + uc->uc_mcontext.mc_r13 = c->uc->uc_mcontext.mc_r13; + uc->uc_mcontext.mc_r14 = c->uc->uc_mcontext.mc_r14; + uc->uc_mcontext.mc_r15 = c->uc->uc_mcontext.mc_r15; + uc->uc_mcontext.mc_rdi = c->uc->uc_mcontext.mc_rdi; + uc->uc_mcontext.mc_rsi = c->uc->uc_mcontext.mc_rsi; + uc->uc_mcontext.mc_rbp = c->uc->uc_mcontext.mc_rbp; + uc->uc_mcontext.mc_rbx = c->uc->uc_mcontext.mc_rbx; + uc->uc_mcontext.mc_rdx = c->uc->uc_mcontext.mc_rdx; + uc->uc_mcontext.mc_rax = c->uc->uc_mcontext.mc_rax; + uc->uc_mcontext.mc_rcx = c->uc->uc_mcontext.mc_rcx; + uc->uc_mcontext.mc_rsp = c->uc->uc_mcontext.mc_rsp; + uc->uc_mcontext.mc_rip = c->uc->uc_mcontext.mc_rip; + + Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", + (unsigned long long) c->dwarf.ip, uc); + sigreturn(uc); + abort(); +} +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gos-linux.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gos-linux.c new file mode 100644 index 0000000..bd14234 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gos-linux.c @@ -0,0 +1,156 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "ucontext_i.h" + +#include + +HIDDEN void +tdep_fetch_frame (struct dwarf_cursor *dw, unw_word_t ip, int need_unwind_info) +{ + struct cursor *c = (struct cursor *) dw; + assert(! need_unwind_info || dw->pi_valid); + assert(! need_unwind_info || dw->pi.unwind_info); + if (dw->pi_valid + && dw->pi.unwind_info + && ((struct dwarf_cie_info *) dw->pi.unwind_info)->signal_frame) + c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME; + else + c->sigcontext_format = X86_64_SCF_NONE; + + Debug(5, "fetch frame ip=0x%lx cfa=0x%lx format=%d\n", + dw->ip, dw->cfa, c->sigcontext_format); +} + +HIDDEN int +tdep_cache_frame (struct dwarf_cursor *dw) +{ + struct cursor *c = (struct cursor *) dw; + + Debug(5, "cache frame ip=0x%lx cfa=0x%lx format=%d\n", + dw->ip, dw->cfa, c->sigcontext_format); + return c->sigcontext_format; +} + +HIDDEN void +tdep_reuse_frame (struct dwarf_cursor *dw, int frame) +{ + struct cursor *c = (struct cursor *) dw; + c->sigcontext_format = frame; + if (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME) + { + c->frame_info.frame_type = UNW_X86_64_FRAME_SIGRETURN; + /* Offset from cfa to ucontext_t in signal frame. */ + c->frame_info.cfa_reg_offset = 0; + c->sigcontext_addr = dw->cfa; + } + + Debug(5, "reuse frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx offset=%+d\n", + dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr, + (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME + ? c->frame_info.cfa_reg_offset : 0)); +} + +int +unw_is_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + return c->sigcontext_format != X86_64_SCF_NONE; +} + +HIDDEN int +x86_64_handle_signal_frame (unw_cursor_t *cursor) +{ +#if UNW_DEBUG /* To silence compiler warnings */ + /* Should not get here because we now use kernel-provided dwarf + information for the signal trampoline and dwarf_step() works. + Hence unw_step() should never call this function. Maybe + restore old non-dwarf signal handling here, but then the + gating on unw_is_signal_frame() needs to be removed. */ + struct cursor *c = (struct cursor *) cursor; + Debug(1, "old format signal frame? format=%d addr=0x%lx cfa=0x%lx\n", + c->sigcontext_format, c->sigcontext_addr, c->dwarf.cfa); +#endif + return -UNW_EBADFRAME; +} + +#ifndef UNW_REMOTE_ONLY +HIDDEN void * +x86_64_r_uc_addr (ucontext_t *uc, int reg) +{ + /* NOTE: common_init() in init.h inlines these for fast path access. */ + void *addr; + + switch (reg) + { + case UNW_X86_64_R8: addr = &uc->uc_mcontext.gregs[REG_R8]; break; + case UNW_X86_64_R9: addr = &uc->uc_mcontext.gregs[REG_R9]; break; + case UNW_X86_64_R10: addr = &uc->uc_mcontext.gregs[REG_R10]; break; + case UNW_X86_64_R11: addr = &uc->uc_mcontext.gregs[REG_R11]; break; + case UNW_X86_64_R12: addr = &uc->uc_mcontext.gregs[REG_R12]; break; + case UNW_X86_64_R13: addr = &uc->uc_mcontext.gregs[REG_R13]; break; + case UNW_X86_64_R14: addr = &uc->uc_mcontext.gregs[REG_R14]; break; + case UNW_X86_64_R15: addr = &uc->uc_mcontext.gregs[REG_R15]; break; + case UNW_X86_64_RDI: addr = &uc->uc_mcontext.gregs[REG_RDI]; break; + case UNW_X86_64_RSI: addr = &uc->uc_mcontext.gregs[REG_RSI]; break; + case UNW_X86_64_RBP: addr = &uc->uc_mcontext.gregs[REG_RBP]; break; + case UNW_X86_64_RBX: addr = &uc->uc_mcontext.gregs[REG_RBX]; break; + case UNW_X86_64_RDX: addr = &uc->uc_mcontext.gregs[REG_RDX]; break; + case UNW_X86_64_RAX: addr = &uc->uc_mcontext.gregs[REG_RAX]; break; + case UNW_X86_64_RCX: addr = &uc->uc_mcontext.gregs[REG_RCX]; break; + case UNW_X86_64_RSP: addr = &uc->uc_mcontext.gregs[REG_RSP]; break; + case UNW_X86_64_RIP: addr = &uc->uc_mcontext.gregs[REG_RIP]; break; + + default: + addr = NULL; + } + return addr; +} + +/* sigreturn() is a no-op on x86_64 glibc. */ +HIDDEN NORETURN void +x86_64_sigreturn (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; + mcontext_t *sc_mcontext = &((ucontext_t*)sc)->uc_mcontext; + /* Copy in saved uc - all preserved regs are at the start of sigcontext */ + memcpy(sc_mcontext, &c->uc->uc_mcontext, + DWARF_NUM_PRESERVED_REGS * sizeof(unw_word_t)); + + Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", + (unsigned long long) c->dwarf.ip, sc); + __asm__ __volatile__ ("mov %0, %%rsp;" + "mov %1, %%rax;" + "syscall" + :: "r"(sc), "i"(SYS_rt_sigreturn) + : "memory"); + abort(); +} + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Greg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Greg_states_iterate.c new file mode 100644 index 0000000..a17dc1b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Greg_states_iterate.c @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_reg_states_iterate (unw_cursor_t *cursor, + unw_reg_states_callback cb, void *token) +{ + struct cursor *c = (struct cursor *) cursor; + + return dwarf_reg_states_iterate (&c->dwarf, cb, token); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gregs.c new file mode 100644 index 0000000..baf8a24 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gregs.c @@ -0,0 +1,138 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +#if 0 +static inline dwarf_loc_t +linux_scratch_loc (struct cursor *c, unw_regnum_t reg) +{ + unw_word_t addr = c->sigcontext_addr; + + switch (c->sigcontext_format) + { + case X86_64_SCF_NONE: + return DWARF_REG_LOC (&c->dwarf, reg); + + case X86_64_SCF_LINUX_RT_SIGFRAME: + addr += LINUX_UC_MCONTEXT_OFF; + break; + + case X86_64_SCF_FREEBSD_SIGFRAME: + addr += FREEBSD_UC_MCONTEXT_OFF; + break; + } + + return DWARF_REG_LOC (&c->dwarf, reg); + +} + +HIDDEN dwarf_loc_t +x86_64_scratch_loc (struct cursor *c, unw_regnum_t reg) +{ + if (c->sigcontext_addr) + return linux_scratch_loc (c, reg); + else + return DWARF_REG_LOC (&c->dwarf, reg); +} +#endif + +HIDDEN int +tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + int write) +{ + dwarf_loc_t loc = DWARF_NULL_LOC; + unsigned int mask; + int arg_num; + + switch (reg) + { + + case UNW_X86_64_RIP: + if (write) + c->dwarf.ip = *valp; /* also update the RIP cache */ + loc = c->dwarf.loc[RIP]; + break; + + case UNW_X86_64_CFA: + case UNW_X86_64_RSP: + if (write) + return -UNW_EREADONLYREG; + *valp = c->dwarf.cfa; + return 0; + + case UNW_X86_64_RAX: + case UNW_X86_64_RDX: + arg_num = reg - UNW_X86_64_RAX; + mask = (1 << arg_num); + if (write) + { + c->dwarf.eh_args[arg_num] = *valp; + c->dwarf.eh_valid_mask |= mask; + return 0; + } + else if ((c->dwarf.eh_valid_mask & mask) != 0) + { + *valp = c->dwarf.eh_args[arg_num]; + return 0; + } + else + loc = c->dwarf.loc[(reg == UNW_X86_64_RAX) ? RAX : RDX]; + break; + + case UNW_X86_64_RCX: loc = c->dwarf.loc[RCX]; break; + case UNW_X86_64_RBX: loc = c->dwarf.loc[RBX]; break; + + case UNW_X86_64_RBP: loc = c->dwarf.loc[RBP]; break; + case UNW_X86_64_RSI: loc = c->dwarf.loc[RSI]; break; + case UNW_X86_64_RDI: loc = c->dwarf.loc[RDI]; break; + case UNW_X86_64_R8: loc = c->dwarf.loc[R8]; break; + case UNW_X86_64_R9: loc = c->dwarf.loc[R9]; break; + case UNW_X86_64_R10: loc = c->dwarf.loc[R10]; break; + case UNW_X86_64_R11: loc = c->dwarf.loc[R11]; break; + case UNW_X86_64_R12: loc = c->dwarf.loc[R12]; break; + case UNW_X86_64_R13: loc = c->dwarf.loc[R13]; break; + case UNW_X86_64_R14: loc = c->dwarf.loc[R14]; break; + case UNW_X86_64_R15: loc = c->dwarf.loc[R15]; break; + + default: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; + } + + if (write) + return dwarf_put (&c->dwarf, loc, *valp); + else + return dwarf_get (&c->dwarf, loc, valp); +} + +HIDDEN int +tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, + int write) +{ + return -UNW_EBADREG; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gresume.c new file mode 100644 index 0000000..944cdaa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gresume.c @@ -0,0 +1,123 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "offsets.h" +#include "unwind_i.h" + +#ifndef UNW_REMOTE_ONLY + +HIDDEN inline int +x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ + struct cursor *c = (struct cursor *) cursor; + ucontext_t *uc = c->uc; + + /* Ensure c->pi is up-to-date. On x86-64, it's relatively common to + be missing DWARF unwind info. We don't want to fail in that + case, because the frame-chain still would let us do a backtrace + at least. */ + dwarf_make_proc_info (&c->dwarf); + + if (unlikely (c->sigcontext_addr != X86_64_SCF_NONE)) + { + x86_64_sigreturn(cursor); + abort(); + } + else + { + Debug (8, "resuming at ip=%llx via setcontext()\n", + (unsigned long long) c->dwarf.ip); + setcontext (uc); + } + return -UNW_EINVAL; +} + +#endif /* !UNW_REMOTE_ONLY */ + +/* This routine is responsible for copying the register values in + cursor C and establishing them as the current machine state. */ + +static inline int +establish_machine_state (struct cursor *c) +{ + int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, + int write, void *); + int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *, + int write, void *); + unw_addr_space_t as = c->dwarf.as; + void *arg = c->dwarf.as_arg; + unw_fpreg_t fpval; + unw_word_t val; + int reg; + + access_reg = as->acc.access_reg; + access_fpreg = as->acc.access_fpreg; + + Debug (8, "copying out cursor state\n"); + + for (reg = 0; reg <= UNW_REG_LAST; ++reg) + { + Debug (16, "copying %s %d\n", unw_regname (reg), reg); + if (unw_is_fpreg (reg)) + { + if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) + (*access_fpreg) (as, reg, &fpval, 1, arg); + } + else + { + if (tdep_access_reg (c, reg, &val, 0) >= 0) + (*access_reg) (as, reg, &val, 1, arg); + } + } + + if (c->dwarf.args_size) + { + if (tdep_access_reg (c, UNW_X86_64_RSP, &val, 0) >= 0) + { + val += c->dwarf.args_size; + (*access_reg) (as, UNW_X86_64_RSP, &val, 1, arg); + } + } + return 0; +} + +int +unw_resume (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + Debug (1, "(cursor=%p)\n", c); + + if ((ret = establish_machine_state (c)) < 0) + return ret; + + return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, + c->dwarf.as_arg); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gstash_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gstash_frame.c new file mode 100644 index 0000000..2c7bc31 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gstash_frame.c @@ -0,0 +1,119 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "ucontext_i.h" + +HIDDEN void +tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs) +{ + struct cursor *c = (struct cursor *) dwarf_to_cursor (d); + unw_tdep_frame_t *f = &c->frame_info; + + Debug (4, "ip=0x%lx cfa=0x%lx type %d cfa [where=%d val=%ld] cfaoff=%ld" + " ra=0x%lx rbp [where=%d val=%ld @0x%lx] rsp [where=%d val=%ld @0x%lx]\n", + d->ip, d->cfa, f->frame_type, + rs->reg.where[DWARF_CFA_REG_COLUMN], + rs->reg.val[DWARF_CFA_REG_COLUMN], + rs->reg.val[DWARF_CFA_OFF_COLUMN], + DWARF_GET_LOC(d->loc[rs->ret_addr_column]), + rs->reg.where[RBP], rs->reg.val[RBP], DWARF_GET_LOC(d->loc[RBP]), + rs->reg.where[RSP], rs->reg.val[RSP], DWARF_GET_LOC(d->loc[RSP])); + + if (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_EXPR && + rs->reg.where[RBP] == DWARF_WHERE_EXPR) { + /* Check for GCC generated alignment frame for rsp. A simple + * def_cfa_expr that loads a constant offset from rbp, where the + * addres of the rip was pushed on the stack */ + unw_word_t cfa_addr = rs->reg.val[DWARF_CFA_REG_COLUMN]; + unw_word_t rbp_addr = rs->reg.val[RBP]; + unw_word_t cfa_offset; + + int ret = dwarf_stack_aligned(d, cfa_addr, rbp_addr, &cfa_offset); + if (ret) { + f->frame_type = UNW_X86_64_FRAME_ALIGNED; + f->cfa_reg_offset = cfa_offset; + f->cfa_reg_rsp = 0; + } + } + + /* A standard frame is defined as: + - CFA is register-relative offset off RBP or RSP; + - Return address is saved at CFA-8; + - RBP is unsaved or saved at CFA+offset, offset != -1; + - RSP is unsaved or saved at CFA+offset, offset != -1. */ + if (f->frame_type == UNW_X86_64_FRAME_OTHER + && (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG) + && (rs->reg.val[DWARF_CFA_REG_COLUMN] == RBP + || rs->reg.val[DWARF_CFA_REG_COLUMN] == RSP) + && labs((long) rs->reg.val[DWARF_CFA_OFF_COLUMN]) < (1 << 28) + && DWARF_GET_LOC(d->loc[rs->ret_addr_column]) == d->cfa-8 + && (rs->reg.where[RBP] == DWARF_WHERE_UNDEF + || rs->reg.where[RBP] == DWARF_WHERE_SAME + || (rs->reg.where[RBP] == DWARF_WHERE_CFAREL + && labs((long) rs->reg.val[RBP]) < (1 << 14) + && rs->reg.val[RBP]+1 != 0)) + && (rs->reg.where[RSP] == DWARF_WHERE_UNDEF + || rs->reg.where[RSP] == DWARF_WHERE_SAME + || (rs->reg.where[RSP] == DWARF_WHERE_CFAREL + && labs((long) rs->reg.val[RSP]) < (1 << 14) + && rs->reg.val[RSP]+1 != 0))) + { + /* Save information for a standard frame. */ + f->frame_type = UNW_X86_64_FRAME_STANDARD; + f->cfa_reg_rsp = (rs->reg.val[DWARF_CFA_REG_COLUMN] == RSP); + f->cfa_reg_offset = rs->reg.val[DWARF_CFA_OFF_COLUMN]; + if (rs->reg.where[RBP] == DWARF_WHERE_CFAREL) + f->rbp_cfa_offset = rs->reg.val[RBP]; + if (rs->reg.where[RSP] == DWARF_WHERE_CFAREL) + f->rsp_cfa_offset = rs->reg.val[RSP]; + Debug (4, " standard frame\n"); + } + + /* Signal frame was detected via augmentation in tdep_fetch_frame() */ + else if (f->frame_type == UNW_X86_64_FRAME_SIGRETURN) + { + /* Later we are going to fish out {RBP,RSP,RIP} from sigcontext via + their ucontext_t offsets. Confirm DWARF info agrees with the + offsets we expect. */ + +#ifndef NDEBUG + const unw_word_t uc = c->sigcontext_addr; + + assert (DWARF_GET_LOC(d->loc[RIP]) - uc == UC_MCONTEXT_GREGS_RIP); + assert (DWARF_GET_LOC(d->loc[RBP]) - uc == UC_MCONTEXT_GREGS_RBP); + assert (DWARF_GET_LOC(d->loc[RSP]) - uc == UC_MCONTEXT_GREGS_RSP); +#endif + + Debug (4, " sigreturn frame\n"); + } + + else if (f->frame_type == UNW_X86_64_FRAME_ALIGNED) { + Debug (4, " aligned frame, offset %li\n", f->cfa_reg_offset); + } + + /* PLT and guessed RBP-walked frames are handled in unw_step(). */ + else + Debug (4, " unusual frame\n"); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gstep.c new file mode 100644 index 0000000..1049817 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gstep.c @@ -0,0 +1,227 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include + +/* Recognise PLT entries such as: + 3bdf0: ff 25 e2 49 13 00 jmpq *0x1349e2(%rip) + 3bdf6: 68 ae 03 00 00 pushq $0x3ae + 3bdfb: e9 00 c5 ff ff jmpq 38300 <_init+0x18> */ +static int +is_plt_entry (struct dwarf_cursor *c) +{ + unw_word_t w0, w1; + unw_accessors_t *a; + int ret; + + a = unw_get_accessors_int (c->as); + if ((ret = (*a->access_mem) (c->as, c->ip, &w0, 0, c->as_arg)) < 0 + || (ret = (*a->access_mem) (c->as, c->ip + 8, &w1, 0, c->as_arg)) < 0) + return 0; + + ret = (((w0 & 0xffff) == 0x25ff) + && (((w0 >> 48) & 0xff) == 0x68) + && (((w1 >> 24) & 0xff) == 0xe9)); + + Debug (14, "ip=0x%lx => 0x%016lx 0x%016lx, ret = %d\n", c->ip, w0, w1, ret); + return ret; +} + +int +unw_step (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret, i; + +#if CONSERVATIVE_CHECKS + int val = c->validate; + c->validate = 1; +#endif + + Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx)\n", + c, c->dwarf.ip, c->dwarf.cfa); + + /* Try DWARF-based unwinding... */ + c->sigcontext_format = X86_64_SCF_NONE; + ret = dwarf_step (&c->dwarf); + +#if CONSERVATIVE_CHECKS + c->validate = val; +#endif + + if (ret < 0 && ret != -UNW_ENOINFO) + { + Debug (2, "returning %d\n", ret); + return ret; + } + + if (likely (ret >= 0)) + { + /* x86_64 ABI specifies that end of call-chain is marked with a + NULL RBP or undefined return address */ + if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) + { + c->dwarf.ip = 0; + ret = 0; + } + } + else + { + /* DWARF failed. There isn't much of a usable frame-chain on x86-64, + but we do need to handle two special-cases: + + (i) signal trampoline: Old kernels and older libcs don't + export the vDSO needed to get proper unwind info for the + trampoline. Recognize that case by looking at the code + and filling in things by hand. + + (ii) PLT (shared-library) call-stubs: PLT stubs are invoked + via CALLQ. Try this for all non-signal trampoline + code. */ + + unw_word_t prev_ip = c->dwarf.ip, prev_cfa = c->dwarf.cfa; + struct dwarf_loc rbp_loc, rsp_loc, rip_loc; + + /* We could get here because of missing/bad unwind information. + Validate all addresses before dereferencing. */ + c->validate = 1; + + Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); + + if (unw_is_signal_frame (cursor) > 0) + { + ret = x86_64_handle_signal_frame(cursor); + if (ret < 0) + { + Debug (2, "returning 0\n"); + return 0; + } + } + else if (is_plt_entry (&c->dwarf)) + { + /* Like regular frame, CFA = RSP+8, RA = [CFA-8], no regs saved. */ + Debug (2, "found plt entry\n"); + c->frame_info.cfa_reg_offset = 8; + c->frame_info.cfa_reg_rsp = -1; + c->frame_info.frame_type = UNW_X86_64_FRAME_STANDARD; + c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); + c->dwarf.cfa += 8; + } + else if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) + { + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + } + else + { + unw_word_t rbp; + + ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &rbp); + if (ret < 0) + { + Debug (2, "returning %d [RBP=0x%lx]\n", ret, + DWARF_GET_LOC (c->dwarf.loc[RBP])); + return ret; + } + + if (!rbp) + { + /* Looks like we may have reached the end of the call-chain. */ + rbp_loc = DWARF_NULL_LOC; + rsp_loc = DWARF_NULL_LOC; + rip_loc = DWARF_NULL_LOC; + } + else + { + unw_word_t rbp1 = 0; + rbp_loc = DWARF_LOC(rbp, 0); + rsp_loc = DWARF_NULL_LOC; + rip_loc = DWARF_LOC (rbp + 8, 0); + ret = dwarf_get (&c->dwarf, rbp_loc, &rbp1); + Debug (1, "[RBP=0x%lx] = 0x%lx (cfa = 0x%lx) -> 0x%lx\n", + (unsigned long) DWARF_GET_LOC (c->dwarf.loc[RBP]), + rbp, c->dwarf.cfa, rbp1); + + /* Heuristic to determine incorrect guess. For RBP to be a + valid frame it needs to be above current CFA, but don't + let it go more than a little. Note that we can't deduce + anything about new RBP (rbp1) since it may not be a frame + pointer in the frame above. Just check we get the value. */ + if (ret < 0 + || rbp < c->dwarf.cfa + || (rbp - c->dwarf.cfa) > 0x4000) + { + rip_loc = DWARF_NULL_LOC; + rbp_loc = DWARF_NULL_LOC; + } + + c->frame_info.frame_type = UNW_X86_64_FRAME_GUESSED; + c->frame_info.cfa_reg_rsp = 0; + c->frame_info.cfa_reg_offset = 16; + c->frame_info.rbp_cfa_offset = -16; + c->dwarf.cfa += 16; + } + + /* Mark all registers unsaved */ + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + + c->dwarf.loc[RBP] = rbp_loc; + c->dwarf.loc[RSP] = rsp_loc; + c->dwarf.loc[RIP] = rip_loc; + c->dwarf.use_prev_instr = 1; + } + + if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) + { + ret = 0; + Debug (2, "NULL %%rbp loc, returning %d\n", ret); + return ret; + } + if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RIP])) + { + ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); + Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", + (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]), + (unsigned long long) c->dwarf.ip); + if (ret < 0) + { + Debug (2, "returning %d\n", ret); + return ret; + } + ret = 1; + } + else + c->dwarf.ip = 0; + + if (c->dwarf.ip == prev_ip && c->dwarf.cfa == prev_cfa) + return -UNW_EBADFRAME; + } + Debug (2, "returning %d\n", ret); + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gtrace.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gtrace.c new file mode 100644 index 0000000..7412271 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Gtrace.c @@ -0,0 +1,551 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "ucontext_i.h" +#include +#include + +#pragma weak pthread_once +#pragma weak pthread_key_create +#pragma weak pthread_getspecific +#pragma weak pthread_setspecific + +/* Initial hash table size. Table expands by 2 bits (times four). */ +#define HASH_MIN_BITS 14 + +typedef struct +{ + unw_tdep_frame_t *frames; + size_t log_size; + size_t used; + size_t dtor_count; /* Counts how many times our destructor has already + been called. */ +} unw_trace_cache_t; + +static const unw_tdep_frame_t empty_frame = { 0, UNW_X86_64_FRAME_OTHER, -1, -1, 0, -1, -1 }; +static define_lock (trace_init_lock); +static pthread_once_t trace_cache_once = PTHREAD_ONCE_INIT; +static sig_atomic_t trace_cache_once_happen; +static pthread_key_t trace_cache_key; +static struct mempool trace_cache_pool; +static __thread unw_trace_cache_t *tls_cache; +static __thread int tls_cache_destroyed; + +/* Free memory for a thread's trace cache. */ +static void +trace_cache_free (void *arg) +{ + unw_trace_cache_t *cache = arg; + if (++cache->dtor_count < PTHREAD_DESTRUCTOR_ITERATIONS) + { + /* Not yet our turn to get destroyed. Re-install ourselves into the key. */ + pthread_setspecific(trace_cache_key, cache); + Debug(5, "delayed freeing cache %p (%zx to go)\n", cache, + PTHREAD_DESTRUCTOR_ITERATIONS - cache->dtor_count); + return; + } + tls_cache_destroyed = 1; + tls_cache = NULL; + munmap (cache->frames, (1u << cache->log_size) * sizeof(unw_tdep_frame_t)); + mempool_free (&trace_cache_pool, cache); + Debug(5, "freed cache %p\n", cache); +} + +/* Initialise frame tracing for threaded use. */ +static void +trace_cache_init_once (void) +{ + pthread_key_create (&trace_cache_key, &trace_cache_free); + mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0); + trace_cache_once_happen = 1; +} + +static unw_tdep_frame_t * +trace_cache_buckets (size_t n) +{ + unw_tdep_frame_t *frames; + size_t i; + + GET_MEMORY(frames, n * sizeof (unw_tdep_frame_t)); + if (likely(frames != NULL)) + for (i = 0; i < n; ++i) + frames[i] = empty_frame; + + return frames; +} + +/* Allocate and initialise hash table for frame cache lookups. + Returns the cache initialised with (1u << HASH_LOW_BITS) hash + buckets, or NULL if there was a memory allocation problem. */ +static unw_trace_cache_t * +trace_cache_create (void) +{ + unw_trace_cache_t *cache; + + if (tls_cache_destroyed) + { + /* The current thread is in the process of exiting. Don't recreate + cache, as we wouldn't have another chance to free it. */ + Debug(5, "refusing to reallocate cache: " + "thread-locals are being deallocated\n"); + return NULL; + } + + if (! (cache = mempool_alloc(&trace_cache_pool))) + { + Debug(5, "failed to allocate cache\n"); + return NULL; + } + + if (! (cache->frames = trace_cache_buckets(1u << HASH_MIN_BITS))) + { + Debug(5, "failed to allocate buckets\n"); + mempool_free(&trace_cache_pool, cache); + return NULL; + } + + cache->log_size = HASH_MIN_BITS; + cache->used = 0; + cache->dtor_count = 0; + tls_cache_destroyed = 0; /* Paranoia: should already be 0. */ + Debug(5, "allocated cache %p\n", cache); + return cache; +} + +/* Expand the hash table in the frame cache if possible. This always + quadruples the hash size, and clears all previous frame entries. */ +static int +trace_cache_expand (unw_trace_cache_t *cache) +{ + size_t old_size = (1u << cache->log_size); + size_t new_log_size = cache->log_size + 2; + unw_tdep_frame_t *new_frames = trace_cache_buckets (1u << new_log_size); + + if (unlikely(! new_frames)) + { + Debug(5, "failed to expand cache to 2^%lu buckets\n", new_log_size); + return -UNW_ENOMEM; + } + + Debug(5, "expanded cache from 2^%lu to 2^%lu buckets\n", cache->log_size, new_log_size); + munmap(cache->frames, old_size * sizeof(unw_tdep_frame_t)); + cache->frames = new_frames; + cache->log_size = new_log_size; + cache->used = 0; + return 0; +} + +static unw_trace_cache_t * +trace_cache_get_unthreaded (void) +{ + unw_trace_cache_t *cache; + intrmask_t saved_mask; + static unw_trace_cache_t *global_cache = NULL; + lock_acquire (&trace_init_lock, saved_mask); + if (! global_cache) + { + mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0); + global_cache = trace_cache_create (); + } + cache = global_cache; + lock_release (&trace_init_lock, saved_mask); + Debug(5, "using cache %p\n", cache); + return cache; +} + +/* Get the frame cache for the current thread. Create it if there is none. */ +static unw_trace_cache_t * +trace_cache_get (void) +{ + unw_trace_cache_t *cache; + if (likely (pthread_once != NULL)) + { + pthread_once(&trace_cache_once, &trace_cache_init_once); + if (!trace_cache_once_happen) + { + return trace_cache_get_unthreaded(); + } + if (! (cache = tls_cache)) + { + cache = trace_cache_create(); + pthread_setspecific(trace_cache_key, cache); + tls_cache = cache; + } + Debug(5, "using cache %p\n", cache); + return cache; + } + else + { + return trace_cache_get_unthreaded(); + } +} + +/* Initialise frame properties for address cache slot F at address + RIP using current CFA, RBP and RSP values. Modifies CURSOR to + that location, performs one unw_step(), and fills F with what + was discovered about the location. Returns F. + + FIXME: This probably should tell DWARF handling to never evaluate + or use registers other than RBP, RSP and RIP in case there is + highly unusual unwind info which uses these creatively. */ +static unw_tdep_frame_t * +trace_init_addr (unw_tdep_frame_t *f, + unw_cursor_t *cursor, + unw_word_t cfa, + unw_word_t rip, + unw_word_t rbp, + unw_word_t rsp) +{ + struct cursor *c = (struct cursor *) cursor; + struct dwarf_cursor *d = &c->dwarf; + int ret = -UNW_EINVAL; + + /* Initialise frame properties: unknown, not last. */ + f->virtual_address = rip; + f->frame_type = UNW_X86_64_FRAME_OTHER; + f->last_frame = 0; + f->cfa_reg_rsp = -1; + f->cfa_reg_offset = 0; + f->rbp_cfa_offset = -1; + f->rsp_cfa_offset = -1; + + /* Reinitialise cursor to this instruction - but undo next/prev RIP + adjustment because unw_step will redo it - and force RIP, RBP + RSP into register locations (=~ ucontext we keep), then set + their desired values. Then perform the step. */ + d->ip = rip + d->use_prev_instr; + d->cfa = cfa; + d->loc[UNW_X86_64_RIP] = DWARF_REG_LOC (d, UNW_X86_64_RIP); + d->loc[UNW_X86_64_RBP] = DWARF_REG_LOC (d, UNW_X86_64_RBP); + d->loc[UNW_X86_64_RSP] = DWARF_REG_LOC (d, UNW_X86_64_RSP); + c->frame_info = *f; + + if (likely(dwarf_put (d, d->loc[UNW_X86_64_RIP], rip) >= 0) + && likely(dwarf_put (d, d->loc[UNW_X86_64_RBP], rbp) >= 0) + && likely(dwarf_put (d, d->loc[UNW_X86_64_RSP], rsp) >= 0) + && likely((ret = unw_step (cursor)) >= 0)) + *f = c->frame_info; + + /* If unw_step() stopped voluntarily, remember that, even if it + otherwise could not determine anything useful. This avoids + failing trace if we hit frames without unwind info, which is + common for the outermost frame (CRT stuff) on many systems. + This avoids failing trace in very common circumstances; failing + to unw_step() loop wouldn't produce any better result. */ + if (ret == 0) + f->last_frame = -1; + + Debug (3, "frame va %lx type %d last %d cfa %s+%d rbp @ cfa%+d rsp @ cfa%+d\n", + f->virtual_address, f->frame_type, f->last_frame, + f->cfa_reg_rsp ? "rsp" : "rbp", f->cfa_reg_offset, + f->rbp_cfa_offset, f->rsp_cfa_offset); + + return f; +} + +/* Look up and if necessary fill in frame attributes for address RIP + in CACHE using current CFA, RBP and RSP values. Uses CURSOR to + perform any unwind steps necessary to fill the cache. Returns the + frame cache slot which describes RIP. */ +static unw_tdep_frame_t * +trace_lookup (unw_cursor_t *cursor, + unw_trace_cache_t *cache, + unw_word_t cfa, + unw_word_t rip, + unw_word_t rbp, + unw_word_t rsp) +{ + /* First look up for previously cached information using cache as + linear probing hash table with probe step of 1. Majority of + lookups should be completed within few steps, but it is very + important the hash table does not fill up, or performance falls + off the cliff. */ + uint64_t i, addr; + uint64_t cache_size = 1u << cache->log_size; + uint64_t slot = ((rip * 0x9e3779b97f4a7c16) >> 43) & (cache_size-1); + unw_tdep_frame_t *frame; + + for (i = 0; i < 16; ++i) + { + frame = &cache->frames[slot]; + addr = frame->virtual_address; + + /* Return if we found the address. */ + if (likely(addr == rip)) + { + Debug (4, "found address after %ld steps\n", i); + return frame; + } + + /* If slot is empty, reuse it. */ + if (likely(! addr)) + break; + + /* Linear probe to next slot candidate, step = 1. */ + if (++slot >= cache_size) + slot -= cache_size; + } + + /* If we collided after 16 steps, or if the hash is more than half + full, force the hash to expand. Fill the selected slot, whether + it's free or collides. Note that hash expansion drops previous + contents; further lookups will refill the hash. */ + Debug (4, "updating slot %lu after %ld steps, replacing 0x%lx\n", slot, i, addr); + if (unlikely(addr || cache->used >= cache_size / 2)) + { + if (unlikely(trace_cache_expand (cache) < 0)) + return NULL; + + cache_size = 1u << cache->log_size; + slot = ((rip * 0x9e3779b97f4a7c16) >> 43) & (cache_size-1); + frame = &cache->frames[slot]; + addr = frame->virtual_address; + } + + if (! addr) + ++cache->used; + + return trace_init_addr (frame, cursor, cfa, rip, rbp, rsp); +} + +/* Fast stack backtrace for x86-64. + + This is used by backtrace() implementation to accelerate frequent + queries for current stack, without any desire to unwind. It fills + BUFFER with the call tree from CURSOR upwards for at most SIZE + stack levels. The first frame, backtrace itself, is omitted. When + called, SIZE should give the maximum number of entries that can be + stored into BUFFER. Uses an internal thread-specific cache to + accelerate queries. + + The caller should fall back to a unw_step() loop if this function + fails by returning -UNW_ESTOPUNWIND, meaning the routine hit a + stack frame that is too complex to be traced in the fast path. + + This function is tuned for clients which only need to walk the + stack to get the call tree as fast as possible but without any + other details, for example profilers sampling the stack thousands + to millions of times per second. The routine handles the most + common x86-64 ABI stack layouts: CFA is RBP or RSP plus/minus + constant offset, return address is at CFA-8, and RBP and RSP are + either unchanged or saved on stack at constant offset from the CFA; + the signal return frame; and frames without unwind info provided + they are at the outermost (final) frame or can conservatively be + assumed to be frame-pointer based. + + Any other stack layout will cause the routine to give up. There + are only a handful of relatively rarely used functions which do + not have a stack in the standard form: vfork, longjmp, setcontext + and _dl_runtime_profile on common linux systems for example. + + On success BUFFER and *SIZE reflect the trace progress up to *SIZE + stack levels or the outermost frame, which ever is less. It may + stop short of outermost frame if unw_step() loop would also do so, + e.g. if there is no more unwind information; this is not reported + as an error. + + The function returns a negative value for errors, -UNW_ESTOPUNWIND + if tracing stopped because of an unusual frame unwind info. The + BUFFER and *SIZE reflect tracing progress up to the error frame. + + Callers of this function would normally look like this: + + unw_cursor_t cur; + unw_context_t ctx; + void addrs[128]; + int depth = 128; + int ret; + + unw_getcontext(&ctx); + unw_init_local(&cur, &ctx); + if ((ret = unw_tdep_trace(&cur, addrs, &depth)) < 0) + { + depth = 0; + unw_getcontext(&ctx); + unw_init_local(&cur, &ctx); + while ((ret = unw_step(&cur)) > 0 && depth < 128) + { + unw_word_t ip; + unw_get_reg(&cur, UNW_REG_IP, &ip); + addresses[depth++] = (void *) ip; + } + } +*/ +HIDDEN int +tdep_trace (unw_cursor_t *cursor, void **buffer, int *size) +{ + struct cursor *c = (struct cursor *) cursor; + struct dwarf_cursor *d = &c->dwarf; + unw_trace_cache_t *cache; + unw_word_t rbp, rsp, rip, cfa; + int maxdepth = 0; + int depth = 0; + int ret; + + /* Check input parametres. */ + if (unlikely(! cursor || ! buffer || ! size || (maxdepth = *size) <= 0)) + return -UNW_EINVAL; + + Debug (1, "begin ip 0x%lx cfa 0x%lx\n", d->ip, d->cfa); + + /* Tell core dwarf routines to call back to us. */ + d->stash_frames = 1; + + /* Determine initial register values. These are direct access safe + because we know they come from the initial machine context. */ + rip = d->ip; + rsp = cfa = d->cfa; + ACCESS_MEM_FAST(ret, 0, d, DWARF_GET_LOC(d->loc[UNW_X86_64_RBP]), rbp); + assert(ret == 0); + + /* Get frame cache. */ + if (unlikely(! (cache = trace_cache_get()))) + { + Debug (1, "returning %d, cannot get trace cache\n", -UNW_ENOMEM); + *size = 0; + d->stash_frames = 0; + return -UNW_ENOMEM; + } + + /* Trace the stack upwards, starting from current RIP. Adjust + the RIP address for previous/next instruction as the main + unwinding logic would also do. We undo this before calling + back into unw_step(). */ + while (depth < maxdepth) + { + rip -= d->use_prev_instr; + Debug (2, "depth %d cfa 0x%lx rip 0x%lx rsp 0x%lx rbp 0x%lx\n", + depth, cfa, rip, rsp, rbp); + + /* See if we have this address cached. If not, evaluate enough of + the dwarf unwind information to fill the cache line data, or to + decide this frame cannot be handled in fast trace mode. We + cache negative results too to prevent unnecessary dwarf parsing + for common failures. */ + unw_tdep_frame_t *f = trace_lookup (cursor, cache, cfa, rip, rbp, rsp); + + /* If we don't have information for this frame, give up. */ + if (unlikely(! f)) + { + ret = -UNW_ENOINFO; + break; + } + + Debug (3, "frame va %lx type %d last %d cfa %s+%d rbp @ cfa%+d rsp @ cfa%+d\n", + f->virtual_address, f->frame_type, f->last_frame, + f->cfa_reg_rsp ? "rsp" : "rbp", f->cfa_reg_offset, + f->rbp_cfa_offset, f->rsp_cfa_offset); + + assert (f->virtual_address == rip); + + /* Stop if this was the last frame. In particular don't evaluate + new register values as it may not be safe - we don't normally + run with full validation on, and do not want to - and there's + enough bad unwind info floating around that we need to trust + what unw_step() previously said, in potentially bogus frames. */ + if (f->last_frame) + break; + + /* Evaluate CFA and registers for the next frame. */ + switch (f->frame_type) + { + case UNW_X86_64_FRAME_GUESSED: + /* Fall thru to standard processing after forcing validation. */ + c->validate = 1; + + case UNW_X86_64_FRAME_STANDARD: + /* Advance standard traceable frame. */ + cfa = (f->cfa_reg_rsp ? rsp : rbp) + f->cfa_reg_offset; + ACCESS_MEM_FAST(ret, c->validate, d, cfa - 8, rip); + if (likely(ret >= 0) && likely(f->rbp_cfa_offset != -1)) + ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->rbp_cfa_offset, rbp); + + /* Don't bother reading RSP from DWARF, CFA becomes new RSP. */ + rsp = cfa; + + /* Next frame needs to back up for unwind info lookup. */ + d->use_prev_instr = 1; + break; + + case UNW_X86_64_FRAME_SIGRETURN: + cfa = cfa + f->cfa_reg_offset; /* cfa now points to ucontext_t. */ + + ACCESS_MEM_FAST(ret, c->validate, d, cfa + UC_MCONTEXT_GREGS_RIP, rip); + if (likely(ret >= 0)) + ACCESS_MEM_FAST(ret, c->validate, d, cfa + UC_MCONTEXT_GREGS_RBP, rbp); + if (likely(ret >= 0)) + ACCESS_MEM_FAST(ret, c->validate, d, cfa + UC_MCONTEXT_GREGS_RSP, rsp); + + /* Resume stack at signal restoration point. The stack is not + necessarily continuous here, especially with sigaltstack(). */ + cfa = rsp; + + /* Next frame should not back up. */ + d->use_prev_instr = 0; + break; + + case UNW_X86_64_FRAME_ALIGNED: + /* Address of RIP was pushed on the stack via a simple + * def_cfa_expr - result stack offset stored in cfa_reg_offset */ + cfa = (f->cfa_reg_rsp ? rsp : rbp) + f->cfa_reg_offset; + ACCESS_MEM_FAST(ret, c->validate, d, cfa, cfa); + if (likely(ret >= 0)) + ACCESS_MEM_FAST(ret, c->validate, d, cfa - 8, rip); + if (likely(ret >= 0)) + ACCESS_MEM_FAST(ret, c->validate, d, rbp, rbp); + + /* Don't bother reading RSP from DWARF, CFA becomes new RSP. */ + rsp = cfa; + + /* Next frame needs to back up for unwind info lookup. */ + d->use_prev_instr = 1; + + break; + + default: + /* We cannot trace through this frame, give up and tell the + caller we had to stop. Data collected so far may still be + useful to the caller, so let it know how far we got. */ + ret = -UNW_ESTOPUNWIND; + break; + } + + Debug (4, "new cfa 0x%lx rip 0x%lx rsp 0x%lx rbp 0x%lx\n", + cfa, rip, rsp, rbp); + + /* If we failed or ended up somewhere bogus, stop. */ + if (unlikely(ret < 0 || rip < 0x4000)) + break; + + /* Record this address in stack trace. We skipped the first address. */ + buffer[depth++] = (void *) (rip - d->use_prev_instr); + } + +#if UNW_DEBUG + Debug (1, "returning %d, depth %d\n", ret, depth); +#endif + *size = depth; + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lapply_reg_state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lapply_reg_state.c new file mode 100644 index 0000000..7ebada4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lapply_reg_state.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gapply_reg_state.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lcreate_addr_space.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lcreate_addr_space.c new file mode 100644 index 0000000..0f2dc6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lcreate_addr_space.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gcreate_addr_space.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lget_proc_info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lget_proc_info.c new file mode 100644 index 0000000..69028b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lget_proc_info.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_proc_info.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lget_save_loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lget_save_loc.c new file mode 100644 index 0000000..9ea048a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lget_save_loc.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_save_loc.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lglobal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lglobal.c new file mode 100644 index 0000000..8c43a67 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lglobal.c @@ -0,0 +1,6 @@ +#define UNW_LOCAL_ONLY +#include "config.h" +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gglobal.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Linit.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Linit.c new file mode 100644 index 0000000..e9abfdd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Linit.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Linit_local.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Linit_local.c new file mode 100644 index 0000000..68a1687 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Linit_local.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_local.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Linit_remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Linit_remote.c new file mode 100644 index 0000000..58cb04a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Linit_remote.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_remote.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Los-freebsd.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Los-freebsd.c new file mode 100644 index 0000000..a75a205 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Los-freebsd.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gos-freebsd.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Los-linux.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Los-linux.c new file mode 100644 index 0000000..3cc18aa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Los-linux.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gos-linux.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lreg_states_iterate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lreg_states_iterate.c new file mode 100644 index 0000000..f1eb1e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lreg_states_iterate.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Greg_states_iterate.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lregs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lregs.c new file mode 100644 index 0000000..2c9c75c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lregs.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gregs.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lresume.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lresume.c new file mode 100644 index 0000000..41a8cf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lresume.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gresume.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lstash_frame.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lstash_frame.c new file mode 100644 index 0000000..7758780 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lstash_frame.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gstash_frame.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lstep.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lstep.c new file mode 100644 index 0000000..c1ac3c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Lstep.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gstep.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ltrace.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ltrace.c new file mode 100644 index 0000000..fcd3f23 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/Ltrace.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gtrace.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/getcontext.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/getcontext.S new file mode 100644 index 0000000..7a8b566 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/getcontext.S @@ -0,0 +1,134 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 Google, Inc + Contributed by Paul Pluzhnikov + Copyright (C) 2010 Konstantin Belousov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "ucontext_i.h" + +/* int _Ux86_64_getcontext (ucontext_t *ucp) + + Saves the machine context in UCP necessary for libunwind. + Unlike the libc implementation, we don't save the signal mask + and hence avoid the cost of a system call per unwind. + +*/ + + .global _Ux86_64_getcontext + .type _Ux86_64_getcontext, @function +_Ux86_64_getcontext: + .cfi_startproc + + /* Callee saved: RBX, RBP, R12-R15 */ + movq %r12, UC_MCONTEXT_GREGS_R12(%rdi) + movq %r13, UC_MCONTEXT_GREGS_R13(%rdi) + movq %r14, UC_MCONTEXT_GREGS_R14(%rdi) + movq %r15, UC_MCONTEXT_GREGS_R15(%rdi) + movq %rbp, UC_MCONTEXT_GREGS_RBP(%rdi) + movq %rbx, UC_MCONTEXT_GREGS_RBX(%rdi) + + /* Save argument registers (not strictly needed, but setcontext + restores them, so don't restore garbage). */ + movq %r8, UC_MCONTEXT_GREGS_R8(%rdi) + movq %r9, UC_MCONTEXT_GREGS_R9(%rdi) + movq %rdi, UC_MCONTEXT_GREGS_RDI(%rdi) + movq %rsi, UC_MCONTEXT_GREGS_RSI(%rdi) + movq %rdx, UC_MCONTEXT_GREGS_RDX(%rdi) + movq %rax, UC_MCONTEXT_GREGS_RAX(%rdi) + movq %rcx, UC_MCONTEXT_GREGS_RCX(%rdi) + +#if defined __linux__ + /* Save fp state (not needed, except for setcontext not + restoring garbage). */ + leaq UC_MCONTEXT_FPREGS_MEM(%rdi),%r8 + movq %r8, UC_MCONTEXT_FPREGS_PTR(%rdi) + fnstenv (%r8) + stmxcsr FPREGS_OFFSET_MXCSR(%r8) +#elif defined __FreeBSD__ + fxsave UC_MCONTEXT_FPSTATE(%rdi) + movq $UC_MCONTEXT_FPOWNED_FPU,UC_MCONTEXT_OWNEDFP(%rdi) + movq $UC_MCONTEXT_FPFMT_XMM,UC_MCONTEXT_FPFORMAT(%rdi) + /* Save rflags and segment registers, so that sigreturn(2) + does not complain. */ + pushfq + .cfi_adjust_cfa_offset 8 + popq UC_MCONTEXT_RFLAGS(%rdi) + .cfi_adjust_cfa_offset -8 + movl $0, UC_MCONTEXT_FLAGS(%rdi) + movw %cs, UC_MCONTEXT_CS(%rdi) + movw %ss, UC_MCONTEXT_SS(%rdi) +#if 0 + /* Setting the flags to 0 above disables restore of segment + registers from the context */ + movw %ds, UC_MCONTEXT_DS(%rdi) + movw %es, UC_MCONTEXT_ES(%rdi) + movw %fs, UC_MCONTEXT_FS(%rdi) + movw %gs, UC_MCONTEXT_GS(%rdi) +#endif + movq $UC_MCONTEXT_MC_LEN_VAL, UC_MCONTEXT_MC_LEN(%rdi) +#else +#error Port me +#endif + + leaq 8(%rsp), %rax /* exclude this call. */ + movq %rax, UC_MCONTEXT_GREGS_RSP(%rdi) + + movq 0(%rsp), %rax + movq %rax, UC_MCONTEXT_GREGS_RIP(%rdi) + + xorq %rax, %rax + retq + .cfi_endproc + .size _Ux86_64_getcontext, . - _Ux86_64_getcontext + +/* int _Ux86_64_getcontext_trace (ucontext_t *ucp) + + Saves limited machine context in UCP necessary for libunwind. + Unlike _Ux86_64_getcontext, saves only the parts needed for + fast trace. If fast trace fails, caller will have to get the + full context. +*/ + + .global _Ux86_64_getcontext_trace + .hidden _Ux86_64_getcontext_trace + .type _Ux86_64_getcontext_trace, @function +_Ux86_64_getcontext_trace: + .cfi_startproc + + /* Save only RBP, RBX, RSP, RIP - exclude this call. */ + movq %rbp, UC_MCONTEXT_GREGS_RBP(%rdi) + movq %rbx, UC_MCONTEXT_GREGS_RBX(%rdi) + + leaq 8(%rsp), %rax + movq %rax, UC_MCONTEXT_GREGS_RSP(%rdi) + + movq 0(%rsp), %rax + movq %rax, UC_MCONTEXT_GREGS_RIP(%rdi) + + xorq %rax, %rax + retq + .cfi_endproc + .size _Ux86_64_getcontext_trace, . - _Ux86_64_getcontext_trace + + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/init.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/init.h new file mode 100644 index 0000000..a7a996f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/init.h @@ -0,0 +1,89 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +/* Avoid a trip to x86_64_r_uc_addr() for purely local initialisation. */ +#if defined UNW_LOCAL_ONLY && defined __linux +# define REG_INIT_LOC(c, rlc, ruc) \ + DWARF_LOC ((unw_word_t) &c->uc->uc_mcontext.gregs[REG_ ## ruc], 0) + +#elif defined UNW_LOCAL_ONLY && defined __FreeBSD__ +# define REG_INIT_LOC(c, rlc, ruc) \ + DWARF_LOC ((unw_word_t) &c->uc->uc_mcontext.mc_ ## rlc, 0) + +#else +# define REG_INIT_LOC(c, rlc, ruc) \ + DWARF_REG_LOC (&c->dwarf, UNW_X86_64_ ## ruc) +#endif + +static inline int +common_init (struct cursor *c, unsigned use_prev_instr) +{ + int ret; + + c->dwarf.loc[RAX] = REG_INIT_LOC(c, rax, RAX); + c->dwarf.loc[RDX] = REG_INIT_LOC(c, rdx, RDX); + c->dwarf.loc[RCX] = REG_INIT_LOC(c, rcx, RCX); + c->dwarf.loc[RBX] = REG_INIT_LOC(c, rbx, RBX); + c->dwarf.loc[RSI] = REG_INIT_LOC(c, rsi, RSI); + c->dwarf.loc[RDI] = REG_INIT_LOC(c, rdi, RDI); + c->dwarf.loc[RBP] = REG_INIT_LOC(c, rbp, RBP); + c->dwarf.loc[RSP] = REG_INIT_LOC(c, rsp, RSP); + c->dwarf.loc[R8] = REG_INIT_LOC(c, r8, R8); + c->dwarf.loc[R9] = REG_INIT_LOC(c, r9, R9); + c->dwarf.loc[R10] = REG_INIT_LOC(c, r10, R10); + c->dwarf.loc[R11] = REG_INIT_LOC(c, r11, R11); + c->dwarf.loc[R12] = REG_INIT_LOC(c, r12, R12); + c->dwarf.loc[R13] = REG_INIT_LOC(c, r13, R13); + c->dwarf.loc[R14] = REG_INIT_LOC(c, r14, R14); + c->dwarf.loc[R15] = REG_INIT_LOC(c, r15, R15); + c->dwarf.loc[RIP] = REG_INIT_LOC(c, rip, RIP); + + ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); + if (ret < 0) + return ret; + + ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_X86_64_RSP), + &c->dwarf.cfa); + if (ret < 0) + return ret; + + c->sigcontext_format = X86_64_SCF_NONE; + c->sigcontext_addr = 0; + + c->dwarf.args_size = 0; + c->dwarf.stash_frames = 0; + c->dwarf.use_prev_instr = use_prev_instr; + c->dwarf.pi_valid = 0; + c->dwarf.pi_is_dynamic = 0; + c->dwarf.hint = 0; + c->dwarf.prev_rs = 0; + c->dwarf.eh_valid_mask = 0; + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/is_fpreg.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/is_fpreg.c new file mode 100644 index 0000000..5c03613 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/is_fpreg.c @@ -0,0 +1,38 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2004-2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + + Modified for x86_64 by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +int +unw_is_fpreg (int regnum) +{ +#if 0 + return ((regnum >= UNW_X86_ST0 && regnum <= UNW_X86_ST7) + || (regnum >= UNW_X86_XMM0_lo && regnum <= UNW_X86_XMM7_hi)); +#endif + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/longjmp.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/longjmp.S new file mode 100644 index 0000000..274778f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/longjmp.S @@ -0,0 +1,34 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + .globl _UI_longjmp_cont + .type _UI_longjmp_cont, @function +_UI_longjmp_cont: + push %rax /* push target IP as return address */ + mov %rdx, %rax /* set up return-value */ + retq + .size _UI_longjmp_cont, .-_UI_longjmp_cont + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/offsets.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/offsets.h new file mode 100644 index 0000000..0807960 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/offsets.h @@ -0,0 +1,3 @@ +/* FreeBSD specific definitions */ + +#define FREEBSD_UC_MCONTEXT_OFF 0x10 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/regname.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/regname.c new file mode 100644 index 0000000..77660af --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/regname.c @@ -0,0 +1,56 @@ +/* libunwind - a platform-independent unwind library + + Contributed by Max Asbock + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static const char *regname[] = + { + "RAX", + "RDX", + "RCX", + "RBX", + "RSI", + "RDI", + "RBP", + "RSP", + "R8", + "R9", + "R10", + "R11", + "R12", + "R13", + "R14", + "R15", + "RIP", + }; + +const char * +unw_regname (unw_regnum_t reg) +{ + if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) + return regname[reg]; + else + return "???"; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/setcontext.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/setcontext.S new file mode 100644 index 0000000..358217d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/setcontext.S @@ -0,0 +1,83 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2007 Google, Inc + Contributed by Arun Sharma + Copyright (C) 2010 Konstantin Belousov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "ucontext_i.h" + +/* int _Ux86_64_setcontext (const ucontext_t *ucp) + + Restores the machine context provided. + Unlike the libc implementation, doesn't clobber %rax + +*/ + .global _Ux86_64_setcontext + .type _Ux86_64_setcontext, @function + +_Ux86_64_setcontext: + +#if defined __linux__ + /* restore fp state */ + mov UC_MCONTEXT_FPREGS_PTR(%rdi),%r8 + fldenv (%r8) + ldmxcsr FPREGS_OFFSET_MXCSR(%r8) +#elif defined __FreeBSD__ + /* restore fp state */ + cmpq $UC_MCONTEXT_FPOWNED_FPU,UC_MCONTEXT_OWNEDFP(%rdi) + jne 1f + cmpq $UC_MCONTEXT_FPFMT_XMM,UC_MCONTEXT_FPFORMAT(%rdi) + jne 1f + fxrstor UC_MCONTEXT_FPSTATE(%rdi) +1: +#else +#error Port me +#endif + + /* restore the rest of the state */ + mov UC_MCONTEXT_GREGS_R8(%rdi),%r8 + mov UC_MCONTEXT_GREGS_R9(%rdi),%r9 + mov UC_MCONTEXT_GREGS_RBX(%rdi),%rbx + mov UC_MCONTEXT_GREGS_RBP(%rdi),%rbp + mov UC_MCONTEXT_GREGS_R12(%rdi),%r12 + mov UC_MCONTEXT_GREGS_R13(%rdi),%r13 + mov UC_MCONTEXT_GREGS_R14(%rdi),%r14 + mov UC_MCONTEXT_GREGS_R15(%rdi),%r15 + mov UC_MCONTEXT_GREGS_RSI(%rdi),%rsi + mov UC_MCONTEXT_GREGS_RDX(%rdi),%rdx + mov UC_MCONTEXT_GREGS_RAX(%rdi),%rax + mov UC_MCONTEXT_GREGS_RCX(%rdi),%rcx + mov UC_MCONTEXT_GREGS_RSP(%rdi),%rsp + + /* push the return address on the stack */ + mov UC_MCONTEXT_GREGS_RIP(%rdi),%rcx + push %rcx + + mov UC_MCONTEXT_GREGS_RCX(%rdi),%rcx + mov UC_MCONTEXT_GREGS_RDI(%rdi),%rdi + retq + + .size _Ux86_64_setcontext, . - _Ux86_64_setcontext + + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/siglongjmp.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/siglongjmp.S new file mode 100644 index 0000000..32489e5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/src/x86_64/siglongjmp.S @@ -0,0 +1,32 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + .globl _UI_siglongjmp_cont + .type _UI_siglongjmp_cont, @function +_UI_siglongjmp_cont: + retq + .size _UI_siglongjmp_cont, . - _UI_siglongjmp_cont + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-nat.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-nat.c new file mode 100644 index 0000000..89df54e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-nat.c @@ -0,0 +1,626 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* This file tests corner-cases of NaT-bit handling. */ + +#include +#include +#include +#include + +#include +#include "compiler.h" + +#ifdef HAVE_SYS_UC_ACCESS_H +# include +#endif + +#include "tdep-ia64/rse.h" + +#define NUM_RUNS 1024 +//#define NUM_RUNS 1 +#define MAX_CHECKS 1024 +//#define MAX_CHECKS 2 +#define MAX_VALUES_PER_FUNC 4 + +#define panic(args...) \ + do { printf (args); ++nerrors; } while (0) + +typedef void save_func_t (void *funcs, unsigned long *vals); +typedef unw_word_t *check_func_t (unw_cursor_t *c, unsigned long *vals); + +extern void flushrs (void); + +extern save_func_t save_static_to_stacked; +static check_func_t check_static_to_stacked; + +extern save_func_t save_static_to_fr; +static check_func_t check_static_to_fr; + +extern save_func_t save_static_to_br; +static check_func_t check_static_to_br; + +extern save_func_t save_static_to_mem; +static check_func_t check_static_to_mem; + +extern save_func_t save_static_to_mem2; +static check_func_t check_static_to_mem2; + +extern save_func_t save_static_to_mem3; +static check_func_t check_static_to_mem3; + +extern save_func_t save_static_to_mem4; +static check_func_t check_static_to_mem4; + +extern save_func_t save_static_to_mem5; +static check_func_t check_static_to_mem5; + +extern save_func_t save_static_to_scratch; +static check_func_t check_static_to_scratch; + +extern save_func_t rotate_regs; +static check_func_t check_rotate_regs; + +extern save_func_t save_pr; +static check_func_t check_pr; + +static int verbose; +static int nerrors; + +static int num_checks; +static save_func_t *funcs[MAX_CHECKS + 1]; +static check_func_t *checks[MAX_CHECKS]; +static unw_word_t values[MAX_CHECKS*MAX_VALUES_PER_FUNC]; + +static struct + { + save_func_t *func; + check_func_t *check; + } +all_funcs[] = + { + { save_static_to_stacked, check_static_to_stacked }, + { save_static_to_fr, check_static_to_fr }, + { save_static_to_br, check_static_to_br }, + { save_static_to_mem, check_static_to_mem }, + { save_static_to_mem2, check_static_to_mem2 }, + { save_static_to_mem3, check_static_to_mem3 }, + { save_static_to_mem4, check_static_to_mem4 }, + { save_static_to_mem5, check_static_to_mem5 }, + { save_static_to_scratch, check_static_to_scratch }, + { save_pr, check_pr }, + { rotate_regs, check_rotate_regs }, + }; + +static unw_word_t +random_word (void) +{ + unw_word_t val = random (); + + if (sizeof (unw_word_t) > 4) + val |= ((unw_word_t) random ()) << 32; + + return val; +} + +void +sighandler (int signal, void *siginfo, void *context) +{ + unsigned long *bsp, *arg1; + save_func_t **arg0; + ucontext_t *uc = context; + +#if defined(__linux) + { + long sof; + int sp; + + if (verbose) + printf ("sighandler: signal %d sp=%p nat=%08lx pr=%lx\n", + signal, &sp, uc->uc_mcontext.sc_nat, uc->uc_mcontext.sc_pr); + sof = uc->uc_mcontext.sc_cfm & 0x7f; + bsp = (unsigned long *) rse_skip_regs (uc->uc_mcontext.sc_ar_bsp, -sof); + } +#elif defined(__hpux) + if (__uc_get_ar (uc, UNW_IA64_AR_BSP - UNW_IA64_AR, &bsp) != 0) + { + panic ("%s: reading of ar.bsp failed, errno=%d", __FUNCTION__, errno); + return; + } +#endif + + flushrs (); + arg0 = (save_func_t **) *bsp; + bsp = (unsigned long *) rse_skip_regs ((uint64_t) bsp, 1); + arg1 = (unsigned long *) *bsp; + + (*arg0[0]) (arg0 + 1, arg1); + + /* skip over the instruction which triggered sighandler() */ +#if defined(__linux) + ++uc->uc_mcontext.sc_ip; +#elif defined(HAVE_SYS_UC_ACCESS_H) + { + unsigned long ip; + + if (__uc_get_ip (uc, &ip) != 0) + { + panic ("%s: reading of ip failed, errno=%d", __FUNCTION__, errno); + return; + } + if (__uc_set_ip (uc, ip) != 0) + { + panic ("%s: writing of ip failed, errno=%d", __FUNCTION__, errno); + return; + } + } +#endif +} + +static void +enable_sighandler (void) +{ + struct sigaction act; + + memset (&act, 0, sizeof (act)); + act.sa_handler = (void (*)(int)) sighandler; + act.sa_flags = SA_SIGINFO | SA_NODEFER; + if (sigaction (SIGSEGV, &act, NULL) < 0) + panic ("sigaction: %s\n", strerror (errno)); +} + +static void +disable_sighandler (void) +{ + struct sigaction act; + + memset (&act, 0, sizeof (act)); + act.sa_handler = SIG_DFL; + act.sa_flags = SA_SIGINFO | SA_NODEFER; + if (sigaction (SIGSEGV, &act, NULL) < 0) + panic ("sigaction: %s\n", strerror (errno)); +} + +static unw_word_t * +check_static_to_stacked (unw_cursor_t *c, unw_word_t *vals) +{ + unw_word_t r[4]; + unw_word_t nat[4]; + int i, ret; + + if (verbose) + printf (" %s()\n", __FUNCTION__); + + vals -= 4; + + for (i = 0; i < 4; ++i) + if ((ret = unw_get_reg (c, UNW_IA64_GR + 4 + i, &r[i])) < 0) + panic ("%s: failed to read register r%d, error=%d\n", + __FUNCTION__, 4 + i, ret); + + for (i = 0; i < 4; ++i) + if ((ret = unw_get_reg (c, UNW_IA64_NAT + 4 + i, &nat[i])) < 0) + panic ("%s: failed to read register nat%d, error=%d\n", + __FUNCTION__, 4 + i, ret); + + for (i = 0; i < 4; ++i) + { + if (verbose) + printf (" r%d = %c%016lx (expected %c%016lx)\n", + 4 + i, nat[i] ? '*' : ' ', r[i], + (vals[i] & 1) ? '*' : ' ', vals[i]); + + if (vals[i] & 1) + { + if (!nat[i]) + panic ("%s: r%d not a NaT!\n", __FUNCTION__, 4 + i); + } + else + { + if (nat[i]) + panic ("%s: r%d a NaT!\n", __FUNCTION__, 4 + i); + if (r[i] != vals[i]) + panic ("%s: r%d=%lx instead of %lx!\n", + __FUNCTION__, 4 + i, r[i], vals[i]); + } + } + return vals; +} + +static unw_word_t * +check_static_to_fr (unw_cursor_t *c, unw_word_t *vals) +{ + unw_word_t r4; + unw_word_t nat4; + int ret; + + if (verbose) + printf (" %s()\n", __FUNCTION__); + + vals -= 1; + + if ((ret = unw_get_reg (c, UNW_IA64_GR + 4, &r4)) < 0) + panic ("%s: failed to read register r4, error=%d\n", __FUNCTION__, ret); + + if ((ret = unw_get_reg (c, UNW_IA64_NAT + 4, &nat4)) < 0) + panic ("%s: failed to read register nat4, error=%d\n", __FUNCTION__, ret); + + if (verbose) + printf (" r4 = %c%016lx (expected %c%016lx)\n", + nat4 ? '*' : ' ', r4, (vals[0] & 1) ? '*' : ' ', vals[0]); + + if (vals[0] & 1) + { + if (!nat4) + panic ("%s: r4 not a NaT!\n", __FUNCTION__); + } + else + { + if (nat4) + panic ("%s: r4 a NaT!\n", __FUNCTION__); + if (r4 != vals[0]) + panic ("%s: r4=%lx instead of %lx!\n", __FUNCTION__, r4, vals[0]); + } + return vals; +} + +static unw_word_t * +check_static_to_br (unw_cursor_t *c, unw_word_t *vals) +{ + unw_word_t r4, nat4; + int ret; + + if (verbose) + printf (" %s()\n", __FUNCTION__); + + vals -= 1; + + if ((ret = unw_get_reg (c, UNW_IA64_GR + 4, &r4)) < 0) + panic ("%s: failed to read register r4, error=%d\n", __FUNCTION__, ret); + + if ((ret = unw_get_reg (c, UNW_IA64_NAT + 4, &nat4)) < 0) + panic ("%s: failed to read register nat4, error=%d\n", __FUNCTION__, ret); + + if (verbose) + printf (" r4 = %c%016lx (expected %c%016lx)\n", + nat4 ? '*' : ' ', r4, (vals[0] & 1) ? '*' : ' ', vals[0]); + + if (vals[0] & 1) + { + if (!nat4) + panic ("%s: r4 not a NaT!\n", __FUNCTION__); + } + else + { + if (nat4) + panic ("%s: r4 a NaT!\n", __FUNCTION__); + if (r4 != vals[0]) + panic ("%s: r4=%lx instead of %lx!\n", __FUNCTION__, r4, vals[0]); + } + return vals; +} + +static unw_word_t * +check_static_to_mem (unw_cursor_t *c, unw_word_t *vals) +{ + unw_word_t r5, nat5; + int ret; + + if (verbose) + printf (" %s()\n", __FUNCTION__); + + vals -= 1; + + if ((ret = unw_get_reg (c, UNW_IA64_GR + 5, &r5)) < 0) + panic ("%s: failed to read register r5, error=%d\n", __FUNCTION__, ret); + + if ((ret = unw_get_reg (c, UNW_IA64_NAT + 5, &nat5)) < 0) + panic ("%s: failed to read register nat5, error=%d\n", __FUNCTION__, ret); + + if (verbose) + printf (" r5 = %c%016lx (expected %c%016lx)\n", + nat5 ? '*' : ' ', r5, (vals[0] & 1) ? '*' : ' ', vals[0]); + + if (vals[0] & 1) + { + if (!nat5) + panic ("%s: r5 not a NaT!\n", __FUNCTION__); + } + else + { + if (nat5) + panic ("%s: r5 a NaT!\n", __FUNCTION__); + if (r5 != vals[0]) + panic ("%s: r5=%lx instead of %lx!\n", __FUNCTION__, r5, vals[0]); + } + return vals; +} + +static unw_word_t * +check_static_to_memN (unw_cursor_t *c, unw_word_t *vals, const char *func) +{ + unw_word_t r6, nat6; + int ret; + + if (verbose) + printf (" %s()\n", func); + + vals -= 1; + + if ((ret = unw_get_reg (c, UNW_IA64_GR + 6, &r6)) < 0) + panic ("%s: failed to read register r6, error=%d\n", __FUNCTION__, ret); + + if ((ret = unw_get_reg (c, UNW_IA64_NAT + 6, &nat6)) < 0) + panic ("%s: failed to read register nat6, error=%d\n", __FUNCTION__, ret); + + if (verbose) + printf (" r6 = %c%016lx (expected %c%016lx)\n", + nat6 ? '*' : ' ', r6, (vals[0] & 1) ? '*' : ' ', vals[0]); + + if (vals[0] & 1) + { + if (!nat6) + panic ("%s: r6 not a NaT!\n", __FUNCTION__); + } + else + { + if (nat6) + panic ("%s: r6 a NaT!\n", __FUNCTION__); + if (r6 != vals[0]) + panic ("%s: r6=%lx instead of %lx!\n", __FUNCTION__, r6, vals[0]); + } + return vals; +} + +static unw_word_t * +check_static_to_mem2 (unw_cursor_t *c, unw_word_t *vals) +{ + return check_static_to_memN (c, vals, __FUNCTION__); +} + +static unw_word_t * +check_static_to_mem3 (unw_cursor_t *c, unw_word_t *vals) +{ + return check_static_to_memN (c, vals, __FUNCTION__); +} + +static unw_word_t * +check_static_to_mem4 (unw_cursor_t *c, unw_word_t *vals) +{ + return check_static_to_memN (c, vals, __FUNCTION__); +} + +static unw_word_t * +check_static_to_mem5 (unw_cursor_t *c, unw_word_t *vals) +{ + return check_static_to_memN (c, vals, __FUNCTION__); +} + +static unw_word_t * +check_static_to_scratch (unw_cursor_t *c, unw_word_t *vals) +{ + unw_word_t r[4], nat[4], ec, expected; + unw_fpreg_t f4; + int i, ret; + + if (verbose) + printf (" %s()\n", __FUNCTION__); + + vals -= 4; + + while (!unw_is_signal_frame (c)) + if ((ret = unw_step (c)) < 0) + panic ("%s: unw_step (ret=%d): Failed to skip over signal handler\n", + __FUNCTION__, ret); + if ((ret = unw_step (c)) < 0) + panic ("%s: unw_step (ret=%d): Failed to skip over signal handler\n", + __FUNCTION__, ret); + + for (i = 0; i < 4; ++i) + if ((ret = unw_get_reg (c, UNW_IA64_GR + 4 + i, &r[i])) < 0) + panic ("%s: failed to read register r%d, error=%d\n", + __FUNCTION__, 4 + i, ret); + + for (i = 0; i < 4; ++i) + if ((ret = unw_get_reg (c, UNW_IA64_NAT + 4 + i, &nat[i])) < 0) + panic ("%s: failed to read register nat%d, error=%d\n", + __FUNCTION__, 4 + i, ret); + + for (i = 0; i < 4; ++i) + { + if (verbose) + printf (" r%d = %c%016lx (expected %c%016lx)\n", + 4 + i, nat[i] ? '*' : ' ', r[i], + (vals[i] & 1) ? '*' : ' ', vals[i]); + + if (vals[i] & 1) + { + if (!nat[i]) + panic ("%s: r%d not a NaT!\n", __FUNCTION__, 4 + i); + } + else + { + if (nat[i]) + panic ("%s: r%d a NaT!\n", __FUNCTION__, 4 + i); + if (r[i] != vals[i]) + panic ("%s: r%d=%lx instead of %lx!\n", + __FUNCTION__, 4 + i, r[i], vals[i]); + } + } + if ((ret = unw_get_fpreg (c, UNW_IA64_FR + 4, &f4)) < 0) + panic ("%s: failed to read f4, error=%d\n", __FUNCTION__, ret); + + /* These tests are little-endian specific: */ + if (nat[0]) + { + if (f4.raw.bits[0] != 0 || f4.raw.bits[1] != 0x1fffe) + panic ("%s: f4=%016lx.%016lx instead of NaTVal!\n", + __FUNCTION__, f4.raw.bits[1], f4.raw.bits[0]); + } + else + { + if (f4.raw.bits[0] != r[0] || f4.raw.bits[1] != 0x1003e) + panic ("%s: f4=%016lx.%016lx instead of %lx!\n", + __FUNCTION__, f4.raw.bits[1], f4.raw.bits[0], r[0]); + } + + if ((unw_get_reg (c, UNW_IA64_AR_EC, &ec)) < 0) + panic ("%s: failed to read register ar.ec, error=%d\n", __FUNCTION__, ret); + + expected = vals[0] & 0x3f; + if (ec != expected) + panic ("%s: ar.ec=%016lx instead of %016lx!\n", + __FUNCTION__, ec, expected); + + return vals; +} + +static unw_word_t * +check_pr (unw_cursor_t *c, unw_word_t *vals) +{ + unw_word_t pr, expected; + int ret; +# define BIT(n) ((unw_word_t) 1 << (n)) +# define DONTCARE (BIT( 6) | BIT( 7) | BIT( 8) | BIT( 9) | BIT(10) \ + | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15)) + + if (verbose) + printf (" %s()\n", __FUNCTION__); + + vals -= 1; + + if ((ret = unw_get_reg (c, UNW_IA64_PR, &pr)) < 0) + panic ("%s: failed to read register pr, error=%d\n", __FUNCTION__, ret); + + pr &= ~DONTCARE; + expected = (vals[0] & ~DONTCARE) | 1; + + if (verbose) + printf (" pr = %016lx (expected %016lx)\n", pr, expected); + + if (pr != expected) + panic ("%s: pr=%lx instead of %lx!\n", __FUNCTION__, pr, expected); + + if ((ret = unw_set_reg (c, UNW_IA64_PR, vals[0])) < 0) + panic ("%s: failed to write register pr, error=%d\n", __FUNCTION__, ret); + + if ((ret = unw_get_reg (c, UNW_IA64_PR, &pr)) < 0) + panic ("%s: failed to read register pr, error=%d\n", __FUNCTION__, ret); + + if (pr != vals[0]) + panic ("%s: secondary pr=%lx instead of %lx!\n", + __FUNCTION__, pr, vals[0]); + return vals; +} + +static unw_word_t * +check_rotate_regs (unw_cursor_t *c, unw_word_t *vals) +{ + if (verbose) + printf (" %s()\n", __FUNCTION__); + return check_pr (c, vals - 1); +} + +static void +start_checks (void *funcs, unsigned long *vals) +{ + unw_context_t uc; + unw_cursor_t c; + int i, ret; + + disable_sighandler (); + + unw_getcontext (&uc); + + if ((ret = unw_init_local (&c, &uc)) < 0) + panic ("%s: unw_init_local (ret=%d)\n", __FUNCTION__, ret); + + if ((ret = unw_step (&c)) < 0) + panic ("%s: unw_step (ret=%d)\n", __FUNCTION__, ret); + + for (i = 0; i < num_checks; ++i) + { + vals = (*checks[num_checks - 1 - i]) (&c, vals); + + if ((ret = unw_step (&c)) < 0) + panic ("%s: unw_step (ret=%d)\n", __FUNCTION__, ret); + } +} + +static void +run_check (int test) +{ + int index, i; + + if (test == 1) + /* Make first test always go the full depth... */ + num_checks = MAX_CHECKS; + else + num_checks = (random () % MAX_CHECKS) + 1; + + for (i = 0; i < num_checks * MAX_VALUES_PER_FUNC; ++i) + values[i] = random_word (); + + for (i = 0; i < num_checks; ++i) + { + if (test == 1) + /* Make first test once go through each test... */ + index = i % (int) ARRAY_SIZE (all_funcs); + else + index = random () % (int) ARRAY_SIZE (all_funcs); + funcs[i] = all_funcs[index].func; + checks[i] = all_funcs[index].check; + } + + funcs[num_checks] = start_checks; + + enable_sighandler (); + (*funcs[0]) (funcs + 1, values); +} + +int +main (int argc, char **argv) +{ + int i; + + if (argc > 1) + verbose = 1; + + for (i = 0; i < NUM_RUNS; ++i) + { + if (verbose) + printf ("Run %d\n", i + 1); + run_check (i + 1); + } + + if (nerrors > 0) + { + fprintf (stderr, "FAILURE: detected %d errors\n", nerrors); + exit (-1); + } + if (verbose) + printf ("SUCCESS.\n"); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-rbs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-rbs.c new file mode 100644 index 0000000..2181e70 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-rbs.c @@ -0,0 +1,193 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* This file tests corner-cases of unwinding across multiple stacks. + In particular, it verifies that the extreme case with a frame of 96 + stacked registers that are all backed up by separate stacks works + as expected. */ + +#include +#include + +#include +#include "compiler.h" + +#include "ia64-test-rbs.h" + +#define panic(args...) \ + do { fprintf (stderr, args); ++nerrors; return -9999; } while (0) + +/* The loadrs field in ar.rsc is 14 bits wide, which limits all ia64 + implementations to at most 2048 physical stacked registers + (actually, slightly less than that, because loadrs also counts RNaT + slots). Since we can dirty 93 stacked registers per recursion, we + need to recurse RECURSION_DEPTH times to ensure all physical + stacked registers are in use. */ +#define MAX_PHYS_STACKED 2048 +#define RECURSION_DEPTH ((MAX_PHYS_STACKED + 92) / 93) + +typedef int spill_func_t (long iteration, int (*next_func[])()); + +extern int loadup (long iteration, int *values, int (*next_func[])()); +extern char resumption_point_label; + +#define DCL(n) \ + extern int rbs_spill_##n (long iteration, int (*next_func[])()) + DCL(2); DCL(3); DCL(4); DCL(5); DCL(6); DCL(7); + DCL(8); DCL(9); DCL(10); DCL(11); DCL(12); DCL(13); DCL(14); DCL(15); + DCL(16); DCL(17); DCL(18); DCL(19); DCL(20); DCL(21); DCL(22); DCL(23); + DCL(24); DCL(25); DCL(26); DCL(27); DCL(28); DCL(29); DCL(30); DCL(31); + DCL(32); DCL(33); DCL(34); DCL(35); DCL(36); DCL(37); DCL(38); DCL(39); + DCL(40); DCL(41); DCL(42); DCL(43); DCL(44); DCL(45); DCL(46); DCL(47); + DCL(48); DCL(49); DCL(50); DCL(51); DCL(52); DCL(53); DCL(54); DCL(55); + DCL(56); DCL(57); DCL(58); DCL(59); DCL(60); DCL(61); DCL(62); DCL(63); + DCL(64); DCL(65); DCL(66); DCL(67); DCL(68); DCL(69); DCL(70); DCL(71); + DCL(72); DCL(73); DCL(74); DCL(75); DCL(76); DCL(77); DCL(78); DCL(79); + DCL(80); DCL(81); DCL(82); DCL(83); DCL(84); DCL(85); DCL(86); DCL(87); + DCL(88); DCL(89); DCL(90); DCL(91); DCL(92); DCL(93); DCL(94); + +#define SPL(n) rbs_spill_##n +spill_func_t *spill_funcs[] = + { + SPL(2), SPL(3), SPL(4), SPL(5), SPL(6), SPL(7), + SPL(8), SPL(9), SPL(10), SPL(11), SPL(12), SPL(13), SPL(14), SPL(15), + SPL(16), SPL(17), SPL(18), SPL(19), SPL(20), SPL(21), SPL(22), SPL(23), + SPL(24), SPL(25), SPL(26), SPL(27), SPL(28), SPL(29), SPL(30), SPL(31), + SPL(32), SPL(33), SPL(34), SPL(35), SPL(36), SPL(37), SPL(38), SPL(39), + SPL(40), SPL(41), SPL(42), SPL(43), SPL(44), SPL(45), SPL(46), SPL(47), + SPL(48), SPL(49), SPL(50), SPL(51), SPL(52), SPL(53), SPL(54), SPL(55), + SPL(56), SPL(57), SPL(58), SPL(59), SPL(60), SPL(61), SPL(62), SPL(63), + SPL(64), SPL(65), SPL(66), SPL(67), SPL(68), SPL(69), SPL(70), SPL(71), + SPL(72), SPL(73), SPL(74), SPL(75), SPL(76), SPL(77), SPL(78), SPL(79), + SPL(80), SPL(81), SPL(82), SPL(83), SPL(84), SPL(85), SPL(86), SPL(87), + SPL(88), SPL(89), SPL(90), SPL(91), SPL(92), SPL(93), SPL(94) + }; + +static int verbose; +static int nerrors; +static int unwind_count; + +static int +unwind_and_resume (long iteration, int (*next_func[])()) +{ + unw_context_t uc; + unw_cursor_t c; + unw_word_t ip; + int i, ret; + + if (verbose) + printf (" %s(iteration=%ld, next_func=%p)\n", + __FUNCTION__, iteration, next_func); + + unw_getcontext (&uc); + if ((ret = unw_init_local (&c, &uc)) < 0) + panic ("unw_init_local (ret=%d)", ret); + + for (i = 0; i < unwind_count; ++i) + if ((ret = unw_step (&c)) < 0) + panic ("unw_step (ret=%d)", ret); + + if (unw_get_reg (&c, UNW_REG_IP, &ip) < 0 + || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) &resumption_point_label) < 0 + || unw_set_reg (&c, UNW_REG_EH + 0, 0) /* ret val */ + || unw_set_reg (&c, UNW_REG_EH + 1, ip)) + panic ("failed to redirect to resumption_point\n"); + + if (verbose) + { + unw_word_t bsp; + if (unw_get_reg (&c, UNW_IA64_BSP, &bsp) < 0) + panic ("unw_get_reg() failed\n"); + printf (" bsp=%lx, old ip=%lx, new ip=%p\n", bsp, + ip, &resumption_point_label); + } + + ret = unw_resume (&c); + panic ("unw_resume() returned (ret=%d)!!\n", ret); + return 0; +} + +static int +run_check (int test) +{ + int nfuncs, nspills, n, ret, i, reg_values[88]; + spill_func_t *func[NSTACKS + 1]; + + /* First, generate a set of 88 random values which loadup() will load + into loc2-loc89 (r37-r124). */ + for (i = 0; i < (int) ARRAY_SIZE (reg_values); ++i) + { + reg_values[i] = random (); + /* Generate NaTs with a reasonably probability (1/16th): */ + if (reg_values[i] < 0x10000000) + reg_values[i] = 0; + } + + nspills = 0; + nfuncs = 0; + do + { + n = random () % (int) ARRAY_SIZE (spill_funcs); + func[nfuncs++] = spill_funcs[n]; + nspills += 2 + n; + } + while (nspills < 128); + func[nfuncs++] = unwind_and_resume; + + unwind_count = 1 + (random () % (nfuncs + RECURSION_DEPTH - 1)); + + if (verbose) + printf ("test%d: nfuncs=%d, unwind_count=%d\n", + test, nfuncs, unwind_count); + + ret = loadup (RECURSION_DEPTH, reg_values, func); + if (ret < 0) + panic ("test%d: load() returned %d\n", test, ret); + else if (ret != RECURSION_DEPTH + nfuncs - unwind_count) + panic ("test%d: resumed wrong frame: expected %d, got %d\n", + test, RECURSION_DEPTH + nfuncs - unwind_count, ret); + return 0; +} + +int +main (int argc, char **argv) +{ + int i; + + if (argc > 1) + verbose = 1; + + for (i = 0; i < 100000; ++i) + run_check (i + 1); + + if (nerrors > 0) + { + fprintf (stderr, "FAILURE: detected %d errors\n", nerrors); + exit (-1); + } + if (verbose) + printf ("SUCCESS.\n"); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-readonly.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-readonly.c new file mode 100644 index 0000000..25f0506 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-readonly.c @@ -0,0 +1,89 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* This file verifies that read-only registers cannot be written to. */ + +#include +#include +#include +#include + +#include + +#define panic(args...) \ + do { printf (args); ++nerrors; } while (0) + +static int verbose; +static int nerrors; + +extern void test_func (void (*) (void)); + +void +checker (void) +{ + unw_fpreg_t fpval; + unw_context_t uc; + unw_cursor_t c; + int ret; + + fpval.raw.bits[0] = 100; + fpval.raw.bits[1] = 101; + + unw_getcontext (&uc); + + if ((ret = unw_init_local (&c, &uc)) < 0) + panic ("%s: unw_init_local (ret=%d)\n", __FUNCTION__, ret); + + if ((ret = unw_step (&c)) < 0) + panic ("%s: unw_step (ret=%d)\n", __FUNCTION__, ret); + + if ((ret = unw_step (&c)) < 0) + panic ("%s: unw_step (ret=%d)\n", __FUNCTION__, ret); + + if ((ret = unw_set_reg (&c, UNW_IA64_IP, 99)) != -UNW_EREADONLYREG) + panic ("%s: unw_set_reg (ip) returned %d instead of %d\n", + __FUNCTION__, ret, -UNW_EREADONLYREG); + if ((ret = unw_set_reg (&c, UNW_IA64_AR_LC, 99)) != -UNW_EREADONLYREG) + panic ("%s: unw_set_reg (ar.lc) returned %d instead of %d\n", + __FUNCTION__, ret, -UNW_EREADONLYREG); +} + +int +main (int argc, char **argv) +{ + if (argc > 1) + verbose = 1; + + test_func (checker); + + if (nerrors > 0) + { + fprintf (stderr, "FAILURE: detected %d errors\n", nerrors); + exit (-1); + } + if (verbose) + printf ("SUCCESS.\n"); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-stack.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-stack.c new file mode 100644 index 0000000..05874b2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gia64-test-stack.c @@ -0,0 +1,176 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* This file tests corner-cases of unwinding across multiple stacks. + In particular, it verifies that the extreme case with a frame of 96 + stacked registers that are all backed up by separate stacks works + as expected. */ + +#include +#include +#include + +#include "ia64-test-stack.h" + +#define panic(args...) \ + { printf (args); ++nerrors; } + +/* The loadrs field in ar.rsc is 14 bits wide, which limits all ia64 + implementations to at most 2048 physical stacked registers + (actually, slightly less than that, because loadrs also counts RNaT + slots). Since we can dirty 95 stacked registers per recursion, we + need to recurse RECURSION_DEPTH times to ensure all physical + stacked registers are in use. */ +#define MAX_PHYS_STACKED 2048 +#define RECURSION_DEPTH ((MAX_PHYS_STACKED + 94) / 95) + +extern void touch_all (unsigned long recursion_depth); +extern void flushrs (void); + +int nerrors; +int verbose; + +void +do_unwind_tests (void) +{ + unw_word_t ip, sp, bsp, v0, v1, v2, v3, n0, n1, n2, n3, cfm, sof, sol, r32; + int ret, reg, i, l; + unw_context_t uc; + unw_cursor_t c; + + if (verbose) + printf ("do_unwind_tests: here we go!\n"); + + /* do a full stack-dump: */ + unw_getcontext (&uc); + unw_init_local (&c, &uc); + i = 0; + do + { + if (verbose) + { + if ((ret = unw_get_reg (&c, UNW_IA64_IP, &ip)) < 0 + || (ret = unw_get_reg (&c, UNW_IA64_SP, &sp)) < 0 + || (ret = unw_get_reg (&c, UNW_IA64_BSP, &bsp)) < 0) + break; + printf ("ip=0x%16lx sp=0x%16lx bsp=0x%16lx\n", ip, sp, bsp); + + for (reg = 32; reg < 128; reg += 4) + { + v0 = v1 = v2 = v3 = 0; + n0 = n1 = n2 = n3 = 0; + (void) + ((ret = unw_get_reg (&c, UNW_IA64_GR + reg, &v0)) < 0 + || (ret = unw_get_reg (&c, UNW_IA64_NAT + reg, &n0)) < 0 + || (ret = unw_get_reg (&c, UNW_IA64_GR + reg + 1, &v1)) < 0 + || (ret = unw_get_reg (&c, UNW_IA64_NAT + reg + 1, &n1)) < 0 + || (ret = unw_get_reg (&c, UNW_IA64_GR + reg + 2, &v2)) < 0 + || (ret = unw_get_reg (&c, UNW_IA64_NAT + reg + 2, &n2)) < 0 + || (ret = unw_get_reg (&c, UNW_IA64_GR + reg + 3, &v3)) < 0 + || (ret = unw_get_reg (&c, UNW_IA64_NAT + reg + 3, &n3)) < 0); + if (reg < 100) + printf (" r%d", reg); + else + printf (" r%d", reg); + printf (" %c%016lx %c%016lx %c%016lx %c%016lx\n", + n0 ? '*' : ' ', v0, n1 ? '*' : ' ', v1, + n2 ? '*' : ' ', v2, n3 ? '*' : ' ', v3); + if (ret < 0) + break; + } + } + + if (i >= 1 && i <= NSTACKS) + { + if ((ret = unw_get_reg (&c, UNW_IA64_CFM, &cfm)) < 0) + break; + sof = cfm & 0x7f; + if (sof != (unw_word_t) (i & 1)) + panic ("\texpected sof=%d, found sof=%lu\n", i - 1, sof); + if (sof == 1) + { + if ((ret = unw_get_reg (&c, UNW_IA64_GR + 32, &r32)) < 0) + break; + if (r32 != (unw_word_t) (i - 1)) + panic ("\texpected r32=%d, found r32=%lu\n", i - 1, r32); + } + } + else if (i > NSTACKS && i <= NSTACKS + RECURSION_DEPTH) + { + if ((ret = unw_get_reg (&c, UNW_IA64_CFM, &cfm)) < 0) + break; + sof = cfm & 0x7f; + sol = (cfm >> 7) & 0x7f; + if (sof != 96) + panic ("\texpected sof=96, found sof=%lu\n", sof); + if (sol != 95) + panic ("\texpected sol=95, found sol=%lu\n", sol); + + for (l = 2; l <= 93; ++l) + { + if ((ret = unw_get_reg (&c, UNW_IA64_GR + 33 + l, &v0)) < 0 + || (ret = unw_get_reg (&c, UNW_IA64_NAT + 33 + l, &n0)) < 0) + break; + switch (l) + { + case 2: case 31: case 73: case 93: + if (!n0) + panic ("\texpected loc%d to be a NaT!\n", l); + break; + + default: + if (n0) + panic ("\tloc%d is unexpectedly a NaT!\n", l); + v1 = ((unw_word_t) (i - NSTACKS) << 32) + l; + if (v0 != v1) + panic ("\tloc%d expected to be %lx, found to be %lx\n", + l, v1, v0); + } + } + } + ++i; + } + while ((ret = unw_step (&c)) > 0); + + if (ret < 0) + panic ("libunwind returned %d\n", ret); +} + +int +main (int argc, char **argv) +{ + if (argc > 1) + ++verbose; + + touch_all (RECURSION_DEPTH); + if (nerrors) + { + printf ("FAILURE: detected %d errors\n", nerrors); + exit (-1); + } + if (verbose) + printf ("SUCCESS\n"); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gperf-simple.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gperf-simple.c new file mode 100644 index 0000000..e181918 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gperf-simple.c @@ -0,0 +1,264 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include +#include + +#include +#include "compiler.h" + +#include +#include + +#define panic(args...) \ + do { fprintf (stderr, args); exit (-1); } while (0) + +long dummy; + +static long iterations = 10000; +static int maxlevel = 100; + +#define KB 1024 +#define MB (1024*1024) + +static char big[64*MB]; /* should be >> max. cache size */ + +static inline double +gettime (void) +{ + struct timeval tv; + + gettimeofday (&tv, NULL); + return tv.tv_sec + 1e-6*tv.tv_usec; +} + +static int NOINLINE +measure_unwind (int maxlevel, double *step) +{ + double stop, start; + unw_cursor_t cursor; + unw_context_t uc; + int ret, level = 0; + + unw_getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + panic ("unw_init_local() failed\n"); + + start = gettime (); + + do + { + ret = unw_step (&cursor); + if (ret < 0) + panic ("unw_step() failed\n"); + ++level; + } + while (ret > 0); + + stop = gettime (); + + if (level <= maxlevel) + panic ("Unwound only %d levels, expected at least %d levels\n", + level, maxlevel); + + *step = (stop - start) / (double) level; + return 0; +} + +static int f1 (int, int, double *); + +static int NOINLINE +g1 (int level, int maxlevel, double *step) +{ + if (level == maxlevel) + return measure_unwind (maxlevel, step); + else + /* defeat last-call/sibcall optimization */ + return f1 (level + 1, maxlevel, step) + level; +} + +static int NOINLINE +f1 (int level, int maxlevel, double *step) +{ + if (level == maxlevel) + return measure_unwind (maxlevel, step); + else + /* defeat last-call/sibcall optimization */ + return g1 (level + 1, maxlevel, step) + level; +} + +static void +doit (const char *label) +{ + double step, min_step, first_step, sum_step; + int i; + + sum_step = first_step = 0.0; + min_step = 1e99; + for (i = 0; i < iterations; ++i) + { + f1 (0, maxlevel, &step); + + sum_step += step; + + if (step < min_step) + min_step = step; + + if (i == 0) + first_step = step; + } + printf ("%s: unw_step : 1st=%9.3f min=%9.3f avg=%9.3f nsec\n", label, + 1e9*first_step, 1e9*min_step, 1e9*sum_step/iterations); +} + +static long +sum (void *buf, size_t size) +{ + long s = 0; + char *cp = buf; + size_t i; + + for (i = 0; i < size; i += 8) + s += cp[i]; + return s; +} + +static void +measure_init (void) +{ +# define N 100 +# define M 10 /* must be at least 2 to get steady-state */ + double stop, start, get_cold, get_warm, init_cold, init_warm, delta; + struct + { + unw_cursor_t c; + char padding[1024]; /* should be > 2 * max. cacheline size */ + } + cursor[N]; + struct + { + unw_context_t uc; + char padding[1024]; /* should be > 2 * max. cacheline size */ + } + uc[N]; + int i, j; + + /* Run each test M times and take the minimum to filter out noise + such dynamic linker resolving overhead, context-switches, + page-in, cache, and TLB effects. */ + + get_cold = 1e99; + for (j = 0; j < M; ++j) + { + dummy += sum (big, sizeof (big)); /* flush the cache */ + for (i = 0; i < N; ++i) + uc[i].padding[511] = i; /* warm up the TLB */ + start = gettime (); + for (i = 0; i < N; ++i) + unw_getcontext (&uc[i].uc); + stop = gettime (); + delta = (stop - start) / N; + if (delta < get_cold) + get_cold = delta; + } + + init_cold = 1e99; + for (j = 0; j < M; ++j) + { + dummy += sum (big, sizeof (big)); /* flush cache */ + for (i = 0; i < N; ++i) + uc[i].padding[511] = i; /* warm up the TLB */ + start = gettime (); + for (i = 0; i < N; ++i) + unw_init_local (&cursor[i].c, &uc[i].uc); + stop = gettime (); + delta = (stop - start) / N; + if (delta < init_cold) + init_cold = delta; + } + + get_warm = 1e99; + for (j = 0; j < M; ++j) + { + start = gettime (); + for (i = 0; i < N; ++i) + unw_getcontext (&uc[0].uc); + stop = gettime (); + delta = (stop - start) / N; + if (delta < get_warm) + get_warm = delta; + } + + init_warm = 1e99; + for (j = 0; j < M; ++j) + { + start = gettime (); + for (i = 0; i < N; ++i) + unw_init_local (&cursor[0].c, &uc[0].uc); + stop = gettime (); + delta = (stop - start) / N; + if (delta < init_warm) + init_warm = delta; + } + + printf ("unw_getcontext : cold avg=%9.3f nsec, warm avg=%9.3f nsec\n", + 1e9 * get_cold, 1e9 * get_warm); + printf ("unw_init_local : cold avg=%9.3f nsec, warm avg=%9.3f nsec\n", + 1e9 * init_cold, 1e9 * init_warm); +} + +int +main (int argc, char **argv) +{ + struct rlimit rlim; + + rlim.rlim_cur = RLIM_INFINITY; + rlim.rlim_max = RLIM_INFINITY; + setrlimit (RLIMIT_STACK, &rlim); + + memset (big, 0xaa, sizeof (big)); + + if (argc > 1) + { + maxlevel = atol (argv[1]); + if (argc > 2) + iterations = atol (argv[2]); + } + + measure_init (); + + doit ("default "); + + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE); + doit ("no cache "); + + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL); + doit ("global cache "); + + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD); + doit ("per-thread cache"); + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gperf-trace.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gperf-trace.c new file mode 100644 index 0000000..4d24fa5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gperf-trace.c @@ -0,0 +1,250 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include +#include + +#include +#include "compiler.h" + +#include +#include + +#define panic(args...) \ + do { fprintf (stderr, args); exit (-1); } while (0) + +long dummy; + +static long iterations = 10000; +static int maxlevel = 100; + +#define KB 1024 +#define MB (1024*1024) + +static char big[64*MB]; /* should be >> max. cache size */ + +static inline double +gettime (void) +{ + struct timeval tv; + + gettimeofday (&tv, NULL); + return tv.tv_sec + 1e-6*tv.tv_usec; +} + +static int NOINLINE +measure_unwind (int maxlevel, double *step) +{ + double stop, start; + int level = 0; + void *buffer[128]; + + start = gettime (); + level = unw_backtrace(buffer, 128); + stop = gettime (); + + if (level <= maxlevel) + panic ("Unwound only %d levels, expected at least %d levels\n", + level, maxlevel); + + *step = (stop - start) / (double) level; + return 0; +} + +static int f1 (int, int, double *); + +static int NOINLINE +g1 (int level, int maxlevel, double *step) +{ + if (level == maxlevel) + return measure_unwind (maxlevel, step); + else + /* defeat last-call/sibcall optimization */ + return f1 (level + 1, maxlevel, step) + level; +} + +static int NOINLINE +f1 (int level, int maxlevel, double *step) +{ + if (level == maxlevel) + return measure_unwind (maxlevel, step); + else + /* defeat last-call/sibcall optimization */ + return g1 (level + 1, maxlevel, step) + level; +} + +static void +doit (const char *label) +{ + double step, min_step, first_step, sum_step; + int i; + + sum_step = first_step = 0.0; + min_step = 1e99; + for (i = 0; i < iterations; ++i) + { + f1 (0, maxlevel, &step); + + sum_step += step; + + if (step < min_step) + min_step = step; + + if (i == 0) + first_step = step; + } + printf ("%s: unw_step : 1st=%9.3f min=%9.3f avg=%9.3f nsec\n", label, + 1e9*first_step, 1e9*min_step, 1e9*sum_step/iterations); +} + +static long +sum (void *buf, size_t size) +{ + long s = 0; + char *cp = buf; + size_t i; + + for (i = 0; i < size; i += 8) + s += cp[i]; + return s; +} + +static void +measure_init (void) +{ +# define N 100 +# define M 10 /* must be at least 2 to get steady-state */ + double stop, start, get_cold, get_warm, init_cold, init_warm, delta; + struct + { + unw_cursor_t c; + char padding[1024]; /* should be > 2 * max. cacheline size */ + } + cursor[N]; + struct + { + unw_context_t uc; + char padding[1024]; /* should be > 2 * max. cacheline size */ + } + uc[N]; + int i, j; + + /* Run each test M times and take the minimum to filter out noise + such dynamic linker resolving overhead, context-switches, + page-in, cache, and TLB effects. */ + + get_cold = 1e99; + for (j = 0; j < M; ++j) + { + dummy += sum (big, sizeof (big)); /* flush the cache */ + for (i = 0; i < N; ++i) + uc[i].padding[511] = i; /* warm up the TLB */ + start = gettime (); + for (i = 0; i < N; ++i) + unw_getcontext (&uc[i].uc); + stop = gettime (); + delta = (stop - start) / N; + if (delta < get_cold) + get_cold = delta; + } + + init_cold = 1e99; + for (j = 0; j < M; ++j) + { + dummy += sum (big, sizeof (big)); /* flush cache */ + for (i = 0; i < N; ++i) + uc[i].padding[511] = i; /* warm up the TLB */ + start = gettime (); + for (i = 0; i < N; ++i) + unw_init_local (&cursor[i].c, &uc[i].uc); + stop = gettime (); + delta = (stop - start) / N; + if (delta < init_cold) + init_cold = delta; + } + + get_warm = 1e99; + for (j = 0; j < M; ++j) + { + start = gettime (); + for (i = 0; i < N; ++i) + unw_getcontext (&uc[0].uc); + stop = gettime (); + delta = (stop - start) / N; + if (delta < get_warm) + get_warm = delta; + } + + init_warm = 1e99; + for (j = 0; j < M; ++j) + { + start = gettime (); + for (i = 0; i < N; ++i) + unw_init_local (&cursor[0].c, &uc[0].uc); + stop = gettime (); + delta = (stop - start) / N; + if (delta < init_warm) + init_warm = delta; + } + + printf ("unw_getcontext : cold avg=%9.3f nsec, warm avg=%9.3f nsec\n", + 1e9 * get_cold, 1e9 * get_warm); + printf ("unw_init_local : cold avg=%9.3f nsec, warm avg=%9.3f nsec\n", + 1e9 * init_cold, 1e9 * init_warm); +} + +int +main (int argc, char **argv) +{ + struct rlimit rlim; + + rlim.rlim_cur = RLIM_INFINITY; + rlim.rlim_max = RLIM_INFINITY; + setrlimit (RLIMIT_STACK, &rlim); + + memset (big, 0xaa, sizeof (big)); + + if (argc > 1) + { + maxlevel = atol (argv[1]); + if (argc > 2) + iterations = atol (argv[2]); + } + + measure_init (); + + doit ("default "); + + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE); + doit ("no cache "); + + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL); + doit ("global cache "); + + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD); + doit ("per-thread cache"); + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-bt.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-bt.c new file mode 100644 index 0000000..beae2a3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-bt.c @@ -0,0 +1,263 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "compiler.h" + +#include +#if HAVE_EXECINFO_H +# include +#else + extern int backtrace (void **, int); +#endif +#include +#include +#include +#include +#include +#include +#include + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +#define SIG_STACK_SIZE 0x100000 + +int verbose; +int num_errors; + +/* These variables are global because they + * cause the signal stack to overflow */ +char buf[512], name[256]; +unw_cursor_t cursor; +unw_context_t uc; + +static void +do_backtrace (void) +{ + unw_word_t ip, sp, off; + unw_proc_info_t pi; + int ret; + + if (verbose) + printf ("\texplicit backtrace:\n"); + + unw_getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + panic ("unw_init_local failed!\n"); + + do + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + unw_get_reg (&cursor, UNW_REG_SP, &sp); + buf[0] = '\0'; + if (unw_get_proc_name (&cursor, name, sizeof (name), &off) == 0) + { + if (off) + snprintf (buf, sizeof (buf), "<%s+0x%lx>", name, (long) off); + else + snprintf (buf, sizeof (buf), "<%s>", name); + } + if (verbose) + { + printf ("%016lx %-32s (sp=%016lx)\n", (long) ip, buf, (long) sp); + + if (unw_get_proc_info (&cursor, &pi) == 0) + { + printf ("\tproc=0x%lx-0x%lx\n\thandler=0x%lx lsda=0x%lx gp=0x%lx", + (long) pi.start_ip, (long) pi.end_ip, + (long) pi.handler, (long) pi.lsda, (long) pi.gp); + } + +#if UNW_TARGET_IA64 + { + unw_word_t bsp; + + unw_get_reg (&cursor, UNW_IA64_BSP, &bsp); + printf (" bsp=%lx", bsp); + } +#endif + printf ("\n"); + } + + ret = unw_step (&cursor); + if (ret < 0) + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + printf ("FAILURE: unw_step() returned %d for ip=%lx\n", + ret, (long) ip); + ++num_errors; + } + } + while (ret > 0); + + { + void *buffer[20]; + int i, n; + + if (verbose) + printf ("\n\tvia backtrace():\n"); + n = backtrace (buffer, 20); + if (verbose) + for (i = 0; i < n; ++i) + printf ("[%d] ip=%p\n", i, buffer[i]); + } +} + +void +foo (long val UNUSED) +{ + do_backtrace (); +} + +void +bar (long v) +{ + extern long f (long); + int arr[v]; + + /* This is a vain attempt to use up lots of registers to force + the frame-chain info to be saved on the memory stack on ia64. + It happens to work with gcc v3.3.4 and gcc v3.4.1 but perhaps + not with any other compiler. */ + foo (f (arr[0]) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + f (v)) + )))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + ))))))))))))))))))))))))))))))))))))))))))))))))))))))); +} + +void +sighandler (int signal, void *siginfo UNUSED, void *context) +{ + ucontext_t *uc UNUSED; + int sp; + + uc = context; + + if (verbose) + { + printf ("sighandler: got signal %d, sp=%p", signal, &sp); +#if UNW_TARGET_IA64 +# if defined(__linux__) + printf (" @ %lx", uc->uc_mcontext.sc_ip); +# else + { + uint16_t reason; + uint64_t ip; + + __uc_get_reason (uc, &reason); + __uc_get_ip (uc, &ip); + printf (" @ %lx (reason=%d)", ip, reason); + } +# endif +#elif UNW_TARGET_X86 +#if defined __linux__ + printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_EIP]); +#elif defined __FreeBSD__ + printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_eip); +#endif +#elif UNW_TARGET_X86_64 +#if defined __linux__ + printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_RIP]); +#elif defined __FreeBSD__ + printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_rip); +#endif +#endif + printf ("\n"); + } + do_backtrace(); +} + +int +main (int argc, char **argv UNUSED) +{ + struct sigaction act; + stack_t stk; + + verbose = (argc > 1); + + if (verbose) + printf ("Normal backtrace:\n"); + + bar (1); + + memset (&act, 0, sizeof (act)); + act.sa_handler = (void (*)(int)) sighandler; + act.sa_flags = SA_SIGINFO; + if (sigaction (SIGTERM, &act, NULL) < 0) + panic ("sigaction: %s\n", strerror (errno)); + + if (verbose) + printf ("\nBacktrace across signal handler:\n"); + kill (getpid (), SIGTERM); + + if (verbose) + printf ("\nBacktrace across signal handler on alternate stack:\n"); + stk.ss_sp = malloc (SIG_STACK_SIZE); + if (!stk.ss_sp) + panic ("failed to allocate %u bytes\n", SIG_STACK_SIZE); + stk.ss_size = SIG_STACK_SIZE; + stk.ss_flags = 0; + if (sigaltstack (&stk, NULL) < 0) + panic ("sigaltstack: %s\n", strerror (errno)); + + memset (&act, 0, sizeof (act)); + act.sa_handler = (void (*)(int)) sighandler; + act.sa_flags = SA_ONSTACK | SA_SIGINFO; + if (sigaction (SIGTERM, &act, NULL) < 0) + panic ("sigaction: %s\n", strerror (errno)); + kill (getpid (), SIGTERM); + + if (num_errors > 0) + { + fprintf (stderr, "FAILURE: detected %d errors\n", num_errors); + exit (-1); + } + if (verbose) + printf ("SUCCESS.\n"); + + signal (SIGTERM, SIG_DFL); + stk.ss_flags = SS_DISABLE; + sigaltstack (&stk, NULL); + free (stk.ss_sp); + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-concurrent.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-concurrent.c new file mode 100644 index 0000000..6f3447f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-concurrent.c @@ -0,0 +1,136 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Verify that multi-threaded concurrent unwinding works as expected. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "compiler.h" + +#include +#include +#include +#include +#include +#include +#include + +#define NTHREADS 128 + +#define panic(args...) \ + do { fprintf (stderr, args); ++nerrors; } while (0) + +int verbose; +int nerrors; +int got_usr1, got_usr2; +char *sigusr1_sp; + +void +handler (int sig UNUSED) +{ + unw_word_t ip; + unw_context_t uc; + unw_cursor_t c; + int ret; + + unw_getcontext (&uc); + unw_init_local (&c, &uc); + do + { + unw_get_reg (&c, UNW_REG_IP, &ip); + if (verbose) + printf ("%lx: IP=%lx\n", (long) pthread_self (), (unsigned long) ip); + } + while ((ret = unw_step (&c)) > 0); + + if (ret < 0) + panic ("unw_step() returned %d\n", ret); +} + +void * +worker (void *arg UNUSED) +{ + signal (SIGUSR1, handler); + + if (verbose) + printf ("sending SIGUSR1\n"); + pthread_kill (pthread_self (), SIGUSR1); + return NULL; +} + +static void +doit (void) +{ + pthread_t th[NTHREADS]; + pthread_attr_t attr; + int i; + + pthread_attr_init (&attr); + pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN + 64*1024); + + for (i = 0; i < NTHREADS; ++i) + if (pthread_create (th + i, &attr, worker, NULL)) + { + fprintf (stderr, "FAILURE: Failed to create %u threads " + "(after %u threads)\n", + NTHREADS, i); + exit (-1); + } + + for (i = 0; i < NTHREADS; ++i) + pthread_join (th[i], NULL); +} + +int +main (int argc, char **argv UNUSED) +{ + if (argc > 1) + verbose = 1; + + if (verbose) + printf ("Caching: none\n"); + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE); + doit (); + + if (verbose) + printf ("Caching: global\n"); + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL); + doit (); + + if (verbose) + printf ("Caching: per-thread\n"); + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD); + doit (); + + if (nerrors) + { + fprintf (stderr, "FAILURE: detected %d errors\n", nerrors); + exit (-1); + } + + if (verbose) + printf ("SUCCESS\n"); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-dyn1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-dyn1.c new file mode 100644 index 0000000..bc7dc9c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-dyn1.c @@ -0,0 +1,223 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* This file tests dynamic code-generation via function-cloning. */ + +#include "flush-cache.h" + +#include "compiler.h" + +#include +#include +#include +#include +#include +#include +#include + +#if UNW_TARGET_ARM +#define MAX_FUNC_SIZE 96 /* FIXME: arch/compiler dependent */ +#else +#define MAX_FUNC_SIZE 2048 /* max. size of cloned function */ +#endif + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +typedef void (*template_t) (int, void (*)(), + int (*)(const char *, ...), const char *, + const char **); + +int verbose; + +static const char *strarr[] = + { + "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix", "x", NULL + }; + +#ifdef __ia64__ +struct fdesc + { + long code; + long gp; + }; +# define get_fdesc(fdesc,func) (fdesc = *(struct fdesc *) &(func)) +# define get_funcp(fdesc) ((template_t) &(fdesc)) +# define get_gp(fdesc) ((fdesc).gp) +#elif __arm__ +struct fdesc + { + long code; + long is_thumb; + }; +/* Workaround GCC bug: https://bugs.launchpad.net/gcc-linaro/+bug/721531 */ +# define get_fdesc(fdesc,func) ({long tmp = (long) &(func); \ + (fdesc).code = (long) &(func) & ~0x1; \ + (fdesc).is_thumb = tmp & 0x1;}) +/*# define get_fdesc(fdesc,func) ({(fdesc).code = (long) &(func) & ~0x1; \ + (fdesc).is_thumb = (long) &(func) & 0x1;})*/ +# define get_funcp(fdesc) ((template_t) ((fdesc).code | (fdesc).is_thumb)) +# define get_gp(fdesc) (0) +#else +struct fdesc + { + long code; + }; +# define get_fdesc(fdesc,func) (fdesc.code = (long) &(func)) +# define get_funcp(fdesc) ((template_t) (fdesc).code) +# define get_gp(fdesc) (0) +#endif + +void +template (int i, template_t self, + int (*printer)(const char *, ...), const char *fmt, const char **arr) +{ + (*printer) (fmt, arr[11 - i][0], arr[11 - i] + 1); + if (i > 0) + (*self) (i - 1, self, printer, fmt, arr); +} + +static void +sighandler (int signal) +{ + unw_cursor_t cursor; + char name[128], off[32]; + unw_word_t ip, offset; + unw_context_t uc; + int count; + + if (verbose) + printf ("caught signal %d\n", signal); + + unw_getcontext (&uc); + unw_init_local (&cursor, &uc); + + count = 0; + while (!unw_is_signal_frame (&cursor)) + { + if (unw_step (&cursor) < 0) + panic ("failed to find signal frame!\n"); + + if (count++ > 20) + { + panic ("Too many steps to the signal frame (%d)\n", count); + break; + } + } + unw_step (&cursor); + + count = 0; + do + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + name[0] = '\0'; + off[0] = '\0'; + if (unw_get_proc_name (&cursor, name, sizeof (name), &offset) == 0 + && offset > 0) + snprintf (off, sizeof (off), "+0x%lx", (long) offset); + if (verbose) + printf ("ip = %lx <%s%s>\n", (long) ip, name, off); + ++count; + + if (count > 20) + { + panic ("Too many steps (%d)\n", count); + break; + } + + } + while (unw_step (&cursor) > 0); + + if (count != 13) + panic ("FAILURE: expected 13, not %d frames below signal frame\n", count); + + if (verbose) + printf ("SUCCESS\n"); + exit (0); +} + +int +dev_null (const char *format UNUSED, ...) +{ + return 0; +} + +int +main (int argc, char *argv[] UNUSED) +{ + unw_dyn_region_info_t *region; + unw_dyn_info_t di; + struct fdesc fdesc; + template_t funcp; + void *mem; + + if (argc > 1) + ++verbose; + + mem = malloc (getpagesize ()); + + get_fdesc (fdesc, template); + + if (verbose) + printf ("old code @ %p, new code @ %p\n", (void *) fdesc.code, mem); + + memcpy (mem, (void *) fdesc.code, MAX_FUNC_SIZE); + mprotect ((void *) ((long) mem & ~(getpagesize () - 1)), + 2*getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC); + + flush_cache (mem, MAX_FUNC_SIZE); + + signal (SIGSEGV, sighandler); + + /* register the new function: */ + region = alloca (_U_dyn_region_info_size (2)); + region->next = NULL; + region->insn_count = 3 * (MAX_FUNC_SIZE / 16); + region->op_count = 2; + _U_dyn_op_alias (®ion->op[0], 0, -1, fdesc.code); + _U_dyn_op_stop (®ion->op[1]); + + memset (&di, 0, sizeof (di)); + di.start_ip = (long) mem; + di.end_ip = (long) mem + 16*region->insn_count/3; + di.gp = get_gp (fdesc); + di.format = UNW_INFO_FORMAT_DYNAMIC; + di.u.pi.name_ptr = (unw_word_t) "copy_of_template"; + di.u.pi.regions = region; + + _U_dyn_register (&di); + + /* call new function: */ + fdesc.code = (long) mem; + funcp = get_funcp (fdesc); + + if (verbose) + (*funcp) (10, funcp, printf, "iteration %c%s\n", strarr); + else + (*funcp) (10, funcp, dev_null, "iteration %c%s\n", strarr); + + _U_dyn_cancel (&di); + return -1; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-exc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-exc.c new file mode 100644 index 0000000..1170bdd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-exc.c @@ -0,0 +1,162 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* This illustrates the basics of using the unwind interface for + exception handling. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include + +#ifdef HAVE_IA64INTRIN_H +# include +#endif + +#define panic(args...) \ + { ++nerrors; fprintf (stderr, args); } + +int nerrors = 0; +int verbose = 0; +int depth = 13; +volatile int got_here = 0; + +extern void b (int); + +void +raise_exception (void) +{ + unw_cursor_t cursor; + unw_context_t uc; + int i; + + unw_getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + { + panic ("unw_init_local() failed!\n"); + return; + } + + /* unwind to top-most frame a(), skipping over b() and raise_exception(): */ + for (i = 0; i < depth + 2; ++i) + if (unw_step (&cursor) < 0) + { + panic ("unw_step() failed!\n"); + return; + } + unw_resume (&cursor); /* transfer control to exception handler */ +} + +uintptr_t +get_bsp (void) +{ +#if UNW_TARGET_IA64 +# ifdef __INTEL_COMPILER + return __getReg (_IA64_REG_AR_BSP); +# else + return (uintptr_t) __builtin_ia64_bsp (); +# endif +#else + return 0; +#endif +} + +int +a (int n) +{ + long stack; + int result = 99; + + if (verbose) + printf ("a(n=%d): sp=%p bsp=0x%lx\n", + n, &stack, (unsigned long) get_bsp ()); + + if (n > 0) + a (n - 1); + else + b (16); + + if (verbose) + { + printf ("exception handler: here we go (sp=%p, bsp=0x%lx)...\n", + &stack, (unsigned long) get_bsp ()); + /* This call works around a bug in gcc (up-to pre3.4) which + causes invalid assembly code to be generated when + __builtin_ia64_bsp() gets predicated. */ + getpid (); + } + if (n == depth) + { + result = 0; + got_here = 1; + } + return result; +} + +void +b (int n) +{ + if ((n & 1) == 0) + { + if (verbose) + printf ("b(n=%d) calling raise_exception()\n", n); + raise_exception (); + } + panic ("FAILURE: b() returned from raise_exception()!!\n"); +} + +int +main (int argc, char **argv) +{ + int result; + + if (argc > 1) + { + ++verbose; + depth = atol (argv[1]); + if (depth < 1) + { + fprintf (stderr, "Usage: %s depth\n" + " depth must be >= 1\n", argv[0]); + exit (-1); + } + } + + result = a (depth); + if (result != 0 || !got_here || nerrors > 0) + { + fprintf (stderr, + "FAILURE: test failed: result=%d got_here=%d nerrors=%d\n", + result, got_here, nerrors); + exit (-1); + } + + if (verbose) + printf ("SUCCESS!\n"); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-init.cxx b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-init.cxx new file mode 100644 index 0000000..afded01 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-init.cxx @@ -0,0 +1,107 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* This file tests unwinding from a constructor from within an + atexit() handler. */ + +#include +#include +#include + +#include +#include "compiler.h" + +int verbose, errors; + +#define panic(args...) \ + { ++errors; fprintf (stderr, args); return; } + +class Test_Class { + public: + Test_Class (void); +}; + +static Test_Class t; + +static void +do_backtrace (void) +{ + char name[128], off[32]; + unw_word_t ip, offset; + unw_cursor_t cursor; + unw_context_t uc; + int ret, count = 0; + + unw_getcontext (&uc); + unw_init_local (&cursor, &uc); + + do + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + name[0] = '\0'; + off[0] = '\0'; + if (unw_get_proc_name (&cursor, name, sizeof (name), &offset) == 0 + && offset > 0) + snprintf (off, sizeof (off), "+0x%lx", (long) offset); + if (verbose) + printf (" [%lx] <%s%s>\n", (long) ip, name, off); + if (++count > 32) + panic ("FAILURE: didn't reach beginning of unwind-chain\n"); + } + while ((ret = unw_step (&cursor)) > 0); + + if (ret < 0) + panic ("FAILURE: unw_step() returned %d\n", ret); +} + +static void +b (void) +{ + do_backtrace(); +} + +static void +a (void) +{ + if (verbose) + printf ("do_backtrace() from atexit()-handler:\n"); + b(); + if (errors) + abort (); /* cannot portably call exit() from an atexit() handler */ +} + +Test_Class::Test_Class (void) +{ + if (verbose) + printf ("do_backtrace() from constructor:\n"); + b(); +} + +int +main (int argc, char **argv UNUSED) +{ + verbose = argc > 1; + return atexit (a); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-nomalloc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-nomalloc.c new file mode 100644 index 0000000..5b97fc7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-nomalloc.c @@ -0,0 +1,110 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2009 Google, Inc + Contributed by Arun Sharma + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include +#include +#include + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +int verbose; +int num_errors; +int in_unwind; + +void * +malloc(size_t s) +{ + static void * (*func)(); + + if(!func) + func = (void *(*)()) dlsym(RTLD_NEXT, "malloc"); + + if (in_unwind) { + num_errors++; + return NULL; + } else { + return func(s); + } +} + +static void +do_backtrace (void) +{ + unw_word_t ip, sp; + unw_cursor_t cursor; + unw_context_t uc; + int ret; + + in_unwind = 1; + unw_getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + panic ("unw_init_local failed!\n"); + + do + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + unw_get_reg (&cursor, UNW_REG_SP, &sp); + + ret = unw_step (&cursor); + if (ret < 0) + { + ++num_errors; + } + } + while (ret > 0); + in_unwind = 0; +} + +void +foo3 (void) +{ + do_backtrace (); +} + +void +foo2 (void) +{ + foo3 (); +} + +void +foo1 (void) +{ + foo2 (); +} + +int +main (void) +{ + foo1(); + + if (num_errors > 0) + { + fprintf (stderr, "FAILURE: detected %d errors\n", num_errors); + exit (-1); + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-resume-sig-rt.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-resume-sig-rt.c new file mode 100644 index 0000000..df515fc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-resume-sig-rt.c @@ -0,0 +1,31 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + Copyright (C) 2012 Tommi Rantala + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* The purpose of this test is to invoke different code paths in libunwind (on + * some architectures), that are executed when the SA_SIGINFO sigaction() flag + * is used. + */ + +#define TEST_WITH_SIGINFO 1 +#include "Gtest-resume-sig.c" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-resume-sig.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-resume-sig.c new file mode 100644 index 0000000..18ec65d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-resume-sig.c @@ -0,0 +1,200 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Verify that unw_resume() restores the signal mask at proper time. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "compiler.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_IA64INTRIN_H +# include +#endif + +#define panic(args...) \ + do { fprintf (stderr, args); ++nerrors; } while (0) + +int verbose; +int nerrors; +int got_usr1, got_usr2; +char *sigusr1_sp; + +uintptr_t +get_bsp (void) +{ +#if UNW_TARGET_IA64 +# ifdef __INTEL_COMPILER + return __getReg (_IA64_REG_AR_BSP); +# else + return (uintptr_t) __builtin_ia64_bsp (); +# endif +#else + return 0; +#endif +} + +#ifdef TEST_WITH_SIGINFO +void +handler (int sig, + siginfo_t *si UNUSED, + void *ucontext UNUSED) +#else +void +handler (int sig) +#endif +{ + unw_word_t ip; + sigset_t mask; + unw_context_t uc; + unw_cursor_t c; + char foo; + int ret; + // The test rely on SIGUSR2 mask to be cleared when the handler returns. + // For local context from the signal handler, there doesn't seem to be a way + // currently to set it so just clear the whole struct to make sure the signal mask is cleared. + // This should probably be fixed to avoid signal mask being set to random values + // by `unw_resume` if the context was not pre-zeroed., + // Using the signal ucontext direction should also work automatically but currently doesn't + // on ARM/AArch64 (or any other archs that doesn't have a proper sigreturn implementation) + memset(&uc, 0x0, sizeof(uc)); + +#if UNW_TARGET_IA64 + if (verbose) + printf ("bsp = %llx\n", (unsigned long long) get_bsp ()); +#endif + + if (verbose) + printf ("got signal %d\n", sig); + + if (sig == SIGUSR1) + { + ++got_usr1; + sigusr1_sp = &foo; + + sigemptyset (&mask); + sigaddset (&mask, SIGUSR2); + sigprocmask (SIG_BLOCK, &mask, NULL); + kill (getpid (), SIGUSR2); /* pend SIGUSR2 */ + + signal (SIGUSR1, SIG_IGN); + + if ((ret = unw_getcontext (&uc)) < 0) + panic ("unw_getcontext() failed: ret=%d\n", ret); + if ((ret = unw_init_local (&c, &uc)) < 0) + panic ("unw_init_local() failed: ret=%d\n", ret); + + if ((ret = unw_step (&c)) < 0) /* step to signal trampoline */ + panic ("unw_step(1) failed: ret=%d\n", ret); + + if ((ret = unw_step (&c)) < 0) /* step to kill() */ + panic ("unw_step(2) failed: ret=%d\n", ret); + +#if defined(UNW_TARGET_TILEGX) + if ((ret = unw_step (&c)) < 0) /* step to signal trampoline */ + panic ("unw_step(2) failed: ret=%d\n", ret); +#endif + + if ((ret = unw_get_reg (&c, UNW_REG_IP, &ip)) < 0) + panic ("unw_get_reg(IP) failed: ret=%d\n", ret); + if (verbose) + printf ("resuming at 0x%lx, with SIGUSR2 pending\n", + (unsigned long) ip); + unw_resume (&c); + } + else if (sig == SIGUSR2) + { + ++got_usr2; + if (got_usr1) + { + if (verbose) + printf ("OK: stack still at %p\n", &foo); + } + signal (SIGUSR2, SIG_IGN); + } + else + panic ("Got unexpected signal %d\n", sig); +} + +int +main (int argc, char **argv UNUSED) +{ + struct sigaction sa; + float d = 1.0; + int n = 0; + + if (argc > 1) + verbose = 1; + + memset (&sa, 0, sizeof(sa)); +#ifdef TEST_WITH_SIGINFO + sa.sa_sigaction = handler; + sa.sa_flags = SA_SIGINFO; +#else + sa.sa_handler = handler; +#endif + + if (sigaction (SIGUSR1, &sa, NULL) != 0 || + sigaction (SIGUSR2, &sa, NULL) != 0) + { + fprintf (stderr, "sigaction() failed: %s\n", strerror (errno)); + return -1; + } + + /* Use the FPU a bit; otherwise we get spurious errors should the + signal handler need to use the FPU for any reason. This seems to + happen on x86-64. */ + while (d > 0.0) + { + d /= 2.0; + ++n; + } + if (n > 9999) + return -1; /* can't happen, but don't tell the compiler... */ + + if (verbose) + printf ("sending SIGUSR1\n"); + kill (getpid (), SIGUSR1); + + if (!got_usr2) + panic ("failed to get SIGUSR2\n"); + + if (nerrors) + { + fprintf (stderr, "FAILURE: detected %d errors\n", nerrors); + exit (-1); + } + + if (verbose) + printf ("SUCCESS\n"); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-trace.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-trace.c new file mode 100644 index 0000000..fc1f646 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Gtest-trace.c @@ -0,0 +1,282 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "compiler.h" + +#include +#if HAVE_EXECINFO_H +# include +#else + extern int backtrace (void **, int); +#endif +#include +#include +#include +#include +#include +#include +#include + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +#define SIG_STACK_SIZE 0x100000 + +int verbose; +int num_errors; + +/* These variables are global because they + * cause the signal stack to overflow */ +char buf[512], name[256]; +void *addresses[3][128]; +unw_cursor_t cursor; +unw_context_t uc; + +static void +do_backtrace (void) +{ + unw_word_t ip; + int ret = -UNW_ENOINFO; + int depth = 0; + int i, n, m; + + if (verbose) + printf ("\tnormal trace:\n"); + + unw_getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + panic ("unw_init_local failed!\n"); + + do + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + addresses[0][depth] = (void *) ip; + } + while ((ret = unw_step (&cursor)) > 0 && ++depth < 128); + + if (ret < 0) + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + printf ("FAILURE: unw_step() returned %d for ip=%lx\n", ret, (long) ip); + ++num_errors; + } + + if (verbose) + for (i = 0; i < depth; ++i) + printf ("\t #%-3d ip=%p\n", i, addresses[0][i]); + + if (verbose) + printf ("\n\tvia backtrace():\n"); + + n = backtrace (addresses[1], 128); + + if (verbose) + for (i = 0; i < n; ++i) + printf ("\t #%-3d ip=%p\n", i, addresses[1][i]); + + if (verbose) + printf ("\n\tvia unw_backtrace():\n"); + + m = unw_backtrace (addresses[2], 128); + + if (verbose) + for (i = 0; i < m; ++i) + printf ("\t #%-3d ip=%p\n", i, addresses[2][i]); + + if (m != depth+1) + { + printf ("FAILURE: unw_step() loop and unw_backtrace() depths differ: %d vs. %d\n", depth, m); + ++num_errors; + } + + if (n != depth+1) + { + printf ("FAILURE: unw_step() loop and backtrace() depths differ: %d vs. %d\n", depth, n); + ++num_errors; + } + + if (n == m) + for (i = 1; i < n; ++i) + /* Allow one in difference in comparison, trace returns adjusted addresses. */ + if (labs((unw_word_t) addresses[1][i] - (unw_word_t) addresses[2][i]) > 1) + { + printf ("FAILURE: backtrace() and unw_backtrace() addresses differ at %d: %p vs. %p\n", + i, addresses[1][i], addresses[2][i]); + ++num_errors; + } + + if (n == depth+1) + for (i = 1; i < depth; ++i) + /* Allow one in difference in comparison, trace returns adjusted addresses. */ + if (labs((unw_word_t) addresses[0][i] - (unw_word_t) addresses[1][i]) > 1) + { + printf ("FAILURE: unw_step() loop and backtrace() addresses differ at %d: %p vs. %p\n", + i, addresses[0][i], addresses[1][i]); + ++num_errors; + } +} + +void +foo (long val UNUSED) +{ + do_backtrace (); +} + +void +bar (long v) +{ + extern long f (long); + int arr[v]; + + /* This is a vain attempt to use up lots of registers to force + the frame-chain info to be saved on the memory stack on ia64. + It happens to work with gcc v3.3.4 and gcc v3.4.1 but perhaps + not with any other compiler. */ + foo (f (arr[0]) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + f (v)) + )))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + ))))))))))))))))))))))))))))))))))))))))))))))))))))))); +} + +void +sighandler (int signal, void *siginfo UNUSED, void *context) +{ + ucontext_t *uc UNUSED; + int sp; + + uc = context; + + if (verbose) + { + printf ("sighandler: got signal %d, sp=%p", signal, &sp); +#if UNW_TARGET_IA64 +# if defined(__linux__) + printf (" @ %lx", uc->uc_mcontext.sc_ip); +# else + { + uint16_t reason; + uint64_t ip; + + __uc_get_reason (uc, &reason); + __uc_get_ip (uc, &ip); + printf (" @ %lx (reason=%d)", ip, reason); + } +# endif +#elif UNW_TARGET_X86 +#if defined __linux__ + printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_EIP]); +#elif defined __FreeBSD__ + printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_eip); +#endif +#elif UNW_TARGET_X86_64 +#if defined __linux__ + printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_RIP]); +#elif defined __FreeBSD__ + printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_rip); +#endif +#elif defined UNW_TARGET_ARM +#if defined __linux__ + printf (" @ %lx", (unsigned long) uc->uc_mcontext.arm_pc); +#elif defined __FreeBSD__ + printf (" @ %lx", (unsigned long) uc->uc_mcontext.__gregs[_REG_PC]); +#endif +#endif + printf ("\n"); + } + do_backtrace(); +} + +int +main (int argc, char **argv UNUSED) +{ + struct sigaction act; + stack_t stk; + + verbose = (argc > 1); + + if (verbose) + printf ("Normal backtrace:\n"); + + bar (1); + + memset (&act, 0, sizeof (act)); + act.sa_handler = (void (*)(int)) sighandler; + act.sa_flags = SA_SIGINFO; + if (sigaction (SIGTERM, &act, NULL) < 0) + panic ("sigaction: %s\n", strerror (errno)); + + if (verbose) + printf ("\nBacktrace across signal handler:\n"); + kill (getpid (), SIGTERM); + + if (verbose) + printf ("\nBacktrace across signal handler on alternate stack:\n"); + stk.ss_sp = malloc (SIG_STACK_SIZE); + if (!stk.ss_sp) + panic ("failed to allocate %u bytes\n", SIG_STACK_SIZE); + stk.ss_size = SIG_STACK_SIZE; + stk.ss_flags = 0; + if (sigaltstack (&stk, NULL) < 0) + panic ("sigaltstack: %s\n", strerror (errno)); + + memset (&act, 0, sizeof (act)); + act.sa_handler = (void (*)(int)) sighandler; + act.sa_flags = SA_ONSTACK | SA_SIGINFO; + if (sigaction (SIGTERM, &act, NULL) < 0) + panic ("sigaction: %s\n", strerror (errno)); + kill (getpid (), SIGTERM); + + if (num_errors > 0) + { + fprintf (stderr, "FAILURE: detected %d errors\n", num_errors); + exit (-1); + } + + if (verbose) + printf ("SUCCESS.\n"); + + signal (SIGTERM, SIG_DFL); + stk.ss_flags = SS_DISABLE; + sigaltstack (&stk, NULL); + free (stk.ss_sp); + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-nat.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-nat.c new file mode 100644 index 0000000..15ef0ca --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-nat.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gia64-test-nat.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-rbs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-rbs.c new file mode 100644 index 0000000..b838ebe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-rbs.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gia64-test-rbs.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-readonly.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-readonly.c new file mode 100644 index 0000000..cd23e92 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-readonly.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gia64-test-readonly.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-stack.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-stack.c new file mode 100644 index 0000000..3647629 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lia64-test-stack.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gia64-test-stack.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lperf-simple.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lperf-simple.c new file mode 100644 index 0000000..cdf38c2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lperf-simple.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gperf-simple.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lperf-trace.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lperf-trace.c new file mode 100644 index 0000000..1c3cf21 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lperf-trace.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gperf-trace.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lrs-race.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lrs-race.c new file mode 100644 index 0000000..6fe4972 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Lrs-race.c @@ -0,0 +1,1514 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2005 Hewlett-Packard Co + Contributed by Paul Pluzhnikov + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Verify that register state caches work under all caching policies + in a multi-threaded environment with a large number IPs */ + +#define UNW_LOCAL_ONLY +#include +#include "compiler.h" + +#include +#include +#include + +/* ITERS=1000, NTHREAD=10 caught some bugs in the past */ +#ifndef ITERS +#define ITERS 100 +#endif + +#ifndef NTHREAD +#define NTHREAD 2 +#endif + +int verbose; + +void +foo_0 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_1 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_2 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_3 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_4 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_5 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_6 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_7 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_8 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_9 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_10 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_11 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_12 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_13 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_14 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_15 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_16 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_17 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_18 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_19 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_20 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_21 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_22 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_23 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_24 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_25 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_26 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_27 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_28 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_29 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_30 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_31 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_32 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_33 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_34 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_35 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_36 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_37 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_38 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_39 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_40 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_41 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_42 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_43 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_44 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_45 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_46 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_47 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_48 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_49 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_50 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_51 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_52 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_53 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_54 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_55 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_56 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_57 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_58 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_59 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_60 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_61 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_62 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_63 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_64 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_65 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_66 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_67 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_68 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_69 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_70 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_71 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_72 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_73 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_74 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_75 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_76 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_77 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_78 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_79 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_80 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_81 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_82 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_83 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_84 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_85 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_86 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_87 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_88 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_89 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_90 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_91 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_92 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_93 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_94 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_95 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_96 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_97 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_98 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_99 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_100 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_101 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_102 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_103 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_104 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_105 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_106 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_107 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_108 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_109 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_110 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_111 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_112 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_113 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_114 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_115 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_116 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_117 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_118 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_119 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_120 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_121 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_122 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_123 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_124 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_125 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_126 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_127 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_128 (void) +{ + void *buf[20]; + int n; + + if ((n = unw_backtrace (buf, 20)) < 3) + abort (); +} + +void * +bar(void *p UNUSED) +{ + int i; + for (i = 0; i < ITERS; ++i) { + foo_0 (); + foo_1 (); + foo_2 (); + foo_3 (); + foo_4 (); + foo_5 (); + foo_6 (); + foo_7 (); + foo_8 (); + foo_9 (); + foo_10 (); + foo_11 (); + foo_12 (); + foo_13 (); + foo_14 (); + foo_15 (); + foo_16 (); + foo_17 (); + foo_18 (); + foo_19 (); + foo_20 (); + foo_21 (); + foo_22 (); + foo_23 (); + foo_24 (); + foo_25 (); + foo_26 (); + foo_27 (); + foo_28 (); + foo_29 (); + foo_30 (); + foo_31 (); + foo_32 (); + foo_33 (); + foo_34 (); + foo_35 (); + foo_36 (); + foo_37 (); + foo_38 (); + foo_39 (); + foo_40 (); + foo_41 (); + foo_42 (); + foo_43 (); + foo_44 (); + foo_45 (); + foo_46 (); + foo_47 (); + foo_48 (); + foo_49 (); + foo_50 (); + foo_51 (); + foo_52 (); + foo_53 (); + foo_54 (); + foo_55 (); + foo_56 (); + foo_57 (); + foo_58 (); + foo_59 (); + foo_60 (); + foo_61 (); + foo_62 (); + foo_63 (); + foo_64 (); + foo_65 (); + foo_66 (); + foo_67 (); + foo_68 (); + foo_69 (); + foo_70 (); + foo_71 (); + foo_72 (); + foo_73 (); + foo_74 (); + foo_75 (); + foo_76 (); + foo_77 (); + foo_78 (); + foo_79 (); + foo_80 (); + foo_81 (); + foo_82 (); + foo_83 (); + foo_84 (); + foo_85 (); + foo_86 (); + foo_87 (); + foo_88 (); + foo_89 (); + foo_90 (); + foo_91 (); + foo_92 (); + foo_93 (); + foo_94 (); + foo_95 (); + foo_96 (); + foo_97 (); + foo_98 (); + foo_99 (); + foo_100 (); + foo_101 (); + foo_102 (); + foo_103 (); + foo_104 (); + foo_105 (); + foo_106 (); + foo_107 (); + foo_108 (); + foo_109 (); + foo_110 (); + foo_111 (); + foo_112 (); + foo_113 (); + foo_114 (); + foo_115 (); + foo_116 (); + foo_117 (); + foo_118 (); + foo_119 (); + foo_120 (); + foo_121 (); + foo_122 (); + foo_123 (); + foo_124 (); + foo_125 (); + foo_126 (); + foo_127 (); + foo_128 (); + } + return NULL; +} + +int doit (void) +{ + pthread_t tid[NTHREAD]; + int i; + + for (i = 0; i < NTHREAD; ++i) + if (pthread_create (&tid[i], NULL, bar, NULL)) + return 1; + + for (i = 0; i < NTHREAD; ++i) + if (pthread_join (tid[i], NULL)) + return 1; + + return 0; +} + +int +main (int argc, char **argv UNUSED) +{ + if (argc > 1) + verbose = 1; + + if (verbose) + printf ("Caching: none\n"); + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE); + doit (); + + if (verbose) + printf ("Caching: global\n"); + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL); + doit (); + + if (verbose) + printf ("Caching: per-thread\n"); + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD); + doit (); + + if (verbose) + printf ("SUCCESS\n"); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-bt.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-bt.c new file mode 100644 index 0000000..3489bf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-bt.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gtest-bt.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-concurrent.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-concurrent.c new file mode 100644 index 0000000..9462607 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-concurrent.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gtest-concurrent.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-cxx-exceptions.cxx b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-cxx-exceptions.cxx new file mode 100644 index 0000000..24bcd13 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-cxx-exceptions.cxx @@ -0,0 +1,80 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2010 stefan.demharter@gmx.net + Copyright (C) 2010 arun.sharma@google.com + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include +#include +#include "compiler.h" + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +static int verbose; + +struct Test +{ + public: // --- ctor/dtor --- + Test() { ++counter_; } + ~Test() { -- counter_; } + Test(const Test&) { ++counter_; } + + public: // --- static members --- + static int counter_; +}; + +int Test::counter_ = 0; + +// Called by foo +extern "C" void bar() +{ + Test t; + try { + Test t; + throw 5; + } catch (...) { + Test t; + if (verbose) + printf("Throwing an int\n"); + throw 6; + } +} + +int main(int argc, char **argv UNUSED) +{ + if (argc > 1) + verbose = 1; + try { + Test t; + bar(); + } catch (int) { + // Dtor of all Test-object has to be called. + if (Test::counter_ != 0) + panic("Counter non-zero\n"); + return Test::counter_; + } catch (...) { + // An int was thrown - we should not get here. + panic("Int was thrown why are we here?\n"); + } + exit(0); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-dyn1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-dyn1.c new file mode 100644 index 0000000..c2cab6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-dyn1.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gtest-dyn1.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-exc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-exc.c new file mode 100644 index 0000000..36a234c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-exc.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gtest-exc.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-init-local-signal-lib.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-init-local-signal-lib.c new file mode 100644 index 0000000..7474f71 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-init-local-signal-lib.c @@ -0,0 +1,6 @@ +#include + +/* To prevent inlining and optimizing away */ +int foo(volatile int* f) { + return *f; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-init-local-signal.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-init-local-signal.c new file mode 100644 index 0000000..4bde218 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-init-local-signal.c @@ -0,0 +1,60 @@ +#include "libunwind.h" +#include +#include +#include + +#include + +#include +#include +#include + +int stepper(unw_cursor_t* c) { + int steps = 0; + int ret = 1; + while (ret) { + + ret = unw_step(c); + if (!ret) { + break; + } + steps++; + } + return steps; +} + +/* Verify that we can step from both ucontext, and from getcontext() + * roughly the same. This tests that the IP from ucontext is used + * correctly (see impl of unw_init_local2) */ +void handler(int num, siginfo_t* info, void* ucontext) { + unw_cursor_t c; + unw_context_t context; + unw_getcontext(&context); + int ret = unw_init_local2(&c, ucontext, UNW_INIT_SIGNAL_FRAME); + assert(!ret); + int ucontext_steps = stepper(&c); + + ret = unw_init_local(&c, &context); + (void)ret; + assert(!ret); + int getcontext_steps = stepper(&c); + if (ucontext_steps == getcontext_steps - 2) { + exit(0); + } + printf("unw_getcontext steps was %i, ucontext steps was %i, should be %i\n", + getcontext_steps, ucontext_steps, getcontext_steps - 2); + exit(-1); +} + +int foo(volatile int* f); + +int main(){ + struct sigaction a; + memset(&a, 0, sizeof(struct sigaction)); + a.sa_sigaction = &handler; + a.sa_flags = SA_SIGINFO; + sigaction(SIGSEGV, &a, NULL); + + foo(NULL); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-init.cxx b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-init.cxx new file mode 100644 index 0000000..58a6ea4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-init.cxx @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gtest-init.cxx" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-mem-validate.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-mem-validate.c new file mode 100644 index 0000000..1cacb9f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-mem-validate.c @@ -0,0 +1,143 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Copyright (c) 2003 Hewlett-Packard Co. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "compiler.h" + +#include +#include +#include +#include +#include + +#include +#include + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +void * stack_start; + +#define PAGE_SIZE 4096 + +void do_backtrace (void) +{ + void* buffer[1024]; + int size = 1024; + mprotect((void*)((uintptr_t)stack_start & ~(PAGE_SIZE - 1)), + PAGE_SIZE, PROT_NONE); + + unw_cursor_t cursor; + unw_word_t ip, sp; + unw_context_t uc; + int ret; + int steps = 0; + + unw_getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + panic ("unw_init_local failed!\n"); + + do + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + unw_get_reg (&cursor, UNW_REG_SP, &sp); + + ret = unw_step (&cursor); + if (ret < 0) + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + } + steps ++; + } + while (ret > 0); + + if (steps < 5) + { + exit(-1); + } + + mprotect((void*)((uintptr_t)stack_start & ~(PAGE_SIZE - 1)), + PAGE_SIZE, PROT_READ|PROT_WRITE); +} + +void consume_and_run (int depth) +{ + unw_cursor_t cursor; + unw_context_t uc; + char string[1024]; + + sprintf (string, "hello %p %p\n", &cursor, &uc); + if (depth == 0) { + do_backtrace(); + } else { + consume_and_run(depth - 1); + } +} + +int +main (int argc, char **argv UNUSED) +{ + int start; + unw_context_t uc; + unw_cursor_t cursor; + + stack_start = &start; + + // Initialize pipe mem validate check, opens file descriptors + unw_getcontext(&uc); + if (unw_init_local (&cursor, &uc) < 0) + panic ("unw_init_local failed!\n"); + + int i; + for (i = 3; i < 10; i++) + { + + pid_t childpid = fork(); + if (!childpid) + { + /* Close fds and make sure we still work */ + int ret = close(i); + } + + int status; + if (childpid) + { + wait(&status); + if (WIFEXITED(status)) + return WEXITSTATUS(status); + else + return -1; + } + else + { + consume_and_run (10); + + return 0; + } + } + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-nocalloc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-nocalloc.c new file mode 100644 index 0000000..f5c31b2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-nocalloc.c @@ -0,0 +1,137 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2011 Google, Inc + Contributed by Paul Pluzhnikov + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#define UNW_LOCAL_ONLY +#include + +#include +#include +#include +#include +#include + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +int num_mallocs; +int num_callocs; +int in_unwind; + +void * +calloc(size_t n, size_t s) +{ + static void * (*func)(size_t, size_t); + +#ifdef __GLIBC__ + /* In glibc, dlsym() calls calloc. Calling dlsym(RTLD_NEXT, "calloc") here + causes infinite recursion. Instead, we simply use it by its other + name. */ + extern void *__libc_calloc(size_t, size_t); + if (!func) + func = &__libc_calloc; +#else + if(!func) + func = dlsym(RTLD_NEXT, "calloc"); +#endif + + if (in_unwind) { + num_callocs++; + return NULL; + } else { + return func(n, s); + } +} + +void * +malloc(size_t s) +{ + static void * (*func)(size_t); + + if(!func) + func = dlsym(RTLD_NEXT, "malloc"); + + if (in_unwind) { + num_mallocs++; + return NULL; + } else { + return func(s); + } +} + +static void +do_backtrace (void) +{ + const int num_levels = 100; + void *pc[num_levels]; + + in_unwind = 1; + unw_backtrace(pc, num_levels); + in_unwind = 0; +} + +void +foo3 (void) +{ + do_backtrace (); +} + +void +foo2 (void) +{ + foo3 (); +} + +void +foo1 (void) +{ + foo2 (); +} + +int +main (void) +{ + int i, num_errors; + + /* Create (and leak) 100 TSDs, then call backtrace() + and check that it doesn't call malloc()/calloc(). */ + for (i = 0; i < 100; ++i) { + pthread_key_t key; + if (pthread_key_create (&key, NULL)) + panic ("FAILURE: unable to create key %d\n", i); + } + /* Call backtrace right after thread creation, + * where we are sure that we're not inside malloc */ + do_backtrace(); + num_mallocs = num_callocs = 0; + foo1 (); + num_errors = num_mallocs + num_callocs; + if (num_errors > 0) + { + fprintf (stderr, + "FAILURE: detected %d error%s (malloc: %d, calloc: %d)\n", + num_errors, num_errors > 1 ? "s" : "", + num_mallocs, num_callocs); + exit (-1); + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-nomalloc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-nomalloc.c new file mode 100644 index 0000000..74d6331 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-nomalloc.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gtest-nomalloc.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-resume-sig-rt.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-resume-sig-rt.c new file mode 100644 index 0000000..01fd6dc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-resume-sig-rt.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gtest-resume-sig-rt.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-resume-sig.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-resume-sig.c new file mode 100644 index 0000000..0047b52 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-resume-sig.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gtest-resume-sig.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-trace.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-trace.c new file mode 100644 index 0000000..fb0e9c1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-trace.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if !defined(UNW_REMOTE_ONLY) +#include "Gtest-trace.c" +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-varargs.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-varargs.c new file mode 100644 index 0000000..17ac600 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Ltest-varargs.c @@ -0,0 +1,84 @@ +#define UNW_LOCAL_ONLY +#include +#include "compiler.h" + +#include +#include +#include +#include + +int ok; +int verbose; + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 3) +void a (int, ...) __attribute__((optimize(0))); +void b (void) __attribute__((optimize(0))); +void c (void) __attribute__((optimize(0))); +#endif + +void NOINLINE +b (void) +{ + void *v[20]; + int i, n; + + n = unw_backtrace(v, 20); + + /* Check that the number of addresses given by unw_backtrace() looks + * reasonable. If the compiler inlined everything, then this check will also + * break. */ + if (n >= 7) + ok = 1; + + if (verbose) + for (i = 0; i < n; ++i) + printf ("[%d] %p\n", i, v[i]); +} + +void NOINLINE +c (void) +{ + b (); +} + +void NOINLINE +a (int d, ...) +{ + switch (d) + { + case 5: + a (4, 2,4); + break; + case 4: + a (3, 1,3,5); + break; + case 3: + a (2, 11, 13, 17, 23); + break; + case 2: + a (1); + break; + case 1: + c (); + } +} + +int +main (int argc, char **argv UNUSED) +{ + if (argc > 1) + verbose = 1; + + a (5, 3, 4, 5, 6); + + if (!ok) + { + fprintf (stderr, "FAILURE: expected deeper backtrace.\n"); + return 1; + } + + if (verbose) + printf ("SUCCESS.\n"); + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Makefile.am b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Makefile.am new file mode 100644 index 0000000..4b0b9db --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/Makefile.am @@ -0,0 +1,234 @@ +AM_CPPFLAGS = -I$(top_srcdir)/include + +EXTRA_DIST = run-ia64-test-dyn1 run-ptrace-mapper run-ptrace-misc \ + run-check-namespace run-coredump-unwind \ + run-coredump-unwind-mdi check-namespace.sh.in \ + Gtest-nomalloc.c + +MAINTAINERCLEANFILES = Makefile.in + +noinst_PROGRAMS_arch = +noinst_PROGRAMS_cdep = +noinst_PROGRAMS_common = +check_PROGRAMS_arch = +check_PROGRAMS_cdep = +check_PROGRAMS_common = test-proc-info test-static-link \ + test-strerror +check_SCRIPTS_arch = +check_SCRIPTS_cdep = +check_SCRIPTS_common = run-check-namespace + +if REMOTE_ONLY + +perf: + +else + LIBUNWIND_local = $(top_builddir)/src/libunwind.la +if ARCH_IA64 + noinst_PROGRAMS_arch += ia64-test-dyn1 + check_SCRIPTS_arch += run-ia64-test-dyn1 + check_PROGRAMS_arch += Gia64-test-stack Lia64-test-stack \ + Gia64-test-nat Lia64-test-nat \ + Gia64-test-rbs Lia64-test-rbs \ + Gia64-test-readonly Lia64-test-readonly \ + ia64-test-setjmp ia64-test-sig +else #!ARCH_IA64 +if ARCH_PPC64 +if USE_ALTIVEC + noinst_PROGRAMS_arch += ppc64-test-altivec +endif #USE_ALTIVEC +endif #ARCH_PPC64 +endif #!ARCH_IA64 + check_PROGRAMS_cdep += Gtest-bt Ltest-bt Gtest-exc Ltest-exc \ + Gtest-init Ltest-init \ + Gtest-concurrent Ltest-concurrent \ + Gtest-resume-sig Ltest-resume-sig \ + Gtest-resume-sig-rt Ltest-resume-sig-rt \ + Gtest-trace Ltest-trace \ + Ltest-init-local-signal \ + Ltest-mem-validate \ + test-async-sig test-flush-cache test-init-remote \ + test-mem test-reg-state Ltest-varargs \ + Ltest-nomalloc Ltest-nocalloc Lrs-race + noinst_PROGRAMS_cdep += forker Gperf-simple Lperf-simple \ + Gperf-trace Lperf-trace + +if BUILD_PTRACE + check_SCRIPTS_cdep += run-ptrace-mapper run-ptrace-misc + check_PROGRAMS_cdep += test-ptrace + noinst_PROGRAMS_cdep += mapper test-ptrace-misc +endif + +if BUILD_SETJMP + check_PROGRAMS_cdep += test-setjmp +endif + +if SUPPORT_CXX_EXCEPTIONS + check_PROGRAMS_cdep += Ltest-cxx-exceptions +endif + +if OS_LINUX +if BUILD_COREDUMP + check_SCRIPTS_cdep += run-coredump-unwind + noinst_PROGRAMS_cdep += crasher test-coredump-unwind + +if HAVE_LZMA + check_SCRIPTS_cdep += run-coredump-unwind-mdi +endif # HAVE_LZMA +endif # BUILD_COREDUMP +endif # OS_LINUX + +perf: perf-startup Gperf-simple Lperf-simple Lperf-trace + @echo "########## Basic performance of generic libunwind:" + @./Gperf-simple + @echo "########## Basic performance of local-only libunwind:" + @./Lperf-simple + @echo "########## Performance of fast unwind:" + @./Lperf-trace + @echo "########## Startup overhead:" + @$(srcdir)/perf-startup @arch@ + +endif + +check_PROGRAMS = $(check_PROGRAMS_common) $(check_PROGRAMS_cdep) \ + $(check_PROGRAMS_arch) +check_SCRIPTS = $(check_SCRIPTS_common) $(check_SCRIPTS_cdep) \ + $(check_SCRIPTS_arch) + + +TESTS = $(check_PROGRAMS) $(check_SCRIPTS) +XFAIL_TESTS = + +if ARCH_IA64 + check_PROGRAMS_cdep += Gtest-dyn1 Ltest-dyn1 +endif + +# Use if arch defines but does not support PTRACE_SINGLESTEP +# ptrace request used in the tests. +XFAIL_TESTS_PTRACE_SINGLESTEP = run-ptrace-mapper run-ptrace-misc + +if ARCH_MIPS +XFAIL_TESTS += $(XFAIL_TESTS_PTRACE_SINGLESTEP) +endif + +if ARCH_ARM +# ARM Linux kernel >=2.6.39 removed PTRACE_SINGLESTEP emulation +XFAIL_TESTS += $(XFAIL_TESTS_PTRACE_SINGLESTEP) +endif + +# This is meant for multilib binaries, -m32. +# ptrace gives EBADREG when testing, +# but generally everything else works. +if NO_PTRACE_TEST + XFAIL_TESTS += run-ptrace-mapper test-ptrace Ltest-init-local-signal +endif + +noinst_PROGRAMS = $(noinst_PROGRAMS_common) $(noinst_PROGRAMS_cdep) \ + $(noinst_PROGRAMS_arch) + +Lia64_test_readonly_SOURCES = Lia64-test-readonly.c ia64-test-readonly-asm.S +Gia64_test_readonly_SOURCES = Gia64-test-readonly.c ia64-test-readonly-asm.S +Lia64_test_stack_SOURCES = Lia64-test-stack.c ia64-test-stack-asm.S \ + ia64-test-stack.h +Gia64_test_stack_SOURCES = Gia64-test-stack.c ia64-test-stack-asm.S \ + ia64-test-stack.h +Lia64_test_rbs_SOURCES = Lia64-test-rbs.c ia64-test-rbs-asm.S ia64-test-rbs.h +Gia64_test_rbs_SOURCES = Gia64-test-rbs.c ia64-test-rbs-asm.S ia64-test-rbs.h +Lia64_test_nat_SOURCES = Lia64-test-nat.c ia64-test-nat-asm.S +Gia64_test_nat_SOURCES = Gia64-test-nat.c ia64-test-nat-asm.S +ia64_test_dyn1_SOURCES = ia64-test-dyn1.c ia64-dyn-asm.S flush-cache.S \ + flush-cache.h +ppc64_test_altivec_SOURCES = ppc64-test-altivec.c ppc64-test-altivec-utils.c +Gtest_init_SOURCES = Gtest-init.cxx +Ltest_init_SOURCES = Ltest-init.cxx +Ltest_cxx_exceptions_SOURCES = Ltest-cxx-exceptions.cxx + +Ltest_init_local_signal_SOURCES = Ltest-init-local-signal.c Ltest-init-local-signal-lib.c + +Gtest_dyn1_SOURCES = Gtest-dyn1.c flush-cache.S flush-cache.h +Ltest_dyn1_SOURCES = Ltest-dyn1.c flush-cache.S flush-cache.h +test_static_link_SOURCES = test-static-link-loc.c test-static-link-gen.c +test_static_link_LDFLAGS = -static +forker_LDFLAGS = -static +Gtest_bt_SOURCES = Gtest-bt.c ident.c +Ltest_bt_SOURCES = Ltest-bt.c ident.c +test_ptrace_misc_SOURCES = test-ptrace-misc.c ident.c +Ltest_nomalloc_SOURCES = Ltest-nomalloc.c +Ltest_nocalloc_SOURCES = Ltest-nocalloc.c +Gtest_trace_SOURCES = Gtest-trace.c ident.c +Ltest_trace_SOURCES = Ltest-trace.c ident.c +Ltest_mem_validate_SOURCES = Ltest-mem-validate.c + +LIBUNWIND = $(top_builddir)/src/libunwind-$(arch).la +LIBUNWIND_ptrace = $(top_builddir)/src/libunwind-ptrace.la +LIBUNWIND_coredump = $(top_builddir)/src/libunwind-coredump.la + +if USE_ELF32 +LIBUNWIND_ELF = $(top_builddir)/src/libunwind-elf32.la +endif +if USE_ELF64 +LIBUNWIND_ELF = $(top_builddir)/src/libunwind-elf64.la +endif +if USE_ELFXX +LIBUNWIND_ELF = $(top_builddir)/src/libunwind-elfxx.la +endif + +LIBUNWIND_setjmp = $(top_builddir)/src/libunwind-setjmp.la \ + $(LIBUNWIND_ELF) $(LIBUNWIND) + +test_async_sig_LDADD = $(LIBUNWIND_local) -lpthread +test_flush_cache_LDADD = $(LIBUNWIND_local) +test_init_remote_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) +test_mem_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) +test_reg_state_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) +test_ptrace_LDADD = $(LIBUNWIND_ptrace) $(LIBUNWIND) +test_proc_info_LDADD = $(LIBUNWIND) +test_static_link_LDADD = $(LIBUNWIND) +test_strerror_LDADD = $(LIBUNWIND) +Lrs_race_LDADD = $(LIBUNWIND_local) -lpthread +Ltest_varargs_LDADD = $(LIBUNWIND_local) +Ltest_init_local_signal_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) + +Gtest_bt_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) +Gtest_concurrent_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) -lpthread +Gtest_dyn1_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) +Gtest_exc_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) +Gtest_init_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) @BACKTRACELIB@ +Gtest_resume_sig_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) +Gtest_resume_sig_rt_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) +Gperf_simple_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) +Gtest_trace_LDADD=$(LIBUNWIND) $(LIBUNWIND_local) +Gperf_trace_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) + +Ltest_bt_LDADD = $(LIBUNWIND_local) +Ltest_concurrent_LDADD = $(LIBUNWIND_local) -lpthread +Ltest_dyn1_LDADD = $(LIBUNWIND_local) +Ltest_exc_LDADD = $(LIBUNWIND_local) +Ltest_init_LDADD = $(LIBUNWIND_local) +Ltest_nomalloc_LDADD = $(LIBUNWIND_local) @DLLIB@ +Ltest_nocalloc_LDADD = $(LIBUNWIND_local) @DLLIB@ -lpthread +Ltest_resume_sig_LDADD = $(LIBUNWIND_local) +Ltest_resume_sig_rt_LDADD = $(LIBUNWIND_local) +Lperf_simple_LDADD = $(LIBUNWIND_local) +Ltest_trace_LDADD = $(LIBUNWIND_local) +Lperf_trace_LDADD = $(LIBUNWIND_local) +Ltest_mem_validate_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) + +test_setjmp_LDADD = $(LIBUNWIND_setjmp) +ia64_test_setjmp_LDADD = $(LIBUNWIND_setjmp) + +if BUILD_COREDUMP +test_coredump_unwind_LDADD = $(LIBUNWIND_coredump) $(LIBUNWIND) @BACKTRACELIB@ +endif + +Gia64_test_nat_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) +Gia64_test_stack_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) +Gia64_test_rbs_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) +Gia64_test_readonly_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) +Lia64_test_nat_LDADD = $(LIBUNWIND_local) +Lia64_test_stack_LDADD = $(LIBUNWIND_local) +Lia64_test_rbs_LDADD = $(LIBUNWIND_local) +Lia64_test_readonly_LDADD = $(LIBUNWIND_local) +ia64_test_dyn1_LDADD = $(LIBUNWIND) +ia64_test_sig_LDADD = $(LIBUNWIND) +ppc64_test_altivec_LDADD = $(LIBUNWIND) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/check-namespace.sh.in b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/check-namespace.sh.in new file mode 100644 index 0000000..6d00817 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/check-namespace.sh.in @@ -0,0 +1,367 @@ +#!/bin/sh +verbose=false +if [ "$1" = "-v" ]; then + verbose=true + shift +fi + +build_plat=@build_arch@ +plat=@arch@ +os=@target_os@ +num_errors=0 + +LIBUNWIND=../src/.libs/libunwind.so +LIBUNWIND_GENERIC=../src/.libs/libunwind-${plat}.so + +fetch_symtab () { + filename=$1 + + if [ ! -r $filename ]; then + return + fi + + if $verbose; then + echo "Checking $filename..." + fi + + # + # Unfortunately, "nm --defined" is a GNU-extension. For portability, + # build the list of defined symbols by hand. + # + symtab=`nm -g $filename` + saved_IFS="$IFS" + IFS="" + undef=`nm -g -u $filename` + for line in $undef; do + symtab=`echo "$symtab" | grep -v "^${line}"\$` + done; + IFS="$saved_IFS" +} + +ignore () { + sym=$1 + symtab=`echo "$symtab" | grep -v " ${sym}\$"` +} + +match () { + sym=$1 + if `echo "$symtab" | grep -q " ${sym}\$"`; then + symtab=`echo "$symtab" | grep -v " ${sym}\$"` + else + echo " ERROR: Symbol \"$sym\" missing." + num_errors=`expr $num_errors + 1` + fi +} + +# +# Filter out miscellaneous symbols that get defined by the +# linker for each shared object. +# +filter_misc () { + ignore _DYNAMIC + ignore _GLOBAL_OFFSET_TABLE_ + ignore __bss_start + ignore _edata + ignore _end + ignore _Uelf32_get_proc_name + ignore _Uelf32_valid_object + ignore _Uelf64_get_proc_name + ignore _Uelf64_valid_object + ignore _U.*debug_level + ignore ICRT.INTERNAL # ICC 8.x defines this + + # Ignore symbols generated by the ARM Linux default linker script. + # For details see the binutils sources (src/ld/emulparams/armelf_linux.sh). + if [ ${plat} = "arm" ]; then + ignore __bss_start__ + ignore __bss_end__ + ignore __end__ + ignore _bss_end__ + fi + + if [ ${plat} = "mips" ]; then + ignore _fbss + ignore _fdata + ignore _ftext + ignore _gp + fi +} + +check_local_unw_abi () { + match _UL${plat}_apply_reg_state + match _UL${plat}_reg_states_iterate + match _UL${plat}_create_addr_space + match _UL${plat}_destroy_addr_space + match _UL${plat}_get_fpreg + match _UL${plat}_get_proc_info + match _UL${plat}_get_proc_info_by_ip + match _UL${plat}_get_proc_name + match _UL${plat}_get_reg + match _UL${plat}_get_save_loc + match _UL${plat}_init_local + match _UL${plat}_init_local2 + match _UL${plat}_init_remote + match _UL${plat}_is_signal_frame + match _UL${plat}_local_addr_space + match _UL${plat}_resume + match _UL${plat}_set_caching_policy + match _UL${plat}_set_cache_size + match _UL${plat}_set_reg + match _UL${plat}_set_fpreg + match _UL${plat}_step + + match _U${plat}_flush_cache + match _U${plat}_get_accessors + match _U${plat}_getcontext + match _U${plat}_regname + match _U${plat}_strerror + + match _U_dyn_cancel + match _U_dyn_info_list_addr + match _U_dyn_register + + match unw_backtrace + match backtrace + + case ${plat} in + arm) + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path + match _U${plat}_is_fpreg + match _UL${plat}_search_unwind_table + match _UL${plat}_dwarf_search_unwind_table + match _UL${plat}_dwarf_find_unwind_table + ;; + hppa) + match _UL${plat}_dwarf_search_unwind_table + match _UL${plat}_dwarf_find_unwind_table + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path + match _U${plat}_setcontext + ;; + ia64) + match _UL${plat}_search_unwind_table + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path + ;; + x86) + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path + match _U${plat}_is_fpreg + match _UL${plat}_dwarf_search_unwind_table + match _UL${plat}_dwarf_find_unwind_table + ;; + x86_64) + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path + match _U${plat}_is_fpreg + match _UL${plat}_dwarf_search_unwind_table + match _UL${plat}_dwarf_find_unwind_table + match _U${plat}_setcontext + ;; + ppc*) + match _U${plat}_get_func_addr + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path + match _U${plat}_is_fpreg + match _UL${plat}_dwarf_search_unwind_table + match _UL${plat}_dwarf_find_unwind_table + ;; + tilegx) + match _U${plat}_is_fpreg + match _UL${plat}_dwarf_search_unwind_table + match _UL${plat}_dwarf_find_unwind_table + match _UL${plat}_local_addr_space_init + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path + match ${plat}_lock + ;; + + *) + match _U${plat}_is_fpreg + match _UL${plat}_dwarf_search_unwind_table + match _UL${plat}_dwarf_find_unwind_table + ;; + esac + + if [ x@enable_debug_frame@ = xyes ]; then + match _UL${plat}_dwarf_find_debug_frame + fi + +} + +check_generic_unw_abi () { + match _U${plat}_apply_reg_state + match _U${plat}_reg_states_iterate + match _U${plat}_create_addr_space + match _U${plat}_destroy_addr_space + match _U${plat}_flush_cache + match _U${plat}_get_accessors + match _U${plat}_get_fpreg + match _U${plat}_get_proc_info + match _U${plat}_get_proc_info_by_ip + match _U${plat}_get_proc_name + match _U${plat}_get_reg + match _U${plat}_get_save_loc + match _U${plat}_init_local + match _U${plat}_init_local2 + match _U${plat}_init_remote + match _U${plat}_is_signal_frame + match _U${plat}_local_addr_space + match _U${plat}_regname + match _U${plat}_resume + match _U${plat}_set_caching_policy + match _U${plat}_set_cache_size + match _U${plat}_set_fpreg + match _U${plat}_set_reg + match _U${plat}_step + match _U${plat}_strerror + + case ${plat} in + arm) + match _U${plat}_is_fpreg + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path + match _U${plat}_search_unwind_table + match _U${plat}_dwarf_search_unwind_table + match _U${plat}_dwarf_find_unwind_table + ;; + hppa) + match _U${plat}_dwarf_search_unwind_table + match _U${plat}_dwarf_find_unwind_table + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path + ;; + ia64) + match _U${plat}_search_unwind_table + match _U${plat}_find_dyn_list + if [ $plat = $build_plat ]; then + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path + case $os in + linux*) + match _U${plat}_get_kernel_table + ;; + esac + fi + ;; + x86) + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path + match _U${plat}_is_fpreg + match _U${plat}_dwarf_search_unwind_table + match _U${plat}_dwarf_find_unwind_table + ;; + x86_64) + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path + match _U${plat}_is_fpreg + match _U${plat}_dwarf_search_unwind_table + match _U${plat}_dwarf_find_unwind_table + ;; + ppc*) + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path + match _U${plat}_get_func_addr + match _U${plat}_is_fpreg + match _U${plat}_dwarf_search_unwind_table + match _U${plat}_dwarf_find_unwind_table + ;; + tilegx) + match _U${plat}_dwarf_search_unwind_table + match _U${plat}_dwarf_find_unwind_table + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path + match _U${plat}_is_fpreg + match _U${plat}_local_addr_space_init + match ${plat}_lock + ;; + *) + match _U${plat}_is_fpreg + match _U${plat}_dwarf_search_unwind_table + match _U${plat}_dwarf_find_unwind_table + ;; + esac + + if [ x@enable_debug_frame@ = xyes ]; then + match _U${plat}_dwarf_find_debug_frame + fi +} + +check_cxx_abi () { + match _Unwind_Backtrace + match _Unwind_DeleteException + match _Unwind_FindEnclosingFunction + match _Unwind_ForcedUnwind + match _Unwind_GetBSP + match _Unwind_GetCFA + match _Unwind_GetDataRelBase + match _Unwind_GetGR + match _Unwind_GetIP + match _Unwind_GetIPInfo + match _Unwind_GetLanguageSpecificData + match _Unwind_GetRegionStart + match _Unwind_GetTextRelBase + match _Unwind_RaiseException + match _Unwind_Resume + match _Unwind_Resume_or_Rethrow + match _Unwind_SetGR + match _Unwind_SetIP + match __libunwind_Unwind_Backtrace + match __libunwind_Unwind_DeleteException + match __libunwind_Unwind_FindEnclosingFunction + match __libunwind_Unwind_ForcedUnwind + match __libunwind_Unwind_GetBSP + match __libunwind_Unwind_GetCFA + match __libunwind_Unwind_GetDataRelBase + match __libunwind_Unwind_GetGR + match __libunwind_Unwind_GetIP + match __libunwind_Unwind_GetIPInfo + match __libunwind_Unwind_GetLanguageSpecificData + match __libunwind_Unwind_GetRegionStart + match __libunwind_Unwind_GetTextRelBase + match __libunwind_Unwind_RaiseException + match __libunwind_Unwind_Resume + match __libunwind_Unwind_Resume_or_Rethrow + match __libunwind_Unwind_SetGR + match __libunwind_Unwind_SetIP + case $os in + linux*) + # needed only for Intel 8.0 bug-compatibility + match _ReadSLEB + match _ReadULEB + ;; + esac +} + +check_empty () { + if [ -n "$symtab" ]; then + printf " ERROR: Extraneous symbols:\n$symtab\n" + num_errors=`expr $num_errors + 1` + fi +} + +if [ $plat = $build_plat ]; then + fetch_symtab $LIBUNWIND + filter_misc + check_local_unw_abi + if [ x@enable_cxx_exceptions@ = xyes ]; then + check_cxx_abi + fi + check_empty +fi + +fetch_symtab $LIBUNWIND_GENERIC +filter_misc +check_generic_unw_abi +check_empty + +if [ $num_errors -gt 0 ]; then + echo "FAILURE: Detected $num_errors errors" + exit 1 +fi + +if $verbose; then + echo " SUCCESS: all checks passed" +fi +exit 0 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/crasher.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/crasher.c new file mode 100644 index 0000000..24c7805 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/crasher.c @@ -0,0 +1,124 @@ +/* This program should crash and produce coredump */ + +#include "compiler.h" + +#include +#include +#include +#include +#ifdef __FreeBSD__ +#include +#include +#include +#endif + +#if defined(__linux__) +void write_maps(char *fname) +{ + char buf[512], path[128]; + char exec; + uintmax_t addr; + FILE *maps = fopen("/proc/self/maps", "r"); + FILE *out = fopen(fname, "w"); + + if (!maps || !out) + exit(EXIT_FAILURE); + + while (fgets(buf, sizeof(buf), maps)) + { + if (sscanf(buf, "%jx-%*x %*c%*c%c%*c %*x %*s %*d /%126[^\n]", &addr, &exec, path+1) != 3) + continue; + + if (exec != 'x') + continue; + + path[0] = '/'; + fprintf(out, "0x%jx:%s ", addr, path); + } + fprintf(out, "\n"); + + fclose(out); + fclose(maps); +} +#elif defined(__FreeBSD__) +void +write_maps(char *fname) +{ + FILE *out; + char *buf, *bp, *eb; + struct kinfo_vmentry *kv; + int mib[4], error; + size_t len; + + out = fopen(fname, "w"); + if (out == NULL) + exit(EXIT_FAILURE); + + len = 0; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_VMMAP; + mib[3] = getpid(); + error = sysctl(mib, 4, NULL, &len, NULL, 0); + if (error == -1) + exit(EXIT_FAILURE); + len = len * 4 / 3; + buf = malloc(len); + if (buf == NULL) + exit(EXIT_FAILURE); + error = sysctl(mib, 4, buf, &len, NULL, 0); + if (error == -1) + exit(EXIT_FAILURE); + + for (bp = buf, eb = buf + len; bp < eb; bp += kv->kve_structsize) { + kv = (struct kinfo_vmentry *)(uintptr_t)bp; + if (kv->kve_type == KVME_TYPE_VNODE && + (kv->kve_protection & KVME_PROT_EXEC) != 0) { + fprintf(out, "0x%jx:%s ", kv->kve_start, kv->kve_path); + } + } + + fprintf(out, "\n"); + fclose(out); + free(buf); +} +#else +#error Port me +#endif + +#ifdef __GNUC__ +int c(int x) NOINLINE ALIAS(b); +#define compiler_barrier() asm volatile(""); +#else +int c(int x); +#define compiler_barrier() +#endif + +int NOINLINE a(void) +{ + *(volatile int *)32 = 1; + return 1; +} + +int NOINLINE b(int x) +{ + int r; + + compiler_barrier(); + + if (x) + r = a(); + else + r = c(1); + return r + 1; +} + +int +main (int argc, char **argv) +{ + if (argc > 1) + write_maps(argv[1]); + b(0); + return 0; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/flush-cache.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/flush-cache.S new file mode 100644 index 0000000..3ee4726 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/flush-cache.S @@ -0,0 +1,104 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef HAVE__BUILTIN___CLEAR_CACHE + +#if defined(__ia64__) + + .global flush_cache + + .proc flush_cache +flush_cache: + .prologue + alloc r2=ar.pfs,2,0,0,0 + add r8=31,in1 // round up to 32 byte-boundary + ;; + shr.u r8=r8,5 // we flush 32 bytes per iteration + ;; + add r8=-1,r8 + .save ar.lc, r3 + mov r3=ar.lc // save ar.lc + ;; + .body + + mov ar.lc=r8 + ;; +.loop: fc in0 // issuable on M0 only + add in0=32,in0 + br.cloop.sptk.few .loop + ;; + sync.i + ;; + srlz.i + ;; + mov ar.lc=r3 // restore ar.lc + br.ret.sptk.many rp + .endp flush_cache + +#elif defined(__i386__) || defined (__x86_64__) + + .globl flush_cache +flush_cache: + ret + +#elif defined(__hppa__) + +# warning FIX ME!! + + .globl flush_cache +flush_cache: + .proc + .callinfo + bv %r0(%rp) + .procend +#elif defined(__powerpc64__) +# warning IMPLEMENT ME FOR PPC64!! + .globl flush_cache +flush_cache: + lwz 11, 0(1) ; + lwz 0, 4(11) ; + mtlr 0 ; + lwz 31, -4(11) ; + mr 1, 11 ; + blr +#elif defined(__powerpc__) +# warning IMPLEMENT ME FOR PPC32!! + .globl flush_cache +flush_cache: + lwz 11, 0(1) ; + lwz 0, 4(11) ; + mtlr 0 ; + lwz 31, -4(11) ; + mr 1, 11 ; + blr +#elif defined(__arm__) + .text + .globl flush_cache +flush_cache: + bx lr +#elif defined(__tilegx__) + .text + .globl flush_cache +flush_cache: + + andi r0, r0, -64 +1: { + flush r0 ; + addi r0, r0, 64 + } + { + bgtz r1, 1b ; + addi r1, r1, -64 + } + jrp lr +#else +# error Need flush_cache code for this architecture. +#endif + +#if defined ( __linux__) && !defined (__arm__) + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/flush-cache.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/flush-cache.h new file mode 100644 index 0000000..8227d85 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/flush-cache.h @@ -0,0 +1,38 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2012 Tommi Rantala + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef FLUSH_CACHE_H +#define FLUSH_CACHE_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE__BUILTIN___CLEAR_CACHE +#define flush_cache(ADDR, LEN) \ + __builtin___clear_cache((ADDR), (ADDR) + (LEN)) +#else +#include +extern void flush_cache (void *addr, size_t len); +#endif + +#endif /* FLUSH_CACHE_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/forker.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/forker.c new file mode 100644 index 0000000..b03f86a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/forker.c @@ -0,0 +1,76 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include + +#include +#include +#include + +int +main (int argc, char **argv, char **envp) +{ + char *program, **child_argv; + struct timeval start, stop; + double secs; + int status, i; + long count; + pid_t pid; + + count = atol (argv[1]); + program = argv[2]; + + child_argv = alloca ((argc - 1) * sizeof (char *)); + for (i = 0; i < argc - 2; ++i) + child_argv[i] = argv[2 + i]; + child_argv[i] = NULL; + + gettimeofday (&start, NULL); + for (i = 0; i < count; ++i) + { + pid = fork (); + if (pid == 0) + { + execve (program, child_argv, envp); + _exit (-1); + } + else + { + waitpid (pid, &status, 0); + if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) + { + fprintf (stderr, "%s: child failed\n", argv[0]); + exit (-1); + } + } + } + gettimeofday (&stop, NULL); + + secs = ((stop.tv_sec + 1e-6 * stop.tv_usec) + - (start.tv_sec + 1e-6 * start.tv_usec)); + printf ("%lu nsec/execution\n", + (unsigned long) (1e9 * secs / (double) count)); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-dyn-asm.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-dyn-asm.S new file mode 100644 index 0000000..79582e9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-dyn-asm.S @@ -0,0 +1,102 @@ + .globl func_add1, func_add1_end + .proc func_add1 +func_add1: +{.mib; add r8 = 1, r32 + nop.i 0 + br.ret.sptk.many rp +} +func_add1_end: + .endp func_add1 + + .globl func_add3, func_add3_end + .proc func_add3 +func_add3: +{.mmi; alloc loc0 = ar.pfs, 2, 1, 2, 0 + mov r2 = sp + add sp = -16, sp +} ;; +{.mii; ld8 r8 = [in1], 8 // load the function pointer + mov r3 = rp + mov rp = loc0 // trash rp +} ;; +{.mmi; ld8 r9 = [r8], 8 // load the entry-point + st8 [r2] = r3 + mov out0 = in0 +} ;; +{.mii; ld8 gp = [r8] // load the gp + mov b6 = r9 + mov out1 = in1 +} +{.mib; nop 0 + nop 0 + br.call.sptk rp = b6 +} +{.mmi; add r2 = 16, sp + ;; + ld8 r3 = [r2] // r3 = saved rp + mov ar.pfs = loc0 +} ;; +{.mii; nop 0 + mov rp = r3 + adds sp = 16, sp +} ;; +{.mib; st8 [sp] = in0 // trash rp save location + add r8 = 2, r8 + br.ret.sptk.many rp +} +func_add3_end: + .endp func_add3 + + .globl func_vframe, func_vframe_end + .proc func_vframe +func_vframe: +{.mii; alloc r16 = ar.pfs, 1, 2, 0, 0 // 0 + mov loc0 = rp + mov loc1 = sp +} ;; +{.mmi; sub sp = sp, in0 + st8 [loc1] = r16 + mov r2 = -99 // 0 +} ;; +{.mii; nop 0 + mov rp = r2 + mov ar.pfs = r0 +} +{.mib; mov r16 = r2 + tbit.nz p6, p0 = in0, 4 +(p6) br.cond.sptk.many .exit +} ;; +{.mmi; ld8 r16 = [loc1] + ;; + mov r3 = loc0 // 8 move saved rp to r3 + mov ar.pfs = r16 +} ;; +{.mmi; mov sp = loc1 // 10 + st8 [loc1] = r0 // trash saved pfs + mov loc0 = r2 +} ;; +{.mib; mov r8 = 10 + mov rp = r3 + br.ret.sptk.many rp +} +.exit: +{.mmi; ld8 r16 = [loc1] + ;; + sub sp = 32, sp + mov ar.pfs = r16 +} ;; +{.mmi; mov sp = loc1 + st8 [loc1] = r0 // trash saved pfs + mov rp = loc0 +} +{.mib; nop 0 + mov r8 = 4 + br.ret.sptk.many rp +} +func_vframe_end: + .endp func_vframe + +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-dyn1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-dyn1.c new file mode 100644 index 0000000..90127dd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-dyn1.c @@ -0,0 +1,223 @@ +#include "flush-cache.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +int verbose; + +#ifdef __ia64__ +# define GET_ENTRY(fdesc) (((uintptr_t *) (fdesc))[0]) +# define GET_GP(fdesc) (((uintptr_t *) (fdesc))[0]) +# define EXTRA 16 +#else +# define GET_ENTRY(fdesc) ((uintptr_t ) (fdesc)) +# define GET_GP(fdesc) (0) +# define EXTRA 0 +#endif + +int +make_executable (void *addr, size_t len) +{ + if (mprotect ((void *) (((long) addr) & -getpagesize ()), len, + PROT_READ | PROT_WRITE | PROT_EXEC) < 0) + { + perror ("mprotect"); + return -1; + } + flush_cache (addr, len); + return 0; +} + +void * +create_func (unw_dyn_info_t *di, const char *name, long (*func) (), + void *end, unw_dyn_region_info_t *region) +{ + void *mem, *memend, *addr, *fptr; + unw_word_t gp = 0; + size_t len; + + len = (uintptr_t) end - GET_ENTRY (func) + EXTRA; + mem = malloc (len); + if (verbose) + printf ("%s: cloning %s at %p (%zu bytes)\n", + __FUNCTION__, name, mem, len); + memend = (char *) mem + len; + +#ifdef __ia64__ + addr = (void *) GET_ENTRY (func); + + /* build function descriptor: */ + ((long *) mem)[0] = (long) mem + 16; /* entry point */ + ((long *) mem)[1] = GET_GP (func); /* global-pointer */ + fptr = mem; + mem = (void *) ((long) mem + 16); +#else + fptr = mem; +#endif + + len = (char *) memend - (char *) mem; + memcpy (mem, addr, len); + + if (make_executable (mem, len) < 0) + return NULL; + + if (di) + { + memset (di, 0, sizeof (*di)); + di->start_ip = (unw_word_t) mem; + di->end_ip = (unw_word_t) memend; + di->gp = gp; + di->format = UNW_INFO_FORMAT_DYNAMIC; + di->u.pi.name_ptr = (unw_word_t) name; + di->u.pi.regions = region; + } + return fptr; +} + +int +main (int argc, char **argv) +{ + extern long func_add1 (long); + extern char func_add1_end[]; + extern long func_add3 (long, long (*[])()); + extern char func_add3_end[]; + extern long func_vframe (long); + extern char func_vframe_end[]; + unw_dyn_region_info_t *r_pro, *r_epi, *r, *rtmp; + unw_dyn_info_t di0, di1, di2, di3; + long (*add1) (long); + long (*add3_0) (long); + long (*add3_1) (long, void *[]); + long (*vframe) (long); + void *flist[2]; + long ret; + int i; + + signal (SIGUSR1, SIG_IGN); + signal (SIGUSR2, SIG_IGN); + + if (argc != 1) + verbose = 1; + + add1 = (long (*)(long)) + create_func (&di0, "func_add1", func_add1, func_add1_end, NULL); + + /* Describe the epilogue of func_add3: */ + i = 0; + r_epi = alloca (_U_dyn_region_info_size (5)); + r_epi->op_count = 5; + r_epi->next = NULL; + r_epi->insn_count = -9; + _U_dyn_op_pop_frames (&r_epi->op[i++], + _U_QP_TRUE, /* when=*/ 5, /* num_frames=*/ 1); + _U_dyn_op_stop (&r_epi->op[i++]); + assert ((unsigned) i <= r_epi->op_count); + + /* Describe the prologue of func_add3: */ + i = 0; + r_pro = alloca (_U_dyn_region_info_size (4)); + r_pro->op_count = 4; + r_pro->next = r_epi; + r_pro->insn_count = 8; + _U_dyn_op_save_reg (&r_pro->op[i++], _U_QP_TRUE, /* when=*/ 0, + /* reg=*/ UNW_IA64_AR_PFS, /* dst=*/ UNW_IA64_GR + 34); + _U_dyn_op_add (&r_pro->op[i++], _U_QP_TRUE, /* when=*/ 2, + /* reg= */ UNW_IA64_SP, /* val=*/ -16); + _U_dyn_op_save_reg (&r_pro->op[i++], _U_QP_TRUE, /* when=*/ 4, + /* reg=*/ UNW_IA64_RP, /* dst=*/ UNW_IA64_GR + 3); + _U_dyn_op_spill_sp_rel (&r_pro->op[i++], _U_QP_TRUE, /* when=*/ 7, + /* reg=*/ UNW_IA64_RP, /* off=*/ 16); + assert ((unsigned) i <= r_pro->op_count); + + /* Create regions for func_vframe: */ + i = 0; + r = alloca (_U_dyn_region_info_size (16)); + r->op_count = 16; + r->next = NULL; + r->insn_count = 4; + _U_dyn_op_label_state (&r->op[i++], /* label=*/ 100402); + _U_dyn_op_pop_frames (&r->op[i++], _U_QP_TRUE, /* when=*/ 3, /* frames=*/ 1); + _U_dyn_op_stop (&r->op[i++]); + assert ((unsigned) i <= r->op_count); + + i = 0; + rtmp = r; + r = alloca (_U_dyn_region_info_size (16)); + r->op_count = 16; + r->next = rtmp; + r->insn_count = 16; + _U_dyn_op_save_reg (&r->op[i++], _U_QP_TRUE, /* when=*/ 8, + /* reg=*/ UNW_IA64_RP, /* dst=*/ UNW_IA64_GR + 3); + _U_dyn_op_pop_frames (&r->op[i++], _U_QP_TRUE, /* when=*/ 10, + /* num_frames=*/ 1); + _U_dyn_op_stop (&r->op[i++]); + assert ((unsigned) i <= r->op_count); + + i = 0; + rtmp = r; + r = alloca (_U_dyn_region_info_size (16)); + r->op_count = 16; + r->next = rtmp; + r->insn_count = 5; + _U_dyn_op_save_reg (&r->op[i++], _U_QP_TRUE, /* when=*/ 1, + /* reg=*/ UNW_IA64_RP, /* dst=*/ UNW_IA64_GR + 33); + _U_dyn_op_save_reg (&r->op[i++], _U_QP_TRUE, /* when=*/ 2, + /* reg=*/ UNW_IA64_SP, /* dst=*/ UNW_IA64_GR + 34); + _U_dyn_op_spill_fp_rel (&r->op[i++], _U_QP_TRUE, /* when=*/ 4, + /* reg=*/ UNW_IA64_AR_PFS, /* off=*/ 16); + _U_dyn_op_label_state (&r->op[i++], /* label=*/ 100402); + _U_dyn_op_stop (&r->op[i++]); + assert ((unsigned) i <= r->op_count); + + /* Create two functions which can share the region-list: */ + add3_0 = (long (*) (long)) + create_func (&di1, "func_add3/0", func_add3, func_add3_end, r_pro); + add3_1 = (long (*) (long, void *[])) + create_func (&di2, "func_add3/1", func_add3, func_add3_end, r_pro); + vframe = (long (*) (long)) + create_func (&di3, "func_vframe", func_vframe, func_vframe_end, r); + + _U_dyn_register (&di1); + _U_dyn_register (&di2); + _U_dyn_register (&di3); + _U_dyn_register (&di0); + + flist[0] = add3_0; + flist[1] = add1; + + kill (getpid (), SIGUSR1); /* do something ptmon can latch onto */ + ret = (*add3_1) (13, flist); + if (ret != 18) + { + fprintf (stderr, "FAILURE: (*add3_1)(13) returned %ld\n", ret); + exit (-1); + } + + ret = (*vframe) (48); + if (ret != 4) + { + fprintf (stderr, "FAILURE: (*vframe)(16) returned %ld\n", ret); + exit (-1); + } + ret = (*vframe) (64); + if (ret != 10) + { + fprintf (stderr, "FAILURE: (*vframe)(32) returned %ld\n", ret); + exit (-1); + } + kill (getpid (), SIGUSR2); /* do something ptmon can latch onto */ + + _U_dyn_cancel (&di0); + _U_dyn_cancel (&di1); + _U_dyn_cancel (&di3); + _U_dyn_cancel (&di2); + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-nat-asm.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-nat-asm.S new file mode 100644 index 0000000..eea5ac2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-nat-asm.S @@ -0,0 +1,508 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + .text + +#define CALL_NEXT_PTR(gp_save_reg, arg0, arg1) \ + ld8 r2 = [arg0], 8;; /* read the next function pointer */ \ + ld8 r3 = [r2], 8;; /* read the function's entry-point */ \ + ld8 r2 = [r2];; /* read the function's gp */ \ + mov b6 = r3; \ + mov gp_save_reg = gp; \ + mov out0 = arg0; \ + mov out1 = arg1; \ + mov gp = r2; \ + br.call.sptk.many rp = b6;; \ + mov gp = gp_save_reg + +#define CALL_NEXT(gp_save_reg) CALL_NEXT_PTR(gp_save_reg, in0, in1) + +#define LOAD_VAL(reg) \ + ld8 reg = [in1], 8;; \ + tbit.nz p15, p0 = reg, 0;; \ +(p15) ld8.s reg = [r0] + + + .global flushrs + .proc flushrs +flushrs: + flushrs;; + br.ret.sptk.many rp + .endp flushrs + + /* Save r4-r7 into stacked registers, load them up with the + values passed via the pointer in in1 and then call the + function passed via the pointer in in0. */ + + .global save_static_to_stacked + .proc save_static_to_stacked +save_static_to_stacked: + .prologue + .regstk 2, 7, 2, 0 + .save ar.pfs, loc0 + alloc loc0 = ar.pfs, 2, 7, 2, 0 + .save rp, loc1 + mov loc1 = rp + .spillreg r4, loc2 + mov loc2 = r4 + .spillreg r5, loc3 + mov loc3 = r5 + .spillreg r6, loc4 + mov loc4 = r6 + .spillreg r7, loc5 + mov loc5 = r7 + .body + LOAD_VAL(r4) + LOAD_VAL(r5) + LOAD_VAL(r6) + LOAD_VAL(r7) + CALL_NEXT(loc6) + + mov r4 = loc2 + mov r5 = loc3 + mov r6 = loc4 + mov r7 = loc5 + + mov ar.pfs = loc0 + mov rp = loc1 + br.ret.sptk.many rp + .endp save_static_to_stacked + + /* Save f2 to the memory stack, save r4 to f2, then load + r4 with the value passed via in1 and call the function + passed via in0. */ + + .global save_static_to_fr + .proc save_static_to_fr +save_static_to_fr: + .prologue + .regstk 2, 3, 2, 0 + .save ar.pfs, loc0 + alloc loc0 = ar.pfs, 2, 3, 2, 0 + .save rp, loc1 + mov loc1 = rp + .fframe 16 + .spillpsp f2, 0 + stf.spill [sp] = f2, -16 + .spillreg r4, f2 + setf.sig f2 = r4 + + .body + + ld8 r4 = [in1], 8;; + tbit.nz p6, p0 = r4, 0;; +(p6) ld8.s r4 = [r0] + + CALL_NEXT(loc2) + + getf.sig r4 = f2 // restore r4 + .restore sp + add sp = 16, sp;; + ldf.fill f2 = [sp] // restore r2 + + mov ar.pfs = loc0 + mov rp = loc1 + br.ret.sptk.many rp + .endp save_static_to_fr + + /* If r4 is not a NaT, save b3 to a stacked register and + then save r4 in b3. The non-NaTness of r4 is saved in + p1. */ + + .global save_static_to_br + .proc save_static_to_br +save_static_to_br: + .prologue + .regstk 2, 6, 2, 0 + .save ar.pfs, loc0 + alloc loc0 = ar.pfs, 2, 6, 2, 0 + .save rp, loc1 + mov loc1 = rp + + .save pr, loc2 + mov loc2 = pr // save predicates + + .spillreg b3, loc3 + mov loc3 = b3 + + tnat.z p1, p2 = r4;; + .spillreg.p p1, r4, b3 +(p1) mov b3 = r4 + .spillreg.p p2, r4, loc4 +(p2) mov loc4 = r4 + + .body + + LOAD_VAL(r4) + CALL_NEXT(loc5) + + .pred.rel.mutex p1, p2 +(p1) mov r4 = b3 // restore r4 +(p2) mov r4 = loc4 + + mov ar.pfs = loc0 + mov rp = loc1 + mov pr = loc2, -1 + mov b3 = loc3 // restore b3 + br.ret.sptk.many rp + .endp save_static_to_br + + /* Spill r4 into memory and then save r5 in r4. */ + + .global save_static_to_mem + .proc save_static_to_mem +save_static_to_mem: + .prologue + .regstk 2, 4, 2, 0 + .save ar.pfs, loc0 + alloc loc0 = ar.pfs, 2, 4, 2, 0 + .save rp, loc1 + mov loc1 = rp + .save ar.unat, loc2 + mov loc2 = ar.unat + + .fframe 16 + .spillpsp r4, 0 + st8.spill [sp] = r4, -16 + + .spillreg r5, r4 + mov r4 = r5 + + .body + + LOAD_VAL(r5) + CALL_NEXT(loc3) + + mov r5 = r4 // restore r5 + .restore sp + add sp = 16, sp;; + ld8.fill r4 = [sp] // restore r4 + + mov ar.pfs = loc0 + mov rp = loc1 + mov ar.unat = loc2 // restore ar.unat + br.ret.sptk.many rp + .endp save_static_to_mem + + /* Spill r6 into memory and save primary ar.unat in a register. */ + + .global save_static_to_mem2 + .proc save_static_to_mem2 +save_static_to_mem2: + .prologue + .regstk 2, 5, 2, 0 + .save ar.pfs, loc0 + alloc loc0 = ar.pfs, 2, 5, 2, 0 + .save rp, loc1 + mov loc1 = rp + .save ar.unat, loc2 + mov loc2 = ar.unat + + .fframe 16 + .spillpsp r6, 0 + st8.spill [sp] = r6, -16;; + .save @priunat, loc3 + mov loc3 = ar.unat + mov ar.unat = 0 // trash ar.unat + + .body + + LOAD_VAL(r6) + CALL_NEXT(loc4) + + mov ar.unat = loc3 // restore primary UNaT + .restore sp + add sp = 16, sp;; + ld8.fill r6 = [sp] // restore r6 + + mov ar.pfs = loc0 + mov rp = loc1 + mov ar.unat = loc2 // restore ar.unat + br.ret.sptk.many rp + .endp save_static_to_mem2 + + /* Spill r6 into memory and save primary ar.unat in memory. */ + + .global save_static_to_mem3 + .proc save_static_to_mem3 +save_static_to_mem3: + .prologue + .regstk 2, 5, 2, 0 + .save ar.pfs, loc0 + alloc loc0 = ar.pfs, 2, 5, 2, 0 + .save rp, loc1 + mov loc1 = rp + .save ar.unat, loc2 + mov loc2 = ar.unat + + add r2 = 8, sp + .fframe 16 + .spillpsp r6, 0 + st8.spill [sp] = r6, -16;; + mov r3 = ar.unat;; + .savepsp @priunat, -8 + st8 [r2] = r3 + mov ar.unat = 0 // trash ar.unat + + .body + + LOAD_VAL(r6) + CALL_NEXT(loc4) + + add r2 = 24, sp;; + ld8 r3 = [r2];; + mov ar.unat = r3 // restore primary UNaT + .restore sp + add sp = 16, sp;; + ld8.fill r6 = [sp] // restore r6 + + mov ar.pfs = loc0 + mov rp = loc1 + mov ar.unat = loc2 // restore ar.unat + br.ret.sptk.many rp + .endp save_static_to_mem3 + + /* Spill r6 into memory and save primary ar.unat in register, + then in memory. */ + + .global save_static_to_mem4 + .proc save_static_to_mem4 +save_static_to_mem4: + .prologue + .regstk 2, 5, 2, 0 + .save ar.pfs, loc0 + alloc loc0 = ar.pfs, 2, 5, 2, 0 + .save rp, loc1 + mov loc1 = rp + .save ar.unat, loc2 + mov loc2 = ar.unat + + add r2 = 8, sp + .fframe 16 + .spillpsp r6, 0 + st8.spill [sp] = r6, -16;; + .save @priunat, r3 + mov r3 = ar.unat;; + mov ar.unat = 0 // trash ar.unat + .savepsp @priunat, -8 + st8 [r2] = r3 + mov r3 = r0 // trash register pri UNaT location + .body + + LOAD_VAL(r6) + CALL_NEXT(loc4) + + add r2 = 24, sp;; + ld8 r3 = [r2];; + mov ar.unat = r3 // restore primary UNaT + .restore sp + add sp = 16, sp;; + ld8.fill r6 = [sp] // restore r6 + + mov ar.pfs = loc0 + mov rp = loc1 + mov ar.unat = loc2 // restore ar.unat + br.ret.sptk.many rp + .endp save_static_to_mem4 + + /* Spill r6 into memory and save primary ar.unat in register, + then in memory. */ + + .global save_static_to_mem5 + .proc save_static_to_mem5 +save_static_to_mem5: + .prologue + .regstk 2, 5, 2, 0 + .save ar.pfs, loc0 + alloc loc0 = ar.pfs, 2, 5, 2, 0 + .save rp, loc1 + mov loc1 = rp + .save ar.unat, loc2 + mov loc2 = ar.unat + + add r2 = 8, sp + .fframe 16 + .spillpsp r6, 0 + st8.spill [sp] = r6, -16;; + mov r3 = ar.unat;; + mov ar.unat = 0 // trash ar.unat + .savepsp @priunat, -8 + st8 [r2] = r3 + .save @priunat, loc3 + mov loc3 = r3 + st8 [r2] = r0 // trash memory pri UNaT location + .body + + LOAD_VAL(r6) + CALL_NEXT(loc4) + + add r2 = 24, sp;; + ld8 r3 = [r2];; + mov ar.unat = loc3 // restore primary UNaT + .restore sp + add sp = 16, sp;; + ld8.fill r6 = [sp] // restore r6 + + mov ar.pfs = loc0 + mov rp = loc1 + mov ar.unat = loc2 // restore ar.unat + br.ret.sptk.many rp + .endp save_static_to_mem5 + + /* Save r4-r7 to various scratch registers, then trigger + a segfault. */ + + .global save_static_to_scratch + .proc save_static_to_scratch +save_static_to_scratch: + .prologue + + .spillreg r4, r16 + mov r16 = r4 // save r4 in r16 + tnat.nz p6, p7 = r5;; + .spillreg.p p6, r5, f31 +(p6) setf.sig f31 = r5 // save r5 in f31 if it's a NaT + .spillreg.p p7, r5, b6 +(p7) mov b6 = r5 // in b6 if it not + .spillreg r6, f32 + setf.sig f32 = r6 // save r6 in f32 (fph partition) + .spillsp r7, 0 + st8.spill [sp] = r7 // save r7 in the scratch stack space + .spillreg f4, f6 + mov f6 = f4;; + .body + + ld8 r2 = [in1] + ;; + mov ar.ec = r2 + + LOAD_VAL(r4) + LOAD_VAL(r5) + LOAD_VAL(r6) + LOAD_VAL(r7) + setf.sig f4 = r4 + + /* Now force a SIGSEGV. Make sure the ld8 is at the beginning of a + bundle, so the signal-handler can skip over it simply by + incrementing the IP. */ + { + .mmi + ld8 r2 = [r0] + nop.m 0 + nop.i 0 ;; + } + + mov f4 = f6 + mov r4 = r16 + .pred.rel.mutex p6, p7 +(p6) getf.sig r5 = f31 +(p7) mov r5 = b6 + getf.sig r6 = f32 + ld8.fill r7 = [sp] + + br.ret.sptk.many rp + .endp save_static_to_scratch + + /* Rotate registers a bit in a vain attempt to sow some confusion. + Care must be taken not to write any rotating general register + after rotation, because we keep the preserved state + there... */ + + .global rotate_regs + .proc rotate_regs +rotate_regs: + .prologue + .regstk 2, 14, 2, 16 + .save ar.pfs, loc0 + alloc loc0 = ar.pfs, 2, 14, 2, 16 + .save rp, loc1 + mov loc1 = rp + .save pr, loc2 + mov loc2 = pr + .save ar.lc, loc3 + mov loc3 = ar.lc + .spillreg r4, loc4 + mov loc4 = r4 + + ld8 r2 = [in1], 8;; + mov pr = r2, -1 + + ld8 r2 = [in1], 8;; + mov r8 = in0 + mov r9 = in1 + and r2 = 127, r2;; + mov ar.ec = 0 + mov ar.lc = r2;; + + // use p6 to preserve p63 as it gets rotated into p16: +(p16) cmp.eq.unc p6,p0 = r0,r0;; +1: +(p6) cmp.eq.unc p16,p0 = r0,r0 +(p63) cmp.eq.unc p6,p0 = r0,r0 + br.ctop.dptk.few 1b;; + +(p6) cmp.eq.unc p63,p0 = r0,r0 + + CALL_NEXT_PTR(r4, r8, r9) + + clrrrb + + mov ar.pfs = loc0 + mov rp = loc1 + mov pr = loc2, -1 + mov ar.lc = loc3 + mov r4 = loc4 + br.ret.sptk.many rp + + .endp rotate_regs + + .global save_pr + .proc save_pr +save_pr: + .prologue + .regstk 2, 4, 2, 0 + .save ar.pfs, loc0 + alloc loc0 = ar.pfs, 2, 4, 2, 0 + .save rp, loc1 + mov loc1 = rp + .save pr, loc2 + mov loc2 = pr + + ld8 r2 = [in1], 8;; + mov pr = r2, -1 + + CALL_NEXT(loc3) + + mov ar.pfs = loc0 + mov rp = loc1 + mov pr = loc2, -1 + br.ret.sptk.many rp + + .endp save_pr + +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-rbs-asm.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-rbs-asm.S new file mode 100644 index 0000000..9a6d33f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-rbs-asm.S @@ -0,0 +1,275 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "ia64-test-rbs.h" + + .common stackmem, NSTACKS*STACK_SIZE, 16 + + .text + +#define SAVED_SP_OFF 0 +#define SAVED_RP_OFF 8 +#define SAVED_PFS_OFF 16 +#define SAVED_RNAT_OFF 24 +#define SAVED_BSP_OFF 32 +#define SAVED_BSPSTORE_OFF 40 +#define FRAME_SIZE 48 + +#define SPILL(n) \ + /* int rbs_spill_#n(long iteration, int (*next_func[])()) */ \ + .globl rbs_spill_##n; \ + .proc rbs_spill_##n; \ +rbs_spill_##n: \ + .prologue; \ + alloc r18 = ar.pfs, 2, (n)-2, 2, 0;/* read ar.pfs */ \ + /* first, calculate address of new stack: */ \ + addl r2 = @ltoff(stackmem), gp; \ + add r8 = 1, in0; \ + ;; \ + ld8 r2 = [r2]; /* r2 = &stackmem */ \ + shl r3 = in0, STACK_SIZE_SHIFT; \ + shladd r8 = r8, 3, in1; /* r8 = &next_func[iteration+1] */ \ + ;; \ + ld8 r8 = [r8]; /* r8 = next_func[iteration+1] */ \ + add r2 = r2, r3; /* r2 = stackmem[iteration] */ \ + ;; \ + ld8 r9 = [r8], 8;; /* r9 = target's entry-point */ \ + ld8 gp = [r8]; /* r22 = target's gp */ \ + addl r3 = STACK_SIZE-FRAME_SIZE, r2; /* r3 = &stackframe */ \ + ;; \ + mov b6 = r9; \ + st8 [r3] = sp; \ + .vframesp SAVED_SP_OFF+16; \ + adds sp = -16, r3; /* switch the memory stack */ \ + ;; \ + adds r3 = (SAVED_RP_OFF - SAVED_SP_OFF), r3; \ + mov r16 = rp; \ + ;; \ + .savesp rp, SAVED_RP_OFF+16; \ + st8 [r3] = r16, (SAVED_PFS_OFF - SAVED_RP_OFF); \ + ;; \ + .savesp ar.pfs, SAVED_PFS_OFF+16; \ + st8 [r3] = r18, (SAVED_BSP_OFF - SAVED_PFS_OFF); \ + mov r16 = ar.bsp; \ + mov r17 = ar.bspstore; \ + mov r18 = ar.rnat; \ + ;; \ + .savesp ar.bsp, SAVED_BSP_OFF+16; \ + st8 [r3] = r16, (SAVED_BSPSTORE_OFF - SAVED_BSP_OFF); \ + ;; \ + .savesp ar.bspstore, SAVED_BSPSTORE_OFF+16; \ + st8 [r3] = r17, (SAVED_RNAT_OFF - SAVED_BSPSTORE_OFF); \ + mov out1 = in1; \ + ;; \ + .savesp ar.rnat, SAVED_RNAT_OFF+16; \ + st8 [r3] = r18; \ + .body; \ + mov ar.bspstore = r2; /* switch the backing store */ \ + adds out0 = 1, in0; \ + ;; \ + br.call.sptk.many rp = b6; \ +1: /* switch back to stack: */ \ + adds r3 = SAVED_SP_OFF+16, sp; \ + cmp.ge p8, p0 = r8, r0; \ + ;; \ +(p8) add r8 = 1, r8; \ + ld8 r16 = [r3], (SAVED_RP_OFF-SAVED_SP_OFF);; /* saved sp */ \ + ld8 r17 = [r3], (SAVED_PFS_OFF-SAVED_RP_OFF);; /* saved rp */ \ + ld8 r18 = [r3], (SAVED_RNAT_OFF-SAVED_PFS_OFF);;/* saved pfs */ \ + ld8 r19 = [r3], (SAVED_BSP_OFF-SAVED_RNAT_OFF);;/* saved rnat */ \ + ld8 r20 = [r3], (SAVED_BSPSTORE_OFF-SAVED_BSP_OFF);;/* saved bsp */ \ + ld8 r21 = [r3];; /* saved bspstore */ \ + mov rp = r17; \ + mov ar.pfs = r18; \ + shl r3 = in0, STACK_SIZE_SHIFT; \ + addl r2 = @ltoff(stackmem), gp;; \ + ld8 r2 = [r2];; /* r2 = &stackmem */ \ + add r2 = r2, r3; /* r2 = stackmem[iteration] */ \ + mov r3 = ar.bsp;; \ + sub r2 = r3, r2;; /* r2 = dirty_size */ \ + shl r2 = r2, 16;; \ + mov ar.rsc = r2;; \ + alloc r3 = ar.pfs, 0, 0, 0, 0;; \ + loadrs;; \ + mov ar.bspstore = r21;; /* this also restores ar.bsp */ \ + mov ar.rnat = r19; \ + .restore sp; \ + mov sp = r16; \ + br.ret.sptk.many rp; \ + .endp rbs_spill_##n + + SPILL(2); SPILL(3) + SPILL(4); SPILL(5); SPILL(6); SPILL(7) + SPILL(8); SPILL(9); SPILL(10); SPILL(11) + SPILL(12); SPILL(13); SPILL(14); SPILL(15) + SPILL(16); SPILL(17); SPILL(18); SPILL(19) + SPILL(20); SPILL(21); SPILL(22); SPILL(23) + SPILL(24); SPILL(25); SPILL(26); SPILL(27) + SPILL(28); SPILL(29); SPILL(30); SPILL(31) + SPILL(32); SPILL(33); SPILL(34); SPILL(35) + SPILL(36); SPILL(37); SPILL(38); SPILL(39) + SPILL(40); SPILL(41); SPILL(42); SPILL(43) + SPILL(44); SPILL(45); SPILL(46); SPILL(47) + SPILL(48); SPILL(49); SPILL(50); SPILL(51) + SPILL(52); SPILL(53); SPILL(54); SPILL(55) + SPILL(56); SPILL(57); SPILL(58); SPILL(59) + SPILL(60); SPILL(61); SPILL(62); SPILL(63) + SPILL(64); SPILL(65); SPILL(66); SPILL(67) + SPILL(68); SPILL(69); SPILL(70); SPILL(71) + SPILL(72); SPILL(73); SPILL(74); SPILL(75) + SPILL(76); SPILL(77); SPILL(78); SPILL(79) + SPILL(80); SPILL(81); SPILL(82); SPILL(83) + SPILL(84); SPILL(85); SPILL(86); SPILL(87) + SPILL(88); SPILL(89); SPILL(90); SPILL(91) + SPILL(92); SPILL(93); SPILL(94) + +#define LD_LOC(n) \ + ld4 loc##n = [in1], 4;; \ + cmp.eq p8, p9 = r0, loc##n;; \ +(p9) or loc##n = loc##n, r8; \ +(p8) ld4.s loc##n = [r0] + +#define CK_LOC(n) \ + ld4 r16 = [in1], 4;; \ + cmp.eq p8, p9 = r0, r16; \ + or r16 = r16, r9;; \ +(p8) tnat.z p10, p0 = loc##n; \ +(p9) cmp.ne p10, p0 = r16, loc##n; \ + ;; \ +(p10) mov r8 = -n; \ +(p10) br.cond.spnt.many .fail + + /* int loadup(long iteration, int *values, next_func[]) */ + + .global loadup + .proc loadup +loadup: + .prologue + .save ar.pfs, r36 + alloc loc1 = ar.pfs, 3, 90, 3, 0 + .save rp, loc0 + mov loc0 = rp + .body + cmp.eq p6, p7 = 1, in0 + ;; + mov ar.rsc = 0 // put RSE into enforced lazy mode +(p6) mov out1 = in2 +(p7) mov out2 = in2 + +(p6) ld8 r17 = [in2] // get address of function descriptor +(p7) add out0 = -1, in0 +(p7) mov out1 = in1 + + ;; +(p6) ld8 r16 = [r17], 8 // load entry point + shl r8 = in0, 32 // store iteration # in top 32 bits + mov r18 = in1 + ;; +(p6) ld8 r1 = [r17] // load gp +(p6) mov b6 = r16 + +(p6) mov out0 = 0 + ;; + LD_LOC( 2); LD_LOC( 3) + LD_LOC( 4); LD_LOC( 5); LD_LOC( 6); LD_LOC( 7) + LD_LOC( 8); LD_LOC( 9); LD_LOC(10); LD_LOC(11) + LD_LOC(12); LD_LOC(13); LD_LOC(14); LD_LOC(15) + LD_LOC(16); LD_LOC(17); LD_LOC(18); LD_LOC(19) + LD_LOC(20); LD_LOC(21); LD_LOC(22); LD_LOC(23) + LD_LOC(24); LD_LOC(25); LD_LOC(26); LD_LOC(27) + LD_LOC(28); LD_LOC(29); LD_LOC(30); LD_LOC(31) + LD_LOC(32); LD_LOC(33); LD_LOC(34); LD_LOC(35) + LD_LOC(36); LD_LOC(37); LD_LOC(38); LD_LOC(39) + LD_LOC(40); LD_LOC(41); LD_LOC(42); LD_LOC(43) + LD_LOC(44); LD_LOC(45); LD_LOC(46); LD_LOC(47) + LD_LOC(48); LD_LOC(49); LD_LOC(50); LD_LOC(51) + LD_LOC(52); LD_LOC(53); LD_LOC(54); LD_LOC(55) + LD_LOC(56); LD_LOC(57); LD_LOC(58); LD_LOC(59) + LD_LOC(60); LD_LOC(61); LD_LOC(62); LD_LOC(63) + LD_LOC(64); LD_LOC(65); LD_LOC(66); LD_LOC(67) + LD_LOC(68); LD_LOC(69); LD_LOC(70); LD_LOC(71) + LD_LOC(72); LD_LOC(73); LD_LOC(74); LD_LOC(75) + LD_LOC(76); LD_LOC(77); LD_LOC(78); LD_LOC(79) + LD_LOC(80); LD_LOC(81); LD_LOC(82); LD_LOC(83) + LD_LOC(84); LD_LOC(85); LD_LOC(86); LD_LOC(87) + LD_LOC(88); LD_LOC(89) + ;; +{ .mbb + mov in1 = r18 +(p6) br.call.sptk.many rp = b6 +(p7) br.call.sptk.many rp = loadup +} + cmp.lt p8, p9 = r8, r0 + shl r9 = in0, 32 // store iteration # in top 32 bits +(p8) br.cond.spnt.few .fail + ;; + add r8 = 1, r8 + CK_LOC( 2); CK_LOC( 3) + CK_LOC( 4); CK_LOC( 5); CK_LOC( 6); CK_LOC( 7) + CK_LOC( 8); CK_LOC( 9); CK_LOC(10); CK_LOC(11) + CK_LOC(12); CK_LOC(13); CK_LOC(14); CK_LOC(15) + CK_LOC(16); CK_LOC(17); CK_LOC(18); CK_LOC(19) + CK_LOC(20); CK_LOC(21); CK_LOC(22); CK_LOC(23) + CK_LOC(24); CK_LOC(25); CK_LOC(26); CK_LOC(27) + CK_LOC(28); CK_LOC(29); CK_LOC(30); CK_LOC(31) + CK_LOC(32); CK_LOC(33); CK_LOC(34); CK_LOC(35) + CK_LOC(36); CK_LOC(37); CK_LOC(38); CK_LOC(39) + CK_LOC(40); CK_LOC(41); CK_LOC(42); CK_LOC(43) + CK_LOC(44); CK_LOC(45); CK_LOC(46); CK_LOC(47) + CK_LOC(48); CK_LOC(49); CK_LOC(50); CK_LOC(51) + CK_LOC(52); CK_LOC(53); CK_LOC(54); CK_LOC(55) + CK_LOC(56); CK_LOC(57); CK_LOC(58); CK_LOC(59) + CK_LOC(60); CK_LOC(61); CK_LOC(62); CK_LOC(63) + CK_LOC(64); CK_LOC(65); CK_LOC(66); CK_LOC(67) + CK_LOC(68); CK_LOC(69); CK_LOC(70); CK_LOC(71) + CK_LOC(72); CK_LOC(73); CK_LOC(74); CK_LOC(75) + CK_LOC(76); CK_LOC(77); CK_LOC(78); CK_LOC(79) + CK_LOC(80); CK_LOC(81); CK_LOC(82); CK_LOC(83) + CK_LOC(84); CK_LOC(85); CK_LOC(86); CK_LOC(87) + CK_LOC(88); CK_LOC(89) +.fail: + mov rp = loc0 + mov ar.pfs = loc1 + br.ret.sptk.many rp + .endp loadup + + .global resumption_point_label + .proc resumption_point +resumption_point: +resumption_point_label: + .prologue + .save rp, r16 + .save ar.pfs, r0 + .body + mov r8 = r15 + mov b6 = r16 + ;; + br.cond.sptk.many b6 + .endp resumption_point + +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-rbs.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-rbs.h new file mode 100644 index 0000000..3315ad6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-rbs.h @@ -0,0 +1,3 @@ +#define NSTACKS 128 +#define STACK_SIZE_SHIFT 17 +#define STACK_SIZE (1 << STACK_SIZE_SHIFT) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-readonly-asm.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-readonly-asm.S new file mode 100644 index 0000000..acd3ada --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-readonly-asm.S @@ -0,0 +1,55 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + .text + + .global test_func + .proc test_func +test_func: + .prologue + .regstk 1, 3, 0, 0 + .save ar.pfs, loc0 + alloc loc0 = ar.pfs, 1, 3, 0, 0 + mov loc1 = rp + .save rp, r0 + .save ar.lc, r0 + .body + mov loc2 = gp + ld8 r2 = [in0], 8;; + ld8 r1 = [in0];; + mov b6 = r2 + br.call.sptk.many rp = b6 + + mov gp = loc2 + mov rp = loc1 + mov ar.pfs = loc0 + br.ret.sptk.many rp + + .endp test_func + +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-setjmp.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-setjmp.c new file mode 100644 index 0000000..50eaa01 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-setjmp.c @@ -0,0 +1,155 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Test to verify that we can siglongjmp() into a frame whose register + window is not backed by valid memory. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef HAVE_IA64INTRIN_H +# include +#endif + +static sigjmp_buf env; +static int return_level; +static uintptr_t return_bsp; +static int verbose; + +uintptr_t +get_bsp (void) +{ +#ifdef __INTEL_COMPILER + return __getReg (_IA64_REG_AR_BSP); +#else + return (uintptr_t) __builtin_ia64_bsp (); +#endif +} + +static void +sighandler (int signal, void *siginfo, void *sigcontext) +{ + ucontext_t *uc = sigcontext; + int local = 0; + + if (verbose) + printf ("got signal, stack at %p, saved bsp=0x%lx\n", + &local, uc->uc_mcontext.sc_ar_bsp); + siglongjmp (env, 1); +} + +/* Direct call of doit () at the end of doit () would get optimized by GCC to + a branch. */ +static void doit (int n); +typedef void (*doit_type) (int); +static volatile doit_type doit_pointer = doit; + +static void +doit (int n) +{ + uintptr_t guard_page_addr, bsp = get_bsp (); + void *ret; + + if (n == 0) + { + size_t page_size = getpagesize (); + + guard_page_addr = (bsp + page_size - 1) & -page_size; + if (verbose) + printf ("guard_page_addr = 0x%lx\n", (unsigned long) guard_page_addr); + ret = mmap ((void *) guard_page_addr, page_size, PROT_NONE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (ret != (void *) guard_page_addr) + { + if (ret == MAP_FAILED) + perror ("mmap"); + else + fprintf (stderr, "mmap() returned %p, expected 0x%lx\n", + ret, guard_page_addr); + exit (EXIT_FAILURE); + } + } + + if (sigsetjmp (env, 1)) + { + return_level = n; + return_bsp = bsp; + } + else + (*doit_pointer) (n + 1); +} + +int +main (int argc, char **argv) +{ + struct sigaction sa; + stack_t ss; + + if (argc > 1) + verbose = 1; + + ss.ss_sp = malloc (2 * SIGSTKSZ); + if (ss.ss_sp == NULL) + { + puts ("failed to allocate alternate stack"); + return EXIT_FAILURE; + } + ss.ss_flags = 0; + ss.ss_size = 2 * SIGSTKSZ; + if (sigaltstack (&ss, NULL) < 0) + { + printf ("sigaltstack failed: %s\n", strerror (errno)); + return EXIT_FAILURE; + } + + sa.sa_handler = (void (*) (int)) sighandler; + sigemptyset (&sa.sa_mask); + sa.sa_flags = SA_SIGINFO | SA_ONSTACK; + if (sigaction (SIGSEGV, &sa, NULL) < 0) + { + printf ("sigaction failed: %s\n", strerror (errno)); + exit (1); + } + + doit (0); + + if (verbose) + { + printf ("sigsetjmp returned at level %d bsp=0x%lx\n", + return_level, return_bsp); + puts ("Test succeeded!"); + } + return EXIT_SUCCESS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-sig.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-sig.c new file mode 100644 index 0000000..473efe9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-sig.c @@ -0,0 +1,102 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* This test uses the unwind interface to modify the IP in an ancestor + frame while still returning to the parent frame. */ + +#include +#include +#include + +#include + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +int verbose; + +static void +sighandler (int signal) +{ + unw_cursor_t cursor, cursor2; + unw_word_t ip; + unw_context_t uc; + + if (verbose) + printf ("caught signal %d\n", signal); + + unw_getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + panic ("unw_init() failed!\n"); + + /* get cursor for caller of sighandler: */ + if (unw_step (&cursor) < 0) + panic ("unw_step() failed!\n"); + + cursor2 = cursor; + while (!unw_is_signal_frame (&cursor2)) + if (unw_step (&cursor2) < 0) + panic ("failed to find signal frame!\n"); + + if (unw_step (&cursor2) < 0) + panic ("unw_step() failed!\n"); + + if (unw_get_reg (&cursor2, UNW_REG_IP, &ip) < 0) + panic ("failed to get IP!\n"); + + /* skip faulting instruction (doesn't handle MLX template) */ + ++ip; + if ((ip & 0x3) == 0x3) + ip += 13; + + if (unw_set_reg (&cursor2, UNW_REG_IP, ip) < 0) + panic ("failed to set IP!\n"); + + unw_resume (&cursor); /* update context & return to caller of sighandler() */ + + panic ("unexpected return from unw_resume()!\n"); +} + +static void +doit (volatile char *p) +{ + int ch; + + ch = *p; /* trigger SIGSEGV */ + + if (verbose) + printf ("doit: finishing execution!\n"); +} + +int +main (int argc, char **argv) +{ + if (argc > 1) + verbose = 1; + + signal (SIGSEGV, sighandler); + doit (0); + if (verbose) + printf ("SUCCESS\n"); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-stack-asm.S b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-stack-asm.S new file mode 100644 index 0000000..0aea33a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-stack-asm.S @@ -0,0 +1,183 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "ia64-test-stack.h" + + .common stackmem, NSTACKS*STACK_SIZE, 16 + + .global do_unwind_tests + + .text + +#define SAVED_SP_OFF 0 +#define SAVED_RP_OFF 8 +#define SAVED_PFS_OFF 16 +#define SAVED_RNAT_OFF 24 +#define SAVED_BSP_OFF 32 +#define SAVED_BSPSTORE_OFF 40 +#define FRAME_SIZE 48 + + .proc stack_it +stack_it: + .prologue + alloc r18 = ar.pfs, 0, 0, 0, 0 // read ar.pfs + // first, calculate address of new stack: + addl r2 = @ltoff(stackmem), gp + shl r3 = r8, STACK_SIZE_SHIFT + ;; + ld8 r2 = [r2] // r2 = &stackmem + ;; + add r2 = r2, r3 // r2 = stackmem[iteration] + ;; + addl r3 = STACK_SIZE-FRAME_SIZE, r2 // r3 = &stackframe + ;; + st8 [r3] = sp + .vframesp SAVED_SP_OFF+16 + adds sp = -16, r3 // switch the memory stack + ;; + adds r3 = (SAVED_RP_OFF - SAVED_SP_OFF), r3 + mov r16 = rp + ;; + .savesp rp, SAVED_RP_OFF+16 + st8 [r3] = r16, (SAVED_PFS_OFF - SAVED_RP_OFF) + ;; + .savesp ar.pfs, SAVED_PFS_OFF+16 + st8 [r3] = r18, (SAVED_BSP_OFF - SAVED_PFS_OFF) + + mov r16 = ar.bsp + mov r17 = ar.bspstore + mov r18 = ar.rnat + ;; + .savesp ar.bsp, SAVED_BSP_OFF+16 + st8 [r3] = r16, (SAVED_BSPSTORE_OFF - SAVED_BSP_OFF) + ;; + .savesp ar.bspstore, SAVED_BSPSTORE_OFF+16 + st8 [r3] = r17, (SAVED_RNAT_OFF - SAVED_BSPSTORE_OFF) + ;; + .savesp ar.rnat, SAVED_RNAT_OFF+16 + st8 [r3] = r18 + ;; + mov ar.bspstore = r2 // switch the backing store + + .body + + // for even iterations, allocate a local variable: + tbit.nz p6, p0 = r8, 0 +(p6) br.cond.sptk.few .skip + ;; + alloc r2 = ar.pfs, 0, 1, 0, 0 + mov loc0 = r8 + ;; +.skip: cmp.ne p6, p7 = 0, r8 + ;; +{ .mbb +(p6) adds r8 = -1, r8 +(p6) br.call.sptk.many rp = stack_it // next iteration +(p7) br.call.sptk.many rp = do_unwind_tests // time for introspection... +} + // switch back to stack: + + adds r3 = SAVED_SP_OFF+16, sp + ;; + ld8 r16 = [r3], (SAVED_RP_OFF-SAVED_SP_OFF);; // saved sp + ld8 r17 = [r3], (SAVED_PFS_OFF-SAVED_RP_OFF);; // saved rp + ld8 r18 = [r3], (SAVED_RNAT_OFF-SAVED_PFS_OFF);; // saved pfs + ld8 r19 = [r3], (SAVED_BSP_OFF-SAVED_RNAT_OFF);; // saved rnat + ld8 r20 = [r3], (SAVED_BSPSTORE_OFF-SAVED_BSP_OFF);; // saved bsp + ld8 r21 = [r3];; // saved bspstore + + mov rp = r17 + mov ar.pfs = r18 + mov ar.bspstore = r21 // this also restores ar.bsp + ;; + mov ar.rnat = r19 + + .restore sp + mov sp = r16 + br.ret.sptk.many rp + .endp stack_it + + +#define SET_LOC(n) add loc##n = n, r8 +#define SET_NAT(n) ld8.s loc##n = [r0] + + .global touch_all + .proc touch_all +touch_all: + .prologue + .save ar.pfs, r34 + alloc loc1 = ar.pfs, 1, 94, 1, 0 + .save rp, loc0 + mov loc0 = rp + .body + + mov ar.rsc = 0 // put RSE into enforced lazy mode + shl r8 = in0, 32 // store iteration # in top 32 bits + add out0 = -1, in0 + cmp.eq p6, p7 = 1, in0 + ;; + SET_LOC( 2); SET_LOC( 3) + SET_LOC( 4); SET_LOC( 5); SET_LOC( 6); SET_LOC( 7) + SET_LOC( 8); SET_LOC( 9); SET_LOC(10); SET_LOC(11) + SET_LOC(12); SET_LOC(13); SET_LOC(14); SET_LOC(15) + SET_LOC(16); SET_LOC(17); SET_LOC(18); SET_LOC(19) + SET_LOC(20); SET_LOC(21); SET_LOC(22); SET_LOC(23) + SET_LOC(24); SET_LOC(25); SET_LOC(26); SET_LOC(27) + SET_LOC(28); SET_LOC(29); SET_LOC(30); SET_LOC(31) + SET_LOC(32); SET_LOC(33); SET_LOC(34); SET_LOC(35) + SET_LOC(36); SET_LOC(37); SET_LOC(38); SET_LOC(39) + SET_LOC(40); SET_LOC(41); SET_LOC(42); SET_LOC(43) + SET_LOC(44); SET_LOC(45); SET_LOC(46); SET_LOC(47) + SET_LOC(48); SET_LOC(49); SET_LOC(50); SET_LOC(51) + SET_LOC(52); SET_LOC(53); SET_LOC(54); SET_LOC(55) + SET_LOC(56); SET_LOC(57); SET_LOC(58); SET_LOC(59) + SET_LOC(60); SET_LOC(61); SET_LOC(62); SET_LOC(63) + SET_LOC(64); SET_LOC(65); SET_LOC(66); SET_LOC(67) + SET_LOC(68); SET_LOC(69); SET_LOC(70); SET_LOC(71) + SET_LOC(72); SET_LOC(73); SET_LOC(74); SET_LOC(75) + SET_LOC(76); SET_LOC(77); SET_LOC(78); SET_LOC(79) + SET_LOC(80); SET_LOC(81); SET_LOC(82); SET_LOC(83) + SET_LOC(84); SET_LOC(85); SET_LOC(86); SET_LOC(87) + SET_LOC(88); SET_LOC(89); SET_LOC(90); SET_LOC(91) + SET_LOC(92); SET_LOC(93) + ;; + SET_NAT(2); SET_NAT(31); SET_NAT(73); SET_NAT(93) + ;; +{ .mbb + mov r8=NSTACKS-1 +(p6) br.call.sptk.many rp = stack_it +(p7) br.call.sptk.many rp = touch_all +} + ;; + + mov rp = loc0 + mov ar.pfs = loc1 + br.ret.sptk.many rp + .endp touch_all + +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-stack.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-stack.h new file mode 100644 index 0000000..5665a79 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ia64-test-stack.h @@ -0,0 +1,3 @@ +#define NSTACKS 1024 +#define STACK_SIZE_SHIFT 17 +#define STACK_SIZE (1 << STACK_SIZE_SHIFT) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ident.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ident.c new file mode 100644 index 0000000..9024e29 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ident.c @@ -0,0 +1,5 @@ +long +f (long val) +{ + return val; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/mapper.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/mapper.c new file mode 100644 index 0000000..b47ae78 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/mapper.c @@ -0,0 +1,78 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* This program creates lots of mappings such that on Linux the + reading of /proc/PID/maps gets very slow. With proper caching, + test-ptrace should still run at acceptable speed once + /proc/PID/maps has been scanned. If the program dies with a + SIGALRM, it means it was running unexpectedly slow. */ + +#include +#include +#include +#include + +#include + +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +# define MAP_ANONYMOUS MAP_ANON +#endif +#if !defined(MAP_NORESERVE) +# define MAP_NORESERVE 0 +#endif + +int +main (void) +{ + long n = 0; + + signal (SIGUSR1, SIG_IGN); + signal (SIGUSR2, SIG_IGN); + + printf ("Starting mmap test...\n"); + for (n = 0; n < 30000; ++n) + { + if (mmap (NULL, 1, (n & 1) ? PROT_READ : PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS +#ifdef MAP_NORESERVE + | MAP_NORESERVE +#endif + , + -1, 0) == MAP_FAILED) + { + printf ("Failed after %ld successful maps\n", n - 1); + exit (0); + } + } + + alarm (80); /* die if we don't finish in 80 seconds */ + + printf ("Turning on single-stepping...\n"); + kill (getpid (), SIGUSR1); /* tell test-ptrace to start single-stepping */ + printf ("Va bene?\n"); + kill (getpid (), SIGUSR2); /* tell test-ptrace to stop single-stepping */ + printf ("Turned single-stepping off...\n"); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/perf-startup b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/perf-startup new file mode 100644 index 0000000..1c24e9a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/perf-startup @@ -0,0 +1,19 @@ +#!/bin/sh +platform=$1 +LIBUNWIND=../src/.libs/libunwind.so +LIBUNWIND_PLAT=../src/.libs/libunwind-$platform.so +warmup=$(./forker 2000 /bin/true | cut -f1 -d' ') + +nsec1=$(./forker 2000 /bin/true | cut -f1 -d' ') +printf "\"/bin/true\"\t\t\t\t\t\t: $nsec1 nsec/execution\n" + +nsec2=$(LD_PRELOAD=$LIBUNWIND ./forker 2000 /bin/true | cut -f1 -d' ') +printf "\"LD_PRELOAD=$LIBUNWIND /bin/true\"\t: $nsec2 nsec/execution\n" + +nsec3=$(LD_PRELOAD=$LIBUNWIND_PLAT ./forker 2000 /bin/true | cut -f1 -d' ') +printf "\"LD_PRELOAD=$LIBUNWIND_PLAT /bin/true\"\t: $nsec3 nsec/execution\n" + +echo + +printf "Overhead of preloading $LIBUNWIND\t: $(($nsec2 - $nsec1)) nsec\n" +printf "Overhead of preloading $LIBUNWIND_PLAT\t: $(($nsec3 - $nsec1)) nsec\n" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ppc64-test-altivec-utils.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ppc64-test-altivec-utils.c new file mode 100644 index 0000000..bd67ff7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ppc64-test-altivec-utils.c @@ -0,0 +1,32 @@ +#include +#include + +union si_overlay +{ + vector signed int v; + int ints[4]; +}; + +vector signed int +vec_init () +{ + vector signed int v; + static int count = 1; + + ((union si_overlay *) &v)->ints[0] = count++; + ((union si_overlay *) &v)->ints[1] = count++; + ((union si_overlay *) &v)->ints[2] = count++; + ((union si_overlay *) &v)->ints[3] = count++; + return v; +} + +void +vec_print (vector signed int v) +{ + printf ("%08x %08x %08x %08x", + ((union si_overlay *) &v)->ints[0], + ((union si_overlay *) &v)->ints[1], + ((union si_overlay *) &v)->ints[2], + ((union si_overlay *) &v)->ints[3]); +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ppc64-test-altivec.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ppc64-test-altivec.c new file mode 100644 index 0000000..a3e95ee --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/ppc64-test-altivec.c @@ -0,0 +1,177 @@ + + +#include +#include +#include +#include +#include +#include + +#include + +#define panic(args...) { fprintf (stderr, args); abort(); } + +extern vector signed int vec_init (); +extern void vec_print (vector signed int v); + +vector signed int vec_stack (int count); + +int +main () +{ + printf ("&vec_stack = %016lx\n", (unsigned long) vec_stack); + vec_stack (3); + return 0; +} + + +vector signed int +vec_stack (int count) +{ + register vector signed int v1; + register vector signed int v2; + register vector signed int v3; + register vector signed int v4; + register vector signed int v5; + register vector signed int v6; + register vector signed int v7; + register vector signed int v8; + register vector signed int v9; + + unw_fpreg_t vr; + + unw_cursor_t cursor; + unw_word_t ip, sp; + unw_context_t uc; + int ret; + int verbose = 1; + + /* if (count == 0) return vec_init(); */ + + if (count == 0) + { + unw_getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + { + panic ("unw_init_local failed!\n"); + } + else + { + do + { + if ((ret = unw_get_reg (&cursor, UNW_REG_IP, &ip)) < 0) + { + panic ("FAILURE: unw_get_reg returned %d for UNW_REG_IP\n", + ret); + } + if ((ret = unw_get_reg (&cursor, UNW_REG_SP, &sp)) < 0) + { + panic ("FAILURE: unw_get_reg returned %d for UNW_REG_SP\n", + ret); + } + if ((ret = unw_get_fpreg (&cursor, UNW_PPC64_V30, &vr)) < 0) + { + panic + ("FAILURE: unw_get_vreg returned %d for UNW_PPC64_V30\n", + ret); + } + + + if (verbose) + { + const char *regname = unw_regname (UNW_PPC64_V30); + char proc_name_buffer[256]; + unw_word_t offset; + unsigned int * vec_half1, * vec_half2; + vec_half1 = (unsigned int *)&vr; + vec_half2 = vec_half1 + 1; + printf ("ip = %016lx, sp=%016lx\n", (long) ip, (long) sp); + printf ("vr30 = %08x %08x %08x %08x\n", + (unsigned int) (*vec_half1 >> 16), + (unsigned int) (*vec_half1 & 0xffffffff), + (unsigned int) (*vec_half2 >> 16), + (unsigned int) (*vec_half2 & 0xffffffff)); + ret = + unw_get_proc_name (&cursor, proc_name_buffer, + sizeof (proc_name_buffer), &offset); + if (ret == 0) + { + printf ("proc name = %s, offset = %lx\n", + proc_name_buffer, offset); + } + else + { + panic ("unw_get_proc_name returned %d\n", ret); + } + printf ("unw_regname(UNW_PPC_V30) = %s\n\n", regname); + } + + ret = unw_step (&cursor); + if (ret < 0) + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + panic ("FAILURE: unw_step() returned %d for ip=%lx\n", ret, + (long) ip); + } + } + while (ret > 0); + } + } + + v1 = vec_init (); + v2 = vec_init (); + v3 = vec_init (); + v4 = vec_init (); + v5 = vec_init (); + v6 = vec_init (); + + /* make use of all of the registers in some calculation */ + v7 = + vec_nor (v1, vec_add (v2, vec_sub (v3, vec_and (v4, vec_or (v5, v6))))); + + /* + * "force" the registers to be non-volatile by making a call and also + * using the registers after the call. + */ + v8 = vec_stack (count - 1); + + /* + * Use the result from the previous call, plus all of the non-volatile + * registers in another calculation. + */ + v9 = + vec_nor (v1, + vec_add (v2, + vec_sub (v3, + vec_and (v4, vec_or (v5, vec_xor (v6, v8)))))); + + printf ("v1 - "); + vec_print (v1); + printf ("\n"); + printf ("v2 - "); + vec_print (v2); + printf ("\n"); + printf ("v3 - "); + vec_print (v3); + printf ("\n"); + printf ("v4 - "); + vec_print (v4); + printf ("\n"); + printf ("v5 - "); + vec_print (v5); + printf ("\n"); + printf ("v6 - "); + vec_print (v6); + printf ("\n"); + printf ("v7 - "); + vec_print (v7); + printf ("\n"); + printf ("v8 - "); + vec_print (v8); + printf ("\n"); + printf ("v9 - "); + vec_print (v9); + printf ("\n"); + + return v9; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-check-namespace b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-check-namespace new file mode 100644 index 0000000..d57c864 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-check-namespace @@ -0,0 +1,3 @@ +#!/bin/sh +chmod +x ./check-namespace.sh +./check-namespace.sh $* diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-coredump-unwind b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-coredump-unwind new file mode 100644 index 0000000..8d07742 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-coredump-unwind @@ -0,0 +1,53 @@ +#!/bin/sh + +# this function is slight modification of the one used in RPM +# found at https://bugzilla.redhat.com/show_bug.cgi?id=834073 +# written by Alexander Larsson +add_minidebug() +{ + debuginfo="$1" ## we don't have separate debuginfo file + binary="$1" + + dynsyms=`mktemp` + funcsyms=`mktemp` + keep_symbols=`mktemp` + mini_debuginfo=`mktemp` + + # Extract the dynamic symbols from the main binary, there is no need to also have these + # in the normal symbol table + nm -D "$binary" --format=posix --defined-only | awk '{ print $1 }' | sort > "$dynsyms" + # Extract all the text (i.e. function) symbols from the debuginfo + nm "$debuginfo" --format=posix --defined-only | awk '{ if ($2 == "T" || $2 == "t") print $1 }' | sort > "$funcsyms" + # Keep all the function symbols not already in the dynamic symbol table + comm -13 "$dynsyms" "$funcsyms" > "$keep_symbols" + # Copy the full debuginfo, keeping only a minumal set of symbols and removing some unnecessary sections + objcopy -S --remove-section .gdb_index --remove-section .comment --keep-symbols="$keep_symbols" "$debuginfo" "$mini_debuginfo" &> /dev/null + #Inject the compressed data into the .gnu_debugdata section of the original binary + xz "$mini_debuginfo" + mini_debuginfo="${mini_debuginfo}.xz" + objcopy --add-section .gnu_debugdata="$mini_debuginfo" "$binary" + rm -f "$dynsyms" "$funcsyms" "$keep_symbols" "$mini_debuginfo" + + strip "$binary" ## throw away the symbol table +} + + +TESTDIR=`pwd` +TEMPDIR=`mktemp --tmpdir -d libunwind-test-XXXXXXXXXX` +trap "rm -r -- $TEMPDIR" EXIT + +cp crasher $TEMPDIR/crasher +if [ "$1" = "-minidebuginfo" ]; then + add_minidebug $TEMPDIR/crasher +fi + +# create core dump +( + cd $TEMPDIR + ulimit -c 10000 + ./crasher backing_files +) 2>/dev/null +COREFILE=$TEMPDIR/core* + +# magic option -testcase enables checking for the specific contents of the stack +./test-coredump-unwind $COREFILE -testcase `cat $TEMPDIR/backing_files` diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-coredump-unwind-mdi b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-coredump-unwind-mdi new file mode 100644 index 0000000..d0a315b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-coredump-unwind-mdi @@ -0,0 +1,8 @@ +#!/bin/sh + +# This test intends to test the unw_get_proc_name function on binaries without +# the symbol table but with so called MiniDebuginfo available. In particular, +# it is tested using the coredump accessors. For more info about MiniDebugInfo +# see e.g. http://fedoraproject.org/wiki/Features/MiniDebugInfo + +${0%/*}/run-coredump-unwind -minidebuginfo diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-ia64-test-dyn1 b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-ia64-test-dyn1 new file mode 100644 index 0000000..acce944 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-ia64-test-dyn1 @@ -0,0 +1,2 @@ +#!/bin/sh +./test-ptrace -t ./ia64-test-dyn1 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-ptrace-mapper b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-ptrace-mapper new file mode 100644 index 0000000..dc3010d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-ptrace-mapper @@ -0,0 +1,2 @@ +#!/bin/sh +./test-ptrace -c -n -t ./mapper $* diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-ptrace-misc b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-ptrace-misc new file mode 100644 index 0000000..c3a6552 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/run-ptrace-misc @@ -0,0 +1,2 @@ +#!/bin/sh +./test-ptrace -c -t ./test-ptrace-misc diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-async-sig.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-async-sig.c new file mode 100644 index 0000000..2ce8b4b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-async-sig.c @@ -0,0 +1,193 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Check whether basic unwinding truly is async-signal safe. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "compiler.h" + +#include +#include +#include +#include +#include + +#include + +#define UNW_LOCAL_ONLY +#include + +static const int nerrors_max = 100; + +struct itimerval interval = + { + .it_interval = { .tv_sec = 0, .tv_usec = 0 }, + .it_value = { .tv_sec = 0, .tv_usec = 1000 } + }; + +int verbose; +int nerrors; +int sigcount; + +#ifndef CONFIG_BLOCK_SIGNALS +/* When libunwind is configured with --enable-block-signals=no, the caller + is responsible for preventing recursion via signal handlers. + We use a simple global here. In a multithreaded program, one would use + a thread-local variable. */ +int recurcount; +#endif + +#define panic(args...) \ + { ++nerrors; fprintf (stderr, args); return; } + +static void +do_backtrace (int may_print, int get_proc_name) +{ + char buf[512], name[256]; + unw_cursor_t cursor; + unw_word_t ip, sp, off; + unw_context_t uc; + int ret; + int depth = 0; + +#ifndef CONFIG_BLOCK_SIGNALS + if (recurcount > 0) + return; + recurcount += 1; +#endif + + unw_getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + panic ("unw_init_local failed!\n"); + + do + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + unw_get_reg (&cursor, UNW_REG_SP, &sp); + + buf[0] = '\0'; + if (get_proc_name || (may_print && verbose)) + { + ret = unw_get_proc_name (&cursor, name, sizeof (name), &off); + if (ret == 0 && (may_print && verbose)) + { + if (off) + snprintf (buf, sizeof (buf), "<%s+0x%lx>", name, (long) off); + else + { + size_t len = strlen (name); + buf[0] = '<'; + memcpy (buf + 1, name, len); + buf[len + 1] = '>'; + buf[len + 2] = '\0'; + } + } + } + + if (may_print && verbose) + printf ("%016lx %-32s (sp=%016lx)\n", (long) ip, buf, (long) sp); + + ret = unw_step (&cursor); + if (ret < 0) + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + panic ("FAILURE: unw_step() returned %d for ip=%lx\n", + ret, (long) ip); + } + if (depth++ > 100) + { + panic ("FAILURE: unw_step() looping over %d iterations\n", depth); + break; + } + } + while (ret > 0); + +#ifndef CONFIG_BLOCK_SIGNALS + recurcount -= 1; +#endif +} + +void +sighandler (int signal) +{ + if (verbose) + printf ("sighandler(signal=%d, count=%d)\n", signal, sigcount); + + do_backtrace (1, 1); + + ++sigcount; + + if (sigcount == 100) + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL); + else if (sigcount == 200) + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD); + else if (sigcount == 300 || nerrors > nerrors_max) + { + if (nerrors > nerrors_max) + panic ("Too many errors (%d)\n", nerrors); + if (nerrors) + { + fprintf (stderr, "FAILURE: detected %d errors\n", nerrors); + exit (-1); + } + if (verbose) + printf ("SUCCESS.\n"); + exit (0); + } + setitimer (ITIMER_VIRTUAL, &interval, NULL); +} + +int +main (int argc, char **argv UNUSED) +{ + struct sigaction act; + long i = 0; + + if (argc > 1) + verbose = 1; + + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE); + + memset (&act, 0, sizeof (act)); + act.sa_handler = sighandler; + act.sa_flags = SA_SIGINFO; + sigaction (SIGVTALRM, &act, NULL); + + setitimer (ITIMER_VIRTUAL, &interval, NULL); + + while (1) + { + if (0 && verbose) + printf ("%s: starting backtrace\n", __FUNCTION__); + do_backtrace (0, (i++ % 100) == 0); + if (nerrors > nerrors_max) + { + fprintf (stderr, "Too many errors (%d)\n", nerrors); + exit (-1); + } + } + return (0); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-coredump-unwind.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-coredump-unwind.c new file mode 100644 index 0000000..5349823 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-coredump-unwind.c @@ -0,0 +1,395 @@ +/* + * Example program for unwinding core dumps. + * + * Compile a-la: + * gcc -Os -Wall \ + * -Wl,--start-group \ + * -lunwind -lunwind-x86 -lunwind-coredump \ + * example-core-unwind.c \ + * -Wl,--end-group \ + * -oexample-core-unwind + * + * Run: + * eu-unstrip -n --core COREDUMP + * figure out which virtual addresses in COREDUMP correspond to which mapped executable files + * (binary and libraries), then supply them like this: + * ./example-core-unwind COREDUMP 0x400000:/bin/crashed_program 0x3458600000:/lib/libc.so.6 [...] + * + * Note: Program eu-unstrip is part of elfutils, virtual addresses of shared + * libraries can be determined by ldd (at least on linux). + */ + +#include "compiler.h" + +#undef _GNU_SOURCE +#define _GNU_SOURCE 1 +#undef __USE_GNU +#define __USE_GNU 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* For SIGSEGV handler code */ +#include +#include + +#include + + +/* Utility logging functions */ + +enum { + LOGMODE_NONE = 0, + LOGMODE_STDIO = (1 << 0), + LOGMODE_SYSLOG = (1 << 1), + LOGMODE_BOTH = LOGMODE_SYSLOG + LOGMODE_STDIO, +}; +const char *msg_prefix = ""; +const char *msg_eol = "\n"; +int logmode = LOGMODE_STDIO; +int xfunc_error_retval = EXIT_FAILURE; + +void xfunc_die(void) +{ + exit(xfunc_error_retval); +} + +static void verror_msg_helper(const char *s, + va_list p, + const char* strerr, + int flags) +{ + char *msg; + int prefix_len, strerr_len, msgeol_len, used; + + if (!logmode) + return; + + used = vasprintf(&msg, s, p); + if (used < 0) + return; + + /* This is ugly and costs +60 bytes compared to multiple + * fprintf's, but is guaranteed to do a single write. + * This is needed for e.g. when multiple children + * can produce log messages simultaneously. */ + + prefix_len = msg_prefix[0] ? strlen(msg_prefix) + 2 : 0; + strerr_len = strerr ? strlen(strerr) : 0; + msgeol_len = strlen(msg_eol); + /* +3 is for ": " before strerr and for terminating NUL */ + char *msg1 = (char*) realloc(msg, prefix_len + used + strerr_len + msgeol_len + 3); + if (!msg1) + { + free(msg); + return; + } + msg = msg1; + /* TODO: maybe use writev instead of memmoving? Need full_writev? */ + if (prefix_len) + { + char *p; + memmove(msg + prefix_len, msg, used); + used += prefix_len; + p = stpcpy(msg, msg_prefix); + p[0] = ':'; + p[1] = ' '; + } + if (strerr) + { + if (s[0]) + { + msg[used++] = ':'; + msg[used++] = ' '; + } + strcpy(&msg[used], strerr); + used += strerr_len; + } + strcpy(&msg[used], msg_eol); + + if (flags & LOGMODE_STDIO) + { + fflush(stdout); + write(STDERR_FILENO, msg, used + msgeol_len); + } + msg[used] = '\0'; /* remove msg_eol (usually "\n") */ + if (flags & LOGMODE_SYSLOG) + { + syslog(LOG_ERR, "%s", msg + prefix_len); + } + free(msg); +} + +void log_msg(const char *s, ...) +{ + va_list p; + va_start(p, s); + verror_msg_helper(s, p, NULL, logmode); + va_end(p); +} +/* It's a macro, not function, since it collides with log() from math.h */ +#undef log +#define log(...) log_msg(__VA_ARGS__) + +void error_msg(const char *s, ...) +{ + va_list p; + va_start(p, s); + verror_msg_helper(s, p, NULL, logmode); + va_end(p); +} + +void error_msg_and_die(const char *s, ...) +{ + va_list p; + va_start(p, s); + verror_msg_helper(s, p, NULL, logmode); + va_end(p); + xfunc_die(); +} + +void perror_msg(const char *s, ...) +{ + va_list p; + va_start(p, s); + /* Guard against ": Success" */ + verror_msg_helper(s, p, errno ? strerror(errno) : NULL, logmode); + va_end(p); +} + +void perror_msg_and_die(const char *s, ...) +{ + va_list p; + va_start(p, s); + /* Guard against ": Success" */ + verror_msg_helper(s, p, errno ? strerror(errno) : NULL, logmode); + va_end(p); + xfunc_die(); +} + +void die_out_of_memory(void) +{ + error_msg_and_die("Out of memory, exiting"); +} + +/* End of utility logging functions */ + + + +static +void handle_sigsegv(int sig, siginfo_t *info, void *ucontext) +{ + long ip = 0; + ucontext_t *uc UNUSED; + + uc = ucontext; +#if defined(__linux__) +#ifdef UNW_TARGET_X86 + ip = uc->uc_mcontext.gregs[REG_EIP]; +#elif defined(UNW_TARGET_X86_64) + ip = uc->uc_mcontext.gregs[REG_RIP]; +#elif defined(UNW_TARGET_ARM) + ip = uc->uc_mcontext.arm_pc; +#endif +#elif defined(__FreeBSD__) +#ifdef __i386__ + ip = uc->uc_mcontext.mc_eip; +#elif defined(__amd64__) + ip = uc->uc_mcontext.mc_rip; +#else +#error Port me +#endif +#else +#error Port me +#endif + dprintf(2, "signal:%d address:0x%lx ip:0x%lx\n", + sig, + /* this is void*, but using %p would print "(null)" + * even for ptrs which are not exactly 0, but, say, 0x123: + */ + (long)info->si_addr, + ip); + + { + /* glibc extension */ + void *array[50]; + int size; + size = backtrace(array, 50); +#ifdef __linux__ + backtrace_symbols_fd(array, size, 2); +#endif + } + + _exit(1); +} + +static void install_sigsegv_handler(void) +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = handle_sigsegv; + sa.sa_flags = SA_SIGINFO; + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGILL, &sa, NULL); + sigaction(SIGFPE, &sa, NULL); + sigaction(SIGBUS, &sa, NULL); +} + +int +main(int argc UNUSED, char **argv) +{ + unw_addr_space_t as; + struct UCD_info *ui; + unw_cursor_t c; + int ret; + +#define TEST_FRAMES 4 +#define TEST_NAME_LEN 32 + int testcase = 0; + int test_cur = 0; + long test_start_ips[TEST_FRAMES]; + char test_names[TEST_FRAMES][TEST_NAME_LEN]; + + install_sigsegv_handler(); + + const char *progname = strrchr(argv[0], '/'); + if (progname) + progname++; + else + progname = argv[0]; + + if (!argv[1]) + error_msg_and_die("Usage: %s COREDUMP [VADDR:BINARY_FILE]...", progname); + + msg_prefix = progname; + + as = unw_create_addr_space(&_UCD_accessors, 0); + if (!as) + error_msg_and_die("unw_create_addr_space() failed"); + + ui = _UCD_create(argv[1]); + if (!ui) + error_msg_and_die("_UCD_create('%s') failed", argv[1]); + ret = unw_init_remote(&c, as, ui); + if (ret < 0) + error_msg_and_die("unw_init_remote() failed: ret=%d\n", ret); + + argv += 2; + + /* Enable checks for the crasher test program? */ + if (*argv && !strcmp(*argv, "-testcase")) + { + testcase = 1; + logmode = LOGMODE_NONE; + argv++; + } + + while (*argv) + { + char *colon; + unsigned long vaddr = strtoul(*argv, &colon, 16); + if (*colon != ':') + error_msg_and_die("Bad format: '%s'", *argv); + if (_UCD_add_backing_file_at_vaddr(ui, vaddr, colon + 1) < 0) + error_msg_and_die("Can't add backing file '%s'", colon + 1); + argv++; + } + + for (;;) + { + unw_word_t ip; + ret = unw_get_reg(&c, UNW_REG_IP, &ip); + if (ret < 0) + error_msg_and_die("unw_get_reg(UNW_REG_IP) failed: ret=%d\n", ret); + + unw_proc_info_t pi; + ret = unw_get_proc_info(&c, &pi); + if (ret < 0) + error_msg_and_die("unw_get_proc_info(ip=0x%lx) failed: ret=%d\n", (long) ip, ret); + + if (!testcase) + printf("\tip=0x%08lx proc=%08lx-%08lx handler=0x%08lx lsda=0x%08lx\n", + (long) ip, + (long) pi.start_ip, (long) pi.end_ip, + (long) pi.handler, (long) pi.lsda); + + if (testcase && test_cur < TEST_FRAMES) + { + unw_word_t off; + + test_start_ips[test_cur] = (long) pi.start_ip; + if (unw_get_proc_name(&c, test_names[test_cur], sizeof(test_names[0]), &off) != 0) + { + test_names[test_cur][0] = '\0'; + } + test_cur++; + } + + log("step"); + ret = unw_step(&c); + log("step done:%d", ret); + if (ret < 0) + error_msg_and_die("FAILURE: unw_step() returned %d", ret); + if (ret == 0) + break; + } + log("stepping ended"); + + /* Check that the second and third frames are equal, but distinct of the + * others */ + if (testcase && + (test_cur != 4 + || test_start_ips[1] != test_start_ips[2] + || test_start_ips[0] == test_start_ips[1] + || test_start_ips[2] == test_start_ips[3] + ) + ) + { + fprintf(stderr, "FAILURE: start IPs incorrect\n"); + return -1; + } + + if (testcase && + ( strcmp(test_names[0], "a") + || strcmp(test_names[1], "b") + || strcmp(test_names[2], "b") + || strcmp(test_names[3], "main") + ) + ) + { + fprintf(stderr, "FAILURE: procedure names are missing/incorrect\n"); + return -1; + } + + _UCD_destroy(ui); + unw_destroy_addr_space(as); + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-flush-cache.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-flush-cache.c new file mode 100644 index 0000000..1611cf4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-flush-cache.c @@ -0,0 +1,143 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Copyright (c) 2003 Hewlett-Packard Co. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#define UNW_LOCAL_ONLY /* must define this for consistency with backtrace() */ +#include + +int verbose; + +int +f257 (void) +{ + void *buffer[300]; + int i, n; + + if (verbose) + printf ("First backtrace:\n"); + n = unw_backtrace (buffer, 300); + if (verbose) + for (i = 0; i < n; ++i) + printf ("[%d] ip=%p\n", i, buffer[i]); + + unw_set_cache_size (unw_local_addr_space, 1023, 0); + unw_flush_cache (unw_local_addr_space, 0, 0); + + if (verbose) + printf ("\nSecond backtrace:\n"); + n = unw_backtrace (buffer, 300); + if (verbose) + for (i = 0; i < n; ++i) + printf ("[%d] ip=%p\n", i, buffer[i]); + return 0; +} + +#define F(n,m) \ +int \ +f##n (void) \ +{ \ + return f##m (); \ +} + +/* Here, we rely on the fact that the script-cache's hash-table is 256 + entries big. With 257 functions, we're guaranteed to get at least + one hash-collision. */ +F(256,257) F(255,256) F(254,255) F(253,254) +F(252,253) F(251,252) F(250,251) F(249,250) +F(248,249) F(247,248) F(246,247) F(245,246) +F(244,245) F(243,244) F(242,243) F(241,242) +F(240,241) F(239,240) F(238,239) F(237,238) +F(236,237) F(235,236) F(234,235) F(233,234) +F(232,233) F(231,232) F(230,231) F(229,230) +F(228,229) F(227,228) F(226,227) F(225,226) +F(224,225) F(223,224) F(222,223) F(221,222) +F(220,221) F(219,220) F(218,219) F(217,218) +F(216,217) F(215,216) F(214,215) F(213,214) +F(212,213) F(211,212) F(210,211) F(209,210) +F(208,209) F(207,208) F(206,207) F(205,206) +F(204,205) F(203,204) F(202,203) F(201,202) +F(200,201) F(199,200) F(198,199) F(197,198) +F(196,197) F(195,196) F(194,195) F(193,194) +F(192,193) F(191,192) F(190,191) F(189,190) +F(188,189) F(187,188) F(186,187) F(185,186) +F(184,185) F(183,184) F(182,183) F(181,182) +F(180,181) F(179,180) F(178,179) F(177,178) +F(176,177) F(175,176) F(174,175) F(173,174) +F(172,173) F(171,172) F(170,171) F(169,170) +F(168,169) F(167,168) F(166,167) F(165,166) +F(164,165) F(163,164) F(162,163) F(161,162) +F(160,161) F(159,160) F(158,159) F(157,158) +F(156,157) F(155,156) F(154,155) F(153,154) +F(152,153) F(151,152) F(150,151) F(149,150) +F(148,149) F(147,148) F(146,147) F(145,146) +F(144,145) F(143,144) F(142,143) F(141,142) +F(140,141) F(139,140) F(138,139) F(137,138) +F(136,137) F(135,136) F(134,135) F(133,134) +F(132,133) F(131,132) F(130,131) F(129,130) +F(128,129) F(127,128) F(126,127) F(125,126) +F(124,125) F(123,124) F(122,123) F(121,122) +F(120,121) F(119,120) F(118,119) F(117,118) +F(116,117) F(115,116) F(114,115) F(113,114) +F(112,113) F(111,112) F(110,111) F(109,110) +F(108,109) F(107,108) F(106,107) F(105,106) +F(104,105) F(103,104) F(102,103) F(101,102) +F(100,101) F(99,100) F(98,99) F(97,98) +F(96,97) F(95,96) F(94,95) F(93,94) +F(92,93) F(91,92) F(90,91) F(89,90) +F(88,89) F(87,88) F(86,87) F(85,86) +F(84,85) F(83,84) F(82,83) F(81,82) +F(80,81) F(79,80) F(78,79) F(77,78) +F(76,77) F(75,76) F(74,75) F(73,74) +F(72,73) F(71,72) F(70,71) F(69,70) +F(68,69) F(67,68) F(66,67) F(65,66) +F(64,65) F(63,64) F(62,63) F(61,62) +F(60,61) F(59,60) F(58,59) F(57,58) +F(56,57) F(55,56) F(54,55) F(53,54) +F(52,53) F(51,52) F(50,51) F(49,50) +F(48,49) F(47,48) F(46,47) F(45,46) +F(44,45) F(43,44) F(42,43) F(41,42) +F(40,41) F(39,40) F(38,39) F(37,38) +F(36,37) F(35,36) F(34,35) F(33,34) +F(32,33) F(31,32) F(30,31) F(29,30) +F(28,29) F(27,28) F(26,27) F(25,26) +F(24,25) F(23,24) F(22,23) F(21,22) +F(20,21) F(19,20) F(18,19) F(17,18) +F(16,17) F(15,16) F(14,15) F(13,14) +F(12,13) F(11,12) F(10,11) F(9,10) +F(8,9) F(7,8) F(6,7) F(5,6) +F(4,5) F(3,4) F(2,3) F(1,2) + +int +main (int argc, char **argv) +{ + if (argc > 1 && strcmp (argv[1], "-v") == 0) + verbose = 1; + + return f1 (); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-init-remote.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-init-remote.c new file mode 100644 index 0000000..66f2d6a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-init-remote.c @@ -0,0 +1,103 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Copyright (c) 2002 Hewlett-Packard Co. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* This test simply verifies that unw_init_remote() can be used in + lieu of unw_init_local(). This was broken for a while on ia64. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "compiler.h" + +#include +#include +#include +#include + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +int verbose; + +static int +do_backtrace (void) +{ + char buf[512], name[256]; + unw_word_t ip, sp, off; + unw_cursor_t cursor; + unw_context_t uc; + int ret; + + unw_getcontext (&uc); + if (unw_init_remote (&cursor, unw_local_addr_space, &uc) < 0) + panic ("unw_init_remote failed!\n"); + + do + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + unw_get_reg (&cursor, UNW_REG_SP, &sp); + buf[0] = '\0'; + if (unw_get_proc_name (&cursor, name, sizeof (name), &off) == 0) + { + if (off) + snprintf (buf, sizeof (buf), "<%s+0x%lx>", name, (long) off); + else + snprintf (buf, sizeof (buf), "<%s>", name); + } + if (verbose) + printf ("%016lx %-32s (sp=%016lx)\n", (long) ip, buf, (long) sp); + + ret = unw_step (&cursor); + if (ret < 0) + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + printf ("FAILURE: unw_step() returned %d for ip=%lx\n", + ret, (long) ip); + return -1; + } + } + while (ret > 0); + + return 0; +} + +static int +foo (void) +{ + return do_backtrace (); +} + +int +main (int argc, char **argv UNUSED) +{ + verbose = (argc > 1); + + if (verbose) + printf ("Normal backtrace:\n"); + return foo (); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-mem.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-mem.c new file mode 100644 index 0000000..52c9774 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-mem.c @@ -0,0 +1,103 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Copyright (c) 2003 Hewlett-Packard Co. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "compiler.h" + +#include +#include +#include +#include +#include + +#include + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +int verbose; + +static void +do_backtrace (void) +{ + unw_cursor_t cursor; + unw_word_t ip, sp; + unw_context_t uc; + int ret; + + unw_getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + panic ("unw_init_local failed!\n"); + + do + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + unw_get_reg (&cursor, UNW_REG_SP, &sp); + + if (verbose) + printf ("%016lx (sp=%016lx)\n", (long) ip, (long) sp); + + ret = unw_step (&cursor); + if (ret < 0) + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + panic ("FAILURE: unw_step() returned %d for ip=%lx\n", + ret, (long) ip); + } + } + while (ret > 0); +} + +int +consume_some_stack_space (void) +{ + unw_cursor_t cursor; + unw_context_t uc; + char string[1024]; + + memset (&cursor, 0, sizeof (cursor)); + memset (&uc, 0, sizeof (uc)); + return sprintf (string, "hello %p %p\n", &cursor, &uc); +} + +int +main (int argc, char **argv UNUSED) +{ + struct rlimit rlim; + + verbose = argc > 1; + + if (consume_some_stack_space () > 9999) + exit (-1); /* can't happen, but don't let the compiler know... */ + + rlim.rlim_cur = 0; + rlim.rlim_max = RLIM_INFINITY; + setrlimit (RLIMIT_DATA, &rlim); + setrlimit (RLIMIT_AS, &rlim); + + do_backtrace (); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-proc-info.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-proc-info.c new file mode 100644 index 0000000..c4145bc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-proc-info.c @@ -0,0 +1,171 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Copyright (c) 2003 Hewlett-Packard Co. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* This test program checks whether proc_info lookup failures are + cached. They must NOT be cached because it could otherwise turn + temporary failures into permanent ones. Furthermore, we allow apps + to return -UNW_ESTOPUNWIND to terminate unwinding (though this + feature is deprecated and dynamic unwind info should be used + instead). */ + +#include +#include + +#include +#include "compiler.h" + +int errors; + +#define panic(args...) \ + { ++errors; fprintf (stderr, args); return -1; } + +static int +find_proc_info (unw_addr_space_t as UNUSED, + unw_word_t ip UNUSED, + unw_proc_info_t *pip UNUSED, + int need_unwind_info UNUSED, + void *arg UNUSED) +{ + return -UNW_ESTOPUNWIND; +} + +static int +access_mem (unw_addr_space_t as UNUSED, + unw_word_t addr UNUSED, + unw_word_t *valp, int write, + void *arg UNUSED) +{ + if (!write) + *valp = 0; + return 0; +} + +static int +access_reg (unw_addr_space_t as UNUSED, + unw_regnum_t regnum UNUSED, + unw_word_t *valp, int write, + void *arg UNUSED) +{ + if (!write) + *valp = 32; + return 0; +} + +static int +access_fpreg (unw_addr_space_t as UNUSED, + unw_regnum_t regnum UNUSED, + unw_fpreg_t *valp, int write, + void *arg UNUSED) +{ + if (!write) + memset (valp, 0, sizeof (*valp)); + return 0; +} + +static int +get_dyn_info_list_addr (unw_addr_space_t as UNUSED, + unw_word_t *dilap UNUSED, + void *arg UNUSED) +{ + return -UNW_ENOINFO; +} + +static void +put_unwind_info (unw_addr_space_t as UNUSED, + unw_proc_info_t *pi UNUSED, + void *arg UNUSED) +{ + ++errors; + fprintf (stderr, "%s() got called!\n", __FUNCTION__); +} + +static int +resume (unw_addr_space_t as UNUSED, + unw_cursor_t *reg UNUSED, + void *arg UNUSED) +{ + panic ("%s() got called!\n", __FUNCTION__); +} + +static int +get_proc_name (unw_addr_space_t as UNUSED, + unw_word_t ip UNUSED, + char *buf UNUSED, + size_t buf_len UNUSED, + unw_word_t *offp UNUSED, + void *arg UNUSED) +{ + panic ("%s() got called!\n", __FUNCTION__); +} + +int +main (int argc, char **argv) +{ + unw_accessors_t acc; + unw_addr_space_t as; + int ret, verbose = 0; + unw_cursor_t c; + + if (argc > 1 && strcmp (argv[1], "-v") == 0) + verbose = 1; + + memset (&acc, 0, sizeof (acc)); + acc.find_proc_info = find_proc_info; + acc.put_unwind_info = put_unwind_info; + acc.get_dyn_info_list_addr = get_dyn_info_list_addr; + acc.access_mem = access_mem; + acc.access_reg = access_reg; + acc.access_fpreg = access_fpreg; + acc.resume = resume; + acc.get_proc_name = get_proc_name; + + as = unw_create_addr_space (&acc, 0); + if (!as) + panic ("unw_create_addr_space() failed\n"); + + unw_set_caching_policy (as, UNW_CACHE_GLOBAL); + + ret = unw_init_remote (&c, as, NULL); + if (ret < 0) + panic ("unw_init_remote() returned %d instead of 0\n", ret); + + ret = unw_step (&c); + if (ret != -UNW_ESTOPUNWIND) + panic ("First call to unw_step() returned %d instead of %d\n", + ret, -UNW_ESTOPUNWIND); + + ret = unw_step (&c); + if (ret != -UNW_ESTOPUNWIND) + panic ("Second call to unw_step() returned %d instead of %d\n", + ret, -UNW_ESTOPUNWIND); + + unw_destroy_addr_space (as); + + if (verbose) + printf ("SUCCESS\n"); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-ptrace-misc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-ptrace-misc.c new file mode 100644 index 0000000..374059d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-ptrace-misc.c @@ -0,0 +1,120 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "compiler.h" + +#include +#include +#include +#include +#include + +#include + +pid_t self; +int global[64]; + +int +func (int arg) +{ + int sum = 0, i, max, arr[1024]; + + if (arg == 0) + { + sum = global[2]; + sum += sum + sum * getppid (); + return sum; + } + else + { + max = arg; + if (max >= 64) + max = 64; + + for (i = 0; i < max; ++i) + arr[i] = func (arg - 1); + + for (i = 0; i < max; ++i) + if (arr[i] > 16) + sum += arr[i]; + else + sum -= arr[i]; + } + return sum; +} + +int +bar (int v) +{ + extern long f (long); + int arr[1] = { v }; + uintptr_t r; + + /* This is a vain attempt to use up lots of registers to force + the frame-chain info to be saved on the memory stack on ia64. + It happens to work with gcc v3.3.4 and gcc v3.4.1 but perhaps + not with any other compiler. */ + r = (uintptr_t) malloc(f (arr[0]) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + f (v)) + )))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + ))))))))))))))))))))))))))))))))))))))))))))))))))))))); + if (r < 2) + v = r; + + kill (self, SIGUSR1); /* tell test-ptrace to start single-stepping */ + v = func (v); + kill (self, SIGUSR2); /* tell test-ptrace to stop single-stepping */ + return v; +} + +int +main (int argc, char **argv UNUSED) +{ + int val = argc; + + signal (SIGUSR1, SIG_IGN); + signal (SIGUSR2, SIG_IGN); + + self = getpid (); + + printf ("sum = %d\n", bar (val)); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-ptrace.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-ptrace.c new file mode 100644 index 0000000..e7c7883 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-ptrace.c @@ -0,0 +1,370 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#ifdef HAVE_TTRACE + +int +main (void) +{ + printf ("FAILURE: ttrace() not supported yet\n"); + return -1; +} + +#else /* !HAVE_TTRACE */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +extern char **environ; + +static const int nerrors_max = 100; + +int nerrors; +int verbose; +int print_names = 1; + +enum + { + INSTRUCTION, + SYSCALL, + TRIGGER + } +trace_mode = SYSCALL; + +#define panic(args...) \ + do { fprintf (stderr, args); ++nerrors; } while (0) + +static unw_addr_space_t as; +static struct UPT_info *ui; + +static int killed; + +void +do_backtrace (void) +{ + unw_word_t ip, sp, start_ip = 0, off; + int n = 0, ret; + unw_proc_info_t pi; + unw_cursor_t c; + char buf[512]; + size_t len; + + ret = unw_init_remote (&c, as, ui); + if (ret < 0) + panic ("unw_init_remote() failed: ret=%d\n", ret); + + do + { + if ((ret = unw_get_reg (&c, UNW_REG_IP, &ip)) < 0 + || (ret = unw_get_reg (&c, UNW_REG_SP, &sp)) < 0) + panic ("unw_get_reg/unw_get_proc_name() failed: ret=%d\n", ret); + + if (n == 0) + start_ip = ip; + + buf[0] = '\0'; + if (print_names) + unw_get_proc_name (&c, buf, sizeof (buf), &off); + + if (verbose) + { + if (off) + { + len = strlen (buf); + if (len >= sizeof (buf) - 32) + len = sizeof (buf) - 32; + sprintf (buf + len, "+0x%lx", (unsigned long) off); + } + printf ("%016lx %-32s (sp=%016lx)\n", (long) ip, buf, (long) sp); + } + + if ((ret = unw_get_proc_info (&c, &pi)) < 0) + panic ("unw_get_proc_info(ip=0x%lx) failed: ret=%d\n", (long) ip, ret); + else if (verbose) + printf ("\tproc=%016lx-%016lx\n\thandler=%lx lsda=%lx", + (long) pi.start_ip, (long) pi.end_ip, + (long) pi.handler, (long) pi.lsda); + +#if UNW_TARGET_IA64 + { + unw_word_t bsp; + + if ((ret = unw_get_reg (&c, UNW_IA64_BSP, &bsp)) < 0) + panic ("unw_get_reg() failed: ret=%d\n", ret); + else if (verbose) + printf (" bsp=%lx", bsp); + } +#endif + if (verbose) + printf ("\n"); + + ret = unw_step (&c); + if (ret < 0) + { + unw_get_reg (&c, UNW_REG_IP, &ip); + panic ("FAILURE: unw_step() returned %d for ip=%lx (start ip=%lx)\n", + ret, (long) ip, (long) start_ip); + } + + if (++n > 64) + { + /* guard against bad unwind info in old libraries... */ + panic ("too deeply nested---assuming bogus unwind (start ip=%lx)\n", + (long) start_ip); + break; + } + if (nerrors > nerrors_max) + { + panic ("Too many errors (%d)!\n", nerrors); + break; + } + } + while (ret > 0); + + if (ret < 0) + panic ("unwind failed with ret=%d\n", ret); + + if (verbose) + printf ("================\n\n"); +} + +static pid_t target_pid; +static void target_pid_kill (void) +{ + kill (target_pid, SIGKILL); +} + +int +main (int argc, char **argv) +{ + int status, pid, pending_sig, optind = 1, state = 1; + + as = unw_create_addr_space (&_UPT_accessors, 0); + if (!as) + panic ("unw_create_addr_space() failed"); + + if (argc == 1) + { + static char *args[] = { "self", "/bin/ls", "/usr", NULL }; + + /* automated test case */ + argv = args; + + /* Unless the args array is 'walked' the child + process is unable to access it and dies with a segfault */ + fprintf(stderr, "Automated test (%s,%s,%s,%s)\n", + args[0],args[1],args[2],args[3]); + } + else if (argc > 1) + while (argv[optind][0] == '-') + { + if (strcmp (argv[optind], "-v") == 0) + ++optind, verbose = 1; + else if (strcmp (argv[optind], "-i") == 0) + ++optind, trace_mode = INSTRUCTION; /* backtrace at each insn */ + else if (strcmp (argv[optind], "-s") == 0) + ++optind, trace_mode = SYSCALL; /* backtrace at each syscall */ + else if (strcmp (argv[optind], "-t") == 0) + /* Execute until raise(SIGUSR1), then backtrace at each insn + until raise(SIGUSR2). */ + ++optind, trace_mode = TRIGGER; + else if (strcmp (argv[optind], "-c") == 0) + /* Enable caching of unwind-info. */ + ++optind, unw_set_caching_policy (as, UNW_CACHE_GLOBAL); + else if (strcmp (argv[optind], "-n") == 0) + /* Don't look-up and print symbol names. */ + ++optind, print_names = 0; + else + fprintf(stderr, "unrecognized option: %s\n", argv[optind++]); + if (optind >= argc) + break; + } + + target_pid = fork (); + if (!target_pid) + { + /* child */ + + if (!verbose) + dup2 (open ("/dev/null", O_WRONLY), 1); + +#if HAVE_DECL_PTRACE_TRACEME + ptrace (PTRACE_TRACEME, 0, 0, 0); +#elif HAVE_DECL_PT_TRACE_ME + ptrace (PT_TRACE_ME, 0, 0, 0); +#else +#error Trace me +#endif + + if ((argc > 1) && (optind == argc)) { + fprintf(stderr, "Need to specify a command line for the child\n"); + exit (-1); + } + execve (argv[optind], argv + optind, environ); + _exit (-1); + } + atexit (target_pid_kill); + + ui = _UPT_create (target_pid); + + while (nerrors <= nerrors_max) + { + pid = wait4 (-1, &status, 0, NULL); + if (pid == -1) + { + if (errno == EINTR) + continue; + + panic ("wait4() failed (errno=%d)\n", errno); + } + pending_sig = 0; + if (WIFSIGNALED (status) || WIFEXITED (status) + || (WIFSTOPPED (status) && WSTOPSIG (status) != SIGTRAP)) + { + if (WIFEXITED (status)) + { + if (WEXITSTATUS (status) != 0) + panic ("child's exit status %d\n", WEXITSTATUS (status)); + break; + } + else if (WIFSIGNALED (status)) + { + if (!killed) + panic ("child terminated by signal %d\n", WTERMSIG (status)); + break; + } + else + { + pending_sig = WSTOPSIG (status); + /* Avoid deadlock: */ + if (WSTOPSIG (status) == SIGKILL) + break; + if (trace_mode == TRIGGER) + { + if (WSTOPSIG (status) == SIGUSR1) + state = 0; + else if (WSTOPSIG (status) == SIGUSR2) + state = 1; + } + if (WSTOPSIG (status) != SIGUSR1 && WSTOPSIG (status) != SIGUSR2) + { + static int count = 0; + + if (count++ > 100) + { + panic ("Too many child unexpected signals (now %d)\n", + WSTOPSIG (status)); + killed = 1; + } + } + } + } + + switch (trace_mode) + { + case TRIGGER: + if (state) +#if HAVE_DECL_PTRACE_CONT + ptrace (PTRACE_CONT, target_pid, 0, 0); +#elif HAVE_DECL_PT_CONTINUE + ptrace (PT_CONTINUE, target_pid, (caddr_t)1, 0); +#else +#error Port me +#endif + else + { + do_backtrace (); +#if HAVE_DECL_PTRACE_SINGLESTEP + if (ptrace (PTRACE_SINGLESTEP, target_pid, 0, pending_sig) < 0) + { + panic ("ptrace(PTRACE_SINGLESTEP) failed (errno=%d)\n", errno); + killed = 1; + } +#elif HAVE_DECL_PT_STEP + if (ptrace (PT_STEP, target_pid, (caddr_t)1, pending_sig) < 0) + { + panic ("ptrace(PT_STEP) failed (errno=%d)\n", errno); + killed = 1; + } +#else +#error Singlestep me +#endif + } + break; + + case SYSCALL: + if (!state) + do_backtrace (); + state ^= 1; +#if HAVE_DECL_PTRACE_SYSCALL + ptrace (PTRACE_SYSCALL, target_pid, 0, pending_sig); +#elif HAVE_DECL_PT_SYSCALL + ptrace (PT_SYSCALL, target_pid, (caddr_t)1, pending_sig); +#else +#error Syscall me +#endif + break; + + case INSTRUCTION: + do_backtrace (); +#if HAVE_DECL_PTRACE_SINGLESTEP + ptrace (PTRACE_SINGLESTEP, target_pid, 0, pending_sig); +#elif HAVE_DECL_PT_STEP + ptrace (PT_STEP, target_pid, (caddr_t)1, pending_sig); +#else +#error Singlestep me +#endif + break; + } + if (killed) + kill (target_pid, SIGKILL); + } + + _UPT_destroy (ui); + unw_destroy_addr_space (as); + + if (nerrors) + { + printf ("FAILURE: detected %d errors\n", nerrors); + exit (-1); + } + if (verbose) + printf ("SUCCESS\n"); + + return 0; +} + +#endif /* !HAVE_TTRACE */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-reg-state.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-reg-state.c new file mode 100644 index 0000000..ac713ea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-reg-state.c @@ -0,0 +1,133 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Copyright (c) 2003 Hewlett-Packard Co. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "compiler.h" + +#include +#include +#include +#include +#include + +#include +#include + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +int verbose; + +struct cb_data +{ + unw_word_t ip; + void* reg_state; + size_t len; +}; + +static int +dwarf_reg_states_callback(void *token, + void *rs, + size_t size, + unw_word_t start_ip, unw_word_t end_ip) +{ + struct cb_data *data = token; + if (start_ip <= data->ip && data->ip < end_ip) + { + data->reg_state = mmap(NULL, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + memcpy(data->reg_state, rs, size); + data->len = size; + } + return 0; +} + +static void +do_backtrace (void) +{ + unw_cursor_t cursor; + unw_word_t ip, sp; + unw_context_t uc; + int ret; + + unw_getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + panic ("unw_init_local failed!\n"); + + do + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + unw_get_reg (&cursor, UNW_REG_SP, &sp); + + if (verbose) + printf ("%016lx (sp=%016lx)\n", (long) ip, (long) sp); + + struct cb_data data = {.ip = ip, .reg_state = NULL}; + ret = unw_reg_states_iterate(&cursor, dwarf_reg_states_callback, &data); + if (ret > 0) + { + ret = unw_apply_reg_state (&cursor, data.reg_state); + munmap(data.reg_state, data.len); + } + if (ret < 0) + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + panic ("FAILURE: unw_step() returned %d for ip=%lx\n", + ret, (long) ip); + } + } + while (ret > 0); +} + +int +consume_some_stack_space (void) +{ + unw_cursor_t cursor; + unw_context_t uc; + char string[1024]; + + memset (&cursor, 0, sizeof (cursor)); + memset (&uc, 0, sizeof (uc)); + return sprintf (string, "hello %p %p\n", &cursor, &uc); +} + +int +main (int argc, char **argv UNUSED) +{ + struct rlimit rlim; + + verbose = argc > 1; + + if (consume_some_stack_space () > 9999) + exit (-1); /* can't happen, but don't let the compiler know... */ + + rlim.rlim_cur = 0; + rlim.rlim_max = RLIM_INFINITY; + setrlimit (RLIMIT_DATA, &rlim); + + do_backtrace (); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-setjmp.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-setjmp.c new file mode 100644 index 0000000..769b71b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-setjmp.c @@ -0,0 +1,285 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* The setjmp()/longjmp(), sigsetjmp()/siglongjmp(). */ + +#include "compiler.h" + +#include +#include +#include +#include +#include +#include + +int nerrors; +int verbose; + +static jmp_buf jbuf; +static sigjmp_buf sigjbuf; +static sigset_t sigset4; + +void +raise_longjmp (jmp_buf jbuf, int i, int n) +{ + while (i < n) + raise_longjmp (jbuf, i + 1, n); + + longjmp (jbuf, n); +} + +void +test_setjmp (void) +{ + volatile int i; + jmp_buf jbuf; + int ret; + + for (i = 0; i < 10; ++i) + { + if ((ret = setjmp (jbuf))) + { + if (verbose) + printf ("%s: secondary setjmp () return, ret=%d\n", + __FUNCTION__, ret); + if (ret != i + 1) + { + fprintf (stderr, "%s: setjmp() returned %d, expected %d\n", + __FUNCTION__, ret, i + 1); + ++nerrors; + } + continue; + } + if (verbose) + printf ("%s.%d: done with setjmp(); calling children\n", + __FUNCTION__, i + 1); + + raise_longjmp (jbuf, 0, i + 1); + + fprintf (stderr, "%s: raise_longjmp() returned unexpectedly\n", + __FUNCTION__); + ++nerrors; + } +} + + +void +raise_siglongjmp (sigjmp_buf jbuf, int i, int n) +{ + while (i < n) + raise_siglongjmp (jbuf, i + 1, n); + + siglongjmp (jbuf, n); +} + +void +test_sigsetjmp (void) +{ + sigjmp_buf jbuf; + volatile int i; + int ret; + + for (i = 0; i < 10; ++i) + { + if ((ret = sigsetjmp (jbuf, 1))) + { + if (verbose) + printf ("%s: secondary sigsetjmp () return, ret=%d\n", + __FUNCTION__, ret); + if (ret != i + 1) + { + fprintf (stderr, "%s: sigsetjmp() returned %d, expected %d\n", + __FUNCTION__, ret, i + 1); + ++nerrors; + } + continue; + } + if (verbose) + printf ("%s.%d: done with sigsetjmp(); calling children\n", + __FUNCTION__, i + 1); + + raise_siglongjmp (jbuf, 0, i + 1); + + fprintf (stderr, "%s: raise_siglongjmp() returned unexpectedly\n", + __FUNCTION__); + ++nerrors; + } +} + +void +sighandler (int signal) +{ + if (verbose) + printf ("%s: got signal %d\n", __FUNCTION__, signal); + + sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset4); + if (verbose) + printf ("%s: back from sigprocmask\n", __FUNCTION__); + + siglongjmp (sigjbuf, 1); + printf ("%s: siglongjmp() returned unexpectedly!\n", __FUNCTION__); +} + +int +main (int argc, char **argv UNUSED) +{ + volatile sigset_t sigset1, sigset2, sigset3; + volatile struct sigaction act; + + if (argc > 1) + verbose = 1; + + sigemptyset ((sigset_t *) &sigset1); + sigaddset ((sigset_t *) &sigset1, SIGUSR1); + sigemptyset ((sigset_t *) &sigset2); + sigaddset ((sigset_t *) &sigset2, SIGUSR2); + + memset ((void *) &act, 0, sizeof (act)); + act.sa_handler = sighandler; + sigaction (SIGTERM, (struct sigaction *) &act, NULL); + + test_setjmp (); + test_sigsetjmp (); + + /* _setjmp() MUST NOT change signal mask: */ + sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL); + if (_setjmp (jbuf)) + { + sigemptyset ((sigset_t *) &sigset3); + sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3); + if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset2, + sizeof (sigset_t)) != 0) + { + fprintf (stderr, "FAILURE: _longjmp() manipulated signal mask!\n"); + ++nerrors; + } + else if (verbose) + printf ("OK: _longjmp() seems not to change signal mask\n"); + } + else + { + sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL); + _longjmp (jbuf, 1); + } + + /* sigsetjmp(jbuf, 1) MUST preserve signal mask: */ + sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL); + if (sigsetjmp (sigjbuf, 1)) + { + sigemptyset ((sigset_t *) &sigset3); + sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3); + if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset1, + sizeof (sigset_t)) != 0) + { + fprintf (stderr, + "FAILURE: siglongjmp() didn't restore signal mask!\n"); + ++nerrors; + } + else if (verbose) + printf ("OK: siglongjmp() restores signal mask when asked to\n"); + } + else + { + sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL); + siglongjmp (sigjbuf, 1); + } + + /* sigsetjmp(jbuf, 0) MUST NOT preserve signal mask: */ + sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL); + if (sigsetjmp (sigjbuf, 0)) + { + sigemptyset ((sigset_t *) &sigset3); + sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3); + if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset2, + sizeof (sigset_t)) != 0) + { + fprintf (stderr, + "FAILURE: siglongjmp() changed signal mask!\n"); + ++nerrors; + } + else if (verbose) + printf ("OK: siglongjmp() leaves signal mask alone when asked to\n"); + } + else + { + sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL); + siglongjmp (sigjbuf, 1); + } + + /* sigsetjmp(jbuf, 1) MUST preserve signal mask: */ + sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL); + if (sigsetjmp (sigjbuf, 1)) + { + sigemptyset ((sigset_t *) &sigset3); + sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3); + if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset1, + sizeof (sigset_t)) != 0) + { + fprintf (stderr, + "FAILURE: siglongjmp() didn't restore signal mask!\n"); + ++nerrors; + } + else if (verbose) + printf ("OK: siglongjmp() restores signal mask when asked to\n"); + } + else + { + sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL); + kill (getpid (), SIGTERM); + fprintf (stderr, "FAILURE: unexpected return from kill()\n"); + ++nerrors; + } + + /* sigsetjmp(jbuf, 0) MUST NOT preserve signal mask: */ + sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL); + if (sigsetjmp (sigjbuf, 0)) + { + sigemptyset ((sigset_t *) &sigset3); + sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3); + if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset4, + sizeof (sigset_t)) != 0) + { + fprintf (stderr, + "FAILURE: siglongjmp() changed signal mask!\n"); + ++nerrors; + } + else if (verbose) + printf ("OK: siglongjmp() leaves signal mask alone when asked to\n"); + } + else + { + sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL); + kill (getpid (), SIGTERM); + fprintf (stderr, "FAILURE: unexpected return from kill()\n"); + ++nerrors; + } + + if (nerrors > 0) + { + fprintf (stderr, "FAILURE: detected %d failures\n", nerrors); + exit (-1); + } + if (verbose) + printf ("SUCCESS\n"); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-static-link-gen.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-static-link-gen.c new file mode 100644 index 0000000..d61e7a5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-static-link-gen.c @@ -0,0 +1,74 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Copyright (c) 2003 Hewlett-Packard Co. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include + +extern int verbose; + +static void *funcs[] = + { + (void *) &unw_get_reg, + (void *) &unw_get_fpreg, + (void *) &unw_set_reg, + (void *) &unw_set_fpreg, + (void *) &unw_resume, + (void *) &unw_create_addr_space, + (void *) &unw_destroy_addr_space, + (void *) &unw_get_accessors, + (void *) &unw_flush_cache, + (void *) &unw_set_caching_policy, + (void *) &unw_set_cache_size, + (void *) &unw_regname, + (void *) &unw_get_proc_info, + (void *) &unw_get_save_loc, + (void *) &unw_is_signal_frame, + (void *) &unw_get_proc_name + }; + +int +test_generic (void) +{ + if (verbose) + printf (__FILE__": funcs[0]=%p\n", funcs[0]); + +#ifndef UNW_REMOTE_ONLY + { + unw_context_t uc; + unw_cursor_t c; + + unw_getcontext (&uc); + unw_init_local (&c, &uc); + unw_init_remote (&c, unw_local_addr_space, &uc); + + return unw_step (&c); + } +#else + return 0; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-static-link-loc.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-static-link-loc.c new file mode 100644 index 0000000..1c7aa03 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-static-link-loc.c @@ -0,0 +1,102 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Copyright (c) 2003 Hewlett-Packard Co. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* The purpose of this program is simply to link in all libunwind-API + functions both in their local-only and generic variants and to make + sure that the final result can be linked statically. */ + +#include + +#define UNW_LOCAL_ONLY +#include +#include "compiler.h" + +extern int test_generic (void); + +int verbose; + +#ifdef UNW_REMOTE_ONLY + +int +test_local (void) +{ + return 0; +} + +#else /* !UNW_REMOTE_ONLY */ + +static void *funcs[] = + { + (void *) &unw_get_reg, + (void *) &unw_get_fpreg, + (void *) &unw_set_reg, + (void *) &unw_set_fpreg, + (void *) &unw_resume, + (void *) &unw_create_addr_space, + (void *) &unw_destroy_addr_space, + (void *) &unw_get_accessors, + (void *) &unw_flush_cache, + (void *) &unw_set_caching_policy, + (void *) &unw_set_cache_size, + (void *) &unw_regname, + (void *) &unw_get_proc_info, + (void *) &unw_get_save_loc, + (void *) &unw_is_signal_frame, + (void *) &unw_get_proc_name, + (void *) &_U_dyn_register, + (void *) &_U_dyn_cancel + }; + +int +test_local (void) +{ + unw_context_t uc; + unw_cursor_t c; + + if (verbose) + printf (__FILE__": funcs[0]=%p\n", funcs[0]); + + unw_getcontext (&uc); + unw_init_local (&c, &uc); + unw_init_remote (&c, unw_local_addr_space, &uc); + return unw_step (&c); +} + +#endif /* !UNW_REMOTE_ONLY */ + +int +main (int argc, char **argv UNUSED) +{ + if (argc > 1) + verbose = 1; + + if (test_local () < 0) + return -1; + if (test_generic () < 0) + return -1; + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-strerror.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-strerror.c new file mode 100644 index 0000000..f7ae61e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/libunwind/tests/test-strerror.c @@ -0,0 +1,18 @@ +#include "compiler.h" +#include +#include + +int +main (int argc, char **argv UNUSED) +{ + int i, verbose = argc > 1; + const char *msg; + + for (i = 0; i < 16; ++i) + { + msg = unw_strerror (-i); + if (verbose) + printf ("%6d -> %s\n", -i, msg); + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/loader/module.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/loader/module.cpp new file mode 100644 index 0000000..8418ef7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/loader/module.cpp @@ -0,0 +1,1812 @@ +// 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: + + module.c + +Abstract: + + Implementation of module related functions in the Win32 API + + + +--*/ + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(LOADER); // some headers have code with asserts, so do this first + +#include "pal/thread.hpp" +#include "pal/malloc.hpp" +#include "pal/file.hpp" +#include "pal/palinternal.h" +#include "pal/module.h" +#include "pal/cs.hpp" +#include "pal/process.h" +#include "pal/file.h" +#include "pal/utils.h" +#include "pal/init.h" +#include "pal/modulename.h" +#include "pal/environ.h" +#include "pal/virtual.h" +#include "pal/map.hpp" +#include "pal/stackstring.hpp" + +#include +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#include +#endif // __APPLE__ + +#include +#include + +#if HAVE_GNU_LIBNAMES_H +#include +#endif + +using namespace CorUnix; + +// In safemath.h, Template SafeInt uses macro _ASSERTE, which need to use variable +// defdbgchan defined by SET_DEFAULT_DEBUG_CHANNEL. Therefore, the include statement +// should be placed after the SET_DEFAULT_DEBUG_CHANNEL(LOADER) +#include + +/* macro definitions **********************************************************/ + +/* get the full name of a module if available, and the short name otherwise*/ +#define MODNAME(x) ((x)->lib_name) + +/* Which path should FindLibrary search? */ +#if defined(__APPLE__) +#define LIBSEARCHPATH "DYLD_LIBRARY_PATH" +#else +#define LIBSEARCHPATH "LD_LIBRARY_PATH" +#endif + +#define LIBC_NAME_WITHOUT_EXTENSION "libc" + +/* static variables ***********************************************************/ + +/* critical section that regulates access to the module list */ +CRITICAL_SECTION module_critsec; + +/* always the first, in the in-load-order list */ +MODSTRUCT exe_module; +MODSTRUCT *pal_module = nullptr; + +char * g_szCoreCLRPath = nullptr; + +int MaxWCharToAcpLength = 3; + +/* static function declarations ***********************************************/ + +template static bool LOADVerifyLibraryPath(const TChar *libraryPath); +static bool LOADConvertLibraryPathWideStringToMultibyteString( + LPCWSTR wideLibraryPath, + LPSTR multibyteLibraryPath, + INT *multibyteLibraryPathLengthRef); +static BOOL LOADValidateModule(MODSTRUCT *module); +static LPWSTR LOADGetModuleFileName(MODSTRUCT *module); +static MODSTRUCT *LOADAddModule(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR libraryNameOrPath); +static NATIVE_LIBRARY_HANDLE LOADLoadLibraryDirect(LPCSTR libraryNameOrPath); +static BOOL LOADFreeLibrary(MODSTRUCT *module, BOOL fCallDllMain); +static HMODULE LOADRegisterLibraryDirect(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR libraryNameOrPath, BOOL fDynamic); +static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic); +static BOOL LOADCallDllMainSafe(MODSTRUCT *module, DWORD dwReason, LPVOID lpReserved); + +/* API function definitions ***************************************************/ + +/*++ +Function: + LoadLibraryA + +See MSDN doc. +--*/ +HMODULE +PALAPI +LoadLibraryA( + IN LPCSTR lpLibFileName) +{ + return LoadLibraryExA(lpLibFileName, nullptr, 0); +} + +/*++ +Function: + LoadLibraryW + +See MSDN doc. +--*/ +HMODULE +PALAPI +LoadLibraryW( + IN LPCWSTR lpLibFileName) +{ + return LoadLibraryExW(lpLibFileName, nullptr, 0); +} + +/*++ +Function: +LoadLibraryExA + +See MSDN doc. +--*/ +HMODULE +PALAPI +LoadLibraryExA( + IN LPCSTR lpLibFileName, + IN /*Reserved*/ HANDLE hFile, + IN DWORD dwFlags) +{ + if (dwFlags != 0) + { + // UNIXTODO: Implement this! + ASSERT("Needs Implementation!!!"); + return nullptr; + } + + LPSTR lpstr = nullptr; + HMODULE hModule = nullptr; + + PERF_ENTRY(LoadLibraryA); + ENTRY("LoadLibraryExA (lpLibFileName=%p (%s)) \n", + (lpLibFileName) ? lpLibFileName : "NULL", + (lpLibFileName) ? lpLibFileName : "NULL"); + + if (!LOADVerifyLibraryPath(lpLibFileName)) + { + goto Done; + } + + /* do the Dos/Unix conversion on our own copy of the name */ + lpstr = strdup(lpLibFileName); + if (!lpstr) + { + ERROR("strdup failure!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto Done; + } + FILEDosToUnixPathA(lpstr); + + hModule = LOADLoadLibrary(lpstr, TRUE); + + /* let LOADLoadLibrary call SetLastError */ + Done: + if (lpstr != nullptr) + { + free(lpstr); + } + + LOGEXIT("LoadLibraryExA returns HMODULE %p\n", hModule); + PERF_EXIT(LoadLibraryExA); + return hModule; + +} + +/*++ +Function: +LoadLibraryExW + +See MSDN doc. +--*/ +HMODULE +PALAPI +LoadLibraryExW( + IN LPCWSTR lpLibFileName, + IN /*Reserved*/ HANDLE hFile, + IN DWORD dwFlags) +{ + if (dwFlags != 0) + { + // UNIXTODO: Implement this! + ASSERT("Needs Implementation!!!"); + return nullptr; + } + + CHAR * lpstr; + INT name_length; + PathCharString pathstr; + HMODULE hModule = nullptr; + + PERF_ENTRY(LoadLibraryExW); + ENTRY("LoadLibraryExW (lpLibFileName=%p (%S)) \n", + lpLibFileName ? lpLibFileName : W16_NULLSTRING, + lpLibFileName ? lpLibFileName : W16_NULLSTRING); + + if (!LOADVerifyLibraryPath(lpLibFileName)) + { + goto done; + } + + lpstr = pathstr.OpenStringBuffer((PAL_wcslen(lpLibFileName)+1) * MaxWCharToAcpLength); + if (nullptr == lpstr) + { + goto done; + } + if (!LOADConvertLibraryPathWideStringToMultibyteString(lpLibFileName, lpstr, &name_length)) + { + goto done; + } + + /* do the Dos/Unix conversion on our own copy of the name */ + FILEDosToUnixPathA(lpstr); + pathstr.CloseBuffer(name_length); + + /* let LOADLoadLibrary call SetLastError in case of failure */ + hModule = LOADLoadLibrary(lpstr, TRUE); + +done: + LOGEXIT("LoadLibraryExW returns HMODULE %p\n", hModule); + PERF_EXIT(LoadLibraryExW); + return hModule; +} + +/*++ +Function: + GetProcAddress + +See MSDN doc. +--*/ +FARPROC +PALAPI +GetProcAddress( + IN HMODULE hModule, + IN LPCSTR lpProcName) +{ + MODSTRUCT *module; + FARPROC ProcAddress = nullptr; + LPCSTR symbolName = lpProcName; + + PERF_ENTRY(GetProcAddress); + ENTRY("GetProcAddress (hModule=%p, lpProcName=%p (%s))\n", + hModule, lpProcName ? lpProcName : "NULL", lpProcName ? lpProcName : "NULL"); + + LockModuleList(); + + module = (MODSTRUCT *) hModule; + + /* try to assert on attempt to locate symbol by ordinal */ + /* this can't be an exact test for HIWORD((DWORD)lpProcName) == 0 + because of the address range reserved for ordinals contain can + be a valid string address on non-Windows systems + */ + if ((DWORD_PTR)lpProcName < GetVirtualPageSize()) + { + ASSERT("Attempt to locate symbol by ordinal?!\n"); + } + + /* parameter validation */ + + if ((lpProcName == nullptr) || (*lpProcName == '\0')) + { + TRACE("No function name given\n"); + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + + if (!LOADValidateModule(module)) + { + TRACE("Invalid module handle %p\n", hModule); + SetLastError(ERROR_INVALID_HANDLE); + goto done; + } + + // Get the symbol's address. + + // If we're looking for a symbol inside the PAL, we try the PAL_ variant + // first because otherwise we run the risk of having the non-PAL_ + // variant preferred over the PAL's implementation. + if (pal_module && module->dl_handle == pal_module->dl_handle) + { + int iLen = 4 + strlen(lpProcName) + 1; + LPSTR lpPALProcName = (LPSTR) alloca(iLen); + + if (strcpy_s(lpPALProcName, iLen, "PAL_") != SAFECRT_SUCCESS) + { + ERROR("strcpy_s failed!\n"); + SetLastError(ERROR_INSUFFICIENT_BUFFER); + goto done; + } + + if (strcat_s(lpPALProcName, iLen, lpProcName) != SAFECRT_SUCCESS) + { + ERROR("strcat_s failed!\n"); + SetLastError(ERROR_INSUFFICIENT_BUFFER); + goto done; + } + + ProcAddress = (FARPROC) dlsym(module->dl_handle, lpPALProcName); + symbolName = lpPALProcName; + } + + // If we aren't looking inside the PAL or we didn't find a PAL_ variant + // inside the PAL, fall back to a normal search. + if (ProcAddress == nullptr) + { + ProcAddress = (FARPROC) dlsym(module->dl_handle, lpProcName); + } + + if (ProcAddress) + { + TRACE("Symbol %s found at address %p in module %p (named %S)\n", + lpProcName, ProcAddress, module, MODNAME(module)); + + /* if we don't know the module's full name yet, this is our chance to obtain it */ + if (!module->lib_name && module->dl_handle) + { + const char* libName = PAL_dladdr((LPVOID)ProcAddress); + if (libName) + { + module->lib_name = UTIL_MBToWC_Alloc(libName, -1); + if (nullptr == module->lib_name) + { + ERROR("MBToWC failure; can't save module's full name\n"); + } + else + { + TRACE("Saving full path of module %p as %s\n", + module, libName); + } + } + } + } + else + { + TRACE("Symbol %s not found in module %p (named %S)\n", + lpProcName, module, MODNAME(module)); + SetLastError(ERROR_PROC_NOT_FOUND); + } +done: + UnlockModuleList(); + LOGEXIT("GetProcAddress returns FARPROC %p\n", ProcAddress); + PERF_EXIT(GetProcAddress); + return ProcAddress; +} + +/*++ +Function: + FreeLibrary + +See MSDN doc. +--*/ +BOOL +PALAPI +FreeLibrary( + IN OUT HMODULE hLibModule) +{ + BOOL retval = FALSE; + + PERF_ENTRY(FreeLibrary); + ENTRY("FreeLibrary (hLibModule=%p)\n", hLibModule); + + retval = LOADFreeLibrary((MODSTRUCT *)hLibModule, TRUE /* fCallDllMain */); + + LOGEXIT("FreeLibrary returns BOOL %d\n", retval); + PERF_EXIT(FreeLibrary); + return retval; +} + +/*++ +Function: + FreeLibraryAndExitThread + +See MSDN doc. + +--*/ +PALIMPORT +VOID +PALAPI +FreeLibraryAndExitThread( + IN HMODULE hLibModule, + IN DWORD dwExitCode) +{ + PERF_ENTRY(FreeLibraryAndExitThread); + ENTRY("FreeLibraryAndExitThread()\n"); + FreeLibrary(hLibModule); + ExitThread(dwExitCode); + LOGEXIT("FreeLibraryAndExitThread\n"); + PERF_EXIT(FreeLibraryAndExitThread); +} + +/*++ +Function: + GetModuleFileNameA + +See MSDN doc. + +Notes : + because of limitations in the dlopen() mechanism, this will only return the + full path name if a relative or absolute path was given to LoadLibrary, or + if the module was used in a GetProcAddress call. otherwise, this will return + the short name as given to LoadLibrary. The exception is if hModule is + NULL : in this case, the full path of the executable is always returned. +--*/ +DWORD +PALAPI +GetModuleFileNameA( + IN HMODULE hModule, + OUT LPSTR lpFileName, + IN DWORD nSize) +{ + INT name_length; + DWORD retval = 0; + LPWSTR wide_name = nullptr; + + PERF_ENTRY(GetModuleFileNameA); + ENTRY("GetModuleFileNameA (hModule=%p, lpFileName=%p, nSize=%u)\n", + hModule, lpFileName, nSize); + + LockModuleList(); + if (hModule && !LOADValidateModule((MODSTRUCT *)hModule)) + { + TRACE("Can't find name for invalid module handle %p\n", hModule); + SetLastError(ERROR_INVALID_HANDLE); + goto done; + } + wide_name = LOADGetModuleFileName((MODSTRUCT *)hModule); + + if (!wide_name) + { + ASSERT("Can't find name for valid module handle %p\n", hModule); + SetLastError(ERROR_INTERNAL_ERROR); + goto done; + } + + /* Convert module name to Ascii, place it in the supplied buffer */ + + name_length = WideCharToMultiByte(CP_ACP, 0, wide_name, -1, lpFileName, + nSize, nullptr, nullptr); + if (name_length == 0) + { + TRACE("Buffer too small to copy module's file name.\n"); + SetLastError(ERROR_INSUFFICIENT_BUFFER); + goto done; + } + + TRACE("File name of module %p is %s\n", hModule, lpFileName); + retval = name_length; +done: + UnlockModuleList(); + LOGEXIT("GetModuleFileNameA returns DWORD %d\n", retval); + PERF_EXIT(GetModuleFileNameA); + return retval; +} + +/*++ +Function: + GetModuleFileNameW + +See MSDN doc. + +Notes : + because of limitations in the dlopen() mechanism, this will only return the + full path name if a relative or absolute path was given to LoadLibrary, or + if the module was used in a GetProcAddress call. otherwise, this will return + the short name as given to LoadLibrary. The exception is if hModule is + NULL : in this case, the full path of the executable is always returned. +--*/ +DWORD +PALAPI +GetModuleFileNameW( + IN HMODULE hModule, + OUT LPWSTR lpFileName, + IN DWORD nSize) +{ + INT name_length; + DWORD retval = 0; + LPWSTR wide_name = nullptr; + + PERF_ENTRY(GetModuleFileNameW); + ENTRY("GetModuleFileNameW (hModule=%p, lpFileName=%p, nSize=%u)\n", + hModule, lpFileName, nSize); + + LockModuleList(); + + wcscpy_s(lpFileName, nSize, W("")); + + if (hModule && !LOADValidateModule((MODSTRUCT *)hModule)) + { + TRACE("Can't find name for invalid module handle %p\n", hModule); + SetLastError(ERROR_INVALID_HANDLE); + goto done; + } + wide_name = LOADGetModuleFileName((MODSTRUCT *)hModule); + + if (!wide_name) + { + TRACE("Can't find name for valid module handle %p\n", hModule); + SetLastError(ERROR_INTERNAL_ERROR); + goto done; + } + + /* Copy module name into supplied buffer */ + + name_length = PAL_wcslen(wide_name); + if (name_length >= (INT)nSize) + { + TRACE("Buffer too small (%u) to copy module's file name (%u).\n", nSize, name_length); + retval = (INT)nSize; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + goto done; + } + + wcscpy_s(lpFileName, nSize, wide_name); + + TRACE("file name of module %p is %S\n", hModule, lpFileName); + retval = (DWORD)name_length; +done: + UnlockModuleList(); + LOGEXIT("GetModuleFileNameW returns DWORD %u\n", retval); + PERF_EXIT(GetModuleFileNameW); + return retval; +} + +LPCSTR FixLibCName(LPCSTR shortAsciiName) +{ + // Check whether we have been requested to load 'libc'. If that's the case, then: + // * For Linux, use the full name of the library that is defined in by the + // LIBC_SO constant. The problem is that calling dlopen("libc.so") will fail for libc even + // though it works for other libraries. The reason is that libc.so is just linker script + // (i.e. a test file). + // As a result, we have to use the full name (i.e. lib.so.6) that is defined by LIBC_SO. + // * For macOS, use constant value absolute path "/usr/lib/libc.dylib". + // * For FreeBSD, use constant value "libc.so.7". + // * For rest of Unices, use constant value "libc.so". + if (strcmp(shortAsciiName, LIBC_NAME_WITHOUT_EXTENSION) == 0) + { +#if defined(__APPLE__) + return "/usr/lib/libc.dylib"; +#elif defined(__FreeBSD__) + return "libc.so.7"; +#elif defined(LIBC_SO) + return LIBC_SO; +#else + return "libc.so"; +#endif + } + + return shortAsciiName; +} + +/* +Function: + PAL_LoadLibraryDirect + + Loads a library using a system call, without registering the library with the module list. + + Returns the system handle to the loaded library, or nullptr upon failure (error is set via SetLastError()). +*/ +NATIVE_LIBRARY_HANDLE +PALAPI +PAL_LoadLibraryDirect( + IN LPCWSTR lpLibFileName) +{ + PathCharString pathstr; + CHAR * lpstr = nullptr; + LPCSTR lpcstr = nullptr; + INT name_length; + NATIVE_LIBRARY_HANDLE dl_handle = nullptr; + + PERF_ENTRY(LoadLibraryDirect); + ENTRY("LoadLibraryDirect (lpLibFileName=%p (%S)) \n", + lpLibFileName ? lpLibFileName : W16_NULLSTRING, + lpLibFileName ? lpLibFileName : W16_NULLSTRING); + + if (!LOADVerifyLibraryPath(lpLibFileName)) + { + goto done; + } + + lpstr = pathstr.OpenStringBuffer((PAL_wcslen(lpLibFileName)+1) * MaxWCharToAcpLength); + if (nullptr == lpstr) + { + goto done; + } + if (!LOADConvertLibraryPathWideStringToMultibyteString(lpLibFileName, lpstr, &name_length)) + { + goto done; + } + + /* do the Dos/Unix conversion on our own copy of the name */ + FILEDosToUnixPathA(lpstr); + pathstr.CloseBuffer(name_length); + lpcstr = FixLibCName(lpstr); + + dl_handle = LOADLoadLibraryDirect(lpcstr); + +done: + LOGEXIT("LoadLibraryDirect returns NATIVE_LIBRARY_HANDLE %p\n", dl_handle); + PERF_EXIT(LoadLibraryDirect); + return dl_handle; +} + +/* +Function: + PAL_FreeLibraryDirect + + Free a loaded library + + Returns true on success, false on failure. +*/ +BOOL +PALAPI +PAL_FreeLibraryDirect( + IN NATIVE_LIBRARY_HANDLE dl_handle) +{ + BOOL retValue = 0; + PERF_ENTRY(PAL_FreeLibraryDirect); + ENTRY("PAL_FreeLibraryDirect (dl_handle=%p) \n", dl_handle); + + retValue = dlclose(dl_handle) == 0; + + LOGEXIT("PAL_FreeLibraryDirect returns BOOL %p\n", retValue); + PERF_EXIT(PAL_FreeLibraryDirect); + return retValue; +} + +/* +Function: + PAL_GetProcAddressDirect + + Get the address corresponding to a symbol in a loaded native library. + + Returns the address of the sumbol loaded in memory. +*/ +FARPROC +PALAPI +PAL_GetProcAddressDirect( + IN NATIVE_LIBRARY_HANDLE dl_handle, + IN LPCSTR lpProcName) +{ + INT name_length; + FARPROC address = nullptr; + + PERF_ENTRY(PAL_GetProcAddressDirect); + ENTRY("PAL_GetProcAddressDirect (lpLibFileName=%p (%S)) \n", + lpProcName ? lpProcName : "NULL", + lpProcName ? lpProcName : "NULL"); + + address = (FARPROC) dlsym(dl_handle, lpProcName); + + LOGEXIT("PAL_GetProcAddressDirect returns FARPROC %p\n", address); + PERF_EXIT(PAL_GetProcAddressDirect); + return address; +} + +/*++ +Function: + PAL_RegisterModule + + Register the module with the target module and return a module handle in + the target module's context. Doesn't call the DllMain because it is used + as part of calling DllMain in the calling module. + +--*/ +HINSTANCE +PALAPI +PAL_RegisterModule( + IN LPCSTR lpLibFileName) +{ + HINSTANCE hinstance = nullptr; + + int err = PAL_InitializeDLL(); + if (err == 0) + { + PERF_ENTRY(PAL_RegisterModule); + ENTRY("PAL_RegisterModule(%s)\n", lpLibFileName ? lpLibFileName : ""); + + LockModuleList(); + + NATIVE_LIBRARY_HANDLE dl_handle = LOADLoadLibraryDirect(lpLibFileName); + if (dl_handle) + { + // This only creates/adds the module handle and doesn't call DllMain + hinstance = LOADAddModule(dl_handle, lpLibFileName); + } + + UnlockModuleList(); + + LOGEXIT("PAL_RegisterModule returns HINSTANCE %p\n", hinstance); + PERF_EXIT(PAL_RegisterModule); + } + + return hinstance; +} + +/*++ +Function: + PAL_UnregisterModule + + Used to cleanup the module HINSTANCE from PAL_RegisterModule. +--*/ +VOID +PALAPI +PAL_UnregisterModule( + IN HINSTANCE hInstance) +{ + PERF_ENTRY(PAL_UnregisterModule); + ENTRY("PAL_UnregisterModule(hInstance=%p)\n", hInstance); + + LOADFreeLibrary((MODSTRUCT *)hInstance, FALSE /* fCallDllMain */); + + LOGEXIT("PAL_UnregisterModule returns\n"); + PERF_EXIT(PAL_UnregisterModule); +} + +/*++ + PAL_LOADLoadPEFile + + Map a PE format file into memory like Windows LoadLibrary() would do. + Doesn't apply base relocations if the function is relocated. + +Parameters: + IN hFile - file to map + +Return value: + non-NULL - the base address of the mapped image + NULL - error, with last error set. +--*/ +PVOID +PALAPI +PAL_LOADLoadPEFile(HANDLE hFile) +{ + ENTRY("PAL_LOADLoadPEFile (hFile=%p)\n", hFile); + + void * loadedBase = MAPMapPEFile(hFile); + +#ifdef _DEBUG + if (loadedBase != nullptr) + { + char* envVar = EnvironGetenv("PAL_ForcePEMapFailure"); + if (envVar) + { + if (strlen(envVar) > 0) + { + TRACE("Forcing failure of PE file map, and retry\n"); + PAL_LOADUnloadPEFile(loadedBase); // unload it + loadedBase = MAPMapPEFile(hFile); // load it again + } + + free(envVar); + } + } +#endif // _DEBUG + + LOGEXIT("PAL_LOADLoadPEFile returns %p\n", loadedBase); + return loadedBase; +} + +/*++ + PAL_LOADUnloadPEFile + + Unload a PE file that was loaded by PAL_LOADLoadPEFile(). + +Parameters: + IN ptr - the file pointer returned by PAL_LOADLoadPEFile() + +Return value: + TRUE - success + FALSE - failure (incorrect ptr, etc.) +--*/ +BOOL +PALAPI +PAL_LOADUnloadPEFile(PVOID ptr) +{ + BOOL retval = FALSE; + + ENTRY("PAL_LOADUnloadPEFile (ptr=%p)\n", ptr); + + if (nullptr == ptr) + { + ERROR( "Invalid pointer value\n" ); + } + else + { + retval = MAPUnmapPEFile(ptr); + } + + LOGEXIT("PAL_LOADUnloadPEFile returns %d\n", retval); + return retval; +} + +/*++ + PAL_LOADMarkSectionAsNotNeeded + + Mark a section as NotNeeded that was loaded by PAL_LOADLoadPEFile(). + +Parameters: + IN ptr - the section address mapped by PAL_LOADLoadPEFile() + +Return value: + TRUE - success + FALSE - failure (incorrect ptr, etc.) +--*/ +BOOL +PALAPI +PAL_LOADMarkSectionAsNotNeeded(void * ptr) +{ + BOOL retval = FALSE; + + ENTRY("PAL_LOADMarkSectionAsNotNeeded (ptr=%p)\n", ptr); + + if (nullptr == ptr) + { + ERROR( "Invalid pointer value\n" ); + } + else + { + retval = MAPMarkSectionAsNotNeeded(ptr); + } + + LOGEXIT("PAL_LOADMarkSectionAsNotNeeded returns %d\n", retval); + return retval; +} + +/*++ + PAL_GetSymbolModuleBase + + Get base address of the module containing a given symbol + +Parameters: + void *symbol - address of symbol + +Return value: + module base address +--*/ +LPCVOID +PALAPI +PAL_GetSymbolModuleBase(PVOID symbol) +{ + LPCVOID retval = nullptr; + + PERF_ENTRY(PAL_GetPalModuleBase); + ENTRY("PAL_GetPalModuleBase\n"); + + if (symbol == nullptr) + { + TRACE("Can't get base address. Argument symbol == nullptr\n"); + SetLastError(ERROR_INVALID_DATA); + } + else + { + Dl_info info; + if (dladdr(symbol, &info) != 0) + { + retval = info.dli_fbase; + } + else + { + TRACE("Can't get base address of the current module\n"); + SetLastError(ERROR_INVALID_DATA); + } + } + + LOGEXIT("PAL_GetPalModuleBase returns %p\n", retval); + PERF_EXIT(PAL_GetPalModuleBase); + return retval; +} + +/*++ + PAL_GetLoadLibraryError + + Wrapper for dlerror() to be used by PAL functions + +Return value: + +A LPCSTR containing the output of dlerror() + +--*/ +PALIMPORT +LPCSTR +PALAPI +PAL_GetLoadLibraryError() +{ + + PERF_ENTRY(PAL_GetLoadLibraryError); + ENTRY("PAL_GetLoadLibraryError"); + + LPCSTR last_error = dlerror(); + + LOGEXIT("PAL_GetLoadLibraryError returns %p\n", last_error); + PERF_EXIT(PAL_GetLoadLibraryError); + return last_error; +} + + +/* Internal PAL functions *****************************************************/ + +/*++ +Function : + LOADInitializeModules + + Initialize the process-wide list of modules + +Parameters : + None + +Return value : + TRUE if initialization succeedded + FALSE otherwise + +--*/ +extern "C" +BOOL LOADInitializeModules() +{ + _ASSERTE(exe_module.prev == nullptr); + + InternalInitializeCriticalSection(&module_critsec); + + // Initialize module for main executable + TRACE("Initializing module for main executable\n"); + + exe_module.self = (HMODULE)&exe_module; + exe_module.dl_handle = dlopen(nullptr, RTLD_LAZY); + if (exe_module.dl_handle == nullptr) + { + ERROR("Executable module will be broken : dlopen(nullptr) failed\n"); + return FALSE; + } + exe_module.lib_name = nullptr; + exe_module.refcount = -1; + exe_module.next = &exe_module; + exe_module.prev = &exe_module; + exe_module.pDllMain = (PDLLMAIN)dlsym(exe_module.dl_handle, "DllMain"); + exe_module.hinstance = (HINSTANCE)&exe_module; + exe_module.threadLibCalls = TRUE; + return TRUE; +} + +/*++ +Function : + LOADSetExeName + + Set the exe name path + +Parameters : + LPWSTR man exe path and name + +Return value : + TRUE if initialization succeedded + FALSE otherwise + +--*/ +extern "C" +BOOL LOADSetExeName(LPWSTR name) +{ +#if RETURNS_NEW_HANDLES_ON_REPEAT_DLOPEN + LPSTR pszExeName = nullptr; +#endif + BOOL result = FALSE; + + LockModuleList(); + + // Save the exe path in the exe module struct + free(exe_module.lib_name); + exe_module.lib_name = name; + + // For platforms where we can't trust the handle to be constant, we need to + // store the inode/device pairs for the modules we just initialized. +#if RETURNS_NEW_HANDLES_ON_REPEAT_DLOPEN + { + struct stat stat_buf; + pszExeName = UTIL_WCToMB_Alloc(name, -1); + if (nullptr == pszExeName) + { + ERROR("WCToMB failure, unable to get full name of exe\n"); + goto exit; + } + if (-1 == stat(pszExeName, &stat_buf)) + { + SetLastError(ERROR_MOD_NOT_FOUND); + goto exit; + } + TRACE("Executable has inode %d and device %d\n", stat_buf.st_ino, stat_buf.st_dev); + + exe_module.inode = stat_buf.st_ino; + exe_module.device = stat_buf.st_dev; + } +#endif + result = TRUE; + +#if RETURNS_NEW_HANDLES_ON_REPEAT_DLOPEN +exit: + if (pszExeName) + { + free(pszExeName); + } +#endif + UnlockModuleList(); + return result; +} + +/*++ +Function : + LOADCallDllMain + + Call DllMain for all modules (that have one) with the given "fwReason" + +Parameters : + DWORD dwReason : parameter to pass down to DllMain, one of DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH, + DLL_THREAD_ATTACH, DLL_THREAD_DETACH + + LPVOID lpReserved : parameter to pass down to DllMain + If dwReason is DLL_PROCESS_ATTACH, lpvReserved is NULL for dynamic loads and non-NULL for static loads. + If dwReason is DLL_PROCESS_DETACH, lpvReserved is NULL if DllMain has been called by using FreeLibrary + and non-NULL if DllMain has been called during process termination. + +(no return value) + +Notes : + This is used to send DLL_THREAD_*TACH messages to modules +--*/ +extern "C" +void LOADCallDllMain(DWORD dwReason, LPVOID lpReserved) +{ + MODSTRUCT *module = nullptr; + BOOL InLoadOrder = TRUE; /* true if in load order, false for reverse */ + CPalThread *pThread; + + pThread = InternalGetCurrentThread(); + if (UserCreatedThread != pThread->GetThreadType()) + { + return; + } + + /* Validate dwReason */ + switch(dwReason) + { + case DLL_PROCESS_ATTACH: + ASSERT("got called with DLL_PROCESS_ATTACH parameter! Why?\n"); + break; + case DLL_PROCESS_DETACH: + ASSERT("got called with DLL_PROCESS_DETACH parameter! Why?\n"); + InLoadOrder = FALSE; + break; + case DLL_THREAD_ATTACH: + TRACE("Calling DllMain(DLL_THREAD_ATTACH) on all known modules.\n"); + break; + case DLL_THREAD_DETACH: + TRACE("Calling DllMain(DLL_THREAD_DETACH) on all known modules.\n"); + InLoadOrder = FALSE; + break; + default: + ASSERT("LOADCallDllMain called with unknown parameter %d!\n", dwReason); + return; + } + + LockModuleList(); + + module = &exe_module; + + do + { + if (!InLoadOrder) + module = module->prev; + + if (module->threadLibCalls) + { + if (module->pDllMain) + { + LOADCallDllMainSafe(module, dwReason, lpReserved); + } + } + + if (InLoadOrder) + module = module->next; + + } while (module != &exe_module); + + UnlockModuleList(); +} + +/*++ +Function: + LOADFreeLibrary + +Parameters: + MODSTRUCT * module - module to free + BOOL fCallDllMain - if TRUE, call the DllMain function + +Returns: + TRUE if successful + +--*/ +static BOOL LOADFreeLibrary(MODSTRUCT *module, BOOL fCallDllMain) +{ + BOOL retval = FALSE; + + LockModuleList(); + + if (terminator) + { + /* PAL shutdown is in progress - ignore FreeLibrary calls */ + retval = TRUE; + goto done; + } + + if (!LOADValidateModule(module)) + { + TRACE("Can't free invalid module %p\n", module); + SetLastError(ERROR_INVALID_HANDLE); + goto done; + } + + if (module->refcount == -1) + { + /* special module - never released */ + retval = TRUE; + goto done; + } + + module->refcount--; + TRACE("Reference count for module %p (named %S) decreases to %d\n", + module, MODNAME(module), module->refcount); + + if (module->refcount != 0) + { + retval = TRUE; + goto done; + } + + /* Releasing the last reference : call dlclose(), remove module from the + process-wide module list */ + + TRACE("Reference count for module %p (named %S) now 0; destroying module structure\n", + module, MODNAME(module)); + + /* unlink the module structure from the list */ + module->prev->next = module->next; + module->next->prev = module->prev; + + /* remove the circular reference so that LOADValidateModule will fail */ + module->self = nullptr; + + /* Call DllMain if the module contains one */ + if (fCallDllMain && module->pDllMain) + { + LOADCallDllMainSafe(module, DLL_PROCESS_DETACH, nullptr); + } + + if (module->hinstance) + { + PUNREGISTER_MODULE unregisterModule = (PUNREGISTER_MODULE)dlsym(module->dl_handle, "PAL_UnregisterModule"); + if (unregisterModule != nullptr) + { + unregisterModule(module->hinstance); + } + module->hinstance = nullptr; + } + + if (module->dl_handle && 0 != dlclose(module->dl_handle)) + { + /* report dlclose() failure, but proceed anyway. */ + WARN("dlclose() call failed!\n"); + } + + /* release all memory */ + free(module->lib_name); + free(module); + + retval = TRUE; + +done: + UnlockModuleList(); + return retval; +} + +/*++ +Function : + LOADCallDllMainSafe + + Exception-safe call to DllMain. + +Parameters : + MODSTRUCT *module : module whose DllMain must be called + + DWORD dwReason : parameter to pass down to DllMain, one of DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH, + DLL_THREAD_ATTACH, DLL_THREAD_DETACH + + LPVOID lpvReserved : parameter to pass down to DllMain, + If dwReason is DLL_PROCESS_ATTACH, lpvReserved is NULL for dynamic loads and non-NULL for static loads. + If dwReason is DLL_PROCESS_DETACH, lpvReserved is NULL if DllMain has been called by using FreeLibrary + and non-NULL if DllMain has been called during process termination. + +Returns: + BOOL : DllMain's return value +*/ +static BOOL LOADCallDllMainSafe(MODSTRUCT *module, DWORD dwReason, LPVOID lpReserved) +{ +#if _ENABLE_DEBUG_MESSAGES_ + /* reset ENTRY nesting level back to zero while inside the callback... */ + int old_level = DBG_change_entrylevel(0); +#endif /* _ENABLE_DEBUG_MESSAGES_ */ + + struct Param + { + MODSTRUCT *module; + DWORD dwReason; + LPVOID lpReserved; + BOOL ret; + } param; + param.module = module; + param.dwReason = dwReason; + param.lpReserved = lpReserved; + param.ret = FALSE; + + PAL_TRY(Param *, pParam, ¶m) + { + TRACE("Calling DllMain (%p) for module %S\n", + pParam->module->pDllMain, + pParam->module->lib_name ? pParam->module->lib_name : W16_NULLSTRING); + + pParam->ret = pParam->module->pDllMain(pParam->module->hinstance, pParam->dwReason, pParam->lpReserved); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + WARN("Call to DllMain (%p) got an unhandled exception; ignoring.\n", module->pDllMain); + } + PAL_ENDTRY + +#if _ENABLE_DEBUG_MESSAGES_ + /* ...and set nesting level back to what it was */ + DBG_change_entrylevel(old_level); +#endif /* _ENABLE_DEBUG_MESSAGES_ */ + + return param.ret; +} + +/*++ +Function: + DisableThreadLibraryCalls + +See MSDN doc. +--*/ +BOOL +PALAPI +DisableThreadLibraryCalls( + IN HMODULE hLibModule) +{ + BOOL ret = FALSE; + MODSTRUCT *module; + PERF_ENTRY(DisableThreadLibraryCalls); + ENTRY("DisableThreadLibraryCalls(hLibModule=%p)\n", hLibModule); + + LockModuleList(); + + if (terminator) + { + /* PAL shutdown in progress - ignore DisableThreadLibraryCalls */ + ret = TRUE; + goto done; + } + + module = (MODSTRUCT *) hLibModule; + + if (!LOADValidateModule(module)) + { + // DisableThreadLibraryCalls() does nothing when given + // an invalid module handle. This matches the Windows + // behavior, though it is counter to MSDN. + WARN("Invalid module handle %p\n", hLibModule); + ret = TRUE; + goto done; + } + + module->threadLibCalls = FALSE; + ret = TRUE; + +done: + UnlockModuleList(); + LOGEXIT("DisableThreadLibraryCalls returns BOOL %d\n", ret); + PERF_EXIT(DisableThreadLibraryCalls); + return ret; +} + +// Checks the library path for null or empty string. On error, calls SetLastError() and returns false. +template +static bool LOADVerifyLibraryPath(const TChar *libraryPath) +{ + if (libraryPath == nullptr) + { + ERROR("libraryPath is null\n"); + SetLastError(ERROR_MOD_NOT_FOUND); + return false; + } + if (libraryPath[0] == '\0') + { + ERROR("libraryPath is empty\n"); + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + return true; +} + +// Converts the wide char library path string into a multibyte-char string. On error, calls SetLastError() and returns false. +static bool LOADConvertLibraryPathWideStringToMultibyteString( + LPCWSTR wideLibraryPath, + LPSTR multibyteLibraryPath, + INT *multibyteLibraryPathLengthRef) +{ + _ASSERTE(multibyteLibraryPathLengthRef != nullptr); + _ASSERTE(wideLibraryPath != nullptr); + + size_t length = (PAL_wcslen(wideLibraryPath)+1) * MaxWCharToAcpLength; + *multibyteLibraryPathLengthRef = WideCharToMultiByte(CP_ACP, 0, wideLibraryPath, -1, multibyteLibraryPath, + length, nullptr, nullptr); + + if (*multibyteLibraryPathLengthRef == 0) + { + DWORD dwLastError = GetLastError(); + + ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); + + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + return true; +} + +/*++ +Function : + LOADValidateModule + + Check whether the given MODSTRUCT pointer is valid + +Parameters : + MODSTRUCT *module : module to check + +Return value : + TRUE if module is valid, FALSE otherwise + +NOTE : + The module lock MUST be owned. + +--*/ +static BOOL LOADValidateModule(MODSTRUCT *module) +{ + MODSTRUCT *modlist_enum = &exe_module; + + /* enumerate through the list of modules to make sure the given handle is + really a module (HMODULEs are actually MODSTRUCT pointers) */ + do + { + if (module == modlist_enum) + { + /* found it; check its integrity to be on the safe side */ + if (module->self != module) + { + ERROR("Found corrupt module %p!\n",module); + return FALSE; + } + TRACE("Module %p is valid (name : %S)\n", module, MODNAME(module)); + return TRUE; + } + modlist_enum = modlist_enum->next; + } + while (modlist_enum != &exe_module); + + TRACE("Module %p is NOT valid.\n", module); + return FALSE; +} + +/*++ +Function : + LOADGetModuleFileName [internal] + + Retrieve the module's full path if it is known, the short name given to + LoadLibrary otherwise. + +Parameters : + MODSTRUCT *module : module to check + +Return value : + pointer to internal buffer with name of module (Unicode) + +Notes : + this function assumes that the module critical section is held, and that + the module has already been validated. +--*/ +static LPWSTR LOADGetModuleFileName(MODSTRUCT *module) +{ + LPWSTR module_name; + /* special case : if module is NULL, we want the name of the executable */ + if (!module) + { + module_name = exe_module.lib_name; + TRACE("Returning name of main executable\n"); + return module_name; + } + + /* return "real" name of module if it is known. we have this if LoadLibrary + was given an absolute or relative path; we can also determine it at the + first GetProcAddress call. */ + TRACE("Returning full path name of module\n"); + return module->lib_name; +} + +/* +Function: + LOADLoadLibraryDirect [internal] + + Loads a library using a system call, without registering the library with the module list. + +Parameters: + LPCSTR libraryNameOrPath: The library to load. + +Return value: + System handle to the loaded library, or nullptr upon failure (error is set via SetLastError()). +*/ +static NATIVE_LIBRARY_HANDLE LOADLoadLibraryDirect(LPCSTR libraryNameOrPath) +{ + _ASSERTE(libraryNameOrPath != nullptr); + _ASSERTE(libraryNameOrPath[0] != '\0'); + + NATIVE_LIBRARY_HANDLE dl_handle = dlopen(libraryNameOrPath, RTLD_LAZY); + if (dl_handle == nullptr) + { + SetLastError(ERROR_MOD_NOT_FOUND); + } + else + { + TRACE("dlopen() found module %s\n", libraryNameOrPath); + } + + return dl_handle; +} + +/*++ +Function : + LOADAllocModule + + Allocate and initialize a new MODSTRUCT structure + +Parameters : + NATIVE_LIBRARY_HANDLE dl_handle : handle returned by dl_open, goes in MODSTRUCT::dl_handle + + char *name : name of new module. after conversion to widechar, + goes in MODSTRUCT::lib_name + +Return value: + a pointer to a new, initialized MODSTRUCT strucutre, or NULL on failure. + +Notes : + 'name' is used to initialize MODSTRUCT::lib_name. The other member is set to NULL + In case of failure (in malloc or MBToWC), this function sets LastError. +--*/ +static MODSTRUCT *LOADAllocModule(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR name) +{ + MODSTRUCT *module; + LPWSTR wide_name; + + /* no match found : try to create a new module structure */ + module = (MODSTRUCT *)InternalMalloc(sizeof(MODSTRUCT)); + if (nullptr == module) + { + ERROR("malloc() failed! errno is %d (%s)\n", errno, strerror(errno)); + return nullptr; + } + + wide_name = UTIL_MBToWC_Alloc(name, -1); + if (nullptr == wide_name) + { + ERROR("couldn't convert name to a wide-character string\n"); + free(module); + return nullptr; + } + + module->dl_handle = dl_handle; + module->refcount = 1; + module->self = module; + module->hinstance = nullptr; + module->threadLibCalls = TRUE; + module->pDllMain = nullptr; + module->next = nullptr; + module->prev = nullptr; + + module->lib_name = wide_name; + + return module; +} + +/* +Function: + LOADAddModule [internal] + + Registers a system handle to a loaded library with the module list. + +Parameters: + NATIVE_LIBRARY_HANDLE dl_handle: System handle to the loaded library. + LPCSTR libraryNameOrPath: The library that was loaded. + +Return value: + PAL handle to the loaded library, or nullptr upon failure (error is set via SetLastError()). +*/ +static MODSTRUCT *LOADAddModule(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR libraryNameOrPath) +{ + _ASSERTE(dl_handle != nullptr); + _ASSERTE(libraryNameOrPath != nullptr); + _ASSERTE(libraryNameOrPath[0] != '\0'); + +#if !RETURNS_NEW_HANDLES_ON_REPEAT_DLOPEN + /* search module list for a match. */ + MODSTRUCT *module = &exe_module; + do + { + if (dl_handle == module->dl_handle) + { + /* found the handle. increment the refcount and return the + existing module structure */ + TRACE("Found matching module %p for module name %s\n", module, libraryNameOrPath); + + if (module->refcount != -1) + { + module->refcount++; + } + dlclose(dl_handle); + return module; + } + module = module->next; + + } while (module != &exe_module); +#endif + + TRACE("Module doesn't exist : creating %s.\n", libraryNameOrPath); + + module = LOADAllocModule(dl_handle, libraryNameOrPath); + if (nullptr == module) + { + ERROR("couldn't create new module\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + dlclose(dl_handle); + return nullptr; + } + + /* We now get the address of DllMain if the module contains one. */ + module->pDllMain = (PDLLMAIN)dlsym(module->dl_handle, "DllMain"); + + /* Add the new module on to the end of the list */ + module->prev = exe_module.prev; + module->next = &exe_module; + exe_module.prev->next = module; + exe_module.prev = module; + +#if RETURNS_NEW_HANDLES_ON_REPEAT_DLOPEN + module->inode = stat_buf.st_ino; + module->device = stat_buf.st_dev; +#endif + + return module; +} + +/* +Function: + LOADRegisterLibraryDirect [internal] + + Registers a system handle to a loaded library with the module list. + +Parameters: + NATIVE_LIBRARY_HANDLE dl_handle: System handle to the loaded library. + LPCSTR libraryNameOrPath: The library that was loaded. + BOOL fDynamic: TRUE if dynamic load through LoadLibrary, FALSE if static load through RegisterLibrary. + +Return value: + PAL handle to the loaded library, or nullptr upon failure (error is set via SetLastError()). +*/ +static HMODULE LOADRegisterLibraryDirect(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR libraryNameOrPath, BOOL fDynamic) +{ + MODSTRUCT *module = LOADAddModule(dl_handle, libraryNameOrPath); + if (module == nullptr) + { + return nullptr; + } + + /* If the module contains a DllMain, call it. */ + if (module->pDllMain) + { + TRACE("Calling DllMain (%p) for module %S\n", + module->pDllMain, + module->lib_name ? module->lib_name : W16_NULLSTRING); + + if (nullptr == module->hinstance) + { + PREGISTER_MODULE registerModule = (PREGISTER_MODULE)dlsym(module->dl_handle, "PAL_RegisterModule"); + if (registerModule != nullptr) + { + module->hinstance = registerModule(libraryNameOrPath); + } + else + { + // If the target module doesn't have the PAL_RegisterModule export, then use this PAL's + // module handle assuming that the target module is referencing this PAL's exported + // functions on said handle. + module->hinstance = (HINSTANCE)module; + } + } + + BOOL dllMainRetVal = LOADCallDllMainSafe(module, DLL_PROCESS_ATTACH, fDynamic ? nullptr : (LPVOID)-1); + + // If DlMain(DLL_PROCESS_ATTACH) returns FALSE, we must immediately unload the module + if (!dllMainRetVal) + { + ERROR("DllMain returned FALSE; unloading module.\n"); + module->pDllMain = nullptr; + FreeLibrary((HMODULE)module); + SetLastError(ERROR_DLL_INIT_FAILED); + module = nullptr; + } + } + else + { + TRACE("Module does not contain a DllMain function.\n"); + } + + return module; +} + +/*++ +Function : + LOADLoadLibrary [internal] + + implementation of LoadLibrary (for use by the A/W variants) + +Parameters : + LPSTR shortAsciiName : name of module as specified to LoadLibrary + + BOOL fDynamic : TRUE if dynamic load through LoadLibrary, FALSE if static load through RegisterLibrary + +Return value : + handle to loaded module + +--*/ +static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic) +{ + HMODULE module = nullptr; + NATIVE_LIBRARY_HANDLE dl_handle = nullptr; + + shortAsciiName = FixLibCName(shortAsciiName); + + LockModuleList(); + + dl_handle = LOADLoadLibraryDirect(shortAsciiName); + if (dl_handle) + { + module = LOADRegisterLibraryDirect(dl_handle, shortAsciiName, fDynamic); + } + + UnlockModuleList(); + + return module; +} + +/*++ + LOADInitializeCoreCLRModule + + Run the initialization methods for CoreCLR module (the module containing this PAL). + +Parameters: + None + +Return value: + TRUE if successful + FALSE if failure +--*/ +BOOL LOADInitializeCoreCLRModule() +{ + MODSTRUCT *module = LOADGetPalLibrary(); + if (!module) + { + ERROR("Can not load the PAL module\n"); + return FALSE; + } + return TRUE; +} + +/*++ +Function : + LOADGetPalLibrary + + Load and initialize the PAL module. + +Parameters : + None + +Return value : + pointer to module struct + +--*/ +MODSTRUCT *LOADGetPalLibrary() +{ + if (pal_module == nullptr) + { + // Initialize the pal module (the module containing LOADGetPalLibrary). Assumes that + // the PAL is linked into the coreclr module because we use the module name containing + // this function for the coreclr path. + TRACE("Loading module for PAL library\n"); + + Dl_info info; + if (dladdr((PVOID)&LOADGetPalLibrary, &info) == 0) + { + ERROR("LOADGetPalLibrary: dladdr() failed.\n"); + goto exit; + } + // Stash a copy of the CoreCLR installation path in a global variable. + // Make sure it's terminated with a slash. + if (g_szCoreCLRPath == nullptr) + { + size_t cbszCoreCLRPath = strlen(info.dli_fname) + 1; + g_szCoreCLRPath = (char*) InternalMalloc(cbszCoreCLRPath); + + if (g_szCoreCLRPath == nullptr) + { + ERROR("LOADGetPalLibrary: InternalMalloc failed!"); + goto exit; + } + + if (strcpy_s(g_szCoreCLRPath, cbszCoreCLRPath, info.dli_fname) != SAFECRT_SUCCESS) + { + ERROR("LOADGetPalLibrary: strcpy_s failed!"); + goto exit; + } + } + + pal_module = (MODSTRUCT *)LOADLoadLibrary(info.dli_fname, FALSE); + } + +exit: + return pal_module; +} + +/*++ +Function: + LockModuleList + +Abstract + Enter the critical section associated to the module list + +Parameter + void + +Return + void +--*/ +extern "C" +void LockModuleList() +{ + CPalThread * pThread = + (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : nullptr); + + InternalEnterCriticalSection(pThread, &module_critsec); +} + +/*++ +Function: + UnlockModuleList + +Abstract + Leave the critical section associated to the module list + +Parameter + void + +Return + void +--*/ +extern "C" +void UnlockModuleList() +{ + CPalThread * pThread = + (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : nullptr); + + InternalLeaveCriticalSection(pThread, &module_critsec); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/loader/modulename.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/loader/modulename.cpp new file mode 100644 index 0000000..92f23cd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/loader/modulename.cpp @@ -0,0 +1,69 @@ +// 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: + + modulename.cpp + +Abstract: + + Implementation of internal functions to get module names + + + +--*/ + +#include "pal/thread.hpp" +#include "pal/malloc.hpp" +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/modulename.h" + +#include + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(LOADER); + +/*++ + PAL_dladdr + + Internal wrapper for dladder used only to get module name + +Parameters: + LPVOID ProcAddress: a pointer to a function in a shared library + +Return value: + Pointer to string with the fullpath to the shared library containing + ProcAddress. + + NULL if error occurred. + +Notes: + The string returned by this function is owned by the OS. + If you need to keep it, strdup() it, because it is unknown how long + this ptr will point at the string you want (over the lifetime of + the system running) It is only safe to use it immediately after calling + this function. +--*/ +const char *PAL_dladdr(LPVOID ProcAddress) +{ + Dl_info dl_info; + if (!dladdr(ProcAddress, &dl_info)) + { + WARN("dladdr() call failed!\n"); + /* If we get an error, return NULL */ + return (NULL); + } + else + { + /* Return the module name */ + return dl_info.dli_fname; + } +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/unicode.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/unicode.cpp new file mode 100644 index 0000000..cca7723 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/unicode.cpp @@ -0,0 +1,495 @@ +// 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: + +unicode.cpp + +Abstract: + +Implementation of all functions related to Unicode support + +Revision History: + + + +--*/ + +#include "pal/thread.hpp" + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/file.h" +#include "pal/utf8.h" +#include "pal/cruntime.h" +#include "pal/stackstring.hpp" +#include "pal/unicodedata.h" + +#include +#include +#include + +#include + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(UNICODE); + +/*++ +Function: +UnicodeDataComp +This is the comparison function used by the bsearch function to search +for unicode characters in the UnicodeData array. + +Parameter: +pnKey +The unicode character value to search for. +elem +A pointer to a UnicodeDataRec. + +Return value: +<0 if pnKey < elem->nUnicodeValue +0 if pnKey == elem->nUnicodeValue +>0 if pnKey > elem->nUnicodeValue +--*/ +static int UnicodeDataComp(const void *pnKey, const void *elem) +{ + WCHAR uValue = ((UnicodeDataRec*)elem)->nUnicodeValue; + + if (*((INT*)pnKey) < uValue) + { + return -1; + } + else if (*((INT*)pnKey) > uValue) + { + return 1; + } + else + { + return 0; + } +} + +/*++ +Function: +GetUnicodeData +This function is used to get information about a Unicode character. + +Parameters: +nUnicodeValue +The numeric value of the Unicode character to get information about. +pDataRec +The UnicodeDataRec to fill in with the data for the Unicode character. + +Return value: +TRUE if the Unicode character was found. + +--*/ +BOOL GetUnicodeData(INT nUnicodeValue, UnicodeDataRec *pDataRec) +{ + BOOL bRet; + + UnicodeDataRec *dataRec; + INT nNumOfChars = UNICODE_DATA_SIZE; + dataRec = (UnicodeDataRec *) bsearch(&nUnicodeValue, UnicodeData, nNumOfChars, + sizeof(UnicodeDataRec), UnicodeDataComp); + if (dataRec == NULL) + { + bRet = FALSE; + } + else + { + bRet = TRUE; + *pDataRec = *dataRec; + } + return bRet; +} + +wchar_16 +__cdecl +PAL_ToUpperInvariant( wchar_16 c ) +{ + UnicodeDataRec dataRec; + + PERF_ENTRY(PAL_ToUpperInvariant); + ENTRY("PAL_ToUpperInvariant (c=%d)\n", c); + + if (!GetUnicodeData(c, &dataRec)) + { + TRACE( "Unable to retrieve unicode data for the character %c.\n", c ); + LOGEXIT("PAL_ToUpperInvariant returns int %d\n", c ); + PERF_EXIT(PAL_ToUpperInvariant); + return c; + } + + if ( dataRec.nFlag != LOWER_CASE ) + { + LOGEXIT("PAL_ToUpperInvariant returns int %d\n", c ); + PERF_EXIT(PAL_ToUpperInvariant); + return c; + } + else + { + LOGEXIT("PAL_ToUpperInvariant returns int %d\n", dataRec.nOpposingCase ); + PERF_EXIT(PAL_ToUpperInvariant); + return dataRec.nOpposingCase; + } +} + +wchar_16 +__cdecl +PAL_ToLowerInvariant( wchar_16 c ) +{ + UnicodeDataRec dataRec; + + PERF_ENTRY(PAL_ToLowerInvariant); + ENTRY("PAL_ToLowerInvariant (c=%d)\n", c); + + if (!GetUnicodeData(c, &dataRec)) + { + TRACE( "Unable to retrieve unicode data for the character %c.\n", c ); + LOGEXIT("PAL_ToLowerInvariant returns int %d\n", c ); + PERF_EXIT(PAL_ToLowerInvariant); + return c; + } + + if ( dataRec.nFlag != UPPER_CASE ) + { + LOGEXIT("PAL_ToLowerInvariant returns int %d\n", c ); + PERF_EXIT(PAL_ToLowerInvariant); + return c; + } + else + { + LOGEXIT("PAL_ToLowerInvariant returns int %d\n", dataRec.nOpposingCase ); + PERF_EXIT(PAL_ToLowerInvariant); + return dataRec.nOpposingCase; + } +} + +/*++ +Function: +GetConsoleOutputCP + +See MSDN doc. +--*/ +UINT +PALAPI +GetConsoleOutputCP( + VOID) +{ + UINT nRet = 0; + PERF_ENTRY(GetConsoleOutputCP); + ENTRY("GetConsoleOutputCP()\n"); + nRet = GetACP(); + LOGEXIT("GetConsoleOutputCP returns UINT %d \n", nRet ); + PERF_EXIT(GetConsoleOutputCP); + return nRet; +} + +/*++ +Function: +GetCPInfo + +See MSDN doc. +--*/ +BOOL +PALAPI +GetCPInfo( + IN UINT CodePage, + OUT LPCPINFO lpCPInfo) +{ + BOOL bRet = FALSE; + + PERF_ENTRY(GetCPInfo); + ENTRY("GetCPInfo(CodePage=%hu, lpCPInfo=%p)\n", CodePage, lpCPInfo); + + /*check if the input code page is valid*/ + if( CP_ACP != CodePage && CP_UTF8 != CodePage ) + { + /* error, invalid argument */ + ERROR("CodePage(%d) parameter is invalid\n",CodePage); + SetLastError( ERROR_INVALID_PARAMETER ); + goto done; + } + + /*check if the lpCPInfo parameter is valid. */ + if( !lpCPInfo ) + { + /* error, invalid argument */ + ERROR("lpCPInfo cannot be NULL\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + goto done; + } + + lpCPInfo->MaxCharSize = 4; + memset( lpCPInfo->LeadByte, 0, MAX_LEADBYTES ); + + /* Don't need to be set, according to the spec. */ + memset( lpCPInfo->DefaultChar, '?', MAX_DEFAULTCHAR ); + + bRet = TRUE; + +done: + LOGEXIT("GetCPInfo returns BOOL %d \n",bRet); + PERF_EXIT(GetCPInfo); + return bRet; +} + + +/*++ +Function: +GetACP + +See MSDN doc. +--*/ +UINT +PALAPI +GetACP(VOID) +{ + PERF_ENTRY(GetACP); + ENTRY("GetACP(VOID)\n"); + + LOGEXIT("GetACP returning UINT %d\n", CP_UTF8); + PERF_EXIT(GetACP); + + return CP_UTF8; +} + + +/*++ +Function: +IsDBCSLeadByteEx + +See MSDN doc. +--*/ +BOOL +PALAPI +IsDBCSLeadByteEx( + IN UINT CodePage, + IN BYTE TestChar) +{ + CPINFO cpinfo; + SIZE_T i; + BOOL bRet = FALSE; + + PERF_ENTRY(IsDBCSLeadByteEx); + ENTRY("IsDBCSLeadByteEx(CodePage=%#x, TestChar=%d)\n", CodePage, TestChar); + + /* Get the lead byte info with respect to the given codepage*/ + if( !GetCPInfo( CodePage, &cpinfo ) ) + { + ERROR("Error CodePage(%#x) parameter is invalid\n", CodePage ); + SetLastError( ERROR_INVALID_PARAMETER ); + goto done; + } + + for( i=0; i < sizeof(cpinfo.LeadByte)/sizeof(cpinfo.LeadByte[0]); i += 2 ) + { + if( 0 == cpinfo.LeadByte[ i ] ) + { + goto done; + } + + /*check if the given char is in one of the lead byte ranges*/ + if( cpinfo.LeadByte[i] <= TestChar && TestChar<= cpinfo.LeadByte[i+1] ) + { + bRet = TRUE; + goto done; + } + } +done: + LOGEXIT("IsDBCSLeadByteEx returns BOOL %d\n",bRet); + PERF_EXIT(IsDBCSLeadByteEx); + return bRet; +} + +/*++ +Function: +IsDBCSLeadByte + +See MSDN doc. +--*/ +BOOL +PALAPI +IsDBCSLeadByte( + IN BYTE TestChar) +{ + // UNIXTODO: Implement this! + ERROR("Needs Implementation!!!"); + return FALSE; +} + +/*++ +Function: +MultiByteToWideChar + +See MSDN doc. + +--*/ +int +PALAPI +MultiByteToWideChar( + IN UINT CodePage, + IN DWORD dwFlags, + IN LPCSTR lpMultiByteStr, + IN int cbMultiByte, + OUT LPWSTR lpWideCharStr, + IN int cchWideChar) +{ + INT retval =0; + + PERF_ENTRY(MultiByteToWideChar); + ENTRY("MultiByteToWideChar(CodePage=%u, dwFlags=%#x, lpMultiByteStr=%p (%s)," + " cbMultiByte=%d, lpWideCharStr=%p, cchWideChar=%d)\n", + CodePage, dwFlags, lpMultiByteStr?lpMultiByteStr:"NULL", lpMultiByteStr?lpMultiByteStr:"NULL", + cbMultiByte, lpWideCharStr, cchWideChar); + + if (dwFlags & ~(MB_ERR_INVALID_CHARS | MB_PRECOMPOSED)) + { + ASSERT("Error dwFlags(0x%x) parameter is invalid\n", dwFlags); + SetLastError(ERROR_INVALID_FLAGS); + goto EXIT; + } + + if ( (cbMultiByte == 0) || (cchWideChar < 0) || + (lpMultiByteStr == NULL) || + ((cchWideChar != 0) && + ((lpWideCharStr == NULL) || + (lpMultiByteStr == (LPSTR)lpWideCharStr))) ) + { + ERROR("Error lpMultiByteStr parameters are invalid\n"); + SetLastError(ERROR_INVALID_PARAMETER); + goto EXIT; + } + + // Use UTF8ToUnicode on all systems, since it replaces + // invalid characters and Core Foundation doesn't do that. + if (CodePage == CP_UTF8 || CodePage == CP_ACP) + { + if (cbMultiByte <= -1) + { + cbMultiByte = strlen(lpMultiByteStr) + 1; + } + + retval = UTF8ToUnicode(lpMultiByteStr, cbMultiByte, lpWideCharStr, cchWideChar, dwFlags); + goto EXIT; + } + + ERROR( "This code page is not in the system.\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + goto EXIT; + +EXIT: + + LOGEXIT("MultiByteToWideChar returns %d.\n",retval); + PERF_EXIT(MultiByteToWideChar); + return retval; +} + + +/*++ +Function: +WideCharToMultiByte + +See MSDN doc. + +--*/ +int +PALAPI +WideCharToMultiByte( + IN UINT CodePage, + IN DWORD dwFlags, + IN LPCWSTR lpWideCharStr, + IN int cchWideChar, + OUT LPSTR lpMultiByteStr, + IN int cbMultiByte, + IN LPCSTR lpDefaultChar, + OUT LPBOOL lpUsedDefaultChar) +{ + INT retval =0; + char defaultChar = '?'; + BOOL usedDefaultChar = FALSE; + + PERF_ENTRY(WideCharToMultiByte); + ENTRY("WideCharToMultiByte(CodePage=%u, dwFlags=%#x, lpWideCharStr=%p (%S), " + "cchWideChar=%d, lpMultiByteStr=%p, cbMultiByte=%d, " + "lpDefaultChar=%p, lpUsedDefaultChar=%p)\n", + CodePage, dwFlags, lpWideCharStr?lpWideCharStr:W16_NULLSTRING, lpWideCharStr?lpWideCharStr:W16_NULLSTRING, + cchWideChar, lpMultiByteStr, cbMultiByte, + lpDefaultChar, lpUsedDefaultChar); + + if (dwFlags & ~WC_NO_BEST_FIT_CHARS) + { + ERROR("dwFlags %d invalid\n", dwFlags); + SetLastError(ERROR_INVALID_FLAGS); + goto EXIT; + } + + // No special action is needed for WC_NO_BEST_FIT_CHARS. The default + // behavior of this API on Unix is not to find the best fit for a unicode + // character that does not map directly into a code point in the given + // code page. The best fit functionality is not available in wctomb on Unix + // and is better left unimplemented for security reasons anyway. + + if ((cchWideChar < -1) || (cbMultiByte < 0) || + (lpWideCharStr == NULL) || + ((cbMultiByte != 0) && + ((lpMultiByteStr == NULL) || + (lpWideCharStr == (LPWSTR)lpMultiByteStr))) ) + { + ERROR("Error lpWideCharStr parameters are invalid\n"); + SetLastError(ERROR_INVALID_PARAMETER); + goto EXIT; + } + + if (lpDefaultChar != NULL) + { + defaultChar = *lpDefaultChar; + } + + // Use UnicodeToUTF8 on all systems because we use + // UTF8ToUnicode in MultiByteToWideChar() on all systems. + if (CodePage == CP_UTF8 || CodePage == CP_ACP) + { + if (cchWideChar == -1) + { + cchWideChar = PAL_wcslen(lpWideCharStr) + 1; + } + retval = UnicodeToUTF8(lpWideCharStr, cchWideChar, lpMultiByteStr, cbMultiByte); + goto EXIT; + } + + ERROR( "This code page is not in the system.\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + goto EXIT; + +EXIT: + + if ( lpUsedDefaultChar != NULL ) + { + *lpUsedDefaultChar = usedDefaultChar; + } + + /* Flag the cases when WC_NO_BEST_FIT_CHARS was not specified + * but we found characters that had to be replaced with default + * characters. Note that Windows would have attempted to find + * best fit characters under these conditions and that could pose + * a security risk. + */ + _ASSERT_MSG((dwFlags & WC_NO_BEST_FIT_CHARS) || !usedDefaultChar, + "WideCharToMultiByte found a string which doesn't round trip: (%p)%S " + "and WC_NO_BEST_FIT_CHARS was not specified\n", + lpWideCharStr, lpWideCharStr); + + LOGEXIT("WideCharToMultiByte returns INT %d\n", retval); + PERF_EXIT(WideCharToMultiByte); + return retval; +} + +extern char * g_szCoreCLRPath; diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/unicodedata.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/unicodedata.cpp new file mode 100644 index 0000000..91787ec --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/unicodedata.cpp @@ -0,0 +1,2362 @@ +// 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. + +#include "pal/unicodedata.h" + +// +// THIS FILE IS GENERATED. DO NOT HAND EDIT. +// + +CONST UnicodeDataRec UnicodeData[] = { + { 0x41, UPPER_CASE, 0x61 }, + { 0x42, UPPER_CASE, 0x62 }, + { 0x43, UPPER_CASE, 0x63 }, + { 0x44, UPPER_CASE, 0x64 }, + { 0x45, UPPER_CASE, 0x65 }, + { 0x46, UPPER_CASE, 0x66 }, + { 0x47, UPPER_CASE, 0x67 }, + { 0x48, UPPER_CASE, 0x68 }, + { 0x49, UPPER_CASE, 0x69 }, + { 0x4A, UPPER_CASE, 0x6A }, + { 0x4B, UPPER_CASE, 0x6B }, + { 0x4C, UPPER_CASE, 0x6C }, + { 0x4D, UPPER_CASE, 0x6D }, + { 0x4E, UPPER_CASE, 0x6E }, + { 0x4F, UPPER_CASE, 0x6F }, + { 0x50, UPPER_CASE, 0x70 }, + { 0x51, UPPER_CASE, 0x71 }, + { 0x52, UPPER_CASE, 0x72 }, + { 0x53, UPPER_CASE, 0x73 }, + { 0x54, UPPER_CASE, 0x74 }, + { 0x55, UPPER_CASE, 0x75 }, + { 0x56, UPPER_CASE, 0x76 }, + { 0x57, UPPER_CASE, 0x77 }, + { 0x58, UPPER_CASE, 0x78 }, + { 0x59, UPPER_CASE, 0x79 }, + { 0x5A, UPPER_CASE, 0x7A }, + { 0x61, LOWER_CASE, 0x41 }, + { 0x62, LOWER_CASE, 0x42 }, + { 0x63, LOWER_CASE, 0x43 }, + { 0x64, LOWER_CASE, 0x44 }, + { 0x65, LOWER_CASE, 0x45 }, + { 0x66, LOWER_CASE, 0x46 }, + { 0x67, LOWER_CASE, 0x47 }, + { 0x68, LOWER_CASE, 0x48 }, + { 0x69, LOWER_CASE, 0x49 }, + { 0x6A, LOWER_CASE, 0x4A }, + { 0x6B, LOWER_CASE, 0x4B }, + { 0x6C, LOWER_CASE, 0x4C }, + { 0x6D, LOWER_CASE, 0x4D }, + { 0x6E, LOWER_CASE, 0x4E }, + { 0x6F, LOWER_CASE, 0x4F }, + { 0x70, LOWER_CASE, 0x50 }, + { 0x71, LOWER_CASE, 0x51 }, + { 0x72, LOWER_CASE, 0x52 }, + { 0x73, LOWER_CASE, 0x53 }, + { 0x74, LOWER_CASE, 0x54 }, + { 0x75, LOWER_CASE, 0x55 }, + { 0x76, LOWER_CASE, 0x56 }, + { 0x77, LOWER_CASE, 0x57 }, + { 0x78, LOWER_CASE, 0x58 }, + { 0x79, LOWER_CASE, 0x59 }, + { 0x7A, LOWER_CASE, 0x5A }, + { 0xB5, LOWER_CASE, 0x39C }, + { 0xC0, UPPER_CASE, 0xE0 }, + { 0xC1, UPPER_CASE, 0xE1 }, + { 0xC2, UPPER_CASE, 0xE2 }, + { 0xC3, UPPER_CASE, 0xE3 }, + { 0xC4, UPPER_CASE, 0xE4 }, + { 0xC5, UPPER_CASE, 0xE5 }, + { 0xC6, UPPER_CASE, 0xE6 }, + { 0xC7, UPPER_CASE, 0xE7 }, + { 0xC8, UPPER_CASE, 0xE8 }, + { 0xC9, UPPER_CASE, 0xE9 }, + { 0xCA, UPPER_CASE, 0xEA }, + { 0xCB, UPPER_CASE, 0xEB }, + { 0xCC, UPPER_CASE, 0xEC }, + { 0xCD, UPPER_CASE, 0xED }, + { 0xCE, UPPER_CASE, 0xEE }, + { 0xCF, UPPER_CASE, 0xEF }, + { 0xD0, UPPER_CASE, 0xF0 }, + { 0xD1, UPPER_CASE, 0xF1 }, + { 0xD2, UPPER_CASE, 0xF2 }, + { 0xD3, UPPER_CASE, 0xF3 }, + { 0xD4, UPPER_CASE, 0xF4 }, + { 0xD5, UPPER_CASE, 0xF5 }, + { 0xD6, UPPER_CASE, 0xF6 }, + { 0xD8, UPPER_CASE, 0xF8 }, + { 0xD9, UPPER_CASE, 0xF9 }, + { 0xDA, UPPER_CASE, 0xFA }, + { 0xDB, UPPER_CASE, 0xFB }, + { 0xDC, UPPER_CASE, 0xFC }, + { 0xDD, UPPER_CASE, 0xFD }, + { 0xDE, UPPER_CASE, 0xFE }, + { 0xE0, LOWER_CASE, 0xC0 }, + { 0xE1, LOWER_CASE, 0xC1 }, + { 0xE2, LOWER_CASE, 0xC2 }, + { 0xE3, LOWER_CASE, 0xC3 }, + { 0xE4, LOWER_CASE, 0xC4 }, + { 0xE5, LOWER_CASE, 0xC5 }, + { 0xE6, LOWER_CASE, 0xC6 }, + { 0xE7, LOWER_CASE, 0xC7 }, + { 0xE8, LOWER_CASE, 0xC8 }, + { 0xE9, LOWER_CASE, 0xC9 }, + { 0xEA, LOWER_CASE, 0xCA }, + { 0xEB, LOWER_CASE, 0xCB }, + { 0xEC, LOWER_CASE, 0xCC }, + { 0xED, LOWER_CASE, 0xCD }, + { 0xEE, LOWER_CASE, 0xCE }, + { 0xEF, LOWER_CASE, 0xCF }, + { 0xF0, LOWER_CASE, 0xD0 }, + { 0xF1, LOWER_CASE, 0xD1 }, + { 0xF2, LOWER_CASE, 0xD2 }, + { 0xF3, LOWER_CASE, 0xD3 }, + { 0xF4, LOWER_CASE, 0xD4 }, + { 0xF5, LOWER_CASE, 0xD5 }, + { 0xF6, LOWER_CASE, 0xD6 }, + { 0xF8, LOWER_CASE, 0xD8 }, + { 0xF9, LOWER_CASE, 0xD9 }, + { 0xFA, LOWER_CASE, 0xDA }, + { 0xFB, LOWER_CASE, 0xDB }, + { 0xFC, LOWER_CASE, 0xDC }, + { 0xFD, LOWER_CASE, 0xDD }, + { 0xFE, LOWER_CASE, 0xDE }, + { 0xFF, LOWER_CASE, 0x178 }, + { 0x100, UPPER_CASE, 0x101 }, + { 0x101, LOWER_CASE, 0x100 }, + { 0x102, UPPER_CASE, 0x103 }, + { 0x103, LOWER_CASE, 0x102 }, + { 0x104, UPPER_CASE, 0x105 }, + { 0x105, LOWER_CASE, 0x104 }, + { 0x106, UPPER_CASE, 0x107 }, + { 0x107, LOWER_CASE, 0x106 }, + { 0x108, UPPER_CASE, 0x109 }, + { 0x109, LOWER_CASE, 0x108 }, + { 0x10A, UPPER_CASE, 0x10B }, + { 0x10B, LOWER_CASE, 0x10A }, + { 0x10C, UPPER_CASE, 0x10D }, + { 0x10D, LOWER_CASE, 0x10C }, + { 0x10E, UPPER_CASE, 0x10F }, + { 0x10F, LOWER_CASE, 0x10E }, + { 0x110, UPPER_CASE, 0x111 }, + { 0x111, LOWER_CASE, 0x110 }, + { 0x112, UPPER_CASE, 0x113 }, + { 0x113, LOWER_CASE, 0x112 }, + { 0x114, UPPER_CASE, 0x115 }, + { 0x115, LOWER_CASE, 0x114 }, + { 0x116, UPPER_CASE, 0x117 }, + { 0x117, LOWER_CASE, 0x116 }, + { 0x118, UPPER_CASE, 0x119 }, + { 0x119, LOWER_CASE, 0x118 }, + { 0x11A, UPPER_CASE, 0x11B }, + { 0x11B, LOWER_CASE, 0x11A }, + { 0x11C, UPPER_CASE, 0x11D }, + { 0x11D, LOWER_CASE, 0x11C }, + { 0x11E, UPPER_CASE, 0x11F }, + { 0x11F, LOWER_CASE, 0x11E }, + { 0x120, UPPER_CASE, 0x121 }, + { 0x121, LOWER_CASE, 0x120 }, + { 0x122, UPPER_CASE, 0x123 }, + { 0x123, LOWER_CASE, 0x122 }, + { 0x124, UPPER_CASE, 0x125 }, + { 0x125, LOWER_CASE, 0x124 }, + { 0x126, UPPER_CASE, 0x127 }, + { 0x127, LOWER_CASE, 0x126 }, + { 0x128, UPPER_CASE, 0x129 }, + { 0x129, LOWER_CASE, 0x128 }, + { 0x12A, UPPER_CASE, 0x12B }, + { 0x12B, LOWER_CASE, 0x12A }, + { 0x12C, UPPER_CASE, 0x12D }, + { 0x12D, LOWER_CASE, 0x12C }, + { 0x12E, UPPER_CASE, 0x12F }, + { 0x12F, LOWER_CASE, 0x12E }, + { 0x130, UPPER_CASE, 0x69 }, + { 0x131, LOWER_CASE, 0x49 }, + { 0x132, UPPER_CASE, 0x133 }, + { 0x133, LOWER_CASE, 0x132 }, + { 0x134, UPPER_CASE, 0x135 }, + { 0x135, LOWER_CASE, 0x134 }, + { 0x136, UPPER_CASE, 0x137 }, + { 0x137, LOWER_CASE, 0x136 }, + { 0x139, UPPER_CASE, 0x13A }, + { 0x13A, LOWER_CASE, 0x139 }, + { 0x13B, UPPER_CASE, 0x13C }, + { 0x13C, LOWER_CASE, 0x13B }, + { 0x13D, UPPER_CASE, 0x13E }, + { 0x13E, LOWER_CASE, 0x13D }, + { 0x13F, UPPER_CASE, 0x140 }, + { 0x140, LOWER_CASE, 0x13F }, + { 0x141, UPPER_CASE, 0x142 }, + { 0x142, LOWER_CASE, 0x141 }, + { 0x143, UPPER_CASE, 0x144 }, + { 0x144, LOWER_CASE, 0x143 }, + { 0x145, UPPER_CASE, 0x146 }, + { 0x146, LOWER_CASE, 0x145 }, + { 0x147, UPPER_CASE, 0x148 }, + { 0x148, LOWER_CASE, 0x147 }, + { 0x14A, UPPER_CASE, 0x14B }, + { 0x14B, LOWER_CASE, 0x14A }, + { 0x14C, UPPER_CASE, 0x14D }, + { 0x14D, LOWER_CASE, 0x14C }, + { 0x14E, UPPER_CASE, 0x14F }, + { 0x14F, LOWER_CASE, 0x14E }, + { 0x150, UPPER_CASE, 0x151 }, + { 0x151, LOWER_CASE, 0x150 }, + { 0x152, UPPER_CASE, 0x153 }, + { 0x153, LOWER_CASE, 0x152 }, + { 0x154, UPPER_CASE, 0x155 }, + { 0x155, LOWER_CASE, 0x154 }, + { 0x156, UPPER_CASE, 0x157 }, + { 0x157, LOWER_CASE, 0x156 }, + { 0x158, UPPER_CASE, 0x159 }, + { 0x159, LOWER_CASE, 0x158 }, + { 0x15A, UPPER_CASE, 0x15B }, + { 0x15B, LOWER_CASE, 0x15A }, + { 0x15C, UPPER_CASE, 0x15D }, + { 0x15D, LOWER_CASE, 0x15C }, + { 0x15E, UPPER_CASE, 0x15F }, + { 0x15F, LOWER_CASE, 0x15E }, + { 0x160, UPPER_CASE, 0x161 }, + { 0x161, LOWER_CASE, 0x160 }, + { 0x162, UPPER_CASE, 0x163 }, + { 0x163, LOWER_CASE, 0x162 }, + { 0x164, UPPER_CASE, 0x165 }, + { 0x165, LOWER_CASE, 0x164 }, + { 0x166, UPPER_CASE, 0x167 }, + { 0x167, LOWER_CASE, 0x166 }, + { 0x168, UPPER_CASE, 0x169 }, + { 0x169, LOWER_CASE, 0x168 }, + { 0x16A, UPPER_CASE, 0x16B }, + { 0x16B, LOWER_CASE, 0x16A }, + { 0x16C, UPPER_CASE, 0x16D }, + { 0x16D, LOWER_CASE, 0x16C }, + { 0x16E, UPPER_CASE, 0x16F }, + { 0x16F, LOWER_CASE, 0x16E }, + { 0x170, UPPER_CASE, 0x171 }, + { 0x171, LOWER_CASE, 0x170 }, + { 0x172, UPPER_CASE, 0x173 }, + { 0x173, LOWER_CASE, 0x172 }, + { 0x174, UPPER_CASE, 0x175 }, + { 0x175, LOWER_CASE, 0x174 }, + { 0x176, UPPER_CASE, 0x177 }, + { 0x177, LOWER_CASE, 0x176 }, + { 0x178, UPPER_CASE, 0xFF }, + { 0x179, UPPER_CASE, 0x17A }, + { 0x17A, LOWER_CASE, 0x179 }, + { 0x17B, UPPER_CASE, 0x17C }, + { 0x17C, LOWER_CASE, 0x17B }, + { 0x17D, UPPER_CASE, 0x17E }, + { 0x17E, LOWER_CASE, 0x17D }, + { 0x17F, LOWER_CASE, 0x53 }, + { 0x180, LOWER_CASE, 0x243 }, + { 0x181, UPPER_CASE, 0x253 }, + { 0x182, UPPER_CASE, 0x183 }, + { 0x183, LOWER_CASE, 0x182 }, + { 0x184, UPPER_CASE, 0x185 }, + { 0x185, LOWER_CASE, 0x184 }, + { 0x186, UPPER_CASE, 0x254 }, + { 0x187, UPPER_CASE, 0x188 }, + { 0x188, LOWER_CASE, 0x187 }, + { 0x189, UPPER_CASE, 0x256 }, + { 0x18A, UPPER_CASE, 0x257 }, + { 0x18B, UPPER_CASE, 0x18C }, + { 0x18C, LOWER_CASE, 0x18B }, + { 0x18E, UPPER_CASE, 0x1DD }, + { 0x18F, UPPER_CASE, 0x259 }, + { 0x190, UPPER_CASE, 0x25B }, + { 0x191, UPPER_CASE, 0x192 }, + { 0x192, LOWER_CASE, 0x191 }, + { 0x193, UPPER_CASE, 0x260 }, + { 0x194, UPPER_CASE, 0x263 }, + { 0x195, LOWER_CASE, 0x1F6 }, + { 0x196, UPPER_CASE, 0x269 }, + { 0x197, UPPER_CASE, 0x268 }, + { 0x198, UPPER_CASE, 0x199 }, + { 0x199, LOWER_CASE, 0x198 }, + { 0x19A, LOWER_CASE, 0x23D }, + { 0x19C, UPPER_CASE, 0x26F }, + { 0x19D, UPPER_CASE, 0x272 }, + { 0x19E, LOWER_CASE, 0x220 }, + { 0x19F, UPPER_CASE, 0x275 }, + { 0x1A0, UPPER_CASE, 0x1A1 }, + { 0x1A1, LOWER_CASE, 0x1A0 }, + { 0x1A2, UPPER_CASE, 0x1A3 }, + { 0x1A3, LOWER_CASE, 0x1A2 }, + { 0x1A4, UPPER_CASE, 0x1A5 }, + { 0x1A5, LOWER_CASE, 0x1A4 }, + { 0x1A6, UPPER_CASE, 0x280 }, + { 0x1A7, UPPER_CASE, 0x1A8 }, + { 0x1A8, LOWER_CASE, 0x1A7 }, + { 0x1A9, UPPER_CASE, 0x283 }, + { 0x1AC, UPPER_CASE, 0x1AD }, + { 0x1AD, LOWER_CASE, 0x1AC }, + { 0x1AE, UPPER_CASE, 0x288 }, + { 0x1AF, UPPER_CASE, 0x1B0 }, + { 0x1B0, LOWER_CASE, 0x1AF }, + { 0x1B1, UPPER_CASE, 0x28A }, + { 0x1B2, UPPER_CASE, 0x28B }, + { 0x1B3, UPPER_CASE, 0x1B4 }, + { 0x1B4, LOWER_CASE, 0x1B3 }, + { 0x1B5, UPPER_CASE, 0x1B6 }, + { 0x1B6, LOWER_CASE, 0x1B5 }, + { 0x1B7, UPPER_CASE, 0x292 }, + { 0x1B8, UPPER_CASE, 0x1B9 }, + { 0x1B9, LOWER_CASE, 0x1B8 }, + { 0x1BC, UPPER_CASE, 0x1BD }, + { 0x1BD, LOWER_CASE, 0x1BC }, + { 0x1BF, LOWER_CASE, 0x1F7 }, + { 0x1C4, UPPER_CASE, 0x1C6 }, + { 0x1C5, LOWER_CASE, 0x1C4 }, + { 0x1C6, LOWER_CASE, 0x1C4 }, + { 0x1C7, UPPER_CASE, 0x1C9 }, + { 0x1C8, LOWER_CASE, 0x1C7 }, + { 0x1C9, LOWER_CASE, 0x1C7 }, + { 0x1CA, UPPER_CASE, 0x1CC }, + { 0x1CB, LOWER_CASE, 0x1CA }, + { 0x1CC, LOWER_CASE, 0x1CA }, + { 0x1CD, UPPER_CASE, 0x1CE }, + { 0x1CE, LOWER_CASE, 0x1CD }, + { 0x1CF, UPPER_CASE, 0x1D0 }, + { 0x1D0, LOWER_CASE, 0x1CF }, + { 0x1D1, UPPER_CASE, 0x1D2 }, + { 0x1D2, LOWER_CASE, 0x1D1 }, + { 0x1D3, UPPER_CASE, 0x1D4 }, + { 0x1D4, LOWER_CASE, 0x1D3 }, + { 0x1D5, UPPER_CASE, 0x1D6 }, + { 0x1D6, LOWER_CASE, 0x1D5 }, + { 0x1D7, UPPER_CASE, 0x1D8 }, + { 0x1D8, LOWER_CASE, 0x1D7 }, + { 0x1D9, UPPER_CASE, 0x1DA }, + { 0x1DA, LOWER_CASE, 0x1D9 }, + { 0x1DB, UPPER_CASE, 0x1DC }, + { 0x1DC, LOWER_CASE, 0x1DB }, + { 0x1DD, LOWER_CASE, 0x18E }, + { 0x1DE, UPPER_CASE, 0x1DF }, + { 0x1DF, LOWER_CASE, 0x1DE }, + { 0x1E0, UPPER_CASE, 0x1E1 }, + { 0x1E1, LOWER_CASE, 0x1E0 }, + { 0x1E2, UPPER_CASE, 0x1E3 }, + { 0x1E3, LOWER_CASE, 0x1E2 }, + { 0x1E4, UPPER_CASE, 0x1E5 }, + { 0x1E5, LOWER_CASE, 0x1E4 }, + { 0x1E6, UPPER_CASE, 0x1E7 }, + { 0x1E7, LOWER_CASE, 0x1E6 }, + { 0x1E8, UPPER_CASE, 0x1E9 }, + { 0x1E9, LOWER_CASE, 0x1E8 }, + { 0x1EA, UPPER_CASE, 0x1EB }, + { 0x1EB, LOWER_CASE, 0x1EA }, + { 0x1EC, UPPER_CASE, 0x1ED }, + { 0x1ED, LOWER_CASE, 0x1EC }, + { 0x1EE, UPPER_CASE, 0x1EF }, + { 0x1EF, LOWER_CASE, 0x1EE }, + { 0x1F1, UPPER_CASE, 0x1F3 }, + { 0x1F2, LOWER_CASE, 0x1F1 }, + { 0x1F3, LOWER_CASE, 0x1F1 }, + { 0x1F4, UPPER_CASE, 0x1F5 }, + { 0x1F5, LOWER_CASE, 0x1F4 }, + { 0x1F6, UPPER_CASE, 0x195 }, + { 0x1F7, UPPER_CASE, 0x1BF }, + { 0x1F8, UPPER_CASE, 0x1F9 }, + { 0x1F9, LOWER_CASE, 0x1F8 }, + { 0x1FA, UPPER_CASE, 0x1FB }, + { 0x1FB, LOWER_CASE, 0x1FA }, + { 0x1FC, UPPER_CASE, 0x1FD }, + { 0x1FD, LOWER_CASE, 0x1FC }, + { 0x1FE, UPPER_CASE, 0x1FF }, + { 0x1FF, LOWER_CASE, 0x1FE }, + { 0x200, UPPER_CASE, 0x201 }, + { 0x201, LOWER_CASE, 0x200 }, + { 0x202, UPPER_CASE, 0x203 }, + { 0x203, LOWER_CASE, 0x202 }, + { 0x204, UPPER_CASE, 0x205 }, + { 0x205, LOWER_CASE, 0x204 }, + { 0x206, UPPER_CASE, 0x207 }, + { 0x207, LOWER_CASE, 0x206 }, + { 0x208, UPPER_CASE, 0x209 }, + { 0x209, LOWER_CASE, 0x208 }, + { 0x20A, UPPER_CASE, 0x20B }, + { 0x20B, LOWER_CASE, 0x20A }, + { 0x20C, UPPER_CASE, 0x20D }, + { 0x20D, LOWER_CASE, 0x20C }, + { 0x20E, UPPER_CASE, 0x20F }, + { 0x20F, LOWER_CASE, 0x20E }, + { 0x210, UPPER_CASE, 0x211 }, + { 0x211, LOWER_CASE, 0x210 }, + { 0x212, UPPER_CASE, 0x213 }, + { 0x213, LOWER_CASE, 0x212 }, + { 0x214, UPPER_CASE, 0x215 }, + { 0x215, LOWER_CASE, 0x214 }, + { 0x216, UPPER_CASE, 0x217 }, + { 0x217, LOWER_CASE, 0x216 }, + { 0x218, UPPER_CASE, 0x219 }, + { 0x219, LOWER_CASE, 0x218 }, + { 0x21A, UPPER_CASE, 0x21B }, + { 0x21B, LOWER_CASE, 0x21A }, + { 0x21C, UPPER_CASE, 0x21D }, + { 0x21D, LOWER_CASE, 0x21C }, + { 0x21E, UPPER_CASE, 0x21F }, + { 0x21F, LOWER_CASE, 0x21E }, + { 0x220, UPPER_CASE, 0x19E }, + { 0x222, UPPER_CASE, 0x223 }, + { 0x223, LOWER_CASE, 0x222 }, + { 0x224, UPPER_CASE, 0x225 }, + { 0x225, LOWER_CASE, 0x224 }, + { 0x226, UPPER_CASE, 0x227 }, + { 0x227, LOWER_CASE, 0x226 }, + { 0x228, UPPER_CASE, 0x229 }, + { 0x229, LOWER_CASE, 0x228 }, + { 0x22A, UPPER_CASE, 0x22B }, + { 0x22B, LOWER_CASE, 0x22A }, + { 0x22C, UPPER_CASE, 0x22D }, + { 0x22D, LOWER_CASE, 0x22C }, + { 0x22E, UPPER_CASE, 0x22F }, + { 0x22F, LOWER_CASE, 0x22E }, + { 0x230, UPPER_CASE, 0x231 }, + { 0x231, LOWER_CASE, 0x230 }, + { 0x232, UPPER_CASE, 0x233 }, + { 0x233, LOWER_CASE, 0x232 }, + { 0x23A, UPPER_CASE, 0x2C65 }, + { 0x23B, UPPER_CASE, 0x23C }, + { 0x23C, LOWER_CASE, 0x23B }, + { 0x23D, UPPER_CASE, 0x19A }, + { 0x23E, UPPER_CASE, 0x2C66 }, + { 0x23F, LOWER_CASE, 0x2C7E }, + { 0x240, LOWER_CASE, 0x2C7F }, + { 0x241, UPPER_CASE, 0x242 }, + { 0x242, LOWER_CASE, 0x241 }, + { 0x243, UPPER_CASE, 0x180 }, + { 0x244, UPPER_CASE, 0x289 }, + { 0x245, UPPER_CASE, 0x28C }, + { 0x246, UPPER_CASE, 0x247 }, + { 0x247, LOWER_CASE, 0x246 }, + { 0x248, UPPER_CASE, 0x249 }, + { 0x249, LOWER_CASE, 0x248 }, + { 0x24A, UPPER_CASE, 0x24B }, + { 0x24B, LOWER_CASE, 0x24A }, + { 0x24C, UPPER_CASE, 0x24D }, + { 0x24D, LOWER_CASE, 0x24C }, + { 0x24E, UPPER_CASE, 0x24F }, + { 0x24F, LOWER_CASE, 0x24E }, + { 0x250, LOWER_CASE, 0x2C6F }, + { 0x251, LOWER_CASE, 0x2C6D }, + { 0x252, LOWER_CASE, 0x2C70 }, + { 0x253, LOWER_CASE, 0x181 }, + { 0x254, LOWER_CASE, 0x186 }, + { 0x256, LOWER_CASE, 0x189 }, + { 0x257, LOWER_CASE, 0x18A }, + { 0x259, LOWER_CASE, 0x18F }, + { 0x25B, LOWER_CASE, 0x190 }, + { 0x25C, LOWER_CASE, 0xA7AB }, + { 0x260, LOWER_CASE, 0x193 }, + { 0x261, LOWER_CASE, 0xA7AC }, + { 0x263, LOWER_CASE, 0x194 }, + { 0x265, LOWER_CASE, 0xA78D }, + { 0x266, LOWER_CASE, 0xA7AA }, + { 0x268, LOWER_CASE, 0x197 }, + { 0x269, LOWER_CASE, 0x196 }, + { 0x26A, LOWER_CASE, 0xA7AE }, + { 0x26B, LOWER_CASE, 0x2C62 }, + { 0x26C, LOWER_CASE, 0xA7AD }, + { 0x26F, LOWER_CASE, 0x19C }, + { 0x271, LOWER_CASE, 0x2C6E }, + { 0x272, LOWER_CASE, 0x19D }, + { 0x275, LOWER_CASE, 0x19F }, + { 0x27D, LOWER_CASE, 0x2C64 }, + { 0x280, LOWER_CASE, 0x1A6 }, + { 0x282, LOWER_CASE, 0xA7C5 }, + { 0x283, LOWER_CASE, 0x1A9 }, + { 0x287, LOWER_CASE, 0xA7B1 }, + { 0x288, LOWER_CASE, 0x1AE }, + { 0x289, LOWER_CASE, 0x244 }, + { 0x28A, LOWER_CASE, 0x1B1 }, + { 0x28B, LOWER_CASE, 0x1B2 }, + { 0x28C, LOWER_CASE, 0x245 }, + { 0x292, LOWER_CASE, 0x1B7 }, + { 0x29D, LOWER_CASE, 0xA7B2 }, + { 0x29E, LOWER_CASE, 0xA7B0 }, + { 0x345, LOWER_CASE, 0x399 }, + { 0x370, UPPER_CASE, 0x371 }, + { 0x371, LOWER_CASE, 0x370 }, + { 0x372, UPPER_CASE, 0x373 }, + { 0x373, LOWER_CASE, 0x372 }, + { 0x376, UPPER_CASE, 0x377 }, + { 0x377, LOWER_CASE, 0x376 }, + { 0x37B, LOWER_CASE, 0x3FD }, + { 0x37C, LOWER_CASE, 0x3FE }, + { 0x37D, LOWER_CASE, 0x3FF }, + { 0x37F, UPPER_CASE, 0x3F3 }, + { 0x386, UPPER_CASE, 0x3AC }, + { 0x388, UPPER_CASE, 0x3AD }, + { 0x389, UPPER_CASE, 0x3AE }, + { 0x38A, UPPER_CASE, 0x3AF }, + { 0x38C, UPPER_CASE, 0x3CC }, + { 0x38E, UPPER_CASE, 0x3CD }, + { 0x38F, UPPER_CASE, 0x3CE }, + { 0x391, UPPER_CASE, 0x3B1 }, + { 0x392, UPPER_CASE, 0x3B2 }, + { 0x393, UPPER_CASE, 0x3B3 }, + { 0x394, UPPER_CASE, 0x3B4 }, + { 0x395, UPPER_CASE, 0x3B5 }, + { 0x396, UPPER_CASE, 0x3B6 }, + { 0x397, UPPER_CASE, 0x3B7 }, + { 0x398, UPPER_CASE, 0x3B8 }, + { 0x399, UPPER_CASE, 0x3B9 }, + { 0x39A, UPPER_CASE, 0x3BA }, + { 0x39B, UPPER_CASE, 0x3BB }, + { 0x39C, UPPER_CASE, 0x3BC }, + { 0x39D, UPPER_CASE, 0x3BD }, + { 0x39E, UPPER_CASE, 0x3BE }, + { 0x39F, UPPER_CASE, 0x3BF }, + { 0x3A0, UPPER_CASE, 0x3C0 }, + { 0x3A1, UPPER_CASE, 0x3C1 }, + { 0x3A3, UPPER_CASE, 0x3C3 }, + { 0x3A4, UPPER_CASE, 0x3C4 }, + { 0x3A5, UPPER_CASE, 0x3C5 }, + { 0x3A6, UPPER_CASE, 0x3C6 }, + { 0x3A7, UPPER_CASE, 0x3C7 }, + { 0x3A8, UPPER_CASE, 0x3C8 }, + { 0x3A9, UPPER_CASE, 0x3C9 }, + { 0x3AA, UPPER_CASE, 0x3CA }, + { 0x3AB, UPPER_CASE, 0x3CB }, + { 0x3AC, LOWER_CASE, 0x386 }, + { 0x3AD, LOWER_CASE, 0x388 }, + { 0x3AE, LOWER_CASE, 0x389 }, + { 0x3AF, LOWER_CASE, 0x38A }, + { 0x3B1, LOWER_CASE, 0x391 }, + { 0x3B2, LOWER_CASE, 0x392 }, + { 0x3B3, LOWER_CASE, 0x393 }, + { 0x3B4, LOWER_CASE, 0x394 }, + { 0x3B5, LOWER_CASE, 0x395 }, + { 0x3B6, LOWER_CASE, 0x396 }, + { 0x3B7, LOWER_CASE, 0x397 }, + { 0x3B8, LOWER_CASE, 0x398 }, + { 0x3B9, LOWER_CASE, 0x399 }, + { 0x3BA, LOWER_CASE, 0x39A }, + { 0x3BB, LOWER_CASE, 0x39B }, + { 0x3BC, LOWER_CASE, 0x39C }, + { 0x3BD, LOWER_CASE, 0x39D }, + { 0x3BE, LOWER_CASE, 0x39E }, + { 0x3BF, LOWER_CASE, 0x39F }, + { 0x3C0, LOWER_CASE, 0x3A0 }, + { 0x3C1, LOWER_CASE, 0x3A1 }, + { 0x3C2, LOWER_CASE, 0x3A3 }, + { 0x3C3, LOWER_CASE, 0x3A3 }, + { 0x3C4, LOWER_CASE, 0x3A4 }, + { 0x3C5, LOWER_CASE, 0x3A5 }, + { 0x3C6, LOWER_CASE, 0x3A6 }, + { 0x3C7, LOWER_CASE, 0x3A7 }, + { 0x3C8, LOWER_CASE, 0x3A8 }, + { 0x3C9, LOWER_CASE, 0x3A9 }, + { 0x3CA, LOWER_CASE, 0x3AA }, + { 0x3CB, LOWER_CASE, 0x3AB }, + { 0x3CC, LOWER_CASE, 0x38C }, + { 0x3CD, LOWER_CASE, 0x38E }, + { 0x3CE, LOWER_CASE, 0x38F }, + { 0x3CF, UPPER_CASE, 0x3D7 }, + { 0x3D0, LOWER_CASE, 0x392 }, + { 0x3D1, LOWER_CASE, 0x398 }, + { 0x3D5, LOWER_CASE, 0x3A6 }, + { 0x3D6, LOWER_CASE, 0x3A0 }, + { 0x3D7, LOWER_CASE, 0x3CF }, + { 0x3D8, UPPER_CASE, 0x3D9 }, + { 0x3D9, LOWER_CASE, 0x3D8 }, + { 0x3DA, UPPER_CASE, 0x3DB }, + { 0x3DB, LOWER_CASE, 0x3DA }, + { 0x3DC, UPPER_CASE, 0x3DD }, + { 0x3DD, LOWER_CASE, 0x3DC }, + { 0x3DE, UPPER_CASE, 0x3DF }, + { 0x3DF, LOWER_CASE, 0x3DE }, + { 0x3E0, UPPER_CASE, 0x3E1 }, + { 0x3E1, LOWER_CASE, 0x3E0 }, + { 0x3E2, UPPER_CASE, 0x3E3 }, + { 0x3E3, LOWER_CASE, 0x3E2 }, + { 0x3E4, UPPER_CASE, 0x3E5 }, + { 0x3E5, LOWER_CASE, 0x3E4 }, + { 0x3E6, UPPER_CASE, 0x3E7 }, + { 0x3E7, LOWER_CASE, 0x3E6 }, + { 0x3E8, UPPER_CASE, 0x3E9 }, + { 0x3E9, LOWER_CASE, 0x3E8 }, + { 0x3EA, UPPER_CASE, 0x3EB }, + { 0x3EB, LOWER_CASE, 0x3EA }, + { 0x3EC, UPPER_CASE, 0x3ED }, + { 0x3ED, LOWER_CASE, 0x3EC }, + { 0x3EE, UPPER_CASE, 0x3EF }, + { 0x3EF, LOWER_CASE, 0x3EE }, + { 0x3F0, LOWER_CASE, 0x39A }, + { 0x3F1, LOWER_CASE, 0x3A1 }, + { 0x3F2, LOWER_CASE, 0x3F9 }, + { 0x3F3, LOWER_CASE, 0x37F }, + { 0x3F4, UPPER_CASE, 0x3B8 }, + { 0x3F5, LOWER_CASE, 0x395 }, + { 0x3F7, UPPER_CASE, 0x3F8 }, + { 0x3F8, LOWER_CASE, 0x3F7 }, + { 0x3F9, UPPER_CASE, 0x3F2 }, + { 0x3FA, UPPER_CASE, 0x3FB }, + { 0x3FB, LOWER_CASE, 0x3FA }, + { 0x3FD, UPPER_CASE, 0x37B }, + { 0x3FE, UPPER_CASE, 0x37C }, + { 0x3FF, UPPER_CASE, 0x37D }, + { 0x400, UPPER_CASE, 0x450 }, + { 0x401, UPPER_CASE, 0x451 }, + { 0x402, UPPER_CASE, 0x452 }, + { 0x403, UPPER_CASE, 0x453 }, + { 0x404, UPPER_CASE, 0x454 }, + { 0x405, UPPER_CASE, 0x455 }, + { 0x406, UPPER_CASE, 0x456 }, + { 0x407, UPPER_CASE, 0x457 }, + { 0x408, UPPER_CASE, 0x458 }, + { 0x409, UPPER_CASE, 0x459 }, + { 0x40A, UPPER_CASE, 0x45A }, + { 0x40B, UPPER_CASE, 0x45B }, + { 0x40C, UPPER_CASE, 0x45C }, + { 0x40D, UPPER_CASE, 0x45D }, + { 0x40E, UPPER_CASE, 0x45E }, + { 0x40F, UPPER_CASE, 0x45F }, + { 0x410, UPPER_CASE, 0x430 }, + { 0x411, UPPER_CASE, 0x431 }, + { 0x412, UPPER_CASE, 0x432 }, + { 0x413, UPPER_CASE, 0x433 }, + { 0x414, UPPER_CASE, 0x434 }, + { 0x415, UPPER_CASE, 0x435 }, + { 0x416, UPPER_CASE, 0x436 }, + { 0x417, UPPER_CASE, 0x437 }, + { 0x418, UPPER_CASE, 0x438 }, + { 0x419, UPPER_CASE, 0x439 }, + { 0x41A, UPPER_CASE, 0x43A }, + { 0x41B, UPPER_CASE, 0x43B }, + { 0x41C, UPPER_CASE, 0x43C }, + { 0x41D, UPPER_CASE, 0x43D }, + { 0x41E, UPPER_CASE, 0x43E }, + { 0x41F, UPPER_CASE, 0x43F }, + { 0x420, UPPER_CASE, 0x440 }, + { 0x421, UPPER_CASE, 0x441 }, + { 0x422, UPPER_CASE, 0x442 }, + { 0x423, UPPER_CASE, 0x443 }, + { 0x424, UPPER_CASE, 0x444 }, + { 0x425, UPPER_CASE, 0x445 }, + { 0x426, UPPER_CASE, 0x446 }, + { 0x427, UPPER_CASE, 0x447 }, + { 0x428, UPPER_CASE, 0x448 }, + { 0x429, UPPER_CASE, 0x449 }, + { 0x42A, UPPER_CASE, 0x44A }, + { 0x42B, UPPER_CASE, 0x44B }, + { 0x42C, UPPER_CASE, 0x44C }, + { 0x42D, UPPER_CASE, 0x44D }, + { 0x42E, UPPER_CASE, 0x44E }, + { 0x42F, UPPER_CASE, 0x44F }, + { 0x430, LOWER_CASE, 0x410 }, + { 0x431, LOWER_CASE, 0x411 }, + { 0x432, LOWER_CASE, 0x412 }, + { 0x433, LOWER_CASE, 0x413 }, + { 0x434, LOWER_CASE, 0x414 }, + { 0x435, LOWER_CASE, 0x415 }, + { 0x436, LOWER_CASE, 0x416 }, + { 0x437, LOWER_CASE, 0x417 }, + { 0x438, LOWER_CASE, 0x418 }, + { 0x439, LOWER_CASE, 0x419 }, + { 0x43A, LOWER_CASE, 0x41A }, + { 0x43B, LOWER_CASE, 0x41B }, + { 0x43C, LOWER_CASE, 0x41C }, + { 0x43D, LOWER_CASE, 0x41D }, + { 0x43E, LOWER_CASE, 0x41E }, + { 0x43F, LOWER_CASE, 0x41F }, + { 0x440, LOWER_CASE, 0x420 }, + { 0x441, LOWER_CASE, 0x421 }, + { 0x442, LOWER_CASE, 0x422 }, + { 0x443, LOWER_CASE, 0x423 }, + { 0x444, LOWER_CASE, 0x424 }, + { 0x445, LOWER_CASE, 0x425 }, + { 0x446, LOWER_CASE, 0x426 }, + { 0x447, LOWER_CASE, 0x427 }, + { 0x448, LOWER_CASE, 0x428 }, + { 0x449, LOWER_CASE, 0x429 }, + { 0x44A, LOWER_CASE, 0x42A }, + { 0x44B, LOWER_CASE, 0x42B }, + { 0x44C, LOWER_CASE, 0x42C }, + { 0x44D, LOWER_CASE, 0x42D }, + { 0x44E, LOWER_CASE, 0x42E }, + { 0x44F, LOWER_CASE, 0x42F }, + { 0x450, LOWER_CASE, 0x400 }, + { 0x451, LOWER_CASE, 0x401 }, + { 0x452, LOWER_CASE, 0x402 }, + { 0x453, LOWER_CASE, 0x403 }, + { 0x454, LOWER_CASE, 0x404 }, + { 0x455, LOWER_CASE, 0x405 }, + { 0x456, LOWER_CASE, 0x406 }, + { 0x457, LOWER_CASE, 0x407 }, + { 0x458, LOWER_CASE, 0x408 }, + { 0x459, LOWER_CASE, 0x409 }, + { 0x45A, LOWER_CASE, 0x40A }, + { 0x45B, LOWER_CASE, 0x40B }, + { 0x45C, LOWER_CASE, 0x40C }, + { 0x45D, LOWER_CASE, 0x40D }, + { 0x45E, LOWER_CASE, 0x40E }, + { 0x45F, LOWER_CASE, 0x40F }, + { 0x460, UPPER_CASE, 0x461 }, + { 0x461, LOWER_CASE, 0x460 }, + { 0x462, UPPER_CASE, 0x463 }, + { 0x463, LOWER_CASE, 0x462 }, + { 0x464, UPPER_CASE, 0x465 }, + { 0x465, LOWER_CASE, 0x464 }, + { 0x466, UPPER_CASE, 0x467 }, + { 0x467, LOWER_CASE, 0x466 }, + { 0x468, UPPER_CASE, 0x469 }, + { 0x469, LOWER_CASE, 0x468 }, + { 0x46A, UPPER_CASE, 0x46B }, + { 0x46B, LOWER_CASE, 0x46A }, + { 0x46C, UPPER_CASE, 0x46D }, + { 0x46D, LOWER_CASE, 0x46C }, + { 0x46E, UPPER_CASE, 0x46F }, + { 0x46F, LOWER_CASE, 0x46E }, + { 0x470, UPPER_CASE, 0x471 }, + { 0x471, LOWER_CASE, 0x470 }, + { 0x472, UPPER_CASE, 0x473 }, + { 0x473, LOWER_CASE, 0x472 }, + { 0x474, UPPER_CASE, 0x475 }, + { 0x475, LOWER_CASE, 0x474 }, + { 0x476, UPPER_CASE, 0x477 }, + { 0x477, LOWER_CASE, 0x476 }, + { 0x478, UPPER_CASE, 0x479 }, + { 0x479, LOWER_CASE, 0x478 }, + { 0x47A, UPPER_CASE, 0x47B }, + { 0x47B, LOWER_CASE, 0x47A }, + { 0x47C, UPPER_CASE, 0x47D }, + { 0x47D, LOWER_CASE, 0x47C }, + { 0x47E, UPPER_CASE, 0x47F }, + { 0x47F, LOWER_CASE, 0x47E }, + { 0x480, UPPER_CASE, 0x481 }, + { 0x481, LOWER_CASE, 0x480 }, + { 0x48A, UPPER_CASE, 0x48B }, + { 0x48B, LOWER_CASE, 0x48A }, + { 0x48C, UPPER_CASE, 0x48D }, + { 0x48D, LOWER_CASE, 0x48C }, + { 0x48E, UPPER_CASE, 0x48F }, + { 0x48F, LOWER_CASE, 0x48E }, + { 0x490, UPPER_CASE, 0x491 }, + { 0x491, LOWER_CASE, 0x490 }, + { 0x492, UPPER_CASE, 0x493 }, + { 0x493, LOWER_CASE, 0x492 }, + { 0x494, UPPER_CASE, 0x495 }, + { 0x495, LOWER_CASE, 0x494 }, + { 0x496, UPPER_CASE, 0x497 }, + { 0x497, LOWER_CASE, 0x496 }, + { 0x498, UPPER_CASE, 0x499 }, + { 0x499, LOWER_CASE, 0x498 }, + { 0x49A, UPPER_CASE, 0x49B }, + { 0x49B, LOWER_CASE, 0x49A }, + { 0x49C, UPPER_CASE, 0x49D }, + { 0x49D, LOWER_CASE, 0x49C }, + { 0x49E, UPPER_CASE, 0x49F }, + { 0x49F, LOWER_CASE, 0x49E }, + { 0x4A0, UPPER_CASE, 0x4A1 }, + { 0x4A1, LOWER_CASE, 0x4A0 }, + { 0x4A2, UPPER_CASE, 0x4A3 }, + { 0x4A3, LOWER_CASE, 0x4A2 }, + { 0x4A4, UPPER_CASE, 0x4A5 }, + { 0x4A5, LOWER_CASE, 0x4A4 }, + { 0x4A6, UPPER_CASE, 0x4A7 }, + { 0x4A7, LOWER_CASE, 0x4A6 }, + { 0x4A8, UPPER_CASE, 0x4A9 }, + { 0x4A9, LOWER_CASE, 0x4A8 }, + { 0x4AA, UPPER_CASE, 0x4AB }, + { 0x4AB, LOWER_CASE, 0x4AA }, + { 0x4AC, UPPER_CASE, 0x4AD }, + { 0x4AD, LOWER_CASE, 0x4AC }, + { 0x4AE, UPPER_CASE, 0x4AF }, + { 0x4AF, LOWER_CASE, 0x4AE }, + { 0x4B0, UPPER_CASE, 0x4B1 }, + { 0x4B1, LOWER_CASE, 0x4B0 }, + { 0x4B2, UPPER_CASE, 0x4B3 }, + { 0x4B3, LOWER_CASE, 0x4B2 }, + { 0x4B4, UPPER_CASE, 0x4B5 }, + { 0x4B5, LOWER_CASE, 0x4B4 }, + { 0x4B6, UPPER_CASE, 0x4B7 }, + { 0x4B7, LOWER_CASE, 0x4B6 }, + { 0x4B8, UPPER_CASE, 0x4B9 }, + { 0x4B9, LOWER_CASE, 0x4B8 }, + { 0x4BA, UPPER_CASE, 0x4BB }, + { 0x4BB, LOWER_CASE, 0x4BA }, + { 0x4BC, UPPER_CASE, 0x4BD }, + { 0x4BD, LOWER_CASE, 0x4BC }, + { 0x4BE, UPPER_CASE, 0x4BF }, + { 0x4BF, LOWER_CASE, 0x4BE }, + { 0x4C0, UPPER_CASE, 0x4CF }, + { 0x4C1, UPPER_CASE, 0x4C2 }, + { 0x4C2, LOWER_CASE, 0x4C1 }, + { 0x4C3, UPPER_CASE, 0x4C4 }, + { 0x4C4, LOWER_CASE, 0x4C3 }, + { 0x4C5, UPPER_CASE, 0x4C6 }, + { 0x4C6, LOWER_CASE, 0x4C5 }, + { 0x4C7, UPPER_CASE, 0x4C8 }, + { 0x4C8, LOWER_CASE, 0x4C7 }, + { 0x4C9, UPPER_CASE, 0x4CA }, + { 0x4CA, LOWER_CASE, 0x4C9 }, + { 0x4CB, UPPER_CASE, 0x4CC }, + { 0x4CC, LOWER_CASE, 0x4CB }, + { 0x4CD, UPPER_CASE, 0x4CE }, + { 0x4CE, LOWER_CASE, 0x4CD }, + { 0x4CF, LOWER_CASE, 0x4C0 }, + { 0x4D0, UPPER_CASE, 0x4D1 }, + { 0x4D1, LOWER_CASE, 0x4D0 }, + { 0x4D2, UPPER_CASE, 0x4D3 }, + { 0x4D3, LOWER_CASE, 0x4D2 }, + { 0x4D4, UPPER_CASE, 0x4D5 }, + { 0x4D5, LOWER_CASE, 0x4D4 }, + { 0x4D6, UPPER_CASE, 0x4D7 }, + { 0x4D7, LOWER_CASE, 0x4D6 }, + { 0x4D8, UPPER_CASE, 0x4D9 }, + { 0x4D9, LOWER_CASE, 0x4D8 }, + { 0x4DA, UPPER_CASE, 0x4DB }, + { 0x4DB, LOWER_CASE, 0x4DA }, + { 0x4DC, UPPER_CASE, 0x4DD }, + { 0x4DD, LOWER_CASE, 0x4DC }, + { 0x4DE, UPPER_CASE, 0x4DF }, + { 0x4DF, LOWER_CASE, 0x4DE }, + { 0x4E0, UPPER_CASE, 0x4E1 }, + { 0x4E1, LOWER_CASE, 0x4E0 }, + { 0x4E2, UPPER_CASE, 0x4E3 }, + { 0x4E3, LOWER_CASE, 0x4E2 }, + { 0x4E4, UPPER_CASE, 0x4E5 }, + { 0x4E5, LOWER_CASE, 0x4E4 }, + { 0x4E6, UPPER_CASE, 0x4E7 }, + { 0x4E7, LOWER_CASE, 0x4E6 }, + { 0x4E8, UPPER_CASE, 0x4E9 }, + { 0x4E9, LOWER_CASE, 0x4E8 }, + { 0x4EA, UPPER_CASE, 0x4EB }, + { 0x4EB, LOWER_CASE, 0x4EA }, + { 0x4EC, UPPER_CASE, 0x4ED }, + { 0x4ED, LOWER_CASE, 0x4EC }, + { 0x4EE, UPPER_CASE, 0x4EF }, + { 0x4EF, LOWER_CASE, 0x4EE }, + { 0x4F0, UPPER_CASE, 0x4F1 }, + { 0x4F1, LOWER_CASE, 0x4F0 }, + { 0x4F2, UPPER_CASE, 0x4F3 }, + { 0x4F3, LOWER_CASE, 0x4F2 }, + { 0x4F4, UPPER_CASE, 0x4F5 }, + { 0x4F5, LOWER_CASE, 0x4F4 }, + { 0x4F6, UPPER_CASE, 0x4F7 }, + { 0x4F7, LOWER_CASE, 0x4F6 }, + { 0x4F8, UPPER_CASE, 0x4F9 }, + { 0x4F9, LOWER_CASE, 0x4F8 }, + { 0x4FA, UPPER_CASE, 0x4FB }, + { 0x4FB, LOWER_CASE, 0x4FA }, + { 0x4FC, UPPER_CASE, 0x4FD }, + { 0x4FD, LOWER_CASE, 0x4FC }, + { 0x4FE, UPPER_CASE, 0x4FF }, + { 0x4FF, LOWER_CASE, 0x4FE }, + { 0x500, UPPER_CASE, 0x501 }, + { 0x501, LOWER_CASE, 0x500 }, + { 0x502, UPPER_CASE, 0x503 }, + { 0x503, LOWER_CASE, 0x502 }, + { 0x504, UPPER_CASE, 0x505 }, + { 0x505, LOWER_CASE, 0x504 }, + { 0x506, UPPER_CASE, 0x507 }, + { 0x507, LOWER_CASE, 0x506 }, + { 0x508, UPPER_CASE, 0x509 }, + { 0x509, LOWER_CASE, 0x508 }, + { 0x50A, UPPER_CASE, 0x50B }, + { 0x50B, LOWER_CASE, 0x50A }, + { 0x50C, UPPER_CASE, 0x50D }, + { 0x50D, LOWER_CASE, 0x50C }, + { 0x50E, UPPER_CASE, 0x50F }, + { 0x50F, LOWER_CASE, 0x50E }, + { 0x510, UPPER_CASE, 0x511 }, + { 0x511, LOWER_CASE, 0x510 }, + { 0x512, UPPER_CASE, 0x513 }, + { 0x513, LOWER_CASE, 0x512 }, + { 0x514, UPPER_CASE, 0x515 }, + { 0x515, LOWER_CASE, 0x514 }, + { 0x516, UPPER_CASE, 0x517 }, + { 0x517, LOWER_CASE, 0x516 }, + { 0x518, UPPER_CASE, 0x519 }, + { 0x519, LOWER_CASE, 0x518 }, + { 0x51A, UPPER_CASE, 0x51B }, + { 0x51B, LOWER_CASE, 0x51A }, + { 0x51C, UPPER_CASE, 0x51D }, + { 0x51D, LOWER_CASE, 0x51C }, + { 0x51E, UPPER_CASE, 0x51F }, + { 0x51F, LOWER_CASE, 0x51E }, + { 0x520, UPPER_CASE, 0x521 }, + { 0x521, LOWER_CASE, 0x520 }, + { 0x522, UPPER_CASE, 0x523 }, + { 0x523, LOWER_CASE, 0x522 }, + { 0x524, UPPER_CASE, 0x525 }, + { 0x525, LOWER_CASE, 0x524 }, + { 0x526, UPPER_CASE, 0x527 }, + { 0x527, LOWER_CASE, 0x526 }, + { 0x528, UPPER_CASE, 0x529 }, + { 0x529, LOWER_CASE, 0x528 }, + { 0x52A, UPPER_CASE, 0x52B }, + { 0x52B, LOWER_CASE, 0x52A }, + { 0x52C, UPPER_CASE, 0x52D }, + { 0x52D, LOWER_CASE, 0x52C }, + { 0x52E, UPPER_CASE, 0x52F }, + { 0x52F, LOWER_CASE, 0x52E }, + { 0x531, UPPER_CASE, 0x561 }, + { 0x532, UPPER_CASE, 0x562 }, + { 0x533, UPPER_CASE, 0x563 }, + { 0x534, UPPER_CASE, 0x564 }, + { 0x535, UPPER_CASE, 0x565 }, + { 0x536, UPPER_CASE, 0x566 }, + { 0x537, UPPER_CASE, 0x567 }, + { 0x538, UPPER_CASE, 0x568 }, + { 0x539, UPPER_CASE, 0x569 }, + { 0x53A, UPPER_CASE, 0x56A }, + { 0x53B, UPPER_CASE, 0x56B }, + { 0x53C, UPPER_CASE, 0x56C }, + { 0x53D, UPPER_CASE, 0x56D }, + { 0x53E, UPPER_CASE, 0x56E }, + { 0x53F, UPPER_CASE, 0x56F }, + { 0x540, UPPER_CASE, 0x570 }, + { 0x541, UPPER_CASE, 0x571 }, + { 0x542, UPPER_CASE, 0x572 }, + { 0x543, UPPER_CASE, 0x573 }, + { 0x544, UPPER_CASE, 0x574 }, + { 0x545, UPPER_CASE, 0x575 }, + { 0x546, UPPER_CASE, 0x576 }, + { 0x547, UPPER_CASE, 0x577 }, + { 0x548, UPPER_CASE, 0x578 }, + { 0x549, UPPER_CASE, 0x579 }, + { 0x54A, UPPER_CASE, 0x57A }, + { 0x54B, UPPER_CASE, 0x57B }, + { 0x54C, UPPER_CASE, 0x57C }, + { 0x54D, UPPER_CASE, 0x57D }, + { 0x54E, UPPER_CASE, 0x57E }, + { 0x54F, UPPER_CASE, 0x57F }, + { 0x550, UPPER_CASE, 0x580 }, + { 0x551, UPPER_CASE, 0x581 }, + { 0x552, UPPER_CASE, 0x582 }, + { 0x553, UPPER_CASE, 0x583 }, + { 0x554, UPPER_CASE, 0x584 }, + { 0x555, UPPER_CASE, 0x585 }, + { 0x556, UPPER_CASE, 0x586 }, + { 0x561, LOWER_CASE, 0x531 }, + { 0x562, LOWER_CASE, 0x532 }, + { 0x563, LOWER_CASE, 0x533 }, + { 0x564, LOWER_CASE, 0x534 }, + { 0x565, LOWER_CASE, 0x535 }, + { 0x566, LOWER_CASE, 0x536 }, + { 0x567, LOWER_CASE, 0x537 }, + { 0x568, LOWER_CASE, 0x538 }, + { 0x569, LOWER_CASE, 0x539 }, + { 0x56A, LOWER_CASE, 0x53A }, + { 0x56B, LOWER_CASE, 0x53B }, + { 0x56C, LOWER_CASE, 0x53C }, + { 0x56D, LOWER_CASE, 0x53D }, + { 0x56E, LOWER_CASE, 0x53E }, + { 0x56F, LOWER_CASE, 0x53F }, + { 0x570, LOWER_CASE, 0x540 }, + { 0x571, LOWER_CASE, 0x541 }, + { 0x572, LOWER_CASE, 0x542 }, + { 0x573, LOWER_CASE, 0x543 }, + { 0x574, LOWER_CASE, 0x544 }, + { 0x575, LOWER_CASE, 0x545 }, + { 0x576, LOWER_CASE, 0x546 }, + { 0x577, LOWER_CASE, 0x547 }, + { 0x578, LOWER_CASE, 0x548 }, + { 0x579, LOWER_CASE, 0x549 }, + { 0x57A, LOWER_CASE, 0x54A }, + { 0x57B, LOWER_CASE, 0x54B }, + { 0x57C, LOWER_CASE, 0x54C }, + { 0x57D, LOWER_CASE, 0x54D }, + { 0x57E, LOWER_CASE, 0x54E }, + { 0x57F, LOWER_CASE, 0x54F }, + { 0x580, LOWER_CASE, 0x550 }, + { 0x581, LOWER_CASE, 0x551 }, + { 0x582, LOWER_CASE, 0x552 }, + { 0x583, LOWER_CASE, 0x553 }, + { 0x584, LOWER_CASE, 0x554 }, + { 0x585, LOWER_CASE, 0x555 }, + { 0x586, LOWER_CASE, 0x556 }, + { 0x10A0, UPPER_CASE, 0x2D00 }, + { 0x10A1, UPPER_CASE, 0x2D01 }, + { 0x10A2, UPPER_CASE, 0x2D02 }, + { 0x10A3, UPPER_CASE, 0x2D03 }, + { 0x10A4, UPPER_CASE, 0x2D04 }, + { 0x10A5, UPPER_CASE, 0x2D05 }, + { 0x10A6, UPPER_CASE, 0x2D06 }, + { 0x10A7, UPPER_CASE, 0x2D07 }, + { 0x10A8, UPPER_CASE, 0x2D08 }, + { 0x10A9, UPPER_CASE, 0x2D09 }, + { 0x10AA, UPPER_CASE, 0x2D0A }, + { 0x10AB, UPPER_CASE, 0x2D0B }, + { 0x10AC, UPPER_CASE, 0x2D0C }, + { 0x10AD, UPPER_CASE, 0x2D0D }, + { 0x10AE, UPPER_CASE, 0x2D0E }, + { 0x10AF, UPPER_CASE, 0x2D0F }, + { 0x10B0, UPPER_CASE, 0x2D10 }, + { 0x10B1, UPPER_CASE, 0x2D11 }, + { 0x10B2, UPPER_CASE, 0x2D12 }, + { 0x10B3, UPPER_CASE, 0x2D13 }, + { 0x10B4, UPPER_CASE, 0x2D14 }, + { 0x10B5, UPPER_CASE, 0x2D15 }, + { 0x10B6, UPPER_CASE, 0x2D16 }, + { 0x10B7, UPPER_CASE, 0x2D17 }, + { 0x10B8, UPPER_CASE, 0x2D18 }, + { 0x10B9, UPPER_CASE, 0x2D19 }, + { 0x10BA, UPPER_CASE, 0x2D1A }, + { 0x10BB, UPPER_CASE, 0x2D1B }, + { 0x10BC, UPPER_CASE, 0x2D1C }, + { 0x10BD, UPPER_CASE, 0x2D1D }, + { 0x10BE, UPPER_CASE, 0x2D1E }, + { 0x10BF, UPPER_CASE, 0x2D1F }, + { 0x10C0, UPPER_CASE, 0x2D20 }, + { 0x10C1, UPPER_CASE, 0x2D21 }, + { 0x10C2, UPPER_CASE, 0x2D22 }, + { 0x10C3, UPPER_CASE, 0x2D23 }, + { 0x10C4, UPPER_CASE, 0x2D24 }, + { 0x10C5, UPPER_CASE, 0x2D25 }, + { 0x10C7, UPPER_CASE, 0x2D27 }, + { 0x10CD, UPPER_CASE, 0x2D2D }, + { 0x10D0, LOWER_CASE, 0x1C90 }, + { 0x10D1, LOWER_CASE, 0x1C91 }, + { 0x10D2, LOWER_CASE, 0x1C92 }, + { 0x10D3, LOWER_CASE, 0x1C93 }, + { 0x10D4, LOWER_CASE, 0x1C94 }, + { 0x10D5, LOWER_CASE, 0x1C95 }, + { 0x10D6, LOWER_CASE, 0x1C96 }, + { 0x10D7, LOWER_CASE, 0x1C97 }, + { 0x10D8, LOWER_CASE, 0x1C98 }, + { 0x10D9, LOWER_CASE, 0x1C99 }, + { 0x10DA, LOWER_CASE, 0x1C9A }, + { 0x10DB, LOWER_CASE, 0x1C9B }, + { 0x10DC, LOWER_CASE, 0x1C9C }, + { 0x10DD, LOWER_CASE, 0x1C9D }, + { 0x10DE, LOWER_CASE, 0x1C9E }, + { 0x10DF, LOWER_CASE, 0x1C9F }, + { 0x10E0, LOWER_CASE, 0x1CA0 }, + { 0x10E1, LOWER_CASE, 0x1CA1 }, + { 0x10E2, LOWER_CASE, 0x1CA2 }, + { 0x10E3, LOWER_CASE, 0x1CA3 }, + { 0x10E4, LOWER_CASE, 0x1CA4 }, + { 0x10E5, LOWER_CASE, 0x1CA5 }, + { 0x10E6, LOWER_CASE, 0x1CA6 }, + { 0x10E7, LOWER_CASE, 0x1CA7 }, + { 0x10E8, LOWER_CASE, 0x1CA8 }, + { 0x10E9, LOWER_CASE, 0x1CA9 }, + { 0x10EA, LOWER_CASE, 0x1CAA }, + { 0x10EB, LOWER_CASE, 0x1CAB }, + { 0x10EC, LOWER_CASE, 0x1CAC }, + { 0x10ED, LOWER_CASE, 0x1CAD }, + { 0x10EE, LOWER_CASE, 0x1CAE }, + { 0x10EF, LOWER_CASE, 0x1CAF }, + { 0x10F0, LOWER_CASE, 0x1CB0 }, + { 0x10F1, LOWER_CASE, 0x1CB1 }, + { 0x10F2, LOWER_CASE, 0x1CB2 }, + { 0x10F3, LOWER_CASE, 0x1CB3 }, + { 0x10F4, LOWER_CASE, 0x1CB4 }, + { 0x10F5, LOWER_CASE, 0x1CB5 }, + { 0x10F6, LOWER_CASE, 0x1CB6 }, + { 0x10F7, LOWER_CASE, 0x1CB7 }, + { 0x10F8, LOWER_CASE, 0x1CB8 }, + { 0x10F9, LOWER_CASE, 0x1CB9 }, + { 0x10FA, LOWER_CASE, 0x1CBA }, + { 0x10FD, LOWER_CASE, 0x1CBD }, + { 0x10FE, LOWER_CASE, 0x1CBE }, + { 0x10FF, LOWER_CASE, 0x1CBF }, + { 0x13A0, UPPER_CASE, 0xAB70 }, + { 0x13A1, UPPER_CASE, 0xAB71 }, + { 0x13A2, UPPER_CASE, 0xAB72 }, + { 0x13A3, UPPER_CASE, 0xAB73 }, + { 0x13A4, UPPER_CASE, 0xAB74 }, + { 0x13A5, UPPER_CASE, 0xAB75 }, + { 0x13A6, UPPER_CASE, 0xAB76 }, + { 0x13A7, UPPER_CASE, 0xAB77 }, + { 0x13A8, UPPER_CASE, 0xAB78 }, + { 0x13A9, UPPER_CASE, 0xAB79 }, + { 0x13AA, UPPER_CASE, 0xAB7A }, + { 0x13AB, UPPER_CASE, 0xAB7B }, + { 0x13AC, UPPER_CASE, 0xAB7C }, + { 0x13AD, UPPER_CASE, 0xAB7D }, + { 0x13AE, UPPER_CASE, 0xAB7E }, + { 0x13AF, UPPER_CASE, 0xAB7F }, + { 0x13B0, UPPER_CASE, 0xAB80 }, + { 0x13B1, UPPER_CASE, 0xAB81 }, + { 0x13B2, UPPER_CASE, 0xAB82 }, + { 0x13B3, UPPER_CASE, 0xAB83 }, + { 0x13B4, UPPER_CASE, 0xAB84 }, + { 0x13B5, UPPER_CASE, 0xAB85 }, + { 0x13B6, UPPER_CASE, 0xAB86 }, + { 0x13B7, UPPER_CASE, 0xAB87 }, + { 0x13B8, UPPER_CASE, 0xAB88 }, + { 0x13B9, UPPER_CASE, 0xAB89 }, + { 0x13BA, UPPER_CASE, 0xAB8A }, + { 0x13BB, UPPER_CASE, 0xAB8B }, + { 0x13BC, UPPER_CASE, 0xAB8C }, + { 0x13BD, UPPER_CASE, 0xAB8D }, + { 0x13BE, UPPER_CASE, 0xAB8E }, + { 0x13BF, UPPER_CASE, 0xAB8F }, + { 0x13C0, UPPER_CASE, 0xAB90 }, + { 0x13C1, UPPER_CASE, 0xAB91 }, + { 0x13C2, UPPER_CASE, 0xAB92 }, + { 0x13C3, UPPER_CASE, 0xAB93 }, + { 0x13C4, UPPER_CASE, 0xAB94 }, + { 0x13C5, UPPER_CASE, 0xAB95 }, + { 0x13C6, UPPER_CASE, 0xAB96 }, + { 0x13C7, UPPER_CASE, 0xAB97 }, + { 0x13C8, UPPER_CASE, 0xAB98 }, + { 0x13C9, UPPER_CASE, 0xAB99 }, + { 0x13CA, UPPER_CASE, 0xAB9A }, + { 0x13CB, UPPER_CASE, 0xAB9B }, + { 0x13CC, UPPER_CASE, 0xAB9C }, + { 0x13CD, UPPER_CASE, 0xAB9D }, + { 0x13CE, UPPER_CASE, 0xAB9E }, + { 0x13CF, UPPER_CASE, 0xAB9F }, + { 0x13D0, UPPER_CASE, 0xABA0 }, + { 0x13D1, UPPER_CASE, 0xABA1 }, + { 0x13D2, UPPER_CASE, 0xABA2 }, + { 0x13D3, UPPER_CASE, 0xABA3 }, + { 0x13D4, UPPER_CASE, 0xABA4 }, + { 0x13D5, UPPER_CASE, 0xABA5 }, + { 0x13D6, UPPER_CASE, 0xABA6 }, + { 0x13D7, UPPER_CASE, 0xABA7 }, + { 0x13D8, UPPER_CASE, 0xABA8 }, + { 0x13D9, UPPER_CASE, 0xABA9 }, + { 0x13DA, UPPER_CASE, 0xABAA }, + { 0x13DB, UPPER_CASE, 0xABAB }, + { 0x13DC, UPPER_CASE, 0xABAC }, + { 0x13DD, UPPER_CASE, 0xABAD }, + { 0x13DE, UPPER_CASE, 0xABAE }, + { 0x13DF, UPPER_CASE, 0xABAF }, + { 0x13E0, UPPER_CASE, 0xABB0 }, + { 0x13E1, UPPER_CASE, 0xABB1 }, + { 0x13E2, UPPER_CASE, 0xABB2 }, + { 0x13E3, UPPER_CASE, 0xABB3 }, + { 0x13E4, UPPER_CASE, 0xABB4 }, + { 0x13E5, UPPER_CASE, 0xABB5 }, + { 0x13E6, UPPER_CASE, 0xABB6 }, + { 0x13E7, UPPER_CASE, 0xABB7 }, + { 0x13E8, UPPER_CASE, 0xABB8 }, + { 0x13E9, UPPER_CASE, 0xABB9 }, + { 0x13EA, UPPER_CASE, 0xABBA }, + { 0x13EB, UPPER_CASE, 0xABBB }, + { 0x13EC, UPPER_CASE, 0xABBC }, + { 0x13ED, UPPER_CASE, 0xABBD }, + { 0x13EE, UPPER_CASE, 0xABBE }, + { 0x13EF, UPPER_CASE, 0xABBF }, + { 0x13F0, UPPER_CASE, 0x13F8 }, + { 0x13F1, UPPER_CASE, 0x13F9 }, + { 0x13F2, UPPER_CASE, 0x13FA }, + { 0x13F3, UPPER_CASE, 0x13FB }, + { 0x13F4, UPPER_CASE, 0x13FC }, + { 0x13F5, UPPER_CASE, 0x13FD }, + { 0x13F8, LOWER_CASE, 0x13F0 }, + { 0x13F9, LOWER_CASE, 0x13F1 }, + { 0x13FA, LOWER_CASE, 0x13F2 }, + { 0x13FB, LOWER_CASE, 0x13F3 }, + { 0x13FC, LOWER_CASE, 0x13F4 }, + { 0x13FD, LOWER_CASE, 0x13F5 }, + { 0x1C80, LOWER_CASE, 0x412 }, + { 0x1C81, LOWER_CASE, 0x414 }, + { 0x1C82, LOWER_CASE, 0x41E }, + { 0x1C83, LOWER_CASE, 0x421 }, + { 0x1C84, LOWER_CASE, 0x422 }, + { 0x1C85, LOWER_CASE, 0x422 }, + { 0x1C86, LOWER_CASE, 0x42A }, + { 0x1C87, LOWER_CASE, 0x462 }, + { 0x1C88, LOWER_CASE, 0xA64A }, + { 0x1C90, UPPER_CASE, 0x10D0 }, + { 0x1C91, UPPER_CASE, 0x10D1 }, + { 0x1C92, UPPER_CASE, 0x10D2 }, + { 0x1C93, UPPER_CASE, 0x10D3 }, + { 0x1C94, UPPER_CASE, 0x10D4 }, + { 0x1C95, UPPER_CASE, 0x10D5 }, + { 0x1C96, UPPER_CASE, 0x10D6 }, + { 0x1C97, UPPER_CASE, 0x10D7 }, + { 0x1C98, UPPER_CASE, 0x10D8 }, + { 0x1C99, UPPER_CASE, 0x10D9 }, + { 0x1C9A, UPPER_CASE, 0x10DA }, + { 0x1C9B, UPPER_CASE, 0x10DB }, + { 0x1C9C, UPPER_CASE, 0x10DC }, + { 0x1C9D, UPPER_CASE, 0x10DD }, + { 0x1C9E, UPPER_CASE, 0x10DE }, + { 0x1C9F, UPPER_CASE, 0x10DF }, + { 0x1CA0, UPPER_CASE, 0x10E0 }, + { 0x1CA1, UPPER_CASE, 0x10E1 }, + { 0x1CA2, UPPER_CASE, 0x10E2 }, + { 0x1CA3, UPPER_CASE, 0x10E3 }, + { 0x1CA4, UPPER_CASE, 0x10E4 }, + { 0x1CA5, UPPER_CASE, 0x10E5 }, + { 0x1CA6, UPPER_CASE, 0x10E6 }, + { 0x1CA7, UPPER_CASE, 0x10E7 }, + { 0x1CA8, UPPER_CASE, 0x10E8 }, + { 0x1CA9, UPPER_CASE, 0x10E9 }, + { 0x1CAA, UPPER_CASE, 0x10EA }, + { 0x1CAB, UPPER_CASE, 0x10EB }, + { 0x1CAC, UPPER_CASE, 0x10EC }, + { 0x1CAD, UPPER_CASE, 0x10ED }, + { 0x1CAE, UPPER_CASE, 0x10EE }, + { 0x1CAF, UPPER_CASE, 0x10EF }, + { 0x1CB0, UPPER_CASE, 0x10F0 }, + { 0x1CB1, UPPER_CASE, 0x10F1 }, + { 0x1CB2, UPPER_CASE, 0x10F2 }, + { 0x1CB3, UPPER_CASE, 0x10F3 }, + { 0x1CB4, UPPER_CASE, 0x10F4 }, + { 0x1CB5, UPPER_CASE, 0x10F5 }, + { 0x1CB6, UPPER_CASE, 0x10F6 }, + { 0x1CB7, UPPER_CASE, 0x10F7 }, + { 0x1CB8, UPPER_CASE, 0x10F8 }, + { 0x1CB9, UPPER_CASE, 0x10F9 }, + { 0x1CBA, UPPER_CASE, 0x10FA }, + { 0x1CBD, UPPER_CASE, 0x10FD }, + { 0x1CBE, UPPER_CASE, 0x10FE }, + { 0x1CBF, UPPER_CASE, 0x10FF }, + { 0x1D79, LOWER_CASE, 0xA77D }, + { 0x1D7D, LOWER_CASE, 0x2C63 }, + { 0x1D8E, LOWER_CASE, 0xA7C6 }, + { 0x1E00, UPPER_CASE, 0x1E01 }, + { 0x1E01, LOWER_CASE, 0x1E00 }, + { 0x1E02, UPPER_CASE, 0x1E03 }, + { 0x1E03, LOWER_CASE, 0x1E02 }, + { 0x1E04, UPPER_CASE, 0x1E05 }, + { 0x1E05, LOWER_CASE, 0x1E04 }, + { 0x1E06, UPPER_CASE, 0x1E07 }, + { 0x1E07, LOWER_CASE, 0x1E06 }, + { 0x1E08, UPPER_CASE, 0x1E09 }, + { 0x1E09, LOWER_CASE, 0x1E08 }, + { 0x1E0A, UPPER_CASE, 0x1E0B }, + { 0x1E0B, LOWER_CASE, 0x1E0A }, + { 0x1E0C, UPPER_CASE, 0x1E0D }, + { 0x1E0D, LOWER_CASE, 0x1E0C }, + { 0x1E0E, UPPER_CASE, 0x1E0F }, + { 0x1E0F, LOWER_CASE, 0x1E0E }, + { 0x1E10, UPPER_CASE, 0x1E11 }, + { 0x1E11, LOWER_CASE, 0x1E10 }, + { 0x1E12, UPPER_CASE, 0x1E13 }, + { 0x1E13, LOWER_CASE, 0x1E12 }, + { 0x1E14, UPPER_CASE, 0x1E15 }, + { 0x1E15, LOWER_CASE, 0x1E14 }, + { 0x1E16, UPPER_CASE, 0x1E17 }, + { 0x1E17, LOWER_CASE, 0x1E16 }, + { 0x1E18, UPPER_CASE, 0x1E19 }, + { 0x1E19, LOWER_CASE, 0x1E18 }, + { 0x1E1A, UPPER_CASE, 0x1E1B }, + { 0x1E1B, LOWER_CASE, 0x1E1A }, + { 0x1E1C, UPPER_CASE, 0x1E1D }, + { 0x1E1D, LOWER_CASE, 0x1E1C }, + { 0x1E1E, UPPER_CASE, 0x1E1F }, + { 0x1E1F, LOWER_CASE, 0x1E1E }, + { 0x1E20, UPPER_CASE, 0x1E21 }, + { 0x1E21, LOWER_CASE, 0x1E20 }, + { 0x1E22, UPPER_CASE, 0x1E23 }, + { 0x1E23, LOWER_CASE, 0x1E22 }, + { 0x1E24, UPPER_CASE, 0x1E25 }, + { 0x1E25, LOWER_CASE, 0x1E24 }, + { 0x1E26, UPPER_CASE, 0x1E27 }, + { 0x1E27, LOWER_CASE, 0x1E26 }, + { 0x1E28, UPPER_CASE, 0x1E29 }, + { 0x1E29, LOWER_CASE, 0x1E28 }, + { 0x1E2A, UPPER_CASE, 0x1E2B }, + { 0x1E2B, LOWER_CASE, 0x1E2A }, + { 0x1E2C, UPPER_CASE, 0x1E2D }, + { 0x1E2D, LOWER_CASE, 0x1E2C }, + { 0x1E2E, UPPER_CASE, 0x1E2F }, + { 0x1E2F, LOWER_CASE, 0x1E2E }, + { 0x1E30, UPPER_CASE, 0x1E31 }, + { 0x1E31, LOWER_CASE, 0x1E30 }, + { 0x1E32, UPPER_CASE, 0x1E33 }, + { 0x1E33, LOWER_CASE, 0x1E32 }, + { 0x1E34, UPPER_CASE, 0x1E35 }, + { 0x1E35, LOWER_CASE, 0x1E34 }, + { 0x1E36, UPPER_CASE, 0x1E37 }, + { 0x1E37, LOWER_CASE, 0x1E36 }, + { 0x1E38, UPPER_CASE, 0x1E39 }, + { 0x1E39, LOWER_CASE, 0x1E38 }, + { 0x1E3A, UPPER_CASE, 0x1E3B }, + { 0x1E3B, LOWER_CASE, 0x1E3A }, + { 0x1E3C, UPPER_CASE, 0x1E3D }, + { 0x1E3D, LOWER_CASE, 0x1E3C }, + { 0x1E3E, UPPER_CASE, 0x1E3F }, + { 0x1E3F, LOWER_CASE, 0x1E3E }, + { 0x1E40, UPPER_CASE, 0x1E41 }, + { 0x1E41, LOWER_CASE, 0x1E40 }, + { 0x1E42, UPPER_CASE, 0x1E43 }, + { 0x1E43, LOWER_CASE, 0x1E42 }, + { 0x1E44, UPPER_CASE, 0x1E45 }, + { 0x1E45, LOWER_CASE, 0x1E44 }, + { 0x1E46, UPPER_CASE, 0x1E47 }, + { 0x1E47, LOWER_CASE, 0x1E46 }, + { 0x1E48, UPPER_CASE, 0x1E49 }, + { 0x1E49, LOWER_CASE, 0x1E48 }, + { 0x1E4A, UPPER_CASE, 0x1E4B }, + { 0x1E4B, LOWER_CASE, 0x1E4A }, + { 0x1E4C, UPPER_CASE, 0x1E4D }, + { 0x1E4D, LOWER_CASE, 0x1E4C }, + { 0x1E4E, UPPER_CASE, 0x1E4F }, + { 0x1E4F, LOWER_CASE, 0x1E4E }, + { 0x1E50, UPPER_CASE, 0x1E51 }, + { 0x1E51, LOWER_CASE, 0x1E50 }, + { 0x1E52, UPPER_CASE, 0x1E53 }, + { 0x1E53, LOWER_CASE, 0x1E52 }, + { 0x1E54, UPPER_CASE, 0x1E55 }, + { 0x1E55, LOWER_CASE, 0x1E54 }, + { 0x1E56, UPPER_CASE, 0x1E57 }, + { 0x1E57, LOWER_CASE, 0x1E56 }, + { 0x1E58, UPPER_CASE, 0x1E59 }, + { 0x1E59, LOWER_CASE, 0x1E58 }, + { 0x1E5A, UPPER_CASE, 0x1E5B }, + { 0x1E5B, LOWER_CASE, 0x1E5A }, + { 0x1E5C, UPPER_CASE, 0x1E5D }, + { 0x1E5D, LOWER_CASE, 0x1E5C }, + { 0x1E5E, UPPER_CASE, 0x1E5F }, + { 0x1E5F, LOWER_CASE, 0x1E5E }, + { 0x1E60, UPPER_CASE, 0x1E61 }, + { 0x1E61, LOWER_CASE, 0x1E60 }, + { 0x1E62, UPPER_CASE, 0x1E63 }, + { 0x1E63, LOWER_CASE, 0x1E62 }, + { 0x1E64, UPPER_CASE, 0x1E65 }, + { 0x1E65, LOWER_CASE, 0x1E64 }, + { 0x1E66, UPPER_CASE, 0x1E67 }, + { 0x1E67, LOWER_CASE, 0x1E66 }, + { 0x1E68, UPPER_CASE, 0x1E69 }, + { 0x1E69, LOWER_CASE, 0x1E68 }, + { 0x1E6A, UPPER_CASE, 0x1E6B }, + { 0x1E6B, LOWER_CASE, 0x1E6A }, + { 0x1E6C, UPPER_CASE, 0x1E6D }, + { 0x1E6D, LOWER_CASE, 0x1E6C }, + { 0x1E6E, UPPER_CASE, 0x1E6F }, + { 0x1E6F, LOWER_CASE, 0x1E6E }, + { 0x1E70, UPPER_CASE, 0x1E71 }, + { 0x1E71, LOWER_CASE, 0x1E70 }, + { 0x1E72, UPPER_CASE, 0x1E73 }, + { 0x1E73, LOWER_CASE, 0x1E72 }, + { 0x1E74, UPPER_CASE, 0x1E75 }, + { 0x1E75, LOWER_CASE, 0x1E74 }, + { 0x1E76, UPPER_CASE, 0x1E77 }, + { 0x1E77, LOWER_CASE, 0x1E76 }, + { 0x1E78, UPPER_CASE, 0x1E79 }, + { 0x1E79, LOWER_CASE, 0x1E78 }, + { 0x1E7A, UPPER_CASE, 0x1E7B }, + { 0x1E7B, LOWER_CASE, 0x1E7A }, + { 0x1E7C, UPPER_CASE, 0x1E7D }, + { 0x1E7D, LOWER_CASE, 0x1E7C }, + { 0x1E7E, UPPER_CASE, 0x1E7F }, + { 0x1E7F, LOWER_CASE, 0x1E7E }, + { 0x1E80, UPPER_CASE, 0x1E81 }, + { 0x1E81, LOWER_CASE, 0x1E80 }, + { 0x1E82, UPPER_CASE, 0x1E83 }, + { 0x1E83, LOWER_CASE, 0x1E82 }, + { 0x1E84, UPPER_CASE, 0x1E85 }, + { 0x1E85, LOWER_CASE, 0x1E84 }, + { 0x1E86, UPPER_CASE, 0x1E87 }, + { 0x1E87, LOWER_CASE, 0x1E86 }, + { 0x1E88, UPPER_CASE, 0x1E89 }, + { 0x1E89, LOWER_CASE, 0x1E88 }, + { 0x1E8A, UPPER_CASE, 0x1E8B }, + { 0x1E8B, LOWER_CASE, 0x1E8A }, + { 0x1E8C, UPPER_CASE, 0x1E8D }, + { 0x1E8D, LOWER_CASE, 0x1E8C }, + { 0x1E8E, UPPER_CASE, 0x1E8F }, + { 0x1E8F, LOWER_CASE, 0x1E8E }, + { 0x1E90, UPPER_CASE, 0x1E91 }, + { 0x1E91, LOWER_CASE, 0x1E90 }, + { 0x1E92, UPPER_CASE, 0x1E93 }, + { 0x1E93, LOWER_CASE, 0x1E92 }, + { 0x1E94, UPPER_CASE, 0x1E95 }, + { 0x1E95, LOWER_CASE, 0x1E94 }, + { 0x1E9B, LOWER_CASE, 0x1E60 }, + { 0x1E9E, UPPER_CASE, 0xDF }, + { 0x1EA0, UPPER_CASE, 0x1EA1 }, + { 0x1EA1, LOWER_CASE, 0x1EA0 }, + { 0x1EA2, UPPER_CASE, 0x1EA3 }, + { 0x1EA3, LOWER_CASE, 0x1EA2 }, + { 0x1EA4, UPPER_CASE, 0x1EA5 }, + { 0x1EA5, LOWER_CASE, 0x1EA4 }, + { 0x1EA6, UPPER_CASE, 0x1EA7 }, + { 0x1EA7, LOWER_CASE, 0x1EA6 }, + { 0x1EA8, UPPER_CASE, 0x1EA9 }, + { 0x1EA9, LOWER_CASE, 0x1EA8 }, + { 0x1EAA, UPPER_CASE, 0x1EAB }, + { 0x1EAB, LOWER_CASE, 0x1EAA }, + { 0x1EAC, UPPER_CASE, 0x1EAD }, + { 0x1EAD, LOWER_CASE, 0x1EAC }, + { 0x1EAE, UPPER_CASE, 0x1EAF }, + { 0x1EAF, LOWER_CASE, 0x1EAE }, + { 0x1EB0, UPPER_CASE, 0x1EB1 }, + { 0x1EB1, LOWER_CASE, 0x1EB0 }, + { 0x1EB2, UPPER_CASE, 0x1EB3 }, + { 0x1EB3, LOWER_CASE, 0x1EB2 }, + { 0x1EB4, UPPER_CASE, 0x1EB5 }, + { 0x1EB5, LOWER_CASE, 0x1EB4 }, + { 0x1EB6, UPPER_CASE, 0x1EB7 }, + { 0x1EB7, LOWER_CASE, 0x1EB6 }, + { 0x1EB8, UPPER_CASE, 0x1EB9 }, + { 0x1EB9, LOWER_CASE, 0x1EB8 }, + { 0x1EBA, UPPER_CASE, 0x1EBB }, + { 0x1EBB, LOWER_CASE, 0x1EBA }, + { 0x1EBC, UPPER_CASE, 0x1EBD }, + { 0x1EBD, LOWER_CASE, 0x1EBC }, + { 0x1EBE, UPPER_CASE, 0x1EBF }, + { 0x1EBF, LOWER_CASE, 0x1EBE }, + { 0x1EC0, UPPER_CASE, 0x1EC1 }, + { 0x1EC1, LOWER_CASE, 0x1EC0 }, + { 0x1EC2, UPPER_CASE, 0x1EC3 }, + { 0x1EC3, LOWER_CASE, 0x1EC2 }, + { 0x1EC4, UPPER_CASE, 0x1EC5 }, + { 0x1EC5, LOWER_CASE, 0x1EC4 }, + { 0x1EC6, UPPER_CASE, 0x1EC7 }, + { 0x1EC7, LOWER_CASE, 0x1EC6 }, + { 0x1EC8, UPPER_CASE, 0x1EC9 }, + { 0x1EC9, LOWER_CASE, 0x1EC8 }, + { 0x1ECA, UPPER_CASE, 0x1ECB }, + { 0x1ECB, LOWER_CASE, 0x1ECA }, + { 0x1ECC, UPPER_CASE, 0x1ECD }, + { 0x1ECD, LOWER_CASE, 0x1ECC }, + { 0x1ECE, UPPER_CASE, 0x1ECF }, + { 0x1ECF, LOWER_CASE, 0x1ECE }, + { 0x1ED0, UPPER_CASE, 0x1ED1 }, + { 0x1ED1, LOWER_CASE, 0x1ED0 }, + { 0x1ED2, UPPER_CASE, 0x1ED3 }, + { 0x1ED3, LOWER_CASE, 0x1ED2 }, + { 0x1ED4, UPPER_CASE, 0x1ED5 }, + { 0x1ED5, LOWER_CASE, 0x1ED4 }, + { 0x1ED6, UPPER_CASE, 0x1ED7 }, + { 0x1ED7, LOWER_CASE, 0x1ED6 }, + { 0x1ED8, UPPER_CASE, 0x1ED9 }, + { 0x1ED9, LOWER_CASE, 0x1ED8 }, + { 0x1EDA, UPPER_CASE, 0x1EDB }, + { 0x1EDB, LOWER_CASE, 0x1EDA }, + { 0x1EDC, UPPER_CASE, 0x1EDD }, + { 0x1EDD, LOWER_CASE, 0x1EDC }, + { 0x1EDE, UPPER_CASE, 0x1EDF }, + { 0x1EDF, LOWER_CASE, 0x1EDE }, + { 0x1EE0, UPPER_CASE, 0x1EE1 }, + { 0x1EE1, LOWER_CASE, 0x1EE0 }, + { 0x1EE2, UPPER_CASE, 0x1EE3 }, + { 0x1EE3, LOWER_CASE, 0x1EE2 }, + { 0x1EE4, UPPER_CASE, 0x1EE5 }, + { 0x1EE5, LOWER_CASE, 0x1EE4 }, + { 0x1EE6, UPPER_CASE, 0x1EE7 }, + { 0x1EE7, LOWER_CASE, 0x1EE6 }, + { 0x1EE8, UPPER_CASE, 0x1EE9 }, + { 0x1EE9, LOWER_CASE, 0x1EE8 }, + { 0x1EEA, UPPER_CASE, 0x1EEB }, + { 0x1EEB, LOWER_CASE, 0x1EEA }, + { 0x1EEC, UPPER_CASE, 0x1EED }, + { 0x1EED, LOWER_CASE, 0x1EEC }, + { 0x1EEE, UPPER_CASE, 0x1EEF }, + { 0x1EEF, LOWER_CASE, 0x1EEE }, + { 0x1EF0, UPPER_CASE, 0x1EF1 }, + { 0x1EF1, LOWER_CASE, 0x1EF0 }, + { 0x1EF2, UPPER_CASE, 0x1EF3 }, + { 0x1EF3, LOWER_CASE, 0x1EF2 }, + { 0x1EF4, UPPER_CASE, 0x1EF5 }, + { 0x1EF5, LOWER_CASE, 0x1EF4 }, + { 0x1EF6, UPPER_CASE, 0x1EF7 }, + { 0x1EF7, LOWER_CASE, 0x1EF6 }, + { 0x1EF8, UPPER_CASE, 0x1EF9 }, + { 0x1EF9, LOWER_CASE, 0x1EF8 }, + { 0x1EFA, UPPER_CASE, 0x1EFB }, + { 0x1EFB, LOWER_CASE, 0x1EFA }, + { 0x1EFC, UPPER_CASE, 0x1EFD }, + { 0x1EFD, LOWER_CASE, 0x1EFC }, + { 0x1EFE, UPPER_CASE, 0x1EFF }, + { 0x1EFF, LOWER_CASE, 0x1EFE }, + { 0x1F00, LOWER_CASE, 0x1F08 }, + { 0x1F01, LOWER_CASE, 0x1F09 }, + { 0x1F02, LOWER_CASE, 0x1F0A }, + { 0x1F03, LOWER_CASE, 0x1F0B }, + { 0x1F04, LOWER_CASE, 0x1F0C }, + { 0x1F05, LOWER_CASE, 0x1F0D }, + { 0x1F06, LOWER_CASE, 0x1F0E }, + { 0x1F07, LOWER_CASE, 0x1F0F }, + { 0x1F08, UPPER_CASE, 0x1F00 }, + { 0x1F09, UPPER_CASE, 0x1F01 }, + { 0x1F0A, UPPER_CASE, 0x1F02 }, + { 0x1F0B, UPPER_CASE, 0x1F03 }, + { 0x1F0C, UPPER_CASE, 0x1F04 }, + { 0x1F0D, UPPER_CASE, 0x1F05 }, + { 0x1F0E, UPPER_CASE, 0x1F06 }, + { 0x1F0F, UPPER_CASE, 0x1F07 }, + { 0x1F10, LOWER_CASE, 0x1F18 }, + { 0x1F11, LOWER_CASE, 0x1F19 }, + { 0x1F12, LOWER_CASE, 0x1F1A }, + { 0x1F13, LOWER_CASE, 0x1F1B }, + { 0x1F14, LOWER_CASE, 0x1F1C }, + { 0x1F15, LOWER_CASE, 0x1F1D }, + { 0x1F18, UPPER_CASE, 0x1F10 }, + { 0x1F19, UPPER_CASE, 0x1F11 }, + { 0x1F1A, UPPER_CASE, 0x1F12 }, + { 0x1F1B, UPPER_CASE, 0x1F13 }, + { 0x1F1C, UPPER_CASE, 0x1F14 }, + { 0x1F1D, UPPER_CASE, 0x1F15 }, + { 0x1F20, LOWER_CASE, 0x1F28 }, + { 0x1F21, LOWER_CASE, 0x1F29 }, + { 0x1F22, LOWER_CASE, 0x1F2A }, + { 0x1F23, LOWER_CASE, 0x1F2B }, + { 0x1F24, LOWER_CASE, 0x1F2C }, + { 0x1F25, LOWER_CASE, 0x1F2D }, + { 0x1F26, LOWER_CASE, 0x1F2E }, + { 0x1F27, LOWER_CASE, 0x1F2F }, + { 0x1F28, UPPER_CASE, 0x1F20 }, + { 0x1F29, UPPER_CASE, 0x1F21 }, + { 0x1F2A, UPPER_CASE, 0x1F22 }, + { 0x1F2B, UPPER_CASE, 0x1F23 }, + { 0x1F2C, UPPER_CASE, 0x1F24 }, + { 0x1F2D, UPPER_CASE, 0x1F25 }, + { 0x1F2E, UPPER_CASE, 0x1F26 }, + { 0x1F2F, UPPER_CASE, 0x1F27 }, + { 0x1F30, LOWER_CASE, 0x1F38 }, + { 0x1F31, LOWER_CASE, 0x1F39 }, + { 0x1F32, LOWER_CASE, 0x1F3A }, + { 0x1F33, LOWER_CASE, 0x1F3B }, + { 0x1F34, LOWER_CASE, 0x1F3C }, + { 0x1F35, LOWER_CASE, 0x1F3D }, + { 0x1F36, LOWER_CASE, 0x1F3E }, + { 0x1F37, LOWER_CASE, 0x1F3F }, + { 0x1F38, UPPER_CASE, 0x1F30 }, + { 0x1F39, UPPER_CASE, 0x1F31 }, + { 0x1F3A, UPPER_CASE, 0x1F32 }, + { 0x1F3B, UPPER_CASE, 0x1F33 }, + { 0x1F3C, UPPER_CASE, 0x1F34 }, + { 0x1F3D, UPPER_CASE, 0x1F35 }, + { 0x1F3E, UPPER_CASE, 0x1F36 }, + { 0x1F3F, UPPER_CASE, 0x1F37 }, + { 0x1F40, LOWER_CASE, 0x1F48 }, + { 0x1F41, LOWER_CASE, 0x1F49 }, + { 0x1F42, LOWER_CASE, 0x1F4A }, + { 0x1F43, LOWER_CASE, 0x1F4B }, + { 0x1F44, LOWER_CASE, 0x1F4C }, + { 0x1F45, LOWER_CASE, 0x1F4D }, + { 0x1F48, UPPER_CASE, 0x1F40 }, + { 0x1F49, UPPER_CASE, 0x1F41 }, + { 0x1F4A, UPPER_CASE, 0x1F42 }, + { 0x1F4B, UPPER_CASE, 0x1F43 }, + { 0x1F4C, UPPER_CASE, 0x1F44 }, + { 0x1F4D, UPPER_CASE, 0x1F45 }, + { 0x1F51, LOWER_CASE, 0x1F59 }, + { 0x1F53, LOWER_CASE, 0x1F5B }, + { 0x1F55, LOWER_CASE, 0x1F5D }, + { 0x1F57, LOWER_CASE, 0x1F5F }, + { 0x1F59, UPPER_CASE, 0x1F51 }, + { 0x1F5B, UPPER_CASE, 0x1F53 }, + { 0x1F5D, UPPER_CASE, 0x1F55 }, + { 0x1F5F, UPPER_CASE, 0x1F57 }, + { 0x1F60, LOWER_CASE, 0x1F68 }, + { 0x1F61, LOWER_CASE, 0x1F69 }, + { 0x1F62, LOWER_CASE, 0x1F6A }, + { 0x1F63, LOWER_CASE, 0x1F6B }, + { 0x1F64, LOWER_CASE, 0x1F6C }, + { 0x1F65, LOWER_CASE, 0x1F6D }, + { 0x1F66, LOWER_CASE, 0x1F6E }, + { 0x1F67, LOWER_CASE, 0x1F6F }, + { 0x1F68, UPPER_CASE, 0x1F60 }, + { 0x1F69, UPPER_CASE, 0x1F61 }, + { 0x1F6A, UPPER_CASE, 0x1F62 }, + { 0x1F6B, UPPER_CASE, 0x1F63 }, + { 0x1F6C, UPPER_CASE, 0x1F64 }, + { 0x1F6D, UPPER_CASE, 0x1F65 }, + { 0x1F6E, UPPER_CASE, 0x1F66 }, + { 0x1F6F, UPPER_CASE, 0x1F67 }, + { 0x1F70, LOWER_CASE, 0x1FBA }, + { 0x1F71, LOWER_CASE, 0x1FBB }, + { 0x1F72, LOWER_CASE, 0x1FC8 }, + { 0x1F73, LOWER_CASE, 0x1FC9 }, + { 0x1F74, LOWER_CASE, 0x1FCA }, + { 0x1F75, LOWER_CASE, 0x1FCB }, + { 0x1F76, LOWER_CASE, 0x1FDA }, + { 0x1F77, LOWER_CASE, 0x1FDB }, + { 0x1F78, LOWER_CASE, 0x1FF8 }, + { 0x1F79, LOWER_CASE, 0x1FF9 }, + { 0x1F7A, LOWER_CASE, 0x1FEA }, + { 0x1F7B, LOWER_CASE, 0x1FEB }, + { 0x1F7C, LOWER_CASE, 0x1FFA }, + { 0x1F7D, LOWER_CASE, 0x1FFB }, + { 0x1F80, LOWER_CASE, 0x1F88 }, + { 0x1F81, LOWER_CASE, 0x1F89 }, + { 0x1F82, LOWER_CASE, 0x1F8A }, + { 0x1F83, LOWER_CASE, 0x1F8B }, + { 0x1F84, LOWER_CASE, 0x1F8C }, + { 0x1F85, LOWER_CASE, 0x1F8D }, + { 0x1F86, LOWER_CASE, 0x1F8E }, + { 0x1F87, LOWER_CASE, 0x1F8F }, + { 0x1F88, UPPER_CASE, 0x1F80 }, + { 0x1F89, UPPER_CASE, 0x1F81 }, + { 0x1F8A, UPPER_CASE, 0x1F82 }, + { 0x1F8B, UPPER_CASE, 0x1F83 }, + { 0x1F8C, UPPER_CASE, 0x1F84 }, + { 0x1F8D, UPPER_CASE, 0x1F85 }, + { 0x1F8E, UPPER_CASE, 0x1F86 }, + { 0x1F8F, UPPER_CASE, 0x1F87 }, + { 0x1F90, LOWER_CASE, 0x1F98 }, + { 0x1F91, LOWER_CASE, 0x1F99 }, + { 0x1F92, LOWER_CASE, 0x1F9A }, + { 0x1F93, LOWER_CASE, 0x1F9B }, + { 0x1F94, LOWER_CASE, 0x1F9C }, + { 0x1F95, LOWER_CASE, 0x1F9D }, + { 0x1F96, LOWER_CASE, 0x1F9E }, + { 0x1F97, LOWER_CASE, 0x1F9F }, + { 0x1F98, UPPER_CASE, 0x1F90 }, + { 0x1F99, UPPER_CASE, 0x1F91 }, + { 0x1F9A, UPPER_CASE, 0x1F92 }, + { 0x1F9B, UPPER_CASE, 0x1F93 }, + { 0x1F9C, UPPER_CASE, 0x1F94 }, + { 0x1F9D, UPPER_CASE, 0x1F95 }, + { 0x1F9E, UPPER_CASE, 0x1F96 }, + { 0x1F9F, UPPER_CASE, 0x1F97 }, + { 0x1FA0, LOWER_CASE, 0x1FA8 }, + { 0x1FA1, LOWER_CASE, 0x1FA9 }, + { 0x1FA2, LOWER_CASE, 0x1FAA }, + { 0x1FA3, LOWER_CASE, 0x1FAB }, + { 0x1FA4, LOWER_CASE, 0x1FAC }, + { 0x1FA5, LOWER_CASE, 0x1FAD }, + { 0x1FA6, LOWER_CASE, 0x1FAE }, + { 0x1FA7, LOWER_CASE, 0x1FAF }, + { 0x1FA8, UPPER_CASE, 0x1FA0 }, + { 0x1FA9, UPPER_CASE, 0x1FA1 }, + { 0x1FAA, UPPER_CASE, 0x1FA2 }, + { 0x1FAB, UPPER_CASE, 0x1FA3 }, + { 0x1FAC, UPPER_CASE, 0x1FA4 }, + { 0x1FAD, UPPER_CASE, 0x1FA5 }, + { 0x1FAE, UPPER_CASE, 0x1FA6 }, + { 0x1FAF, UPPER_CASE, 0x1FA7 }, + { 0x1FB0, LOWER_CASE, 0x1FB8 }, + { 0x1FB1, LOWER_CASE, 0x1FB9 }, + { 0x1FB3, LOWER_CASE, 0x1FBC }, + { 0x1FB8, UPPER_CASE, 0x1FB0 }, + { 0x1FB9, UPPER_CASE, 0x1FB1 }, + { 0x1FBA, UPPER_CASE, 0x1F70 }, + { 0x1FBB, UPPER_CASE, 0x1F71 }, + { 0x1FBC, UPPER_CASE, 0x1FB3 }, + { 0x1FBE, LOWER_CASE, 0x399 }, + { 0x1FC3, LOWER_CASE, 0x1FCC }, + { 0x1FC8, UPPER_CASE, 0x1F72 }, + { 0x1FC9, UPPER_CASE, 0x1F73 }, + { 0x1FCA, UPPER_CASE, 0x1F74 }, + { 0x1FCB, UPPER_CASE, 0x1F75 }, + { 0x1FCC, UPPER_CASE, 0x1FC3 }, + { 0x1FD0, LOWER_CASE, 0x1FD8 }, + { 0x1FD1, LOWER_CASE, 0x1FD9 }, + { 0x1FD8, UPPER_CASE, 0x1FD0 }, + { 0x1FD9, UPPER_CASE, 0x1FD1 }, + { 0x1FDA, UPPER_CASE, 0x1F76 }, + { 0x1FDB, UPPER_CASE, 0x1F77 }, + { 0x1FE0, LOWER_CASE, 0x1FE8 }, + { 0x1FE1, LOWER_CASE, 0x1FE9 }, + { 0x1FE5, LOWER_CASE, 0x1FEC }, + { 0x1FE8, UPPER_CASE, 0x1FE0 }, + { 0x1FE9, UPPER_CASE, 0x1FE1 }, + { 0x1FEA, UPPER_CASE, 0x1F7A }, + { 0x1FEB, UPPER_CASE, 0x1F7B }, + { 0x1FEC, UPPER_CASE, 0x1FE5 }, + { 0x1FF3, LOWER_CASE, 0x1FFC }, + { 0x1FF8, UPPER_CASE, 0x1F78 }, + { 0x1FF9, UPPER_CASE, 0x1F79 }, + { 0x1FFA, UPPER_CASE, 0x1F7C }, + { 0x1FFB, UPPER_CASE, 0x1F7D }, + { 0x1FFC, UPPER_CASE, 0x1FF3 }, + { 0x2126, UPPER_CASE, 0x3C9 }, + { 0x212A, UPPER_CASE, 0x6B }, + { 0x212B, UPPER_CASE, 0xE5 }, + { 0x2132, UPPER_CASE, 0x214E }, + { 0x214E, LOWER_CASE, 0x2132 }, + { 0x2160, UPPER_CASE, 0x2170 }, + { 0x2161, UPPER_CASE, 0x2171 }, + { 0x2162, UPPER_CASE, 0x2172 }, + { 0x2163, UPPER_CASE, 0x2173 }, + { 0x2164, UPPER_CASE, 0x2174 }, + { 0x2165, UPPER_CASE, 0x2175 }, + { 0x2166, UPPER_CASE, 0x2176 }, + { 0x2167, UPPER_CASE, 0x2177 }, + { 0x2168, UPPER_CASE, 0x2178 }, + { 0x2169, UPPER_CASE, 0x2179 }, + { 0x216A, UPPER_CASE, 0x217A }, + { 0x216B, UPPER_CASE, 0x217B }, + { 0x216C, UPPER_CASE, 0x217C }, + { 0x216D, UPPER_CASE, 0x217D }, + { 0x216E, UPPER_CASE, 0x217E }, + { 0x216F, UPPER_CASE, 0x217F }, + { 0x2170, LOWER_CASE, 0x2160 }, + { 0x2171, LOWER_CASE, 0x2161 }, + { 0x2172, LOWER_CASE, 0x2162 }, + { 0x2173, LOWER_CASE, 0x2163 }, + { 0x2174, LOWER_CASE, 0x2164 }, + { 0x2175, LOWER_CASE, 0x2165 }, + { 0x2176, LOWER_CASE, 0x2166 }, + { 0x2177, LOWER_CASE, 0x2167 }, + { 0x2178, LOWER_CASE, 0x2168 }, + { 0x2179, LOWER_CASE, 0x2169 }, + { 0x217A, LOWER_CASE, 0x216A }, + { 0x217B, LOWER_CASE, 0x216B }, + { 0x217C, LOWER_CASE, 0x216C }, + { 0x217D, LOWER_CASE, 0x216D }, + { 0x217E, LOWER_CASE, 0x216E }, + { 0x217F, LOWER_CASE, 0x216F }, + { 0x2183, UPPER_CASE, 0x2184 }, + { 0x2184, LOWER_CASE, 0x2183 }, + { 0x24B6, UPPER_CASE, 0x24D0 }, + { 0x24B7, UPPER_CASE, 0x24D1 }, + { 0x24B8, UPPER_CASE, 0x24D2 }, + { 0x24B9, UPPER_CASE, 0x24D3 }, + { 0x24BA, UPPER_CASE, 0x24D4 }, + { 0x24BB, UPPER_CASE, 0x24D5 }, + { 0x24BC, UPPER_CASE, 0x24D6 }, + { 0x24BD, UPPER_CASE, 0x24D7 }, + { 0x24BE, UPPER_CASE, 0x24D8 }, + { 0x24BF, UPPER_CASE, 0x24D9 }, + { 0x24C0, UPPER_CASE, 0x24DA }, + { 0x24C1, UPPER_CASE, 0x24DB }, + { 0x24C2, UPPER_CASE, 0x24DC }, + { 0x24C3, UPPER_CASE, 0x24DD }, + { 0x24C4, UPPER_CASE, 0x24DE }, + { 0x24C5, UPPER_CASE, 0x24DF }, + { 0x24C6, UPPER_CASE, 0x24E0 }, + { 0x24C7, UPPER_CASE, 0x24E1 }, + { 0x24C8, UPPER_CASE, 0x24E2 }, + { 0x24C9, UPPER_CASE, 0x24E3 }, + { 0x24CA, UPPER_CASE, 0x24E4 }, + { 0x24CB, UPPER_CASE, 0x24E5 }, + { 0x24CC, UPPER_CASE, 0x24E6 }, + { 0x24CD, UPPER_CASE, 0x24E7 }, + { 0x24CE, UPPER_CASE, 0x24E8 }, + { 0x24CF, UPPER_CASE, 0x24E9 }, + { 0x24D0, LOWER_CASE, 0x24B6 }, + { 0x24D1, LOWER_CASE, 0x24B7 }, + { 0x24D2, LOWER_CASE, 0x24B8 }, + { 0x24D3, LOWER_CASE, 0x24B9 }, + { 0x24D4, LOWER_CASE, 0x24BA }, + { 0x24D5, LOWER_CASE, 0x24BB }, + { 0x24D6, LOWER_CASE, 0x24BC }, + { 0x24D7, LOWER_CASE, 0x24BD }, + { 0x24D8, LOWER_CASE, 0x24BE }, + { 0x24D9, LOWER_CASE, 0x24BF }, + { 0x24DA, LOWER_CASE, 0x24C0 }, + { 0x24DB, LOWER_CASE, 0x24C1 }, + { 0x24DC, LOWER_CASE, 0x24C2 }, + { 0x24DD, LOWER_CASE, 0x24C3 }, + { 0x24DE, LOWER_CASE, 0x24C4 }, + { 0x24DF, LOWER_CASE, 0x24C5 }, + { 0x24E0, LOWER_CASE, 0x24C6 }, + { 0x24E1, LOWER_CASE, 0x24C7 }, + { 0x24E2, LOWER_CASE, 0x24C8 }, + { 0x24E3, LOWER_CASE, 0x24C9 }, + { 0x24E4, LOWER_CASE, 0x24CA }, + { 0x24E5, LOWER_CASE, 0x24CB }, + { 0x24E6, LOWER_CASE, 0x24CC }, + { 0x24E7, LOWER_CASE, 0x24CD }, + { 0x24E8, LOWER_CASE, 0x24CE }, + { 0x24E9, LOWER_CASE, 0x24CF }, + { 0x2C00, UPPER_CASE, 0x2C30 }, + { 0x2C01, UPPER_CASE, 0x2C31 }, + { 0x2C02, UPPER_CASE, 0x2C32 }, + { 0x2C03, UPPER_CASE, 0x2C33 }, + { 0x2C04, UPPER_CASE, 0x2C34 }, + { 0x2C05, UPPER_CASE, 0x2C35 }, + { 0x2C06, UPPER_CASE, 0x2C36 }, + { 0x2C07, UPPER_CASE, 0x2C37 }, + { 0x2C08, UPPER_CASE, 0x2C38 }, + { 0x2C09, UPPER_CASE, 0x2C39 }, + { 0x2C0A, UPPER_CASE, 0x2C3A }, + { 0x2C0B, UPPER_CASE, 0x2C3B }, + { 0x2C0C, UPPER_CASE, 0x2C3C }, + { 0x2C0D, UPPER_CASE, 0x2C3D }, + { 0x2C0E, UPPER_CASE, 0x2C3E }, + { 0x2C0F, UPPER_CASE, 0x2C3F }, + { 0x2C10, UPPER_CASE, 0x2C40 }, + { 0x2C11, UPPER_CASE, 0x2C41 }, + { 0x2C12, UPPER_CASE, 0x2C42 }, + { 0x2C13, UPPER_CASE, 0x2C43 }, + { 0x2C14, UPPER_CASE, 0x2C44 }, + { 0x2C15, UPPER_CASE, 0x2C45 }, + { 0x2C16, UPPER_CASE, 0x2C46 }, + { 0x2C17, UPPER_CASE, 0x2C47 }, + { 0x2C18, UPPER_CASE, 0x2C48 }, + { 0x2C19, UPPER_CASE, 0x2C49 }, + { 0x2C1A, UPPER_CASE, 0x2C4A }, + { 0x2C1B, UPPER_CASE, 0x2C4B }, + { 0x2C1C, UPPER_CASE, 0x2C4C }, + { 0x2C1D, UPPER_CASE, 0x2C4D }, + { 0x2C1E, UPPER_CASE, 0x2C4E }, + { 0x2C1F, UPPER_CASE, 0x2C4F }, + { 0x2C20, UPPER_CASE, 0x2C50 }, + { 0x2C21, UPPER_CASE, 0x2C51 }, + { 0x2C22, UPPER_CASE, 0x2C52 }, + { 0x2C23, UPPER_CASE, 0x2C53 }, + { 0x2C24, UPPER_CASE, 0x2C54 }, + { 0x2C25, UPPER_CASE, 0x2C55 }, + { 0x2C26, UPPER_CASE, 0x2C56 }, + { 0x2C27, UPPER_CASE, 0x2C57 }, + { 0x2C28, UPPER_CASE, 0x2C58 }, + { 0x2C29, UPPER_CASE, 0x2C59 }, + { 0x2C2A, UPPER_CASE, 0x2C5A }, + { 0x2C2B, UPPER_CASE, 0x2C5B }, + { 0x2C2C, UPPER_CASE, 0x2C5C }, + { 0x2C2D, UPPER_CASE, 0x2C5D }, + { 0x2C2E, UPPER_CASE, 0x2C5E }, + { 0x2C30, LOWER_CASE, 0x2C00 }, + { 0x2C31, LOWER_CASE, 0x2C01 }, + { 0x2C32, LOWER_CASE, 0x2C02 }, + { 0x2C33, LOWER_CASE, 0x2C03 }, + { 0x2C34, LOWER_CASE, 0x2C04 }, + { 0x2C35, LOWER_CASE, 0x2C05 }, + { 0x2C36, LOWER_CASE, 0x2C06 }, + { 0x2C37, LOWER_CASE, 0x2C07 }, + { 0x2C38, LOWER_CASE, 0x2C08 }, + { 0x2C39, LOWER_CASE, 0x2C09 }, + { 0x2C3A, LOWER_CASE, 0x2C0A }, + { 0x2C3B, LOWER_CASE, 0x2C0B }, + { 0x2C3C, LOWER_CASE, 0x2C0C }, + { 0x2C3D, LOWER_CASE, 0x2C0D }, + { 0x2C3E, LOWER_CASE, 0x2C0E }, + { 0x2C3F, LOWER_CASE, 0x2C0F }, + { 0x2C40, LOWER_CASE, 0x2C10 }, + { 0x2C41, LOWER_CASE, 0x2C11 }, + { 0x2C42, LOWER_CASE, 0x2C12 }, + { 0x2C43, LOWER_CASE, 0x2C13 }, + { 0x2C44, LOWER_CASE, 0x2C14 }, + { 0x2C45, LOWER_CASE, 0x2C15 }, + { 0x2C46, LOWER_CASE, 0x2C16 }, + { 0x2C47, LOWER_CASE, 0x2C17 }, + { 0x2C48, LOWER_CASE, 0x2C18 }, + { 0x2C49, LOWER_CASE, 0x2C19 }, + { 0x2C4A, LOWER_CASE, 0x2C1A }, + { 0x2C4B, LOWER_CASE, 0x2C1B }, + { 0x2C4C, LOWER_CASE, 0x2C1C }, + { 0x2C4D, LOWER_CASE, 0x2C1D }, + { 0x2C4E, LOWER_CASE, 0x2C1E }, + { 0x2C4F, LOWER_CASE, 0x2C1F }, + { 0x2C50, LOWER_CASE, 0x2C20 }, + { 0x2C51, LOWER_CASE, 0x2C21 }, + { 0x2C52, LOWER_CASE, 0x2C22 }, + { 0x2C53, LOWER_CASE, 0x2C23 }, + { 0x2C54, LOWER_CASE, 0x2C24 }, + { 0x2C55, LOWER_CASE, 0x2C25 }, + { 0x2C56, LOWER_CASE, 0x2C26 }, + { 0x2C57, LOWER_CASE, 0x2C27 }, + { 0x2C58, LOWER_CASE, 0x2C28 }, + { 0x2C59, LOWER_CASE, 0x2C29 }, + { 0x2C5A, LOWER_CASE, 0x2C2A }, + { 0x2C5B, LOWER_CASE, 0x2C2B }, + { 0x2C5C, LOWER_CASE, 0x2C2C }, + { 0x2C5D, LOWER_CASE, 0x2C2D }, + { 0x2C5E, LOWER_CASE, 0x2C2E }, + { 0x2C60, UPPER_CASE, 0x2C61 }, + { 0x2C61, LOWER_CASE, 0x2C60 }, + { 0x2C62, UPPER_CASE, 0x26B }, + { 0x2C63, UPPER_CASE, 0x1D7D }, + { 0x2C64, UPPER_CASE, 0x27D }, + { 0x2C65, LOWER_CASE, 0x23A }, + { 0x2C66, LOWER_CASE, 0x23E }, + { 0x2C67, UPPER_CASE, 0x2C68 }, + { 0x2C68, LOWER_CASE, 0x2C67 }, + { 0x2C69, UPPER_CASE, 0x2C6A }, + { 0x2C6A, LOWER_CASE, 0x2C69 }, + { 0x2C6B, UPPER_CASE, 0x2C6C }, + { 0x2C6C, LOWER_CASE, 0x2C6B }, + { 0x2C6D, UPPER_CASE, 0x251 }, + { 0x2C6E, UPPER_CASE, 0x271 }, + { 0x2C6F, UPPER_CASE, 0x250 }, + { 0x2C70, UPPER_CASE, 0x252 }, + { 0x2C72, UPPER_CASE, 0x2C73 }, + { 0x2C73, LOWER_CASE, 0x2C72 }, + { 0x2C75, UPPER_CASE, 0x2C76 }, + { 0x2C76, LOWER_CASE, 0x2C75 }, + { 0x2C7E, UPPER_CASE, 0x23F }, + { 0x2C7F, UPPER_CASE, 0x240 }, + { 0x2C80, UPPER_CASE, 0x2C81 }, + { 0x2C81, LOWER_CASE, 0x2C80 }, + { 0x2C82, UPPER_CASE, 0x2C83 }, + { 0x2C83, LOWER_CASE, 0x2C82 }, + { 0x2C84, UPPER_CASE, 0x2C85 }, + { 0x2C85, LOWER_CASE, 0x2C84 }, + { 0x2C86, UPPER_CASE, 0x2C87 }, + { 0x2C87, LOWER_CASE, 0x2C86 }, + { 0x2C88, UPPER_CASE, 0x2C89 }, + { 0x2C89, LOWER_CASE, 0x2C88 }, + { 0x2C8A, UPPER_CASE, 0x2C8B }, + { 0x2C8B, LOWER_CASE, 0x2C8A }, + { 0x2C8C, UPPER_CASE, 0x2C8D }, + { 0x2C8D, LOWER_CASE, 0x2C8C }, + { 0x2C8E, UPPER_CASE, 0x2C8F }, + { 0x2C8F, LOWER_CASE, 0x2C8E }, + { 0x2C90, UPPER_CASE, 0x2C91 }, + { 0x2C91, LOWER_CASE, 0x2C90 }, + { 0x2C92, UPPER_CASE, 0x2C93 }, + { 0x2C93, LOWER_CASE, 0x2C92 }, + { 0x2C94, UPPER_CASE, 0x2C95 }, + { 0x2C95, LOWER_CASE, 0x2C94 }, + { 0x2C96, UPPER_CASE, 0x2C97 }, + { 0x2C97, LOWER_CASE, 0x2C96 }, + { 0x2C98, UPPER_CASE, 0x2C99 }, + { 0x2C99, LOWER_CASE, 0x2C98 }, + { 0x2C9A, UPPER_CASE, 0x2C9B }, + { 0x2C9B, LOWER_CASE, 0x2C9A }, + { 0x2C9C, UPPER_CASE, 0x2C9D }, + { 0x2C9D, LOWER_CASE, 0x2C9C }, + { 0x2C9E, UPPER_CASE, 0x2C9F }, + { 0x2C9F, LOWER_CASE, 0x2C9E }, + { 0x2CA0, UPPER_CASE, 0x2CA1 }, + { 0x2CA1, LOWER_CASE, 0x2CA0 }, + { 0x2CA2, UPPER_CASE, 0x2CA3 }, + { 0x2CA3, LOWER_CASE, 0x2CA2 }, + { 0x2CA4, UPPER_CASE, 0x2CA5 }, + { 0x2CA5, LOWER_CASE, 0x2CA4 }, + { 0x2CA6, UPPER_CASE, 0x2CA7 }, + { 0x2CA7, LOWER_CASE, 0x2CA6 }, + { 0x2CA8, UPPER_CASE, 0x2CA9 }, + { 0x2CA9, LOWER_CASE, 0x2CA8 }, + { 0x2CAA, UPPER_CASE, 0x2CAB }, + { 0x2CAB, LOWER_CASE, 0x2CAA }, + { 0x2CAC, UPPER_CASE, 0x2CAD }, + { 0x2CAD, LOWER_CASE, 0x2CAC }, + { 0x2CAE, UPPER_CASE, 0x2CAF }, + { 0x2CAF, LOWER_CASE, 0x2CAE }, + { 0x2CB0, UPPER_CASE, 0x2CB1 }, + { 0x2CB1, LOWER_CASE, 0x2CB0 }, + { 0x2CB2, UPPER_CASE, 0x2CB3 }, + { 0x2CB3, LOWER_CASE, 0x2CB2 }, + { 0x2CB4, UPPER_CASE, 0x2CB5 }, + { 0x2CB5, LOWER_CASE, 0x2CB4 }, + { 0x2CB6, UPPER_CASE, 0x2CB7 }, + { 0x2CB7, LOWER_CASE, 0x2CB6 }, + { 0x2CB8, UPPER_CASE, 0x2CB9 }, + { 0x2CB9, LOWER_CASE, 0x2CB8 }, + { 0x2CBA, UPPER_CASE, 0x2CBB }, + { 0x2CBB, LOWER_CASE, 0x2CBA }, + { 0x2CBC, UPPER_CASE, 0x2CBD }, + { 0x2CBD, LOWER_CASE, 0x2CBC }, + { 0x2CBE, UPPER_CASE, 0x2CBF }, + { 0x2CBF, LOWER_CASE, 0x2CBE }, + { 0x2CC0, UPPER_CASE, 0x2CC1 }, + { 0x2CC1, LOWER_CASE, 0x2CC0 }, + { 0x2CC2, UPPER_CASE, 0x2CC3 }, + { 0x2CC3, LOWER_CASE, 0x2CC2 }, + { 0x2CC4, UPPER_CASE, 0x2CC5 }, + { 0x2CC5, LOWER_CASE, 0x2CC4 }, + { 0x2CC6, UPPER_CASE, 0x2CC7 }, + { 0x2CC7, LOWER_CASE, 0x2CC6 }, + { 0x2CC8, UPPER_CASE, 0x2CC9 }, + { 0x2CC9, LOWER_CASE, 0x2CC8 }, + { 0x2CCA, UPPER_CASE, 0x2CCB }, + { 0x2CCB, LOWER_CASE, 0x2CCA }, + { 0x2CCC, UPPER_CASE, 0x2CCD }, + { 0x2CCD, LOWER_CASE, 0x2CCC }, + { 0x2CCE, UPPER_CASE, 0x2CCF }, + { 0x2CCF, LOWER_CASE, 0x2CCE }, + { 0x2CD0, UPPER_CASE, 0x2CD1 }, + { 0x2CD1, LOWER_CASE, 0x2CD0 }, + { 0x2CD2, UPPER_CASE, 0x2CD3 }, + { 0x2CD3, LOWER_CASE, 0x2CD2 }, + { 0x2CD4, UPPER_CASE, 0x2CD5 }, + { 0x2CD5, LOWER_CASE, 0x2CD4 }, + { 0x2CD6, UPPER_CASE, 0x2CD7 }, + { 0x2CD7, LOWER_CASE, 0x2CD6 }, + { 0x2CD8, UPPER_CASE, 0x2CD9 }, + { 0x2CD9, LOWER_CASE, 0x2CD8 }, + { 0x2CDA, UPPER_CASE, 0x2CDB }, + { 0x2CDB, LOWER_CASE, 0x2CDA }, + { 0x2CDC, UPPER_CASE, 0x2CDD }, + { 0x2CDD, LOWER_CASE, 0x2CDC }, + { 0x2CDE, UPPER_CASE, 0x2CDF }, + { 0x2CDF, LOWER_CASE, 0x2CDE }, + { 0x2CE0, UPPER_CASE, 0x2CE1 }, + { 0x2CE1, LOWER_CASE, 0x2CE0 }, + { 0x2CE2, UPPER_CASE, 0x2CE3 }, + { 0x2CE3, LOWER_CASE, 0x2CE2 }, + { 0x2CEB, UPPER_CASE, 0x2CEC }, + { 0x2CEC, LOWER_CASE, 0x2CEB }, + { 0x2CED, UPPER_CASE, 0x2CEE }, + { 0x2CEE, LOWER_CASE, 0x2CED }, + { 0x2CF2, UPPER_CASE, 0x2CF3 }, + { 0x2CF3, LOWER_CASE, 0x2CF2 }, + { 0x2D00, LOWER_CASE, 0x10A0 }, + { 0x2D01, LOWER_CASE, 0x10A1 }, + { 0x2D02, LOWER_CASE, 0x10A2 }, + { 0x2D03, LOWER_CASE, 0x10A3 }, + { 0x2D04, LOWER_CASE, 0x10A4 }, + { 0x2D05, LOWER_CASE, 0x10A5 }, + { 0x2D06, LOWER_CASE, 0x10A6 }, + { 0x2D07, LOWER_CASE, 0x10A7 }, + { 0x2D08, LOWER_CASE, 0x10A8 }, + { 0x2D09, LOWER_CASE, 0x10A9 }, + { 0x2D0A, LOWER_CASE, 0x10AA }, + { 0x2D0B, LOWER_CASE, 0x10AB }, + { 0x2D0C, LOWER_CASE, 0x10AC }, + { 0x2D0D, LOWER_CASE, 0x10AD }, + { 0x2D0E, LOWER_CASE, 0x10AE }, + { 0x2D0F, LOWER_CASE, 0x10AF }, + { 0x2D10, LOWER_CASE, 0x10B0 }, + { 0x2D11, LOWER_CASE, 0x10B1 }, + { 0x2D12, LOWER_CASE, 0x10B2 }, + { 0x2D13, LOWER_CASE, 0x10B3 }, + { 0x2D14, LOWER_CASE, 0x10B4 }, + { 0x2D15, LOWER_CASE, 0x10B5 }, + { 0x2D16, LOWER_CASE, 0x10B6 }, + { 0x2D17, LOWER_CASE, 0x10B7 }, + { 0x2D18, LOWER_CASE, 0x10B8 }, + { 0x2D19, LOWER_CASE, 0x10B9 }, + { 0x2D1A, LOWER_CASE, 0x10BA }, + { 0x2D1B, LOWER_CASE, 0x10BB }, + { 0x2D1C, LOWER_CASE, 0x10BC }, + { 0x2D1D, LOWER_CASE, 0x10BD }, + { 0x2D1E, LOWER_CASE, 0x10BE }, + { 0x2D1F, LOWER_CASE, 0x10BF }, + { 0x2D20, LOWER_CASE, 0x10C0 }, + { 0x2D21, LOWER_CASE, 0x10C1 }, + { 0x2D22, LOWER_CASE, 0x10C2 }, + { 0x2D23, LOWER_CASE, 0x10C3 }, + { 0x2D24, LOWER_CASE, 0x10C4 }, + { 0x2D25, LOWER_CASE, 0x10C5 }, + { 0x2D27, LOWER_CASE, 0x10C7 }, + { 0x2D2D, LOWER_CASE, 0x10CD }, + { 0xA640, UPPER_CASE, 0xA641 }, + { 0xA641, LOWER_CASE, 0xA640 }, + { 0xA642, UPPER_CASE, 0xA643 }, + { 0xA643, LOWER_CASE, 0xA642 }, + { 0xA644, UPPER_CASE, 0xA645 }, + { 0xA645, LOWER_CASE, 0xA644 }, + { 0xA646, UPPER_CASE, 0xA647 }, + { 0xA647, LOWER_CASE, 0xA646 }, + { 0xA648, UPPER_CASE, 0xA649 }, + { 0xA649, LOWER_CASE, 0xA648 }, + { 0xA64A, UPPER_CASE, 0xA64B }, + { 0xA64B, LOWER_CASE, 0xA64A }, + { 0xA64C, UPPER_CASE, 0xA64D }, + { 0xA64D, LOWER_CASE, 0xA64C }, + { 0xA64E, UPPER_CASE, 0xA64F }, + { 0xA64F, LOWER_CASE, 0xA64E }, + { 0xA650, UPPER_CASE, 0xA651 }, + { 0xA651, LOWER_CASE, 0xA650 }, + { 0xA652, UPPER_CASE, 0xA653 }, + { 0xA653, LOWER_CASE, 0xA652 }, + { 0xA654, UPPER_CASE, 0xA655 }, + { 0xA655, LOWER_CASE, 0xA654 }, + { 0xA656, UPPER_CASE, 0xA657 }, + { 0xA657, LOWER_CASE, 0xA656 }, + { 0xA658, UPPER_CASE, 0xA659 }, + { 0xA659, LOWER_CASE, 0xA658 }, + { 0xA65A, UPPER_CASE, 0xA65B }, + { 0xA65B, LOWER_CASE, 0xA65A }, + { 0xA65C, UPPER_CASE, 0xA65D }, + { 0xA65D, LOWER_CASE, 0xA65C }, + { 0xA65E, UPPER_CASE, 0xA65F }, + { 0xA65F, LOWER_CASE, 0xA65E }, + { 0xA660, UPPER_CASE, 0xA661 }, + { 0xA661, LOWER_CASE, 0xA660 }, + { 0xA662, UPPER_CASE, 0xA663 }, + { 0xA663, LOWER_CASE, 0xA662 }, + { 0xA664, UPPER_CASE, 0xA665 }, + { 0xA665, LOWER_CASE, 0xA664 }, + { 0xA666, UPPER_CASE, 0xA667 }, + { 0xA667, LOWER_CASE, 0xA666 }, + { 0xA668, UPPER_CASE, 0xA669 }, + { 0xA669, LOWER_CASE, 0xA668 }, + { 0xA66A, UPPER_CASE, 0xA66B }, + { 0xA66B, LOWER_CASE, 0xA66A }, + { 0xA66C, UPPER_CASE, 0xA66D }, + { 0xA66D, LOWER_CASE, 0xA66C }, + { 0xA680, UPPER_CASE, 0xA681 }, + { 0xA681, LOWER_CASE, 0xA680 }, + { 0xA682, UPPER_CASE, 0xA683 }, + { 0xA683, LOWER_CASE, 0xA682 }, + { 0xA684, UPPER_CASE, 0xA685 }, + { 0xA685, LOWER_CASE, 0xA684 }, + { 0xA686, UPPER_CASE, 0xA687 }, + { 0xA687, LOWER_CASE, 0xA686 }, + { 0xA688, UPPER_CASE, 0xA689 }, + { 0xA689, LOWER_CASE, 0xA688 }, + { 0xA68A, UPPER_CASE, 0xA68B }, + { 0xA68B, LOWER_CASE, 0xA68A }, + { 0xA68C, UPPER_CASE, 0xA68D }, + { 0xA68D, LOWER_CASE, 0xA68C }, + { 0xA68E, UPPER_CASE, 0xA68F }, + { 0xA68F, LOWER_CASE, 0xA68E }, + { 0xA690, UPPER_CASE, 0xA691 }, + { 0xA691, LOWER_CASE, 0xA690 }, + { 0xA692, UPPER_CASE, 0xA693 }, + { 0xA693, LOWER_CASE, 0xA692 }, + { 0xA694, UPPER_CASE, 0xA695 }, + { 0xA695, LOWER_CASE, 0xA694 }, + { 0xA696, UPPER_CASE, 0xA697 }, + { 0xA697, LOWER_CASE, 0xA696 }, + { 0xA698, UPPER_CASE, 0xA699 }, + { 0xA699, LOWER_CASE, 0xA698 }, + { 0xA69A, UPPER_CASE, 0xA69B }, + { 0xA69B, LOWER_CASE, 0xA69A }, + { 0xA722, UPPER_CASE, 0xA723 }, + { 0xA723, LOWER_CASE, 0xA722 }, + { 0xA724, UPPER_CASE, 0xA725 }, + { 0xA725, LOWER_CASE, 0xA724 }, + { 0xA726, UPPER_CASE, 0xA727 }, + { 0xA727, LOWER_CASE, 0xA726 }, + { 0xA728, UPPER_CASE, 0xA729 }, + { 0xA729, LOWER_CASE, 0xA728 }, + { 0xA72A, UPPER_CASE, 0xA72B }, + { 0xA72B, LOWER_CASE, 0xA72A }, + { 0xA72C, UPPER_CASE, 0xA72D }, + { 0xA72D, LOWER_CASE, 0xA72C }, + { 0xA72E, UPPER_CASE, 0xA72F }, + { 0xA72F, LOWER_CASE, 0xA72E }, + { 0xA732, UPPER_CASE, 0xA733 }, + { 0xA733, LOWER_CASE, 0xA732 }, + { 0xA734, UPPER_CASE, 0xA735 }, + { 0xA735, LOWER_CASE, 0xA734 }, + { 0xA736, UPPER_CASE, 0xA737 }, + { 0xA737, LOWER_CASE, 0xA736 }, + { 0xA738, UPPER_CASE, 0xA739 }, + { 0xA739, LOWER_CASE, 0xA738 }, + { 0xA73A, UPPER_CASE, 0xA73B }, + { 0xA73B, LOWER_CASE, 0xA73A }, + { 0xA73C, UPPER_CASE, 0xA73D }, + { 0xA73D, LOWER_CASE, 0xA73C }, + { 0xA73E, UPPER_CASE, 0xA73F }, + { 0xA73F, LOWER_CASE, 0xA73E }, + { 0xA740, UPPER_CASE, 0xA741 }, + { 0xA741, LOWER_CASE, 0xA740 }, + { 0xA742, UPPER_CASE, 0xA743 }, + { 0xA743, LOWER_CASE, 0xA742 }, + { 0xA744, UPPER_CASE, 0xA745 }, + { 0xA745, LOWER_CASE, 0xA744 }, + { 0xA746, UPPER_CASE, 0xA747 }, + { 0xA747, LOWER_CASE, 0xA746 }, + { 0xA748, UPPER_CASE, 0xA749 }, + { 0xA749, LOWER_CASE, 0xA748 }, + { 0xA74A, UPPER_CASE, 0xA74B }, + { 0xA74B, LOWER_CASE, 0xA74A }, + { 0xA74C, UPPER_CASE, 0xA74D }, + { 0xA74D, LOWER_CASE, 0xA74C }, + { 0xA74E, UPPER_CASE, 0xA74F }, + { 0xA74F, LOWER_CASE, 0xA74E }, + { 0xA750, UPPER_CASE, 0xA751 }, + { 0xA751, LOWER_CASE, 0xA750 }, + { 0xA752, UPPER_CASE, 0xA753 }, + { 0xA753, LOWER_CASE, 0xA752 }, + { 0xA754, UPPER_CASE, 0xA755 }, + { 0xA755, LOWER_CASE, 0xA754 }, + { 0xA756, UPPER_CASE, 0xA757 }, + { 0xA757, LOWER_CASE, 0xA756 }, + { 0xA758, UPPER_CASE, 0xA759 }, + { 0xA759, LOWER_CASE, 0xA758 }, + { 0xA75A, UPPER_CASE, 0xA75B }, + { 0xA75B, LOWER_CASE, 0xA75A }, + { 0xA75C, UPPER_CASE, 0xA75D }, + { 0xA75D, LOWER_CASE, 0xA75C }, + { 0xA75E, UPPER_CASE, 0xA75F }, + { 0xA75F, LOWER_CASE, 0xA75E }, + { 0xA760, UPPER_CASE, 0xA761 }, + { 0xA761, LOWER_CASE, 0xA760 }, + { 0xA762, UPPER_CASE, 0xA763 }, + { 0xA763, LOWER_CASE, 0xA762 }, + { 0xA764, UPPER_CASE, 0xA765 }, + { 0xA765, LOWER_CASE, 0xA764 }, + { 0xA766, UPPER_CASE, 0xA767 }, + { 0xA767, LOWER_CASE, 0xA766 }, + { 0xA768, UPPER_CASE, 0xA769 }, + { 0xA769, LOWER_CASE, 0xA768 }, + { 0xA76A, UPPER_CASE, 0xA76B }, + { 0xA76B, LOWER_CASE, 0xA76A }, + { 0xA76C, UPPER_CASE, 0xA76D }, + { 0xA76D, LOWER_CASE, 0xA76C }, + { 0xA76E, UPPER_CASE, 0xA76F }, + { 0xA76F, LOWER_CASE, 0xA76E }, + { 0xA779, UPPER_CASE, 0xA77A }, + { 0xA77A, LOWER_CASE, 0xA779 }, + { 0xA77B, UPPER_CASE, 0xA77C }, + { 0xA77C, LOWER_CASE, 0xA77B }, + { 0xA77D, UPPER_CASE, 0x1D79 }, + { 0xA77E, UPPER_CASE, 0xA77F }, + { 0xA77F, LOWER_CASE, 0xA77E }, + { 0xA780, UPPER_CASE, 0xA781 }, + { 0xA781, LOWER_CASE, 0xA780 }, + { 0xA782, UPPER_CASE, 0xA783 }, + { 0xA783, LOWER_CASE, 0xA782 }, + { 0xA784, UPPER_CASE, 0xA785 }, + { 0xA785, LOWER_CASE, 0xA784 }, + { 0xA786, UPPER_CASE, 0xA787 }, + { 0xA787, LOWER_CASE, 0xA786 }, + { 0xA78B, UPPER_CASE, 0xA78C }, + { 0xA78C, LOWER_CASE, 0xA78B }, + { 0xA78D, UPPER_CASE, 0x265 }, + { 0xA790, UPPER_CASE, 0xA791 }, + { 0xA791, LOWER_CASE, 0xA790 }, + { 0xA792, UPPER_CASE, 0xA793 }, + { 0xA793, LOWER_CASE, 0xA792 }, + { 0xA794, LOWER_CASE, 0xA7C4 }, + { 0xA796, UPPER_CASE, 0xA797 }, + { 0xA797, LOWER_CASE, 0xA796 }, + { 0xA798, UPPER_CASE, 0xA799 }, + { 0xA799, LOWER_CASE, 0xA798 }, + { 0xA79A, UPPER_CASE, 0xA79B }, + { 0xA79B, LOWER_CASE, 0xA79A }, + { 0xA79C, UPPER_CASE, 0xA79D }, + { 0xA79D, LOWER_CASE, 0xA79C }, + { 0xA79E, UPPER_CASE, 0xA79F }, + { 0xA79F, LOWER_CASE, 0xA79E }, + { 0xA7A0, UPPER_CASE, 0xA7A1 }, + { 0xA7A1, LOWER_CASE, 0xA7A0 }, + { 0xA7A2, UPPER_CASE, 0xA7A3 }, + { 0xA7A3, LOWER_CASE, 0xA7A2 }, + { 0xA7A4, UPPER_CASE, 0xA7A5 }, + { 0xA7A5, LOWER_CASE, 0xA7A4 }, + { 0xA7A6, UPPER_CASE, 0xA7A7 }, + { 0xA7A7, LOWER_CASE, 0xA7A6 }, + { 0xA7A8, UPPER_CASE, 0xA7A9 }, + { 0xA7A9, LOWER_CASE, 0xA7A8 }, + { 0xA7AA, UPPER_CASE, 0x266 }, + { 0xA7AB, UPPER_CASE, 0x25C }, + { 0xA7AC, UPPER_CASE, 0x261 }, + { 0xA7AD, UPPER_CASE, 0x26C }, + { 0xA7AE, UPPER_CASE, 0x26A }, + { 0xA7B0, UPPER_CASE, 0x29E }, + { 0xA7B1, UPPER_CASE, 0x287 }, + { 0xA7B2, UPPER_CASE, 0x29D }, + { 0xA7B3, UPPER_CASE, 0xAB53 }, + { 0xA7B4, UPPER_CASE, 0xA7B5 }, + { 0xA7B5, LOWER_CASE, 0xA7B4 }, + { 0xA7B6, UPPER_CASE, 0xA7B7 }, + { 0xA7B7, LOWER_CASE, 0xA7B6 }, + { 0xA7B8, UPPER_CASE, 0xA7B9 }, + { 0xA7B9, LOWER_CASE, 0xA7B8 }, + { 0xA7BA, UPPER_CASE, 0xA7BB }, + { 0xA7BB, LOWER_CASE, 0xA7BA }, + { 0xA7BC, UPPER_CASE, 0xA7BD }, + { 0xA7BD, LOWER_CASE, 0xA7BC }, + { 0xA7BE, UPPER_CASE, 0xA7BF }, + { 0xA7BF, LOWER_CASE, 0xA7BE }, + { 0xA7C2, UPPER_CASE, 0xA7C3 }, + { 0xA7C3, LOWER_CASE, 0xA7C2 }, + { 0xA7C4, UPPER_CASE, 0xA794 }, + { 0xA7C5, UPPER_CASE, 0x282 }, + { 0xA7C6, UPPER_CASE, 0x1D8E }, + { 0xA7C7, UPPER_CASE, 0xA7C8 }, + { 0xA7C8, LOWER_CASE, 0xA7C7 }, + { 0xA7C9, UPPER_CASE, 0xA7CA }, + { 0xA7CA, LOWER_CASE, 0xA7C9 }, + { 0xA7F5, UPPER_CASE, 0xA7F6 }, + { 0xA7F6, LOWER_CASE, 0xA7F5 }, + { 0xAB53, LOWER_CASE, 0xA7B3 }, + { 0xAB70, LOWER_CASE, 0x13A0 }, + { 0xAB71, LOWER_CASE, 0x13A1 }, + { 0xAB72, LOWER_CASE, 0x13A2 }, + { 0xAB73, LOWER_CASE, 0x13A3 }, + { 0xAB74, LOWER_CASE, 0x13A4 }, + { 0xAB75, LOWER_CASE, 0x13A5 }, + { 0xAB76, LOWER_CASE, 0x13A6 }, + { 0xAB77, LOWER_CASE, 0x13A7 }, + { 0xAB78, LOWER_CASE, 0x13A8 }, + { 0xAB79, LOWER_CASE, 0x13A9 }, + { 0xAB7A, LOWER_CASE, 0x13AA }, + { 0xAB7B, LOWER_CASE, 0x13AB }, + { 0xAB7C, LOWER_CASE, 0x13AC }, + { 0xAB7D, LOWER_CASE, 0x13AD }, + { 0xAB7E, LOWER_CASE, 0x13AE }, + { 0xAB7F, LOWER_CASE, 0x13AF }, + { 0xAB80, LOWER_CASE, 0x13B0 }, + { 0xAB81, LOWER_CASE, 0x13B1 }, + { 0xAB82, LOWER_CASE, 0x13B2 }, + { 0xAB83, LOWER_CASE, 0x13B3 }, + { 0xAB84, LOWER_CASE, 0x13B4 }, + { 0xAB85, LOWER_CASE, 0x13B5 }, + { 0xAB86, LOWER_CASE, 0x13B6 }, + { 0xAB87, LOWER_CASE, 0x13B7 }, + { 0xAB88, LOWER_CASE, 0x13B8 }, + { 0xAB89, LOWER_CASE, 0x13B9 }, + { 0xAB8A, LOWER_CASE, 0x13BA }, + { 0xAB8B, LOWER_CASE, 0x13BB }, + { 0xAB8C, LOWER_CASE, 0x13BC }, + { 0xAB8D, LOWER_CASE, 0x13BD }, + { 0xAB8E, LOWER_CASE, 0x13BE }, + { 0xAB8F, LOWER_CASE, 0x13BF }, + { 0xAB90, LOWER_CASE, 0x13C0 }, + { 0xAB91, LOWER_CASE, 0x13C1 }, + { 0xAB92, LOWER_CASE, 0x13C2 }, + { 0xAB93, LOWER_CASE, 0x13C3 }, + { 0xAB94, LOWER_CASE, 0x13C4 }, + { 0xAB95, LOWER_CASE, 0x13C5 }, + { 0xAB96, LOWER_CASE, 0x13C6 }, + { 0xAB97, LOWER_CASE, 0x13C7 }, + { 0xAB98, LOWER_CASE, 0x13C8 }, + { 0xAB99, LOWER_CASE, 0x13C9 }, + { 0xAB9A, LOWER_CASE, 0x13CA }, + { 0xAB9B, LOWER_CASE, 0x13CB }, + { 0xAB9C, LOWER_CASE, 0x13CC }, + { 0xAB9D, LOWER_CASE, 0x13CD }, + { 0xAB9E, LOWER_CASE, 0x13CE }, + { 0xAB9F, LOWER_CASE, 0x13CF }, + { 0xABA0, LOWER_CASE, 0x13D0 }, + { 0xABA1, LOWER_CASE, 0x13D1 }, + { 0xABA2, LOWER_CASE, 0x13D2 }, + { 0xABA3, LOWER_CASE, 0x13D3 }, + { 0xABA4, LOWER_CASE, 0x13D4 }, + { 0xABA5, LOWER_CASE, 0x13D5 }, + { 0xABA6, LOWER_CASE, 0x13D6 }, + { 0xABA7, LOWER_CASE, 0x13D7 }, + { 0xABA8, LOWER_CASE, 0x13D8 }, + { 0xABA9, LOWER_CASE, 0x13D9 }, + { 0xABAA, LOWER_CASE, 0x13DA }, + { 0xABAB, LOWER_CASE, 0x13DB }, + { 0xABAC, LOWER_CASE, 0x13DC }, + { 0xABAD, LOWER_CASE, 0x13DD }, + { 0xABAE, LOWER_CASE, 0x13DE }, + { 0xABAF, LOWER_CASE, 0x13DF }, + { 0xABB0, LOWER_CASE, 0x13E0 }, + { 0xABB1, LOWER_CASE, 0x13E1 }, + { 0xABB2, LOWER_CASE, 0x13E2 }, + { 0xABB3, LOWER_CASE, 0x13E3 }, + { 0xABB4, LOWER_CASE, 0x13E4 }, + { 0xABB5, LOWER_CASE, 0x13E5 }, + { 0xABB6, LOWER_CASE, 0x13E6 }, + { 0xABB7, LOWER_CASE, 0x13E7 }, + { 0xABB8, LOWER_CASE, 0x13E8 }, + { 0xABB9, LOWER_CASE, 0x13E9 }, + { 0xABBA, LOWER_CASE, 0x13EA }, + { 0xABBB, LOWER_CASE, 0x13EB }, + { 0xABBC, LOWER_CASE, 0x13EC }, + { 0xABBD, LOWER_CASE, 0x13ED }, + { 0xABBE, LOWER_CASE, 0x13EE }, + { 0xABBF, LOWER_CASE, 0x13EF }, + { 0xFF21, UPPER_CASE, 0xFF41 }, + { 0xFF22, UPPER_CASE, 0xFF42 }, + { 0xFF23, UPPER_CASE, 0xFF43 }, + { 0xFF24, UPPER_CASE, 0xFF44 }, + { 0xFF25, UPPER_CASE, 0xFF45 }, + { 0xFF26, UPPER_CASE, 0xFF46 }, + { 0xFF27, UPPER_CASE, 0xFF47 }, + { 0xFF28, UPPER_CASE, 0xFF48 }, + { 0xFF29, UPPER_CASE, 0xFF49 }, + { 0xFF2A, UPPER_CASE, 0xFF4A }, + { 0xFF2B, UPPER_CASE, 0xFF4B }, + { 0xFF2C, UPPER_CASE, 0xFF4C }, + { 0xFF2D, UPPER_CASE, 0xFF4D }, + { 0xFF2E, UPPER_CASE, 0xFF4E }, + { 0xFF2F, UPPER_CASE, 0xFF4F }, + { 0xFF30, UPPER_CASE, 0xFF50 }, + { 0xFF31, UPPER_CASE, 0xFF51 }, + { 0xFF32, UPPER_CASE, 0xFF52 }, + { 0xFF33, UPPER_CASE, 0xFF53 }, + { 0xFF34, UPPER_CASE, 0xFF54 }, + { 0xFF35, UPPER_CASE, 0xFF55 }, + { 0xFF36, UPPER_CASE, 0xFF56 }, + { 0xFF37, UPPER_CASE, 0xFF57 }, + { 0xFF38, UPPER_CASE, 0xFF58 }, + { 0xFF39, UPPER_CASE, 0xFF59 }, + { 0xFF3A, UPPER_CASE, 0xFF5A }, + { 0xFF41, LOWER_CASE, 0xFF21 }, + { 0xFF42, LOWER_CASE, 0xFF22 }, + { 0xFF43, LOWER_CASE, 0xFF23 }, + { 0xFF44, LOWER_CASE, 0xFF24 }, + { 0xFF45, LOWER_CASE, 0xFF25 }, + { 0xFF46, LOWER_CASE, 0xFF26 }, + { 0xFF47, LOWER_CASE, 0xFF27 }, + { 0xFF48, LOWER_CASE, 0xFF28 }, + { 0xFF49, LOWER_CASE, 0xFF29 }, + { 0xFF4A, LOWER_CASE, 0xFF2A }, + { 0xFF4B, LOWER_CASE, 0xFF2B }, + { 0xFF4C, LOWER_CASE, 0xFF2C }, + { 0xFF4D, LOWER_CASE, 0xFF2D }, + { 0xFF4E, LOWER_CASE, 0xFF2E }, + { 0xFF4F, LOWER_CASE, 0xFF2F }, + { 0xFF50, LOWER_CASE, 0xFF30 }, + { 0xFF51, LOWER_CASE, 0xFF31 }, + { 0xFF52, LOWER_CASE, 0xFF32 }, + { 0xFF53, LOWER_CASE, 0xFF33 }, + { 0xFF54, LOWER_CASE, 0xFF34 }, + { 0xFF55, LOWER_CASE, 0xFF35 }, + { 0xFF56, LOWER_CASE, 0xFF36 }, + { 0xFF57, LOWER_CASE, 0xFF37 }, + { 0xFF58, LOWER_CASE, 0xFF38 }, + { 0xFF59, LOWER_CASE, 0xFF39 }, + { 0xFF5A, LOWER_CASE, 0xFF3A }, +}; +CONST UINT UNICODE_DATA_SIZE = sizeof(UnicodeData)/sizeof(UnicodeDataRec); diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/unicodedata.cs b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/unicodedata.cs new file mode 100644 index 0000000..ad67796 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/unicodedata.cs @@ -0,0 +1,65 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; + +class Program +{ + static void Main(string[] args) + { + Console.WriteLine("// Licensed to the .NET Foundation under one or more agreements."); + Console.WriteLine("// The .NET Foundation licenses this file to you under the MIT license."); + Console.WriteLine("// See the LICENSE file in the project root for more information."); + Console.WriteLine(); + + Console.WriteLine("#include \"pal/unicodedata.h\""); + + Console.WriteLine(); + Console.WriteLine("//"); + Console.WriteLine("// THIS FILE IS GENERATED. DO NOT HAND EDIT."); + Console.WriteLine("//"); + Console.WriteLine(); + + Console.WriteLine("CONST UnicodeDataRec UnicodeData[] = {"); + + string sourceFileName = args[0]; + + using (StreamReader sourceFile = File.OpenText(sourceFileName)) + while (sourceFile.ReadLine() is string line) + { + var fields = line.Split(';'); + + var code = int.Parse(fields[0], NumberStyles.HexNumber); + + bool hasUpperCaseMapping = fields[12].Length != 0; + bool hasLowerCaseMapping = fields[13].Length != 0; + + if (!hasLowerCaseMapping && !hasUpperCaseMapping) + continue; + + + int opposingCase = hasUpperCaseMapping ? + int.Parse(fields[12], NumberStyles.HexNumber) : + int.Parse(fields[13], NumberStyles.HexNumber); + + // These won't fit in 16 bits - no point carrying them + if (code > 0xFFFF) + continue; + + Debug.Assert(opposingCase <= 0xFFFF); + + string specifier = hasUpperCaseMapping ? "LOWER_CASE" : "UPPER_CASE"; + + Console.WriteLine($" {{ 0x{code:X}, {specifier}, 0x{opposingCase:X} }},"); + } + + Console.WriteLine("};"); + + Console.WriteLine("CONST UINT UNICODE_DATA_SIZE = sizeof(UnicodeData)/sizeof(UnicodeDataRec);"); + } +} \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/utf8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/utf8.cpp new file mode 100644 index 0000000..d263248 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/locale/utf8.cpp @@ -0,0 +1,2946 @@ +// 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: + + unicode/utf8.c + +Abstract: + Functions to encode and decode UTF-8 strings. This is a port of the C# version from mscorlib. + +Revision History: + + + +--*/ + +#include "pal/utf8.h" +#include "pal/malloc.hpp" + +using namespace CorUnix; + +#define FASTLOOP + +#ifndef COUNTOF +#define COUNTOF(x) (sizeof(x) / sizeof((x)[0])) +#endif + +struct CharUnicodeInfo +{ + static const WCHAR HIGH_SURROGATE_START = 0xd800; + static const WCHAR HIGH_SURROGATE_END = 0xdbff; + static const WCHAR LOW_SURROGATE_START = 0xdc00; + static const WCHAR LOW_SURROGATE_END = 0xdfff; +}; + +struct Char +{ + // Test if the wide character is a high surrogate + static bool IsHighSurrogate(const WCHAR c) + { + return (c & 0xFC00) == CharUnicodeInfo::HIGH_SURROGATE_START; + } + + // Test if the wide character is a low surrogate + static bool IsLowSurrogate(const WCHAR c) + { + return (c & 0xFC00) == CharUnicodeInfo::LOW_SURROGATE_START; + } + + // Test if the wide character is a low surrogate + static bool IsSurrogate(const WCHAR c) + { + return (c & 0xF800) == CharUnicodeInfo::HIGH_SURROGATE_START; + } + + // Test if the wide character is a high surrogate + static bool IsHighSurrogate(const WCHAR* s, int index) + { + return IsHighSurrogate(s[index]); + } + + // Test if the wide character is a low surrogate + static bool IsLowSurrogate(const WCHAR* s, int index) + { + return IsLowSurrogate(s[index]); + } + + // Test if the wide character is a low surrogate + static bool IsSurrogate(const WCHAR* s, int index) + { + return IsSurrogate(s[index]); + } +}; + +class ArgumentException +{ + +public: + ArgumentException(LPCSTR message) + { + } + + ArgumentException(LPCSTR message, LPCSTR argName) + { + } +}; + +class ArgumentNullException : public ArgumentException +{ +public: + ArgumentNullException(LPCSTR argName) + : ArgumentException("Argument is NULL", argName) + { + + } +}; + +class ArgumentOutOfRangeException : public ArgumentException +{ +public: + ArgumentOutOfRangeException(LPCSTR argName, LPCSTR message) + : ArgumentException(message, argName) + { + + } +}; + +class InsufficientBufferException : public ArgumentException +{ +public: + InsufficientBufferException(LPCSTR message, LPCSTR argName) + : ArgumentException(message, argName) + { + + } +}; + +class Contract +{ +public: + static void Assert(bool cond, LPCSTR str) + { + if (!cond) + { + throw ArgumentException(str); + } + } + + static void EndContractBlock() + { + } +}; + +class DecoderFallbackException : public ArgumentException +{ + BYTE *bytesUnknown; + int index; + +public: + DecoderFallbackException( + LPCSTR message, BYTE bytesUnknown[], int index) : ArgumentException(message) + { + this->bytesUnknown = bytesUnknown; + this->index = index; + } + + BYTE *BytesUnknown() + { + return (bytesUnknown); + } + + int GetIndex() + { + return index; + } +}; + +class DecoderFallbackBuffer; + +class DecoderFallback +{ +public: + + // Fallback + // + // Return the appropriate unicode string alternative to the character that need to fall back. + + virtual DecoderFallbackBuffer* CreateFallbackBuffer() = 0; + + // Maximum number of characters that this instance of this fallback could return + + virtual int GetMaxCharCount() = 0; +}; + +class DecoderReplacementFallback : public DecoderFallback +{ + // Our variables + WCHAR strDefault[2]; + int strDefaultLength; + +public: + // Construction. Default replacement fallback uses no best fit and ? replacement string + DecoderReplacementFallback() : DecoderReplacementFallback(W("?")) + { + } + + DecoderReplacementFallback(const WCHAR* replacement) + { + // Must not be null + if (replacement == nullptr) + throw ArgumentNullException("replacement"); + Contract::EndContractBlock(); + + // Make sure it doesn't have bad surrogate pairs + bool bFoundHigh = false; + int replacementLength = PAL_wcslen((const WCHAR *)replacement); + for (int i = 0; i < replacementLength; i++) + { + // Found a surrogate? + if (Char::IsSurrogate(replacement, i)) + { + // High or Low? + if (Char::IsHighSurrogate(replacement, i)) + { + // if already had a high one, stop + if (bFoundHigh) + break; // break & throw at the bFoundHIgh below + bFoundHigh = true; + } + else + { + // Low, did we have a high? + if (!bFoundHigh) + { + // Didn't have one, make if fail when we stop + bFoundHigh = true; + break; + } + + // Clear flag + bFoundHigh = false; + } + } + // If last was high we're in trouble (not surrogate so not low surrogate, so break) + else if (bFoundHigh) + break; + } + if (bFoundHigh) + throw ArgumentException("String 'replacement' contains invalid Unicode code points.", "replacement"); + + wcscpy_s(strDefault, COUNTOF(strDefault), replacement); + strDefaultLength = replacementLength; + } + + WCHAR* GetDefaultString() + { + return strDefault; + } + + virtual DecoderFallbackBuffer* CreateFallbackBuffer(); + + // Maximum number of characters that this instance of this fallback could return + virtual int GetMaxCharCount() + { + return strDefaultLength; + } +}; + +class DecoderFallbackBuffer +{ + friend class UTF8Encoding; + // Most implimentations will probably need an implimenation-specific constructor + + // internal methods that cannot be overriden that let us do our fallback thing + // These wrap the internal methods so that we can check for people doing stuff that's incorrect + +public: + virtual ~DecoderFallbackBuffer() = default; + + virtual bool Fallback(BYTE bytesUnknown[], int index, int size) = 0; + + // Get next character + virtual WCHAR GetNextChar() = 0; + + //Back up a character + virtual bool MovePrevious() = 0; + + // How many chars left in this fallback? + virtual int GetRemaining() = 0; + + // Clear the buffer + virtual void Reset() + { + while (GetNextChar() != (WCHAR)0); + } + + // Internal items to help us figure out what we're doing as far as error messages, etc. + // These help us with our performance and messages internally +protected: + BYTE* byteStart; + WCHAR* charEnd; + + // Internal reset + void InternalReset() + { + byteStart = nullptr; + Reset(); + } + + // Set the above values + // This can't be part of the constructor because EncoderFallbacks would have to know how to impliment these. + void InternalInitialize(BYTE* byteStart, WCHAR* charEnd) + { + this->byteStart = byteStart; + this->charEnd = charEnd; + } + + // Fallback the current byte by sticking it into the remaining char buffer. + // This can only be called by our encodings (other have to use the public fallback methods), so + // we can use our DecoderNLS here too (except we don't). + // Returns true if we are successful, false if we can't fallback the character (no buffer space) + // So caller needs to throw buffer space if return false. + // Right now this has both bytes and bytes[], since we might have extra bytes, hence the + // array, and we might need the index, hence the byte* + // Don't touch ref chars unless we succeed + virtual bool InternalFallback(BYTE bytes[], BYTE* pBytes, WCHAR** chars, int size) + { + + Contract::Assert(byteStart != nullptr, "[DecoderFallback.InternalFallback]Used InternalFallback without calling InternalInitialize"); + + // See if there's a fallback character and we have an output buffer then copy our string. + if (this->Fallback(bytes, (int)(pBytes - byteStart - size), size)) + { + // Copy the chars to our output + WCHAR ch; + WCHAR* charTemp = *chars; + bool bHighSurrogate = false; + while ((ch = GetNextChar()) != 0) + { + // Make sure no mixed up surrogates + if (Char::IsSurrogate(ch)) + { + if (Char::IsHighSurrogate(ch)) + { + // High Surrogate + if (bHighSurrogate) + throw ArgumentException("String 'chars' contains invalid Unicode code points."); + bHighSurrogate = true; + } + else + { + // Low surrogate + if (!bHighSurrogate) + throw ArgumentException("String 'chars' contains invalid Unicode code points."); + bHighSurrogate = false; + } + } + + if (charTemp >= charEnd) + { + // No buffer space + return false; + } + + *(charTemp++) = ch; + } + + // Need to make sure that bHighSurrogate isn't true + if (bHighSurrogate) + throw ArgumentException("String 'chars' contains invalid Unicode code points."); + + // Now we aren't going to be false, so its OK to update chars + *chars = charTemp; + } + + return true; + } + + // This version just counts the fallback and doesn't actually copy anything. + virtual int InternalFallback(BYTE bytes[], BYTE* pBytes, int size) + // Right now this has both bytes[] and BYTE* bytes, since we might have extra bytes, hence the + // array, and we might need the index, hence the byte* + { + + Contract::Assert(byteStart != nullptr, "[DecoderFallback.InternalFallback]Used InternalFallback without calling InternalInitialize"); + + // See if there's a fallback character and we have an output buffer then copy our string. + if (this->Fallback(bytes, (int)(pBytes - byteStart - size), size)) + { + int count = 0; + + WCHAR ch; + bool bHighSurrogate = false; + while ((ch = GetNextChar()) != 0) + { + // Make sure no mixed up surrogates + if (Char::IsSurrogate(ch)) + { + if (Char::IsHighSurrogate(ch)) + { + // High Surrogate + if (bHighSurrogate) + throw ArgumentException("String 'chars' contains invalid Unicode code points."); + bHighSurrogate = true; + } + else + { + // Low surrogate + if (!bHighSurrogate) + throw ArgumentException("String 'chars' contains invalid Unicode code points."); + bHighSurrogate = false; + } + } + + count++; + } + + // Need to make sure that bHighSurrogate isn't true + if (bHighSurrogate) + throw ArgumentException("String 'chars' contains invalid Unicode code points."); + + return count; + } + + // If no fallback return 0 + return 0; + } + + // private helper methods + void ThrowLastBytesRecursive(BYTE bytesUnknown[]) + { + throw ArgumentException("Recursive fallback not allowed"); + } +}; + +class DecoderReplacementFallbackBuffer : public DecoderFallbackBuffer +{ + // Store our default string + WCHAR strDefault[2]; + int strDefaultLength; + int fallbackCount = -1; + int fallbackIndex = -1; + +public: + // Construction + DecoderReplacementFallbackBuffer(DecoderReplacementFallback* fallback) + { + wcscpy_s(strDefault, COUNTOF(strDefault), fallback->GetDefaultString()); + strDefaultLength = PAL_wcslen((const WCHAR *)fallback->GetDefaultString()); + } + + // Fallback Methods + virtual bool Fallback(BYTE bytesUnknown[], int index, int size) + { + // We expect no previous fallback in our buffer + // We can't call recursively but others might (note, we don't test on last char!!!) + if (fallbackCount >= 1) + { + ThrowLastBytesRecursive(bytesUnknown); + } + + // Go ahead and get our fallback + if (strDefaultLength == 0) + return false; + + fallbackCount = strDefaultLength; + fallbackIndex = -1; + + return true; + } + + virtual WCHAR GetNextChar() + { + // We want it to get < 0 because == 0 means that the current/last character is a fallback + // and we need to detect recursion. We could have a flag but we already have this counter. + fallbackCount--; + fallbackIndex++; + + // Do we have anything left? 0 is now last fallback char, negative is nothing left + if (fallbackCount < 0) + return '\0'; + + // Need to get it out of the buffer. + // Make sure it didn't wrap from the fast count-- path + if (fallbackCount == INT_MAX) + { + fallbackCount = -1; + return '\0'; + } + + // Now make sure its in the expected range + Contract::Assert(fallbackIndex < strDefaultLength && fallbackIndex >= 0, + "Index exceeds buffer range"); + + return strDefault[fallbackIndex]; + } + + virtual bool MovePrevious() + { + // Back up one, only if we just processed the last character (or earlier) + if (fallbackCount >= -1 && fallbackIndex >= 0) + { + fallbackIndex--; + fallbackCount++; + return true; + } + + // Return false 'cause we couldn't do it. + return false; + } + + // How many characters left to output? + virtual int GetRemaining() + { + // Our count is 0 for 1 character left. + return (fallbackCount < 0) ? 0 : fallbackCount; + } + + // Clear the buffer + virtual void Reset() + { + fallbackCount = -1; + fallbackIndex = -1; + byteStart = nullptr; + } + + // This version just counts the fallback and doesn't actually copy anything. + virtual int InternalFallback(BYTE bytes[], BYTE* pBytes, int size) + // Right now this has both bytes and bytes[], since we might have extra bytes, hence the + // array, and we might need the index, hence the byte* + { + // return our replacement string Length + return strDefaultLength; + } +}; + +class DecoderExceptionFallbackBuffer : public DecoderFallbackBuffer +{ +public: + DecoderExceptionFallbackBuffer() + { + } + + virtual bool Fallback(BYTE bytesUnknown[], int index, int size) + { + throw DecoderFallbackException( + "Unable to translate UTF-8 character to Unicode", bytesUnknown, index); + } + + virtual WCHAR GetNextChar() + { + return 0; + } + + virtual bool MovePrevious() + { + // Exception fallback doesn't have anywhere to back up to. + return false; + } + + // Exceptions are always empty + virtual int GetRemaining() + { + return 0; + } + +}; + +class DecoderExceptionFallback : public DecoderFallback +{ + // Construction +public: + DecoderExceptionFallback() + { + } + + virtual DecoderFallbackBuffer* CreateFallbackBuffer() + { + return InternalNew(); + } + + // Maximum number of characters that this instance of this fallback could return + virtual int GetMaxCharCount() + { + return 0; + } +}; + +DecoderFallbackBuffer* DecoderReplacementFallback::CreateFallbackBuffer() +{ + return InternalNew(this); +} + +class EncoderFallbackException : public ArgumentException +{ + WCHAR charUnknown; + WCHAR charUnknownHigh; + WCHAR charUnknownLow; + int index; + +public: + EncoderFallbackException( + LPCSTR message, WCHAR charUnknown, int index) : ArgumentException(message) + { + this->charUnknown = charUnknown; + this->index = index; + } + + EncoderFallbackException( + LPCSTR message, WCHAR charUnknownHigh, WCHAR charUnknownLow, int index) : ArgumentException(message) + { + if (!Char::IsHighSurrogate(charUnknownHigh)) + { + throw ArgumentOutOfRangeException("charUnknownHigh", + "Argument out of range 0xD800..0xDBFF"); + } + if (!Char::IsLowSurrogate(charUnknownLow)) + { + throw ArgumentOutOfRangeException("charUnknownLow", + "Argument out of range 0xDC00..0xDFFF"); + } + Contract::EndContractBlock(); + + this->charUnknownHigh = charUnknownHigh; + this->charUnknownLow = charUnknownLow; + this->index = index; + } + + WCHAR GetCharUnknown() + { + return (charUnknown); + } + + WCHAR GetCharUnknownHigh() + { + return (charUnknownHigh); + } + + WCHAR GetCharUnknownLow() + { + return (charUnknownLow); + } + + int GetIndex() + { + return index; + } + + // Return true if the unknown character is a surrogate pair. + bool IsUnknownSurrogate() + { + return (charUnknownHigh != '\0'); + } +}; + +class EncoderFallbackBuffer; + +class EncoderFallback +{ +public: + + // Fallback + // + // Return the appropriate unicode string alternative to the character that need to fall back. + + virtual EncoderFallbackBuffer* CreateFallbackBuffer() = 0; + + // Maximum number of characters that this instance of this fallback could return + virtual int GetMaxCharCount() = 0; +}; + +class EncoderReplacementFallback : public EncoderFallback +{ + // Our variables + WCHAR strDefault[2]; + int strDefaultLength; + +public: + // Construction. Default replacement fallback uses no best fit and ? replacement string + EncoderReplacementFallback() : EncoderReplacementFallback(W("?")) + { + } + + EncoderReplacementFallback(const WCHAR* replacement) + { + // Must not be null + if (replacement == nullptr) + throw ArgumentNullException("replacement"); + Contract::EndContractBlock(); + + // Make sure it doesn't have bad surrogate pairs + bool bFoundHigh = false; + int replacementLength = PAL_wcslen((const WCHAR *)replacement); + for (int i = 0; i < replacementLength; i++) + { + // Found a surrogate? + if (Char::IsSurrogate(replacement, i)) + { + // High or Low? + if (Char::IsHighSurrogate(replacement, i)) + { + // if already had a high one, stop + if (bFoundHigh) + break; // break & throw at the bFoundHIgh below + bFoundHigh = true; + } + else + { + // Low, did we have a high? + if (!bFoundHigh) + { + // Didn't have one, make if fail when we stop + bFoundHigh = true; + break; + } + + // Clear flag + bFoundHigh = false; + } + } + // If last was high we're in trouble (not surrogate so not low surrogate, so break) + else if (bFoundHigh) + break; + } + if (bFoundHigh) + throw ArgumentException("String 'replacement' contains invalid Unicode code points.", "replacement"); + + wcscpy_s(strDefault, COUNTOF(strDefault), replacement); + strDefaultLength = replacementLength; + } + + WCHAR* GetDefaultString() + { + return strDefault; + } + + virtual EncoderFallbackBuffer* CreateFallbackBuffer(); + + // Maximum number of characters that this instance of this fallback could return + virtual int GetMaxCharCount() + { + return strDefaultLength; + } +}; + +class EncoderFallbackBuffer +{ + friend class UTF8Encoding; + // Most implementations will probably need an implemenation-specific constructor + + // Public methods that cannot be overriden that let us do our fallback thing + // These wrap the internal methods so that we can check for people doing stuff that is incorrect + +public: + virtual ~EncoderFallbackBuffer() = default; + + virtual bool Fallback(WCHAR charUnknown, int index) = 0; + + virtual bool Fallback(WCHAR charUnknownHigh, WCHAR charUnknownLow, int index) = 0; + + // Get next character + virtual WCHAR GetNextChar() = 0; + + // Back up a character + virtual bool MovePrevious() = 0; + + // How many chars left in this fallback? + virtual int GetRemaining() = 0; + + // Not sure if this should be public or not. + // Clear the buffer + virtual void Reset() + { + while (GetNextChar() != (WCHAR)0); + } + + // Internal items to help us figure out what we're doing as far as error messages, etc. + // These help us with our performance and messages internally +protected: + WCHAR* charStart; + WCHAR* charEnd; + bool setEncoder; + bool bUsedEncoder; + bool bFallingBack = false; + int iRecursionCount = 0; + static const int iMaxRecursion = 250; + + // Internal Reset + // For example, what if someone fails a conversion and wants to reset one of our fallback buffers? + void InternalReset() + { + charStart = nullptr; + bFallingBack = false; + iRecursionCount = 0; + Reset(); + } + + // Set the above values + // This can't be part of the constructor because EncoderFallbacks would have to know how to impliment these. + void InternalInitialize(WCHAR* charStart, WCHAR* charEnd, bool setEncoder) + { + this->charStart = charStart; + this->charEnd = charEnd; + this->setEncoder = setEncoder; + this->bUsedEncoder = false; + this->bFallingBack = false; + this->iRecursionCount = 0; + } + + WCHAR InternalGetNextChar() + { + WCHAR ch = GetNextChar(); + bFallingBack = (ch != 0); + if (ch == 0) iRecursionCount = 0; + return ch; + } + + // Fallback the current character using the remaining buffer and encoder if necessary + // This can only be called by our encodings (other have to use the public fallback methods), so + // we can use our EncoderNLS here too. + // setEncoder is true if we're calling from a GetBytes method, false if we're calling from a GetByteCount + // + // Note that this could also change the contents of this->encoder, which is the same + // object that the caller is using, so the caller could mess up the encoder for us + // if they aren't careful. + virtual bool InternalFallback(WCHAR ch, WCHAR** chars) + { + // Shouldn't have null charStart + Contract::Assert(charStart != nullptr, + "[EncoderFallback.InternalFallbackBuffer]Fallback buffer is not initialized"); + + // Get our index, remember chars was preincremented to point at next char, so have to -1 + int index = (int)(*chars - charStart) - 1; + + // See if it was a high surrogate + if (Char::IsHighSurrogate(ch)) + { + // See if there's a low surrogate to go with it + if (*chars >= this->charEnd) + { + // Nothing left in input buffer + // No input, return 0 + } + else + { + // Might have a low surrogate + WCHAR cNext = **chars; + if (Char::IsLowSurrogate(cNext)) + { + // If already falling back then fail + if (bFallingBack && iRecursionCount++ > iMaxRecursion) + ThrowLastCharRecursive(ch, cNext); + + // Next is a surrogate, add it as surrogate pair, and increment chars + (*chars)++; + bFallingBack = Fallback(ch, cNext, index); + return bFallingBack; + } + + // Next isn't a low surrogate, just fallback the high surrogate + } + } + + // If already falling back then fail + if (bFallingBack && iRecursionCount++ > iMaxRecursion) + ThrowLastCharRecursive((int)ch); + + // Fall back our char + bFallingBack = Fallback(ch, index); + + return bFallingBack; + } + + // private helper methods + void ThrowLastCharRecursive(WCHAR highSurrogate, WCHAR lowSurrogate) + { + // Throw it, using our complete character + throw ArgumentException("Recursive fallback not allowed", "chars"); + } + + void ThrowLastCharRecursive(int utf32Char) + { + throw ArgumentException("Recursive fallback not allowed", "chars"); + } + +}; + +class EncoderReplacementFallbackBuffer : public EncoderFallbackBuffer +{ + // Store our default string + WCHAR strDefault[4]; + int strDefaultLength; + int fallbackCount = -1; + int fallbackIndex = -1; +public: + // Construction + EncoderReplacementFallbackBuffer(EncoderReplacementFallback* fallback) + { + // 2X in case we're a surrogate pair + wcscpy_s(strDefault, COUNTOF(strDefault), fallback->GetDefaultString()); + wcscat_s(strDefault, COUNTOF(strDefault), fallback->GetDefaultString()); + strDefaultLength = 2 * PAL_wcslen((const WCHAR *)fallback->GetDefaultString()); + + } + + // Fallback Methods + virtual bool Fallback(WCHAR charUnknown, int index) + { + // If we had a buffer already we're being recursive, throw, it's probably at the suspect + // character in our array. + if (fallbackCount >= 1) + { + // If we're recursive we may still have something in our buffer that makes this a surrogate + if (Char::IsHighSurrogate(charUnknown) && fallbackCount >= 0 && + Char::IsLowSurrogate(strDefault[fallbackIndex + 1])) + ThrowLastCharRecursive(charUnknown, strDefault[fallbackIndex + 1]); + + // Nope, just one character + ThrowLastCharRecursive((int)charUnknown); + } + + // Go ahead and get our fallback + // Divide by 2 because we aren't a surrogate pair + fallbackCount = strDefaultLength / 2; + fallbackIndex = -1; + + return fallbackCount != 0; + } + + virtual bool Fallback(WCHAR charUnknownHigh, WCHAR charUnknownLow, int index) + { + // Double check input surrogate pair + if (!Char::IsHighSurrogate(charUnknownHigh)) + throw ArgumentOutOfRangeException("charUnknownHigh", + "Argument out of range 0xD800..0xDBFF"); + + if (!Char::IsLowSurrogate(charUnknownLow)) + throw ArgumentOutOfRangeException("charUnknownLow", + "Argument out of range 0xDC00..0xDFFF"); + Contract::EndContractBlock(); + + // If we had a buffer already we're being recursive, throw, it's probably at the suspect + // character in our array. + if (fallbackCount >= 1) + ThrowLastCharRecursive(charUnknownHigh, charUnknownLow); + + // Go ahead and get our fallback + fallbackCount = strDefaultLength; + fallbackIndex = -1; + + return fallbackCount != 0; + } + + virtual WCHAR GetNextChar() + { + // We want it to get < 0 because == 0 means that the current/last character is a fallback + // and we need to detect recursion. We could have a flag but we already have this counter. + fallbackCount--; + fallbackIndex++; + + // Do we have anything left? 0 is now last fallback char, negative is nothing left + if (fallbackCount < 0) + return '\0'; + + // Need to get it out of the buffer. + // Make sure it didn't wrap from the fast count-- path + if (fallbackCount == INT_MAX) + { + fallbackCount = -1; + return '\0'; + } + + // Now make sure its in the expected range + Contract::Assert(fallbackIndex < strDefaultLength && fallbackIndex >= 0, + "Index exceeds buffer range"); + + return strDefault[fallbackIndex]; + } + + virtual bool MovePrevious() + { + // Back up one, only if we just processed the last character (or earlier) + if (fallbackCount >= -1 && fallbackIndex >= 0) + { + fallbackIndex--; + fallbackCount++; + return true; + } + + // Return false 'cause we couldn't do it. + return false; + } + + // How many characters left to output? + virtual int GetRemaining() + { + // Our count is 0 for 1 character left. + return (fallbackCount < 0) ? 0 : fallbackCount; + } + + // Clear the buffer + virtual void Reset() + { + fallbackCount = -1; + fallbackIndex = 0; + charStart = nullptr; + bFallingBack = false; + } +}; + +class EncoderExceptionFallbackBuffer : public EncoderFallbackBuffer +{ +public: + EncoderExceptionFallbackBuffer() + { + } + + virtual bool Fallback(WCHAR charUnknown, int index) + { + // Fall back our char + throw EncoderFallbackException("Unable to translate Unicode character to UTF-8", charUnknown, index); + } + + virtual bool Fallback(WCHAR charUnknownHigh, WCHAR charUnknownLow, int index) + { + if (!Char::IsHighSurrogate(charUnknownHigh)) + { + throw ArgumentOutOfRangeException("charUnknownHigh", + "Argument out of range 0xD800..0xDBFF"); + } + if (!Char::IsLowSurrogate(charUnknownLow)) + { + throw ArgumentOutOfRangeException("charUnknownLow", + "Argument out of range 0xDC00..0xDFFF"); + } + Contract::EndContractBlock(); + + //int iTemp = Char::ConvertToUtf32(charUnknownHigh, charUnknownLow); + + // Fall back our char + throw EncoderFallbackException( + "Unable to translate Unicode character to UTF-8", charUnknownHigh, charUnknownLow, index); + } + + virtual WCHAR GetNextChar() + { + return 0; + } + + virtual bool MovePrevious() + { + // Exception fallback doesn't have anywhere to back up to. + return false; + } + + // Exceptions are always empty + virtual int GetRemaining() + { + return 0; + } +}; + +class EncoderExceptionFallback : public EncoderFallback +{ + // Construction +public: + EncoderExceptionFallback() + { + } + + virtual EncoderFallbackBuffer* CreateFallbackBuffer() + { + return InternalNew(); + } + + // Maximum number of characters that this instance of this fallback could return + virtual int GetMaxCharCount() + { + return 0; + } +}; + +EncoderFallbackBuffer* EncoderReplacementFallback::CreateFallbackBuffer() +{ + return InternalNew(this); +} + +class UTF8Encoding +{ + EncoderFallback* encoderFallback; + // Instances of the two possible fallbacks. The constructor parameter + // determines which one to use. + EncoderReplacementFallback encoderReplacementFallback; + EncoderExceptionFallback encoderExceptionFallback; + + DecoderFallback* decoderFallback; + // Instances of the two possible fallbacks. The constructor parameter + // determines which one to use. + DecoderReplacementFallback decoderReplacementFallback; + DecoderExceptionFallback decoderExceptionFallback; + + bool InRange(WCHAR c, WCHAR begin, WCHAR end) + { + return begin <= c && c <= end; + } + + size_t PtrDiff(WCHAR* ptr1, WCHAR* ptr2) + { + return ptr1 - ptr2; + } + + size_t PtrDiff(BYTE* ptr1, BYTE* ptr2) + { + return ptr1 - ptr2; + } + + void ThrowBytesOverflow() + { + // Special message to include fallback type in case fallback's GetMaxCharCount is broken + // This happens if user has implimented an encoder fallback with a broken GetMaxCharCount + throw InsufficientBufferException("The output byte buffer is too small to contain the encoded data", "bytes"); + } + + void ThrowBytesOverflow(bool nothingEncoded) + { + // Special message to include fallback type in case fallback's GetMaxCharCount is broken + // This happens if user has implimented an encoder fallback with a broken GetMaxCharCount + if (nothingEncoded){ + ThrowBytesOverflow(); + } + } + + void ThrowCharsOverflow() + { + // Special message to include fallback type in case fallback's GetMaxCharCount is broken + // This happens if user has implimented a decoder fallback with a broken GetMaxCharCount + throw InsufficientBufferException("The output char buffer is too small to contain the encoded data", "chars"); + } + + void ThrowCharsOverflow(bool nothingEncoded) + { + // Special message to include fallback type in case fallback's GetMaxCharCount is broken + // This happens if user has implimented an decoder fallback with a broken GetMaxCharCount + if (nothingEncoded){ + ThrowCharsOverflow(); + } + } + + // During GetChars we had an invalid byte sequence + // pSrc is backed up to the start of the bad sequence if we didn't have room to + // fall it back. Otherwise pSrc remains where it is. + bool FallbackInvalidByteSequence(BYTE** pSrc, int ch, DecoderFallbackBuffer* fallback, WCHAR** pTarget) + { + // Get our byte[] + BYTE* pStart = *pSrc; + BYTE bytesUnknown[3]; + int size = GetBytesUnknown(pStart, ch, bytesUnknown); + + // Do the actual fallback + if (!fallback->InternalFallback(bytesUnknown, *pSrc, pTarget, size)) + { + // Oops, it failed, back up to pStart + *pSrc = pStart; + return false; + } + + // It worked + return true; + } + + int FallbackInvalidByteSequence(BYTE* pSrc, int ch, DecoderFallbackBuffer *fallback) + { + // Get our byte[] + BYTE bytesUnknown[3]; + int size = GetBytesUnknown(pSrc, ch, bytesUnknown); + + // Do the actual fallback + int count = fallback->InternalFallback(bytesUnknown, pSrc, size); + + // # of fallback chars expected. + // Note that we only get here for "long" sequences, and have already unreserved + // the count that we prereserved for the input bytes + return count; + } + + int GetBytesUnknown(BYTE* pSrc, int ch, BYTE* bytesUnknown) + { + int size; + + // See if it was a plain char + // (have to check >= 0 because we have all sorts of wierd bit flags) + if (ch < 0x100 && ch >= 0) + { + pSrc--; + bytesUnknown[0] = (BYTE)ch; + size = 1; + } + // See if its an unfinished 2 byte sequence + else if ((ch & (SupplimentarySeq | ThreeByteSeq)) == 0) + { + pSrc--; + bytesUnknown[0] = (BYTE)((ch & 0x1F) | 0xc0); + size = 1; + } + // So now we're either 2nd byte of 3 or 4 byte sequence or + // we hit a non-trail byte or we ran out of space for 3rd byte of 4 byte sequence + // 1st check if its a 4 byte sequence + else if ((ch & SupplimentarySeq) != 0) + { + // 3rd byte of 4 byte sequence? + if ((ch & (FinalByte >> 6)) != 0) + { + // 3rd byte of 4 byte sequence + pSrc -= 3; + bytesUnknown[0] = (BYTE)(((ch >> 12) & 0x07) | 0xF0); + bytesUnknown[1] = (BYTE)(((ch >> 6) & 0x3F) | 0x80); + bytesUnknown[2] = (BYTE)(((ch)& 0x3F) | 0x80); + size = 3; + } + else if ((ch & (FinalByte >> 12)) != 0) + { + // 2nd byte of a 4 byte sequence + pSrc -= 2; + bytesUnknown[0] = (BYTE)(((ch >> 6) & 0x07) | 0xF0); + bytesUnknown[1] = (BYTE)(((ch)& 0x3F) | 0x80); + size = 2; + } + else + { + // 4th byte of a 4 byte sequence + pSrc--; + bytesUnknown[0] = (BYTE)(((ch)& 0x07) | 0xF0); + size = 1; + } + } + else + { + // 2nd byte of 3 byte sequence? + if ((ch & (FinalByte >> 6)) != 0) + { + // So its 2nd byte of a 3 byte sequence + pSrc -= 2; + bytesUnknown[0] = (BYTE)(((ch >> 6) & 0x0F) | 0xE0); + bytesUnknown[1] = (BYTE)(((ch)& 0x3F) | 0x80); + size = 2; + } + else + { + // 1st byte of a 3 byte sequence + pSrc--; + bytesUnknown[0] = (BYTE)(((ch)& 0x0F) | 0xE0); + size = 1; + } + } + + return size; + } + +public: + + UTF8Encoding(bool isThrowException) + : encoderReplacementFallback(W("\xFFFD")), decoderReplacementFallback(W("\xFFFD")) + { + if (isThrowException) + { + encoderFallback = &encoderExceptionFallback; + decoderFallback = &decoderExceptionFallback; + } + else + { + encoderFallback = &encoderReplacementFallback; + decoderFallback = &decoderReplacementFallback; + } + } + + // These are bitmasks used to maintain the state in the decoder. They occupy the higher bits + // while the actual character is being built in the lower bits. They are shifted together + // with the actual bits of the character. + + // bits 30 & 31 are used for pending bits fixup + const int FinalByte = 1 << 29; + const int SupplimentarySeq = 1 << 28; + const int ThreeByteSeq = 1 << 27; + + int GetCharCount(BYTE* bytes, int count) + { + Contract::Assert(bytes != nullptr, "[UTF8Encoding.GetCharCount]bytes!=nullptr"); + Contract::Assert(count >= 0, "[UTF8Encoding.GetCharCount]count >=0"); + + // Initialize stuff + BYTE *pSrc = bytes; + BYTE *pEnd = pSrc + count; + + // Start by assuming we have as many as count, charCount always includes the adjustment + // for the character being decoded + int charCount = count; + int ch = 0; + DecoderFallbackBuffer *fallback = nullptr; + + for (;;) + { + // SLOWLOOP: does all range checks, handles all special cases, but it is slow + if (pSrc >= pEnd) { + break; + } + + // read next byte. The JIT optimization seems to be getting confused when + // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead + int cha = *pSrc; + + if (ch == 0) { + // no pending bits + goto ReadChar; + } + + pSrc++; + + // we are expecting to see trailing bytes like 10vvvvvv + if ((cha & 0xC0) != 0x80) { + // This can be a valid starting byte for another UTF8 byte sequence, so let's put + // the current byte back, and try to see if this is a valid byte for another UTF8 byte sequence + pSrc--; + charCount += (ch >> 30); + goto InvalidByteSequence; + } + + // fold in the new byte + ch = (ch << 6) | (cha & 0x3F); + + if ((ch & FinalByte) == 0) { + Contract::Assert((ch & (SupplimentarySeq | ThreeByteSeq)) != 0, + "[UTF8Encoding.GetChars]Invariant volation"); + + if ((ch & SupplimentarySeq) != 0) { + if ((ch & (FinalByte >> 6)) != 0) { + // this is 3rd byte (of 4 byte supplimentary) - nothing to do + continue; + } + + // 2nd byte, check for non-shortest form of supplimentary char and the valid + // supplimentary characters in range 0x010000 - 0x10FFFF at the same time + if (!InRange(ch & 0x1F0, 0x10, 0x100)) { + goto InvalidByteSequence; + } + } + else { + // Must be 2nd byte of a 3-byte sequence + // check for non-shortest form of 3 byte seq + if ((ch & (0x1F << 5)) == 0 || // non-shortest form + (ch & (0xF800 >> 6)) == (0xD800 >> 6)) // illegal individually encoded surrogate + { + goto InvalidByteSequence; + } + } + continue; + } + + // ready to punch + + // adjust for surrogates in non-shortest form + if ((ch & (SupplimentarySeq | 0x1F0000)) == SupplimentarySeq) { + charCount--; + } + goto EncodeChar; + + InvalidByteSequence: + // this code fragment should be close to the gotos referencing it + // Have to do fallback for invalid bytes + if (fallback == nullptr) + { + fallback = decoderFallback->CreateFallbackBuffer(); + fallback->InternalInitialize(bytes, nullptr); + } + charCount += FallbackInvalidByteSequence(pSrc, ch, fallback); + + ch = 0; + continue; + + ReadChar: + ch = *pSrc; + pSrc++; + + ProcessChar: + if (ch > 0x7F) { + // If its > 0x7F, its start of a new multi-byte sequence + + // Long sequence, so unreserve our char. + charCount--; + + // bit 6 has to be non-zero for start of multibyte chars. + if ((ch & 0x40) == 0) { + // Unexpected trail byte + goto InvalidByteSequence; + } + + // start a new long code + if ((ch & 0x20) != 0) { + if ((ch & 0x10) != 0) { + // 4 byte encoding - supplimentary character (2 surrogates) + + ch &= 0x0F; + + // check that bit 4 is zero and the valid supplimentary character + // range 0x000000 - 0x10FFFF at the same time + if (ch > 0x04) { + ch |= 0xf0; + goto InvalidByteSequence; + } + + // Add bit flags so that when we check new characters & rotate we'll be flagged correctly. + // Final byte flag, count fix if we don't make final byte & supplimentary sequence flag. + ch |= (FinalByte >> 3 * 6) | // Final byte is 3 more bytes from now + (1 << 30) | // If it dies on next byte we'll need an extra char + (3 << (30 - 2 * 6)) | // If it dies on last byte we'll need to subtract a char + (SupplimentarySeq) | (SupplimentarySeq >> 6) | + (SupplimentarySeq >> 2 * 6) | (SupplimentarySeq >> 3 * 6); + + // Our character count will be 2 characters for these 4 bytes, so subtract another char + charCount--; + } + else { + // 3 byte encoding + // Add bit flags so that when we check new characters & rotate we'll be flagged correctly. + ch = (ch & 0x0F) | ((FinalByte >> 2 * 6) | (1 << 30) | + (ThreeByteSeq) | (ThreeByteSeq >> 6) | (ThreeByteSeq >> 2 * 6)); + + // We'll expect 1 character for these 3 bytes, so subtract another char. + charCount--; + } + } + else { + // 2 byte encoding + + ch &= 0x1F; + + // check for non-shortest form + if (ch <= 1) { + ch |= 0xc0; + goto InvalidByteSequence; + } + + // Add bit flags so we'll be flagged correctly + ch |= (FinalByte >> 6); + } + continue; + } + + EncodeChar: + +#ifdef FASTLOOP + int availableBytes = PtrDiff(pEnd, pSrc); + + // don't fall into the fast decoding loop if we don't have enough bytes + if (availableBytes <= 13) { + // try to get over the remainder of the ascii characters fast though + BYTE* pLocalEnd = pEnd; // hint to get pLocalEnd enregistered + while (pSrc < pLocalEnd) { + ch = *pSrc; + pSrc++; + + if (ch > 0x7F) + goto ProcessChar; + } + // we are done + ch = 0; + break; + } + + // To compute the upper bound, assume that all characters are ASCII characters at this point, + // the boundary will be decreased for every non-ASCII character we encounter + // Also, we need 7 chars reserve for the unrolled ansi decoding loop and for decoding of multibyte sequences + BYTE *pStop = pSrc + availableBytes - 7; + + while (pSrc < pStop) { + ch = *pSrc; + pSrc++; + + if (ch > 0x7F) { + goto LongCode; + } + + // get pSrc 2-byte aligned + if (((size_t)pSrc & 0x1) != 0) { + ch = *pSrc; + pSrc++; + if (ch > 0x7F) { + goto LongCode; + } + } + + // get pSrc 4-byte aligned + if (((size_t)pSrc & 0x2) != 0) { + ch = *(USHORT*)pSrc; + if ((ch & 0x8080) != 0) { + goto LongCodeWithMask16; + } + pSrc += 2; + } + + + // Run 8 + 8 characters at a time! + while (pSrc < pStop) { + ch = *(int*)pSrc; + int chb = *(int*)(pSrc + 4); + if (((ch | chb) & (int)0x80808080) != 0) { + goto LongCodeWithMask32; + } + pSrc += 8; + + // This is a really small loop - unroll it + if (pSrc >= pStop) + break; + + ch = *(int*)pSrc; + chb = *(int*)(pSrc + 4); + if (((ch | chb) & (int)0x80808080) != 0) { + goto LongCodeWithMask32; + } + pSrc += 8; + } + break; + +#if BIGENDIAN + LongCodeWithMask32 : + // be careful about the sign extension + ch = (int)(((uint)ch) >> 16); + LongCodeWithMask16: + ch = (int)(((uint)ch) >> 8); +#else // BIGENDIAN + LongCodeWithMask32: + LongCodeWithMask16: + ch &= 0xFF; +#endif // BIGENDIAN + pSrc++; + if (ch <= 0x7F) { + continue; + } + + LongCode: + int chc = *pSrc; + pSrc++; + + if ( + // bit 6 has to be zero + (ch & 0x40) == 0 || + // we are expecting to see trailing bytes like 10vvvvvv + (chc & 0xC0) != 0x80) + { + goto BadLongCode; + } + + chc &= 0x3F; + + // start a new long code + if ((ch & 0x20) != 0) { + + // fold the first two bytes together + chc |= (ch & 0x0F) << 6; + + if ((ch & 0x10) != 0) { + // 4 byte encoding - surrogate + ch = *pSrc; + if ( + // check that bit 4 is zero, the non-shortest form of surrogate + // and the valid surrogate range 0x000000 - 0x10FFFF at the same time + !InRange(chc >> 4, 0x01, 0x10) || + // we are expecting to see trailing bytes like 10vvvvvv + (ch & 0xC0) != 0x80) + { + goto BadLongCode; + } + + chc = (chc << 6) | (ch & 0x3F); + + ch = *(pSrc + 1); + // we are expecting to see trailing bytes like 10vvvvvv + if ((ch & 0xC0) != 0x80) { + goto BadLongCode; + } + pSrc += 2; + + // extra byte + charCount--; + } + else { + // 3 byte encoding + ch = *pSrc; + if ( + // check for non-shortest form of 3 byte seq + (chc & (0x1F << 5)) == 0 || + // Can't have surrogates here. + (chc & (0xF800 >> 6)) == (0xD800 >> 6) || + // we are expecting to see trailing bytes like 10vvvvvv + (ch & 0xC0) != 0x80) + { + goto BadLongCode; + } + pSrc++; + + // extra byte + charCount--; + } + } + else { + // 2 byte encoding + + // check for non-shortest form + if ((ch & 0x1E) == 0) { + goto BadLongCode; + } + } + + // extra byte + charCount--; + } +#endif // FASTLOOP + + // no pending bits at this point + ch = 0; + continue; + + BadLongCode: + pSrc -= 2; + ch = 0; + continue; + } + + // May have a problem if we have to flush + if (ch != 0) + { + // We were already adjusting for these, so need to unadjust + charCount += (ch >> 30); + // Have to do fallback for invalid bytes + if (fallback == nullptr) + { + fallback = decoderFallback->CreateFallbackBuffer(); + fallback->InternalInitialize(bytes, nullptr); + } + charCount += FallbackInvalidByteSequence(pSrc, ch, fallback); + } + + // Shouldn't have anything in fallback buffer for GetCharCount + // (don't have to check m_throwOnOverflow for count) + Contract::Assert(fallback == nullptr || fallback->GetRemaining() == 0, + "[UTF8Encoding.GetCharCount]Expected empty fallback buffer at end"); + + InternalDelete(fallback); + + return charCount; + + } + + int GetChars(BYTE* bytes, int byteCount, WCHAR* chars, int charCount) + { + Contract::Assert(chars != nullptr, "[UTF8Encoding.GetChars]chars!=nullptr"); + Contract::Assert(byteCount >= 0, "[UTF8Encoding.GetChars]byteCount >=0"); + Contract::Assert(charCount >= 0, "[UTF8Encoding.GetChars]charCount >=0"); + Contract::Assert(bytes != nullptr, "[UTF8Encoding.GetChars]bytes!=nullptr"); + + BYTE *pSrc = bytes; + WCHAR *pTarget = chars; + + BYTE *pEnd = pSrc + byteCount; + WCHAR *pAllocatedBufferEnd = pTarget + charCount; + + int ch = 0; + + DecoderFallbackBuffer *fallback = nullptr; + + for (;;) + { + // SLOWLOOP: does all range checks, handles all special cases, but it is slow + + if (pSrc >= pEnd) { + break; + } + + // read next byte. The JIT optimization seems to be getting confused when + // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead + int cha = *pSrc; + + if (ch == 0) { + // no pending bits + goto ReadChar; + } + + pSrc++; + + // we are expecting to see trailing bytes like 10vvvvvv + if ((cha & 0xC0) != 0x80) { + // This can be a valid starting byte for another UTF8 byte sequence, so let's put + // the current byte back, and try to see if this is a valid byte for another UTF8 byte sequence + pSrc--; + goto InvalidByteSequence; + } + + // fold in the new byte + ch = (ch << 6) | (cha & 0x3F); + + if ((ch & FinalByte) == 0) { + // Not at last byte yet + Contract::Assert((ch & (SupplimentarySeq | ThreeByteSeq)) != 0, + "[UTF8Encoding.GetChars]Invariant volation"); + + if ((ch & SupplimentarySeq) != 0) { + // Its a 4-byte supplimentary sequence + if ((ch & (FinalByte >> 6)) != 0) { + // this is 3rd byte of 4 byte sequence - nothing to do + continue; + } + + // 2nd byte of 4 bytes + // check for non-shortest form of surrogate and the valid surrogate + // range 0x000000 - 0x10FFFF at the same time + if (!InRange(ch & 0x1F0, 0x10, 0x100)) { + goto InvalidByteSequence; + } + } + else { + // Must be 2nd byte of a 3-byte sequence + // check for non-shortest form of 3 byte seq + if ((ch & (0x1F << 5)) == 0 || // non-shortest form + (ch & (0xF800 >> 6)) == (0xD800 >> 6)) // illegal individually encoded surrogate + { + goto InvalidByteSequence; + } + } + continue; + } + + // ready to punch + + // surrogate in shortest form? + // Might be possible to get rid of this? Already did non-shortest check for 4-byte sequence when reading 2nd byte? + if ((ch & (SupplimentarySeq | 0x1F0000)) > SupplimentarySeq) { + // let the range check for the second char throw the exception + if (pTarget < pAllocatedBufferEnd) { + *pTarget = (WCHAR)(((ch >> 10) & 0x7FF) + + (SHORT)((CharUnicodeInfo::HIGH_SURROGATE_START - (0x10000 >> 10)))); + pTarget++; + + ch = (ch & 0x3FF) + + (int)(CharUnicodeInfo::LOW_SURROGATE_START); + } + } + + goto EncodeChar; + + InvalidByteSequence: + // this code fragment should be close to the gotos referencing it + // Have to do fallback for invalid bytes + if (fallback == nullptr) + { + fallback = decoderFallback->CreateFallbackBuffer(); + fallback->InternalInitialize(bytes, pAllocatedBufferEnd); + } + + // That'll back us up the appropriate # of bytes if we didn't get anywhere + if (!FallbackInvalidByteSequence(&pSrc, ch, fallback, &pTarget)) + { + // Ran out of buffer space + // Need to throw an exception? + Contract::Assert(pSrc >= bytes || pTarget == chars, + "[UTF8Encoding.GetChars]Expected to throw or remain in byte buffer after fallback"); + fallback->InternalReset(); + ThrowCharsOverflow(pTarget == chars); + ch = 0; + break; + } + Contract::Assert(pSrc >= bytes, + "[UTF8Encoding.GetChars]Expected invalid byte sequence to have remained within the byte array"); + ch = 0; + continue; + + ReadChar: + ch = *pSrc; + pSrc++; + + ProcessChar: + if (ch > 0x7F) { + // If its > 0x7F, its start of a new multi-byte sequence + + // bit 6 has to be non-zero + if ((ch & 0x40) == 0) { + goto InvalidByteSequence; + } + + // start a new long code + if ((ch & 0x20) != 0) { + if ((ch & 0x10) != 0) { + // 4 byte encoding - supplimentary character (2 surrogates) + + ch &= 0x0F; + + // check that bit 4 is zero and the valid supplimentary character + // range 0x000000 - 0x10FFFF at the same time + if (ch > 0x04) { + ch |= 0xf0; + goto InvalidByteSequence; + } + + ch |= (FinalByte >> 3 * 6) | (1 << 30) | (3 << (30 - 2 * 6)) | + (SupplimentarySeq) | (SupplimentarySeq >> 6) | + (SupplimentarySeq >> 2 * 6) | (SupplimentarySeq >> 3 * 6); + } + else { + // 3 byte encoding + ch = (ch & 0x0F) | ((FinalByte >> 2 * 6) | (1 << 30) | + (ThreeByteSeq) | (ThreeByteSeq >> 6) | (ThreeByteSeq >> 2 * 6)); + } + } + else { + // 2 byte encoding + + ch &= 0x1F; + + // check for non-shortest form + if (ch <= 1) { + ch |= 0xc0; + goto InvalidByteSequence; + } + + ch |= (FinalByte >> 6); + } + continue; + } + + EncodeChar: + // write the pending character + if (pTarget >= pAllocatedBufferEnd) + { + // Fix chars so we make sure to throw if we didn't output anything + ch &= 0x1fffff; + if (ch > 0x7f) + { + if (ch > 0x7ff) + { + if (ch >= CharUnicodeInfo::LOW_SURROGATE_START && + ch <= CharUnicodeInfo::LOW_SURROGATE_END) + { + pSrc--; // It was 4 bytes + pTarget--; // 1 was stored already, but we can't remember 1/2, so back up + } + else if (ch > 0xffff) + { + pSrc--; // It was 4 bytes, nothing was stored + } + pSrc--; // It was at least 3 bytes + } + pSrc--; // It was at least 2 bytes + } + pSrc--; + + // Throw that we don't have enough room (pSrc could be < chars if we had started to process + // a 4 byte sequence alredy) + Contract::Assert(pSrc >= bytes || pTarget == chars, + "[UTF8Encoding.GetChars]Expected pSrc to be within input buffer or throw due to no output]"); + ThrowCharsOverflow(pTarget == chars); + + // Don't store ch in decoder, we already backed up to its start + ch = 0; + + // Didn't throw, just use this buffer size. + break; + } + *pTarget = (WCHAR)ch; + pTarget++; + +#ifdef FASTLOOP + int availableChars = PtrDiff(pAllocatedBufferEnd, pTarget); + int availableBytes = PtrDiff(pEnd, pSrc); + + // don't fall into the fast decoding loop if we don't have enough bytes + // Test for availableChars is done because pStop would be <= pTarget. + if (availableBytes <= 13) { + // we may need as many as 1 character per byte + if (availableChars < availableBytes) { + // not enough output room. no pending bits at this point + ch = 0; + continue; + } + + // try to get over the remainder of the ascii characters fast though + BYTE* pLocalEnd = pEnd; // hint to get pLocalEnd enregistered + while (pSrc < pLocalEnd) { + ch = *pSrc; + pSrc++; + + if (ch > 0x7F) + goto ProcessChar; + + *pTarget = (WCHAR)ch; + pTarget++; + } + // we are done + ch = 0; + break; + } + + // we may need as many as 1 character per byte, so reduce the byte count if necessary. + // If availableChars is too small, pStop will be before pTarget and we won't do fast loop. + if (availableChars < availableBytes) { + availableBytes = availableChars; + } + + // To compute the upper bound, assume that all characters are ASCII characters at this point, + // the boundary will be decreased for every non-ASCII character we encounter + // Also, we need 7 chars reserve for the unrolled ansi decoding loop and for decoding of multibyte sequences + WCHAR *pStop = pTarget + availableBytes - 7; + + while (pTarget < pStop) { + ch = *pSrc; + pSrc++; + + if (ch > 0x7F) { + goto LongCode; + } + *pTarget = (WCHAR)ch; + pTarget++; + + // get pSrc to be 2-byte aligned + if ((((size_t)pSrc) & 0x1) != 0) { + ch = *pSrc; + pSrc++; + if (ch > 0x7F) { + goto LongCode; + } + *pTarget = (WCHAR)ch; + pTarget++; + } + + // get pSrc to be 4-byte aligned + if ((((size_t)pSrc) & 0x2) != 0) { + ch = *(USHORT*)pSrc; + if ((ch & 0x8080) != 0) { + goto LongCodeWithMask16; + } + + // Unfortunately, this is endianess sensitive +#if BIGENDIAN + *pTarget = (WCHAR)((ch >> 8) & 0x7F); + pSrc += 2; + *(pTarget + 1) = (WCHAR)(ch & 0x7F); + pTarget += 2; +#else // BIGENDIAN + *pTarget = (WCHAR)(ch & 0x7F); + pSrc += 2; + *(pTarget + 1) = (WCHAR)((ch >> 8) & 0x7F); + pTarget += 2; +#endif // BIGENDIAN + } + + // Run 8 characters at a time! + while (pTarget < pStop) { + ch = *(int*)pSrc; + int chb = *(int*)(pSrc + 4); + if (((ch | chb) & (int)0x80808080) != 0) { + goto LongCodeWithMask32; + } + + // Unfortunately, this is endianess sensitive +#if BIGENDIAN + *pTarget = (WCHAR)((ch >> 24) & 0x7F); + *(pTarget + 1) = (WCHAR)((ch >> 16) & 0x7F); + *(pTarget + 2) = (WCHAR)((ch >> 8) & 0x7F); + *(pTarget + 3) = (WCHAR)(ch & 0x7F); + pSrc += 8; + *(pTarget + 4) = (WCHAR)((chb >> 24) & 0x7F); + *(pTarget + 5) = (WCHAR)((chb >> 16) & 0x7F); + *(pTarget + 6) = (WCHAR)((chb >> 8) & 0x7F); + *(pTarget + 7) = (WCHAR)(chb & 0x7F); + pTarget += 8; +#else // BIGENDIAN + *pTarget = (WCHAR)(ch & 0x7F); + *(pTarget + 1) = (WCHAR)((ch >> 8) & 0x7F); + *(pTarget + 2) = (WCHAR)((ch >> 16) & 0x7F); + *(pTarget + 3) = (WCHAR)((ch >> 24) & 0x7F); + pSrc += 8; + *(pTarget + 4) = (WCHAR)(chb & 0x7F); + *(pTarget + 5) = (WCHAR)((chb >> 8) & 0x7F); + *(pTarget + 6) = (WCHAR)((chb >> 16) & 0x7F); + *(pTarget + 7) = (WCHAR)((chb >> 24) & 0x7F); + pTarget += 8; +#endif // BIGENDIAN + } + break; + +#if BIGENDIAN + LongCodeWithMask32 : + // be careful about the sign extension + ch = (int)(((uint)ch) >> 16); + LongCodeWithMask16: + ch = (int)(((uint)ch) >> 8); +#else // BIGENDIAN + LongCodeWithMask32: + LongCodeWithMask16: + ch &= 0xFF; +#endif // BIGENDIAN + pSrc++; + if (ch <= 0x7F) { + *pTarget = (WCHAR)ch; + pTarget++; + continue; + } + + LongCode: + int chc = *pSrc; + pSrc++; + + if ( + // bit 6 has to be zero + (ch & 0x40) == 0 || + // we are expecting to see trailing bytes like 10vvvvvv + (chc & 0xC0) != 0x80) + { + goto BadLongCode; + } + + chc &= 0x3F; + + // start a new long code + if ((ch & 0x20) != 0) { + + // fold the first two bytes together + chc |= (ch & 0x0F) << 6; + + if ((ch & 0x10) != 0) { + // 4 byte encoding - surrogate + ch = *pSrc; + if ( + // check that bit 4 is zero, the non-shortest form of surrogate + // and the valid surrogate range 0x000000 - 0x10FFFF at the same time + !InRange(chc >> 4, 0x01, 0x10) || + // we are expecting to see trailing bytes like 10vvvvvv + (ch & 0xC0) != 0x80) + { + goto BadLongCode; + } + + chc = (chc << 6) | (ch & 0x3F); + + ch = *(pSrc + 1); + // we are expecting to see trailing bytes like 10vvvvvv + if ((ch & 0xC0) != 0x80) { + goto BadLongCode; + } + pSrc += 2; + + ch = (chc << 6) | (ch & 0x3F); + + *pTarget = (WCHAR)(((ch >> 10) & 0x7FF) + + (SHORT)(CharUnicodeInfo::HIGH_SURROGATE_START - (0x10000 >> 10))); + pTarget++; + + ch = (ch & 0x3FF) + + (SHORT)(CharUnicodeInfo::LOW_SURROGATE_START); + + // extra byte, we're already planning 2 chars for 2 of these bytes, + // but the big loop is testing the target against pStop, so we need + // to subtract 2 more or we risk overrunning the input. Subtract + // one here and one below. + pStop--; + } + else { + // 3 byte encoding + ch = *pSrc; + if ( + // check for non-shortest form of 3 byte seq + (chc & (0x1F << 5)) == 0 || + // Can't have surrogates here. + (chc & (0xF800 >> 6)) == (0xD800 >> 6) || + // we are expecting to see trailing bytes like 10vvvvvv + (ch & 0xC0) != 0x80) + { + goto BadLongCode; + } + pSrc++; + + ch = (chc << 6) | (ch & 0x3F); + + // extra byte, we're only expecting 1 char for each of these 3 bytes, + // but the loop is testing the target (not source) against pStop, so + // we need to subtract 2 more or we risk overrunning the input. + // Subtract 1 here and one more below + pStop--; + } + } + else { + // 2 byte encoding + + ch &= 0x1F; + + // check for non-shortest form + if (ch <= 1) { + goto BadLongCode; + } + ch = (ch << 6) | chc; + } + + *pTarget = (WCHAR)ch; + pTarget++; + + // extra byte, we're only expecting 1 char for each of these 2 bytes, + // but the loop is testing the target (not source) against pStop. + // subtract an extra count from pStop so that we don't overrun the input. + pStop--; + } +#endif // FASTLOOP + + Contract::Assert(pTarget <= pAllocatedBufferEnd, "[UTF8Encoding.GetChars]pTarget <= pAllocatedBufferEnd"); + + // no pending bits at this point + ch = 0; + continue; + + BadLongCode: + pSrc -= 2; + ch = 0; + continue; + } + + if (ch != 0) + { + // Have to do fallback for invalid bytes + if (fallback == nullptr) + { + fallback = decoderFallback->CreateFallbackBuffer(); + fallback->InternalInitialize(bytes, pAllocatedBufferEnd); + } + + // This'll back us up the appropriate # of bytes if we didn't get anywhere + if (!FallbackInvalidByteSequence(pSrc, ch, fallback)) + { + Contract::Assert(pSrc >= bytes || pTarget == chars, + "[UTF8Encoding.GetChars]Expected to throw or remain in byte buffer while flushing"); + + // Ran out of buffer space + // Need to throw an exception? + fallback->InternalReset(); + ThrowCharsOverflow(pTarget == chars); + } + Contract::Assert(pSrc >= bytes, + "[UTF8Encoding.GetChars]Expected flushing invalid byte sequence to have remained within the byte array"); + ch = 0; + } + + // Shouldn't have anything in fallback buffer for GetChars + // (don't have to check m_throwOnOverflow for chars) + Contract::Assert(fallback == nullptr || fallback->GetRemaining() == 0, + "[UTF8Encoding.GetChars]Expected empty fallback buffer at end"); + + InternalDelete(fallback); + + return PtrDiff(pTarget, chars); + } + + int GetBytes(WCHAR* chars, int charCount, BYTE* bytes, int byteCount) + { + Contract::Assert(chars != nullptr, "[UTF8Encoding.GetBytes]chars!=nullptr"); + Contract::Assert(byteCount >= 0, "[UTF8Encoding.GetBytes]byteCount >=0"); + Contract::Assert(charCount >= 0, "[UTF8Encoding.GetBytes]charCount >=0"); + Contract::Assert(bytes != nullptr, "[UTF8Encoding.GetBytes]bytes!=nullptr"); + + // For fallback we may need a fallback buffer. + // We wait to initialize it though in case we don't have any broken input unicode + EncoderFallbackBuffer* fallbackBuffer = nullptr; + WCHAR *pSrc = chars; + BYTE *pTarget = bytes; + + WCHAR *pEnd = pSrc + charCount; + BYTE *pAllocatedBufferEnd = pTarget + byteCount; + + int ch = 0; + + // assume that JIT will enregister pSrc, pTarget and ch + + for (;;) { + // SLOWLOOP: does all range checks, handles all special cases, but it is slow + + if (pSrc >= pEnd) { + + if (ch == 0) { + // Check if there's anything left to get out of the fallback buffer + ch = fallbackBuffer != nullptr ? fallbackBuffer->InternalGetNextChar() : 0; + if (ch > 0) { + goto ProcessChar; + } + } + else { + // Case of leftover surrogates in the fallback buffer + if (fallbackBuffer != nullptr && fallbackBuffer->bFallingBack) { + Contract::Assert(ch >= 0xD800 && ch <= 0xDBFF, + "[UTF8Encoding.GetBytes]expected high surrogate"); //, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture)); + + int cha = ch; + + ch = fallbackBuffer->InternalGetNextChar(); + + if (InRange(ch, CharUnicodeInfo::LOW_SURROGATE_START, CharUnicodeInfo::LOW_SURROGATE_END)) { + ch = ch + (cha << 10) + (0x10000 - CharUnicodeInfo::LOW_SURROGATE_START - (CharUnicodeInfo::HIGH_SURROGATE_START << 10)); + goto EncodeChar; + } + else if (ch > 0){ + goto ProcessChar; + } + else { + break; + } + } + } + + // attempt to encode the partial surrogate (will fail or ignore) + if (ch > 0) + goto EncodeChar; + + // We're done + break; + } + + if (ch > 0) { + // We have a high surrogate left over from a previous loop. + Contract::Assert(ch >= 0xD800 && ch <= 0xDBFF, + "[UTF8Encoding.GetBytes]expected high surrogate");//, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture)); + + // use separate helper variables for local contexts so that the jit optimizations + // won't get confused about the variable lifetimes + int cha = *pSrc; + + // In previous byte, we encountered a high surrogate, so we are expecting a low surrogate here. + // if (IsLowSurrogate(cha)) { + if (InRange(cha, CharUnicodeInfo::LOW_SURROGATE_START, CharUnicodeInfo::LOW_SURROGATE_END)) { + ch = cha + (ch << 10) + + (0x10000 + - CharUnicodeInfo::LOW_SURROGATE_START + - (CharUnicodeInfo::HIGH_SURROGATE_START << 10)); + + pSrc++; + } + // else ch is still high surrogate and encoding will fail + + // attempt to encode the surrogate or partial surrogate + goto EncodeChar; + } + + // If we've used a fallback, then we have to check for it + if (fallbackBuffer != nullptr) + { + ch = fallbackBuffer->InternalGetNextChar(); + if (ch > 0) goto ProcessChar; + } + + // read next char. The JIT optimization seems to be getting confused when + // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead + ch = *pSrc; + pSrc++; + + ProcessChar: + if (InRange(ch, CharUnicodeInfo::HIGH_SURROGATE_START, CharUnicodeInfo::HIGH_SURROGATE_END)) { + continue; + } + // either good char or partial surrogate + + EncodeChar: + // throw exception on partial surrogate if necessary + if (InRange(ch, CharUnicodeInfo::HIGH_SURROGATE_START, CharUnicodeInfo::LOW_SURROGATE_END)) + { + // Lone surrogates aren't allowed, we have to do fallback for them + // Have to make a fallback buffer if we don't have one + if (fallbackBuffer == nullptr) + { + // wait on fallbacks if we can + // For fallback we may need a fallback buffer + fallbackBuffer = encoderFallback->CreateFallbackBuffer(); + + // Set our internal fallback interesting things. + fallbackBuffer->InternalInitialize(chars, pEnd, true); + } + + // Do our fallback. Actually we already know its a mixed up surrogate, + // so the ref pSrc isn't gonna do anything. + fallbackBuffer->InternalFallback((WCHAR)ch, &pSrc); + + // Ignore it if we don't throw + ch = 0; + continue; + } + + // Count bytes needed + int bytesNeeded = 1; + if (ch > 0x7F) { + if (ch > 0x7FF) { + if (ch > 0xFFFF) { + bytesNeeded++; // 4 bytes (surrogate pair) + } + bytesNeeded++; // 3 bytes (800-FFFF) + } + bytesNeeded++; // 2 bytes (80-7FF) + } + + if (pTarget > pAllocatedBufferEnd - bytesNeeded) { + // Left over surrogate from last time will cause pSrc == chars, so we'll throw + if (fallbackBuffer != nullptr && fallbackBuffer->bFallingBack) + { + fallbackBuffer->MovePrevious(); // Didn't use this fallback char + if (ch > 0xFFFF) + fallbackBuffer->MovePrevious(); // Was surrogate, didn't use 2nd part either + } + else + { + pSrc--; // Didn't use this char + if (ch > 0xFFFF) + pSrc--; // Was surrogate, didn't use 2nd part either + } + Contract::Assert(pSrc >= chars || pTarget == bytes, + "[UTF8Encoding.GetBytes]Expected pSrc to be within buffer or to throw with insufficient room."); + ThrowBytesOverflow(pTarget == bytes); // Throw if we must + ch = 0; // Nothing left over (we backed up to start of pair if supplimentary) + break; + } + + if (ch <= 0x7F) { + *pTarget = (BYTE)ch; + } + else { + // use separate helper variables for local contexts so that the jit optimizations + // won't get confused about the variable lifetimes + int chb; + if (ch <= 0x7FF) { + // 2 BYTE encoding + chb = (BYTE)(0xC0 | (ch >> 6)); + } + else + { + if (ch <= 0xFFFF) { + chb = (BYTE)(0xE0 | (ch >> 12)); + } + else + { + *pTarget = (BYTE)(0xF0 | (ch >> 18)); + pTarget++; + + chb = 0x80 | ((ch >> 12) & 0x3F); + } + *pTarget = (BYTE)chb; + pTarget++; + + chb = 0x80 | ((ch >> 6) & 0x3F); + } + *pTarget = (BYTE)chb; + pTarget++; + + *pTarget = (BYTE)0x80 | (ch & 0x3F); + } + pTarget++; + + +#ifdef FASTLOOP + // If still have fallback don't do fast loop + if (fallbackBuffer != nullptr && (ch = fallbackBuffer->InternalGetNextChar()) != 0) + goto ProcessChar; + + int availableChars = PtrDiff(pEnd, pSrc); + int availableBytes = PtrDiff(pAllocatedBufferEnd, pTarget); + + // don't fall into the fast decoding loop if we don't have enough characters + // Note that if we don't have enough bytes, pStop will prevent us from entering the fast loop. + if (availableChars <= 13) { + // we are hoping for 1 BYTE per char + if (availableBytes < availableChars) { + // not enough output room. no pending bits at this point + ch = 0; + continue; + } + + // try to get over the remainder of the ascii characters fast though + WCHAR* pLocalEnd = pEnd; // hint to get pLocalEnd enregistered + while (pSrc < pLocalEnd) { + ch = *pSrc; + pSrc++; + + // Not ASCII, need more than 1 BYTE per char + if (ch > 0x7F) + goto ProcessChar; + + *pTarget = (BYTE)ch; + pTarget++; + } + // we are done, let ch be 0 to clear encoder + ch = 0; + break; + } + + // we need at least 1 BYTE per character, but Convert might allow us to convert + // only part of the input, so try as much as we can. Reduce charCount if necessary + if (availableBytes < availableChars) + { + availableChars = availableBytes; + } + + // FASTLOOP: + // - optimistic range checks + // - fallbacks to the slow loop for all special cases, exception throwing, etc. + + // To compute the upper bound, assume that all characters are ASCII characters at this point, + // the boundary will be decreased for every non-ASCII character we encounter + // Also, we need 5 chars reserve for the unrolled ansi decoding loop and for decoding of surrogates + // If there aren't enough bytes for the output, then pStop will be <= pSrc and will bypass the loop. + WCHAR *pStop = pSrc + availableChars - 5; + + while (pSrc < pStop) { + ch = *pSrc; + pSrc++; + + if (ch > 0x7F) { + goto LongCode; + } + *pTarget = (BYTE)ch; + pTarget++; + + // get pSrc aligned + if (((size_t)pSrc & 0x2) != 0) { + ch = *pSrc; + pSrc++; + if (ch > 0x7F) { + goto LongCode; + } + *pTarget = (BYTE)ch; + pTarget++; + } + + // Run 4 characters at a time! + while (pSrc < pStop) { + ch = *(int*)pSrc; + int chc = *(int*)(pSrc + 2); + if (((ch | chc) & (int)0xFF80FF80) != 0) { + goto LongCodeWithMask; + } + + // Unfortunately, this is endianess sensitive +#if BIGENDIAN + *pTarget = (BYTE)(ch >> 16); + *(pTarget + 1) = (BYTE)ch; + pSrc += 4; + *(pTarget + 2) = (BYTE)(chc >> 16); + *(pTarget + 3) = (BYTE)chc; + pTarget += 4; +#else // BIGENDIAN + *pTarget = (BYTE)ch; + *(pTarget + 1) = (BYTE)(ch >> 16); + pSrc += 4; + *(pTarget + 2) = (BYTE)chc; + *(pTarget + 3) = (BYTE)(chc >> 16); + pTarget += 4; +#endif // BIGENDIAN + } + continue; + + LongCodeWithMask: +#if BIGENDIAN + // be careful about the sign extension + ch = (int)(((uint)ch) >> 16); +#else // BIGENDIAN + ch = (WCHAR)ch; +#endif // BIGENDIAN + pSrc++; + + if (ch > 0x7F) { + goto LongCode; + } + *pTarget = (BYTE)ch; + pTarget++; + continue; + + LongCode: + // use separate helper variables for slow and fast loop so that the jit optimizations + // won't get confused about the variable lifetimes + int chd; + if (ch <= 0x7FF) { + // 2 BYTE encoding + chd = 0xC0 | (ch >> 6); + } + else { + if (!InRange(ch, CharUnicodeInfo::HIGH_SURROGATE_START, CharUnicodeInfo::LOW_SURROGATE_END)) { + // 3 BYTE encoding + chd = 0xE0 | (ch >> 12); + } + else + { + // 4 BYTE encoding - high surrogate + low surrogate + if (ch > CharUnicodeInfo::HIGH_SURROGATE_END) { + // low without high -> bad, try again in slow loop + pSrc -= 1; + break; + } + + chd = *pSrc; + pSrc++; + + // if (!IsLowSurrogate(chd)) { + if (!InRange(chd, CharUnicodeInfo::LOW_SURROGATE_START, CharUnicodeInfo::LOW_SURROGATE_END)) { + // high not followed by low -> bad, try again in slow loop + pSrc -= 2; + break; + } + + ch = chd + (ch << 10) + + (0x10000 + - CharUnicodeInfo::LOW_SURROGATE_START + - (CharUnicodeInfo::HIGH_SURROGATE_START << 10)); + + *pTarget = (BYTE)(0xF0 | (ch >> 18)); + // pStop - this BYTE is compensated by the second surrogate character + // 2 input chars require 4 output bytes. 2 have been anticipated already + // and 2 more will be accounted for by the 2 pStop-- calls below. + pTarget++; + + chd = 0x80 | ((ch >> 12) & 0x3F); + } + *pTarget = (BYTE)chd; + pStop--; // 3 BYTE sequence for 1 char, so need pStop-- and the one below too. + pTarget++; + + chd = 0x80 | ((ch >> 6) & 0x3F); + } + *pTarget = (BYTE)chd; + pStop--; // 2 BYTE sequence for 1 char so need pStop--. + pTarget++; + + *pTarget = (BYTE)(0x80 | (ch & 0x3F)); + // pStop - this BYTE is already included + pTarget++; + } + + Contract::Assert(pTarget <= pAllocatedBufferEnd, "[UTF8Encoding.GetBytes]pTarget <= pAllocatedBufferEnd"); + +#endif // FASTLOOP + + // no pending char at this point + ch = 0; + } + + InternalDelete(fallbackBuffer); + + return (int)(pTarget - bytes); + } + + int GetByteCount(WCHAR *chars, int count) + { + // For fallback we may need a fallback buffer. + // We wait to initialize it though in case we don't have any broken input unicode + EncoderFallbackBuffer* fallbackBuffer = nullptr; + WCHAR *pSrc = chars; + WCHAR *pEnd = pSrc + count; + + // Start by assuming we have as many as count + int byteCount = count; + + int ch = 0; + + for (;;) { + // SLOWLOOP: does all range checks, handles all special cases, but it is slow + if (pSrc >= pEnd) { + + if (ch == 0) { + // Unroll any fallback that happens at the end + ch = fallbackBuffer != nullptr ? fallbackBuffer->InternalGetNextChar() : 0; + if (ch > 0) { + byteCount++; + goto ProcessChar; + } + } + else { + // Case of surrogates in the fallback. + if (fallbackBuffer != nullptr && fallbackBuffer->bFallingBack) { + Contract::Assert(ch >= 0xD800 && ch <= 0xDBFF, + "[UTF8Encoding.GetBytes]expected high surrogate");// , not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture)); + + ch = fallbackBuffer->InternalGetNextChar(); + byteCount++; + + if (InRange(ch, CharUnicodeInfo::LOW_SURROGATE_START, CharUnicodeInfo::LOW_SURROGATE_END)) { + ch = 0xfffd; + byteCount++; + goto EncodeChar; + } + else if (ch > 0){ + goto ProcessChar; + } + else { + byteCount--; // ignore last one. + break; + } + } + } + + if (ch <= 0) { + break; + } + + // attempt to encode the partial surrogate (will fallback or ignore it), it'll also subtract 1. + byteCount++; + goto EncodeChar; + } + + if (ch > 0) { + Contract::Assert(ch >= 0xD800 && ch <= 0xDBFF, + "[UTF8Encoding.GetBytes]expected high surrogate"); // , not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture)); + + // use separate helper variables for local contexts so that the jit optimizations + // won't get confused about the variable lifetimes + int cha = *pSrc; + + // count the pending surrogate + byteCount++; + + // In previous byte, we encountered a high surrogate, so we are expecting a low surrogate here. + // if (IsLowSurrogate(cha)) { + if (InRange(cha, CharUnicodeInfo::LOW_SURROGATE_START, CharUnicodeInfo::LOW_SURROGATE_END)) { + // Don't need a real # because we're just counting, anything > 0x7ff ('cept surrogate) will do. + ch = 0xfffd; + // ch = cha + (ch << 10) + + // (0x10000 + // - CharUnicodeInfo::LOW_SURROGATE_START + // - (CharUnicodeInfo::HIGH_SURROGATE_START << 10) ); + + // Use this next char + pSrc++; + } + // else ch is still high surrogate and encoding will fail (so don't add count) + + // attempt to encode the surrogate or partial surrogate + goto EncodeChar; + } + + // If we've used a fallback, then we have to check for it + if (fallbackBuffer != nullptr) + { + ch = fallbackBuffer->InternalGetNextChar(); + if (ch > 0) + { + // We have an extra byte we weren't expecting. + byteCount++; + goto ProcessChar; + } + } + + // read next char. The JIT optimization seems to be getting confused when + // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead + ch = *pSrc; + pSrc++; + + ProcessChar: + if (InRange(ch, CharUnicodeInfo::HIGH_SURROGATE_START, CharUnicodeInfo::HIGH_SURROGATE_END)) { + // we will count this surrogate next time around + byteCount--; + continue; + } + // either good char or partial surrogate + + EncodeChar: + // throw exception on partial surrogate if necessary + if (InRange(ch, CharUnicodeInfo::HIGH_SURROGATE_START, CharUnicodeInfo::LOW_SURROGATE_END)) + { + // Lone surrogates aren't allowed + // Have to make a fallback buffer if we don't have one + if (fallbackBuffer == nullptr) + { + // wait on fallbacks if we can + // For fallback we may need a fallback buffer + fallbackBuffer = encoderFallback->CreateFallbackBuffer(); + + // Set our internal fallback interesting things. + fallbackBuffer->InternalInitialize(chars, chars + count, false); + } + + // Do our fallback. Actually we already know its a mixed up surrogate, + // so the ref pSrc isn't gonna do anything. + fallbackBuffer->InternalFallback((WCHAR)ch, &pSrc); + + // Ignore it if we don't throw (we had preallocated this ch) + byteCount--; + ch = 0; + continue; + } + + // Count them + if (ch > 0x7F) { + if (ch > 0x7FF) { + // the extra surrogate byte was compensated by the second surrogate character + // (2 surrogates make 4 bytes. We've already counted 2 bytes, 1 per char) + byteCount++; + } + byteCount++; + } + +#if WIN64 + // check for overflow + if (byteCount < 0) { + break; + } +#endif + +#ifdef FASTLOOP + // If still have fallback don't do fast loop + if (fallbackBuffer != nullptr && (ch = fallbackBuffer->InternalGetNextChar()) != 0) + { + // We're reserving 1 byte for each char by default + byteCount++; + goto ProcessChar; + } + + int availableChars = PtrDiff(pEnd, pSrc); + + // don't fall into the fast decoding loop if we don't have enough characters + if (availableChars <= 13) { + // try to get over the remainder of the ascii characters fast though + WCHAR* pLocalEnd = pEnd; // hint to get pLocalEnd enregistered + while (pSrc < pLocalEnd) { + ch = *pSrc; + pSrc++; + if (ch > 0x7F) + goto ProcessChar; + } + + // we are done + break; + } + +#if WIN64 + // make sure that we won't get a silent overflow inside the fast loop + // (Fall out to slow loop if we have this many characters) + availableChars &= 0x0FFFFFFF; +#endif + + // To compute the upper bound, assume that all characters are ASCII characters at this point, + // the boundary will be decreased for every non-ASCII character we encounter + // Also, we need 3 + 4 chars reserve for the unrolled ansi decoding loop and for decoding of surrogates + WCHAR *pStop = pSrc + availableChars - (3 + 4); + + while (pSrc < pStop) { + ch = *pSrc; + pSrc++; + + if (ch > 0x7F) // Not ASCII + { + if (ch > 0x7FF) // Not 2 Byte + { + if ((ch & 0xF800) == 0xD800) // See if its a Surrogate + goto LongCode; + byteCount++; + } + byteCount++; + } + + // get pSrc aligned + if (((size_t)pSrc & 0x2) != 0) { + ch = *pSrc; + pSrc++; + if (ch > 0x7F) // Not ASCII + { + if (ch > 0x7FF) // Not 2 Byte + { + if ((ch & 0xF800) == 0xD800) // See if its a Surrogate + goto LongCode; + byteCount++; + } + byteCount++; + } + } + + // Run 2 * 4 characters at a time! + while (pSrc < pStop) { + ch = *(int*)pSrc; + int chc = *(int*)(pSrc + 2); + if (((ch | chc) & (int)0xFF80FF80) != 0) // See if not ASCII + { + if (((ch | chc) & (int)0xF800F800) != 0) // See if not 2 Byte + { + goto LongCodeWithMask; + } + + + if ((ch & (int)0xFF800000) != 0) // Actually 0x07800780 is all we care about (4 bits) + byteCount++; + if ((ch & (int)0xFF80) != 0) + byteCount++; + if ((chc & (int)0xFF800000) != 0) + byteCount++; + if ((chc & (int)0xFF80) != 0) + byteCount++; + } + pSrc += 4; + + ch = *(int*)pSrc; + chc = *(int*)(pSrc + 2); + if (((ch | chc) & (int)0xFF80FF80) != 0) // See if not ASCII + { + if (((ch | chc) & (int)0xF800F800) != 0) // See if not 2 Byte + { + goto LongCodeWithMask; + } + + if ((ch & (int)0xFF800000) != 0) + byteCount++; + if ((ch & (int)0xFF80) != 0) + byteCount++; + if ((chc & (int)0xFF800000) != 0) + byteCount++; + if ((chc & (int)0xFF80) != 0) + byteCount++; + } + pSrc += 4; + } + break; + + LongCodeWithMask: +#if BIGENDIAN + // be careful about the sign extension + ch = (int)(((uint)ch) >> 16); +#else // BIGENDIAN + ch = (WCHAR)ch; +#endif // BIGENDIAN + pSrc++; + + if (ch <= 0x7F) { + continue; + } + + LongCode: + // use separate helper variables for slow and fast loop so that the jit optimizations + // won't get confused about the variable lifetimes + if (ch > 0x7FF) { + if (InRange(ch, CharUnicodeInfo::HIGH_SURROGATE_START, CharUnicodeInfo::LOW_SURROGATE_END)) { + // 4 byte encoding - high surrogate + low surrogate + + int chd = *pSrc; + if ( + ch > CharUnicodeInfo::HIGH_SURROGATE_END || + !InRange(chd, CharUnicodeInfo::LOW_SURROGATE_START, CharUnicodeInfo::LOW_SURROGATE_END)) + { + // Back up and drop out to slow loop to figure out error + pSrc--; + break; + } + pSrc++; + + // byteCount - this byte is compensated by the second surrogate character + } + byteCount++; + } + byteCount++; + + // byteCount - the last byte is already included + } +#endif // FASTLOOP + + // no pending char at this point + ch = 0; + } + +#if WIN64 + // check for overflow + if (byteCount < 0) { + throw ArgumentException("Conversion buffer overflow."); + } +#endif + + Contract::Assert(fallbackBuffer == nullptr || fallbackBuffer->GetRemaining() == 0, + "[UTF8Encoding.GetByteCount]Expected Empty fallback buffer"); + + InternalDelete(fallbackBuffer); + + return byteCount; + } + +}; + + +//////////////////////////////////////////////////////////////////////////// +// +// UTF8ToUnicode +// +// Maps a UTF-8 character string to its wide character string counterpart. +// +//////////////////////////////////////////////////////////////////////////// + +int UTF8ToUnicode( + LPCSTR lpSrcStr, + int cchSrc, + LPWSTR lpDestStr, + int cchDest, + DWORD dwFlags + ) +{ + int ret; + UTF8Encoding enc(dwFlags & MB_ERR_INVALID_CHARS); + try { + ret = enc.GetCharCount((BYTE*)lpSrcStr, cchSrc); + if (cchDest){ + if (ret > cchDest){ + SetLastError(ERROR_INSUFFICIENT_BUFFER); + ret = 0; + } + enc.GetChars((BYTE*)lpSrcStr, cchSrc, (WCHAR*)lpDestStr, ret); + } + } + catch (const InsufficientBufferException& e){ + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + catch (const DecoderFallbackException& e){ + SetLastError(ERROR_NO_UNICODE_TRANSLATION); + return 0; + } + catch (const ArgumentException& e){ + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + return ret; +} + +//////////////////////////////////////////////////////////////////////////// +// +// UnicodeToUTF8 +// +// Maps a Unicode character string to its UTF-8 string counterpart. +// +//////////////////////////////////////////////////////////////////////////// + +int UnicodeToUTF8( + LPCWSTR lpSrcStr, + int cchSrc, + LPSTR lpDestStr, + int cchDest) +{ + int ret; + UTF8Encoding enc(false); + try{ + ret = enc.GetByteCount((WCHAR*)lpSrcStr, cchSrc); + if (cchDest){ + if (ret > cchDest){ + SetLastError(ERROR_INSUFFICIENT_BUFFER); + ret = 0; + } + enc.GetBytes((WCHAR*)lpSrcStr, cchSrc, (BYTE*)lpDestStr, ret); + } + } + catch (const InsufficientBufferException& e){ + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + catch (const EncoderFallbackException& e){ + SetLastError(ERROR_NO_UNICODE_TRANSLATION); + return 0; + } + catch (const ArgumentException& e){ + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/common.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/common.cpp new file mode 100644 index 0000000..49b1b6d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/common.cpp @@ -0,0 +1,66 @@ +// 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: + + common.c + +Abstract: + + Implementation of the common mapping functions. + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" + +#include "common.h" + +#include + +SET_DEFAULT_DEBUG_CHANNEL(VIRTUAL); + +/***** + * + * W32toUnixAccessControl( DWORD ) - Maps Win32 to Unix memory access controls . + * + */ +INT W32toUnixAccessControl( IN DWORD flProtect ) +{ + INT MemAccessControl = 0; + + switch ( flProtect & 0xff ) + { + case PAGE_READONLY : + MemAccessControl = PROT_READ; + break; + case PAGE_READWRITE : + MemAccessControl = PROT_READ | PROT_WRITE; + break; + case PAGE_EXECUTE_READWRITE: + MemAccessControl = PROT_EXEC | PROT_READ | PROT_WRITE; + break; + case PAGE_EXECUTE : + MemAccessControl = PROT_EXEC; + break; + case PAGE_EXECUTE_READ : + MemAccessControl = PROT_EXEC | PROT_READ; + break; + case PAGE_NOACCESS : + MemAccessControl = PROT_NONE; + break; + + default: + MemAccessControl = 0; + ERROR( "Incorrect or no protection flags specified.\n" ); + break; + } + return MemAccessControl; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/common.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/common.h new file mode 100644 index 0000000..68d8fc6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/common.h @@ -0,0 +1,43 @@ +// 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: + + include/pal/common.h + +Abstract: + Header file for common helper functions in the map module. + + + +--*/ + +#ifndef __COMMON_H_ +#define __COMMON_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/***** + * + * W32toUnixAccessControl( DWORD ) - Maps Win32 to Unix memory access controls . + * + */ +INT W32toUnixAccessControl( IN DWORD flProtect ); + +#ifdef __cplusplus +} +#endif + +#endif /* __COMMON_H_ */ + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/map.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/map.cpp new file mode 100644 index 0000000..cac7364 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/map.cpp @@ -0,0 +1,2726 @@ +// 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: + + map.cpp + +Abstract: + + Implementation of file mapping API. + + + +--*/ + + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/init.h" +#include "pal/critsect.h" +#include "pal/virtual.h" +#include "pal/environ.h" +#include "common.h" +#include "pal/map.hpp" +#include "pal/thread.hpp" +#include "pal/file.hpp" +#include "pal/malloc.hpp" + +#include +#include +#include +#include +#include +#include + +#include "rt/ntimage.h" +#include + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(VIRTUAL); + +#include "pal/utils.h" + +// +// The mapping critical section guards access to the list +// of currently mapped views. If a thread needs to access +// both this critical section and the data for an object +// it must acquire the object data first. That is, a thread +// cannot acquire any other locks after taking hold of +// this critical section. +// + +CRITICAL_SECTION mapping_critsec; +LIST_ENTRY MappedViewList; + +#ifndef CORECLR +static PAL_ERROR MAPCreateTempFile(CPalThread *, PINT, PSZ); +#endif // !CORECLR +static PAL_ERROR MAPGrowLocalFile(INT, UINT); +static PMAPPED_VIEW_LIST MAPGetViewForAddress( LPCVOID ); +static PAL_ERROR MAPDesiredAccessAllowed( DWORD, DWORD, DWORD ); + +static INT MAPProtectionToFileOpenFlags( DWORD ); +static BOOL MAPIsRequestPermissible( DWORD, CFileProcessLocalData * ); +static BOOL MAPContainsInvalidFlags( DWORD ); +static DWORD MAPConvertProtectToAccess( DWORD ); +static INT MAPFileMapToMmapFlags( DWORD ); +static DWORD MAPMmapProtToAccessFlags( int prot ); +#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS +static NativeMapHolder * NewNativeMapHolder(CPalThread *pThread, LPVOID address, SIZE_T size, + SIZE_T offset, long init_ref_count); +static LONG NativeMapHolderAddRef(NativeMapHolder * thisPMH); +static LONG NativeMapHolderRelease(CPalThread *pThread, NativeMapHolder * thisPMH); +static PMAPPED_VIEW_LIST FindSharedMappingReplacement(CPalThread *pThread, dev_t deviceNum, ino_t inodeNum, + SIZE_T size, SIZE_T offset); +#endif + +static PAL_ERROR +MAPRecordMapping( + IPalObject *pMappingObject, + void *pPEBaseAddress, + void *addr, + size_t len, + int prot + ); + +static PAL_ERROR +MAPmmapAndRecord( + IPalObject *pMappingObject, + void *pPEBaseAddress, + void *addr, + size_t len, + int prot, + int flags, + int fd, + off_t offset, + LPVOID *ppvBaseAddress + ); + +#if !HAVE_MMAP_DEV_ZERO +/* We need MAP_ANON. However on some platforms like HP-UX, it is defined as MAP_ANONYMOUS */ +#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS) +#define MAP_ANON MAP_ANONYMOUS +#endif +#endif + +void +FileMappingCleanupRoutine( + CPalThread *pThread, + IPalObject *pObjectToCleanup, + bool fShutdown, + bool fCleanupSharedState + ); + +PAL_ERROR +FileMappingInitializationRoutine( + CPalThread *pThread, + CObjectType *pObjectType, + void *pImmutableData, + void *pSharedData, + void *pProcessLocalData + ); + +void +CFileMappingImmutableDataCopyRoutine( + void *pImmData, + void *pImmDataTarget + ); + +void +CFileMappingImmutableDataCleanupRoutine( + void *pImmData + ); + +CObjectType CorUnix::otFileMapping( + otiFileMapping, + FileMappingCleanupRoutine, + FileMappingInitializationRoutine, + sizeof(CFileMappingImmutableData), + CFileMappingImmutableDataCopyRoutine, + CFileMappingImmutableDataCleanupRoutine, + sizeof(CFileMappingProcessLocalData), + NULL, // No process local data cleanup routine + 0, + PAGE_READWRITE | PAGE_READONLY | PAGE_WRITECOPY, + CObjectType::SecuritySupported, + CObjectType::SecurityInfoNotPersisted, + CObjectType::UnnamedObject, + CObjectType::LocalDuplicationOnly, + CObjectType::UnwaitableObject, + CObjectType::SignalingNotApplicable, + CObjectType::ThreadReleaseNotApplicable, + CObjectType::OwnershipNotApplicable + ); + +CAllowedObjectTypes aotFileMapping(otiFileMapping); + +void +CFileMappingImmutableDataCopyRoutine( + void *pImmData, + void *pImmDataTarget + ) +{ + PAL_ERROR palError = NO_ERROR; + CFileMappingImmutableData *pImmutableData = (CFileMappingImmutableData *) pImmData; + CFileMappingImmutableData *pImmutableDataTarget = (CFileMappingImmutableData *) pImmDataTarget; + + if (NULL != pImmutableData->lpFileName) + { + pImmutableDataTarget->lpFileName = strdup(pImmutableData->lpFileName); + } +} + +void +CFileMappingImmutableDataCleanupRoutine( + void *pImmData + ) +{ + PAL_ERROR palError = NO_ERROR; + CFileMappingImmutableData *pImmutableData = (CFileMappingImmutableData *) pImmData; + + free(pImmutableData->lpFileName); +} + +void +FileMappingCleanupRoutine( + CPalThread *pThread, + IPalObject *pObjectToCleanup, + bool fShutdown, + bool fCleanupSharedState + ) +{ + PAL_ERROR palError = NO_ERROR; + CFileMappingImmutableData *pImmutableData = NULL; + CFileMappingProcessLocalData *pLocalData = NULL; + IDataLock *pLocalDataLock = NULL; + bool fDataChanged = FALSE; + + if (TRUE == fCleanupSharedState) + { + // + // If we created a temporary file to back this mapping we need + // to unlink it now + // + + palError = pObjectToCleanup->GetImmutableData( + reinterpret_cast(&pImmutableData) + ); + + if (NO_ERROR != palError) + { + ASSERT("Unable to obtain immutable data for object to be reclaimed"); + return; + } + + if (pImmutableData->bPALCreatedTempFile) + { + unlink(pImmutableData->lpFileName); + } + } + + if (FALSE == fShutdown) + { + // + // We only need to close the object's descriptor if we're not + // shutting down + // + + palError = pObjectToCleanup->GetProcessLocalData( + pThread, + WriteLock, + &pLocalDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + ASSERT("Unable to obtain process local data for object to be reclaimed"); + return; + } + + if (-1 != pLocalData->UnixFd) + { + close(pLocalData->UnixFd); + pLocalData->UnixFd = -1; + fDataChanged = TRUE; + } + + pLocalDataLock->ReleaseLock(pThread, fDataChanged); + } + + // + // Why don't we need to deal with any views that may have been created + // from this mapping? If the process is shutting down then there's nothing + // that we need to take care of, as the OS will remove the underlying + // mappings when the process goes away. If we're not shutting down then + // there's no way for a view to exist against this mapping, since each + // view holds a reference against the mapping object. + // +} + +PAL_ERROR +FileMappingInitializationRoutine( + CPalThread *pThread, + CObjectType *pObjectType, + void *pvImmutableData, + void *pvSharedData, + void *pvProcessLocalData + ) +{ + PAL_ERROR palError = NO_ERROR; + + CFileMappingImmutableData *pImmutableData = + reinterpret_cast(pvImmutableData); + CFileMappingProcessLocalData *pProcessLocalData = + reinterpret_cast(pvProcessLocalData); + + pProcessLocalData->UnixFd = InternalOpen( + pImmutableData->lpFileName, + MAPProtectionToFileOpenFlags(pImmutableData->flProtect) | O_CLOEXEC + ); + + if (-1 == pProcessLocalData->UnixFd) + { + palError = ERROR_INTERNAL_ERROR; + goto ExitFileMappingInitializationRoutine; + } + +#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + struct stat st; + + if (0 == fstat(pProcessLocalData->UnixFd, &st)) + { + pProcessLocalData->MappedFileDevNum = st.st_dev; + pProcessLocalData->MappedFileInodeNum = st.st_ino; + } + else + { + ERROR("Couldn't get inode info for fd=%d to be stored in mapping object\n", pProcessLocalData->UnixFd); + } +#endif + +ExitFileMappingInitializationRoutine: + + return palError; +} + +/*++ +Function: + CreateFileMappingA + +Note: + File mapping are used to do inter-process communication. + +See MSDN doc. +--*/ +HANDLE +PALAPI +CreateFileMappingA( + IN HANDLE hFile, + IN LPSECURITY_ATTRIBUTES lpFileMappingAttributes, + IN DWORD flProtect, + IN DWORD dwMaximumSizeHigh, + IN DWORD dwMaximumSizeLow, + IN LPCSTR lpName) +{ + HANDLE hFileMapping = NULL; + CPalThread *pThread = NULL; + PAL_ERROR palError = NO_ERROR; + + PERF_ENTRY(CreateFileMappingA); + ENTRY("CreateFileMappingA(hFile=%p, lpAttributes=%p, flProtect=%#x, " + "dwMaxSizeH=%d, dwMaxSizeL=%d, lpName=%p (%s))\n", + hFile, lpFileMappingAttributes, flProtect, + dwMaximumSizeHigh, dwMaximumSizeLow, + lpName?lpName:"NULL", + lpName?lpName:"NULL"); + + pThread = InternalGetCurrentThread(); + + if (lpName != nullptr) + { + ASSERT("lpName: Cross-process named objects are not supported in PAL"); + palError = ERROR_NOT_SUPPORTED; + } + else + { + palError = InternalCreateFileMapping( + pThread, + hFile, + lpFileMappingAttributes, + flProtect, + dwMaximumSizeHigh, + dwMaximumSizeLow, + NULL, + &hFileMapping + ); + } + + + // + // We always need to set last error, even on success: + // we need to protect ourselves from the situation + // where last error is set to ERROR_ALREADY_EXISTS on + // entry to the function + // + + pThread->SetLastError(palError); + + LOGEXIT( "CreateFileMappingA returns HANDLE %p. \n", hFileMapping ); + PERF_EXIT(CreateFileMappingA); + return hFileMapping; +} + +/*++ +Function: + CreateFileMappingW + +Note: + File mapping are used to do inter-process communication. + +See MSDN doc. +--*/ +HANDLE +PALAPI +CreateFileMappingW( + IN HANDLE hFile, + IN LPSECURITY_ATTRIBUTES lpFileMappingAttributes, + IN DWORD flProtect, + IN DWORD dwMaximumSizeHigh, + IN DWORD dwMaximumSizeLow, + IN LPCWSTR lpName) +{ + HANDLE hFileMapping = NULL; + CPalThread *pThread = NULL; + PAL_ERROR palError = NO_ERROR; + + PERF_ENTRY(CreateFileMappingW); + ENTRY("CreateFileMappingW(hFile=%p, lpAttributes=%p, flProtect=%#x, " + "dwMaxSizeH=%u, dwMaxSizeL=%u, lpName=%p (%S))\n", + hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, + dwMaximumSizeLow, lpName?lpName:W16_NULLSTRING, lpName?lpName:W16_NULLSTRING); + + pThread = InternalGetCurrentThread(); + + palError = InternalCreateFileMapping( + pThread, + hFile, + lpFileMappingAttributes, + flProtect, + dwMaximumSizeHigh, + dwMaximumSizeLow, + lpName, + &hFileMapping + ); + + // + // We always need to set last error, even on success: + // we need to protect ourselves from the situation + // where last error is set to ERROR_ALREADY_EXISTS on + // entry to the function + // + + pThread->SetLastError(palError); + + LOGEXIT( "CreateFileMappingW returning %p .\n", hFileMapping ); + PERF_EXIT(CreateFileMappingW); + return hFileMapping; +} + +PAL_ERROR +CorUnix::InternalCreateFileMapping( + CPalThread *pThread, + HANDLE hFile, + LPSECURITY_ATTRIBUTES lpFileMappingAttributes, + DWORD flProtect, + DWORD dwMaximumSizeHigh, + DWORD dwMaximumSizeLow, + LPCWSTR lpName, + HANDLE *phMapping + ) +{ + CObjectAttributes objectAttributes(lpName, lpFileMappingAttributes); + PAL_ERROR palError = NO_ERROR; + IPalObject *pMapping = NULL; + IPalObject *pRegisteredMapping = NULL; + CFileMappingProcessLocalData *pLocalData = NULL; + IDataLock *pLocalDataLock = NULL; + CFileMappingImmutableData *pImmutableData = NULL; + IPalObject *pFileObject = NULL; + CFileProcessLocalData *pFileLocalData = NULL; + IDataLock *pFileLocalDataLock = NULL; + + struct stat UnixFileInformation; + INT UnixFd = -1; + BOOL bPALCreatedTempFile = FALSE; + UINT nFileSize = 0; + + // + // Validate parameters + // + + if (lpName != nullptr) + { + ASSERT("lpName: Cross-process named objects are not supported in PAL"); + palError = ERROR_NOT_SUPPORTED; + goto ExitInternalCreateFileMapping; + } + + if (0 != dwMaximumSizeHigh) + { + ASSERT("dwMaximumSizeHigh is always 0.\n"); + palError = ERROR_INVALID_PARAMETER; + goto ExitInternalCreateFileMapping; + } + + if (PAGE_READWRITE != flProtect + && PAGE_READONLY != flProtect + && PAGE_WRITECOPY != flProtect) + { + ASSERT( "invalid flProtect %#x, acceptable values are PAGE_READONLY " + "(%#x), PAGE_READWRITE (%#x) and PAGE_WRITECOPY (%#x).\n", + flProtect, PAGE_READONLY, PAGE_READWRITE, PAGE_WRITECOPY ); + palError = ERROR_INVALID_PARAMETER; + goto ExitInternalCreateFileMapping; + } + + if (hFile == INVALID_HANDLE_VALUE && 0 == dwMaximumSizeLow) + { + ERROR( "If hFile is INVALID_HANDLE_VALUE, then you must specify a size.\n" ); + palError = ERROR_INVALID_PARAMETER; + goto ExitInternalCreateFileMapping; + } + + if (hFile != INVALID_HANDLE_VALUE && NULL != lpName) + { + ASSERT( "If hFile is not -1, then lpName must be NULL.\n" ); + palError = ERROR_INVALID_PARAMETER; + goto ExitInternalCreateFileMapping; + } + + palError = g_pObjectManager->AllocateObject( + pThread, + &otFileMapping, + &objectAttributes, + &pMapping + ); + + if (NO_ERROR != palError) + { + goto ExitInternalCreateFileMapping; + } + + palError = pMapping->GetImmutableData(reinterpret_cast(&pImmutableData)); + if (NO_ERROR != palError) + { + goto ExitInternalCreateFileMapping; + } + + if (hFile == INVALID_HANDLE_VALUE +#ifndef CORECLR + && NULL == lpName +#endif // !CORECLR + ) + { + // + // Note: this path is what prevents us supporting the + // duplication of file mapping objects across processes, since + // there is no backing file that the other process can open. We can + // avoid this restriction by always using a temp backing file for + // anonymous mappings. + // + + /* Anonymous mapped files. */ + _ASSERTE(pImmutableData->lpFileName == NULL); + pImmutableData->lpFileName = strdup("/dev/zero"); + if (pImmutableData->lpFileName == NULL) + { + ASSERT("Unable to copy string\n"); + palError = ERROR_INTERNAL_ERROR; + goto ExitInternalCreateFileMapping; + } + +#if HAVE_MMAP_DEV_ZERO + + UnixFd = InternalOpen(pImmutableData->lpFileName, O_RDWR | O_CLOEXEC); + if ( -1 == UnixFd ) + { + ERROR( "Unable to open the file.\n"); + palError = ERROR_INTERNAL_ERROR; + goto ExitInternalCreateFileMapping; + } + +#else //!HAVE_MMAP_DEV_ZERO + + UnixFd = -1; /* will pass MAP_ANON to mmap() instead */ + +#endif //!HAVE_MMAP_DEV_ZERO + + } + else + { + if ( hFile != INVALID_HANDLE_VALUE ) + { + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hFile, + &aotFile, + &pFileObject + ); + + if (NO_ERROR != palError) + { + ERROR("Unable to obtain file data.\n"); + palError = ERROR_INVALID_PARAMETER; + goto ExitInternalCreateFileMapping; + } + + palError = pFileObject->GetProcessLocalData( + pThread, + ReadLock, + &pFileLocalDataLock, + reinterpret_cast(&pFileLocalData) + ); + + if (NO_ERROR != palError) + { + goto ExitInternalCreateFileMapping; + } + + /* We need to check to ensure flProtect jives with + the permission on the file handle */ + if (!MAPIsRequestPermissible(flProtect, pFileLocalData)) + { + ERROR("File handle does not have the correct " + "permissions to create mapping\n" ); + palError = ERROR_ACCESS_DENIED; + if (NULL != pFileLocalDataLock) + { + pFileLocalDataLock->ReleaseLock(pThread, FALSE); + } + goto ExitInternalCreateFileMapping; + } + + // + // TODO: technically, the file mapping object should hold + // a reference to the passed in file object. This implementation + // only keeps the underlying native file structure (i.e., what + // the duplicated descriptors point to) open. There may be a risk + // here pertaining to the file lock information that the PAL must + // maintain (e.g,. if the passed in handle is closed immediately + // after the file mapping is opened then the lock information will + // be released, since we're not doing anything to keep it alive + // here). + // + // Having a direct reference to the underlying file object adds + // some complication, especially in cross-process cases. We may + // want to consider adding a reference to the PAL's file lock + // information, though... + // + + UnixFd = fcntl(pFileLocalData->unix_fd, F_DUPFD_CLOEXEC, 0); // dup, but with CLOEXEC + if (-1 == UnixFd) + { + ERROR( "Unable to duplicate the Unix file descriptor!\n" ); + palError = ERROR_INTERNAL_ERROR; + if (NULL != pFileLocalDataLock) + { + pFileLocalDataLock->ReleaseLock(pThread, FALSE); + } + goto ExitInternalCreateFileMapping; + } + + _ASSERTE(pImmutableData->lpFileName == NULL); + pImmutableData->lpFileName = strdup(pFileLocalData->unix_filename); + if (pImmutableData->lpFileName == NULL) + { + ASSERT("Unable to copy string\n"); + palError = ERROR_INTERNAL_ERROR; + if (NULL != pFileLocalDataLock) + { + pFileLocalDataLock->ReleaseLock(pThread, FALSE); + } + goto ExitInternalCreateFileMapping; + } + + if (NULL != pFileLocalDataLock) + { + pFileLocalDataLock->ReleaseLock(pThread, FALSE); + } + } + else + { +#ifndef CORECLR + TRACE( "INVALID_HANDLE_VALUE was the hFile, time to try to create a " + "temporary file" ); + + /* Create a temporary file on the filesystem in order to be + shared across processes. */ + palError = MAPCreateTempFile(pThread, &UnixFd, pImmutableData->lpFileName); + if (NO_ERROR != palError) + { + ERROR("Unable to create the temporary file.\n"); + goto ExitInternalCreateFileMapping; + } + bPALCreatedTempFile = TRUE; +#else // !CORECLR + ASSERT("should not get here\n"); + palError = ERROR_INTERNAL_ERROR; + goto ExitInternalCreateFileMapping; +#endif // !CORECLR + } + + if (-1 == fstat(UnixFd, &UnixFileInformation)) + { + ASSERT("fstat() failed for this reason %s.\n", strerror(errno)); + palError = ERROR_INTERNAL_ERROR; + goto ExitInternalCreateFileMapping; + } + + if ( 0 == UnixFileInformation.st_size && + 0 == dwMaximumSizeHigh && 0 == dwMaximumSizeLow ) + { + ERROR( "The file cannot be a zero length file.\n" ); + palError = ERROR_FILE_INVALID; + goto ExitInternalCreateFileMapping; + } + + if ( INVALID_HANDLE_VALUE != hFile && + dwMaximumSizeLow > (DWORD) UnixFileInformation.st_size && + ( PAGE_READONLY == flProtect || PAGE_WRITECOPY == flProtect ) ) + { + /* In this situation, Windows returns an error, because the + permissions requested do not allow growing the file */ + ERROR( "The file cannot be grown do to the map's permissions.\n" ); + palError = ERROR_NOT_ENOUGH_MEMORY; + goto ExitInternalCreateFileMapping; + } + + if ( (DWORD) UnixFileInformation.st_size < dwMaximumSizeLow ) + { + TRACE( "Growing the size of file on disk to match requested size.\n" ); + + /* Need to grow the file on disk to match size. */ + palError = MAPGrowLocalFile(UnixFd, dwMaximumSizeLow); + if (NO_ERROR != palError) + { + ERROR( "Unable to grow the file on disk.\n" ); + goto ExitInternalCreateFileMapping; + } + } + } + + nFileSize = ( 0 == dwMaximumSizeLow && 0 == dwMaximumSizeHigh ) ? + UnixFileInformation.st_size : dwMaximumSizeLow; + + pImmutableData->MaxSize = nFileSize; + pImmutableData->flProtect = flProtect; + pImmutableData->bPALCreatedTempFile = bPALCreatedTempFile; + pImmutableData->dwDesiredAccessWhenOpened = MAPConvertProtectToAccess(flProtect); + + + // + // The local data isn't grabbed / modified until here so that we don't + // need to worry ourselves with locking issues with the passed in + // file handle -- all operations concerning the file handle are completed + // before we deal with the lock for the new object. + // + + palError = pMapping->GetProcessLocalData( + pThread, + WriteLock, + &pLocalDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + goto ExitInternalCreateFileMapping; + } + + pLocalData->UnixFd = UnixFd; + +#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + if (-1 == UnixFd) + { + pLocalData->MappedFileDevNum = (dev_t)-1; /* there is no standard NO_DEV */ + pLocalData->MappedFileInodeNum = NO_INO; + } + else + { + struct stat st; + + if (0 == fstat(UnixFd, &st)) + { + pLocalData->MappedFileDevNum = st.st_dev; + pLocalData->MappedFileInodeNum = st.st_ino; + } + else + { + ERROR("Couldn't get inode info for fd=%d to be stored in mapping object\n", UnixFd); + palError = ERROR_INTERNAL_ERROR; + goto ExitInternalCreateFileMapping; + } + } +#endif + + pLocalDataLock->ReleaseLock(pThread, TRUE); + pLocalDataLock = NULL; + + palError = g_pObjectManager->RegisterObject( + pThread, + pMapping, + &aotFileMapping, + phMapping, + &pRegisteredMapping + ); + + // + // pMapping is invalidated by the call to RegisterObject, so NULL it + // out here to ensure that we don't try to release a reference on + // it down the line. This also ensures that we won't attempt to release + // any data associated with the mapping object here, as if any cleanup is + // necessary due to a failure in RegisterObject (which includes another + // object by the same name already existing) the cleanup will take place + // when that routine releases the reference to pMapping. + // + + pMapping = NULL; + +ExitInternalCreateFileMapping: + + if (NULL != pLocalDataLock) + { + pLocalDataLock->ReleaseLock( + pThread, + TRUE + ); + } + + if (NULL != pMapping) + { + pMapping->ReleaseReference(pThread); + + if (bPALCreatedTempFile) + { + unlink(pImmutableData->lpFileName); + } + + if (-1 != UnixFd) + { + close(UnixFd); + } + } + + if (NULL != pRegisteredMapping) + { + pRegisteredMapping->ReleaseReference(pThread); + } + + if (NULL != pFileObject) + { + pFileObject->ReleaseReference(pThread); + } + + return palError; +} + +/*++ +Function: + OpenFileMappingA + +See MSDN doc. +--*/ +HANDLE +PALAPI +OpenFileMappingA( + IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCSTR lpName) +{ + HANDLE hFileMapping = NULL; + CPalThread *pThread = NULL; + PAL_ERROR palError = NO_ERROR; + + PERF_ENTRY(OpenFileMappingA); + ENTRY("OpenFileMappingA(dwDesiredAccess=%u, bInheritHandle=%d, lpName=%p (%s)\n", + dwDesiredAccess, bInheritHandle, lpName?lpName:"NULL", lpName?lpName:"NULL"); + + pThread = InternalGetCurrentThread(); + + if (lpName == nullptr) + { + ERROR("name is NULL\n"); + palError = ERROR_INVALID_PARAMETER; + } + else + { + ASSERT("lpName: Cross-process named objects are not supported in PAL"); + palError = ERROR_NOT_SUPPORTED; + } + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + LOGEXIT( "OpenFileMappingA returning %p\n", hFileMapping ); + PERF_EXIT(OpenFileMappingA); + return hFileMapping; +} + + +/*++ +Function: + OpenFileMappingW + +See MSDN doc. +--*/ +HANDLE +PALAPI +OpenFileMappingW( + IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCWSTR lpName) +{ + HANDLE hFileMapping = NULL; + PAL_ERROR palError = NO_ERROR; + CPalThread *pThread = NULL; + + PERF_ENTRY(OpenFileMappingW); + ENTRY("OpenFileMappingW(dwDesiredAccess=%#x, bInheritHandle=%d, lpName=%p (%S)\n", + dwDesiredAccess, bInheritHandle, lpName?lpName:W16_NULLSTRING, lpName?lpName:W16_NULLSTRING); + + pThread = InternalGetCurrentThread(); + + /* validate parameters */ + if (lpName == nullptr) + { + ERROR("name is NULL\n"); + palError = ERROR_INVALID_PARAMETER; + } + else + { + ASSERT("lpName: Cross-process named objects are not supported in PAL"); + palError = ERROR_NOT_SUPPORTED; + } + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + LOGEXIT("OpenFileMappingW returning %p.\n", hFileMapping); + PERF_EXIT(OpenFileMappingW); + return hFileMapping; +} + +/*++ +Function: + MapViewOfFile + + Limitations: 1) Currently file mappings are supported only at file + offset 0. + 2) Some platforms (specifically HP-UX) do not support + multiple simultaneous shared mapping of the same file + region in the same process. On these platforms, in case + we are asked for a new view completely contained in an + existing one, we return an address within the existing + mapping. In case the new requested view is overlapping + with the existing one, but not contained in it, the + mapping is impossible, and MapViewOfFile will fail. + Since currently the mappings are supported only at file + offset 0, MapViewOfFile will succeed if the new view + is equal or smaller of the existing one, and the address + returned will be the same address of the existing + mapping. + Since the underlying mapping is always the same, all + the shared views of the same file region will share the + same protection, i.e. they will have the largest + protection requested. If any mapping asked for a + read-write access, all the read-only mappings of the + same region will silently get a read-write access to + it. + +See MSDN doc. +--*/ +LPVOID +PALAPI +MapViewOfFile( + IN HANDLE hFileMappingObject, + IN DWORD dwDesiredAccess, + IN DWORD dwFileOffsetHigh, + IN DWORD dwFileOffsetLow, + IN SIZE_T dwNumberOfBytesToMap) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pThread = NULL; + LPVOID pvMappedBaseAddress = NULL; + + PERF_ENTRY(MapViewOfFile); + ENTRY("MapViewOfFile(hFileMapping=%p, dwDesiredAccess=%u, " + "dwFileOffsetH=%u, dwFileOffsetL=%u, dwNumberOfBytes=%u)\n", + hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, + dwFileOffsetLow, dwNumberOfBytesToMap); + + pThread = InternalGetCurrentThread(); + + palError = InternalMapViewOfFile( + pThread, + hFileMappingObject, + dwDesiredAccess, + dwFileOffsetHigh, + dwFileOffsetLow, + dwNumberOfBytesToMap, + &pvMappedBaseAddress + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT( "MapViewOfFile returning %p.\n", pvMappedBaseAddress ); + PERF_EXIT(MapViewOfFile); + return pvMappedBaseAddress; +} + +LPVOID +PALAPI +MapViewOfFileEx( + IN HANDLE hFileMappingObject, + IN DWORD dwDesiredAccess, + IN DWORD dwFileOffsetHigh, + IN DWORD dwFileOffsetLow, + IN SIZE_T dwNumberOfBytesToMap, + IN LPVOID lpBaseAddress) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pThread = NULL; + LPVOID pvMappedBaseAddress = NULL; + + PERF_ENTRY(MapViewOfFileEx); + ENTRY("MapViewOfFileEx(hFileMapping=%p, dwDesiredAccess=%u, " + "dwFileOffsetH=%u, dwFileOffsetL=%u, dwNumberOfBytes=%u, lpBaseAddress=%p)\n", + hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, + dwFileOffsetLow, dwNumberOfBytesToMap, lpBaseAddress); + + pThread = InternalGetCurrentThread(); + + if (lpBaseAddress == NULL) + { + palError = InternalMapViewOfFile( + pThread, + hFileMappingObject, + dwDesiredAccess, + dwFileOffsetHigh, + dwFileOffsetLow, + dwNumberOfBytesToMap, + &pvMappedBaseAddress + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + } + else + { + // TODO: Figure out if we can support mapping at a specific address on Linux. + pThread->SetLastError(ERROR_INVALID_PARAMETER); + } + + LOGEXIT( "MapViewOfFileEx returning %p.\n", pvMappedBaseAddress ); + PERF_EXIT(MapViewOfFileEx); + return pvMappedBaseAddress; +} + + +/*++ +Function: + UnmapViewOfFile + +See MSDN doc. +--*/ +BOOL +PALAPI +UnmapViewOfFile( + IN LPCVOID lpBaseAddress) +{ + PAL_ERROR palError; + CPalThread *pThread; + + PERF_ENTRY(UnmapViewOfFile); + ENTRY("UnmapViewOfFile(lpBaseAddress=%p)\n", lpBaseAddress); + + pThread = InternalGetCurrentThread(); + + palError = InternalUnmapViewOfFile(pThread, lpBaseAddress); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT( "UnmapViewOfFile returning %s.\n", (NO_ERROR == palError) ? "TRUE" : "FALSE" ); + PERF_EXIT(UnmapViewOfFile); + return (NO_ERROR == palError); +} + +PAL_ERROR +CorUnix::InternalMapViewOfFile( + CPalThread *pThread, + HANDLE hFileMappingObject, + DWORD dwDesiredAccess, + DWORD dwFileOffsetHigh, + DWORD dwFileOffsetLow, + SIZE_T dwNumberOfBytesToMap, + LPVOID *ppvBaseAddress + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pMappingObject = NULL; + CFileMappingImmutableData *pImmutableData = NULL; + CFileMappingProcessLocalData *pProcessLocalData = NULL; + IDataLock *pProcessLocalDataLock = NULL; +#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + PMAPPED_VIEW_LIST pReusedMapping = NULL; +#endif + LPVOID pvBaseAddress = NULL; + + /* Sanity checks */ + if ( MAPContainsInvalidFlags( dwDesiredAccess ) ) + { + ASSERT( "dwDesiredAccess can be one of FILE_MAP_WRITE, FILE_MAP_READ," + " FILE_MAP_COPY or FILE_MAP_ALL_ACCESS.\n" ); + palError = ERROR_INVALID_PARAMETER; + goto InternalMapViewOfFileExit; + } + + if ( 0 != dwFileOffsetHigh || 0 != dwFileOffsetLow ) + { + ASSERT( "dwFileOffsetHigh and dwFileOffsetLow are always 0.\n" ); + palError = ERROR_INVALID_PARAMETER; + goto InternalMapViewOfFileExit; + } + + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hFileMappingObject, + &aotFileMapping, + &pMappingObject + ); + + if (NO_ERROR != palError) + { + ERROR( "Unable to reference handle %p.\n",hFileMappingObject ); + goto InternalMapViewOfFileExit; + } + + palError = pMappingObject->GetImmutableData( + reinterpret_cast(&pImmutableData) + ); + + if (NO_ERROR != palError) + { + ERROR( "Unable to obtain object immutable data"); + goto InternalMapViewOfFileExit; + } + + palError = pMappingObject->GetProcessLocalData( + pThread, + ReadLock, + &pProcessLocalDataLock, + reinterpret_cast(&pProcessLocalData) + ); + + if (NO_ERROR != palError) + { + ERROR( "Unable to obtain object process local data"); + goto InternalMapViewOfFileExit; + } + + /* If dwNumberOfBytesToMap is 0, we need to map the entire file. + * mmap doesn't do the same thing as Windows in that case, though, + * so we use the file size instead. */ + if (0 == dwNumberOfBytesToMap) + { + dwNumberOfBytesToMap = pImmutableData->MaxSize; + } + + palError = MAPDesiredAccessAllowed( + pImmutableData->flProtect, + dwDesiredAccess, + pImmutableData->dwDesiredAccessWhenOpened + ); + + if (NO_ERROR != palError) + { + goto InternalMapViewOfFileExit; + } + + InternalEnterCriticalSection(pThread, &mapping_critsec); + + if (FILE_MAP_COPY == dwDesiredAccess) + { + int flags = MAP_PRIVATE; + +#if !HAVE_MMAP_DEV_ZERO + if (pProcessLocalData->UnixFd == -1) + { + flags |= MAP_ANON; + } +#endif + pvBaseAddress = mmap( + NULL, + dwNumberOfBytesToMap, + PROT_READ|PROT_WRITE, + flags, + pProcessLocalData->UnixFd, + 0 + ); + } + else + { + INT prot = MAPFileMapToMmapFlags(dwDesiredAccess); + if (prot != -1) + { + int flags = MAP_SHARED; + +#if !HAVE_MMAP_DEV_ZERO + if (pProcessLocalData->UnixFd == -1) + { + flags |= MAP_ANON; + } +#endif + + pvBaseAddress = mmap( + NULL, + dwNumberOfBytesToMap, + prot, + flags, + pProcessLocalData->UnixFd, + 0 + ); + +#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + if ((MAP_FAILED == pvBaseAddress) && (ENOMEM == errno)) + { + /* Search in list of MAPPED_MEMORY_INFO for a shared mapping + with the same inode number + */ + TRACE("Mmap() failed with errno=ENOMEM probably for multiple mapping " + "limitation. Searching for a replacement among existing mappings\n"); + + pReusedMapping = FindSharedMappingReplacement( + pThread, + pProcessLocalData->MappedFileDevNum, + pProcessLocalData->MappedFileInodeNum, + dwNumberOfBytesToMap, + 0 + ); + + if (pReusedMapping) + { + int ret; + + TRACE("Mapping @ %p {sz=%d offs=%d} fully " + "contains the requested one {sz=%d offs=%d}: reusing it\n", + pReusedMapping->pNMHolder->address, + (int)pReusedMapping->pNMHolder->size, + (int)pReusedMapping->pNMHolder->offset, + dwNumberOfBytesToMap, 0); + + /* Let's check the mapping's current protection */ + ret = mprotect(pReusedMapping->pNMHolder->address, + pReusedMapping->pNMHolder->size, + prot | PROT_CHECK); + if (0 != ret) + { + /* We need to raise the protection to the desired + one. That will give write access to any read-only + mapping sharing this native mapping, but there is + no way around this problem on systems that do not + allow more than one mapping per file region, per + process */ + TRACE("Raising protections on mapping @ %p to 0x%x\n", + pReusedMapping->pNMHolder->address, prot); + ret = mprotect(pReusedMapping->pNMHolder->address, + pReusedMapping->pNMHolder->size, + prot); + } + + if (ret != 0) + { + ERROR( "Failed setting protections on reused mapping\n"); + + NativeMapHolderRelease(pThread, pReusedMapping->pNMHolder); + free(pReusedMapping); + pReusedMapping = NULL; + } + } + } +#endif // ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + } + else + { + ASSERT( "MapFileMapToMmapFlags failed!\n" ); + palError = ERROR_INTERNAL_ERROR; + goto InternalMapViewOfFileLeaveCriticalSection; + } + } + + if (MAP_FAILED == pvBaseAddress +#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + && (pReusedMapping == NULL) +#endif // ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + ) + { + ERROR( "mmap failed with code %s.\n", strerror( errno ) ); + palError = ERROR_NOT_ENOUGH_MEMORY; + goto InternalMapViewOfFileLeaveCriticalSection; + + } + +#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + if (pReusedMapping != NULL) + { + // + // Add a reference to the file mapping object the reused mapping + // points to (note that it may be different than the object this + // call was actually made against) and add the view to the global + // list. All other initialization took place in + // FindSharedMappingReplacement + // + + pvBaseAddress = pReusedMapping->lpAddress; + pReusedMapping->pFileMapping->AddReference(); + InsertTailList(&MappedViewList, &pReusedMapping->Link); + } + else +#endif // ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + { + // + // Allocate and fill out a new view structure, and add it to + // the global list. + // + + PMAPPED_VIEW_LIST pNewView = (PMAPPED_VIEW_LIST)InternalMalloc(sizeof(*pNewView)); + if (NULL != pNewView) + { + pNewView->lpAddress = pvBaseAddress; + pNewView->NumberOfBytesToMap = dwNumberOfBytesToMap; + pNewView->dwDesiredAccess = dwDesiredAccess; + pNewView->pFileMapping = pMappingObject; + pNewView->pFileMapping->AddReference(); + pNewView->lpPEBaseAddress = 0; + InsertTailList(&MappedViewList, &pNewView->Link); + +#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + pNewView->MappedFileDevNum = pProcessLocalData->MappedFileDevNum; + pNewView->MappedFileInodeNum = pProcessLocalData->MappedFileInodeNum; + + pNewView->pNMHolder = NewNativeMapHolder( + pThread, + pvBaseAddress, + dwNumberOfBytesToMap, + 0, + 1 + ); + + if (NULL == pNewView->pNMHolder) + { + pNewView->pFileMapping->ReleaseReference(pThread); + RemoveEntryList(&pNewView->Link); + free(pNewView); + palError = ERROR_INTERNAL_ERROR; + } +#endif // ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + } + else + { + palError = ERROR_INTERNAL_ERROR; + } + + if (NO_ERROR != palError) + { + if (-1 == munmap(pvBaseAddress, dwNumberOfBytesToMap)) + { + ERROR("Unable to unmap the file. Expect trouble.\n"); + goto InternalMapViewOfFileLeaveCriticalSection; + } + } + } + + if (NO_ERROR == palError) + { + TRACE( "Added %p to the list.\n", pvBaseAddress ); + *ppvBaseAddress = pvBaseAddress; + } + +InternalMapViewOfFileLeaveCriticalSection: + + InternalLeaveCriticalSection(pThread, &mapping_critsec); + +InternalMapViewOfFileExit: + + if (NULL != pProcessLocalDataLock) + { + pProcessLocalDataLock->ReleaseLock(pThread, FALSE); + } + + if (NULL != pMappingObject) + { + pMappingObject->ReleaseReference(pThread); + } + + return palError; +} + + +PAL_ERROR +CorUnix::InternalUnmapViewOfFile( + CPalThread *pThread, + LPCVOID lpBaseAddress + ) +{ + PAL_ERROR palError = NO_ERROR; + PMAPPED_VIEW_LIST pView = NULL; + IPalObject *pMappingObject = NULL; + + InternalEnterCriticalSection(pThread, &mapping_critsec); + + pView = MAPGetViewForAddress(lpBaseAddress); + if (NULL == pView) + { + ERROR("lpBaseAddress has to be the address returned by MapViewOfFile[Ex]"); + palError = ERROR_INVALID_HANDLE; + goto InternalUnmapViewOfFileExit; + } + +#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + NativeMapHolderRelease(pThread, pView->pNMHolder); + pView->pNMHolder = NULL; +#else + if (-1 == munmap((LPVOID)lpBaseAddress, pView->NumberOfBytesToMap)) + { + ASSERT( "Unable to unmap the memory. Error=%s.\n", + strerror( errno ) ); + palError = ERROR_INTERNAL_ERROR; + + // + // Even if the unmap fails we want to continue removing the + // info for this view + // + } +#endif + + RemoveEntryList(&pView->Link); + pMappingObject = pView->pFileMapping; + free(pView); + +InternalUnmapViewOfFileExit: + + InternalLeaveCriticalSection(pThread, &mapping_critsec); + + // + // We can't dereference the file mapping object until after + // we've released the mapping critical section, since it may + // start going down its cleanup path and we don't want to make + // any assumptions as to what locks that might grab... + // + + if (NULL != pMappingObject) + { + pMappingObject->ReleaseReference(pThread); + } + + return palError; +} + +/*++ +Function : + MAPInitialize + + Initialize the critical sections. + +Return value: + TRUE if initialization succeeded + FALSE otherwise +--*/ +BOOL +MAPInitialize( void ) +{ + TRACE( "Initialising the critical section.\n" ); + + InternalInitializeCriticalSection(&mapping_critsec); + + InitializeListHead(&MappedViewList); + + return TRUE; +} + +/*++ +Function : + MAPCleanup + + Deletes the critical sections. And all other necessary cleanup. + +Note: + This function is called after the handle manager is stopped. So + there shouldn't be any call that will cause an access to the handle + manager. + +--*/ +void MAPCleanup( void ) +{ + TRACE( "Deleting the critical section.\n" ); + InternalDeleteCriticalSection(&mapping_critsec); +} + +/*++ +Function : + MAPGetViewForAddress + + Returns the mapped view (if any) that is based at the passed in address. + + Callers to this function must hold mapping_critsec +--*/ +static PMAPPED_VIEW_LIST MAPGetViewForAddress( LPCVOID lpAddress ) +{ + if ( NULL == lpAddress ) + { + ERROR( "lpAddress cannot be NULL\n" ); + return NULL; + } + + for(LIST_ENTRY *pLink = MappedViewList.Flink; + pLink != &MappedViewList; + pLink = pLink->Flink) + { + PMAPPED_VIEW_LIST pView = CONTAINING_RECORD(pLink, MAPPED_VIEW_LIST, Link); + + if (pView->lpAddress == lpAddress) + { + return pView; + } + } + + WARN( "No match found.\n" ); + + return NULL; +} + +/*++ +Function : + + MAPDesiredAccessAllowed + + Determines if desired access is allowed based on the protection state. + + if dwDesiredAccess conflicts with flProtect then the error is + ERROR_INVALID_PARAMETER, if the dwDesiredAccess conflicts with + dwDesiredAccessWhenOpened, then the error code is ERROR_ACCESS_DENIED +--*/ +static PAL_ERROR MAPDesiredAccessAllowed( DWORD flProtect, + DWORD dwUserDesiredAccess, + DWORD dwDesiredAccessWhenOpened ) +{ + TRACE( "flProtect=%d, dwUserDesiredAccess=%d, dwDesiredAccessWhenOpened=%d\n", + flProtect, dwUserDesiredAccess, dwDesiredAccessWhenOpened ); + + /* check flProtect parameters*/ + if ( FILE_MAP_READ!= dwUserDesiredAccess && PAGE_READONLY == flProtect ) + { + ERROR( "map object is read-only, can't map a view with write access\n"); + return ERROR_INVALID_PARAMETER; + } + + if ( FILE_MAP_WRITE == dwUserDesiredAccess && PAGE_READWRITE != flProtect ) + { + ERROR( "map object not open read-write, can't map a view with write " + "access.\n" ); + return ERROR_INVALID_PARAMETER; + } + + if ( FILE_MAP_COPY == dwUserDesiredAccess && PAGE_WRITECOPY != flProtect ) + { + ERROR( "map object not open for copy-on-write, can't map copy-on-write " + "view.\n" ); + return ERROR_INVALID_PARAMETER; + } + + /* Check to see we don't confict with the desired access we + opened the mapping object with. */ + if ( ( dwUserDesiredAccess == FILE_MAP_READ ) && + !( ( dwDesiredAccessWhenOpened == FILE_MAP_READ ) || + ( dwDesiredAccessWhenOpened == FILE_MAP_ALL_ACCESS ) ) ) + { + ERROR( "dwDesiredAccess conflict : read access requested, object not " + "opened with read access.\n" ); + return ERROR_ACCESS_DENIED; + } + if ( ( dwUserDesiredAccess & FILE_MAP_WRITE ) && + !( ( dwDesiredAccessWhenOpened == FILE_MAP_WRITE ) || + ( dwDesiredAccessWhenOpened == FILE_MAP_ALL_ACCESS ) ) ) + { + ERROR( "dwDesiredAccess conflict : write access requested, object not " + "opened with write access.\n" ); + return ERROR_ACCESS_DENIED; + } + if ( ( dwUserDesiredAccess == FILE_MAP_COPY ) && + !( dwDesiredAccessWhenOpened == FILE_MAP_COPY ) ) + { + ERROR( "dwDesiredAccess conflict : copy-on-write access requested, " + "object not opened with copy-on-write access.\n" ); + return ERROR_ACCESS_DENIED; + } + + return NO_ERROR; +} + +/*++ +Function : + MAPConvertProtectToAccess + + Converts the PAGE_READONLY type flags to FILE_MAP_READ flags. + +--*/ +static DWORD MAPConvertProtectToAccess( DWORD flProtect ) +{ + if ( PAGE_READONLY == flProtect ) + { + return FILE_MAP_READ; + } + if ( PAGE_READWRITE == flProtect ) + { + return FILE_MAP_ALL_ACCESS; + } + if ( PAGE_WRITECOPY == flProtect ) + { + return FILE_MAP_COPY; + } + + ASSERT( "Unknown flag for flProtect. This line " + "should not have been executed.\n " ); + return (DWORD) -1; +} + +/*++ +Function : + MAPConvertAccessToProtect + + Converts the FILE_MAP_READ type flags to PAGE_READONLY flags. + Currently, this function only deals with the access flags recognized as valid + by MAPContainsInvalidFlags(). + +--*/ +static DWORD MAPConvertAccessToProtect(DWORD flAccess) +{ + if (flAccess == FILE_MAP_ALL_ACCESS) + { + return PAGE_READWRITE; + } + else if ((flAccess == FILE_MAP_COPY) || (flAccess == FILE_MAP_WRITE)) + { + return PAGE_WRITECOPY; + } + else if (flAccess == FILE_MAP_READ) + { + return PAGE_READONLY; + } + else if (flAccess == 0) + { + return PAGE_NOACCESS; + } + + ASSERT("Unknown flag for flAccess.\n"); + return (DWORD) -1; +} + +/*++ +Function : + MAPFileMapToMmapFlags + + Converts the mapping flags to unix protection flags. +--*/ +static INT MAPFileMapToMmapFlags( DWORD flags ) +{ + if ( FILE_MAP_READ == flags ) + { + TRACE( "FILE_MAP_READ\n" ); + return PROT_READ; + } + else if ( FILE_MAP_WRITE == flags ) + { + TRACE( "FILE_MAP_WRITE\n" ); + /* The limitation of x86 architecture + means you cant have writable but not readable + page. In Windows maps of FILE_MAP_WRITE can still be + read from. */ + return PROT_WRITE | PROT_READ; + } + else if ( (FILE_MAP_READ|FILE_MAP_WRITE) == flags ) + { + TRACE( "FILE_MAP_READ|FILE_MAP_WRITE\n" ); + return PROT_READ | PROT_WRITE; + } + else if( FILE_MAP_COPY == flags) + { + TRACE( "FILE_MAP_COPY\n"); + return PROT_READ | PROT_WRITE; + } + + ASSERT( "Unknown flag. This line should not have been executed.\n" ); + return -1; +} + +/*++ +Function : + MAPMmapProtToAccessFlags + + Converts unix protection flags to file access flags. + We ignore PROT_EXEC. +--*/ +static DWORD MAPMmapProtToAccessFlags( int prot ) +{ + DWORD flAccess = 0; // default: no access + + if (PROT_NONE == prot) + { + flAccess = 0; + } + else if ( ((PROT_READ | PROT_WRITE) & prot) == (PROT_READ | PROT_WRITE) ) + { + flAccess = FILE_MAP_ALL_ACCESS; + } + else if ( (PROT_WRITE & prot) == PROT_WRITE ) + { + flAccess = FILE_MAP_WRITE; + } + else if ( (PROT_READ & prot) == PROT_READ ) + { + flAccess = FILE_MAP_READ; + } + else + { + ASSERT( "Unknown Unix protection flag\n" ); + } + + return flAccess; +} + +/*++ +Function : + + MAPGrowLocalFile + + Grows the file on disk to match the specified size. + +--*/ +static PAL_ERROR MAPGrowLocalFile( INT UnixFD, UINT NewSize ) +{ + PAL_ERROR palError = NO_ERROR; + INT TruncateRetVal = -1; + struct stat FileInfo; + TRACE( "Entered MapGrowLocalFile (UnixFD=%d,NewSize%d)\n", UnixFD, NewSize ); + + // + // TODO: can we add configure flags to model the behavior of ftruncate + // among our various target platforms? How much would that actually gain + // us? + // + + /* ftruncate is a standard function, but the behavior of enlarging files is + non-standard. So I will try to enlarge a file, and if that fails try the + less efficent way.*/ + TruncateRetVal = ftruncate( UnixFD, NewSize ); + fstat( UnixFD, &FileInfo ); + + if ( TruncateRetVal != 0 || FileInfo.st_size != (int) NewSize ) + { + INT OrigSize; + CONST UINT BUFFER_SIZE = 128; + BYTE buf[BUFFER_SIZE]; + UINT x = 0; + UINT CurrentPosition = 0; + + TRACE( "Trying the less efficent way.\n" ); + + CurrentPosition = lseek( UnixFD, 0, SEEK_CUR ); + OrigSize = lseek( UnixFD, 0, SEEK_END ); + if ( OrigSize == -1 ) + { + ERROR( "Unable to locate the EOF marker. Reason=%s\n", + strerror( errno ) ); + palError = ERROR_INTERNAL_ERROR; + goto done; + } + + if (NewSize <= (UINT) OrigSize) + { + return TRUE; + } + + memset( buf, 0, BUFFER_SIZE ); + + for ( x = 0; x < NewSize - OrigSize - BUFFER_SIZE; x += BUFFER_SIZE ) + { + if ( write( UnixFD, (LPVOID)buf, BUFFER_SIZE ) == -1 ) + { + ERROR( "Unable to grow the file. Reason=%s\n", strerror( errno ) ); + if((errno == ENOSPC) || (errno == EDQUOT)) + { + palError = ERROR_DISK_FULL; + } + else + { + palError = ERROR_INTERNAL_ERROR; + } + goto done; + } + } + /* Catch any left overs. */ + if ( x != NewSize ) + { + if ( write( UnixFD, (LPVOID)buf, NewSize - OrigSize - x) == -1 ) + { + ERROR( "Unable to grow the file. Reason=%s\n", strerror( errno ) ); + if((errno == ENOSPC) || (errno == EDQUOT)) + { + palError = ERROR_DISK_FULL; + } + else + { + palError = ERROR_INTERNAL_ERROR; + } + goto done; + } + } + + /* restore the file pointer position */ + lseek( UnixFD, CurrentPosition, SEEK_SET ); + } + +done: + return palError; +} + +/*++ +Function : + MAPContainsInvalidFlags + + Checks that only valid flags are in the parameter. + +--*/ +static BOOL MAPContainsInvalidFlags( DWORD flags ) +{ + + if ( (flags == FILE_MAP_READ) || + (flags == FILE_MAP_WRITE) || + (flags == FILE_MAP_ALL_ACCESS) || + (flags == FILE_MAP_COPY) ) + { + return FALSE; + } + else + { + return TRUE; + } +} + +/*++ +Function : + MAPProtectionToFileOpenFlags + + Converts the PAGE_* flags to the O_* flags. + + Returns the file open flags. +--*/ +static INT MAPProtectionToFileOpenFlags( DWORD flProtect ) +{ + INT retVal = 0; + switch(flProtect) + { + case PAGE_READONLY: + retVal = O_RDONLY; + break; + case PAGE_READWRITE: + retVal = O_RDWR; + break; + case PAGE_WRITECOPY: + retVal = O_RDONLY; + break; + default: + ASSERT("unexpected flProtect value %#x\n", flProtect); + retVal = 0; + break; + } + return retVal; +} + +/*++ +Function : + + MAPIsRequestPermissible + + DWORD flProtect - The requested file mapping protection . + file * pFileStruct - The file structure containing all the information. + +--*/ +static BOOL MAPIsRequestPermissible( DWORD flProtect, CFileProcessLocalData * pFileLocalData ) +{ + if ( ( (flProtect == PAGE_READONLY || flProtect == PAGE_WRITECOPY) && + (pFileLocalData->open_flags_deviceaccessonly == TRUE || + pFileLocalData->open_flags & O_WRONLY) ) + ) + { + /* + * PAGE_READONLY or PAGE_WRITECOPY access to a file must at least be + * readable. Contrary to what MSDN says, PAGE_WRITECOPY + * only needs to be readable. + */ + return FALSE; + } + else if ( flProtect == PAGE_READWRITE && !(pFileLocalData->open_flags & O_RDWR) ) + { + /* + * PAGE_READWRITE access to a file needs to be readable and writable + */ + return FALSE; + } + else + { + /* Action is permissible */ + return TRUE; + } +} + +// returns TRUE if we have information about the specified address +BOOL MAPGetRegionInfo(LPVOID lpAddress, + PMEMORY_BASIC_INFORMATION lpBuffer) +{ + BOOL fFound = FALSE; + CPalThread * pThread = InternalGetCurrentThread(); + + InternalEnterCriticalSection(pThread, &mapping_critsec); + + for(LIST_ENTRY *pLink = MappedViewList.Flink; + pLink != &MappedViewList; + pLink = pLink->Flink) + { + UINT MappedSize; + VOID * real_map_addr; + SIZE_T real_map_sz; + PMAPPED_VIEW_LIST pView = CONTAINING_RECORD(pLink, MAPPED_VIEW_LIST, Link); + +#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + real_map_addr = pView->pNMHolder->address; + real_map_sz = pView->pNMHolder->size; +#else + real_map_addr = pView->lpAddress; + real_map_sz = pView->NumberOfBytesToMap; +#endif + + MappedSize = ALIGN_UP(real_map_sz, GetVirtualPageSize()); + if ( real_map_addr <= lpAddress && + (VOID *)((UINT_PTR)real_map_addr+MappedSize) > lpAddress ) + { + if (lpBuffer) + { + SIZE_T regionSize = MappedSize + (UINT_PTR) real_map_addr - + ALIGN_DOWN((UINT_PTR)lpAddress, GetVirtualPageSize()); + + lpBuffer->BaseAddress = lpAddress; + lpBuffer->AllocationProtect = 0; + lpBuffer->RegionSize = regionSize; + lpBuffer->State = MEM_COMMIT; + lpBuffer->Protect = MAPConvertAccessToProtect(pView->dwDesiredAccess); + lpBuffer->Type = MEM_MAPPED; + } + + fFound = TRUE; + break; + } + } + + InternalLeaveCriticalSection(pThread, &mapping_critsec); + + return fFound; +} + +#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + +// +// Callers of FindSharedMappingReplacement must hold mapping_critsec +// + +static PMAPPED_VIEW_LIST FindSharedMappingReplacement( + CPalThread *pThread, + dev_t deviceNum, + ino_t inodeNum, + SIZE_T size, + SIZE_T offset) +{ + PMAPPED_VIEW_LIST pNewView = NULL; + + if (size == 0) + { + ERROR("Mapping size cannot be NULL\n"); + return NULL; + } + + for (LIST_ENTRY *pLink = MappedViewList.Flink; + pLink != &MappedViewList; + pLink = pLink->Flink) + { + PMAPPED_VIEW_LIST pView = CONTAINING_RECORD(pLink, MAPPED_VIEW_LIST, Link); + + if (pView->MappedFileDevNum != deviceNum + || pView->MappedFileInodeNum != inodeNum + || pView->dwDesiredAccess == FILE_MAP_COPY) + { + continue; + } + + // + // This is a shared mapping for the same indoe / device. Now, check + // to see if it overlaps with the range for the new view + // + + SIZE_T real_map_offs = pView->pNMHolder->offset; + SIZE_T real_map_sz = pView->pNMHolder->size; + + if (real_map_offs <= offset + && real_map_offs+real_map_sz >= offset) + { + // + // The views overlap. Even if this view is not reusable for the + // new once the search is over, as on + // ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS systems there + // cannot be shared mappings of two overlapping regions of the + // same file, in the same process. Therefore, whether this view + // is reusable or not we cannot mmap the requested region of + // the specified file. + // + + if (real_map_offs+real_map_sz >= offset+size) + { + /* The new desired mapping is fully contained in the + one just found: we can reuse this one */ + + pNewView = (PMAPPED_VIEW_LIST)InternalMalloc(sizeof(MAPPED_VIEW_LIST)); + if (pNewView) + { + memcpy(pNewView, pView, sizeof(*pNewView)); + NativeMapHolderAddRef(pNewView->pNMHolder); + pNewView->lpAddress = (VOID*)((CHAR*)pNewView->pNMHolder->address + + offset - pNewView->pNMHolder->offset); + pNewView->NumberOfBytesToMap = size; + } + else + { + ERROR("No memory for new MAPPED_VIEW_LIST node\n"); + } + } + + break; + } + } + + TRACE ("FindSharedMappingReplacement returning %p\n", pNewView); + return pNewView; +} + +static NativeMapHolder * NewNativeMapHolder(CPalThread *pThread, LPVOID address, SIZE_T size, + SIZE_T offset, long init_ref_count) +{ + NativeMapHolder * pThisMapHolder; + + if (init_ref_count < 0) + { + ASSERT("Negative initial reference count for new map holder\n"); + return NULL; + } + + pThisMapHolder = + (NativeMapHolder *)InternalMalloc(sizeof(NativeMapHolder)); + + if (pThisMapHolder) + { + pThisMapHolder->ref_count = init_ref_count; + pThisMapHolder->address = address; + pThisMapHolder->size = size; + pThisMapHolder->offset = offset; + } + + return pThisMapHolder; +} + +static LONG NativeMapHolderAddRef(NativeMapHolder * thisNMH) +{ + LONG ret = InterlockedIncrement(&thisNMH->ref_count); + return ret; +} + +static LONG NativeMapHolderRelease(CPalThread *pThread, NativeMapHolder * thisNMH) +{ + LONG ret = InterlockedDecrement(&thisNMH->ref_count); + if (ret == 0) + { + if (-1 == munmap(thisNMH->address, thisNMH->size)) + { + ASSERT( "Unable to unmap memory. Error=%s.\n", + strerror( errno ) ); + } + else + { + TRACE( "Successfully unmapped %p (size=%lu)\n", + thisNMH->address, (unsigned long)thisNMH->size); + } + free (thisNMH); + } + else if (ret < 0) + { + ASSERT( "Negative reference count for map holder %p" + " {address=%p, size=%lu}\n", thisNMH->address, + (unsigned long)thisNMH->size); + } + + return ret; +} + +#endif // ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS + +// Record a mapping in the MappedViewList list. +// This call assumes the mapping_critsec has already been taken. +static PAL_ERROR +MAPRecordMapping( + IPalObject *pMappingObject, + void *pPEBaseAddress, + void *addr, + size_t len, + int prot + ) +{ + if (pPEBaseAddress == NULL) + { + return ERROR_INTERNAL_ERROR; + } + + PAL_ERROR palError = NO_ERROR; + PMAPPED_VIEW_LIST pNewView; + pNewView = (PMAPPED_VIEW_LIST)InternalMalloc(sizeof(*pNewView)); + if (NULL != pNewView) + { + pNewView->lpAddress = addr; + pNewView->NumberOfBytesToMap = len; + pNewView->dwDesiredAccess = MAPMmapProtToAccessFlags(prot); + pMappingObject->AddReference(); + pNewView->pFileMapping = pMappingObject; + pNewView->lpPEBaseAddress = pPEBaseAddress; + InsertTailList(&MappedViewList, &pNewView->Link); + + TRACE_(LOADER)("Added address %p, size 0x%x, to the mapped file list.\n", addr, len); + } + else + { + palError = ERROR_INTERNAL_ERROR; + } + + return palError; +} + +// Do the actual mmap() call, and record the mapping in the MappedViewList list. +// This call assumes the mapping_critsec has already been taken. +static PAL_ERROR +MAPmmapAndRecord( + IPalObject *pMappingObject, + void *pPEBaseAddress, + void *addr, + size_t len, + int prot, + int flags, + int fd, + off_t offset, + LPVOID *ppvBaseAddress + ) +{ + _ASSERTE(pPEBaseAddress != NULL); + + PAL_ERROR palError = NO_ERROR; + off_t adjust = offset & (GetVirtualPageSize() - 1); + LPVOID pvBaseAddress = static_cast(addr) - adjust; + +#ifdef __APPLE__ + if ((prot & PROT_EXEC) != 0 && IsRunningOnMojaveHardenedRuntime()) + { + // Mojave hardened runtime doesn't allow executable mappings of a file. So we have to create an + // anonymous mapping and read the file contents into it instead. + + // Set the requested mapping with forced PROT_WRITE to ensure data from the file can be read there, + // read the data in and finally remove the forced PROT_WRITE + if ((mprotect(pvBaseAddress, len + adjust, prot | PROT_WRITE) == -1) || + (pread(fd, pvBaseAddress, len + adjust, offset - adjust) == -1) || + (((prot & PROT_WRITE) == 0) && mprotect(pvBaseAddress, len + adjust, prot) == -1)) + { + palError = FILEGetLastErrorFromErrno(); + } + } + else +#endif + { + pvBaseAddress = mmap(static_cast(addr) - adjust, len + adjust, prot, flags, fd, offset - adjust); + if (MAP_FAILED == pvBaseAddress) + { + ERROR_(LOADER)( "mmap failed with code %d: %s.\n", errno, strerror( errno ) ); + palError = FILEGetLastErrorFromErrno(); + } + } + + if (NO_ERROR == palError) + { + palError = MAPRecordMapping(pMappingObject, pPEBaseAddress, pvBaseAddress, len, prot); + if (NO_ERROR != palError) + { + if (-1 == munmap(pvBaseAddress, len)) + { + ERROR_(LOADER)("Unable to unmap the file. Expect trouble.\n"); + } + } + else + { + *ppvBaseAddress = pvBaseAddress; + } + } + + return palError; +} + +/*++ + MAPMapPEFile - + + Map a PE format file into memory like Windows LoadLibrary() would do. + Doesn't apply base relocations if the function is relocated. + +Parameters: + IN hFile - file to map + +Return value: + non-NULL - the base address of the mapped image + NULL - error, with last error set. +--*/ + +void * MAPMapPEFile(HANDLE hFile) +{ + PAL_ERROR palError = 0; + IPalObject *pFileObject = NULL; + IDataLock *pLocalDataLock = NULL; + CFileProcessLocalData *pLocalData = NULL; + CPalThread *pThread = InternalGetCurrentThread(); + void * loadedBase = NULL; + IMAGE_DOS_HEADER * loadedHeader = NULL; + void * retval; +#if _DEBUG + bool forceRelocs = false; + char* envVar; +#endif + + ENTRY("MAPMapPEFile (hFile=%p)\n", hFile); + + //Step 0: Verify values, find internal pal data structures. + if (INVALID_HANDLE_VALUE == hFile) + { + ERROR_(LOADER)( "Invalid file handle\n" ); + palError = ERROR_INVALID_HANDLE; + goto done; + } + + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hFile, + &aotFile, + &pFileObject + ); + if (NO_ERROR != palError) + { + ERROR_(LOADER)( "ReferenceObjectByHandle failed\n" ); + goto done; + } + + palError = pFileObject->GetProcessLocalData( + pThread, + ReadLock, + &pLocalDataLock, + reinterpret_cast(&pLocalData) + ); + if (NO_ERROR != palError) + { + ERROR_(LOADER)( "GetProcessLocalData failed\n" ); + goto done; + } + + int fd; + fd = pLocalData->unix_fd; + //Step 1: Read the PE headers and reserve enough space for the whole image somewhere. + IMAGE_DOS_HEADER dosHeader; + IMAGE_NT_HEADERS ntHeader; + if (sizeof(dosHeader) != pread(fd, &dosHeader, sizeof(dosHeader), 0)) + { + palError = FILEGetLastErrorFromErrno(); + ERROR_(LOADER)( "reading dos header failed\n" ); + goto done; + } + if (sizeof(ntHeader) != pread(fd, &ntHeader, sizeof(ntHeader), dosHeader.e_lfanew)) + { + palError = FILEGetLastErrorFromErrno(); + goto done; + } + + if ((VAL16(IMAGE_DOS_SIGNATURE) != VAL16(dosHeader.e_magic)) + || (VAL32(IMAGE_NT_SIGNATURE) != VAL32(ntHeader.Signature)) + || (VAL16(IMAGE_NT_OPTIONAL_HDR_MAGIC) != VAL16(ntHeader.OptionalHeader.Magic) ) ) + { + ERROR_(LOADER)( "Magic number mismatch\n" ); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + + //This doesn't read the entire NT header (the optional header technically has a variable length. But I + //don't need more directories. + + //I now know how big the file is. Reserve enough address space for the whole thing. Try to get the + //preferred base. Create the intial mapping as "no access". We'll use that for the guard pages in the + //"holes" between sections. + SIZE_T preferredBase, virtualSize; + preferredBase = ntHeader.OptionalHeader.ImageBase; + virtualSize = ntHeader.OptionalHeader.SizeOfImage; + + // Validate the image header + if ( (preferredBase == 0) + || (virtualSize == 0) + || (preferredBase + virtualSize < preferredBase) // Does the image overflow? + ) + { + ERROR_(LOADER)( "image is corrupt\n" ); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + +#if _DEBUG + envVar = EnvironGetenv("PAL_ForceRelocs"); + if (envVar) + { + if (strlen(envVar) > 0) + { + forceRelocs = true; + TRACE_(LOADER)("Forcing rebase of image\n"); + } + + free(envVar); + } + + void * pForceRelocBase; + pForceRelocBase = NULL; + if (forceRelocs) + { + //if we're forcing relocs, create an anonymous mapping at the preferred base. Only create the + //mapping if we can create it at the specified address. + pForceRelocBase = mmap( (void*)preferredBase, GetVirtualPageSize(), PROT_NONE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0 ); + if (pForceRelocBase == MAP_FAILED) + { + TRACE_(LOADER)("Attempt to take preferred base of %p to force relocation failed\n", (void*)preferredBase); + forceRelocs = false; + } + else if ((void*)preferredBase != pForceRelocBase) + { + TRACE_(LOADER)("Attempt to take preferred base of %p to force relocation failed; actually got %p\n", (void*)preferredBase, pForceRelocBase); + } + } +#endif // _DEBUG + + // The first mmap mapping covers the entire file but just reserves space. Subsequent mappings cover + // individual parts of the file, and actually map pages in. Note that according to the mmap() man page, "A + // successful mmap deletes any previous mapping in the allocated address range." Also, "If a MAP_FIXED + // request is successful, the mapping established by mmap() replaces any previous mappings for the process' pages + // in the range from addr to addr + len." Thus, we will record a series of mappings here, one for the header + // and each of the sections, as well as all the space between them that we give PROT_NONE protections. + + // We're going to start adding mappings to the mapping list, so take the critical section + InternalEnterCriticalSection(pThread, &mapping_critsec); + +#ifdef HOST_64BIT + // First try to reserve virtual memory using ExecutableAllocator. This allows all PE images to be + // near each other and close to the coreclr library which also allows the runtime to generate + // more efficient code (by avoiding usage of jump stubs). Alignment to a 64 KB granularity should + // not be necessary (alignment to page size should be sufficient), but see + // ExecutableMemoryAllocator::AllocateMemory() for the reason why it is done. + loadedBase = ReserveMemoryFromExecutableAllocator(pThread, ALIGN_UP(virtualSize, VIRTUAL_64KB)); +#endif // HOST_64BIT + + if (loadedBase == NULL) + { + void *usedBaseAddr = NULL; +#ifdef FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION + if (g_useDefaultBaseAddr) + { + usedBaseAddr = (void*) preferredBase; + } +#endif // FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION + // MAC64 requires we pass MAP_SHARED (or MAP_PRIVATE) flags - otherwise, the call is failed. + // Refer to mmap documentation at http://www.manpagez.com/man/2/mmap/ for details. + int mapFlags = MAP_ANON|MAP_PRIVATE; +#ifdef __APPLE__ + if (IsRunningOnMojaveHardenedRuntime()) + { + mapFlags |= MAP_JIT; + } +#endif // __APPLE__ + loadedBase = mmap(usedBaseAddr, virtualSize, PROT_NONE, mapFlags, -1, 0); + } + + if (MAP_FAILED == loadedBase) + { + ERROR_(LOADER)( "mmap failed with code %d: %s.\n", errno, strerror( errno ) ); + palError = FILEGetLastErrorFromErrno(); + loadedBase = NULL; // clear it so we don't try to use it during clean-up + goto doneReleaseMappingCriticalSection; + } + + // All subsequent mappings of the PE file will be in the range [loadedBase, loadedBase + virtualSize) + +#if _DEBUG + if (forceRelocs) + { + _ASSERTE(((SIZE_T)loadedBase) != preferredBase); + munmap(pForceRelocBase, GetVirtualPageSize()); // now that we've forced relocation, let the original address mapping go + } + if (((SIZE_T)loadedBase) != preferredBase) + { + TRACE_(LOADER)("Image rebased from preferredBase of %p to loadedBase of %p\n", preferredBase, loadedBase); + } + else + { + TRACE_(LOADER)("Image loaded at preferred base %p\n", loadedBase); + } +#endif // _DEBUG + + //we have now reserved memory (potentially we got rebased). Walk the PE sections and map each part + //separately. + + size_t headerSize; + headerSize = GetVirtualPageSize(); // if there are lots of sections, this could be wrong + + //first, map the PE header to the first page in the image. Get pointers to the section headers + palError = MAPmmapAndRecord(pFileObject, loadedBase, + loadedBase, headerSize, PROT_READ, MAP_FILE|MAP_PRIVATE|MAP_FIXED, fd, 0, + (void**)&loadedHeader); + if (NO_ERROR != palError) + { + ERROR_(LOADER)( "mmap of PE header failed\n" ); + goto doneReleaseMappingCriticalSection; + } + + TRACE_(LOADER)("PE header loaded @ %p\n", loadedHeader); + _ASSERTE(loadedHeader == loadedBase); // we already preallocated the space, and we used MAP_FIXED, so we should have gotten this address + IMAGE_SECTION_HEADER * firstSection; + firstSection = (IMAGE_SECTION_HEADER*)(((char *)loadedHeader) + + loadedHeader->e_lfanew + + offsetof(IMAGE_NT_HEADERS, OptionalHeader) + + VAL16(ntHeader.FileHeader.SizeOfOptionalHeader)); + unsigned numSections; + numSections = ntHeader.FileHeader.NumberOfSections; + + // Validation + char* sectionHeaderEnd; + sectionHeaderEnd = (char*)firstSection + numSections * sizeof(IMAGE_SECTION_HEADER); + if ( ((void*)firstSection < loadedBase) + || ((char*)firstSection > sectionHeaderEnd) + || (sectionHeaderEnd > (char*)loadedBase + virtualSize) + ) + { + ERROR_(LOADER)( "image is corrupt\n" ); + palError = ERROR_INVALID_PARAMETER; + goto doneReleaseMappingCriticalSection; + } + + void* prevSectionEnd; + prevSectionEnd = (char*)loadedBase + headerSize; // the first "section" for our purposes is the header + for (unsigned i = 0; i < numSections; ++i) + { + //for each section, map the section of the file to the correct virtual offset. Gather the + //protection bits from the PE file and convert them to the correct mmap PROT_* flags. + void * sectionData; + int prot = 0; + IMAGE_SECTION_HEADER ¤tHeader = firstSection[i]; + + void* sectionBase = (char*)loadedBase + currentHeader.VirtualAddress; + void* sectionBaseAligned = ALIGN_DOWN(sectionBase, GetVirtualPageSize()); + + // Validate the section header + if ( (sectionBase < loadedBase) // Did computing the section base overflow? + || ((char*)sectionBase + currentHeader.SizeOfRawData < (char*)sectionBase) // Does the section overflow? + || ((char*)sectionBase + currentHeader.SizeOfRawData > (char*)loadedBase + virtualSize) // Does the section extend past the end of the image as the header stated? + || (prevSectionEnd > sectionBase) // Does this section overlap the previous one? + ) + { + ERROR_(LOADER)( "section %d is corrupt\n", i ); + palError = ERROR_INVALID_PARAMETER; + goto doneReleaseMappingCriticalSection; + } + if (currentHeader.Misc.VirtualSize > currentHeader.SizeOfRawData) + { + ERROR_(LOADER)( "no support for zero-padded sections, section %d\n", i ); + palError = ERROR_INVALID_PARAMETER; + goto doneReleaseMappingCriticalSection; + } + + // Is there space between the previous section and this one? If so, add a PROT_NONE mapping to cover it. + if (prevSectionEnd < sectionBaseAligned) + { + palError = MAPRecordMapping(pFileObject, + loadedBase, + prevSectionEnd, + (char*)sectionBaseAligned - (char*)prevSectionEnd, + PROT_NONE); + if (NO_ERROR != palError) + { + ERROR_(LOADER)( "recording gap section before section %d failed\n", i ); + goto doneReleaseMappingCriticalSection; + } + } + + //Don't discard these sections. We need them to verify PE files + //if (currentHeader.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) + // continue; + if (currentHeader.Characteristics & IMAGE_SCN_MEM_EXECUTE) + prot |= PROT_EXEC; + if (currentHeader.Characteristics & IMAGE_SCN_MEM_READ) + prot |= PROT_READ; + if (currentHeader.Characteristics & IMAGE_SCN_MEM_WRITE) + prot |= PROT_WRITE; + + palError = MAPmmapAndRecord(pFileObject, loadedBase, + sectionBase, + currentHeader.SizeOfRawData, + prot, + MAP_FILE|MAP_PRIVATE|MAP_FIXED, + fd, + currentHeader.PointerToRawData, + §ionData); + if (NO_ERROR != palError) + { + ERROR_(LOADER)( "mmap of section %d failed\n", i ); + goto doneReleaseMappingCriticalSection; + } + +#if _DEBUG + { + // Ensure null termination of section name (which is allowed to not be null terminated if exactly 8 characters long) + char sectionName[9]; + sectionName[8] = '\0'; + memcpy(sectionName, currentHeader.Name, sizeof(currentHeader.Name)); + TRACE_(LOADER)("Section %d '%s' (header @ %p) loaded @ %p (RVA: 0x%x, SizeOfRawData: 0x%x, PointerToRawData: 0x%x)\n", + i, sectionName, ¤tHeader, sectionData, currentHeader.VirtualAddress, currentHeader.SizeOfRawData, currentHeader.PointerToRawData); + } +#endif // _DEBUG + + prevSectionEnd = ALIGN_UP((char*)sectionBase + currentHeader.SizeOfRawData, GetVirtualPageSize()); // round up to page boundary + } + + // Is there space after the last section and before the end of the mapped image? If so, add a PROT_NONE mapping to cover it. + char* imageEnd; + imageEnd = (char*)loadedBase + virtualSize; // actually, points just after the mapped end + if (prevSectionEnd < imageEnd) + { + palError = MAPRecordMapping(pFileObject, + loadedBase, + prevSectionEnd, + (char*)imageEnd - (char*)prevSectionEnd, + PROT_NONE); + if (NO_ERROR != palError) + { + ERROR_(LOADER)( "recording end of image gap section failed\n" ); + goto doneReleaseMappingCriticalSection; + } + } + + palError = ERROR_SUCCESS; + +doneReleaseMappingCriticalSection: + + InternalLeaveCriticalSection(pThread, &mapping_critsec); + +done: + + if (NULL != pLocalDataLock) + { + pLocalDataLock->ReleaseLock(pThread, FALSE); + } + + if (NULL != pFileObject) + { + pFileObject->ReleaseReference(pThread); + } + + if (palError == ERROR_SUCCESS) + { + retval = loadedBase; + LOGEXIT("MAPMapPEFile returns %p\n", retval); + } + else + { + retval = NULL; + LOGEXIT("MAPMapPEFile error: %d\n", palError); + + // If we had an error, and had mapped anything, we need to unmap it + if (loadedBase != NULL) + { + MAPUnmapPEFile(loadedBase); + } + } + return retval; +} + +/*++ +Function : + MAPUnmapPEFile - unmap a PE file, and remove it from the recorded list of PE files mapped + + returns TRUE if successful, FALSE otherwise +--*/ +BOOL MAPUnmapPEFile(LPCVOID lpAddress) +{ + TRACE_(LOADER)("MAPUnmapPEFile(lpAddress=%p)\n", lpAddress); + + if ( NULL == lpAddress ) + { + ERROR_(LOADER)( "lpAddress cannot be NULL\n" ); + return FALSE; + } + + BOOL retval = TRUE; + CPalThread * pThread = InternalGetCurrentThread(); + InternalEnterCriticalSection(pThread, &mapping_critsec); + PLIST_ENTRY pLink, pLinkNext, pLinkLocal = NULL; + unsigned nPESections = 0; + + // Look through the entire MappedViewList for all mappings associated with the + // PE file with base address 'lpAddress'. We want to unmap all the memory + // and then release the file mapping object. Unfortunately, based on the comment + // in CorUnix::InternalUnmapViewOfFile(), we can't release the file mapping object + // while within the mapping critical section. So, we unlink all the elements from the + // main list while in the critical section, and then run through this local list + // doing the real work after releasing the main list critical section. The order + // of the unmapping doesn't matter, so we don't fully set all the list link pointers, + // only a minimal set. + + for(pLink = MappedViewList.Flink; + pLink != &MappedViewList; + pLink = pLinkNext) + { + pLinkNext = pLink->Flink; + PMAPPED_VIEW_LIST pView = CONTAINING_RECORD(pLink, MAPPED_VIEW_LIST, Link); + + if (pView->lpPEBaseAddress == lpAddress) // this entry is associated with the PE file + { + ++nPESections; // for debugging, check that we see at least one + + RemoveEntryList(&pView->Link); + pView->Link.Flink = pLinkLocal; // the local list is singly-linked, NULL terminated + pLinkLocal = &pView->Link; + } + } + +#if _DEBUG + if (nPESections == 0) + { + ERROR_(LOADER)( "MAPUnmapPEFile called to unmap a file that was not in the PE file mapping list\n" ); + } +#endif // _DEBUG + + InternalLeaveCriticalSection(pThread, &mapping_critsec); + + // Now, outside the critical section, do the actual unmapping work + + for(pLink = pLinkLocal; + pLink != NULL; + pLink = pLinkNext) + { + pLinkNext = pLink->Flink; + PMAPPED_VIEW_LIST pView = CONTAINING_RECORD(pLink, MAPPED_VIEW_LIST, Link); + + // remove pView mapping from the list + if (-1 == munmap(pView->lpAddress, pView->NumberOfBytesToMap)) + { + // Emit an error message in a trace, but continue trying to do the rest + ERROR_(LOADER)("Unable to unmap the file. Expect trouble.\n"); + retval = FALSE; + } + + IPalObject* pFileObject = pView->pFileMapping; + if (NULL != pFileObject) + { + pFileObject->ReleaseReference(pThread); + } + free(pView); // this leaves pLink dangling + } + + TRACE_(LOADER)("MAPUnmapPEFile returning %d\n", retval); + return retval; +} + +/*++ +Function : + MAPMarkSectionAsNotNeeded - Mark a section as NotNeeded + returns TRUE if successful, FALSE otherwise +--*/ +BOOL MAPMarkSectionAsNotNeeded(LPCVOID lpAddress) +{ + TRACE_(LOADER)("MAPMarkSectionAsNotNeeded(lpAddress=%p)\n", lpAddress); + + if ( NULL == lpAddress ) + { + ERROR_(LOADER)( "lpAddress cannot be NULL\n" ); + return FALSE; + } + + BOOL retval = TRUE; + CPalThread * pThread = InternalGetCurrentThread(); + InternalEnterCriticalSection(pThread, &mapping_critsec); + PLIST_ENTRY pLink, pLinkNext = NULL; + + // Look through the entire MappedViewList for all mappings associated with the + // section with an address 'lpAddress' which we want to mark as NotNeeded. + + for(pLink = MappedViewList.Flink; + pLink != &MappedViewList; + pLink = pLinkNext) + { + pLinkNext = pLink->Flink; + PMAPPED_VIEW_LIST pView = CONTAINING_RECORD(pLink, MAPPED_VIEW_LIST, Link); + + if (pView->lpAddress == lpAddress) // this entry is associated with the section + { + if (-1 == posix_madvise(pView->lpAddress, pView->NumberOfBytesToMap, POSIX_MADV_DONTNEED)) + { + ERROR_(LOADER)("Unable to mark the section as NotNeeded.\n"); + retval = FALSE; + } + else + { + pView->dwDesiredAccess = 0; + } + break; + } + } + + InternalLeaveCriticalSection(pThread, &mapping_critsec); + + TRACE_(LOADER)("MAPMarkSectionAsNotNeeded returning %d\n", retval); + return retval; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/virtual.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/virtual.cpp new file mode 100644 index 0000000..d6a33c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/map/virtual.cpp @@ -0,0 +1,2290 @@ +// 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: + + virtual.cpp + +Abstract: + + Implementation of virtual memory management functions. + + + +--*/ + +#include "pal/dbgmsg.h" + +SET_DEFAULT_DEBUG_CHANNEL(VIRTUAL); // some headers have code with asserts, so do this first + +#include "pal/thread.hpp" +#include "pal/cs.hpp" +#include "pal/malloc.hpp" +#include "pal/file.hpp" +#include "pal/seh.hpp" +#include "pal/virtual.h" +#include "pal/map.h" +#include "pal/init.h" +#include "pal/utils.h" +#include "common.h" + +#include +#include +#include +#include +#include +#include + +#if HAVE_VM_ALLOCATE +#include +#include +#endif // HAVE_VM_ALLOCATE + +using namespace CorUnix; + +CRITICAL_SECTION virtual_critsec; + +// The first node in our list of allocated blocks. +static PCMI pVirtualMemory; + +static size_t s_virtualPageSize = 0; + +/* We need MAP_ANON. However on some platforms like HP-UX, it is defined as MAP_ANONYMOUS */ +#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS) +#define MAP_ANON MAP_ANONYMOUS +#endif + +/*++ +Function: + ReserveVirtualMemory() + + Helper function that is used by Virtual* APIs and ExecutableMemoryAllocator + to reserve virtual memory from the OS. + +--*/ +static LPVOID ReserveVirtualMemory( + IN CPalThread *pthrCurrent, /* Currently executing thread */ + IN LPVOID lpAddress, /* Region to reserve or commit */ + IN SIZE_T dwSize, /* Size of Region */ + IN DWORD fAllocationType); /* Allocation Type */ + + +// A memory allocator that allocates memory from a pre-reserved region +// of virtual memory that is located near the CoreCLR library. +static ExecutableMemoryAllocator g_executableMemoryAllocator; + +// +// +// Virtual Memory Logging +// +// We maintain a lightweight in-memory circular buffer recording virtual +// memory operations so that we can better diagnose failures and crashes +// caused by one of these operations mishandling memory in some way. +// +// +namespace VirtualMemoryLogging +{ + // Specifies the operation being logged + enum class VirtualOperation + { + Allocate = 0x10, + Reserve = 0x20, + Commit = 0x30, + Decommit = 0x40, + Release = 0x50, + Reset = 0x60, + ReserveFromExecutableMemoryAllocatorWithinRange = 0x70 + }; + + // Indicates that the attempted operation has failed + const DWORD FailedOperationMarker = 0x80000000; + + // An entry in the in-memory log + struct LogRecord + { + ULONG RecordId; + DWORD Operation; + LPVOID CurrentThread; + LPVOID RequestedAddress; + LPVOID ReturnedAddress; + SIZE_T Size; + DWORD AllocationType; + DWORD Protect; + }; + + // Maximum number of records in the in-memory log + const ULONG MaxRecords = 128; + + // Buffer used to store the logged data + volatile LogRecord logRecords[MaxRecords]; + + // Current record number. Use (recordNumber % MaxRecords) to determine + // the current position in the circular buffer. + volatile ULONG recordNumber = 0; + + // Record an entry in the in-memory log + void LogVaOperation( + IN VirtualOperation operation, + IN LPVOID requestedAddress, + IN SIZE_T size, + IN DWORD flAllocationType, + IN DWORD flProtect, + IN LPVOID returnedAddress, + IN BOOL result) + { + ULONG i = (ULONG)InterlockedIncrement((LONG *)&recordNumber) - 1; + LogRecord* curRec = (LogRecord*)&logRecords[i % MaxRecords]; + + curRec->RecordId = i; + curRec->CurrentThread = reinterpret_cast(pthread_self()); + curRec->RequestedAddress = requestedAddress; + curRec->ReturnedAddress = returnedAddress; + curRec->Size = size; + curRec->AllocationType = flAllocationType; + curRec->Protect = flProtect; + curRec->Operation = static_cast(operation) | (result ? 0 : FailedOperationMarker); + } +} + +/*++ +Function: + VIRTUALInitialize() + + Initializes this section's critical section. + +Return value: + TRUE if initialization succeeded + FALSE otherwise. + +--*/ +extern "C" +BOOL +VIRTUALInitialize(bool initializeExecutableMemoryAllocator) +{ + s_virtualPageSize = getpagesize(); + + TRACE("Initializing the Virtual Critical Sections. \n"); + + InternalInitializeCriticalSection(&virtual_critsec); + + pVirtualMemory = NULL; + + if (initializeExecutableMemoryAllocator) + { + g_executableMemoryAllocator.Initialize(); + } + + return TRUE; +} + +/*** + * + * VIRTUALCleanup() + * Deletes this section's critical section. + * + */ +extern "C" +void VIRTUALCleanup() +{ + PCMI pEntry; + PCMI pTempEntry; + CPalThread * pthrCurrent = InternalGetCurrentThread(); + + InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + + // Clean up the allocated memory. + pEntry = pVirtualMemory; + while ( pEntry ) + { + WARN( "The memory at %d was not freed through a call to VirtualFree.\n", + pEntry->startBoundary ); + free(pEntry->pAllocState); + free(pEntry->pProtectionState ); + pTempEntry = pEntry; + pEntry = pEntry->pNext; + free(pTempEntry ); + } + pVirtualMemory = NULL; + + InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + + TRACE( "Deleting the Virtual Critical Sections. \n" ); + DeleteCriticalSection( &virtual_critsec ); +} + +/*** + * + * VIRTUALContainsInvalidProtectionFlags() + * Returns TRUE if an invalid flag is specified. FALSE otherwise. + */ +static BOOL VIRTUALContainsInvalidProtectionFlags( IN DWORD flProtect ) +{ + if ( ( flProtect & ~( PAGE_NOACCESS | PAGE_READONLY | + PAGE_READWRITE | PAGE_EXECUTE | PAGE_EXECUTE_READ | + PAGE_EXECUTE_READWRITE ) ) != 0 ) + { + return TRUE; + } + else + { + return FALSE; + } +} + + +/**** + * + * VIRTUALIsPageCommitted + * + * SIZE_T nBitToRetrieve - Which page to check. + * + * Returns TRUE if committed, FALSE otherwise. + * + */ +static BOOL VIRTUALIsPageCommitted( SIZE_T nBitToRetrieve, CONST PCMI pInformation ) +{ + SIZE_T nByteOffset = 0; + UINT nBitOffset = 0; + UINT byteMask = 0; + + if ( !pInformation ) + { + ERROR( "pInformation was NULL!\n" ); + return FALSE; + } + + nByteOffset = nBitToRetrieve / CHAR_BIT; + nBitOffset = nBitToRetrieve % CHAR_BIT; + + byteMask = 1 << nBitOffset; + + if ( pInformation->pAllocState[ nByteOffset ] & byteMask ) + { + return TRUE; + } + else + { + return FALSE; + } +} + +/********* + * + * VIRTUALGetAllocationType + * + * IN SIZE_T Index - The page within the range to retrieve + * the state for. + * + * IN pInformation - The virtual memory object. + * + */ +static INT VIRTUALGetAllocationType( SIZE_T Index, CONST PCMI pInformation ) +{ + if ( VIRTUALIsPageCommitted( Index, pInformation ) ) + { + return MEM_COMMIT; + } + else + { + return MEM_RESERVE; + } +} + +/**** + * + * VIRTUALSetPageBits + * + * IN UINT nStatus - Bit set / reset [0: reset, any other value: set]. + * IN SIZE_T nStartingBit - The bit to set. + * + * IN SIZE_T nNumberOfBits - The range of bits to set. + * IN BYTE* pBitArray - A pointer the array to be manipulated. + * + * Returns TRUE on success, FALSE otherwise. + * Turn on/off memory status bits. + * + */ +static BOOL VIRTUALSetPageBits ( UINT nStatus, SIZE_T nStartingBit, + SIZE_T nNumberOfBits, BYTE * pBitArray ) +{ + /* byte masks for optimized modification of partial bytes (changing less + than 8 bits in a single byte). note that bits are treated in little + endian order : value 1 is bit 0; value 128 is bit 7. in the binary + representations below, bit 0 is on the right */ + + /* start masks : for modifying bits >= n while preserving bits < n. + example : if nStartignBit%8 is 3, then bits 0, 1, 2 remain unchanged + while bits 3..7 are changed; startmasks[3] can be used for this. */ + static const BYTE startmasks[8] = { + 0xff, /* start at 0 : 1111 1111 */ + 0xfe, /* start at 1 : 1111 1110 */ + 0xfc, /* start at 2 : 1111 1100 */ + 0xf8, /* start at 3 : 1111 1000 */ + 0xf0, /* start at 4 : 1111 0000 */ + 0xe0, /* start at 5 : 1110 0000 */ + 0xc0, /* start at 6 : 1100 0000 */ + 0x80 /* start at 7 : 1000 0000 */ + }; + + /* end masks : for modifying bits <= n while preserving bits > n. + example : if the last bit to change is 5, then bits 6 & 7 stay unchanged + while bits 1..5 are changed; endmasks[5] can be used for this. */ + static const BYTE endmasks[8] = { + 0x01, /* end at 0 : 0000 0001 */ + 0x03, /* end at 1 : 0000 0011 */ + 0x07, /* end at 2 : 0000 0111 */ + 0x0f, /* end at 3 : 0000 1111 */ + 0x1f, /* end at 4 : 0001 1111 */ + 0x3f, /* end at 5 : 0011 1111 */ + 0x7f, /* end at 6 : 0111 1111 */ + 0xff /* end at 7 : 1111 1111 */ + }; + /* last example : if only the middle of a byte must be changed, both start + and end masks can be combined (bitwise AND) to obtain the correct mask. + if we want to change bits 2 to 4 : + startmasks[2] : 0xfc 1111 1100 (change 2,3,4,5,6,7) + endmasks[4]: 0x1f 0001 1111 (change 0,1,2,3,4) + bitwise AND : 0x1c 0001 1100 (change 2,3,4) + */ + + BYTE byte_mask; + SIZE_T nLastBit; + SIZE_T nFirstByte; + SIZE_T nLastByte; + SIZE_T nFullBytes; + + TRACE( "VIRTUALSetPageBits( nStatus = %d, nStartingBit = %d, " + "nNumberOfBits = %d, pBitArray = 0x%p )\n", + nStatus, nStartingBit, nNumberOfBits, pBitArray ); + + if ( 0 == nNumberOfBits ) + { + ERROR( "nNumberOfBits was 0!\n" ); + return FALSE; + } + + nLastBit = nStartingBit+nNumberOfBits-1; + nFirstByte = nStartingBit / 8; + nLastByte = nLastBit / 8; + + /* handle partial first byte (if any) */ + if(0 != (nStartingBit % 8)) + { + byte_mask = startmasks[nStartingBit % 8]; + + /* if 1st byte is the only changing byte, combine endmask to preserve + trailing bits (see 3rd example above) */ + if( nLastByte == nFirstByte) + { + byte_mask &= endmasks[nLastBit % 8]; + } + + /* byte_mask contains 1 for bits to change, 0 for bits to leave alone */ + if(0 == nStatus) + { + /* bits to change must be set to 0 : invert byte_mask (giving 0 for + bits to change), use bitwise AND */ + pBitArray[nFirstByte] &= ~byte_mask; + } + else + { + /* bits to change must be set to 1 : use bitwise OR */ + pBitArray[nFirstByte] |= byte_mask; + } + + /* stop right away if only 1 byte is being modified */ + if(nLastByte == nFirstByte) + { + return TRUE; + } + + /* we're done with the 1st byte; skip over it */ + nFirstByte++; + } + + /* number of bytes to change, excluding the last byte (handled separately)*/ + nFullBytes = nLastByte - nFirstByte; + + if(0 != nFullBytes) + { + // Turn off/on dirty bits + memset( &(pBitArray[nFirstByte]), (0 == nStatus) ? 0 : 0xFF, nFullBytes ); + } + + /* handle last (possibly partial) byte */ + byte_mask = endmasks[nLastBit % 8]; + + /* byte_mask contains 1 for bits to change, 0 for bits to leave alone */ + if(0 == nStatus) + { + /* bits to change must be set to 0 : invert byte_mask (giving 0 for + bits to change), use bitwise AND */ + pBitArray[nLastByte] &= ~byte_mask; + } + else + { + /* bits to change must be set to 1 : use bitwise OR */ + pBitArray[nLastByte] |= byte_mask; + } + + return TRUE; +} + +/**** + * + * VIRTUALSetAllocState + * + * IN UINT nAction - Which action to perform. + * IN SIZE_T nStartingBit - The bit to set. + * + * IN SIZE_T nNumberOfBits - The range of bits to set. + * IN PCMI pStateArray - A pointer the array to be manipulated. + * + * Returns TRUE on success, FALSE otherwise. + * Turn bit on to indicate committed, turn bit off to indicate reserved. + * + */ +static BOOL VIRTUALSetAllocState( UINT nAction, SIZE_T nStartingBit, + SIZE_T nNumberOfBits, CONST PCMI pInformation ) +{ + TRACE( "VIRTUALSetAllocState( nAction = %d, nStartingBit = %d, " + "nNumberOfBits = %d, pStateArray = 0x%p )\n", + nAction, nStartingBit, nNumberOfBits, pInformation ); + + if ( !pInformation ) + { + ERROR( "pInformation was invalid!\n" ); + return FALSE; + } + + return VIRTUALSetPageBits((MEM_COMMIT == nAction) ? 1 : 0, nStartingBit, + nNumberOfBits, pInformation->pAllocState); +} + +/**** + * + * VIRTUALFindRegionInformation( ) + * + * IN UINT_PTR address - The address to look for. + * + * Returns the PCMI if found, NULL otherwise. + */ +static PCMI VIRTUALFindRegionInformation( IN UINT_PTR address ) +{ + PCMI pEntry = NULL; + + TRACE( "VIRTUALFindRegionInformation( %#x )\n", address ); + + pEntry = pVirtualMemory; + + while( pEntry ) + { + if ( pEntry->startBoundary > address ) + { + /* Gone past the possible location in the list. */ + pEntry = NULL; + break; + } + if ( pEntry->startBoundary + pEntry->memSize > address ) + { + break; + } + + pEntry = pEntry->pNext; + } + return pEntry; +} + +/*++ +Function : + + VIRTUALReleaseMemory + + Removes a PCMI entry from the list. + + Returns true on success. FALSE otherwise. +--*/ +static BOOL VIRTUALReleaseMemory( PCMI pMemoryToBeReleased ) +{ + BOOL bRetVal = TRUE; + + if ( !pMemoryToBeReleased ) + { + ASSERT( "Invalid pointer.\n" ); + return FALSE; + } + + if ( pMemoryToBeReleased == pVirtualMemory ) + { + /* This is either the first entry, or the only entry. */ + pVirtualMemory = pMemoryToBeReleased->pNext; + if ( pMemoryToBeReleased->pNext ) + { + pMemoryToBeReleased->pNext->pPrevious = NULL; + } + } + else /* Could be anywhere in the list. */ + { + /* Delete the entry from the linked list. */ + if ( pMemoryToBeReleased->pPrevious ) + { + pMemoryToBeReleased->pPrevious->pNext = pMemoryToBeReleased->pNext; + } + + if ( pMemoryToBeReleased->pNext ) + { + pMemoryToBeReleased->pNext->pPrevious = pMemoryToBeReleased->pPrevious; + } + } + + free( pMemoryToBeReleased->pAllocState ); + pMemoryToBeReleased->pAllocState = NULL; + + free( pMemoryToBeReleased->pProtectionState ); + pMemoryToBeReleased->pProtectionState = NULL; + + free( pMemoryToBeReleased ); + pMemoryToBeReleased = NULL; + + return bRetVal; +} + +/**** + * VIRTUALConvertWinFlags() - + * Converts win32 protection flags to + * internal VIRTUAL flags. + * + */ +static BYTE VIRTUALConvertWinFlags( IN DWORD flProtect ) +{ + BYTE MemAccessControl = 0; + + switch ( flProtect & 0xff ) + { + case PAGE_NOACCESS : + MemAccessControl = VIRTUAL_NOACCESS; + break; + case PAGE_READONLY : + MemAccessControl = VIRTUAL_READONLY; + break; + case PAGE_READWRITE : + MemAccessControl = VIRTUAL_READWRITE; + break; + case PAGE_EXECUTE : + MemAccessControl = VIRTUAL_EXECUTE; + break; + case PAGE_EXECUTE_READ : + MemAccessControl = VIRTUAL_EXECUTE_READ; + break; + case PAGE_EXECUTE_READWRITE: + MemAccessControl = VIRTUAL_EXECUTE_READWRITE; + break; + + default : + MemAccessControl = 0; + ERROR( "Incorrect or no protection flags specified.\n" ); + break; + } + return MemAccessControl; +} + +/**** + * VIRTUALConvertVirtualFlags() - + * Converts internal virtual protection + * flags to their win32 counterparts. + */ +static DWORD VIRTUALConvertVirtualFlags( IN BYTE VirtualProtect ) +{ + DWORD MemAccessControl = 0; + + if ( VirtualProtect == VIRTUAL_READONLY ) + { + MemAccessControl = PAGE_READONLY; + } + else if ( VirtualProtect == VIRTUAL_READWRITE ) + { + MemAccessControl = PAGE_READWRITE; + } + else if ( VirtualProtect == VIRTUAL_EXECUTE_READWRITE ) + { + MemAccessControl = PAGE_EXECUTE_READWRITE; + } + else if ( VirtualProtect == VIRTUAL_EXECUTE_READ ) + { + MemAccessControl = PAGE_EXECUTE_READ; + } + else if ( VirtualProtect == VIRTUAL_EXECUTE ) + { + MemAccessControl = PAGE_EXECUTE; + } + else if ( VirtualProtect == VIRTUAL_NOACCESS ) + { + MemAccessControl = PAGE_NOACCESS; + } + + else + { + MemAccessControl = 0; + ERROR( "Incorrect or no protection flags specified.\n" ); + } + return MemAccessControl; +} + +/*** + * Displays the linked list. + * + */ +#if defined _DEBUG +static void VIRTUALDisplayList( void ) +{ + if (!DBG_ENABLED(DLI_TRACE, defdbgchan)) + return; + + PCMI p; + SIZE_T count; + SIZE_T index; + CPalThread * pthrCurrent = InternalGetCurrentThread(); + + InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + + p = pVirtualMemory; + count = 0; + while ( p ) { + + DBGOUT( "Entry %d : \n", count ); + DBGOUT( "\t startBoundary %#x \n", p->startBoundary ); + DBGOUT( "\t memSize %d \n", p->memSize ); + + DBGOUT( "\t pAllocState " ); + for ( index = 0; index < p->memSize / GetVirtualPageSize(); index++) + { + DBGOUT( "[%d] ", VIRTUALGetAllocationType( index, p ) ); + } + DBGOUT( "\t pProtectionState " ); + for ( index = 0; index < p->memSize / GetVirtualPageSize(); index++ ) + { + DBGOUT( "[%d] ", (UINT)p->pProtectionState[ index ] ); + } + DBGOUT( "\n" ); + DBGOUT( "\t accessProtection %d \n", p->accessProtection ); + DBGOUT( "\t allocationType %d \n", p->allocationType ); + DBGOUT( "\t pNext %p \n", p->pNext ); + DBGOUT( "\t pLast %p \n", p->pPrevious ); + + count++; + p = p->pNext; + } + + InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); +} +#endif + +#ifdef DEBUG +void VerifyRightEntry(PCMI pEntry) +{ + volatile PCMI pRight = pEntry->pNext; + SIZE_T endAddress; + if (pRight != nullptr) + { + endAddress = ((SIZE_T)pEntry->startBoundary) + pEntry->memSize; + _ASSERTE(endAddress <= (SIZE_T)pRight->startBoundary); + } +} + +void VerifyLeftEntry(PCMI pEntry) +{ + volatile PCMI pLeft = pEntry->pPrevious; + SIZE_T endAddress; + if (pLeft != NULL) + { + endAddress = ((SIZE_T)pLeft->startBoundary) + pLeft->memSize; + _ASSERTE(endAddress <= (SIZE_T)pEntry->startBoundary); + } +} +#endif // DEBUG + +/**** + * VIRTUALStoreAllocationInfo() + * + * Stores the allocation information in the linked list. + * NOTE: The caller must own the critical section. + */ +static BOOL VIRTUALStoreAllocationInfo( + IN UINT_PTR startBoundary, /* Start of the region. */ + IN SIZE_T memSize, /* Size of the region. */ + IN DWORD flAllocationType, /* Allocation Types. */ + IN DWORD flProtection ) /* Protections flags on the memory. */ +{ + PCMI pNewEntry = nullptr; + PCMI pMemInfo = nullptr; + SIZE_T nBufferSize = 0; + + if (!IS_ALIGNED(memSize, GetVirtualPageSize())) + { + ERROR("The memory size was not a multiple of the page size. \n"); + return FALSE; + } + + if (!(pNewEntry = (PCMI)InternalMalloc(sizeof(*pNewEntry)))) + { + ERROR( "Unable to allocate memory for the structure.\n"); + return FALSE; + } + + pNewEntry->startBoundary = startBoundary; + pNewEntry->memSize = memSize; + pNewEntry->allocationType = flAllocationType; + pNewEntry->accessProtection = flProtection; + + nBufferSize = memSize / GetVirtualPageSize() / CHAR_BIT; + if ((memSize / GetVirtualPageSize()) % CHAR_BIT != 0) + { + nBufferSize++; + } + + pNewEntry->pAllocState = (BYTE*)InternalMalloc(nBufferSize); + pNewEntry->pProtectionState = (BYTE*)InternalMalloc((memSize / GetVirtualPageSize())); + + if (pNewEntry->pAllocState && pNewEntry->pProtectionState) + { + /* Set the intial allocation state, and initial allocation protection. */ + VIRTUALSetAllocState(MEM_RESERVE, 0, nBufferSize * CHAR_BIT, pNewEntry); + memset(pNewEntry->pProtectionState, + VIRTUALConvertWinFlags(flProtection), + memSize / GetVirtualPageSize()); + } + else + { + ERROR( "Unable to allocate memory for the structure.\n"); + + if (pNewEntry->pProtectionState) free(pNewEntry->pProtectionState); + pNewEntry->pProtectionState = nullptr; + + if (pNewEntry->pAllocState) free(pNewEntry->pAllocState); + pNewEntry->pAllocState = nullptr; + + free(pNewEntry); + pNewEntry = nullptr; + + return FALSE; + } + + pMemInfo = pVirtualMemory; + + if (pMemInfo && pMemInfo->startBoundary < startBoundary) + { + /* Look for the correct insert point */ + TRACE("Looking for the correct insert location.\n"); + while (pMemInfo->pNext && (pMemInfo->pNext->startBoundary < startBoundary)) + { + pMemInfo = pMemInfo->pNext; + } + + pNewEntry->pNext = pMemInfo->pNext; + pNewEntry->pPrevious = pMemInfo; + + if (pNewEntry->pNext) + { + pNewEntry->pNext->pPrevious = pNewEntry; + } + + pMemInfo->pNext = pNewEntry; + } + else + { + /* This is the first entry in the list. */ + pNewEntry->pNext = pMemInfo; + pNewEntry->pPrevious = nullptr; + + if (pNewEntry->pNext) + { + pNewEntry->pNext->pPrevious = pNewEntry; + } + + pVirtualMemory = pNewEntry ; + } + +#ifdef DEBUG + VerifyRightEntry(pNewEntry); + VerifyLeftEntry(pNewEntry); +#endif // DEBUG + + return TRUE; +} + +/****** + * + * VIRTUALResetMemory() - Helper function that resets the memory + * + * + */ +static LPVOID VIRTUALResetMemory( + IN CPalThread *pthrCurrent, /* Currently executing thread */ + IN LPVOID lpAddress, /* Region to reserve or commit */ + IN SIZE_T dwSize) /* Size of Region */ +{ + LPVOID pRetVal = NULL; + UINT_PTR StartBoundary; + SIZE_T MemSize; + + TRACE( "Resetting the memory now..\n"); + + StartBoundary = (UINT_PTR) ALIGN_DOWN(lpAddress, GetVirtualPageSize()); + MemSize = ALIGN_UP((UINT_PTR)lpAddress + dwSize, GetVirtualPageSize()) - StartBoundary; + + int st; +#if HAVE_MADV_FREE + // Try to use MADV_FREE if supported. It tells the kernel that the application doesn't + // need the pages in the range. Freeing the pages can be delayed until a memory pressure + // occurs. + st = madvise((LPVOID)StartBoundary, MemSize, MADV_FREE); + if (st != 0) +#endif + { + // In case the MADV_FREE is not supported, use MADV_DONTNEED + st = posix_madvise((LPVOID)StartBoundary, MemSize, POSIX_MADV_DONTNEED); + } + + if (st == 0) + { + pRetVal = lpAddress; + +#ifdef MADV_DONTDUMP + // Do not include reset memory in coredump. + madvise((LPVOID)StartBoundary, MemSize, MADV_DONTDUMP); +#endif + } + + LogVaOperation( + VirtualMemoryLogging::VirtualOperation::Reset, + lpAddress, + dwSize, + 0, + 0, + pRetVal, + pRetVal != NULL); + + return pRetVal; +} + +/****** + * + * VIRTUALReserveMemory() - Helper function that actually reserves the memory. + * + * NOTE: I call SetLastError in here, because many different error states + * exists, and that would be very complicated to work around. + * + */ +static LPVOID VIRTUALReserveMemory( + IN CPalThread *pthrCurrent, /* Currently executing thread */ + IN LPVOID lpAddress, /* Region to reserve or commit */ + IN SIZE_T dwSize, /* Size of Region */ + IN DWORD flAllocationType, /* Type of allocation */ + IN DWORD flProtect) /* Type of access protection */ +{ + LPVOID pRetVal = NULL; + UINT_PTR StartBoundary; + SIZE_T MemSize; + + TRACE( "Reserving the memory now..\n"); + + // First, figure out where we're trying to reserve the memory and + // how much we need. On most systems, requests to mmap must be + // page-aligned and at multiples of the page size. Unlike on Windows, on + // Unix, the allocation granularity is the page size, so the memory size to + // reserve is not aligned to 64 KB. Nor should the start boundary need to + // to be aligned down to 64 KB, but it is expected that there are other + // components that rely on this alignment when providing a specific address + // (note that mmap itself does not make any such guarantees). + StartBoundary = (UINT_PTR)ALIGN_DOWN(lpAddress, VIRTUAL_64KB); + MemSize = ALIGN_UP((UINT_PTR)lpAddress + dwSize, GetVirtualPageSize()) - StartBoundary; + + // If this is a request for special executable (JIT'ed) memory then, first of all, + // try to get memory from the executable memory allocator to satisfy the request. + if (((flAllocationType & MEM_RESERVE_EXECUTABLE) != 0) && (lpAddress == NULL)) + { + // Alignment to a 64 KB granularity should not be necessary (alignment to page size should be sufficient), but see + // ExecutableMemoryAllocator::AllocateMemory() for the reason why it is done + SIZE_T reservationSize = ALIGN_UP(MemSize, VIRTUAL_64KB); + pRetVal = g_executableMemoryAllocator.AllocateMemory(reservationSize); + if (pRetVal != nullptr) + { + MemSize = reservationSize; + } + } + + if (pRetVal == NULL) + { + // Try to reserve memory from the OS + if ((flProtect & 0xff) == PAGE_EXECUTE_READWRITE) + { + flAllocationType |= MEM_RESERVE_EXECUTABLE; + } + pRetVal = ReserveVirtualMemory(pthrCurrent, (LPVOID)StartBoundary, MemSize, flAllocationType); + } + + if (pRetVal != NULL) + { + if ( !lpAddress ) + { + /* Compute the real values instead of the null values. */ + StartBoundary = (UINT_PTR) ALIGN_DOWN(pRetVal, GetVirtualPageSize()); + MemSize = ALIGN_UP((UINT_PTR)pRetVal + dwSize, GetVirtualPageSize()) - StartBoundary; + } + + if ( !VIRTUALStoreAllocationInfo( StartBoundary, MemSize, + flAllocationType, flProtect ) ) + { + ASSERT( "Unable to store the structure in the list.\n"); + pthrCurrent->SetLastError( ERROR_INTERNAL_ERROR ); + munmap( pRetVal, MemSize ); + pRetVal = NULL; + } + } + + LogVaOperation( + VirtualMemoryLogging::VirtualOperation::Reserve, + lpAddress, + dwSize, + flAllocationType, + flProtect, + pRetVal, + pRetVal != NULL); + + return pRetVal; +} + +/****** + * + * ReserveVirtualMemory() - Helper function that is used by Virtual* APIs + * and ExecutableMemoryAllocator to reserve virtual memory from the OS. + * + */ +static LPVOID ReserveVirtualMemory( + IN CPalThread *pthrCurrent, /* Currently executing thread */ + IN LPVOID lpAddress, /* Region to reserve or commit */ + IN SIZE_T dwSize, /* Size of Region */ + IN DWORD fAllocationType) /* Allocation type */ +{ + UINT_PTR StartBoundary = (UINT_PTR)lpAddress; + SIZE_T MemSize = dwSize; + + TRACE( "Reserving the memory now.\n"); + + // Most platforms will only commit memory if it is dirtied, + // so this should not consume too much swap space. + int mmapFlags = MAP_ANON | MAP_PRIVATE; + + if ((fAllocationType & MEM_LARGE_PAGES) != 0) + { +#if HAVE_MAP_HUGETLB + mmapFlags |= MAP_HUGETLB; + TRACE("MAP_HUGETLB flag set\n"); +#elif HAVE_VM_FLAGS_SUPERPAGE_SIZE_ANY + mmapFlags |= VM_FLAGS_SUPERPAGE_SIZE_ANY; + TRACE("VM_FLAGS_SUPERPAGE_SIZE_ANY flag set\n"); +#else + TRACE("Large Pages requested, but not supported in this PAL configuration\n"); +#endif + } + +#ifdef __APPLE__ + if ((fAllocationType & MEM_RESERVE_EXECUTABLE) && IsRunningOnMojaveHardenedRuntime()) + { + mmapFlags |= MAP_JIT; + } +#endif + + LPVOID pRetVal = mmap((LPVOID) StartBoundary, + MemSize, + PROT_NONE, + mmapFlags, + -1 /* fd */, + 0 /* offset */); + + if (pRetVal == MAP_FAILED) + { + ERROR( "Failed due to insufficient memory.\n" ); + + pthrCurrent->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return nullptr; + } + + /* Check to see if the region is what we asked for. */ + if (lpAddress != nullptr && StartBoundary != (UINT_PTR)pRetVal) + { + ERROR("We did not get the region we asked for from mmap!\n"); + pthrCurrent->SetLastError(ERROR_INVALID_ADDRESS); + munmap(pRetVal, MemSize); + return nullptr; + } + +#if MMAP_ANON_IGNORES_PROTECTION + if (mprotect(pRetVal, MemSize, PROT_NONE) != 0) + { + ERROR("mprotect failed to protect the region!\n"); + pthrCurrent->SetLastError(ERROR_INVALID_ADDRESS); + munmap(pRetVal, MemSize); + return nullptr; + } +#endif // MMAP_ANON_IGNORES_PROTECTION + +#ifdef MADV_DONTDUMP + // Do not include reserved memory in coredump. + madvise(pRetVal, MemSize, MADV_DONTDUMP); +#endif + + return pRetVal; +} + +/****** + * + * VIRTUALCommitMemory() - Helper function that actually commits the memory. + * + * NOTE: I call SetLastError in here, because many different error states + * exists, and that would be very complicated to work around. + * + */ +static LPVOID +VIRTUALCommitMemory( + IN CPalThread *pthrCurrent, /* Currently executing thread */ + IN LPVOID lpAddress, /* Region to reserve or commit */ + IN SIZE_T dwSize, /* Size of Region */ + IN DWORD flAllocationType, /* Type of allocation */ + IN DWORD flProtect) /* Type of access protection */ +{ + UINT_PTR StartBoundary = 0; + SIZE_T MemSize = 0; + PCMI pInformation = 0; + LPVOID pRetVal = NULL; + BOOL IsLocallyReserved = FALSE; + SIZE_T totalPages; + INT allocationType, curAllocationType; + INT protectionState, curProtectionState; + SIZE_T initialRunStart; + SIZE_T runStart; + SIZE_T runLength; + SIZE_T index; + INT nProtect; + INT vProtect; + + if ( lpAddress ) + { + StartBoundary = (UINT_PTR) ALIGN_DOWN(lpAddress, GetVirtualPageSize()); + MemSize = ALIGN_UP((UINT_PTR)lpAddress + dwSize, GetVirtualPageSize()) - StartBoundary; + } + else + { + MemSize = ALIGN_UP(dwSize, GetVirtualPageSize()); + } + + /* See if we have already reserved this memory. */ + pInformation = VIRTUALFindRegionInformation( StartBoundary ); + + if ( !pInformation ) + { + /* According to the new MSDN docs, if MEM_COMMIT is specified, + and the memory is not reserved, you reserve and then commit. + */ + LPVOID pReservedMemory = + VIRTUALReserveMemory( pthrCurrent, lpAddress, dwSize, + flAllocationType, flProtect ); + + TRACE( "Reserve and commit the memory!\n " ); + + if ( pReservedMemory ) + { + /* Re-align the addresses and try again to find the memory. */ + StartBoundary = (UINT_PTR) ALIGN_DOWN(pReservedMemory, GetVirtualPageSize()); + MemSize = ALIGN_UP((UINT_PTR)pReservedMemory + dwSize, GetVirtualPageSize()) - StartBoundary; + + pInformation = VIRTUALFindRegionInformation( StartBoundary ); + + if ( !pInformation ) + { + ASSERT( "Unable to locate the region information.\n" ); + pthrCurrent->SetLastError( ERROR_INTERNAL_ERROR ); + pRetVal = NULL; + goto done; + } + IsLocallyReserved = TRUE; + } + else + { + ERROR( "Unable to reserve the memory.\n" ); + /* Don't set last error here, it will already be set. */ + pRetVal = NULL; + goto done; + } + } + + TRACE( "Committing the memory now..\n"); + + // Pages that aren't already committed need to be committed. Pages that + // are committed don't need to be committed, but they might need to have + // their permissions changed. + // To get this right, we find runs of pages with similar states and + // permissions. If a run is not committed, we commit it and then set + // its permissions. If a run is committed but has different permissions + // from what we're trying to set, we set its permissions. Finally, + // if a run is already committed and has the right permissions, + // we don't need to do anything to it. + + totalPages = MemSize / GetVirtualPageSize(); + runStart = (StartBoundary - pInformation->startBoundary) / + GetVirtualPageSize(); // Page index + initialRunStart = runStart; + allocationType = VIRTUALGetAllocationType(runStart, pInformation); + protectionState = pInformation->pProtectionState[runStart]; + curAllocationType = allocationType; + curProtectionState = protectionState; + runLength = 1; + nProtect = W32toUnixAccessControl(flProtect); + vProtect = VIRTUALConvertWinFlags(flProtect); + + if (totalPages > pInformation->memSize / GetVirtualPageSize() - runStart) + { + ERROR("Trying to commit beyond the end of the region!\n"); + goto error; + } + + while(runStart < initialRunStart + totalPages) + { + // Find the next run of pages + for(index = runStart + 1; index < initialRunStart + totalPages; + index++) + { + curAllocationType = VIRTUALGetAllocationType(index, pInformation); + curProtectionState = pInformation->pProtectionState[index]; + if (curAllocationType != allocationType || + curProtectionState != protectionState) + { + break; + } + runLength++; + } + + StartBoundary = pInformation->startBoundary + runStart * GetVirtualPageSize(); + pRetVal = (void *)StartBoundary; + MemSize = runLength * GetVirtualPageSize(); + + if (allocationType != MEM_COMMIT) + { + // Commit the pages + if (mprotect((void *) StartBoundary, MemSize, PROT_WRITE | PROT_READ) != 0) + { + ERROR("mprotect() failed! Error(%d)=%s\n", errno, strerror(errno)); + goto error; + } + +#ifdef MADV_DODUMP + // Include committed memory in coredump. + madvise((void *) StartBoundary, MemSize, MADV_DODUMP); +#endif + + VIRTUALSetAllocState(MEM_COMMIT, runStart, runLength, pInformation); + + if (nProtect == (PROT_WRITE | PROT_READ)) + { + // Handle this case specially so we don't bother + // mprotect'ing the region. + memset(pInformation->pProtectionState + runStart, + vProtect, runLength); + } + + protectionState = VIRTUAL_READWRITE; + } + + if (protectionState != vProtect) + { + // Change permissions. + if (mprotect((void *) StartBoundary, MemSize, nProtect) != -1) + { + memset(pInformation->pProtectionState + runStart, + vProtect, runLength); + } + else + { + ERROR("mprotect() failed! Error(%d)=%s\n", + errno, strerror(errno)); + goto error; + } + } + + runStart = index; + runLength = 1; + allocationType = curAllocationType; + protectionState = curProtectionState; + } + + pRetVal = (void *) (pInformation->startBoundary + initialRunStart * GetVirtualPageSize()); + goto done; + +error: + if ( flAllocationType & MEM_RESERVE || IsLocallyReserved ) + { + munmap( pRetVal, MemSize ); + if ( VIRTUALReleaseMemory( pInformation ) == FALSE ) + { + ASSERT( "Unable to remove the PCMI entry from the list.\n" ); + pthrCurrent->SetLastError( ERROR_INTERNAL_ERROR ); + pRetVal = NULL; + goto done; + } + } + + pInformation = NULL; + pRetVal = NULL; +done: + + LogVaOperation( + VirtualMemoryLogging::VirtualOperation::Commit, + lpAddress, + dwSize, + flAllocationType, + flProtect, + pRetVal, + pRetVal != NULL); + + return pRetVal; +} + +/*++ +Function: + PAL_VirtualReserveFromExecutableMemoryAllocatorWithinRange + + This function attempts to allocate the requested amount of memory in the specified address range, from the executable memory + allocator. If unable to do so, the function returns nullptr and does not set the last error. + + lpBeginAddress - Inclusive beginning of range + lpEndAddress - Exclusive end of range + dwSize - Number of bytes to allocate +--*/ +LPVOID +PALAPI +PAL_VirtualReserveFromExecutableMemoryAllocatorWithinRange( + IN LPCVOID lpBeginAddress, + IN LPCVOID lpEndAddress, + IN SIZE_T dwSize) +{ +#ifdef HOST_64BIT + PERF_ENTRY(PAL_VirtualReserveFromExecutableMemoryAllocatorWithinRange); + ENTRY( + "PAL_VirtualReserveFromExecutableMemoryAllocatorWithinRange(lpBeginAddress = %p, lpEndAddress = %p, dwSize = %Iu)\n", + lpBeginAddress, + lpEndAddress, + dwSize); + + _ASSERTE(lpBeginAddress <= lpEndAddress); + + // Alignment to a 64 KB granularity should not be necessary (alignment to page size should be sufficient), but see + // ExecutableMemoryAllocator::AllocateMemory() for the reason why it is done + SIZE_T reservationSize = ALIGN_UP(dwSize, VIRTUAL_64KB); + + CPalThread *currentThread = InternalGetCurrentThread(); + InternalEnterCriticalSection(currentThread, &virtual_critsec); + + void *address = g_executableMemoryAllocator.AllocateMemoryWithinRange(lpBeginAddress, lpEndAddress, reservationSize); + if (address != nullptr) + { + _ASSERTE(IS_ALIGNED(address, GetVirtualPageSize())); + if (!VIRTUALStoreAllocationInfo((UINT_PTR)address, reservationSize, MEM_RESERVE | MEM_RESERVE_EXECUTABLE, PAGE_NOACCESS)) + { + ASSERT("Unable to store the structure in the list.\n"); + munmap(address, reservationSize); + address = nullptr; + } + } + + LogVaOperation( + VirtualMemoryLogging::VirtualOperation::ReserveFromExecutableMemoryAllocatorWithinRange, + nullptr, + dwSize, + MEM_RESERVE | MEM_RESERVE_EXECUTABLE, + PAGE_NOACCESS, + address, + TRUE); + + InternalLeaveCriticalSection(currentThread, &virtual_critsec); + + LOGEXIT("PAL_VirtualReserveFromExecutableMemoryAllocatorWithinRange returning %p\n", address); + PERF_EXIT(PAL_VirtualReserveFromExecutableMemoryAllocatorWithinRange); + return address; +#else // !HOST_64BIT + return nullptr; +#endif // HOST_64BIT +} + +/*++ +Function: + VirtualAlloc + +Note: + MEM_TOP_DOWN, MEM_PHYSICAL, MEM_WRITE_WATCH are not supported. + Unsupported flags are ignored. + + Page size on i386 is set to 4k. + +See MSDN doc. +--*/ +LPVOID +PALAPI +VirtualAlloc( + IN LPVOID lpAddress, /* Region to reserve or commit */ + IN SIZE_T dwSize, /* Size of Region */ + IN DWORD flAllocationType, /* Type of allocation */ + IN DWORD flProtect) /* Type of access protection */ +{ + LPVOID pRetVal = NULL; + CPalThread *pthrCurrent; + + PERF_ENTRY(VirtualAlloc); + ENTRY("VirtualAlloc(lpAddress=%p, dwSize=%u, flAllocationType=%#x, \ + flProtect=%#x)\n", lpAddress, dwSize, flAllocationType, flProtect); + + pthrCurrent = InternalGetCurrentThread(); + + if ( ( flAllocationType & MEM_WRITE_WATCH ) != 0 ) + { + pthrCurrent->SetLastError( ERROR_INVALID_PARAMETER ); + goto done; + } + + /* Test for un-supported flags. */ + if ( ( flAllocationType & ~( MEM_COMMIT | MEM_RESERVE | MEM_RESET | MEM_TOP_DOWN | MEM_RESERVE_EXECUTABLE | MEM_LARGE_PAGES ) ) != 0 ) + { + ASSERT( "flAllocationType can be one, or any combination of MEM_COMMIT, \ + MEM_RESERVE, MEM_TOP_DOWN, MEM_RESERVE_EXECUTABLE, or MEM_LARGE_PAGES.\n" ); + pthrCurrent->SetLastError( ERROR_INVALID_PARAMETER ); + goto done; + } + if ( VIRTUALContainsInvalidProtectionFlags( flProtect ) ) + { + ASSERT( "flProtect can be one of PAGE_READONLY, PAGE_READWRITE, or \ + PAGE_EXECUTE_READWRITE || PAGE_NOACCESS. \n" ); + + pthrCurrent->SetLastError( ERROR_INVALID_PARAMETER ); + goto done; + } + if ( flAllocationType & MEM_TOP_DOWN ) + { + WARN( "Ignoring the allocation flag MEM_TOP_DOWN.\n" ); + } + + LogVaOperation( + VirtualMemoryLogging::VirtualOperation::Allocate, + lpAddress, + dwSize, + flAllocationType, + flProtect, + NULL, + TRUE); + + if ( flAllocationType & MEM_RESET ) + { + if ( flAllocationType != MEM_RESET ) + { + ASSERT( "MEM_RESET cannot be used with any other allocation flags in flAllocationType.\n" ); + pthrCurrent->SetLastError( ERROR_INVALID_PARAMETER ); + goto done; + } + + InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + pRetVal = VIRTUALResetMemory( pthrCurrent, lpAddress, dwSize ); + InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + + if ( !pRetVal ) + { + /* Error messages are already displayed, just leave. */ + goto done; + } + } + + if ( flAllocationType & MEM_RESERVE ) + { + InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + pRetVal = VIRTUALReserveMemory( pthrCurrent, lpAddress, dwSize, flAllocationType, flProtect ); + InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + + if ( !pRetVal ) + { + /* Error messages are already displayed, just leave. */ + goto done; + } + } + + if ( flAllocationType & MEM_COMMIT ) + { + InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + if ( pRetVal != NULL ) + { + /* We are reserving and committing. */ + pRetVal = VIRTUALCommitMemory( pthrCurrent, pRetVal, dwSize, + flAllocationType, flProtect ); + } + else + { + /* Just a commit. */ + pRetVal = VIRTUALCommitMemory( pthrCurrent, lpAddress, dwSize, + flAllocationType, flProtect ); + } + InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + } + +done: +#if defined _DEBUG + VIRTUALDisplayList(); +#endif + LOGEXIT("VirtualAlloc returning %p\n ", pRetVal ); + PERF_EXIT(VirtualAlloc); + return pRetVal; +} + +/*++ +Function: + VirtualFree + +See MSDN doc. +--*/ +BOOL +PALAPI +VirtualFree( + IN LPVOID lpAddress, /* Address of region. */ + IN SIZE_T dwSize, /* Size of region. */ + IN DWORD dwFreeType ) /* Operation type. */ +{ + BOOL bRetVal = TRUE; + CPalThread *pthrCurrent; + + PERF_ENTRY(VirtualFree); + ENTRY("VirtualFree(lpAddress=%p, dwSize=%u, dwFreeType=%#x)\n", + lpAddress, dwSize, dwFreeType); + + pthrCurrent = InternalGetCurrentThread(); + InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + + /* Sanity Checks. */ + if ( !lpAddress ) + { + ERROR( "lpAddress cannot be NULL. You must specify the base address of\ + regions to be de-committed. \n" ); + pthrCurrent->SetLastError( ERROR_INVALID_ADDRESS ); + bRetVal = FALSE; + goto VirtualFreeExit; + } + + if ( !( dwFreeType & MEM_RELEASE ) && !(dwFreeType & MEM_DECOMMIT ) ) + { + ERROR( "dwFreeType must contain one of the following: \ + MEM_RELEASE or MEM_DECOMMIT\n" ); + pthrCurrent->SetLastError( ERROR_INVALID_PARAMETER ); + bRetVal = FALSE; + goto VirtualFreeExit; + } + /* You cannot release and decommit in one call.*/ + if ( dwFreeType & MEM_RELEASE && dwFreeType & MEM_DECOMMIT ) + { + ERROR( "MEM_RELEASE cannot be combined with MEM_DECOMMIT.\n" ); + bRetVal = FALSE; + goto VirtualFreeExit; + } + + if ( dwFreeType & MEM_DECOMMIT ) + { + UINT_PTR StartBoundary = 0; + SIZE_T MemSize = 0; + + if ( dwSize == 0 ) + { + ERROR( "dwSize cannot be 0. \n" ); + pthrCurrent->SetLastError( ERROR_INVALID_PARAMETER ); + bRetVal = FALSE; + goto VirtualFreeExit; + } + /* + * A two byte range straddling 2 pages caues both pages to be either + * released or decommitted. So round the dwSize up to the next page + * boundary and round the lpAddress down to the next page boundary. + */ + StartBoundary = (UINT_PTR) ALIGN_DOWN(lpAddress, GetVirtualPageSize()); + MemSize = ALIGN_UP((UINT_PTR)lpAddress + dwSize, GetVirtualPageSize()) - StartBoundary; + + PCMI pUnCommittedMem; + pUnCommittedMem = VIRTUALFindRegionInformation( StartBoundary ); + if (!pUnCommittedMem) + { + ASSERT( "Unable to locate the region information.\n" ); + pthrCurrent->SetLastError( ERROR_INTERNAL_ERROR ); + bRetVal = FALSE; + goto VirtualFreeExit; + } + + TRACE( "Un-committing the following page(s) %d to %d.\n", + StartBoundary, MemSize ); + + // Explicitly calling mmap instead of mprotect here makes it + // that much more clear to the operating system that we no + // longer need these pages. + if ( mmap( (LPVOID)StartBoundary, MemSize, PROT_NONE, + MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0 ) != MAP_FAILED ) + { +#if (MMAP_ANON_IGNORES_PROTECTION) + if (mprotect((LPVOID) StartBoundary, MemSize, PROT_NONE) != 0) + { + ASSERT("mprotect failed to protect the region!\n"); + pthrCurrent->SetLastError(ERROR_INTERNAL_ERROR); + munmap((LPVOID) StartBoundary, MemSize); + bRetVal = FALSE; + goto VirtualFreeExit; + } +#endif // MMAP_ANON_IGNORES_PROTECTION + +#ifdef MADV_DONTDUMP + // Do not include freed memory in coredump. + madvise((LPVOID) StartBoundary, MemSize, MADV_DONTDUMP); +#endif + + SIZE_T index = 0; + SIZE_T nNumOfPagesToChange = 0; + + /* We can now commit this memory by calling VirtualAlloc().*/ + index = (StartBoundary - pUnCommittedMem->startBoundary) / GetVirtualPageSize(); + + nNumOfPagesToChange = MemSize / GetVirtualPageSize(); + VIRTUALSetAllocState( MEM_RESERVE, index, + nNumOfPagesToChange, pUnCommittedMem ); + + goto VirtualFreeExit; + } + else + { + ASSERT( "mmap() returned an abnormal value.\n" ); + bRetVal = FALSE; + pthrCurrent->SetLastError( ERROR_INTERNAL_ERROR ); + goto VirtualFreeExit; + } + } + + if ( dwFreeType & MEM_RELEASE ) + { + PCMI pMemoryToBeReleased = + VIRTUALFindRegionInformation( (UINT_PTR)lpAddress ); + + if ( !pMemoryToBeReleased ) + { + ERROR( "lpAddress must be the base address returned by VirtualAlloc.\n" ); + pthrCurrent->SetLastError( ERROR_INVALID_ADDRESS ); + bRetVal = FALSE; + goto VirtualFreeExit; + } + if ( dwSize != 0 ) + { + ERROR( "dwSize must be 0 if you are releasing the memory.\n" ); + pthrCurrent->SetLastError( ERROR_INVALID_PARAMETER ); + bRetVal = FALSE; + goto VirtualFreeExit; + } + + TRACE( "Releasing the following memory %d to %d.\n", + pMemoryToBeReleased->startBoundary, pMemoryToBeReleased->memSize ); + + if ( munmap( (LPVOID)pMemoryToBeReleased->startBoundary, + pMemoryToBeReleased->memSize ) == 0 ) + { + if ( VIRTUALReleaseMemory( pMemoryToBeReleased ) == FALSE ) + { + ASSERT( "Unable to remove the PCMI entry from the list.\n" ); + pthrCurrent->SetLastError( ERROR_INTERNAL_ERROR ); + bRetVal = FALSE; + goto VirtualFreeExit; + } + pMemoryToBeReleased = NULL; + } + else + { + ASSERT( "Unable to unmap the memory, munmap() returned an abnormal value.\n" ); + pthrCurrent->SetLastError( ERROR_INTERNAL_ERROR ); + bRetVal = FALSE; + goto VirtualFreeExit; + } + } + +VirtualFreeExit: + + LogVaOperation( + (dwFreeType & MEM_DECOMMIT) ? VirtualMemoryLogging::VirtualOperation::Decommit + : VirtualMemoryLogging::VirtualOperation::Release, + lpAddress, + dwSize, + dwFreeType, + 0, + NULL, + bRetVal); + + InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + LOGEXIT( "VirtualFree returning %s.\n", bRetVal == TRUE ? "TRUE" : "FALSE" ); + PERF_EXIT(VirtualFree); + return bRetVal; +} + + +/*++ +Function: + VirtualProtect + +See MSDN doc. +--*/ +BOOL +PALAPI +VirtualProtect( + IN LPVOID lpAddress, + IN SIZE_T dwSize, + IN DWORD flNewProtect, + OUT PDWORD lpflOldProtect) +{ + BOOL bRetVal = FALSE; + PCMI pEntry = NULL; + SIZE_T MemSize = 0; + UINT_PTR StartBoundary = 0; + SIZE_T Index = 0; + SIZE_T NumberOfPagesToChange = 0; + SIZE_T OffSet = 0; + CPalThread * pthrCurrent; + + PERF_ENTRY(VirtualProtect); + ENTRY("VirtualProtect(lpAddress=%p, dwSize=%u, flNewProtect=%#x, " + "flOldProtect=%p)\n", + lpAddress, dwSize, flNewProtect, lpflOldProtect); + + pthrCurrent = InternalGetCurrentThread(); + InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + + StartBoundary = (UINT_PTR) ALIGN_DOWN(lpAddress, GetVirtualPageSize()); + MemSize = ALIGN_UP((UINT_PTR)lpAddress + dwSize, GetVirtualPageSize()) - StartBoundary; + + if ( VIRTUALContainsInvalidProtectionFlags( flNewProtect ) ) + { + ASSERT( "flProtect can be one of PAGE_NOACCESS, PAGE_READONLY, " + "PAGE_READWRITE, PAGE_EXECUTE, PAGE_EXECUTE_READ " + ", or PAGE_EXECUTE_READWRITE. \n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + goto ExitVirtualProtect; + } + + if ( !lpflOldProtect) + { + ERROR( "lpflOldProtect was invalid.\n" ); + SetLastError( ERROR_NOACCESS ); + goto ExitVirtualProtect; + } + + pEntry = VIRTUALFindRegionInformation( StartBoundary ); + if ( NULL != pEntry ) + { + /* See if the pages are committed. */ + Index = OffSet = StartBoundary - pEntry->startBoundary == 0 ? + 0 : ( StartBoundary - pEntry->startBoundary ) / GetVirtualPageSize(); + NumberOfPagesToChange = MemSize / GetVirtualPageSize(); + + TRACE( "Number of pages to check %d, starting page %d \n", NumberOfPagesToChange, Index ); + + for ( ; Index < NumberOfPagesToChange; Index++ ) + { + if ( !VIRTUALIsPageCommitted( Index, pEntry ) ) + { + ERROR( "You can only change the protection attributes" + " on committed memory.\n" ) + SetLastError( ERROR_INVALID_ADDRESS ); + goto ExitVirtualProtect; + } + } + } + + if ( 0 == mprotect( (LPVOID)StartBoundary, MemSize, + W32toUnixAccessControl( flNewProtect ) ) ) + { + /* Reset the access protection. */ + TRACE( "Number of pages to change %d, starting page %d \n", + NumberOfPagesToChange, OffSet ); + /* + * Set the old protection flags. We only use the first flag, so + * if there were several regions with each with different flags only the + * first region's protection flag will be returned. + */ + if ( pEntry ) + { + *lpflOldProtect = + VIRTUALConvertVirtualFlags( pEntry->pProtectionState[ OffSet ] ); + + memset( pEntry->pProtectionState + OffSet, + VIRTUALConvertWinFlags( flNewProtect ), + NumberOfPagesToChange ); + } + else + { + *lpflOldProtect = PAGE_EXECUTE_READWRITE; + } + +#ifdef MADV_DONTDUMP + // Include or exclude memory from coredump based on the protection. + int advise = flNewProtect == PAGE_NOACCESS ? MADV_DONTDUMP : MADV_DODUMP; + madvise((LPVOID)StartBoundary, MemSize, advise); +#endif + + bRetVal = TRUE; + } + else + { + ERROR( "%s\n", strerror( errno ) ); + if ( errno == EINVAL ) + { + SetLastError( ERROR_INVALID_ADDRESS ); + } + else if ( errno == EACCES ) + { + SetLastError( ERROR_INVALID_ACCESS ); + } + } +ExitVirtualProtect: + InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + +#if defined _DEBUG + VIRTUALDisplayList(); +#endif + LOGEXIT( "VirtualProtect returning %s.\n", bRetVal == TRUE ? "TRUE" : "FALSE" ); + PERF_EXIT(VirtualProtect); + return bRetVal; +} + +#if HAVE_VM_ALLOCATE +//--------------------------------------------------------------------------------------- +// +// Convert a vm_prot_t flag on the Mach kernel to the corresponding memory protection on Windows. +// +// Arguments: +// protection - Mach protection to be converted +// +// Return Value: +// Return the corresponding memory protection on Windows (e.g. PAGE_READ_WRITE, etc.) +// + +static DWORD VirtualMapMachProtectToWinProtect(vm_prot_t protection) +{ + if (protection & VM_PROT_READ) + { + if (protection & VM_PROT_WRITE) + { + if (protection & VM_PROT_EXECUTE) + { + return PAGE_EXECUTE_READWRITE; + } + else + { + return PAGE_READWRITE; + } + } + else + { + if (protection & VM_PROT_EXECUTE) + { + return PAGE_EXECUTE_READ; + } + else + { + return PAGE_READONLY; + } + } + } + else + { + if (protection & VM_PROT_WRITE) + { + if (protection & VM_PROT_EXECUTE) + { + return PAGE_EXECUTE_WRITECOPY; + } + else + { + return PAGE_WRITECOPY; + } + } + else + { + if (protection & VM_PROT_EXECUTE) + { + return PAGE_EXECUTE; + } + else + { + return PAGE_NOACCESS; + } + } + } +} + +static void VM_ALLOCATE_VirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer) +{ + kern_return_t MachRet; + vm_address_t vm_address; + vm_size_t vm_size; + vm_region_flavor_t vm_flavor; + mach_msg_type_number_t infoCnt; + mach_port_t object_name; +#ifdef HOST_64BIT + vm_region_basic_info_data_64_t info; + infoCnt = VM_REGION_BASIC_INFO_COUNT_64; + vm_flavor = VM_REGION_BASIC_INFO_64; +#else + vm_region_basic_info_data_t info; + infoCnt = VM_REGION_BASIC_INFO_COUNT; + vm_flavor = VM_REGION_BASIC_INFO; +#endif + + vm_address = (vm_address_t)lpAddress; +#ifdef HOST_64BIT + MachRet = vm_region_64( +#else + MachRet = vm_region( +#endif + mach_task_self(), + &vm_address, + &vm_size, + vm_flavor, + (vm_region_info_t)&info, + &infoCnt, + &object_name); + if (MachRet != KERN_SUCCESS) { + return; + } + + if (vm_address > (vm_address_t)lpAddress) { + /* lpAddress was pointing into a free region */ + lpBuffer->State = MEM_FREE; + return; + } + + lpBuffer->BaseAddress = (PVOID)vm_address; + + // We don't actually have any information on the Mach kernel which maps to AllocationProtect. + lpBuffer->AllocationProtect = VM_PROT_NONE; + + lpBuffer->RegionSize = (SIZE_T)vm_size; + + if (info.reserved) + { + lpBuffer->State = MEM_RESERVE; + } + else + { + lpBuffer->State = MEM_COMMIT; + } + + lpBuffer->Protect = VirtualMapMachProtectToWinProtect(info.protection); + + /* Note that if a mapped region and a private region are adjacent, this + will return MEM_PRIVATE but the region size will span + both the mapped and private regions. */ + if (!info.shared) + { + lpBuffer->Type = MEM_PRIVATE; + } + else + { + // What should this be? It's either MEM_MAPPED or MEM_IMAGE, but without an image list, + // we can't determine which one it is. + lpBuffer->Type = MEM_MAPPED; + } +} +#endif // HAVE_VM_ALLOCATE + +/*++ +Function: + VirtualQuery + +See MSDN doc. +--*/ +SIZE_T +PALAPI +VirtualQuery( + IN LPCVOID lpAddress, + OUT PMEMORY_BASIC_INFORMATION lpBuffer, + IN SIZE_T dwLength) +{ + PCMI pEntry = NULL; + UINT_PTR StartBoundary = 0; + CPalThread * pthrCurrent; + + PERF_ENTRY(VirtualQuery); + ENTRY("VirtualQuery(lpAddress=%p, lpBuffer=%p, dwLength=%u)\n", + lpAddress, lpBuffer, dwLength); + + pthrCurrent = InternalGetCurrentThread(); + InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + + if ( !lpBuffer) + { + ERROR( "lpBuffer has to be a valid pointer.\n" ); + pthrCurrent->SetLastError( ERROR_NOACCESS ); + goto ExitVirtualQuery; + } + if ( dwLength < sizeof( *lpBuffer ) ) + { + ERROR( "dwLength cannot be smaller then the size of *lpBuffer.\n" ); + pthrCurrent->SetLastError( ERROR_BAD_LENGTH ); + goto ExitVirtualQuery; + } + + StartBoundary = ALIGN_DOWN((SIZE_T)lpAddress, GetVirtualPageSize()); + +#if MMAP_IGNORES_HINT + // Make sure we have memory to map before we try to query it. + VIRTUALGetBackingFile(pthrCurrent); + + // If we're suballocating, claim that any memory that isn't in our + // suballocated block is already allocated. This keeps callers from + // using these results to try to allocate those blocks and failing. + if (StartBoundary < (UINT_PTR) gBackingBaseAddress || + StartBoundary >= (UINT_PTR) gBackingBaseAddress + BACKING_FILE_SIZE) + { + if (StartBoundary < (UINT_PTR) gBackingBaseAddress) + { + lpBuffer->RegionSize = (UINT_PTR) gBackingBaseAddress - StartBoundary; + } + else + { + lpBuffer->RegionSize = -StartBoundary; + } + lpBuffer->BaseAddress = (void *) StartBoundary; + lpBuffer->State = MEM_COMMIT; + lpBuffer->Type = MEM_MAPPED; + lpBuffer->AllocationProtect = 0; + lpBuffer->Protect = 0; + goto ExitVirtualQuery; + } +#endif // MMAP_IGNORES_HINT + + /* Find the entry. */ + pEntry = VIRTUALFindRegionInformation( StartBoundary ); + + if ( !pEntry ) + { + /* Can't find a match, or no list present. */ + /* Next, looking for this region in file maps */ + if (!MAPGetRegionInfo((LPVOID)StartBoundary, lpBuffer)) + { + // When all else fails, call vm_region() if it's available. + + // Initialize the State to be MEM_FREE, in which case AllocationBase, AllocationProtect, + // Protect, and Type are all undefined. + lpBuffer->BaseAddress = (LPVOID)StartBoundary; + lpBuffer->RegionSize = 0; + lpBuffer->State = MEM_FREE; +#if HAVE_VM_ALLOCATE + VM_ALLOCATE_VirtualQuery(lpAddress, lpBuffer); +#endif + } + } + else + { + /* Starting page. */ + SIZE_T Index = ( StartBoundary - pEntry->startBoundary ) / GetVirtualPageSize(); + + /* Attributes to check for. */ + BYTE AccessProtection = pEntry->pProtectionState[ Index ]; + INT AllocationType = VIRTUALGetAllocationType( Index, pEntry ); + SIZE_T RegionSize = 0; + + TRACE( "Index = %d, Number of Pages = %d. \n", + Index, pEntry->memSize / GetVirtualPageSize() ); + + while ( Index < pEntry->memSize / GetVirtualPageSize() && + VIRTUALGetAllocationType( Index, pEntry ) == AllocationType && + pEntry->pProtectionState[ Index ] == AccessProtection ) + { + RegionSize += GetVirtualPageSize(); + Index++; + } + + TRACE( "RegionSize = %d.\n", RegionSize ); + + /* Fill the structure.*/ + lpBuffer->AllocationProtect = pEntry->accessProtection; + lpBuffer->BaseAddress = (LPVOID)StartBoundary; + + lpBuffer->Protect = AllocationType == MEM_COMMIT ? + VIRTUALConvertVirtualFlags( AccessProtection ) : 0; + + lpBuffer->RegionSize = RegionSize; + lpBuffer->State = + ( AllocationType == MEM_COMMIT ? MEM_COMMIT : MEM_RESERVE ); + WARN( "Ignoring lpBuffer->Type. \n" ); + } + +ExitVirtualQuery: + + InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + + LOGEXIT( "VirtualQuery returning %d.\n", sizeof( *lpBuffer ) ); + PERF_EXIT(VirtualQuery); + return sizeof( *lpBuffer ); +} + +size_t GetVirtualPageSize() +{ + _ASSERTE(s_virtualPageSize); + return s_virtualPageSize; +} + +/*++ +Function : + ReserveMemoryFromExecutableAllocator + + This function is used to reserve a region of virual memory (not commited) + that is located close to the coreclr library. The memory comes from the virtual + address range that is managed by ExecutableMemoryAllocator. +--*/ +void* ReserveMemoryFromExecutableAllocator(CPalThread* pThread, SIZE_T allocationSize) +{ +#ifdef HOST_64BIT + InternalEnterCriticalSection(pThread, &virtual_critsec); + void* mem = g_executableMemoryAllocator.AllocateMemory(allocationSize); + InternalLeaveCriticalSection(pThread, &virtual_critsec); + + return mem; +#else // !HOST_64BIT + return nullptr; +#endif // HOST_64BIT +} + +/*++ +Function: + ExecutableMemoryAllocator::Initialize() + + This function initializes the allocator. It should be called early during process startup + (when process address space is pretty much empty) in order to have a chance to reserve + sufficient amount of memory that is close to the coreclr library. + +--*/ +void ExecutableMemoryAllocator::Initialize() +{ + m_startAddress = NULL; + m_nextFreeAddress = NULL; + m_totalSizeOfReservedMemory = 0; + m_remainingReservedMemory = 0; + + // Enable the executable memory allocator on 64-bit platforms only + // because 32-bit platforms have limited amount of virtual address space. +#ifdef HOST_64BIT + TryReserveInitialMemory(); +#endif // HOST_64BIT + +} + +/*++ +Function: + ExecutableMemoryAllocator::TryReserveInitialMemory() + + This function is called during PAL initialization. It opportunistically tries to reserve + a large chunk of virtual memory that can be later used to store JIT'ed code.\ + +--*/ +void ExecutableMemoryAllocator::TryReserveInitialMemory() +{ + CPalThread* pthrCurrent = InternalGetCurrentThread(); + int32_t sizeOfAllocation = MaxExecutableMemorySizeNearCoreClr; + int32_t preferredStartAddressIncrement; + UINT_PTR preferredStartAddress; + UINT_PTR coreclrLoadAddress; + const int32_t MemoryProbingIncrement = 128 * 1024 * 1024; + + // Try to find and reserve an available region of virtual memory that is located + // within 2GB range (defined by the MaxExecutableMemorySizeNearCoreClr constant) from the + // location of the coreclr library. + // Potentially, as a possible future improvement, we can get precise information + // about available memory ranges by parsing data from '/proc/self/maps'. + // But since this code is called early during process startup, the user address space + // is pretty much empty so the simple algorithm that is implemented below is sufficient + // for this purpose. + + // First of all, we need to determine the current address of libcoreclr. Please note that depending on + // the OS implementation, the library is usually loaded either at the end or at the start of the user + // address space. If the library is loaded at low addresses then try to reserve memory above libcoreclr + // (thus avoiding reserving memory below 4GB; besides some operating systems do not allow that). + // If libcoreclr is loaded at high addresses then try to reserve memory below its location. + coreclrLoadAddress = (UINT_PTR)PAL_GetSymbolModuleBase((void*)VirtualAlloc); + if ((coreclrLoadAddress < 0xFFFFFFFF) || ((coreclrLoadAddress - MaxExecutableMemorySizeNearCoreClr) < 0xFFFFFFFF)) + { + // Try to allocate above the location of libcoreclr + preferredStartAddress = coreclrLoadAddress + CoreClrLibrarySize; + preferredStartAddressIncrement = MemoryProbingIncrement; + } + else + { + // Try to allocate below the location of libcoreclr + preferredStartAddress = coreclrLoadAddress - MaxExecutableMemorySizeNearCoreClr; + preferredStartAddressIncrement = 0; + } + + // Do actual memory reservation. + do + { + m_startAddress = ReserveVirtualMemory(pthrCurrent, (void*)preferredStartAddress, sizeOfAllocation, MEM_RESERVE_EXECUTABLE); + if (m_startAddress != nullptr) + { + break; + } + + // Try to allocate a smaller region + sizeOfAllocation -= MemoryProbingIncrement; + preferredStartAddress += preferredStartAddressIncrement; + + } while (sizeOfAllocation >= MemoryProbingIncrement); + + if (m_startAddress == nullptr) + { + // We were not able to reserve any memory near libcoreclr. Try to reserve approximately 2 GB of address space somewhere + // anyway: + // - This sets aside address space that can be used for executable code, such that jumps/calls between such code may + // continue to use short relative addresses instead of long absolute addresses that would currently require jump + // stubs. + // - The inability to allocate memory in a specific range for jump stubs is an unrecoverable problem. This reservation + // would mitigate such issues that can become prevalent depending on which security features are enabled and to what + // extent, such as in particular, PaX's RANDMMAP: + // - https://en.wikibooks.org/wiki/Grsecurity/Appendix/Grsecurity_and_PaX_Configuration_Options + // - Jump stubs for executable code residing in this region can request memory from this allocator + // - Native images can be loaded into this address space, including any jump stubs that are required for its helper + // table. This satisfies the vast majority of practical cases where the total amount of loaded native image memory + // does not exceed approximately 2 GB. + // - The code heap allocator for the JIT can allocate from this address space. Beyond this reservation, one can use + // the COMPlus_CodeHeapReserveForJumpStubs environment variable to reserve space for jump stubs. + sizeOfAllocation = MaxExecutableMemorySize; + m_startAddress = ReserveVirtualMemory(pthrCurrent, nullptr, sizeOfAllocation, MEM_RESERVE_EXECUTABLE); + if (m_startAddress == nullptr) + { + return; + } + } + + // Memory has been successfully reserved. + m_totalSizeOfReservedMemory = sizeOfAllocation; + + // Randomize the location at which we start allocating from the reserved memory range. Alignment to a 64 KB granularity + // should not be necessary, but see AllocateMemory() for the reason why it is done. + int32_t randomOffset = GenerateRandomStartOffset(); + m_nextFreeAddress = ALIGN_UP((void*)(((UINT_PTR)m_startAddress) + randomOffset), VIRTUAL_64KB); + _ASSERTE(sizeOfAllocation >= (int32_t)((UINT_PTR)m_nextFreeAddress - (UINT_PTR)m_startAddress)); + m_remainingReservedMemory = + ALIGN_DOWN(sizeOfAllocation - ((UINT_PTR)m_nextFreeAddress - (UINT_PTR)m_startAddress), VIRTUAL_64KB); +} + +/*++ +Function: + ExecutableMemoryAllocator::AllocateMemory + + This function attempts to allocate the requested amount of memory from its reserved virtual + address space. The function will return null if the allocation request cannot + be satisfied by the memory that is currently available in the allocator. + + Note: This function MUST be called with the virtual_critsec lock held. + +--*/ +void* ExecutableMemoryAllocator::AllocateMemory(SIZE_T allocationSize) +{ +#ifdef HOST_64BIT + void* allocatedMemory = nullptr; + + // Alignment to a 64 KB granularity should not be necessary (alignment to page size should be sufficient), but + // VIRTUALReserveMemory() aligns down the specified address to a 64 KB granularity, and as long as that is necessary, the + // reservation size here must be aligned to a 64 KB granularity to guarantee that all returned addresses are also aligned to + // a 64 KB granularity. Otherwise, attempting to reserve memory starting from an unaligned address returned by this function + // would fail in VIRTUALReserveMemory. + _ASSERTE(IS_ALIGNED(allocationSize, VIRTUAL_64KB)); + + // The code below assumes that the caller owns the virtual_critsec lock. + // So the calculations are not done in thread-safe manner. + if ((allocationSize > 0) && (allocationSize <= (SIZE_T)m_remainingReservedMemory)) + { + allocatedMemory = m_nextFreeAddress; + m_nextFreeAddress = (void*)(((UINT_PTR)m_nextFreeAddress) + allocationSize); + m_remainingReservedMemory -= allocationSize; + } + + return allocatedMemory; +#else // !HOST_64BIT + return nullptr; +#endif // HOST_64BIT +} + +/*++ +Function: + AllocateMemory + + This function attempts to allocate the requested amount of memory from its reserved virtual + address space, if memory is available within the specified range. The function will return + null if the allocation request cannot satisfied by the memory that is currently available in + the allocator. + + Note: This function MUST be called with the virtual_critsec lock held. +--*/ +void *ExecutableMemoryAllocator::AllocateMemoryWithinRange(const void *beginAddress, const void *endAddress, SIZE_T allocationSize) +{ +#ifdef HOST_64BIT + _ASSERTE(beginAddress <= endAddress); + + // Alignment to a 64 KB granularity should not be necessary (alignment to page size should be sufficient), but see + // AllocateMemory() for the reason why it is necessary + _ASSERTE(IS_ALIGNED(allocationSize, VIRTUAL_64KB)); + + // The code below assumes that the caller owns the virtual_critsec lock. + // So the calculations are not done in thread-safe manner. + + if (allocationSize == 0 || allocationSize > (SIZE_T)m_remainingReservedMemory) + { + return nullptr; + } + + void *address = m_nextFreeAddress; + if (address < beginAddress) + { + return nullptr; + } + + void *nextFreeAddress = (void *)((UINT_PTR)address + allocationSize); + if (nextFreeAddress > endAddress) + { + return nullptr; + } + + m_nextFreeAddress = nextFreeAddress; + m_remainingReservedMemory -= allocationSize; + return address; +#else // !HOST_64BIT + return nullptr; +#endif // HOST_64BIT +} + +/*++ +Function: + ExecutableMemoryAllocator::GenerateRandomStartOffset() + + This function returns a random offset (in multiples of the virtual page size) + at which the allocator should start allocating memory from its reserved memory range. + +--*/ +int32_t ExecutableMemoryAllocator::GenerateRandomStartOffset() +{ + int32_t pageCount; + const int32_t MaxStartPageOffset = 64; + + // This code is similar to what coreclr runtime does on Windows. + // It generates a random number of pages to skip between 0...MaxStartPageOffset. + srandom(time(NULL)); + pageCount = (int32_t)(MaxStartPageOffset * (int64_t)random() / RAND_MAX); + + return pageCount * GetVirtualPageSize(); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/memory/local.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/memory/local.cpp new file mode 100644 index 0000000..e41f7a4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/memory/local.cpp @@ -0,0 +1,140 @@ +// 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: + + local.c + +Abstract: + + Implementation of local memory management functions. + +Revision History: + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" + + +SET_DEFAULT_DEBUG_CHANNEL(MEM); + + +/*++ +Function: + LocalAlloc + +See MSDN doc. +--*/ +HLOCAL +PALAPI +LocalAlloc( + IN UINT uFlags, + IN SIZE_T uBytes) +{ + LPVOID lpRetVal = NULL; + PERF_ENTRY(LocalAlloc); + ENTRY("LocalAlloc (uFlags=%#x, uBytes=%u)\n", uFlags, uBytes); + + if ((uFlags & ~LMEM_ZEROINIT) != 0) + { + ASSERT("Invalid parameter AllocFlags=0x%x\n", uFlags); + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + + lpRetVal = PAL_malloc(uBytes); + + if (lpRetVal == NULL) + { + ERROR("Not enough memory\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + + if ((uFlags & LMEM_ZEROINIT) != 0) + { + memset(lpRetVal, 0, uBytes); + } + +done: + LOGEXIT( "LocalAlloc returning %p.\n", lpRetVal ); + PERF_EXIT(LocalAlloc); + return (HLOCAL) lpRetVal; +} + +/*++ +Function: +LocalReAlloc + +See MSDN doc. +--*/ +HLOCAL +PALAPI +LocalReAlloc( + IN HLOCAL hMem, + IN SIZE_T uBytes, + IN UINT uFlags) +{ + LPVOID lpRetVal = NULL; + PERF_ENTRY(LocalReAlloc); + ENTRY("LocalReAlloc (hMem=%p, uBytes=%u, uFlags=%#x)\n", hMem, uBytes, uFlags); + + if (uFlags != LMEM_MOVEABLE) + { + // Currently valid iff uFlags is LMEM_MOVEABLE + ASSERT("Invalid parameter uFlags=0x%x\n", uFlags); + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + + if (uBytes == 0) + { + // PAL's realloc behaves like free for a requested size of zero bytes. Force a nonzero size to get a valid pointer. + uBytes = 1; + } + + lpRetVal = PAL_realloc(hMem, uBytes); + + if (lpRetVal == NULL) + { + ERROR("Not enough memory\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + +done: + LOGEXIT("LocalReAlloc returning %p.\n", lpRetVal); + PERF_EXIT(LocalReAlloc); + return (HLOCAL)lpRetVal; +} + +/*++ +Function: + LocalFree + +See MSDN doc. +--*/ +HLOCAL +PALAPI +LocalFree( + IN HLOCAL hMem) +{ + BOOL bRetVal = FALSE; + PERF_ENTRY(LocalFree); + ENTRY("LocalFree (hmem=%p)\n", hMem); + + free(hMem); + bRetVal = TRUE; + + LOGEXIT( "LocalFree returning %p.\n", bRetVal == TRUE ? (HLOCAL)NULL : hMem ); + PERF_EXIT(LocalFree); + return bRetVal == TRUE ? (HLOCAL)NULL : hMem; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/cgroup.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/cgroup.cpp new file mode 100644 index 0000000..42a5dd2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/cgroup.cpp @@ -0,0 +1,686 @@ +// 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: + + cgroup.cpp + +Abstract: + Read memory and cpu limits for the current process +--*/ + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(MISC); +#include "pal/palinternal.h" +#include +#include +#include "pal/virtual.h" +#include "pal/cgroup.h" +#include +#if defined(__APPLE__) || defined(__FreeBSD__) +#include +#include +#else +#include +#endif + +#define CGROUP2_SUPER_MAGIC 0x63677270 +#define TMPFS_MAGIC 0x01021994 + +#define BASE_TEN 10 + +#define PROC_MOUNTINFO_FILENAME "/proc/self/mountinfo" +#define PROC_CGROUP_FILENAME "/proc/self/cgroup" +#define PROC_STATM_FILENAME "/proc/self/statm" +#define CGROUP1_MEMORY_LIMIT_FILENAME "/memory.limit_in_bytes" +#define CGROUP2_MEMORY_LIMIT_FILENAME "/memory.max" +#define CGROUP1_MEMORY_USAGE_FILENAME "/memory.usage_in_bytes" +#define CGROUP2_MEMORY_USAGE_FILENAME "/memory.current" +#define CGROUP1_CFS_QUOTA_FILENAME "/cpu.cfs_quota_us" +#define CGROUP1_CFS_PERIOD_FILENAME "/cpu.cfs_period_us" +#define CGROUP2_CPU_MAX_FILENAME "/cpu.max" + +class CGroup +{ + // the cgroup version number or 0 to indicate cgroups are not found or not enabled + static int s_cgroup_version; + + static char *s_memory_cgroup_path; + static char *s_cpu_cgroup_path; +public: + static void Initialize() + { + s_cgroup_version = FindCGroupVersion(); + s_memory_cgroup_path = FindCGroupPath(&IsCGroup1MemorySubsystem); + s_cpu_cgroup_path = FindCGroupPath(&IsCGroup1CpuSubsystem); + } + + static void Cleanup() + { + PAL_free(s_memory_cgroup_path); + PAL_free(s_cpu_cgroup_path); + } + + static bool GetPhysicalMemoryLimit(uint64_t *val) + { + if (s_cgroup_version == 0) + return false; + else if (s_cgroup_version == 1) + return GetCGroupMemoryLimit(val, CGROUP1_MEMORY_LIMIT_FILENAME); + else if (s_cgroup_version == 2) + return GetCGroupMemoryLimit(val, CGROUP2_MEMORY_LIMIT_FILENAME); + else + { + _ASSERTE(!"Unknown cgroup version."); + return false; + } + } + + static bool GetPhysicalMemoryUsage(size_t *val) + { + if (s_cgroup_version == 0) + return false; + else if (s_cgroup_version == 1) + return GetCGroupMemoryUsage(val, CGROUP1_MEMORY_USAGE_FILENAME); + else if (s_cgroup_version == 2) + return GetCGroupMemoryUsage(val, CGROUP2_MEMORY_USAGE_FILENAME); + else + { + _ASSERTE(!"Unknown cgroup version."); + return false; + } + } + + static bool GetCpuLimit(UINT *val) + { + if (s_cgroup_version == 0) + return false; + else if (s_cgroup_version == 1) + return GetCGroup1CpuLimit(val); + else if (s_cgroup_version == 2) + return GetCGroup2CpuLimit(val); + else + { + _ASSERTE(!"Unknown cgroup version."); + return false; + } + } + +private: + static int FindCGroupVersion() + { + // It is possible to have both cgroup v1 and v2 enabled on a system. + // Most non-bleeding-edge Linux distributions fall in this group. We + // look at the file system type of /sys/fs/cgroup to determine which + // one is the default. For more details, see: + // https://systemd.io/CGROUP_DELEGATION/#three-different-tree-setups- + // We dont care about the difference between the "legacy" and "hybrid" + // modes because both of those involve cgroup v1 controllers managing + // resources. + +#if !HAVE_NON_LEGACY_STATFS + return 0; +#else + struct statfs stats; + int result = statfs("/sys/fs/cgroup", &stats); + + if (result != 0) + return 0; + + switch (stats.f_type) + { + case TMPFS_MAGIC: return 1; + case CGROUP2_SUPER_MAGIC: return 2; + default: + _ASSERTE(!"Unexpected file system type for /sys/fs/cgroup"); + return 0; + } +#endif + } + + static bool IsCGroup1MemorySubsystem(const char *strTok){ + return strcmp("memory", strTok) == 0; + } + + static bool IsCGroup1CpuSubsystem(const char *strTok){ + return strcmp("cpu", strTok) == 0; + } + + static char* FindCGroupPath(bool (*is_subsystem)(const char *)){ + char *cgroup_path = nullptr; + char *hierarchy_mount = nullptr; + char *hierarchy_root = nullptr; + char *cgroup_path_relative_to_mount = nullptr; + size_t len; + size_t common_path_prefix_len; + + FindHierarchyMount(is_subsystem, &hierarchy_mount, &hierarchy_root); + if (hierarchy_mount == nullptr || hierarchy_root == nullptr) + goto done; + + cgroup_path_relative_to_mount = FindCGroupPathForSubsystem(is_subsystem); + if (cgroup_path_relative_to_mount == nullptr) + goto done; + + len = strlen(hierarchy_mount); + len += strlen(cgroup_path_relative_to_mount); + cgroup_path = (char*)PAL_malloc(len+1); + if (cgroup_path == nullptr) + goto done; + + strcpy_s(cgroup_path, len+1, hierarchy_mount); + // For a host cgroup, we need to append the relative path. + // The root and cgroup path can share a common prefix of the path that should not be appended. + // Example 1 (docker): + // hierarchy_mount: /sys/fs/cgroup/cpu + // hierarchy_root: /docker/87ee2de57e51bc75175a4d2e81b71d162811b179d549d6601ed70b58cad83578 + // cgroup_path_relative_to_mount: /docker/87ee2de57e51bc75175a4d2e81b71d162811b179d549d6601ed70b58cad83578/my_named_cgroup + // append do the cgroup_path: /my_named_cgroup + // final cgroup_path: /sys/fs/cgroup/cpu/my_named_cgroup + // + // Example 2 (out of docker) + // hierarchy_mount: /sys/fs/cgroup/cpu + // hierarchy_root: / + // cgroup_path_relative_to_mount: /my_named_cgroup + // append do the cgroup_path: /my_named_cgroup + // final cgroup_path: /sys/fs/cgroup/cpu/my_named_cgroup + common_path_prefix_len = strlen(hierarchy_root); + if ((common_path_prefix_len == 1) || strncmp(hierarchy_root, cgroup_path_relative_to_mount, common_path_prefix_len) != 0) + { + common_path_prefix_len = 0; + } + + _ASSERTE((cgroup_path_relative_to_mount[common_path_prefix_len] == '/') || (cgroup_path_relative_to_mount[common_path_prefix_len] == '\0')); + + strcat_s(cgroup_path, len+1, cgroup_path_relative_to_mount + common_path_prefix_len); + + done: + PAL_free(hierarchy_mount); + PAL_free(hierarchy_root); + PAL_free(cgroup_path_relative_to_mount); + return cgroup_path; + } + + static void FindHierarchyMount(bool (*is_subsystem)(const char *), char** pmountpath, char** pmountroot) + { + char *line = nullptr; + size_t lineLen = 0, maxLineLen = 0; + char *filesystemType = nullptr; + char *options = nullptr; + char *mountpath = nullptr; + char *mountroot = nullptr; + + FILE *mountinfofile = fopen(PROC_MOUNTINFO_FILENAME, "r"); + if (mountinfofile == nullptr) + goto done; + + while (getline(&line, &lineLen, mountinfofile) != -1) + { + if (filesystemType == nullptr || lineLen > maxLineLen) + { + PAL_free(filesystemType); + PAL_free(options); + filesystemType = (char*)PAL_malloc(lineLen+1); + if (filesystemType == nullptr) + goto done; + options = (char*)PAL_malloc(lineLen+1); + if (options == nullptr) + goto done; + maxLineLen = lineLen; + } + char* separatorChar = strstr(line, " - ");; + + // See man page of proc to get format for /proc/self/mountinfo file + int sscanfRet = sscanf_s(separatorChar, + " - %s %*s %s", + filesystemType, lineLen+1, + options, lineLen+1); + if (sscanfRet != 2) + { + _ASSERTE(!"Failed to parse mount info file contents with sscanf_s."); + goto done; + } + + if (strncmp(filesystemType, "cgroup", 6) == 0) + { + char* context = nullptr; + char* strTok = strtok_s(options, ",", &context); + while (strTok != nullptr) + { + if (is_subsystem(strTok)) + { + mountpath = (char*)PAL_malloc(lineLen+1); + if (mountpath == nullptr) + goto done; + mountroot = (char*)PAL_malloc(lineLen+1); + if (mountroot == nullptr) + goto done; + + sscanfRet = sscanf_s(line, + "%*s %*s %*s %s %s ", + mountroot, lineLen+1, + mountpath, lineLen+1); + if (sscanfRet != 2) + _ASSERTE(!"Failed to parse mount info file contents with sscanf_s."); + + // assign the output arguments and clear the locals so we don't free them. + *pmountpath = mountpath; + *pmountroot = mountroot; + mountpath = mountroot = nullptr; + goto done; + } + strTok = strtok_s(nullptr, ",", &context); + } + } + } + done: + PAL_free(mountpath); + PAL_free(mountroot); + PAL_free(filesystemType); + PAL_free(options); + free(line); + if (mountinfofile) + fclose(mountinfofile); + } + + static char* FindCGroupPathForSubsystem(bool (*is_subsystem)(const char *)) + { + char *line = nullptr; + size_t lineLen = 0; + size_t maxLineLen = 0; + char *subsystem_list = nullptr; + char *cgroup_path = nullptr; + bool result = false; + + FILE *cgroupfile = fopen(PROC_CGROUP_FILENAME, "r"); + if (cgroupfile == nullptr) + goto done; + + while (!result && getline(&line, &lineLen, cgroupfile) != -1) + { + if (subsystem_list == nullptr || lineLen > maxLineLen) + { + PAL_free(subsystem_list); + PAL_free(cgroup_path); + subsystem_list = (char*)PAL_malloc(lineLen+1); + if (subsystem_list == nullptr) + goto done; + cgroup_path = (char*)PAL_malloc(lineLen+1); + if (cgroup_path == nullptr) + goto done; + maxLineLen = lineLen; + } + + if (s_cgroup_version == 1) + { + // See man page of proc to get format for /proc/self/cgroup file + int sscanfRet = sscanf_s(line, + "%*[^:]:%[^:]:%s", + subsystem_list, lineLen+1, + cgroup_path, lineLen+1); + if (sscanfRet != 2) + { + _ASSERTE(!"Failed to parse cgroup info file contents with sscanf_s."); + goto done; + } + + char* context = nullptr; + char* strTok = strtok_s(subsystem_list, ",", &context); + while (strTok != nullptr) + { + if (is_subsystem(strTok)) + { + result = true; + break; + } + strTok = strtok_s(nullptr, ",", &context); + } + } + else if (s_cgroup_version == 2) + { + // See https://www.kernel.org/doc/Documentation/cgroup-v2.txt + // Look for a "0::/some/path" + int sscanfRet = sscanf_s(line, + "0::%s", lineLen+1, + cgroup_path, lineLen+1); + if (sscanfRet == 1) + { + result = true; + } + } + else + { + _ASSERTE(!"Unknown cgroup version in mountinfo."); + goto done; + } + } + done: + PAL_free(subsystem_list); + if (!result) + { + PAL_free(cgroup_path); + cgroup_path = nullptr; + } + free(line); + if (cgroupfile) + fclose(cgroupfile); + return cgroup_path; + } + + static bool GetCGroupMemoryLimit(uint64_t *val, const char *filename) + { + if (s_memory_cgroup_path == nullptr) + return false; + + char* mem_limit_filename = nullptr; + if (asprintf(&mem_limit_filename, "%s%s", s_memory_cgroup_path, filename) < 0) + return false; + + bool result = ReadMemoryValueFromFile(mem_limit_filename, val); + free(mem_limit_filename); + return result; + } + + static bool GetCGroupMemoryUsage(size_t *val, const char *filename) + { + if (s_memory_cgroup_path == nullptr) + return false; + + char* mem_usage_filename = nullptr; + if (asprintf(&mem_usage_filename, "%s%s", s_memory_cgroup_path, filename) < 0) + return false; + + uint64_t temp = 0; + bool result = ReadMemoryValueFromFile(mem_usage_filename, &temp); + if (result) + { + if (temp > std::numeric_limits::max()) + { + *val = std::numeric_limits::max(); + } + else + { + *val = (size_t)temp; + } + } + + return result; + } + + static bool ReadMemoryValueFromFile(const char* filename, uint64_t* val) + { + return ::ReadMemoryValueFromFile(filename, val); + } + + static bool GetCGroup1CpuLimit(UINT *val) + { + long long quota; + long long period; + + quota = ReadCpuCGroupValue(CGROUP1_CFS_QUOTA_FILENAME); + if (quota <= 0) + return false; + + period = ReadCpuCGroupValue(CGROUP1_CFS_PERIOD_FILENAME); + if (period <= 0) + return false; + + ComputeCpuLimit(period, quota, val); + + return true; + } + + static bool GetCGroup2CpuLimit(UINT *val) + { + char *filename = nullptr; + FILE *file = nullptr; + char *endptr = nullptr; + char *max_quota_string = nullptr; + char *period_string = nullptr; + char *context = nullptr; + char *line = nullptr; + size_t lineLen = 0; + + long long quota = 0; + long long period = 0; + + bool result = false; + + if (s_cpu_cgroup_path == nullptr) + return false; + + if (asprintf(&filename, "%s%s", s_cpu_cgroup_path, CGROUP2_CPU_MAX_FILENAME) < 0) + return false; + + file = fopen(filename, "r"); + if (file == nullptr) + goto done; + + if (getline(&line, &lineLen, file) == -1) + goto done; + + // The expected format is: + // $MAX $PERIOD + // Where "$MAX" may be the string literal "max" + + max_quota_string = strtok_s(line, " ", &context); + if (max_quota_string == nullptr) + { + _ASSERTE(!"Unable to parse " CGROUP2_CPU_MAX_FILENAME " file contents."); + goto done; + } + period_string = strtok_s(nullptr, " ", &context); + if (period_string == nullptr) + { + _ASSERTE(!"Unable to parse " CGROUP2_CPU_MAX_FILENAME " file contents."); + goto done; + } + + // "max" means no cpu limit + if (strcmp("max", max_quota_string) == 0) + goto done; + + errno = 0; + quota = strtoll(max_quota_string, &endptr, BASE_TEN); + if (max_quota_string == endptr || errno != 0) + goto done; + + period = strtoll(period_string, &endptr, BASE_TEN); + if (period_string == endptr || errno != 0) + goto done; + + ComputeCpuLimit(period, quota, val); + result = true; + + done: + if (file) + fclose(file); + free(filename); + free(line); + + return result; + } + + static void ComputeCpuLimit(long long period, long long quota, uint32_t *val) + { + // Cannot have less than 1 CPU + if (quota <= period) + { + *val = 1; + return; + } + + // Calculate cpu count based on quota and round it up + double cpu_count = (double) quota / period + 0.999999999; + *val = (cpu_count < UINT32_MAX) ? (uint32_t)cpu_count : UINT32_MAX; + } + + static long long ReadCpuCGroupValue(const char* subsystemFilename){ + char *filename = nullptr; + bool result = false; + long long val; + + if (s_cpu_cgroup_path == nullptr) + return -1; + + if (asprintf(&filename, "%s%s", s_cpu_cgroup_path, subsystemFilename) < 0) + return -1; + + result = ReadLongLongValueFromFile(filename, &val); + free(filename); + if (!result) + return -1; + + return val; + } + + static bool ReadLongLongValueFromFile(const char* filename, long long* val) + { + bool result = false; + char *line = nullptr; + size_t lineLen = 0; + char *endptr = nullptr; + + if (val == nullptr) + return false; + + FILE* file = fopen(filename, "r"); + if (file == nullptr) + goto done; + + if (getline(&line, &lineLen, file) == -1) + goto done; + + errno = 0; + *val = strtoll(line, &endptr, BASE_TEN); + if (line == endptr || errno != 0) + goto done; + + result = true; + done: + if (file) + fclose(file); + free(line); + return result; + } +}; + +int CGroup::s_cgroup_version = 0; +char *CGroup::s_memory_cgroup_path = nullptr; +char *CGroup::s_cpu_cgroup_path = nullptr; + +void InitializeCGroup() +{ + CGroup::Initialize(); +} + +void CleanupCGroup() +{ + CGroup::Cleanup(); +} + +size_t +PALAPI +PAL_GetRestrictedPhysicalMemoryLimit() +{ + uint64_t physical_memory_limit_64 = 0; + size_t physical_memory_limit = 0; + + if (!CGroup::GetPhysicalMemoryLimit(&physical_memory_limit_64)) + return 0; + + // If there's no memory limit specified on the container this + // actually returns 0x7FFFFFFFFFFFF000 (2^63-1 rounded down to + // 4k which is a common page size). So we know we are not + // running in a memory restricted environment. + if (physical_memory_limit_64 > 0x7FFFFFFF00000000) + { + return 0; + } + + if (physical_memory_limit_64 > std::numeric_limits::max()) + { + // It is observed in practice when the memory is unrestricted, Linux control + // group returns a physical limit that is bigger than the address space + physical_memory_limit = std::numeric_limits::max(); + } + else + { + physical_memory_limit = (size_t)physical_memory_limit_64; + } + + struct rlimit curr_rlimit; + size_t rlimit_soft_limit = (size_t)RLIM_INFINITY; + if (getrlimit(RLIMIT_AS, &curr_rlimit) == 0) + { + rlimit_soft_limit = curr_rlimit.rlim_cur; + } + physical_memory_limit = std::min(physical_memory_limit, rlimit_soft_limit); + + // Ensure that limit is not greater than real memory size + long pages = sysconf(_SC_PHYS_PAGES); + if (pages != -1) + { + long pageSize = sysconf(_SC_PAGE_SIZE); + if (pageSize != -1) + { + physical_memory_limit = std::min(physical_memory_limit, + (size_t)(pages * pageSize)); + } + } + + if(physical_memory_limit == SIZE_T_MAX) + physical_memory_limit = 0; + return physical_memory_limit; +} + +BOOL +PALAPI +PAL_GetPhysicalMemoryUsed(size_t* val) +{ + BOOL result = false; + size_t linelen; + char* line = nullptr; + + if (val == nullptr) + return FALSE; + + // Linux uses cgroup usage to trigger oom kills. + if (CGroup::GetPhysicalMemoryUsage(val)) + return TRUE; + + // process resident set size. + FILE* file = fopen(PROC_STATM_FILENAME, "r"); + if (file != nullptr && getline(&line, &linelen, file) != -1) + { + char* context = nullptr; + char* strTok = strtok_s(line, " ", &context); + strTok = strtok_s(nullptr, " ", &context); + + errno = 0; + *val = strtoull(strTok, nullptr, 0); + if(errno == 0) + { + *val = *val * GetVirtualPageSize(); + result = true; + } + } + + if (file) + fclose(file); + free(line); + return result; +} + +BOOL +PALAPI +PAL_GetCpuLimit(UINT* val) +{ + if (val == nullptr) + return FALSE; + + return CGroup::GetCpuLimit(val); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/dbgmsg.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/dbgmsg.cpp new file mode 100644 index 0000000..609eea1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/dbgmsg.cpp @@ -0,0 +1,862 @@ +// 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: + + misc/dbgmsg.cpp + +Abstract: + Implementation of Debug Message utilies. Relay channel information, + output functions, etc. + + + +--*/ + +/* PAL headers */ + +#include "pal/thread.hpp" +#include "pal/malloc.hpp" +#include "pal/file.hpp" + +#include "config.h" +#include "pal/dbgmsg.h" +#include "pal/cruntime.h" +#include "pal/critsect.h" +#include "pal/file.h" +#include "pal/environ.h" + +/* standard headers */ + +#include +#include +#include +#include /* for pthread_self */ +#include +#include +#include + +/* needs to be included after "palinternal.h" to avoid name + collision for va_start and va_end */ +#include + +using namespace CorUnix; + +/* append mode file I/O is safer */ +#define _PAL_APPEND_DBG_OUTPUT_ + +static const char FOPEN_FLAGS[] = "at"; + +/* number of ENTRY nesting levels to indicate with a '.' */ +#define MAX_NESTING 50 + +/* size of output buffer (arbitrary) */ +#define DBG_BUFFER_SIZE 20000 + +/* global and static variables */ + +LPCWSTR W16_NULLSTRING = (LPCWSTR) "N\0U\0L\0L\0\0"; + +DWORD dbg_channel_flags[DCI_LAST]; +BOOL g_Dbg_asserts_enabled; + +/* we must use stdio functions directly rather that rely on PAL functions for + output, because those functions do tracing and we need to avoid recursion */ +FILE *output_file = NULL; + +/* master switch for debug channel enablement, to be modified by debugger */ +Volatile dbg_master_switch = TRUE; + + +static const char *dbg_channel_names[]= +{ + "PAL", + "LOADER", + "HANDLE", + "SHMEM", + "PROCESS", + "THREAD", + "EXCEPT", + "CRT", + "UNICODE", + "ARCH", + "SYNC", + "FILE", + "VIRTUAL", + "MEM", + "SOCKET", + "DEBUG", + "LOCALE", + "MISC", + "MUTEX", + "CRITSEC", + "POLL", + "CRYPT", + "SHFOLDER" + , "SXS" + , "DCI_NUMA" +}; + +// Verify the number of elements in dbg_channel_names +static_assert_no_msg(_countof(dbg_channel_names) == DCI_LAST); + +static const char *dbg_level_names[]= +{ + "ENTRY", + "TRACE", + "WARN", + "ERROR", + "ASSERT", + "EXIT" +}; + +static const char ENV_FILE[]="PAL_API_TRACING"; +static const char ENV_CHANNELS[]="PAL_DBG_CHANNELS"; +static const char ENV_ASSERTS[]="PAL_DISABLE_ASSERTS"; +static const char ENV_ENTRY_LEVELS[]="PAL_API_LEVELS"; + +/* per-thread storage for ENTRY tracing level */ +static pthread_key_t entry_level_key; + +/* entry level limitation */ +static int max_entry_level; + +/* character to use for ENTRY indentation */ +static const char INDENT_CHAR = '.'; + +static BOOL DBG_get_indent(DBG_LEVEL_ID level, const char *format, + char *indent_string); + +static CRITICAL_SECTION fprintf_crit_section; + +/* Function definitions */ + +/*++ +Function : + DBG_init_channels + + Parse environment variables PAL_DBG_CHANNELS and PAL_API_TRACING for debug + channel settings; initialize static variables. + + (no parameters, no return value) +--*/ +BOOL DBG_init_channels(void) +{ + INT i; + LPSTR env_string; + LPSTR env_workstring; + LPSTR env_pcache; + LPSTR entry_ptr; + LPSTR level_ptr; + CHAR plus_or_minus; + DWORD flag_mask = 0; + int ret; + + /* output only asserts by default [only affects no-vararg-support case; if + we have varargs, these flags aren't even checked for ASSERTs] */ + for(i=0;i DBG_BUFFER_SIZE) + { + output_size = DBG_BUFFER_SIZE; + } + } + else + { + output_size = 0; + } + + { + va_list args; + va_start(args, format); + INT result = _vsnprintf_s(buffer+output_size, DBG_BUFFER_SIZE-output_size, _TRUNCATE, + format, args); + va_end(args); + if( result < 0 ) + { + // if we didn't get data from _vsnprintf_s, print an error and exit + if ( output_size == 0 || buffer[output_size] == '\0' ) + { + fprintf(stderr, "ERROR : DBG_printf: vsnprintf_s failed errno:%d (%s)\n", errno, strerror(errno)); + return 1; + } + else if (output_size < DBG_BUFFER_SIZE) + { + fprintf(stderr, "ERROR : DBG_printf: message truncated, vsnprintf_s failed errno:%d (%s)\n", errno, strerror(errno)); + // do not return, print what we have + } + } + else + { + output_size+=result; + } + } + + if( output_size >= DBG_BUFFER_SIZE ) + { + fprintf(stderr, "ERROR : DBG_printf: message truncated"); + } + + /* Use a Critical section before calling printf code to + avoid holding a libc lock while another thread is calling + SuspendThread on this one. */ + + InternalEnterCriticalSection(NULL, &fprintf_crit_section); + fprintf( output_file, "%s%s", indent, buffer ); + InternalLeaveCriticalSection(NULL, &fprintf_crit_section); + + /* flush the output to file */ + if ( fflush(output_file) != 0 ) + { + fprintf(stderr, "ERROR : fflush() failed errno:%d (%s)\n", + errno, strerror(errno)); + } + + // Some systems support displaying a GUI dialog. We attempt this only for asserts. + if ( level == DLI_ASSERT ) + PAL_DisplayDialog("PAL ASSERT", buffer); + + return 1; +} + +/*++ +Function : + DBG_get_indent + + generate an indentation string to be used for message output + +Parameters : + DBG_LEVEL_ID level : level of message (DLI_ENTRY, etc) + const char *format : printf format string of message + char *indent_string : destination for indentation string + +Return value : + TRUE if output can proceed, FALSE otherwise + +Notes: +As a side-effect, this function updates the ENTRY nesting level for the current +thread : it decrements it if 'format' contains the string 'return', increments +it otherwise (but only if 'level' is DLI_ENTRY). The function will return +FALSE if the current nesting level is beyond our treshold (max_nesting_level); +it always returns TRUE for other message levels +--*/ +static BOOL DBG_get_indent(DBG_LEVEL_ID level, const char *format, + char *indent_string) +{ + int ret; + + /* determine whether to output an ENTRY line */ + if(DLI_ENTRY == level||DLI_EXIT == level) + { + if(0 != max_entry_level) + { + INT_PTR nesting; + + /* Determine if this is an entry or an + exit */ + if(DLI_EXIT == level) + { + nesting = (INT_PTR) pthread_getspecific(entry_level_key); + /* avoid going negative */ + if(nesting != 0) + { + nesting--; + if ((ret = pthread_setspecific(entry_level_key, + (LPVOID)nesting)) != 0) + { + fprintf(stderr, "ERROR : pthread_setspecific() failed " + "error:%d (%s)\n", ret, strerror(ret)); + } + } + } + else + { + nesting = (INT_PTR) pthread_getspecific(entry_level_key); + + if ((ret = pthread_setspecific(entry_level_key, + (LPVOID)(nesting+1))) != 0) + { + fprintf(stderr, "ERROR : pthread_setspecific() failed " + "error:%d (%s)\n", ret, strerror(ret)); + } + } + + /* see if we're past the level treshold */ + if(nesting >= max_entry_level) + { + return FALSE; + } + + /* generate indentation string */ + if(MAX_NESTING < nesting) + { + nesting = MAX_NESTING; + } + memset(indent_string,INDENT_CHAR ,nesting); + indent_string[nesting] = '\0'; + } + else + { + indent_string[0] = '\0'; + } + } + else + { + indent_string[0] = '\0'; + } + return TRUE; +} + +/*++ +Function : + DBG_change_entrylevel + + retrieve current ENTRY nesting level and [optionnally] modify it + +Parameters : + int new_level : value to which the nesting level must be set, or -1 + +Return value : + nesting level at the time the function was called + +Notes: +if new_level is -1, the nesting level will not be modified +--*/ +int DBG_change_entrylevel(int new_level) +{ + int old_level; + int ret; + + if(0 == max_entry_level) + { + return 0; + } + old_level = PtrToInt(pthread_getspecific(entry_level_key)); + if(-1 != new_level) + { + if ((ret = pthread_setspecific(entry_level_key,(LPVOID)(IntToPtr(new_level)))) != 0) + { + fprintf(stderr, "ERROR : pthread_setspecific() failed " + "error:%d (%s)\n", ret, strerror(ret)); + } + } + return old_level; +} + +#if _DEBUG && defined(__APPLE__) +/*++ +Function: + DBG_ShouldCheckStackAlignment + + Wires up stack alignment checks (debug builds only) +--*/ +static const char * PAL_CHECK_ALIGNMENT_MODE = "PAL_CheckAlignmentMode"; +enum CheckAlignmentMode +{ + // special value to indicate we've not initialized yet + CheckAlignment_Uninitialized = -1, + + CheckAlignment_Off = 0, + CheckAlignment_On = 1, + + CheckAlignment_Default = CheckAlignment_On +}; + +bool DBG_ShouldCheckStackAlignment() +{ + static CheckAlignmentMode caMode = CheckAlignment_Uninitialized; + + if (caMode == CheckAlignment_Uninitialized) + { + char* checkAlignmentSettings; + bool shouldFreeCheckAlignmentSettings = false; + if (palEnvironment == nullptr) + { + // This function might be called before the PAL environment is initialized. + // In this case, use the system getenv instead. + checkAlignmentSettings = ::getenv(PAL_CHECK_ALIGNMENT_MODE); + } + else + { + checkAlignmentSettings = EnvironGetenv(PAL_CHECK_ALIGNMENT_MODE); + shouldFreeCheckAlignmentSettings = true; + } + + caMode = checkAlignmentSettings ? + (CheckAlignmentMode)atoi(checkAlignmentSettings) : CheckAlignment_Default; + + if (checkAlignmentSettings && shouldFreeCheckAlignmentSettings) + { + free(checkAlignmentSettings); + } + } + + return caMode == CheckAlignment_On; +} +#endif // _DEBUG && __APPLE__ + +#ifdef __APPLE__ +#include "CoreFoundation/CFUserNotification.h" +#include "CoreFoundation/CFString.h" +#include "Security/AuthSession.h" + +static const char * PAL_DISPLAY_DIALOG = "PAL_DisplayDialog"; +enum DisplayDialogMode +{ + DisplayDialog_Uninitialized = -1, + + DisplayDialog_Suppress = 0, + DisplayDialog_Show = 1, + + DisplayDialog_Default = DisplayDialog_Suppress, +}; + +/*++ +Function : + PAL_DisplayDialog + + Display a simple modal dialog with an alert icon and a single OK button. Caller supplies the title of the + dialog and the main text. The dialog is displayed only if the PAL_DisplayDialog environment + variable is set to the value "1" and the session has access to the display. + +--*/ +void PAL_DisplayDialog(const char *szTitle, const char *szText) +{ + static DisplayDialogMode dispDialog = DisplayDialog_Uninitialized; + + if (dispDialog == DisplayDialog_Uninitialized) + { + char* displayDialog = EnvironGetenv(PAL_DISPLAY_DIALOG); + if (displayDialog) + { + int i = atoi(displayDialog); + free(displayDialog); + + switch (i) + { + case 0: + dispDialog = DisplayDialog_Suppress; + break; + + case 1: + dispDialog = DisplayDialog_Show; + break; + + default: + // Asserting here would just be re-entrant. :/ + dispDialog = DisplayDialog_Default; + break; + } + } + else + dispDialog = DisplayDialog_Default; + + if (dispDialog == DisplayDialog_Show) + { + // We may not be allowed to show. + OSStatus osstatus; + SecuritySessionId secSession; + SessionAttributeBits secSessionInfo; + + osstatus = SessionGetInfo(callerSecuritySession, &secSession, &secSessionInfo); + if (noErr != osstatus || (secSessionInfo & sessionHasGraphicAccess) == 0) + dispDialog = DisplayDialog_Suppress; + } + } + + if (dispDialog == DisplayDialog_Suppress) + return; + + CFStringRef cfsTitle = CFStringCreateWithCString(kCFAllocatorDefault, + szTitle, + kCFStringEncodingUTF8); + if (cfsTitle != NULL) + { + CFStringRef cfsText = CFStringCreateWithCString(kCFAllocatorDefault, + szText, + kCFStringEncodingUTF8); + if (cfsText != NULL) + { + CFOptionFlags response; + CFUserNotificationDisplayAlert(0, // Never time-out, wait for user to hit 'OK' + 0, // No flags + NULL, // Default icon + NULL, // Default sound + NULL, // No-localization support for text + cfsTitle, // Title for dialog + cfsText, // The actual alert text + NULL, // Default default button title ('OK') + NULL, // No alternate button + NULL, // No third button + &response); // User's response (discarded) + CFRelease(cfsText); + } + CFRelease(cfsTitle); + } +} + +/*++ +Function : + PAL_DisplayDialogFormatted + + As above but takes a printf-style format string and insertion values to form the main text. + +--*/ +void PAL_DisplayDialogFormatted(const char *szTitle, const char *szTextFormat, ...) +{ + va_list args; + + va_start(args, szTextFormat); + + const int cchBuffer = 4096; + char *szBuffer = (char*)alloca(cchBuffer); + _vsnprintf_s(szBuffer, cchBuffer, _TRUNCATE, szTextFormat, args); + PAL_DisplayDialog(szTitle, szBuffer); + + va_end(args); +} +#endif // __APPLE__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/environ.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/environ.cpp new file mode 100644 index 0000000..9fec8a3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/environ.cpp @@ -0,0 +1,1125 @@ +// 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: + + environ.cpp + +Abstract: + + Implementation of functions manipulating environment variables. + +Revision History: + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/critsect.h" +#include "pal/dbgmsg.h" +#include "pal/environ.h" +#include "pal/malloc.hpp" + +#if HAVE_CRT_EXTERNS_H +#include +#endif + +#include + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(MISC); + +char **palEnvironment = nullptr; +int palEnvironmentCount = 0; +int palEnvironmentCapacity = 0; + +CRITICAL_SECTION gcsEnvironment; + +/*++ +Function: + GetEnvironmentVariableA + +The GetEnvironmentVariable function retrieves the value of the +specified variable from the environment block of the calling +process. The value is in the form of a null-terminated string of +characters. + +Parameters + +lpName + [in] Pointer to a null-terminated string that specifies the environment variable. +lpBuffer + [out] Pointer to a buffer to receive the value of the specified environment variable. +nSize + [in] Specifies the size, in TCHARs, of the buffer pointed to by the lpBuffer parameter. + +Return Values + +If the function succeeds, the return value is the number of TCHARs +stored into the buffer pointed to by lpBuffer, not including the +terminating null character. + +If the specified environment variable name was not found in the +environment block for the current process, the return value is zero. + +If the buffer pointed to by lpBuffer is not large enough, the return +value is the buffer size, in TCHARs, required to hold the value string +and its terminating null character. + +--*/ +DWORD +PALAPI +GetEnvironmentVariableA( + IN LPCSTR lpName, + OUT LPSTR lpBuffer, + IN DWORD nSize) +{ + char *value; + DWORD dwRet = 0; + + PERF_ENTRY(GetEnvironmentVariableA); + ENTRY("GetEnvironmentVariableA(lpName=%p (%s), lpBuffer=%p, nSize=%u)\n", + lpName ? lpName : "NULL", + lpName ? lpName : "NULL", lpBuffer, nSize); + + CPalThread * pthrCurrent = InternalGetCurrentThread(); + + if (lpName == nullptr) + { + ERROR("lpName is null\n"); + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + + if (lpName[0] == 0) + { + TRACE("lpName is an empty string\n", lpName); + SetLastError(ERROR_ENVVAR_NOT_FOUND); + goto done; + } + + if (strchr(lpName, '=') != nullptr) + { + // GetEnvironmentVariable doesn't permit '=' in variable names. + value = nullptr; + } + else + { + // Enter the environment critical section so that we can safely get + // the environment variable value without EnvironGetenv making an + // intermediate copy. We will just copy the string to the output + // buffer anyway, so just stay in the critical section until then. + InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + + value = EnvironGetenv(lpName, /* copyValue */ FALSE); + + if (value != nullptr) + { + DWORD valueLength = strlen(value); + if (valueLength < nSize) + { + strcpy_s(lpBuffer, nSize, value); + dwRet = valueLength; + } + else + { + dwRet = valueLength + 1; + } + + SetLastError(ERROR_SUCCESS); + } + + InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); + } + + if (value == nullptr) + { + TRACE("%s is not found\n", lpName); + SetLastError(ERROR_ENVVAR_NOT_FOUND); + } + +done: + + LOGEXIT("GetEnvironmentVariableA returns DWORD 0x%x\n", dwRet); + PERF_EXIT(GetEnvironmentVariableA); + return dwRet; +} + +/*++ +Function: + GetEnvironmentVariableW + +See MSDN doc. +--*/ +DWORD +PALAPI +GetEnvironmentVariableW( + IN LPCWSTR lpName, + OUT LPWSTR lpBuffer, + IN DWORD nSize) +{ + CHAR *inBuff = nullptr; + CHAR *outBuff = nullptr; + INT inBuffSize; + DWORD size = 0; + + PERF_ENTRY(GetEnvironmentVariableW); + ENTRY("GetEnvironmentVariableW(lpName=%p (%S), lpBuffer=%p, nSize=%u)\n", + lpName ? lpName : W16_NULLSTRING, + lpName ? lpName : W16_NULLSTRING, lpBuffer, nSize); + + inBuffSize = WideCharToMultiByte(CP_ACP, 0, lpName, -1, + inBuff, 0, nullptr, nullptr); + if (0 == inBuffSize) + { + ERROR("lpName has to be a valid parameter\n"); + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + + inBuff = (CHAR *)PAL_malloc(inBuffSize); + if (inBuff == nullptr) + { + ERROR("malloc failed\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + + if (nSize) + { + outBuff = (CHAR *)PAL_malloc(nSize*2); + if (outBuff == nullptr) + { + ERROR("malloc failed\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + } + + if (0 == WideCharToMultiByte(CP_ACP, 0, lpName, -1, inBuff, + inBuffSize, nullptr, nullptr)) + { + ASSERT("WideCharToMultiByte failed!\n"); + SetLastError(ERROR_INTERNAL_ERROR); + goto done; + } + + size = GetEnvironmentVariableA(inBuff, outBuff, nSize); + if (size > nSize) + { + TRACE("Insufficient buffer\n"); + } + else if (size == 0) + { + // If size is 0, it either means GetEnvironmentVariableA failed, or that + // it succeeded and the value of the variable is empty. Check GetLastError + // to determine which. If the call failed, we won't touch the buffer. + if (GetLastError() == ERROR_SUCCESS) + { + *lpBuffer = '\0'; + } + } + else + { + size = MultiByteToWideChar(CP_ACP, 0, outBuff, -1, lpBuffer, nSize); + if (0 != size) + { + // -1 for the null. + size--; + } + else + { + ASSERT("MultiByteToWideChar failed!\n"); + SetLastError(ERROR_INTERNAL_ERROR); + size = 0; + *lpBuffer = '\0'; + } + } + +done: + PAL_free(outBuff); + PAL_free(inBuff); + + LOGEXIT("GetEnvironmentVariableW returns DWORD 0x%x\n", size); + PERF_EXIT(GetEnvironmentVariableW); + + return size; +} + +/*++ +Function: + SetEnvironmentVariableW + +The SetEnvironmentVariable function sets the value of an environment +variable for the current process. + +Parameters + +lpName + [in] Pointer to a null-terminated string that specifies the + environment variable whose value is being set. The operating + system creates the environment variable if it does not exist + and lpValue is not null. +lpValue + [in] Pointer to a null-terminated string containing the new + value of the specified environment variable. If this parameter + is null, the variable is deleted from the current process's + environment. + +Return Values + +If the function succeeds, the return value is nonzero. + +If the function fails, the return value is zero. To get extended error +information, call GetLastError. + +Remarks + +This function has no effect on the system environment variables or the +environment variables of other processes. + +--*/ +BOOL +PALAPI +SetEnvironmentVariableW( + IN LPCWSTR lpName, + IN LPCWSTR lpValue) +{ + PCHAR name = nullptr; + PCHAR value = nullptr; + INT nameSize = 0; + INT valueSize = 0; + BOOL bRet = FALSE; + + PERF_ENTRY(SetEnvironmentVariableW); + ENTRY("SetEnvironmentVariableW(lpName=%p (%S), lpValue=%p (%S))\n", + lpName?lpName:W16_NULLSTRING, + lpName?lpName:W16_NULLSTRING, lpValue?lpValue:W16_NULLSTRING, lpValue?lpValue:W16_NULLSTRING); + + if ((nameSize = WideCharToMultiByte(CP_ACP, 0, lpName, -1, name, 0, + nullptr, nullptr)) == 0) + { + ERROR("WideCharToMultiByte failed\n"); + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + + name = (PCHAR)PAL_malloc(sizeof(CHAR)* nameSize); + if (name == nullptr) + { + ERROR("malloc failed\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + + if (0 == WideCharToMultiByte(CP_ACP, 0, lpName, -1, + name, nameSize, nullptr, nullptr)) + { + ASSERT("WideCharToMultiByte returned 0\n"); + SetLastError(ERROR_INTERNAL_ERROR); + goto done; + } + + if (lpValue != nullptr) + { + if ((valueSize = WideCharToMultiByte(CP_ACP, 0, lpValue, -1, value, + 0, nullptr, nullptr)) == 0) + { + ERROR("WideCharToMultiByte failed\n"); + SetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + + value = (PCHAR)PAL_malloc(sizeof(CHAR)*valueSize); + + if (value == nullptr) + { + ERROR("malloc failed\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + + if (0 == WideCharToMultiByte(CP_ACP, 0, lpValue, -1, + value, valueSize, nullptr, nullptr)) + { + ASSERT("WideCharToMultiByte failed\n"); + SetLastError( ERROR_INTERNAL_ERROR ); + goto done; + } + } + + bRet = SetEnvironmentVariableA(name, value); +done: + PAL_free(value); + PAL_free(name); + + LOGEXIT("SetEnvironmentVariableW returning BOOL %d\n", bRet); + PERF_EXIT(SetEnvironmentVariableW); + return bRet; +} + +/*++ +Function: + GetEnvironmentStringsW + +The GetEnvironmentStrings function retrieves the environment block for +the current process. + +Parameters + +This function has no parameters. + +Return Values + +The return value is a pointer to an environment block for the current process. + +Remarks + +The GetEnvironmentStrings function returns a pointer to the +environment block of the calling process. This should be treated as a +read-only block; do not modify it directly. Instead, use the +GetEnvironmentVariable and SetEnvironmentVariable functions to +retrieve or change the environment variables within this block. When +the block is no longer needed, it should be freed by calling +FreeEnvironmentStrings. + +--*/ +LPWSTR +PALAPI +GetEnvironmentStringsW( + VOID) +{ + WCHAR *wenviron = nullptr, *tempEnviron; + int i, len, envNum; + + PERF_ENTRY(GetEnvironmentStringsW); + ENTRY("GetEnvironmentStringsW()\n"); + + CPalThread * pthrCurrent = InternalGetCurrentThread(); + InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + + envNum = 0; + len = 0; + + /* get total length of the bytes that we need to allocate */ + for (i = 0; palEnvironment[i] != 0; i++) + { + len = MultiByteToWideChar(CP_ACP, 0, palEnvironment[i], -1, wenviron, 0); + envNum += len; + } + + wenviron = (WCHAR *)PAL_malloc(sizeof(WCHAR)* (envNum + 1)); + if (wenviron == nullptr) + { + ERROR("malloc failed\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto EXIT; + } + + len = 0; + tempEnviron = wenviron; + for (i = 0; palEnvironment[i] != 0; i++) + { + len = MultiByteToWideChar(CP_ACP, 0, palEnvironment[i], -1, tempEnviron, envNum); + tempEnviron += len; + envNum -= len; + } + + *tempEnviron = 0; /* Put an extra null at the end */ + + EXIT: + InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); + + LOGEXIT("GetEnvironmentStringsW returning %p\n", wenviron); + PERF_EXIT(GetEnvironmentStringsW); + return wenviron; +} + +/*++ +Function: + GetEnvironmentStringsA + +See GetEnvironmentStringsW. + +--*/ +LPSTR +PALAPI +GetEnvironmentStringsA( + VOID) +{ + char *environ = nullptr, *tempEnviron; + int i, len, envNum; + + PERF_ENTRY(GetEnvironmentStringsA); + ENTRY("GetEnvironmentStringsA()\n"); + + CPalThread * pthrCurrent = InternalGetCurrentThread(); + InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + + envNum = 0; + len = 0; + + /* get total length of the bytes that we need to allocate */ + for (i = 0; palEnvironment[i] != 0; i++) + { + len = strlen(palEnvironment[i]) + 1; + envNum += len; + } + + environ = (char *)PAL_malloc(envNum + 1); + if (environ == nullptr) + { + ERROR("malloc failed\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto EXIT; + } + + len = 0; + tempEnviron = environ; + for (i = 0; palEnvironment[i] != 0; i++) + { + len = strlen(palEnvironment[i]) + 1; + memcpy(tempEnviron, palEnvironment[i], len); + tempEnviron += len; + envNum -= len; + } + + *tempEnviron = 0; /* Put an extra null at the end */ + + EXIT: + InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); + + LOGEXIT("GetEnvironmentStringsA returning %p\n", environ); + PERF_EXIT(GetEnvironmentStringsA); + return environ; +} + +/*++ +Function: + FreeEnvironmentStringsW + +The FreeEnvironmentStrings function frees a block of environment strings. + +Parameters + +lpszEnvironmentBlock [in] Pointer to a block of environment strings. The pointer to + the block must be obtained by calling the + GetEnvironmentStrings function. + +Return Values + +If the function succeeds, the return value is nonzero. If the +function fails, the return value is zero. To get extended error +information, call GetLastError. + +Remarks + +When GetEnvironmentStrings is called, it allocates memory for a block +of environment strings. When the block is no longer needed, it should +be freed by calling FreeEnvironmentStrings. + +--*/ +BOOL +PALAPI +FreeEnvironmentStringsW( + IN LPWSTR lpValue) +{ + PERF_ENTRY(FreeEnvironmentStringsW); + ENTRY("FreeEnvironmentStringsW(lpValue=%p (%S))\n", lpValue ? lpValue : W16_NULLSTRING, lpValue ? lpValue : W16_NULLSTRING); + + if (lpValue != nullptr) + { + PAL_free(lpValue); + } + + LOGEXIT("FreeEnvironmentStringW returning BOOL TRUE\n"); + PERF_EXIT(FreeEnvironmentStringsW); + return TRUE; +} + +/*++ +Function: + FreeEnvironmentStringsA + +See FreeEnvironmentStringsW. + +--*/ +BOOL +PALAPI +FreeEnvironmentStringsA( + IN LPSTR lpValue) +{ + PERF_ENTRY(FreeEnvironmentStringsA); + ENTRY("FreeEnvironmentStringsA(lpValue=%p (%s))\n", lpValue ? lpValue : "NULL", lpValue ? lpValue : "NULL"); + + if (lpValue != nullptr) + { + PAL_free(lpValue); + } + + LOGEXIT("FreeEnvironmentStringA returning BOOL TRUE\n"); + PERF_EXIT(FreeEnvironmentStringsA); + return TRUE; +} + +/*++ +Function: + SetEnvironmentVariableA + +The SetEnvironmentVariable function sets the value of an environment +variable for the current process. + +Parameters + +lpName + [in] Pointer to a null-terminated string that specifies the + environment variable whose value is being set. The operating + system creates the environment variable if it does not exist + and lpValue is not null. +lpValue + [in] Pointer to a null-terminated string containing the new + value of the specified environment variable. If this parameter + is null, the variable is deleted from the current process's + environment. + +Return Values + +If the function succeeds, the return value is nonzero. + +If the function fails, the return value is zero. To get extended error +information, call GetLastError. + +Remarks + +This function has no effect on the system environment variables or the +environment variables of other processes. + +--*/ +BOOL +PALAPI +SetEnvironmentVariableA( + IN LPCSTR lpName, + IN LPCSTR lpValue) +{ + + BOOL bRet = FALSE; + int nResult =0; + PERF_ENTRY(SetEnvironmentVariableA); + ENTRY("SetEnvironmentVariableA(lpName=%p (%s), lpValue=%p (%s))\n", + lpName ? lpName : "NULL", lpName ? lpName : "NULL", + lpValue ? lpValue : "NULL", lpValue ? lpValue : "NULL"); + + // exit if the input variable name is null + if ((lpName == nullptr) || (lpName[0] == 0)) + { + ERROR("lpName is null\n"); + goto done; + } + + /* check if the input value is null and if so + * check if the input name is valid and delete + * the variable name from process environment */ + if (lpValue == nullptr) + { + // We tell EnvironGetenv not to bother with making a copy of the + // value since we're not going to use it for anything interesting + // apart from checking whether it's null. + if ((lpValue = EnvironGetenv(lpName, /* copyValue */ FALSE)) == nullptr) + { + ERROR("Couldn't find environment variable (%s)\n", lpName); + SetLastError(ERROR_ENVVAR_NOT_FOUND); + goto done; + } + + EnvironUnsetenv(lpName); + } + else + { + // All the conditions are met. Set the variable. + int iLen = strlen(lpName) + strlen(lpValue) + 2; + LPSTR string = (LPSTR) PAL_malloc(iLen); + if (string == nullptr) + { + bRet = FALSE; + ERROR("Unable to allocate memory\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + + sprintf_s(string, iLen, "%s=%s", lpName, lpValue); + nResult = EnvironPutenv(string, FALSE) ? 0 : -1; + + PAL_free(string); + string = nullptr; + + // If EnvironPutenv returns FALSE, it almost certainly failed to allocate memory. + if (nResult == -1) + { + bRet = FALSE; + ERROR("Unable to allocate memory\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + } + + bRet = TRUE; + +done: + LOGEXIT("SetEnvironmentVariableA returning BOOL %d\n", bRet); + PERF_EXIT(SetEnvironmentVariableA); + return bRet; +} + +/*++ +Function: + ResizeEnvironment + +Resizes the PAL environment buffer. + +Parameters + + newSize + [in] New size of palEnvironment + +Return Values + + TRUE on success, FALSE otherwise + +--*/ +BOOL ResizeEnvironment(int newSize) +{ + CPalThread * pthrCurrent = InternalGetCurrentThread(); + InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + + BOOL ret = FALSE; + if (newSize >= palEnvironmentCount) + { + // If palEnvironment is null, realloc acts like malloc. + char **newEnvironment = (char**)realloc(palEnvironment, newSize * sizeof(char *)); + if (newEnvironment != nullptr) + { + // realloc succeeded, so set palEnvironment to what it returned. + palEnvironment = newEnvironment; + palEnvironmentCapacity = newSize; + ret = TRUE; + } + } + else + { + ASSERT("ResizeEnvironment: newSize < current palEnvironmentCount!\n"); + } + + InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); + return ret; +} + +/*++ +Function: + EnvironUnsetenv + +Remove the environment variable with the given name from the PAL version +of the environment if it exists. + +Parameters + + name + [in] Name of variable to unset. + +--*/ +void EnvironUnsetenv(const char *name) +{ + int nameLength = strlen(name); + + CPalThread * pthrCurrent = InternalGetCurrentThread(); + InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + + for (int i = 0; palEnvironment[i] != nullptr; ++i) + { + const char *equalsSignPosition = strchr(palEnvironment[i], '='); + if (equalsSignPosition == nullptr) + { + equalsSignPosition = palEnvironment[i] + strlen(palEnvironment[i]); + } + + // Check whether the name of this variable has the same length as the one + // we're looking for before proceeding to compare them. + if (equalsSignPosition - palEnvironment[i] == nameLength) + { + if (memcmp(name, palEnvironment[i], nameLength) == 0) + { + // Free the string we're removing. + free(palEnvironment[i]); + + // Move the last environment variable pointer here. + palEnvironment[i] = palEnvironment[palEnvironmentCount - 1]; + palEnvironment[palEnvironmentCount - 1] = nullptr; + + palEnvironmentCount--; + } + } + } + + InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); +} + +/*++ +Function: + EnvironPutenv + +Add the environment variable string provided to the PAL version +of the environment. + +Parameters + + entry + [in] The variable string to add. Should be in the format + "name=value", where value might be empty (see below). + deleteIfEmpty + [in] If this is TRUE, "name=" will unset the 'name' variable. + +Return Values + + TRUE on success, FALSE otherwise + +--*/ +BOOL EnvironPutenv(const char* entry, BOOL deleteIfEmpty) +{ + BOOL result = FALSE; + + bool fOwningCS = false; + + CPalThread * pthrCurrent = InternalGetCurrentThread(); + + const char *equalsSignPosition = strchr(entry, '='); + if (equalsSignPosition == entry || equalsSignPosition == nullptr) + { + // "=foo" and "foo" have no meaning + return FALSE; + } + + char* copy = strdup(entry); + if (copy == nullptr) + { + return FALSE; + } + + int nameLength = equalsSignPosition - entry; + + if (equalsSignPosition[1] == '\0' && deleteIfEmpty) + { + // "foo=" removes foo from the environment in _putenv() on Windows. + // The same string can result from a call to SetEnvironmentVariable() + // with the empty string as the value, but in that case we want to + // set the variable's value to "". deleteIfEmpty will be FALSE in + // that case. + + // Change '=' to '\0' + copy[nameLength] = '\0'; + + EnvironUnsetenv(copy); + free(copy); + + result = TRUE; + } + else + { + // See if we are replacing an item or adding one. + + InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + fOwningCS = true; + + int i; + for (i = 0; palEnvironment[i] != nullptr; i++) + { + const char *existingEquals = strchr(palEnvironment[i], '='); + if (existingEquals == nullptr) + { + // The PAL screens out malformed strings, but the strings which + // came from the system during initialization might not have the + // equals sign. We treat the entire string as a name in that case. + existingEquals = palEnvironment[i] + strlen(palEnvironment[i]); + } + + if (existingEquals - palEnvironment[i] == nameLength) + { + if (memcmp(entry, palEnvironment[i], nameLength) == 0) + { + free(palEnvironment[i]); + palEnvironment[i] = copy; + + result = TRUE; + break; + } + } + } + + if (palEnvironment[i] == nullptr) + { + _ASSERTE(i < palEnvironmentCapacity); + if (i == (palEnvironmentCapacity - 1)) + { + // We found the first null, but it's the last element in our environment + // block. We need more space in our environment, so let's double its size. + int resizeRet = ResizeEnvironment(palEnvironmentCapacity * 2); + if (resizeRet != TRUE) + { + free(copy); + goto done; + } + } + + _ASSERTE(copy != nullptr); + palEnvironment[i] = copy; + palEnvironment[i + 1] = nullptr; + palEnvironmentCount++; + + result = TRUE; + } + } +done: + + if (fOwningCS) + { + InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); + } + + return result; +} + + +/*++ +Function: + FindEnvVarValue + +Get the value of environment variable with the given name. +Caller should take care of locking and releasing palEnvironment. + +Parameters + + name + [in] The name of the environment variable to get. + +Return Value + + A pointer to the value of the environment variable if it exists, + or nullptr otherwise. + +--*/ +char* FindEnvVarValue(const char* name) +{ + if (*name == '\0') + return nullptr; + + for (int i = 0; palEnvironment[i] != nullptr; ++i) + { + const char* pch = name; + char* p = palEnvironment[i]; + + do + { + if (*pch == '\0') + { + if (*p == '=') + return p + 1; + + if (*p == '\0') // no = sign -> empty value + return p; + + break; + } + } + while (*pch++ == *p++); + } + + return nullptr; +} + + +/*++ +Function: + EnvironGetenv + +Get the value of environment variable with the given name. + +Parameters + + name + [in] The name of the environment variable to get. + copyValue + [in] If this is TRUE, the function will make a copy of the + value and return a pointer to that. Otherwise, it will + return a pointer to the value in the PAL environment + directly. Calling this function with copyValue set to + FALSE is therefore unsafe without taking special pre- + cautions since the pointer may point to garbage later. + +Return Value + + A pointer to the value of the environment variable if it exists, + or nullptr otherwise. + +--*/ +char* EnvironGetenv(const char* name, BOOL copyValue) +{ + CPalThread * pthrCurrent = InternalGetCurrentThread(); + InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + + char* retValue = FindEnvVarValue(name); + + if ((retValue != nullptr) && copyValue) + { + retValue = strdup(retValue); + } + + InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); + return retValue; +} + + +/*++ +Function: + EnvironGetSystemEnvironment + +Get a pointer to the array of pointers representing the process's +environment. + +See 'man environ' for details. + +Return Value + + A pointer to the environment. + +--*/ +char** EnvironGetSystemEnvironment() +{ + char** sysEnviron; + +#if HAVE__NSGETENVIRON + sysEnviron = *(_NSGetEnviron()); +#else // HAVE__NSGETENVIRON + extern char **environ; + sysEnviron = environ; +#endif // HAVE__NSGETENVIRON + + return sysEnviron; +} + +/*++ +Function: + EnvironInitialize + +Initialization function called from PAL_Initialize. + +Note: This is called before debug channels are initialized, so it + cannot use debug tracing calls. +--*/ +BOOL +EnvironInitialize(void) +{ + BOOL ret = FALSE; + + InternalInitializeCriticalSection(&gcsEnvironment); + + CPalThread * pthrCurrent = InternalGetCurrentThread(); + InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + + char** sourceEnviron = EnvironGetSystemEnvironment(); + + int variableCount = 0; + while (sourceEnviron[variableCount] != nullptr) + variableCount++; + + palEnvironmentCount = 0; + + // We need to decide how much space to allocate. Since we need enough + // space for all of the 'n' current environment variables, but we don't + // know how many more there will be, we will initially make room for + // '2n' variables. If even more are added, we will resize again. + // If there are no variables, we will still make room for 1 entry to + // store a nullptr there. + int initialSize = (variableCount == 0) ? 1 : variableCount * 2; + + ret = ResizeEnvironment(initialSize); + if (ret == TRUE) + { + _ASSERTE(palEnvironment != nullptr); + for (int i = 0; i < variableCount; ++i) + { + palEnvironment[i] = strdup(sourceEnviron[i]); + palEnvironmentCount++; + } + + // Set the entry after the last variable to null to indicate the end. + palEnvironment[variableCount] = nullptr; + } + + InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); + return ret; +} + +/*++ + +Function : _putenv. + +See MSDN for more details. + +Note: The BSD implementation can cause + memory leaks. See man pages for more details. +--*/ +int +__cdecl +_putenv( const char * envstring ) +{ + int ret = -1; + + PERF_ENTRY(_putenv); + ENTRY( "_putenv( %p (%s) )\n", envstring ? envstring : "NULL", envstring ? envstring : "NULL") ; + + if (envstring != nullptr) + { + ret = EnvironPutenv(envstring, TRUE) ? 0 : -1; + } + else + { + ERROR( "_putenv() called with NULL envstring!\n"); + } + + LOGEXIT( "_putenv returning %d\n", ret); + PERF_EXIT(_putenv); + return ret; +} + +/*++ + +Function : PAL_getenv + +See MSDN for more details. +--*/ +char * __cdecl PAL_getenv(const char *varname) +{ + char *retval; + + PERF_ENTRY(getenv); + ENTRY("getenv (%p (%s))\n", varname ? varname : "NULL", varname ? varname : "NULL"); + + if (strcmp(varname, "") == 0) + { + ERROR("getenv called with a empty variable name\n"); + LOGEXIT("getenv returning NULL\n"); + PERF_EXIT(getenv); + return(NULL); + } + + retval = EnvironGetenv(varname); + + LOGEXIT("getenv returning %p\n", retval); + PERF_EXIT(getenv); + return(retval); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/error.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/error.cpp new file mode 100644 index 0000000..aaa7095 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/error.cpp @@ -0,0 +1,126 @@ +// 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: + + error.c + +Abstract: + + Implementation of Error management functions. + +Revision History: + + + +--*/ + +#include "pal/thread.hpp" +#include "pal/dbgmsg.h" + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(MISC); + +/*++ +Function: + SetErrorMode + +The SetErrorMode function controls whether the system will handle the +specified types of serious errors, or whether the process will handle +them. + +Parameters + +uMode + [in] Specifies the process error mode. This parameter can be one or more of the following values. + + Value Action + 0 Use the system default, which is to display all error dialog boxes. + SEM_FAILCRITICALERRORS The system does not display the critical-error-handler message box. Instead, + the system sends the error to the calling process. + SEM_NOOPENFILEERRORBOX The system does not display a message box when it fails to find a file. Instead, + the error is returned to the calling process. + +Return Values + +The return value is the previous state of the error-mode bit flags. + +--*/ +UINT +PALAPI +SetErrorMode( + IN UINT uMode) +{ + PERF_ENTRY(SetErrorMode); + ENTRY("SetErrorMode (uMode=%#x)\n", uMode); + + LOGEXIT("SetErrorMode returns UINT 0\n"); + PERF_EXIT(SetErrorMode); + return 0; +} + + +/*++ +Function: + GetLastError + +GetLastError + +The GetLastError function retrieves the calling thread's last-error +code value. The last-error code is maintained on a per-thread +basis. Multiple threads do not overwrite each other's last-error code. + +Parameters + +This function has no parameters. + +Return Values + +The return value is the calling thread's last-error code +value. Functions set this value by calling the SetLastError +function. The Return Value section of each reference page notes the +conditions under which the function sets the last-error code. + +--*/ +DWORD +PALAPI +GetLastError( + VOID) +{ + return CPalThread::GetLastError(); +} + + + +/*++ +Function: + SetLastError + +SetLastError + +The SetLastError function sets the last-error code for the calling thread. + +Parameters + +dwErrCode + [in] Specifies the last-error code for the thread. + +Return Values + +This function does not return a value. + +--*/ +VOID +PALAPI +SetLastError( + IN DWORD dwErrCode) +{ + CPalThread::SetLastError(dwErrCode); +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/errorstrings.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/errorstrings.cpp new file mode 100644 index 0000000..2863495 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/errorstrings.cpp @@ -0,0 +1,172 @@ +// 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: + + errorstrings.cpp + +Abstract: + + Conversion of PAL error code to string + +Revision History: + + + +--*/ + +#include "pal/palinternal.h" +#include "errorstrings.h" + +struct ErrorString +{ + DWORD code; + LPCWSTR const string; +}; + +ErrorString palErrorStrings[] = +{ + { ERROR_SUCCESS, W("The operation completed successfully.\n") }, + { ERROR_INVALID_FUNCTION, W("Incorrect function.\n") }, + { ERROR_FILE_NOT_FOUND, W("The system cannot find the file specified.\n") }, + { ERROR_PATH_NOT_FOUND, W("The system cannot find the path specified.\n") }, + { ERROR_TOO_MANY_OPEN_FILES, W("The system cannot open the file.\n") }, + { ERROR_ACCESS_DENIED, W("Access is denied.\n") }, + { ERROR_INVALID_HANDLE, W("The handle is invalid.\n") }, + { ERROR_NOT_ENOUGH_MEMORY, W("Not enough storage is available to process this command.\n") }, + { ERROR_BAD_ENVIRONMENT, W("The environment is incorrect.\n") }, + { ERROR_BAD_FORMAT, W("An attempt was made to load a program with an incorrect format.\n") }, + { ERROR_INVALID_ACCESS, W("The access code is invalid.\n") }, + { ERROR_INVALID_DATA, W("The data is invalid.\n") }, + { ERROR_OUTOFMEMORY, W("Not enough storage is available to complete this operation.\n") }, + { ERROR_INVALID_DRIVE, W("The system cannot find the drive specified.\n") }, + { ERROR_NO_MORE_FILES, W("There are no more files.\n") }, + { ERROR_WRITE_PROTECT, W("The media is write protected.\n") }, + { ERROR_NOT_READY, W("The device is not ready.\n") }, + { ERROR_BAD_COMMAND, W("The device does not recognize the command.\n") }, + { ERROR_BAD_LENGTH, W("The program issued a command but the command length is incorrect.\n") }, + { ERROR_WRITE_FAULT, W("The system cannot write to the specified device.\n") }, + { ERROR_READ_FAULT, W("The system cannot read from the specified device.\n") }, + { ERROR_GEN_FAILURE, W("A device attached to the system is not functioning.\n") }, + { ERROR_SHARING_VIOLATION, W("The process cannot access the file because it is being used by another process.\n") }, + { ERROR_LOCK_VIOLATION, W("The process cannot access the file because another process has locked a portion of the file.\n") }, + { ERROR_SHARING_BUFFER_EXCEEDED, W("Too many files opened for sharing.\n") }, + { ERROR_HANDLE_EOF, W("Reached the end of the file.\n") }, + { ERROR_HANDLE_DISK_FULL, W("The disk is full.\n") }, + { ERROR_NOT_SUPPORTED, W("The request is not supported.\n") }, + { ERROR_DUP_NAME, W("A duplicate name exists on the network.\n") }, + { ERROR_BAD_NETPATH, W("The network path was not found.\n") }, + { ERROR_DEV_NOT_EXIST, W("The specified network resource or device is no longer available.\n") }, + { ERROR_BAD_NET_NAME, W("The network name cannot be found.\n") }, + { ERROR_FILE_EXISTS, W("The file exists.\n") }, + { ERROR_CANNOT_MAKE, W("The directory or file cannot be created.\n") }, + { ERROR_INVALID_PARAMETER, W("The parameter is incorrect.\n") }, + { ERROR_NET_WRITE_FAULT, W("A write fault occurred on the network.\n") }, + { ERROR_DRIVE_LOCKED, W("The disk is in use or locked by another process.\n") }, + { ERROR_BROKEN_PIPE, W("The pipe has been ended.\n") }, + { ERROR_OPEN_FAILED, W("The system cannot open the device or file specified.\n") }, + { ERROR_BUFFER_OVERFLOW, W("The file name is too long.\n") }, + { ERROR_DISK_FULL, W("There is not enough space on the disk.\n") }, + { ERROR_CALL_NOT_IMPLEMENTED, W("This function is not supported on this system.\n") }, + { ERROR_SEM_TIMEOUT, W("The semaphore timeout period has expired.\n") }, + { ERROR_INSUFFICIENT_BUFFER, W("The data area passed to a system call is too small.\n") }, + { ERROR_INVALID_NAME, W("The filename, directory name, or volume label syntax is incorrect.\n") }, + { ERROR_MOD_NOT_FOUND, W("The specified module or one of its dependencies could not be found.\n") }, + { ERROR_PROC_NOT_FOUND, W("The specified procedure could not be found.\n") }, + { ERROR_WAIT_NO_CHILDREN, W("There are no child processes to wait for.\n") }, + { ERROR_NEGATIVE_SEEK, W("An attempt was made to move the file pointer before the beginning of the file.\n") }, + { ERROR_SEEK_ON_DEVICE, W("The file pointer cannot be set on the specified device or file.\n") }, + { ERROR_DIR_NOT_EMPTY, W("The directory is not empty.\n") }, + { ERROR_SIGNAL_REFUSED, W("The recipient process has refused the signal.\n") }, + { ERROR_NOT_LOCKED, W("The segment is already unlocked.\n") }, + { ERROR_BAD_PATHNAME, W("The specified path is invalid.\n") }, + { ERROR_BUSY, W("The requested resource is in use.\n") }, + { ERROR_INVALID_ORDINAL, W("The operating system cannot run %1.\n") }, + { ERROR_ALREADY_EXISTS, W("Cannot create a file when that file already exists.\n") }, + { ERROR_INVALID_EXE_SIGNATURE, W("Cannot run %1 in Win32 mode.\n") }, + { ERROR_EXE_MARKED_INVALID, W("The operating system cannot run %1.\n") }, + { ERROR_BAD_EXE_FORMAT, W("%1 is not a valid Win32 application.\n") }, + { ERROR_ENVVAR_NOT_FOUND, W("The system could not find the environment option that was entered.\n") }, + { ERROR_FILENAME_EXCED_RANGE, W("The filename or extension is too long.\n") }, + { ERROR_PIPE_BUSY, W("All pipe instances are busy.\n") }, + { ERROR_NO_DATA, W("The pipe is being closed\n")}, + { ERROR_MORE_DATA, W("More data is available.\n") }, + { ERROR_NO_MORE_ITEMS, W("No more data is available.\n") }, + { ERROR_DIRECTORY, W("The directory name is invalid.\n") }, + { ERROR_NOT_OWNER, W("Attempt to release mutex not owned by caller.\n") }, + { ERROR_PARTIAL_COPY, W("Only part of a ReadProcessMemory or WriteProcessMemory request was completed.\n") }, + { ERROR_INVALID_ADDRESS, W("Attempt to access invalid address.\n") }, + { ERROR_ARITHMETIC_OVERFLOW, W("Arithmetic result exceeded 32 bits.\n") }, + { ERROR_OPERATION_ABORTED, W("The I/O operation has been aborted because of either a thread exit or an application request.\n") }, + { ERROR_IO_INCOMPLETE, W("Overlapped I/O event is not in a signaled state.\n") }, + { ERROR_IO_PENDING, W("Overlapped I/O operation is in progress.\n") }, + { ERROR_NOACCESS, W("Invalid access to memory location.\n") }, + { ERROR_STACK_OVERFLOW, W("Recursion too deep; the stack overflowed.\n") }, + { ERROR_INVALID_FLAGS, W("Invalid flags.\n") }, + { ERROR_UNRECOGNIZED_VOLUME, W("The volume does not contain a recognized file system.\nPlease make sure that all required file system drivers are loaded and that the volume is not corrupted.\n") }, + { ERROR_FILE_INVALID, W("The volume for a file has been externally altered so that the opened file is no longer valid.\n") }, + { ERROR_PROCESS_ABORTED, W("The process terminated unexpectedly.\n") }, + { ERROR_NO_UNICODE_TRANSLATION, W("No mapping for the Unicode character exists in the target multi-byte code page.\n") }, + { ERROR_DLL_INIT_FAILED, W("A dynamic link library (DLL) initialization routine failed.\n") }, + { ERROR_IO_DEVICE, W("The request could not be performed because of an I/O device error.\n") }, + { ERROR_DISK_OPERATION_FAILED, W("While accessing the hard disk, a disk operation failed even after retries.\n") }, + { ERROR_POSSIBLE_DEADLOCK, W("A potential deadlock condition has been detected.\n") }, + { ERROR_TOO_MANY_LINKS, W("An attempt was made to create more links on a file than the file system supports.\n") }, + { ERROR_INVALID_DLL, W("One of the library files needed to run this application is damaged.\n") }, + { ERROR_DLL_NOT_FOUND, W("One of the library files needed to run this application cannot be found.\n") }, + { ERROR_NOT_FOUND, W("Element not found.\n") }, + { ERROR_CANCELLED, W("The operation was canceled by the user.\n") }, + { ERROR_NOT_AUTHENTICATED, W("The operation being requested was not performed because the user has not been authenticated.\n") }, + { ERROR_INTERNAL_ERROR, W("An internal error occurred.\n") }, + { ERROR_FILE_CORRUPT, W("The file or directory is corrupted and unreadable.\n") }, + { ERROR_DISK_CORRUPT, W("The disk structure is corrupted and unreadable.\n") }, + { ERROR_WRONG_TARGET_NAME, W("Logon Failure: The target account name is incorrect.\n") }, + { ERROR_NO_SYSTEM_RESOURCES, W("Insufficient system resources exist to complete the requested service.\n") }, + { ERROR_COMMITMENT_LIMIT, W("The paging file is too small for this operation to complete.\n") }, + { ERROR_TIMEOUT, W("This operation returned because the timeout period expired.\n") }, + { ERROR_EVENTLOG_FILE_CORRUPT, W("The event log file is corrupted.\n") }, + { ERROR_LOG_FILE_FULL, W("The event log file is full.\n") }, + { ERROR_UNSUPPORTED_TYPE, W("Data of this type is not supported.\n") }, + { RPC_S_INVALID_VERS_OPTION, W("The version option is invalid.\n") }, + { ERROR_RESOURCE_DATA_NOT_FOUND, W("The specified image file did not contain a resource section.\n") }, + { ERROR_RESOURCE_LANG_NOT_FOUND, W("The specified resource language ID cannot be found in the image file.\n") }, + { ERROR_TAG_NOT_PRESENT, W("A required tag is not present.\n") } +}; + +int CompareErrorStrings(const void *a, const void *b) +{ + DWORD codeA = ((ErrorString *)a)->code; + DWORD codeB = ((ErrorString *)b)->code; + + if (codeA < codeB) + { + return -1; + } + else if (codeA == codeB) + { + return 0; + } + else + { + return 1; + } +} + +LPCWSTR GetPalErrorString(DWORD code) +{ + // Search the sorted set of resources for the ID we're interested in. + ErrorString searchEntry = {code, NULL}; + ErrorString *stringEntry = (ErrorString *)bsearch( + &searchEntry, + palErrorStrings, + sizeof(palErrorStrings) / sizeof(palErrorStrings[0]), + sizeof(ErrorString), + CompareErrorStrings); + + return (stringEntry != NULL) ? stringEntry->string : NULL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/ndpversion.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/errorstrings.h similarity index 63% rename from CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/ndpversion.h rename to CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/errorstrings.h index ba6d018..d24f025 100644 --- a/CoreCLRProfiler/native/coreclr_headers/src/pal/prebuilt/inc/ndpversion.h +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/errorstrings.h @@ -1,4 +1,10 @@ // 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. -#include + +#ifndef _ERRORSTRINGS_H_ +#define _ERRORSTRINGS_H_ + +LPCWSTR GetPalErrorString(DWORD code); + +#endif // _ERRORSTRINGS_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/fmtmessage.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/fmtmessage.cpp new file mode 100644 index 0000000..210f32b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/fmtmessage.cpp @@ -0,0 +1,692 @@ +// 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: + + fmtmessage.c + +Abstract: + + Implementation of FormatMessage function. + +Revision History: + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/critsect.h" +#include "pal/module.h" +#include "pal/misc.h" + +#include "pal/printfcpp.hpp" + +#include "errorstrings.h" + +#include +#include +#include +#include + +SET_DEFAULT_DEBUG_CHANNEL(MISC); + +/* Defines */ + +#define MAX_ERROR_STRING_LENGTH 32 + +/*++ +Function: + + FMTMSG_GetMessageString + +Returns the message as a wide string. +--*/ +static LPWSTR FMTMSG_GetMessageString( DWORD dwErrCode ) +{ + TRACE("Entered FMTMSG_GetMessageString\n"); + + LPCWSTR lpErrorString = GetPalErrorString(dwErrCode); + int allocChars; + + if (lpErrorString != NULL) + { + allocChars = PAL_wcslen(lpErrorString) + 1; + } + else + { + allocChars = MAX_ERROR_STRING_LENGTH + 1; + } + + LPWSTR lpRetVal = (LPWSTR)LocalAlloc(LMEM_FIXED, allocChars * sizeof(WCHAR)); + + if (lpRetVal) + { + if (lpErrorString != NULL) + { + PAL_wcscpy(lpRetVal, lpErrorString); + } + else + { + swprintf_s(lpRetVal, MAX_ERROR_STRING_LENGTH, W("Error %u"), dwErrCode); + } + } + else + { + ERROR("Unable to allocate memory.\n"); + } + + return lpRetVal; +} + +/*++ + +Function : + + FMTMSG__watoi + + Converts a wide string repersentation of an integer number + into a interger number. + + Returns a integer number, or 0 on failure. 0 is not a valid number + for FormatMessage inserts. + +--*/ +static INT FMTMSG__watoi( LPWSTR str ) +{ + CONST UINT MAX_NUMBER_LENGTH = 3; + CHAR buf[ MAX_NUMBER_LENGTH ]; + INT nRetVal = 0; + + nRetVal = WideCharToMultiByte( CP_ACP, 0, str, -1, buf, + MAX_NUMBER_LENGTH, NULL, 0 ); + + if ( nRetVal != 0 ) + { + return atoi( buf ); + } + else + { + ERROR( "Unable to convert the string to a number.\n" ); + return 0; + } +} + +/* Adds the character to the working string. */ +#define _ADD_TO_STRING( c ) \ +{\ + TRACE( "Adding %c to the string.\n", (CHAR)c );\ + *lpWorkingString = c;\ + lpWorkingString++;\ + nCount++;\ +} + +/* Grows the buffer. */ +#define _GROW_BUFFER() \ +{\ + if ( bIsLocalAlloced ) \ + { \ + LPWSTR lpTemp = NULL; \ + UINT NumOfBytes = 0; \ + nSize *= 2; \ + NumOfBytes = nSize * sizeof( WCHAR ); \ + lpTemp = static_cast( LocalAlloc( LMEM_FIXED, NumOfBytes ) ); \ + TRACE( "Growing the buffer.\n" );\ + \ + if ( !lpTemp ) \ + { \ + ERROR( "Out of buffer\n" ); \ + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); \ + nCount = 0; \ + lpWorkingString = NULL; \ + goto exit; \ + } \ + \ + *lpWorkingString = '\0';\ + PAL_wcscpy( lpTemp, lpReturnString );\ + LocalFree( lpReturnString ); \ + lpWorkingString = lpReturnString = lpTemp; \ + lpWorkingString += nCount; \ + } \ + else \ + { \ + WARN( "Out of buffer.\n" ); \ + SetLastError( ERROR_INSUFFICIENT_BUFFER ); \ + nCount = 0; \ + lpWorkingString = NULL; \ + goto exit; \ + } \ +} +/* Adds a character to the working string. This is a safer version +of _ADD_TO_STRING, as we will resize the buffer if necessary. */ +#define _CHECKED_ADD_TO_STRING( c ) \ +{\ + if ( nCount+1 == nSize ) \ + {\ + _GROW_BUFFER();\ + } \ + _ADD_TO_STRING( c );\ +} + + +/*++ +Function : + + FMTMSG_ProcessPrintf + + Processes the printf formatters based on the format. + + Returns the LPWSTR string, or NULL on failure. +*/ + +static LPWSTR FMTMSG_ProcessPrintf( WCHAR c , + LPWSTR lpPrintfString, + LPWSTR lpInsertString) +{ + LPWSTR lpBuffer = NULL; + LPWSTR lpBuffer2 = NULL; + LPWSTR lpFormat = NULL; +#if _DEBUG + // small size for _DEBUG to exercise buffer reallocation logic + int tmpSize = 4; +#else + int tmpSize = 64; +#endif + UINT nFormatLength = 0; + int nBufferLength = 0; + + TRACE( "FMTMSG_ProcessPrintf( %C, %S, %p )\n", c, + lpPrintfString, lpInsertString ); + + switch ( c ) + { + case 'e' : + /* Fall through */ + case 'E' : + /* Fall through */ + case 'f' : + /* Fall through */ + case 'g' : + /* Fall through */ + case 'G' : + ERROR( "%%%c is not supported by FormatMessage.\n", c ); + SetLastError( ERROR_INVALID_PARAMETER ); + return NULL; + } + + nFormatLength = PAL_wcslen( lpPrintfString ) + 2; /* Need to count % AND NULL */ + lpFormat = (LPWSTR)PAL_malloc( nFormatLength * sizeof( WCHAR ) ); + if ( !lpFormat ) + { + ERROR( "Unable to allocate memory.\n" ); + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return NULL; + } + /* Create the format string. */ + memset( lpFormat, 0, nFormatLength * sizeof(WCHAR) ); + *lpFormat = '%'; + + PAL_wcscat( lpFormat, lpPrintfString ); + + lpBuffer = (LPWSTR) PAL_malloc(tmpSize*sizeof(WCHAR)); + + /* try until the buffer is big enough */ + while (TRUE) + { + if (!lpBuffer) + { + ERROR("Unable to allocate memory\n"); + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + PAL_free(lpFormat); + return NULL; + } + nBufferLength = _snwprintf_s( lpBuffer, tmpSize, tmpSize, + lpFormat, lpInsertString); + + if ((nBufferLength >= 0) && (nBufferLength != tmpSize)) + { + break; /* succeeded */ + } + else + { + tmpSize *= 2; + lpBuffer2 = static_cast( + PAL_realloc(lpBuffer, tmpSize*sizeof(WCHAR))); + if (lpBuffer2 == NULL) + PAL_free(lpBuffer); + lpBuffer = lpBuffer2; + } + } + + PAL_free( lpFormat ); + lpFormat = NULL; + + return lpBuffer; +} + +/*++ +Function: + FormatMessageW + +See MSDN doc. +--*/ +DWORD +PALAPI +FormatMessageW( + IN DWORD dwFlags, + IN LPCVOID lpSource, + IN DWORD dwMessageId, + IN DWORD dwLanguageId, + OUT LPWSTR lpBuffer, + IN DWORD nSize, + IN va_list *Arguments) +{ + BOOL bIgnoreInserts = FALSE; + BOOL bIsVaList = TRUE; + BOOL bIsLocalAlloced = FALSE; + LPWSTR lpSourceString = NULL; + UINT nCount = 0; + LPWSTR lpReturnString = NULL; + LPWSTR lpWorkingString = NULL; + + PERF_ENTRY(FormatMessageW); + ENTRY( "FormatMessageW(dwFlags=%#x, lpSource=%p, dwMessageId=%#x, " + "dwLanguageId=%#x, lpBuffer=%p, nSize=%u, va_list=%p)\n", + dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, + Arguments); + + /* Sanity checks. */ + if ( dwFlags & FORMAT_MESSAGE_FROM_STRING && !lpSource ) + { + /* This behavior is different then in Windows. + Windows would just crash.*/ + ERROR( "lpSource cannot be NULL.\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + goto exit; + } + + if ( !(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER ) && !lpBuffer ) + { + /* This behavior is different then in Windows. + Windows would just crash.*/ + ERROR( "lpBuffer cannot be NULL, if " + " FORMAT_MESSAGE_ALLOCATE_BUFFER is not specified.\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + goto exit; + } + + if ( ( dwFlags & FORMAT_MESSAGE_FROM_STRING ) && + ( dwFlags & FORMAT_MESSAGE_FROM_SYSTEM ) ) + { + ERROR( "These flags cannot co-exist. You can either " + "specify FORMAT_MESSAGE_FROM_STRING, or " + "FORMAT_MESSAGE_FROM_SYSTEM.\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + goto exit; + } + + if ( !( dwFlags & FORMAT_MESSAGE_FROM_STRING ) && + ( dwLanguageId != 0) ) + { + ERROR( "Invalid language indentifier.\n" ); + SetLastError( ERROR_RESOURCE_LANG_NOT_FOUND ); + goto exit; + } + + /* Parameter processing. */ + if ( dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER ) + { + TRACE( "Allocated %d TCHARs. Don't forget to call LocalFree to " + "free the memory when done.\n", nSize ); + bIsLocalAlloced = TRUE; + } + + if ( dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS ) + { + bIgnoreInserts = TRUE; + } + + if ( dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY ) + { + if ( !Arguments && !bIgnoreInserts ) + { + ERROR( "The va_list cannot be NULL.\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + goto exit; + } + else + { + bIsVaList = FALSE; + } + } + + if ( dwFlags & FORMAT_MESSAGE_FROM_STRING ) + { + lpSourceString = (LPWSTR)lpSource; + } + else if ( dwFlags & FORMAT_MESSAGE_FROM_SYSTEM ) + { + if ((dwMessageId & 0xFFFF0000) == 0x80070000) + { + // This message has been produced by HRESULT_FROM_WIN32. Undo its work. + dwMessageId &= 0xFFFF; + } + + lpWorkingString = lpReturnString = + FMTMSG_GetMessageString( dwMessageId ); + + if ( !lpWorkingString ) + { + ERROR( "Unable to find the message %d.\n", dwMessageId ); + SetLastError( ERROR_INTERNAL_ERROR ); + nCount = 0; + goto exit; + } + + nCount = PAL_wcslen( lpWorkingString ); + + if ( !bIsLocalAlloced && nCount > nSize ) + { + ERROR( "Insufficient buffer.\n" ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + lpWorkingString = NULL; + nCount = 0; + goto exit; + } + if ( !lpWorkingString ) + { + ERROR( "Invalid error indentifier.\n" ); + SetLastError( ERROR_INVALID_ADDRESS ); + } + goto exit; + } + else + { + ERROR( "Unknown flag.\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + goto exit; + } + + if ( nSize == 0 && bIsLocalAlloced ) + { + nSize = 1; + } + + lpWorkingString = static_cast( + LocalAlloc( LMEM_FIXED, nSize * sizeof( WCHAR ) ) ); + if ( !lpWorkingString ) + { + ERROR( "Unable to allocate memory for the working string.\n" ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + goto exit; + } + + + /* Process the string. */ + lpReturnString = lpWorkingString; + while ( *lpSourceString ) + { + if ( *lpSourceString == '%' && !bIgnoreInserts ) + { + lpSourceString++; + /* Escape sequences. */ + if ( *lpSourceString == '0' ) + { + /* Terminates a message without a newline character. */ + *lpWorkingString = '\0'; + goto exit; + } + else if ( iswdigit( *lpSourceString ) ) + { + /* Get the insert number. */ + WCHAR Number[] = { '\0', '\0', '\0' }; + SIZE_T Index = 0; + + Number[ 0 ] = *lpSourceString; + lpSourceString++; + + if ( iswdigit( *lpSourceString ) ) + { + Number[ 1 ] = *lpSourceString; + lpSourceString++; + if ( iswdigit( *lpSourceString ) ) + { + ERROR( "Invalid insert indentifier.\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + lpWorkingString = NULL; + nCount = 0; + goto exit; + } + } + Index = FMTMSG__watoi( Number ); + if ( Index == 0 ) + { + ERROR( "Invalid insert indentifier.\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + lpWorkingString = NULL; + nCount = 0; + goto exit; + } + if ( *lpSourceString == '!' ) + { + LPWSTR lpInsertString = NULL; + LPWSTR lpPrintfString = NULL; + LPWSTR lpStartOfFormattedString = NULL; + UINT nPrintfLength = 0; + LPWSTR lpFormattedString = NULL; + UINT nFormattedLength = 0; + + if ( !bIsVaList ) + { + lpInsertString = ((LPWSTR*)Arguments)[ Index - 1 ]; + } + else + { + va_list TheArgs; + + va_copy(TheArgs, *Arguments); + UINT i = 0; + for ( ; i < Index; i++ ) + { + lpInsertString = va_arg( TheArgs, LPWSTR ); + } + } + + /* Calculate the length, and extract the printf string.*/ + lpSourceString++; + { + LPWSTR p = PAL_wcschr( lpSourceString, '!' ); + + if ( NULL == p ) + { + nPrintfLength = 0; + } + else + { + nPrintfLength = p - lpSourceString; + } + } + + lpPrintfString = + (LPWSTR)PAL_malloc( ( nPrintfLength + 1 ) * sizeof( WCHAR ) ); + + if ( !lpPrintfString ) + { + ERROR( "Unable to allocate memory.\n" ); + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + lpWorkingString = NULL; + nCount = 0; + goto exit; + } + + PAL_wcsncpy( lpPrintfString, lpSourceString, nPrintfLength ); + *( lpPrintfString + nPrintfLength ) = '\0'; + + lpStartOfFormattedString = lpFormattedString = + FMTMSG_ProcessPrintf( *lpPrintfString, + lpPrintfString, + lpInsertString); + + if ( !lpFormattedString ) + { + ERROR( "Unable to process the format string.\n" ); + /* Function will set the error code. */ + PAL_free( lpPrintfString ); + lpWorkingString = NULL; + goto exit; + } + + + nFormattedLength = PAL_wcslen( lpFormattedString ); + + /* Append the processed printf string into the working string */ + while ( *lpFormattedString ) + { + _CHECKED_ADD_TO_STRING( *lpFormattedString ); + lpFormattedString++; + } + + lpSourceString += nPrintfLength + 1; + PAL_free( lpPrintfString ); + PAL_free( lpStartOfFormattedString ); + lpPrintfString = lpFormattedString = NULL; + } + else + { + /* The printf format string defaults to 's'.*/ + LPWSTR lpInsert = NULL; + + if ( !bIsVaList ) + { + lpInsert = ((LPWSTR*)Arguments)[Index - 1]; + } + else + { + va_list TheArgs; + va_copy(TheArgs, *Arguments); + UINT i = 0; + for ( ; i < Index; i++ ) + { + lpInsert = va_arg( TheArgs, LPWSTR ); + } + } + + while ( *lpInsert ) + { + _CHECKED_ADD_TO_STRING( *lpInsert ); + lpInsert++; + } + } + } + /* Format specifiers. */ + else if ( *lpSourceString == '%' ) + { + _CHECKED_ADD_TO_STRING( '%' ); + lpSourceString++; + } + else if ( *lpSourceString == 'n' ) + { + /* Hard line break. */ + _CHECKED_ADD_TO_STRING( '\n' ); + lpSourceString++; + } + else if ( *lpSourceString == '.' ) + { + _CHECKED_ADD_TO_STRING( '.' ); + lpSourceString++; + } + else if ( *lpSourceString == '!' ) + { + _CHECKED_ADD_TO_STRING( '!' ); + lpSourceString++; + } + else if ( !*lpSourceString ) + { + ERROR( "Invalid parameter.\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + lpWorkingString = NULL; + nCount = 0; + goto exit; + } + else /* Append the character. */ + { + _CHECKED_ADD_TO_STRING( *lpSourceString ); + lpSourceString++; + } + }/* END if ( *lpSourceString == '%' ) */ + else + { + /* In Windows if FormatMessage is called with ignore inserts, + then FormatMessage strips %1!s! down to %1, since string is the + default. */ + if ( bIgnoreInserts && *lpSourceString == '!' && + *( lpSourceString + 1 ) == 's' ) + { + LPWSTR lpLastBang = PAL_wcschr( lpSourceString + 1, '!' ); + + if ( lpLastBang && ( 2 == lpLastBang - lpSourceString ) ) + { + lpSourceString = lpLastBang + 1; + } + else + { + ERROR( "Mal-formed string\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + lpWorkingString = NULL; + nCount = 0; + goto exit; + } + } + else + { + /* Append to the string. */ + _CHECKED_ADD_TO_STRING( *lpSourceString ); + lpSourceString++; + } + } + } + + /* Terminate the message. */ + _CHECKED_ADD_TO_STRING( '\0' ); + /* NULL does not count. */ + nCount--; + +exit: /* Function clean-up and exit. */ + if ( lpWorkingString ) + { + if ( bIsLocalAlloced ) + { + TRACE( "Assigning the buffer to the pointer.\n" ); + // when FORMAT_MESSAGE_ALLOCATE_BUFFER is specified, nSize + // does not specify the size of lpBuffer, rather it specifies + // the minimum size of the string + // as such we have to blindly assume that lpBuffer has enough space to + // store PVOID + // might cause a prefast warning, but there is no good way to suppress it yet + _ASSERTE(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER); + *((LPVOID*)lpBuffer) = (LPVOID)lpReturnString; + } + else /* Only delete lpReturnString if the caller has their own buffer.*/ + { + TRACE( "Copying the string into the buffer.\n" ); + PAL_wcsncpy( lpBuffer, lpReturnString, nCount + 1 ); + LocalFree( lpReturnString ); + } + } + else /* Error, something occurred. */ + { + if ( lpReturnString ) + { + LocalFree( lpReturnString ); + } + } + LOGEXIT( "FormatMessageW returns %d.\n", nCount ); + PERF_EXIT(FormatMessageW); + return nCount; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/jitsupport.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/jitsupport.cpp new file mode 100644 index 0000000..db9b4e2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/jitsupport.cpp @@ -0,0 +1,131 @@ +// 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. + + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(MISC); + +#include "../../../inc/corjitflags.h" + +#if HAVE_AUXV_HWCAP_H +#include +#include +#endif + +PALIMPORT +VOID +PALAPI +PAL_GetJitCpuCapabilityFlags(CORJIT_FLAGS *flags) +{ + _ASSERTE(flags); + + CORJIT_FLAGS &CPUCompileFlags = *flags; +#if defined(HOST_ARM64) +#if HAVE_AUXV_HWCAP_H + unsigned long hwCap = getauxval(AT_HWCAP); + +// HWCAP_* flags are introduced by ARM into the Linux kernel as new extensions are published. +// For a given kernel, some of these flags may not be present yet. +// Use ifdef for each to allow for compilation with any vintage kernel. +// From a single binary distribution perspective, compiling with latest kernel asm/hwcap.h should +// include all published flags. Given flags are merged to kernel and published before silicon is +// available, using the latest kernel for release should be sufficient. + CPUCompileFlags.Set(InstructionSet_ArmBase); +#ifdef HWCAP_AES + if (hwCap & HWCAP_AES) + CPUCompileFlags.Set(InstructionSet_Aes); +#endif +#ifdef HWCAP_ATOMICS + if (hwCap & HWCAP_ATOMICS) + CPUCompileFlags.Set(InstructionSet_Atomics); +#endif +#ifdef HWCAP_CRC32 + if (hwCap & HWCAP_CRC32) + CPUCompileFlags.Set(InstructionSet_Crc32); +#endif +#ifdef HWCAP_DCPOP +// if (hwCap & HWCAP_DCPOP) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_DCPOP); +#endif +#ifdef HWCAP_ASIMDDP +// if (hwCap & HWCAP_ASIMDDP) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_DP); +#endif +#ifdef HWCAP_FCMA +// if (hwCap & HWCAP_FCMA) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FCMA); +#endif +#ifdef HWCAP_FP +// if (hwCap & HWCAP_FP) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FP); +#endif +#ifdef HWCAP_FPHP +// if (hwCap & HWCAP_FPHP) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FP16); +#endif +#ifdef HWCAP_JSCVT +// if (hwCap & HWCAP_JSCVT) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_JSCVT); +#endif +#ifdef HWCAP_LRCPC +// if (hwCap & HWCAP_LRCPC) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_LRCPC); +#endif +#ifdef HWCAP_PMULL +// if (hwCap & HWCAP_PMULL) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_PMULL); +#endif +#ifdef HWCAP_SHA1 + if (hwCap & HWCAP_SHA1) + CPUCompileFlags.Set(InstructionSet_Sha1); +#endif +#ifdef HWCAP_SHA2 + if (hwCap & HWCAP_SHA2) + CPUCompileFlags.Set(InstructionSet_Sha256); +#endif +#ifdef HWCAP_SHA512 +// if (hwCap & HWCAP_SHA512) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA512); +#endif +#ifdef HWCAP_SHA3 +// if (hwCap & HWCAP_SHA3) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SHA3); +#endif +#ifdef HWCAP_ASIMD + if (hwCap & HWCAP_ASIMD) + CPUCompileFlags.Set(InstructionSet_AdvSimd); +#endif +#ifdef HWCAP_ASIMDRDM +// if (hwCap & HWCAP_ASIMDRDM) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ADVSIMD_V81); +#endif +#ifdef HWCAP_ASIMDHP +// if (hwCap & HWCAP_ASIMDHP) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_ADVSIMD_FP16); +#endif +#ifdef HWCAP_SM3 +// if (hwCap & HWCAP_SM3) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SM3); +#endif +#ifdef HWCAP_SM4 +// if (hwCap & HWCAP_SM4) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SM4); +#endif +#ifdef HWCAP_SVE +// if (hwCap & HWCAP_SVE) +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_SVE); +#endif +#else // !HAVE_AUXV_HWCAP_H + // CoreCLR SIMD and FP support is included in ARM64 baseline + // On exceptional basis platforms may leave out support, but CoreCLR does not + // yet support such platforms + // Set baseline flags if OS has not exposed mechanism for us to determine CPU capabilities + CPUCompileFlags.Set(InstructionSet_AdvSimd); +// CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FP); +#endif // HAVE_AUXV_HWCAP_H +#endif // defined(HOST_ARM64) + CPUCompileFlags.Set64BitInstructionSetVariants(); + CPUCompileFlags.EnsureValidInstructionSetSupport(); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/miscpalapi.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/miscpalapi.cpp new file mode 100644 index 0000000..3475ed2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/miscpalapi.cpp @@ -0,0 +1,313 @@ +// 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: + + miscpalapi.c + +Abstract: + + Implementation misc PAL APIs + +Revision History: + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/file.h" +#include "pal/process.h" +#include "pal/module.h" +#include "pal/malloc.hpp" +#include "pal/stackstring.hpp" + +#include +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#endif // __APPLE__ + +SET_DEFAULT_DEBUG_CHANNEL(MISC); + +static const char URANDOM_DEVICE_NAME[]="/dev/urandom"; + +/*++ + +Function : + + PAL_GetPALDirectoryW + + Returns the fully qualified path name + where the PALL DLL was loaded from. + + On failure it returns FALSE and sets the + proper LastError code. + +--*/ +BOOL +PAL_GetPALDirectoryW(PathWCharString& lpDirectoryName) +{ + LPCWSTR lpFullPathAndName = NULL; + LPCWSTR lpEndPoint = NULL; + BOOL bRet = FALSE; + + PERF_ENTRY(PAL_GetPALDirectoryW); + + MODSTRUCT *module = LOADGetPalLibrary(); + if (!module) + { + SetLastError(ERROR_INTERNAL_ERROR); + goto EXIT; + } + lpFullPathAndName = module->lib_name; + if (lpFullPathAndName == NULL) + { + SetLastError(ERROR_INTERNAL_ERROR); + goto EXIT; + } + lpEndPoint = PAL_wcsrchr( lpFullPathAndName, '/' ); + if ( lpEndPoint ) + { + /* The path that we return is required to have + the trailing slash on the end.*/ + lpEndPoint++; + + + if(!lpDirectoryName.Set(lpFullPathAndName,lpEndPoint - lpFullPathAndName)) + { + ASSERT( "The buffer was not large enough.\n" ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + goto EXIT; + } + + bRet = TRUE; + } + else + { + ASSERT( "Unable to determine the path.\n" ); + /* Error path, should not be executed. */ + SetLastError( ERROR_INTERNAL_ERROR ); + } + +EXIT: + PERF_EXIT(PAL_GetPALDirectoryW); + return bRet; +} + +BOOL +PAL_GetPALDirectoryA(PathCharString& lpDirectoryName) +{ + BOOL bRet; + PathWCharString directory; + + PERF_ENTRY(PAL_GetPALDirectoryA); + + bRet = PAL_GetPALDirectoryW(directory); + + if (bRet) + { + + int length = WideCharToMultiByte(CP_ACP, 0, directory.GetString(), -1, NULL, 0, NULL, 0); + LPSTR DirectoryName = lpDirectoryName.OpenStringBuffer(length); + if (NULL == DirectoryName) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + bRet = FALSE; + } + + length = WideCharToMultiByte(CP_ACP, 0, directory.GetString(), -1, DirectoryName, length, NULL, 0); + + if (0 == length) + { + bRet = FALSE; + length++; + } + + lpDirectoryName.CloseBuffer(length - 1); + } + + PERF_EXIT(PAL_GetPALDirectoryA); + return bRet; +} + +/*++ + +Function : + + PAL_GetPALDirectoryW + + Returns the fully qualified path name + where the PALL DLL was loaded from. + + On failure it returns FALSE and sets the + proper LastError code. + +--*/ +PALIMPORT +BOOL +PALAPI +PAL_GetPALDirectoryW( OUT LPWSTR lpDirectoryName, IN OUT UINT* cchDirectoryName ) +{ + PathWCharString directory; + BOOL bRet; + PERF_ENTRY(PAL_GetPALDirectoryW); + ENTRY( "PAL_GetPALDirectoryW( %p, %d )\n", lpDirectoryName, *cchDirectoryName ); + + bRet = PAL_GetPALDirectoryW(directory); + + if (bRet) { + + if (directory.GetCount() > *cchDirectoryName) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + bRet = FALSE; + } + else + { + PAL_wcscpy(lpDirectoryName, directory.GetString()); + } + + *cchDirectoryName = directory.GetCount(); + } + + LOGEXIT( "PAL_GetPALDirectoryW returns BOOL %d.\n", bRet); + PERF_EXIT(PAL_GetPALDirectoryW); + return bRet; + +} + +PALIMPORT +BOOL +PALAPI +PAL_GetPALDirectoryA( + OUT LPSTR lpDirectoryName, + IN UINT* cchDirectoryName) +{ + BOOL bRet; + PathCharString directory; + + PERF_ENTRY(PAL_GetPALDirectoryA); + ENTRY( "PAL_GetPALDirectoryA( %p, %d )\n", lpDirectoryName, *cchDirectoryName ); + + bRet = PAL_GetPALDirectoryA(directory); + + if (bRet) + { + if (directory.GetCount() > *cchDirectoryName) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + bRet = FALSE; + *cchDirectoryName = directory.GetCount(); + } + else if (strcpy_s(lpDirectoryName, directory.GetCount(), directory.GetString()) == SAFECRT_SUCCESS) + { + } + else + { + bRet = FALSE; + } + } + + LOGEXIT( "PAL_GetPALDirectoryA returns BOOL %d.\n", bRet); + PERF_EXIT(PAL_GetPALDirectoryA); + return bRet; +} + +VOID +PALAPI +PAL_Random( + IN OUT LPVOID lpBuffer, + IN DWORD dwLength) +{ + int rand_des = -1; + DWORD i; + long num = 0; + static BOOL sMissingDevURandom; + static BOOL sInitializedMRand; + + PERF_ENTRY(PAL_Random); + ENTRY("PAL_Random(lpBuffer=%p, dwLength=%d)\n", lpBuffer, dwLength); + + if (!sMissingDevURandom) + { + do + { + rand_des = open("/dev/urandom", O_RDONLY | O_CLOEXEC); + } + while ((rand_des == -1) && (errno == EINTR)); + + if (rand_des == -1) + { + if (errno == ENOENT) + { + sMissingDevURandom = TRUE; + } + else + { + ASSERT("PAL__open() failed, errno:%d (%s)\n", errno, strerror(errno)); + } + + // Back off and try mrand48. + } + else + { + DWORD offset = 0; + do + { + ssize_t n = read(rand_des, (BYTE*)lpBuffer + offset , dwLength - offset); + if (n == -1) + { + if (errno == EINTR) + { + continue; + } + ASSERT("read() failed, errno:%d (%s)\n", errno, strerror(errno)); + + break; + } + + offset += n; + } + while (offset != dwLength); + + _ASSERTE(offset == dwLength); + + close(rand_des); + } + } + + if (!sInitializedMRand) + { + srand48(time(NULL)); + sInitializedMRand = TRUE; + } + + // always xor srand48 over the whole buffer to get some randomness + // in case /dev/urandom is not really random + + for (i = 0; i < dwLength; i++) + { + if (i % sizeof(long) == 0) { + num = mrand48(); + } + + *(((BYTE*)lpBuffer) + i) ^= num; + num >>= 8; + } + + LOGEXIT("PAL_Random\n"); + PERF_EXIT(PAL_Random); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/msgbox.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/msgbox.cpp new file mode 100644 index 0000000..fccaf30 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/msgbox.cpp @@ -0,0 +1,416 @@ +// 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: + + msgbox.c + +Abstract: + + Implementation of Message Box. + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/critsect.h" +#include "pal/dbgmsg.h" +#include "pal/misc.h" + +#include + +SET_DEFAULT_DEBUG_CHANNEL(MISC); + +CRITICAL_SECTION msgbox_critsec; + + +/*++ +Function : + MsgBoxInitialize + + Initialize the critical sections. + +Return value: + TRUE if initialize succeeded + FALSE otherwise + +--*/ +BOOL +MsgBoxInitialize( void ) +{ + TRACE( "Initialising the critical section.\n" ); + InternalInitializeCriticalSection(&msgbox_critsec); + + return TRUE; +} + +/*++ +Function : + MsgBoxCleanup + + Deletes the critical sections. + +--*/ +void MsgBoxCleanup( void ) +{ + TRACE( "Deleting the critical section.\n" ); + DeleteCriticalSection( &msgbox_critsec ); +} + + + +#ifdef __APPLE__ +#include "CoreFoundation/CFUserNotification.h" +#include "CoreFoundation/CFString.h" +#include "Security/AuthSession.h" +#endif // __APPLE__ + + +/*++ +Function: + MessageBoxW + +This is a small subset of MessageBox that simply logs a message to the +system logging facility and returns. A typical log entry will look +like: + +May 23 15:48:10 rice example1: MessageBox: Caption: Error Text + +Note: + hWnd should always be NULL. + +See MSDN doc. +--*/ +int +PALAPI +MessageBoxW( + IN LPVOID hWnd, + IN LPCWSTR lpText, + IN LPCWSTR lpCaption, + IN UINT uType) +{ + CHAR *text = NULL; + CHAR *caption = NULL; + INT len = 0; + INT rc = 0; + + PERF_ENTRY(MessageBoxW); + ENTRY( "MessageBoxW (hWnd=%p, lpText=%p (%S), lpCaption=%p (%S), uType=%#x)\n", + hWnd, lpText?lpText:W16_NULLSTRING, lpText?lpText:W16_NULLSTRING, + lpCaption?lpCaption:W16_NULLSTRING, + lpCaption?lpCaption:W16_NULLSTRING, uType ); + + if (hWnd != NULL) + { + ASSERT("hWnd != NULL"); + } + + if(lpText) + { + len = WideCharToMultiByte(CP_ACP, 0, lpText, -1, NULL, 0, NULL, NULL); + if(len) + { + text = (LPSTR)PAL_malloc(len); + if(!text) + { + ERROR("malloc() failed!\n"); + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + goto error; + } + if( !WideCharToMultiByte( CP_ACP, 0, lpText, -1, text, len, + NULL, NULL)) + { + ASSERT("WideCharToMultiByte failure\n"); + SetLastError( ERROR_INTERNAL_ERROR ); + goto error; + } + } + else + { + ASSERT("WideCharToMultiByte failure\n"); + SetLastError( ERROR_INTERNAL_ERROR ); + goto error; + } + } + else + { + WARN("No message text\n"); + + if (NULL == (text = PAL__strdup("(no message text)"))) + { + ASSERT("strdup() failed\n"); + SetLastError( ERROR_INTERNAL_ERROR ); + goto error; + } + } + if (lpCaption) + { + len = WideCharToMultiByte( CP_ACP, 0, lpCaption, -1, NULL, 0, + NULL, NULL); + if(len) + { + caption = (CHAR*)PAL_malloc(len); + if(!caption) + { + ERROR("malloc() failed!\n"); + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + goto error; + } + if( !WideCharToMultiByte( CP_ACP, 0, lpCaption, -1, caption, len, + NULL, NULL)) + { + ASSERT("WideCharToMultiByte failure\n"); + SetLastError( ERROR_INTERNAL_ERROR ); + goto error; + } + } + else + { + ASSERT("WideCharToMultiByte failure\n"); + SetLastError( ERROR_INTERNAL_ERROR ); + goto error; + } + } + else + { + if (NULL == (caption = PAL__strdup("Error"))) + { + ERROR("strdup() failed\n"); + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + goto error; + } + } + + rc = MessageBoxA(hWnd, text, caption, uType); + +error: + PAL_free(caption); + PAL_free(text); + + + LOGEXIT("MessageBoxW returns %d\n", rc); + PERF_EXIT(MessageBoxW); + return rc; +} + + +/*++ +Function: + MessageBoxA + +This is a small subset of MessageBox that simply logs a message to the +system logging facility and returns. A typical log entry will look +like: + +May 23 15:48:10 rice example1: MessageBox: Caption: Error Text + +Note: + hWnd should always be NULL. + +See MSDN doc. +--*/ +int +PALAPI +MessageBoxA( + IN LPVOID hWnd, + IN LPCSTR lpText, + IN LPCSTR lpCaption, + IN UINT uType) +{ + INT rc = 0; + + PERF_ENTRY(MessageBoxA); + ENTRY( "MessageBoxA (hWnd=%p, lpText=%p (%s), lpCaption=%p (%s), uType=%#x)\n", + hWnd, lpText?lpText:"NULL", lpText?lpText:"NULL", + lpCaption?lpCaption:"NULL", + lpCaption?lpCaption:"NULL", uType ); + + if (hWnd != NULL) + { + ASSERT("hWnd != NULL"); + } + + if (lpText == NULL) + { + WARN("No message text\n"); + + lpText = "(no message text)"; + } + + if (lpCaption == NULL) + { + lpCaption = "Error"; + } + + if (uType & MB_DEFMASK) + { + WARN("No support for alternate default buttons.\n"); + } + + /* set default status based on the type of button */ + switch(uType & MB_TYPEMASK) + { + case MB_OK: + rc = IDOK; + break; + + case MB_ABORTRETRYIGNORE: + rc = IDABORT; + break; + + case MB_YESNO: + rc = IDNO; + break; + + case MB_OKCANCEL : + rc = IDCANCEL; + break; + + case MB_RETRYCANCEL : + rc = IDCANCEL; + break; + + default: + ASSERT("Bad uType"); + rc = IDOK; + break; + } + + PALCEnterCriticalSection( &msgbox_critsec); + +#ifdef __APPLE__ + OSStatus osstatus; + + SecuritySessionId secSession; + SessionAttributeBits secSessionInfo; + + osstatus = SessionGetInfo(callerSecuritySession, &secSession, &secSessionInfo); + if (noErr == osstatus && (secSessionInfo & sessionHasGraphicAccess) != 0) + { + CFStringRef cfsTitle = CFStringCreateWithCString(kCFAllocatorDefault, lpCaption, kCFStringEncodingUTF8); + CFStringRef cfsText = CFStringCreateWithCString(kCFAllocatorDefault, lpText, kCFStringEncodingUTF8); + CFStringRef cfsButton1 = NULL; + CFStringRef cfsButton2 = NULL; + CFStringRef cfsButton3 = NULL; + CFOptionFlags alertFlags = 0; + CFOptionFlags response; + + switch (uType & MB_TYPEMASK) + { + case MB_OK: + // Nothing needed; since if all the buttons are null, a stock "OK" is used. + break; + + case MB_ABORTRETRYIGNORE: + // Localization? Would be needed if this were used outside of debugging. + cfsButton1 = CFSTR("Abort"); + cfsButton2 = CFSTR("Retry"); + cfsButton3 = CFSTR("Ignore"); + alertFlags = kCFUserNotificationCautionAlertLevel; + break; + + case MB_YESNO: + cfsButton1 = CFSTR("Yes"); + cfsButton2 = CFSTR("No"); + break; + + case MB_OKCANCEL: + cfsButton1 = CFSTR("OK"); + cfsButton2 = CFSTR("Cancel"); + break; + + case MB_RETRYCANCEL: + cfsButton1 = CFSTR("Retry"); + cfsButton2 = CFSTR("Cancel"); + break; + } + + CFUserNotificationDisplayAlert(0 /* no time out */, alertFlags, NULL /* iconURL */, + NULL /* soundURL */, NULL /* localizationURL */, cfsTitle, cfsText, cfsButton1, + cfsButton2, cfsButton3, &response); + + switch (uType & MB_TYPEMASK) + { + case MB_OK: + break; + + case MB_ABORTRETRYIGNORE: + switch (response) + { + case kCFUserNotificationDefaultResponse: + rc = IDABORT; + break; + case kCFUserNotificationAlternateResponse: + rc = IDRETRY; + break; + case kCFUserNotificationOtherResponse: + rc = IDIGNORE; + break; + } + break; + + case MB_YESNO: + switch (response) + { + case kCFUserNotificationDefaultResponse: + rc = IDYES; + break; + case kCFUserNotificationAlternateResponse: + rc = IDNO; + break; + } + break; + + case MB_OKCANCEL: + switch (response) + { + case kCFUserNotificationDefaultResponse: + rc = IDOK; + break; + case kCFUserNotificationAlternateResponse: + rc = IDCANCEL; + break; + } + break; + + case MB_RETRYCANCEL: + switch (response) + { + case kCFUserNotificationDefaultResponse: + rc = IDRETRY; + break; + case kCFUserNotificationAlternateResponse: + rc = IDCANCEL; + break; + } + break; + } + } + else + { + // We're not in a login session, e.g., running via ssh, and so bringing + // up a message box would be bad form. + fprintf ( stderr, "MessageBox: %s: %s", lpCaption, lpText ); + syslog(LOG_USER|LOG_ERR, "MessageBox: %s: %s", lpCaption, lpText); + } +#else // __APPLE__ + fprintf ( stderr, "MessageBox: %s: %s", lpCaption, lpText ); + syslog(LOG_USER|LOG_ERR, "MessageBox: %s: %s", lpCaption, lpText); + + // Some systems support displaying a GUI dialog. (This will suspend the current thread until they hit the + // 'OK' button and allow a debugger to be attached). + PAL_DisplayDialog(lpCaption, lpText); +#endif // __APPLE__ else + + PALCLeaveCriticalSection( &msgbox_critsec); + + LOGEXIT("MessageBoxA returns %d\n", rc); + PERF_EXIT(MessageBoxA); + return rc; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/perfjitdump.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/perfjitdump.cpp new file mode 100644 index 0000000..e75d598 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/perfjitdump.cpp @@ -0,0 +1,413 @@ +// 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. +// =========================================================================== + +#if defined(__linux__) +#define JITDUMP_SUPPORTED +#endif + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" + +#include + +#ifdef JITDUMP_SUPPORTED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../inc/llvm/ELF.h" + +SET_DEFAULT_DEBUG_CHANNEL(MISC); + +namespace +{ + enum + { + JIT_DUMP_MAGIC = 0x4A695444, + JIT_DUMP_VERSION = 1, + +#if defined(HOST_X86) + ELF_MACHINE = EM_386, +#elif defined(HOST_ARM) + ELF_MACHINE = EM_ARM, +#elif defined(HOST_AMD64) + ELF_MACHINE = EM_X86_64, +#elif defined(HOST_ARM64) + ELF_MACHINE = EM_AARCH64, +#else +#error ELF_MACHINE unsupported for target +#endif + + JIT_CODE_LOAD = 0, + }; + + uint64_t GetTimeStampNS() + { +#if HAVE_CLOCK_MONOTONIC + struct timespec ts; + int result = clock_gettime(CLOCK_MONOTONIC, &ts); + + if (result != 0) + { + ASSERT("clock_gettime(CLOCK_MONOTONIC) failed: %d\n", result); + return 0; + } + else + { + return ts.tv_sec * 1000000000ULL + ts.tv_nsec; + } +#else + #error "The PAL jitdump requires clock_gettime(CLOCK_MONOTONIC) to be supported." +#endif + } + + struct FileHeader + { + FileHeader() : + magic(JIT_DUMP_MAGIC), + version(JIT_DUMP_VERSION), + total_size(sizeof(FileHeader)), + elf_mach(ELF_MACHINE), + pad1(0), + pid(getpid()), + timestamp(GetTimeStampNS()), + flags(0) + {} + + uint32_t magic; + uint32_t version; + uint32_t total_size; + uint32_t elf_mach; + uint32_t pad1; + uint32_t pid; + uint64_t timestamp; + uint64_t flags; + }; + + struct RecordHeader + { + uint32_t id; + uint32_t total_size; + uint64_t timestamp; + }; + + struct JitCodeLoadRecord + { + JitCodeLoadRecord() : + pid(getpid()), + tid(syscall(SYS_gettid)) + { + header.id = JIT_CODE_LOAD; + header.timestamp = GetTimeStampNS(); + } + + RecordHeader header; + uint32_t pid; + uint32_t tid; + uint64_t vma; + uint64_t code_addr; + uint64_t code_size; + uint64_t code_index; + // Null terminated name + // Optional native code + }; +}; + +struct PerfJitDumpState +{ + PerfJitDumpState() : + enabled(false), + fd(-1), + mmapAddr(MAP_FAILED), + mutex(PTHREAD_MUTEX_INITIALIZER), + codeIndex(0) + {} + + volatile bool enabled; + int fd; + void *mmapAddr; + pthread_mutex_t mutex; + volatile uint64_t codeIndex; + + int FatalError(bool locked) + { + enabled = false; + + if (mmapAddr != MAP_FAILED) + { + munmap(mmapAddr, sizeof(FileHeader)); + mmapAddr = MAP_FAILED; + } + + if (fd != -1) + { + close(fd); + fd = -1; + } + + if (locked) + { + pthread_mutex_unlock(&mutex); + } + + return -1; + } + + int Start(const char* path) + { + int result = 0; + + // Write file header + FileHeader header; + + result = pthread_mutex_lock(&mutex); + + if (result != 0) + return FatalError(false); + + if (enabled) + goto exit; + + char jitdumpPath[PATH_MAX]; + + result = snprintf(jitdumpPath, sizeof(jitdumpPath), "%s/jit-%i.dump", path, getpid()); + + if (result >= PATH_MAX) + return FatalError(true); + + result = open(jitdumpPath, O_CREAT|O_TRUNC|O_RDWR|O_CLOEXEC, S_IRUSR|S_IWUSR ); + + if (result == -1) + return FatalError(true); + + fd = result; + + result = write(fd, &header, sizeof(FileHeader)); + + if (result == -1) + return FatalError(true); + + result = fsync(fd); + + if (result == -1) + return FatalError(true); + + // mmap jitdump file + // this is a marker for perf inject to find the jitdumpfile + mmapAddr = mmap(nullptr, sizeof(FileHeader), PROT_READ | PROT_EXEC, MAP_PRIVATE, fd, 0); + + if (mmapAddr == MAP_FAILED) + return FatalError(true); + + enabled = true; + +exit: + result = pthread_mutex_unlock(&mutex); + + if (result != 0) + return FatalError(false); + + return 0; + } + + int LogMethod(void* pCode, size_t codeSize, const char* symbol, void* debugInfo, void* unwindInfo) + { + int result = 0; + + if (enabled) + { + size_t symbolLen = strlen(symbol); + + JitCodeLoadRecord record; + + size_t bytesRemaining = sizeof(JitCodeLoadRecord) + symbolLen + 1 + codeSize; + + record.header.timestamp = GetTimeStampNS(); + record.vma = (uint64_t) pCode; + record.code_addr = (uint64_t) pCode; + record.code_size = codeSize; + record.header.total_size = bytesRemaining; + + iovec items[] = { + // ToDo insert debugInfo and unwindInfo record items immediately before the JitCodeLoadRecord. + { &record, sizeof(JitCodeLoadRecord) }, + { (void *)symbol, symbolLen + 1 }, + { pCode, codeSize }, + }; + size_t itemsCount = sizeof(items) / sizeof(items[0]); + + size_t itemsWritten = 0; + + result = pthread_mutex_lock(&mutex); + + if (result != 0) + return FatalError(false); + + if (!enabled) + goto exit; + + // Increment codeIndex while locked + record.code_index = ++codeIndex; + + do + { + result = writev(fd, items + itemsWritten, itemsCount - itemsWritten); + + if ((size_t)result == bytesRemaining) + break; + + if (result == -1) + { + if (errno == EINTR) + continue; + + return FatalError(true); + } + + // Detect unexpected failure cases. + _ASSERTE(bytesRemaining > (size_t)result); + _ASSERTE(result > 0); + + // Handle partial write case + + bytesRemaining -= result; + + do + { + if ((size_t)result < items[itemsWritten].iov_len) + { + items[itemsWritten].iov_len -= result; + items[itemsWritten].iov_base = (void*)((size_t) items[itemsWritten].iov_base + result); + break; + } + else + { + result -= items[itemsWritten].iov_len; + itemsWritten++; + + // Detect unexpected failure case. + _ASSERTE(itemsWritten < itemsCount); + } + } while (result > 0); + } while (true); + +exit: + result = pthread_mutex_unlock(&mutex); + + if (result != 0) + return FatalError(false); + } + return 0; + } + + int Finish() + { + int result = 0; + + if (enabled) + { + enabled = false; + + // Lock the mutex + result = pthread_mutex_lock(&mutex); + + if (result != 0) + return FatalError(false); + + if (!enabled) + goto exit; + + result = munmap(mmapAddr, sizeof(FileHeader)); + + if (result == -1) + return FatalError(true); + + mmapAddr = MAP_FAILED; + + result = fsync(fd); + + if (result == -1) + return FatalError(true); + + result = close(fd); + + if (result == -1) + return FatalError(true); + + fd = -1; +exit: + result = pthread_mutex_unlock(&mutex); + + if (result != 0) + return -1; + } + return 0; + } +}; + + +PerfJitDumpState& GetState() +{ + static PerfJitDumpState s; + + return s; +} + +int +PALAPI +PAL_PerfJitDump_Start(const char* path) +{ + return GetState().Start(path); +} + +int +PALAPI +PAL_PerfJitDump_LogMethod(void* pCode, size_t codeSize, const char* symbol, void* debugInfo, void* unwindInfo) +{ + return GetState().LogMethod(pCode, codeSize, symbol, debugInfo, unwindInfo); +} + +int +PALAPI +PAL_PerfJitDump_Finish() +{ + return GetState().Finish(); +} + +#else // JITDUMP_SUPPORTED + +int +PALAPI +PAL_PerfJitDump_Start(const char* path) +{ + return 0; +} + +int +PALAPI +PAL_PerfJitDump_LogMethod(void* pCode, size_t codeSize, const char* symbol, void* debugInfo, void* unwindInfo) +{ + return 0; +} + +int +PALAPI +PAL_PerfJitDump_Finish() +{ + return 0; +} + +#endif // JITDUMP_SUPPORTED diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/perftrace.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/perftrace.cpp new file mode 100644 index 0000000..82969a1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/perftrace.cpp @@ -0,0 +1,1345 @@ +// 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: + + misc/perftrace.c + +Abstract: + Implementation of PAL Performance trace utilities. + + + +--*/ + +/* PAL headers */ + + + +#ifdef PAL_PERF + +/* PAL Headers */ +#include "pal/palinternal.h" +#include "pal/perftrace.h" +#include "pal/dbgmsg.h" +#include "pal/cruntime.h" +#include "pal/misc.h" + +/* Standard headers */ +#include +#include +#include +#include +#include /* for pthread_self */ +#include +#include + +SET_DEFAULT_DEBUG_CHANNEL(MISC); + + +#define PAL_PERF_MAX_LOGLINE 0x400 /* 1K */ +#define PAL_PERF_MAX_INPUT 0x1000 /* 4k for single line of input file */ +#define PAL_PERF_MAX_FUNCTION_NAME 128 /* any one want a function name longer than 127 bytes? */ +#define PAL_PERF_PROFILE_BUFFER_SIZE 0x400000 /* 4M */ +#define PAL_PERF_BUFFER_FULL (PAL_PERF_PROFILE_BUFFER_SIZE - PAL_PERF_MAX_LOGLINE ) /* (Buffer size - 1K) */ + +typedef struct _pal_perf_api_info +{ + ULONGLONG entries; /* number of PERF_ENTRY calls for an API function */ + ULONGLONG counter; /* number of PERF_EXIT calls for an API function */ + ULONGLONG min_duration; /* Minimum duration in CPU clock ticks in an API function */ + ULONGLONG max_duration; /* Maximum duration in CPU clock ticks in an API function */ + ULONGLONG sum_duration; /* Sum of duration*/ + double sum_of_square_duration; /* Sum of square of durations */ + DWORD *histograms; /* An array to store the histogram of an API execution cpu ticks. */ +} pal_perf_api_info; + + +typedef struct _pal_perf_thread_info +{ + DWORD threadId; + pal_perf_api_info * api_table; + char * pal_write_buf; + DWORD buf_offset; + BOOL profile_enabled; + ULONGLONG start_ticks; + ULONGLONG total_duration; +} pal_perf_thread_info; + +typedef struct _pal_thread_list_node +{ + pal_perf_thread_info * thread_info; + struct _pal_thread_list_node * next; + +} pal_thread_list_node; + +typedef struct _pal_perf_program_info +{ + char command_line[PAL_PERF_MAX_LOGLINE]; + char exe_path[PAL_PERF_MAX_LOGLINE]; + char hostname[PAL_PERF_MAX_FUNCTION_NAME]; + double cpu_clock_frequency; + ULONGLONG start_ticks; + ULONGLONG elapsed_time; /* Duration in CPU clock ticks of the program */ + ULONGLONG total_duration; /* Total CPU clock ticks of all the threads */ + ULONGLONG pal_duration; /* Total CPU clock ticks spent inside PAL */ + + pid_t process_id; + char start_time[32]; /* must be at least 26 characters */ +} pal_perf_program_info; + +typedef PAL_FILE PERF_FILE; +#define PERF_FILEFN(x) PAL_ ## x + +static ULONGLONG PERFGetTicks(); +static double PERFComputeStandardDeviation(pal_perf_api_info *api); +static void PERFPrintProgramHeaderInfo(PERF_FILE * hFile, BOOL completedExecution); +static BOOL PERFInitProgramInfo(LPWSTR command_line, LPWSTR exe_path); +static BOOL PERFReadSetting( ); +static void PERFLogFileName(PathCharString * destFileString, const char *fileName, const char *suffix, int max_length); +static void PERFlushAllLogs(); +static int PERFWriteCounters(pal_perf_api_info * table); +static BOOL PERFFlushLog(pal_perf_thread_info * local_buffer, BOOL output_header); +static void PERFUpdateApiInfo(pal_perf_api_info *api, ULONGLONG duration); +static char * PERFIsValidPath( const char * path ); +static char * PERFIsValidFile( const char * path, const char * file); + +typedef char PAL_API_NAME[PAL_PERF_MAX_FUNCTION_NAME]; + +static PAL_API_NAME API_list[PAL_API_NUMBER] ; +static pal_perf_program_info program_info; + +static pthread_key_t PERF_tlsTableKey=0 ; + +static pal_thread_list_node * process_pal_thread_list=NULL; +static BOOL pal_profile_on=FALSE; +static BOOL pal_perf_enabled=FALSE; +static char * pal_function_map=NULL; +static char * perf_default_path=NULL; +static char * traced_apis_file=NULL; +static char * enabledapis_path=NULL; +static char * profile_log_path=NULL; +static char * profile_summary_log_name=NULL; +static char * profile_time_log_name=NULL; +static BOOL summary_only=FALSE; +static BOOL nested_tracing=FALSE; +static BOOL calibrate=FALSE; + +/* If report_only_called_apis is TRUE, + those PAL APIs with no function entry or exit + will not be shown in the PAL perf summary file. */ +static BOOL report_only_called_apis=FALSE; + +/* If the wait_for_startup is TRUE, process profiling + will not start until the application + has called PAL_EnableProcessProfile(). */ +static BOOL wait_for_startup=FALSE; + +/* The size of a PAL API execution CPU ticks histogram, i.e., + Number of categories of frequency distrubution of PAL API + execution CPU ticks.*/ +static DWORD pal_perf_histogram_size = 0; + +/* The step size in CPU ticks of each category of the + PAL API execution CPU ticks histogram.*/ +static DWORD pal_perf_histogram_step = 100; + +static const char PAL_PERF_TRACING[]="PAL_PERF_TRACING"; +static const char PAL_DEFAULT_PATH[]="PAL_PERF_DEFAULT_PATH"; +static const char PAL_PERF_TRACEDAPIS_PATH[]="PAL_PERF_TRACEDAPIS_FILE"; +static const char PAL_PERF_LOG_PATH[]="PAL_PERF_LOG_PATH"; +static const char PAL_PERF_SUMMARY_LOG_NAME[]="PAL_PERF_SUMMARY_LOG_NAME"; +static const char PAL_PERF_TIME_LOG_NAME[]="PAL_PERF_TIME_LOG_NAME"; +static const char PAL_PERF_ENABLED_APIS_PATH[]="PAL_PERF_ENABLEDAPIS_FILE"; +static const char PAL_SUMMARY_FLAG[]="PAL_PERF_SUMMARY_ONLY"; +static const char PAL_PERF_NESTED_TRACING[]="PAL_PERF_NESTED_TRACING"; +static const char PAL_PERF_CALIBRATE[]="PAL_PERF_CALIBRATE"; +static const char PAL_PERF_REPORT_ONLY_CALLED_APIS[]="PAL_PERF_REPORT_ONLY_CALLED_APIS"; +static const char PAL_PERF_WAIT_FOR_STARTUP[]="PAL_PERF_WAIT_FOR_STARTUP"; +static const char PAL_PERF_HISTOGRAM_SIZE[]="PAL_PERF_HISTOGRAM_SIZE"; +static const char PAL_PERF_HISTOGRAM_STEP[]="PAL_PERF_HISTOGRAM_STEP"; +static const char traced_apis_filename[]="PerfTracedAPIs.txt"; +static const char perf_enabled_filename[]="AllPerfEnabledAPIs.txt"; +static const char PATH_SEPARATOR[] = "/"; + + + +#define LLFORMAT "%llu" + +static +ULONGLONG +PERFGetTicks(){ +#ifdef HOST_X86 // for BSD and Windows. + unsigned long a, d; + #ifdef _MSC_VER + __asm{ + rdtsc + mov a, eax + mov d, edx + } + #else + #undef volatile + asm volatile("rdtsc":"=a" (a), "=d" (d)); + #define volatile DoNotUseVolatileKeyword + #endif + return ((ULONGLONG)((unsigned int)(d)) << 32) | (unsigned int)(a); +#else + return 0; // on non-BSD and non-Windows, we'll return 0 for now. +#endif // HOST_X86 +} + +static +double +PERFComputeStandardDeviation(pal_perf_api_info *api) +{ + double n; + double sum_of_variance; + if (api->counter <= 1) + return 0.0; + n = (double) api->counter; + // Calculates standard deviation based on the entire population given as arguments. + // Same as stdevp in Excel. + sum_of_variance = (n*api->sum_of_square_duration) - (api->sum_duration*api->sum_duration); + if (sum_of_variance <= 0.0) + return 0.0; + return sqrt(sum_of_variance/(n*n)); +} + + +static +void +PERFPrintProgramHeaderInfo(PERF_FILE * hFile, BOOL completedExecution) +{ + ULONGLONG etime = 0; + ULONGLONG ttime = 0; + ULONGLONG ptime = 0; + if (completedExecution) { + etime = program_info.elapsed_time; + ttime = program_info.total_duration; + ptime = program_info.pal_duration; + } + PERF_FILEFN(fprintf)(hFile,"#LOG\tversion=1.00\n"); + + PERF_FILEFN(fprintf)(hFile, "#MACHINE\thostname=%s\tcpu_clock_frequency=%g\n", program_info.hostname, + program_info.cpu_clock_frequency); + PERF_FILEFN(fprintf)(hFile, "#PROCESS\tprocess_id=%d\ttotal_latency=" LLFORMAT "\tthread_times=" LLFORMAT "\tpal_time=" LLFORMAT "\texe_path=%s\tcommand_line=%s\tstart_time=%s", + program_info.process_id, etime, ttime, ptime, + program_info.exe_path,program_info.command_line,program_info.start_time); +} + +static +BOOL +PERFInitProgramInfo(LPWSTR command_line, LPWSTR exe_path) +{ + ULONGLONG start_tick; + struct timeval tv; + + if (WideCharToMultiByte(CP_ACP, 0, command_line, -1, + program_info.command_line, PAL_PERF_MAX_LOGLINE-1, NULL, NULL) == 0) + return FALSE; + if (WideCharToMultiByte(CP_ACP, 0, exe_path, -1, + program_info.exe_path, PAL_PERF_MAX_LOGLINE-1, NULL, NULL) == 0) + return FALSE; + + gethostname(program_info.hostname, PAL_PERF_MAX_FUNCTION_NAME); + program_info.process_id = getpid(); + + gettimeofday(&tv, NULL); + ctime_r(&tv.tv_sec, program_info.start_time); + + // estimate the cpu clock cycles + start_tick = PERFGetTicks(); + if (start_tick != 0) + { + sleep(1); + program_info.cpu_clock_frequency = (double) (PERFGetTicks() - start_tick); + } + else + { + program_info.cpu_clock_frequency = 0.0; + } + + program_info.start_ticks = 0; + program_info.elapsed_time = 0; + program_info.total_duration = 0; + program_info.pal_duration = 0; + + return TRUE; +} + +static +void +PERFCalibrationFunction() +{ + PERF_ENTRY(CalibrationFunction); + PERF_EXIT(CalibrationFunction); +} + +void +PERFCalibrate(const char* msg) +{ + ULONGLONG start_tick, cal_ticks; + int i=0; + int cal_length=100000; + + if (calibrate) { + start_tick = PERFGetTicks(); + for(i=0; ithread_info = local_info; + local_info->api_table=apiTable; + local_info->threadId = THREADSilentGetCurrentThreadId(); + + for (i = 0; i < PAL_API_NUMBER; i++) + { + apiTable[i].entries = 0; + apiTable[i].counter = 0; + apiTable[i].min_duration = _UI64_MAX; + apiTable[i].max_duration = 0; + apiTable[i].sum_duration = 0; + apiTable[i].sum_of_square_duration = 0.0; + if (pal_perf_histogram_size > 0) + { + apiTable[i].histograms = (DWORD *)PAL_malloc(pal_perf_histogram_size*sizeof(DWORD)); + if (apiTable[i].histograms == NULL) + { + ret = FALSE; + goto PERFAllocThreadInfoExit; + } + memset(apiTable[i].histograms, 0, pal_perf_histogram_size*sizeof(DWORD)); + } + else + { + apiTable[i].histograms = NULL; + } + } + + log_buf = (char * )PAL_malloc( PAL_PERF_PROFILE_BUFFER_SIZE ); + + if(log_buf == NULL) + { + ret = FALSE; + goto PERFAllocThreadInfoExit; + } + + local_info->pal_write_buf=log_buf; + local_info->buf_offset = 0; + local_info->profile_enabled = FALSE; + local_info->total_duration = 0; + local_info->start_ticks = 0; + memset(log_buf, 0, PAL_PERF_PROFILE_BUFFER_SIZE); + + if (pthread_setspecific(PERF_tlsTableKey, local_info) != 0) + ret = FALSE; + +PERFAllocThreadInfoExit: + if (ret == TRUE) + { + node->next = process_pal_thread_list; + process_pal_thread_list = node; + PERFFlushLog(local_info, TRUE); + } + else + { + if (node != NULL) + { + PAL_free(node); + } + if (local_info != NULL) + { + PAL_free(local_info); + } + if (apiTable != NULL) + { + for (i = 0; i < PAL_API_NUMBER; i++) + { + if (apiTable[i].histograms != NULL) + { + PAL_free(apiTable[i].histograms); + } + } + PAL_free(apiTable); + } + if (log_buf != NULL) + { + PAL_free(log_buf); + } + } + return ret; +} + +static +void +PERFUpdateProgramInfo(pal_perf_thread_info* local_info) +{ + int i; + + if (!local_info) return; + + // add the elapsed time to the program's total + if (local_info->total_duration == 0) + { + // this thread did not go through PERFDisableThreadProfile code + // so compute the total elapsed time for the thread here + local_info->total_duration = PERFGetTicks() - local_info->start_ticks; + } + program_info.total_duration += local_info->total_duration; + + // Add up all the time spent in PAL + if (local_info->api_table) { + for(i=0; iapi_table[i].sum_duration; + } + } +} + + +static +void +PERFlushAllLogs( ) +{ + pal_thread_list_node * current, * node; + pal_perf_api_info * table1, *table0; + int i; + node = process_pal_thread_list; + if(node == NULL || node->thread_info == NULL || node->thread_info->api_table == NULL ) // should not come here + { + return ; + } + process_pal_thread_list = process_pal_thread_list->next; + table0 = node->thread_info->api_table; + + PERFUpdateProgramInfo(node->thread_info); + + while(process_pal_thread_list) + { + current=process_pal_thread_list; + process_pal_thread_list = process_pal_thread_list->next; + if (current->thread_info) + { + if (current->thread_info->api_table) + { + table1 = current->thread_info->api_table; + for(i=0;i table1[i].min_duration) + table0[i].min_duration = table1[i].min_duration; + if (table0[i].max_duration < table1[i].max_duration) + table0[i].max_duration = table1[i].max_duration; + table0[i].sum_duration += table1[i].sum_duration; + table0[i].sum_of_square_duration += table1[i].sum_of_square_duration; + } + PERFUpdateProgramInfo(current->thread_info); + if (table1->histograms != NULL) + { + PAL_free(table1->histograms); + } + PAL_free(table1); + } + PERFFlushLog(current->thread_info, FALSE); + PAL_free(current->thread_info->pal_write_buf); + PAL_free(current->thread_info); + } + PAL_free(current); + } + PERFWriteCounters(table0); + if (table0->histograms != NULL) + { + PAL_free(table0->histograms); + } + PAL_free(table0); + PERFFlushLog(node->thread_info, FALSE); + PAL_free(node->thread_info->pal_write_buf); + PAL_free(node->thread_info); + PAL_free(node); +} + +static +void +PERFLogFileName(PathCharString& destFileString, const char *fileName, const char *suffix) +{ + const char *dir_path; + CPalThread* pThread = InternalGetCurrentThread(); + dir_path = (profile_log_path == NULL) ? "." : profile_log_path; + + destFileString.Append(dir_path, strlen(dir_path)); + destFileString.Append(PATH_SEPARATOR, strlen(PATH_SEPARATOR)); + if (fileName != NULL) + { + destFileString.Append(fileName, strlen(fileName)); + } + else + { + char buffer[33]; + char* process_id = itoa(program_info.process_id, buffer, 10); + destFileString.Append(process_id, strlen(process_id)); + destFileString.Append("_", 1); + + char* current_thread = itoa(THREADSilentGetCurrentThreadId(),buffer, 10); + destFileString.Append(current_thread, strlen( current_thread)); + destFileString.Append(suffix, strlen(suffix)); + } + +} + +static +int +PERFWriteCounters( pal_perf_api_info * table ) +{ + PathCharString fileName; + pal_perf_api_info * off; + PERF_FILE * hFile; + int i; + + off = table; + + PERFLogFileName(fileName, profile_summary_log_name, "_perf_summary.log"); + hFile = PERF_FILEFN(fopen)(fileName, "a+"); + if(hFile != NULL) + { + PERFPrintProgramHeaderInfo(hFile, TRUE); + PERF_FILEFN(fprintf)(hFile,"#api_name\tapi_id\tperf_entries\tperf_exits\tsum_of_latency\tmin_latency\tmax_latency\tstd_dev_latency\tsum_of_square_latency\n"); + for(i=0;imin_duration == _UI64_MAX) ? 0 : off->min_duration; + if (off->counter >= 1) + { + dev = PERFComputeStandardDeviation(off); + } + else + { + dev = 0.0; + } + + if (off->counter > 0 || !report_only_called_apis) + { + PERF_FILEFN(fprintf)(hFile,"%s\t%d\t" LLFORMAT "\t" LLFORMAT "\t" LLFORMAT "\t" LLFORMAT "\t" LLFORMAT "\t%g\t%g\n", + API_list[i], i, off->entries, off->counter,off->sum_duration, + min_duration, off->max_duration, dev, off->sum_of_square_duration); + } + + off++; + } + } + else + { + return -1; + } + PERF_FILEFN(fclose)(hFile); + + if (pal_perf_histogram_size > 0) + { + off = table; + PERFLogFileName(fileName, profile_summary_log_name, "_perf_summary.hist"); + hFile = PERF_FILEFN(fopen)(fileName, "a+"); + + if (hFile != NULL) + { + DWORD j; + PERF_FILEFN(fprintf)(hFile,"#api_name\tapi_id"); + for (j = 0; j < pal_perf_histogram_size; j++) + { + PERF_FILEFN(fprintf)(hFile, "\t%d", j*pal_perf_histogram_step); + } + PERF_FILEFN(fprintf)(hFile, "\n"); + + for(i = 0; i < PAL_API_NUMBER; i++) + { + if (off->counter > 0) + { + PERF_FILEFN(fprintf)(hFile,"%s\t%d", API_list[i], i); + + for (j = 0; j < pal_perf_histogram_size; j++) + { + PERF_FILEFN(fprintf)(hFile, "\t%d", off->histograms[j]); + } + + PERF_FILEFN(fprintf)(hFile, "\n"); + } + + off++; + } + } + else + { + return -1; + } + PERF_FILEFN(fclose)(hFile); + } + + return 0; +} + +static +BOOL +PERFReadSetting( ) +{ + // this function is not safe right now. + //more code is required to deal with corrupted input file. + BOOL ret; + unsigned int index; + char line[PAL_PERF_MAX_INPUT]; + char * ptr; + char function_name[PAL_PERF_MAX_FUNCTION_NAME]; //no function can be longer than 127 bytes. + + char * file_name_buf; + PathCharString file_name_bufPS; + char * input_file_name; + char * summary_flag_env; + char * nested_tracing_env; + char * calibrate_env; + char * report_only_called_apis_env; + char * wait_for_startup_env; + char * pal_perf_histogram_size_env; + char * pal_perf_histogram_step_env; + + PAL_FILE * hFile; + + if((pal_function_map == NULL) || (PAL_API_NUMBER < 0) ) + { + // should not be here. + } + + /* do some env setting here */ + summary_flag_env = MiscGetenv(PAL_SUMMARY_FLAG); + if (summary_flag_env == NULL || strlen(summary_flag_env) == 0) + { + summary_only = FALSE; + } + else + { + summary_only = TRUE; + } + nested_tracing_env = MiscGetenv(PAL_PERF_NESTED_TRACING); + if (nested_tracing_env == NULL || strlen(nested_tracing_env) == 0) + { + nested_tracing = FALSE; + } + else + { + nested_tracing = TRUE; + } + + calibrate_env = MiscGetenv(PAL_PERF_CALIBRATE); + if (calibrate_env == NULL || strlen(calibrate_env) == 0) + { + calibrate = FALSE; + } + else + { + calibrate = TRUE; + } + + report_only_called_apis_env = MiscGetenv(PAL_PERF_REPORT_ONLY_CALLED_APIS); + if (report_only_called_apis_env == NULL || strlen(report_only_called_apis_env) == 0) + { + report_only_called_apis = FALSE; + } + else + { + report_only_called_apis = TRUE; + } + + wait_for_startup_env = MiscGetenv(PAL_PERF_WAIT_FOR_STARTUP); + if (wait_for_startup_env == NULL || strlen(wait_for_startup_env) == 0) + { + wait_for_startup = FALSE; + } + else + { + wait_for_startup = TRUE; + } + + pal_perf_histogram_size_env = MiscGetenv(PAL_PERF_HISTOGRAM_SIZE); + if (pal_perf_histogram_size_env != NULL && strlen(pal_perf_histogram_size_env) > 0) + { + long value; + char *endptr; + value = strtol(pal_perf_histogram_size_env, &endptr, 10); + if (value > 0) + { + pal_perf_histogram_size = (DWORD) value; + } + } + + pal_perf_histogram_step_env = MiscGetenv(PAL_PERF_HISTOGRAM_STEP); + if (pal_perf_histogram_step_env != NULL && strlen(pal_perf_histogram_step_env) > 0) + { + long value; + char *endptr; + value = strtol(pal_perf_histogram_step_env, &endptr, 10); + if (value > 0) + { + pal_perf_histogram_step = (DWORD) value; + } + } + + traced_apis_file = PERFIsValidFile("", MiscGetenv(PAL_PERF_TRACEDAPIS_PATH)); + enabledapis_path = PERFIsValidFile("", MiscGetenv(PAL_PERF_ENABLED_APIS_PATH)); + profile_log_path = PERFIsValidPath(MiscGetenv(PAL_PERF_LOG_PATH)); + perf_default_path = PERFIsValidPath( MiscGetenv(PAL_DEFAULT_PATH)); + profile_summary_log_name = MiscGetenv(PAL_PERF_SUMMARY_LOG_NAME); + if (profile_summary_log_name != NULL && strlen(profile_summary_log_name) == 0) + profile_summary_log_name = NULL; + profile_time_log_name = MiscGetenv(PAL_PERF_TIME_LOG_NAME); + if (profile_time_log_name != NULL && strlen(profile_time_log_name) == 0) + profile_time_log_name = NULL; + + if( traced_apis_file == NULL) + { + if(perf_default_path==NULL) + { + ret=FALSE; + input_file_name = NULL; + } + else + { + if( PERFIsValidFile(perf_default_path,traced_apis_filename)) + { + int length = strlen(perf_default_path) + strlen(PATH_SEPARATOR) + strlen(traced_apis_filename); + file_name_buf = file_name_bufPS.OpenStringBuffer(length); + if ((strcpy_s(file_name_buf, file_name_bufPS.GetSizeOf(), perf_default_path) != SAFECRT_SUCCESS) || + (strcat_s(file_name_buf, file_name_bufPS.GetSizeOf(), PATH_SEPARATOR) != SAFECRT_SUCCESS) || + (strcat_s(file_name_buf, file_name_bufPS.GetSizeOf(), traced_apis_filename) != SAFECRT_SUCCESS)) + { + file_name_bufPS.CloseBuffer(0); + ret = FALSE; + input_file_name = NULL; + } + else + { + file_name_bufPS.CloseBuffer(length); + input_file_name = file_name_buf; + } + } + else + { + ret = FALSE; + input_file_name=NULL; + } + } + } + else + { + input_file_name=traced_apis_file; + } + + if(input_file_name) + { + hFile = PAL_fopen(input_file_name, "r+"); + if ( hFile == NULL ) + { + memset(pal_function_map, 1, PAL_API_NUMBER); + ret = FALSE; + } + else + { + memset(pal_function_map, 0, PAL_API_NUMBER); + + PAL_fseek(hFile, 0L, SEEK_SET); + + /* Read a line of data from file: */ + while ( PAL_fgets(line, PAL_PERF_MAX_INPUT, hFile) != NULL ) + { + if(strlen(line)==0) + continue; + ptr = strchr( line, '#'); + if( ptr ) + continue; + sscanf_s(line, "%s %u", function_name,&index); + + if( index >= PAL_API_NUMBER) + { + // some code here to deal with incorrect index. + // use function name to cover it. + } + else if(pal_function_map[index]==1) + { + // some code here to deal with conflict index. + // use function name to cover it. + } + else + { + pal_function_map[index]=1; + } + + } + + PAL_fclose(hFile); + ret = TRUE; + } + } + else + { + memset(pal_function_map, 1, PAL_API_NUMBER); + ret = FALSE; + } + + if( enabledapis_path == NULL) + { + if(perf_default_path==NULL) + { + input_file_name = NULL; + } + else + { + if( PERFIsValidFile(perf_default_path,perf_enabled_filename)) + { + if ((strcpy_s(file_name_buf, sizeof(file_name_buf), perf_default_path) != SAFECRT_SUCCESS) || + (strcat_s(file_name_buf, sizeof(file_name_buf), PATH_SEPARATOR) != SAFECRT_SUCCESS) || + (strcat_s(file_name_buf, sizeof(file_name_buf), perf_enabled_filename) != SAFECRT_SUCCESS)) + { + ret = FALSE; + input_file_name = NULL; + } + else + { + input_file_name = file_name_buf; + } + } + else + { + input_file_name=NULL; + } + } + } + else + { + input_file_name=enabledapis_path; + } + + if(input_file_name == NULL) + { + return ret; + } + + hFile = PAL_fopen(input_file_name, "r+"); + + if ( hFile != NULL ) + { + PAL_fseek(hFile, 0L, SEEK_SET); + + /* Read a line of data from file: */ + while (PAL_fgets(line, PAL_PERF_MAX_INPUT, hFile) != NULL) + { + if(strlen(line)==0) + continue; + ptr = strchr( line, '#'); + if( ptr ) + continue; + sscanf_s(line, "%s %u", function_name,&index); + + if( index >= PAL_API_NUMBER) + { + // some code here to deal with incorrect index. + // use function name to cover it. + continue; + } + + if (strcpy_s(API_list[index], sizeof(API_list[index]), function_name) != SAFECRT_SUCCESS) + { + ret = FALSE; + break; + } + } + + PAL_fclose(hFile); + } + + return ret; + +} + + +static +BOOL +PERFFlushLog(pal_perf_thread_info * local_info, BOOL output_header) +{ + BOOL ret = FALSE; + PathCharString fileName; + int nWrittenBytes = 0; + PERF_FILE * hFile; + + if (summary_only) + return TRUE; + + PERFLogFileName(fileName, profile_time_log_name, "_perf_time.log"); + + hFile = PERF_FILEFN(fopen)(fileName, "a+"); + + if(hFile) + { + if (output_header) + { + PERFPrintProgramHeaderInfo(hFile, FALSE); + } + if (local_info->buf_offset > 0) + { + nWrittenBytes = PERF_FILEFN(fwrite)(local_info->pal_write_buf, local_info->buf_offset, 1, hFile); + if (nWrittenBytes < 1) + { + ERROR("fwrite() failed with errno == %d\n", errno); + return ret; + } + local_info->buf_offset = 0; + } + PERF_FILEFN(fclose)(hFile); + ret = TRUE; + } + + return ret; +} + +void +PERFLogFunctionEntry(unsigned int pal_api_id, ULONGLONG *pal_perf_start_tick ) +{ + pal_perf_thread_info * local_info=NULL; + pal_perf_api_info * table; + char * write_buf; + __int32 buf_off; + short bufused = 0; + + + struct timeval tv; + + + if(!pal_perf_enabled || pal_function_map==NULL || !pal_profile_on ) // haven't initialize, just quit. + return; + + if( pal_function_map[pal_api_id] ) + { + local_info= (pal_perf_thread_info * )pthread_getspecific(PERF_tlsTableKey); + + if (local_info==NULL ) + { + return; + } + if ( !local_info->profile_enabled ) /* prevent recursion. */ + { + return; + } + // turn on this flag before call any other functions + local_info->profile_enabled = FALSE; + table = local_info->api_table; + table[pal_api_id].entries++; + + if(!summary_only) + { + write_buf = (local_info->pal_write_buf); + if(local_info->buf_offset >= PAL_PERF_BUFFER_FULL) + { + PERFFlushLog(local_info, FALSE); + } + + gettimeofday(&tv, NULL); + + buf_off = local_info->buf_offset; + + bufused = snprintf(&write_buf[buf_off], PAL_PERF_MAX_LOGLINE, "----> %d %lu %06u entry.\n", pal_api_id, tv.tv_sec, tv.tv_usec ); + local_info->buf_offset += bufused; + } + if(nested_tracing) + local_info->profile_enabled = TRUE; + *pal_perf_start_tick = PERFGetTicks(); + } + return; +} + +static +void +PERFUpdateApiInfo(pal_perf_api_info *api, ULONGLONG duration) +{ + DWORD iBucket; + + api->counter++; + if (api->min_duration > duration) + api->min_duration = duration; + if (api->max_duration < duration) + api->max_duration = duration; + api->sum_duration += duration; + api->sum_of_square_duration += (double) duration * (double)duration; + + if (pal_perf_histogram_size > 0) + { + iBucket = (DWORD)(duration / pal_perf_histogram_step); + if (iBucket >= pal_perf_histogram_size) + { + iBucket = pal_perf_histogram_size - 1; + } + api->histograms[iBucket]++; + } + +} + +void +PERFLogFunctionExit(unsigned int pal_api_id, ULONGLONG *pal_perf_start_tick ) +{ + + pal_perf_thread_info * local_info; + char * buf; + short bufused = 0; + DWORD off; + ULONGLONG duration = 0; + struct timeval timev; + + + if(!pal_perf_enabled || (pal_function_map == NULL) || !pal_profile_on ) // haven't initiallize yet, just quit. + return; + + if (*pal_perf_start_tick != 0) + { + duration = PERFGetTicks() - *pal_perf_start_tick; + } + else + { + return; // pal_perf_start_tick == 0 indicates that we exited PERFLogFunctionEntry before getting the ticks. + } + + if( pal_function_map[pal_api_id] ) + { + local_info = (pal_perf_thread_info*)pthread_getspecific(PERF_tlsTableKey); + + if (NULL == local_info ){ + return; + } + PERFUpdateApiInfo(&local_info->api_table[pal_api_id], duration); + *pal_perf_start_tick = 0; + + if(summary_only) + { + local_info->profile_enabled = TRUE; + return; + } + + gettimeofday(&timev, NULL); + + buf = local_info->pal_write_buf; + if(local_info->buf_offset >= PAL_PERF_BUFFER_FULL) + { + PERFFlushLog(local_info, FALSE); + } + off = local_info->buf_offset; + + bufused = snprintf(&buf[off], PAL_PERF_MAX_LOGLINE, "<---- %d %lu %06u exit. \n", pal_api_id, timev.tv_sec, timev.tv_usec ); + local_info->buf_offset += bufused; + local_info->profile_enabled = TRUE; + } + return; +} + +void +PERFNoLatencyProfileEntry(unsigned int pal_api_id ) +{ + pal_perf_thread_info * local_info=NULL; + pal_perf_api_info * table; + + if(!pal_perf_enabled || pal_function_map==NULL || !pal_profile_on ) // haven't initialize, just quit. + return; + if( pal_function_map[pal_api_id] ) + { + local_info= (pal_perf_thread_info * )pthread_getspecific(PERF_tlsTableKey); + if (local_info==NULL ) + { + return; + } + else{ + table = local_info->api_table; + table[pal_api_id].entries++; + } + } + return; +} + + +void +PERFEnableThreadProfile(BOOL isInternal) +{ + pal_perf_thread_info * local_info; + if (!pal_perf_enabled) + return; + if (NULL != (local_info = (pal_perf_thread_info*)pthread_getspecific(PERF_tlsTableKey))) + { + if (!isInternal || nested_tracing) { + local_info->profile_enabled = TRUE; + local_info->start_ticks = PERFGetTicks(); + } + } +} + + +void +PERFDisableThreadProfile(BOOL isInternal) +{ + pal_perf_thread_info * local_info; + if (!pal_perf_enabled) + return; + if (NULL != (local_info = (pal_perf_thread_info*)pthread_getspecific(PERF_tlsTableKey))) + { + if (!isInternal || nested_tracing) { + local_info->profile_enabled = FALSE; + local_info->total_duration = PERFGetTicks() - local_info->start_ticks; + } + } +} + + +void +PERFEnableProcessProfile( ) +{ + if (!pal_perf_enabled || wait_for_startup) + return; + pal_profile_on = TRUE; + PERFCalibrate("Overhead when profiling is disabled temporarily for a thread"); + // record the cpu clock ticks at the beginning of the profiling. + program_info.start_ticks = PERFGetTicks(); +} + + +void +PERFDisableProcessProfile( ) +{ + if (!pal_perf_enabled) + return; + pal_profile_on = FALSE; + // compute the total program duration in cpu clock ticks. + if (program_info.start_ticks != 0) + { + program_info.elapsed_time += (PERFGetTicks() - program_info.start_ticks); + program_info.start_ticks = 0; + } +} + +BOOL +PERFIsProcessProfileEnabled( ) +{ + return pal_profile_on; +} + +static +char * +PERFIsValidPath( const char * path ) +{ + DIR * dir; + + if(( path==NULL) || (strlen(path)==0)) + return NULL; + + dir = opendir(path); + if( dir!=NULL) + { + closedir(dir); + return ((char *)path); + } + return NULL; +} + +static +char * +PERFIsValidFile( const char * path, const char * file) +{ + FILE * hFile; + char * temp; + PathCharString tempPS; + + if(file==NULL || strlen(file)==0) + return NULL; + + if ( strcmp(path, "") ) + { + int length = strlen(path) + strlen(PATH_SEPARATOR) + strlen(file); + temp = tempPS.OpenStringBuffer(length); + if ((strcpy_s(temp, sizeof(temp), path) != SAFECRT_SUCCESS) || + (strcat_s(temp, sizeof(temp), PATH_SEPARATOR) != SAFECRT_SUCCESS) || + (strcat_s(temp, sizeof(temp), file) != SAFECRT_SUCCESS)) + { + tempPS.CloseBuffer(0); + return NULL; + } + + tempPS.CloseBuffer(length); + hFile = fopen(temp, "r"); + } + else + { + hFile = fopen(file, "r"); + } + + if(hFile) + { + fclose(hFile); + return ((char *) file); + } + else + return NULL; + +} + +PALIMPORT +VOID +PALAPI +PAL_EnableProcessProfile(VOID) +{ + wait_for_startup = FALSE; + pal_profile_on = TRUE; + PERFEnableProcessProfile(); +} + +PALIMPORT +VOID +PALAPI +PAL_DisableProcessProfile(VOID) +{ + pal_profile_on = FALSE; + PERFDisableProcessProfile(); +} + +PALIMPORT +BOOL +PALAPI +PAL_IsProcessProfileEnabled(VOID) +{ + return PERFIsProcessProfileEnabled(); +} + +PALIMPORT +INT64 +PALAPI +PAL_GetCpuTickCount(VOID) +{ + return PERFGetTicks(); +} + +#endif /* PAL_PERF */ + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/strutil.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/strutil.cpp new file mode 100644 index 0000000..6c03256 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/strutil.cpp @@ -0,0 +1,96 @@ +// 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: + + strutil.cpp + +Abstract: + Various string-related utility functions + + + +--*/ + +#include "pal/corunix.hpp" +#include "pal/thread.hpp" +#include "pal/malloc.hpp" +#include "pal/dbgmsg.h" + +SET_DEFAULT_DEBUG_CHANNEL(PAL); + +using namespace CorUnix; + +/*++ +Function: + CPalString::CopyString + + Copies a CPalString into a new (empty) instance, allocating buffer space + as necessary + +Parameters: + psSource -- the string to copy from +--*/ + +PAL_ERROR +CPalString::CopyString( + CPalString *psSource + ) +{ + PAL_ERROR palError = NO_ERROR; + + _ASSERTE(NULL != psSource); + _ASSERTE(NULL == m_pwsz); + _ASSERTE(0 == m_dwStringLength); + _ASSERTE(0 == m_dwMaxLength); + + if (0 != psSource->GetStringLength()) + { + _ASSERTE(psSource->GetMaxLength() > psSource->GetStringLength()); + + WCHAR *pwsz = reinterpret_cast( + InternalMalloc(psSource->GetMaxLength() * sizeof(WCHAR)) + ); + + if (NULL != pwsz) + { + _ASSERTE(NULL != psSource->GetString()); + + CopyMemory( + pwsz, + psSource->GetString(), + psSource->GetMaxLength() * sizeof(WCHAR) + ); + + m_pwsz = pwsz; + m_dwStringLength = psSource->GetStringLength(); + m_dwMaxLength = psSource->GetMaxLength(); + } + else + { + palError = ERROR_OUTOFMEMORY; + } + } + + return palError; +} + +/*++ +Function: + CPalString::FreeBuffer + + Frees the contained string buffer + +--*/ + +void +CPalString::FreeBuffer() +{ + _ASSERTE(NULL != m_pwsz); + free(const_cast(m_pwsz)); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/sysinfo.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/sysinfo.cpp new file mode 100644 index 0000000..17efa17 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/sysinfo.cpp @@ -0,0 +1,629 @@ +// 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: + + sysinfo.c + +Abstract: + + Implements GetSystemInfo. + +Revision History: + + + +--*/ + +#include "pal/palinternal.h" + +#include +#include +#include +#define __STDC_FORMAT_MACROS +#include +#include + +#if HAVE_SYSCONF +// already included above +#elif HAVE_SYSCTL +#include +#else +#error Either sysctl or sysconf is required for GetSystemInfo. +#endif + +#if HAVE_SYSCTLBYNAME +#include +#endif + +#if HAVE_SYSINFO +#include +#endif + +#include + +#if HAVE_SYS_VMPARAM_H +#include +#endif // HAVE_SYS_VMPARAM_H + +#if HAVE_XSWDEV +#include +#endif // HAVE_XSWDEV + +#if HAVE_MACH_VM_TYPES_H +#include +#endif // HAVE_MACH_VM_TYPES_H + +#if HAVE_MACH_VM_PARAM_H +#include +#endif // HAVE_MACH_VM_PARAM_H + +#if HAVE_MACHINE_VMPARAM_H +#include +#endif // HAVE_MACHINE_VMPARAM_H + +#if defined(TARGET_OSX) +#include +#include +#include +#include +#endif // defined(TARGET_OSX) + +// On some platforms sys/user.h ends up defining _DEBUG; if so +// remove the definition before including the header and put +// back our definition afterwards +#if USER_H_DEFINES_DEBUG +#define OLD_DEBUG _DEBUG +#undef _DEBUG +#endif +#include +#if USER_H_DEFINES_DEBUG +#undef _DEBUG +#define _DEBUG OLD_DEBUG +#undef OLD_DEBUG +#endif + +#include "pal/dbgmsg.h" +#include "pal/process.h" + +#include + +#if HAVE_SWAPCTL +#include +#endif + +SET_DEFAULT_DEBUG_CHANNEL(MISC); + +#ifndef __APPLE__ +#if HAVE_SYSCONF && HAVE__SC_AVPHYS_PAGES +#define SYSCONF_PAGES _SC_AVPHYS_PAGES +#elif HAVE_SYSCONF && HAVE__SC_PHYS_PAGES +#define SYSCONF_PAGES _SC_PHYS_PAGES +#else +#error Dont know how to get page-size on this architecture! +#endif +#endif // __APPLE__ + +DWORD +PALAPI +PAL_GetTotalCpuCount() +{ + int nrcpus = 0; + +#if HAVE_SYSCONF + +#if defined(HOST_ARM) || defined(HOST_ARM64) +#define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_CONF +#define SYSCONF_GET_NUMPROCS_NAME "_SC_NPROCESSORS_CONF" +#else +#define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_ONLN +#define SYSCONF_GET_NUMPROCS_NAME "_SC_NPROCESSORS_ONLN" +#endif + nrcpus = sysconf(SYSCONF_GET_NUMPROCS); + if (nrcpus < 1) + { + ASSERT("sysconf failed for %s (%d)\n", SYSCONF_GET_NUMPROCS_NAME, errno); + } +#elif HAVE_SYSCTL + int rc; + size_t sz; + int mib[2]; + + sz = sizeof(nrcpus); + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + rc = sysctl(mib, 2, &nrcpus, &sz, NULL, 0); + if (rc != 0) + { + ASSERT("sysctl failed for HW_NCPU (%d)\n", errno); + } +#else // HAVE_SYSCONF +#error "Don't know how to get total CPU count on this platform" +#endif // HAVE_SYSCONF + + return nrcpus; +} + +DWORD +PALAPI +PAL_GetLogicalCpuCountFromOS() +{ + static int nrcpus = -1; + + if (nrcpus == -1) + { +#if HAVE_SCHED_GETAFFINITY + + cpu_set_t cpuSet; + int st = sched_getaffinity(gPID, sizeof(cpu_set_t), &cpuSet); + if (st != 0) + { + ASSERT("sched_getaffinity failed (%d)\n", errno); + } + + nrcpus = CPU_COUNT(&cpuSet); +#else // HAVE_SCHED_GETAFFINITY + nrcpus = PAL_GetTotalCpuCount(); +#endif // HAVE_SCHED_GETAFFINITY + } + + return nrcpus; +} + +/*++ +Function: + GetSystemInfo + +GetSystemInfo + +The GetSystemInfo function returns information about the current system. + +Parameters + +lpSystemInfo + [out] Pointer to a SYSTEM_INFO structure that receives the information. + +Return Values + +This function does not return a value. + +Note: + fields returned by this function are: + dwNumberOfProcessors + dwPageSize +Others are set to zero. + +--*/ +VOID +PALAPI +GetSystemInfo( + OUT LPSYSTEM_INFO lpSystemInfo) +{ + int nrcpus = 0; + long pagesize; + + PERF_ENTRY(GetSystemInfo); + ENTRY("GetSystemInfo (lpSystemInfo=%p)\n", lpSystemInfo); + + pagesize = getpagesize(); + + lpSystemInfo->wProcessorArchitecture_PAL_Undefined = 0; + lpSystemInfo->wReserved_PAL_Undefined = 0; + lpSystemInfo->dwPageSize = pagesize; + lpSystemInfo->dwActiveProcessorMask_PAL_Undefined = 0; + + nrcpus = PAL_GetLogicalCpuCountFromOS(); + TRACE("dwNumberOfProcessors=%d\n", nrcpus); + lpSystemInfo->dwNumberOfProcessors = nrcpus; + +#ifdef VM_MAXUSER_ADDRESS + lpSystemInfo->lpMaximumApplicationAddress = (PVOID) VM_MAXUSER_ADDRESS; +#elif defined(__linux__) + lpSystemInfo->lpMaximumApplicationAddress = (PVOID) (1ull << 47); +#elif defined(__sun) + lpSystemInfo->lpMaximumApplicationAddress = (PVOID) 0xfffffd7fffe00000ul; +#elif defined(USERLIMIT) + lpSystemInfo->lpMaximumApplicationAddress = (PVOID) USERLIMIT; +#elif defined(HOST_64BIT) +#if defined(USRSTACK64) + lpSystemInfo->lpMaximumApplicationAddress = (PVOID) USRSTACK64; +#else // !USRSTACK64 +#error How come USRSTACK64 is not defined for 64bit? +#endif // USRSTACK64 +#elif defined(USRSTACK) + lpSystemInfo->lpMaximumApplicationAddress = (PVOID) USRSTACK; +#else +#error The maximum application address is not known on this platform. +#endif + + lpSystemInfo->lpMinimumApplicationAddress = (PVOID) pagesize; + + lpSystemInfo->dwProcessorType_PAL_Undefined = 0; + + lpSystemInfo->dwAllocationGranularity = pagesize; + + lpSystemInfo->wProcessorLevel_PAL_Undefined = 0; + lpSystemInfo->wProcessorRevision_PAL_Undefined = 0; + + LOGEXIT("GetSystemInfo returns VOID\n"); + PERF_EXIT(GetSystemInfo); +} + +// Get memory size multiplier based on the passed in units (k = kilo, m = mega, g = giga) +static uint64_t GetMemorySizeMultiplier(char units) +{ + switch(units) + { + case 'g': + case 'G': return 1024 * 1024 * 1024; + case 'm': + case 'M': return 1024 * 1024; + case 'k': + case 'K': return 1024; + } + + // No units multiplier + return 1; +} + +#ifndef __APPLE__ +// Try to read the MemAvailable entry from /proc/meminfo. +// Return true if the /proc/meminfo existed, the entry was present and we were able to parse it. +static bool ReadMemAvailable(uint64_t* memAvailable) +{ + bool foundMemAvailable = false; + FILE* memInfoFile = fopen("/proc/meminfo", "r"); + if (memInfoFile != NULL) + { + char *line = nullptr; + size_t lineLen = 0; + + while (getline(&line, &lineLen, memInfoFile) != -1) + { + char units = '\0'; + uint64_t available; + int fieldsParsed = sscanf(line, "MemAvailable: %" SCNu64 " %cB", &available, &units); + + if (fieldsParsed >= 1) + { + uint64_t multiplier = GetMemorySizeMultiplier(units); + *memAvailable = available * multiplier; + foundMemAvailable = true; + break; + } + } + + free(line); + fclose(memInfoFile); + } + + return foundMemAvailable; +} +#endif // __APPLE__ + +/*++ +Function: + GlobalMemoryStatusEx + +GlobalMemoryStatusEx + +Retrieves information about the system's current usage of both physical and virtual memory. + +Return Values + +This function returns a BOOL to indicate its success status. + +--*/ +BOOL +PALAPI +GlobalMemoryStatusEx( + IN OUT LPMEMORYSTATUSEX lpBuffer) +{ + + PERF_ENTRY(GlobalMemoryStatusEx); + ENTRY("GlobalMemoryStatusEx (lpBuffer=%p)\n", lpBuffer); + + lpBuffer->dwMemoryLoad = 0; + lpBuffer->ullTotalPhys = 0; + lpBuffer->ullAvailPhys = 0; + lpBuffer->ullTotalPageFile = 0; + lpBuffer->ullAvailPageFile = 0; + lpBuffer->ullTotalVirtual = 0; + lpBuffer->ullAvailVirtual = 0; + lpBuffer->ullAvailExtendedVirtual = 0; + + BOOL fRetVal = FALSE; + int mib[3]; + int rc; + + // Get the physical memory size +#if HAVE_SYSCONF && HAVE__SC_PHYS_PAGES + int64_t physical_memory; + + // Get the Physical memory size + physical_memory = sysconf( _SC_PHYS_PAGES ) * sysconf( _SC_PAGE_SIZE ); + lpBuffer->ullTotalPhys = (DWORDLONG)physical_memory; + fRetVal = TRUE; +#elif HAVE_SYSCTL + int64_t physical_memory; + size_t length; + + // Get the Physical memory size + mib[0] = CTL_HW; + mib[1] = HW_MEMSIZE; + length = sizeof(INT64); + rc = sysctl(mib, 2, &physical_memory, &length, NULL, 0); + if (rc != 0) + { + ASSERT("sysctl failed for HW_MEMSIZE (%d)\n", errno); + } + else + { + lpBuffer->ullTotalPhys = (DWORDLONG)physical_memory; + fRetVal = TRUE; + } + +#endif // HAVE_SYSCTL + + // Get swap file size, consider the ability to get the values optional + // (don't return FALSE from the GlobalMemoryStatusEx) +#if HAVE_XSW_USAGE + // This is available on OSX + struct xsw_usage xsu; + mib[0] = CTL_VM; + mib[1] = VM_SWAPUSAGE; + size_t length = sizeof(xsu); + rc = sysctl(mib, 2, &xsu, &length, NULL, 0); + if (rc == 0) + { + lpBuffer->ullTotalPageFile = xsu.xsu_total; + lpBuffer->ullAvailPageFile = xsu.xsu_avail; + } +#elif HAVE_XSWDEV + // E.g. FreeBSD + struct xswdev xsw; + + size_t length = 2; + rc = sysctlnametomib("vm.swap_info", mib, &length); + if (rc == 0) + { + int pagesize = getpagesize(); + // Aggregate the information for all swap files on the system + for (mib[2] = 0; ; mib[2]++) + { + length = sizeof(xsw); + rc = sysctl(mib, 3, &xsw, &length, NULL, 0); + if ((rc < 0) || (xsw.xsw_version != XSWDEV_VERSION)) + { + // All the swap files were processed or coreclr was built against + // a version of headers not compatible with the current XSWDEV_VERSION. + break; + } + + DWORDLONG avail = xsw.xsw_nblks - xsw.xsw_used; + lpBuffer->ullTotalPageFile += (DWORDLONG)xsw.xsw_nblks * pagesize; + lpBuffer->ullAvailPageFile += (DWORDLONG)avail * pagesize; + } + } +#elif HAVE_SWAPCTL + struct anoninfo ai; + if (swapctl(SC_AINFO, &ai) != -1) + { + int pagesize = getpagesize(); + lpBuffer->ullTotalPageFile = ai.ani_max * pagesize; + lpBuffer->ullAvailPageFile = ai.ani_free * pagesize; + } +#elif HAVE_SYSINFO + // Linux + struct sysinfo info; + rc = sysinfo(&info); + if (rc == 0) + { + lpBuffer->ullTotalPageFile = info.totalswap; + lpBuffer->ullAvailPageFile = info.freeswap; +#if HAVE_SYSINFO_WITH_MEM_UNIT + // A newer version of the sysinfo structure represents all the sizes + // in mem_unit instead of bytes + lpBuffer->ullTotalPageFile *= info.mem_unit; + lpBuffer->ullAvailPageFile *= info.mem_unit; +#endif // HAVE_SYSINFO_WITH_MEM_UNIT + } +#endif // HAVE_SYSINFO + + // Get the physical memory in use - from it, we can get the physical memory available. + // We do this only when we have the total physical memory available. + if (lpBuffer->ullTotalPhys > 0) + { +#ifndef __APPLE__ + static volatile bool tryReadMemInfo = true; + + if (tryReadMemInfo) + { + // Ensure that we don't try to read the /proc/meminfo in successive calls to the GlobalMemoryStatusEx + // if we have failed to access the file or the file didn't contain the MemAvailable value. + tryReadMemInfo = ReadMemAvailable(&lpBuffer->ullAvailPhys); + } + + if (!tryReadMemInfo) + { + // The /proc/meminfo doesn't exist or it doesn't contain the MemAvailable row or the format of the row is invalid + // Fall back to getting the available pages using sysconf. + lpBuffer->ullAvailPhys = sysconf(SYSCONF_PAGES) * sysconf(_SC_PAGE_SIZE); + } + + INT64 used_memory = lpBuffer->ullTotalPhys - lpBuffer->ullAvailPhys; + lpBuffer->dwMemoryLoad = (DWORD)((used_memory * 100) / lpBuffer->ullTotalPhys); +#else + vm_size_t page_size; + mach_port_t mach_port; + mach_msg_type_number_t count; + vm_statistics_data_t vm_stats; + mach_port = mach_host_self(); + count = sizeof(vm_stats) / sizeof(natural_t); + if (KERN_SUCCESS == host_page_size(mach_port, &page_size)) + { + if (KERN_SUCCESS == host_statistics(mach_port, HOST_VM_INFO, (host_info_t)&vm_stats, &count)) + { + lpBuffer->ullAvailPhys = (int64_t)vm_stats.free_count * (int64_t)page_size; + INT64 used_memory = ((INT64)vm_stats.active_count + (INT64)vm_stats.inactive_count + (INT64)vm_stats.wire_count) * (INT64)page_size; + lpBuffer->dwMemoryLoad = (DWORD)((used_memory * 100) / lpBuffer->ullTotalPhys); + } + } + mach_port_deallocate(mach_task_self(), mach_port); +#endif // __APPLE__ + } + + // There is no API to get the total virtual address space size on + // Unix, so we use a constant value representing 128TB, which is + // the approximate size of total user virtual address space on + // the currently supported Unix systems. + static const UINT64 _128TB = (1ull << 47); + lpBuffer->ullTotalVirtual = _128TB; + lpBuffer->ullAvailVirtual = lpBuffer->ullAvailPhys; + + LOGEXIT("GlobalMemoryStatusEx returns %d\n", fRetVal); + PERF_EXIT(GlobalMemoryStatusEx); + + return fRetVal; +} + +PALIMPORT +DWORD +PALAPI +GetCurrentProcessorNumber() +{ +#if HAVE_SCHED_GETCPU + return sched_getcpu(); +#else //HAVE_SCHED_GETCPU + return -1; +#endif //HAVE_SCHED_GETCPU +} + +BOOL +PALAPI +PAL_HasGetCurrentProcessorNumber() +{ + return HAVE_SCHED_GETCPU; +} + +bool +ReadMemoryValueFromFile(const char* filename, uint64_t* val) +{ + bool result = false; + char *line = nullptr; + size_t lineLen = 0; + char* endptr = nullptr; + uint64_t num = 0, l, multiplier; + + if (val == nullptr) + return false; + + FILE* file = fopen(filename, "r"); + if (file == nullptr) + goto done; + + if (getline(&line, &lineLen, file) == -1) + goto done; + + errno = 0; + num = strtoull(line, &endptr, 0); + if (errno != 0) + goto done; + + multiplier = GetMemorySizeMultiplier(*endptr); + *val = num * multiplier; + result = true; + if (*val/multiplier != num) + result = false; +done: + if (file) + fclose(file); + free(line); + return result; +} + +size_t +PALAPI +PAL_GetLogicalProcessorCacheSizeFromOS() +{ + size_t cacheSize = 0; + +#ifdef _SC_LEVEL1_DCACHE_SIZE + cacheSize = std::max(cacheSize, (size_t)sysconf(_SC_LEVEL1_DCACHE_SIZE)); +#endif +#ifdef _SC_LEVEL2_CACHE_SIZE + cacheSize = std::max(cacheSize, (size_t)sysconf(_SC_LEVEL2_CACHE_SIZE)); +#endif +#ifdef _SC_LEVEL3_CACHE_SIZE + cacheSize = std::max(cacheSize, (size_t)sysconf(_SC_LEVEL3_CACHE_SIZE)); +#endif +#ifdef _SC_LEVEL4_CACHE_SIZE + cacheSize = std::max(cacheSize, (size_t)sysconf(_SC_LEVEL4_CACHE_SIZE)); +#endif + +#if defined(HOST_ARM64) + if(cacheSize == 0) + { + size_t size; + + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index0/size", &size)) + cacheSize = std::max(cacheSize, size); + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index1/size", &size)) + cacheSize = std::max(cacheSize, size); + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index2/size", &size)) + cacheSize = std::max(cacheSize, size); + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index3/size", &size)) + cacheSize = std::max(cacheSize, size); + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index4/size", &size)) + cacheSize = std::max(cacheSize, size); + } + + if(cacheSize == 0) + { + // It is currently expected to be missing cache size info + // + // _SC_LEVEL*_*CACHE_SIZE is not yet present. Work is in progress to enable this for arm64 + // + // /sys/devices/system/cpu/cpu*/cache/index*/ is also not yet present in most systems. + // Arm64 patch is in Linux kernel tip. + // + // midr_el1 is available in "/sys/devices/system/cpu/cpu0/regs/identification/midr_el1", + // but without an exhaustive list of ARM64 processors any decode of midr_el1 + // Would likely be incomplete + + // Published information on ARM64 architectures is limited. + // If we use recent high core count chips as a guide for state of the art, we find + // total L3 cache to be 1-2MB/core. As always, there are exceptions. + + // Estimate cache size based on CPU count + // Assume lower core count are lighter weight parts which are likely to have smaller caches + // Assume L3$/CPU grows linearly from 256K to 1.5M/CPU as logicalCPUs grows from 2 to 12 CPUs + DWORD logicalCPUs = PAL_GetLogicalCpuCountFromOS(); + + cacheSize = logicalCPUs*std::min(1536, std::max(256, (int)logicalCPUs*128))*1024; + } +#endif + +#if HAVE_SYSCTLBYNAME + if (cacheSize == 0) + { + int64_t cacheSizeFromSysctl = 0; + size_t sz = sizeof(cacheSizeFromSysctl); + const bool success = sysctlbyname("hw.l3cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0 + || sysctlbyname("hw.l2cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0 + || sysctlbyname("hw.l1dcachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0; + if (success) + { + _ASSERTE(cacheSizeFromSysctl > 0); + cacheSize = (size_t) cacheSizeFromSysctl; + } + } +#endif + + return cacheSize; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/time.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/time.cpp new file mode 100644 index 0000000..ce65f3d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/time.cpp @@ -0,0 +1,404 @@ +// 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: + + time.c + +Abstract: + + Implementation of time related WIN API functions. + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/misc.h" + +#include +#include +#include +#include +#include + +#if HAVE_MACH_ABSOLUTE_TIME +#include +static mach_timebase_info_data_t s_TimebaseInfo; +#endif + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(MISC); + +/*++ +Function : +TIMEInitialize + +Initialize all Time-related stuff related + +(no parameters) + +Return value : +TRUE if Time support initialization succeeded +FALSE otherwise +--*/ +BOOL TIMEInitialize(void) +{ + BOOL retval = TRUE; + +#if HAVE_MACH_ABSOLUTE_TIME + kern_return_t result = mach_timebase_info(&s_TimebaseInfo); + + if (result != KERN_SUCCESS) + { + ASSERT("mach_timebase_info() failed: %s\n", mach_error_string(result)); + retval = FALSE; + } +#endif + + return retval; +} + + +/*++ +Function: + GetSystemTime + +The GetSystemTime function retrieves the current system date and +time. The system time is expressed in Coordinated Universal Time +(UTC). + +Parameters + +lpSystemTime + [out] Pointer to a SYSTEMTIME structure to receive the current system date and time. + +Return Values + +This function does not return a value. + +--*/ +VOID +PALAPI +GetSystemTime( + OUT LPSYSTEMTIME lpSystemTime) +{ + time_t tt; +#if HAVE_GMTIME_R + struct tm ut; +#endif /* HAVE_GMTIME_R */ + struct tm *utPtr; + struct timeval timeval; + int timeofday_retval; + + PERF_ENTRY(GetSystemTime); + ENTRY("GetSystemTime (lpSystemTime=%p)\n", lpSystemTime); + + tt = time(NULL); + + /* We can't get millisecond resolution from time(), so we get it from + gettimeofday() */ + timeofday_retval = gettimeofday(&timeval,NULL); + +#if HAVE_GMTIME_R + utPtr = &ut; + if (gmtime_r(&tt, utPtr) == NULL) +#else /* HAVE_GMTIME_R */ + if ((utPtr = gmtime(&tt)) == NULL) +#endif /* HAVE_GMTIME_R */ + { + ASSERT("gmtime() failed; errno is %d (%s)\n", errno, strerror(errno)); + goto EXIT; + } + + lpSystemTime->wYear = 1900 + utPtr->tm_year; + lpSystemTime->wMonth = utPtr->tm_mon + 1; + lpSystemTime->wDayOfWeek = utPtr->tm_wday; + lpSystemTime->wDay = utPtr->tm_mday; + lpSystemTime->wHour = utPtr->tm_hour; + lpSystemTime->wMinute = utPtr->tm_min; + lpSystemTime->wSecond = utPtr->tm_sec; + + if(-1 == timeofday_retval) + { + ASSERT("gettimeofday() failed; errno is %d (%s)\n", + errno, strerror(errno)); + lpSystemTime->wMilliseconds = 0; + } + else + { + int old_seconds; + int new_seconds; + + lpSystemTime->wMilliseconds = timeval.tv_usec/tccMillieSecondsToMicroSeconds; + + old_seconds = utPtr->tm_sec; + new_seconds = timeval.tv_sec%60; + + /* just in case we reached the next second in the interval between + time() and gettimeofday() */ + if( old_seconds!=new_seconds ) + { + TRACE("crossed seconds boundary; setting milliseconds to 999\n"); + lpSystemTime->wMilliseconds = 999; + } + } +EXIT: + LOGEXIT("GetSystemTime returns void\n"); + PERF_EXIT(GetSystemTime); +} + +/*++ +Function: + GetTickCount + +The GetTickCount function retrieves the number of milliseconds that +have elapsed since the system was started. It is limited to the +resolution of the system timer. To obtain the system timer resolution, +use the GetSystemTimeAdjustment function. + +Parameters + +This function has no parameters. + +Return Values + +The return value is the number of milliseconds that have elapsed since +the system was started. + +In the PAL implementation the return value is the elapsed time since +the start of the epoch. + +--*/ +DWORD +PALAPI +GetTickCount( + VOID) +{ + DWORD retval = 0; + PERF_ENTRY(GetTickCount); + ENTRY("GetTickCount ()\n"); + + // Get the 64-bit count from GetTickCount64 and truncate the results. + retval = (DWORD) GetTickCount64(); + + LOGEXIT("GetTickCount returns DWORD %u\n", retval); + PERF_EXIT(GetTickCount); + return retval; +} + +BOOL +PALAPI +QueryPerformanceCounter( + OUT LARGE_INTEGER *lpPerformanceCount + ) +{ + BOOL retval = TRUE; + PERF_ENTRY(QueryPerformanceCounter); + ENTRY("QueryPerformanceCounter()\n"); + +#if HAVE_MACH_ABSOLUTE_TIME + lpPerformanceCount->QuadPart = (LONGLONG)mach_absolute_time(); +#elif HAVE_CLOCK_MONOTONIC + struct timespec ts; + int result = clock_gettime(CLOCK_MONOTONIC, &ts); + + if (result != 0) + { + ASSERT("clock_gettime(CLOCK_MONOTONIC) failed: %d\n", result); + retval = FALSE; + } + else + { + lpPerformanceCount->QuadPart = + ((LONGLONG)(ts.tv_sec) * (LONGLONG)(tccSecondsToNanoSeconds)) + (LONGLONG)(ts.tv_nsec); + } +#else + #error "The PAL requires either mach_absolute_time() or clock_gettime(CLOCK_MONOTONIC) to be supported." +#endif + + LOGEXIT("QueryPerformanceCounter\n"); + PERF_EXIT(QueryPerformanceCounter); + return retval; +} + +BOOL +PALAPI +QueryPerformanceFrequency( + OUT LARGE_INTEGER *lpFrequency + ) +{ + BOOL retval = TRUE; + PERF_ENTRY(QueryPerformanceFrequency); + ENTRY("QueryPerformanceFrequency()\n"); + +#if HAVE_MACH_ABSOLUTE_TIME + // use denom == 0 to indicate that s_TimebaseInfo is uninitialised. + if (s_TimebaseInfo.denom == 0) + { + ASSERT("s_TimebaseInfo is uninitialized.\n"); + retval = FALSE; + } + else + { + // (numer / denom) gives you the nanoseconds per tick, so the below code + // computes the number of ticks per second. We explicitly do the multiplication + // first in order to help minimize the error that is produced by integer division. + + lpFrequency->QuadPart = ((LONGLONG)(tccSecondsToNanoSeconds) * (LONGLONG)(s_TimebaseInfo.denom)) / (LONGLONG)(s_TimebaseInfo.numer); + } +#elif HAVE_CLOCK_MONOTONIC + // clock_gettime() returns a result in terms of nanoseconds rather than a count. This + // means that we need to either always scale the result by the actual resolution (to + // get a count) or we need to say the resolution is in terms of nanoseconds. We prefer + // the latter since it allows the highest throughput and should minimize error propagated + // to the user. + + lpFrequency->QuadPart = (LONGLONG)(tccSecondsToNanoSeconds); +#else + #error "The PAL requires either mach_absolute_time() or clock_gettime(CLOCK_MONOTONIC) to be supported." +#endif + + LOGEXIT("QueryPerformanceFrequency\n"); + PERF_EXIT(QueryPerformanceFrequency); + return retval; +} + +/*++ +Function: + QueryThreadCycleTime + +Puts the execution time (in nanoseconds) for the thread pointed to by ThreadHandle, into the unsigned long +pointed to by CycleTime. ThreadHandle must refer to the current thread. Returns TRUE on success, FALSE on +failure. +--*/ + +BOOL +PALAPI +QueryThreadCycleTime( + IN HANDLE ThreadHandle, + OUT PULONG64 CycleTime + ) +{ + + ULONG64 calcTime; + FILETIME kernelTime, userTime; + BOOL retval = TRUE; + + if(!GetThreadTimesInternal(ThreadHandle, &kernelTime, &userTime)) + { + ASSERT("Could not get cycle time for current thread"); + retval = FALSE; + goto EXIT; + } + + calcTime = ((ULONG64)kernelTime.dwHighDateTime << 32); + calcTime += (ULONG64)kernelTime.dwLowDateTime; + calcTime += ((ULONG64)userTime.dwHighDateTime << 32); + calcTime += (ULONG64)userTime.dwLowDateTime; + *CycleTime = calcTime; + +EXIT: + return retval; +} + +/*++ +Function: + GetTickCount64 + +Returns a 64-bit tick count with a millisecond resolution. It tries its best +to return monotonically increasing counts and avoid being affected by changes +to the system clock (either due to drift or due to explicit changes to system +time). +--*/ +PALAPI +ULONGLONG +GetTickCount64() +{ + LONGLONG retval = 0; + +#if HAVE_MACH_ABSOLUTE_TIME + // use denom == 0 to indicate that s_TimebaseInfo is uninitialised. + if (s_TimebaseInfo.denom == 0) + { + ASSERT("s_TimebaseInfo is uninitialized.\n"); + retval = FALSE; + } + else + { + retval = ((LONGLONG)mach_absolute_time() * (LONGLONG)(s_TimebaseInfo.numer)) / ((LONGLONG)(tccMillieSecondsToNanoSeconds) * (LONGLONG)(s_TimebaseInfo.denom)); + } +#elif HAVE_CLOCK_MONOTONIC || HAVE_CLOCK_MONOTONIC_COARSE + struct timespec ts; + +#if HAVE_CLOCK_MONOTONIC_COARSE + // CLOCK_MONOTONIC_COARSE has enough precision for GetTickCount but + // doesn't have the same overhead as CLOCK_MONOTONIC. This allows + // overall higher throughput. See dotnet/coreclr#2257 for more details. + + const clockid_t clockType = CLOCK_MONOTONIC_COARSE; +#else + const clockid_t clockType = CLOCK_MONOTONIC; +#endif + + int result = clock_gettime(clockType, &ts); + + if (result != 0) + { +#if HAVE_CLOCK_MONOTONIC_COARSE + ASSERT("clock_gettime(CLOCK_MONOTONIC_COARSE) failed: %d\n", result); +#else + ASSERT("clock_gettime(CLOCK_MONOTONIC) failed: %d\n", result); +#endif + retval = FALSE; + } + else + { + retval = ((LONGLONG)(ts.tv_sec) * (LONGLONG)(tccSecondsToMillieSeconds)) + ((LONGLONG)(ts.tv_nsec) / (LONGLONG)(tccMillieSecondsToNanoSeconds)); + } +#else + #error "The PAL requires either mach_absolute_time() or clock_gettime(CLOCK_MONOTONIC) to be supported." +#endif + + return (ULONGLONG)(retval); +} + +/*++ +Function: + PAL_nanosleep + +Sleeps for the time specified in timeInNs. +Returns 0 on successful completion of the operation. +--*/ +PALAPI +INT +PAL_nanosleep( + IN long timeInNs + ) +{ + struct timespec req; + struct timespec rem; + int result; + + req.tv_sec = 0; + req.tv_nsec = timeInNs; + + do + { + // Sleep for the requested time. + result = nanosleep(&req, &rem); + + // Save the remaining time (used if the loop runs another iteration). + req = rem; + } + while(result == -1 && errno == EINTR); + + return result; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/tracepointprovider.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/tracepointprovider.cpp new file mode 100644 index 0000000..49ddf5d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/tracepointprovider.cpp @@ -0,0 +1,121 @@ +// 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: + + tracepointprovider.cpp + +Abstract: + + Trace point provider support + +Revision History: + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/file.h" +#include "pal/process.h" +#include "pal/module.h" +#include "pal/malloc.hpp" +#include "pal/stackstring.hpp" + +#include +#include +#include +#include + +SET_DEFAULT_DEBUG_CHANNEL(MISC); + +/*++ + +Initialization logic for LTTng tracepoint providers. + +--*/ +#if defined(__linux__) + +static const char tpLibName[] = "libcoreclrtraceptprovider.so"; + + +/*++ + +NOTE: PAL_InitializeTracing MUST NOT depend on anything in the PAL itself +as it is called prior to PAL initialization. + +Constructor priority is set to 200, which allows for constructors to +guarantee that they run before or after this constructor by setting +their priority appropriately. + +Priority values must be greater than 100. The lower the value, +the higher the priority. + +--*/ +__attribute__((__unused__)) +__attribute__((constructor (200))) +static void +PAL_InitializeTracing(void) +{ + int fShouldLoad = 1; + // Check if loading the LTTng providers should be disabled. + // Note: this env var is formally declared in clrconfigvalues.h, but + // this code is executed too early to use the mechanics that come with that definition. + char *disableValue = getenv("COMPlus_LTTng"); + if (disableValue != NULL) + { + fShouldLoad = strtol(disableValue, NULL, 10); + } + + // Get the path to the currently executing shared object (libcoreclr.so). + Dl_info info; + int succeeded = dladdr((void *)PAL_InitializeTracing, &info); + if(!succeeded) + { + return; + } + + // Copy the path and modify the shared object name to be the tracepoint provider. + PathCharString tpProvPath; + int pathLen = strlen(info.dli_fname); + + // Find the length of the full path without the shared object name, including the trailing slash. + int lastTrailingSlashLen = -1; + for(int i=pathLen-1; i>=0; i--) + { + if(info.dli_fname[i] == '/') + { + lastTrailingSlashLen = i+1; + break; + } + } + + // Make sure we found the last trailing slash. + if(lastTrailingSlashLen == -1) + { + return; + } + + SIZE_T tpLibNameLen = strlen(tpLibName); + + if( !tpProvPath.Reserve(tpLibNameLen + lastTrailingSlashLen) || + // Copy the path without the shared object name. + !tpProvPath.Append(info.dli_fname, lastTrailingSlashLen) || + // Append the shared object name for the tracepoint provider. + !tpProvPath.Append(tpLibName, tpLibNameLen)) + { + return; + } + + + if (fShouldLoad) + { + // Load the tracepoint provider. + // It's OK if this fails - that just means that tracing dependencies aren't available. + dlopen(tpProvPath, RTLD_NOW | RTLD_GLOBAL); + } +} + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/utils.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/utils.cpp new file mode 100644 index 0000000..a41f7a7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/misc/utils.cpp @@ -0,0 +1,365 @@ +// 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: + + misc/utils.c + +Abstract: + + Miscellaneous helper functions for the PAL, which don't fit anywhere else + + + +--*/ + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(MISC); // some headers have code with asserts, so do this first + +#include "pal/palinternal.h" +#if HAVE_VM_ALLOCATE +#include +#endif //HAVE_VM_ALLOCATE + +#include + +#include "pal/utils.h" +#include "pal/file.h" + +#include +#include + + +// In safemath.h, Template SafeInt uses macro _ASSERTE, which need to use variable +// defdbgchan defined by SET_DEFAULT_DEBUG_CHANNEL. Therefore, the include statement +// should be placed after the SET_DEFAULT_DEBUG_CHANNEL(MISC) +#include + +/*++ +Function: + UTIL_inverse_wcspbrk + + Opposite of wcspbrk : searches a string for the first character NOT in the + given set + +Parameters : + LPWSTR lpwstr : string to search + LPCWSTR charset : list of characters to search for + +Return value : + pointer to first character of lpwstr that isn't in the set + NULL if all characters are in the set +--*/ +LPWSTR UTIL_inverse_wcspbrk(LPWSTR lpwstr, LPCWSTR charset) +{ + while(*lpwstr) + { + if(NULL == PAL_wcschr(charset,*lpwstr)) + { + return lpwstr; + } + lpwstr++; + } + return NULL; +} + + +/*++ +Function : + UTIL_IsReadOnlyBitsSet + + Takes a struct stat * + Returns true if the file is read only, +--*/ +BOOL UTIL_IsReadOnlyBitsSet( struct stat * stat_data ) +{ + BOOL bRetVal = FALSE; + + /* Check for read permissions. */ + if ( stat_data->st_uid == geteuid() ) + { + /* The process owner is the file owner as well. */ + if ( ( stat_data->st_mode & S_IRUSR ) && !( stat_data->st_mode & S_IWUSR ) ) + { + bRetVal = TRUE; + } + } + else if ( stat_data->st_gid == getegid() ) + { + /* The process's owner is in the same group as the file's owner. */ + if ( ( stat_data->st_mode & S_IRGRP ) && !( stat_data->st_mode & S_IWGRP ) ) + { + bRetVal = TRUE; + } + } + else + { + /* Check the other bits to see who can access the file. */ + if ( ( stat_data->st_mode & S_IROTH ) && !( stat_data->st_mode & S_IWOTH ) ) + { + bRetVal = TRUE; + } + } + + return bRetVal; +} + +/*++ +Function : + UTIL_IsExecuteBitsSet + + Takes a struct stat * + Returns true if the file is executable, +--*/ +BOOL UTIL_IsExecuteBitsSet( struct stat * stat_data ) +{ + BOOL bRetVal = FALSE; + + if ( (stat_data->st_mode & S_IFMT) == S_IFDIR ) + { + return FALSE; + } + + /* Check for read permissions. */ + if ( 0 == geteuid() ) + { + /* The process owner is root */ + bRetVal = TRUE; + } + else if ( stat_data->st_uid == geteuid() ) + { + /* The process owner is the file owner as well. */ + if ( ( stat_data->st_mode & S_IXUSR ) ) + { + bRetVal = TRUE; + } + } + else if ( stat_data->st_gid == getegid() ) + { + /* The process's owner is in the same group as the file's owner. */ + if ( ( stat_data->st_mode & S_IXGRP ) ) + { + bRetVal = TRUE; + } + } + else + { + /* Check the other bits to see who can access the file. */ + if ( ( stat_data->st_mode & S_IXOTH ) ) + { + bRetVal = TRUE; + } + } + + return bRetVal; +} + +/*++ +Function : + UTIL_WCToMB_Alloc + + Converts a wide string to a multibyte string, allocating the required buffer + +Parameters : + LPCWSTR lpWideCharStr : string to convert + int cchWideChar : number of wide characters to convert + (-1 to convert a complete null-termnated string) + +Return Value : + newly allocated buffer containing the converted string. Conversion is + performed using CP_ACP. Buffer is allocated with malloc(), release it + with free(). + In case if failure, LastError will be set. +--*/ +LPSTR UTIL_WCToMB_Alloc(LPCWSTR lpWideCharStr, int cchWideChar) +{ + int length; + LPSTR lpMultiByteStr; + + /* get required buffer length */ + length = WideCharToMultiByte(CP_ACP, 0, lpWideCharStr, cchWideChar, + NULL, 0, NULL, NULL); + if(0 == length) + { + ERROR("WCToMB error; GetLastError returns %#x", GetLastError()); + return NULL; + } + + /* allocate required buffer */ + lpMultiByteStr = (LPSTR)PAL_malloc(length); + if(NULL == lpMultiByteStr) + { + ERROR("malloc() failed! errno is %d (%s)\n", errno,strerror(errno)); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + + /* convert into allocated buffer */ + length = WideCharToMultiByte(CP_ACP, 0, lpWideCharStr, cchWideChar, + lpMultiByteStr, length, NULL, NULL); + if(0 == length) + { + ASSERT("WCToMB error; GetLastError returns %#x\n", GetLastError()); + PAL_free(lpMultiByteStr); + return NULL; + } + return lpMultiByteStr; +} + +/*++ +Function : + UTIL_MBToWC_Alloc + + Converts a multibyte string to a wide string, allocating the required buffer + +Parameters : + LPCSTR lpMultiByteStr : string to convert + int cbMultiByte : number of bytes to convert + (-1 to convert a complete null-termnated string) + +Return Value : + newly allocated buffer containing the converted string. Conversion is + performed using CP_ACP. Buffer is allocated with malloc(), release it + with free(). + In case if failure, LastError will be set. +--*/ +LPWSTR UTIL_MBToWC_Alloc(LPCSTR lpMultiByteStr, int cbMultiByte) +{ + int length; + LPWSTR lpWideCharStr; + + /* get required buffer length */ + length = MultiByteToWideChar(CP_ACP, 0, lpMultiByteStr, cbMultiByte, + NULL, 0); + if(0 == length) + { + ERROR("MBToWC error; GetLastError returns %#x", GetLastError()); + return NULL; + } + + /* allocate required buffer */ + size_t fullsize; + if (!ClrSafeInt::multiply(length,sizeof(WCHAR),fullsize)) + { + ERROR("integer overflow! length = %d , sizeof(WCHAR) = (%d)\n", length,sizeof(WCHAR) ); + SetLastError(ERROR_ARITHMETIC_OVERFLOW); + return NULL; + } + + lpWideCharStr = (LPWSTR)PAL_malloc(fullsize); + if(NULL == lpWideCharStr) + { + ERROR("malloc() failed! errno is %d (%s)\n", errno,strerror(errno)); + SetLastError(FILEGetLastErrorFromErrno()); + return NULL; + } + + /* convert into allocated buffer */ + length = MultiByteToWideChar(CP_ACP, 0, lpMultiByteStr, cbMultiByte, + lpWideCharStr, length); + if(0 >= length) + { + ASSERT("MCToMB error; GetLastError returns %#x\n", GetLastError()); + PAL_free(lpWideCharStr); + return NULL; + } + return lpWideCharStr; +} + +#if HAVE_VM_ALLOCATE +/*++ +Function: + UTIL_MachErrorToPalError + + Maps a Mach kern_return_t to a Win32 error code. +--*/ +DWORD UTIL_MachErrorToPalError(kern_return_t MachReturn) +{ + switch (MachReturn) + { + case KERN_SUCCESS: + return ERROR_SUCCESS; + + case KERN_NO_ACCESS: + case KERN_INVALID_CAPABILITY: + return ERROR_ACCESS_DENIED; + + case KERN_TERMINATED: + return ERROR_INVALID_HANDLE; + + case KERN_INVALID_ADDRESS: + return ERROR_INVALID_ADDRESS; + + case KERN_NO_SPACE: + return ERROR_NOT_ENOUGH_MEMORY; + + case KERN_INVALID_ARGUMENT: + return ERROR_INVALID_PARAMETER; + + default: + ASSERT("Unknown kern_return_t value %d - reporting ERROR_INTERNAL_ERROR\n", MachReturn); + return ERROR_INTERNAL_ERROR; + } +} + +/*++ +Function: + UTIL_SetLastErrorFromMach + + Sets Win32 LastError according to the argument Mach kern_return_t value, + provided it indicates an error. If the argument indicates success, does + not modify LastError. +--*/ +void UTIL_SetLastErrorFromMach(kern_return_t MachReturn) +{ + DWORD palError = UTIL_MachErrorToPalError(MachReturn); + if (palError != ERROR_SUCCESS) + { + SetLastError(palError); + } +} +#endif //HAVE_VM_ALLOCATE + +#ifdef __APPLE__ + +/*++ +Function: + IsRunningOnMojaveHardenedRuntime() - Test if the current process is running on Mojave hardened runtime +--*/ +BOOL IsRunningOnMojaveHardenedRuntime() +{ + static volatile int isRunningOnMojaveHardenedRuntime = -1; + + if (isRunningOnMojaveHardenedRuntime == -1) + { + BOOL mhrDetected = FALSE; + int pageSize = sysconf(_SC_PAGE_SIZE); + // Try to map a page with read-write-execute protection. It should fail on Mojave hardened runtime. + void* testPage = mmap(NULL, pageSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (testPage == MAP_FAILED && (errno == EACCES)) + { + // The mapping has failed with EACCES, check if making the same mapping with MAP_JIT flag works + testPage = mmap(NULL, pageSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE | MAP_JIT, -1, 0); + if (testPage != MAP_FAILED) + { + mhrDetected = TRUE; + } + } + + if (testPage != MAP_FAILED) + { + munmap(testPage, pageSize); + } + + isRunningOnMojaveHardenedRuntime = (int)mhrDetected; + } + + return (BOOL)isRunningOnMojaveHardenedRuntime; +} + +#endif // __APPLE__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/numa/numa.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/numa/numa.cpp new file mode 100644 index 0000000..4d75508 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/numa/numa.cpp @@ -0,0 +1,289 @@ +// 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: + + numa.cpp + +Abstract: + + Implementation of NUMA related APIs + +--*/ + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(NUMA); + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/numa.h" +#include "pal/corunix.hpp" +#include "pal/thread.hpp" + +#include +#ifdef __FreeBSD__ +#include +#else +#include +#endif + +#include + +#include "numashim.h" + +using namespace CorUnix; + +// The highest NUMA node available +int g_highestNumaNode = 0; +// Is numa available +bool g_numaAvailable = false; + +void* numaHandle = nullptr; + +#if HAVE_NUMA_H +#include +#include +#include + +#define PER_FUNCTION_BLOCK(fn) decltype(fn)* fn##_ptr; +FOR_ALL_NUMA_FUNCTIONS +#undef PER_FUNCTION_BLOCK + +#if defined(__linux__) +static bool ShouldOpenLibNuma() +{ + // This is a simple heuristic to determine if libnuma.so should be opened. There's + // no point in linking and resolving everything in this library if we're running on + // a system that's not NUMA-capable. + int fd = open("/sys/devices/system/node/possible", O_RDONLY | O_CLOEXEC); + + if (fd == -1) + { + // sysfs might not be mounted, not available, or the interface might have + // changed. Return `true' here so NUMASupportInitialize() can try initializing + // NUMA support with libnuma. + return true; + } + + while (true) + { + char buffer[32]; + ssize_t bytesRead = read(fd, buffer, 32); + + if (bytesRead == -1 && errno == EINTR) + { + continue; + } + + close(fd); + + // If an unknown error happened (bytesRead < 0), or the file was empty + // (bytesRead = 0), let libnuma handle this. Otherwise, if there's just + // one NUMA node, don't bother linking in libnuma. + return (bytesRead <= 0) ? true : strncmp(buffer, "0\n", bytesRead) != 0; + } +} +#else +static bool ShouldOpenLibNuma() +{ + return true; +} +#endif // __linux__ + +#endif // HAVE_NUMA_H + +/*++ +Function: + NUMASupportInitialize + +Initialize data structures for getting and setting thread affinities to processors and +querying NUMA related processor information. +On systems with no NUMA support, it behaves as if there was a single NUMA node with +a single group of processors. +--*/ +BOOL +NUMASupportInitialize() +{ +#if HAVE_NUMA_H + if (!ShouldOpenLibNuma()) + { + g_numaAvailable = false; + g_highestNumaNode = 0; + return TRUE; + } + + numaHandle = dlopen("libnuma.so", RTLD_LAZY); + if (numaHandle == 0) + { + numaHandle = dlopen("libnuma.so.1", RTLD_LAZY); + } + if (numaHandle != 0) + { +#define PER_FUNCTION_BLOCK(fn) \ + fn##_ptr = (decltype(fn)*)dlsym(numaHandle, #fn); \ + if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from libnuma\n"); abort(); } +FOR_ALL_NUMA_FUNCTIONS +#undef PER_FUNCTION_BLOCK + + if (numa_available() == -1) + { + dlclose(numaHandle); + } + else + { + g_numaAvailable = true; + g_highestNumaNode = numa_max_node(); + } + } +#endif // HAVE_NUMA_H + if (!g_numaAvailable) + { + // No NUMA + g_highestNumaNode = 0; + } + + return TRUE; +} + +/*++ +Function: + NUMASupportCleanup + +Cleanup of the NUMA support data structures +--*/ +VOID +NUMASupportCleanup() +{ +#if HAVE_NUMA_H + if (g_numaAvailable) + { + dlclose(numaHandle); + } +#endif // HAVE_NUMA_H +} + +/*++ +Function: + GetNumaHighestNodeNumber + +See MSDN doc. +--*/ +BOOL +PALAPI +GetNumaHighestNodeNumber( + OUT PULONG HighestNodeNumber +) +{ + PERF_ENTRY(GetNumaHighestNodeNumber); + ENTRY("GetNumaHighestNodeNumber(HighestNodeNumber=%p)\n", HighestNodeNumber); + *HighestNodeNumber = (ULONG)g_highestNumaNode; + + BOOL success = TRUE; + + LOGEXIT("GetNumaHighestNodeNumber returns BOOL %d\n", success); + PERF_EXIT(GetNumaHighestNodeNumber); + + return success; +} + +/*++ +Function: + PAL_GetNumaProcessorNode + +Abstract + Get NUMA node of a processor + +Parameters: + procNo - number of the processor to get the NUMA node for + node - the resulting NUMA node + +Return value: + TRUE if the function was able to get the NUMA node, FALSE if it has failed. +--*/ +BOOL +PALAPI +PAL_GetNumaProcessorNode(WORD procNo, WORD* node) +{ +#if HAVE_NUMA_H + if (g_numaAvailable) + { + int result = numa_node_of_cpu(procNo); + if (result >= 0) + { + *node = (WORD)result; + return TRUE; + } + } +#endif // HAVE_NUMA_H + + return FALSE; +} + +/*++ +Function: + VirtualAllocExNuma + +See MSDN doc. +--*/ +LPVOID +PALAPI +VirtualAllocExNuma( + IN HANDLE hProcess, + IN OPTIONAL LPVOID lpAddress, + IN SIZE_T dwSize, + IN DWORD flAllocationType, + IN DWORD flProtect, + IN DWORD nndPreferred +) +{ + PERF_ENTRY(VirtualAllocExNuma); + ENTRY("VirtualAllocExNuma(hProcess=%p, lpAddress=%p, dwSize=%u, flAllocationType=%#x, flProtect=%#x, nndPreferred=%d\n", + hProcess, lpAddress, dwSize, flAllocationType, flProtect, nndPreferred); + + LPVOID result = NULL; + + if (hProcess == GetCurrentProcess()) + { + if ((int)nndPreferred <= g_highestNumaNode) + { + result = VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect); +#if HAVE_NUMA_H + if (result != NULL && g_numaAvailable) + { + int usedNodeMaskBits = g_highestNumaNode + 1; + int nodeMaskLength = (usedNodeMaskBits + sizeof(unsigned long) - 1) / sizeof(unsigned long); + unsigned long nodeMask[nodeMaskLength]; + memset(nodeMask, 0, sizeof(nodeMask)); + + int index = nndPreferred / sizeof(unsigned long); + nodeMask[index] = ((unsigned long)1) << (nndPreferred & (sizeof(unsigned long) - 1)); + + int st = mbind(result, dwSize, MPOL_PREFERRED, nodeMask, usedNodeMaskBits, 0); + + _ASSERTE(st == 0); + // If the mbind fails, we still return the allocated memory since the nndPreferred is just a hint + } +#endif // HAVE_NUMA_H + } + else + { + // The specified node number is larger than the maximum available one + SetLastError(ERROR_INVALID_PARAMETER); + } + } + else + { + // PAL supports allocating from the current process virtual space only + SetLastError(ERROR_INVALID_PARAMETER); + } + + LOGEXIT("VirtualAllocExNuma returns %p\n", result); + PERF_EXIT(VirtualAllocExNuma); + + return result; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/numa/numashim.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/numa/numashim.h new file mode 100644 index 0000000..e56cfab --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/numa/numashim.h @@ -0,0 +1,37 @@ +// 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. + +// Enable calling numa functions through shims to make it a soft +// runtime dependency. + +#ifndef __NUMASHIM_H__ +#define __NUMASHIM_H__ + +#if HAVE_NUMA_H + +#include +#include + +// List of all functions from the numa library that are used +#define FOR_ALL_NUMA_FUNCTIONS \ + PER_FUNCTION_BLOCK(numa_available) \ + PER_FUNCTION_BLOCK(mbind) \ + PER_FUNCTION_BLOCK(numa_max_node) \ + PER_FUNCTION_BLOCK(numa_node_of_cpu) + +// Declare pointers to all the used numa functions +#define PER_FUNCTION_BLOCK(fn) extern decltype(fn)* fn##_ptr; +FOR_ALL_NUMA_FUNCTIONS +#undef PER_FUNCTION_BLOCK + +// Redefine all calls to numa functions as calls through pointers that are set +// to the functions of libnuma in the initialization. +#define numa_available() numa_available_ptr() +#define mbind(...) mbind_ptr(__VA_ARGS__) +#define numa_max_node() numa_max_node_ptr() +#define numa_node_of_cpu(...) numa_node_of_cpu_ptr(__VA_ARGS__) + +#endif // HAVE_NUMA_H + +#endif // __NUMASHIM_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/palobjbase.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/palobjbase.cpp new file mode 100644 index 0000000..ca4ee61 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/palobjbase.cpp @@ -0,0 +1,369 @@ +// 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: + + palobjbase.cpp + +Abstract: + PAL object base class + + + +--*/ + +#include "palobjbase.hpp" +#include "pal/malloc.hpp" +#include "pal/dbgmsg.h" + +SET_DEFAULT_DEBUG_CHANNEL(PAL); + +using namespace CorUnix; + +CObjectType* CObjectType::s_rgotIdMapping[ObjectTypeIdCount]; + +/*++ +Function: + CPalObjectBase::Initialize + + Performs possibly-failing initialization for a newly-constructed + object + +Parameters: + pthr -- thread data for calling thread + poa -- the object attributes (e.g., name) for the object +--*/ + +PAL_ERROR +CPalObjectBase::Initialize( + CPalThread *pthr, + CObjectAttributes *poa + ) +{ + PAL_ERROR palError = NO_ERROR; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != poa); + + ENTRY("CPalObjectBase::Initialize" + "(this = %p, pthr = %p, poa = %p)\n", + this, + pthr, + poa + ); + + if (0 != m_pot->GetImmutableDataSize()) + { + m_pvImmutableData = InternalMalloc(m_pot->GetImmutableDataSize()); + if (NULL != m_pvImmutableData) + { + ZeroMemory(m_pvImmutableData, m_pot->GetImmutableDataSize()); + } + else + { + ERROR("Unable to allocate immutable data\n"); + palError = ERROR_OUTOFMEMORY; + goto IntializeExit; + } + } + + if (0 != m_pot->GetProcessLocalDataSize()) + { + palError = m_sdlLocalData.Initialize(); + if (NO_ERROR != palError) + { + ERROR("Unable to initialize local data lock!\n"); + goto IntializeExit; + } + + m_pvLocalData = InternalMalloc(m_pot->GetProcessLocalDataSize()); + if (NULL != m_pvLocalData) + { + ZeroMemory(m_pvLocalData, m_pot->GetProcessLocalDataSize()); + } + else + { + ERROR("Unable to allocate local data\n"); + palError = ERROR_OUTOFMEMORY; + goto IntializeExit; + } + } + + if (0 != poa->sObjectName.GetStringLength()) + { + palError = m_oa.sObjectName.CopyString(&poa->sObjectName); + } + +IntializeExit: + + LOGEXIT("CPalObjectBase::Initialize returns %d\n", palError); + + return palError; +} + +/*++ +Function: + CPalObjectBase::GetObjectType + + Returns the type of the object +--*/ + +CObjectType * +CPalObjectBase::GetObjectType( + VOID + ) +{ + ENTRY("CPalObjectBase::GetObjectType(this = %p)\n", this); + LOGEXIT("CPalObjectBase::GetObjectType returns %p\n", m_pot); + + return m_pot; +} + +/*++ +Function: + CPalObjectBase::GetObjectAttributes + + Returns the attributes of the object +--*/ + +CObjectAttributes * +CPalObjectBase::GetObjectAttributes( + VOID + ) +{ + ENTRY("CPalObjectBase::GetObjectAttributes(this = %p)\n", this); + LOGEXIT("CPalObjectBase::GetObjectAttributes returns %p\n", &m_oa); + + return &m_oa; +} + +/*++ +Function: + CPalObjectBase::GetImmutableData + + Provides the caller access to the object's immutable data (if any) + +Parameters: + ppvImmutableData -- on success, receives a pointer to the object's + immutable data +--*/ + +PAL_ERROR +CPalObjectBase::GetImmutableData( + void **ppvImmutableData // OUT + ) +{ + _ASSERTE(NULL != ppvImmutableData); + + ENTRY("CPalObjectBase::GetImmutableData" + "(this = %p, ppvImmutableData = %p)\n", + this, + ppvImmutableData + ); + + _ASSERTE(0 < m_pot->GetImmutableDataSize()); + + *ppvImmutableData = m_pvImmutableData; + + LOGEXIT("CPalObjectBase::GetImmutableData returns %d\n", NO_ERROR); + + return NO_ERROR; +} + +/*++ +Function: + CPalObjectBase::GetProcessLocalData + + Provides the caller access to the object's local data (if any) + +Parameters: + pthr -- thread data for calling thread + eLockRequest -- specifies if the caller desires a read lock or a + write lock on the data (currently ignored) + ppDataLock -- on success, receives a pointer to the data lock instance + for the local data + ppvProcssLocalData -- on success, receives a pointer to the local data +--*/ + +PAL_ERROR +CPalObjectBase::GetProcessLocalData( + CPalThread *pthr, + LockType eLockRequest, + IDataLock **ppDataLock, // OUT + void **ppvProcessLocalData // OUT + ) +{ + _ASSERTE(NULL != pthr); + _ASSERTE(ReadLock == eLockRequest || WriteLock == eLockRequest); + _ASSERTE(NULL != ppDataLock); + _ASSERTE(NULL != ppvProcessLocalData); + + ENTRY("CPalObjectBase::GetProcessLocalData" + "(this = %p, pthr = %p, eLockRequest = %d, ppDataLock = %p," + " ppvProcessLocalData = %p)\n", + this, + pthr, + eLockRequest, + ppDataLock, + ppvProcessLocalData + ); + + _ASSERTE(0 < m_pot->GetProcessLocalDataSize()); + + m_sdlLocalData.AcquireLock(pthr, ppDataLock); + *ppvProcessLocalData = m_pvLocalData; + + LOGEXIT("CPalObjectBase::GetProcessLocalData returns %d\n", NO_ERROR); + + return NO_ERROR; +} + +/*++ +Function: + CPalObjectBase::AddReference + + Increments the object's reference count. The updated count is returned + for diagnostic purposes only +--*/ + +DWORD +CPalObjectBase::AddReference( + void + ) +{ + LONG lRefCount; + + ENTRY("CPalObjectBase::AddReference(this = %p)\n", this); + + _ASSERTE(m_lRefCount > 0); + lRefCount = InterlockedIncrement(&m_lRefCount); + + LOGEXIT("CPalObjectBase::AddReference returns %d\n", lRefCount); + + return lRefCount; +} + +/*++ +Function: + CPalObjectBase::ReleaseReference + + Decrements the object's reference count. The updated count is returned + for diagnostic purposes only + +Parameters: + pthr -- thread data for calling thread +--*/ + +DWORD +CPalObjectBase::ReleaseReference( + CPalThread *pthr + ) +{ + LONG lRefCount; + + _ASSERTE(NULL != pthr); + + ENTRY("CPalObjectBase::ReleaseReference" + "(this = %p, pthr = %p)\n", + this, + pthr + ); + + AcquireObjectDestructionLock(pthr); + + _ASSERTE(m_lRefCount > 0); + + // + // Even though object destruction takes place under a lock + // we still need to use an interlocked decrement, as AddRef + // operates lock free + // + + lRefCount = InterlockedDecrement(&m_lRefCount); + + if (0 == lRefCount) + { + bool fCleanupSharedState = ReleaseObjectDestructionLock(pthr, TRUE); + + // + // We need to do two things with the calling thread data here: + // 1) store it in m_pthrCleanup so it is available to the destructors + // 2) Add a reference to it before starting any cleanup, and release + // that reference afterwords. + // + // Step 2 is necessary when we're cleaning up the thread object that + // represents the calling thread -- it ensures that the thread data + // is available throughout the entire cleanup process. + // + + m_pthrCleanup = pthr; + pthr->AddThreadReference(); + + if (NULL != m_pot->GetObjectCleanupRoutine()) + { + (*m_pot->GetObjectCleanupRoutine())( + pthr, + static_cast(this), + FALSE, + fCleanupSharedState + ); + } + + if (NULL != m_pot->GetImmutableDataCleanupRoutine()) + { + (*m_pot->GetImmutableDataCleanupRoutine())(m_pvImmutableData); + } + + if (NULL != m_pot->GetProcessLocalDataCleanupRoutine()) + { + (*m_pot->GetProcessLocalDataCleanupRoutine())(pthr, static_cast(this)); + } + + InternalDelete(this); + + pthr->ReleaseThreadReference(); + } + else + { + ReleaseObjectDestructionLock(pthr, FALSE); + } + + LOGEXIT("CPalObjectBase::ReleaseReference returns %d\n", lRefCount); + + return lRefCount; +} + +/*++ +Function: + CPalObjectBase::~CPalObjectBase + + Object destructor +--*/ + +CPalObjectBase::~CPalObjectBase() +{ + ENTRY("CPalObjectBase::~CPalObjectBase(this = %p)\n", this); + + if (NULL != m_pvImmutableData) + { + free(m_pvImmutableData); + } + + if (NULL != m_pvLocalData) + { + free(m_pvLocalData); + } + + if (NULL != m_oa.sObjectName.GetString()) + { + m_oa.sObjectName.FreeBuffer(); + } + + LOGEXIT("CPalObjectBase::~CPalObjectBase\n"); +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/palobjbase.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/palobjbase.hpp new file mode 100644 index 0000000..28efe0d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/palobjbase.hpp @@ -0,0 +1,191 @@ +// 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: + + palobjbase.hpp + +Abstract: + PAL object base class + + + +--*/ + +#ifndef _PALOBJBASE_HPP_ +#define _PALOBJBASE_HPP_ + +#include "pal/corunix.hpp" +#include "pal/cs.hpp" +#include "pal/thread.hpp" + +namespace CorUnix +{ + class CSimpleDataLock : IDataLock + { + private: + + CRITICAL_SECTION m_cs; + bool m_fInitialized; + + public: + + CSimpleDataLock() + : + m_fInitialized(FALSE) + { + }; + + virtual ~CSimpleDataLock() + { + if (m_fInitialized) + { + InternalDeleteCriticalSection(&m_cs); + } + }; + + PAL_ERROR + Initialize( + void + ) + { + PAL_ERROR palError = NO_ERROR; + + InternalInitializeCriticalSection(&m_cs); + m_fInitialized = TRUE; + + return palError; + }; + + void + AcquireLock( + CPalThread *pthr, + IDataLock **pDataLock + ) + { + InternalEnterCriticalSection(pthr, &m_cs); + *pDataLock = static_cast(this); + }; + + virtual + void + ReleaseLock( + CPalThread *pthr, + bool fDataChanged + ) + { + InternalLeaveCriticalSection(pthr, &m_cs); + }; + + }; + + class CPalObjectBase : public IPalObject + { + template friend void InternalDelete(T *p); + + protected: + + LONG m_lRefCount; + + VOID *m_pvImmutableData; + VOID *m_pvLocalData; + + CObjectType *m_pot; + CObjectAttributes m_oa; + + CSimpleDataLock m_sdlLocalData; + + // + // The thread that initiated object cleanup + // + + CPalThread *m_pthrCleanup; + + virtual ~CPalObjectBase(); + + virtual + void + AcquireObjectDestructionLock( + CPalThread *pthr + ) = 0; + + virtual + bool + ReleaseObjectDestructionLock( + CPalThread *pthr, + bool fDestructionPending + ) = 0; + + public: + + CPalObjectBase( + CObjectType *pot + ) + : + m_lRefCount(1), + m_pvImmutableData(NULL), + m_pvLocalData(NULL), + m_pot(pot), + m_pthrCleanup(NULL) + { + }; + + virtual + PAL_ERROR + Initialize( + CPalThread *pthr, + CObjectAttributes *poa + ); + + // + // IPalObject routines + // + + virtual + CObjectType * + GetObjectType( + VOID + ); + + virtual + CObjectAttributes * + GetObjectAttributes( + VOID + ); + + virtual + PAL_ERROR + GetImmutableData( + void **ppvImmutableData // OUT + ); + + virtual + PAL_ERROR + GetProcessLocalData( + CPalThread *pthr, // IN, OPTIONAL + LockType eLockRequest, + IDataLock **ppDataLock, // OUT + void **ppvProcessLocalData // OUT + ); + + virtual + DWORD + AddReference( + void + ); + + virtual + DWORD + ReleaseReference( + CPalThread *pthr + ); + }; +} + +#endif // _PALOBJBASE_HPP_ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobject.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobject.cpp new file mode 100644 index 0000000..2d3a182 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobject.cpp @@ -0,0 +1,1229 @@ +// 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: + + shmobject.hpp + +Abstract: + Shared memory based object + + + +--*/ + +#include "shmobject.hpp" +#include "pal/malloc.hpp" +#include "pal/cs.hpp" +#include "pal/dbgmsg.h" + +#include + +SET_DEFAULT_DEBUG_CHANNEL(PAL); + +using namespace CorUnix; + +/*++ +Function: + CSharedMemoryObject::Initialize + + Performs possibly-failing initialization for a newly-constructed + object + +Parameters: + pthr -- thread data for calling thread + poa -- the object attributes (e.g., name) for the object +--*/ + +PAL_ERROR +CSharedMemoryObject::Initialize( + CPalThread *pthr, + CObjectAttributes *poa + ) +{ + PAL_ERROR palError = NO_ERROR; + SHMObjData *psmod = NULL; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != poa); + + ENTRY("CSharedMemoryObject::Initialize" + "(this = %p, pthr = %p, poa = %p)\n", + this, + pthr, + poa + ); + + palError = CPalObjectBase::Initialize(pthr, poa); + if (NO_ERROR != palError) + { + goto InitializeExit; + } + + // + // If this is a named object it needs to go into the shared domain; + // otherwise it remains local + // + + if (0 != m_oa.sObjectName.GetStringLength()) + { + m_ObjectDomain = SharedObject; + + palError = AllocateSharedDataItems(&m_shmod, &psmod); + if (NO_ERROR != palError || NULL == psmod) + { + goto InitializeExit; + } + } + + if (0 != m_pot->GetSharedDataSize()) + { + if (SharedObject == m_ObjectDomain) + { + // + // Map the shared data into our address space + // + if (NULL == psmod) + { + ASSERT("psmod should not be NULL"); + palError = ERROR_INTERNAL_ERROR; + goto InitializeExit; + } + + m_pvSharedData = SHMPTR_TO_TYPED_PTR(VOID, psmod->shmObjSharedData); + if (NULL == m_pvSharedData) + { + ASSERT("Unable to map shared data area\n"); + palError = ERROR_INTERNAL_ERROR; + goto InitializeExit; + } + } + else + { + // + // Initialize the local shared data lock. + // + + palError = m_sdlSharedData.Initialize(); + if (NO_ERROR != palError) + { + ERROR("Failure initializing m_sdlSharedData\n"); + goto InitializeExit; + } + + // + // Allocate local memory to hold the shared data + // + + m_pvSharedData = InternalMalloc(m_pot->GetSharedDataSize()); + if (NULL == m_pvSharedData) + { + ERROR("Failure allocating m_pvSharedData (local copy)\n"); + palError = ERROR_OUTOFMEMORY; + goto InitializeExit; + } + } + + ZeroMemory(m_pvSharedData, m_pot->GetSharedDataSize()); + } + + +InitializeExit: + + LOGEXIT("CSharedMemoryObject::Initalize returns %d\n", palError); + + return palError; +} + +/*++ +Function: + CSharedMemoryObject::InitializeFromExistingSharedData + + Performs possibly-failing initialization for a newly-constructed + object that is to represent an existing object (i.e., importing + a shared object into this process) + + The shared memory lock must be held when calling this method + +Parameters: + pthr -- thread data for calling thread + poa -- the object attributes for the object +--*/ + +PAL_ERROR +CSharedMemoryObject::InitializeFromExistingSharedData( + CPalThread *pthr, + CObjectAttributes *poa + ) +{ + PAL_ERROR palError = NO_ERROR; + SHMObjData *psmod = NULL; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != poa); + + ENTRY("CSharedMemoryObject::InitializeFromExistingSharedData" + "(this = %p, pthr = %p, poa = %p)\n", + this, + pthr, + poa + ); + + // + // This object is obviously shared... + // + + m_ObjectDomain = SharedObject; + + _ASSERTE(NULL != m_shmod); + + psmod = SHMPTR_TO_TYPED_PTR(SHMObjData, m_shmod); + if (NULL == psmod) + { + ASSERT("Unable to map shared object data\n"); + palError = ERROR_INTERNAL_ERROR; + goto InitializeFromExistingSharedDataExit; + } + + // + // When we're being called on the duplicate handle path the passed + // in object attributes likely won't have an object name in it. + // If there is an object name in the shared data place that in the + // object attributs so that the constructed object has a local copy + // of the name + // + + if (0 == poa->sObjectName.GetStringLength() + && 0 != psmod->dwNameLength) + { + WCHAR *wsz; + + wsz = SHMPTR_TO_TYPED_PTR(WCHAR, psmod->shmObjName); + if (NULL != wsz) + { + poa->sObjectName.SetStringWithLength(wsz, psmod->dwNameLength); + } + else + { + ASSERT("Unable to map object name\n"); + palError = ERROR_INTERNAL_ERROR; + goto InitializeFromExistingSharedDataExit; + } + } +#if _DEBUG + else if (0 != psmod->dwNameLength) + { + WCHAR *wsz; + + // + // Verify that the names are consistent + // + + wsz = SHMPTR_TO_TYPED_PTR(WCHAR, psmod->shmObjName); + _ASSERTE(NULL != wsz); + _ASSERTE(0 == PAL_wcscmp(wsz, poa->sObjectName.GetString())); + } +#endif // debug + + palError = CPalObjectBase::Initialize(pthr, poa); + if (NO_ERROR != palError) + { + goto InitializeFromExistingSharedDataExit; + } + + if (NULL != psmod->shmObjImmutableData) + { + VOID *pv = SHMPTR_TO_TYPED_PTR(VOID, psmod->shmObjImmutableData); + if (NULL != pv) + { + memcpy(m_pvImmutableData, pv, m_pot->GetImmutableDataSize()); + if (NULL != psmod->pCopyRoutine) + { + (*psmod->pCopyRoutine)(pv, m_pvImmutableData); + } + + m_pot->SetImmutableDataCopyRoutine(psmod->pCopyRoutine); + m_pot->SetImmutableDataCleanupRoutine(psmod->pCleanupRoutine); + } + else + { + ASSERT("Unable to map object immutable data\n"); + palError = ERROR_INTERNAL_ERROR; + goto InitializeFromExistingSharedDataExit; + } + } + + if (NULL != psmod->shmObjSharedData) + { + m_pvSharedData = SHMPTR_TO_TYPED_PTR(VOID, psmod->shmObjSharedData); + if (NULL == m_pvSharedData) + { + ASSERT("Unable to map object shared data\n"); + palError = ERROR_INTERNAL_ERROR; + goto InitializeFromExistingSharedDataExit; + } + } + + if (NULL != m_pot->GetObjectInitRoutine()) + { + palError = (*m_pot->GetObjectInitRoutine())( + pthr, + m_pot, + m_pvImmutableData, + m_pvSharedData, + m_pvLocalData + ); + } + +InitializeFromExistingSharedDataExit: + + LOGEXIT("CSharedMemoryObject::InitalizeFromExistingSharedData returns %d\n", palError); + + return palError; +} + +/*++ +Function: + CSharedMemoryObject::AllocatedSharedDataItems + + Allocates and initialiazes the shared memory structures necessary to make an + object available to other processes + +Parameters: + pshmObjData -- on success, receives the shared memory pointer for the + shared memory object data + ppsmod -- on success, receives the locally-mapped pointer for the shared + memory object data +--*/ + +PAL_ERROR +CSharedMemoryObject::AllocateSharedDataItems( + SHMPTR *pshmObjData, + SHMObjData **ppsmod + ) +{ + PAL_ERROR palError = NO_ERROR; + SHMPTR shmod = NULL; + SHMObjData *psmod = NULL; + + _ASSERTE(NULL != pshmObjData); + _ASSERTE(NULL != ppsmod); + + ENTRY("CSharedMemoryObject::AllocateSharedDataItems" + "(this = %p, pshmObjData = %p, ppsmod = %p)\n", + this, + pshmObjData, + ppsmod + ); + + // + // We're about to make a number of shared memory allocations, + // so grab the lock for the entirety of the routine. + // + + SHMLock(); + + shmod = malloc(sizeof(SHMObjData)); + if (NULL == shmod) + { + ERROR("Unable to allocate m_shmod for new object\n"); + palError = ERROR_OUTOFMEMORY; + goto AllocateSharedDataItemsExit; + } + + psmod = SHMPTR_TO_TYPED_PTR(SHMObjData, shmod); + _ASSERTE(NULL != psmod); + + ZeroMemory(psmod, sizeof(*psmod)); + + psmod->eTypeId = m_pot->GetId(); + psmod->lProcessRefCount = 1; + + if (0 != m_oa.sObjectName.GetStringLength()) + { + LPCWSTR str = m_oa.sObjectName.GetString(); + _ASSERTE(str); + + psmod->dwNameLength = m_oa.sObjectName.GetStringLength(); + + UINT length = (PAL_wcslen(str) + 1) * sizeof(WCHAR); + psmod->shmObjName = malloc(length); + + if (psmod->shmObjName != 0) + { + memcpy(psmod->shmObjName, str, length); + } + else + { + ERROR("Unable to allocate psmod->shmObjName for new object\n"); + palError = ERROR_OUTOFMEMORY; + goto AllocateSharedDataItemsExit; + } + } + + if (0 != m_pot->GetImmutableDataSize()) + { + // + // The shared copy of the object's immutable data will be initialized + // by CSharedMemoryObjectManager::RegisterObject or PromoteSharedData + // + + psmod->shmObjImmutableData = malloc(m_pot->GetImmutableDataSize()); + if (NULL == psmod->shmObjImmutableData) + { + ERROR("Unable to allocate psmod->shmObjImmutableData for new object\n"); + palError = ERROR_OUTOFMEMORY; + goto AllocateSharedDataItemsExit; + } + } + + if (0 != m_pot->GetSharedDataSize()) + { + psmod->shmObjSharedData = malloc(m_pot->GetSharedDataSize()); + if (NULL == psmod->shmObjSharedData) + { + ERROR("Unable to allocate psmod->shmObjSharedData for new object\n"); + palError = ERROR_OUTOFMEMORY; + goto AllocateSharedDataItemsExit; + } + } + + *pshmObjData = shmod; + *ppsmod = psmod; + +AllocateSharedDataItemsExit: + + if (NO_ERROR != palError && NULL != shmod) + { + FreeSharedDataAreas(shmod); + } + + SHMRelease(); + + LOGEXIT("CSharedMemoryObject::AllocateSharedDataItems returns %d\n", palError); + + return palError; +} + +/*++ +Function: + CSharedMemoryObject::FreeSharedDataItems + + Frees the shared memory structures referenced by the provided shared + memory pointer + +Parameters: + shmObjData -- shared memory pointer to the structures to free +--*/ + +// static +void +CSharedMemoryObject::FreeSharedDataAreas( + SHMPTR shmObjData + ) +{ + SHMObjData *psmod; + + _ASSERTE(NULL != shmObjData); + + ENTRY("CSharedMemoryObject::FreeSharedDataAreas" + "(shmObjData = %p)\n", + shmObjData + ); + + SHMLock(); + + psmod = SHMPTR_TO_TYPED_PTR(SHMObjData, shmObjData); + _ASSERTE(NULL != psmod); + + if (NULL != psmod->shmObjImmutableData) + { + if (NULL != psmod->pCleanupRoutine) + { + (*psmod->pCleanupRoutine)(psmod->shmObjImmutableData); + } + free(psmod->shmObjImmutableData); + } + + if (NULL != psmod->shmObjSharedData) + { + free(psmod->shmObjSharedData); + } + + if (NULL != psmod->shmObjName) + { + free(psmod->shmObjName); + } + + free(shmObjData); + + SHMRelease(); + + LOGEXIT("CSharedMemoryObject::FreeSharedDataAreas\n"); +} + +/*++ +Function: + CSharedMemoryObject::CleanupForProcessShutdown + + Cleanup routine called by the object manager when shutting down + +Parameters: + pthr -- thread data for the calling thread +--*/ + +void +CSharedMemoryObject::CleanupForProcessShutdown( + CPalThread *pthr + ) +{ + bool fCleanupSharedState; + + _ASSERTE(NULL != pthr); + + ENTRY("CSharedMemoryObject::CleanupForProcessShutdown" + "(this = %p, pthr = %p)\n", + this, + pthr + ); + + fCleanupSharedState = DereferenceSharedData(); + + if (NULL != m_pot->GetObjectCleanupRoutine()) + { + (*m_pot->GetObjectCleanupRoutine())( + pthr, + static_cast(this), + TRUE, + fCleanupSharedState + ); + } + + if (NULL != m_pot->GetImmutableDataCleanupRoutine()) + { + (*m_pot->GetImmutableDataCleanupRoutine())(m_pvImmutableData); + } + + if (NULL != m_pot->GetProcessLocalDataCleanupRoutine()) + { + (*m_pot->GetProcessLocalDataCleanupRoutine())(pthr, static_cast(this)); + } + + // + // We need to do two things with the calling thread data here: + // 1) store it in m_pthrCleanup so it is available to the destructors + // 2) Add a reference to it before starting any cleanup, and release + // that reference afterwords. + // + // Step 2 is necessary when we're cleaning up the thread object that + // represents the calling thread -- it ensures that the thread data + // is available throughout the entire cleanup process. + // + + m_pthrCleanup = pthr; + pthr->AddThreadReference(); + + InternalDelete(this); + + pthr->ReleaseThreadReference(); + + LOGEXIT("CSharedMemoryObject::CleanupForProcessShutdown\n"); +} + +/*++ +Function: + CSharedMemoryObject::AcquiteObjectDestructionLock + + Acquires the lock that must be held when decrementing the object's + reference count (and, if the count drops to 0, while removing the + object from the object manager's lists). + +Parameters: + pthr -- thread data for the calling thread +--*/ + +void +CSharedMemoryObject::AcquireObjectDestructionLock( + CPalThread *pthr + ) +{ + _ASSERTE(NULL != pthr); + + ENTRY("CSharedMemoryObject::AcquireObjectDestructionLock" + "(this = %p, pthr = $p)\n", + this, + pthr + ); + + InternalEnterCriticalSection(pthr, m_pcsObjListLock); + + LOGEXIT("CSharedMemoryObject::AcquireObjectDestructionLock\n"); +} + +/*++ +Function: + CSharedMemoryObject::ReleaseObjectDestructionLock + + Releases the lock acquired by AcquireObjectDestructionLock + +Parameters: + pthr -- thread data for the calling thread + fDestructionPending -- if TRUE, the reference count for this + object has dropped to 0; the object will be destroyed after + this routine returns +--*/ + +bool +CSharedMemoryObject::ReleaseObjectDestructionLock( + CPalThread *pthr, + bool fDestructionPending + ) +{ + bool fCleanupSharedState = FALSE; + + _ASSERTE(NULL != pthr); + + ENTRY("CSharedMemoryObject::ReleaseObjectDestructionLock" + "(this = %p, pthr = %p, fDestructionPending = %d\n", + this, + pthr, + fDestructionPending + ); + + if (fDestructionPending) + { + RemoveEntryList(&m_le); + fCleanupSharedState = DereferenceSharedData(); + } + + InternalLeaveCriticalSection(pthr, m_pcsObjListLock); + + LOGEXIT("CSharedMemoryObject::ReleaseObjectDestructionLock returns %d\n", + fCleanupSharedState + ); + + return fCleanupSharedState; +} + +/*++ +Function: + CSharedMemoryObject::DereferenceSharedData + + Called to decrement the global refcount (i.e., the count of + the number of processes that have reference to the object) when + the local reference to the object is being destroyed. + +Return value: + Returns TRUE if this process needs to clean up the object's shared + data (i.e., the global refcount has dropped to 0, or the object + is in the local domain) +--*/ + +bool +CSharedMemoryObject::DereferenceSharedData() +{ + LONG fSharedDataAlreadDereferenced; + + ENTRY("CSharedMemoryObject::DereferenceSharedData(this = %p)\n", this); + + fSharedDataAlreadDereferenced = InterlockedExchange( + &m_fSharedDataDereferenced, + TRUE + ); + + if (!fSharedDataAlreadDereferenced) + { + if (NULL != m_shmod) + { + SHMObjData *psmod; + + SHMLock(); + + psmod = SHMPTR_TO_TYPED_PTR(SHMObjData, m_shmod); + _ASSERTE(NULL != psmod); + + psmod->lProcessRefCount -= 1; + if (0 == psmod->lProcessRefCount) + { + // + // No other process is using this object, so remove + // it from the shared memory named object list (if it + // had been added to it). The final cleanup will happen + // in the object's destructor + // + + m_fDeleteSharedData = TRUE; + + if (psmod->fAddedToList) + { + // + // This object better have a name... + // + + _ASSERTE(0 != psmod->dwNameLength); + + if (NULL != psmod->shmPrevObj) + { + SHMObjData *psmodPrevious = SHMPTR_TO_TYPED_PTR(SHMObjData, psmod->shmPrevObj); + _ASSERTE(NULL != psmodPrevious); + + psmodPrevious->shmNextObj = psmod->shmNextObj; + } + else + { + // + // This object is the head of the shared memory named object + // list -- reset that pointer now + // + + if (!SHMSetInfo(SIID_NAMED_OBJECTS, psmod->shmNextObj)) + { + ASSERT("Failed to set shared named object list head"); + } + } + + if (NULL != psmod->shmNextObj) + { + SHMObjData *psmodNext = SHMPTR_TO_TYPED_PTR(SHMObjData, psmod->shmNextObj); + _ASSERTE(NULL != psmodNext); + + psmodNext->shmPrevObj = psmod->shmPrevObj; + } + } +#if _DEBUG + else + { + _ASSERTE(NULL == psmod->shmPrevObj); + _ASSERTE(NULL == psmod->shmNextObj); + } +#endif + } + + SHMRelease(); + } + else if (ProcessLocalObject == m_ObjectDomain) + { + // + // If the object is local the shared data needs to be + // deleted by definition + // + + m_fDeleteSharedData = TRUE; + } + } + else + { + ASSERT("Multiple calls to DereferenceSharedData\n"); + } + + LOGEXIT("CSharedMemoryObject::DereferenceSharedData returns %d\n", + m_fDeleteSharedData + ); + + return m_fDeleteSharedData; +} + +/*++ +Function: + CSharedMemoryObject::~CSharedMemoryObject + + Destructor; should only be called from ReleaseReference +--*/ + +CSharedMemoryObject::~CSharedMemoryObject() +{ + ENTRY("CSharedMemoryObject::~CSharedMemoryObject(this = %p)\n", this); + + if (!m_fSharedDataDereferenced) + { + ASSERT("DereferenceSharedData not called before object destructor -- delete called directly?\n"); + DereferenceSharedData(); + } + + if (NULL != m_pvSharedData && ProcessLocalObject == m_ObjectDomain) + { + free(m_pvSharedData); + } + else if (NULL != m_shmod && m_fDeleteSharedData) + { + FreeSharedDataAreas(m_shmod); + } + + LOGEXIT("CSharedMemoryObject::~CSharedMemoryObject\n"); +} + +// +// C++ standard, 18.1.5 - offsetof requires a POD (plain old data) struct or +// union. Since offsetof is a macro, gcc doesn't actually check for improper +// use of offsetof, it keys off of the -> from NULL (which is also invalid for +// non-POD types by 18.1.5) +// +// As we have numerous examples of this behavior in our codebase, +// making an offsetof which doesn't use 0. +// +// PAL_safe_offsetof is a version of offsetof that protects against an +// overridden operator& +// + +#define PAL_safe_offsetof(s,m) ((size_t)((ptrdiff_t)&(char&)(((s *)64)->m))-64) + +/*++ +Function: + CSharedMemoryObject::GetObjectFromListLink + + Given a list link returns the object that contains it. Since m_le is + protected the caller cannot perform this computation directly + +Parameters: + ple -- the list entry to obtain the object for +--*/ + +// static +CSharedMemoryObject* +CSharedMemoryObject::GetObjectFromListLink(PLIST_ENTRY ple) +{ + CSharedMemoryObject *pshmo; + + _ASSERTE(NULL != ple); + + ENTRY("CSharedMemoryObject::GetObjectFromListLink(ple = %p)\n", ple); + + // + // Ideally we'd use CONTAINING_RECORD here, but it uses offsetof (see above + // comment + // + + pshmo = reinterpret_cast( + reinterpret_cast(ple) - PAL_safe_offsetof(CSharedMemoryObject, m_le) + ); + + _ASSERTE(ple == &pshmo->m_le); + + LOGEXIT("CSharedMemoryObject::GetObjectFromListLink returns %p\n", pshmo); + + return pshmo; +} + +/*++ +Function: + CSharedMemoryObject::GetSharedData + + Provides the caller access to the object's shared data (if any) + +Parameters: + pthr -- thread data for calling thread + eLockRequest -- specifies if the caller desires a read lock or a + write lock on the data (currently ignored) + ppDataLock -- on success, receives a pointer to the data lock instance + for the shared data + ppvProcssSharedData -- on success, receives a pointer to the shared data +--*/ + +PAL_ERROR +CSharedMemoryObject::GetSharedData( + CPalThread *pthr, + LockType eLockRequest, + IDataLock **ppDataLock, // OUT + void **ppvSharedData // OUT + ) +{ + IDataLock *pDataLock; + + _ASSERTE(NULL != pthr); + _ASSERTE(ReadLock == eLockRequest || WriteLock == eLockRequest); + _ASSERTE(NULL != ppDataLock); + _ASSERTE(NULL != ppvSharedData); + + ENTRY("CSharedMemoryObject::GetSharedData" + "(this = %p, pthr = %p, eLockRequest = %d, ppDataLock = %p," + " ppvSharedData = %p)\n", + this, + pthr, + eLockRequest, + ppDataLock, + ppvSharedData + ); + + _ASSERTE(0 < m_pot->GetSharedDataSize()); + + if (ProcessLocalObject == m_ObjectDomain) + { + // + // We need to grab the local shared data lock and re-check + // the object's domain, as there's a chance the object might + // have been promoted after we made the above check but before + // we grabbed the lock + // + + m_sdlSharedData.AcquireLock(pthr, &pDataLock); + + if (SharedObject == m_ObjectDomain) + { + pDataLock->ReleaseLock(pthr, FALSE); + m_ssmlSharedData.AcquireLock(pthr, &pDataLock); + } + } + else + { + // + // A shared object can never transition back to local, + // so there's no need to recheck the domain on this path + // + + m_ssmlSharedData.AcquireLock(pthr, &pDataLock); + } + + *ppDataLock = pDataLock; + *ppvSharedData = m_pvSharedData; + + LOGEXIT("CSharedMemoryObject::GetSharedData returns %d\n", NO_ERROR); + + return NO_ERROR; +} + +/*++ +Function: + CSharedMemoryObject::GetSynchStateController + + Obtain a synchronization state controller for this object. Should + never be called. + +Parameters: + pthr -- thread data for calling thread + ppStateController -- on success, receives a pointer to the state controller + instance +--*/ + +PAL_ERROR +CSharedMemoryObject::GetSynchStateController( + CPalThread *pthr, + ISynchStateController **ppStateController // OUT + ) +{ + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != ppStateController); + + // + // This is not a waitable object! + // + + ASSERT("Attempt to obtain a synch state controller on a non-waitable object\n"); + return ERROR_INVALID_HANDLE; +} + +/*++ +Function: + CSharedMemoryObject::GetSynchWaitController + + Obtain a synchronization wait controller for this object. Should + never be called. + +Parameters: + pthr -- thread data for calling thread + ppWaitController -- on success, receives a pointer to the wait controller + instance +--*/ + +PAL_ERROR +CSharedMemoryObject::GetSynchWaitController( + CPalThread *pthr, + ISynchWaitController **ppWaitController // OUT + ) +{ + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != ppWaitController); + + // + // This is not a waitable object!!! + // + + ASSERT("Attempt to obtain a synch wait controller on a non-waitable object\n"); + return ERROR_INVALID_HANDLE; +} + +/*++ +Function: + CSharedMemoryObject::GetObjectDomain + + Returns the object's domain (local or shared) + +--*/ + +ObjectDomain +CSharedMemoryObject::GetObjectDomain( + void + ) +{ + TRACE("CSharedMemoryObject::GetObjectDomain(this = %p)\n", this); + LOGEXIT("CSharedMemoryObject::GetObjectDomain returns %d\n", m_ObjectDomain); + + return m_ObjectDomain; +} + +/*++ +Function: + CSharedMemoryObject::GetObjectSynchData + + Obtain the synchronization data for this object. Should + never be called. + +Parameters: + ppvSynchData -- on success, receives a pointer to the object's synch data +--*/ + +PAL_ERROR +CSharedMemoryObject::GetObjectSynchData( + VOID **ppvSynchData // OUT + ) +{ + _ASSERTE(NULL != ppvSynchData); + + // + // This is not a waitable object!!! + // + + ASSERT("Attempt to obtain a synch data for a non-waitable object\n"); + return ERROR_INVALID_HANDLE; +} + +/*++ +Function: + CSharedMemoryWaitableObject::Initialize + + Performs possibly-failing initialization for a newly-constructed + object + +Parameters: + pthr -- thread data for calling thread + poa -- the object attributes (e.g., name) for the object +--*/ + +PAL_ERROR +CSharedMemoryWaitableObject::Initialize( + CPalThread *pthr, + CObjectAttributes *poa + ) +{ + PAL_ERROR palError = NO_ERROR; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != poa); + + ENTRY("CSharedMemoryWaitableObject::Initialize" + "(this = %p, pthr = %p, poa = %p)\n", + this, + pthr, + poa + ); + + palError = CSharedMemoryObject::Initialize(pthr, poa); + if (NO_ERROR != palError) + { + goto InitializeExit; + } + + // + // Sanity check the passed in object type + // + + _ASSERTE(CObjectType::WaitableObject == m_pot->GetSynchronizationSupport()); + + palError = g_pSynchronizationManager->AllocateObjectSynchData( + m_pot, + m_ObjectDomain, + &m_pvSynchData + ); + + if (NO_ERROR == palError && SharedObject == m_ObjectDomain) + { + SHMObjData *pshmod = SHMPTR_TO_TYPED_PTR(SHMObjData, m_shmod); + _ASSERTE(NULL != pshmod); + + pshmod->pvSynchData = m_pvSynchData; + } + +InitializeExit: + + LOGEXIT("CSharedMemoryWaitableObject::Initialize returns %d\n", palError); + + return palError; +} + +/*++ +Function: + CSharedMemoryWaitableObject::~CSharedMemoryWaitableObject + + Destructor; should only be called from ReleaseReference +--*/ + +CSharedMemoryWaitableObject::~CSharedMemoryWaitableObject() +{ + ENTRY("CSharedMemoryWaitableObject::~CSharedMemoryWaitableObject" + "(this = %p)\n", + this + ); + + if (!m_fSharedDataDereferenced) + { + ASSERT("DereferenceSharedData not called before object destructor -- delete called directly?\n"); + DereferenceSharedData(); + } + + if (NULL != m_pvSynchData && m_fDeleteSharedData) + { + g_pSynchronizationManager->FreeObjectSynchData( + m_pot, + m_ObjectDomain, + m_pvSynchData + ); + } + + LOGEXIT("CSharedMemoryWaitableObject::~CSharedMemoryWaitableObject\n"); +} + +/*++ +Function: + CSharedMemoryWaitableObject::GetSynchStateController + + Obtain a synchronization state controller for this object. + +Parameters: + pthr -- thread data for calling thread + ppStateController -- on success, receives a pointer to the state controller + instance +--*/ + +PAL_ERROR +CSharedMemoryWaitableObject::GetSynchStateController( + CPalThread *pthr, // IN, OPTIONAL + ISynchStateController **ppStateController // OUT + ) +{ + PAL_ERROR palError = NO_ERROR; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != ppStateController); + + ENTRY("CSharedMemoryWaitableObject::GetSynchStateController" + "(this = %p, pthr = %p, ppStateController = %p", + this, + pthr, + ppStateController + ); + + // + // We need to grab the local synch lock before creating the controller + // (otherwise we could get promoted after passing in our parameters) + // + + g_pSynchronizationManager->AcquireProcessLock(pthr); + + palError = g_pSynchronizationManager->CreateSynchStateController( + pthr, + m_pot, + m_pvSynchData, + m_ObjectDomain, + ppStateController + ); + + g_pSynchronizationManager->ReleaseProcessLock(pthr); + + LOGEXIT("CSharedMemoryWaitableObject::GetSynchStateController returns %d\n", + palError + ); + + return palError; +} + +/*++ +Function: + CSharedMemoryWaitableObject::GetSynchWaitController + + Obtain a synchronization wait controller for this object. + +Parameters: + pthr -- thread data for calling thread + ppWaitController -- on success, receives a pointer to the wait controller + instance +--*/ + +PAL_ERROR +CSharedMemoryWaitableObject::GetSynchWaitController( + CPalThread *pthr, // IN, OPTIONAL + ISynchWaitController **ppWaitController // OUT + ) +{ + PAL_ERROR palError = NO_ERROR; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != ppWaitController); + + ENTRY("CSharedMemoryWaitableObject::GetSynchWaitController" + "(this = %p, pthr = %p, ppWaitController = %p", + this, + pthr, + ppWaitController + ); + + // + // We need to grab the local synch lock before creating the controller + // (otherwise we could get promoted after passing in our parameters) + // + + g_pSynchronizationManager->AcquireProcessLock(pthr); + + palError = g_pSynchronizationManager->CreateSynchWaitController( + pthr, + m_pot, + m_pvSynchData, + m_ObjectDomain, + ppWaitController + ); + + g_pSynchronizationManager->ReleaseProcessLock(pthr); + + LOGEXIT("CSharedMemoryWaitableObject::GetSynchWaitController returns %d\n", + palError + ); + + return palError; +} + +/*++ +Function: + CSharedMemoryWaitableObject::GetObjectSynchData + + Obtain the synchronization data for this object. This method should only + be called by the synchronization manager + +Parameters: + ppvSynchData -- on success, receives a pointer to the object's synch data +--*/ + +PAL_ERROR +CSharedMemoryWaitableObject::GetObjectSynchData( + VOID **ppvSynchData // OUT + ) +{ + _ASSERTE(NULL != ppvSynchData); + + ENTRY("CSharedMemoryWaitableObject::GetObjectSynchData" + "(this = %p, ppvSynchData = %p)\n", + this, + ppvSynchData + ); + + *ppvSynchData = m_pvSynchData; + + LOGEXIT("CSharedMemoryWaitableObject::GetObjectSynchData returns %d\n", + NO_ERROR + ); + + return NO_ERROR; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobject.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobject.hpp new file mode 100644 index 0000000..8c8727b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobject.hpp @@ -0,0 +1,375 @@ +// 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: + + shmobject.hpp + +Abstract: + Shared memory based object + + + +--*/ + +#ifndef _PAL_SHMOBJECT_HPP +#define _PAL_SHMOBJECT_HPP + +#include "palobjbase.hpp" +#include "pal/shm.hpp" + +extern "C" +{ +#include "pal/list.h" +} + +namespace CorUnix +{ + class CSimpleSharedMemoryLock : public IDataLock + { + public: + + void + AcquireLock( + CPalThread *pthr, + IDataLock **ppDataLock + ) + { + SHMLock(); + *ppDataLock = static_cast(this); + }; + + virtual + void + ReleaseLock( + CPalThread *pthr, + bool fDataChanged + ) + { + SHMRelease(); + }; + }; + + typedef struct _SHMObjData + { + SHMPTR shmPrevObj; + SHMPTR shmNextObj; + BOOL fAddedToList; + + SHMPTR shmObjName; + SHMPTR shmObjImmutableData; + SHMPTR shmObjSharedData; + + OBJECT_IMMUTABLE_DATA_COPY_ROUTINE pCopyRoutine; + OBJECT_IMMUTABLE_DATA_CLEANUP_ROUTINE pCleanupRoutine; + + LONG lProcessRefCount; + DWORD dwNameLength; + + PalObjectTypeId eTypeId; + + PVOID pvSynchData; + } SHMObjData; + + class CSharedMemoryObject : public CPalObjectBase + { + template friend void InternalDelete(T *p); + + protected: + + // + // Entry on the process's named or anonymous object list + // + + LIST_ENTRY m_le; + + // + // The lock that guards access to that list + // + + CRITICAL_SECTION *m_pcsObjListLock; + + // + // The SHMObjData for this object, protected by the + // shared memory lock. + // + + SHMPTR m_shmod; + + // + // The shared data (i.e., m_shmObjData->shmObjSharedData) + // for this object, mapped into this process. This will be + // NULL if m_pot->dwSharedDataSize is 0. Access to this data + // is controlled by m_ssmlSharedData when m_ObjectDomain is + // SharedObject, and m_sdlSharedData when it is ProcessLocalObject. + // + + VOID *m_pvSharedData; + + CSimpleSharedMemoryLock m_ssmlSharedData; + CSimpleDataLock m_sdlSharedData; + + // + // Is this object process local or shared? + // + + ObjectDomain m_ObjectDomain; + + // + // m_fSharedDataDereferenced will be TRUE if DereferenceSharedData + // has already been called. (N.B. -- this is a LONG instead of a bool + // because it is passed to InterlockedExchange). If the shared data blob + // should be freed in the object's destructor DereferenceSharedData will + // set m_fDeleteSharedData to TRUE. + // + + LONG m_fSharedDataDereferenced; + LONG m_fDeleteSharedData; + + PAL_ERROR + AllocateSharedDataItems( + SHMPTR *pshmObjData, + SHMObjData **ppsmod + ); + + static + void + FreeSharedDataAreas( + SHMPTR shmObjData + ); + + bool + DereferenceSharedData(); + + virtual + void + AcquireObjectDestructionLock( + CPalThread *pthr + ); + + virtual + bool + ReleaseObjectDestructionLock( + CPalThread *pthr, + bool fDestructionPending + ); + + virtual ~CSharedMemoryObject(); + + public: + + // + // Constructor used for new object + // + + CSharedMemoryObject( + CObjectType *pot, + CRITICAL_SECTION *pcsObjListLock + ) + : + CPalObjectBase(pot), + m_pcsObjListLock(pcsObjListLock), + m_shmod(NULL), + m_pvSharedData(NULL), + m_ObjectDomain(ProcessLocalObject), + m_fSharedDataDereferenced(FALSE), + m_fDeleteSharedData(FALSE) + { + InitializeListHead(&m_le); + }; + + // + // Constructor used to import a shared object into this process. The + // shared memory lock must be held when calling this contstructor + // + + CSharedMemoryObject( + CObjectType *pot, + CRITICAL_SECTION *pcsObjListLock, + SHMPTR shmSharedObjectData, + SHMObjData *psmod, + bool fAddRefSharedData + ) + : + CPalObjectBase(pot), + m_pcsObjListLock(pcsObjListLock), + m_shmod(shmSharedObjectData), + m_pvSharedData(NULL), + m_ObjectDomain(SharedObject), + m_fSharedDataDereferenced(FALSE), + m_fDeleteSharedData(FALSE) + { + InitializeListHead(&m_le); + if (fAddRefSharedData) + { + psmod->lProcessRefCount += 1; + } + }; + + virtual + PAL_ERROR + Initialize( + CPalThread *pthr, + CObjectAttributes *poa + ); + + virtual + PAL_ERROR + InitializeFromExistingSharedData( + CPalThread *pthr, + CObjectAttributes *poa + ); + + void + CleanupForProcessShutdown( + CPalThread *pthr + ); + + SHMPTR + GetShmObjData( + void + ) + { + return m_shmod; + }; + + PLIST_ENTRY + GetObjectListLink( + void + ) + { + return &m_le; + } + + // + // Clients of this object -- in particular, CSharedMemoryObjectManager + // -- can't use CONTAINING_RECORD directly, since they don't have + // access to m_Link. + // + + static + CSharedMemoryObject* + GetObjectFromListLink(PLIST_ENTRY pLink); + + // + // IPalObject routines + // + + virtual + PAL_ERROR + GetSharedData( + CPalThread *pthr, + LockType eLockRequest, + IDataLock **ppDataLock, + void **ppvSharedData + ); + + virtual + PAL_ERROR + GetSynchStateController( + CPalThread *pthr, + ISynchStateController **ppStateController + ); + + virtual + PAL_ERROR + GetSynchWaitController( + CPalThread *pthr, + ISynchWaitController **ppWaitController + ); + + virtual + ObjectDomain + GetObjectDomain( + void + ); + + virtual + PAL_ERROR + GetObjectSynchData( + VOID **ppvSynchData + ); + + }; + + class CSharedMemoryWaitableObject : public CSharedMemoryObject + { + template friend void InternalDelete(T *p); + + protected: + + VOID *m_pvSynchData; + + virtual ~CSharedMemoryWaitableObject(); + + public: + + CSharedMemoryWaitableObject( + CObjectType *pot, + CRITICAL_SECTION *pcsObjListLock + ) + : + CSharedMemoryObject(pot, pcsObjListLock), + m_pvSynchData(NULL) + { + }; + + // + // Constructor used to import a shared object into this process. The + // shared memory lock must be held when calling this contstructor + // + + CSharedMemoryWaitableObject( + CObjectType *pot, + CRITICAL_SECTION *pcsObjListLock, + SHMPTR shmSharedObjectData, + SHMObjData *psmod, + bool fAddRefSharedData + ) + : + CSharedMemoryObject(pot, pcsObjListLock, shmSharedObjectData, psmod, fAddRefSharedData), + m_pvSynchData(psmod->pvSynchData) + { + }; + + virtual + PAL_ERROR + Initialize( + CPalThread *pthr, + CObjectAttributes *poa + ); + + // + // IPalObject routines + // + + virtual + PAL_ERROR + GetSynchStateController( + CPalThread *pthr, + ISynchStateController **ppStateController + ); + + virtual + PAL_ERROR + GetSynchWaitController( + CPalThread *pthr, + ISynchWaitController **ppWaitController + ); + + virtual + PAL_ERROR + GetObjectSynchData( + VOID **ppvSynchData + ); + }; + +} + +#endif // _PAL_SHMOBJECT_HPP + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobjectmanager.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobjectmanager.cpp new file mode 100644 index 0000000..7769779 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobjectmanager.cpp @@ -0,0 +1,1130 @@ +// 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: + + shmobjectmgr.cpp + +Abstract: + Shared memory based object manager + + + +--*/ + +#include "shmobjectmanager.hpp" +#include "shmobject.hpp" +#include "pal/cs.hpp" +#include "pal/thread.hpp" +#include "pal/procobj.hpp" +#include "pal/dbgmsg.h" + +SET_DEFAULT_DEBUG_CHANNEL(PAL); + +#include "pal/corunix.inl" + +using namespace CorUnix; + +IPalObjectManager * CorUnix::g_pObjectManager; + +static +PAL_ERROR +CheckObjectTypeAndRights( + IPalObject *pobj, + CAllowedObjectTypes *paot + ); + +/*++ +Function: + CSharedMemoryObjectManager::Initialize + + Performs (possibly failing) startup tasks for the object manager + +Parameters: + None +--*/ + +PAL_ERROR +CSharedMemoryObjectManager::Initialize( + void + ) +{ + PAL_ERROR palError = NO_ERROR; + + ENTRY("CSharedMemoryObjectManager::Initialize (this=%p)\n", this); + + InitializeListHead(&m_leNamedObjects); + InitializeListHead(&m_leAnonymousObjects); + + InternalInitializeCriticalSection(&m_csListLock); + m_fListLockInitialized = TRUE; + + palError = m_HandleManager.Initialize(); + + LOGEXIT("CSharedMemoryObjectManager::Initialize returns %d", palError); + + return palError; +} + +/*++ +Function: + CSharedMemoryObjectManager::Shutdown + + Cleans up the object manager. This routine will call cleanup routines + for all objects referenced by this process. After this routine is called + no attempt should be made to access an IPalObject. + +Parameters: + pthr -- thread data for calling thread +--*/ + +PAL_ERROR +CSharedMemoryObjectManager::Shutdown( + CPalThread *pthr + ) +{ + PLIST_ENTRY ple; + CSharedMemoryObject *pshmobj; + + _ASSERTE(NULL != pthr); + + ENTRY("CSharedMemoryObjectManager::Shutdown (this=%p, pthr=%p)\n", + this, + pthr + ); + + InternalEnterCriticalSection(pthr, &m_csListLock); + SHMLock(); + + while (!IsListEmpty(&m_leAnonymousObjects)) + { + ple = RemoveTailList(&m_leAnonymousObjects); + pshmobj = CSharedMemoryObject::GetObjectFromListLink(ple); + pshmobj->CleanupForProcessShutdown(pthr); + } + + while (!IsListEmpty(&m_leNamedObjects)) + { + ple = RemoveTailList(&m_leNamedObjects); + pshmobj = CSharedMemoryObject::GetObjectFromListLink(ple); + pshmobj->CleanupForProcessShutdown(pthr); + } + + SHMRelease(); + InternalLeaveCriticalSection(pthr, &m_csListLock); + + LOGEXIT("CSharedMemoryObjectManager::Shutdown returns %d\n", NO_ERROR); + + return NO_ERROR; +} + +/*++ +Function: + CSharedMemoryObjectManager::AllocateObject + + Allocates a new object instance of the specified type. + +Parameters: + pthr -- thread data for calling thread + pot -- type of object to allocate + poa -- attributes (name and SD) of object to allocate + ppobjNew -- on success, receives a reference to the new object +--*/ + +PAL_ERROR +CSharedMemoryObjectManager::AllocateObject( + CPalThread *pthr, + CObjectType *pot, + CObjectAttributes *poa, + IPalObject **ppobjNew // OUT + ) +{ + PAL_ERROR palError = NO_ERROR; + CSharedMemoryObject *pshmobj = NULL; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != pot); + _ASSERTE(NULL != poa); + _ASSERTE(NULL != ppobjNew); + + ENTRY("CSharedMemoryObjectManager::AllocateObject " + "(this=%p, pthr=%p, pot=%p, poa=%p, ppobjNew=%p)\n", + this, + pthr, + pot, + poa, + ppobjNew + ); + + if (CObjectType::WaitableObject == pot->GetSynchronizationSupport()) + { + pshmobj = InternalNew(pot, &m_csListLock); + } + else + { + pshmobj = InternalNew(pot, &m_csListLock); + } + + if (NULL != pshmobj) + { + palError = pshmobj->Initialize(pthr, poa); + if (NO_ERROR == palError) + { + *ppobjNew = static_cast(pshmobj); + } + } + else + { + ERROR("Unable to allocate pshmobj\n"); + palError = ERROR_OUTOFMEMORY; + } + + LOGEXIT("CSharedMemoryObjectManager::AllocateObject returns %d\n", palError); + return palError; +} + +/*++ +Function: + CSharedMemoryObjectManager::RegisterObject + + Registers a newly-allocated object instance. If the object to be registered + has a name, and a previously registered object has the same name the new + object will not be registered. + +Distinguished return values: + ERROR_ALREADY_EXISTS -- an object of a compatible type was already registered + with the specified name + ERROR_INVALID_HANDLE -- an object of an incompatible type was already + registered with the specified name + +Parameters: + pthr -- thread data for calling thread + pobjToRegister -- the object instance to register. This routine will always + call ReleaseReference on this instance + paot -- object types that are compatible with the new object instance + pHandle -- on success, receives a handle to the registered object + ppobjRegistered -- on success, receives a reference to the registered object + instance. +--*/ + +PAL_ERROR +CSharedMemoryObjectManager::RegisterObject( + CPalThread *pthr, + IPalObject *pobjToRegister, + CAllowedObjectTypes *paot, + HANDLE *pHandle, // OUT + IPalObject **ppobjRegistered // OUT + ) +{ + PAL_ERROR palError = NO_ERROR; + CSharedMemoryObject *pshmobj = static_cast(pobjToRegister); + SHMObjData *psmodNew = NULL; + CObjectAttributes *poa; + CObjectType *potObj; + IPalObject *pobjExisting; + BOOL fShared = FALSE; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != pobjToRegister); + _ASSERTE(NULL != paot); + _ASSERTE(NULL != pHandle); + _ASSERTE(NULL != ppobjRegistered); + + ENTRY("CSharedMemoryObjectManager::RegisterObject " + "(this=%p, pthr=%p, pobjToRegister=%p, paot=%p, " + "pHandle=%p, ppobjRegistered=%p)\n", + this, + pthr, + pobjToRegister, + paot, + pHandle, + ppobjRegistered + ); + + poa = pobjToRegister->GetObjectAttributes(); + _ASSERTE(NULL != poa); + + potObj = pobjToRegister->GetObjectType(); + fShared = (SharedObject == pshmobj->GetObjectDomain()); + + InternalEnterCriticalSection(pthr, &m_csListLock); + + if (fShared) + { + // + // We only need to acquire the shared memory lock if this + // object is actually shared. + // + + SHMLock(); + } + + if (0 != poa->sObjectName.GetStringLength()) + { + SHMPTR shmObjectListHead = NULL; + + // + // The object must be shared + // + + _ASSERTE(fShared); + + // + // Check if an object by this name alredy exists + // + + palError = LocateObject( + pthr, + &poa->sObjectName, + paot, + &pobjExisting + ); + + if (NO_ERROR == palError) + { + // + // Obtain a new handle to the existing object + // + + palError = ObtainHandleForObject( + pthr, + pobjExisting, + pHandle + ); + + if (NO_ERROR == palError) + { + // + // Transfer object reference to out param + // + + *ppobjRegistered = pobjExisting; + palError = ERROR_ALREADY_EXISTS; + } + else + { + pobjExisting->ReleaseReference(pthr); + } + + goto RegisterObjectExit; + } + else if (ERROR_INVALID_NAME != palError) + { + // + // Something different than an object not found error + // occurred. This is most likely due to a type conflict. + // + + goto RegisterObjectExit; + } + + // + // Insert the object on the named object lists + // + + InsertTailList(&m_leNamedObjects, pshmobj->GetObjectListLink()); + + psmodNew = SHMPTR_TO_TYPED_PTR(SHMObjData, pshmobj->GetShmObjData()); + if (NULL == psmodNew) + { + ASSERT("Failure to map shared object data\n"); + palError = ERROR_INTERNAL_ERROR; + goto RegisterObjectExit; + } + + shmObjectListHead = SHMGetInfo(SIID_NAMED_OBJECTS); + if (NULL != shmObjectListHead) + { + SHMObjData *psmodListHead; + + psmodListHead = SHMPTR_TO_TYPED_PTR(SHMObjData, shmObjectListHead); + if (NULL != psmodListHead) + { + psmodNew->shmNextObj = shmObjectListHead; + psmodListHead->shmPrevObj = pshmobj->GetShmObjData(); + } + else + { + ASSERT("Failure to map shared object data\n"); + palError = ERROR_INTERNAL_ERROR; + goto RegisterObjectExit; + } + } + + psmodNew->fAddedToList = TRUE; + + if (!SHMSetInfo(SIID_NAMED_OBJECTS, pshmobj->GetShmObjData())) + { + ASSERT("Failed to set shared named object list head\n"); + palError = ERROR_INTERNAL_ERROR; + goto RegisterObjectExit; + } + } + else + { + // + // Place the object on the anonymous object list + // + + InsertTailList(&m_leAnonymousObjects, pshmobj->GetObjectListLink()); + } + + // + // Hoist the object's immutable data (if any) into shared memory if + // the object is shared + // + + if (fShared && 0 != potObj->GetImmutableDataSize()) + { + VOID *pvImmutableData; + SHMObjData *psmod; + + palError = pobjToRegister->GetImmutableData(&pvImmutableData); + if (NO_ERROR != palError) + { + ASSERT("Failure to obtain object immutable data\n"); + goto RegisterObjectExit; + } + + psmod = SHMPTR_TO_TYPED_PTR(SHMObjData, pshmobj->GetShmObjData()); + if (NULL != psmod) + { + VOID *pvSharedImmutableData = + SHMPTR_TO_TYPED_PTR(VOID, psmod->shmObjImmutableData); + + if (NULL != pvSharedImmutableData) + { + CopyMemory( + pvSharedImmutableData, + pvImmutableData, + potObj->GetImmutableDataSize() + ); + + if (NULL != potObj->GetImmutableDataCopyRoutine()) + { + (*potObj->GetImmutableDataCopyRoutine())(pvImmutableData, pvSharedImmutableData); + } + + psmod->pCopyRoutine = potObj->GetImmutableDataCopyRoutine(); + psmod->pCleanupRoutine = potObj->GetImmutableDataCleanupRoutine(); + } + else + { + ASSERT("Failure to map psmod->shmObjImmutableData\n"); + palError = ERROR_INTERNAL_ERROR; + goto RegisterObjectExit; + } + } + else + { + ASSERT("Failure to map pshmobj->GetShmObjData()\n"); + palError = ERROR_INTERNAL_ERROR; + goto RegisterObjectExit; + } + } + + // + // Obtain a handle for the new object + // + + palError = ObtainHandleForObject( + pthr, + pobjToRegister, + pHandle + ); + + if (NO_ERROR == palError) + { + // + // Transfer pobjToRegister reference to out param + // + + *ppobjRegistered = pobjToRegister; + pobjToRegister = NULL; + } + +RegisterObjectExit: + + if (fShared) + { + SHMRelease(); + } + + InternalLeaveCriticalSection(pthr, &m_csListLock); + + if (NULL != pobjToRegister) + { + pobjToRegister->ReleaseReference(pthr); + } + + LOGEXIT("CSharedMemoryObjectManager::RegisterObject return %d\n", palError); + + return palError; +} + +/*++ +Function: + CSharedMemoryObjectManager::LocateObject + + Search for a previously registered object with a give name and type + +Distinguished return values: + ERROR_INVALID_NAME -- no object with the specified name was previously + registered + ERROR_INVALID_HANDLE -- an object with the specified name was previously + registered, but its type is not compatible + +Parameters: + pthr -- thread data for calling thread + psObjectToLocate -- the name of the object to locate + paot -- acceptable types for the object + ppobj -- on success, receives a reference to the object instance +--*/ + +PAL_ERROR +CSharedMemoryObjectManager::LocateObject( + CPalThread *pthr, + CPalString *psObjectToLocate, + CAllowedObjectTypes *paot, + IPalObject **ppobj // OUT + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pobjExisting = NULL; + SHMPTR shmSharedObjectData = NULL; + SHMPTR shmObjectListEntry = NULL; + SHMObjData *psmod = NULL; + LPWSTR pwsz = NULL; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != psObjectToLocate); + _ASSERTE(NULL != psObjectToLocate->GetString()); + _ASSERTE(PAL_wcslen(psObjectToLocate->GetString()) == psObjectToLocate->GetStringLength()); + _ASSERTE(NULL != ppobj); + + ENTRY("CSharedMemoryObjectManager::LocateObject " + "(this=%p, pthr=%p, psObjectToLocate=%p, paot=%p, " + "ppobj=%p)\n", + this, + pthr, + psObjectToLocate, + paot, + ppobj + ); + + TRACE("Searching for object name %S\n", psObjectToLocate->GetString()); + + InternalEnterCriticalSection(pthr, &m_csListLock); + + // + // Search the local named object list for this object + // + + for (PLIST_ENTRY ple = m_leNamedObjects.Flink; + ple != &m_leNamedObjects; + ple = ple->Flink) + { + CObjectAttributes *poa; + CSharedMemoryObject *pshmobj = + CSharedMemoryObject::GetObjectFromListLink(ple); + + poa = pshmobj->GetObjectAttributes(); + _ASSERTE(NULL != poa); + + if (poa->sObjectName.GetStringLength() != psObjectToLocate->GetStringLength()) + { + continue; + } + + if (0 != PAL_wcscmp(poa->sObjectName.GetString(), psObjectToLocate->GetString())) + { + continue; + } + + // + // This object has the name we're looking for + // + + pobjExisting = static_cast(pshmobj); + break; + } + + if (NULL != pobjExisting) + { + // + // Validate the located object's type + // + + if (paot->IsTypeAllowed( + pobjExisting->GetObjectType()->GetId() + )) + { + TRACE("Local object exists with compatible type\n"); + + // + // Add a reference to the found object + // + + pobjExisting->AddReference(); + *ppobj = pobjExisting; + } + else + { + TRACE("Local object exists w/ incompatible type\n"); + palError = ERROR_INVALID_HANDLE; + } + + goto LocateObjectExit; + } + + // + // Search the shared memory named object list for a matching object + // + + SHMLock(); + + shmObjectListEntry = SHMGetInfo(SIID_NAMED_OBJECTS); + while (NULL != shmObjectListEntry) + { + psmod = SHMPTR_TO_TYPED_PTR(SHMObjData, shmObjectListEntry); + if (NULL != psmod) + { + if (psmod->dwNameLength == psObjectToLocate->GetStringLength()) + { + pwsz = SHMPTR_TO_TYPED_PTR(WCHAR, psmod->shmObjName); + if (NULL != pwsz) + { + if (0 == PAL_wcscmp(pwsz, psObjectToLocate->GetString())) + { + // + // This is the object we were looking for. + // + + shmSharedObjectData = shmObjectListEntry; + break; + } + } + else + { + ASSERT("Unable to map psmod->shmObjName\n"); + break; + } + } + + shmObjectListEntry = psmod->shmNextObj; + } + else + { + ASSERT("Unable to map shmObjectListEntry\n"); + break; + } + } + + if (NULL != shmSharedObjectData) + { + CSharedMemoryObject *pshmobj = NULL; + CObjectAttributes oa(pwsz, NULL); + + // + // Check if the type is allowed + // + + if (!paot->IsTypeAllowed(psmod->eTypeId)) + { + TRACE("Remote object exists w/ incompatible type\n"); + palError = ERROR_INVALID_HANDLE; + goto LocateObjectExitSHMRelease; + } + + // + // Get the local instance of the CObjectType + // + + CObjectType *pot = CObjectType::GetObjectTypeById(psmod->eTypeId); + if (NULL == pot) + { + ASSERT("Invalid object type ID in shared memory info\n"); + goto LocateObjectExitSHMRelease; + } + + TRACE("Remote object exists compatible type -- importing\n"); + + // + // Create the local state for the shared object + // + + palError = ImportSharedObjectIntoProcess( + pthr, + pot, + &oa, + shmSharedObjectData, + psmod, + TRUE, + &pshmobj + ); + + if (NO_ERROR == palError) + { + *ppobj = static_cast(pshmobj); + } + else + { + ERROR("Failure initializing object from shared data\n"); + goto LocateObjectExitSHMRelease; + } + + } + else + { + // + // The object was not found + // + + palError = ERROR_INVALID_NAME; + } + +LocateObjectExitSHMRelease: + + SHMRelease(); + +LocateObjectExit: + + InternalLeaveCriticalSection(pthr, &m_csListLock); + + LOGEXIT("CSharedMemoryObjectManager::LocateObject returns %d\n", palError); + + return palError; +} + +/*++ +Function: + CSharedMemoryObjectManager::ObtainHandleForObject + + Allocated a new handle for an object + +Parameters: + pthr -- thread data for calling thread + pobj -- the object to allocate a handle for + pNewHandle -- on success, receives the newly allocated handle +--*/ + +PAL_ERROR +CSharedMemoryObjectManager::ObtainHandleForObject( + CPalThread *pthr, + IPalObject *pobj, + HANDLE *pNewHandle // OUT + ) +{ + PAL_ERROR palError = NO_ERROR; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != pobj); + _ASSERTE(NULL != pNewHandle); + + ENTRY("CSharedMemoryObjectManager::ObtainHandleForObject " + "(this=%p, pthr=%p, pobj=%p, " + "pNewHandle=%p)\n", + this, + pthr, + pobj, + pNewHandle + ); + + palError = m_HandleManager.AllocateHandle( + pthr, + pobj, + pNewHandle + ); + + LOGEXIT("CSharedMemoryObjectManager::ObtainHandleForObject return %d\n", palError); + + return palError; +} + +/*++ +Function: + CSharedMemoryObjectManager::RevokeHandle + + Removes a handle from the process's handle table, which in turn releases + the handle's reference on the object instance it refers to + +Parameters: + pthr -- thread data for calling thread + hHandleToRevoke -- the handle to revoke +--*/ + +PAL_ERROR +CSharedMemoryObjectManager::RevokeHandle( + CPalThread *pthr, + HANDLE hHandleToRevoke + ) +{ + PAL_ERROR palError = NO_ERROR; + + _ASSERTE(NULL != pthr); + + ENTRY("CSharedMemoryObjectManager::RevokeHandle " + "(this=%p, pthr=%p, hHandleToRevoke=%p)\n", + this, + pthr, + hHandleToRevoke + ); + + palError = m_HandleManager.FreeHandle(pthr, hHandleToRevoke); + + LOGEXIT("CSharedMemoryObjectManager::RevokeHandle returns %d\n", palError); + + return palError; +} + +/*++ +Function: + CSharedMemoryObjectManager::ReferenceObjectByHandle + + Returns a referenced object instance that a handle refers to + +Parameters: + pthr -- thread data for calling thread + hHandleToReference -- the handle to reference + paot -- acceptable types for the underlying object + granted; currently ignored + ppobj -- on success, receives a reference to the object instance +--*/ + +PAL_ERROR +CSharedMemoryObjectManager::ReferenceObjectByHandle( + CPalThread *pthr, + HANDLE hHandleToReference, + CAllowedObjectTypes *paot, + IPalObject **ppobj // OUT + ) +{ + PAL_ERROR palError; + IPalObject *pobj; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != paot); + _ASSERTE(NULL != ppobj); + + ENTRY("CSharedMemoryObjectManager::ReferenceObjectByHandle " + "(this=%p, pthr=%p, hHandleToReference=%p, paot=%p, ppobj=%p)\n", + this, + pthr, + hHandleToReference, + paot, + ppobj + ); + + palError = m_HandleManager.GetObjectFromHandle( + pthr, + hHandleToReference, + &pobj + ); + + if (NO_ERROR == palError) + { + palError = CheckObjectTypeAndRights( + pobj, + paot + ); + + if (NO_ERROR == palError) + { + // + // Transfer object reference to out parameter + // + + *ppobj = pobj; + } + else + { + pobj->ReleaseReference(pthr); + } + } + + LOGEXIT("CSharedMemoryObjectManager::ReferenceObjectByHandle returns %d\n", + palError + ); + + return palError; +} + +/*++ +Function: + CSharedMemoryObjectManager::ReferenceObjectByHandleArray + + Returns the referenced object instances that an array of handles + refer to. + +Parameters: + pthr -- thread data for calling thread + rgHandlesToReference -- the array of handles to reference + dwHandleCount -- the number of handles in the arrayu + paot -- acceptable types for the underlying objects + rgpobjs -- on success, receives references to the object instances; will + be empty on failures +--*/ + +PAL_ERROR +CSharedMemoryObjectManager::ReferenceMultipleObjectsByHandleArray( + CPalThread *pthr, + HANDLE rghHandlesToReference[], + DWORD dwHandleCount, + CAllowedObjectTypes *paot, + IPalObject *rgpobjs[] // OUT (caller allocated) + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pobj = NULL; + DWORD dw; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != rghHandlesToReference); + _ASSERTE(0 < dwHandleCount); + _ASSERTE(NULL != paot); + _ASSERTE(NULL != rgpobjs); + + ENTRY("CSharedMemoryObjectManager::ReferenceMultipleObjectsByHandleArray " + "(this=%p, pthr=%p, rghHandlesToReference=%p, dwHandleCount=%d, " + "pAllowedTyped=%d, rgpobjs=%p)\n", + this, + pthr, + rghHandlesToReference, + dwHandleCount, + paot, + rgpobjs + ); + + m_HandleManager.Lock(pthr); + + for (dw = 0; dw < dwHandleCount; dw += 1) + { + palError = m_HandleManager.GetObjectFromHandle( + pthr, + rghHandlesToReference[dw], + &pobj + ); + + if (NO_ERROR == palError) + { + palError = CheckObjectTypeAndRights( + pobj, + paot + ); + + if (NO_ERROR == palError) + { + // + // Transfer reference to out array + // + + rgpobjs[dw] = pobj; + pobj = NULL; + } + } + + if (NO_ERROR != palError) + { + break; + } + } + + // + // The handle manager lock must be released before releasing + // any object references, as ReleaseReference will acquire + // the object manager list lock (which needs to be acquired before + // the handle manager lock) + // + + m_HandleManager.Unlock(pthr); + + if (NO_ERROR != palError) + { + // + // dw's current value is the failing index, so we want + // to free from dw - 1. + // + + while (dw > 0) + { + rgpobjs[--dw]->ReleaseReference(pthr); + } + + if (NULL != pobj) + { + pobj->ReleaseReference(pthr); + } + } + + LOGEXIT("CSharedMemoryObjectManager::ReferenceMultipleObjectsByHandleArray" + " returns %d\n", + palError + ); + + return palError; +} + +/*++ +Function: + CSharedMemoryObjectManager::ImportSharedObjectIntoProcess + + Takes an object's shared memory data and from it creates the + necessary in-process structures for the object + +Parameters: + pthr -- thread data for calling thread + pot -- the object's type + poa -- attributes for the object + shmSharedObjectData -- the shared memory pointer for the object's shared + data + psmod -- the shared memory data for the object, mapped into this process's + address space + fAddRefSharedData -- if TRUE, we need to add to the shared data reference + count + ppshmobj -- on success, receives a pointer to the newly created local + object instance +--*/ + +PAL_ERROR +CSharedMemoryObjectManager::ImportSharedObjectIntoProcess( + CPalThread *pthr, + CObjectType *pot, + CObjectAttributes *poa, + SHMPTR shmSharedObjectData, + SHMObjData *psmod, + bool fAddRefSharedData, + CSharedMemoryObject **ppshmobj + ) +{ + PAL_ERROR palError = NO_ERROR; + CSharedMemoryObject *pshmobj; + PLIST_ENTRY pleObjectList; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != pot); + _ASSERTE(NULL != poa); + _ASSERTE(NULL != shmSharedObjectData); + _ASSERTE(NULL != psmod); + _ASSERTE(NULL != ppshmobj); + + ENTRY("CSharedMemoryObjectManager::ImportSharedObjectIntoProcess(pthr=%p, " + "pot=%p, poa=%p, shmSharedObjectData=%p, psmod=%p, fAddRefSharedData=%d, " + "ppshmobj=%p)\n", + pthr, + pot, + poa, + shmSharedObjectData, + psmod, + fAddRefSharedData, + ppshmobj + ); + + if (CObjectType::WaitableObject == pot->GetSynchronizationSupport()) + { + pshmobj = InternalNew(pot, + &m_csListLock, + shmSharedObjectData, + psmod, + fAddRefSharedData); + } + else + { + pshmobj = InternalNew(pot, + &m_csListLock, + shmSharedObjectData, + psmod, + fAddRefSharedData); + } + + if (NULL != pshmobj) + { + palError = pshmobj->InitializeFromExistingSharedData(pthr, poa); + if (NO_ERROR == palError) + { + if (0 != psmod->dwNameLength) + { + pleObjectList = &m_leNamedObjects; + } + else + { + pleObjectList = &m_leAnonymousObjects; + } + + InsertTailList(pleObjectList, pshmobj->GetObjectListLink()); + } + else + { + goto ImportSharedObjectIntoProcessExit; + } + } + else + { + ERROR("Unable to allocate new object\n"); + palError = ERROR_OUTOFMEMORY; + goto ImportSharedObjectIntoProcessExit; + } + + *ppshmobj = pshmobj; + +ImportSharedObjectIntoProcessExit: + + LOGEXIT("CSharedMemoryObjectManager::ImportSharedObjectIntoProcess returns %d\n", palError); + + return palError; +} + +static PalObjectTypeId RemotableObjectTypes[] = + {otiManualResetEvent, otiAutoResetEvent, otiMutex, otiProcess}; + +static CAllowedObjectTypes aotRemotable( + RemotableObjectTypes, + sizeof(RemotableObjectTypes) / sizeof(RemotableObjectTypes[0]) + ); + +/*++ +Function: + CheckObjectTypeAndRights + + Helper routine that determines if: + 1) An object instance is of a specified type + 2) A set of granted access rights satisfies the required access rights + (currently ignored) + +Parameters: + pobj -- the object instance whose type is to be checked + paot -- the acceptable type for the object instance +--*/ + +static +PAL_ERROR +CheckObjectTypeAndRights( + IPalObject *pobj, + CAllowedObjectTypes *paot + ) +{ + PAL_ERROR palError = NO_ERROR; + + _ASSERTE(NULL != pobj); + _ASSERTE(NULL != paot); + + ENTRY("CheckObjectTypeAndRights (pobj=%p, paot=%p)\n", + pobj, + paot + ); + + if (!paot->IsTypeAllowed(pobj->GetObjectType()->GetId())) + { + palError = ERROR_INVALID_HANDLE; + } + + LOGEXIT("CheckObjectTypeAndRights returns %d\n", palError); + + return palError; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobjectmanager.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobjectmanager.hpp new file mode 100644 index 0000000..f10f988 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/objmgr/shmobjectmanager.hpp @@ -0,0 +1,143 @@ +// 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: + + shmobjectmanager.hpp + +Abstract: + Shared memory based object manager + + + +--*/ + +#ifndef _PAL_SHMOBJECTMANAGER_HPP_ +#define _PAL_SHMOBJECTMANAGER_HPP_ + +#include "pal/corunix.hpp" +#include "pal/handlemgr.hpp" +#include "pal/list.h" +#include "shmobject.hpp" + +namespace CorUnix +{ + class CSharedMemoryObjectManager : public IPalObjectManager + { + protected: + + CRITICAL_SECTION m_csListLock; + bool m_fListLockInitialized; + LIST_ENTRY m_leNamedObjects; + LIST_ENTRY m_leAnonymousObjects; + + CSimpleHandleManager m_HandleManager; + + PAL_ERROR + ImportSharedObjectIntoProcess( + CPalThread *pthr, + CObjectType *pot, + CObjectAttributes *poa, + SHMPTR shmSharedObjectData, + SHMObjData *psmod, + bool fAddRefSharedData, + CSharedMemoryObject **ppshmobj + ); + + public: + + CSharedMemoryObjectManager() + : + m_fListLockInitialized(FALSE) + { + }; + + virtual ~CSharedMemoryObjectManager() + { + }; + + PAL_ERROR + Initialize( + void + ); + + PAL_ERROR + Shutdown( + CPalThread *pthr + ); + + // + // IPalObjectManager routines + // + + virtual + PAL_ERROR + AllocateObject( + CPalThread *pthr, + CObjectType *pot, + CObjectAttributes *poa, + IPalObject **ppobjNew + ); + + virtual + PAL_ERROR + RegisterObject( + CPalThread *pthr, + IPalObject *pobjToRegister, + CAllowedObjectTypes *paot, + HANDLE *pHandle, + IPalObject **ppobjRegistered + ); + + virtual + PAL_ERROR + LocateObject( + CPalThread *pthr, + CPalString *psObjectToLocate, + CAllowedObjectTypes *paot, + IPalObject **ppobj + ); + + virtual + PAL_ERROR + ObtainHandleForObject( + CPalThread *pthr, + IPalObject *pobj, + HANDLE *pNewHandle + ); + + virtual + PAL_ERROR + RevokeHandle( + CPalThread *pthr, + HANDLE hHandleToRevoke + ); + + virtual + PAL_ERROR + ReferenceObjectByHandle( + CPalThread *pthr, + HANDLE hHandleToReference, + CAllowedObjectTypes *paot, + IPalObject **ppobj + ); + + virtual + PAL_ERROR + ReferenceMultipleObjectsByHandleArray( + CPalThread *pthr, + HANDLE rghHandlesToReference[], + DWORD dwHandleCount, + CAllowedObjectTypes *paot, + IPalObject *rgpobjs[] + ); + }; +} + +#endif // _PAL_SHMOBJECTMANAGER_HPP_ + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/poll/fakepoll.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/poll/fakepoll.cpp new file mode 100644 index 0000000..489175c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/poll/fakepoll.cpp @@ -0,0 +1,133 @@ +// 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. + +// fakepoll.h +// poll using select +// Warning: a call to this poll() takes about 4K of stack space. + +// Greg Parker gparker@cs.stanford.edu December 2000 +// This code is in the public domain and may be copied or modified without +// permission. + +// Located at . + + + +#include "pal/palinternal.h" +#include "pal/fakepoll.h" +#include "pal/dbgmsg.h" +#include +#include +#include +#include +#include +#include + +SET_DEFAULT_DEBUG_CHANNEL(POLL); + +int poll(struct pollfd *pollSet, int pollCount, int pollTimeout) +{ + struct timeval tv; + struct timeval *tvp; + fd_set readFDs, writeFDs, exceptFDs; + fd_set *readp, *writep, *exceptp; + struct pollfd *pollEnd, *p; + int selected; + int result; + int maxFD; + + if (!pollSet) { + pollEnd = NULL; + readp = NULL; + writep = NULL; + exceptp = NULL; + maxFD = 0; + } + else { + pollEnd = pollSet + pollCount; + readp = &readFDs; + writep = &writeFDs; + exceptp = &exceptFDs; + + FD_ZERO(readp); + FD_ZERO(writep); + FD_ZERO(exceptp); + + // Find the biggest fd in the poll set + maxFD = 0; + for (p = pollSet; p < pollEnd; p++) { + if (p->fd > maxFD) maxFD = p->fd; + } + + if (maxFD >= FD_SETSIZE) { + // At least one fd is too big + errno = EINVAL; + return -1; + } + + // Transcribe flags from the poll set to the fd sets + for (p = pollSet; p < pollEnd; p++) { + if (p->fd < 0) { + // Negative fd checks nothing and always reports zero + } else { + if (p->events & POLLIN) FD_SET(p->fd, readp); + if (p->events & POLLOUT) FD_SET(p->fd, writep); + if (p->events != 0) FD_SET(p->fd, exceptp); + // POLLERR is never set coming in; poll() always reports errors. + // But don't report if we're not listening to anything at all. + } + } + } + + // poll timeout is in milliseconds. Convert to struct timeval. + // poll timeout == -1 : wait forever : select timeout of NULL + // poll timeout == 0 : return immediately : select timeout of zero + if (pollTimeout >= 0) { + tv.tv_sec = pollTimeout / 1000; + tv.tv_usec = (pollTimeout % 1000) * 1000; + tvp = &tv; + } else { + tvp = NULL; + } + + selected = select(maxFD+1, readp, writep, exceptp, tvp); + + if (selected < 0) { + // Error during select + result = -1; + } + else if (selected > 0) { + // Select found something + // Transcribe result from fd sets to poll set. + // Also count the number of selected fds. poll returns the + // number of ready fds; select returns the number of bits set. + int polled = 0; + for (p = pollSet; p < pollEnd; p++) { + p->revents = 0; + if (p->fd > -1) { + // Check p->events before setting p->revents. If we + // have multiple pollfds with the same fd, we want to + // set the appropriate revents value for each pollfd. + if (FD_ISSET(p->fd, readp) && (p->events & POLLIN)) + p->revents |= POLLIN; + if (FD_ISSET(p->fd, writep) && (p->events & POLLOUT)) + p->revents |= POLLOUT; + if (FD_ISSET(p->fd, exceptp) && (p->events != 0)) + p->revents |= POLLERR; + if (p->revents) polled++; + } + } + result = polled; + } + else { + // selected == 0, select timed out before anything happened + // Clear all result bits and return zero. + for (p = pollSet; p < pollEnd; p++) { + p->revents = 0; + } + result = 0; + } + + return result; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/cruntime.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/cruntime.h new file mode 100644 index 0000000..9508e8f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/cruntime.h @@ -0,0 +1,98 @@ +// 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. + +/*** +*cruntime.h - definitions specific to the target operating system and hardware +* + +* +*Purpose: +* This header file contains widely used definitions specific to the +* host operating system and hardware. It is included by every C source +* and most every other header file. +* +* [Internal] +* +****/ + +#if _MSC_VER > 1000 +#pragma once +#endif /* _MSC_VER > 1000 */ + +#ifndef _INC_CRUNTIME +#define _INC_CRUNTIME + +#ifndef _CRTBLD +/* + * This is an internal C runtime header file. It is used when building + * the C runtimes only. It is not to be used as a public header file. + */ +#error ERROR: Use of C runtime library internal header file. +#endif /* _CRTBLD */ + +#if defined (_SYSCRT) && defined (HOST_64BIT) +#define _USE_OLD_STDCPP 1 +#endif /* defined (_SYSCRT) && defined (HOST_64BIT) */ + +#if !defined (UNALIGNED) +#if defined (_M_AMD64) +#define UNALIGNED __unaligned +#else /* defined (_M_AMD64) */ +#define UNALIGNED +#endif /* defined (_M_AMD64) */ +#endif /* !defined (UNALIGNED) */ + +#ifdef _M_IX86 +/* + * 386/486 + */ +#define REG1 register +#define REG2 register +#define REG3 register +#define REG4 +#define REG5 +#define REG6 +#define REG7 +#define REG8 +#define REG9 + +#elif defined (_M_AMD64) +/* + * AMD64 + */ +#define REG1 register +#define REG2 register +#define REG3 register +#define REG4 register +#define REG5 register +#define REG6 register +#define REG7 register +#define REG8 register +#define REG9 register + +#else /* defined (_M_AMD64) */ + +#pragma message ("Machine register set not defined") + +/* + * Unknown machine + */ + +#define REG1 +#define REG2 +#define REG3 +#define REG4 +#define REG5 +#define REG6 +#define REG7 +#define REG8 +#define REG9 + +#endif /* defined (_M_AMD64) */ + +/* + * Are the macro definitions below still needed in this file? + */ + +#endif /* _INC_CRUNTIME */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/input.inl b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/input.inl new file mode 100644 index 0000000..0f578e0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/input.inl @@ -0,0 +1,1317 @@ +// 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. + +/*** +*input.c - C formatted input, used by scanf, etc. +* + +* +*Purpose: +* defines _input() to do formatted input; called from scanf(), +* etc. functions. This module defines _cscanf() instead when +* CPRFLAG is defined. The file cscanf.c defines that symbol +* and then includes this file in order to implement _cscanf(). +* +*Note: +* this file is included in safecrt.lib build directly, plese refer +* to safecrt_[w]input_s.c +* +*******************************************************************************/ + + +#define ALLOW_RANGE /* enable "%[a-z]"-style scansets */ + + +/* temporary work-around for compiler without 64-bit support */ + +#ifndef _INTEGRAL_MAX_BITS +#define _INTEGRAL_MAX_BITS 64 +#endif /* _INTEGRAL_MAX_BITS */ + +// typedef __int64_t __int64; + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#define UNALIGNED + +#define _BEGIN_SECURE_CRT_DEPRECATION_DISABLE +#define _END_SECURE_CRT_DEPRECATION_DISABLE + +#define _CVTBUFSIZE (309+40) /* # of digits in max. dp value + slop */ + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +//#ifndef _INC_INTERNAL_SAFECRT +//#include +//#endif /* _INC_INTERNAL_SAFECRT */ + +//#ifdef _MBCS +//#undef _MBCS +//#endif /* _MBCS */ +//#include + +#define _MBTOWC(x,y,z) _minimal_chartowchar( x, y ) + +#define _istspace(x) isspace((unsigned char)x) + +#define _malloc_crt PAL_malloc +#define _realloc_crt PAL_realloc +#define _free_crt PAL_free + +#define _FASSIGN(flag, argument, number, dec_point, locale) _safecrt_fassign((flag), (argument), (number)) +#define _WFASSIGN(flag, argument, number, dec_point, locale) _safecrt_wfassign((flag), (argument), (number)) + +#if defined (UNICODE) +#define ALLOC_TABLE 1 +#else /* defined (UNICODE) */ +#define ALLOC_TABLE 0 +#endif /* defined (UNICODE) */ + +#define HEXTODEC(chr) _hextodec(chr) + +#define LEFT_BRACKET ('[' | ('a' - 'A')) /* 'lowercase' version */ + +static int __cdecl _hextodec(_TCHAR); +#ifdef CPRFLAG + +#define INC() (++charcount, _inc()) +#define UN_INC(chr) (--charcount, _un_inc(chr)) +#define EAT_WHITE() _whiteout(&charcount) + +static int __cdecl _inc(void); +static void __cdecl _un_inc(int); +static int __cdecl _whiteout(int *); + +#else /* CPRFLAG */ + +#define INC() (++charcount, _inc(stream)) +#define UN_INC(chr) (--charcount, _un_inc(chr, stream)) +#define EAT_WHITE() _whiteout(&charcount, stream) + +static int __cdecl _inc(miniFILE *); +static void __cdecl _un_inc(int, miniFILE *); +static int __cdecl _whiteout(int *, miniFILE *); + +#endif /* CPRFLAG */ + +#undef _ISDIGIT +#undef _ISXDIGIT + +#ifndef _UNICODE +#define _ISDIGIT(chr) isdigit((unsigned char)chr) +#define _ISXDIGIT(chr) isxdigit((unsigned char)chr) +#else /* _UNICODE */ +#define _ISDIGIT(chr) ( !(chr & 0xff00) && isdigit( ((chr) & 0x00ff) ) ) +#define _ISXDIGIT(chr) ( !(chr & 0xff00) && isxdigit( ((chr) & 0x00ff) ) ) +#endif /* _UNICODE */ + +#define MUL10(x) ( (((x)<<2) + (x))<<1 ) + + +#define LONGLONG_IS_INT64 1 /* 1 means long long is same as int64 + 0 means long long is same as long */ + +/*** +* int __check_float_string(size_t,size_t *, _TCHAR**, _TCHAR*, int*) +* +* Purpose: +* Check if there is enough space insert onemore character in the given +* block, if not then allocate more memory. +* +* Return: +* FALSE if more memory needed and the reallocation failed. +* +*******************************************************************************/ + +static int __check_float_string(size_t nFloatStrUsed, + size_t *pnFloatStrSz, + _TCHAR **pFloatStr, + _TCHAR *floatstring, + int *pmalloc_FloatStrFlag) +{ + void *tmpPointer; + _ASSERTE(nFloatStrUsed<=(*pnFloatStrSz)); + if (nFloatStrUsed==(*pnFloatStrSz)) + { + size_t newSize; + + // Will (*pnFloatStrSz) * 2 * sizeof(_TCHAR) overflow? + if ( *pnFloatStrSz > (SIZE_T_MAX / 2 / sizeof(_TCHAR))) + { + return FALSE; + } + + newSize = *pnFloatStrSz * 2 * sizeof(_TCHAR); + + if ((*pFloatStr)==floatstring) + { + if (((*pFloatStr)=(_TCHAR *)_malloc_crt(newSize))==NULL) + { + return FALSE; + } + + (*pmalloc_FloatStrFlag)=1; + + memcpy((*pFloatStr),floatstring,(*pnFloatStrSz)*sizeof(_TCHAR)); + (*pnFloatStrSz)*=2; + } + else + { + if ((tmpPointer=(_TCHAR *)_realloc_crt((*pFloatStr), newSize))==NULL) + { + return FALSE; + } + (*pFloatStr)=(_TCHAR *)(tmpPointer); + (*pnFloatStrSz)*=2; + } + } + return TRUE; +} + + +#define ASCII 32 /* # of bytes needed to hold 256 bits */ + +#define SCAN_SHORT 0 /* also for FLOAT */ +#define SCAN_LONG 1 /* also for DOUBLE */ +#define SCAN_L_DOUBLE 2 /* only for LONG DOUBLE */ + +#define SCAN_NEAR 0 +#define SCAN_FAR 1 + +#ifndef _UNICODE +#define TABLESIZE ASCII +#else /* _UNICODE */ +#define TABLESIZE (ASCII * 256) +#endif /* _UNICODE */ + + +/*** +*int _input(stream, format, arglist), static int input(format, arglist) +* +*Purpose: +* get input items (data items or literal matches) from the input stream +* and assign them if appropriate to the items thru the arglist. this +* function is intended for internal library use only, not for the user +* +* The _input entry point is for the normal scanf() functions +* The input entry point is used when compiling for _cscanf() [CPRFLAF +* defined] and is a static function called only by _cscanf() -- reads from +* console. +* +* This code also defines _input_s, which works differently for %c, %s & %[. +* For these, _input_s first picks up the next argument from the variable +* argument list & uses it as the maximum size of the character array pointed +* to by the next argument in the list. +* +*Entry: +* FILE *stream - file to read from +* char *format - format string to determine the data to read +* arglist - list of pointer to data items +* +*Exit: +* returns number of items assigned and fills in data items +* returns EOF if error or EOF found on stream before 1st data item matched +* +*Exceptions: +* +*******************************************************************************/ + + #define _INTRN_LOCALE_CONV( x ) localeconv() + +#ifndef _UNICODE + int __cdecl __tinput_s (miniFILE* stream, const _TUCHAR* format, va_list arglist) +#else + int __cdecl __twinput_s (miniFILE* stream, const _TUCHAR* format, va_list arglist) +#endif /* _UNICODE */ +{ + _TCHAR floatstring[_CVTBUFSIZE + 1]; + _TCHAR *pFloatStr=floatstring; + size_t nFloatStrUsed=0; + size_t nFloatStrSz=sizeof(floatstring)/sizeof(floatstring[0]); + int malloc_FloatStrFlag=0; + + unsigned long number; /* temp hold-value */ +#if ALLOC_TABLE + char *table = NULL; /* which chars allowed for %[] */ + int malloc_flag = 0; /* is "table" allocated on the heap? */ +#else /* ALLOC_TABLE */ + char AsciiTable[TABLESIZE]; + char *table = AsciiTable; +#endif /* ALLOC_TABLE */ + +#if _INTEGRAL_MAX_BITS >= 64 + uint64_t num64 = 0LL; /* temp for 64-bit integers */ +#endif /* _INTEGRAL_MAX_BITS >= 64 */ + void *pointer=NULL; /* points to user data receptacle */ + void *start; /* indicate non-empty string */ + + +#ifndef _UNICODE + char16_t wctemp=L'\0'; +#endif /* _UNICODE */ + _TUCHAR *scanptr; /* for building "table" data */ + int ch = 0; + int charcount; /* total number of chars read */ + int comchr; /* holds designator type */ + int count; /* return value. # of assignments */ + + int started; /* indicate good number */ + int width; /* width of field */ + int widthset; /* user has specified width */ +#ifdef _SECURE_SCANF + size_t array_width = 0; + size_t original_array_width = 0; + int enomem = 0; + int format_error = FALSE; +#endif /* _SECURE_SCANF */ + +/* Neither coerceshort nor farone are need for the 386 */ + + + char done_flag; /* general purpose loop monitor */ + char longone; /* 0 = SHORT, 1 = LONG, 2 = L_DOUBLE */ +#if _INTEGRAL_MAX_BITS >= 64 + int integer64; /* 1 for 64-bit integer, 0 otherwise */ +#endif /* _INTEGRAL_MAX_BITS >= 64 */ + signed char widechar; /* -1 = char, 0 = ????, 1 = char16_t */ + char reject; /* %[^ABC] instead of %[ABC] */ + char negative; /* flag for '-' detected */ + char suppress; /* don't assign anything */ + char match; /* flag: !0 if any fields matched */ + va_list arglistsave; /* save arglist value */ + + char fl_wchar_arg; /* flags wide char/string argument */ + + _TCHAR decimal; + + + _TUCHAR rngch; + _TUCHAR last; + _TUCHAR prevchar; + _TCHAR tch; + + _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); + +#ifndef CPRFLAG + _VALIDATE_RETURN( (stream != NULL), EINVAL, EOF); +#endif /* CPRFLAG */ + + /* + count = # fields assigned + charcount = # chars read + match = flag indicating if any fields were matched + + [Note that we need both count and match. For example, a field + may match a format but have assignments suppressed. In this case, + match will get set, but 'count' will still equal 0. We need to + distinguish 'match vs no-match' when terminating due to EOF.] + */ + + count = charcount = match = 0; + + while (*format) { + + if (_istspace((_TUCHAR)*format)) { + + UN_INC(EAT_WHITE()); /* put first non-space char back */ + + do { + tch = *++format; + } while (_istspace((_TUCHAR)tch)); + + continue; + + } + + if (_T('%') == *format) { + + number = 0; + prevchar = 0; + width = widthset = started = 0; +#ifdef _SECURE_SCANF + original_array_width = array_width = 0; + enomem = 0; +#endif /* _SECURE_SCANF */ + fl_wchar_arg = done_flag = suppress = negative = reject = 0; + widechar = 0; + + longone = 1; + +#if _INTEGRAL_MAX_BITS >= 64 + integer64 = 0; +#endif /* _INTEGRAL_MAX_BITS >= 64 */ + + while (!done_flag) { + + comchr = *++format; + if (_ISDIGIT((_TUCHAR)comchr)) { + ++widthset; + width = MUL10(width) + (comchr - _T('0')); + } else + switch (comchr) { + case _T('F') : + case _T('N') : /* no way to push NEAR in large model */ + break; /* NEAR is default in small model */ + case _T('h') : + /* set longone to 0 */ + --longone; + --widechar; /* set widechar = -1 */ + break; + +#if _INTEGRAL_MAX_BITS >= 64 + case _T('I'): + if ( (*(format + 1) == _T('6')) && + (*(format + 2) == _T('4')) ) + { + format += 2; + ++integer64; + num64 = 0; + break; + } + else if ( (*(format + 1) == _T('3')) && + (*(format + 2) == _T('2')) ) + { + format += 2; + break; + } + else if ( (*(format + 1) == _T('d')) || + (*(format + 1) == _T('i')) || + (*(format + 1) == _T('o')) || + (*(format + 1) == _T('x')) || + (*(format + 1) == _T('X')) ) + { + if (sizeof(void*) == sizeof(__int64)) + { + ++integer64; + num64 = 0; + } + break; + } + if (sizeof(void*) == sizeof(__int64)) + { + ++integer64; + num64 = 0; + } + goto DEFAULT_LABEL; +#endif /* _INTEGRAL_MAX_BITS >= 64 */ + + case _T('L') : + /* ++longone; */ + ++longone; + break; + + case _T('q'): + ++integer64; + num64 = 0; + break; + + case _T('l') : + if (*(format + 1) == _T('l')) + { + ++format; +#ifdef LONGLONG_IS_INT64 + ++integer64; + num64 = 0; + break; +#else /* LONGLONG_IS_INT64 */ + ++longone; + /* NOBREAK */ +#endif /* LONGLONG_IS_INT64 */ + } + else + { + ++longone; + /* NOBREAK */ + } + case _T('w') : + ++widechar; /* set widechar = 1 */ + break; + + case _T('*') : + ++suppress; + break; + + default: +DEFAULT_LABEL: + ++done_flag; + break; + } + } + + if (!suppress) { + va_copy(arglistsave, arglist); + pointer = va_arg(arglist,void *); + } else { + pointer = NULL; // doesn't matter what value we use here - we're only using it as a flag + } + + done_flag = 0; + + if (!widechar) { /* use case if not explicitly specified */ + if ((*format == _T('S')) || (*format == _T('C'))) +#ifdef _UNICODE + --widechar; + else + ++widechar; +#else /* _UNICODE */ + ++widechar; + else + --widechar; +#endif /* _UNICODE */ + } + + /* switch to lowercase to allow %E,%G, and to + keep the switch table small */ + + comchr = *format | (_T('a') - _T('A')); + + if (_T('n') != comchr) + { + if (_T('c') != comchr && LEFT_BRACKET != comchr) + ch = EAT_WHITE(); + else + ch = INC(); + } + + if (_T('n') != comchr) + { + if (_TEOF == ch) + goto error_return; + } + + if (!widthset || width) { + +#ifdef _SECURE_SCANF + if(!suppress && (comchr == _T('c') || comchr == _T('s') || comchr == LEFT_BRACKET)) { + + va_copy(arglist, arglistsave); + + /* Reinitialize pointer to point to the array to which we write the input */ + pointer = va_arg(arglist, void*); + + va_copy(arglistsave, arglist); + + /* Get the next argument - size of the array in characters */ +#ifdef HOST_64BIT + original_array_width = array_width = (size_t)(va_arg(arglist, unsigned int)); +#else /* HOST_64BIT */ + original_array_width = array_width = va_arg(arglist, size_t); +#endif /* HOST_64BIT */ + + if(array_width < 1) { + if (widechar > 0) + *(char16_t UNALIGNED *)pointer = L'\0'; + else + *(char *)pointer = '\0'; + + errno = ENOMEM; + + goto error_return; + } + } +#endif /* _SECURE_SCANF */ + switch(comchr) { + + case _T('c'): + /* case _T('C'): */ + if (!widthset) { + ++widthset; + ++width; + } + if (widechar > 0) + fl_wchar_arg++; + goto scanit; + + + case _T('s'): + /* case _T('S'): */ + if(widechar > 0) + fl_wchar_arg++; + goto scanit; + + + case LEFT_BRACKET : /* scanset */ + if (widechar>0) + fl_wchar_arg++; + scanptr = (_TUCHAR *)(++format); + + if (_T('^') == *scanptr) { + ++scanptr; + --reject; /* set reject to 255 */ + } + + /* Allocate "table" on first %[] spec */ +#if ALLOC_TABLE + if (table == NULL) { + table = (char*)_malloc_crt(TABLESIZE); + if ( table == NULL) + goto error_return; + malloc_flag = 1; + } +#endif /* ALLOC_TABLE */ + memset(table, 0, TABLESIZE); + + + if (LEFT_BRACKET == comchr) + if (_T(']') == *scanptr) { + prevchar = _T(']'); + ++scanptr; + + table[ _T(']') >> 3] = 1 << (_T(']') & 7); + + } + + while (_T(']') != *scanptr) { + + rngch = *scanptr++; + + if (_T('-') != rngch || + !prevchar || /* first char */ + _T(']') == *scanptr) /* last char */ + + table[(prevchar = rngch) >> 3] |= 1 << (rngch & 7); + + else { /* handle a-z type set */ + + rngch = *scanptr++; /* get end of range */ + + if (prevchar < rngch) /* %[a-z] */ + last = rngch; + else { /* %[z-a] */ + last = prevchar; + prevchar = rngch; + } + for (rngch = prevchar; rngch <= last; ++rngch) + table[rngch >> 3] |= 1 << (rngch & 7); + + prevchar = 0; + + } + } + + + if (!*scanptr) + goto error_return; /* trunc'd format string */ + + /* scanset completed. Now read string */ + + if (LEFT_BRACKET == comchr) + format = scanptr; + +scanit: + start = pointer; + + /* + * execute the format directive. that is, scan input + * characters until the directive is fulfilled, eof + * is reached, or a non-matching character is + * encountered. + * + * it is important not to get the next character + * unless that character needs to be tested! other- + * wise, reads from line-buffered devices (e.g., + * scanf()) would require an extra, spurious, newline + * if the first newline completes the current format + * directive. + */ + UN_INC(ch); + +#ifdef _SECURE_SCANF + /* One element is needed for '\0' for %s & %[ */ + if(comchr != _T('c')) { + --array_width; + } +#endif /* _SECURE_SCANF */ + while ( !widthset || width-- ) { + + ch = INC(); + if ( +#ifndef CPRFLAG + (_TEOF != ch) && +#endif /* CPRFLAG */ + // char conditions + ( ( comchr == _T('c')) || + // string conditions !isspace() + ( ( comchr == _T('s') && + (!(ch >= _T('\t') && ch <= _T('\r')) && + ch != _T(' ')))) || + // BRACKET conditions + ( (comchr == LEFT_BRACKET) && + ((table[ch >> 3] ^ reject) & (1 << (ch & 7))) + ) + ) + ) + { + if (!suppress) { +#ifdef _SECURE_SCANF + if(!array_width) { + /* We have exhausted the user's buffer */ + + enomem = 1; + break; + } +#endif /* _SECURE_SCANF */ +#ifndef _UNICODE + if (fl_wchar_arg) { + wctemp = W('?'); + char temp[2]; + temp[0] = (char) ch; +#if 0 // we are not supporting multibyte input strings + if (isleadbyte((unsigned char)ch)) + { + temp[1] = (char) INC(); + } +#endif /* 0 */ + _MBTOWC(&wctemp, temp, MB_CUR_MAX); + *(char16_t UNALIGNED *)pointer = wctemp; + /* just copy W('?') if mbtowc fails, errno is set by mbtowc */ + pointer = (char16_t *)pointer + 1; +#ifdef _SECURE_SCANF + --array_width; +#endif /* _SECURE_SCANF */ + } else +#else /* _UNICODE */ + if (fl_wchar_arg) { + *(char16_t UNALIGNED *)pointer = ch; + pointer = (char16_t *)pointer + 1; +#ifdef _SECURE_SCANF + --array_width; +#endif /* _SECURE_SCANF */ + } else +#endif /* _UNICODE */ + { +#ifndef _UNICODE + *(char *)pointer = (char)ch; + pointer = (char *)pointer + 1; +#ifdef _SECURE_SCANF + --array_width; +#endif /* _SECURE_SCANF */ +#else /* _UNICODE */ + int temp = 0; +#ifndef _SECURE_SCANF + /* convert wide to multibyte */ + if (_ERRCHECK_EINVAL_ERANGE(wctomb_s(&temp, (char *)pointer, MB_LEN_MAX, ch)) == 0) + { + /* do nothing if wctomb fails, errno will be set to EILSEQ */ + pointer = (char *)pointer + temp; + } +#else /* _SECURE_SCANF */ + /* convert wide to multibyte */ + if (array_width >= ((size_t)MB_CUR_MAX)) + { +_BEGIN_SECURE_CRT_DEPRECATION_DISABLE + temp = wctomb((char *)pointer, ch); +_END_SECURE_CRT_DEPRECATION_DISABLE + } + else + { + char tmpbuf[MB_LEN_MAX]; +_BEGIN_SECURE_CRT_DEPRECATION_DISABLE + temp = wctomb(tmpbuf, ch); +_END_SECURE_CRT_DEPRECATION_DISABLE + if (temp > 0 && ((size_t)temp) > array_width) + { + /* We have exhausted the user's buffer */ + enomem = 1; + break; + } + memcpy(pointer, tmpbuf, temp); + } + if (temp > 0) + { + /* do nothing if wctomb fails, errno will be set to EILSEQ */ + pointer = (char *)pointer + temp; + array_width -= temp; + } +#endif /* _SECURE_SCANF */ +#endif /* _UNICODE */ + } + } /* suppress */ + else { + /* just indicate a match */ + start = (_TCHAR *)start + 1; + } + } + else { + UN_INC(ch); + break; + } + } + + /* make sure something has been matched and, if + assignment is not suppressed, null-terminate + output string if comchr != c */ + +#ifdef _SECURE_SCANF + if(enomem) { + errno = ENOMEM; + /* In case of error, blank out the input buffer */ + if (fl_wchar_arg) + { + _RESET_STRING(((char16_t UNALIGNED *)start), original_array_width); + } + else + { + _RESET_STRING(((char *)start), original_array_width); + } + + goto error_return; + } +#endif /* _SECURE_SCANF */ + + if (start != pointer) { + if (!suppress) { + ++count; + if ('c' != comchr) /* null-terminate strings */ + { + if (fl_wchar_arg) + { + *(char16_t UNALIGNED *)pointer = L'\0'; +#ifdef _SECURE_SCANF + _FILL_STRING(((char16_t UNALIGNED *)start), original_array_width, + ((char16_t UNALIGNED *)pointer - (char16_t UNALIGNED *)start + 1)) +#endif /* _SECURE_SCANF */ + } + else + { + *(char *)pointer = '\0'; +#ifdef _SECURE_SCANF + _FILL_STRING(((char *)start), original_array_width, + ((char *)pointer - (char *)start + 1)) +#endif /* _SECURE_SCANF */ + } + } + } + else + { + // supress set, do nothing + } + } + else + goto error_return; + + break; + + case _T('i') : /* could be d, o, or x */ + + comchr = _T('d'); /* use as default */ + + case _T('x'): + + if (_T('-') == ch) { + ++negative; + + goto x_incwidth; + + } else if (_T('+') == ch) { +x_incwidth: + if (!--width && widthset) + ++done_flag; + else + ch = INC(); + } + + if (_T('0') == ch) { + + if (_T('x') == (_TCHAR)(ch = INC()) || _T('X') == (_TCHAR)ch) { + ch = INC(); + if (widthset) { + width -= 2; + if (width < 1) + ++done_flag; + } + comchr = _T('x'); + } else { + ++started; + if (_T('x') != comchr) { + if (widthset && !--width) + ++done_flag; + comchr = _T('o'); + } + else { + /* scanning a hex number that starts */ + /* with a 0. push back the character */ + /* currently in ch and restore the 0 */ + UN_INC(ch); + ch = _T('0'); + } + } + } + goto getnum; + + /* NOTREACHED */ + + case _T('p') : + /* force %hp to be treated as %p */ + longone = 1; +#ifdef HOST_64BIT + /* force %p to be 64 bit in WIN64 */ + ++integer64; + num64 = 0; +#endif /* HOST_64BIT */ + case _T('o') : + case _T('u') : + case _T('d') : + + if (_T('-') == ch) { + ++negative; + + goto d_incwidth; + + } else if (_T('+') == ch) { +d_incwidth: + if (!--width && widthset) + ++done_flag; + else + ch = INC(); + } + +getnum: +#if _INTEGRAL_MAX_BITS >= 64 + if ( integer64 ) { + + while (!done_flag) { + + if (_T('x') == comchr || _T('p') == comchr) + + if (_ISXDIGIT(ch)) { + num64 <<= 4; + ch = _hextodec(ch); + } + else + ++done_flag; + + else if (_ISDIGIT(ch)) + + if (_T('o') == comchr) + if (_T('8') > ch) + num64 <<= 3; + else { + ++done_flag; + } + else /* _T('d') == comchr */ + num64 = MUL10(num64); + + else + ++done_flag; + + if (!done_flag) { + ++started; + num64 += ch - _T('0'); + + if (widthset && !--width) + ++done_flag; + else + ch = INC(); + } else + UN_INC(ch); + + } /* end of WHILE loop */ + + if (negative) + num64 = (uint64_t )(-(__int64)num64); + } + else { +#endif /* _INTEGRAL_MAX_BITS >= 64 */ + while (!done_flag) { + + if (_T('x') == comchr || _T('p') == comchr) + + if (_ISXDIGIT(ch)) { + number = (number << 4); + ch = _hextodec(ch); + } + else + ++done_flag; + + else if (_ISDIGIT(ch)) + + if (_T('o') == comchr) + if (_T('8') > ch) + number = (number << 3); + else { + ++done_flag; + } + else /* _T('d') == comchr */ + number = MUL10(number); + + else + ++done_flag; + + if (!done_flag) { + ++started; + number += ch - _T('0'); + + if (widthset && !--width) + ++done_flag; + else + ch = INC(); + } else + UN_INC(ch); + + } /* end of WHILE loop */ + + if (negative) + number = (unsigned long)(-(long)number); +#if _INTEGRAL_MAX_BITS >= 64 + } +#endif /* _INTEGRAL_MAX_BITS >= 64 */ + if (_T('F')==comchr) /* expected ':' in long pointer */ + started = 0; + + if (started) + if (!suppress) { + + ++count; +assign_num: +#if _INTEGRAL_MAX_BITS >= 64 + if ( integer64 ) + *(__int64 UNALIGNED *)pointer = ( uint64_t )num64; + else +#endif /* _INTEGRAL_MAX_BITS >= 64 */ + if (longone) + *(int UNALIGNED *)pointer = (unsigned int)number; + else + *(short UNALIGNED *)pointer = (unsigned short)number; + + } else /*NULL*/; + else + goto error_return; + + break; + + case _T('n') : /* char count, don't inc return value */ + number = charcount; + if(!suppress) + goto assign_num; /* found in number code above */ + break; + + + case _T('e') : + /* case _T('E') : */ + case _T('f') : + case _T('g') : /* scan a float */ + /* case _T('G') : */ + nFloatStrUsed=0; + + if (_T('-') == ch) { + pFloatStr[nFloatStrUsed++] = _T('-'); + goto f_incwidth; + + } else if (_T('+') == ch) { +f_incwidth: + --width; + ch = INC(); + } + + if (!widthset) /* must watch width */ + width = -1; + + + /* now get integral part */ + + while (_ISDIGIT(ch) && width--) { + ++started; + pFloatStr[nFloatStrUsed++] = (char)ch; + if (__check_float_string(nFloatStrUsed, + &nFloatStrSz, + &pFloatStr, + floatstring, + &malloc_FloatStrFlag + )==FALSE) { + goto error_return; + } + ch = INC(); + } + +#ifdef _UNICODE + /* convert decimal point to wide-char */ + /* if mbtowc fails (should never happen), we use L'.' */ + decimal = L'.'; + _MBTOWC(&decimal, _INTRN_LOCALE_CONV(_loc_update)->decimal_point, MB_CUR_MAX); +#else /* _UNICODE */ + + decimal=*((_INTRN_LOCALE_CONV(_loc_update))->decimal_point); +#endif /* _UNICODE */ + + /* now check for decimal */ + if (decimal == (char)ch && width--) { + ch = INC(); + pFloatStr[nFloatStrUsed++] = decimal; + if (__check_float_string(nFloatStrUsed, + &nFloatStrSz, + &pFloatStr, + floatstring, + &malloc_FloatStrFlag + )==FALSE) { + goto error_return; + } + + while (_ISDIGIT(ch) && width--) { + ++started; + pFloatStr[nFloatStrUsed++] = (_TCHAR)ch; + if (__check_float_string(nFloatStrUsed, + &nFloatStrSz, + &pFloatStr, + floatstring, + &malloc_FloatStrFlag + )==FALSE) { + goto error_return; + } + ch = INC(); + } + } + + /* now check for exponent */ + + if (started && (_T('e') == ch || _T('E') == ch) && width--) { + pFloatStr[nFloatStrUsed++] = _T('e'); + if (__check_float_string(nFloatStrUsed, + &nFloatStrSz, + &pFloatStr, + floatstring, + &malloc_FloatStrFlag + )==FALSE) { + goto error_return; + } + + if (_T('-') == (ch = INC())) { + + pFloatStr[nFloatStrUsed++] = _T('-'); + if (__check_float_string(nFloatStrUsed, + &nFloatStrSz, + &pFloatStr, + floatstring, + &malloc_FloatStrFlag + )==FALSE) { + goto error_return; + } + goto f_incwidth2; + + } else if (_T('+') == ch) { +f_incwidth2: + if (!width--) + ++width; + else + ch = INC(); + } + + + while (_ISDIGIT(ch) && width--) { + ++started; + pFloatStr[nFloatStrUsed++] = (_TCHAR)ch; + if (__check_float_string(nFloatStrUsed, + &nFloatStrSz, + &pFloatStr, + floatstring, + &malloc_FloatStrFlag + )==FALSE) { + goto error_return; + } + ch = INC(); + } + + } + + UN_INC(ch); + + if (started) + if (!suppress) { + ++count; + pFloatStr[nFloatStrUsed]= _T('\0'); +#ifdef _UNICODE + _WFASSIGN( longone-1, pointer, pFloatStr, (char)decimal, _loc_update.GetLocaleT()); +#else /* _UNICODE */ + _FASSIGN( longone-1, pointer, pFloatStr, (char)decimal, _loc_update.GetLocaleT()); +#endif /* _UNICODE */ + } else /*NULL */; + else + goto error_return; + + break; + + + default: /* either found '%' or something else */ + + if ((int)*format != (int)ch) { + UN_INC(ch); +#ifdef _SECURE_SCANF + /* error_return ASSERT's if format_error is true */ + format_error = TRUE; +#endif /* _SECURE_SCANF */ + goto error_return; + } + else + match--; /* % found, compensate for inc below */ + + if (!suppress) + va_copy(arglist, arglistsave); + + } /* SWITCH */ + + match++; /* matched a format field - set flag */ + + } /* WHILE (width) */ + + else { /* zero-width field in format string */ + UN_INC(ch); /* check for input error */ + goto error_return; + } + + ++format; /* skip to next char */ + + } else /* ('%' != *format) */ + { + + if ((int)*format++ != (int)(ch = INC())) + { + UN_INC(ch); + goto error_return; + } +#if 0 // we are not supporting multibyte input strings +#ifndef _UNICODE + if (isleadbyte((unsigned char)ch)) + { + int ch2; + if ((int)*format++ != (ch2=INC())) + { + UN_INC(ch2); + UN_INC(ch); + goto error_return; + } + + --charcount; /* only count as one character read */ + } +#endif /* _UNICODE */ +#endif + } + +#ifndef CPRFLAG + if ( (_TEOF == ch) && ((*format != _T('%')) || (*(format + 1) != _T('n'))) ) + break; +#endif /* CPRFLAG */ + + } /* WHILE (*format) */ + +error_return: +#if ALLOC_TABLE + if (malloc_flag == 1) + { + _free_crt(table); + } +#endif /* ALLOC_TABLE */ + if (malloc_FloatStrFlag == 1) + { + _free_crt(pFloatStr); + } + +#ifndef CPRFLAG + if (_TEOF == ch) + /* If any fields were matched or assigned, return count */ + return ( (count || match) ? count : EOF); + else +#endif /* CPRFLAG */ +#ifdef _SECURE_SCANF + if(format_error == TRUE) { + _VALIDATE_RETURN( ("Invalid Input Format" && 0), EINVAL, count); + } +#endif /* _SECURE_SCANF */ + return count; + +} + +/* _hextodec() returns a value of 0-15 and expects a char 0-9, a-f, A-F */ +/* _inc() is the one place where we put the actual getc code. */ +/* _whiteout() returns the first non-blank character, as defined by isspace() */ + +static int __cdecl _hextodec ( _TCHAR chr) +{ + return _ISDIGIT(chr) ? chr : (chr & ~(_T('a') - _T('A'))) - _T('A') + 10 + _T('0'); +} + +#ifdef CPRFLAG + +static int __cdecl _inc(void) +{ + return (_gettche_nolock()); +} + +static void __cdecl _un_inc(int chr) +{ + if (_TEOF != chr) { + _ungettch_nolock(chr); + } +} + +static int __cdecl _whiteout(REG1 int* counter) +{ + REG2 int ch; + + do + { + ++*counter; + ch = _inc(); + + if (ch == _TEOF) + { + break; + } + } + while(_istspace((_TUCHAR)ch)); + return ch; +} + +#else /* CPRFLAG */ + +static int __cdecl _inc(miniFILE* fileptr) +{ + return (_gettc_nolock(fileptr)); +} + +static void __cdecl _un_inc(int chr, miniFILE* fileptr) +{ + if (_TEOF != chr) { + _ungettc_nolock(chr,fileptr); + } +} + +static int __cdecl _whiteout(int* counter, miniFILE* fileptr) +{ + int ch; + + do + { + ++*counter; + ch = _inc(fileptr); + + if (ch == _TEOF) + { + break; + } + } + while(_istspace((_TUCHAR)ch)); + return ch; +} + +#endif /* CPRFLAG */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/internal.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/internal.h new file mode 100644 index 0000000..3b3b3e6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/internal.h @@ -0,0 +1,1088 @@ +// 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. + +/*** +*internal.h - contains declarations of internal routines and variables +* + +* +*Purpose: +* Declares routines and variables used internally by the C run-time. +* +* [Internal] +* +****/ + +#if _MSC_VER > 1000 +#pragma once +#endif /* _MSC_VER > 1000 */ + +#ifndef _INC_INTERNAL +#define _INC_INTERNAL + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +/* + * Conditionally include windows.h to pick up the definition of + * CRITICAL_SECTION. + */ +#include + +#ifdef _MSC_VER +#pragma pack(push,_CRT_PACKING) +#endif /* _MSC_VER */ + +/* Define function types used in several startup sources */ + +typedef void (__cdecl *_PVFV)(void); +typedef int (__cdecl *_PIFV)(void); +typedef void (__cdecl *_PVFI)(int); + +#if _MSC_VER >= 1400 && defined(_M_CEE) +typedef const void* (__clrcall *_PVFVM)(void); +typedef int (__clrcall *_PIFVM)(void); +typedef void (__clrcall *_CPVFV)(void); +#endif /* _MSC_VER >= 1400 && defined(_M_CEE) */ + +#if defined (_M_CEE_PURE) || (defined (_DLL) && defined (_M_IX86)) +/* Retained for compatibility with VC++ 5.0 and earlier versions */ +_CRTIMP int * __cdecl __p__commode(void); +#endif /* defined (_M_CEE_PURE) || (defined (_DLL) && defined (_M_IX86)) */ +#if defined (SPECIAL_CRTEXE) && defined (_DLL) + extern int _commode; +#else /* defined (SPECIAL_CRTEXE) && defined (_DLL) */ +#ifndef _M_CEE_PURE +_CRTIMP extern int _commode; +#else /* _M_CEE_PURE */ +#define _commode (*__p___commode()) +#endif /* _M_CEE_PURE */ +#endif /* defined (SPECIAL_CRTEXE) && defined (_DLL) */ + +#define __IOINFO_TM_ANSI 0 /* Regular Text */ +#define __IOINFO_TM_UTF8 1 /* UTF8 Encoded */ +#define __IOINFO_TM_UTF16LE 2 /* UTF16 Little Endian Encoded */ + +/* + * Control structure for lowio file handles + */ +typedef struct { + intptr_t osfhnd; /* underlying OS file HANDLE */ + char osfile; /* attributes of file (e.g., open in text mode?) */ + char pipech; /* one char buffer for handles opened on pipes */ + int lockinitflag; + CRITICAL_SECTION lock; +#ifndef _SAFECRT_IMPL + /* Not used in the safecrt downlevel. We do not define them, so we cannot use them accidentally */ + char textmode : 7; /* __IOINFO_TM_ANSI or __IOINFO_TM_UTF8 or __IOINFO_TM_UTF16LE */ + char unicode : 1; /* Was the file opened as unicode? */ + char pipech2[2]; /* 2 more peak ahead chars for UNICODE mode */ +#endif /* _SAFECRT_IMPL */ + } ioinfo; + +/* + * Definition of IOINFO_L2E, the log base 2 of the number of elements in each + * array of ioinfo structs. + */ +#define IOINFO_L2E 5 + +/* + * Definition of IOINFO_ARRAY_ELTS, the number of elements in ioinfo array + */ +#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) + +/* + * Definition of IOINFO_ARRAYS, maximum number of supported ioinfo arrays. + */ +#define IOINFO_ARRAYS 64 + +#define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS) + +#define _TZ_STRINGS_SIZE 64 + +/* + * Access macros for getting at an ioinfo struct and its fields from a + * file handle + */ +#define _pioinfo(i) ( __pioinfo[(i) >> IOINFO_L2E] + ((i) & (IOINFO_ARRAY_ELTS - \ + 1)) ) +#define _osfhnd(i) ( _pioinfo(i)->osfhnd ) + +#define _osfile(i) ( _pioinfo(i)->osfile ) + +#define _pipech(i) ( _pioinfo(i)->pipech ) + +#define _pipech2(i) ( _pioinfo(i)->pipech2 ) + +#define _textmode(i) ( _pioinfo(i)->textmode ) + +#define _tm_unicode(i) ( _pioinfo(i)->unicode ) + +/* + * Safer versions of the above macros. Currently, only _osfile_safe is + * used. + */ +#define _pioinfo_safe(i) ( (((i) != -1) && ((i) != -2)) ? _pioinfo(i) : &__badioinfo ) + +#define _osfhnd_safe(i) ( _pioinfo_safe(i)->osfhnd ) + +#define _osfile_safe(i) ( _pioinfo_safe(i)->osfile ) + +#define _pipech_safe(i) ( _pioinfo_safe(i)->pipech ) + +#define _pipech2_safe(i) ( _pioinfo_safe(i)->pipech2 ) + +#ifdef _SAFECRT_IMPL +/* safecrt does not have support for textmode, so we always return __IOINFO_TM_ANSI */ +#define _textmode_safe(i) __IOINFO_TM_ANSI +#define _tm_unicode_safe(i) 0 +#else /* _SAFECRT_IMPL */ +#define _textmode_safe(i) ( _pioinfo_safe(i)->textmode ) +#define _tm_unicode_safe(i) ( _pioinfo_safe(i)->unicode ) +#endif /* _SAFECRT_IMPL */ + +#ifndef _M_CEE_PURE +#ifdef _SAFECRT_IMPL +/* We need to get this from the downlevel DLL, even when we build safecrt.lib */ +extern __declspec(dllimport) ioinfo __badioinfo; +extern __declspec(dllimport) ioinfo * __pioinfo[]; +#else /* _SAFECRT_IMPL */ +/* + * Special, static ioinfo structure used only for more graceful handling + * of a C file handle value of -1 (results from common errors at the stdio + * level). + */ +extern _CRTIMP ioinfo __badioinfo; + +/* + * Array of arrays of control structures for lowio files. + */ +extern _CRTIMP ioinfo * __pioinfo[]; +#endif /* _SAFECRT_IMPL */ +#endif /* _M_CEE_PURE */ + +/* + * Current number of allocated ioinfo structures (_NHANDLE_ is the upper + * limit). + */ +extern int _nhandle; + +int __cdecl _alloc_osfhnd(void); +int __cdecl _free_osfhnd(int); +int __cdecl _set_osfhnd(int, intptr_t); + +/* + fileno for stdout, stdin & stderr when there is no console +*/ +#define _NO_CONSOLE_FILENO (intptr_t)-2 + + +extern const char __dnames[]; +extern const char __mnames[]; + +extern int _days[]; +extern int _lpdays[]; + +extern __time32_t __cdecl __loctotime32_t(int, int, int, int, int, int, int); +extern __time64_t __cdecl __loctotime64_t(int, int, int, int, int, int, int); + +extern void __cdecl __tzset(void); + +extern int __cdecl _validdrive(unsigned); + +/* + * If we are only interested in years between 1901 and 2099, we could use this: + * + * #define IS_LEAP_YEAR(y) (y % 4 == 0) + */ + +#define IS_LEAP_YEAR(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0) + +/* + * This variable is in the C start-up; the length must be kept synchronized + * It is used by the *cenvarg.c modules + */ + +extern char _acfinfo[]; /* "_C_FILE_INFO=" */ + +#define CFI_LENGTH 12 /* "_C_FILE_INFO" is 12 bytes long */ + + +/* + * stdio internals + */ +#ifndef _FILE_DEFINED +struct _iobuf { + char *_ptr; + int _cnt; + char *_base; + int _flag; + int _file; + int _charbuf; + int _bufsiz; + char *_tmpfname; + }; +typedef struct _iobuf FILE; +#define _FILE_DEFINED +#endif /* _FILE_DEFINED */ + +#if !defined (_FILEX_DEFINED) && defined (_WINDOWS_) + +/* + * Variation of FILE type used for the dynamically allocated portion of + * __piob[]. For single thread, _FILEX is the same as FILE. For multithread + * models, _FILEX has two fields: the FILE struct and the CRITICAL_SECTION + * struct used to serialize access to the FILE. + */ + +typedef struct { + FILE f; + CRITICAL_SECTION lock; + } _FILEX; + + +#define _FILEX_DEFINED +#endif /* !defined (_FILEX_DEFINED) && defined (_WINDOWS_) */ + +/* + * Number of entries supported in the array pointed to by __piob[]. That is, + * the number of stdio-level files which may be open simultaneously. This + * is normally set to _NSTREAM_ by the stdio initialization code. + */ +extern int _nstream; + +/* + * Pointer to the array of pointers to FILE/_FILEX structures that are used + * to manage stdio-level files. + */ +extern void **__piob; + +FILE * __cdecl _getstream(void); +FILE * __cdecl _openfile(__in_z const char * _Filename, __in_z const char * _Mode, __in int _ShFlag, __out FILE * _File); +FILE * __cdecl _wopenfile(__in_z const char16_t * _Filename, __in_z const char16_t * _Mode, __in int _ShFlag, __out FILE * _File); +void __cdecl _getbuf(__out FILE * _File); +int __cdecl _filwbuf (__inout FILE * _File); +int __cdecl _flswbuf(__in int _Ch, __inout FILE * _File); +void __cdecl _freebuf(__inout FILE * _File); +int __cdecl _stbuf(__inout FILE * _File); +void __cdecl _ftbuf(int _Flag, __inout FILE * _File); + +#ifdef _SAFECRT_IMPL + +int __cdecl _output(__inout FILE * _File, __in_z __format_string const char *_Format, va_list _ArgList); +int __cdecl _woutput(__inout FILE * _File, __in_z __format_string const char16_t *_Format, va_list _ArgList); +int __cdecl _output_s(__inout FILE * _File, __in_z __format_string const char *_Format, va_list _ArgList); +int __cdecl _output_p(__inout FILE * _File, __in_z __format_string const char *_Format, va_list _ArgList); +int __cdecl _woutput_s(__inout FILE * _File, __in_z __format_string const char16_t *_Format, va_list _ArgList); +int __cdecl _woutput_p(__inout FILE * _File, __in_z __format_string const char16_t *_Format, va_list _ArgList); +typedef int (*OUTPUTFN)(FILE *, const char *, va_list); +typedef int (*WOUTPUTFN)(FILE *, const char16_t *, va_list); + +#else /* _SAFECRT_IMPL */ + +int __cdecl _output_l(__inout FILE * _File, __in_z __format_string const char *_Format, __in_opt _locale_t _Locale, va_list _ArgList); +int __cdecl _woutput_l(__inout FILE * _File, __in_z __format_string const char16_t *_Format, __in_opt _locale_t _Locale, va_list _ArgList); +int __cdecl _output_s_l(__inout FILE * _File, __in_z __format_string const char *_Format, __in_opt _locale_t _Locale, va_list _ArgList); +int __cdecl _output_p_l(__inout FILE * _File, __in_z __format_string const char *_Format, __in_opt _locale_t _Locale, va_list _ArgList); +int __cdecl _woutput_s_l(__inout FILE * _File, __in_z __format_string const char16_t *_Format, __in_opt _locale_t _Locale, va_list _ArgList); +int __cdecl _woutput_p_l(__inout FILE * _File, __in_z __format_string const char16_t *_Format, __in_opt _locale_t _Locale, va_list _ArgList); +typedef int (*OUTPUTFN)(__inout FILE * _File, const char *, _locale_t, va_list); +typedef int (*WOUTPUTFN)(__inout FILE * _File, const char16_t *, _locale_t, va_list); + +#endif /* _SAFECRT_IMPL */ + +#ifdef _SAFECRT_IMPL + +int __cdecl _input(__in FILE * _File, __in_z __format_string const unsigned char * _Format, va_list _ArgList); +int __cdecl _winput(__in FILE * _File, __in_z __format_string const char16_t * _Format, va_list _ArgList); +int __cdecl _input_s(__in FILE * _File, __in_z __format_string const unsigned char * _Format, va_list _ArgList); +int __cdecl _winput_s(__in FILE * _File, __in_z __format_string const char16_t * _Format, va_list _ArgList); +typedef int (*INPUTFN)(FILE *, const unsigned char *, va_list); +typedef int (*WINPUTFN)(FILE *, const char16_t *, va_list); + +#else /* _SAFECRT_IMPL */ + +int __cdecl _input_l(__inout FILE * _File, __in_z __format_string const unsigned char *, __in_opt _locale_t _Locale, va_list _ArgList); +int __cdecl _winput_l(__inout FILE * _File, __in_z __format_string const char16_t *, __in_opt _locale_t _Locale, va_list _ArgList); +int __cdecl _input_s_l(__inout FILE * _File, __in_z __format_string const unsigned char *, __in_opt _locale_t _Locale, va_list _ArgList); +int __cdecl _winput_s_l(__inout FILE * _File, __in_z __format_string const char16_t *, __in_opt _locale_t _Locale, va_list _ArgList); +typedef int (*INPUTFN)(FILE *, const unsigned char *, _locale_t, va_list); +typedef int (*WINPUTFN)(FILE *, const char16_t *, _locale_t, va_list); + +#ifdef _UNICODE +#define TINPUTFN WINPUTFN +#else /* _UNICODE */ +#define TINPUTFN INPUTFN +#endif /* _UNICODE */ + +#endif /* _SAFECRT_IMPL */ + +int __cdecl _flush(__inout FILE * _File); +void __cdecl _endstdio(void); + +errno_t __cdecl _sopen_helper(__in_z const char * _Filename, + __in int _OFlag, __in int _ShFlag, __in int _PMode, + __out int * _PFileHandle, int _BSecure); +errno_t __cdecl _wsopen_helper(__in_z const char16_t * _Filename, + __in int _OFlag, __in int _ShFlag, __in int _PMode, + __out int * _PFileHandle, int _BSecure); + +#ifndef CRTDLL +extern int _cflush; +#endif /* CRTDLL */ + +extern unsigned int _tempoff; + +extern unsigned int _old_pfxlen; + +extern int _umaskval; /* the umask value */ + +extern char _pipech[]; /* pipe lookahead */ + +extern char _exitflag; /* callable termination flag */ + +extern int _C_Termination_Done; /* termination done flag */ + +char * __cdecl _getpath(__in_z const char * _Src, __out_ecount_z(_SizeInChars) char * _Dst, __in size_t _SizeInChars); +char16_t * __cdecl _wgetpath(__in_z const char16_t * _Src, __out_ecount_z(_SizeInWords) char16_t * _Dst, __in size_t _SizeInWords); + +extern int _dowildcard; /* flag to enable argv[] wildcard expansion */ + +#ifndef _PNH_DEFINED +typedef int (__cdecl * _PNH)( size_t ); +#define _PNH_DEFINED +#endif /* _PNH_DEFINED */ + +#if _MSC_VER >= 1400 && defined(_M_CEE) +#ifndef __MPNH_DEFINED +typedef int (__clrcall * __MPNH)( size_t ); +#define __MPNH_DEFINED +#endif /* __MPNH_DEFINED */ +#endif /* _MSC_VER >= 1400 && defined(_M_CEE) */ + + +/* calls the currently installed new handler */ +int __cdecl _callnewh(__in size_t _Size); + +extern int _newmode; /* malloc new() handler mode */ + +/* pointer to initial environment block that is passed to [w]main */ +#ifndef _M_CEE_PURE +extern _CRTIMP char16_t **__winitenv; +extern _CRTIMP char **__initenv; +#endif /* _M_CEE_PURE */ + +/* _calloca helper */ +#define _calloca(count, size) ((count<=0 || size<=0 || ((((size_t)_HEAP_MAXREQ) / ((size_t)count)) < ((size_t)size)))? NULL : _malloca(count * size)) + +/* startup set values */ +extern char *_aenvptr; /* environment ptr */ +extern char16_t *_wenvptr; /* wide environment ptr */ + +/* command line */ + +#if defined (_DLL) +_CRTIMP char ** __cdecl __p__acmdln(void); +_CRTIMP char16_t ** __cdecl __p__wcmdln(void); +#endif /* defined (_DLL) */ +#ifndef _M_CEE_PURE +_CRTIMP extern char *_acmdln; +_CRTIMP extern char16_t *_wcmdln; +#else /* _M_CEE_PURE */ +#define _acmdln (*__p__acmdln()) +#define _wcmdln (*__p__wcmdln()) +#endif /* _M_CEE_PURE */ + +/* + * prototypes for internal startup functions + */ +int __cdecl _cwild(void); /* wild.c */ +int __cdecl _wcwild(void); /* wwild.c */ +int __cdecl _mtinit(void); /* tidtable.c */ +void __cdecl _mtterm(void); /* tidtable.c */ +int __cdecl _mtinitlocks(void); /* mlock.c */ +void __cdecl _mtdeletelocks(void); /* mlock.c */ +int __cdecl _mtinitlocknum(int); /* mlock.c */ + +/* Wrapper for InitializeCriticalSection API, with default spin count */ +int __cdecl __crtInitCritSecAndSpinCount(PCRITICAL_SECTION, DWORD); +#define _CRT_SPINCOUNT 4000 + +/* + * C source build only!!!! + * + * more prototypes for internal startup functions + */ +void __cdecl _amsg_exit(int); /* crt0.c */ +void __cdecl __crtExitProcess(int); /* crt0dat.c */ +void __cdecl __crtCorExitProcess(int); /* crt0dat.c */ +void __cdecl __crtdll_callstaticterminators(void); /* crt0dat.c */ + +/* +_cinit now allows the caller to suppress floating point precision init +This allows the DLLs that use the CRT to not initialise FP precision, +allowing the EXE's setting to persist even when a DLL is loaded +*/ +int __cdecl _cinit(int /* initFloatingPrecision */); /* crt0dat.c */ +void __cdecl __doinits(void); /* astart.asm */ +void __cdecl __doterms(void); /* astart.asm */ +void __cdecl __dopreterms(void); /* astart.asm */ +void __cdecl _FF_MSGBANNER(void); +void __cdecl _fpmath(int /*initPrecision*/); +void __cdecl _fpclear(void); +void __cdecl _fptrap(void); /* crt0fp.c */ +int __cdecl _heap_init(int); +void __cdecl _heap_term(void); +void __cdecl _heap_abort(void); +void __cdecl __initconin(void); /* initcon.c */ +void __cdecl __initconout(void); /* initcon.c */ +int __cdecl _ioinit(void); /* crt0.c, crtlib.c */ +void __cdecl _ioterm(void); /* crt0.c, crtlib.c */ +char * __cdecl _GET_RTERRMSG(int); +void __cdecl _NMSG_WRITE(int); +int __CRTDECL _setargv(void); /* setargv.c, stdargv.c */ +int __CRTDECL __setargv(void); /* stdargv.c */ +int __CRTDECL _wsetargv(void); /* wsetargv.c, wstdargv.c */ +int __CRTDECL __wsetargv(void); /* wstdargv.c */ +int __cdecl _setenvp(void); /* stdenvp.c */ +int __cdecl _wsetenvp(void); /* wstdenvp.c */ +void __cdecl __setmbctable(unsigned int); /* mbctype.c */ + +#ifdef MRTDLL +_MRTIMP int __cdecl _onexit_process(_CPVFV); +_MRTIMP int __cdecl _onexit_app_domain(_CPVFV); +#endif /* MRTDLL */ + +#ifdef _MBCS +int __cdecl __initmbctable(void); /* mbctype.c */ +#endif /* _MBCS */ + +#ifndef _MANAGED_MAIN +int __CRTDECL main(__in int _Argc, __in_ecount_z(_Argc) char ** _Argv, __in_z char ** _Env); +int __CRTDECL wmain(__in int _Argc, __in_ecount_z(_Argc) char16_t ** _Argv, __in_z char16_t ** _Env); +#endif /* _MANAGED_MAIN */ + +/* helper functions for wide/multibyte environment conversion */ +int __cdecl __mbtow_environ (void); +int __cdecl __wtomb_environ (void); + +/* These two functions take a char ** for the environment option + At some point during their execution, they take ownership of the + memory block passed in using option. At this point, they + NULL out the incoming char * / char16_t * to ensure there is no + double-free +*/ +int __cdecl __crtsetenv (__deref_inout_opt char ** _POption, __in const int _Primary); +int __cdecl __crtwsetenv (__deref_inout_opt char16_t ** _POption, __in const int _Primary); + +#ifndef _M_CEE_PURE +_CRTIMP extern void (__cdecl * _aexit_rtn)(int); +#endif /* _M_CEE_PURE */ + +#if defined (_DLL) || defined (CRTDLL) + +#ifndef _STARTUP_INFO_DEFINED +typedef struct +{ + int newmode; +} _startupinfo; +#define _STARTUP_INFO_DEFINED +#endif /* _STARTUP_INFO_DEFINED */ + +_CRTIMP int __cdecl __getmainargs(__out int * _Argc, __deref_out_ecount(*_Argc) char *** _Argv, + __deref_out_opt char *** _Env, __in int _DoWildCard, + __in _startupinfo * _StartInfo); + +_CRTIMP int __cdecl __wgetmainargs(__out int * _Argc, __deref_out_ecount(*_Argc)char16_t *** _Argv, + __deref_out_opt char16_t *** _Env, __in int _DoWildCard, + __in _startupinfo * _StartInfo); + +#endif /* defined (_DLL) || defined (CRTDLL) */ + +/* + * Prototype, variables and constants which determine how error messages are + * written out. + */ +#define _UNKNOWN_APP 0 +#define _CONSOLE_APP 1 +#define _GUI_APP 2 + +extern int __app_type; + +#if !defined (_M_CEE_PURE) + +extern Volatile __native_startup_lock; + +#define __NO_REASON UINT_MAX +extern Volatile __native_dllmain_reason; +extern Volatile __native_vcclrit_reason; + +#if defined (__cplusplus) + +#pragma warning(push) +#pragma warning(disable: 4483) +#if _MSC_FULL_VER >= 140050415 +#define _NATIVE_STARTUP_NAMESPACE __identifier("") +#else /* _MSC_FULL_VER >= 140050415 */ +#define _NATIVE_STARTUP_NAMESPACE __CrtImplementationDetails +#endif /* _MSC_FULL_VER >= 140050415 */ + +namespace _NATIVE_STARTUP_NAMESPACE +{ + class NativeDll + { + private: + static const unsigned int ProcessDetach = 0; + static const unsigned int ProcessAttach = 1; + static const unsigned int ThreadAttach = 2; + static const unsigned int ThreadDetach = 3; + static const unsigned int ProcessVerifier = 4; + + public: + + inline static bool IsInDllMain() + { + return (__native_dllmain_reason != __NO_REASON); + } + + inline static bool IsInProcessAttach() + { + return (__native_dllmain_reason == ProcessAttach); + } + + inline static bool IsInProcessDetach() + { + return (__native_dllmain_reason == ProcessDetach); + } + + inline static bool IsInVcclrit() + { + return (__native_vcclrit_reason != __NO_REASON); + } + + inline static bool IsSafeForManagedCode() + { + if (!IsInDllMain()) + { + return true; + } + + if (IsInVcclrit()) + { + return true; + } + + return !IsInProcessAttach() && !IsInProcessDetach(); + } + }; +} +#pragma warning(pop) + +#endif /* defined (__cplusplus) */ + +#endif /* !defined (_M_CEE_PURE) */ + +extern int __error_mode; + +_CRTIMP void __cdecl __set_app_type(int); +#if defined (CRTDLL) && !defined (_SYSCRT) +/* + * All these function pointer are used for creating global state of CRT + * functions. Either all of them will be set or all of them will be NULL + */ +typedef void (__cdecl *_set_app_type_function)(int); +typedef int (__cdecl *_get_app_type_function)(); +extern _set_app_type_function __set_app_type_server; +extern _get_app_type_function __get_app_type_server; +#endif /* defined (CRTDLL) && !defined (_SYSCRT) */ + +/* + * C source build only!!!! + * + * map Win32 errors into Xenix errno values -- for modules written in C + */ +_CRTIMP void __cdecl _dosmaperr(unsigned long); +extern int __cdecl _get_errno_from_oserr(unsigned long); + +/* + * internal routines used by the exec/spawn functions + */ + +extern intptr_t __cdecl _dospawn(__in int _Mode, __in_z_opt const char * _Name, __inout_z char * _Cmd, __in_z_opt char * _Env); +extern intptr_t __cdecl _wdospawn(__in int _Mode, __in_z_opt const char16_t * _Name, __inout_z char16_t * _Cmd, __in_z_opt char16_t * _Env); +extern int __cdecl _cenvarg(__in_z const char * const * _Argv, __in_z_opt const char * const * _Env, + __deref_out_opt char ** _ArgBlk, __deref_out_opt char ** _EnvBlk, __in_z const char *_Name); +extern int __cdecl _wcenvarg(__in_z const char16_t * const * _Argv, __in_z_opt const char16_t * const * _Env, + __deref_out_opt char16_t ** _ArgBlk, __deref_out_opt char16_t ** _EnvBlk, __in_z const char16_t * _Name); +#ifndef _M_IX86 +extern char ** _capture_argv(__in va_list *, __in_z const char * _FirstArg, __out_ecount_z(_MaxCount) char ** _Static_argv, __in size_t _MaxCount); +extern char16_t ** _wcapture_argv(__in va_list *, __in_z const char16_t * _FirstArg, __out_ecount_z(_MaxCount) char16_t ** _Static_argv, __in size_t _MaxCount); +#endif /* _M_IX86 */ + +/* + * internal routine used by the abort + */ + +extern _PHNDLR __cdecl __get_sigabrt(void); + +/* + * Type from ntdef.h + */ + +typedef LONG NTSTATUS; + +/* + * Exception code used in _invalid_parameter + */ + +#ifndef STATUS_INVALID_PARAMETER +#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL) +#endif /* STATUS_INVALID_PARAMETER */ + +/* + * Exception code used for abort and _CALL_REPORTFAULT + */ + +#ifndef STATUS_FATAL_APP_EXIT +#define STATUS_FATAL_APP_EXIT ((NTSTATUS)0x40000015L) +#endif /* STATUS_FATAL_APP_EXIT */ + +/* + * Validate functions + */ +#include /* _ASSERTE */ +#include + +#define __STR2WSTR(str) L##str + +#define _STR2WSTR(str) __STR2WSTR(str) + +#define __FILEW__ _STR2WSTR(__FILE__) +#define __FUNCTIONW__ _STR2WSTR(__FUNCTION__) + +/* We completely fill the buffer only in debug (see _SECURECRT__FILL_STRING + * and _SECURECRT__FILL_BYTE macros). + */ +#if !defined (_SECURECRT_FILL_BUFFER) +#ifdef _DEBUG +#define _SECURECRT_FILL_BUFFER 1 +#else /* _DEBUG */ +#define _SECURECRT_FILL_BUFFER 0 +#endif /* _DEBUG */ +#endif /* !defined (_SECURECRT_FILL_BUFFER) */ + +#ifndef _SAFECRT_IMPL +/* _invalid_parameter is already defined in safecrt.h and safecrt.lib */ +#if !defined (_NATIVE_char16_t_DEFINED) && defined (_M_CEE_PURE) +extern "C++" +#endif /* !defined (_NATIVE_char16_t_DEFINED) && defined (_M_CEE_PURE) */ +_CRTIMP +#endif /* _SAFECRT_IMPL */ +void __cdecl _invalid_parameter(__in_z_opt const char16_t *, __in_z_opt const char16_t *, __in_z_opt const char16_t *, unsigned int, uintptr_t); + +#if !defined (_NATIVE_char16_t_DEFINED) && defined (_M_CEE_PURE) +extern "C++" +#endif /* !defined (_NATIVE_char16_t_DEFINED) && defined (_M_CEE_PURE) */ +_CRTIMP +void __cdecl _invoke_watson(__in_z_opt const char16_t *, __in_z_opt const char16_t *, __in_z_opt const char16_t *, unsigned int, uintptr_t); + +#ifndef _DEBUG +#if !defined (_NATIVE_char16_t_DEFINED) && defined (_M_CEE_PURE) +extern "C++" +#endif /* !defined (_NATIVE_char16_t_DEFINED) && defined (_M_CEE_PURE) */ +_CRTIMP +void __cdecl _invalid_parameter_noinfo(void); +#endif /* _DEBUG */ + +/* Invoke Watson if _ExpressionError is not 0; otherwise simply return _EspressionError */ +__forceinline +void _invoke_watson_if_error( + errno_t _ExpressionError, + const char16_t *_Expression, + const char16_t *_Function, + const char16_t *_File, + unsigned int _Line, + uintptr_t _Reserved + ) +{ + if (_ExpressionError == 0) + { + return; + } + _invoke_watson(_Expression, _Function, _File, _Line, _Reserved); +} + +/* Invoke Watson if _ExpressionError is not 0 and equal to _ErrorValue1 or _ErrorValue2; otherwise simply return _EspressionError */ +__forceinline +errno_t _invoke_watson_if_oneof( + errno_t _ExpressionError, + errno_t _ErrorValue1, + errno_t _ErrorValue2, + const char16_t *_Expression, + const char16_t *_Function, + const char16_t *_File, + unsigned int _Line, + uintptr_t _Reserved + ) +{ + if (_ExpressionError == 0 || (_ExpressionError != _ErrorValue1 && _ExpressionError != _ErrorValue2)) + { + return _ExpressionError; + } + _invoke_watson(_Expression, _Function, _File, _Line, _Reserved); + return _ExpressionError; +} + +/* + * Assert in debug builds. + * set errno and return + * + */ +#ifdef _DEBUG +#define _CALL_INVALID_PARAMETER_FUNC(funcname, expr) funcname(expr, __FUNCTIONW__, __FILEW__, __LINE__, 0) +#define _INVOKE_WATSON_IF_ERROR(expr) _invoke_watson_if_error((expr), __STR2WSTR(#expr), __FUNCTIONW__, __FILEW__, __LINE__, 0) +#define _INVOKE_WATSON_IF_ONEOF(expr, errvalue1, errvalue2) _invoke_watson_if_oneof(expr, (errvalue1), (errvalue2), __STR2WSTR(#expr), __FUNCTIONW__, __FILEW__, __LINE__, 0) +#else /* _DEBUG */ +#define _CALL_INVALID_PARAMETER_FUNC(funcname, expr) funcname(NULL, NULL, NULL, 0, 0) +#define _INVOKE_WATSON_IF_ERROR(expr) _invoke_watson_if_error(expr, NULL, NULL, NULL, 0, 0) +#define _INVOKE_WATSON_IF_ONEOF(expr, errvalue1, errvalue2) _invoke_watson_if_oneof((expr), (errvalue1), (errvalue2), NULL, NULL, NULL, 0, 0) +#endif /* _DEBUG */ + +#define _INVALID_PARAMETER(expr) _CALL_INVALID_PARAMETER_FUNC(_invalid_parameter, expr) + +#define _VALIDATE_RETURN_VOID( expr, errorcode ) \ + { \ + int _Expr_val=!!(expr); \ + _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ + if ( !( _Expr_val ) ) \ + { \ + errno = errorcode; \ + _INVALID_PARAMETER(_CRT_WIDE(#expr)); \ + return; \ + } \ + } + +/* + * Assert in debug builds. + * set errno and return value + */ + +#ifndef _VALIDATE_RETURN +#define _VALIDATE_RETURN( expr, errorcode, retexpr ) \ + { \ + int _Expr_val=!!(expr); \ + _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ + if ( !( _Expr_val ) ) \ + { \ + errno = errorcode; \ + _INVALID_PARAMETER(_CRT_WIDE(#expr) ); \ + return ( retexpr ); \ + } \ + } +#endif /* _VALIDATE_RETURN */ + +#ifndef _VALIDATE_RETURN_NOEXC +#define _VALIDATE_RETURN_NOEXC( expr, errorcode, retexpr ) \ + { \ + if ( !(expr) ) \ + { \ + errno = errorcode; \ + return ( retexpr ); \ + } \ + } +#endif /* _VALIDATE_RETURN_NOEXC */ + +/* + * Assert in debug builds. + * set errno and set retval for later usage + */ + +#define _VALIDATE_SETRET( expr, errorcode, retval, retexpr ) \ + { \ + int _Expr_val=!!(expr); \ + _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ + if ( !( _Expr_val ) ) \ + { \ + errno = errorcode; \ + _INVALID_PARAMETER(_CRT_WIDE(#expr)); \ + retval=( retexpr ); \ + } \ + } + +#define _CHECK_FH_RETURN( handle, errorcode, retexpr ) \ + { \ + if(handle == _NO_CONSOLE_FILENO) \ + { \ + errno = errorcode; \ + return ( retexpr ); \ + } \ + } + +/* + We use _VALIDATE_STREAM_ANSI_RETURN to ensure that ANSI file operations( + fprintf etc) aren't called on files opened as UNICODE. We do this check + only if it's an actual FILE pointer & not a string +*/ + +#define _VALIDATE_STREAM_ANSI_RETURN( stream, errorcode, retexpr ) \ + { \ + FILE *_Stream=stream; \ + _VALIDATE_RETURN(( (_Stream->_flag & _IOSTRG) || \ + ( (_textmode_safe(_fileno(_Stream)) == __IOINFO_TM_ANSI) && \ + !_tm_unicode_safe(_fileno(_Stream)))), \ + errorcode, retexpr) \ + } + +/* + We use _VALIDATE_STREAM_ANSI_SETRET to ensure that ANSI file operations( + fprintf etc) aren't called on files opened as UNICODE. We do this check + only if it's an actual FILE pointer & not a string. It doesn't actually return + immediately +*/ + +#define _VALIDATE_STREAM_ANSI_SETRET( stream, errorcode, retval, retexpr) \ + { \ + FILE *_Stream=stream; \ + _VALIDATE_SETRET(( (_Stream->_flag & _IOSTRG) || \ + ( (_textmode_safe(_fileno(_Stream)) == __IOINFO_TM_ANSI) && \ + !_tm_unicode_safe(_fileno(_Stream)))), \ + errorcode, retval, retexpr) \ + } + +/* + * Assert in debug builds. + * Return value (do not set errno) + */ + +#define _VALIDATE_RETURN_NOERRNO( expr, retexpr ) \ + { \ + int _Expr_val=!!(expr); \ + _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ + if ( !( _Expr_val ) ) \ + { \ + _INVALID_PARAMETER(_CRT_WIDE(#expr)); \ + return ( retexpr ); \ + } \ + } + +/* + * Assert in debug builds. + * set errno and return errorcode + */ + +#define _VALIDATE_RETURN_ERRCODE( expr, errorcode ) \ + { \ + int _Expr_val=!!(expr); \ + _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ + if ( !( _Expr_val ) ) \ + { \ + errno = errorcode; \ + _INVALID_PARAMETER(_CRT_WIDE(#expr)); \ + return ( errorcode ); \ + } \ + } + +#define _VALIDATE_RETURN_ERRCODE_NOEXC( expr, errorcode ) \ + { \ + if (!(expr)) \ + { \ + errno = errorcode; \ + return ( errorcode ); \ + } \ + } + +#define _VALIDATE_CLEAR_OSSERR_RETURN( expr, errorcode, retexpr ) \ + { \ + int _Expr_val=!!(expr); \ + _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ + if ( !( _Expr_val ) ) \ + { \ + _doserrno = 0L; \ + errno = errorcode; \ + _INVALID_PARAMETER(_CRT_WIDE(#expr) ); \ + return ( retexpr ); \ + } \ + } + +#define _CHECK_FH_CLEAR_OSSERR_RETURN( handle, errorcode, retexpr ) \ + { \ + if(handle == _NO_CONSOLE_FILENO) \ + { \ + _doserrno = 0L; \ + errno = errorcode; \ + return ( retexpr ); \ + } \ + } + +#define _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE( expr, errorcode ) \ + { \ + int _Expr_val=!!(expr); \ + _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ + if ( !( _Expr_val ) ) \ + { \ + _doserrno = 0L; \ + errno = errorcode; \ + _INVALID_PARAMETER(_CRT_WIDE(#expr)); \ + return ( errorcode ); \ + } \ + } + +#define _CHECK_FH_CLEAR_OSSERR_RETURN_ERRCODE( handle, retexpr ) \ + { \ + if(handle == _NO_CONSOLE_FILENO) \ + { \ + _doserrno = 0L; \ + return ( retexpr ); \ + } \ + } + +#ifdef _DEBUG +extern size_t __crtDebugFillThreshold; +#endif /* _DEBUG */ + +#if !defined (_SECURECRT_FILL_BUFFER_THRESHOLD) +#ifdef _DEBUG +#define _SECURECRT_FILL_BUFFER_THRESHOLD __crtDebugFillThreshold +#else /* _DEBUG */ +#define _SECURECRT_FILL_BUFFER_THRESHOLD ((size_t)0) +#endif /* _DEBUG */ +#endif /* !defined (_SECURECRT_FILL_BUFFER_THRESHOLD) */ + +#if _SECURECRT_FILL_BUFFER +#define _SECURECRT__FILL_STRING(_String, _Size, _Offset) \ + if ((_Size) != ((size_t)-1) && (_Size) != INT_MAX && \ + ((size_t)(_Offset)) < (_Size)) \ + { \ + memset((_String) + (_Offset), \ + _SECURECRT_FILL_BUFFER_PATTERN, \ + (_SECURECRT_FILL_BUFFER_THRESHOLD < ((size_t)((_Size) - (_Offset))) ? \ + _SECURECRT_FILL_BUFFER_THRESHOLD : \ + ((_Size) - (_Offset))) * sizeof(*(_String))); \ + } +#else /* _SECURECRT_FILL_BUFFER */ +#define _SECURECRT__FILL_STRING(_String, _Size, _Offset) +#endif /* _SECURECRT_FILL_BUFFER */ + +#if _SECURECRT_FILL_BUFFER +#define _SECURECRT__FILL_BYTE(_Position) \ + if (_SECURECRT_FILL_BUFFER_THRESHOLD > 0) \ + { \ + (_Position) = _SECURECRT_FILL_BUFFER_PATTERN; \ + } +#else /* _SECURECRT_FILL_BUFFER */ +#define _SECURECRT__FILL_BYTE(_Position) +#endif /* _SECURECRT_FILL_BUFFER */ + +#ifdef __cplusplus +#define _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE extern "C" +#else /* __cplusplus */ +#define _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE +#endif /* __cplusplus */ + +/* helper macros to redirect an mbs function to the corresponding _l version */ +#define _REDIRECT_TO_L_VERSION_1(_ReturnType, _FunctionName, _Type1) \ + _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE \ + _ReturnType __cdecl _FunctionName(_Type1 _Arg1) \ + { \ + return _FunctionName##_l(_Arg1, NULL); \ + } + +#define _REDIRECT_TO_L_VERSION_2(_ReturnType, _FunctionName, _Type1, _Type2) \ + _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE \ + _ReturnType __cdecl _FunctionName(_Type1 _Arg1, _Type2 _Arg2) \ + { \ + return _FunctionName##_l(_Arg1, _Arg2, NULL); \ + } + +#define _REDIRECT_TO_L_VERSION_3(_ReturnType, _FunctionName, _Type1, _Type2, _Type3) \ + _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE \ + _ReturnType __cdecl _FunctionName(_Type1 _Arg1, _Type2 _Arg2, _Type3 _Arg3) \ + { \ + return _FunctionName##_l(_Arg1, _Arg2, _Arg3, NULL); \ + } + +#define _REDIRECT_TO_L_VERSION_4(_ReturnType, _FunctionName, _Type1, _Type2, _Type3, _Type4) \ + _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE \ + _ReturnType __cdecl _FunctionName(_Type1 _Arg1, _Type2 _Arg2, _Type3 _Arg3, _Type4 _Arg4) \ + { \ + return _FunctionName##_l(_Arg1, _Arg2, _Arg3, _Arg4, NULL); \ + } + +#define _REDIRECT_TO_L_VERSION_5(_ReturnType, _FunctionName, _Type1, _Type2, _Type3, _Type4, _Type5) \ + _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE \ + _ReturnType __cdecl _FunctionName(_Type1 _Arg1, _Type2 _Arg2, _Type3 _Arg3, _Type4 _Arg4, _Type5 _Arg5) \ + { \ + return _FunctionName##_l(_Arg1, _Arg2, _Arg3, _Arg4, _Arg5, NULL); \ + } + +#define _REDIRECT_TO_L_VERSION_6(_ReturnType, _FunctionName, _Type1, _Type2, _Type3, _Type4, _Type5, _Type6) \ + _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE \ + _ReturnType __cdecl _FunctionName(_Type1 _Arg1, _Type2 _Arg2, _Type3 _Arg3, _Type4 _Arg4, _Type5 _Arg5, _Type6 _Arg6) \ + { \ + return _FunctionName##_l(_Arg1, _Arg2, _Arg3, _Arg4, _Arg5, _Arg6, NULL); \ + } + +/* internal helper functions for encoding and decoding pointers */ +void __cdecl _init_pointers(); +_CRTIMP void * __cdecl _encode_pointer(void *); +_CRTIMP void * __cdecl _encoded_null(); +_CRTIMP void * __cdecl _decode_pointer(void *); + +/* internal helper function for communicating with the debugger */ +BOOL DebuggerKnownHandle(); + +/* Macros to simplify the use of Secure CRT in the CRT itself. + * We should use [_BEGIN/_END]_SECURE_CRT_DEPRECATION_DISABLE sparingly. + */ +#define _BEGIN_SECURE_CRT_DEPRECATION_DISABLE \ + __pragma(warning(push)) \ + __pragma(warning(disable:4996)) + +#define _END_SECURE_CRT_DEPRECATION_DISABLE \ + __pragma(warning(pop)) + +#define _ERRCHECK(e) \ + _INVOKE_WATSON_IF_ERROR(e) + +#define _ERRCHECK_EINVAL(e) \ + _INVOKE_WATSON_IF_ONEOF(e, EINVAL, EINVAL) + +#define _ERRCHECK_EINVAL_ERANGE(e) \ + _INVOKE_WATSON_IF_ONEOF(e, EINVAL, ERANGE) + +#define _ERRCHECK_SPRINTF(_PrintfCall) \ + { \ + errno_t _SaveErrno = errno; \ + errno = 0; \ + if ( ( _PrintfCall ) < 0) \ + { \ + _ERRCHECK_EINVAL_ERANGE(errno); \ + } \ + errno = _SaveErrno; \ + } + +/* internal helper function to access environment variable in read-only mode */ +const char16_t * __cdecl _wgetenv_helper_nolock(const char16_t *); +const char * __cdecl _getenv_helper_nolock(const char *); + +/* internal helper routines used to query a PE image header. */ +BOOL __cdecl _ValidateImageBase(PBYTE pImageBase); +PIMAGE_SECTION_HEADER __cdecl _FindPESection(PBYTE pImageBase, DWORD_PTR rva); +BOOL __cdecl _IsNonwritableInCurrentImage(PBYTE pTarget); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#ifdef _MSC_VER +#pragma pack(pop) +#endif /* _MSC_VER */ + +#endif /* _INC_INTERNAL */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/internal_securecrt.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/internal_securecrt.h new file mode 100644 index 0000000..4d8be05 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/internal_securecrt.h @@ -0,0 +1,292 @@ +// 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. + +/*** +*internal_securecrt.h - contains declarations of internal routines and variables for securecrt +* + +* +*Purpose: +* Declares routines and variables used internally in the SecureCRT implementation. +* In this include file we define the macros needed to implement the secure functions +* inlined in the *.inl files like tcscpy_s.inl, etc. +* Note that this file is used for the CRT implementation, while internal_safecrt is used +* to build the downlevel library safecrt.lib. +* +* [Internal] +* +****/ + +#pragma once + +#ifndef _INC_INTERNAL_SECURECRT +#define _INC_INTERNAL_SECURECRT + +/* more VS specific goodness */ +#define __out_ecount_z( x ) +#define __out_ecount( x ) +#define __in_opt +#define __in_z_opt +#define __out_ecount_z_opt( x ) +#define __in_z +#define __in + +/* + * The original SafeCRT implemention allows runtime control over buffer checking. + * For now we'll key this off the debug flag. + */ +#ifdef _DEBUG + #define _CrtGetCheckCount() ((int)1) +#else + #define _CrtGetCheckCount() ((int)0) +#endif + +/* Assert message and Invalid parameter */ +#ifdef _DEBUG + #define _ASSERT_EXPR( val, exp ) \ + { \ + if ( ( val ) == 0 ) \ + { \ + if ( sMBUSafeCRTAssertFunc != NULL ) \ + { \ + ( *sMBUSafeCRTAssertFunc )( #exp, "SafeCRT assert failed", __FILE__, __LINE__ ); \ + } \ + } \ + } + #define _INVALID_PARAMETER( exp ) _ASSERT_EXPR( 0, exp ) + #define _ASSERTE( exp ) _ASSERT_EXPR( exp, exp ) +#else + #define _ASSERT_EXPR( val, expr ) + #define _INVALID_PARAMETER( exp ) + #define _ASSERTE( exp ) +#endif + +/* _TRUNCATE */ +#if !defined (_TRUNCATE) +#define _TRUNCATE ((size_t)-1) +#endif /* !defined (_TRUNCATE) */ + +/* #include */ + +#define _VALIDATE_RETURN_VOID( expr, errorcode ) \ + { \ + int _Expr_val=!!(expr); \ + _ASSERT_EXPR( ( _Expr_val ), #expr ); \ + if ( !( _Expr_val ) ) \ + { \ + errno = errorcode; \ + _INVALID_PARAMETER(#expr); \ + return; \ + } \ + } + +/* + * Assert in debug builds. + * set errno and return value + */ + +#ifndef _VALIDATE_RETURN +#define _VALIDATE_RETURN( expr, errorcode, retexpr ) \ + { \ + int _Expr_val=!!(expr); \ + _ASSERT_EXPR( ( _Expr_val ), #expr ); \ + if ( !( _Expr_val ) ) \ + { \ + errno = errorcode; \ + _INVALID_PARAMETER(#expr ); \ + return ( retexpr ); \ + } \ + } +#endif /* _VALIDATE_RETURN */ + +#ifndef _VALIDATE_RETURN_NOEXC +#define _VALIDATE_RETURN_NOEXC( expr, errorcode, retexpr ) \ + { \ + if ( !(expr) ) \ + { \ + errno = errorcode; \ + return ( retexpr ); \ + } \ + } +#endif /* _VALIDATE_RETURN_NOEXC */ + +/* + * Assert in debug builds. + * set errno and return errorcode + */ + +#define _VALIDATE_RETURN_ERRCODE( expr, errorcode ) \ + { \ + int _Expr_val=!!(expr); \ + _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ + if ( !( _Expr_val ) ) \ + { \ + errno = errorcode; \ + _INVALID_PARAMETER(_CRT_WIDE(#expr)); \ + return ( errorcode ); \ + } \ + } + +/* We completely fill the buffer only in debug (see _SECURECRT__FILL_STRING + * and _SECURECRT__FILL_BYTE macros). + */ +#if !defined (_SECURECRT_FILL_BUFFER) +#ifdef _DEBUG +#define _SECURECRT_FILL_BUFFER 1 +#else /* _DEBUG */ +#define _SECURECRT_FILL_BUFFER 0 +#endif /* _DEBUG */ +#endif /* !defined (_SECURECRT_FILL_BUFFER) */ + +/* _SECURECRT_FILL_BUFFER_PATTERN is the same as _bNoMansLandFill */ +#define _SECURECRT_FILL_BUFFER_PATTERN 0xFD + +#if !defined (_SECURECRT_FILL_BUFFER_THRESHOLD) +#ifdef _DEBUG +#define _SECURECRT_FILL_BUFFER_THRESHOLD ((size_t)8) +#else /* _DEBUG */ +#define _SECURECRT_FILL_BUFFER_THRESHOLD ((size_t)0) +#endif /* _DEBUG */ +#endif /* !defined (_SECURECRT_FILL_BUFFER_THRESHOLD) */ + +#if _SECURECRT_FILL_BUFFER +#define _SECURECRT__FILL_STRING(_String, _Size, _Offset) \ + if ((_Size) != ((size_t)-1) && (_Size) != INT_MAX && \ + ((size_t)(_Offset)) < (_Size)) \ + { \ + memset((_String) + (_Offset), \ + _SECURECRT_FILL_BUFFER_PATTERN, \ + (_SECURECRT_FILL_BUFFER_THRESHOLD < ((size_t)((_Size) - (_Offset))) ? \ + _SECURECRT_FILL_BUFFER_THRESHOLD : \ + ((_Size) - (_Offset))) * sizeof(*(_String))); \ + } +#else /* _SECURECRT_FILL_BUFFER */ +#define _SECURECRT__FILL_STRING(_String, _Size, _Offset) +#endif /* _SECURECRT_FILL_BUFFER */ + +#if _SECURECRT_FILL_BUFFER +#define _SECURECRT__FILL_BYTE(_Position) \ + if (_SECURECRT_FILL_BUFFER_THRESHOLD > 0) \ + { \ + (_Position) = _SECURECRT_FILL_BUFFER_PATTERN; \ + } +#else /* _SECURECRT_FILL_BUFFER */ +#define _SECURECRT__FILL_BYTE(_Position) +#endif /* _SECURECRT_FILL_BUFFER */ + +/* string resetting */ +#define _FILL_STRING _SECURECRT__FILL_STRING + +#define _FILL_BYTE _SECURECRT__FILL_BYTE + +#define _RESET_STRING(_String, _Size) \ + { \ + *(_String) = 0; \ + _FILL_STRING((_String), (_Size), 1); \ + } + +/* validations */ +#define _VALIDATE_STRING_ERROR(_String, _Size, _Ret) \ + _VALIDATE_RETURN((_String) != NULL && (_Size) > 0, EINVAL, (_Ret)) + +#define _VALIDATE_STRING(_String, _Size) \ + _VALIDATE_STRING_ERROR((_String), (_Size), EINVAL) + +#define _VALIDATE_POINTER_ERROR_RETURN(_Pointer, _ErrorCode, _Ret) \ + _VALIDATE_RETURN((_Pointer) != NULL, (_ErrorCode), (_Ret)) + +#define _VALIDATE_POINTER_ERROR(_Pointer, _Ret) \ + _VALIDATE_POINTER_ERROR_RETURN((_Pointer), EINVAL, (_Ret)) + +#define _VALIDATE_POINTER(_Pointer) \ + _VALIDATE_POINTER_ERROR((_Pointer), EINVAL) + +#define _VALIDATE_CONDITION_ERROR_RETURN(_Condition, _ErrorCode, _Ret) \ + _VALIDATE_RETURN((_Condition), (_ErrorCode), (_Ret)) + +#define _VALIDATE_CONDITION_ERROR(_Condition, _Ret) \ + _VALIDATE_CONDITION_ERROR_RETURN((_Condition), EINVAL, (_Ret)) + +#define _VALIDATE_POINTER_RESET_STRING_ERROR(_Pointer, _String, _Size, _Ret) \ + if ((_Pointer) == NULL) \ + { \ + _RESET_STRING((_String), (_Size)); \ + _VALIDATE_POINTER_ERROR_RETURN((_Pointer), EINVAL, (_Ret)) \ + } + +#define _VALIDATE_POINTER_RESET_STRING(_Pointer, _String, _Size) \ + _VALIDATE_POINTER_RESET_STRING_ERROR((_Pointer), (_String), (_Size), EINVAL) + +#define _RETURN_BUFFER_TOO_SMALL_ERROR(_String, _Size, _Ret) \ + _VALIDATE_RETURN(("Buffer is too small" && 0), ERANGE, _Ret) + +#define _RETURN_BUFFER_TOO_SMALL(_String, _Size) \ + _RETURN_BUFFER_TOO_SMALL_ERROR((_String), (_Size), ERANGE) + +#define _RETURN_DEST_NOT_NULL_TERMINATED(_String, _Size) \ + _VALIDATE_RETURN(("String is not null terminated" && 0), EINVAL, EINVAL) + +#define _RETURN_EINVAL \ + _VALIDATE_RETURN(("Invalid parameter" && 0), EINVAL, EINVAL) + +#define _RETURN_ERROR(_Msg, _Ret) \ + _VALIDATE_RETURN(((_Msg), 0), EINVAL, _Ret) + +/* returns without calling _invalid_parameter */ +#define _RETURN_NO_ERROR \ + return 0 + +/* Note that _RETURN_TRUNCATE does not set errno */ +#define _RETURN_TRUNCATE \ + return STRUNCATE + +#define _SET_MBCS_ERROR \ + (errno = EILSEQ) + +#define _RETURN_MBCS_ERROR \ + return _SET_MBCS_ERROR + +/* locale dependent */ +#define _LOCALE_ARG \ + _LocInfo + +#define _LOCALE_ARG_DECL \ + _locale_t _LOCALE_ARG + +#define _LOCALE_UPDATE \ + _LocaleUpdate _LocUpdate(_LOCALE_ARG) + +#define _ISMBBLEAD(_Character) \ + _ismbblead_l((_Character), _LocUpdate.GetLocaleT()) + +#define _MBSDEC(_String, _Current) \ + _mbsdec((_String), (_Current)) + +#define _ISMBBLEADPREFIX(_Result, _StringStart, _BytePtr) \ + { \ + unsigned char *_Tmp_VAR, *_StringStart_VAR, *_BytePtr_VAR; \ + \ + _StringStart_VAR = (_StringStart); \ + _BytePtr_VAR = (_BytePtr); \ + _Tmp_VAR = _BytePtr_VAR; \ + while ((_Tmp_VAR >= _StringStart_VAR) && _ISMBBLEAD(*_Tmp_VAR)) \ + { \ + _Tmp_VAR--; \ + } \ + (_Result) = ((_BytePtr_VAR - _Tmp_VAR) & 1) != 0; \ + } + +#define _LOCALE_SHORTCUT_TEST \ + _LocUpdate.GetLocaleT()->mbcinfo->ismbcodepage == 0 + +#define _USE_LOCALE_ARG 1 + +/* misc */ +#define _ASSIGN_IF_NOT_NULL(_Pointer, _Value) \ + if ((_Pointer) != NULL) \ + { \ + *(_Pointer) = (_Value); \ + } + +#endif /* _INC_INTERNAL_SECURECRT */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/makepath_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/makepath_s.cpp new file mode 100644 index 0000000..4342685 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/makepath_s.cpp @@ -0,0 +1,31 @@ +// 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. + +/*** +*makepath_s.c - create path name from components +* + +* +*Purpose: +* To provide support for creation of full path names from components +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _FUNC_PROLOGUE +#define _FUNC_NAME _makepath_s +#define _CHAR char +#define _DEST _Dst +#define _SIZE _SizeInBytes +#define _T(_Character) _Character + +#define _MBS_SUPPORT 0 + +#include "tmakepath_s.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/mbusafecrt.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/mbusafecrt.cpp new file mode 100644 index 0000000..82bc08a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/mbusafecrt.cpp @@ -0,0 +1,249 @@ +// 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. + +/*** +* mbusafecrt.c - implementaion of support functions and data for MBUSafeCRT +* + +* +* Purpose: +* This file contains the implementation of support functions and +* data for MBUSafeCRT declared in mbusafecrt.h and mbusafecrt_internal.h. +****/ + +#include "pal/palinternal.h" +#include +#include +#include + +#include "mbusafecrt_internal.h" + +/* global data */ +tSafeCRT_AssertFuncPtr sMBUSafeCRTAssertFunc = NULL; + +/*** +* MBUSafeCRTSetAssertFunc - Set the function called when an assert fails. +****/ + +void MBUSafeCRTSetAssertFunc( tSafeCRT_AssertFuncPtr inAssertFuncPtr ) +{ + /* set it */ + sMBUSafeCRTAssertFunc = inAssertFuncPtr; +} + +/*** +* _putc_nolock - putc for the miniFILE stream. +****/ + +int _putc_nolock( char inChar, miniFILE* inStream ) +{ + int returnValue = EOF; + + inStream->_cnt -= sizeof( char ); + + if ( ( inStream->_cnt ) >= 0 ) + { + *( inStream->_ptr ) = inChar; + inStream->_ptr += sizeof( char ); + returnValue = ( int )inChar; + } + + return returnValue; +} + +/*** +* _putwc_nolock - putwc for the miniFILE stream. +****/ + +int _putwc_nolock( char16_t inChar, miniFILE* inStream ) +{ + int returnValue = WEOF; + + inStream->_cnt -= sizeof( char16_t ); + + if ( ( inStream->_cnt ) >= 0 ) + { + *( ( char16_t* )( inStream->_ptr ) ) = inChar; + inStream->_ptr += sizeof( char16_t ); + returnValue = ( int )inChar; + } + + return returnValue; +} + +/*** +* _getc_nolock - getc for the miniFILE stream. +****/ + +int _getc_nolock( miniFILE* inStream ) +{ + int returnValue = EOF; + + if ( ( inStream->_cnt ) >= ( int )( sizeof( char ) ) ) + { + inStream->_cnt -= sizeof( char ); + returnValue = ( int )( *( inStream->_ptr ) ); + inStream->_ptr += sizeof( char ); + } + + return returnValue; +} + +/*** +* _getwc_nolock - getc for the miniFILE stream. +****/ + +int _getwc_nolock( miniFILE* inStream ) +{ + int returnValue = EOF; + + if ( ( inStream->_cnt ) >= ( int )( sizeof( char16_t ) ) ) + { + inStream->_cnt -= sizeof( char16_t ); + returnValue = ( int )( *( ( char16_t* )( inStream->_ptr ) ) ); + inStream->_ptr += sizeof( char16_t ); + } + + return returnValue; +} + +/*** +* _ungetc_nolock - ungetc for the miniFILE stream. +****/ + +int _ungetc_nolock( char inChar, miniFILE* inStream ) +{ + int returnValue = EOF; + + if ( ( size_t )( ( inStream->_ptr ) - ( inStream->_base ) ) >= ( sizeof( char ) ) ) + { + inStream->_cnt += sizeof( char ); + inStream->_ptr -= sizeof( char ); + return ( int )inChar; + } + + return returnValue; +} + +/*** +* _ungetwc_nolock - ungetwc for the miniFILE stream. +****/ + +int _ungetwc_nolock( char16_t inChar, miniFILE* inStream ) +{ + int returnValue = WEOF; + + if ( ( size_t )( ( inStream->_ptr ) - ( inStream->_base ) ) >= ( sizeof( char16_t ) ) ) + { + inStream->_cnt += sizeof( char16_t ); + inStream->_ptr -= sizeof( char16_t ); + returnValue = ( unsigned short )inChar; + } + + return returnValue; +} + + +/*** +* _safecrt_cfltcvt - convert a float to an ascii string. +****/ + +/* routine used for floating-point output */ +#define FORMATSIZE 30 + +// taken from output.inl +#define FL_ALTERNATE 0x00080 /* alternate form requested */ + +errno_t _safecrt_cfltcvt(double *arg, char *buffer, size_t sizeInBytes, int type, int precision, int flags) +{ + char format[FORMATSIZE]; + size_t formatlen = 0; + int retvalue; + + if (flags & 1) + { + type -= 'a' - 'A'; + } + formatlen = 0; + format[formatlen++] = '%'; + if (flags & FL_ALTERNATE) + { + format[formatlen++] = '#'; + } + format[formatlen++] = '.'; + _itoa_s(precision, format + formatlen, FORMATSIZE - formatlen, 10); + formatlen = strlen(format); + format[formatlen++] = (char)type; + format[formatlen] = 0; + + buffer[sizeInBytes - 1] = 0; + retvalue = snprintf(buffer, sizeInBytes, format, *arg); + if (buffer[sizeInBytes - 1] != 0 || retvalue <= 0) + { + buffer[0] = 0; + return EINVAL; + } + return 0; +} + + +/*** +* _safecrt_fassign - convert a string into a float or double. +****/ + +void _safecrt_fassign(int flag, void* argument, char* number ) +{ + if ( flag != 0 ) // double + { + double dblValue = strtod(number, NULL); + *( ( double* )argument ) = dblValue; + } + else // float + { + float fltValue = strtof(number, NULL); + *( ( float* )argument ) = fltValue; + } +} + + +/*** +* _safecrt_wfassign - convert a char16_t string into a float or double. +****/ + +void _safecrt_wfassign(int flag, void* argument, char16_t* number ) +{ + // We cannot use system functions for this - they + // assume that char16_t is four bytes, while we assume + // two. So, we need to convert to a regular char string + // without using any system functions. To do this, + // we'll assume that the numbers are in the 0-9 range and + // do a simple conversion. + + char* numberAsChars = ( char* )number; + int position = 0; + + // do the convert + while ( number[ position ] != 0 ) + { + numberAsChars[ position ] = ( char )( number[ position ] & 0x00FF ); + position++; + } + numberAsChars[ position ] = ( char )( number[ position ] & 0x00FF ); + + // call the normal char version + _safecrt_fassign( flag, argument, numberAsChars ); +} + + +/*** +* _minimal_chartowchar - do a simple char to wchar conversion. +****/ + +int _minimal_chartowchar( char16_t* outWChar, const char* inChar ) +{ + *outWChar = ( char16_t )( ( unsigned short )( ( unsigned char )( *inChar ) ) ); + return 1; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/mbusafecrt_internal.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/mbusafecrt_internal.h new file mode 100644 index 0000000..4f9ee5f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/mbusafecrt_internal.h @@ -0,0 +1,98 @@ +// 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. + +/*** +* mbusafecrt_internal.h - internal declarations for SafeCRT functions +* + +* +* Purpose: +* This file contains the internal declarations SafeCRT +* functions ported to MacOS. These are the safe versions of +* functions standard functions banned by SWI +****/ + +/* shields! */ + +#ifndef MBUSAFECRT_INTERNAL_H +#define MBUSAFECRT_INTERNAL_H + +#define PAL_IMPLEMENTATION + +#include "pal_mstypes.h" + +#ifndef DLLEXPORT +#ifdef _MSC_VER +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT __attribute__ ((visibility ("default"))) +#endif // _MSC_VER +#endif // !DLLEXPORT + +typedef __builtin_va_list va_list; + +// The ifdef below are to accommodate Unix build +// that complains about them being declared in stdarg.h already. +#ifndef va_start +#define va_start __builtin_va_start +#endif +#ifndef va_end +#define va_end __builtin_va_end +#endif + +#include "mbusafecrt.h" + +#ifdef EOF +#undef EOF +#endif +#define EOF -1 + +#ifdef WEOF +#undef WEOF +#endif +#define WEOF -1 + +#define CASSERT(p) extern int sanity_check_dummy[1+((!(p))*(-2))]; + +extern tSafeCRT_AssertFuncPtr sMBUSafeCRTAssertFunc; + +typedef struct miniFILE_struct +{ + char* _ptr; + int _cnt; + char* _base; + int _flag; +} miniFILE; + +#undef _IOWRT +#undef _IOREAD +#undef _IOMYBUF + +#define _IOSTRG 1 +#define _IOWRT 2 +#define _IOREAD 4 +#define _IOMYBUF 8 + +int _putc_nolock( char inChar, miniFILE* inStream ); +int _putwc_nolock( char16_t inChar, miniFILE* inStream ); +int _getc_nolock( miniFILE* inStream ); +int _getwc_nolock( miniFILE* inStream ); +int _ungetc_nolock( char inChar, miniFILE* inStream ); +int _ungetwc_nolock( char16_t inChar, miniFILE* inStream ); + +errno_t _safecrt_cfltcvt(double *arg, char *buffer, size_t sizeInBytes, int type, int precision, int flags); + +void _safecrt_fassign(int flag, void* argument, char * number ); +void _safecrt_wfassign(int flag, void* argument, char16_t * number ); + +int _minimal_chartowchar( char16_t* outWChar, const char* inChar ); + +int _output_s( miniFILE* outfile, const char* _Format, va_list _ArgList); +int _woutput_s( miniFILE* outfile, const char16_t* _Format, va_list _ArgList); +int _output( miniFILE *outfile, const char* _Format, va_list _ArgList); + +int __tinput_s( miniFILE* inFile, const unsigned char * inFormat, va_list inArgList ); +int __twinput_s( miniFILE* inFile, const char16_t * inFormat, va_list inArgList ); + +#endif /* MBUSAFECRT_INTERNAL_H */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/memcpy_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/memcpy_s.cpp new file mode 100644 index 0000000..db3bb5f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/memcpy_s.cpp @@ -0,0 +1,82 @@ +// 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. + +/*** +*memcpy_s.c - contains memcpy_s routine +* + +* +*Purpose: +* memcpy_s() copies a source memory buffer to a destination buffer. +* Overlapping buffers are not treated specially, so propagation may occur. +* +*Revision History: +* 10-07-03 AC Module created. +* 03-10-04 AC Return ERANGE when buffer is too small +* 01-14-05 AC Prefast (espx) fixes +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" +#include "mbusafecrt_internal.h" + +/*** +*memcpy_s - Copy source buffer to destination buffer +* +*Purpose: +* memcpy_s() copies a source memory buffer to a destination memory buffer. +* This routine does NOT recognize overlapping buffers, and thus can lead +* to propagation. +* +* For cases where propagation must be avoided, memmove_s() must be used. +* +*Entry: +* void *dst = pointer to destination buffer +* size_t sizeInBytes = size in bytes of the destination buffer +* const void *src = pointer to source buffer +* size_t count = number of bytes to copy +* +*Exit: +* Returns 0 if everything is ok, else return the error code. +* +*Exceptions: +* Input parameters are validated. Refer to the validation section of the function. +* On error, the error code is returned and the destination buffer is zeroed. +* +*******************************************************************************/ + +DLLEXPORT errno_t __cdecl memcpy_s( + void * dst, + size_t sizeInBytes, + const void * src, + size_t count +) THROW_DECL +{ + if (count == 0) + { + /* nothing to do */ + return 0; + } + + /* validation section */ + _VALIDATE_RETURN_ERRCODE(dst != NULL, EINVAL); + if (src == NULL || sizeInBytes < count) + { + /* zeroes the destination buffer */ + memset(dst, 0, sizeInBytes); + + _VALIDATE_RETURN_ERRCODE(src != NULL, EINVAL); + _VALIDATE_RETURN_ERRCODE(sizeInBytes >= count, ERANGE); + /* useless, but prefast is confused */ + return EINVAL; + } + + UINT_PTR x = (UINT_PTR)dst, y = (UINT_PTR)src; + assert((x + count <= y) || (y + count <= x)); + memcpy(dst, src, count); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/memmove_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/memmove_s.cpp new file mode 100644 index 0000000..a0ae5f7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/memmove_s.cpp @@ -0,0 +1,69 @@ +// 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. + +/*** +*memmove_s.c - contains memmove_s routine +* + +* +*Purpose: +* memmove_s() copies a source memory buffer to a destination buffer. +* Overlapping buffers are treated specially, to avoid propagation. +* +*Revision History: +* 10-07-03 AC Module created. +* 03-10-04 AC Return ERANGE when buffer is too small +* +*******************************************************************************/ + +#include +#include +#include "internal_securecrt.h" +#include "mbusafecrt_internal.h" + +/*** +*memmove - Copy source buffer to destination buffer +* +*Purpose: +* memmove() copies a source memory buffer to a destination memory buffer. +* This routine recognize overlapping buffers to avoid propagation. +* +* For cases where propagation is not a problem, memcpy_s() can be used. +* +*Entry: +* void *dst = pointer to destination buffer +* size_t sizeInBytes = size in bytes of the destination buffer +* const void *src = pointer to source buffer +* size_t count = number of bytes to copy +* +*Exit: +* Returns 0 if everything is ok, else return the error code. +* +*Exceptions: +* Input parameters are validated. Refer to the validation section of the function. +* On error, the error code is returned. Nothing is written to the destination buffer. +* +*******************************************************************************/ + +errno_t __cdecl memmove_s( + void * dst, + size_t sizeInBytes, + const void * src, + size_t count +) +{ + if (count == 0) + { + /* nothing to do */ + return 0; + } + + /* validation section */ + _VALIDATE_RETURN_ERRCODE(dst != NULL, EINVAL); + _VALIDATE_RETURN_ERRCODE(src != NULL, EINVAL); + _VALIDATE_RETURN_ERRCODE(sizeInBytes >= count, ERANGE); + + memmove(dst, src, count); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/output.inl b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/output.inl new file mode 100644 index 0000000..cab3a80 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/output.inl @@ -0,0 +1,1575 @@ +// 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. + +/*** +*output.c - printf style output to a FILE +* + +* +*Purpose: +* This file contains the code that does all the work for the +* printf family of functions. It should not be called directly, only +* by the *printf functions. We don't make any assumtions about the +* sizes of ints, longs, shorts, or long doubles, but if types do overlap, +* we also try to be efficient. We do assume that pointers are the same +* size as either ints or longs. +* If CPRFLAG is defined, defines _cprintf instead. +* **** DOESN'T CURRENTLY DO MTHREAD LOCKING **** +* +*Note: +* this file is included in safecrt.lib build directly, plese refer +* to safecrt_[w]output_s.c +* +*******************************************************************************/ + + +//typedef __int64_t __int64; + + +#define FORMAT_VALIDATIONS + +typedef double _CRT_DOUBLE; + +//typedef int* intptr_t; + +/* +Buffer size required to be passed to _gcvt, fcvt and other fp conversion routines +*/ +#define _CVTBUFSIZE (309+40) /* # of digits in max. dp value + slop */ + +/* temporary work-around for compiler without 64-bit support */ +#ifndef _INTEGRAL_MAX_BITS +#define _INTEGRAL_MAX_BITS 64 +#endif /* _INTEGRAL_MAX_BITS */ + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#define _MBTOWC(x,y,z) _minimal_chartowchar( x, y ) + +#ifndef _WCTOMB_S +#define _WCTOMB_S wctomb_s +#endif /* _WCTOMB_S */ + +#undef _malloc_crt +#define _malloc_crt malloc + +#undef _free_crt +#define _free_crt free + +#ifndef _CFLTCVT +#define _CFLTCVT _cfltcvt +#endif /* _CFLTCVT */ + +#ifndef _CLDCVT +#define _CLDCVT _cldcvt +#endif /* _CLDCVT */ + +#ifdef _MBCS +#undef _MBCS +#endif /* _MBCS */ +//#include + +/* this macro defines a function which is private and as fast as possible: */ +/* for example, in C 6.0, it might be static _fastcall near. */ +#define LOCAL(x) static x __cdecl + +/* int/long/short/pointer sizes */ + +/* the following should be set depending on the sizes of various types */ +#if __LP64__ + #define LONG_IS_INT 0 + CASSERT(sizeof(long) > sizeof(int)); +#else + #define LONG_IS_INT 1 /* 1 means long is same size as int */ + CASSERT(sizeof(long) == sizeof(int)); +#endif + +#define SHORT_IS_INT 0 /* 1 means short is same size as int */ +#define LONGLONG_IS_INT64 1 /* 1 means long long is same as int64 */ +#if defined (HOST_64BIT) + #define PTR_IS_INT 0 /* 1 means ptr is same size as int */ + CASSERT(sizeof(void *) != sizeof(int)); + #if __LP64__ + #define PTR_IS_LONG 1 /* 1 means ptr is same size as long */ + CASSERT(sizeof(void *) == sizeof(long)); + #else + #define PTR_IS_LONG 0 /* 1 means ptr is same size as long */ + CASSERT(sizeof(void *) != sizeof(long)); + #endif + #define PTR_IS_INT64 1 /* 1 means ptr is same size as int64 */ + CASSERT(sizeof(void *) == sizeof(int64_t)); +#else /* defined (HOST_64BIT) */ + #define PTR_IS_INT 1 /* 1 means ptr is same size as int */ + CASSERT(sizeof(void *) == sizeof(int)); + #define PTR_IS_LONG 1 /* 1 means ptr is same size as long */ + CASSERT(sizeof(void *) == sizeof(long)); + #define PTR_IS_INT64 0 /* 1 means ptr is same size as int64 */ + CASSERT(sizeof(void *) != sizeof(int64_t)); +#endif /* defined (HOST_64BIT) */ + +/* CONSTANTS */ + +/* size of conversion buffer (ANSI-specified minimum is 509) */ + +#define BUFFERSIZE 512 +#define MAXPRECISION BUFFERSIZE + +#if BUFFERSIZE < _CVTBUFSIZE + 6 +/* + * Buffer needs to be big enough for default minimum precision + * when converting floating point needs bigger buffer, and malloc + * fails + */ +#error Conversion buffer too small for max double. +#endif /* BUFFERSIZE < _CVTBUFSIZE + 6 */ + +/* flag definitions */ +#define FL_SIGN 0x00001 /* put plus or minus in front */ +#define FL_SIGNSP 0x00002 /* put space or minus in front */ +#define FL_LEFT 0x00004 /* left justify */ +#define FL_LEADZERO 0x00008 /* pad with leading zeros */ +#define FL_LONG 0x00010 /* long value given */ +#define FL_SHORT 0x00020 /* short value given */ +#define FL_SIGNED 0x00040 /* signed data given */ +#define FL_ALTERNATE 0x00080 /* alternate form requested */ +#define FL_NEGATIVE 0x00100 /* value is negative */ +#define FL_FORCEOCTAL 0x00200 /* force leading '0' for octals */ +#define FL_LONGDOUBLE 0x00400 /* long double value given */ +#define FL_WIDECHAR 0x00800 /* wide characters */ +#define FL_LONGLONG 0x01000 /* long long value given */ +#define FL_I64 0x08000 /* __int64 value given */ + +/* state definitions */ +enum STATE { + ST_NORMAL, /* normal state; outputting literal chars */ + ST_PERCENT, /* just read '%' */ + ST_FLAG, /* just read flag character */ + ST_WIDTH, /* just read width specifier */ + ST_DOT, /* just read '.' */ + ST_PRECIS, /* just read precision specifier */ + ST_SIZE, /* just read size specifier */ + ST_TYPE /* just read type specifier */ +#ifdef FORMAT_VALIDATIONS + ,ST_INVALID /* Invalid format */ +#endif /* FORMAT_VALIDATIONS */ + +}; + +#ifdef FORMAT_VALIDATIONS +#define NUMSTATES (ST_INVALID + 1) +#else /* FORMAT_VALIDATIONS */ +#define NUMSTATES (ST_TYPE + 1) +#endif /* FORMAT_VALIDATIONS */ + +/* character type values */ +enum CHARTYPE { + CH_OTHER, /* character with no special meaning */ + CH_PERCENT, /* '%' */ + CH_DOT, /* '.' */ + CH_STAR, /* '*' */ + CH_ZERO, /* '0' */ + CH_DIGIT, /* '1'..'9' */ + CH_FLAG, /* ' ', '+', '-', '#' */ + CH_SIZE, /* 'h', 'l', 'L', 'N', 'F', 'w' */ + CH_TYPE /* type specifying character */ +}; + +/* static data (read only, since we are re-entrant) */ +//#if defined (_UNICODE) || defined (CPRFLAG) || defined (FORMAT_VALIDATIONS) +//extern const char __nullstring[]; /* string to print on null ptr */ +//extern const char16_t __wnullstring[]; /* string to print on null ptr */ +//#else /* defined (_UNICODE) || defined (CPRFLAG) || defined (FORMAT_VALIDATIONS) */ +static const char __nullstring[] = "(null)"; /* string to print on null ptr */ +static const char16_t __wnullstring[] = {'(', 'n', 'u', 'l', 'l', ')', '\0'};/* string to print on null ptr */ +//#endif /* defined (_UNICODE) || defined (CPRFLAG) || defined (FORMAT_VALIDATIONS) */ + +/* The state table. This table is actually two tables combined into one. */ +/* The lower nybble of each byte gives the character class of any */ +/* character; while the uper nybble of the byte gives the next state */ +/* to enter. See the macros below the table for details. */ +/* */ +/* The table is generated by maketabc.c -- use this program to make */ +/* changes. */ + +#ifndef FORMAT_VALIDATIONS + +//#if defined (_UNICODE) || defined (CPRFLAG) +//extern const char __lookuptable[]; +//#else /* defined (_UNICODE) || defined (CPRFLAG) */ +extern const char __lookuptable[] = { + /* ' ' */ 0x06, + /* '!' */ 0x00, + /* '"' */ 0x00, + /* '#' */ 0x06, + /* '$' */ 0x00, + /* '%' */ 0x01, + /* '&' */ 0x00, + /* ''' */ 0x00, + /* '(' */ 0x10, + /* ')' */ 0x00, + /* '*' */ 0x03, + /* '+' */ 0x06, + /* ',' */ 0x00, + /* '-' */ 0x06, + /* '.' */ 0x02, + /* '/' */ 0x10, + /* '0' */ 0x04, + /* '1' */ 0x45, + /* '2' */ 0x45, + /* '3' */ 0x45, + /* '4' */ 0x05, + /* '5' */ 0x05, + /* '6' */ 0x05, + /* '7' */ 0x05, + /* '8' */ 0x05, + /* '9' */ 0x35, + /* ':' */ 0x30, + /* ';' */ 0x00, + /* '<' */ 0x50, + /* '=' */ 0x00, + /* '>' */ 0x00, + /* '?' */ 0x00, + /* '@' */ 0x00, + /* 'A' */ 0x20, // Disable %A format + /* 'B' */ 0x20, + /* 'C' */ 0x38, + /* 'D' */ 0x50, + /* 'E' */ 0x58, + /* 'F' */ 0x07, + /* 'G' */ 0x08, + /* 'H' */ 0x00, + /* 'I' */ 0x37, + /* 'J' */ 0x30, + /* 'K' */ 0x30, + /* 'L' */ 0x57, + /* 'M' */ 0x50, + /* 'N' */ 0x07, + /* 'O' */ 0x00, + /* 'P' */ 0x00, + /* 'Q' */ 0x20, + /* 'R' */ 0x20, + /* 'S' */ 0x08, + /* 'T' */ 0x00, + /* 'U' */ 0x00, + /* 'V' */ 0x00, + /* 'W' */ 0x00, + /* 'X' */ 0x08, + /* 'Y' */ 0x60, + /* 'Z' */ 0x68, + /* '[' */ 0x60, + /* '\' */ 0x60, + /* ']' */ 0x60, + /* '^' */ 0x60, + /* '_' */ 0x00, + /* '`' */ 0x00, + /* 'a' */ 0x70, // Disable %a format + /* 'b' */ 0x70, + /* 'c' */ 0x78, + /* 'd' */ 0x78, + /* 'e' */ 0x78, + /* 'f' */ 0x78, + /* 'g' */ 0x08, + /* 'h' */ 0x07, + /* 'i' */ 0x08, + /* 'j' */ 0x00, + /* 'k' */ 0x00, + /* 'l' */ 0x07, + /* 'm' */ 0x00, + /* 'n' */ 0x00, // Disable %n format + /* 'o' */ 0x08, + /* 'p' */ 0x08, + /* 'q' */ 0x00, + /* 'r' */ 0x00, + /* 's' */ 0x08, + /* 't' */ 0x00, + /* 'u' */ 0x08, + /* 'v' */ 0x00, + /* 'w' */ 0x07, + /* 'x' */ 0x08 +}; + +//#endif /* defined (_UNICODE) || defined (CPRFLAG) */ + +#else /* FORMAT_VALIDATIONS */ + +//#if defined (_UNICODE) || defined (CPRFLAG) +//extern const unsigned char __lookuptable_s[]; +//#else /* defined (_UNICODE) || defined (CPRFLAG) */ +static const unsigned char __lookuptable_s[] = { + /* ' ' */ 0x06, + /* '!' */ 0x80, + /* '"' */ 0x80, + /* '#' */ 0x86, + /* '$' */ 0x80, + /* '%' */ 0x81, + /* '&' */ 0x80, + /* ''' */ 0x00, + /* '(' */ 0x00, + /* ')' */ 0x10, + /* '*' */ 0x03, + /* '+' */ 0x86, + /* ',' */ 0x80, + /* '-' */ 0x86, + /* '.' */ 0x82, + /* '/' */ 0x80, + /* '0' */ 0x14, + /* '1' */ 0x05, + /* '2' */ 0x05, + /* '3' */ 0x45, + /* '4' */ 0x45, + /* '5' */ 0x45, + /* '6' */ 0x85, + /* '7' */ 0x85, + /* '8' */ 0x85, + /* '9' */ 0x05, + /* ':' */ 0x00, + /* ';' */ 0x00, + /* '<' */ 0x30, + /* '=' */ 0x30, + /* '>' */ 0x80, + /* '?' */ 0x50, + /* '@' */ 0x80, + /* 'A' */ 0x80, // Disable %A format + /* 'B' */ 0x00, + /* 'C' */ 0x08, + /* 'D' */ 0x00, + /* 'E' */ 0x28, + /* 'F' */ 0x27, + /* 'G' */ 0x38, + /* 'H' */ 0x50, + /* 'I' */ 0x57, + /* 'J' */ 0x80, + /* 'K' */ 0x00, + /* 'L' */ 0x07, + /* 'M' */ 0x00, + /* 'N' */ 0x37, + /* 'O' */ 0x30, + /* 'P' */ 0x30, + /* 'Q' */ 0x50, + /* 'R' */ 0x50, + /* 'S' */ 0x88, + /* 'T' */ 0x00, + /* 'U' */ 0x00, + /* 'V' */ 0x00, + /* 'W' */ 0x20, + /* 'X' */ 0x28, + /* 'Y' */ 0x80, + /* 'Z' */ 0x88, + /* '[' */ 0x80, + /* '\' */ 0x80, + /* ']' */ 0x00, + /* '^' */ 0x00, + /* '_' */ 0x00, + /* '`' */ 0x60, + /* 'a' */ 0x60, // Disable %a format + /* 'b' */ 0x60, + /* 'c' */ 0x68, + /* 'd' */ 0x68, + /* 'e' */ 0x68, + /* 'f' */ 0x08, + /* 'g' */ 0x08, + /* 'h' */ 0x07, + /* 'i' */ 0x78, + /* 'j' */ 0x70, + /* 'k' */ 0x70, + /* 'l' */ 0x77, + /* 'm' */ 0x70, + /* 'n' */ 0x70, + /* 'o' */ 0x08, + /* 'p' */ 0x08, + /* 'q' */ 0x00, + /* 'r' */ 0x00, + /* 's' */ 0x08, + /* 't' */ 0x00, + /* 'u' */ 0x08, + /* 'v' */ 0x00, + /* 'w' */ 0x07, + /* 'x' */ 0x08 +}; +//#endif /* defined (_UNICODE) || defined (CPRFLAG) */ + +#endif /* FORMAT_VALIDATIONS */ + +#define FIND_CHAR_CLASS(lookuptbl, c) \ + ((c) < _T(' ') || (c) > _T('x') ? \ + CH_OTHER \ + : \ + (enum CHARTYPE)(lookuptbl[(c)-_T(' ')] & 0xF)) + +#define FIND_NEXT_STATE(lookuptbl, class, state) \ + (enum STATE)(lookuptbl[(class) * NUMSTATES + (state)] >> 4) + +/* + * Note: CPRFLAG and _UNICODE cases are currently mutually exclusive. + */ + +/* prototypes */ + +#ifdef CPRFLAG + +#define WRITE_CHAR(ch, pnw) write_char(ch, pnw) +#define WRITE_MULTI_CHAR(ch, num, pnw) write_multi_char(ch, num, pnw) +#define WRITE_STRING(s, len, pnw) write_string(s, len, pnw) + +LOCAL(void) write_char(_TCHAR ch, int *pnumwritten); +LOCAL(void) write_multi_char(_TCHAR ch, int num, int *pnumwritten); +LOCAL(void) write_string(const _TCHAR *string, int len, int *numwritten); + +#else /* CPRFLAG */ + +#define WRITE_CHAR(ch, pnw) write_char(ch, stream, pnw) +#define WRITE_MULTI_CHAR(ch, num, pnw) write_multi_char(ch, num, stream, pnw) +#define WRITE_STRING(s, len, pnw) write_string(s, len, stream, pnw) + +LOCAL(void) write_char(_TCHAR ch, miniFILE *f, int *pnumwritten); +LOCAL(void) write_multi_char(_TCHAR ch, int num, miniFILE *f, int *pnumwritten); +LOCAL(void) write_string(const _TCHAR *string, int len, miniFILE *f, int *numwritten); + +#endif /* CPRFLAG */ + +#define get_int_arg(list) va_arg(*list, int) +#define get_long_arg(list) va_arg(*list, long) +#define get_long_long_arg(list) va_arg(*list, long long) +#define get_int64_arg(list) va_arg(*list, __int64) +#define get_crtdouble_arg(list) va_arg(*list, _CRT_DOUBLE) +#define get_ptr_arg(list) va_arg(*list, void *) + +#ifdef CPRFLAG +LOCAL(int) output(const _TCHAR *, _locale_t , va_list); +_CRTIMP int __cdecl _vtcprintf_l (const _TCHAR *, _locale_t, va_list); +_CRTIMP int __cdecl _vtcprintf_s_l (const _TCHAR *, _locale_t, va_list); +_CRTIMP int __cdecl _vtcprintf_p_l (const _TCHAR *, _locale_t, va_list); + + +/*** +*int _cprintf(format, arglist) - write formatted output directly to console +* +*Purpose: +* Writes formatted data like printf, but uses console I/O functions. +* +*Entry: +* char *format - format string to determine data formats +* arglist - list of POINTERS to where to put data +* +*Exit: +* returns number of characters written +* +*Exceptions: +* +*******************************************************************************/ +#ifndef FORMAT_VALIDATIONS +_CRTIMP int __cdecl _tcprintf_l ( + const _TCHAR * format, + _locale_t plocinfo, + ... + ) +#else /* FORMAT_VALIDATIONS */ +_CRTIMP int __cdecl _tcprintf_s_l ( + const _TCHAR * format, + _locale_t plocinfo, + ... + ) +#endif /* FORMAT_VALIDATIONS */ + +{ + int ret; + va_list arglist; + va_start(arglist, plocinfo); + +#ifndef FORMAT_VALIDATIONS + ret = _vtcprintf_l(format, plocinfo, arglist); +#else /* FORMAT_VALIDATIONS */ + ret = _vtcprintf_s_l(format, plocinfo, arglist); + +#endif /* FORMAT_VALIDATIONS */ + + va_end(arglist); + + return ret; +} + +#ifndef FORMAT_VALIDATIONS +_CRTIMP int __cdecl _tcprintf ( + const _TCHAR * format, + ... + ) +#else /* FORMAT_VALIDATIONS */ +_CRTIMP int __cdecl _tcprintf_s ( + const _TCHAR * format, + ... + ) +#endif /* FORMAT_VALIDATIONS */ + +{ + int ret; + va_list arglist; + + va_start(arglist, format); + +#ifndef FORMAT_VALIDATIONS + ret = _vtcprintf_l(format, NULL, arglist); +#else /* FORMAT_VALIDATIONS */ + ret = _vtcprintf_s_l(format, NULL, arglist); + +#endif /* FORMAT_VALIDATIONS */ + + va_end(arglist); + + return ret; +} + +#endif /* CPRFLAG */ + + +/*** +*int _output(stream, format, argptr), static int output(format, argptr) +* +*Purpose: +* Output performs printf style output onto a stream. It is called by +* printf/fprintf/sprintf/vprintf/vfprintf/vsprintf to so the dirty +* work. In multi-thread situations, _output assumes that the given +* stream is already locked. +* +* Algorithm: +* The format string is parsed by using a finite state automaton +* based on the current state and the current character read from +* the format string. Thus, looping is on a per-character basis, +* not a per conversion specifier basis. Once the format specififying +* character is read, output is performed. +* +*Entry: +* FILE *stream - stream for output +* char *format - printf style format string +* va_list argptr - pointer to list of subsidiary arguments +* +*Exit: +* Returns the number of characters written, or -1 if an output error +* occurs. +*ifdef _UNICODE +* The wide-character flavour returns the number of wide-characters written. +*endif +* +*Exceptions: +* +*******************************************************************************/ +#ifdef CPRFLAG +#ifndef FORMAT_VALIDATIONS +_CRTIMP int __cdecl _vtcprintf ( + const _TCHAR *format, + va_list argptr + ) +{ + return _vtcprintf_l(format, NULL, argptr); +} + +#else /* FORMAT_VALIDATIONS */ +_CRTIMP int __cdecl _vtcprintf_s ( + const _TCHAR *format, + va_list argptr + ) +{ + return _vtcprintf_s_l(format, NULL, argptr); +} + +#endif /* FORMAT_VALIDATIONS */ +#endif /* CPRFLAG */ + +#ifdef CPRFLAG +#ifndef FORMAT_VALIDATIONS +_CRTIMP int __cdecl _vtcprintf_l ( +#else /* FORMAT_VALIDATIONS */ +_CRTIMP int __cdecl _vtcprintf_s_l ( +#endif /* FORMAT_VALIDATIONS */ +#else /* CPRFLAG */ + +#ifdef _UNICODE +#ifndef FORMAT_VALIDATIONS +int __cdecl _woutput ( + miniFILE *stream, +#else /* FORMAT_VALIDATIONS */ +int __cdecl _woutput_s ( + miniFILE *stream, +#endif /* FORMAT_VALIDATIONS */ +#else /* _UNICODE */ +#ifndef FORMAT_VALIDATIONS +int __cdecl _output ( + miniFILE *stream, +#else /* FORMAT_VALIDATIONS */ + int __cdecl _output_s ( + miniFILE *stream, + +#endif /* FORMAT_VALIDATIONS */ +#endif /* _UNICODE */ + +#endif /* CPRFLAG */ + const _TCHAR *format, + va_list argptr + ) +{ + int hexadd=0; /* offset to add to number to get 'a'..'f' */ + TCHAR ch; /* character just read */ + int flags=0; /* flag word -- see #defines above for flag values */ + enum STATE state; /* current state */ + enum CHARTYPE chclass; /* class of current character */ + int radix; /* current conversion radix */ + int charsout; /* characters currently written so far, -1 = IO error */ + int fldwidth = 0; /* selected field width -- 0 means default */ + int precision = 0; /* selected precision -- -1 means default */ + TCHAR prefix[2]; /* numeric prefix -- up to two characters */ + int prefixlen=0; /* length of prefix -- 0 means no prefix */ + int capexp = 0; /* non-zero = 'E' exponent signifient, zero = 'e' */ + int no_output=0; /* non-zero = prodcue no output for this specifier */ + union { + const char *sz; /* pointer text to be printed, not zero terminated */ + const char16_t *wz; + } text; + + int textlen; /* length of the text in bytes/wchars to be printed. + textlen is in multibyte or wide chars if _UNICODE */ + union { + char sz[BUFFERSIZE]; +#ifdef _UNICODE + char16_t wz[BUFFERSIZE]; +#endif /* _UNICODE */ + } buffer; + char16_t wchar; /* temp char16_t */ + int buffersize; /* size of text.sz (used only for the call to _cfltcvt) */ + int bufferiswide=0; /* non-zero = buffer contains wide chars already */ + +#ifndef CPRFLAG + _VALIDATE_RETURN( (stream != NULL), EINVAL, -1); +#endif /* CPRFLAG */ + _VALIDATE_RETURN( (format != NULL), EINVAL, -1); + + charsout = 0; /* no characters written yet */ + textlen = 0; /* no text yet */ + state = ST_NORMAL; /* starting state */ + buffersize = 0; + + /* main loop -- loop while format character exist and no I/O errors */ + while ((ch = *format++) != _T('\0') && charsout >= 0) { +#ifndef FORMAT_VALIDATIONS + chclass = FIND_CHAR_CLASS(__lookuptable, ch); /* find character class */ + state = FIND_NEXT_STATE(__lookuptable, chclass, state); /* find next state */ +#else /* FORMAT_VALIDATIONS */ + chclass = FIND_CHAR_CLASS(__lookuptable_s, ch); /* find character class */ + state = FIND_NEXT_STATE(__lookuptable_s, chclass, state); /* find next state */ + + _VALIDATE_RETURN((state != ST_INVALID), EINVAL, -1); + +#endif /* FORMAT_VALIDATIONS */ + + /* execute code for each state */ + switch (state) { + + case ST_NORMAL: + + NORMAL_STATE: + + /* normal state -- just write character */ +#ifdef _UNICODE + bufferiswide = 1; +#else /* _UNICODE */ + bufferiswide = 0; +#endif /* _UNICODE */ + WRITE_CHAR(ch, &charsout); + break; + + case ST_PERCENT: + /* set default value of conversion parameters */ + prefixlen = fldwidth = no_output = capexp = 0; + flags = 0; + precision = -1; + bufferiswide = 0; /* default */ + break; + + case ST_FLAG: + /* set flag based on which flag character */ + switch (ch) { + case _T('-'): + flags |= FL_LEFT; /* '-' => left justify */ + break; + case _T('+'): + flags |= FL_SIGN; /* '+' => force sign indicator */ + break; + case _T(' '): + flags |= FL_SIGNSP; /* ' ' => force sign or space */ + break; + case _T('#'): + flags |= FL_ALTERNATE; /* '#' => alternate form */ + break; + case _T('0'): + flags |= FL_LEADZERO; /* '0' => pad with leading zeros */ + break; + } + break; + + case ST_WIDTH: + /* update width value */ + if (ch == _T('*')) { + /* get width from arg list */ + fldwidth = get_int_arg(&argptr); + if (fldwidth < 0) { + /* ANSI says neg fld width means '-' flag and pos width */ + flags |= FL_LEFT; + fldwidth = -fldwidth; + } + } + else { + /* add digit to current field width */ + fldwidth = fldwidth * 10 + (ch - _T('0')); + } + break; + + case ST_DOT: + /* zero the precision, since dot with no number means 0 + not default, according to ANSI */ + precision = 0; + break; + + case ST_PRECIS: + /* update precison value */ + if (ch == _T('*')) { + /* get precision from arg list */ + precision = get_int_arg(&argptr); + if (precision < 0) + precision = -1; /* neg precision means default */ + } + else { + /* add digit to current precision */ + precision = precision * 10 + (ch - _T('0')); + } + break; + + case ST_SIZE: + /* just read a size specifier, set the flags based on it */ + switch (ch) { + case _T('l'): + /* + * In order to handle the ll case, we depart from the + * simple deterministic state machine. + */ + if (*format == _T('l')) + { + ++format; + flags |= FL_LONGLONG; /* 'll' => long long */ + } + else + { + flags |= FL_LONG; /* 'l' => long int or char16_t */ + } + break; + case _T('L'): + if (*format == _T('p')) + { + flags |= FL_LONG; + } + break; + + case _T('I'): + /* + * In order to handle the I, I32, and I64 size modifiers, we + * depart from the simple deterministic state machine. The + * code below scans for characters following the 'I', + * and defaults to 64 bit on WIN64 and 32 bit on WIN32 + */ +#if PTR_IS_INT64 + flags |= FL_I64; /* 'I' => __int64 on WIN64 systems */ +#endif /* PTR_IS_INT64 */ + if ( (*format == _T('6')) && (*(format + 1) == _T('4')) ) + { + format += 2; + flags |= FL_I64; /* I64 => __int64 */ + } + else if ( (*format == _T('3')) && (*(format + 1) == _T('2')) ) + { + format += 2; + flags &= ~FL_I64; /* I32 => __int32 */ + } + else if ( (*format == _T('d')) || + (*format == _T('i')) || + (*format == _T('o')) || + (*format == _T('u')) || + (*format == _T('x')) || + (*format == _T('X')) ) + { + /* + * Nothing further needed. %Id (et al) is + * handled just like %d, except that it defaults to 64 bits + * on WIN64. Fall through to the next iteration. + */ + } + else { + state = ST_NORMAL; + goto NORMAL_STATE; + } + break; + + case _T('h'): + flags |= FL_SHORT; /* 'h' => short int or char */ + break; + + case _T('w'): + flags |= FL_WIDECHAR; /* 'w' => wide character */ + break; + + } + break; + + case ST_TYPE: + /* we have finally read the actual type character, so we */ + /* now format and "print" the output. We use a big switch */ + /* statement that sets 'text' to point to the text that should */ + /* be printed, and 'textlen' to the length of this text. */ + /* Common code later on takes care of justifying it and */ + /* other miscellaneous chores. Note that cases share code, */ + /* in particular, all integer formatting is done in one place. */ + /* Look at those funky goto statements! */ + + switch (ch) { + + case _T('C'): /* ISO wide character */ + if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR))) +#ifdef _UNICODE + flags |= FL_SHORT; +#else /* _UNICODE */ + flags |= FL_WIDECHAR; /* ISO std. */ +#endif /* _UNICODE */ + /* fall into 'c' case */ + + case _T('c'): { + /* print a single character specified by int argument */ +#ifdef _UNICODE + bufferiswide = 1; + wchar = (char16_t) get_int_arg(&argptr); + if (flags & FL_SHORT) { + /* format multibyte character */ + /* this is an extension of ANSI */ + char tempchar[2]; + { + tempchar[0] = (char)(wchar & 0x00ff); + tempchar[1] = '\0'; + } + + if (_MBTOWC(buffer.wz,tempchar, MB_CUR_MAX) < 0) + { + /* ignore if conversion was unsuccessful */ + no_output = 1; + } + } else { + buffer.wz[0] = wchar; + } + text.wz = buffer.wz; + textlen = 1; /* print just a single character */ +#else /* _UNICODE */ + if (flags & (FL_LONG|FL_WIDECHAR)) { + wchar = (char16_t) get_int_arg(&argptr); + textlen = snprintf(buffer.sz, BUFFERSIZE, "%lc", wchar); + if (textlen == 0) + { + no_output = 1; + } + } else { + /* format multibyte character */ + /* this is an extension of ANSI */ + unsigned short temp; + wchar = (char16_t)get_int_arg(&argptr); + temp = (unsigned short)wchar; + { + buffer.sz[0] = (char) temp; + textlen = 1; + } + } + text.sz = buffer.sz; +#endif /* _UNICODE */ + } + break; + + case _T('Z'): { + /* print a Counted String */ + struct _count_string { + short Length; + short MaximumLength; + char *Buffer; + } *pstr; + + pstr = (struct _count_string *)get_ptr_arg(&argptr); + if (pstr == NULL || pstr->Buffer == NULL) { + /* null ptr passed, use special string */ + text.sz = __nullstring; + textlen = (int)strlen(text.sz); + } else { + if (flags & FL_WIDECHAR) { + text.wz = (char16_t *)pstr->Buffer; + textlen = pstr->Length / (int)sizeof(char16_t); + bufferiswide = 1; + } else { + bufferiswide = 0; + text.sz = pstr->Buffer; + textlen = pstr->Length; + } + } + } + break; + + case _T('S'): /* ISO wide character string */ +#ifndef _UNICODE + if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR))) + flags |= FL_WIDECHAR; +#else /* _UNICODE */ + if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR))) + flags |= FL_SHORT; +#endif /* _UNICODE */ + + case _T('s'): { + /* print a string -- */ + /* ANSI rules on how much of string to print: */ + /* all if precision is default, */ + /* min(precision, length) if precision given. */ + /* prints '(null)' if a null string is passed */ + + int i; + const char *p; /* temps */ + const char16_t *pwch; + + /* At this point it is tempting to use strlen(), but */ + /* if a precision is specified, we're not allowed to */ + /* scan past there, because there might be no null */ + /* at all. Thus, we must do our own scan. */ + + i = (precision == -1) ? INT_MAX : precision; + text.sz = (char *)get_ptr_arg(&argptr); + + /* scan for null upto i characters */ +#ifdef _UNICODE + if (flags & FL_SHORT) { + if (text.sz == NULL) /* NULL passed, use special string */ + text.sz = __nullstring; + p = text.sz; + for (textlen=0; textlen MAXPRECISION) + precision = MAXPRECISION; + + if (precision > BUFFERSIZE - _CVTBUFSIZE) { + /* cap precision further */ + precision = BUFFERSIZE - _CVTBUFSIZE; + } + + /* for safecrt, we pass along the FL_ALTERNATE flag to _safecrt_cfltcvt */ + if (flags & FL_ALTERNATE) + { + capexp |= FL_ALTERNATE; + } + + _CRT_DOUBLE tmp; + tmp=va_arg(argptr, _CRT_DOUBLE); + /* Note: assumes ch is in ASCII range */ + /* In safecrt, we provide a special version of _cfltcvt which internally calls printf (see safecrt_output_s.c) */ + _CFLTCVT(&tmp, buffer.sz, buffersize, (char)ch, precision, capexp); + + /* check if result was negative, save '-' for later */ + /* and point to positive part (this is for '0' padding) */ + if (*text.sz == '-') { + flags |= FL_NEGATIVE; + ++text.sz; + } + + textlen = (int)strlen(text.sz); /* compute length of text */ + } + break; + + case _T('d'): + case _T('i'): + /* signed decimal output */ + flags |= FL_SIGNED; + radix = 10; + goto COMMON_INT; + + case _T('u'): + radix = 10; + goto COMMON_INT; + + case _T('p'): + /* write a pointer -- this is like an integer or long */ + /* except we force precision to pad with zeros and */ + /* output in big hex. */ + + precision = 2 * sizeof(void *); /* number of hex digits needed */ +#if PTR_IS_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 */ + /* DROP THROUGH to hex formatting */ + + case _T('X'): + /* unsigned upper hex output */ + hexadd = _T('A') - _T('9') - 1; /* set hexadd for uppercase hex */ + goto COMMON_HEX; + + case _T('x'): + /* unsigned lower hex output */ + hexadd = _T('a') - _T('9') - 1; /* set hexadd for lowercase hex */ + /* DROP THROUGH TO COMMON_HEX */ + + COMMON_HEX: + radix = 16; + if (flags & FL_ALTERNATE) { + /* alternate form means '0x' prefix */ + prefix[0] = _T('0'); + prefix[1] = (TCHAR)(_T('x') - _T('a') + _T('9') + 1 + hexadd); /* 'x' or 'X' */ + prefixlen = 2; + } + goto COMMON_INT; + + case _T('o'): + /* unsigned octal output */ + radix = 8; + if (flags & FL_ALTERNATE) { + /* alternate form means force a leading 0 */ + flags |= FL_FORCEOCTAL; + } + /* DROP THROUGH to COMMON_INT */ + + COMMON_INT: { + /* This is the general integer formatting routine. */ + /* Basically, we get an argument, make it positive */ + /* if necessary, and convert it according to the */ + /* correct radix, setting text and textlen */ + /* appropriately. */ + +#if _INTEGRAL_MAX_BITS >= 64 + uint64_t number; /* number to convert */ + int digit; /* ascii value of digit */ + __int64 l; /* temp long value */ +#else /* _INTEGRAL_MAX_BITS >= 64 */ + unsigned long number; /* number to convert */ + int digit; /* ascii value of digit */ + long l; /* temp long value */ +#endif /* _INTEGRAL_MAX_BITS >= 64 */ + + /* 1. read argument into l, sign extend as needed */ +#if _INTEGRAL_MAX_BITS >= 64 + if (flags & FL_I64) + l = get_int64_arg(&argptr); + else +#endif /* _INTEGRAL_MAX_BITS >= 64 */ + + if (flags & FL_LONGLONG) + l = get_long_long_arg(&argptr); + + else + +#if !LONG_IS_INT + if (flags & FL_LONG) + l = get_long_arg(&argptr); + else +#endif /* !LONG_IS_INT */ + +#if !SHORT_IS_INT + if (flags & FL_SHORT) { + if (flags & FL_SIGNED) + l = (short) get_int_arg(&argptr); /* sign extend */ + else + l = (unsigned short) get_int_arg(&argptr); /* zero-extend*/ + + } else +#endif /* !SHORT_IS_INT */ + { + if (flags & FL_SIGNED) + l = get_int_arg(&argptr); /* sign extend */ + else + l = (unsigned int) get_int_arg(&argptr); /* zero-extend*/ + } + + /* 2. check for negative; copy into number */ + if ( (flags & FL_SIGNED) && l < 0) { + number = -l; + flags |= FL_NEGATIVE; /* remember negative sign */ + } else { + number = l; + } + +#if _INTEGRAL_MAX_BITS >= 64 + if ( (flags & FL_I64) == 0 && (flags & FL_LONGLONG) == 0 ) { + /* + * Unless printing a full 64-bit value, insure values + * here are not in cananical longword format to prevent + * the sign extended upper 32-bits from being printed. + */ + number &= 0xffffffff; + } +#endif /* _INTEGRAL_MAX_BITS >= 64 */ + + /* 3. check precision value for default; non-default */ + /* turns off 0 flag, according to ANSI. */ + if (precision < 0) + precision = 1; /* default precision */ + else { + flags &= ~FL_LEADZERO; + if (precision > MAXPRECISION) + precision = MAXPRECISION; + } + + /* 4. Check if data is 0; if so, turn off hex prefix */ + if (number == 0) + prefixlen = 0; + + /* 5. Convert data to ASCII -- note if precision is zero */ + /* and number is zero, we get no digits at all. */ + + char *sz; + sz = &buffer.sz[BUFFERSIZE-1]; /* last digit at end of buffer */ + + while (precision-- > 0 || number != 0) { + digit = (int)(number % radix) + '0'; + number /= radix; /* reduce number */ + if (digit > '9') { + /* a hex digit, make it a letter */ + digit += hexadd; + } + *sz-- = (char)digit; /* store the digit */ + } + + textlen = (int)((char *)&buffer.sz[BUFFERSIZE-1] - sz); /* compute length of number */ + ++sz; /* text points to first digit now */ + + + /* 6. Force a leading zero if FORCEOCTAL flag set */ + if ((flags & FL_FORCEOCTAL) && (textlen == 0 || sz[0] != '0')) { + *--sz = '0'; + ++textlen; /* add a zero */ + } + + text.sz = sz; + } + break; + } + + + /* At this point, we have done the specific conversion, and */ + /* 'text' points to text to print; 'textlen' is length. Now we */ + /* justify it, put on prefixes, leading zeros, and then */ + /* print it. */ + + if (!no_output) { + int padding; /* amount of padding, negative means zero */ + + if (flags & FL_SIGNED) { + if (flags & FL_NEGATIVE) { + /* prefix is a '-' */ + prefix[0] = _T('-'); + prefixlen = 1; + } + else if (flags & FL_SIGN) { + /* prefix is '+' */ + prefix[0] = _T('+'); + prefixlen = 1; + } + else if (flags & FL_SIGNSP) { + /* prefix is ' ' */ + prefix[0] = _T(' '); + prefixlen = 1; + } + } + + /* calculate amount of padding -- might be negative, */ + /* but this will just mean zero */ + padding = fldwidth - textlen - prefixlen; + + /* put out the padding, prefix, and text, in the correct order */ + + if (!(flags & (FL_LEFT | FL_LEADZERO))) { + /* pad on left with blanks */ + WRITE_MULTI_CHAR(_T(' '), padding, &charsout); + } + + /* write prefix */ + WRITE_STRING(prefix, prefixlen, &charsout); + + if ((flags & FL_LEADZERO) && !(flags & FL_LEFT)) { + /* write leading zeros */ + WRITE_MULTI_CHAR(_T('0'), padding, &charsout); + } + + /* write text */ +#ifndef _UNICODE + if (bufferiswide && (textlen > 0)) { + 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); + } +#else /* _UNICODE */ + if (!bufferiswide && textlen > 0) { + const char *p; + int retval = 0; + int count; + + p = text.sz; + count = textlen; + while (count-- > 0) { + retval = _MBTOWC(&wchar, p, MB_CUR_MAX); + if (retval <= 0) { + charsout = -1; + break; + } + WRITE_CHAR(wchar, &charsout); + p += retval; + } + } else { + WRITE_STRING(text.wz, textlen, &charsout); + } +#endif /* _UNICODE */ + + if (charsout >= 0 && (flags & FL_LEFT)) { + /* pad on right with blanks */ + WRITE_MULTI_CHAR(_T(' '), padding, &charsout); + } + + /* we're done! */ + } + break; + case ST_INVALID: + _VALIDATE_RETURN(0 /* FALSE */, EINVAL, -1); + break; + } + } + +#ifdef FORMAT_VALIDATIONS + /* The format string shouldn't be incomplete - i.e. when we are finished + with the format string, the last thing we should have encountered + should have been a regular char to be output or a type specifier. Else + the format string was incomplete */ + _VALIDATE_RETURN(((state == ST_NORMAL) || (state == ST_TYPE)), EINVAL, -1); +#endif /* FORMAT_VALIDATIONS */ + + return charsout; /* return value = number of characters written */ +} + +/* + * Future Optimizations for swprintf: + * - Don't free the memory used for converting the buffer to wide chars. + * Use realloc if the memory is not sufficient. Free it at the end. + */ + +/*** +*void write_char(char ch, int *pnumwritten) +*ifdef _UNICODE +*void write_char(char16_t ch, FILE *f, int *pnumwritten) +*endif +*void write_char(char ch, FILE *f, int *pnumwritten) +* +*Purpose: +* Writes a single character to the given file/console. If no error occurs, +* then *pnumwritten is incremented; otherwise, *pnumwritten is set +* to -1. +* +*Entry: +* _TCHAR ch - character to write +* FILE *f - file to write to +* int *pnumwritten - pointer to integer to update with total chars written +* +*Exit: +* No return value. +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef CPRFLAG + +LOCAL(void) write_char ( + _TCHAR ch, + int *pnumwritten + ) +{ +#ifdef _UNICODE + if (_putwch_nolock(ch) == WEOF) +#else /* _UNICODE */ + if (_putch_nolock(ch) == EOF) +#endif /* _UNICODE */ + *pnumwritten = -1; + else + ++(*pnumwritten); +} + +#else /* CPRFLAG */ + +LOCAL(void) write_char ( + _TCHAR ch, + miniFILE *f, + int *pnumwritten + ) +{ + if ( (f->_flag & _IOSTRG) && f->_base == NULL) + { + ++(*pnumwritten); + return; + } +#ifdef _UNICODE + if (_putwc_nolock(ch, f) == WEOF) +#else /* _UNICODE */ + if (_putc_nolock(ch, f) == EOF) +#endif /* _UNICODE */ + *pnumwritten = -1; + else + ++(*pnumwritten); +} + +#endif /* CPRFLAG */ + +/*** +*void write_multi_char(char ch, int num, int *pnumwritten) +*ifdef _UNICODE +*void write_multi_char(char16_t ch, int num, FILE *f, int *pnumwritten) +*endif +*void write_multi_char(char ch, int num, FILE *f, int *pnumwritten) +* +*Purpose: +* Writes num copies of a character to the given file/console. If no error occurs, +* then *pnumwritten is incremented by num; otherwise, *pnumwritten is set +* to -1. If num is negative, it is treated as zero. +* +*Entry: +* _TCHAR ch - character to write +* int num - number of times to write the characters +* FILE *f - file to write to +* int *pnumwritten - pointer to integer to update with total chars written +* +*Exit: +* No return value. +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef CPRFLAG +LOCAL(void) write_multi_char ( + _TCHAR ch, + int num, + int *pnumwritten + ) +{ + while (num-- > 0) { + write_char(ch, pnumwritten); + if (*pnumwritten == -1) + break; + } +} + +#else /* CPRFLAG */ + +LOCAL(void) write_multi_char ( + _TCHAR ch, + int num, + miniFILE *f, + int *pnumwritten + ) +{ + while (num-- > 0) { + write_char(ch, f, pnumwritten); + if (*pnumwritten == -1) + break; + } +} + +#endif /* CPRFLAG */ + +/*** +*void write_string(const char *string, int len, int *pnumwritten) +*void write_string(const char *string, int len, FILE *f, int *pnumwritten) +*ifdef _UNICODE +*void write_string(const char16_t *string, int len, FILE *f, int *pnumwritten) +*endif +* +*Purpose: +* Writes a string of the given length to the given file. If no error occurs, +* then *pnumwritten is incremented by len; otherwise, *pnumwritten is set +* to -1. If len is negative, it is treated as zero. +* +*Entry: +* _TCHAR *string - string to write (NOT null-terminated) +* int len - length of string +* FILE *f - file to write to +* int *pnumwritten - pointer to integer to update with total chars written +* +*Exit: +* No return value. +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef CPRFLAG + +LOCAL(void) write_string ( + const _TCHAR *string, + int len, + int *pnumwritten + ) +{ + while (len-- > 0) { + write_char(*string++, pnumwritten); + if (*pnumwritten == -1) + { + if (errno == EILSEQ) + write_char(_T('?'), pnumwritten); + else + break; + } + } +} + +#else /* CPRFLAG */ + +LOCAL(void) write_string ( + const _TCHAR *string, + int len, + miniFILE *f, + int *pnumwritten + ) +{ + if ( (f->_flag & _IOSTRG) && f->_base == NULL) + { + (*pnumwritten) += len; + return; + } + while (len-- > 0) { + write_char(*string++, f, pnumwritten); + if (*pnumwritten == -1) + { + if (errno == EILSEQ) + write_char(_T('?'), f, pnumwritten); + else + break; + } + } +} +#endif /* CPRFLAG */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_input_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_input_s.cpp new file mode 100644 index 0000000..6ba607c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_input_s.cpp @@ -0,0 +1,46 @@ +// 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. + +/*** +*safecrt_input_s.c - implementation of the _input family for safecrt.lib +* + +* +*Purpose: +* This file contains the implementation of the _input family for safecrt.lib. +* +*Revision History: +* 07/19/04 AC Created +* +****/ + +#define _SAFECRT_IMPL +#define _SECURE_SCANF + +#include "pal/palinternal.h" +#include +#include +#include +#include +#include +#include +#include + +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _TCHAR CRT_TCHAR +#define TCHAR CRTTCHAR + +typedef char _TCHAR; +typedef char TCHAR; +typedef unsigned char _TUCHAR; +#define _T(x) x +#define _TEOF EOF + +#define _gettc_nolock(x) _getc_nolock(x) +#define _ungettc_nolock(x,y) _ungetc_nolock(x,y) + +#include "input.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_output_l.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_output_l.cpp new file mode 100644 index 0000000..8b71fd3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_output_l.cpp @@ -0,0 +1,1467 @@ +// 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. + +/*** +*safecrt_output_l.c - implementation of the _output family for safercrt.lib +* + +* +*Purpose: +* This file contains the implementation of the _output family for safercrt.lib. +* +*Revision History: +* 07-08-04 SJ Stub module created. +* 07-13-04 AC Added support for floating-point types. +* 07-29-04 AC Added macros for a safecrt version of mctowc and wctomb, which target ntdll.dll or msvcrt.dll +* based on the _NTSUBSET_ #define +* 09-24-04 MSL Prefix disallow NULL deref +* +****/ + +#define _SAFECRT_IMPL + +#define __STDC_LIMIT_MACROS +#include "pal/palinternal.h" +#include +#include +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _CFLTCVT _safecrt_cfltcvt + +//typedef __int64_t __int64; +typedef double _CRT_DOUBLE; +typedef char _TCHAR; +typedef char TCHAR; +#define _T(x) x +/* +Buffer size required to be passed to _gcvt, fcvt and other fp conversion routines +*/ +#define _CVTBUFSIZE (309+40) /* # of digits in max. dp value + slop */ + +//------------------------------------------------------------------------------ +// This code was taken from the 'ouput.c' file located in Visual Studio 8 (i.e. 2005) +// in the '\Microsoft Visual Studio 8\VC\crt\src' directory. It was moved into +// this file to support only the '_output' function used by _vscprintf() in vsprintf.c +// UNUSED / NON-RELEVANT PORTIONS OF THE CODE HAVE BEEN REMOVED - do not try and +// use it to generate any other safecrt 'output' functions +// +// Noteable modifications +// - changed FILE to miniFILE (defined in mbusafecrt_internal.h) +// - removed _soutput_s - it was unused in this case and conflicted with output.inl +// - changed #define SHORT_IS_INT to true varargs promotes shorts to ints in GCC +// - removed definition of __lookuptable_s when using FORMAT_VALIDATIONS, we don't use them + +// 7/03/07 - Created by Stephen Shaw (steshaw) +//------------------------------------------------------------------------------ + + +/* temporary work-around for compiler without 64-bit support */ +#ifndef _INTEGRAL_MAX_BITS +#define _INTEGRAL_MAX_BITS 64 +#endif /* _INTEGRAL_MAX_BITS */ + +#include +#include +#include +#include +#include +#include +#include + +#define _MBTOWC(x,y,z) _minimal_chartowchar( x, y ) + +#undef _malloc_crt +#define _malloc_crt malloc + +#undef _free_crt +#define _free_crt free + +// SNIP -srs 7/3/07 + +#ifndef _CFLTCVT +#define _CFLTCVT _cfltcvt +#endif /* _CFLTCVT */ + +#ifndef _CLDCVT +#define _CLDCVT _cldcvt +#endif /* _CLDCVT */ + +#ifdef _MBCS +#undef _MBCS +#endif /* _MBCS */ +//#include + +/* this macro defines a function which is private and as fast as possible: */ +/* for example, in C 6.0, it might be static _fastcall near. */ +#define LOCAL(x) static x __cdecl + +/* int/long/short/pointer sizes */ + +/* the following should be set depending on the sizes of various types */ +#if __LP64__ + #define LONG_IS_INT 0 + CASSERT(sizeof(long) > sizeof(int)); +#else + #define LONG_IS_INT 1 /* 1 means long is same size as int */ + CASSERT(sizeof(long) == sizeof(int)); +#endif + +// GCC: short is not int, but GCC promotes va_arg to int +#define SHORT_IS_INT 1 + +#define LONGLONG_IS_INT64 1 /* 1 means long long is same as int64 */ + CASSERT(sizeof(long long) == sizeof(int64_t)); + +#if defined (HOST_64BIT) + #define PTR_IS_INT 0 /* 1 means ptr is same size as int */ + CASSERT(sizeof(void *) != sizeof(int)); + #if __LP64__ + #define PTR_IS_LONG 1 /* 1 means ptr is same size as long */ + CASSERT(sizeof(void *) == sizeof(long)); + #else + #define PTR_IS_LONG 0 /* 1 means ptr is same size as long */ + CASSERT(sizeof(void *) != sizeof(long)); + #endif + #define PTR_IS_INT64 1 /* 1 means ptr is same size as int64 */ + CASSERT(sizeof(void *) == sizeof(int64_t)); +#else /* defined (HOST_64BIT) */ + #define PTR_IS_INT 1 /* 1 means ptr is same size as int */ + CASSERT(sizeof(void *) == sizeof(int)); + #define PTR_IS_LONG 1 /* 1 means ptr is same size as long */ + CASSERT(sizeof(void *) == sizeof(long)); + #define PTR_IS_INT64 0 /* 1 means ptr is same size as int64 */ + CASSERT(sizeof(void *) != sizeof(int64_t)); +#endif /* defined (HOST_64BIT) */ + +/* CONSTANTS */ + +/* size of conversion buffer (ANSI-specified minimum is 509) */ + +#define BUFFERSIZE 512 +#define MAXPRECISION BUFFERSIZE + +#if BUFFERSIZE < _CVTBUFSIZE + 6 +/* + * Buffer needs to be big enough for default minimum precision + * when converting floating point needs bigger buffer, and malloc + * fails + */ +#error Conversion buffer too small for max double. +#endif /* BUFFERSIZE < _CVTBUFSIZE + 6 */ + +/* flag definitions */ +#define FL_SIGN 0x00001 /* put plus or minus in front */ +#define FL_SIGNSP 0x00002 /* put space or minus in front */ +#define FL_LEFT 0x00004 /* left justify */ +#define FL_LEADZERO 0x00008 /* pad with leading zeros */ +#define FL_LONG 0x00010 /* long value given */ +#define FL_SHORT 0x00020 /* short value given */ +#define FL_SIGNED 0x00040 /* signed data given */ +#define FL_ALTERNATE 0x00080 /* alternate form requested */ +#define FL_NEGATIVE 0x00100 /* value is negative */ +#define FL_FORCEOCTAL 0x00200 /* force leading '0' for octals */ +#define FL_LONGDOUBLE 0x00400 /* long double value given */ +#define FL_WIDECHAR 0x00800 /* wide characters */ +#define FL_LONGLONG 0x01000 /* long long value given */ +#define FL_I64 0x08000 /* __int64 value given */ + +/* state definitions */ +enum STATE { + ST_NORMAL, /* normal state; outputting literal chars */ + ST_PERCENT, /* just read '%' */ + ST_FLAG, /* just read flag character */ + ST_WIDTH, /* just read width specifier */ + ST_DOT, /* just read '.' */ + ST_PRECIS, /* just read precision specifier */ + ST_SIZE, /* just read size specifier */ + ST_TYPE /* just read type specifier */ +#ifdef FORMAT_VALIDATIONS + ,ST_INVALID /* Invalid format */ +#endif /* FORMAT_VALIDATIONS */ + +}; + +#ifdef FORMAT_VALIDATIONS +#define NUMSTATES (ST_INVALID + 1) +#else /* FORMAT_VALIDATIONS */ +#define NUMSTATES (ST_TYPE + 1) +#endif /* FORMAT_VALIDATIONS */ + +/* character type values */ +enum CHARTYPE { + CH_OTHER, /* character with no special meaning */ + CH_PERCENT, /* '%' */ + CH_DOT, /* '.' */ + CH_STAR, /* '*' */ + CH_ZERO, /* '0' */ + CH_DIGIT, /* '1'..'9' */ + CH_FLAG, /* ' ', '+', '-', '#' */ + CH_SIZE, /* 'h', 'l', 'L', 'N', 'F', 'w' */ + CH_TYPE /* type specifying character */ +}; + +/* static data (read only, since we are re-entrant) */ +#if defined (_UNICODE) || defined (CPRFLAG) || defined (FORMAT_VALIDATIONS) +extern const char __nullstring[]; /* string to print on null ptr */ +extern const char16_t __wnullstring[]; /* string to print on null ptr */ +#else /* defined (_UNICODE) || defined (CPRFLAG) || defined (FORMAT_VALIDATIONS) */ +static const char __nullstring[] = "(null)"; /* string to print on null ptr */ +static const char16_t __wnullstring[] = { '(', 'n', 'u', 'l', 'l', ')', '\0' };/* string to print on null ptr */ +#endif /* defined (_UNICODE) || defined (CPRFLAG) || defined (FORMAT_VALIDATIONS) */ + +/* The state table. This table is actually two tables combined into one. */ +/* The lower nybble of each byte gives the character class of any */ +/* character; while the uper nybble of the byte gives the next state */ +/* to enter. See the macros below the table for details. */ +/* */ +/* The table is generated by maketabc.c -- use this program to make */ +/* changes. */ + +#ifndef FORMAT_VALIDATIONS +#if defined (_UNICODE) || defined (CPRFLAG) +extern const char __lookuptable[]; +#else /* defined (_UNICODE) || defined (CPRFLAG) */ +//extern const char __lookuptable[] = { +const char __lookuptable[] = { + /* ' ' */ 0x06, + /* '!' */ 0x00, + /* '"' */ 0x00, + /* '#' */ 0x06, + /* '$' */ 0x00, + /* '%' */ 0x01, + /* '&' */ 0x00, + /* ''' */ 0x00, + /* '(' */ 0x10, + /* ')' */ 0x00, + /* '*' */ 0x03, + /* '+' */ 0x06, + /* ',' */ 0x00, + /* '-' */ 0x06, + /* '.' */ 0x02, + /* '/' */ 0x10, + /* '0' */ 0x04, + /* '1' */ 0x45, + /* '2' */ 0x45, + /* '3' */ 0x45, + /* '4' */ 0x05, + /* '5' */ 0x05, + /* '6' */ 0x05, + /* '7' */ 0x05, + /* '8' */ 0x05, + /* '9' */ 0x35, + /* ':' */ 0x30, + /* ';' */ 0x00, + /* '<' */ 0x50, + /* '=' */ 0x00, + /* '>' */ 0x00, + /* '?' */ 0x00, + /* '@' */ 0x00, + /* 'A' */ 0x20, // Disable %A format + /* 'B' */ 0x20, + /* 'C' */ 0x38, + /* 'D' */ 0x50, + /* 'E' */ 0x58, + /* 'F' */ 0x07, + /* 'G' */ 0x08, + /* 'H' */ 0x00, + /* 'I' */ 0x37, + /* 'J' */ 0x30, + /* 'K' */ 0x30, + /* 'L' */ 0x57, + /* 'M' */ 0x50, + /* 'N' */ 0x07, + /* 'O' */ 0x00, + /* 'P' */ 0x00, + /* 'Q' */ 0x20, + /* 'R' */ 0x20, + /* 'S' */ 0x08, + /* 'T' */ 0x00, + /* 'U' */ 0x00, + /* 'V' */ 0x00, + /* 'W' */ 0x00, + /* 'X' */ 0x08, + /* 'Y' */ 0x60, + /* 'Z' */ 0x68, + /* '[' */ 0x60, + /* '\' */ 0x60, + /* ']' */ 0x60, + /* '^' */ 0x60, + /* '_' */ 0x00, + /* '`' */ 0x00, + /* 'a' */ 0x70, // Disable %a format + /* 'b' */ 0x70, + /* 'c' */ 0x78, + /* 'd' */ 0x78, + /* 'e' */ 0x78, + /* 'f' */ 0x78, + /* 'g' */ 0x08, + /* 'h' */ 0x07, + /* 'i' */ 0x08, + /* 'j' */ 0x00, + /* 'k' */ 0x00, + /* 'l' */ 0x07, + /* 'm' */ 0x00, + /* 'n' */ 0x00, // Disable %n format + /* 'o' */ 0x08, + /* 'p' */ 0x08, + /* 'q' */ 0x00, + /* 'r' */ 0x00, + /* 's' */ 0x08, + /* 't' */ 0x00, + /* 'u' */ 0x08, + /* 'v' */ 0x00, + /* 'w' */ 0x07, + /* 'x' */ 0x08 +}; + +#endif /* defined (_UNICODE) || defined (CPRFLAG) */ + +#else /* FORMAT_VALIDATIONS */ +// SNIP -srs 7/3/07 +#error code has been removed +#endif /* FORMAT_VALIDATIONS */ + +#define FIND_CHAR_CLASS(lookuptbl, c) \ + ((c) < _T(' ') || (c) > _T('x') ? \ + CH_OTHER \ + : \ + (enum CHARTYPE)(lookuptbl[(c)-_T(' ')] & 0xF)) + +#define FIND_NEXT_STATE(lookuptbl, class, state) \ + (enum STATE)(lookuptbl[(class) * NUMSTATES + (state)] >> 4) + +/* + * Note: CPRFLAG and _UNICODE cases are currently mutually exclusive. + */ + +/* prototypes */ + +#ifdef CPRFLAG + +#define WRITE_CHAR(ch, pnw) write_char(ch, pnw) +#define WRITE_MULTI_CHAR(ch, num, pnw) write_multi_char(ch, num, pnw) +#define WRITE_STRING(s, len, pnw) write_string(s, len, pnw) +#define WRITE_WSTRING(s, len, pnw) write_wstring(s, len, pnw) + +LOCAL(void) write_char(_TCHAR ch, int *pnumwritten); +LOCAL(void) write_multi_char(_TCHAR ch, int num, int *pnumwritten); +LOCAL(void) write_string(const _TCHAR *string, int len, int *numwritten); +LOCAL(void) write_wstring(const char16_t *string, int len, int *numwritten); + +#else /* CPRFLAG */ + +#define WRITE_CHAR(ch, pnw) write_char(ch, stream, pnw) +#define WRITE_MULTI_CHAR(ch, num, pnw) write_multi_char(ch, num, stream, pnw) +#define WRITE_STRING(s, len, pnw) write_string(s, len, stream, pnw) +#define WRITE_WSTRING(s, len, pnw) write_wstring(s, len, stream, pnw) + +LOCAL(void) write_char(_TCHAR ch, miniFILE *f, int *pnumwritten); +LOCAL(void) write_multi_char(_TCHAR ch, int num, miniFILE *f, int *pnumwritten); +LOCAL(void) write_string(const _TCHAR *string, int len, miniFILE *f, int *numwritten); +//LOCAL(void) write_wstring(const char16_t *string, int len, miniFILE *f, int *numwritten); + +#endif /* CPRFLAG */ + +#define get_short_arg(list) va_arg(*list, int) // GCC promotes va_arg shorts into int values +#define get_int_arg(list) va_arg(*list, int) +#define get_long_arg(list) va_arg(*list, long) +#define get_long_long_arg(list) va_arg(*list, long long) +#define get_int64_arg(list) va_arg(*list, __int64) +#define get_crtdouble_arg(list) va_arg(*list, _CRT_DOUBLE) +#define get_ptr_arg(list) va_arg(*list, void *) + +#ifdef CPRFLAG +LOCAL(int) output(const _TCHAR *, _locale_t , va_list); +_CRTIMP int __cdecl _vtcprintf_l (const _TCHAR *, _locale_t, va_list); +_CRTIMP int __cdecl _vtcprintf_s_l (const _TCHAR *, _locale_t, va_list); +_CRTIMP int __cdecl _vtcprintf_p_l (const _TCHAR *, _locale_t, va_list); + + +/*** +*int _cprintf(format, arglist) - write formatted output directly to console +* +*Purpose: +* Writes formatted data like printf, but uses console I/O functions. +* +*Entry: +* char *format - format string to determine data formats +* arglist - list of POINTERS to where to put data +* +*Exit: +* returns number of characters written +* +*Exceptions: +* +*******************************************************************************/ +#ifndef FORMAT_VALIDATIONS +_CRTIMP int __cdecl _tcprintf_l ( + const _TCHAR * format, + _locale_t plocinfo, + ... + ) +#else /* FORMAT_VALIDATIONS */ +_CRTIMP int __cdecl _tcprintf_s_l ( + const _TCHAR * format, + _locale_t plocinfo, + ... + ) +#endif /* FORMAT_VALIDATIONS */ + +{ + int ret; + va_list arglist; + va_start(arglist, plocinfo); + +#ifndef FORMAT_VALIDATIONS + ret = _vtcprintf_l(format, plocinfo, arglist); +#else /* FORMAT_VALIDATIONS */ + ret = _vtcprintf_s_l(format, plocinfo, arglist); + +#endif /* FORMAT_VALIDATIONS */ + + va_end(arglist); + + return ret; +} + +#ifndef FORMAT_VALIDATIONS +_CRTIMP int __cdecl _tcprintf ( + const _TCHAR * format, + ... + ) +#else /* FORMAT_VALIDATIONS */ +_CRTIMP int __cdecl _tcprintf_s ( + const _TCHAR * format, + ... + ) +#endif /* FORMAT_VALIDATIONS */ + +{ + int ret; + va_list arglist; + + va_start(arglist, format); + +#ifndef FORMAT_VALIDATIONS + ret = _vtcprintf_l(format, NULL, arglist); +#else /* FORMAT_VALIDATIONS */ + ret = _vtcprintf_s_l(format, NULL, arglist); + +#endif /* FORMAT_VALIDATIONS */ + + va_end(arglist); + + return ret; +} + +#endif /* CPRFLAG */ + + +/*** +*int _output(stream, format, argptr), static int output(format, argptr) +* +*Purpose: +* Output performs printf style output onto a stream. It is called by +* printf/fprintf/sprintf/vprintf/vfprintf/vsprintf to so the dirty +* work. In multi-thread situations, _output assumes that the given +* stream is already locked. +* +* Algorithm: +* The format string is parsed by using a finite state automaton +* based on the current state and the current character read from +* the format string. Thus, looping is on a per-character basis, +* not a per conversion specifier basis. Once the format specififying +* character is read, output is performed. +* +*Entry: +* FILE *stream - stream for output +* char *format - printf style format string +* va_list argptr - pointer to list of subsidiary arguments +* +*Exit: +* Returns the number of characters written, or -1 if an output error +* occurs. +*ifdef _UNICODE +* The wide-character flavour returns the number of wide-characters written. +*endif +* +*Exceptions: +* +*******************************************************************************/ +#ifdef CPRFLAG +#ifndef FORMAT_VALIDATIONS +_CRTIMP int __cdecl _vtcprintf ( + const _TCHAR *format, + va_list argptr + ) +{ + return _vtcprintf_l(format, NULL, argptr); +} + +#else /* FORMAT_VALIDATIONS */ +_CRTIMP int __cdecl _vtcprintf_s ( + const _TCHAR *format, + va_list argptr + ) +{ + return _vtcprintf_s_l(format, NULL, argptr); +} + +#endif /* FORMAT_VALIDATIONS */ +#endif /* CPRFLAG */ + +#ifdef CPRFLAG +#ifndef FORMAT_VALIDATIONS +_CRTIMP int __cdecl _vtcprintf_l ( +#else /* FORMAT_VALIDATIONS */ +_CRTIMP int __cdecl _vtcprintf_s_l ( +#endif /* FORMAT_VALIDATIONS */ +#else /* CPRFLAG */ + +#ifdef _UNICODE +#ifndef FORMAT_VALIDATIONS +int __cdecl _woutput ( + miniFILE *stream, +#else /* FORMAT_VALIDATIONS */ +int __cdecl _woutput_s ( + miniFILE *stream, +#endif /* FORMAT_VALIDATIONS */ +#else /* _UNICODE */ +#ifndef FORMAT_VALIDATIONS +int __cdecl _output ( + miniFILE *stream, +#else /* FORMAT_VALIDATIONS */ + int __cdecl _output_s ( + miniFILE *stream, + +#endif /* FORMAT_VALIDATIONS */ +#endif /* _UNICODE */ + +#endif /* CPRFLAG */ + const _TCHAR *format, + va_list argptr + ) +{ + int hexadd=0; /* offset to add to number to get 'a'..'f' */ + TCHAR ch; /* character just read */ + int flags=0; /* flag word -- see #defines above for flag values */ + enum STATE state; /* current state */ + enum CHARTYPE chclass; /* class of current character */ + int radix; /* current conversion radix */ + int charsout; /* characters currently written so far, -1 = IO error */ + int fldwidth = 0; /* selected field width -- 0 means default */ + int precision = 0; /* selected precision -- -1 means default */ + TCHAR prefix[2]; /* numeric prefix -- up to two characters */ + int prefixlen=0; /* length of prefix -- 0 means no prefix */ + int capexp = 0; /* non-zero = 'E' exponent signifient, zero = 'e' */ + int no_output=0; /* non-zero = prodcue no output for this specifier */ + union { + const char *sz; /* pointer text to be printed, not zero terminated */ + const char16_t *wz; + } text; + + int textlen; /* length of the text in bytes/wchars to be printed. + textlen is in multibyte or wide chars if _UNICODE */ + union { + char sz[BUFFERSIZE]; +#ifdef _UNICODE + char16_t wz[BUFFERSIZE]; +#endif /* _UNICODE */ + } buffer; + char16_t wchar; /* temp char16_t */ + int buffersize; /* size of text.sz (used only for the call to _cfltcvt) */ + int bufferiswide=0; /* non-zero = buffer contains wide chars already */ + +#ifndef CPRFLAG + _VALIDATE_RETURN( (stream != NULL), EINVAL, -1); +#endif /* CPRFLAG */ + _VALIDATE_RETURN( (format != NULL), EINVAL, -1); + + charsout = 0; /* no characters written yet */ + textlen = 0; /* no text yet */ + state = ST_NORMAL; /* starting state */ + buffersize = 0; + + /* main loop -- loop while format character exist and no I/O errors */ + while ((ch = *format++) != _T('\0') && charsout >= 0) { +#ifndef FORMAT_VALIDATIONS + chclass = FIND_CHAR_CLASS(__lookuptable, ch); /* find character class */ + state = FIND_NEXT_STATE(__lookuptable, chclass, state); /* find next state */ +#else /* FORMAT_VALIDATIONS */ + chclass = FIND_CHAR_CLASS(__lookuptable_s, ch); /* find character class */ + state = FIND_NEXT_STATE(__lookuptable_s, chclass, state); /* find next state */ + + _VALIDATE_RETURN((state != ST_INVALID), EINVAL, -1); + +#endif /* FORMAT_VALIDATIONS */ + + /* execute code for each state */ + switch (state) { + + case ST_NORMAL: + + NORMAL_STATE: + + /* normal state -- just write character */ +#ifdef _UNICODE + bufferiswide = 1; +#else /* _UNICODE */ + bufferiswide = 0; +#endif /* _UNICODE */ + WRITE_CHAR(ch, &charsout); + break; + + case ST_PERCENT: + /* set default value of conversion parameters */ + prefixlen = fldwidth = no_output = capexp = 0; + flags = 0; + precision = -1; + bufferiswide = 0; /* default */ + break; + + case ST_FLAG: + /* set flag based on which flag character */ + switch (ch) { + case _T('-'): + flags |= FL_LEFT; /* '-' => left justify */ + break; + case _T('+'): + flags |= FL_SIGN; /* '+' => force sign indicator */ + break; + case _T(' '): + flags |= FL_SIGNSP; /* ' ' => force sign or space */ + break; + case _T('#'): + flags |= FL_ALTERNATE; /* '#' => alternate form */ + break; + case _T('0'): + flags |= FL_LEADZERO; /* '0' => pad with leading zeros */ + break; + } + break; + + case ST_WIDTH: + /* update width value */ + if (ch == _T('*')) { + /* get width from arg list */ + fldwidth = get_int_arg(&argptr); + if (fldwidth < 0) { + /* ANSI says neg fld width means '-' flag and pos width */ + flags |= FL_LEFT; + fldwidth = -fldwidth; + } + } + else { + /* add digit to current field width */ + fldwidth = fldwidth * 10 + (ch - _T('0')); + } + break; + + case ST_DOT: + /* zero the precision, since dot with no number means 0 + not default, according to ANSI */ + precision = 0; + break; + + case ST_PRECIS: + /* update precison value */ + if (ch == _T('*')) { + /* get precision from arg list */ + precision = get_int_arg(&argptr); + if (precision < 0) + precision = -1; /* neg precision means default */ + } + else { + /* add digit to current precision */ + precision = precision * 10 + (ch - _T('0')); + } + break; + + case ST_SIZE: + /* just read a size specifier, set the flags based on it */ + switch (ch) { + case _T('l'): + /* + * In order to handle the ll case, we depart from the + * simple deterministic state machine. + */ + if (*format == _T('l')) + { + ++format; + flags |= FL_LONGLONG; /* 'll' => long long */ + } + else + { + flags |= FL_LONG; /* 'l' => long int or char16_t */ + } + break; + + case _T('I'): + /* + * In order to handle the I, I32, and I64 size modifiers, we + * depart from the simple deterministic state machine. The + * code below scans for characters following the 'I', + * and defaults to 64 bit on WIN64 and 32 bit on WIN32 + */ +#if PTR_IS_INT64 + flags |= FL_I64; /* 'I' => __int64 on WIN64 systems */ +#endif /* PTR_IS_INT64 */ + if ( (*format == _T('6')) && (*(format + 1) == _T('4')) ) + { + format += 2; + flags |= FL_I64; /* I64 => __int64 */ + } + else if ( (*format == _T('3')) && (*(format + 1) == _T('2')) ) + { + format += 2; + flags &= ~FL_I64; /* I32 => __int32 */ + } + else if ( (*format == _T('d')) || + (*format == _T('i')) || + (*format == _T('o')) || + (*format == _T('u')) || + (*format == _T('x')) || + (*format == _T('X')) ) + { + /* + * Nothing further needed. %Id (et al) is + * handled just like %d, except that it defaults to 64 bits + * on WIN64. Fall through to the next iteration. + */ + } + else { + state = ST_NORMAL; + goto NORMAL_STATE; + } + break; + + case _T('h'): + flags |= FL_SHORT; /* 'h' => short int or char */ + break; + + case _T('w'): + flags |= FL_WIDECHAR; /* 'w' => wide character */ + break; + + } + break; + + case ST_TYPE: + /* we have finally read the actual type character, so we */ + /* now format and "print" the output. We use a big switch */ + /* statement that sets 'text' to point to the text that should */ + /* be printed, and 'textlen' to the length of this text. */ + /* Common code later on takes care of justifying it and */ + /* other miscellaneous chores. Note that cases share code, */ + /* in particular, all integer formatting is done in one place. */ + /* Look at those funky goto statements! */ + + switch (ch) { + + case _T('C'): /* ISO wide character */ + if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR))) +#ifdef _UNICODE + flags |= FL_SHORT; +#else /* _UNICODE */ + flags |= FL_WIDECHAR; /* ISO std. */ +#endif /* _UNICODE */ + /* fall into 'c' case */ + + case _T('c'): { + /* print a single character specified by int argument */ +#ifdef _UNICODE + bufferiswide = 1; + wchar = (char16_t) get_int_arg(&argptr); + if (flags & FL_SHORT) { + /* format multibyte character */ + /* this is an extension of ANSI */ + char tempchar[2]; + { + tempchar[0] = (char)(wchar & 0x00ff); + tempchar[1] = '\0'; + } + + if (_MBTOWC(buffer.wz,tempchar, MB_CUR_MAX) < 0) + { + /* ignore if conversion was unsuccessful */ + no_output = 1; + } + } else { + buffer.wz[0] = wchar; + } + text.wz = buffer.wz; + textlen = 1; /* print just a single character */ +#else /* _UNICODE */ + if (flags & (FL_LONG|FL_WIDECHAR)) { + wchar = (char16_t) get_short_arg(&argptr); + no_output = 1; + } else { + /* format multibyte character */ + /* this is an extension of ANSI */ + unsigned short temp; + wchar = (char16_t)get_int_arg(&argptr); + temp = (unsigned short)wchar; + { + buffer.sz[0] = (char) temp; + textlen = 1; + } + } + text.sz = buffer.sz; +#endif /* _UNICODE */ + } + break; + + case _T('Z'): { + /* print a Counted String */ + struct _count_string { + short Length; + short MaximumLength; + char *Buffer; + } *pstr; + + pstr = (struct _count_string *)get_ptr_arg(&argptr); + if (pstr == NULL || pstr->Buffer == NULL) { + /* null ptr passed, use special string */ + text.sz = __nullstring; + textlen = (int)strlen(text.sz); + } else { + if (flags & FL_WIDECHAR) { + text.wz = (char16_t *)pstr->Buffer; + textlen = pstr->Length / (int)sizeof(char16_t); + bufferiswide = 1; + } else { + bufferiswide = 0; + text.sz = pstr->Buffer; + textlen = pstr->Length; + } + } + } + break; + + case _T('S'): /* ISO wide character string */ +#ifndef _UNICODE + if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR))) + flags |= FL_WIDECHAR; +#else /* _UNICODE */ + if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR))) + flags |= FL_SHORT; +#endif /* _UNICODE */ + + case _T('s'): { + /* print a string -- */ + /* ANSI rules on how much of string to print: */ + /* all if precision is default, */ + /* min(precision, length) if precision given. */ + /* prints '(null)' if a null string is passed */ + + int i; + const char *p; /* temps */ + const char16_t *pwch; + + /* At this point it is tempting to use strlen(), but */ + /* if a precision is specified, we're not allowed to */ + /* scan past there, because there might be no null */ + /* at all. Thus, we must do our own scan. */ + + i = (precision == -1) ? INT_MAX : precision; + text.sz = (char *)get_ptr_arg(&argptr); + + /* scan for null upto i characters */ +#ifdef _UNICODE + if (flags & FL_SHORT) { + if (text.sz == NULL) /* NULL passed, use special string */ + text.sz = __nullstring; + p = text.sz; + for (textlen=0; textlen MAXPRECISION) + precision = MAXPRECISION; + + if (precision > BUFFERSIZE - _CVTBUFSIZE) { + precision = BUFFERSIZE - _CVTBUFSIZE; + } + + /* for safecrt, we pass along the FL_ALTERNATE flag to _safecrt_cfltcvt */ + if (flags & FL_ALTERNATE) + { + capexp |= FL_ALTERNATE; + } + + _CRT_DOUBLE tmp; + tmp=va_arg(argptr, _CRT_DOUBLE); + /* Note: assumes ch is in ASCII range */ + /* In safecrt, we provide a special version of _cfltcvt which internally calls printf (see safecrt_output_s.c) */ + _CFLTCVT(&tmp, buffer.sz, buffersize, (char)ch, precision, capexp); + + /* check if result was negative, save '-' for later */ + /* and point to positive part (this is for '0' padding) */ + if (*text.sz == '-') { + flags |= FL_NEGATIVE; + ++text.sz; + } + + textlen = (int)strlen(text.sz); /* compute length of text */ + } + break; + + case _T('d'): + case _T('i'): + /* signed decimal output */ + flags |= FL_SIGNED; + radix = 10; + goto COMMON_INT; + + case _T('u'): + radix = 10; + goto COMMON_INT; + + case _T('p'): + /* write a pointer -- this is like an integer or long */ + /* except we force precision to pad with zeros and */ + /* output in big hex. */ + + precision = 2 * sizeof(void *); /* number of hex digits needed */ +#if PTR_IS_INT64 + 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 */ + /* DROP THROUGH to hex formatting */ + + case _T('X'): + /* unsigned upper hex output */ + hexadd = _T('A') - _T('9') - 1; /* set hexadd for uppercase hex */ + goto COMMON_HEX; + + case _T('x'): + /* unsigned lower hex output */ + hexadd = _T('a') - _T('9') - 1; /* set hexadd for lowercase hex */ + /* DROP THROUGH TO COMMON_HEX */ + + COMMON_HEX: + radix = 16; + if (flags & FL_ALTERNATE) { + /* alternate form means '0x' prefix */ + prefix[0] = _T('0'); + prefix[1] = (TCHAR)(_T('x') - _T('a') + _T('9') + 1 + hexadd); /* 'x' or 'X' */ + prefixlen = 2; + } + goto COMMON_INT; + + case _T('o'): + /* unsigned octal output */ + radix = 8; + if (flags & FL_ALTERNATE) { + /* alternate form means force a leading 0 */ + flags |= FL_FORCEOCTAL; + } + /* DROP THROUGH to COMMON_INT */ + + COMMON_INT: { + /* This is the general integer formatting routine. */ + /* Basically, we get an argument, make it positive */ + /* if necessary, and convert it according to the */ + /* correct radix, setting text and textlen */ + /* appropriately. */ + +#if _INTEGRAL_MAX_BITS >= 64 +// unsigned __int64 number; /* number to convert */ + uint64_t number; /* number to convert */ + int digit; /* ascii value of digit */ + __int64 l; /* temp long value */ +#else /* _INTEGRAL_MAX_BITS >= 64 */ + unsigned long number; /* number to convert */ + int digit; /* ascii value of digit */ + long l; /* temp long value */ +#endif /* _INTEGRAL_MAX_BITS >= 64 */ + + /* 1. read argument into l, sign extend as needed */ +#if _INTEGRAL_MAX_BITS >= 64 + if (flags & FL_I64) + l = get_int64_arg(&argptr); + else +#endif /* _INTEGRAL_MAX_BITS >= 64 */ + + if (flags & FL_LONGLONG) + l = get_long_long_arg(&argptr); + else + +#if !LONG_IS_INT + if (flags & FL_LONG) + l = get_long_arg(&argptr); + else +#endif /* !LONG_IS_INT */ + +#if !SHORT_IS_INT + if (flags & FL_SHORT) { + if (flags & FL_SIGNED) + l = (short) get_int_arg(&argptr); /* sign extend */ + else + l = (unsigned short) get_int_arg(&argptr); /* zero-extend*/ + + } else +#endif /* !SHORT_IS_INT */ + { + if (flags & FL_SIGNED) + l = get_int_arg(&argptr); /* sign extend */ + else + l = (unsigned int) get_int_arg(&argptr); /* zero-extend*/ + + } + + /* 2. check for negative; copy into number */ + if ( (flags & FL_SIGNED) && l < 0) { + number = -l; + flags |= FL_NEGATIVE; /* remember negative sign */ + } else { + number = l; + } + +#if _INTEGRAL_MAX_BITS >= 64 + if ( (flags & FL_I64) == 0 && (flags & FL_LONGLONG) == 0 ) { + /* + * Unless printing a full 64-bit value, insure values + * here are not in cananical longword format to prevent + * the sign extended upper 32-bits from being printed. + */ + number &= 0xffffffff; + } +#endif /* _INTEGRAL_MAX_BITS >= 64 */ + + /* 3. check precision value for default; non-default */ + /* turns off 0 flag, according to ANSI. */ + if (precision < 0) + precision = 1; /* default precision */ + else { + flags &= ~FL_LEADZERO; + if (precision > MAXPRECISION) + precision = MAXPRECISION; + } + + /* 4. Check if data is 0; if so, turn off hex prefix */ + if (number == 0) + prefixlen = 0; + + /* 5. Convert data to ASCII -- note if precision is zero */ + /* and number is zero, we get no digits at all. */ + + char *sz; + sz = &buffer.sz[BUFFERSIZE-1]; /* last digit at end of buffer */ + + while (precision-- > 0 || number != 0) { + digit = (int)(number % radix) + '0'; + number /= radix; /* reduce number */ + if (digit > '9') { + /* a hex digit, make it a letter */ + digit += hexadd; + } + *sz-- = (char)digit; /* store the digit */ + } + + textlen = (int)((char *)&buffer.sz[BUFFERSIZE-1] - sz); /* compute length of number */ + ++sz; /* text points to first digit now */ + + + /* 6. Force a leading zero if FORCEOCTAL flag set */ + if ((flags & FL_FORCEOCTAL) && (textlen == 0 || sz[0] != '0')) { + *--sz = '0'; + ++textlen; /* add a zero */ + } + + text.sz = sz; + } + break; + } + + + /* At this point, we have done the specific conversion, and */ + /* 'text' points to text to print; 'textlen' is length. Now we */ + /* justify it, put on prefixes, leading zeros, and then */ + /* print it. */ + + if (!no_output) { + int padding; /* amount of padding, negative means zero */ + + if (flags & FL_SIGNED) { + if (flags & FL_NEGATIVE) { + /* prefix is a '-' */ + prefix[0] = _T('-'); + prefixlen = 1; + } + else if (flags & FL_SIGN) { + /* prefix is '+' */ + prefix[0] = _T('+'); + prefixlen = 1; + } + else if (flags & FL_SIGNSP) { + /* prefix is ' ' */ + prefix[0] = _T(' '); + prefixlen = 1; + } + } + + /* calculate amount of padding -- might be negative, */ + /* but this will just mean zero */ + padding = fldwidth - textlen - prefixlen; + + /* put out the padding, prefix, and text, in the correct order */ + + if (!(flags & (FL_LEFT | FL_LEADZERO))) { + /* pad on left with blanks */ + WRITE_MULTI_CHAR(_T(' '), padding, &charsout); + } + + /* write prefix */ + WRITE_STRING(prefix, prefixlen, &charsout); + + if ((flags & FL_LEADZERO) && !(flags & FL_LEFT)) { + /* write leading zeros */ + WRITE_MULTI_CHAR(_T('0'), padding, &charsout); + } + + /* write text */ +#ifndef _UNICODE + if (bufferiswide && (textlen > 0)) { + charsout = -1; + } else { + WRITE_STRING(text.sz, textlen, &charsout); + } +#else /* _UNICODE */ + if (!bufferiswide && textlen > 0) { + char *p; + int retval = 0 + int count; + + p = text.sz; + count = textlen; + while (count-- > 0) { + retval = _MBTOWC(&wchar, p, MB_CUR_MAX); + if (retval <= 0) { + charsout = -1; + break; + } + WRITE_CHAR(wchar, &charsout); + p += retval; + } + } else { + WRITE_STRING(text.wz, textlen, &charsout); + } +#endif /* _UNICODE */ + + if (charsout >= 0 && (flags & FL_LEFT)) { + /* pad on right with blanks */ + WRITE_MULTI_CHAR(_T(' '), padding, &charsout); + } + + /* we're done! */ + } + break; + } + } + +#ifdef FORMAT_VALIDATIONS + /* The format string shouldn't be incomplete - i.e. when we are finished + with the format string, the last thing we should have encountered + should have been a regular char to be output or a type specifier. Else + the format string was incomplete */ + _VALIDATE_RETURN(((state == ST_NORMAL) || (state == ST_TYPE)), EINVAL, -1); +#endif /* FORMAT_VALIDATIONS */ + + return charsout; /* return value = number of characters written */ +} + +/* + * Future Optimizations for swprintf: + * - Don't free the memory used for converting the buffer to wide chars. + * Use realloc if the memory is not sufficient. Free it at the end. + */ + +/*** +*void write_char(char ch, int *pnumwritten) +*ifdef _UNICODE +*void write_char(char16_t ch, FILE *f, int *pnumwritten) +*endif +*void write_char(char ch, FILE *f, int *pnumwritten) +* +*Purpose: +* Writes a single character to the given file/console. If no error occurs, +* then *pnumwritten is incremented; otherwise, *pnumwritten is set +* to -1. +* +*Entry: +* _TCHAR ch - character to write +* FILE *f - file to write to +* int *pnumwritten - pointer to integer to update with total chars written +* +*Exit: +* No return value. +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef CPRFLAG + +LOCAL(void) write_char ( + _TCHAR ch, + int *pnumwritten + ) +{ +#ifdef _UNICODE + if (_putwch_nolock(ch) == WEOF) +#else /* _UNICODE */ + if (_putch_nolock(ch) == EOF) +#endif /* _UNICODE */ + *pnumwritten = -1; + else + ++(*pnumwritten); +} + +#else /* CPRFLAG */ + +LOCAL(void) write_char ( + _TCHAR ch, + miniFILE *f, + int *pnumwritten + ) +{ + if ( (f->_flag & _IOSTRG) && f->_base == NULL) + { + ++(*pnumwritten); + return; + } +#ifdef _UNICODE + if (_putwc_nolock(ch, f) == WEOF) +#else /* _UNICODE */ + if (_putc_nolock(ch, f) == EOF) +#endif /* _UNICODE */ + *pnumwritten = -1; + else + ++(*pnumwritten); +} + +#endif /* CPRFLAG */ + +/*** +*void write_multi_char(char ch, int num, int *pnumwritten) +*ifdef _UNICODE +*void write_multi_char(char16_t ch, int num, FILE *f, int *pnumwritten) +*endif +*void write_multi_char(char ch, int num, FILE *f, int *pnumwritten) +* +*Purpose: +* Writes num copies of a character to the given file/console. If no error occurs, +* then *pnumwritten is incremented by num; otherwise, *pnumwritten is set +* to -1. If num is negative, it is treated as zero. +* +*Entry: +* _TCHAR ch - character to write +* int num - number of times to write the characters +* FILE *f - file to write to +* int *pnumwritten - pointer to integer to update with total chars written +* +*Exit: +* No return value. +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef CPRFLAG +LOCAL(void) write_multi_char ( + _TCHAR ch, + int num, + int *pnumwritten + ) +{ + while (num-- > 0) { + write_char(ch, pnumwritten); + if (*pnumwritten == -1) + break; + } +} + +#else /* CPRFLAG */ + +LOCAL(void) write_multi_char ( + _TCHAR ch, + int num, + miniFILE *f, + int *pnumwritten + ) +{ + while (num-- > 0) { + write_char(ch, f, pnumwritten); + if (*pnumwritten == -1) + break; + } +} + +#endif /* CPRFLAG */ + +/*** +*void write_string(const char *string, int len, int *pnumwritten) +*void write_string(const char *string, int len, FILE *f, int *pnumwritten) +*ifdef _UNICODE +*void write_string(const char16_t *string, int len, FILE *f, int *pnumwritten) +*endif +*void write_wstring(const char16_t *string, int len, int *pnumwritten) +*void write_wstring(const char16_t *string, int len, FILE *f, int *pnumwritten) +* +*Purpose: +* Writes a string of the given length to the given file. If no error occurs, +* then *pnumwritten is incremented by len; otherwise, *pnumwritten is set +* to -1. If len is negative, it is treated as zero. +* +*Entry: +* _TCHAR *string - string to write (NOT null-terminated) +* int len - length of string +* FILE *f - file to write to +* int *pnumwritten - pointer to integer to update with total chars written +* +*Exit: +* No return value. +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef CPRFLAG + +LOCAL(void) write_string ( + const _TCHAR *string, + int len, + int *pnumwritten + ) +{ + while (len-- > 0) { + write_char(*string++, pnumwritten); + if (*pnumwritten == -1) + { + if (errno == EILSEQ) + write_char(_T('?'), pnumwritten); + else + break; + } + } +} + +#else /* CPRFLAG */ + +LOCAL(void) write_string ( + const _TCHAR *string, + int len, + miniFILE *f, + int *pnumwritten + ) +{ + if ( (f->_flag & _IOSTRG) && f->_base == NULL) + { + (*pnumwritten) += len; + return; + } + while (len-- > 0) { + write_char(*string++, f, pnumwritten); + if (*pnumwritten == -1) + { + if (errno == EILSEQ) + write_char(_T('?'), f, pnumwritten); + else + break; + } + } +} +#endif /* CPRFLAG */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_output_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_output_s.cpp new file mode 100644 index 0000000..c3e7f91 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_output_s.cpp @@ -0,0 +1,46 @@ +// 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. + +/*** +*safecrt_output_s.c - implementation of the _output family for safercrt.lib +* + +* +*Purpose: +* This file contains the implementation of the _output family for safercrt.lib. +* +*Revision History: +* 07-08-04 SJ Stub module created. +* 07-13-04 AC Added support for floating-point types. +* 07-29-04 AC Added macros for a safecrt version of mctowc and wctomb, which target ntdll.dll or msvcrt.dll +* based on the _NTSUBSET_ #define +* 09-24-04 MSL Prefix disallow NULL deref +* +****/ + +#define _SAFECRT_IMPL + +#define __STDC_LIMIT_MACROS +#include "pal/palinternal.h" +#include +#include +#include +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define FORMAT_VALIDATIONS +#define _CFLTCVT _safecrt_cfltcvt + +#define _TCHAR CRT_TCHAR +#define TCHAR CRTTCHAR + +typedef char _TCHAR; +typedef char TCHAR; +#define _T(x) x + +#include "output.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_winput_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_winput_s.cpp new file mode 100644 index 0000000..459a9b5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_winput_s.cpp @@ -0,0 +1,55 @@ +// 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. + +/*** +*safecrt_winput_s.c - implementation of the _winput family for safecrt.lib +* + +* +*Purpose: +* This file contains the implementation of the _winput family for safecrt.lib. +* +*Revision History: +* 07/19/04 AC Created +* +****/ + + +#ifndef _UNICODE /* CRT flag */ +#define _UNICODE 1 +#endif + +#ifndef UNICODE /* NT flag */ +#define UNICODE 1 +#endif + +#define _SAFECRT_IMPL +#define _SECURE_SCANF + +#include "pal/palinternal.h" +#include +#include +#include +#include +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _TCHAR CRT_TCHAR +#define TCHAR CRTTCHAR + +typedef char16_t _TCHAR; +typedef char16_t TCHAR; +typedef char16_t _TUCHAR; +#define _T(x) x +#define _TEOF WEOF + +#define _gettc_nolock(x) _getwc_nolock(x) +#define _ungettc_nolock(x,y) _ungetwc_nolock(x,y) + +#include "input.inl" + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_woutput_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_woutput_s.cpp new file mode 100644 index 0000000..814a19d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/safecrt_woutput_s.cpp @@ -0,0 +1,59 @@ +// 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. + +/*** +*safecrt_woutput_s.c - implementation of the _woutput family for safercrt.lib +* + +* +*Purpose: +* This file contains the implementation of the _woutput family for safercrt.lib. +* +*Revision History: +* 07-08-04 SJ Stub module created. +* 07-13-04 AC Added support for floating-point types. +* 07-29-04 AC Added macros for a safecrt version of mctowc and wctomb, which target ntdll.dll or msvcrt.dll +* based on the _NTSUBSET_ #define +* +****/ + +#define _SAFECRT_IMPL + +#define __STDC_LIMIT_MACROS + +#include "pal/palinternal.h" +#include +#include +#include +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#ifndef _UNICODE /* CRT flag */ +#define _UNICODE 1 +#endif + +#ifndef UNICODE /* NT flag */ +#define UNICODE 1 +#endif + +#define FORMAT_VALIDATIONS +#if defined(_NTSUBSET_) +#define _MBTOWC _safecrt_mbtowc +#endif +#define _WCTOMB_S _safecrt_wctomb_s +#define _CFLTCVT _safecrt_cfltcvt +#define _CLDCVT _safecrt_cldcvt + +#define _TCHAR CRT_TCHAR +#define TCHAR CRTTCHAR + +typedef char16_t _TCHAR; +typedef char16_t TCHAR; +#define _T(x) L##x + +#include "output.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/snprintf.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/snprintf.cpp new file mode 100644 index 0000000..dea8716 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/snprintf.cpp @@ -0,0 +1,18 @@ +// 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. + +/*** +*snprintf.c - "Count" version of sprintf +* + +* +*Purpose: +* The sprintf_s() flavor takes a count argument that is +* the max number of bytes that should be written to the +* user's buffer. +* +*******************************************************************************/ + +#define _COUNT_ 1 +#include "sprintf.c" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/splitpath_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/splitpath_s.cpp new file mode 100644 index 0000000..cb8a364 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/splitpath_s.cpp @@ -0,0 +1,31 @@ +// 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. + +/*** +*splitpath_s.c - break down path name into components +* + +* +*Purpose: +* To provide support for accessing the individual components of an +* arbitrary path name +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _FUNC_PROLOGUE +#define _FUNC_NAME _splitpath_s +#define _CHAR char +#define _TCSNCPY_S strncpy_s +#define _T(_Character) _Character + +#define _MBS_SUPPORT 0 + +#include "tsplitpath_s.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/sprintf_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/sprintf_s.cpp new file mode 100644 index 0000000..79a4e43 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/sprintf_s.cpp @@ -0,0 +1,97 @@ +// 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. + +/*** +*sprintf_s.c - print formatted to string +* + +* +*Purpose: +* defines sprintf_s() and _snprintf_s() - print formatted data to string +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + + +/*** +*ifndef _COUNT_ +*int sprintf_s(string, format, ...) - print formatted data to string +*else +*int _snprintf_s(string, cnt, format, ...) - print formatted data to string +*endif +* +*Purpose: +* Prints formatted data to the using the format string to +* format data and getting as many arguments as called for +* Sets up a FILE so file i/o operations can be used, make +* string look like a huge buffer to it, but _flsbuf will +* refuse to flush it if it fills up. Appends '\0' to make +* it a true string. _output does the real work here +* +* Allocate the 'fake' _iob[] entry statically instead of on +* the stack so that other routines can assume that _iob[] +* entries are in are in DGROUP and, thus, are near. +* +*ifdef _COUNT_ +* 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 +* +* 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) Also, since there is only one statically +* allocated 'fake' iob, we must lock/unlock to prevent collisions. +* +*Entry: +* char *string - pointer to place to put output +*ifdef _COUNT_ +* size_t count - max number of bytes to put in buffer +*endif +* char *format - format string to control data format/number +* of arguments followed by list of arguments, number and type +* controlled by format string +* +*Exit: +* returns number of characters printed +* +*Exceptions: +* +*******************************************************************************/ +DLLEXPORT int sprintf_s ( + char *string, + size_t sizeInBytes, + const char *format, + ... + ) +{ + int ret; + va_list arglist; + va_start(arglist, format); + ret = vsprintf_s(string, sizeInBytes, format, arglist); + va_end(arglist); + return ret; +} + +DLLEXPORT int _snprintf_s ( + char *string, + size_t sizeInBytes, + size_t count, + const char *format, + ... + ) +{ + int ret; + va_list arglist; + va_start(arglist, format); + ret = _vsnprintf_s(string, sizeInBytes, count, format, arglist); + va_end(arglist); + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/sscanf_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/sscanf_s.cpp new file mode 100644 index 0000000..39c8ce3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/sscanf_s.cpp @@ -0,0 +1,218 @@ +// 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. + +/*** +*sscanf_s.c - read formatted data from string +* + +* +*Purpose: +* defines scanf() - reads formatted data from string +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +typedef int (*INPUTFN)(miniFILE *, const unsigned char*, va_list); +typedef int (*WINPUTFN)(miniFILE *, const char16_t*, va_list); +extern size_t PAL_wcsnlen(const WCHAR* inString, size_t inMaxSize); + +/*** +*static int v[nw]scan_fn([w]inputfn, string, [count], format, ...) +* +*Purpose: +* this is a helper function which is called by the other functions +* in this file - sscanf/swscanf/snscanf etc. It calls either _(w)input or +* _(w)input_s depending on the first parameter. +* +*******************************************************************************/ + +static int __cdecl vscan_fn ( + INPUTFN inputfn, + const char *string, + const char *format, + va_list arglist + ) +{ + miniFILE str; + miniFILE *infile = &str; + int retval; + size_t count = strlen(string); + + _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); + _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); + + infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; + infile->_ptr = infile->_base = (char *) string; + + if(count>(INT_MAX/sizeof(char))) + { + /* old-style functions allow any large value to mean unbounded */ + infile->_cnt = INT_MAX; + } + else + { + infile->_cnt = (int)count*sizeof(char); + } + + retval = (inputfn(infile, ( const unsigned char* )format, arglist)); + + return(retval); +} + +static int __cdecl vnscan_fn ( + INPUTFN inputfn, + const char *string, + size_t count, + const char *format, + va_list arglist + ) +{ + miniFILE str; + miniFILE *infile = &str; + int retval; + size_t length = strlen(string); + + _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); + _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); + + infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; + infile->_ptr = infile->_base = (char *) string; + + if ( count > length ) + { + count = length; + } + + if(count>(INT_MAX/sizeof(char))) + { + /* old-style functions allow any large value to mean unbounded */ + infile->_cnt = INT_MAX; + } + else + { + infile->_cnt = (int)count*sizeof(char); + } + + retval = (inputfn(infile, ( const unsigned char* )format, arglist)); + + return(retval); +} + +static int __cdecl vwscan_fn ( + WINPUTFN inputfn, + const char16_t *string, + const char16_t *format, + va_list arglist + ) +{ + miniFILE str; + miniFILE *infile = &str; + int retval; + size_t count = PAL_wcsnlen(string, INT_MAX); + + _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); + _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); + + infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; + infile->_ptr = infile->_base = (char *) string; + + if(count>(INT_MAX/sizeof(char16_t))) + { + /* old-style functions allow any large value to mean unbounded */ + infile->_cnt = INT_MAX; + } + else + { + infile->_cnt = (int)count*sizeof(char16_t); + } + + retval = (inputfn(infile, format, arglist)); + + return(retval); +} + +static int __cdecl vnwscan_fn ( + WINPUTFN inputfn, + const char16_t *string, + size_t count, + const char16_t *format, + va_list arglist + ) +{ + miniFILE str; + miniFILE *infile = &str; + int retval; + size_t length = PAL_wcsnlen(string, INT_MAX); + + _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); + _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); + + infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; + infile->_ptr = infile->_base = (char *) string; + + if ( count > length ) + { + count = length; + } + + if(count>(INT_MAX/sizeof(char16_t))) + { + /* old-style functions allow any large value to mean unbounded */ + infile->_cnt = INT_MAX; + } + else + { + infile->_cnt = (int)count*sizeof(char16_t); + } + + retval = (inputfn(infile, format, arglist)); + + return(retval); +} + + +/*** +*int sscanf_s(string, format, ...) +* Same as sscanf above except that it calls _input_s to do the real work. +* +*int snscanf_s(string, size, format, ...) +* Same as snscanf above except that it calls _input_s to do the real work. +* +* _input_s has a size check for array parameters. +* +*******************************************************************************/ + +DLLEXPORT int __cdecl sscanf_s ( + const char *string, + const char *format, + ... + ) +{ + int ret; + va_list arglist; + va_start(arglist, format); + ret = vscan_fn(__tinput_s, string, format, arglist); + va_end(arglist); + return ret; +} + +int __cdecl swscanf_s ( + const char16_t *string, + const char16_t *format, + ... + ) +{ + int ret; + va_list arglist; + va_start(arglist, format); + ret = vwscan_fn(__twinput_s, string, format, arglist); + va_end(arglist); + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strcat_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strcat_s.cpp new file mode 100644 index 0000000..4dc2332 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strcat_s.cpp @@ -0,0 +1,33 @@ +// 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. + +/*** +*strcat_s.c - contains strcat_s() +* + +* +*Purpose: +* strcat_s() concatenates (appends) a copy of the source string to the +* end of the destination string. +* +*******************************************************************************/ + +#define _SECURECRT_FILL_BUFFER 1 +#define _SECURECRT_FILL_BUFFER_THRESHOLD ((size_t)8) + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _FUNC_PROLOGUE +#define _FUNC_NAME strcat_s +#define _CHAR char +#define _DEST _Dst +#define _SIZE _SizeInBytes +#define _SRC _Src + +#include "tcscat_s.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strcpy_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strcpy_s.cpp new file mode 100644 index 0000000..821dbe8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strcpy_s.cpp @@ -0,0 +1,29 @@ +// 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. + +/*** +*strcpy_s.c - contains strcpy_s() +* + +* +*Purpose: +* strcpy_s() copies one string onto another. +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _FUNC_PROLOGUE +#define _FUNC_NAME strcpy_s +#define _CHAR char +#define _DEST _Dst +#define _SIZE _SizeInBytes +#define _SRC _Src + +#include "tcscpy_s.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strlen_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strlen_s.cpp new file mode 100644 index 0000000..3f1e1cf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strlen_s.cpp @@ -0,0 +1,58 @@ +// 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. + +/*** +*strlen_s.c - contains strnlen() routine +* + +* +*Purpose: +* strnlen returns the length of a null-terminated string, +* not including the null byte itself, up to the specified max size +* +*******************************************************************************/ + + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +/*** +*strnlen - return the length of a null-terminated string +* +*Purpose: +* Finds the length in bytes of the given string, not including +* the final null character. Only the first maxsize characters +* are inspected: if the null character is not found, maxsize is +* returned. +* +*Entry: +* const char * str - string whose length is to be computed +* size_t maxsize +* +*Exit: +* Length of the string "str", exclusive of the final null byte, or +* maxsize if the null character is not found. +* +*Exceptions: +* +*******************************************************************************/ + +size_t __cdecl PAL_strnlen(const char *str, size_t maxsize) +{ + size_t n; + + /* Note that we do not check if str == NULL, because we do not + * return errno_t... + */ + + for (n = 0; n < maxsize && *str; n++, str++) + ; + + return n; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strncat_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strncat_s.cpp new file mode 100644 index 0000000..ef8c6cf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strncat_s.cpp @@ -0,0 +1,31 @@ +// 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. + +/*** +*strncat_s.c - append n chars of string to new string +* + +* +*Purpose: +* defines strncat_s() - appends n characters of string onto +* end of other string +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _FUNC_PROLOGUE +#define _FUNC_NAME strncat_s +#define _CHAR char +#define _DEST _Dst +#define _SIZE _SizeInBytes +#define _SRC _Src +#define _COUNT _Count + +#include "tcsncat_s.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strncpy_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strncpy_s.cpp new file mode 100644 index 0000000..f819ebb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strncpy_s.cpp @@ -0,0 +1,30 @@ +// 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. + +/*** +*strncpy_s.c - copy at most n characters of string +* + +* +*Purpose: +* defines strncpy_s() - copy at most n characters of string +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _FUNC_PROLOGUE +#define _FUNC_NAME strncpy_s +#define _CHAR char +#define _DEST _Dst +#define _SIZE _SizeInBytes +#define _SRC _Src +#define _COUNT _Count + +#include "tcsncpy_s.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strtok_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strtok_s.cpp new file mode 100644 index 0000000..6f1c806 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/strtok_s.cpp @@ -0,0 +1,27 @@ +// 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. + +/*** +*strtok_s.c - tokenize a string with given delimiters +* + +* +*Purpose: +* defines strtok_s() - breaks string into series of token +* via repeated calls. +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _FUNC_PROLOGUE +#define _FUNC_NAME strtok_s +#define _CHAR char + +#include "tcstok_s.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/swprintf.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/swprintf.cpp new file mode 100644 index 0000000..bf0970e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/swprintf.cpp @@ -0,0 +1,120 @@ +// 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. + +/*** +*swprintf.c - print formatted to string +* +*Purpose: +* defines _swprintf(), _swprintf_c and _snwprintf() - print formatted data +* to string +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +/*** +*ifndef _COUNT_ +*int _swprintf(string, format, ...) - print formatted data to string +*else +*ifndef _SWPRINTFS_ERROR_RETURN_FIX +*int _snwprintf(string, cnt, format, ...) - print formatted data to string +*else +*int _swprintf_c(string, cnt, format, ...) - print formatted data to string +*endif +*endif +* +*Purpose: +* Prints formatted data to the using the format string to +* format data and getting as many arguments as called for +* Sets up a FILE so file i/o operations can be used, make +* string look like a huge buffer to it, but _flsbuf will +* refuse to flush it if it fills up. Appends '\0' to make +* it a true string. _output does the real work here +* +* Allocate the 'fake' _iob[] entry statically instead of on +* the stack so that other routines can assume that _iob[] +* entries are in are in DGROUP and, thus, are near. +* +* We alias swprintf to _swprintf +* +*ifdef _COUNT_ +*ifndef _SWPRINTFS_ERROR_RETURN_FIX +* The _snwprintf() flavor takes a count argument that is +* the max number of wide characters that should be written to the +* user's buffer. +* We don't expose this function directly in the headers. +*else +* The _swprintf_c() flavor does the same thing as the _snwprintf +* above, but, it also fixes a 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 _snwprintf because of backward +* compatibility. In new code, however, _snwprintf is #defined to +* _swprintf_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) Also, since there is only one statically +* allocated 'fake' iob, we must lock/unlock to prevent collisions. +* +*Entry: +* char16_t *string - pointer to place to put output +*ifdef _COUNT_ +* size_t count - max number of wide characters to put in buffer +*endif +* char16_t *format - format string to control data format/number +* of arguments followed by list of arguments, number and type +* controlled by format string +* +*Exit: +* returns number of wide characters printed +* +*Exceptions: +* +*******************************************************************************/ + +DLLEXPORT int __cdecl swprintf_s ( + char16_t *string, + size_t sizeInWords, + const char16_t *format, + ... + ) +{ + int ret; + va_list arglist; + + va_start(arglist, format); + + ret = vswprintf_s(string, sizeInWords, format, arglist); + + va_end(arglist); + + return ret; +} + +DLLEXPORT int __cdecl _snwprintf_s ( + char16_t *string, + size_t sizeInWords, + size_t count, + const char16_t *format, + ... + ) +{ + int ret; + va_list arglist; + + va_start(arglist, format); + + ret = _vsnwprintf_s(string, sizeInWords, count, format, arglist); + + va_end(arglist); + + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcscat_s.inl b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcscat_s.inl new file mode 100644 index 0000000..b6fefdc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcscat_s.inl @@ -0,0 +1,51 @@ +// 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. + +/*** +*tcscat_s.inl - general implementation of _tcscpy_s +* + +* +*Purpose: +* This file contains the general algorithm for strcat_s and its variants. +* +****/ + +_FUNC_PROLOGUE +errno_t __cdecl _FUNC_NAME(_CHAR *_DEST, size_t _SIZE, const _CHAR *_SRC) +{ + _CHAR *p; + size_t available; + + /* validation section */ + _VALIDATE_STRING(_DEST, _SIZE); + _VALIDATE_POINTER_RESET_STRING(_SRC, _DEST, _SIZE); + + p = _DEST; + available = _SIZE; + while (available > 0 && *p != 0) + { + p++; + available--; + } + + if (available == 0) + { + _RESET_STRING(_DEST, _SIZE); + _RETURN_DEST_NOT_NULL_TERMINATED(_DEST, _SIZE); + } + + while ((*p++ = *_SRC++) != 0 && --available > 0) + { + } + + if (available == 0) + { + _RESET_STRING(_DEST, _SIZE); + _RETURN_BUFFER_TOO_SMALL(_DEST, _SIZE); + } + _FILL_STRING(_DEST, _SIZE, _SIZE - available + 1); + _RETURN_NO_ERROR; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcscpy_s.inl b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcscpy_s.inl new file mode 100644 index 0000000..b1192d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcscpy_s.inl @@ -0,0 +1,39 @@ +// 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. + +/*** +*tcscpy_s.inl - general implementation of _tcscpy_s +* + +* +*Purpose: +* This file contains the general algorithm for strcpy_s and its variants. +* +****/ + +_FUNC_PROLOGUE +errno_t __cdecl _FUNC_NAME(_CHAR *_DEST, size_t _SIZE, const _CHAR *_SRC) +{ + _CHAR *p; + size_t available; + + /* validation section */ + _VALIDATE_STRING(_DEST, _SIZE); + _VALIDATE_POINTER_RESET_STRING(_SRC, _DEST, _SIZE); + + p = _DEST; + available = _SIZE; + while ((*p++ = *_SRC++) != 0 && --available > 0) + { + } + + if (available == 0) + { + _RESET_STRING(_DEST, _SIZE); + _RETURN_BUFFER_TOO_SMALL(_DEST, _SIZE); + } + _FILL_STRING(_DEST, _SIZE, _SIZE - available + 1); + _RETURN_NO_ERROR; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcsncat_s.inl b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcsncat_s.inl new file mode 100644 index 0000000..6de5017 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcsncat_s.inl @@ -0,0 +1,81 @@ +// 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. + +/*** +*tcsncat_s.inl - general implementation of _tcscpy_s +* + +* +*Purpose: +* This file contains the general algorithm for strncat_s and its variants. +* +****/ + +_FUNC_PROLOGUE +errno_t __cdecl _FUNC_NAME(_CHAR *_DEST, size_t _SIZE, const _CHAR *_SRC, size_t _COUNT) +{ + _CHAR *p; + size_t available; + + if (_COUNT == 0 && _DEST == NULL && _SIZE == 0) + { + /* this case is allowed; nothing to do */ + _RETURN_NO_ERROR; + } + + /* validation section */ + _VALIDATE_STRING(_DEST, _SIZE); + if (_COUNT != 0) + { + _VALIDATE_POINTER_RESET_STRING(_SRC, _DEST, _SIZE); + } + + p = _DEST; + available = _SIZE; + while (available > 0 && *p != 0) + { + p++; + available--; + } + + if (available == 0) + { + _RESET_STRING(_DEST, _SIZE); + _RETURN_DEST_NOT_NULL_TERMINATED(_DEST, _SIZE); + } + + if (_COUNT == _TRUNCATE) + { + while ((*p++ = *_SRC++) != 0 && --available > 0) + { + } + } + else + { + _ASSERT_EXPR((!_CrtGetCheckCount() || _COUNT < available), "Buffer is too small"); + + while (_COUNT > 0 && (*p++ = *_SRC++) != 0 && --available > 0) + { + _COUNT--; + } + if (_COUNT == 0) + { + *p = 0; + } + } + + if (available == 0) + { + if (_COUNT == _TRUNCATE) + { + _DEST[_SIZE - 1] = 0; + _RETURN_TRUNCATE; + } + _RESET_STRING(_DEST, _SIZE); + _RETURN_BUFFER_TOO_SMALL(_DEST, _SIZE); + } + _FILL_STRING(_DEST, _SIZE, _SIZE - available + 1); + _RETURN_NO_ERROR; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcsncpy_s.inl b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcsncpy_s.inl new file mode 100644 index 0000000..54a79a0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcsncpy_s.inl @@ -0,0 +1,71 @@ +// 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. + +/*** +*tcsncpy_s.inl - general implementation of _tcsncpy_s +* + +* +*Purpose: +* This file contains the general algorithm for strncpy_s and its variants. +* +****/ + +_FUNC_PROLOGUE +errno_t __cdecl _FUNC_NAME(_CHAR *_DEST, size_t _SIZE, const _CHAR *_SRC, size_t _COUNT) +{ + _CHAR *p; + size_t available; + + if (_COUNT == 0 && _DEST == NULL && _SIZE == 0) + { + /* this case is allowed; nothing to do */ + _RETURN_NO_ERROR; + } + + /* validation section */ + _VALIDATE_STRING(_DEST, _SIZE); + if (_COUNT == 0) + { + /* notice that the source string pointer can be NULL in this case */ + _RESET_STRING(_DEST, _SIZE); + _RETURN_NO_ERROR; + } + _VALIDATE_POINTER_RESET_STRING(_SRC, _DEST, _SIZE); + + p = _DEST; + available = _SIZE; + if (_COUNT == _TRUNCATE) + { + while ((*p++ = *_SRC++) != 0 && --available > 0) + { + } + } + else + { + _ASSERT_EXPR((!_CrtGetCheckCount() || _COUNT < _SIZE), "Buffer is too small"); + + while ((*p++ = *_SRC++) != 0 && --available > 0 && --_COUNT > 0) + { + } + if (_COUNT == 0) + { + *p = 0; + } + } + + if (available == 0) + { + if (_COUNT == _TRUNCATE) + { + _DEST[_SIZE - 1] = 0; + _RETURN_TRUNCATE; + } + _RESET_STRING(_DEST, _SIZE); + _RETURN_BUFFER_TOO_SMALL(_DEST, _SIZE); + } + _FILL_STRING(_DEST, _SIZE, _SIZE - available + 1); + _RETURN_NO_ERROR; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcstok_s.inl b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcstok_s.inl new file mode 100644 index 0000000..29ca5c6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tcstok_s.inl @@ -0,0 +1,71 @@ +// 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. + +/*** +*tcstok_s.inl - general implementation of _tcstok_s +* + +* +*Purpose: +* This file contains the general algorithm for strtok_s and its variants. +* +****/ + +_FUNC_PROLOGUE +_CHAR * __cdecl _FUNC_NAME(_CHAR *_String, const _CHAR *_Control, _CHAR **_Context) +{ + _CHAR *token; + const _CHAR *ctl; + + /* validation section */ + _VALIDATE_POINTER_ERROR_RETURN(_Context, EINVAL, NULL); + _VALIDATE_POINTER_ERROR_RETURN(_Control, EINVAL, NULL); + _VALIDATE_CONDITION_ERROR_RETURN(_String != NULL || *_Context != NULL, EINVAL, NULL); + + /* If string==NULL, continue with previous string */ + if (!_String) + { + _String = *_Context; + } + + /* Find beginning of token (skip over leading delimiters). Note that + * there is no token iff this loop sets string to point to the terminal null. */ + for ( ; *_String != 0 ; _String++) + { + for (ctl = _Control; *ctl != 0 && *ctl != *_String; ctl++) + ; + if (*ctl == 0) + { + break; + } + } + + token = _String; + + /* Find the end of the token. If it is not the end of the string, + * put a null there. */ + for ( ; *_String != 0 ; _String++) + { + for (ctl = _Control; *ctl != 0 && *ctl != *_String; ctl++) + ; + if (*ctl != 0) + { + *_String++ = 0; + break; + } + } + + /* Update the context */ + *_Context = _String; + + /* Determine if a token has been found. */ + if (token == _String) + { + return NULL; + } + else + { + return token; + } +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tmakepath_s.inl b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tmakepath_s.inl new file mode 100644 index 0000000..34c4842 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tmakepath_s.inl @@ -0,0 +1,116 @@ +// 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. + +/*** +*tmakepath_s.inl - general implementation of _tmakepath_s +* + +* +*Purpose: +* This file contains the general algorithm for _makepath_s and its variants. +* +*******************************************************************************/ + +_FUNC_PROLOGUE +errno_t __cdecl _FUNC_NAME(__out_ecount_z(_SIZE) _CHAR *_DEST, __in_opt size_t _SIZE, __in_z_opt const _CHAR *_Drive, __in_z_opt const _CHAR *_Dir, __in_z_opt const _CHAR *_Filename, __in_z_opt const _CHAR *_Ext) +{ + size_t written; + const _CHAR *p; + _CHAR *d; + + /* validation section */ + _VALIDATE_STRING(_DEST, _SIZE); + + /* copy drive */ + written = 0; + d = _DEST; + if (_Drive != NULL && *_Drive != 0) + { + written += 2; + if(written >= _SIZE) + { + goto error_return; + } + *d++ = *_Drive; + *d++ = _T(':'); + } + + /* copy dir */ + p = _Dir; + if (p != NULL && *p != 0) + { + do { + if(++written >= _SIZE) + { + goto error_return; + } + *d++ = *p++; + } while (*p != 0); + +#if _MBS_SUPPORT + p = _MBSDEC(_Dir, p); +#else /* _MBS_SUPPORT */ + p = p - 1; +#endif /* _MBS_SUPPORT */ + if (*p != _T('/') && *p != _T('\\')) + { + if(++written >= _SIZE) + { + goto error_return; + } + *d++ = _T('\\'); + } + } + + /* copy fname */ + p = _Filename; + if (p != NULL) + { + while (*p != 0) + { + if(++written >= _SIZE) + { + goto error_return; + } + *d++ = *p++; + } + } + + /* copy extension; check to see if a '.' needs to be inserted */ + p = _Ext; + if (p != NULL) + { + if (*p != 0 && *p != _T('.')) + { + if(++written >= _SIZE) + { + goto error_return; + } + *d++ = _T('.'); + } + while (*p != 0) + { + if(++written >= _SIZE) + { + goto error_return; + } + *d++ = *p++; + } + } + + if(++written > _SIZE) + { + goto error_return; + } + *d = 0; + _FILL_STRING(_DEST, _SIZE, written); + _RETURN_NO_ERROR; + +error_return: + _RESET_STRING(_DEST, _SIZE); + _RETURN_BUFFER_TOO_SMALL(_DEST, _SIZE); + + /* should never happen, but compiler can't tell */ + return EINVAL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tsplitpath_s.inl b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tsplitpath_s.inl new file mode 100644 index 0000000..77dd32a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/tsplitpath_s.inl @@ -0,0 +1,280 @@ +// 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. + +/*** +*tsplitpath_s.inl - general implementation of _tsplitpath_s +* + +* +*Purpose: +* This file contains the general algorithm for _splitpath_s and its variants. +* +*******************************************************************************/ + +_FUNC_PROLOGUE +errno_t __cdecl _FUNC_NAME( + __in_z const _CHAR *_Path, + __out_ecount_z_opt(_DriveSize) _CHAR *_Drive, __in size_t _DriveSize, + __out_ecount_z_opt(_DirSize) _CHAR *_Dir, __in size_t _DirSize, + __out_ecount_z_opt(_FilenameSize) _CHAR *_Filename, __in size_t _FilenameSize, + __out_ecount_z_opt(_ExtSize) _CHAR *_Ext, __in size_t _ExtSize +) +{ + const _CHAR *tmp; + const _CHAR *last_slash; + const _CHAR *dot; + int drive_set = 0; + size_t length = 0; + int bEinval = 0; + + /* validation section */ + if (_Path == NULL) + { + goto error_einval; + } + if ((_Drive == NULL && _DriveSize != 0) || (_Drive != NULL && _DriveSize == 0)) + { + goto error_einval; + } + if ((_Dir == NULL && _DirSize != 0) || (_Dir != NULL && _DirSize == 0)) + { + goto error_einval; + } + if ((_Filename == NULL && _FilenameSize != 0) || (_Filename != NULL && _FilenameSize == 0)) + { + goto error_einval; + } + if ((_Ext == NULL && _ExtSize != 0) || (_Ext != NULL && _ExtSize == 0)) + { + goto error_einval; + } + + /* check if _Path begins with the longpath prefix */ + if (_Path[0] == _T('\\') && _Path[1] == _T('\\') && _Path[2] == _T('?') && _Path[3] == _T('\\')) + { + _Path += 4; + } + + /* extract drive letter and ':', if any */ + if (!drive_set) + { +// The CorUnix PAL is never built on Windows and thus, the code below +// for the drive check is not required. +#if 0 + size_t skip = _MAX_DRIVE - 2; + tmp = _Path; + while (skip > 0 && *tmp != 0) + { + skip--; + tmp++; + } + if (*tmp == _T(':')) + { + if (_Drive != NULL) + { + if (_DriveSize < _MAX_DRIVE) + { + goto error_erange; + } + _TCSNCPY_S(_Drive, _DriveSize, _Path, _MAX_DRIVE - 1); + } + _Path = tmp + 1; + } + else +#endif + { + if (_Drive != NULL) + { + _RESET_STRING(_Drive, _DriveSize); + } + } + } + + /* extract path string, if any. _Path now points to the first character + * of the path, if any, or the filename or extension, if no path was + * specified. Scan ahead for the last occurence, if any, of a '/' or + * '\' path separator character. If none is found, there is no path. + * We will also note the last '.' character found, if any, to aid in + * handling the extension. + */ + last_slash = NULL; + dot = NULL; + tmp = _Path; + for (; *tmp != 0; ++tmp) + { +#if _MBS_SUPPORT +#pragma warning(push) +#pragma warning(disable:4127) + if (_ISMBBLEAD(*tmp)) +#pragma warning(pop) + { + tmp++; + } + else +#endif /* _MBS_SUPPORT */ + { + if (*tmp == _T('/') || *tmp == _T('\\')) + { + /* point to one beyond for later copy */ + last_slash = tmp + 1; + } + else if (*tmp == _T('.')) + { + dot = tmp; + } + } + } + + if (last_slash != NULL) + { + /* found a path - copy up through last_slash or max characters + * allowed, whichever is smaller + */ + if (_Dir != NULL) { + length = (size_t)(last_slash - _Path); + if (_DirSize <= length) + { + goto error_erange; + } + _TCSNCPY_S(_Dir, _DirSize, _Path, length); + + // Normalize the path seperator + size_t iIndex; + for(iIndex = 0; iIndex < length; iIndex++) + { + if (_Dir[iIndex] == _T('\\')) + { + _Dir[iIndex] = _T('/'); + } + } + } + _Path = last_slash; + } + else + { + /* there is no path */ + if (_Dir != NULL) + { + _RESET_STRING(_Dir, _DirSize); + } + } + + /* extract file name and extension, if any. Path now points to the + * first character of the file name, if any, or the extension if no + * file name was given. Dot points to the '.' beginning the extension, + * if any. + */ + if (dot != NULL && (dot >= _Path)) + { + /* found the marker for an extension - copy the file name up to the '.' */ + if (_Filename) + { + length = (size_t)(dot - _Path); + if (length == 0) + { + // At this time, dot will be equal to _Path if string is something like "/." + // since _path was set to last_slash, which in turn, was set to "tmp +1" + // where "tmp" is the location where "/" was found. See code above for + // clarification. + // + // For such cases, return the "." in filename buffer. + // + // Thus, if the length is zero, we know its a string like "/." and thus, we + // set length to 1 to get the "." in filename buffer. + length = 1; + } + + if (_FilenameSize <= length) + { + goto error_erange; + } + _TCSNCPY_S(_Filename, _FilenameSize, _Path, length); + } + + /* now we can get the extension - remember that tmp still points + * to the terminating NULL character of path. + */ + if (_Ext) + { + // At this time, _Path is pointing to the character after the last slash found. + // (See comments and code above for clarification). + // + // Returns extension as empty string for strings like "/.". + if (dot > _Path) + { + length = (size_t)(tmp - dot); + if (_ExtSize <= length) + { + goto error_erange; + } + + /* Since dot pointed to the ".", make sure we actually have an extension + like ".cmd" and not just ".", OR + + Confirm that its a string like "/.." - for this, return the + second "." in the extension part. + + However, for strings like "/myfile.", return empty string + in extension buffer. + */ + int fIsDir = (*(dot-1) == _T('.'))?1:0; + if (length > 1 || (length == 1 && fIsDir == 1)) + _TCSNCPY_S(_Ext, _ExtSize, dot, length); + else + _RESET_STRING(_Ext, _ExtSize); + } + else + _RESET_STRING(_Ext, _ExtSize); + } + } + else + { + /* found no extension, give empty extension and copy rest of + * string into fname. + */ + if (_Filename) + { + length = (size_t)(tmp - _Path); + if (_FilenameSize <= length) + { + goto error_erange; + } + _TCSNCPY_S(_Filename, _FilenameSize, _Path, length); + } + if (_Ext) + { + _RESET_STRING(_Ext, _ExtSize); + } + } + + _RETURN_NO_ERROR; + +error_einval: + bEinval = 1; + +error_erange: + if (_Drive != NULL && _DriveSize > 0) + { + _RESET_STRING(_Drive, _DriveSize); + } + if (_Dir != NULL && _DirSize > 0) + { + _RESET_STRING(_Dir, _DirSize); + } + if (_Filename != NULL && _FilenameSize > 0) + { + _RESET_STRING(_Filename, _FilenameSize); + } + if (_Ext != NULL && _ExtSize > 0) + { + _RESET_STRING(_Ext, _ExtSize); + } + + _VALIDATE_POINTER(_Path); + if (bEinval) + { + _RETURN_EINVAL; + } + return (errno = ERANGE); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/vsprintf.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/vsprintf.cpp new file mode 100644 index 0000000..6d4b786 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/vsprintf.cpp @@ -0,0 +1,268 @@ +// 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. + +/*** +*vsprintf.c - print formatted data into a string from var arg list +* + +* +*Purpose: +* defines vsprintf(), _vsnprintf() and _vsnprintf_s() - print formatted output to +* a string, get the data from an argument ptr instead of explicit +* arguments. +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +typedef int (*OUTPUTFN)(miniFILE *, const char *, va_list); + +static int _vsnprintf_helper( OUTPUTFN outfn, char *string, size_t count, const char *format, va_list ap ); +static int _vscprintf_helper ( OUTPUTFN outfn, const char *format, va_list ap); + +/*** +*ifndef _COUNT_ +*int vsprintf(string, format, ap) - print formatted data to string from arg ptr +*else +*int _vsnprintf(string, cnt, format, ap) - print formatted data to string from arg ptr +*endif +* +*Purpose: +* Prints formatted data, but to a string and gets data from an argument +* pointer. +* Sets up a FILE so file i/o operations can be used, make string look +* like a huge buffer to it, but _flsbuf will refuse to flush it if it +* fills up. Appends '\0' to make it a true string. +* +* Allocate the 'fake' _iob[] entryit statically instead of on +* the stack so that other routines can assume that _iob[] entries are in +* are in DGROUP and, thus, are near. +* +*ifdef _COUNT_ +* The _vsnprintf() flavor takes a count argument that is +* the max number of bytes that should be written to the +* user's buffer. +*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) +* Also, since there is only one staticly allocated 'fake' iob, we must +* lock/unlock to prevent collisions. +* +*Entry: +* char *string - place to put destination string +*ifdef _COUNT_ +* size_t count - max number of bytes to put in buffer +*endif +* char *format - format string, describes format of data +* va_list ap - varargs argument pointer +* +*Exit: +* returns number of characters in string +* returns -2 if the string has been truncated (only in _vsnprintf_helper) +* returns -1 in other error cases +* +*Exceptions: +* +*******************************************************************************/ + +int __cdecl _vsnprintf_helper ( + OUTPUTFN outfn, + char *string, + size_t count, + const char *format, + va_list ap + ) +{ + miniFILE str; + miniFILE *outfile = &str; + int retval; + + _VALIDATE_RETURN( (format != NULL), EINVAL, -1); + + _VALIDATE_RETURN( (count == 0) || (string != NULL), EINVAL, -1 ); + + if(count>INT_MAX) + { + /* old-style functions allow any large value to mean unbounded */ + outfile->_cnt = INT_MAX; + } + else + { + outfile->_cnt = (int)count; + } + + outfile->_flag = _IOWRT|_IOSTRG; + outfile->_ptr = outfile->_base = string; + + retval = outfn(outfile, format, ap ); + + if ( string==NULL) + return(retval); + + if((retval >= 0) && (_putc_nolock('\0',outfile) != EOF)) + return(retval); + + string[count - 1] = 0; + + if (outfile->_cnt < 0) + { + /* the buffer was too small; we return -2 to indicate truncation */ + return -2; + } + return -1; +} + +DLLEXPORT int __cdecl vsprintf_s ( + char *string, + size_t sizeInBytes, + const char *format, + va_list ap + ) +{ + int retvalue = -1; + + /* validation section */ + _VALIDATE_RETURN(format != NULL, EINVAL, -1); + _VALIDATE_RETURN(string != NULL && sizeInBytes > 0, EINVAL, -1); + + retvalue = _vsnprintf_helper(_output_s, string, sizeInBytes, format, ap); + if (retvalue < 0) + { + string[0] = 0; + _SECURECRT__FILL_STRING(string, sizeInBytes, 1); + } + if (retvalue == -2) + { + _VALIDATE_RETURN(("Buffer too small" && 0), ERANGE, -1); + } + if (retvalue >= 0) + { + _SECURECRT__FILL_STRING(string, sizeInBytes, retvalue + 1); + } + + return retvalue; +} + +DLLEXPORT int __cdecl _vsnprintf_s ( + char *string, + size_t sizeInBytes, + size_t count, + const char *format, + va_list ap + ) +{ + int retvalue = -1; + errno_t save_errno = 0; + + /* validation section */ + _VALIDATE_RETURN(format != NULL, EINVAL, -1); + if (count == 0 && string == NULL && sizeInBytes == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + _VALIDATE_RETURN(string != NULL && sizeInBytes > 0, EINVAL, -1); + + if (sizeInBytes > count) + { + save_errno = errno; + retvalue = _vsnprintf_helper(_output_s, string, count + 1, format, ap); + if (retvalue == -2) + { + /* the string has been truncated, return -1 */ + _SECURECRT__FILL_STRING(string, sizeInBytes, count + 1); + if (errno == ERANGE) + { + errno = save_errno; + } + return -1; + } + } + else /* sizeInBytes <= count */ + { + save_errno = errno; + retvalue = _vsnprintf_helper(_output_s, string, sizeInBytes, format, ap); + string[sizeInBytes - 1] = 0; + /* we allow truncation if count == _TRUNCATE */ + if (retvalue == -2 && count == _TRUNCATE) + { + if (errno == ERANGE) + { + errno = save_errno; + } + return -1; + } + } + + if (retvalue < 0) + { + string[0] = 0; + _SECURECRT__FILL_STRING(string, sizeInBytes, 1); + if (retvalue == -2) + { + _VALIDATE_RETURN(("Buffer too small" && 0), ERANGE, -1); + } + return -1; + } + + _SECURECRT__FILL_STRING(string, sizeInBytes, retvalue + 1); + + return (retvalue < 0 ? -1 : retvalue); +} + +/*** +* _vscprintf() - counts the number of character needed to print the formatted +* data +* +*Purpose: +* Counts the number of characters in the fotmatted data. +* +*Entry: +* char *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 _vscprintf_helper ( + OUTPUTFN outfn, + const char *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 = outfn(outfile, format, ap); + return(retval); +} + +int __cdecl _vscprintf ( + const char *format, + va_list ap + ) +{ + return _vscprintf_helper(_output, format, ap); +} + +#endif /* _COUNT_ */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/vswprint.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/vswprint.cpp new file mode 100644 index 0000000..4ba1565 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/vswprint.cpp @@ -0,0 +1,211 @@ +// 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. + +/*** +*vswprint.c - print formatted data into a string from var arg list +* +*Purpose: +* defines vswprintf_s() and _vsnwprintf_s() - print formatted output to +* a string, get the data from an argument ptr instead of explicit +* arguments. +* +*******************************************************************************/ + + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +typedef int (*WOUTPUTFN)(miniFILE *, const char16_t *, va_list); + +static int _vswprintf_helper( WOUTPUTFN outfn, char16_t *string, size_t count, const char16_t *format, va_list ap ); + +/*** +*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. +* Sets up a FILE so file i/o operations can be used, make string look +* like a huge buffer to it, but _flsbuf will refuse to flush it if it +* fills up. Appends '\0' to make it a true string. +* +* Allocate the 'fake' _iob[] entryit statically instead of on +* the stack so that other routines can assume that _iob[] entries are in +* are in DGROUP and, thus, are near. +* +* 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. +* +* 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) +* Also, since there is only one statically allocated 'fake' iob, we must +* lock/unlock to prevent collisions. +* +*Entry: +* char16_t *string - place to put destination string +* size_t sizeInWords - size of the string buffer in char16_t units +* size_t count - max number of bytes to put in buffer +* char16_t *format - format string, describes format of data +* va_list ap - varargs argument pointer +* +*Exit: +* returns number of wide characters in string +* returns -2 if the string has been truncated (only in _vsnprintf_helper) +* returns -1 in other error cases +* +*Exceptions: +* +*******************************************************************************/ + +int __cdecl _vswprintf_helper ( + WOUTPUTFN woutfn, + char16_t *string, + size_t count, + const char16_t *format, + va_list ap + ) +{ + miniFILE str; + miniFILE *outfile = &str; + int retval; + + _VALIDATE_RETURN( (format != NULL), EINVAL, -1); + + _VALIDATE_RETURN( (count == 0) || (string != NULL), EINVAL, -1 ); + + outfile->_flag = _IOWRT|_IOSTRG; + outfile->_ptr = outfile->_base = (char *) string; + + if(count>(INT_MAX/sizeof(char16_t))) + { + /* old-style functions allow any large value to mean unbounded */ + outfile->_cnt = INT_MAX; + } + else + { + outfile->_cnt = (int)(count*sizeof(char16_t)); + } + + retval = woutfn(outfile, format, ap ); + + if(string==NULL) + { + return retval; + } + + if((retval >= 0) && (_putc_nolock('\0',outfile) != EOF) && (_putc_nolock('\0',outfile) != EOF)) + return(retval); + + string[count - 1] = 0; + if (outfile->_cnt < 0) + { + /* the buffer was too small; we return -2 to indicate truncation */ + return -2; + } + return -1; +} + +DLLEXPORT int __cdecl vswprintf_s ( + char16_t *string, + size_t sizeInWords, + const char16_t *format, + va_list ap + ) +{ + int retvalue = -1; + + /* validation section */ + _VALIDATE_RETURN(format != NULL, EINVAL, -1); + _VALIDATE_RETURN(string != NULL && sizeInWords > 0, EINVAL, -1); + + retvalue = _vswprintf_helper(_woutput_s, string, sizeInWords, format, ap); + if (retvalue < 0) + { + string[0] = 0; + _SECURECRT__FILL_STRING(string, sizeInWords, 1); + } + if (retvalue == -2) + { + _VALIDATE_RETURN(("Buffer too small" && 0), ERANGE, -1); + } + if (retvalue >= 0) + { + _SECURECRT__FILL_STRING(string, sizeInWords, retvalue + 1); + } + + return retvalue; +} + +DLLEXPORT int __cdecl _vsnwprintf_s ( + char16_t *string, + size_t sizeInWords, + size_t count, + const char16_t *format, + va_list ap + ) +{ + int retvalue = -1; + errno_t save_errno = 0; + + /* validation section */ + _VALIDATE_RETURN(format != NULL, EINVAL, -1); + if (count == 0 && string == NULL && sizeInWords == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + _VALIDATE_RETURN(string != NULL && sizeInWords > 0, EINVAL, -1); + + if (sizeInWords > count) + { + save_errno = errno; + retvalue = _vswprintf_helper(_woutput_s, string, count + 1, format, ap); + if (retvalue == -2) + { + /* the string has been truncated, return -1 */ + _SECURECRT__FILL_STRING(string, sizeInWords, count + 1); + if (errno == ERANGE) + { + errno = save_errno; + } + return -1; + } + } + else /* sizeInWords <= count */ + { + save_errno = errno; + retvalue = _vswprintf_helper(_woutput_s, string, sizeInWords, format, ap); + string[sizeInWords - 1] = 0; + /* we allow truncation if count == _TRUNCATE */ + if (retvalue == -2 && count == _TRUNCATE) + { + if (errno == ERANGE) + { + errno = save_errno; + } + return -1; + } + } + + if (retvalue < 0) + { + string[0] = 0; + _SECURECRT__FILL_STRING(string, sizeInWords, 1); + if (retvalue == -2) + { + _VALIDATE_RETURN(("Buffer too small" && 0), ERANGE, -1); + } + return -1; + } + + _SECURECRT__FILL_STRING(string, sizeInWords, retvalue + 1); + + return (retvalue < 0 ? -1 : retvalue); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcscat_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcscat_s.cpp new file mode 100644 index 0000000..507db7c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcscat_s.cpp @@ -0,0 +1,36 @@ +// 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. + +/*** +*wcscat_s.c - contains wcscat_s() +* + +* +*Purpose: +* wcscat_s() appends one char16_t string onto another. +* +* wcscat() concatenates (appends) a copy of the source string to the +* end of the destination string. +* Strings are wide-character strings. +* +*******************************************************************************/ + +#define _SECURECRT_FILL_BUFFER 1 +#define _SECURECRT_FILL_BUFFER_THRESHOLD ((size_t)8) + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _FUNC_PROLOGUE +#define _FUNC_NAME wcscat_s +#define _CHAR char16_t +#define _DEST _Dst +#define _SIZE _SizeInBytes +#define _SRC _Src + +#include "tcscat_s.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcscpy_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcscpy_s.cpp new file mode 100644 index 0000000..5285eac --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcscpy_s.cpp @@ -0,0 +1,33 @@ +// 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. + +/*** +*strcpy_s.c - contains wcscpy_s() +* + +* +*Purpose: +* wcscpy_s() copies one string onto another. +* +*******************************************************************************/ + +#define _SECURECRT_FILL_BUFFER 1 +#define _SECURECRT_FILL_BUFFER_THRESHOLD ((size_t)8) + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _FUNC_PROLOGUE +#define _FUNC_NAME wcscpy_s +#define _CHAR char16_t +#define _DEST _Dst +#define _SIZE _SizeInWords +#define _SRC _Src + +#include "tcscpy_s.inl" + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcslen_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcslen_s.cpp new file mode 100644 index 0000000..70cbb3a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcslen_s.cpp @@ -0,0 +1,58 @@ +// 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. + +/*** +*wcslen_s.c - contains wcsnlen() routine +* + +* +*Purpose: +* wcslen returns the length of a null-terminated wide-character string, +* not including the null char16_t itself. +* +*******************************************************************************/ + + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +/*** +*wcsnlen - return the length of a null-terminated wide-character string +* +*Purpose: +* Finds the length in bytes of the given string, not including +* the final null character. Only the first maxsize characters +* are inspected: if the null character is not found, maxsize is +* returned. +* +*Entry: +* const char16_t * wcs - string whose length is to be computed +* size_t maxsize +* +*Exit: +* Length of the string "wcs", exclusive of the final null byte, or +* maxsize if the null character is not found. +* +*Exceptions: +* +*******************************************************************************/ + +size_t __cdecl PAL_wcsnlen(const char16_t *wcs, size_t maxsize) +{ + size_t n; + + /* Note that we do not check if s == NULL, because we do not + * return errno_t... + */ + + for (n = 0; n < maxsize && *wcs; n++, wcs++) + ; + + return n; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcsncat_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcsncat_s.cpp new file mode 100644 index 0000000..b2e4701 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcsncat_s.cpp @@ -0,0 +1,35 @@ +// 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. + +/*** +*wcsncat_s.c - append n chars of string to new string +* + +* +*Purpose: +* defines wcsncat_s() - appends n characters of string onto +* end of other string +* +*******************************************************************************/ + +#define _SECURECRT_FILL_BUFFER 1 +#define _SECURECRT_FILL_BUFFER_THRESHOLD ((size_t)8) + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _FUNC_PROLOGUE +#define _FUNC_NAME wcsncat_s +#define _CHAR char16_t +#define _DEST _Dst +#define _SIZE _SizeInWords +#define _SRC _Src +#define _COUNT _Count + +#include "tcsncat_s.inl" + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcsncpy_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcsncpy_s.cpp new file mode 100644 index 0000000..932231f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcsncpy_s.cpp @@ -0,0 +1,34 @@ +// 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. + +/*** +*wcsncpy_s.c - copy at most n characters of wide-character string +* + +* +*Purpose: +* defines wcsncpy_s() - copy at most n characters of char16_t string +* +*******************************************************************************/ + +#define _SECURECRT_FILL_BUFFER 1 +#define _SECURECRT_FILL_BUFFER_THRESHOLD ((size_t)8) + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _FUNC_PROLOGUE +#define _FUNC_NAME wcsncpy_s +#define _CHAR char16_t +#define _DEST _Dst +#define _SIZE _SizeInWords +#define _SRC _Src +#define _COUNT _Count + +#include "tcsncpy_s.inl" + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcstok_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcstok_s.cpp new file mode 100644 index 0000000..adc9813 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wcstok_s.cpp @@ -0,0 +1,27 @@ +// 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. + +/*** +*wcstok_s.c - tokenize a wide-character string with given delimiters +* + +* +*Purpose: +* defines wcstok_s() - breaks wide-character string into series of token +* via repeated calls. +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _FUNC_PROLOGUE +#define _FUNC_NAME wcstok_s +#define _CHAR char16_t + +#include "tcstok_s.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wmakepath_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wmakepath_s.cpp new file mode 100644 index 0000000..efc52d1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wmakepath_s.cpp @@ -0,0 +1,30 @@ +// 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. + +/*** +*wmakepath_s.c - create path name from components +* + +* +*Purpose: +* To provide support for creation of full path names from components +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _FUNC_PROLOGUE +#define _FUNC_NAME _wmakepath_s +#define _CHAR char16_t +#define _DEST _Dst +#define _SIZE _SizeInWords +#define _T(_Character) L##_Character +#define _MBS_SUPPORT 0 + +#include "tmakepath_s.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wsplitpath_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wsplitpath_s.cpp new file mode 100644 index 0000000..64483f7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/wsplitpath_s.cpp @@ -0,0 +1,30 @@ +// 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. + +/*** +*wsplitpath_s.c - break down path name into components +* + +* +*Purpose: +* To provide support for accessing the individual components of an +* arbitrary path name +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _FUNC_PROLOGUE +#define _FUNC_NAME _wsplitpath_s +#define _CHAR char16_t +#define _TCSNCPY_S wcsncpy_s +#define _T(_Character) L##_Character +#define _MBS_SUPPORT 0 + +#include "tsplitpath_s.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/xtoa_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/xtoa_s.cpp new file mode 100644 index 0000000..2857bea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/xtoa_s.cpp @@ -0,0 +1,29 @@ +// 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. + +/*** +*strtok_s.c - tokenize a string with given delimiters +* + +* +*Purpose: +* defines strtok_s() - breaks string into series of token +* via repeated calls. +* +*******************************************************************************/ +#include "pal/palinternal.h" +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +//#define __int64 long long + +#define _SECURE_ITOA + +#define TCHAR char +#define _T(x) x +#include "xtox_s.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/xtow_s.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/xtow_s.cpp new file mode 100644 index 0000000..e001cc3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/xtow_s.cpp @@ -0,0 +1,28 @@ +// 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. + +/*** +*strtok_s.c - tokenize a string with given delimiters +* + +* +*Purpose: +* defines strtok_s() - breaks string into series of token +* via repeated calls. +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +#define _SECURE_ITOA + +#define _UNICODE +#define TCHAR char16_t +#define _T(x) L##x +#include "xtox_s.inl" diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/xtox_s.inl b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/xtox_s.inl new file mode 100644 index 0000000..f43b53d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/safecrt/xtox_s.inl @@ -0,0 +1,415 @@ +// 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. + +/*** +*xtoa.c - convert integers/longs to ASCII string +* + +* +*Purpose: +* The module has code to convert integers/longs to ASCII strings. See +* +*******************************************************************************/ + +#ifdef _UNICODE +#define xtox_s xtow_s +#define _itox_s _itow_s +#define _ltox_s _ltow_s +#define _ultox_s _ultow_s +#define _i64tox_s _i64tow_s +#define xtox xtow +#define _ltox _ltow +#define _ultox _ultow +#else /* _UNICODE */ +#define xtox_s xtoa_s +#define _itox_s _itoa_s +#define _ltox_s _ltoa_s +#define _ultox_s _ultoa_s +#define _i64tox_s _i64toa_s +#define xtox xtoa +#define _ltox _ltoa +#define _ultox _ultoa +#endif /* _UNICODE */ + +/*** +*char *_itoa_s, *_ltoa_s, *_ultoa_s(val, buf, sizeInTChars, radix) - convert binary int to ASCII +* string +* +*Purpose: +* Converts an int to a character string. +* +*Entry: +* val - number to be converted (int, long or unsigned long) +* char *buf - ptr to buffer to place result +* size_t sizeInTChars - size of the destination buffer +* int radix - base to convert into +* +*Exit: +* Fills in space pointed to by buf with string result. +* Returns the errno_t: err != 0 means that something went wrong, and +* an empty string (buf[0] = 0) is returned. +* +*Exceptions: +* Input parameters and buffer length are validated. +* Refer to the validation section of the function. +* +*******************************************************************************/ + +/* helper routine that does the main job. */ +#ifdef _SECURE_ITOA +static errno_t __stdcall xtox_s + ( + unsigned long val, + TCHAR *buf, + size_t sizeInTChars, + unsigned radix, + int is_neg + ) +#else /* _SECURE_ITOA */ +static void __stdcall xtox + ( + unsigned long val, + TCHAR *buf, + unsigned radix, + int is_neg + ) +#endif /* _SECURE_ITOA */ +{ + TCHAR *p; /* pointer to traverse string */ + TCHAR *firstdig; /* pointer to first digit */ + TCHAR temp; /* temp char */ + unsigned digval; /* value of digit */ +#ifdef _SECURE_ITOA + size_t length; /* current length of the string */ + + /* validation section */ + _VALIDATE_RETURN_ERRCODE(buf != NULL, EINVAL); + _VALIDATE_RETURN_ERRCODE(sizeInTChars > 0, EINVAL); + _RESET_STRING(buf, sizeInTChars); + _VALIDATE_RETURN_ERRCODE(sizeInTChars > (size_t)(is_neg ? 2 : 1), ERANGE); + _VALIDATE_RETURN_ERRCODE(2 <= radix && radix <= 36, EINVAL); + length = 0; + +#endif /* _SECURE_ITOA */ + p = buf; + + if (is_neg) { + /* negative, so output '-' and negate */ + *p++ = _T('-'); +#ifdef _SECURE_ITOA + length++; +#endif /* _SECURE_ITOA */ + val = (unsigned long)(-(long)val); + } + + firstdig = p; /* save pointer to first digit */ + + do { + digval = (unsigned) (val % radix); + val /= radix; /* get next digit */ + + /* convert to ascii and store */ + if (digval > 9) + *p++ = (TCHAR) (digval - 10 + _T('a')); /* a letter */ + else + *p++ = (TCHAR) (digval + _T('0')); /* a digit */ +#ifndef _SECURE_ITOA + } while (val > 0); +#else /* _SECURE_ITOA */ + length++; + } while (val > 0 && length < sizeInTChars); + + /* Check for buffer overrun */ + if (length >= sizeInTChars) + { + buf[0] = '\0'; + _VALIDATE_RETURN_ERRCODE(length < sizeInTChars, ERANGE); + } +#endif /* _SECURE_ITOA */ + /* We now have the digit of the number in the buffer, but in reverse + order. Thus we reverse them now. */ + + *p-- = _T('\0'); /* terminate string; p points to last digit */ + + do { + temp = *p; + *p = *firstdig; + *firstdig = temp; /* swap *p and *firstdig */ + --p; + ++firstdig; /* advance to next two digits */ + } while (firstdig < p); /* repeat until halfway */ +#ifdef _SECURE_ITOA + return 0; +#endif /* _SECURE_ITOA */ +} + +/* Actual functions just call conversion helper with neg flag set correctly, + and return pointer to buffer. */ + +#ifdef _SECURE_ITOA +DLLEXPORT errno_t __cdecl _itox_s ( + int val, + TCHAR *buf, + size_t sizeInTChars, + int radix + ) +{ + errno_t e = 0; + + if (radix == 10 && val < 0) + e = xtox_s((unsigned long)val, buf, sizeInTChars, radix, 1); + else + e = xtox_s((unsigned long)(unsigned int)val, buf, sizeInTChars, radix, 0); + + return e; +} + +errno_t __cdecl _ltox_s ( + long val, + TCHAR *buf, + size_t sizeInTChars, + int radix + ) +{ + return xtox_s((unsigned long)val, buf, sizeInTChars, radix, (radix == 10 && val < 0)); +} + +errno_t __cdecl _ultox_s ( + unsigned long val, + TCHAR *buf, + size_t sizeInTChars, + int radix + ) +{ + return xtox_s(val, buf, sizeInTChars, radix, 0); +} + +#else /* _SECURE_ITOA */ + +/*** +*char *_itoa, *_ltoa, *_ultoa(val, buf, radix) - convert binary int to ASCII +* string +* +*Purpose: +* Converts an int to a character string. +* +*Entry: +* val - number to be converted (int, long or unsigned long) +* int radix - base to convert into +* char *buf - ptr to buffer to place result +* +*Exit: +* fills in space pointed to by buf with string result +* returns a pointer to this buffer +* +*Exceptions: +* Input parameters are validated. The buffer is assumed to be big enough to +* contain the string. Refer to the validation section of the function. +* +*******************************************************************************/ + +/* Actual functions just call conversion helper with neg flag set correctly, + and return pointer to buffer. */ + +TCHAR * __cdecl _ltox ( + long val, + TCHAR *buf, + int radix + ) +{ + xtox((unsigned long)val, buf, radix, (radix == 10 && val < 0)); + return buf; +} + +TCHAR * __cdecl _ultox ( + unsigned long val, + TCHAR *buf, + int radix + ) +{ + xtox(val, buf, radix, 0); + return buf; +} + +#endif /* _SECURE_ITOA */ + +#ifndef _NO_INT64 + +/*** +*char *_i64toa_s(val, buf, sizeInTChars, radix) - convert binary int to ASCII +* string +* +*Purpose: +* Converts an int64 to a character string. +* +*Entry: +* val - number to be converted +* char *buf - ptr to buffer to place result +* size_t sizeInTChars - size of the destination buffer +* int radix - base to convert into +* +*Exit: +* Fills in space pointed to by buf with string result. +* Returns the errno_t: err != 0 means that something went wrong, and +* an empty string (buf[0] = 0) is returned. +* +*Exceptions: +* Input parameters and buffer length are validated. +* Refer to the validation section of the function. +* +*******************************************************************************/ + +#ifdef _SECURE_ITOA +static errno_t __fastcall x64tox_s + (/* stdcall is faster and smaller... Might as well use it for the helper. */ + unsigned __int64 val, + TCHAR *buf, + size_t sizeInTChars, + unsigned radix, + int is_neg + ) +#else /* _SECURE_ITOA */ +static void __fastcall x64tox + (/* stdcall is faster and smaller... Might as well use it for the helper. */ + unsigned __int64 val, + TCHAR *buf, + unsigned radix, + int is_neg + ) +#endif /* _SECURE_ITOA */ +{ + TCHAR *p; /* pointer to traverse string */ + TCHAR *firstdig; /* pointer to first digit */ + TCHAR temp; /* temp char */ + unsigned digval; /* value of digit */ +#ifdef _SECURE_ITOA + size_t length; /* current length of the string */ + + /* validation section */ + _VALIDATE_RETURN_ERRCODE(buf != NULL, EINVAL); + _VALIDATE_RETURN_ERRCODE(sizeInTChars > 0, EINVAL); + _RESET_STRING(buf, sizeInTChars); + _VALIDATE_RETURN_ERRCODE(sizeInTChars > (size_t)(is_neg ? 2 : 1), ERANGE); + _VALIDATE_RETURN_ERRCODE(2 <= radix && radix <= 36, EINVAL); + length = 0; +#endif /* _SECURE_ITOA */ + p = buf; + + if ( is_neg ) + { + *p++ = _T('-'); /* negative, so output '-' and negate */ +#ifdef _SECURE_ITOA + length++; +#endif /* _SECURE_ITOA */ + val = (unsigned __int64)(-(__int64)val); + } + + firstdig = p; /* save pointer to first digit */ + + do { + digval = (unsigned) (val % radix); + val /= radix; /* get next digit */ + + /* convert to ascii and store */ + if (digval > 9) + *p++ = (TCHAR) (digval - 10 + _T('a')); /* a letter */ + else + *p++ = (TCHAR) (digval + _T('0')); /* a digit */ + +#ifndef _SECURE_ITOA + } while (val > 0); +#else /* _SECURE_ITOA */ + length++; + } while (val > 0 && length < sizeInTChars); + + /* Check for buffer overrun */ + if (length >= sizeInTChars) + { + buf[0] = '\0'; + _VALIDATE_RETURN_ERRCODE(length < sizeInTChars, ERANGE); + } +#endif /* _SECURE_ITOA */ + /* We now have the digit of the number in the buffer, but in reverse + order. Thus we reverse them now. */ + + *p-- = _T('\0'); /* terminate string; p points to last digit */ + + do { + temp = *p; + *p = *firstdig; + *firstdig = temp; /* swap *p and *firstdig */ + --p; + ++firstdig; /* advance to next two digits */ + } while (firstdig < p); /* repeat until halfway */ + +#ifdef _SECURE_ITOA + return 0; +#endif /* _SECURE_ITOA */ +} + +#ifdef _SECURE_ITOA + +/* Actual functions just call conversion helper with neg flag set correctly, + and return pointer to buffer. */ + +DLLEXPORT errno_t __cdecl _i64tox_s ( + long long val, + TCHAR *buf, + size_t sizeInTChars, + int radix + ) +{ + return x64tox_s((unsigned __int64)val, buf, sizeInTChars, radix, (radix == 10 && val < 0)); +} + +errno_t __cdecl _ui64tox_s ( + unsigned long long val, + TCHAR *buf, + size_t sizeInTChars, + int radix + ) +{ + return x64tox_s(val, buf, sizeInTChars, radix, 0); +} + +#else /* _SECURE_ITOA */ + +/*** +*char *_i64toa(val, buf, radix) - convert binary int to ASCII +* string +* +*Purpose: +* Converts an int64 to a character string. +* +*Entry: +* val - number to be converted +* int radix - base to convert into +* char *buf - ptr to buffer to place result +* +*Exit: +* fills in space pointed to by buf with string result +* returns a pointer to this buffer +* +*Exceptions: +* Input parameters are validated. The buffer is assumed to be big enough to +* contain the string. Refer to the validation section of the function. +* +*******************************************************************************/ + +/* Actual functions just call conversion helper with neg flag set correctly, + and return pointer to buffer. */ + +TCHAR * __cdecl _ui64tox ( + unsigned __int64 val, + TCHAR *buf, + int radix + ) +{ + x64tox(val, buf, radix, 0); + return buf; +} + +#endif /* _SECURE_ITOA */ + +#endif /* _NO_INT64 */ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/sharedmemory/sharedmemory.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/sharedmemory/sharedmemory.cpp new file mode 100644 index 0000000..619fae0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/sharedmemory/sharedmemory.cpp @@ -0,0 +1,1227 @@ +// 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. + +#include "pal/sharedmemory.h" + +#include "pal/dbgmsg.h" +#include "pal/file.hpp" +#include "pal/malloc.hpp" +#include "pal/thread.hpp" +#include "pal/virtual.h" +#include "pal/process.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(SHMEM); + +#include "pal/sharedmemory.inl" + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// AutoFreeBuffer + +AutoFreeBuffer::AutoFreeBuffer(void *buffer) : m_buffer(buffer), m_cancel(false) +{ +} + +AutoFreeBuffer::~AutoFreeBuffer() +{ + if (!m_cancel && m_buffer != nullptr) + { + free(m_buffer); + } +} + +void AutoFreeBuffer::Cancel() +{ + m_cancel = true; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SharedMemoryException + +SharedMemoryException::SharedMemoryException(DWORD errorCode) : m_errorCode(errorCode) +{ +} + +DWORD SharedMemoryException::GetErrorCode() const +{ + return m_errorCode; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SharedMemoryHelpers + +const mode_t SharedMemoryHelpers::PermissionsMask_CurrentUser_ReadWriteExecute = S_IRUSR | S_IWUSR | S_IXUSR; +const mode_t SharedMemoryHelpers::PermissionsMask_AllUsers_ReadWrite = + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; +const mode_t SharedMemoryHelpers::PermissionsMask_AllUsers_ReadWriteExecute = + PermissionsMask_AllUsers_ReadWrite | (S_IXUSR | S_IXGRP | S_IXOTH); +const UINT32 SharedMemoryHelpers::InvalidProcessId = static_cast(-1); +const SIZE_T SharedMemoryHelpers::InvalidThreadId = static_cast(-1); +const UINT64 SharedMemoryHelpers::InvalidSharedThreadId = static_cast(-1); + +void *SharedMemoryHelpers::Alloc(SIZE_T byteCount) +{ + void *buffer = InternalMalloc(byteCount); + if (buffer == nullptr) + { + throw SharedMemoryException(static_cast(SharedMemoryError::OutOfMemory)); + } + return buffer; +} + +SIZE_T SharedMemoryHelpers::AlignDown(SIZE_T value, SIZE_T alignment) +{ + _ASSERTE((alignment & (alignment - 1)) == 0); // must be a power of 2 + return value & ~(alignment - 1); +} + +SIZE_T SharedMemoryHelpers::AlignUp(SIZE_T value, SIZE_T alignment) +{ + _ASSERTE((alignment & (alignment - 1)) == 0); // must be a power of 2 + return AlignDown(value + (alignment - 1), alignment); +} + +bool SharedMemoryHelpers::EnsureDirectoryExists( + const char *path, + bool isGlobalLockAcquired, + bool createIfNotExist, + bool isSystemDirectory) +{ + _ASSERTE(path != nullptr); + _ASSERTE(!(isSystemDirectory && createIfNotExist)); // should not create or change permissions on system directories + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + _ASSERTE(!isGlobalLockAcquired || SharedMemoryManager::IsCreationDeletionFileLockAcquired()); + + // Check if the path already exists + struct stat statInfo; + int statResult = stat(path, &statInfo); + if (statResult != 0 && errno == ENOENT) + { + if (!createIfNotExist) + { + return false; + } + + // The path does not exist, create the directory. The permissions mask passed to mkdir() is filtered by the process' + // permissions umask, so mkdir() may not set all of the requested permissions. We need to use chmod() to set the proper + // permissions. That creates a race when there is no global lock acquired when creating the directory. Another user's + // process may create the directory and this user's process may try to use it before the other process sets the full + // permissions. In that case, create a temporary directory first, set the permissions, and rename it to the actual + // directory name. + + if (isGlobalLockAcquired) + { + if (mkdir(path, PermissionsMask_AllUsers_ReadWriteExecute) != 0) + { + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + if (chmod(path, PermissionsMask_AllUsers_ReadWriteExecute) != 0) + { + rmdir(path); + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + return true; + } + + PathCharString tempPath; + BuildSharedFilesPath(tempPath, SHARED_MEMORY_UNIQUE_TEMP_NAME_TEMPLATE); + + if (mkdtemp(tempPath.OpenStringBuffer()) == nullptr) + { + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + if (chmod(tempPath, PermissionsMask_AllUsers_ReadWriteExecute) != 0) + { + rmdir(tempPath); + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + if (rename(tempPath, path) == 0) + { + return true; + } + + // Another process may have beaten us to it. Delete the temp directory and continue to check the requested directory to + // see if it meets our needs. + rmdir(tempPath); + statResult = stat(path, &statInfo); + } + + // If the path exists, check that it's a directory + if (statResult != 0 || !(statInfo.st_mode & S_IFDIR)) + { + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + + if (isSystemDirectory) + { + // For system directories (such as TEMP_DIRECTORY_PATH), require sufficient permissions only for the + // current user. For instance, "docker run --mount ..." to mount /tmp to some directory on the host mounts the + // destination directory with the same permissions as the source directory, which may not include some permissions for + // other users. In the docker container, other user permissions are typically not relevant and relaxing the permissions + // requirement allows for that scenario to work without having to work around it by first giving sufficient permissions + // for all users. + if ((statInfo.st_mode & PermissionsMask_CurrentUser_ReadWriteExecute) == PermissionsMask_CurrentUser_ReadWriteExecute) + { + return true; + } + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + + // For non-system directories (such as gSharedFilesPath/SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_NAME), + // require sufficient permissions for all users and try to update them if requested to create the directory, so that + // shared memory files may be shared by all processes on the system. + if ((statInfo.st_mode & PermissionsMask_AllUsers_ReadWriteExecute) == PermissionsMask_AllUsers_ReadWriteExecute) + { + return true; + } + if (!createIfNotExist || chmod(path, PermissionsMask_AllUsers_ReadWriteExecute) != 0) + { + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + return true; +} + +int SharedMemoryHelpers::Open(LPCSTR path, int flags, mode_t mode) +{ + int openErrorCode; + + flags |= O_CLOEXEC; + do + { + int fileDescriptor = InternalOpen(path, flags, mode); + if (fileDescriptor != -1) + { + return fileDescriptor; + } + openErrorCode = errno; + } while (openErrorCode == EINTR); + + switch (openErrorCode) + { + case ENOENT: + _ASSERTE(!(flags & O_CREAT)); + errno = openErrorCode; + return -1; + + case ENAMETOOLONG: + throw SharedMemoryException(static_cast(SharedMemoryError::NameTooLong)); + + case EMFILE: + case ENFILE: + case ENOMEM: + throw SharedMemoryException(static_cast(SharedMemoryError::OutOfMemory)); + + default: + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } +} + +int SharedMemoryHelpers::OpenDirectory(LPCSTR path) +{ + _ASSERTE(path != nullptr); + _ASSERTE(path[0] != '\0'); + + int fileDescriptor = Open(path, O_RDONLY); + _ASSERTE(fileDescriptor != -1 || errno == ENOENT); + return fileDescriptor; +} + +int SharedMemoryHelpers::CreateOrOpenFile(LPCSTR path, bool createIfNotExist, bool *createdRef) +{ + _ASSERTE(path != nullptr); + _ASSERTE(path[0] != '\0'); + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + _ASSERTE(!createIfNotExist || SharedMemoryManager::IsCreationDeletionFileLockAcquired()); + + // Try to open the file + int openFlags = O_RDWR; + int fileDescriptor = Open(path, openFlags); + if (fileDescriptor != -1) + { + if (createdRef != nullptr) + { + *createdRef = false; + } + return fileDescriptor; + } + _ASSERTE(errno == ENOENT); + if (!createIfNotExist) + { + if (createdRef != nullptr) + { + *createdRef = false; + } + return -1; + } + + // File does not exist, create the file + openFlags |= O_CREAT | O_EXCL; + fileDescriptor = Open(path, openFlags, PermissionsMask_AllUsers_ReadWrite); + _ASSERTE(fileDescriptor != -1); + + // The permissions mask passed to open() is filtered by the process' permissions umask, so open() may not set all of + // the requested permissions. Use chmod() to set the proper permissions. + if (chmod(path, PermissionsMask_AllUsers_ReadWrite) != 0) + { + CloseFile(fileDescriptor); + unlink(path); + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + + if (createdRef != nullptr) + { + *createdRef = true; + } + return fileDescriptor; +} + +void SharedMemoryHelpers::CloseFile(int fileDescriptor) +{ + _ASSERTE(fileDescriptor != -1); + + int closeResult; + do + { + closeResult = close(fileDescriptor); + } while (closeResult != 0 && errno == EINTR); +} + +SIZE_T SharedMemoryHelpers::GetFileSize(int fileDescriptor) +{ + _ASSERTE(fileDescriptor != -1); + + off_t endOffset = lseek(fileDescriptor, 0, SEEK_END); + if (endOffset == static_cast(-1) || + lseek(fileDescriptor, 0, SEEK_SET) == static_cast(-1)) + { + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + return endOffset; +} + +void SharedMemoryHelpers::SetFileSize(int fileDescriptor, SIZE_T byteCount) +{ + _ASSERTE(fileDescriptor != -1); + _ASSERTE(static_cast(byteCount) == byteCount); + + while (true) + { + int ftruncateResult = ftruncate(fileDescriptor, static_cast(byteCount)); + if (ftruncateResult == 0) + { + break; + } + if (errno != EINTR) + { + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + } +} + +void *SharedMemoryHelpers::MemoryMapFile(int fileDescriptor, SIZE_T byteCount) +{ + _ASSERTE(fileDescriptor != -1); + _ASSERTE(byteCount > sizeof(SharedMemorySharedDataHeader)); + _ASSERTE(AlignDown(byteCount, GetVirtualPageSize()) == byteCount); + + void *sharedMemoryBuffer = mmap(nullptr, byteCount, PROT_READ | PROT_WRITE, MAP_SHARED, fileDescriptor, 0); + if (sharedMemoryBuffer != MAP_FAILED) + { + return sharedMemoryBuffer; + } + switch (errno) + { + case ENFILE: + case ENOMEM: + throw SharedMemoryException(static_cast(SharedMemoryError::OutOfMemory)); + + default: + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } +} + +bool SharedMemoryHelpers::TryAcquireFileLock(int fileDescriptor, int operation) +{ + // A file lock is acquired once per file descriptor, so the caller will need to synchronize threads of this process + + _ASSERTE(fileDescriptor != -1); + _ASSERTE(!(operation & LOCK_UN)); + + while (true) + { + if (flock(fileDescriptor, operation) == 0) + { + return true; + } + + int flockError = errno; + switch (flockError) + { + case EWOULDBLOCK: + return false; + + case EINTR: + continue; + + default: + throw SharedMemoryException(static_cast(SharedMemoryError::OutOfMemory)); + } + } +} + +void SharedMemoryHelpers::ReleaseFileLock(int fileDescriptor) +{ + _ASSERTE(fileDescriptor != -1); + + int flockResult; + do + { + flockResult = flock(fileDescriptor, LOCK_UN); + } while (flockResult != 0 && errno == EINTR); +} + +void SharedMemoryHelpers::BuildSharedFilesPath(PathCharString& destination, const char *suffix, int suffixCharCount) +{ + _ASSERTE((int)strlen(suffix) == suffixCharCount); + + VerifyStringOperation(destination.Set(*gSharedFilesPath)); + VerifyStringOperation(destination.Append(suffix, suffixCharCount)); +} + +bool SharedMemoryHelpers::AppendUInt32String( + PathCharString& destination, + UINT32 value) +{ + char int32String[16]; + + int valueCharCount = + sprintf_s(int32String, sizeof(int32String), "%u", value); + _ASSERTE(valueCharCount > 0); + return destination.Append(int32String, valueCharCount) != FALSE; +} + +void SharedMemoryHelpers::VerifyStringOperation(bool success) +{ + if (!success) + { + throw SharedMemoryException(static_cast(SharedMemoryError::OutOfMemory)); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SharedMemoryId + +SharedMemoryId::SharedMemoryId() : m_name(nullptr) +{ +} + +SharedMemoryId::SharedMemoryId(LPCSTR name, SIZE_T nameCharCount, bool isSessionScope) + : m_name(name), m_nameCharCount(nameCharCount), m_isSessionScope(isSessionScope) +{ + _ASSERTE(name != nullptr); + _ASSERTE(nameCharCount != 0); + _ASSERTE(nameCharCount <= SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT); + _ASSERTE(strlen(name) == nameCharCount); +} + +SharedMemoryId::SharedMemoryId(LPCSTR name) +{ + _ASSERTE(name != nullptr); + + // Look for "Global\" and "Local\" prefixes in the name, and determine the session ID + if (strncmp(name, "Global\\", 7) == 0) + { + m_isSessionScope = false; + name += _countof("Global\\") - 1; + } + else + { + if (strncmp(name, "Local\\", 6) == 0) + { + name += _countof("Local\\") - 1; + } + m_isSessionScope = true; + } + m_name = name; + + m_nameCharCount = strlen(name); + if (m_nameCharCount == 0) + { + throw SharedMemoryException(static_cast(SharedMemoryError::NameEmpty)); + } + if (m_nameCharCount > SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT) + { + throw SharedMemoryException(static_cast(SharedMemoryError::NameTooLong)); + } + + // Look for invalid characters '\' and '/' in the name + for (SIZE_T i = 0; i < m_nameCharCount; ++i) + { + char c = name[i]; + if (c == '\\' || c == '/') + { + throw SharedMemoryException(static_cast(SharedMemoryError::NameInvalid)); + } + } +} + +LPCSTR SharedMemoryId::GetName() const +{ + _ASSERTE(m_name != nullptr); + return m_name; +} + +SIZE_T SharedMemoryId::GetNameCharCount() const +{ + _ASSERTE(m_name != nullptr); + return m_nameCharCount; +} + +bool SharedMemoryId::IsSessionScope() const +{ + _ASSERTE(m_name != nullptr); + return m_isSessionScope; +} + +bool SharedMemoryId::Equals(SharedMemoryId *other) const +{ + return + GetNameCharCount() == other->GetNameCharCount() && + IsSessionScope() == other->IsSessionScope() && + strcmp(GetName(), other->GetName()) == 0; +} + +bool SharedMemoryId::AppendSessionDirectoryName(PathCharString& path) const +{ + if (IsSessionScope()) + { + return path.Append(SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX) != FALSE + && SharedMemoryHelpers::AppendUInt32String(path, GetCurrentSessionId()); + } + else + { + return path.Append(SHARED_MEMORY_GLOBAL_DIRECTORY_NAME) != FALSE; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SharedMemorySharedDataHeader + +SIZE_T SharedMemorySharedDataHeader::DetermineTotalByteCount(SIZE_T dataByteCount) +{ + return SharedMemoryHelpers::AlignUp(sizeof(SharedMemorySharedDataHeader) + dataByteCount, GetVirtualPageSize()); +} + +SharedMemorySharedDataHeader::SharedMemorySharedDataHeader(SharedMemoryType type, UINT8 version) + : m_type(type), m_version(version) +{ +} + +SharedMemoryType SharedMemorySharedDataHeader::GetType() const +{ + return m_type; +} + +UINT8 SharedMemorySharedDataHeader::GetVersion() const +{ + return m_version; +} + +void *SharedMemorySharedDataHeader::GetData() +{ + return this + 1; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SharedMemoryProcessDataHeader + +SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( + LPCSTR name, + SharedMemorySharedDataHeader requiredSharedDataHeader, + SIZE_T sharedDataByteCount, + bool createIfNotExist, + bool *createdRef) +{ + _ASSERTE(name != nullptr); + _ASSERTE(sharedDataByteCount != 0); + _ASSERTE(!createIfNotExist || createdRef != nullptr); + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + _ASSERTE(!SharedMemoryManager::IsCreationDeletionFileLockAcquired()); + + if (createdRef != nullptr) + { + *createdRef = false; + } + + PathCharString filePath; + SharedMemoryId id(name); + + struct AutoCleanup + { + bool m_acquiredCreationDeletionFileLock; + PathCharString *m_filePath; + SIZE_T m_sessionDirectoryPathCharCount; + bool m_createdFile; + int m_fileDescriptor; + bool m_acquiredFileLock; + void *m_mappedBuffer; + SIZE_T m_mappedBufferByteCount; + bool m_cancel; + + AutoCleanup() + : m_acquiredCreationDeletionFileLock(false), + m_filePath(nullptr), + m_sessionDirectoryPathCharCount(0), + m_createdFile(false), + m_fileDescriptor(-1), + m_acquiredFileLock(false), + m_mappedBuffer(nullptr), + m_mappedBufferByteCount(0), + m_cancel(false) + { + } + + ~AutoCleanup() + { + if (m_cancel) + { + return; + } + + if (m_mappedBuffer != nullptr) + { + _ASSERTE(m_mappedBufferByteCount != 0); + munmap(m_mappedBuffer, m_mappedBufferByteCount); + } + + if (m_acquiredFileLock) + { + _ASSERTE(m_fileDescriptor != -1); + SharedMemoryHelpers::ReleaseFileLock(m_fileDescriptor); + } + + if (m_fileDescriptor != -1) + { + SharedMemoryHelpers::CloseFile(m_fileDescriptor); + } + + if (m_createdFile) + { + _ASSERTE(m_filePath != nullptr); + unlink(*m_filePath); + } + + if (m_sessionDirectoryPathCharCount != 0) + { + _ASSERTE(*m_filePath != nullptr); + m_filePath->CloseBuffer(m_sessionDirectoryPathCharCount); + rmdir(*m_filePath); + } + + if (m_acquiredCreationDeletionFileLock) + { + SharedMemoryManager::ReleaseCreationDeletionFileLock(); + } + } + } autoCleanup; + + SharedMemoryProcessDataHeader *processDataHeader = SharedMemoryManager::FindProcessDataHeader(&id); + if (processDataHeader != nullptr) + { + _ASSERTE( + processDataHeader->GetSharedDataTotalByteCount() == + SharedMemorySharedDataHeader::DetermineTotalByteCount(sharedDataByteCount)); + processDataHeader->IncRefCount(); + return processDataHeader; + } + + SharedMemoryManager::AcquireCreationDeletionFileLock(); + autoCleanup.m_acquiredCreationDeletionFileLock = true; + + // Create the session directory + SharedMemoryHelpers::VerifyStringOperation(SharedMemoryManager::CopySharedMemoryBasePath(filePath)); + SharedMemoryHelpers::VerifyStringOperation(filePath.Append('/')); + SharedMemoryHelpers::VerifyStringOperation(id.AppendSessionDirectoryName(filePath)); + if (!SharedMemoryHelpers::EnsureDirectoryExists(filePath, true /* isGlobalLockAcquired */, createIfNotExist)) + { + _ASSERTE(!createIfNotExist); + return nullptr; + } + autoCleanup.m_filePath = &filePath; + autoCleanup.m_sessionDirectoryPathCharCount = filePath.GetCount(); + + // Create or open the shared memory file + SharedMemoryHelpers::VerifyStringOperation(filePath.Append('/')); + SharedMemoryHelpers::VerifyStringOperation(filePath.Append(id.GetName(), id.GetNameCharCount())); + + bool createdFile; + int fileDescriptor = SharedMemoryHelpers::CreateOrOpenFile(filePath, createIfNotExist, &createdFile); + if (fileDescriptor == -1) + { + _ASSERTE(!createIfNotExist); + return nullptr; + } + autoCleanup.m_createdFile = createdFile; + autoCleanup.m_fileDescriptor = fileDescriptor; + + bool clearContents = false; + if (!createdFile) + { + // A shared file lock on the shared memory file would be held by any process that has opened the same file. Try to take + // an exclusive lock on the file. Successfully acquiring an exclusive lock indicates that no process has a reference to + // the shared memory file, and this process can reinitialize its contents. + if (SharedMemoryHelpers::TryAcquireFileLock(fileDescriptor, LOCK_EX | LOCK_NB)) + { + // The shared memory file is not being used, flag it as created so that its contents will be reinitialized + SharedMemoryHelpers::ReleaseFileLock(fileDescriptor); + autoCleanup.m_createdFile = true; + if (!createIfNotExist) + { + return nullptr; + } + createdFile = true; + clearContents = true; + } + } + + // Set or validate the file length + SIZE_T sharedDataTotalByteCount = SharedMemorySharedDataHeader::DetermineTotalByteCount(sharedDataByteCount); + if (createdFile) + { + SharedMemoryHelpers::SetFileSize(fileDescriptor, sharedDataTotalByteCount); + } + else if (SharedMemoryHelpers::GetFileSize(fileDescriptor) != sharedDataTotalByteCount) + { + throw SharedMemoryException(static_cast(SharedMemoryError::HeaderMismatch)); + } + + // Acquire and hold a shared file lock on the shared memory file as long as it is open, to indicate that this process is + // using the file. An exclusive file lock is attempted above to detect whether the file contents are valid, for the case + // where a process crashes or is killed after the file is created. Since we already hold the creation/deletion locks, a + // non-blocking file lock should succeed. + if (!SharedMemoryHelpers::TryAcquireFileLock(fileDescriptor, LOCK_SH | LOCK_NB)) + { + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + autoCleanup.m_acquiredFileLock = true; + + // Map the file into memory, and initialize or validate the header + void *mappedBuffer = SharedMemoryHelpers::MemoryMapFile(fileDescriptor, sharedDataTotalByteCount); + autoCleanup.m_mappedBuffer = mappedBuffer; + autoCleanup.m_mappedBufferByteCount = sharedDataTotalByteCount; + SharedMemorySharedDataHeader *sharedDataHeader; + if (createdFile) + { + if (clearContents) + { + memset(mappedBuffer, 0, sharedDataTotalByteCount); + } + sharedDataHeader = new(mappedBuffer) SharedMemorySharedDataHeader(requiredSharedDataHeader); + } + else + { + sharedDataHeader = reinterpret_cast(mappedBuffer); + if (sharedDataHeader->GetType() != requiredSharedDataHeader.GetType() || + sharedDataHeader->GetVersion() != requiredSharedDataHeader.GetVersion()) + { + throw SharedMemoryException(static_cast(SharedMemoryError::HeaderMismatch)); + } + } + + // When *createdRef is true, the creation/deletion file lock will remain locked upon returning for the caller to initialize + // the shared data. The caller must release the file lock afterwards. + if (!createdFile) + { + autoCleanup.m_acquiredCreationDeletionFileLock = false; + SharedMemoryManager::ReleaseCreationDeletionFileLock(); + } + + processDataHeader = SharedMemoryProcessDataHeader::New(&id, fileDescriptor, sharedDataHeader, sharedDataTotalByteCount); + + autoCleanup.m_cancel = true; + if (createdFile) + { + _ASSERTE(createIfNotExist); + _ASSERTE(createdRef != nullptr); + *createdRef = true; + } + return processDataHeader; +} + +SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::PalObject_GetProcessDataHeader(CorUnix::IPalObject *object) +{ + _ASSERTE(object != nullptr); + _ASSERTE(object->GetObjectType()->GetId() == otiNamedMutex); + _ASSERTE(object->GetObjectType()->GetImmutableDataSize() == sizeof(SharedMemoryProcessDataHeader *)); + + void *immutableDataBuffer; + PAL_ERROR errorCode = object->GetImmutableData(&immutableDataBuffer); + _ASSERTE(errorCode == NO_ERROR); + _ASSERTE(immutableDataBuffer != nullptr); + return *reinterpret_cast(immutableDataBuffer); +} + +void SharedMemoryProcessDataHeader::PalObject_SetProcessDataHeader( + CorUnix::IPalObject *object, + SharedMemoryProcessDataHeader *processDataHeader) +{ + _ASSERTE(object != nullptr); + _ASSERTE(object->GetObjectType()->GetId() == otiNamedMutex); + _ASSERTE(object->GetObjectType()->GetImmutableDataSize() == sizeof(SharedMemoryProcessDataHeader *)); + _ASSERTE(processDataHeader != nullptr); + + void *immutableDataBuffer; + PAL_ERROR errorCode = object->GetImmutableData(&immutableDataBuffer); + _ASSERTE(errorCode == NO_ERROR); + _ASSERTE(immutableDataBuffer != nullptr); + *reinterpret_cast(immutableDataBuffer) = processDataHeader; +} + +void SharedMemoryProcessDataHeader::PalObject_Close( + CPalThread *thread, + IPalObject *object, + bool isShuttingDown, + bool cleanUpPalSharedState) +{ + // This function's signature matches OBJECTCLEANUPROUTINE + _ASSERTE(thread != nullptr); + _ASSERTE(object != nullptr); + _ASSERTE(object->GetObjectType()->GetId() == otiNamedMutex); + _ASSERTE(object->GetObjectType()->GetImmutableDataSize() == sizeof(SharedMemoryProcessDataHeader *)); + + SharedMemoryProcessDataHeader *processDataHeader = PalObject_GetProcessDataHeader(object); + if (processDataHeader == nullptr) + { + // The object was created, but an error must have occurred before the process data was initialized + return; + } + + SharedMemoryManager::AcquireCreationDeletionProcessLock(); + processDataHeader->DecRefCount(); + SharedMemoryManager::ReleaseCreationDeletionProcessLock(); +} + +SharedMemoryProcessDataHeader::SharedMemoryProcessDataHeader( + SharedMemoryId *id, + int fileDescriptor, + SharedMemorySharedDataHeader *sharedDataHeader, + SIZE_T sharedDataTotalByteCount) + : + m_refCount(1), + m_data(nullptr), + m_fileDescriptor(fileDescriptor), + m_sharedDataHeader(sharedDataHeader), + m_sharedDataTotalByteCount(sharedDataTotalByteCount), + m_nextInProcessDataHeaderList(nullptr) +{ + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + _ASSERTE(id != nullptr); + _ASSERTE(fileDescriptor != -1); + _ASSERTE(sharedDataHeader != nullptr); + _ASSERTE(sharedDataTotalByteCount > sizeof(SharedMemorySharedDataHeader)); + _ASSERTE(SharedMemoryHelpers::AlignDown(sharedDataTotalByteCount, GetVirtualPageSize()) == sharedDataTotalByteCount); + + // Copy the name and initialize the ID + char *nameCopy = reinterpret_cast(this + 1); + SIZE_T nameByteCount = id->GetNameCharCount() + 1; + memcpy_s(nameCopy, nameByteCount, id->GetName(), nameByteCount); + m_id = SharedMemoryId(nameCopy, id->GetNameCharCount(), id->IsSessionScope()); + + SharedMemoryManager::AddProcessDataHeader(this); +} + +SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::New( + SharedMemoryId *id, + int fileDescriptor, + SharedMemorySharedDataHeader *sharedDataHeader, + SIZE_T sharedDataTotalByteCount) +{ + _ASSERTE(id != nullptr); + + // Allocate space for the header and a copy of the name + SIZE_T nameByteCount = id->GetNameCharCount() + 1; + SIZE_T totalByteCount = sizeof(SharedMemoryProcessDataHeader) + nameByteCount; + void *buffer = SharedMemoryHelpers::Alloc(totalByteCount); + AutoFreeBuffer autoFreeBuffer(buffer); + SharedMemoryProcessDataHeader *processDataHeader = + new(buffer) SharedMemoryProcessDataHeader(id, fileDescriptor, sharedDataHeader, sharedDataTotalByteCount); + autoFreeBuffer.Cancel(); + return processDataHeader; +} + +SharedMemoryProcessDataHeader::~SharedMemoryProcessDataHeader() +{ + _ASSERTE(m_refCount == 0); + Close(); +} + +void SharedMemoryProcessDataHeader::Close() +{ + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + _ASSERTE(!SharedMemoryManager::IsCreationDeletionFileLockAcquired()); + + // If the ref count is nonzero, we are shutting down the process abruptly without having closed some shared memory objects. + // There could still be threads running with active references to the shared memory object. So when the ref count is + // nonzero, don't clean up any object or global process-local state. + if (m_refCount == 0) + { + SharedMemoryManager::RemoveProcessDataHeader(this); + } + + struct AutoReleaseCreationDeletionFileLock + { + bool m_acquired; + + AutoReleaseCreationDeletionFileLock() : m_acquired(false) + { + } + + ~AutoReleaseCreationDeletionFileLock() + { + if (m_acquired) + { + SharedMemoryManager::ReleaseCreationDeletionFileLock(); + } + } + } autoReleaseCreationDeletionFileLock; + + // A shared file lock on the shared memory file would be held by any process that has opened the same file. Try to take + // an exclusive lock on the file. Successfully acquiring an exclusive lock indicates that no process has a reference to + // the shared memory file, and this process can delete the file. File locks on the shared memory file are only ever acquired + // or released while holding the creation/deletion locks, so holding the creation/deletion locks while trying an exclusive + // lock on the shared memory file guarantees that another process cannot start using the shared memory file after this + // process has decided to delete the file. + bool releaseSharedData = false; + try + { + SharedMemoryManager::AcquireCreationDeletionFileLock(); + autoReleaseCreationDeletionFileLock.m_acquired = true; + + SharedMemoryHelpers::ReleaseFileLock(m_fileDescriptor); + if (SharedMemoryHelpers::TryAcquireFileLock(m_fileDescriptor, LOCK_EX | LOCK_NB)) + { + SharedMemoryHelpers::ReleaseFileLock(m_fileDescriptor); + releaseSharedData = true; + } + } + catch (SharedMemoryException) + { + // Ignore the error, just don't release shared data + } + + if (m_data != nullptr) + { + m_data->Close(m_refCount != 0 /* isAbruptShutdown */, releaseSharedData); + } + + if (m_refCount == 0) + { + if (m_data != nullptr) + { + InternalDelete(m_data); + } + + if (releaseSharedData) + { + m_sharedDataHeader->~SharedMemorySharedDataHeader(); + } + + munmap(m_sharedDataHeader, m_sharedDataTotalByteCount); + SharedMemoryHelpers::CloseFile(m_fileDescriptor); + } + + if (!releaseSharedData) + { + return; + } + + try + { + // Delete the shared memory file, and the session directory if it's not empty + PathCharString path; + SharedMemoryHelpers::VerifyStringOperation(SharedMemoryManager::CopySharedMemoryBasePath(path)); + SharedMemoryHelpers::VerifyStringOperation(path.Append('/')); + SharedMemoryHelpers::VerifyStringOperation(m_id.AppendSessionDirectoryName(path)); + SharedMemoryHelpers::VerifyStringOperation(path.Append('/')); + + SIZE_T sessionDirectoryPathCharCount = path.GetCount(); + SharedMemoryHelpers::VerifyStringOperation(path.Append(m_id.GetName(), m_id.GetNameCharCount())); + unlink(path); + path.CloseBuffer(sessionDirectoryPathCharCount); + rmdir(path); + } + catch (SharedMemoryException) + { + // Ignore the error, just don't release shared data + } +} + +SharedMemoryId *SharedMemoryProcessDataHeader::GetId() +{ + return &m_id; +} + +SharedMemoryProcessDataBase *SharedMemoryProcessDataHeader::GetData() const +{ + return m_data; +} + +void SharedMemoryProcessDataHeader::SetData(SharedMemoryProcessDataBase *data) +{ + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + _ASSERTE(m_data == nullptr); + _ASSERTE(data != nullptr); + + m_data = data; +} + +SharedMemorySharedDataHeader *SharedMemoryProcessDataHeader::GetSharedDataHeader() const +{ + return m_sharedDataHeader; +} + +SIZE_T SharedMemoryProcessDataHeader::GetSharedDataTotalByteCount() const +{ + return m_sharedDataTotalByteCount; +} + +SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::GetNextInProcessDataHeaderList() const +{ + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + return m_nextInProcessDataHeaderList; +} + +void SharedMemoryProcessDataHeader::SetNextInProcessDataHeaderList(SharedMemoryProcessDataHeader *next) +{ + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + m_nextInProcessDataHeaderList = next; +} + +void SharedMemoryProcessDataHeader::IncRefCount() +{ + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + _ASSERTE(m_refCount != 0); + + ++m_refCount; +} + +void SharedMemoryProcessDataHeader::DecRefCount() +{ + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + _ASSERTE(m_refCount != 0); + + if (--m_refCount == 0) + { + InternalDelete(this); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SharedMemoryManager + +CRITICAL_SECTION SharedMemoryManager::s_creationDeletionProcessLock; +int SharedMemoryManager::s_creationDeletionLockFileDescriptor = -1; + +SharedMemoryProcessDataHeader *SharedMemoryManager::s_processDataHeaderListHead = nullptr; +PathCharString* SharedMemoryManager::s_runtimeTempDirectoryPath; +PathCharString* SharedMemoryManager::s_sharedMemoryDirectoryPath; + +#ifdef _DEBUG +SIZE_T SharedMemoryManager::s_creationDeletionProcessLockOwnerThreadId = SharedMemoryHelpers::InvalidThreadId; +SIZE_T SharedMemoryManager::s_creationDeletionFileLockOwnerThreadId = SharedMemoryHelpers::InvalidThreadId; +#endif // _DEBUG + +bool SharedMemoryManager::StaticInitialize() +{ + InitializeCriticalSection(&s_creationDeletionProcessLock); + + s_runtimeTempDirectoryPath = InternalNew(); + s_sharedMemoryDirectoryPath = InternalNew(); + + if (s_runtimeTempDirectoryPath && s_sharedMemoryDirectoryPath) + { + try + { + SharedMemoryHelpers::BuildSharedFilesPath(*s_runtimeTempDirectoryPath, SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_NAME); + SharedMemoryHelpers::BuildSharedFilesPath(*s_sharedMemoryDirectoryPath, SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_NAME); + + return true; + } + catch (SharedMemoryException) + { + // Ignore and let function fail + } + } + return false; +} + +void SharedMemoryManager::StaticClose() +{ + // This function could very well be running during abrupt shutdown, and there could still be user threads running. + // Synchronize the deletion, and don't remove or delete items in the linked list. + AcquireCreationDeletionProcessLock(); + for (SharedMemoryProcessDataHeader *current = s_processDataHeaderListHead; + current != nullptr; + current = current->GetNextInProcessDataHeaderList()) + { + current->Close(); + } + ReleaseCreationDeletionProcessLock(); + + // This function could very well be running during abrupt shutdown, and there could still be user threads running. Don't + // delete the creation/deletion process lock, the process is shutting down anyway. +} + +void SharedMemoryManager::AcquireCreationDeletionProcessLock() +{ + _ASSERTE(!IsCreationDeletionProcessLockAcquired()); + _ASSERTE(!IsCreationDeletionFileLockAcquired()); + + EnterCriticalSection(&s_creationDeletionProcessLock); +#ifdef _DEBUG + s_creationDeletionProcessLockOwnerThreadId = THREADSilentGetCurrentThreadId(); +#endif // _DEBUG +} + +void SharedMemoryManager::ReleaseCreationDeletionProcessLock() +{ + _ASSERTE(IsCreationDeletionProcessLockAcquired()); + _ASSERTE(!IsCreationDeletionFileLockAcquired()); + +#ifdef _DEBUG + s_creationDeletionProcessLockOwnerThreadId = SharedMemoryHelpers::InvalidThreadId; +#endif // _DEBUG + LeaveCriticalSection(&s_creationDeletionProcessLock); +} + +void SharedMemoryManager::AcquireCreationDeletionFileLock() +{ + _ASSERTE(IsCreationDeletionProcessLockAcquired()); + _ASSERTE(!IsCreationDeletionFileLockAcquired()); + + if (s_creationDeletionLockFileDescriptor == -1) + { + if (!SharedMemoryHelpers::EnsureDirectoryExists( + *gSharedFilesPath, + false /* isGlobalLockAcquired */, + false /* createIfNotExist */, + true /* isSystemDirectory */)) + { + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + SharedMemoryHelpers::EnsureDirectoryExists( + *s_runtimeTempDirectoryPath, + false /* isGlobalLockAcquired */); + SharedMemoryHelpers::EnsureDirectoryExists( + *s_sharedMemoryDirectoryPath, + false /* isGlobalLockAcquired */); + s_creationDeletionLockFileDescriptor = SharedMemoryHelpers::OpenDirectory(*s_sharedMemoryDirectoryPath); + if (s_creationDeletionLockFileDescriptor == -1) + { + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + } + + bool acquiredFileLock = SharedMemoryHelpers::TryAcquireFileLock(s_creationDeletionLockFileDescriptor, LOCK_EX); + _ASSERTE(acquiredFileLock); +#ifdef _DEBUG + s_creationDeletionFileLockOwnerThreadId = THREADSilentGetCurrentThreadId(); +#endif // _DEBUG +} + +void SharedMemoryManager::ReleaseCreationDeletionFileLock() +{ + _ASSERTE(IsCreationDeletionProcessLockAcquired()); + _ASSERTE(IsCreationDeletionFileLockAcquired()); + _ASSERTE(s_creationDeletionLockFileDescriptor != -1); + +#ifdef _DEBUG + s_creationDeletionFileLockOwnerThreadId = SharedMemoryHelpers::InvalidThreadId; +#endif // _DEBUG + SharedMemoryHelpers::ReleaseFileLock(s_creationDeletionLockFileDescriptor); +} + +#ifdef _DEBUG +bool SharedMemoryManager::IsCreationDeletionProcessLockAcquired() +{ + return s_creationDeletionProcessLockOwnerThreadId == THREADSilentGetCurrentThreadId(); +} + +bool SharedMemoryManager::IsCreationDeletionFileLockAcquired() +{ + return s_creationDeletionFileLockOwnerThreadId == THREADSilentGetCurrentThreadId(); +} +#endif // _DEBUG + +void SharedMemoryManager::AddProcessDataHeader(SharedMemoryProcessDataHeader *processDataHeader) +{ + _ASSERTE(processDataHeader != nullptr); + _ASSERTE(IsCreationDeletionProcessLockAcquired()); + _ASSERTE(processDataHeader->GetNextInProcessDataHeaderList() == nullptr); + _ASSERTE(FindProcessDataHeader(processDataHeader->GetId()) == nullptr); + + processDataHeader->SetNextInProcessDataHeaderList(s_processDataHeaderListHead); + s_processDataHeaderListHead = processDataHeader; +} + +void SharedMemoryManager::RemoveProcessDataHeader(SharedMemoryProcessDataHeader *processDataHeader) +{ + _ASSERTE(processDataHeader != nullptr); + _ASSERTE(IsCreationDeletionProcessLockAcquired()); + + if (s_processDataHeaderListHead == processDataHeader) + { + s_processDataHeaderListHead = processDataHeader->GetNextInProcessDataHeaderList(); + processDataHeader->SetNextInProcessDataHeaderList(nullptr); + return; + } + for (SharedMemoryProcessDataHeader + *previous = s_processDataHeaderListHead, + *current = previous->GetNextInProcessDataHeaderList(); + current != nullptr; + previous = current, current = current->GetNextInProcessDataHeaderList()) + { + if (current == processDataHeader) + { + previous->SetNextInProcessDataHeaderList(current->GetNextInProcessDataHeaderList()); + current->SetNextInProcessDataHeaderList(nullptr); + return; + } + } + _ASSERTE(false); +} + +SharedMemoryProcessDataHeader *SharedMemoryManager::FindProcessDataHeader(SharedMemoryId *id) +{ + _ASSERTE(IsCreationDeletionProcessLockAcquired()); + + // TODO: Use a hash table + for (SharedMemoryProcessDataHeader *current = s_processDataHeaderListHead; + current != nullptr; + current = current->GetNextInProcessDataHeaderList()) + { + if (current->GetId()->Equals(id)) + { + return current; + } + } + return nullptr; +} + +bool SharedMemoryManager::CopySharedMemoryBasePath(PathCharString& destination) +{ + return destination.Set(*s_sharedMemoryDirectoryPath) != FALSE; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/shmemory/shmemory.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/shmemory/shmemory.cpp new file mode 100644 index 0000000..9539d10 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/shmemory/shmemory.cpp @@ -0,0 +1,388 @@ +// 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: + + shmemory/shmemory.c + +Abstract: + + Implementation of shared memory infrastructure for IPC + + + +--*/ + +#include "pal/dbgmsg.h" +#include "pal/shmemory.h" +#include "pal/critsect.h" +#include "pal/process.h" + +#if HAVE_YIELD_SYSCALL +#include +#endif /* HAVE_YIELD_SYSCALL */ + +SET_DEFAULT_DEBUG_CHANNEL(SHMEM); + +/* Type definitions ***********************************************************/ + +/* +SHM_HEADER +Global information about the shared memory system + +The spinlock is used to ensure that only one process accesses shared memory at +the same time. A process can only take the spinlock if its contents is 0, and +it takes the spinlock by placing its PID in it. (this allows a process to catch +the special case where it tries to take a spinlock it already owns. +*/ + +typedef struct +{ + Volatile spinlock; + Volatile shm_info[SIID_LAST]; /* basic blocks of shared information.*/ +} SHM_HEADER; + +static SHM_HEADER shm_header; + +/* Static variables ***********************************************************/ + +/* Critical section to ensure that only one thread at a time accesses shared +memory. Rationale : +-Using a spinlock means that processes must busy-wait for the lock to be + available. The critical section ensures taht only one thread will busy-wait, + while the rest are put to sleep. +-Since the spinlock only contains a PID, it isn't possible to make a difference + between threads of the same process. This could be resolved by using 2 + spinlocks, but this would introduce more busy-wait. +*/ +static CRITICAL_SECTION shm_critsec; + +/* number of locks the process currently holds (SHMLock calls without matching +SHMRelease). Because we take the critical section while inside a +SHMLock/SHMRelease pair, this is actually the number of locks held by a single +thread. */ +static Volatile lock_count; + +/* thread ID of thread holding the SHM lock. used for debugging purposes : + SHMGet/SetInfo will verify that the calling thread holds the lock */ +static Volatile locking_thread; + +/* Public function implementations ********************************************/ + +/*++ +SHMInitialize + +Hook this process into the PAL shared memory system; initialize the shared +memory if no other process has done it. + +--*/ +BOOL SHMInitialize(void) +{ + InternalInitializeCriticalSection(&shm_critsec); + + TRACE("Now initializing global shared memory system\n"); + + InterlockedExchange((LONG *)&shm_header.spinlock, 0); + + /* SHM information array starts with NULLs */ + memset((void *)shm_header.shm_info, 0, SIID_LAST*sizeof(SHMPTR)); + + TRACE("Global shared memory initialization complete.\n"); + + lock_count = 0; + locking_thread = 0; + + return TRUE; +} + +/*++ +SHMCleanup + +Release all shared memory resources held; remove ourselves from the list of +registered processes, and remove all shared memory files if no process remains + +Note that this function does not use thread suspension wrapper for unlink and free +because all thread objects are deleted before this function is called +in PALCommonCleanup. + +--*/ +void SHMCleanup(void) +{ + pid_t my_pid; + + TRACE("Starting shared memory cleanup\n"); + + SHMLock(); + SHMRelease(); + + /* We should not be holding the spinlock at this point. If we are, release + the spinlock. by setting it to 0 */ + my_pid = gPID; + + _ASSERT_MSG(shm_header.spinlock != my_pid, + "SHMCleanup called while the current process still owns the lock " + "[owner thread=%u, current thread: %u]\n", + locking_thread.Load(), THREADSilentGetCurrentThreadId()); + + /* Now for the interprocess stuff. */ + DeleteCriticalSection(&shm_critsec); + + TRACE("SHMCleanup complete!\n"); +} + +/*++ +SHMLock + +Restrict shared memory access to the current thread of the current process + +(no parameters) + +Return value : + New lock count + +Notes : +see comments at the declaration of shm_critsec for rationale of critical +section usage +--*/ +int SHMLock(void) +{ + /* Hold the critical section until the lock is released */ + PALCEnterCriticalSection(&shm_critsec); + + _ASSERTE((0 == lock_count && 0 == locking_thread) || + (0 < lock_count && reinterpret_cast(pthread_self()) == locking_thread)); + + if(lock_count == 0) + { + pid_t my_pid, tmp_pid; + int spincount = 1; + + TRACE("First-level SHM lock : taking spinlock\n"); + + // Store the id of the current thread as the (only) one that is + // trying to grab the spinlock from the current process + locking_thread = reinterpret_cast(pthread_self()); + + my_pid = gPID; + + while(TRUE) + { + // + // Try to grab the spinlock + // + tmp_pid = InterlockedCompareExchange((LONG *) &shm_header.spinlock, my_pid,0); + + if (0 == tmp_pid) + { + // Spinlock acquired: break out of the loop + break; + } + + /* Check if lock holder is alive. If it isn't, we can reset the + spinlock and try to take it again. If it is, we have to wait. + We use "spincount" to do this check only every 8th time through + the loop, for performance reasons.*/ + if( (0 == (spincount&0x7)) && + (-1 == kill(tmp_pid,0)) && + (errno == ESRCH)) + { + TRACE("SHM spinlock owner (%08x) is dead; releasing its lock\n", + tmp_pid); + + InterlockedCompareExchange((LONG *) &shm_header.spinlock, 0, tmp_pid); + } + else + { + /* another process is holding the lock... we want to yield and + give the holder a chance to release the lock + The function sched_yield() only yields to a thread in the + current process; this doesn't help us much, and doesn't help + at all if there's only 1 thread. There doesn't seem to be + any clean way to force a yield to another process, but the + FreeBSD syscall "yield" does the job. We alternate between + both methods to give other threads of this process a chance + to run while we wait. + */ +#if HAVE_YIELD_SYSCALL + if(spincount&1) + { +#endif /* HAVE_YIELD_SYSCALL */ + sched_yield(); +#if HAVE_YIELD_SYSCALL + } + else + { + /* use the syscall first, since we know we'l need to yield + to another process eventually - the lock can't be held + by the current process, thanks to the critical section */ + syscall(SYS_yield, 0); + } +#endif /* HAVE_YIELD_SYSCALL */ + } + + // Increment spincount + spincount++; + } + + _ASSERT_MSG(my_pid == shm_header.spinlock, + "\n(my_pid = %u) != (header->spinlock = %u)\n" + "tmp_pid = %u\n" + "spincount = %d\n" + "locking_thread = %u\n", + (DWORD)my_pid, (DWORD)shm_header.spinlock, + (DWORD)tmp_pid, + (int)spincount, + (HANDLE)locking_thread); + } + + lock_count++; + TRACE("SHM lock level is now %d\n", lock_count.Load()); + return lock_count; +} + +/*++ +SHMRelease + +Release a lock on shared memory taken with SHMLock. + +(no parameters) + +Return value : + New lock count + +--*/ +int SHMRelease(void) +{ + /* prevent a thread from releasing another thread's lock */ + PALCEnterCriticalSection(&shm_critsec); + + if(lock_count==0) + { + ASSERT("SHMRelease called without matching SHMLock!\n"); + PALCLeaveCriticalSection(&shm_critsec); + return 0; + } + + lock_count--; + + _ASSERTE(lock_count >= 0); + + /* If lock count is 0, this call matches the first Lock call; it's time to + set the spinlock back to 0. */ + if(lock_count == 0) + { + pid_t my_pid, tmp_pid; + + TRACE("Releasing first-level SHM lock : resetting spinlock\n"); + + my_pid = gPID; + + /* Make sure we don't touch the spinlock if we don't own it. We're + supposed to own it if we get here, but just in case... */ + tmp_pid = InterlockedCompareExchange((LONG *) &shm_header.spinlock, 0, my_pid); + + if (tmp_pid != my_pid) + { + ASSERT("Process 0x%08x tried to release spinlock owned by process " + "0x%08x! \n", my_pid, tmp_pid); + PALCLeaveCriticalSection(&shm_critsec); + return 0; + } + + /* indicate no thread (in this process) holds the SHM lock */ + locking_thread = 0; + } + + TRACE("SHM lock level is now %d\n", lock_count.Load()); + + /* This matches the EnterCriticalSection from SHMRelease */ + PALCLeaveCriticalSection(&shm_critsec); + + /* This matches the EnterCriticalSection from SHMLock */ + PALCLeaveCriticalSection(&shm_critsec); + + return lock_count; +} + +/*++ +Function : + SHMGetInfo + + Retrieve some information from shared memory + +Parameters : + SHM_INFO_ID element : identifier of element to retrieve + +Return value : + Value of specified element + +Notes : + The SHM lock should be held while manipulating shared memory +--*/ +SHMPTR SHMGetInfo(SHM_INFO_ID element) +{ + SHMPTR retval = 0; + + if(element < 0 || element >= SIID_LAST) + { + ASSERT("Invalid SHM info element %d\n", element); + return 0; + } + + /* verify that this thread holds the SHM lock. No race condition: if the + current thread is here, it can't be in SHMLock or SHMUnlock */ + if( reinterpret_cast(pthread_self()) != locking_thread ) + { + ASSERT("SHMGetInfo called while thread does not hold the SHM lock!\n"); + } + + retval = shm_header.shm_info[element]; + + TRACE("SHM info element %d is %08x\n", element, retval ); + return retval; +} + + +/*++ +Function : + SHMSetInfo + + Place some information into shared memory + +Parameters : + SHM_INFO_ID element : identifier of element to save + SHMPTR value : new value of element + +Return value : + TRUE if successful, FALSE otherwise. + +Notes : + The SHM lock should be held while manipulating shared memory +--*/ +BOOL SHMSetInfo(SHM_INFO_ID element, SHMPTR value) +{ + if(element < 0 || element >= SIID_LAST) + { + ASSERT("Invalid SHM info element %d\n", element); + return FALSE; + } + + /* verify that this thread holds the SHM lock. No race condition: if the + current thread is here, it can't be in SHMLock or SHMUnlock */ + if( reinterpret_cast(pthread_self()) != locking_thread ) + { + ASSERT("SHMGetInfo called while thread does not hold the SHM lock!\n"); + } + + TRACE("Setting SHM info element %d to %08x; used to be %08x\n", + element, value, shm_header.shm_info[element].Load() ); + + shm_header.shm_info[element] = value; + + return TRUE; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/sync/cs.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/sync/cs.cpp new file mode 100644 index 0000000..3545500 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/sync/cs.cpp @@ -0,0 +1,1607 @@ +// 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. + +/////////////////////////////////////////////////////////////////////////////// +// +// File: +// cs.cpp +// +// Purpose: +// Implementation of critical sections +// +/////////////////////////////////////////////////////////////////////////////// + +#include "pal/thread.hpp" +#include "pal/cs.hpp" +#include "pal/malloc.hpp" +#include "pal/list.h" +#include "pal/dbgmsg.h" +#include "pal/init.h" +#include "pal/process.h" + +#include +#include + +using namespace CorUnix; + +// +// Uncomment the following line to turn CS behavior from +// unfair to fair lock +// +// #define PALCS_TRANSFER_OWNERSHIP_ON_RELEASE + +// +// Uncomment the following line to enable simple mutex based CSs +// Note: when MUTEX_BASED_CSS is defined, PALCS_TRANSFER_OWNERSHIP_ON_RELEASE +// has no effect +// +// #define MUTEX_BASED_CSS + +// +// Important notes on critical sections layout/semantics on Unix +// +// 1) The PAL_CRITICAL_SECTION structure below must match the size of the +// CRITICAL_SECTION defined in pal.h. Besides the "windows part" +// of both the structures must be identical. +// 2) Both PAL_CRITICAL_SECTION and CRITICAL_SECTION currently do not match +// the size of the Windows' CRITICAL_SECTION. +// - From unmanaged code point of view, one should never make assumptions +// on the size and layout of the CRITICAL_SECTION structure, and anyway +// on Unix PAL's CRITICAL_SECTION extends the Windows one, so that some +// assumptions may still work. +// - From managed code point of view, one could try to interop directly +// to unmanaged critical sections APIs (though that would be quite +// meaningless). In order to do that, one would need to define a copy +// of the CRITICAL_SECTION structure in one's code, and that may lead +// to access random data beyond the structure limit, if that managed +// code is compiled on Unix. +// In case such scenario should be supported, the current implementation +// will have to be modified in a way to go back to the original Windows +// CRITICAL_SECTION layout. That would require to dynamically allocate +// the native data and use LockSemaphore as a pointer to it. The current +// solution intentionally avoids that since an effort has been made to +// make CSs objects completely independent from any other PAL subsystem, +// so that they can be used during initialization and shutdown. +// In case the "dynamically allocate native data" solution should be +// implemented, CSs would acquire a dependency on memory allocation and +// thread suspension subsystems, since the first contention on a specific +// CS would trigger the native data allocation. +// 3) The semantics of the LockCount field has not been kept compatible with +// the Windows implementation. +// Both on Windows and Unix the lower bit of LockCount indicates +// whether or not the CS is locked (for both fair and unfair lock +// solution), the second bit indicates whether or not currently there is a +// waiter that has been awakened and that is trying to acquire the CS +// (only unfair lock solution, unused in the fair one); starting from the +// third bit, LockCount represents the number of waiter threads currently +// waiting on the CS. +// Windows, anyway, implements this semantics in negative logic, so that +// an unlocked CS is represented by a LockCount == -1 (i.e. 0xFFFFFFFF, +// all the bits set), while on Unix an unlocked CS has LockCount == 0. +// Windows needs to use negative logic to support legacy code bad enough +// to directly access CS's fields making the assumption that +// LockCount == -1 means CS unlocked. Unix will not support that, and +// it uses positive logic. +// 4) The CRITICAL_SECTION_DEBUG_INFO layout on Unix is intentionally not +// compatible with the Windows layout. +// 5) For legacy code dependencies issues similar to those just described for +// the LockCount field, Windows CS code maintains a per-process list of +// debug info for all the CSs, both on debug and free/retail builds. On +// Unix such a list is maintained only on debug builds, and no debug +// info structure is allocated on free/retail builds +// + +SET_DEFAULT_DEBUG_CHANNEL(CRITSEC); + +#ifdef TRACE_CS_LOGIC +#define CS_TRACE TRACE +#else +#ifdef __GNUC__ +#define CS_TRACE(args...) +#else +#define CS_TRACE(...) +#endif +#endif // TRACE_CS_LOGIC + +// +// Note: PALCS_LOCK_WAITER_INC must be 2 * PALCS_LOCK_AWAKENED_WAITER +// +#define PALCS_LOCK_INIT 0 +#define PALCS_LOCK_BIT 1 +#define PALCS_LOCK_AWAKENED_WAITER 2 +#define PALCS_LOCK_WAITER_INC 4 + +#define PALCS_GETLBIT(val) ((int)(0!=(PALCS_LOCK_BIT&val))) +#define PALCS_GETAWBIT(val) ((int)(0!=(PALCS_LOCK_AWAKENED_WAITER&val))) +#define PALCS_GETWCOUNT(val) (val/PALCS_LOCK_WAITER_INC) + +enum PalCsInitState +{ + PalCsNotInitialized, // Critical section not initialized (InitializedCriticalSection + // has not yet been called, or DeleteCriticalsection has been + // called). + PalCsUserInitialized, // Critical section initialized from the user point of view, + // i.e. InitializedCriticalSection has been called. + PalCsFullyInitializing, // A thread found the CS locked, this is the first contention on + // this CS, and the thread is initializing the CS's native data. + PalCsFullyInitialized // Internal CS's native data has been fully initialized. +}; + +enum PalCsWaiterReturnState +{ + PalCsReturnWaiterAwakened, + PalCsWaiterDidntWait +}; + +struct _PAL_CRITICAL_SECTION; // fwd declaration + +typedef struct _CRITICAL_SECTION_DEBUG_INFO +{ + LIST_ENTRY Link; + struct _PAL_CRITICAL_SECTION * pOwnerCS; + Volatile lAcquireCount; + Volatile lEnterCount; + Volatile lContentionCount; +} CRITICAL_SECTION_DEBUG_INFO, *PCRITICAL_SECTION_DEBUG_INFO; + +typedef struct _PAL_CRITICAL_SECTION_NATIVE_DATA +{ + pthread_mutex_t mutex; + pthread_cond_t condition; + int iPredicate; +} PAL_CRITICAL_SECTION_NATIVE_DATA, *PPAL_CRITICAL_SECTION_NATIVE_DATA; + +typedef struct _PAL_CRITICAL_SECTION { + // Windows part + PCRITICAL_SECTION_DEBUG_INFO DebugInfo; + Volatile LockCount; + LONG RecursionCount; + SIZE_T OwningThread; + ULONG_PTR SpinCount; + // Private Unix part +#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA + BOOL fInternal; +#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA + Volatile cisInitState; + PAL_CRITICAL_SECTION_NATIVE_DATA csndNativeData; +} PAL_CRITICAL_SECTION, *PPAL_CRITICAL_SECTION, *LPPAL_CRITICAL_SECTION; + +#ifdef _DEBUG +namespace CorUnix +{ + PAL_CRITICAL_SECTION g_csPALCSsListLock; + LIST_ENTRY g_PALCSList = { &g_PALCSList, &g_PALCSList}; +} +#endif // _DEBUG + +#define ObtainCurrentThreadId(thread) ObtainCurrentThreadIdImpl(thread, __func__) +static SIZE_T ObtainCurrentThreadIdImpl(CPalThread *pCurrentThread, const char *callingFuncName) +{ + SIZE_T threadId; + if(pCurrentThread) + { + threadId = pCurrentThread->GetThreadId(); + _ASSERTE(threadId == THREADSilentGetCurrentThreadId()); + } + else + { + threadId = THREADSilentGetCurrentThreadId(); + CS_TRACE("Early %s, no pthread data, getting TID internally\n", callingFuncName); + } + _ASSERTE(0 != threadId); + + return threadId; +} + + +/*++ +Function: + InitializeCriticalSection + +See MSDN doc. +--*/ +void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + PERF_ENTRY(InitializeCriticalSection); + ENTRY("InitializeCriticalSection(lpCriticalSection=%p)\n", + lpCriticalSection); + + InternalInitializeCriticalSectionAndSpinCount(lpCriticalSection, + 0, false); + + LOGEXIT("InitializeCriticalSection returns void\n"); + PERF_EXIT(InitializeCriticalSection); +} + +/*++ +Function: + InitializeCriticalSectionEx - Flags is ignored. + +See MSDN doc. +--*/ +BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags) +{ + PERF_ENTRY(InitializeCriticalSection); + ENTRY("InitializeCriticalSectionEx(lpCriticalSection=%p, dwSpinCount=%d, Flags=%d)\n", + lpCriticalSection, dwSpinCount, Flags); + + InternalInitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount, false); + + LOGEXIT("InitializeCriticalSectionEx returns TRUE\n"); + PERF_EXIT(InitializeCriticalSection); + return true; +} + +/*++ +Function: + InitializeCriticalSectionAndSpinCount + +See MSDN doc. +--*/ +BOOL InitializeCriticalSectionAndSpinCount(LPCRITICAL_SECTION lpCriticalSection, + DWORD dwSpinCount) +{ + BOOL bRet = TRUE; + PERF_ENTRY(InitializeCriticalSectionAndSpinCount); + ENTRY("InitializeCriticalSectionAndSpinCount(lpCriticalSection=%p, " + "dwSpinCount=%u)\n", lpCriticalSection, dwSpinCount); + + InternalInitializeCriticalSectionAndSpinCount(lpCriticalSection, + dwSpinCount, false); + + LOGEXIT("InitializeCriticalSectionAndSpinCount returns BOOL %d\n", + bRet); + PERF_EXIT(InitializeCriticalSectionAndSpinCount); + return bRet; +} + +/*++ +Function: + DeleteCriticalSection + +See MSDN doc. +--*/ +void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + PERF_ENTRY(DeleteCriticalSection); + ENTRY("DeleteCriticalSection(lpCriticalSection=%p)\n", lpCriticalSection); + + InternalDeleteCriticalSection(lpCriticalSection); + + LOGEXIT("DeleteCriticalSection returns void\n"); + PERF_EXIT(DeleteCriticalSection); +} + +/*++ +Function: + EnterCriticalSection + +See MSDN doc. +--*/ +void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + PERF_ENTRY(EnterCriticalSection); + ENTRY("EnterCriticalSection(lpCriticalSection=%p)\n", lpCriticalSection); + + CPalThread * pThread = InternalGetCurrentThread(); + + InternalEnterCriticalSection(pThread, lpCriticalSection); + + LOGEXIT("EnterCriticalSection returns void\n"); + PERF_EXIT(EnterCriticalSection); +} + +/*++ +Function: + TryEnterCriticalSection + +See MSDN doc. +--*/ +BOOL TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + PERF_ENTRY(TryEnterCriticalSection); + ENTRY("TryEnterCriticalSection(lpCriticalSection=%p)\n", lpCriticalSection); + + CPalThread * pThread = InternalGetCurrentThread(); + + bool fRet = InternalTryEnterCriticalSection(pThread, + lpCriticalSection); + + LOGEXIT("TryEnterCriticalSection returns bool %d\n", (int)fRet); + PERF_EXIT(TryEnterCriticalSection); + + return (BOOL)fRet; +} + +/*++ +Function: + LeaveCriticalSection + +See MSDN doc. +--*/ +VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + PERF_ENTRY(LeaveCriticalSection); + ENTRY("LeaveCriticalSection(lpCriticalSection=%p)\n", lpCriticalSection); + + CPalThread * pThread = InternalGetCurrentThread(); + + InternalLeaveCriticalSection(pThread, lpCriticalSection); + + LOGEXIT("LeaveCriticalSection returns void\n"); + PERF_EXIT(LeaveCriticalSection); +} + +/*++ +Function: + InternalInitializeCriticalSection + +Initializes a critical section. It assumes the CS is an internal one, +i.e. thread entering it will be marked unsafe for suspension +--*/ +VOID InternalInitializeCriticalSection(CRITICAL_SECTION *pcs) +{ + InternalInitializeCriticalSectionAndSpinCount(pcs, 0, true); +} + +/*++ +Function: + InternalDeleteCriticalSection + +Deletes a critical section +--*/ +VOID InternalDeleteCriticalSection( + PCRITICAL_SECTION pCriticalSection) +{ + PAL_CRITICAL_SECTION * pPalCriticalSection = + reinterpret_cast(pCriticalSection); + + _ASSERT_MSG(PalCsUserInitialized == pPalCriticalSection->cisInitState || + PalCsFullyInitialized == pPalCriticalSection->cisInitState, + "CS %p is not initialized", pPalCriticalSection); + +#ifdef _DEBUG + CPalThread * pThread = + (PALIsThreadDataInitialized() ? GetCurrentPalThread() : NULL); + + if (0 != pPalCriticalSection->LockCount) + { + SIZE_T tid; + tid = ObtainCurrentThreadId(pThread); + int iWaiterCount = (int)PALCS_GETWCOUNT(pPalCriticalSection->LockCount); + + if (0 != (PALCS_LOCK_BIT & pPalCriticalSection->LockCount)) + { + // CS is locked + if (tid != pPalCriticalSection->OwningThread) + { + // not owner + ASSERT("Thread tid=%u deleting a CS owned by thread tid=%u\n", + tid, pPalCriticalSection->OwningThread); + } + else + { + // owner + if (0 != iWaiterCount) + { + ERROR("Thread tid=%u is deleting a CS with %d threads waiting on it\n", + tid, iWaiterCount); + } + else + { + WARN("Thread tid=%u is deleting a critical section it still owns\n", + tid); + } + } + } + else + { + // CS is not locked + if (0 != iWaiterCount) + { + ERROR("Deleting a CS with %d threads waiting on it\n", + iWaiterCount); + } + else + { + ERROR("Thread tid=%u is deleting a critical section currently not " + "owned, but with one waiter awakened\n", tid); + } + } + } + + if (NULL != pPalCriticalSection->DebugInfo) + { + if (pPalCriticalSection != &CorUnix::g_csPALCSsListLock) + { + InternalEnterCriticalSection(pThread, + reinterpret_cast(&g_csPALCSsListLock)); + RemoveEntryList(&pPalCriticalSection->DebugInfo->Link); + InternalLeaveCriticalSection(pThread, + reinterpret_cast(&g_csPALCSsListLock)); + } + else + { + RemoveEntryList(&pPalCriticalSection->DebugInfo->Link); + } + +#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA + LONG lVal, lNewVal; + Volatile * plDest; + + // Update delete count + InterlockedIncrement(pPalCriticalSection->fInternal ? + &g_lPALCSInternalDeleteCount : &g_lPALCSDeleteCount); + + // Update acquire count + plDest = pPalCriticalSection->fInternal ? + &g_lPALCSInternalAcquireCount : &g_lPALCSAcquireCount; + do { + lVal = *plDest; + lNewVal = lVal + pPalCriticalSection->DebugInfo->lAcquireCount; + lNewVal = InterlockedCompareExchange(plDest, lNewVal, lVal); + } while (lVal != lNewVal); + + // Update enter count + plDest = pPalCriticalSection->fInternal ? + &g_lPALCSInternalEnterCount : &g_lPALCSEnterCount; + do { + lVal = *plDest; + lNewVal = lVal + pPalCriticalSection->DebugInfo->lEnterCount; + lNewVal = InterlockedCompareExchange(plDest, lNewVal, lVal); + } while (lVal != lNewVal); + + // Update contention count + plDest = pPalCriticalSection->fInternal ? + &g_lPALCSInternalContentionCount : &g_lPALCSContentionCount; + do { + lVal = *plDest; + lNewVal = lVal + pPalCriticalSection->DebugInfo->lContentionCount; + lNewVal = InterlockedCompareExchange(plDest, lNewVal, lVal); + } while (lVal != lNewVal); + +#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA + + InternalDelete(pPalCriticalSection->DebugInfo); + pPalCriticalSection->DebugInfo = NULL; + } +#endif // _DEBUG + + if (PalCsFullyInitialized == pPalCriticalSection->cisInitState) + { + int iRet; + + // destroy condition + iRet = pthread_cond_destroy(&pPalCriticalSection->csndNativeData.condition); + _ASSERT_MSG(0 == iRet, "Failed destroying condition in CS @ %p " + "[err=%d]\n", pPalCriticalSection, iRet); + + // destroy mutex + iRet = pthread_mutex_destroy(&pPalCriticalSection->csndNativeData.mutex); + _ASSERT_MSG(0 == iRet, "Failed destroying mutex in CS @ %p " + "[err=%d]\n", pPalCriticalSection, iRet); + } + + // Reset critical section state + pPalCriticalSection->cisInitState = PalCsNotInitialized; +} + +// The following PALCEnterCriticalSection and PALCLeaveCriticalSection +// functions are intended to provide CorUnix's InternalEnterCriticalSection +// and InternalLeaveCriticalSection functionalities to legacy C code, +// which has no knowledge of CPalThread, classes and namespaces. + +/*++ +Function: + PALCEnterCriticalSection + +Provides CorUnix's InternalEnterCriticalSection functionality to legacy C code, +which has no knowledge of CPalThread, classes and namespaces. +--*/ +VOID PALCEnterCriticalSection(CRITICAL_SECTION * pcs) +{ + CPalThread * pThread = + (PALIsThreadDataInitialized() ? GetCurrentPalThread() : NULL); + CorUnix::InternalEnterCriticalSection(pThread, pcs); +} + +/*++ +Function: + PALCLeaveCriticalSection + +Provides CorUnix's InternalLeaveCriticalSection functionality to legacy C code, +which has no knowledge of CPalThread, classes and namespaces. +--*/ +VOID PALCLeaveCriticalSection(CRITICAL_SECTION * pcs) +{ + CPalThread * pThread = + (PALIsThreadDataInitialized() ? GetCurrentPalThread() : NULL); + CorUnix::InternalLeaveCriticalSection(pThread, pcs); +} + +namespace CorUnix +{ + static PalCsWaiterReturnState PALCS_WaitOnCS( + PAL_CRITICAL_SECTION * pPalCriticalSection, + LONG lInc); + static PAL_ERROR PALCS_DoActualWait(PAL_CRITICAL_SECTION * pPalCriticalSection); + static PAL_ERROR PALCS_WakeUpWaiter(PAL_CRITICAL_SECTION * pPalCriticalSection); + static bool PALCS_FullyInitialize(PAL_CRITICAL_SECTION * pPalCriticalSection); + +#ifdef _DEBUG + enum CSSubSysInitState + { + CSSubSysNotInitialzed, + CSSubSysInitializing, + CSSubSysInitialized + }; + static Volatile csssInitState = CSSubSysNotInitialzed; + +#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA + static Volatile g_lPALCSInitializeCount = 0; + static Volatile g_lPALCSDeleteCount = 0; + static Volatile g_lPALCSAcquireCount = 0; + static Volatile g_lPALCSEnterCount = 0; + static Volatile g_lPALCSContentionCount = 0; + static Volatile g_lPALCSInternalInitializeCount = 0; + static Volatile g_lPALCSInternalDeleteCount = 0; + static Volatile g_lPALCSInternalAcquireCount = 0; + static Volatile g_lPALCSInternalEnterCount = 0; + static Volatile g_lPALCSInternalContentionCount = 0; +#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA +#endif // _DEBUG + + + /*++ + Function: + CorUnix::CriticalSectionSubSysInitialize + + Initializes CS subsystem + --*/ + void CriticalSectionSubSysInitialize() + { + static_assert(sizeof(CRITICAL_SECTION) >= sizeof(PAL_CRITICAL_SECTION), + "PAL fatal internal error: sizeof(CRITICAL_SECTION) is " + "smaller than sizeof(PAL_CRITICAL_SECTION)"); + +#ifdef _DEBUG + LONG lRet = InterlockedCompareExchange((LONG *)&csssInitState, + (LONG)CSSubSysInitializing, + (LONG)CSSubSysNotInitialzed); + if ((LONG)CSSubSysNotInitialzed == lRet) + { + InitializeListHead(&g_PALCSList); + + InternalInitializeCriticalSectionAndSpinCount( + reinterpret_cast(&g_csPALCSsListLock), + 0, true); + InterlockedExchange((LONG *)&csssInitState, + (LONG)CSSubSysInitialized); + } + else + { + while (csssInitState != CSSubSysInitialized) + { + sched_yield(); + } + } +#endif // _DEBUG + } + + /*++ + Function: + CorUnix::InternalInitializeCriticalSectionAndSpinCount + + Initializes a CS with the given spin count. If 'fInternal' is true + the CS will be treatead as an internal one for its whole lifetime, + i.e. any thread that will enter it will be marked as unsafe for + suspension as long as it holds the CS + --*/ + void InternalInitializeCriticalSectionAndSpinCount( + PCRITICAL_SECTION pCriticalSection, + DWORD dwSpinCount, + bool fInternal) + { + PAL_CRITICAL_SECTION * pPalCriticalSection = + reinterpret_cast(pCriticalSection); + +#ifndef PALCS_TRANSFER_OWNERSHIP_ON_RELEASE + // Make sure bits are defined in a usable way + _ASSERTE(PALCS_LOCK_AWAKENED_WAITER * 2 == PALCS_LOCK_WAITER_INC); +#endif // !PALCS_TRANSFER_OWNERSHIP_ON_RELEASE + + // Make sure structure sizes are compatible + _ASSERTE(sizeof(CRITICAL_SECTION) >= sizeof(PAL_CRITICAL_SECTION)); + +#ifdef _DEBUG + if (sizeof(CRITICAL_SECTION) > sizeof(PAL_CRITICAL_SECTION)) + { + WARN("PAL_CS_NATIVE_DATA_SIZE appears to be defined to a value (%d) " + "larger than needed on this platform (%d).\n", + sizeof(CRITICAL_SECTION), sizeof(PAL_CRITICAL_SECTION)); + } +#endif // _DEBUG + + // Init CS data + pPalCriticalSection->DebugInfo = NULL; + pPalCriticalSection->LockCount = 0; + pPalCriticalSection->RecursionCount = 0; + pPalCriticalSection->SpinCount = dwSpinCount; + pPalCriticalSection->OwningThread = 0; + +#ifdef _DEBUG + CPalThread * pThread = + (PALIsThreadDataInitialized() ? GetCurrentPalThread() : NULL); + + pPalCriticalSection->DebugInfo = InternalNew(); + _ASSERT_MSG(NULL != pPalCriticalSection->DebugInfo, + "Failed to allocate debug info for new CS\n"); + + // Init debug info data + pPalCriticalSection->DebugInfo->lAcquireCount = 0; + pPalCriticalSection->DebugInfo->lEnterCount = 0; + pPalCriticalSection->DebugInfo->lContentionCount = 0; + pPalCriticalSection->DebugInfo->pOwnerCS = pPalCriticalSection; + + // Insert debug info struct in global list + if (pPalCriticalSection != &g_csPALCSsListLock) + { + InternalEnterCriticalSection(pThread, + reinterpret_cast(&g_csPALCSsListLock)); + InsertTailList(&g_PALCSList, &pPalCriticalSection->DebugInfo->Link); + InternalLeaveCriticalSection(pThread, + reinterpret_cast(&g_csPALCSsListLock)); + } + else + { + InsertTailList(&g_PALCSList, &pPalCriticalSection->DebugInfo->Link); + } + +#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA + pPalCriticalSection->fInternal = fInternal; + InterlockedIncrement(fInternal ? + &g_lPALCSInternalInitializeCount : &g_lPALCSInitializeCount); +#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA +#endif // _DEBUG + + // Set initializazion state + pPalCriticalSection->cisInitState = PalCsUserInitialized; + +#ifdef MUTEX_BASED_CSS + bool fInit; + do + { + fInit = PALCS_FullyInitialize(pPalCriticalSection); + _ASSERTE(fInit); + } while (!fInit && 0 == sched_yield()); + + if (fInit) + { + // Set initializazion state + pPalCriticalSection->cisInitState = PalCsFullyInitialized; + } +#endif // MUTEX_BASED_CSS + } + +#ifndef MUTEX_BASED_CSS + /*++ + Function: + CorUnix::InternalEnterCriticalSection + + Enters a CS, causing the thread to block if the CS is owned by + another thread + --*/ + void InternalEnterCriticalSection( + CPalThread * pThread, + PCRITICAL_SECTION pCriticalSection) + { + PAL_CRITICAL_SECTION * pPalCriticalSection = + reinterpret_cast(pCriticalSection); + + LONG lSpinCount; + LONG lVal, lNewVal; + LONG lBitsToChange, lWaitInc; + PalCsWaiterReturnState cwrs; + SIZE_T threadId; + + _ASSERTE(PalCsNotInitialized != pPalCriticalSection->cisInitState); + + threadId = ObtainCurrentThreadId(pThread); + + + // Check if the current thread already owns the CS + // + // Note: there is no need for this double check to be atomic. In fact + // if the first check fails, the second doesn't count (and it's not + // even executed). If the first one succeeds and the second one + // doesn't, it doesn't matter if LockCount has already changed by the + // time OwningThread is tested. Instead, if the first one succeeded, + // and the second also succeeds, LockCount cannot have changed in the + // meanwhile, since this is the owning thread and only the owning + // thread can change the lock bit when the CS is owned. + if ((pPalCriticalSection->LockCount & PALCS_LOCK_BIT) && + (pPalCriticalSection->OwningThread == threadId)) + { + pPalCriticalSection->RecursionCount += 1; +#ifdef _DEBUG + if (NULL != pPalCriticalSection->DebugInfo) + { + pPalCriticalSection->DebugInfo->lEnterCount += 1; + } +#endif // _DEBUG + goto IECS_exit; + } + + // Set bits to change and waiter increment for an incoming thread + lBitsToChange = PALCS_LOCK_BIT; + lWaitInc = PALCS_LOCK_WAITER_INC; + lSpinCount = pPalCriticalSection->SpinCount; + + while (TRUE) + { + // Either this is an incoming thread, and therefore lBitsToChange + // is just PALCS_LOCK_BIT, or this is an awakened waiter + _ASSERTE(PALCS_LOCK_BIT == lBitsToChange || + (PALCS_LOCK_BIT | PALCS_LOCK_AWAKENED_WAITER) == lBitsToChange); + + // Make sure the waiter increment is in a valid range + _ASSERTE(PALCS_LOCK_WAITER_INC == lWaitInc || + PALCS_LOCK_AWAKENED_WAITER == lWaitInc); + + do { + lVal = pPalCriticalSection->LockCount; + + while (0 == (lVal & PALCS_LOCK_BIT)) + { + // CS is not locked: try lo lock it + + // Make sure that whether we are an incoming thread + // or the PALCS_LOCK_AWAKENED_WAITER bit is set + _ASSERTE((PALCS_LOCK_BIT == lBitsToChange) || + (PALCS_LOCK_AWAKENED_WAITER & lVal)); + + lNewVal = lVal ^ lBitsToChange; + + // Make sure we are actually trying to lock + _ASSERTE(lNewVal & PALCS_LOCK_BIT); + + CS_TRACE("[ECS %p] Switching from {%d, %d, %d} to " + "{%d, %d, %d} ==>\n", pPalCriticalSection, + PALCS_GETWCOUNT(lVal), PALCS_GETAWBIT(lVal), PALCS_GETLBIT(lVal), + PALCS_GETWCOUNT(lNewVal), PALCS_GETAWBIT(lNewVal), PALCS_GETLBIT(lNewVal)); + + // Try to switch the value + lNewVal = InterlockedCompareExchange (&pPalCriticalSection->LockCount, + lNewVal, lVal); + + CS_TRACE("[ECS %p] ==> %s LockCount={%d, %d, %d} " + "lVal={%d, %d, %d}\n", pPalCriticalSection, + (lNewVal == lVal) ? "OK" : "NO", + PALCS_GETWCOUNT(pPalCriticalSection->LockCount), + PALCS_GETAWBIT(pPalCriticalSection->LockCount), + PALCS_GETLBIT(pPalCriticalSection->LockCount), + PALCS_GETWCOUNT(lVal), PALCS_GETAWBIT(lVal), PALCS_GETLBIT(lVal)); + + if (lNewVal == lVal) + { + // CS successfully acquired + goto IECS_set_ownership; + } + + // Acquisition failed, some thread raced with us; + // update value for next loop + lVal = lNewVal; + } + + if (0 < lSpinCount) + { + sched_yield(); + } + } while (0 <= --lSpinCount); + + cwrs = PALCS_WaitOnCS(pPalCriticalSection, lWaitInc); + + if (PalCsReturnWaiterAwakened == cwrs) + { +#ifdef PALCS_TRANSFER_OWNERSHIP_ON_RELEASE + // + // Fair Critical Sections + // + // In the fair lock case, when a waiter wakes up the CS + // must be locked (i.e. ownership passed on to the waiter) + _ASSERTE(0 != (PALCS_LOCK_BIT & pPalCriticalSection->LockCount)); + + // CS successfully acquired + goto IECS_set_ownership; + +#else // PALCS_TRANSFER_OWNERSHIP_ON_RELEASE + // + // Unfair Critical Sections + // + _ASSERTE(PALCS_LOCK_AWAKENED_WAITER & pPalCriticalSection->LockCount); + + lBitsToChange = PALCS_LOCK_BIT | PALCS_LOCK_AWAKENED_WAITER; + lWaitInc = PALCS_LOCK_AWAKENED_WAITER; +#endif // PALCS_TRANSFER_OWNERSHIP_ON_RELEASE + } + } + + IECS_set_ownership: + // Critical section acquired: set ownership data + pPalCriticalSection->OwningThread = threadId; + pPalCriticalSection->RecursionCount = 1; +#ifdef _DEBUG + if (NULL != pPalCriticalSection->DebugInfo) + { + pPalCriticalSection->DebugInfo->lAcquireCount += 1; + pPalCriticalSection->DebugInfo->lEnterCount += 1; + } +#endif // _DEBUG + + IECS_exit: + return; + } + + /*++ + Function: + CorUnix::InternalLeaveCriticalSection + + Leaves a currently owned CS + --*/ + void InternalLeaveCriticalSection(CPalThread * pThread, + PCRITICAL_SECTION pCriticalSection) + { + PAL_CRITICAL_SECTION * pPalCriticalSection = + reinterpret_cast(pCriticalSection); + LONG lVal, lNewVal; + +#ifdef _DEBUG + SIZE_T threadId; + + _ASSERTE(PalCsNotInitialized != pPalCriticalSection->cisInitState); + + threadId = ObtainCurrentThreadId(pThread); + _ASSERTE(threadId == pPalCriticalSection->OwningThread); +#endif // _DEBUG + + _ASSERT_MSG(PALCS_LOCK_BIT & pPalCriticalSection->LockCount, + "Trying to release an unlocked CS\n"); + _ASSERT_MSG(0 < pPalCriticalSection->RecursionCount, + "Trying to release an unlocked CS\n"); + + if (--pPalCriticalSection->RecursionCount > 0) + { + // Recursion was > 1, still owning the CS + goto ILCS_cs_exit; + } + + // Reset CS ownership + pPalCriticalSection->OwningThread = 0; + + // Load the current LockCount value + lVal = pPalCriticalSection->LockCount; + + while (true) + { + _ASSERT_MSG(0 != (PALCS_LOCK_BIT & lVal), + "Trying to release an unlocked CS\n"); + + // NB: In the fair lock case (PALCS_TRANSFER_OWNERSHIP_ON_RELEASE) the + // PALCS_LOCK_AWAKENED_WAITER bit is not used + if ( (PALCS_LOCK_BIT == lVal) +#ifndef PALCS_TRANSFER_OWNERSHIP_ON_RELEASE + || (PALCS_LOCK_AWAKENED_WAITER & lVal) +#endif // !PALCS_TRANSFER_OWNERSHIP_ON_RELEASE + ) + { + // Whether there are no waiters (PALCS_LOCK_BIT == lVal) + // or a waiter has already been awakened, therefore we + // just need to reset the lock bit and return + lNewVal = lVal & ~PALCS_LOCK_BIT; + CS_TRACE("[LCS-UN %p] Switching from {%d, %d, %d} to " + "{%d, %d, %d} ==>\n", pPalCriticalSection, + PALCS_GETWCOUNT(lVal), PALCS_GETAWBIT(lVal), PALCS_GETLBIT(lVal), + PALCS_GETWCOUNT(lNewVal), PALCS_GETAWBIT(lNewVal), PALCS_GETLBIT(lNewVal)); + + lNewVal = InterlockedCompareExchange(&pPalCriticalSection->LockCount, + lNewVal, lVal); + + CS_TRACE("[LCS-UN %p] ==> %s\n", pPalCriticalSection, + (lNewVal == lVal) ? "OK" : "NO"); + + if (lNewVal == lVal) + { + goto ILCS_cs_exit; + } + } + else + { + // There is at least one waiter, we need to wake it up + +#ifdef PALCS_TRANSFER_OWNERSHIP_ON_RELEASE + // Fair lock case: passing ownership on to the first waiter. + // Here we need only to decrement the waiters count. CS will + // remain locked and ownership will be passed to the waiter, + // which will take care of setting ownership data as soon as + // it wakes up + lNewVal = lVal - PALCS_LOCK_WAITER_INC; +#else // PALCS_TRANSFER_OWNERSHIP_ON_RELEASE + // Unfair lock case: we need to atomically decrement the waiters + // count (we are about ot wake up one of them), set the + // "waiter awakened" bit and to reset the "CS locked" bit. + // Note that, since we know that at this time PALCS_LOCK_BIT + // is set and PALCS_LOCK_AWAKENED_WAITER is not set, none of + // the addenda will affect bits other than its target bit(s), + // i.e. PALCS_LOCK_BIT will not affect PALCS_LOCK_AWAKENED_WAITER, + // PALCS_LOCK_AWAKENED_WAITER will not affect the actual + // count of waiters, and the latter will not change the two + // former ones + lNewVal = lVal - PALCS_LOCK_WAITER_INC + + PALCS_LOCK_AWAKENED_WAITER - PALCS_LOCK_BIT; +#endif // PALCS_TRANSFER_OWNERSHIP_ON_RELEASE + CS_TRACE("[LCS-CN %p] Switching from {%d, %d, %d} to {%d, %d, %d} ==>\n", + pPalCriticalSection, + PALCS_GETWCOUNT(lVal), PALCS_GETAWBIT(lVal), PALCS_GETLBIT(lVal), + PALCS_GETWCOUNT(lNewVal), PALCS_GETAWBIT(lNewVal), PALCS_GETLBIT(lNewVal)); + + lNewVal = InterlockedCompareExchange(&pPalCriticalSection->LockCount, + lNewVal, lVal); + + CS_TRACE("[LCS-CN %p] ==> %s\n", pPalCriticalSection, + (lNewVal == lVal) ? "OK" : "NO"); + + if (lNewVal == lVal) + { + // Wake up the waiter + PALCS_WakeUpWaiter (pPalCriticalSection); + +#ifdef PALCS_TRANSFER_OWNERSHIP_ON_RELEASE + // In the fair lock case, we need to yield here to defeat + // the inherently unfair nature of the condition/predicate + // construct + sched_yield(); +#endif // PALCS_TRANSFER_OWNERSHIP_ON_RELEASE + + goto ILCS_cs_exit; + } + } + + // CS unlock failed due to race with another thread trying to + // register as waiter on it. We need to keep on looping. We + // intentionally do not yield here in order to reserve higher + // priority for the releasing thread. + // + // At this point lNewVal contains the latest LockCount value + // retrieved by one of the two InterlockedCompareExchange above; + // we can use this value as expected LockCount for the next loop, + // without the need to fetch it again. + lVal = lNewVal; + } + + ILCS_cs_exit: + return; + } + + /*++ + Function: + CorUnix::InternalTryEnterCriticalSection + + Tries to acquire a CS. It returns true on success, false if the CS is + locked by another thread + --*/ + bool InternalTryEnterCriticalSection( + CPalThread * pThread, + PCRITICAL_SECTION pCriticalSection) + { + PAL_CRITICAL_SECTION * pPalCriticalSection = + reinterpret_cast(pCriticalSection); + + LONG lNewVal; + SIZE_T threadId; + bool fRet = true; + + _ASSERTE(PalCsNotInitialized != pPalCriticalSection->cisInitState); + + threadId = ObtainCurrentThreadId(pThread); + + lNewVal = InterlockedCompareExchange (&pPalCriticalSection->LockCount, + (LONG)PALCS_LOCK_BIT, + (LONG)PALCS_LOCK_INIT); + if (lNewVal == PALCS_LOCK_INIT) + { + // CS successfully acquired: setting ownership data + pPalCriticalSection->OwningThread = threadId; + pPalCriticalSection->RecursionCount = 1; +#ifdef _DEBUG + if (NULL != pPalCriticalSection->DebugInfo) + { + pPalCriticalSection->DebugInfo->lAcquireCount += 1; + pPalCriticalSection->DebugInfo->lEnterCount += 1; + } +#endif // _DEBUG + + goto ITECS_exit; + } + + // check if the current thread already owns the criticalSection + if ((lNewVal & PALCS_LOCK_BIT) && + (pPalCriticalSection->OwningThread == threadId)) + { + pPalCriticalSection->RecursionCount += 1; +#ifdef _DEBUG + if (NULL != pPalCriticalSection->DebugInfo) + { + pPalCriticalSection->DebugInfo->lEnterCount += 1; + } +#endif // _DEBUG + + goto ITECS_exit; + } + + // Failed to acquire the CS + fRet = false; + + ITECS_exit: + return fRet; + } +#endif // MUTEX_BASED_CSS + + /*++ + Function: + CorUnix::PALCS_FullyInitialize + + Fully initializes a CS previously initialied true InitializeCriticalSection. + This method is called at the first contention on the target CS + --*/ + bool PALCS_FullyInitialize(PAL_CRITICAL_SECTION * pPalCriticalSection) + { + LONG lVal, lNewVal; + bool fRet = true; + + lVal = pPalCriticalSection->cisInitState; + if (PalCsFullyInitialized == lVal) + { + goto PCDI_exit; + } + if (PalCsUserInitialized == lVal) + { + int iRet; + lNewVal = (LONG)PalCsFullyInitializing; + lNewVal = InterlockedCompareExchange( + (LONG *)&pPalCriticalSection->cisInitState, lNewVal, lVal); + if (lNewVal != lVal) + { + if (PalCsFullyInitialized == lNewVal) + { + // Another thread did initialize this CS: we can + // safely return 'true' + goto PCDI_exit; + } + + // Another thread is still initializing this CS: yield and + // spin by returning 'false' + sched_yield(); + fRet = false; + goto PCDI_exit; + } + + // + // Actual native initialization + // + // Mutex + iRet = pthread_mutex_init(&pPalCriticalSection->csndNativeData.mutex, NULL); + if (0 != iRet) + { + ASSERT("Failed initializing mutex in CS @ %p [err=%d]\n", + pPalCriticalSection, iRet); + pPalCriticalSection->cisInitState = PalCsUserInitialized; + fRet = false; + goto PCDI_exit; + } +#ifndef MUTEX_BASED_CSS + // Condition + iRet = pthread_cond_init(&pPalCriticalSection->csndNativeData.condition, NULL); + if (0 != iRet) + { + ASSERT("Failed initializing condition in CS @ %p [err=%d]\n", + pPalCriticalSection, iRet); + pthread_mutex_destroy(&pPalCriticalSection->csndNativeData.mutex); + pPalCriticalSection->cisInitState = PalCsUserInitialized; + fRet = false; + goto PCDI_exit; + } + // Predicate + pPalCriticalSection->csndNativeData.iPredicate = 0; +#endif + + pPalCriticalSection->cisInitState = PalCsFullyInitialized; + } + else if (PalCsFullyInitializing == lVal) + { + // Another thread is still initializing this CS: yield and + // spin by returning 'false' + sched_yield(); + fRet = false; + goto PCDI_exit; + } + else + { + ASSERT("CS %p is not initialized", pPalCriticalSection); + fRet = false; + goto PCDI_exit; + } + + PCDI_exit: + return fRet; + } + + + /*++ + Function: + CorUnix::PALCS_WaitOnCS + + Waits on a CS owned by another thread. It returns PalCsReturnWaiterAwakened + if the thread actually waited on the CS and it has been awakened on CS + release. It returns PalCsWaiterDidntWait if another thread is currently + fully-initializing the CS and therefore the current thread couldn't wait + on it + --*/ + PalCsWaiterReturnState PALCS_WaitOnCS(PAL_CRITICAL_SECTION * pPalCriticalSection, + LONG lInc) + { + DWORD lVal, lNewVal; + PAL_ERROR palErr = NO_ERROR; + + if (PalCsFullyInitialized != pPalCriticalSection->cisInitState) + { + // First contention, the CS native wait support need to be + // initialized at this time + if (!PALCS_FullyInitialize(pPalCriticalSection)) + { + // The current thread failed the full initialization of the CS, + // whether because another thread is race-initializing it, or + // there are no enough memory/resources at this time, or + // InitializeCriticalSection has never been called. By + // returning we will cause the thread to spin on CS trying + // again until the CS is initialized + return PalCsWaiterDidntWait; + } + } + + // Make sure we have a valid waiter increment + _ASSERTE(PALCS_LOCK_WAITER_INC == lInc || + PALCS_LOCK_AWAKENED_WAITER == lInc); + + do { + lVal = pPalCriticalSection->LockCount; + + // Make sure the waiter increment is compatible with the + // awakened waiter bit value + _ASSERTE(PALCS_LOCK_WAITER_INC == lInc || + PALCS_LOCK_AWAKENED_WAITER & lVal); + + if (0 == (lVal & PALCS_LOCK_BIT)) + { + // the CS is no longer locked, let's bail out + return PalCsWaiterDidntWait; + } + + lNewVal = lVal + lInc; + + // Make sure that this thread was whether an incoming one or it + // was an awakened waiter and, in this case, we are now going to + // turn off the awakened waiter bit + _ASSERT_MSG(PALCS_LOCK_WAITER_INC == lInc || + 0 == (PALCS_LOCK_AWAKENED_WAITER & lNewVal)); + + CS_TRACE("[WCS %p] Switching from {%d, %d, %d} to " + "{%d, %d, %d} ==> ", pPalCriticalSection, + PALCS_GETWCOUNT(lVal), PALCS_GETAWBIT(lVal), PALCS_GETLBIT(lVal), + PALCS_GETWCOUNT(lNewVal), PALCS_GETAWBIT(lNewVal), PALCS_GETLBIT(lNewVal)); + + lNewVal = InterlockedCompareExchange (&pPalCriticalSection->LockCount, + lNewVal, lVal); + + CS_TRACE("[WCS %p] ==> %s\n", pPalCriticalSection, + (lNewVal == lVal) ? "OK" : "NO"); + + } while (lNewVal != lVal); + +#ifdef _DEBUG + if (NULL != pPalCriticalSection->DebugInfo) + { + pPalCriticalSection->DebugInfo->lContentionCount += 1; + } +#endif // _DEBUG + + // Do the actual native wait + palErr = PALCS_DoActualWait(pPalCriticalSection); + _ASSERT_MSG(NO_ERROR == palErr, "Native CS wait failed\n"); + + return PalCsReturnWaiterAwakened; + } + + /*++ + Function: + CorUnix::PALCS_DoActualWait + + Performs the actual native wait on the CS + --*/ + PAL_ERROR PALCS_DoActualWait(PAL_CRITICAL_SECTION * pPalCriticalSection) + { + int iRet; + PAL_ERROR palErr = NO_ERROR; + + CS_TRACE("Trying to go to sleep [CS=%p]\n", pPalCriticalSection); + + // Lock the mutex + iRet = pthread_mutex_lock(&pPalCriticalSection->csndNativeData.mutex); + if (0 != iRet) + { + palErr = ERROR_INTERNAL_ERROR; + goto PCDAW_exit; + } + + CS_TRACE("Actually Going to sleep [CS=%p]\n", pPalCriticalSection); + + while (0 == pPalCriticalSection->csndNativeData.iPredicate) + { + // Wait on the condition + iRet = pthread_cond_wait(&pPalCriticalSection->csndNativeData.condition, + &pPalCriticalSection->csndNativeData.mutex); + + CS_TRACE("Got a signal on condition [pred=%d]!\n", + pPalCriticalSection->csndNativeData.iPredicate); + if (0 != iRet) + { + // Failed: unlock the mutex and bail out + ASSERT("Failed waiting on condition in CS %p [err=%d]\n", + pPalCriticalSection, iRet); + pthread_mutex_unlock(&pPalCriticalSection->csndNativeData.mutex); + palErr = ERROR_INTERNAL_ERROR; + goto PCDAW_exit; + } + } + + // Reset the predicate + pPalCriticalSection->csndNativeData.iPredicate = 0; + + // Unlock the mutex + iRet = pthread_mutex_unlock(&pPalCriticalSection->csndNativeData.mutex); + if (0 != iRet) + { + palErr = ERROR_INTERNAL_ERROR; + goto PCDAW_exit; + } + + PCDAW_exit: + + CS_TRACE("Just woken up [CS=%p]\n", pPalCriticalSection); + + return palErr; + } + + /*++ + Function: + CorUnix::PALCS_WakeUpWaiter + + Wakes up the first thread waiting on the CS + --*/ + PAL_ERROR PALCS_WakeUpWaiter(PAL_CRITICAL_SECTION * pPalCriticalSection) + { + int iRet; + PAL_ERROR palErr = NO_ERROR; + + _ASSERT_MSG(PalCsFullyInitialized == pPalCriticalSection->cisInitState, + "Trying to wake up a waiter on CS not fully initialized\n"); + + // Lock the mutex + iRet = pthread_mutex_lock(&pPalCriticalSection->csndNativeData.mutex); + if (0 != iRet) + { + palErr = ERROR_INTERNAL_ERROR; + goto PCWUW_exit; + } + + // Set the predicate + pPalCriticalSection->csndNativeData.iPredicate = 1; + + CS_TRACE("Signaling condition/predicate [pred=%d]!\n", + pPalCriticalSection->csndNativeData.iPredicate); + + // Signal the condition + iRet = pthread_cond_signal(&pPalCriticalSection->csndNativeData.condition); + if (0 != iRet) + { + // Failed: set palErr, but continue in order to unlock + // the mutex anyway + ASSERT("Failed setting condition in CS %p [ret=%d]\n", + pPalCriticalSection, iRet); + palErr = ERROR_INTERNAL_ERROR; + } + + // Unlock the mutex + iRet = pthread_mutex_unlock(&pPalCriticalSection->csndNativeData.mutex); + if (0 != iRet) + { + palErr = ERROR_INTERNAL_ERROR; + goto PCWUW_exit; + } + + PCWUW_exit: + return palErr; + } + +#ifdef _DEBUG + /*++ + Function: + CorUnix::PALCS_ReportStatisticalData + + Report creation/acquisition/contention statistical data for the all the + CSs so far existed and no longer existing in the current process + --*/ + void PALCS_ReportStatisticalData() + { +#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA + CPalThread * pThread = InternalGetCurrentThread(); + + if (NULL == pThread) DebugBreak(); + + // Take the lock for the global list of CS debug infos + InternalEnterCriticalSection(pThread, (CRITICAL_SECTION*)&g_csPALCSsListLock); + + LONG lPALCSInitializeCount = g_lPALCSInitializeCount; + LONG lPALCSDeleteCount = g_lPALCSDeleteCount; + LONG lPALCSAcquireCount = g_lPALCSAcquireCount; + LONG lPALCSEnterCount = g_lPALCSEnterCount; + LONG lPALCSContentionCount = g_lPALCSContentionCount; + LONG lPALCSInternalInitializeCount = g_lPALCSInternalInitializeCount; + LONG lPALCSInternalDeleteCount = g_lPALCSInternalDeleteCount; + LONG lPALCSInternalAcquireCount = g_lPALCSInternalAcquireCount; + LONG lPALCSInternalEnterCount = g_lPALCSInternalEnterCount; + LONG lPALCSInternalContentionCount = g_lPALCSInternalContentionCount; + + PLIST_ENTRY pItem = g_PALCSList.Flink; + while (&g_PALCSList != pItem) + { + PCRITICAL_SECTION_DEBUG_INFO pDebugInfo = + (PCRITICAL_SECTION_DEBUG_INFO)pItem; + + if (pDebugInfo->pOwnerCS->fInternal) + { + lPALCSInternalAcquireCount += pDebugInfo->lAcquireCount; + lPALCSInternalEnterCount += pDebugInfo->lEnterCount; + lPALCSInternalContentionCount += pDebugInfo->lContentionCount; + } + else + { + lPALCSAcquireCount += pDebugInfo->lAcquireCount; + lPALCSEnterCount += pDebugInfo->lEnterCount; + lPALCSContentionCount += pDebugInfo->lContentionCount; + } + + pItem = pItem->Flink; + } + + // Release the lock for the global list of CS debug infos + InternalLeaveCriticalSection(pThread, (CRITICAL_SECTION*)&g_csPALCSsListLock); + + TRACE("Critical Sections Statistical Data:\n"); + TRACE("{\n"); + TRACE(" Client code CSs:\n"); + TRACE(" {\n"); + TRACE(" Initialize Count: %d\n", lPALCSInitializeCount); + TRACE(" Delete Count: %d\n", lPALCSDeleteCount); + TRACE(" Acquire Count: %d\n", lPALCSAcquireCount); + TRACE(" Enter Count: %d\n", lPALCSEnterCount); + TRACE(" Contention Count: %d\n", lPALCSContentionCount); + TRACE(" }\n"); + TRACE(" Internal PAL CSs:\n"); + TRACE(" {\n"); + TRACE(" Initialize Count: %d\n", lPALCSInternalInitializeCount); + TRACE(" Delete Count: %d\n", lPALCSInternalDeleteCount); + TRACE(" Acquire Count: %d\n", lPALCSInternalAcquireCount); + TRACE(" Enter Count: %d\n", lPALCSInternalEnterCount); + TRACE(" Contention Count: %d\n", lPALCSInternalContentionCount); + TRACE(" }\n"); + TRACE("}\n"); +#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA + } + + /*++ + Function: + CorUnix::PALCS_DumpCSList + + Dumps the list of all the CS currently existing in this process. + --*/ + void PALCS_DumpCSList() + { + CPalThread * pThread = InternalGetCurrentThread(); + + // Take the lock for the global list of CS debug infos + InternalEnterCriticalSection(pThread, (CRITICAL_SECTION*)&g_csPALCSsListLock); + + PLIST_ENTRY pItem = g_PALCSList.Flink; + while (&g_PALCSList != pItem) + { + PCRITICAL_SECTION_DEBUG_INFO pDebugInfo = + (PCRITICAL_SECTION_DEBUG_INFO)pItem; + PPAL_CRITICAL_SECTION pCS = pDebugInfo->pOwnerCS; + + printf("CS @ %p \n" + "{\tDebugInfo = %p -> \n", + pCS, pDebugInfo); + + printf("\t{\n\t\t[Link]\n\t\tpOwnerCS = %p\n" + "\t\tAcquireCount \t= %d\n" + "\t\tEnterCount \t= %d\n" + "\t\tContentionCount = %d\n", + pDebugInfo->pOwnerCS, pDebugInfo->lAcquireCount.Load(), + pDebugInfo->lEnterCount.Load(), pDebugInfo->lContentionCount.Load()); + printf("\t}\n"); + + printf("\tLockCount \t= %#x\n" + "\tRecursionCount \t= %d\n" + "\tOwningThread \t= %p\n" + "\tSpinCount \t= %u\n" + "\tfInternal \t= %d\n" + "\teInitState \t= %u\n" + "\tpNativeData \t= %p ->\n", + pCS->LockCount.Load(), pCS->RecursionCount, (void *)pCS->OwningThread, + (unsigned)pCS->SpinCount, +#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA + (int)pCS->fInternal, +#else + (int)0, +#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA + pCS->cisInitState.Load(), &pCS->csndNativeData); + + printf("\t{\n\t\t[mutex]\n\t\t[condition]\n" + "\t\tPredicate \t= %d\n" + "\t}\n}\n",pCS->csndNativeData.iPredicate); + + printf("}\n"); + + pItem = pItem->Flink; + } + + // Release the lock for the global list of CS debug infos + InternalLeaveCriticalSection(pThread, (CRITICAL_SECTION*)&g_csPALCSsListLock); + } +#endif // _DEBUG + + +#if defined(MUTEX_BASED_CSS) || defined(_DEBUG) + /*++ + Function: + CorUnix::InternalEnterCriticalSection + + Enters a CS, causing the thread to block if the CS is owned by + another thread + --*/ +#ifdef MUTEX_BASED_CSS + void InternalEnterCriticalSection( + CPalThread * pThread, + PCRITICAL_SECTION pCriticalSection) +#else // MUTEX_BASED_CSS + void MTX_InternalEnterCriticalSection( + CPalThread * pThread, + PCRITICAL_SECTION pCriticalSection) +#endif // MUTEX_BASED_CSS + + { + PAL_CRITICAL_SECTION * pPalCriticalSection = + reinterpret_cast(pCriticalSection); + int iRet; + SIZE_T threadId; + + _ASSERTE(PalCsNotInitialized != pPalCriticalSection->cisInitState); + + threadId = ObtainCurrentThreadId(pThread); + + /* check if the current thread already owns the criticalSection */ + if (pPalCriticalSection->OwningThread == threadId) + { + _ASSERTE(0 < pPalCriticalSection->RecursionCount); + pPalCriticalSection->RecursionCount += 1; + return; + } + + iRet = pthread_mutex_lock(&pPalCriticalSection->csndNativeData.mutex); + _ASSERTE(0 == iRet); + + pPalCriticalSection->OwningThread = threadId; + pPalCriticalSection->RecursionCount = 1; + } + + + /*++ + Function: + CorUnix::InternalLeaveCriticalSection + + Leaves a currently owned CS + --*/ +#ifdef MUTEX_BASED_CSS + void InternalLeaveCriticalSection( + CPalThread * pThread, + PCRITICAL_SECTION pCriticalSection) +#else // MUTEX_BASED_CSS + void MTX_InternalLeaveCriticalSection( + CPalThread * pThread, + PCRITICAL_SECTION pCriticalSection) +#endif // MUTEX_BASED_CSS + { + PAL_CRITICAL_SECTION * pPalCriticalSection = + reinterpret_cast(pCriticalSection); + int iRet; +#ifdef _DEBUG + SIZE_T threadId; + + _ASSERTE(PalCsNotInitialized != pPalCriticalSection->cisInitState); + + threadId = ObtainCurrentThreadId(pThread); + _ASSERTE(threadId == pPalCriticalSection->OwningThread); + + if (0 >= pPalCriticalSection->RecursionCount) + DebugBreak(); + + _ASSERTE(0 < pPalCriticalSection->RecursionCount); +#endif // _DEBUG + + if (0 < --pPalCriticalSection->RecursionCount) + return; + + pPalCriticalSection->OwningThread = 0; + + iRet = pthread_mutex_unlock(&pPalCriticalSection->csndNativeData.mutex); + _ASSERTE(0 == iRet); + } + + /*++ + Function: + CorUnix::InternalTryEnterCriticalSection + + Tries to acquire a CS. It returns true on success, false if the CS is + locked by another thread + --*/ +#ifdef MUTEX_BASED_CSS + bool InternalTryEnterCriticalSection( + CPalThread * pThread, + PCRITICAL_SECTION pCriticalSection) +#else // MUTEX_BASED_CSS + bool MTX_InternalTryEnterCriticalSection( + CPalThread * pThread, + PCRITICAL_SECTION pCriticalSection) +#endif // MUTEX_BASED_CSS + { + PAL_CRITICAL_SECTION * pPalCriticalSection = + reinterpret_cast(pCriticalSection); + bool fRet; + SIZE_T threadId; + + _ASSERTE(PalCsNotInitialized != pPalCriticalSection->cisInitState); + + threadId = ObtainCurrentThreadId(pThread); + + /* check if the current thread already owns the criticalSection */ + if (pPalCriticalSection->OwningThread == threadId) + { + pPalCriticalSection->RecursionCount += 1; + fRet = true; + goto ITECS_exit; + } + + fRet = (0 == pthread_mutex_trylock(&pPalCriticalSection->csndNativeData.mutex)); + + if (fRet) + { + pPalCriticalSection->OwningThread = threadId; + pPalCriticalSection->RecursionCount = 1; + } + + ITECS_exit: + return fRet; + } +#endif // MUTEX_BASED_CSS || _DEBUG +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/synchcontrollers.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/synchcontrollers.cpp new file mode 100644 index 0000000..513d8b8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/synchcontrollers.cpp @@ -0,0 +1,2046 @@ +// 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: + + synchcontrollers.cpp + +Abstract: + Implementation of Synchronization Controllers and related objects + + + +--*/ + +#include "pal/dbgmsg.h" + +SET_DEFAULT_DEBUG_CHANNEL(SYNC); // some headers have code with asserts, so do this first + +#include "synchmanager.hpp" + +#include +#include +#include +#include +#include +#include +#include + +namespace CorUnix +{ +#ifdef SYNCH_STATISTICS + LONG g_rglStatWaitCount[ObjectTypeIdCount] = { 0 }; + LONG g_rglStatContentionCount[ObjectTypeIdCount] = { 0 }; +#endif // SYNCH_STATISTICS + //////////////////////////// + // // + // CSynchControllerBase // + // // + //////////////////////////// + + /*++ + Method: + CSynchControllerBase::Init + + Initializes a generic controller + --*/ + PAL_ERROR CSynchControllerBase::Init( + CPalThread * pthrCurrent, + ControllerType ctCtrlrType, + ObjectDomain odObjectDomain, + CObjectType *potObjectType, + CSynchData * psdSynchData, + WaitDomain wdWaitDomain) + { + VALIDATEOBJECT(psdSynchData); + + _ASSERTE(InternalGetCurrentThread() == pthrCurrent); + + // Initialize internal controller data + m_pthrOwner = pthrCurrent; + m_ctCtrlrType = ctCtrlrType; + m_odObjectDomain = odObjectDomain; + m_potObjectType = potObjectType; + m_psdSynchData = psdSynchData; + m_wdWaitDomain = wdWaitDomain; + + // Add reference to target synch data + m_psdSynchData->AddRef(); + + // Acquire lock implied by the controller + CPalSynchronizationManager::AcquireLocalSynchLock(m_pthrOwner); + if (LocalWait != m_wdWaitDomain) + { + CPalSynchronizationManager::AcquireSharedSynchLock(m_pthrOwner); + } + + return NO_ERROR; + } + + /*++ + Method: + CSynchControllerBase::Release + + Releases a generic controller a return it to the appropriate cache + --*/ + void CSynchControllerBase::Release() + { + VALIDATEOBJECT(m_psdSynchData); + +#ifdef _DEBUG + ThreadWaitInfo * ptwiWaitInfo = + CPalSynchronizationManager::GetThreadWaitInfo(m_pthrOwner); +#endif // _DEBUG + + CPalSynchronizationManager * pSynchManager = + CPalSynchronizationManager::GetInstance(); + + _ASSERTE(InternalGetCurrentThread() == m_pthrOwner); + _ASSERTE(ptwiWaitInfo->pthrOwner == m_pthrOwner); + + // Release reference to target synch data + m_psdSynchData->Release(m_pthrOwner); + + // Release lock implied by the controller + if (LocalWait != m_wdWaitDomain) + { + CPalSynchronizationManager::ReleaseSharedSynchLock(m_pthrOwner); + } + CPalSynchronizationManager::ReleaseLocalSynchLock(m_pthrOwner); + + // Return controller to the appropriate cache + if (WaitController == m_ctCtrlrType) + { + // The cast here must be static_cast and not reinterpet_cast. + // In fact in general static_cast(this) is + // equal to this-sizeof(void*), given that CSynchWaitController + // has a virtual table, while CSynchControllerBase doesn't. + pSynchManager->CacheAddWaitCtrlr(m_pthrOwner, + static_cast(this)); + } + else + { + // The cast here must be static_cast and not reinterpet_cast + pSynchManager->CacheAddStateCtrlr(m_pthrOwner, + static_cast(this)); + } + } + + //////////////////////////// + // // + // CSynchWaitController // + // // + //////////////////////////// + + /*++ + Method: + CSynchWaitController::CanThreadWaitWithoutBlocking + + Returns whether or not the thread owning this controller can + wait on the target object without blocking (i.e. the objet is + signaled) + --*/ + PAL_ERROR CSynchWaitController::CanThreadWaitWithoutBlocking( + bool * pfCanWaitWithoutBlocking, + bool * pfAbandoned) + { + VALIDATEOBJECT(m_psdSynchData); + + bool fRetVal = false; + + _ASSERTE(InternalGetCurrentThread() == m_pthrOwner); + _ASSERTE(NULL != pfCanWaitWithoutBlocking); + _ASSERTE(NULL != pfAbandoned); + + fRetVal = m_psdSynchData->CanWaiterWaitWithoutBlocking(m_pthrOwner, pfAbandoned); + + if(!fRetVal && otiProcess == m_psdSynchData->GetObjectTypeId()) + { + // Note: if the target object is a process, here we need to check + // whether or not it has already exited. In fact, since currently + // we do not monitor a process status as long as there is no + // thread waiting on it, in general if the process already exited + // the process object is likely not to be signaled yet, therefore + // the above CanWaiterWaitWithoutBlocking call probably returned + // false, and, without the check below, that would cause the + // current thread to eventually go to sleep for a short time + // (until the worker thread notifies that the waited process has + // indeed exited), while it would not be necessary. + // As side effect that would cause a WaitForSingleObject with zero + // timeout to always return WAIT_TIMEOUT, even though the target + // process already exited. WaitForSingleObject with zero timeout + // is a common way to probe whether or not a process has already + // exited, and it is supposed to return WAIT_OBJECT_0 if the + // process exited, and WAIT_TIMEOUT if it is still active. + // In order to support this feature we need to check at this time + // whether or not the process has already exited. + + CProcProcessLocalData * pProcLocalData = GetProcessLocalData(); + DWORD dwExitCode = 0; + bool fIsActualExitCode = false; + + _ASSERT_MSG(NULL != pProcLocalData, + "Process synch data pointer is missing\n"); + + if (NULL != pProcLocalData && + CPalSynchronizationManager::HasProcessExited(pProcLocalData->dwProcessId, + &dwExitCode, + &fIsActualExitCode)) + { + TRACE("Process pid=%u exited with %s exitcode=%u\n", + pProcLocalData->dwProcessId, + fIsActualExitCode ? "actual" : "guessed", + dwExitCode); + + // Store the exit code in the process local data + if (fIsActualExitCode) + { + pProcLocalData->dwExitCode = dwExitCode; + } + + // Set process status to PS_DONE + pProcLocalData->ps = PS_DONE; + + // Set signal count + m_psdSynchData->SetSignalCount(1); + + // Releasing all local waiters + // (see comments in DoMonitorProcesses) + m_psdSynchData->ReleaseAllLocalWaiters(m_pthrOwner); + + fRetVal = true; + } + } + + *pfCanWaitWithoutBlocking = fRetVal; + return NO_ERROR; + } + + /*++ + Method: + CSynchWaitController::ReleaseWaitingThreadWithoutBlocking + + Performs all the steps needed to be done by the controller's owner + thread in order to wait on the target object without blocking + (e.g. modifying the object signal count accordingly with its + thread release semantics) + This method should be called only after having received positive + response from CanThreadWaitWithoutBlocking called on the same + controller. + --*/ + PAL_ERROR CSynchWaitController::ReleaseWaitingThreadWithoutBlocking() + { + VALIDATEOBJECT(m_psdSynchData); + + PAL_ERROR palErr = NO_ERROR; + + _ASSERTE(InternalGetCurrentThread() == m_pthrOwner); + + palErr = m_psdSynchData->ReleaseWaiterWithoutBlocking(m_pthrOwner, m_pthrOwner); + +#ifdef SYNCH_STATISTICS + if (NO_ERROR == palErr) + { + m_psdSynchData->IncrementStatWaitCount(); + } +#endif + return palErr; + } + + /*++ + Method: + CSynchWaitController::RegisterWaitingThread + + Registers the controller's owner thread for waiting on the target + object + --*/ + PAL_ERROR CSynchWaitController::RegisterWaitingThread( + WaitType wtWaitType, + DWORD dwIndex, + bool fAlertable, + bool fPrioritize) + { + VALIDATEOBJECT(m_psdSynchData); + + PAL_ERROR palErr = NO_ERROR; + WaitingThreadsListNode * pwtlnNewNode = NULL; + SharedID shridNewNode = NULL; + ThreadWaitInfo * ptwiWaitInfo; + DWORD * pdwWaitState; + bool fSharedObject = (SharedObject == m_odObjectDomain); + bool fEarlyDeath = false; + bool fSynchDataRefd = false; + CPalSynchronizationManager * pSynchManager = + CPalSynchronizationManager::GetInstance(); + + _ASSERTE(InternalGetCurrentThread() == m_pthrOwner); + + ptwiWaitInfo = CPalSynchronizationManager::GetThreadWaitInfo( + m_pthrOwner); + + _ASSERTE(ptwiWaitInfo->pthrOwner == m_pthrOwner); + + pdwWaitState = SharedIDToTypePointer(DWORD, + m_pthrOwner->synchronizationInfo.m_shridWaitAwakened); + + if (fSharedObject) + { + shridNewNode = pSynchManager->CacheGetSharedWTListNode(m_pthrOwner); + pwtlnNewNode = SharedIDToTypePointer(WaitingThreadsListNode, shridNewNode); + } + else + { + pwtlnNewNode = pSynchManager->CacheGetLocalWTListNode(m_pthrOwner); + } + + if (!pwtlnNewNode) + { + if (fSharedObject && (NULL != shridNewNode)) + { + ASSERT("Bad Shared Memory ptr %p\n", shridNewNode); + palErr = ERROR_INTERNAL_ERROR; + } + else + { + ERROR("Out of memory\n"); + palErr = ERROR_NOT_ENOUGH_MEMORY; + } + goto RWT_exit; + } + + if (ptwiWaitInfo->lObjCount >= MAXIMUM_WAIT_OBJECTS) + { + ASSERT("Too many objects"); + palErr = ERROR_INTERNAL_ERROR; + goto RWT_exit; + } + + if (0 == ptwiWaitInfo->lObjCount) + { + ptwiWaitInfo->wtWaitType = wtWaitType; + ptwiWaitInfo->wdWaitDomain = m_wdWaitDomain; + } + else + { + _ASSERT_MSG(wtWaitType == ptwiWaitInfo->wtWaitType, + "Conflicting wait types in wait registration\n"); + + if (m_wdWaitDomain != ptwiWaitInfo->wdWaitDomain) + { + ptwiWaitInfo->wdWaitDomain = MixedWait; + } + } + + pwtlnNewNode->shridSHRThis = NULL; + pwtlnNewNode->ptwiWaitInfo = ptwiWaitInfo; + pwtlnNewNode->dwObjIndex = dwIndex; + pwtlnNewNode->dwProcessId = gPID; + pwtlnNewNode->dwThreadId = m_pthrOwner->GetThreadId(); + pwtlnNewNode->dwFlags = (MultipleObjectsWaitAll == wtWaitType) ? + WTLN_FLAG_WAIT_ALL : 0; + pwtlnNewNode->shridWaitingState = m_pthrOwner->synchronizationInfo.m_shridWaitAwakened; + if (fSharedObject) + { + pwtlnNewNode->dwFlags |= WTLN_FLAG_OWNER_OBJECT_IS_SHARED; + pwtlnNewNode->shridSHRThis = shridNewNode; + pwtlnNewNode->ptrOwnerObjSynchData.shrid = m_psdSynchData->GetSharedThis(); + } + else + { + pwtlnNewNode->ptrOwnerObjSynchData.ptr = m_psdSynchData; + } + + // AddRef the synch data (will be released in UnregisterWait) + m_psdSynchData->AddRef(); + fSynchDataRefd = true; + + ptwiWaitInfo->rgpWTLNodes[ptwiWaitInfo->lObjCount] = pwtlnNewNode; + + if(otiProcess == m_psdSynchData->GetObjectTypeId()) + { + CProcProcessLocalData * pProcLocalData = GetProcessLocalData(); + + if (NULL == pProcLocalData) + { + // Process local data pointer not set in the controller. + // This pointer is set in CSynchWaitController only when the + // wait controller for the object is created by calling + // GetSynchWaitControllersForObjects + ASSERT("Process synch data pointer is missing\n"); + palErr = ERROR_INTERNAL_ERROR; + goto RWT_exit; + } + + palErr = pSynchManager->RegisterProcessForMonitoring(m_pthrOwner, + m_psdSynchData, + m_pProcessObject, + pProcLocalData); + if (NO_ERROR != palErr) + { + goto RWT_exit; + } + } + + if (0 == ptwiWaitInfo->lObjCount) + { + DWORD dwWaitState; + + // Setting the thread in wait state + dwWaitState = (DWORD)(fAlertable ? TWS_ALERTABLE: TWS_WAITING); + + TRACE("Switching my wait state [%p] from TWS_ACTIVE to %u \n", + pdwWaitState, dwWaitState); + + dwWaitState = InterlockedCompareExchange( + (LONG *)pdwWaitState, (LONG)dwWaitState, TWS_ACTIVE); + if ((DWORD)TWS_ACTIVE != dwWaitState) + { + if ((DWORD)TWS_EARLYDEATH == dwWaitState) + { + // Process is terminating, this thread will soon be + // suspended (by SuspendOtherThreads). + WARN("Thread is about to get suspended by " + "TerminateProcess\n"); + + fEarlyDeath = true; + palErr = WAIT_FAILED; + } + else + { + ASSERT("Unexpected thread wait state %d\n", dwWaitState); + palErr = ERROR_INTERNAL_ERROR; + } + goto RWT_exit; + } + } + + // Add new node to queue + if (fSharedObject) + { + m_psdSynchData->SharedWaiterEnqueue(shridNewNode, fPrioritize); + ptwiWaitInfo->lSharedObjCount += 1; + } + else + { + m_psdSynchData->WaiterEnqueue(pwtlnNewNode, fPrioritize); + } + + // Succeeded: update object count + ptwiWaitInfo->lObjCount++; + + RWT_exit: + if (palErr != NO_ERROR) + { + // Unregister any partial wait registration + pSynchManager->UnRegisterWait(m_pthrOwner, ptwiWaitInfo, fSharedObject); + + if (fSynchDataRefd) + { + m_psdSynchData->Release(m_pthrOwner); + } + if ((fSharedObject) && (NULL != shridNewNode)) + { + pSynchManager->CacheAddSharedWTListNode(m_pthrOwner, shridNewNode); + } + else if (NULL != pwtlnNewNode) + { + pSynchManager->CacheAddLocalWTListNode(m_pthrOwner, pwtlnNewNode); + } + + if (fEarlyDeath) + { + // Early death detected, i.e. the process is about to exit. + // We need to completely release the synch lock(s) before + // going to sleep + LONG lLocalSynchLockCount; + LONG lSharedSynchLockCount; + + lSharedSynchLockCount = CPalSynchronizationManager::ResetSharedSynchLock(m_pthrOwner); + lLocalSynchLockCount = CPalSynchronizationManager::ResetLocalSynchLock(m_pthrOwner); + + _ASSERTE(0 < lLocalSynchLockCount); + + // Sleep for ever + CPalSynchronizationManager::ThreadPrepareForShutdown(); + } + } +#ifdef SYNCH_STATISTICS + else + { + m_psdSynchData->IncrementStatWaitCount(); + m_psdSynchData->IncrementStatContentionCount(); + } +#endif + return palErr; + } + + /*++ + Method: + CSynchWaitController::ReleaseController + + Releases the current controller + --*/ + void CSynchWaitController::ReleaseController() + { + VALIDATEOBJECT(m_psdSynchData); + + _ASSERTE(InternalGetCurrentThread() == m_pthrOwner); + + Release(); + } + + /*++ + Method: + CSynchWaitController::GetProcessLocalData + + Accessor Get method for process local data of the target object + --*/ + CProcProcessLocalData * CSynchWaitController::GetProcessLocalData() + { + VALIDATEOBJECT(m_psdSynchData); + + _ASSERTE(InternalGetCurrentThread() == m_pthrOwner); + _ASSERT_MSG(NULL != m_pProcLocalData, + "Pointer to process local data not yet initialized\n"); + + return m_pProcLocalData; + } + + /*++ + Method: + CSynchWaitController::SetProcessData + + Accessor Set method for process local data of the target object + --*/ + void CSynchWaitController::SetProcessData(IPalObject* pProcessObject, CProcProcessLocalData * pProcLocalData) + { + VALIDATEOBJECT(m_psdSynchData); + + _ASSERTE(InternalGetCurrentThread() == m_pthrOwner); + _ASSERT_MSG(m_pProcessObject == nullptr, "SetProcessData should not be called more than once"); + _ASSERT_MSG(pProcessObject != nullptr && pProcessObject->GetObjectType()->GetId() == otiProcess, "Invalid process object passed to SetProcessData"); + + m_pProcessObject = pProcessObject; + m_pProcLocalData = pProcLocalData; + } + + ///////////////////////////// + // // + // CSynchStateController // + // // + ///////////////////////////// + + /*++ + Method: + CSynchStateController::GetSignalCount + + Returns the current signal count of the target object + --*/ + PAL_ERROR CSynchStateController::GetSignalCount(LONG *plSignalCount) + { + VALIDATEOBJECT(m_psdSynchData); + + PAL_ERROR palErr = NO_ERROR; + LONG lCount = m_psdSynchData->GetSignalCount(); + + _ASSERTE(InternalGetCurrentThread() == m_pthrOwner); + _ASSERTE(NULL != plSignalCount); + _ASSERT_MSG(0 <= lCount, + "Internal error: negative signal count [signal count=%d]", + lCount); + + *plSignalCount = lCount; + return palErr; + } + + /*++ + Method: + CSynchStateController::SetSignalCount + + Sets the signal count of the target object, possibly triggering + waiting threads awakening. + --*/ + PAL_ERROR CSynchStateController::SetSignalCount(LONG lNewCount) + { + VALIDATEOBJECT(m_psdSynchData); + + _ASSERTE(InternalGetCurrentThread() == m_pthrOwner); + _ASSERTE(lNewCount >= 0); + + m_psdSynchData->Signal(m_pthrOwner, lNewCount, false); + + return NO_ERROR; + } + + /*++ + Method: + CSynchStateController::IncrementSignalCount + + Increments the signal count of the target object, possibly triggering + waiting threads awakening. + --*/ + PAL_ERROR CSynchStateController::IncrementSignalCount( + LONG lAmountToIncrement) + { + VALIDATEOBJECT(m_psdSynchData); + + _ASSERTE(InternalGetCurrentThread() == m_pthrOwner); + _ASSERTE(lAmountToIncrement > 0); + + LONG lOldCount = m_psdSynchData->GetSignalCount(); + LONG lNewCount = lOldCount + lAmountToIncrement; + + _ASSERT_MSG(lNewCount > lOldCount, + "Signal count increment %d would make current signal count %d to " + "wrap around\n", lAmountToIncrement, lOldCount); + + m_psdSynchData->Signal(m_pthrOwner, lNewCount, false); + + return NO_ERROR; + } + + /*++ + Method: + CSynchStateController::DecrementSignalCount + + Decrements the signal count of the target object. + --*/ + PAL_ERROR CSynchStateController::DecrementSignalCount( + LONG lAmountToDecrement) + { + VALIDATEOBJECT(m_psdSynchData); + + _ASSERTE(InternalGetCurrentThread() == m_pthrOwner); + _ASSERTE(lAmountToDecrement > 0); + + PAL_ERROR palErr = NO_ERROR; + LONG lCount = m_psdSynchData->GetSignalCount(); + _ASSERTE(lAmountToDecrement <= lCount); + + m_psdSynchData->SetSignalCount(lCount - lAmountToDecrement); + + return palErr; + } + + /*++ + Method: + CSynchStateController::SetOwner + + Sets the owner of the target object and initializes the ownership + count to 1 (for objects with tracked ownership). + --*/ + PAL_ERROR CSynchStateController::SetOwner(CPalThread * pNewOwningThread) + { + VALIDATEOBJECT(m_psdSynchData); + + PAL_ERROR palErr = NO_ERROR; + + _ASSERTE(InternalGetCurrentThread() == m_pthrOwner); + _ASSERTE(NULL != pNewOwningThread); + _ASSERT_MSG(CObjectType::OwnershipTracked == + m_potObjectType->GetOwnershipSemantics(), + "SetOwner called on an object without OwnershipTracked " + "semantics\n"); + + if (0 != m_psdSynchData->GetOwnershipCount()) + { + ASSERT("Ownership count should be zero at this time\n"); + palErr = ERROR_INTERNAL_ERROR; + goto SO_exit; + } + + palErr = m_psdSynchData->AssignOwnershipToThread(m_pthrOwner, + pNewOwningThread); + + _ASSERT_MSG(0 == m_psdSynchData->GetOwnershipCount() || + 0 == m_psdSynchData->GetSignalCount(), + "Conflicting values for SignalCount [%d] and " + "OwnershipCount [%d]\n", + m_psdSynchData->GetOwnershipCount(), + m_psdSynchData->GetSignalCount()); + + SO_exit: + return palErr; + } + + /*++ + Method: + CSynchStateController::DecrementOwnershipCount + + Decrements the ownership count of the target object possibly triggering + waiting threads awakening (for objects with tracked ownership). + --*/ + PAL_ERROR CSynchStateController::DecrementOwnershipCount() + { + VALIDATEOBJECT(m_psdSynchData); + + PAL_ERROR palErr = NO_ERROR; + LONG lOwnershipCount = m_psdSynchData->GetOwnershipCount(); + + _ASSERTE(InternalGetCurrentThread() == m_pthrOwner); + _ASSERT_MSG(CObjectType::OwnershipTracked == + m_potObjectType->GetOwnershipSemantics(), + "Trying to decrement ownership count on an object with " + "ownership semantics other than OwnershipTracked\n"); + _ASSERT_MSG(0 <= lOwnershipCount, + "Operation would make ownership count negative - object " + "should be owned at this time [ownership count=%d]\n", + lOwnershipCount); + + if ( (1 > lOwnershipCount) || + (m_psdSynchData->GetOwnerProcessID() != gPID) || + (m_psdSynchData->GetOwnerThread() != m_pthrOwner) ) + { + palErr = ERROR_NOT_OWNER; + goto DOC_exit; + } + + lOwnershipCount--; + m_psdSynchData->SetOwnershipCount(lOwnershipCount); + + if (0 == lOwnershipCount) + { + CPalSynchronizationManager * pSynchManager = + CPalSynchronizationManager::GetInstance(); + OwnedObjectsListNode * pooln = + m_psdSynchData->GetOwnershipListNode(); + + _ASSERT_MSG(NULL != pooln, + "Null ownership node pointer in SynchData with ownership " + "semantics\n"); + _ASSERT_MSG(m_psdSynchData == pooln->pPalObjSynchData, + "Corrupted ownership node\n"); + + // Object has been released + // Remove it from list of owned objs for current thread + m_pthrOwner->synchronizationInfo.RemoveObjectFromOwnedList(pooln); + + // Release SynchData reference count implied by the ownership + // list node + m_psdSynchData->Release(m_pthrOwner); + + // Return node to the cache + pSynchManager->CacheAddOwnedObjsListNode(m_pthrOwner, pooln); + + // Reset ownership + m_psdSynchData->ResetOwnership(); + + // Signal it and trigger waiter thread awakening + m_psdSynchData->Signal(m_pthrOwner, 1, false); + } + + DOC_exit: + return palErr; + } + + /*++ + Method: + CSynchStateController::ReleaseController + + Releases the controller. + --*/ + void CSynchStateController::ReleaseController(void) + { + VALIDATEOBJECT(m_psdSynchData); + + _ASSERTE(InternalGetCurrentThread() == m_pthrOwner); + + Release(); + } + + ////////////////// + // // + // CSynchData // + // // + ////////////////// + + /*++ + Method: + CSynchData::Release + + Decremnt the reference count of the target synchdata and retrurns + it to the appropriate cache if the reference count reaches zero. + --*/ + LONG CSynchData::Release(CPalThread * pthrCurrent) + { + VALIDATEOBJECT(this); + + LONG lCount = InterlockedDecrement(&m_lRefCount); + + _ASSERT_MSG(0 <= lCount, + "CSynchData %p with negative reference count [%d]\n", + this, lCount); + + if (0 == lCount) + { + CPalSynchronizationManager * pSynchManager = + CPalSynchronizationManager::GetInstance(); + bool fSharedObject = (SharedObject == m_odObjectDomain); + + _ASSERT_MSG((fSharedObject && (NULL == m_ptrWTLHead.shrid)) || + (!fSharedObject && (NULL == m_ptrWTLHead.ptr)), + "Final Release on CSynchData with threads still in " + "the waiting list\n"); + + TRACE("Disposing %s waitable object with SynchData @ " + "{shrid=%p, p=%p}\n", + (SharedObject == m_odObjectDomain) ? "shared" : "local", + (PVOID)m_shridThis, this); + + +#ifdef SYNCH_STATISTICS + LONG lStatWaitCount = GetStatWaitCount(); + LONG lStatContentionCount = GetStatContentionCount(); + LONG lCount, lNewCount; + + TRACE("Statistical data for SynchData of otiType=%u @ %p: WaitCount=%d " + "ContentionCount=%d\n", m_otiObjectTypeId, this, lStatWaitCount, + lStatContentionCount); + + do { + lCount = g_rglStatWaitCount[m_otiObjectTypeId]; + lNewCount = lCount + lStatWaitCount; + lNewCount = InterlockedCompareExchange(&(g_rglStatWaitCount[m_otiObjectTypeId]), + lNewCount, lCount); + } while (lCount != lNewCount); + + lStatWaitCount = lNewCount; + + do { + lCount = g_rglStatContentionCount[m_otiObjectTypeId]; + lNewCount = lCount + lStatContentionCount; + lNewCount = InterlockedCompareExchange(&(g_rglStatContentionCount[m_otiObjectTypeId]), + lNewCount, lCount); + } while (lCount != lNewCount); + + lStatContentionCount = lNewCount; + + TRACE("Total current statistical data for otiType=%u objects: WaitCount=%d " + "ContentionCount=%d\n", m_otiObjectTypeId, lStatWaitCount, + lStatContentionCount); +#endif // SYNCH_STATISTICS + + if (fSharedObject) + { + pSynchManager->CacheAddSharedSynchData(pthrCurrent, m_shridThis); + } + else + { + pSynchManager->CacheAddLocalSynchData(pthrCurrent, this); + } + } + + return lCount; + } + + /*++ + Method: + CSynchData::ReleaseWaiterWithoutBlocking + + Performs all the steps needed to be done by the target thread in order + to wait without blocking on the object associated with the current + SynchData (e.g. modifying the object signal count accordingly with its + thread release semantics) + + Note: this method must be called while holding the appropriate + synchronization locks (the local process synch lock if the target + object is local, both local and shared one if the object is shared). + --*/ + PAL_ERROR CSynchData::ReleaseWaiterWithoutBlocking( + CPalThread * pthrCurrent, + CPalThread * pthrTarget) + { + VALIDATEOBJECT(this); + + PAL_ERROR palErr = NO_ERROR; + CObjectType * potObjectType = GetObjectType(); +#ifdef _DEBUG + CObjectType::SignalingSemantics ssSignalingSemantics = + potObjectType->GetSignalingSemantics(); +#endif // _DEBUG + CObjectType::OwnershipSemantics osOwnershipSemantics = + potObjectType->GetOwnershipSemantics(); + CObjectType::ThreadReleaseSemantics trsThreadReleaseSemantics = + potObjectType->GetThreadReleaseSemantics(); + bool fReenteringObjWithOwnership = false; + + _ASSERT_MSG(CObjectType::SignalingNotApplicable != ssSignalingSemantics, + "Signaling not applicable"); + _ASSERT_MSG(CObjectType::ThreadReleaseNotApplicable != + trsThreadReleaseSemantics, + "Thread releasing not applicable"); + _ASSERT_MSG(CObjectType::SingleTransitionObject != ssSignalingSemantics || + (CObjectType::ThreadReleaseHasNoSideEffects == + trsThreadReleaseSemantics && + CObjectType::NoOwner == osOwnershipSemantics), + "Conflicting object synchronization attributes " + "[SignalingSemantics=%u OwnershipSemantics=%u " + "ThreadReleaseSemantics=%u]\n", ssSignalingSemantics, + osOwnershipSemantics, trsThreadReleaseSemantics); + + if (CObjectType::OwnershipTracked == osOwnershipSemantics && + 0 < GetOwnershipCount()) + { + // We are rentering an object with ownership: we need to skip + // the object unsignaling + fReenteringObjWithOwnership = true; + } + + if (!fReenteringObjWithOwnership && + CObjectType::ThreadReleaseAltersSignalCount == trsThreadReleaseSemantics) + { + _ASSERT_MSG(0 < GetSignalCount(), + "Internal error: operation would make signal count " + "negative - object should be signaled at this time " + "[signal count=%d]", GetSignalCount()); + _ASSERT_MSG(CObjectType::OwnershipTracked != osOwnershipSemantics || + 1 == GetSignalCount(), + "Ownable objects cannot have signal count greater " + "than zero [current SignalCount=%d]\n", + GetSignalCount()); + + // Unsignal the object + DecrementSignalCount(); + } + + if (CObjectType::OwnershipTracked == osOwnershipSemantics) + { + _ASSERT_MSG(0 == GetOwnershipCount() || 0 == GetSignalCount(), + "OwnershipCount and SignalCount with conflicting " + "values\n"); + + // Take ownership or increment ownership count. + // We do this after the object unsignaling to minimize possibilities + // of having both SignalCount and OwnershipCount greater than zero + // (see comment in AssignOwnershipToThread) + palErr = AssignOwnershipToThread(pthrCurrent, pthrTarget); + + if (NO_ERROR != palErr) + { + ERROR("AssignOwnershipToThread failed with error %u; " + "ownership data on object with SynchData {shrid=%p p=%p} " + "may be corrupted\n", palErr, (void *)m_shridThis, this); + } + } + +#ifdef SYNCH_STATISTICS + if (NO_ERROR == palErr) + { + IncrementStatWaitCount(); + } +#endif + return palErr; + + } + + /*++ + Method: + CSynchData::CanWaiterWaitWithoutBlocking + + Returns whether or not the waiter thread can wait on the target object + without blocking (i.e. the objet is signaled) + + Note: this method must be called while holding the appropriate + synchronization locks (the local process synch lock if the target + object is local, both local and shared one if the object is shared). + --*/ + bool CSynchData::CanWaiterWaitWithoutBlocking( + CPalThread * pWaiterThread, + bool * pfAbandoned) + { + VALIDATEOBJECT(this); + + bool fRetVal = (0 < GetSignalCount()); + bool fAbandoned = false; + bool fOwnershipTracked = (CObjectType::OwnershipTracked == + GetObjectType()->GetOwnershipSemantics()); + if (fRetVal) + { + // Object signaled: thread can wait without blocking + if (fOwnershipTracked) + { + fAbandoned = IsAbandoned(); + } + + goto CWWWB_exit; + } + + // Object not signaled: thread can wait without blocking only if the + // object is an ownable one, and it is owned by the current thread + if (fOwnershipTracked) + { + _ASSERT_MSG(0 < GetSignalCount() || 0 < GetOwnershipCount(), + "Objects with ownership must be either signaled or " + "owned by a thread\n"); + + if ((GetOwnerProcessID() == gPID) && + (GetOwnerThread() == pWaiterThread) ) + { + fRetVal = true; + goto CWWWB_exit; + } + } + + CWWWB_exit: + *pfAbandoned = fAbandoned; + return fRetVal; + } + + /*++ + Method: + CSynchData::Signal + + Sets the signal count of the object owning the target SynchData, + possibly triggering awakening of waiting threads. + + Note: this method must be called while holding the appropriate + synchronization locks (the local process synch lock if the target + object is local, both local and shared one if the object is shared). + --*/ + void CSynchData::Signal( + CPalThread * pthrCurrent, + LONG lSignalCount, + bool fWorkerThread) + { + VALIDATEOBJECT(this); + + bool fThreadReleased = false; + bool fDelegatedSignaling = false; + bool fReleaseAltersSignalCount = + (CObjectType::ThreadReleaseAltersSignalCount == + GetObjectType()->GetThreadReleaseSemantics()); + + _ASSERTE(0 <= lSignalCount); + + // Preset the signal count to the new value, so that it can be used + // by ReleaseFirstWaiter when delegating signaling to another process + m_lSignalCount = lSignalCount; + + while (m_lSignalCount > 0) + { + fThreadReleased = ReleaseFirstWaiter(pthrCurrent, + &fDelegatedSignaling, + fWorkerThread); + if (!fThreadReleased) + { + // No more threads to release: break out of the loop + // keeping the current signal count + break; + } + if (fReleaseAltersSignalCount) + { + // Adjust signal count + m_lSignalCount--; + } + if (fDelegatedSignaling) + { + // Object signaling has been delegated + m_lSignalCount = 0; + } + } + + _ASSERT_MSG(CObjectType::OwnershipTracked != + GetObjectType()->GetOwnershipSemantics() || + 0 == GetOwnershipCount() || 0 == GetSignalCount(), + "Conflicting values for SignalCount [%d] and " + "OwnershipCount [%d]\n", + GetOwnershipCount(), GetSignalCount()); + + _ASSERT_MSG(otiMutex != m_otiObjectTypeId || m_lSignalCount <= 1, + "Mutex with invalid singal count\n"); + + return; + } + + /*++ + Method: + CSynchData::ReleaseFirstWaiter + + Releases the first thread from the front of the list of waiting threads + whose wait is fully satisfied, possibly triggering remote awakening (if + the target thread lives in a different process) or object signaling + delegation (if the target thread lives in a different processing and it + is blocked on a wait-all). + + Note: this method must be called while holding the appropriate + synchronization locks (the local process synch lock if the target + object is local, both local and shared one if the object is shared). + --*/ + bool CSynchData::ReleaseFirstWaiter( + CPalThread * pthrCurrent, + bool * pfDelegated, + bool fWorkerThread) + { + PAL_ERROR palErr = NO_ERROR; + bool fSharedSynchLock = false; + bool fSharedObject = (SharedObject == GetObjectDomain()); + bool fThreadAwakened = false; + bool fDelegatedSignaling = false; + DWORD * pdwWaitState; + DWORD dwObjIdx; + SharedID shridItem = NULL, shridNextItem = NULL; + WaitingThreadsListNode * pwtlnItem, * pwtlnNextItem; + DWORD dwPid = gPID; + CPalSynchronizationManager * pSynchManager = + CPalSynchronizationManager::GetInstance(); + + VALIDATEOBJECT(this); + + *pfDelegated = false; + + if (fSharedObject) + { + shridItem = GetWTLHeadShmPtr(); + pwtlnItem = SharedIDToTypePointer(WaitingThreadsListNode, shridItem); + } + else + { + pwtlnItem = GetWTLHeadPtr(); + } + + while (pwtlnItem) + { + VALIDATEOBJECT(pwtlnItem); + + WaitCompletionState wcsWaitCompletionState; + bool fWaitAll = (0 != (WTLN_FLAG_WAIT_ALL & pwtlnItem->dwFlags)); + pdwWaitState = SharedIDToTypePointer(DWORD, + pwtlnItem->shridWaitingState); + + if (fSharedObject) + { + shridNextItem = pwtlnItem->ptrNext.shrid; + pwtlnNextItem = SharedIDToTypePointer(WaitingThreadsListNode, + shridNextItem); + } + else + { + pwtlnNextItem = pwtlnItem->ptrNext.ptr; + } + + if (fWaitAll) + { + // Wait All: we need to find out whether the wait is satisfied, + // or it is not, or if that cannot be determined from within + // this process (WaitMayBeSatisfied); in this case we need to + // delegate the object signaling to the process hosting the + // thread that owns the current target WaitingThreadsListNode + + // If the target object is local (fSharedObject == false) + // we're probably not holding the shared lock. + // If the wait is not a LocalWait, it involves at least one + // shared object. If that is the case, at this time we need + // to grab the shared lock. In fact IsRestOfWaitAllSatisfied + // and UnsignalRestOfLocalAwakeningWaitAll must be called + // atomically to prevent that another thread living + // in a different process could race with us stealing the + // signaling from one of the objects involved in the wait-all. + // + // Note: pwtlnItem->ptwiWaitInfo is valid only if the target + // wait originates in the current process. Anyway in the + // following 'if' we don't need to check that since we are + // already making sure that the object is local (!fSharedObject). + // If a wait involves at least one object local to this process, + // it can only be a wait performed by a thread in the current + // process, therefore pwtlnItem->ptwiWaitInfo is valid. + + _ASSERTE(fSharedObject || pwtlnItem->dwProcessId == gPID); + + if (!fSharedSynchLock && !fSharedObject && + LocalWait != pwtlnItem->ptwiWaitInfo->wdWaitDomain) + { + CPalSynchronizationManager::AcquireSharedSynchLock(pthrCurrent); + fSharedSynchLock = true; + } + + // First check if the current target node is already marked for + // wait all check in progress, and in case skip it by setting + // wcsWaitCompletionState to WaitIsNotSatisfied + bool fMarkedForDelegatedObjectSingalingInProgress = + (0 != (WTLN_FLAG_DELEGATED_OBJECT_SIGNALING_IN_PROGRESS & pwtlnItem->dwFlags)); + + wcsWaitCompletionState = + fMarkedForDelegatedObjectSingalingInProgress ? WaitIsNotSatisfied : + IsRestOfWaitAllSatisfied(pwtlnItem); + } + else + { + // Normal Wait: the wait is satisfied by definition + wcsWaitCompletionState = WaitIsSatisfied; + } + + if (WaitIsSatisfied == wcsWaitCompletionState) + { + // + // Target wait is satisfied + // + TRACE("Trying to switch wait state [%p] from WAIT/ALERTABLE " + "to ACTIVE for thread=%u\n", + pdwWaitState, pwtlnItem->dwThreadId); + + if (CPalSynchronizationManager::InterlockedAwaken(pdwWaitState, FALSE)) + { + TRACE("Succeeded switching wait state [%p] from WAIT/ALERTABLE " + "to TWS_ACTIVE for trhead=%u\n", + pdwWaitState, pwtlnItem->dwThreadId); + + dwObjIdx = pwtlnItem->dwObjIndex; + + if (dwPid == pwtlnItem->dwProcessId) + { + /////////////////////////// + // + // Local Thread Awakening + // + /////////////////////////// + ThreadWaitInfo * ptwiWaitInfo = pwtlnItem->ptwiWaitInfo; + bool fAbandoned = false; + + if (CObjectType::OwnershipTracked == + GetObjectType()->GetOwnershipSemantics()) + { + // Get the abandoned status before resetting it by + // assigning ownership to target thread + fAbandoned = IsAbandoned(); + + // Assign ownership to target thread + // Note: This will cause both ownership count and + // signal count to be greater than zero at the + // same time; the signal count will be anyway + // decremented immediately by the caller + // CsynchData::Signal + palErr = AssignOwnershipToThread(pthrCurrent, + ptwiWaitInfo->pthrOwner); + if (NO_ERROR != palErr) + { + ERROR("Synch Worker: AssignOwnershipToThread " + "failed with error %u; ownership data on " + "object with SynchData %p may be " + "corrupted\n", palErr, this); + } + } + + if (fWaitAll) + { + // Wait all satisfied: unsignal other objects + // involved in the wait + CPalSynchronizationManager::UnsignalRestOfLocalAwakeningWaitAll( + pthrCurrent, + ptwiWaitInfo->pthrOwner, + pwtlnItem, + this); + } + + TRACE("Unregistering wait for thread %u and waking it up " + "[pdwWaitState=%p]\n", pwtlnItem->dwThreadId, + pdwWaitState); + + // Unregister the wait + pSynchManager->UnRegisterWait(pthrCurrent, + ptwiWaitInfo, + fSharedObject || fSharedSynchLock); + + // After UnRegisterWait pwtlnItem is invalid + pwtlnItem = NULL; + + palErr = CPalSynchronizationManager::WakeUpLocalThread( + pthrCurrent, + ptwiWaitInfo->pthrOwner, + fAbandoned ? MutexAbondoned : WaitSucceeded, + dwObjIdx); + + if (NO_ERROR != palErr) + { + ERROR("Failed to wakeup local thread %#x: " + "object signaling may be " + "lost\n", ptwiWaitInfo->pthrOwner->GetThreadId()); + } + } + else + { + /////////////////////////// + // + // Remote Thread Awakening + // + /////////////////////////// + + // Note: if we are here, this cannot be a wait-all + _ASSERT_MSG(!fWaitAll, + "Control should never reach this point if " + "target wait is a wait-all\n"); + + // Wake up remote thread + palErr = CPalSynchronizationManager::WakeUpRemoteThread(shridItem); + + if (NO_ERROR != palErr) + { + ERROR("Failed to dispatch remote awakening cmd to " + "worker thread in process pid=%d to wake up" + "thread tid=%#x; object signaling may be " + "lost\n", pwtlnItem->dwProcessId, + pwtlnItem->dwThreadId); + } + } + + // A thread has been awakened + fThreadAwakened = true; + + // break out of the while loop + break; + } + } + else if (WaitMayBeSatisfied == wcsWaitCompletionState) + { + ////////////////////////////////////////// + // + // Wait All with remote thread awakening + // + ////////////////////////////////////////// + + // + // We need to transfer the object signaling to the process + // hosting the target waiter thread + // + + _ASSERT_MSG(fWaitAll, + "IsRestOfWaitAllSatisfied() apparently " + "returned -1 on a normal (non wait all) " + "wait\n"); + _ASSERT_MSG(fSharedObject, + "About to delegate object signaling to a remote " + "process, but the signaled object is actually " + "local\n"); + + // Delegate object signaling to target process + palErr = CPalSynchronizationManager::DelegateSignalingToRemoteProcess( + pthrCurrent, + pwtlnItem->dwProcessId, + pwtlnItem->ptrOwnerObjSynchData.shrid); + + TRACE("Delegating object signaling for SynchData shrid=%p\n", + (VOID *)pwtlnItem->ptrOwnerObjSynchData.shrid); + + if (NO_ERROR == palErr) + { + // A remote thread will be awakened + // This will also cause the object to be unsignaled by the + // code calling ReleaseFirstWaiter before releasing the + // synch locks, so no other WaitForMultipleObjects + // involving the target object may race stealing this + // particuklar object signaling + fThreadAwakened = true; + + fDelegatedSignaling = true; + + // break out of the while loop + break; + } + else + { + ERROR("Failed to delegate object signaling to remote " + "process %d. Looking for another waiter.\n", + pwtlnItem->dwProcessId); + + // Go on: a different target waiter will be selected + } + } + + if (fWorkerThread && fWaitAll && (dwPid == pwtlnItem->dwProcessId)) + { + // Mark the target wait for object signaling + CPalSynchronizationManager::MarkWaitForDelegatedObjectSignalingInProgress( + pthrCurrent, + pwtlnItem); + } + + // Go to the next item + shridItem = shridNextItem; + pwtlnItem = pwtlnNextItem; + } + + if (fDelegatedSignaling) + { + *pfDelegated = true; + } + else if (fWorkerThread) + { + // Reset 'delegated object signaling in progress' flags + CPalSynchronizationManager::UnmarkTWListForDelegatedObjectSignalingInProgress( + this); + } + + if (fSharedSynchLock) + { + CPalSynchronizationManager::ReleaseSharedSynchLock(pthrCurrent); + } + return fThreadAwakened; + } + + /*++ + Method: + CSynchData::Signal + + Releases all the threads waiting on this object and living in the current + process. + + Note: this method must be called while holding the appropriate + synchronization locks (the local process synch lock if the target + object is local, both local and shared one if the object is shared). + --*/ + LONG CSynchData::ReleaseAllLocalWaiters( + CPalThread * pthrCurrent) + { + PAL_ERROR palErr = NO_ERROR; + LONG lAwakenedCount = 0; + bool fSharedSynchLock = false; + bool fSharedObject = (SharedObject == GetObjectDomain()); + DWORD * pdwWaitState; + DWORD dwObjIdx; + SharedID shridItem = NULL, shridNextItem = NULL; + WaitingThreadsListNode * pwtlnItem, * pwtlnNextItem; + DWORD dwPid = gPID; + CPalSynchronizationManager * pSynchManager = + CPalSynchronizationManager::GetInstance(); + + VALIDATEOBJECT(this); + + if (fSharedObject) + { + shridItem = GetWTLHeadShmPtr(); + pwtlnItem = SharedIDToTypePointer(WaitingThreadsListNode, shridItem); + } + else + { + pwtlnItem = GetWTLHeadPtr(); + } + + while (pwtlnItem) + { + VALIDATEOBJECT(pwtlnItem); + + bool fWaitAll = (0 != (WTLN_FLAG_WAIT_ALL & pwtlnItem->dwFlags)); + pdwWaitState = SharedIDToTypePointer(DWORD, + pwtlnItem->shridWaitingState); + + if (fSharedObject) + { + shridNextItem = pwtlnItem->ptrNext.shrid; + pwtlnNextItem = SharedIDToTypePointer(WaitingThreadsListNode, + shridNextItem); + } + else + { + pwtlnNextItem = pwtlnItem->ptrNext.ptr; + } + + // See note in similar spot in ReleaseFirstWaiter + + _ASSERTE(fSharedObject || pwtlnItem->dwProcessId == gPID); + + if (!fSharedSynchLock && !fSharedObject && + LocalWait != pwtlnItem->ptwiWaitInfo->wdWaitDomain) + { + CPalSynchronizationManager::AcquireSharedSynchLock(pthrCurrent); + fSharedSynchLock = true; + } + + if( dwPid == pwtlnItem->dwProcessId && + (!fWaitAll || WaitIsSatisfied == IsRestOfWaitAllSatisfied(pwtlnItem)) ) + { + // + // Target wait is satisfied + // + TRACE("Trying to switch wait state [%p] from WAIT/ALERTABLE " + "to ACTIVE for thread=%u\n", + pdwWaitState, pwtlnItem->dwThreadId); + + if (CPalSynchronizationManager::InterlockedAwaken(pdwWaitState, FALSE)) + { + TRACE("Succeeded switching wait state [%p] from WAIT/ALERTABLE " + "to TWS_ACTIVE for trhead=%u\n", + pdwWaitState, pwtlnItem->dwThreadId); + + dwObjIdx = pwtlnItem->dwObjIndex; + + ThreadWaitInfo * ptwiWaitInfo = pwtlnItem->ptwiWaitInfo; + bool fAbandoned = false; + + if (CObjectType::OwnershipTracked == + GetObjectType()->GetOwnershipSemantics()) + { + // Get the abandoned status before resetting it by + // assigning ownership to target thread + fAbandoned = IsAbandoned(); + + // Assign ownership to target thread + palErr = AssignOwnershipToThread(pthrCurrent, + ptwiWaitInfo->pthrOwner); + if (NO_ERROR != palErr) + { + ERROR("Synch Worker: AssignOwnershipToThread " + "failed with error %u; ownership data on " + "object with SynchData %p may be " + "corrupted\n", palErr, this); + } + } + + if (fWaitAll) + { + // Wait all satisfied: unsignal other objects + // involved in the wait + CPalSynchronizationManager::UnsignalRestOfLocalAwakeningWaitAll( + pthrCurrent, + ptwiWaitInfo->pthrOwner, + pwtlnItem, + this); + } + + TRACE("Unregistering wait for thread %u and waking it up " + "[pdwWaitState=%p]\n", pwtlnItem->dwThreadId, + pdwWaitState); + + // Unregister the wait + pSynchManager->UnRegisterWait(pthrCurrent, + ptwiWaitInfo, + fSharedObject || fSharedSynchLock); + + // After UnRegisterWait pwtlnItem is invalid + pwtlnItem = NULL; + + palErr = CPalSynchronizationManager::WakeUpLocalThread( + pthrCurrent, + ptwiWaitInfo->pthrOwner, + fAbandoned ? MutexAbondoned : WaitSucceeded, + dwObjIdx); + + if (NO_ERROR != palErr) + { + ERROR("Failed to wakeup local thread %#x: " + "object signaling may be " + "lost\n", ptwiWaitInfo->pthrOwner->GetThreadId()); + } + else + { + // A thread has been awakened + lAwakenedCount++; + } + } + } + + // Go to the next item + shridItem = shridNextItem; + pwtlnItem = pwtlnNextItem; + } + + if (fSharedSynchLock) + { + CPalSynchronizationManager::ReleaseSharedSynchLock(pthrCurrent); + } + return lAwakenedCount; + } + + /*++ + Method: + CSynchData::IsRestOfWaitAllSatisfied + + Returns whether or not the current wait-all operation is fully satisfied, + assuming the current target object as signaled (i.e. whether or not all the + involved object, except the current one, are signaled). + It returns: + - WaitIsNotSatisfied if the wait-all is not fully satisfied. + - WaitIsSatisfied if the wait-all is fully satisfied. + - WaitMayBeSatisfied if the target thread lives in a different process and + therefore the wait may involve objects local to the remote process, and + as result is generally not possible to say whther or not the wait-all is + fully satisfied from the current process. + + Note: this method must be called while holding the synchronization locks + appropriate to all the objects involved in the wait-all. If any + of the objects is shared, the caller must own both local and + shared synch locks; if no shared object is involved in the wait, + only the local synch lock is needed. + --*/ + WaitCompletionState CSynchData::IsRestOfWaitAllSatisfied( + WaitingThreadsListNode * pwtlnNode) + { + int iSignaledOrOwnedObjCount = 0; + int iTgtCount = 0; + int i; + WaitCompletionState wcsWaitCompletionState = WaitIsNotSatisfied; + CSynchData * psdSynchDataItem = NULL; + ThreadWaitInfo * ptwiWaitInfo = NULL; + + VALIDATEOBJECT(this); + VALIDATEOBJECT(pwtlnNode); + + _ASSERT_MSG(0 != (WTLN_FLAG_WAIT_ALL & pwtlnNode->dwFlags), + "IsRestOfWaitAllSatisfied() called on a normal " + "(non wait all) wait"); + _ASSERT_MSG((SharedObject == GetObjectDomain()) == + (0 != (WTLN_FLAG_OWNER_OBJECT_IS_SHARED & pwtlnNode->dwFlags)), + "WTLN_FLAG_OWNER_OBJECT_IS_SHARED in WaitingThreadsListNode " + "not consistent with target object's domain\n"); + + if(gPID != pwtlnNode->dwProcessId) + { + //////////////////////////// + // + // Remote Thread Awakening + // + //////////////////////////// + + // Cannot determine whether or not the wait all is satisfied from + // this process + wcsWaitCompletionState = WaitMayBeSatisfied; + goto IROWAS_exit; + } + + /////////////////////////// + // + // Local Thread Awakening + // + /////////////////////////// + + ptwiWaitInfo = pwtlnNode->ptwiWaitInfo; + + iTgtCount = ptwiWaitInfo->lObjCount; + for (i=0; i < iTgtCount; i++) + { + WaitingThreadsListNode * pwtlnItem = ptwiWaitInfo->rgpWTLNodes[i]; + bool fRetVal; + bool fIsAbandoned; + + VALIDATEOBJECT(pwtlnItem); + + if (0 != (WTLN_FLAG_OWNER_OBJECT_IS_SHARED & pwtlnItem->dwFlags)) + { + psdSynchDataItem = SharedIDToTypePointer(CSynchData, + pwtlnItem->ptrOwnerObjSynchData.shrid); + } + else + { + psdSynchDataItem = pwtlnItem->ptrOwnerObjSynchData.ptr; + } + + VALIDATEOBJECT(psdSynchDataItem); + + if (pwtlnItem == pwtlnNode) + { + _ASSERT_MSG (this == psdSynchDataItem, + "pwtlnNode and pwtlnItem match, but this " + "and psdSynchDataItem don't\n"); + + // The target object (the one related to pwtlnNode) is counted as + // signaled/owned without checking it (also if it is not, as + // it normally happens when this method is called) + iSignaledOrOwnedObjCount++; + continue; + } + + fRetVal = psdSynchDataItem->CanWaiterWaitWithoutBlocking( + ptwiWaitInfo->pthrOwner, + &fIsAbandoned); + + if (fRetVal) + { + iSignaledOrOwnedObjCount++; + } + else + { + break; + } + } + + if (iSignaledOrOwnedObjCount < iTgtCount) + { + wcsWaitCompletionState = WaitIsNotSatisfied; + } + else + { + wcsWaitCompletionState = WaitIsSatisfied; + } + + IROWAS_exit: + TRACE("IsRestOfWaitAllSatisfied() returning %u \n", wcsWaitCompletionState); + + return wcsWaitCompletionState; + } + + + /*++ + Method: + CSynchData::SetOwner + + Blindly sets the thread whose CPalThread is passed as argument, as the + owner of the current object. + WARNING: this method discards any previous ownership data and does not + update the list of the object owned by the owner thread. + + Note: this method must be called while holding the appropriate + synchronization locks (the local process synch lock if the target + object is local, both local and shared one if the object is shared). + --*/ + void CSynchData::SetOwner(CPalThread * pOwnerThread) + { + VALIDATEOBJECT(this); + + m_dwOwnerPid = gPID; + m_dwOwnerTid = pOwnerThread->GetThreadId(); + m_pOwnerThread = pOwnerThread; + } + + /*++ + Method: + CSynchData::ResetOwnership + + Resets current object's ownership data + + Note: this method must be called while holding the appropriate + synchronization locks (the local process synch lock if the target + object is local, both local and shared one if the object is shared). + --*/ + void CSynchData::ResetOwnership() + { + VALIDATEOBJECT(this); + + m_lOwnershipCount = 0; + m_dwOwnerPid = 0; + m_dwOwnerTid = 0; + m_pOwnerThread = NULL; + m_poolnOwnedObjectListNode = NULL; + } + + /*++ + Method: + CSynchData::AssignOwnershipToThread + + Assigns thw ownership of the current object to the target thread, performing + all the operations neede to mantain the correct status of ownership data, + also handling recursive object ownership acquisition + + Note: this method must be called while holding the appropriate + synchronization locks (the local process synch lock if the target + object is local, both local and shared one if the object is shared). + --*/ + PAL_ERROR CSynchData::AssignOwnershipToThread( + CPalThread * pthrCurrent, + CPalThread * pthrTarget) + { + // Note: when this method is called by ReleaseFirstWaiter there is + // a small time window in which both SignalCount and + // OwnershipCount can be greater than zero (which normally + // is illegal). Anyway that is fine since ReleaseFirstWaiter + // will restore the value right after, and such situation + // takes place while holding synchroniztion locks, so no + // other thread/process can access the object. + + PAL_ERROR palErr = NO_ERROR; + + _ASSERT_MSG(CObjectType::OwnershipTracked == + GetObjectType()->GetOwnershipSemantics(), + "AssignOwnershipToThread called on a non-ownable " + "CSynchData [this=%p OwnershipSemantics=%u]\n", this, + GetObjectType()->GetOwnershipSemantics()); + + + if (0 < m_lOwnershipCount) + { + // + // Object already owned, incrementing ownership count + // + _ASSERT_MSG(0 == GetSignalCount(), + "Conflicting OwnershipCount and SignalCount values\n"); + + _ASSERT_MSG(pthrTarget == m_pOwnerThread && gPID == m_dwOwnerPid, + "Attempting to assign ownership of CSynchData %p to " + "thread {pid=%#x tid=%#x} while it is currently owned " + "by thread {pid=%#x tid=%#x}\n", this, + gPID, pthrTarget->GetThreadId(), + m_dwOwnerPid, m_pOwnerThread->GetThreadId()); + + m_lOwnershipCount++; + + TRACE("Incrementing ownership count for object with " + "SynchData %p owned by thread %#x [new count=%d]\n", + this, pthrTarget->GetThreadId(), m_lOwnershipCount); + } + else + { + // + // Acquiring currently not owned object + // + CPalSynchronizationManager * pSynchManager = + CPalSynchronizationManager::GetInstance(); + OwnedObjectsListNode * pooln; + + pooln = pSynchManager->CacheGetOwnedObjsListNode(pthrCurrent); + if (NULL == pooln) + { + ERROR("Out of memory while acquiring mutex ownership"); + // In this case we bail out. It will result in no + // thread being awakend, which may cause deadlock, + // but it is anyway better than corrupting the + // ownership list + palErr = ERROR_NOT_ENOUGH_MEMORY; + goto AOTT_exit; + } + + TRACE("Assigning ownable object with SynchData %p to " + "thread %#x\n", + this, pthrTarget->GetThreadId()); + + // Set ownership data + SetOwner(pthrTarget); + SetOwnershipListNode(pooln); + SetOwnershipCount(1); + SetAbandoned(false); + + // Add object to list of owned objs for current thread + pooln->pPalObjSynchData = this; + AddRef(); + pthrTarget->synchronizationInfo.AddObjectToOwnedList(pooln); + } + + AOTT_exit: + return palErr; + } + + /*++ + Method: + CSynchData::WaiterEnqueue + + Adds the WaitingThreadsListNode passed as argument at the end of the + list of WaitingThreadsListNode for the current object, representing + the threads waiting on the current object. The target SynchData is + assumed to be local to the current process + + Note: this method must be called while holding the local process + synchronization lock. + --*/ + void CSynchData::WaiterEnqueue(WaitingThreadsListNode * pwtlnNewNode, bool fPrioritize) + { + VALIDATEOBJECT(this); + VALIDATEOBJECT(pwtlnNewNode); + + _ASSERT_MSG(ProcessLocalObject == GetObjectDomain(), + "Trying to enqueue a WaitingThreadsListNode as local " + "on a shared object\n"); + _ASSERT_MSG(0 == (WTLN_FLAG_OWNER_OBJECT_IS_SHARED & pwtlnNewNode->dwFlags), + "Trying to add a WaitingThreadsListNode marked as shared " + "as it was a local one\n"); + + if (!fPrioritize) + { + // Enqueue normally to the end of the queue + WaitingThreadsListNode * pwtlnCurrLast = m_ptrWTLTail.ptr; + + pwtlnNewNode->ptrNext.ptr = NULL; + if (NULL == pwtlnCurrLast) + { + _ASSERT_MSG(NULL == m_ptrWTLHead.ptr, + "Corrupted waiting list on local CSynchData @ %p\n", + this); + + pwtlnNewNode->ptrPrev.ptr = NULL; + m_ptrWTLHead.ptr = pwtlnNewNode; + m_ptrWTLTail.ptr = pwtlnNewNode; + } + else + { + VALIDATEOBJECT(pwtlnCurrLast); + + pwtlnNewNode->ptrPrev.ptr = pwtlnCurrLast; + pwtlnCurrLast->ptrNext.ptr = pwtlnNewNode; + m_ptrWTLTail.ptr = pwtlnNewNode; + } + } + else + { + // The wait is prioritized, enqueue to the beginning of the queue + WaitingThreadsListNode * pwtlnCurrFirst = m_ptrWTLHead.ptr; + + pwtlnNewNode->ptrPrev.ptr = NULL; + if (NULL == pwtlnCurrFirst) + { + _ASSERT_MSG(NULL == m_ptrWTLTail.ptr, + "Corrupted waiting list on local CSynchData @ %p\n", + this); + + pwtlnNewNode->ptrNext.ptr = NULL; + m_ptrWTLHead.ptr = pwtlnNewNode; + m_ptrWTLTail.ptr = pwtlnNewNode; + } + else + { + VALIDATEOBJECT(pwtlnCurrFirst); + + pwtlnNewNode->ptrNext.ptr = pwtlnCurrFirst; + pwtlnCurrFirst->ptrPrev.ptr = pwtlnNewNode; + m_ptrWTLHead.ptr = pwtlnNewNode; + } + } + + m_ulcWaitingThreads += 1; + + return; + } + + /*++ + Method: + CSynchData::SharedWaiterEnqueue + + Adds the WaitingThreadsListNode passed as argument at the end of the + list of WaitingThreadsListNode for the current object, representing + the threads waiting on the current object. The target SynchData is + assumed to be shared among processes + + Note: this method must be called while holding both local and shared + synchronization locks. + --*/ + void CSynchData::SharedWaiterEnqueue(SharedID shridNewNode, bool fPrioritize) + { + VALIDATEOBJECT(this); + + _ASSERT_MSG(SharedObject == GetObjectDomain(), + "Trying to enqueue a WaitingThreadsListNode as shared " + "on a local object\n"); + + if (!fPrioritize) + { + // Enqueue normally to the end of the queue + SharedID shridCurrLast; + WaitingThreadsListNode * pwtlnCurrLast, * pwtlnNewNode; + + shridCurrLast = m_ptrWTLTail.shrid; + pwtlnCurrLast = SharedIDToTypePointer(WaitingThreadsListNode, shridCurrLast); + pwtlnNewNode = SharedIDToTypePointer(WaitingThreadsListNode, shridNewNode); + + _ASSERT_MSG(1 == (WTLN_FLAG_OWNER_OBJECT_IS_SHARED & pwtlnNewNode->dwFlags), + "Trying to add a WaitingThreadsListNode marked as local " + "as it was a shared one\n"); + + VALIDATEOBJECT(pwtlnNewNode); + + pwtlnNewNode->ptrNext.shrid = NULL; + if (NULL == pwtlnCurrLast) + { + _ASSERT_MSG(NULL == m_ptrWTLHead.shrid, + "Corrupted waiting list on shared CSynchData at " + "{shrid=%p, p=%p}\n", m_shridThis, this); + + pwtlnNewNode->ptrPrev.shrid = NULL; + m_ptrWTLHead.shrid = shridNewNode; + m_ptrWTLTail.shrid = shridNewNode; + } + else + { + VALIDATEOBJECT(pwtlnCurrLast); + + pwtlnNewNode->ptrPrev.shrid = shridCurrLast; + pwtlnCurrLast->ptrNext.shrid = shridNewNode; + m_ptrWTLTail.shrid = shridNewNode; + } + } + else + { + // The wait is prioritized, enqueue to the beginning of the queue + SharedID shridCurrFirst; + WaitingThreadsListNode * pwtlnCurrFirst, * pwtlnNewNode; + + shridCurrFirst = m_ptrWTLHead.shrid; + pwtlnCurrFirst = SharedIDToTypePointer(WaitingThreadsListNode, shridCurrFirst); + pwtlnNewNode = SharedIDToTypePointer(WaitingThreadsListNode, shridNewNode); + + _ASSERT_MSG(1 == (WTLN_FLAG_OWNER_OBJECT_IS_SHARED & pwtlnNewNode->dwFlags), + "Trying to add a WaitingThreadsListNode marked as local " + "as it was a shared one\n"); + + VALIDATEOBJECT(pwtlnNewNode); + + pwtlnNewNode->ptrPrev.shrid = NULL; + if (NULL == pwtlnCurrFirst) + { + _ASSERT_MSG(NULL == m_ptrWTLTail.shrid, + "Corrupted waiting list on shared CSynchData at " + "{shrid=%p, p=%p}\n", m_shridThis, this); + + pwtlnNewNode->ptrNext.shrid = NULL; + m_ptrWTLHead.shrid = shridNewNode; + m_ptrWTLTail.shrid = shridNewNode; + } + else + { + VALIDATEOBJECT(pwtlnCurrFirst); + + pwtlnNewNode->ptrNext.shrid = shridCurrFirst; + pwtlnCurrFirst->ptrPrev.shrid = shridNewNode; + m_ptrWTLHead.shrid = shridNewNode; + } + } + + m_ulcWaitingThreads += 1; + + return; + } + +#ifdef SYNCH_OBJECT_VALIDATION + CSynchData::~CSynchData() + { + ValidateObject(true); + InvalidateObject(); + } + /*++ + Method: + CSynchData::ValidateObject + + Makes sure that the signature at the beginning and at the end of the + current object are those of a currently alive object (i.e. the object + has been constructed and does not appear to have been overwritten) + --*/ + void CSynchData::ValidateObject(bool fDestructor) + { + TRACE("Verifying in-use CSynchData @ %p\n", this); + _ASSERT_MSG(HeadSignature == m_dwDebugHeadSignature, + "CSynchData header signature corruption [p=%p]", this); + _ASSERT_MSG(TailSignature == m_dwDebugTailSignature, + "CSynchData trailer signature corruption [p=%p]", this); + _ASSERT_MSG((fDestructor && 0 == m_lRefCount) || + (!fDestructor && 0 < m_lRefCount), + "CSynchData %p with NULL reference count\n", this); + } + /*++ + Method: + CSynchData::ValidateEmptyObject + + Makes sure that the signature at the beginning and at the end of the + current object are not those of a currently alive object (i.e. the + object has not yet been constructed or it has alread been destructed) + --*/ + void CSynchData::ValidateEmptyObject() + { + TRACE("Verifying empty CSynchData @ %p\n", this); + _ASSERT_MSG(HeadSignature != m_dwDebugHeadSignature, + "CSynchData header previously signed [p=%p]", this); + _ASSERT_MSG(TailSignature != m_dwDebugTailSignature, + "CSynchData trailer previously signed [p=%p]", this); + } + /*++ + Method: + CSynchData::InvalidateObject + + Turns signatures from alive object to destructed object + --*/ + void CSynchData::InvalidateObject() + { + TRACE("Invalidating CSynchData @ %p\n", this); + m_dwDebugHeadSignature = EmptySignature; + m_dwDebugTailSignature = EmptySignature; + } +#endif // SYNCH_OBJECT_VALIDATION +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/synchmanager.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/synchmanager.cpp new file mode 100644 index 0000000..9d868c0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/synchmanager.cpp @@ -0,0 +1,4624 @@ +// 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: + + synchmanager.cpp + +Abstract: + Implementation of Synchronization Manager and related objects + + + +--*/ + +#include "pal/dbgmsg.h" + +SET_DEFAULT_DEBUG_CHANNEL(SYNC); // some headers have code with asserts, so do this first + +#include "synchmanager.hpp" +#include "pal/file.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if HAVE_POLL +#include +#else +#include "pal/fakepoll.h" +#endif // HAVE_POLL + +#include + +const int CorUnix::CThreadSynchronizationInfo::PendingSignalingsArraySize; + +// We use the synchronization manager's worker thread to handle +// process termination requests. It does so by calling the +// registered handler function. +PTERMINATION_REQUEST_HANDLER g_terminationRequestHandler = NULL; + +// Set the handler for process termination requests. +VOID PALAPI PAL_SetTerminationRequestHandler( + IN PTERMINATION_REQUEST_HANDLER terminationHandler) +{ + g_terminationRequestHandler = terminationHandler; +} + +namespace CorUnix +{ + ///////////////////////////////// + // // + // WaitingThreadsListNode // + // // + ///////////////////////////////// +#ifdef SYNCH_OBJECT_VALIDATION + _WaitingThreadsListNode::_WaitingThreadsListNode() + { + ValidateEmptyObject(); + dwDebugHeadSignature = HeadSignature; + dwDebugTailSignature = TailSignature; + } + _WaitingThreadsListNode::~_WaitingThreadsListNode() + { + ValidateObject(); + InvalidateObject(); + } + void _WaitingThreadsListNode::ValidateObject() + { + TRACE("Verifying WaitingThreadsListNode @ %p\n", this); + _ASSERT_MSG(HeadSignature == dwDebugHeadSignature, + "WaitingThreadsListNode header signature corruption [p=%p]", + this); + _ASSERT_MSG(TailSignature == dwDebugTailSignature, + "WaitingThreadsListNode trailer signature corruption [p=%p]", + this); + } + void _WaitingThreadsListNode::ValidateEmptyObject() + { + _ASSERT_MSG(HeadSignature != dwDebugHeadSignature, + "WaitingThreadsListNode header previously signed [p=%p]", + this); + _ASSERT_MSG(TailSignature != dwDebugTailSignature, + "WaitingThreadsListNode trailer previously signed [p=%p]", + this); + } + void _WaitingThreadsListNode::InvalidateObject() + { + TRACE("Invalidating WaitingThreadsListNode @ %p\n", this); + dwDebugHeadSignature = EmptySignature; + dwDebugTailSignature = EmptySignature; + } +#endif // SYNCH_OBJECT_VALIDATION + + ////////////////////////////// + // // + // CPalSynchMgrController // + // // + ////////////////////////////// + + /*++ + Method: + CPalSynchMgrController::CreatePalSynchronizationManager + + Creates the Synchronization Manager. It must be called once per process. + --*/ + IPalSynchronizationManager * CPalSynchMgrController::CreatePalSynchronizationManager() + { + return CPalSynchronizationManager::CreatePalSynchronizationManager(); + }; + + /*++ + Method: + CPalSynchMgrController::StartWorker + + Starts the Synchronization Manager's Worker Thread + --*/ + PAL_ERROR CPalSynchMgrController::StartWorker( + CPalThread * pthrCurrent) + { + return CPalSynchronizationManager::StartWorker(pthrCurrent); + } + + /*++ + Method: + CPalSynchMgrController::PrepareForShutdown + + This method performs the part of Synchronization Manager's shutdown that + needs to be carried out when core PAL subsystems are still active + --*/ + PAL_ERROR CPalSynchMgrController::PrepareForShutdown() + { + return CPalSynchronizationManager::PrepareForShutdown(); + } + + ////////////////////////////////// + // // + // CPalSynchronizationManager // + // // + ////////////////////////////////// + + IPalSynchronizationManager * g_pSynchronizationManager = NULL; + + CPalSynchronizationManager * CPalSynchronizationManager::s_pObjSynchMgr = NULL; + Volatile CPalSynchronizationManager::s_lInitStatus = SynchMgrStatusIdle; + CRITICAL_SECTION CPalSynchronizationManager::s_csSynchProcessLock; + CRITICAL_SECTION CPalSynchronizationManager::s_csMonitoredProcessesLock; + + CPalSynchronizationManager::CPalSynchronizationManager() + : m_dwWorkerThreadTid(0), + m_pipoThread(NULL), + m_pthrWorker(NULL), + m_iProcessPipeRead(-1), + m_iProcessPipeWrite(-1), + m_pmplnMonitoredProcesses(NULL), + m_lMonitoredProcessesCount(0), + m_pmplnExitedNodes(NULL), + m_cacheWaitCtrlrs(CtrlrsCacheMaxSize), + m_cacheStateCtrlrs(CtrlrsCacheMaxSize), + m_cacheSynchData(SynchDataCacheMaxSize), + m_cacheSHRSynchData(SynchDataCacheMaxSize), + m_cacheWTListNodes(WTListNodeCacheMaxSize), + m_cacheSHRWTListNodes(WTListNodeCacheMaxSize), + m_cacheThreadApcInfoNodes(ApcInfoNodeCacheMaxSize), + m_cacheOwnedObjectsListNodes(OwnedObjectsListCacheMaxSize) + { +#if HAVE_KQUEUE && !HAVE_BROKEN_FIFO_KEVENT + m_iKQueue = -1; + // Initialize data to 0 and flags to EV_EOF + EV_SET(&m_keProcessPipeEvent, 0, 0, EV_EOF, 0, 0, 0); +#endif // HAVE_KQUEUE + } + + CPalSynchronizationManager::~CPalSynchronizationManager() + { + } + + /*++ + Method: + CPalSynchronizationManager::BlockThread + + Called by a thread to go to sleep for a wait or a sleep + + NOTE: This method must must be called without holding any + synchronization lock (as well as other locks) + --*/ + PAL_ERROR CPalSynchronizationManager::BlockThread( + CPalThread *pthrCurrent, + DWORD dwTimeout, + bool fAlertable, + bool fIsSleep, + ThreadWakeupReason *ptwrWakeupReason, + DWORD * pdwSignaledObject) + { + PAL_ERROR palErr = NO_ERROR; + ThreadWakeupReason twrWakeupReason = WaitFailed; + DWORD * pdwWaitState; + DWORD dwWaitState = 0; + DWORD dwSigObjIdx = 0; + bool fRaceAlerted = false; + bool fEarlyDeath = false; + + pdwWaitState = SharedIDToTypePointer(DWORD, + pthrCurrent->synchronizationInfo.m_shridWaitAwakened); + + _ASSERT_MSG(NULL != pdwWaitState, + "Got NULL pdwWaitState from m_shridWaitAwakened=%p\n", + (VOID *)pthrCurrent->synchronizationInfo.m_shridWaitAwakened); + + if (fIsSleep) + { + // If fIsSleep is true we are being called by Sleep/SleepEx + // and we need to switch the wait state to TWS_WAITING or + // TWS_ALERTABLE (according to fAlertable) + + if (fAlertable) + { + // If we are in alertable mode we need to grab the lock to + // make sure that no APC is queued right before the + // InterlockedCompareExchange. + // If there are APCs queued at this time, no native wakeup + // will be posted, so we need to skip the native wait + + // Lock + AcquireLocalSynchLock(pthrCurrent); + AcquireSharedSynchLock(pthrCurrent); + + if (AreAPCsPending(pthrCurrent)) + { + // APCs have been queued when the thread wait status was + // still TWS_ACTIVE, therefore the queueing thread will not + // post any native wakeup: we need to skip the actual + // native wait + fRaceAlerted = true; + } + } + + if (!fRaceAlerted) + { + // Setting the thread in wait state + dwWaitState = (DWORD)(fAlertable ? TWS_ALERTABLE : TWS_WAITING); + + TRACE("Switching my wait state [%p] from TWS_ACTIVE to %u [current *pdwWaitState=%u]\n", + pdwWaitState, dwWaitState, *pdwWaitState); + + dwWaitState = InterlockedCompareExchange((LONG *)pdwWaitState, + dwWaitState, + TWS_ACTIVE); + + if ((DWORD)TWS_ACTIVE != dwWaitState) + { + if (fAlertable) + { + // Unlock + ReleaseSharedSynchLock(pthrCurrent); + ReleaseLocalSynchLock(pthrCurrent); + } + + if ((DWORD)TWS_EARLYDEATH == dwWaitState) + { + // Process is terminating, this thread will soon be suspended (by SuspendOtherThreads). + WARN("Thread is about to get suspended by TerminateProcess\n"); + + fEarlyDeath = true; + palErr = WAIT_FAILED; + } + else + { + ASSERT("Unexpected thread wait state %u\n", dwWaitState); + palErr = ERROR_INTERNAL_ERROR; + } + + goto BT_exit; + } + } + + if (fAlertable) + { + // Unlock + ReleaseSharedSynchLock(pthrCurrent); + ReleaseLocalSynchLock(pthrCurrent); + } + } + + if (fRaceAlerted) + { + twrWakeupReason = Alerted; + } + else + { + TRACE("Current thread is about to block for waiting\n"); + + palErr = ThreadNativeWait( + &pthrCurrent->synchronizationInfo.m_tnwdNativeData, + dwTimeout, + &twrWakeupReason, + &dwSigObjIdx); + + if (NO_ERROR != palErr) + { + ERROR("ThreadNativeWait() failed [palErr=%d]\n", palErr); + twrWakeupReason = WaitFailed; + goto BT_exit; + } + + TRACE("ThreadNativeWait returned {WakeupReason=%u " + "dwSigObjIdx=%u}\n", twrWakeupReason, dwSigObjIdx); + } + + if (WaitTimeout == twrWakeupReason) + { + // timeout reached. set wait state back to 'active' + dwWaitState = (DWORD)(fAlertable ? TWS_ALERTABLE : TWS_WAITING); + + TRACE("Current thread awakened for timeout: switching wait " + "state [%p] from %u to TWS_ACTIVE [current *pdwWaitState=%u]\n", + pdwWaitState, dwWaitState, *pdwWaitState); + + DWORD dwOldWaitState = InterlockedCompareExchange( + (LONG *)pdwWaitState, + TWS_ACTIVE, (LONG)dwWaitState); + + switch (dwOldWaitState) + { + case TWS_ACTIVE: + // We were already ACTIVE; someone decided to wake up this + // thread sometime between the moment the native wait + // timed out and here. Since the signaling side succeeded + // its InterlockedCompareExchange, it will signal the + // condition/predicate pair (we just raced overtaking it); + // therefore we need to clear the condition/predicate + // by waiting on it one more time. + // That will also cause this method to report a signal + // rather than a timeout. + // In the remote signaling scenario, this second wait + // also makes sure that the shared id passed over the + // process pipe is valid for the entire duration of time + // in which the worker thread deals with it + TRACE("Current thread already ACTIVE: a signaling raced " + "with the timeout: re-waiting natively to clear the " + "predicate\n"); + + palErr = ThreadNativeWait( + &pthrCurrent->synchronizationInfo.m_tnwdNativeData, + SecondNativeWaitTimeout, + &twrWakeupReason, + &dwSigObjIdx); + + if (NO_ERROR != palErr) + { + ERROR("ThreadNativeWait() failed [palErr=%d]\n", + palErr); + twrWakeupReason = WaitFailed; + } + + if (WaitTimeout == twrWakeupReason) + { + ERROR("Second native wait timed out\n"); + } + + break; + case TWS_EARLYDEATH: + // Thread is about to be suspended by TerminateProcess. + // Anyway, if the wait timed out, we still want to + // (try to) unregister the wait (especially if it + // involves shared objects) + WARN("Thread is about to be suspended by TerminateProcess\n"); + fEarlyDeath = true; + palErr = WAIT_FAILED; + break; + case TWS_WAITING: + case TWS_ALERTABLE: + default: + _ASSERT_MSG(dwOldWaitState == dwWaitState, + "Unexpected wait status: actual=%u, expected=%u\n", + dwOldWaitState, dwWaitState); + break; + } + } + + switch (twrWakeupReason) + { + case WaitTimeout: + { + // Awakened for timeout: we need to unregister the wait + ThreadWaitInfo * ptwiWaitInfo; + + TRACE("Current thread awakened for timeout: unregistering the wait\n"); + + // Local lock + AcquireLocalSynchLock(pthrCurrent); + + ptwiWaitInfo = GetThreadWaitInfo(pthrCurrent); + + // Unregister the wait + // Note: UnRegisterWait will take care of grabbing the shared synch lock, if needed. + UnRegisterWait(pthrCurrent, ptwiWaitInfo, false); + + // Unlock + ReleaseLocalSynchLock(pthrCurrent); + + break; + } + case WaitSucceeded: + case MutexAbondoned: + *pdwSignaledObject = dwSigObjIdx; + break; + default: + // 'Alerted' and 'WaitFailed' go through this case + break; + } + + // Set the returned wakeup reason + *ptwrWakeupReason = twrWakeupReason; + + TRACE("Current thread is now active [WakeupReason=%u SigObjIdx=%u]\n", + twrWakeupReason, dwSigObjIdx); + + _ASSERT_MSG(TWS_ACTIVE == VolatileLoad(pdwWaitState) || + TWS_EARLYDEATH == VolatileLoad(pdwWaitState), + "Unexpected thread wait state %u\n", VolatileLoad(pdwWaitState)); + + BT_exit: + if (fEarlyDeath) + { + ThreadPrepareForShutdown(); + } + + return palErr; + } + + PAL_ERROR CPalSynchronizationManager::ThreadNativeWait( + ThreadNativeWaitData * ptnwdNativeWaitData, + DWORD dwTimeout, + ThreadWakeupReason * ptwrWakeupReason, + DWORD * pdwSignaledObject) + { + PAL_ERROR palErr = NO_ERROR; + int iRet, iWaitRet = 0; + struct timespec tsAbsTmo; + + TRACE("ThreadNativeWait(ptnwdNativeWaitData=%p, dwTimeout=%u, ...)\n", + ptnwdNativeWaitData, dwTimeout); + + if (dwTimeout != INFINITE) + { + // Calculate absolute timeout + palErr = GetAbsoluteTimeout(dwTimeout, &tsAbsTmo, /*fPreferMonotonicClock*/ TRUE); + if (NO_ERROR != palErr) + { + ERROR("Failed to convert timeout to absolute timeout\n"); + goto TNW_exit; + } + } + + // Lock the mutex + iRet = pthread_mutex_lock(&ptnwdNativeWaitData->mutex); + if (0 != iRet) + { + ERROR("Internal Error: cannot lock mutex\n"); + palErr = ERROR_INTERNAL_ERROR; + *ptwrWakeupReason = WaitFailed; + goto TNW_exit; + } + + while (FALSE == ptnwdNativeWaitData->iPred) + { + if (INFINITE == dwTimeout) + { + iWaitRet = pthread_cond_wait(&ptnwdNativeWaitData->cond, + &ptnwdNativeWaitData->mutex); + } + else + { + iWaitRet = pthread_cond_timedwait(&ptnwdNativeWaitData->cond, + &ptnwdNativeWaitData->mutex, + &tsAbsTmo); + } + + if (ETIMEDOUT == iWaitRet) + { + _ASSERT_MSG(INFINITE != dwTimeout, + "Got ETIMEDOUT despite timeout being INFINITE\n"); + break; + } + else if (0 != iWaitRet) + { + ERROR("pthread_cond_%swait returned %d [errno=%d (%s)]\n", + (INFINITE == dwTimeout) ? "" : "timed", + iWaitRet, errno, strerror(errno)); + palErr = ERROR_INTERNAL_ERROR; + break; + } + } + + // Reset the predicate + if (0 == iWaitRet) + { + // We don't want to reset the predicate if pthread_cond_timedwait + // timed out racing with a pthread_cond_signal. When + // pthread_cond_timedwait times out, it needs to grab the mutex + // before returning. At timeout time, it may happen that the + // signaling thread just grabbed the mutex, but it hasn't called + // pthread_cond_signal yet. In this scenario pthread_cond_timedwait + // will have to wait for the signaling side to release the mutex. + // As a result it will return with error timeout, but the predicate + // will be set. Since pthread_cond_timedwait timed out, the + // predicate value is intended for the next signal. In case of a + // object signaling racing with a wait timeout this predicate value + // will be picked up by the 'second native wait' (see comments in + // BlockThread). + + ptnwdNativeWaitData->iPred = FALSE; + } + + // Unlock the mutex + iRet = pthread_mutex_unlock(&ptnwdNativeWaitData->mutex); + if (0 != iRet) + { + ERROR("Cannot unlock mutex [err=%d]\n", iRet); + palErr = ERROR_INTERNAL_ERROR; + goto TNW_exit; + } + + _ASSERT_MSG(ETIMEDOUT != iRet || INFINITE != dwTimeout, "Got timeout return code with INFINITE timeout\n"); + + if (0 == iWaitRet) + { + *ptwrWakeupReason = ptnwdNativeWaitData->twrWakeupReason; + *pdwSignaledObject = ptnwdNativeWaitData->dwObjectIndex; + } + else if (ETIMEDOUT == iWaitRet) + { + *ptwrWakeupReason = WaitTimeout; + } + + TNW_exit: + TRACE("ThreadNativeWait: returning %u [WakeupReason=%u]\n", palErr, *ptwrWakeupReason); + return palErr; + } + + /*++ + Method: + CPalSynchronizationManager::AbandonObjectsOwnedByThread + + This method is called by a thread at thread-exit time to abandon + any currently owned waitable object (mutexes). If pthrTarget is + different from pthrCurrent, AbandonObjectsOwnedByThread assumes + to be called whether by TerminateThread or at shutdown time. See + comments below for more details + --*/ + PAL_ERROR CPalSynchronizationManager::AbandonObjectsOwnedByThread( + CPalThread * pthrCurrent, + CPalThread * pthrTarget) + { + PAL_ERROR palErr = NO_ERROR; + OwnedObjectsListNode * poolnItem; + bool fSharedSynchLock = false; + CThreadSynchronizationInfo * pSynchInfo = &pthrTarget->synchronizationInfo; + CPalSynchronizationManager * pSynchManager = GetInstance(); + + // Local lock + AcquireLocalSynchLock(pthrCurrent); + + // Abandon owned objects + while (NULL != (poolnItem = pSynchInfo->RemoveFirstObjectFromOwnedList())) + { + CSynchData * psdSynchData = poolnItem->pPalObjSynchData; + + _ASSERT_MSG(NULL != psdSynchData, + "NULL psdSynchData pointer in ownership list node\n"); + + VALIDATEOBJECT(psdSynchData); + + TRACE("Abandoning object with SynchData at %p\n", psdSynchData); + + if (!fSharedSynchLock && + (SharedObject == psdSynchData->GetObjectDomain())) + { + AcquireSharedSynchLock(pthrCurrent); + fSharedSynchLock = true; + } + + // Reset ownership data + psdSynchData->ResetOwnership(); + + // Set abandoned status; in case there is a thread to be released: + // - if the thread is local, ReleaseFirstWaiter will reset the + // abandoned status + // - if the thread is remote, the remote worker thread will use + // the value and reset it + psdSynchData->SetAbandoned(true); + + // Signal the object and trigger thread awakening + psdSynchData->Signal(pthrCurrent, 1, false); + + // Release reference to to SynchData + psdSynchData->Release(pthrCurrent); + + // Return node to the cache + pSynchManager->m_cacheOwnedObjectsListNodes.Add(pthrCurrent, poolnItem); + } + + // Abandon owned named mutexes + while (true) + { + NamedMutexProcessData *processData = pSynchInfo->RemoveFirstOwnedNamedMutex(); + if (processData == nullptr) + { + break; + } + processData->Abandon(); + } + + if (pthrTarget != pthrCurrent) + { + // If the target thead is not the current one, we are being called + // at shutdown time, right before the target thread is suspended, + // or anyway the target thread is being terminated. + // In this case we switch its wait state to TWS_EARLYDEATH so that, + // if the thread is currently waiting/sleeping and it wakes up + // before shutdown code manage to suspend it, it will be rerouted + // to ThreadPrepareForShutdown (that will be done without holding + // any internal lock, in a way to accomodate shutdown time thread + // suspension). + // At this time we also unregister the wait, so no dummy nodes are + // left around on waiting objects. + // The TWS_EARLYDEATH wait-state will also prevent the thread from + // successfully registering for a possible new wait in the same + // time window. + LONG lTWState; + DWORD * pdwWaitState; + + pdwWaitState = SharedIDToTypePointer(DWORD, pthrTarget->synchronizationInfo.m_shridWaitAwakened); + lTWState = InterlockedExchange((LONG *)pdwWaitState, TWS_EARLYDEATH); + + if (( ((LONG)TWS_WAITING == lTWState) || ((LONG)TWS_ALERTABLE == lTWState) ) && + (0 < pSynchInfo->m_twiWaitInfo.lObjCount)) + { + // Unregister the wait + // Note: UnRegisterWait will take care of grabbing the shared synch lock, if needed. + UnRegisterWait(pthrCurrent, &pSynchInfo->m_twiWaitInfo, fSharedSynchLock); + } + } + + // Unlock + if (fSharedSynchLock) + { + ReleaseSharedSynchLock(pthrCurrent); + fSharedSynchLock = false; + } + + ReleaseLocalSynchLock(pthrCurrent); + DiscardAllPendingAPCs(pthrCurrent, pthrTarget); + + return palErr; + } + + /*++ + Method: + CPalSynchronizationManager::GetSynchWaitControllersForObjects + + Returns an array of wait controllers, one for each of the objects + in rgObjects + --*/ + PAL_ERROR CPalSynchronizationManager::GetSynchWaitControllersForObjects( + CPalThread *pthrCurrent, + IPalObject *rgObjects[], + DWORD dwObjectCount, + ISynchWaitController * rgControllers[]) + { + return GetSynchControllersForObjects(pthrCurrent, + rgObjects, + dwObjectCount, + (void **)rgControllers, + CSynchControllerBase::WaitController); + } + + /*++ + Method: + CPalSynchronizationManager::GetSynchStateControllersForObjects + + Returns an array of state controllers, one for each of the objects + in rgObjects + --*/ + PAL_ERROR CPalSynchronizationManager::GetSynchStateControllersForObjects( + CPalThread *pthrCurrent, + IPalObject *rgObjects[], + DWORD dwObjectCount, + ISynchStateController *rgControllers[]) + { + return GetSynchControllersForObjects(pthrCurrent, + rgObjects, + dwObjectCount, + (void **)rgControllers, + CSynchControllerBase::StateController); + } + + /*++ + Method: + CPalSynchronizationManager::GetSynchControllersForObjects + + Internal common implementation for GetSynchWaitControllersForObjects and + GetSynchStateControllersForObjects + --*/ + PAL_ERROR CPalSynchronizationManager::GetSynchControllersForObjects( + CPalThread *pthrCurrent, + IPalObject *rgObjects[], + DWORD dwObjectCount, + void ** ppvControllers, + CSynchControllerBase::ControllerType ctCtrlrType) + { + PAL_ERROR palErr = NO_ERROR; + unsigned int uIdx, uCount = 0, uSharedObjectCount = 0; + WaitDomain wdWaitDomain = LocalWait; + CObjectType * potObjectType = NULL; + unsigned int uErrCleanupIdxFirstNotInitializedCtrlr = 0; + unsigned int uErrCleanupIdxLastCtrlr = 0; + bool fLocalSynchLock = false; + + union + { + CSynchWaitController * pWaitCtrlrs[MAXIMUM_WAIT_OBJECTS]; + CSynchStateController * pStateCtrlrs[MAXIMUM_WAIT_OBJECTS]; + } Ctrlrs; + + if ((dwObjectCount <= 0) || (dwObjectCount > MAXIMUM_WAIT_OBJECTS)) + { + palErr = ERROR_INVALID_PARAMETER; + goto GSCFO_exit; + } + + if (CSynchControllerBase::WaitController == ctCtrlrType) + { + uCount = (unsigned int)m_cacheWaitCtrlrs.Get(pthrCurrent, + dwObjectCount, + Ctrlrs.pWaitCtrlrs); + } + else + { + uCount = (unsigned int)m_cacheStateCtrlrs.Get(pthrCurrent, + dwObjectCount, + Ctrlrs.pStateCtrlrs); + } + + if (uCount < dwObjectCount) + { + // We got less controllers (uCount) than we asked for (dwObjectCount), + // probably because of low memory. + // None of these controllers is initialized, so they must be all + // returned directly to the cache + uErrCleanupIdxLastCtrlr = uCount; + + palErr = ERROR_NOT_ENOUGH_MEMORY; + goto GSCFO_error_cleanup; + } + + // + // We need to acquire the local synch lock before evaluating object domains + // + AcquireLocalSynchLock(pthrCurrent); + fLocalSynchLock = true; + + for (uIdx=0; uIdxGetObjectDomain()) + { + ++uSharedObjectCount; + } + + if (uSharedObjectCount > 0 && uSharedObjectCount <= uIdx) + { + wdWaitDomain = MixedWait; + break; + } + } + + if (dwObjectCount == uSharedObjectCount) + { + wdWaitDomain = SharedWait; + } + + for (uIdx=0;uIdxGetObjectDomain(); + + palErr = rgObjects[uIdx]->GetObjectSynchData((void **)&pvSData); + if (NO_ERROR != palErr) + { + break; + } + + psdSynchData = (SharedObject == odObjectDomain) ? SharedIDToTypePointer( + CSynchData, reinterpret_cast(pvSData)) : + static_cast(pvSData); + + VALIDATEOBJECT(psdSynchData); + + potObjectType = rgObjects[uIdx]->GetObjectType(); + + if (CSynchControllerBase::WaitController == ctCtrlrType) + { + Ctrlrs.pWaitCtrlrs[uIdx]->Init(pthrCurrent, + ctCtrlrType, + odObjectDomain, + potObjectType, + psdSynchData, + wdWaitDomain); + } + else + { + Ctrlrs.pStateCtrlrs[uIdx]->Init(pthrCurrent, + ctCtrlrType, + odObjectDomain, + potObjectType, + psdSynchData, + wdWaitDomain); + } + + if (CSynchControllerBase::WaitController == ctCtrlrType && + otiProcess == potObjectType->GetId()) + { + CProcProcessLocalData * pProcLocData; + IDataLock * pDataLock; + + palErr = rgObjects[uIdx]->GetProcessLocalData( + pthrCurrent, + ReadLock, + &pDataLock, + (void **)&pProcLocData); + + if (NO_ERROR != palErr) + { + // In case of failure here, bail out of the loop, but + // keep track (by incrementing the counter 'uIdx') of the + // fact that this controller has already being initialized + // and therefore need to be Release'd rather than just + // returned to the cache + uIdx++; + break; + } + + Ctrlrs.pWaitCtrlrs[uIdx]->SetProcessData(rgObjects[uIdx], pProcLocData); + pDataLock->ReleaseLock(pthrCurrent, false); + } + } + if (NO_ERROR != palErr) + { + // An error occurred while initializing the (uIdx+1)-th controller, + // i.e. the one at index uIdx; therefore the first uIdx controllers + // must be Release'd, while the remaining uCount-uIdx must be returned + // directly to the cache. + uErrCleanupIdxFirstNotInitializedCtrlr = uIdx; + uErrCleanupIdxLastCtrlr = dwObjectCount; + + goto GSCFO_error_cleanup; + } + + // Succeeded + if (CSynchControllerBase::WaitController == ctCtrlrType) + { + for (uIdx=0;uIdx( + static_cast(Ctrlrs.pWaitCtrlrs[uIdx])); + } + } + else + { + for (uIdx=0;uIdx( + static_cast(Ctrlrs.pStateCtrlrs[uIdx])); + } + } + + // Succeeded: skip error cleanup + goto GSCFO_exit; + + GSCFO_error_cleanup: + if (CSynchControllerBase::WaitController == ctCtrlrType) + { + // Release already initialized wait controllers + for (uIdx=0; uIdxRelease(); + } + + // Return to the cache not yet initialized wait controllers + for (uIdx=uErrCleanupIdxFirstNotInitializedCtrlr; uIdxRelease(); + } + + // Return to the cache not yet initialized state controllers + for (uIdx=uErrCleanupIdxFirstNotInitializedCtrlr; uIdxSetWTLHeadShrPtr(NULL); + psdSynchData->SetWTLTailShrPtr(NULL); + + // Store shared pointer to this object + psdSynchData->SetSharedThis(shridSynchData); + + *ppvSynchData = reinterpret_cast(shridSynchData); + } + else + { + psdSynchData = m_cacheSynchData.Get(pthrCurrent); + if (NULL == psdSynchData) + { + ERROR("Unable to allocate memory\n"); + return ERROR_NOT_ENOUGH_MEMORY; + } + + // Initialize waiting list pointers + psdSynchData->SetWTLHeadPtr(NULL); + psdSynchData->SetWTLTailPtr(NULL); + + // Set shared this pointer to NULL + psdSynchData->SetSharedThis(NULL); + + *ppvSynchData = static_cast(psdSynchData); + } + + // Initialize object domain and object type; + psdSynchData->SetObjectDomain(odObjectDomain); + psdSynchData->SetObjectType(potObjectType); + + return palErr; + } + + /*++ + Method: + CPalSynchronizationManager::FreeObjectSynchData + + Called to return a no longer used SynchData to the Synchronization Manager. + The SynchData may actually survive this call, since it is a ref-counted + object and at FreeObjectSynchData time it may still be used from within + the Synchronization Manager itself (e.g. the worker thread). + --*/ + void CPalSynchronizationManager::FreeObjectSynchData( + CObjectType *potObjectType, + ObjectDomain odObjectDomain, + VOID *pvSynchData) + { + CSynchData * psdSynchData; + CPalThread * pthrCurrent = InternalGetCurrentThread(); + + if (odObjectDomain == SharedObject) + { + psdSynchData = SharedIDToTypePointer(CSynchData, + reinterpret_cast(pvSynchData)); + + if (NULL == psdSynchData) + { + ASSERT("Bad shared memory pointer\n"); + return; + } + } + else + { + psdSynchData = static_cast(pvSynchData); + } + + psdSynchData->Release(pthrCurrent); + } + + /*++ + Method: + CPalSynchronizationManager::CreateSynchStateController + + Creates a state controller for the given object + --*/ + PAL_ERROR CPalSynchronizationManager::CreateSynchStateController( + CPalThread *pthrCurrent, + CObjectType *potObjectType, + VOID *pvSynchData, + ObjectDomain odObjectDomain, + ISynchStateController **ppStateController) + { + PAL_ERROR palErr = NO_ERROR; + CSynchStateController * pCtrlr = NULL; + WaitDomain wdWaitDomain = (SharedObject == odObjectDomain) ? SharedWait : LocalWait; + CSynchData * psdSynchData; + + psdSynchData = (SharedObject == odObjectDomain) ? SharedIDToTypePointer(CSynchData, reinterpret_cast(pvSynchData)) + : static_cast(pvSynchData); + + VALIDATEOBJECT(psdSynchData); + + pCtrlr = m_cacheStateCtrlrs.Get(pthrCurrent); + if (NULL == pCtrlr) + { + return ERROR_NOT_ENOUGH_MEMORY; + } + + pCtrlr->Init(pthrCurrent, + CSynchControllerBase::StateController, + odObjectDomain, + potObjectType, + psdSynchData, + wdWaitDomain); + + // Succeeded + *ppStateController = (ISynchStateController *)pCtrlr; + + if (NO_ERROR != palErr) + { + m_cacheStateCtrlrs.Add(pthrCurrent, pCtrlr); + } + + return palErr; + } + + /*++ + Method: + CPalSynchronizationManager::CreateSynchWaitController + + Creates a wait controller for the given object + --*/ + PAL_ERROR CPalSynchronizationManager::CreateSynchWaitController( + CPalThread *pthrCurrent, + CObjectType *potObjectType, + VOID *pvSynchData, + ObjectDomain odObjectDomain, + ISynchWaitController **ppWaitController) + { + CSynchWaitController * pCtrlr = NULL; + WaitDomain wdWaitDomain = (SharedObject == odObjectDomain) ? SharedWait : LocalWait; + CSynchData * psdSynchData; + + psdSynchData = (SharedObject == odObjectDomain) ? SharedIDToTypePointer( + CSynchData, reinterpret_cast(pvSynchData)) : + static_cast(pvSynchData); + + VALIDATEOBJECT(psdSynchData); + + pCtrlr = m_cacheWaitCtrlrs.Get(pthrCurrent); + if (NULL == pCtrlr) + { + return ERROR_NOT_ENOUGH_MEMORY; + } + + pCtrlr->Init(pthrCurrent, + CSynchControllerBase::WaitController, + odObjectDomain, + potObjectType, + psdSynchData, + wdWaitDomain); + + // Succeeded + *ppWaitController = (ISynchWaitController *)pCtrlr; + + return NO_ERROR; + } + + /*++ + Method: + CPalSynchronizationManager::QueueUserAPC + + Internal implementation of QueueUserAPC + --*/ + PAL_ERROR CPalSynchronizationManager::QueueUserAPC(CPalThread * pthrCurrent, + CPalThread * pthrTarget, + PAPCFUNC pfnAPC, + ULONG_PTR uptrData) + { + PAL_ERROR palErr = NO_ERROR; + ThreadApcInfoNode * ptainNode = NULL; + DWORD dwWaitState; + DWORD * pdwWaitState; + ThreadWaitInfo * pTargetTWInfo = GetThreadWaitInfo(pthrTarget); + bool fLocalSynchLock = false; + bool fSharedSynchLock = false; + bool fThreadLock = false; + + ptainNode = m_cacheThreadApcInfoNodes.Get(pthrCurrent); + if (NULL == ptainNode) + { + ERROR("No memory for new APCs linked list entry\n"); + palErr = ERROR_NOT_ENOUGH_MEMORY; + goto QUAPC_exit; + } + + ptainNode->pfnAPC = pfnAPC; + ptainNode->pAPCData = uptrData; + ptainNode->pNext = NULL; + + AcquireLocalSynchLock(pthrCurrent); + fLocalSynchLock = true; + + if (LocalWait != pTargetTWInfo->wdWaitDomain) + { + AcquireSharedSynchLock(pthrCurrent); + fSharedSynchLock = true; + } + + pthrTarget->Lock(pthrCurrent); + fThreadLock = true; + + if (TS_DONE == pthrTarget->synchronizationInfo.GetThreadState()) + { + ERROR("Thread %#x has terminated; can't queue an APC on it\n", + pthrTarget->GetThreadId()); + palErr = ERROR_INVALID_PARAMETER; + goto QUAPC_exit; + } + pdwWaitState = SharedIDToTypePointer(DWORD, + pthrTarget->synchronizationInfo.m_shridWaitAwakened); + if (TWS_EARLYDEATH == VolatileLoad(pdwWaitState)) + { + ERROR("Thread %#x is about to be suspended for process shutdwon, " + "can't queue an APC on it\n", pthrTarget->GetThreadId()); + palErr = ERROR_INVALID_PARAMETER; + goto QUAPC_exit; + } + + if (NULL == pthrTarget->apcInfo.m_ptainTail) + { + _ASSERT_MSG(NULL == pthrTarget->apcInfo.m_ptainHead, "Corrupted APC list\n"); + + pthrTarget->apcInfo.m_ptainHead = ptainNode; + pthrTarget->apcInfo.m_ptainTail = ptainNode; + } + else + { + pthrTarget->apcInfo.m_ptainTail->pNext = ptainNode; + pthrTarget->apcInfo.m_ptainTail = ptainNode; + } + + // Set ptainNode to NULL so it won't be readded to the cache + ptainNode = NULL; + + TRACE("APC %p with parameter %p added to APC queue\n", pfnAPC, uptrData); + + dwWaitState = InterlockedCompareExchange((LONG *)pdwWaitState, + (LONG)TWS_ACTIVE, + (LONG)TWS_ALERTABLE); + + // Release thread lock + pthrTarget->Unlock(pthrCurrent); + fThreadLock = false; + + if (TWS_ALERTABLE == dwWaitState) + { + // Unregister the wait + UnRegisterWait(pthrCurrent, pTargetTWInfo, fSharedSynchLock); + + // Wake up target thread + palErr = WakeUpLocalThread( + pthrCurrent, + pthrTarget, + Alerted, + 0); + + if (NO_ERROR != palErr) + { + ERROR("Failed to wakeup local thread %#x for dispatching APCs [err=%u]\n", + pthrTarget->GetThreadId(), palErr); + } + } + + QUAPC_exit: + if (fThreadLock) + { + pthrTarget->Unlock(pthrCurrent); + } + + if (fSharedSynchLock) + { + ReleaseSharedSynchLock(pthrCurrent); + } + + if (fLocalSynchLock) + { + ReleaseLocalSynchLock(pthrCurrent); + } + + if (ptainNode) + { + m_cacheThreadApcInfoNodes.Add(pthrCurrent, ptainNode); + } + + return palErr; + } + + /*++ + Method: + CPalSynchronizationManager::SendTerminationRequestToWorkerThread + + Send a request to the worker thread to initiate process termination. + --*/ + PAL_ERROR CPalSynchronizationManager::SendTerminationRequestToWorkerThread() + { + PAL_ERROR palErr = GetInstance()->WakeUpLocalWorkerThread(SynchWorkerCmdTerminationRequest); + if (palErr != NO_ERROR) + { + ERROR("Failed to wake up worker thread [errno=%d {%s%}]\n", + errno, strerror(errno)); + palErr = ERROR_INTERNAL_ERROR; + } + + return palErr; + } + + /*++ + Method: + CPalSynchronizationManager::AreAPCsPending + + Returns 'true' if there are APCs currently pending for the target + thread (normally the current one) + --*/ + bool CPalSynchronizationManager::AreAPCsPending( + CPalThread * pthrTarget) + { + // No need to lock here + return (NULL != pthrTarget->apcInfo.m_ptainHead); + } + + /*++ + Method: + CPalSynchronizationManager::DispatchPendingAPCs + + Executes any pending APC for the current thread + --*/ + PAL_ERROR CPalSynchronizationManager::DispatchPendingAPCs( + CPalThread * pthrCurrent) + { + ThreadApcInfoNode * ptainNode, * ptainLocalHead; + int iAPCsCalled = 0; + + while (TRUE) + { + // Lock + pthrCurrent->Lock(pthrCurrent); + ptainLocalHead = pthrCurrent->apcInfo.m_ptainHead; + if (ptainLocalHead) + { + pthrCurrent->apcInfo.m_ptainHead = NULL; + pthrCurrent->apcInfo.m_ptainTail = NULL; + } + + // Unlock + pthrCurrent->Unlock(pthrCurrent); + + if (NULL == ptainLocalHead) + { + break; + } + + while (ptainLocalHead) + { + ptainNode = ptainLocalHead; + ptainLocalHead = ptainNode->pNext; + +#if _ENABLE_DEBUG_MESSAGES_ + // reset ENTRY nesting level back to zero while + // inside the callback ... + int iOldLevel = DBG_change_entrylevel(0); +#endif /* _ENABLE_DEBUG_MESSAGES_ */ + + TRACE("Calling APC %p with parameter %#x\n", + ptainNode->pfnAPC, ptainNode->pfnAPC); + + // Actual APC call + ptainNode->pfnAPC(ptainNode->pAPCData); + +#if _ENABLE_DEBUG_MESSAGES_ + // ... and set nesting level back to what it was + DBG_change_entrylevel(iOldLevel); +#endif /* _ENABLE_DEBUG_MESSAGES_ */ + + iAPCsCalled++; + m_cacheThreadApcInfoNodes.Add(pthrCurrent, ptainNode); + } + } + + return (iAPCsCalled > 0) ? NO_ERROR : ERROR_NOT_FOUND; + } + + /*++ + Method: + CPalSynchronizationManager::DiscardAllPendingAPCs + + Discards any pending APC for the target pthrTarget thread + --*/ + void CPalSynchronizationManager::DiscardAllPendingAPCs( + CPalThread * pthrCurrent, + CPalThread * pthrTarget) + { + ThreadApcInfoNode * ptainNode, * ptainLocalHead; + + // Lock + pthrTarget->Lock(pthrCurrent); + ptainLocalHead = pthrTarget->apcInfo.m_ptainHead; + if (ptainLocalHead) + { + pthrTarget->apcInfo.m_ptainHead = NULL; + pthrTarget->apcInfo.m_ptainTail = NULL; + } + + // Unlock + pthrTarget->Unlock(pthrCurrent); + + while (ptainLocalHead) + { + ptainNode = ptainLocalHead; + ptainLocalHead = ptainNode->pNext; + + m_cacheThreadApcInfoNodes.Add(pthrCurrent, ptainNode); + } + } + + /*++ + Method: + CPalSynchronizationManager::CreatePalSynchronizationManager + + Creates the Synchronization Manager. + Private method, it is called only by CPalSynchMgrController. + --*/ + IPalSynchronizationManager * CPalSynchronizationManager::CreatePalSynchronizationManager() + { + if (s_pObjSynchMgr != NULL) + { + ASSERT("Multiple PAL Synchronization manager initializations\n"); + return NULL; + } + + Initialize(); + return static_cast(s_pObjSynchMgr); + } + + /*++ + Method: + CPalSynchronizationManager::Initialize + + Internal Synchronization Manager initialization + --*/ + PAL_ERROR CPalSynchronizationManager::Initialize() + { + PAL_ERROR palErr = NO_ERROR; + LONG lInit; + CPalSynchronizationManager * pSynchManager = NULL; + + lInit = InterlockedCompareExchange(&s_lInitStatus, + (LONG)SynchMgrStatusInitializing, + (LONG)SynchMgrStatusIdle); + + if ((LONG)SynchMgrStatusIdle != lInit) + { + ASSERT("Synchronization Manager already being initialized"); + palErr = ERROR_INTERNAL_ERROR; + goto I_exit; + } + + InternalInitializeCriticalSection(&s_csSynchProcessLock); + InternalInitializeCriticalSection(&s_csMonitoredProcessesLock); + + pSynchManager = InternalNew(); + if (NULL == pSynchManager) + { + ERROR("Failed to allocate memory for Synchronization Manager"); + palErr = ERROR_NOT_ENOUGH_MEMORY; + goto I_exit; + } + + if (!pSynchManager->CreateProcessPipe()) + { + ERROR("Unable to create process pipe \n"); + palErr = ERROR_OPEN_FAILED; + goto I_exit; + } + + s_pObjSynchMgr = pSynchManager; + + // Initialization was successful + g_pSynchronizationManager = + static_cast(pSynchManager); + s_lInitStatus = (LONG)SynchMgrStatusRunning; + + I_exit: + if (NO_ERROR != palErr) + { + s_lInitStatus = (LONG)SynchMgrStatusError; + if (NULL != pSynchManager) + { + pSynchManager->ShutdownProcessPipe(); + } + + s_pObjSynchMgr = NULL; + g_pSynchronizationManager = NULL; + InternalDelete(pSynchManager); + } + + return palErr; + } + + /*++ + Method: + CPalSynchronizationManager::StartWorker + + Starts the Synchronization Manager's Worker Thread. + Private method, it is called only by CPalSynchMgrController. + --*/ + PAL_ERROR CPalSynchronizationManager::StartWorker( + CPalThread * pthrCurrent) + { + PAL_ERROR palErr = NO_ERROR; + CPalSynchronizationManager * pSynchManager = GetInstance(); + + if ((NULL == pSynchManager) || ((LONG)SynchMgrStatusRunning != s_lInitStatus)) + { + ERROR("Trying to to create worker thread in invalid state\n"); + return ERROR_INTERNAL_ERROR; + } + + HANDLE hWorkerThread = NULL; + SIZE_T osThreadId = 0; + palErr = InternalCreateThread(pthrCurrent, + NULL, + 0, + &WorkerThread, + (PVOID)pSynchManager, + 0, + PalWorkerThread, + &osThreadId, + &hWorkerThread); + + if (NO_ERROR == palErr) + { + pSynchManager->m_dwWorkerThreadTid = (DWORD)osThreadId; + palErr = InternalGetThreadDataFromHandle(pthrCurrent, + hWorkerThread, + &pSynchManager->m_pthrWorker, + &pSynchManager->m_pipoThread); + if (NO_ERROR != palErr) + { + ERROR("Unable to get worker thread data\n"); + } + } + else + { + ERROR("Unable to create worker thread\n"); + } + + if (NULL != hWorkerThread) + { + CloseHandle(hWorkerThread); + } + + return palErr; + } + + /*++ + Method: + CPalSynchronizationManager::PrepareForShutdown + + This method performs the part of Synchronization Manager's shutdown that + needs to be carried out when core PAL subsystems are still active. + Private method, it is called only by CPalSynchMgrController. + --*/ + PAL_ERROR CPalSynchronizationManager::PrepareForShutdown() + { + PAL_ERROR palErr = NO_ERROR; + CPalSynchronizationManager * pSynchManager = GetInstance(); + CPalThread * pthrCurrent = InternalGetCurrentThread(); + int iRet; + ThreadNativeWaitData * ptnwdWorkerThreadNativeData; + struct timespec tsAbsTmo = { 0, 0 }; + + LONG lInit = InterlockedCompareExchange(&s_lInitStatus, + (LONG)SynchMgrStatusShuttingDown, (LONG)SynchMgrStatusRunning); + + if ((LONG)SynchMgrStatusRunning != lInit) + { + ASSERT("Unexpected initialization status found " + "in PrepareForShutdown [expected=%d current=%d]\n", + SynchMgrStatusRunning, lInit); + // We intentionally not set s_lInitStatus to SynchMgrStatusError + // cause this could interfere with a previous thread already + // executing shutdown + palErr = ERROR_INTERNAL_ERROR; + goto PFS_exit; + } + + // Discard process monitoring for process waits + pSynchManager->DiscardMonitoredProcesses(pthrCurrent); + + if (NULL == pSynchManager->m_pipoThread) + { + // If m_pipoThread is NULL here, that means that StartWorker has + // never been called. That may happen if PAL_Initialize fails + // sometime after having called CreatePalSynchronizationManager, + // but before calling StartWorker. Nothing else to do here. + goto PFS_exit; + } + + palErr = pSynchManager->WakeUpLocalWorkerThread(SynchWorkerCmdShutdown); + if (NO_ERROR != palErr) + { + ERROR("Failed stopping worker thread [palErr=%u]\n", palErr); + s_lInitStatus = SynchMgrStatusError; + goto PFS_exit; + } + + ptnwdWorkerThreadNativeData = + &pSynchManager->m_pthrWorker->synchronizationInfo.m_tnwdNativeData; + + palErr = GetAbsoluteTimeout(WorkerThreadTerminationTimeout, &tsAbsTmo, /*fPreferMonotonicClock*/ TRUE); + if (NO_ERROR != palErr) + { + ERROR("Failed to convert timeout to absolute timeout\n"); + s_lInitStatus = SynchMgrStatusError; + goto PFS_exit; + } + + // Using the worker thread's predicate/condition/mutex + // to wait for worker thread to be done + iRet = pthread_mutex_lock(&ptnwdWorkerThreadNativeData->mutex); + if (0 != iRet) + { + // pthread calls might fail if the shutdown is called + // from a signal handler. In this case just don't wait + // for the worker thread + ERROR("Cannot lock mutex [err=%d]\n", iRet); + palErr = ERROR_INTERNAL_ERROR; + s_lInitStatus = SynchMgrStatusError; + goto PFS_exit; + } + + while (FALSE == ptnwdWorkerThreadNativeData->iPred) + { + iRet = pthread_cond_timedwait(&ptnwdWorkerThreadNativeData->cond, + &ptnwdWorkerThreadNativeData->mutex, + &tsAbsTmo); + if (0 != iRet) + { + if (ETIMEDOUT == iRet) + { + WARN("Timed out waiting for worker thread to exit " + "(tmo=%u ms)\n", WorkerThreadTerminationTimeout); + } + else + { + ERROR("pthread_cond_timedwait returned %d [errno=%d (%s)]\n", + iRet, errno, strerror(errno)); + } + break; + } + } + if (0 == iRet) + { + ptnwdWorkerThreadNativeData->iPred = FALSE; + } + iRet = pthread_mutex_unlock(&ptnwdWorkerThreadNativeData->mutex); + if (0 != iRet) + { + ERROR("Cannot unlock mutex [err=%d]\n", iRet); + palErr = ERROR_INTERNAL_ERROR; + s_lInitStatus = SynchMgrStatusError; + goto PFS_exit; + } + + PFS_exit: + if (NO_ERROR == palErr) + { + if (NULL != pSynchManager->m_pipoThread) + { + pSynchManager->m_pipoThread->ReleaseReference(pthrCurrent); + + // After this release both m_pipoThread and m_pthrWorker + // are no longer valid + pSynchManager->m_pipoThread = NULL; + pSynchManager->m_pthrWorker = NULL; + } + + // Ready for process shutdown + s_lInitStatus = SynchMgrStatusReadyForProcessShutDown; + } + + return palErr; + } + + // Entry point routine for the thread that initiates process termination. + DWORD PALAPI TerminationRequestHandlingRoutine(LPVOID pArg) + { + // Call the termination request handler if one is registered. + if (g_terminationRequestHandler != NULL) + { + // The process will terminate normally by calling exit. + // We use an exit code of '128 + signo'. This is a convention used in popular + // shells to calculate an exit code when the process was terminated by a signal. + // This is also used by the Process.ExitCode implementation. + g_terminationRequestHandler(128 + SIGTERM); + } + + return 0; + } + + /*++ + Method: + CPalSynchronizationManager::WorkerThread + + Synchronization Manager's Worker Thread + --*/ + DWORD PALAPI CPalSynchronizationManager::WorkerThread(LPVOID pArg) + { + PAL_ERROR palErr; + bool fShuttingDown = false; + bool fWorkerIsDone = false; + int iPollTimeout = INFTIM; + SynchWorkerCmd swcCmd; + ThreadWakeupReason twrWakeUpReason; + SharedID shridMarshaledData; + DWORD dwData; + CPalSynchronizationManager * pSynchManager = + reinterpret_cast(pArg); + CPalThread * pthrWorker = InternalGetCurrentThread(); + + while (!fWorkerIsDone) + { + LONG lProcessCount; + + palErr = pSynchManager->ReadCmdFromProcessPipe(iPollTimeout, + &swcCmd, + &shridMarshaledData, + &dwData); + if (NO_ERROR != palErr) + { + ERROR("Received error %x from ReadCmdFromProcessPipe()\n", + palErr); + continue; + } + switch (swcCmd) + { + case SynchWorkerCmdTerminationRequest: + // This worker thread is being asked to initiate process termination + + HANDLE hTerminationRequestHandlingThread; + palErr = InternalCreateThread(pthrWorker, + NULL, + 0, + &TerminationRequestHandlingRoutine, + NULL, + 0, + PalWorkerThread, + NULL, + &hTerminationRequestHandlingThread); + + if (NO_ERROR != palErr) + { + ERROR("Unable to create worker thread\n"); + } + + if (hTerminationRequestHandlingThread != NULL) + { + CloseHandle(hTerminationRequestHandlingThread); + } + + break; + case SynchWorkerCmdNop: + TRACE("Synch Worker: received SynchWorkerCmdNop\n"); + if (fShuttingDown) + { + TRACE("Synch Worker: received a timeout when " + "fShuttingDown==true: worker is done, bailing " + "out from the loop\n"); + + // Whether WorkerThreadShuttingDownTimeout has elapsed + // or the last process with a descriptor opened for + // write on our process pipe, has just closed it, + // causing an EOF on the read fd (that can happen only + // at shutdown time since during normal run time we + // hold a fd opened for write within this process). + // In both the case it is time to go for the worker + // thread. + fWorkerIsDone = true; + } + else + { + lProcessCount = pSynchManager->DoMonitorProcesses(pthrWorker); + if (lProcessCount > 0) + { + iPollTimeout = WorkerThreadProcMonitoringTimeout; + } + else + { + iPollTimeout = INFTIM; + } + } + break; + case SynchWorkerCmdRemoteSignal: + { + // Note: this cannot be a wait all + WaitingThreadsListNode * pWLNode; + ThreadWaitInfo * ptwiWaitInfo; + DWORD dwObjIndex; + bool fSharedSynchLock = false; + + // Lock + AcquireLocalSynchLock(pthrWorker); + AcquireSharedSynchLock(pthrWorker); + fSharedSynchLock = true; + + pWLNode = SharedIDToTypePointer(WaitingThreadsListNode, + shridMarshaledData); + + _ASSERT_MSG(NULL != pWLNode, "Received bad Shared ID %p\n", + shridMarshaledData); + _ASSERT_MSG(gPID == pWLNode->dwProcessId, + "Remote signal apparently sent to the wrong " + "process [target pid=%u current pid=%u]\n", + pWLNode->dwProcessId, gPID); + _ASSERT_MSG(0 == (WTLN_FLAG_WAIT_ALL & pWLNode->dwFlags), + "Wait all with remote awakening delegated " + "through SynchWorkerCmdRemoteSignal rather than " + "SynchWorkerCmdDelegatedObjectSignaling\n"); + + + // Get the object index + dwObjIndex = pWLNode->dwObjIndex; + + // Get the WaitInfo + ptwiWaitInfo = pWLNode->ptwiWaitInfo; + + // Initialize the WakeUpReason to WaitSucceeded + twrWakeUpReason = WaitSucceeded; + + CSynchData * psdSynchData = + SharedIDToTypePointer(CSynchData, + pWLNode->ptrOwnerObjSynchData.shrid); + + TRACE("Synch Worker: received REMOTE SIGNAL cmd " + "[WInfo=%p {Type=%u Domain=%u ObjCount=%d TgtThread=%x} " + "SynchData={shriId=%p p=%p} {SigCount=%d IsAbandoned=%d}\n", + ptwiWaitInfo, ptwiWaitInfo->wtWaitType, ptwiWaitInfo->wdWaitDomain, + ptwiWaitInfo->lObjCount, ptwiWaitInfo->pthrOwner->GetThreadId(), + (VOID *)pWLNode->ptrOwnerObjSynchData.shrid, psdSynchData, + psdSynchData->GetSignalCount(), psdSynchData->IsAbandoned()); + + if (CObjectType::OwnershipTracked == + psdSynchData->GetObjectType()->GetOwnershipSemantics()) + { + // Abandoned status is not propagated through process + // pipe: need to get it from the object itself before + // resetting the data by acquiring the object ownership + if (psdSynchData->IsAbandoned()) + { + twrWakeUpReason = MutexAbondoned; + } + + // Acquire ownership + palErr = psdSynchData->AssignOwnershipToThread( + pthrWorker, + ptwiWaitInfo->pthrOwner); + if (NO_ERROR != palErr) + { + ERROR("Synch Worker: AssignOwnershipToThread " + "failed with error %u; ownership data on " + "object with SynchData %p may be " + "corrupted\n", palErr, psdSynchData); + } + } + + // Unregister the wait + pSynchManager->UnRegisterWait(pthrWorker, + ptwiWaitInfo, + fSharedSynchLock); + + // pWLNode is no longer valid after UnRegisterWait + pWLNode = NULL; + + TRACE("Synch Worker: Waking up local thread %x " + "{WakeUpReason=%u ObjIndex=%u}\n", + ptwiWaitInfo->pthrOwner->GetThreadId(), + twrWakeUpReason, dwObjIndex); + + // Wake up the target thread + palErr = WakeUpLocalThread( + pthrWorker, + ptwiWaitInfo->pthrOwner, + twrWakeUpReason, + dwObjIndex); + if (NO_ERROR != palErr) + { + ERROR("Synch Worker: Failed to wake up local thread " + "%#x while propagating remote signaling: " + "object signaling may be lost\n", + ptwiWaitInfo->pthrOwner->GetThreadId()); + } + + // Unlock + ReleaseSharedSynchLock(pthrWorker); + fSharedSynchLock = false; + ReleaseLocalSynchLock(pthrWorker); + + break; + } + case SynchWorkerCmdDelegatedObjectSignaling: + { + CSynchData * psdSynchData; + + TRACE("Synch Worker: received " + "SynchWorkerCmdDelegatedObjectSignaling\n"); + + psdSynchData = SharedIDToTypePointer(CSynchData, + shridMarshaledData); + + _ASSERT_MSG(NULL != psdSynchData, "Received bad Shared ID %p\n", + shridMarshaledData); + _ASSERT_MSG(0 < dwData && (DWORD)INT_MAX > dwData, + "Received remote signaling with invalid signal " + "count\n"); + + // Lock + AcquireLocalSynchLock(pthrWorker); + AcquireSharedSynchLock(pthrWorker); + + TRACE("Synch Worker: received DELEGATED OBJECT SIGNALING " + "cmd [SynchData={shriId=%p p=%p} SigCount=%u] [Current obj SigCount=%d " + "IsAbandoned=%d]\n", (VOID *)shridMarshaledData, + psdSynchData, dwData, psdSynchData->GetSignalCount(), + psdSynchData->IsAbandoned()); + + psdSynchData->Signal(pthrWorker, + psdSynchData->GetSignalCount() + dwData, + true); + + // Current SynchData has been AddRef'd by remote process in + // order to be marshaled to the current one, therefore at + // this point we need to release it + psdSynchData->Release(pthrWorker); + + // Unlock + ReleaseSharedSynchLock(pthrWorker); + ReleaseLocalSynchLock(pthrWorker); + + break; + } + case SynchWorkerCmdShutdown: + TRACE("Synch Worker: received SynchWorkerCmdShutdown\n"); + + // Shutdown the process pipe: this will cause the process + // pipe to be unlinked and its write-only file descriptor + // to be closed, so that when the last fd opened for write + // on the fifo (from another process) will be closed, we + // will receive an EOF on the read end (i.e. poll in + // ReadBytesFromProcessPipe will return 1 with no data to + // be read). That will allow the worker thread to process + // possible commands already successfully written to the + // pipe by some other process, before shutting down. + pSynchManager->ShutdownProcessPipe(); + + // Shutting down: this will cause the worker thread to + // fetch residual cmds from the process pipe until an + // EOF is converted to a SynchWorkerCmdNop or the + // WorkerThreadShuttingDownTimeout has elapsed without + // receiving any cmd. + fShuttingDown = true; + + // Set the timeout to WorkerThreadShuttingDownTimeout + iPollTimeout = WorkerThreadShuttingDownTimeout; + break; + default: + ASSERT("Synch Worker: Unknown worker cmd [swcWorkerCmd=%d]\n", + swcCmd); + break; + } + } + + int iRet; + ThreadNativeWaitData * ptnwdWorkerThreadNativeData = + &pthrWorker->synchronizationInfo.m_tnwdNativeData; + + // Using the worker thread's predicate/condition/mutex + // (that normally are never used) to signal the shutting + // down thread that the worker thread is done + iRet = pthread_mutex_lock(&ptnwdWorkerThreadNativeData->mutex); + _ASSERT_MSG(0 == iRet, "Cannot lock mutex [err=%d]\n", iRet); + + ptnwdWorkerThreadNativeData->iPred = TRUE; + + iRet = pthread_cond_signal(&ptnwdWorkerThreadNativeData->cond); + if (0 != iRet) + { + ERROR ("pthread_cond_signal returned %d [errno=%d (%s)]\n", + iRet, errno, strerror(errno)); + } + + iRet = pthread_mutex_unlock(&ptnwdWorkerThreadNativeData->mutex); + _ASSERT_MSG(0 == iRet, "Cannot lock mutex [err=%d]\n", iRet); + + // Sleep forever + ThreadPrepareForShutdown(); + + return 0; + } + + /*++ + Method: + CPalSynchronizationManager::ReadCmdFromProcessPipe + + Reads a worker thread cmd from the process pipe. If there is no data + to be read on the pipe, it blocks until there is data available or the + timeout expires. + --*/ + PAL_ERROR CPalSynchronizationManager::ReadCmdFromProcessPipe( + int iPollTimeout, + SynchWorkerCmd * pswcWorkerCmd, + SharedID * pshridMarshaledData, + DWORD * pdwData) + { + int iRet; + BYTE byVal; + SynchWorkerCmd swcWorkerCmd = SynchWorkerCmdNop; + + _ASSERTE(NULL != pswcWorkerCmd); + _ASSERTE(NULL != pshridMarshaledData); + _ASSERTE(NULL != pdwData); + + iRet = ReadBytesFromProcessPipe(iPollTimeout, &byVal, sizeof(BYTE)); + + if (0 > iRet) + { + ERROR("Failed polling the process pipe [ret=%d errno=%d (%s)]\n", + iRet, errno, strerror(errno)); + + return ERROR_INTERNAL_ERROR; + } + + if (iRet != 0) + { + _ASSERT_MSG(sizeof(BYTE) == iRet, + "Got %d bytes from process pipe while expecting for %d\n", + iRet, sizeof(BYTE)); + + swcWorkerCmd = (SynchWorkerCmd)byVal; + + if (SynchWorkerCmdLast <= swcWorkerCmd) + { + ERROR("Got unknown worker command code %d from the process " + "pipe!\n", swcWorkerCmd); + + return ERROR_INTERNAL_ERROR; + } + + _ASSERT_MSG(SynchWorkerCmdNop == swcWorkerCmd || + SynchWorkerCmdRemoteSignal == swcWorkerCmd || + SynchWorkerCmdDelegatedObjectSignaling == swcWorkerCmd || + SynchWorkerCmdShutdown == swcWorkerCmd || + SynchWorkerCmdTerminationRequest == swcWorkerCmd, + "Unknown worker command code %u\n", swcWorkerCmd); + + TRACE("Got cmd %u from process pipe\n", swcWorkerCmd); + } + + if (SynchWorkerCmdRemoteSignal == swcWorkerCmd || + SynchWorkerCmdDelegatedObjectSignaling == swcWorkerCmd) + { + SharedID shridMarshaledId = NULL; + + TRACE("Received %s cmd\n", + (swcWorkerCmd == SynchWorkerCmdRemoteSignal) ? + "REMOTE SIGNAL" : "DELEGATED OBJECT SIGNALING" ); + + iRet = ReadBytesFromProcessPipe(WorkerCmdCompletionTimeout, + (BYTE *)&shridMarshaledId, + sizeof(shridMarshaledId)); + if (sizeof(shridMarshaledId) != iRet) + { + ERROR("Unable to read marshaled Shared ID from the " + "process pipe [pipe=%d ret=%d errno=%d (%s)]\n", + m_iProcessPipeRead, iRet, errno, strerror(errno)); + + return ERROR_INTERNAL_ERROR; + } + + TRACE("Received marshaled shrid=%p\n", (VOID *)shridMarshaledId); + + *pshridMarshaledData = shridMarshaledId; + } + + if (SynchWorkerCmdDelegatedObjectSignaling == swcWorkerCmd) + { + DWORD dwData; + + iRet = ReadBytesFromProcessPipe(WorkerCmdCompletionTimeout, + (BYTE *)&dwData, + sizeof(dwData)); + if (sizeof(dwData) != iRet) + { + ERROR("Unable to read signal count from the " + "process pipe [pipe=%d ret=%d errno=%d (%s)]\n", + m_iProcessPipeRead, iRet, errno, strerror(errno)); + + return ERROR_INTERNAL_ERROR; + } + + TRACE("Received signal count %u\n", dwData); + + *pdwData = dwData; + } + + *pswcWorkerCmd = swcWorkerCmd; + return NO_ERROR; + } + + /*++ + Method: + CPalSynchronizationManager::ReadBytesFromProcessPipe + + Reads the specified number of bytes from the process pipe. If there is + no data to be read on the pipe, it blocks until there is data available + or the timeout expires. + --*/ + int CPalSynchronizationManager::ReadBytesFromProcessPipe( + int iTimeout, + BYTE * pRecvBuf, + LONG iBytes) + { +#if !HAVE_KQUEUE + struct pollfd Poll; +#endif // !HAVE_KQUEUE + int iRet = -1; + int iConsecutiveEintrs = 0; + LONG iBytesRead = 0; + BYTE * pPos = pRecvBuf; +#if HAVE_KQUEUE && !HAVE_BROKEN_FIFO_KEVENT + struct kevent keChanges; + struct timespec ts, *pts; + int iNChanges; +#endif // HAVE_KQUEUE + + _ASSERTE(0 <= iBytes); + + do + { + while (TRUE) + { + int iErrno = 0; +#if HAVE_KQUEUE +#if HAVE_BROKEN_FIFO_KEVENT +#if HAVE_BROKEN_FIFO_SELECT +#error Found no way to wait on a FIFO. +#endif + + timeval *ptv; + timeval tv; + + if (INFTIM == iTimeout) + { + ptv = NULL; + } + else + { + tv.tv_usec = (iTimeout % tccSecondsToMillieSeconds) * + tccMillieSecondsToMicroSeconds; + tv.tv_sec = iTimeout / tccSecondsToMillieSeconds; + ptv = &tv; + } + + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(m_iProcessPipeRead, &readfds); + iRet = select(m_iProcessPipeRead + 1, &readfds, NULL, NULL, ptv); + +#else // HAVE_BROKEN_FIFO_KEVENT + + // Note: FreeBSD needs to use kqueue/kevent support here, since on this + // platform the EOF notification on FIFOs is not surfaced through poll, + // and process pipe shutdown relies on this feature. + // If a thread is polling a FIFO or a pipe for POLLIN, when the last + // write descriptor for that pipe is closed, poll() is supposed to + // return with a POLLIN event but no data to be read on the FIFO/pipe, + // which means EOF. + // On FreeBSD such feature works for pipes but it doesn't for FIFOs. + // Using kevent the EOF is instead surfaced correctly. + + if (iBytes > m_keProcessPipeEvent.data) + { + if (INFTIM == iTimeout) + { + pts = NULL; + } + else + { + ts.tv_nsec = (iTimeout % tccSecondsToMillieSeconds) * + tccMillieSecondsToNanoSeconds; + ts.tv_sec = iTimeout / tccSecondsToMillieSeconds; + pts = &ts; + } + + if (0 != (EV_EOF & m_keProcessPipeEvent.flags)) + { + TRACE("Refreshing kevent settings\n"); + EV_SET(&keChanges, m_iProcessPipeRead, EVFILT_READ, + EV_ADD | EV_CLEAR, 0, 0, 0); + iNChanges = 1; + } + else + { + iNChanges = 0; + } + + iRet = kevent(m_iKQueue, &keChanges, iNChanges, + &m_keProcessPipeEvent, 1, pts); + + if (0 < iRet) + { + _ASSERTE(1 == iRet); + _ASSERTE(EVFILT_READ == m_keProcessPipeEvent.filter); + + if (EV_ERROR & m_keProcessPipeEvent.flags) + { + ERROR("EV_ERROR from kevent [ident=%d filter=%d flags=%x]\n", m_keProcessPipeEvent.ident, m_keProcessPipeEvent.filter, m_keProcessPipeEvent.flags); + iRet = -1; + iErrno = m_keProcessPipeEvent.data; + m_keProcessPipeEvent.data = 0; + } + } + else if (0 > iRet) + { + iErrno = errno; + } + + TRACE("Woken up from kevent() with ret=%d flags=%#x data=%d " + "[iTimeout=%d]\n", iRet, m_keProcessPipeEvent.flags, + m_keProcessPipeEvent.data, iTimeout); + } + else + { + // There is enough data already available in the buffer, just use that. + iRet = 1; + } + +#endif // HAVE_BROKEN_FIFO_KEVENT +#else // HAVE_KQUEUE + + Poll.fd = m_iProcessPipeRead; + Poll.events = POLLIN; + Poll.revents = 0; + + iRet = poll(&Poll, 1, iTimeout); + + TRACE("Woken up from poll() with ret=%d [iTimeout=%d]\n", + iRet, iTimeout); + + if (1 == iRet && + ((POLLERR | POLLHUP | POLLNVAL) & Poll.revents)) + { + // During PAL shutdown the pipe gets closed and Poll.revents is set to POLLHUP + // (note: no other flags are set). We will also receive an EOF on from the read call. + // Please see the comment for SynchWorkerCmdShutdown in CPalSynchronizationManager::WorkerThread. + if (!PALIsShuttingDown() || (Poll.revents != POLLHUP)) + { + ERROR("Unexpected revents=%x while polling pipe %d\n", + Poll.revents, Poll.fd); + iErrno = EINVAL; + iRet = -1; + } + } + else if (0 > iRet) + { + iErrno = errno; + } + +#endif // HAVE_KQUEUE + + if (0 == iRet || 1 == iRet) + { + // 0 == wait timed out + // 1 == FIFO has data available + break; + } + else + { + if (1 < iRet) + { + // Unexpected iRet > 1 + ASSERT("Unexpected return code %d from blocking poll/kevent call\n", + iRet); + goto RBFPP_exit; + } + + if (EINTR != iErrno) + { + // Unexpected error + ASSERT("Unexpected error from blocking poll/kevent call: %d (%s)\n", + iErrno, strerror(iErrno)); + goto RBFPP_exit; + } + + iConsecutiveEintrs++; + TRACE("poll() failed with EINTR; re-polling\n"); + + if (iConsecutiveEintrs >= MaxWorkerConsecutiveEintrs) + { + if (iTimeout != INFTIM) + { + WARN("Receiving too many EINTRs; converting one of them " + "to a timeout"); + iRet = 0; + break; + } + else if (0 == (iConsecutiveEintrs % MaxWorkerConsecutiveEintrs)) + { + WARN("Receiving too many EINTRs [%d so far]", + iConsecutiveEintrs); + } + } + } + } + + if (0 == iRet) + { + // Time out + break; + } + else + { +#if HAVE_KQUEUE && !HAVE_BROKEN_FIFO_KEVENT + if (0 != (EV_EOF & m_keProcessPipeEvent.flags) && 0 == m_keProcessPipeEvent.data) + { + // EOF + TRACE("Received an EOF on process pipe via kevent\n"); + goto RBFPP_exit; + } +#endif // HAVE_KQUEUE + + iRet = read(m_iProcessPipeRead, pPos, iBytes - iBytesRead); + + if (0 == iRet) + { + // Poll returned 1 and read returned zero: this is an EOF, + // i.e. no other process has the pipe still open for write + TRACE("Received an EOF on process pipe via poll\n"); + goto RBFPP_exit; + } + else if (0 > iRet) + { + ERROR("Unable to read %d bytes from the the process pipe " + "[pipe=%d ret=%d errno=%d (%s)]\n", iBytes - iBytesRead, + m_iProcessPipeRead, iRet, errno, strerror(errno)); + goto RBFPP_exit; + } + + TRACE("Read %d bytes from process pipe\n", iRet); + + iBytesRead += iRet; + pPos += iRet; + +#if HAVE_KQUEUE && !HAVE_BROKEN_FIFO_KEVENT + // Update available data count + m_keProcessPipeEvent.data -= iRet; + _ASSERTE(0 <= m_keProcessPipeEvent.data); +#endif // HAVE_KQUEUE + } + } while(iBytesRead < iBytes); + + RBFPP_exit: + return (iRet < 0) ? iRet : iBytesRead; + } + + /*++ + Method: + CPalSynchronizationManager::WakeUpLocalThread + + Wakes up a local thead currently sleeping for a wait or a sleep + --*/ + PAL_ERROR CPalSynchronizationManager::WakeUpLocalThread( + CPalThread * pthrCurrent, + CPalThread * pthrTarget, + ThreadWakeupReason twrWakeupReason, + DWORD dwObjectIndex) + { + PAL_ERROR palErr = NO_ERROR; + ThreadNativeWaitData * ptnwdNativeWaitData = + pthrTarget->synchronizationInfo.GetNativeData(); + + TRACE("Waking up a local thread [WakeUpReason=%u ObjectIndex=%u " + "ptnwdNativeWaitData=%p]\n", twrWakeupReason, dwObjectIndex, + ptnwdNativeWaitData); + + // Set wakeup reason and signaled object index + ptnwdNativeWaitData->twrWakeupReason = twrWakeupReason; + ptnwdNativeWaitData->dwObjectIndex = dwObjectIndex; + +#if SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + if (0 < GetLocalSynchLockCount(pthrCurrent)) + { + // Defer the actual thread signaling to right after + // releasing the synch lock(s), so that signaling + // can happen from a thread-suspension safe area + palErr = DeferThreadConditionSignaling(pthrCurrent, pthrTarget); + } + else + { + // Signal the target thread's condition + palErr = SignalThreadCondition(ptnwdNativeWaitData); + } +#else // SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + // Signal the target thread's condition + palErr = SignalThreadCondition(ptnwdNativeWaitData); +#endif // SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + + return palErr; + } + +#if SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + /*++ + Method: + CPalSynchronizationManager::DeferThreadConditionSignaling + + Defers thread signaling to the final release of synchronization + lock(s), so that condition signaling can happen when the signaling + thread is marked as safe for thread suspension. + --*/ + PAL_ERROR CPalSynchronizationManager::DeferThreadConditionSignaling( + CPalThread * pthrCurrent, + CPalThread * pthrTarget) + { + PAL_ERROR palErr = NO_ERROR; + LONG lCount = pthrCurrent->synchronizationInfo.m_lPendingSignalingCount; + + _ASSERTE(pthrTarget != pthrCurrent); + + if (CThreadSynchronizationInfo::PendingSignalingsArraySize > lCount) + { + // If there is available room, add the target thread object to + // the array of pending thread signalings. + pthrCurrent->synchronizationInfo.m_rgpthrPendingSignalings[lCount] = pthrTarget; + } + else + { + // If the array is full, add the target thread object at the end + // of the overflow list + DeferredSignalingListNode * pdsln = + InternalNew(); + + if (pdsln) + { + pdsln->pthrTarget = pthrTarget; + + // Add the note to the end of the list. + // Note: no need to synchronize the access to this list since + // it is meant to be accessed only by the owner thread. + InsertTailList(&pthrCurrent->synchronizationInfo.m_lePendingSignalingsOverflowList, + &pdsln->Link); + } + else + { + palErr = ERROR_NOT_ENOUGH_MEMORY; + } + } + + if (NO_ERROR == palErr) + { + // Increment the count of pending signalings + pthrCurrent->synchronizationInfo.m_lPendingSignalingCount += 1; + + // Add a reference to the target CPalThread object; this is + // needed since deferring signaling after releasing the synch + // locks implies accessing the target thread object without + // holding the local synch lock. In rare circumstances, the + // target thread may have already exited while deferred signaling + // takes place, therefore invalidating the thread object. The + // reference added here ensures that the thread object is still + // good, even if the target thread has exited. + pthrTarget->AddThreadReference(); + } + + return palErr; + } +#endif // SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + + /*++ + Method: + CPalSynchronizationManager::SignalThreadCondition + + Performs the actual condition signaling in to wake up the target thread + --*/ + PAL_ERROR CPalSynchronizationManager::SignalThreadCondition( + ThreadNativeWaitData * ptnwdNativeWaitData) + { + PAL_ERROR palErr = NO_ERROR; + int iRet; + + // Lock the mutex + iRet = pthread_mutex_lock(&ptnwdNativeWaitData->mutex); + if (0 != iRet) + { + ERROR("Cannot lock mutex [err=%d]\n", iRet); + return ERROR_INTERNAL_ERROR; + } + + // Set the predicate + ptnwdNativeWaitData->iPred = TRUE; + + // Signal the condition + iRet = pthread_cond_signal(&ptnwdNativeWaitData->cond); + if (0 != iRet) + { + ERROR("Failed to signal condition: pthread_cond_signal " + "returned %d [errno=%d (%s)]\n", iRet, errno, + strerror(errno)); + palErr = ERROR_INTERNAL_ERROR; + // Continue in order to unlock the mutex anyway + } + + // Unlock the mutex + iRet = pthread_mutex_unlock(&ptnwdNativeWaitData->mutex); + if (0 != iRet) + { + ERROR("Cannot unlock mutex [err=%d]\n", iRet); + return ERROR_INTERNAL_ERROR; + } + + return palErr; + } + + /*++ + Method: + CPalSynchronizationManager::ReadBytesFromProcessPipe + + Wakes up a remote thead currently sleeping for a wait or a sleep + by sending the appropriate cmd to the remote process' worker + thread, which will take care to convert this command into a + WakeUpLocalThread in the remote process + --*/ + PAL_ERROR CPalSynchronizationManager::WakeUpRemoteThread( + SharedID shridWLNode) + { + const int MsgSize = sizeof(BYTE) + sizeof(SharedID); + PAL_ERROR palErr = NO_ERROR; + BYTE rgSendBuf[MsgSize]; + BYTE * pbySrc, * pbyDst = rgSendBuf; + WaitingThreadsListNode * pWLNode = SharedIDToTypePointer(WaitingThreadsListNode, shridWLNode); + + + _ASSERT_MSG(NULL != pWLNode, "Bad shared wait list node identifier (%p)\n", (VOID*)shridWLNode); + _ASSERT_MSG(gPID != pWLNode->dwProcessId, "WakeUpRemoteThread called on local thread\n"); + _ASSERT_MSG(NULL != shridWLNode, "NULL shared identifier\n"); + _ASSERT_MSG(MsgSize <= PIPE_BUF, "Message too long [MsgSize=%d PIPE_BUF=%d]\n", MsgSize, (int)PIPE_BUF); + + TRACE("Waking up remote thread {pid=%x, tid=%x} by sending cmd=%u and shridWLNode=%p over process pipe\n", + pWLNode->dwProcessId, pWLNode->dwThreadId, SynchWorkerCmdRemoteSignal, (VOID *)shridWLNode); + + // Prepare the message + // Cmd + *pbyDst++ = (BYTE)(SynchWorkerCmdRemoteSignal & 0xFF); + + // WaitingThreadsListNode (not aligned, copy byte by byte) + pbySrc = (BYTE *)&shridWLNode; + for (int i = 0; i < (int)sizeof(SharedID); i++) + { + *pbyDst++ = *pbySrc++; + } + + _ASSERT_MSG(pbyDst <= rgSendBuf + MsgSize + 1, "Buffer overrun"); + + // Send the message + palErr = SendMsgToRemoteWorker(pWLNode->dwProcessId, rgSendBuf, MsgSize); + if (NO_ERROR != palErr) + { + ERROR("Failed sending message to remote worker in process %u\n", pWLNode->dwProcessId); + } + + return palErr; + } + + /*++ + Method: + CPalSynchronizationManager::DelegateSignalingToRemoteProcess + + This method transfers an object signaling operation to a remote process, + where it will be performed by the worker thread. Such delegation takes + place when the currently processed thread (among those waiting on the + signald object) lives in a different process as the signaling thread, + and it is performing a wait all. In this case generally is not possible + to find out whether or not the wait all is satisfied, therefore the + signaling operation must be continued in the target process. + --*/ + PAL_ERROR CPalSynchronizationManager::DelegateSignalingToRemoteProcess( + CPalThread * pthrCurrent, + DWORD dwTargetProcessId, + SharedID shridSynchData) + { + const int MsgSize = sizeof(BYTE) + sizeof(SharedID) + sizeof(DWORD); + int i; + PAL_ERROR palErr = NO_ERROR; + BYTE rgSendBuf[MsgSize]; + BYTE * pbySrc, * pbyDst = rgSendBuf; + DWORD dwSigCount; + CSynchData * psdSynchData = + SharedIDToTypePointer(CSynchData, shridSynchData); + + _ASSERT_MSG(gPID != dwTargetProcessId, " called on local thread\n"); + _ASSERT_MSG(NULL != shridSynchData, "NULL shared identifier\n"); + _ASSERT_MSG(NULL != psdSynchData, "Bad shared SynchData identifier (%p)\n", (VOID*)shridSynchData); + _ASSERT_MSG(MsgSize <= PIPE_BUF, "Message too long [MsgSize=%d PIPE_BUF=%d]\n", MsgSize, (int)PIPE_BUF); + + TRACE("Transfering wait all signaling to remote process pid=%x by sending cmd=%u and shridSynchData=%p over process pipe\n", + dwTargetProcessId, SynchWorkerCmdDelegatedObjectSignaling, (VOID *)shridSynchData); + + dwSigCount = psdSynchData->GetSignalCount(); + + // AddRef SynchData to be marshaled to remote process + psdSynchData->AddRef(); + + // + // Prepare the message + // + + // Cmd + *pbyDst++ = (BYTE)(SynchWorkerCmdDelegatedObjectSignaling & 0xFF); + + // CSynchData (not aligned, copy byte by byte) + pbySrc = (BYTE *)&shridSynchData; + for (i=0; i<(int)sizeof(SharedID); i++) + { + *pbyDst++ = *pbySrc++; + } + + // Signal Count (not aligned, copy byte by byte) + pbySrc = (BYTE *)&dwSigCount; + for (i=0; i<(int)sizeof(DWORD); i++) + { + *pbyDst++ = *pbySrc++; + } + + _ASSERT_MSG(pbyDst <= rgSendBuf + MsgSize + 1, "Buffer overrun"); + + // Send the message + palErr = SendMsgToRemoteWorker(dwTargetProcessId, rgSendBuf, MsgSize); + if (NO_ERROR != palErr) + { + TRACE("Failed sending message to remote worker in process %u\n", dwTargetProcessId); + + // Undo refcounting + psdSynchData->Release(pthrCurrent); + } + + return palErr; + } + + /*++ + Method: + CPalSynchronizationManager::SendMsgToRemoteWorker + + Sends a message (command + data) to a remote process's worker thread. + --*/ + PAL_ERROR CPalSynchronizationManager::SendMsgToRemoteWorker( + DWORD dwProcessId, + BYTE * pMsg, + int iMsgSize) + { +#ifndef CORECLR + PAL_ERROR palErr = NO_ERROR; + int iProcessPipe, iBytesToWrite, iRetryCount; + ssize_t sszRet; + char strPipeFilename[MAX_PATH]; + BYTE * pPos = pMsg; + bool fRet; + CPalThread *pthrCurrent = InternalGetCurrentThread(); + + _ASSERT_MSG(gPID != dwProcessId, "SendMsgToRemoteWorker called with local process as target process\n"); + + fRet = GetProcessPipeName(strPipeFilename, MAX_PATH, dwProcessId); + + _ASSERT_MSG(fRet, "Failed to retrieve process pipe's name!\n"); + + iProcessPipe = InternalOpen(strPipeFilename, O_WRONLY); + if (-1 == iProcessPipe) + { + ERROR("Unable to open a process pipe to wake up a remote thread " + "[pid=%u errno=%d (%s) PipeFilename=%s]\n", dwProcessId, + errno, strerror(errno), strPipeFilename); + palErr = ERROR_INTERNAL_ERROR; + goto SMTRW_exit; + } + + pPos = pMsg; + iBytesToWrite = iMsgSize; + while (0 < iBytesToWrite) + { + iRetryCount = 0; + do + { + sszRet = write(iProcessPipe, pPos, iBytesToWrite); + } while (-1 == sszRet && + EAGAIN == errno && + ++iRetryCount < MaxConsecutiveEagains && + 0 == sched_yield()); + + if (0 >= sszRet) + { + ERROR("Error writing message to process pipe %d [target_pid=%u " + "bytes_to_write=%d bytes_written=%d ret=%d errno=%d (%s) " + "PipeFilename=%s]\n", iProcessPipe, dwProcessId, iMsgSize, + iMsgSize - iBytesToWrite, (int)sszRet, errno, strerror(errno), + strPipeFilename); + palErr = ERROR_INTERNAL_ERROR; + break; + } + iBytesToWrite -= (int)sszRet; + pPos += sszRet; + + _ASSERT_MSG(0 == iBytesToWrite, + "Interleaved messages while writing to process pipe %d\n", + iProcessPipe); + } + + // Close the opened pipe + close(iProcessPipe); + + SMTRW_exit: + return palErr; +#else // !CORECLR + ASSERT("There should never be a reason to send a message to a remote worker\n"); + return ERROR_INTERNAL_ERROR; +#endif // !CORECLR + } + + /*++ + Method: + CPalSynchronizationManager::WakeUpLocalWorkerThread + + Wakes up the local worker thread by writing a 'nop' cmd to the + process pipe. + --*/ + PAL_ERROR CPalSynchronizationManager::WakeUpLocalWorkerThread( + SynchWorkerCmd swcWorkerCmd) + { + PAL_ERROR palErr = NO_ERROR; + + _ASSERT_MSG((swcWorkerCmd & 0xFF) == swcWorkerCmd, + "Value too big for swcWorkerCmd\n"); + + _ASSERT_MSG((SynchWorkerCmdNop == swcWorkerCmd) || + (SynchWorkerCmdShutdown == swcWorkerCmd) || + (SynchWorkerCmdTerminationRequest == swcWorkerCmd), + "WakeUpLocalWorkerThread supports only SynchWorkerCmdNop, SynchWorkerCmdShutdown, and SynchWorkerCmdTerminationRequest." + "[received cmd=%d]\n", swcWorkerCmd); + + BYTE byCmd = (BYTE)(swcWorkerCmd & 0xFF); + + TRACE("Waking up Synch Worker Thread for %u [byCmd=%u]\n", + swcWorkerCmd, (unsigned int)byCmd); + + // As long as we use pipes and we keep the message size + // within PIPE_BUF, there's no need to lock here, since the + // write is guaranteed not to be interleaved with/into other + // writes of PIPE_BUF bytes or less. + _ASSERT_MSG(sizeof(BYTE) <= PIPE_BUF, "Message too long\n"); + + int iRetryCount = 0; + ssize_t sszWritten; + do + { + sszWritten = write(m_iProcessPipeWrite, &byCmd, sizeof(BYTE)); + } while (-1 == sszWritten && + EAGAIN == errno && + ++iRetryCount < MaxConsecutiveEagains && + 0 == sched_yield()); + + if (sszWritten != sizeof(BYTE)) + { + ERROR("Unable to write to the process pipe to wake up the " + "worker thread [errno=%d (%s)]\n", errno, strerror(errno)); + palErr = ERROR_INTERNAL_ERROR; + } + + return palErr; + } + + /*++ + Method: + CPalSynchronizationManager::GetThreadWaitInfo + + Returns a pointer to the WaitInfo structure for the passed CPalThread object + --*/ + ThreadWaitInfo * CPalSynchronizationManager::GetThreadWaitInfo( + CPalThread * pthrCurrent) + { + return &pthrCurrent->synchronizationInfo.m_twiWaitInfo; + } + + /*++ + Method: + CPalSynchronizationManager::UnRegisterWait + + Unregister the wait described by ptwiWaitInfo that in general involves + a thread other than the current one (most of the times the deregistration + is performed by the signaling thread) + + Note: this method must be called while holding the local process + synchronization lock. + --*/ + void CPalSynchronizationManager::UnRegisterWait( + CPalThread * pthrCurrent, + ThreadWaitInfo * ptwiWaitInfo, + bool fHaveSharedLock) + { + int i = 0; + CSynchData * psdSynchData = NULL; + bool fSharedSynchLock = false; + + if (!fHaveSharedLock && LocalWait != ptwiWaitInfo->wdWaitDomain) + { + AcquireSharedSynchLock(pthrCurrent); + fSharedSynchLock = true; + } + + TRACE("Unregistering wait for thread=%u [ObjCount=%d WaitType=%u WaitDomain=%u]\n", + ptwiWaitInfo->pthrOwner->GetThreadId(), + ptwiWaitInfo->lObjCount, ptwiWaitInfo->wtWaitType, + ptwiWaitInfo->wdWaitDomain); + + for (i=0; i < ptwiWaitInfo->lObjCount; i++) + { + WaitingThreadsListNode * pwtlnItem = ptwiWaitInfo->rgpWTLNodes[i]; + + VALIDATEOBJECT(pwtlnItem); + + if (pwtlnItem->dwFlags & WTLN_FLAG_OWNER_OBJECT_IS_SHARED) + { + // Shared object + WaitingThreadsListNode * pwtlnItemNext, * pwtlnItemPrev; + + psdSynchData = SharedIDToTypePointer(CSynchData, + pwtlnItem->ptrOwnerObjSynchData.shrid); + + VALIDATEOBJECT(psdSynchData); + + pwtlnItemNext = SharedIDToTypePointer(WaitingThreadsListNode, + pwtlnItem->ptrNext.shrid); + pwtlnItemPrev = SharedIDToTypePointer(WaitingThreadsListNode, + pwtlnItem->ptrPrev.shrid); + if (pwtlnItemPrev) + { + VALIDATEOBJECT(pwtlnItemPrev); + pwtlnItemPrev->ptrNext.shrid = pwtlnItem->ptrNext.shrid; + } + else + { + psdSynchData->SetWTLHeadShrPtr(pwtlnItem->ptrNext.shrid); + } + + if (pwtlnItemNext) + { + VALIDATEOBJECT(pwtlnItemNext); + pwtlnItemNext->ptrPrev.shrid = pwtlnItem->ptrPrev.shrid; + } + else + { + psdSynchData->SetWTLTailShrPtr(pwtlnItem->ptrPrev.shrid); + } + + m_cacheSHRWTListNodes.Add(pthrCurrent, pwtlnItem->shridSHRThis); + } + else + { + // Local object + psdSynchData = pwtlnItem->ptrOwnerObjSynchData.ptr; + + VALIDATEOBJECT(psdSynchData); + + if (pwtlnItem->ptrPrev.ptr) + { + VALIDATEOBJECT(pwtlnItem); + pwtlnItem->ptrPrev.ptr->ptrNext.ptr = pwtlnItem->ptrNext.ptr; + } + else + { + psdSynchData->SetWTLHeadPtr(pwtlnItem->ptrNext.ptr); + } + + if (pwtlnItem->ptrNext.ptr) + { + VALIDATEOBJECT(pwtlnItem); + pwtlnItem->ptrNext.ptr->ptrPrev.ptr = pwtlnItem->ptrPrev.ptr; + } + else + { + psdSynchData->SetWTLTailPtr(pwtlnItem->ptrPrev.ptr); + } + + m_cacheWTListNodes.Add(pthrCurrent, pwtlnItem); + } + + // Release the node's refcount on the synch data, and decerement + // waiting thread count + psdSynchData->DecrementWaitingThreadCount(); + psdSynchData->Release(pthrCurrent); + } + + // Reset wait data in ThreadWaitInfo structure: it is enough + // to reset lObjCount, lSharedObjCount and wdWaitDomain. + ptwiWaitInfo->lObjCount = 0; + ptwiWaitInfo->lSharedObjCount = 0; + ptwiWaitInfo->wdWaitDomain = LocalWait; + + // Done + if (fSharedSynchLock) + { + ReleaseSharedSynchLock(pthrCurrent); + } + + return; + } + + /*++ + Method: + CPalSynchronizationManager::UnsignalRestOfLocalAwakeningWaitAll + + Unsignals all the objects involved in a wait all, except the target + one (i.e. psdTgtObjectSynchData) + + Note: this method must be called while holding the synchronization locks + appropriate to all the objects involved in the wait-all. If any + of the objects is shared, the caller must own both local and + shared synch locks; if no shared object is involved in the wait, + only the local synch lock is needed. + --*/ + void CPalSynchronizationManager::UnsignalRestOfLocalAwakeningWaitAll( + CPalThread * pthrCurrent, + CPalThread * pthrTarget, + WaitingThreadsListNode * pwtlnNode, + CSynchData * psdTgtObjectSynchData) + { + PAL_ERROR palErr = NO_ERROR; + CSynchData * psdSynchDataItem = NULL; + +#ifdef _DEBUG + bool bOriginatingNodeFound = false; +#endif + + VALIDATEOBJECT(psdTgtObjectSynchData); + VALIDATEOBJECT(pwtlnNode); + + _ASSERT_MSG(0 != (WTLN_FLAG_WAIT_ALL & pwtlnNode->dwFlags), + "UnsignalRestOfLocalAwakeningWaitAll() called on a normal (non wait all) wait"); + + _ASSERT_MSG(gPID == pwtlnNode->dwProcessId, + "UnsignalRestOfLocalAwakeningWaitAll() called on a wait all with remote awakening"); + + ThreadWaitInfo *ptwiWaitInfo = pwtlnNode->ptwiWaitInfo; + + int iObjCount = ptwiWaitInfo->lObjCount; + for (int i = 0; i < iObjCount; i++) + { + WaitingThreadsListNode * pwtlnItem = ptwiWaitInfo->rgpWTLNodes[i]; + + VALIDATEOBJECT(pwtlnItem); + + if (0 != (WTLN_FLAG_OWNER_OBJECT_IS_SHARED & pwtlnItem->dwFlags)) + { + psdSynchDataItem = SharedIDToTypePointer(CSynchData, pwtlnItem->ptrOwnerObjSynchData.shrid); + } + else + { + psdSynchDataItem = pwtlnItem->ptrOwnerObjSynchData.ptr; + } + + VALIDATEOBJECT(psdSynchDataItem); + + // Skip originating node + if (psdTgtObjectSynchData == psdSynchDataItem) + { +#ifdef _DEBUG + bOriginatingNodeFound = true; +#endif + continue; + } + + palErr = psdSynchDataItem->ReleaseWaiterWithoutBlocking(pthrCurrent, pthrTarget); + if (NO_ERROR != palErr) + { + ERROR("ReleaseWaiterWithoutBlocking failed on SynchData @ %p [palErr = %u]\n", psdSynchDataItem, palErr); + } + } + + _ASSERT_MSG(bOriginatingNodeFound, "Couldn't find originating node while unsignaling rest of the wait all\n"); + } + + /*++ + Method: + CPalSynchronizationManager::MarkWaitForDelegatedObjectSignalingInProgress + + Marks all the thread waiting list nodes involved in the the current wait-all + for "delegated object signaling in progress", so that this wait cannot be + involved in another delegated object signaling that may happen while the + current object singaling is being tranfered to the target process (while + transfering it, synchronization locks are released in this process and later + grabbed again in the target process; in this time window another thread + could signal another object part of the same wait-all. In this case no + signal delegation must take place. + + Note: this method must be called while holding the synchronization locks + appropriate to the target object described by pwtlnNode (i.e. the + local process synch lock if the target object is local, both local + and shared one if the object is shared). + --*/ + void CPalSynchronizationManager::MarkWaitForDelegatedObjectSignalingInProgress( + CPalThread * pthrCurrent, + WaitingThreadsListNode * pwtlnNode) + { + bool fSharedSynchLock = false; + bool fTargetObjectIsShared = (0 != (WTLN_FLAG_OWNER_OBJECT_IS_SHARED & pwtlnNode->dwFlags)); + + VALIDATEOBJECT(pwtlnNode); + + _ASSERT_MSG(gPID == pwtlnNode->dwProcessId, + "MarkWaitForDelegatedObjectSignalingInProgress() called from the wrong process"); + + ThreadWaitInfo *ptwiWaitInfo = pwtlnNode->ptwiWaitInfo; + + if (!fSharedSynchLock && !fTargetObjectIsShared && + LocalWait != ptwiWaitInfo->wdWaitDomain) + { + AcquireSharedSynchLock(pthrCurrent); + fSharedSynchLock = true; + } + + _ASSERT_MSG(MultipleObjectsWaitAll == ptwiWaitInfo->wtWaitType, + "MarkWaitForDelegatedObjectSignalingInProgress() called on a normal (non wait-all) wait"); + + // Unmark all nodes other than the target one + int iTgtCount = ptwiWaitInfo->lObjCount; + for (int i = 0; i < iTgtCount; i++) + { + VALIDATEOBJECT(ptwiWaitInfo->rgpWTLNodes[i]); + ptwiWaitInfo->rgpWTLNodes[i]->dwFlags &= ~WTLN_FLAG_DELEGATED_OBJECT_SIGNALING_IN_PROGRESS; + } + + // Mark the target node + pwtlnNode->dwFlags |= WTLN_FLAG_DELEGATED_OBJECT_SIGNALING_IN_PROGRESS; + + // Done + if (fSharedSynchLock) + { + ReleaseSharedSynchLock(pthrCurrent); + } + + return; + } + + /*++ + Method: + CPalSynchronizationManager::UnmarkTWListForDelegatedObjectSignalingInProgress + + Resets the "delegated object signaling in progress" flags in all the + nodes of the thread waitin list for the target waitable objects (represented + by its SynchData) + + Note: this method must be called while holding the appropriate + synchronization locks (the local process synch lock if the target + object is local, both local and shared one if the object is shared). + --*/ + void CPalSynchronizationManager::UnmarkTWListForDelegatedObjectSignalingInProgress( + CSynchData * pTgtObjectSynchData) + { + bool fSharedObject = (SharedObject == pTgtObjectSynchData->GetObjectDomain()); + WaitingThreadsListNode * pwtlnNode; + + VALIDATEOBJECT(pTgtObjectSynchData); + + pwtlnNode = fSharedObject ? SharedIDToTypePointer(WaitingThreadsListNode, pTgtObjectSynchData->GetWTLHeadShmPtr()) + : pTgtObjectSynchData->GetWTLHeadPtr(); + + while (pwtlnNode) + { + VALIDATEOBJECT(pwtlnNode); + + pwtlnNode->dwFlags &= ~WTLN_FLAG_DELEGATED_OBJECT_SIGNALING_IN_PROGRESS; + pwtlnNode = fSharedObject ? SharedIDToTypePointer(WaitingThreadsListNode, pwtlnNode->ptrNext.shrid) + : pwtlnNode->ptrNext.ptr; + } + } + + /*++ + Method: + CPalSynchronizationManager::RegisterProcessForMonitoring + + Registers the process object represented by the passed psdSynchData and + pProcLocalData. The worker thread will monitor the actual process and, + upon process termination, it will set the exit code in pProcLocalData, + and it will signal the process object, by signaling its psdSynchData. + --*/ + PAL_ERROR CPalSynchronizationManager::RegisterProcessForMonitoring( + CPalThread * pthrCurrent, + CSynchData *psdSynchData, + IPalObject *pProcessObject, + CProcProcessLocalData * pProcLocalData) + { + PAL_ERROR palErr = NO_ERROR; + MonitoredProcessesListNode * pmpln; + bool fWakeUpWorker = false; + bool fMonitoredProcessesLock = false; + + VALIDATEOBJECT(psdSynchData); + + InternalEnterCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + + fMonitoredProcessesLock = true; + + pmpln = m_pmplnMonitoredProcesses; + while (pmpln) + { + if (psdSynchData == pmpln->psdSynchData) + { + _ASSERT_MSG(pmpln->dwPid == pProcLocalData->dwProcessId, "Invalid node in Monitored Processes List\n"); + break; + } + + pmpln = pmpln->pNext; + } + + if (pmpln) + { + pmpln->lRefCount++; + } + else + { + pmpln = InternalNew(); + if (NULL == pmpln) + { + ERROR("No memory to allocate MonitoredProcessesListNode structure\n"); + palErr = ERROR_NOT_ENOUGH_MEMORY; + goto RPFM_exit; + } + + pmpln->lRefCount = 1; + pmpln->dwPid = pProcLocalData->dwProcessId; + pmpln->dwExitCode = 0; + pmpln->pProcessObject = pProcessObject; + pmpln->pProcessObject->AddReference(); + pmpln->pProcLocalData = pProcLocalData; + + // Acquire SynchData and AddRef it + pmpln->psdSynchData = psdSynchData; + psdSynchData->AddRef(); + + pmpln->pNext = m_pmplnMonitoredProcesses; + m_pmplnMonitoredProcesses = pmpln; + m_lMonitoredProcessesCount++; + + fWakeUpWorker = true; + } + + // Unlock + InternalLeaveCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + fMonitoredProcessesLock = false; + + if (fWakeUpWorker) + { + CPalSynchronizationManager * pSynchManager = GetInstance(); + + palErr = pSynchManager->WakeUpLocalWorkerThread(SynchWorkerCmdNop); + if (NO_ERROR != palErr) + { + ERROR("Failed waking up worker thread for process " + "monitoring registration [errno=%d {%s%}]\n", + errno, strerror(errno)); + palErr = ERROR_INTERNAL_ERROR; + } + } + + RPFM_exit: + if (fMonitoredProcessesLock) + { + InternalLeaveCriticalSection(pthrCurrent, + &s_csMonitoredProcessesLock); + } + + return palErr; + } + + /*++ + Method: + CPalSynchronizationManager::UnRegisterProcessForMonitoring + + Unregisters a process object currently monitored by the worker thread + (typically called if the wait timed out before the process exited, or + if the wait was a normal (i.e. non wait-all) wait that involved othter + objects, and another object has been signaled). + --*/ + PAL_ERROR CPalSynchronizationManager::UnRegisterProcessForMonitoring( + CPalThread * pthrCurrent, + CSynchData *psdSynchData, + DWORD dwPid) + { + PAL_ERROR palErr = NO_ERROR; + MonitoredProcessesListNode * pmpln, * pmplnPrev = NULL; + + VALIDATEOBJECT(psdSynchData); + + InternalEnterCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + + pmpln = m_pmplnMonitoredProcesses; + while (pmpln) + { + if (psdSynchData == pmpln->psdSynchData) + { + _ASSERT_MSG(dwPid == pmpln->dwPid, "Invalid node in Monitored Processes List\n"); + break; + } + + pmplnPrev = pmpln; + pmpln = pmpln->pNext; + } + + if (pmpln) + { + if (0 == --pmpln->lRefCount) + { + if (NULL != pmplnPrev) + { + pmplnPrev->pNext = pmpln->pNext; + } + else + { + m_pmplnMonitoredProcesses = pmpln->pNext; + } + + m_lMonitoredProcessesCount--; + pmpln->pProcessObject->ReleaseReference(pthrCurrent); + pmpln->psdSynchData->Release(pthrCurrent); + InternalDelete(pmpln); + } + } + else + { + palErr = ERROR_NOT_FOUND; + } + + InternalLeaveCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + return palErr; + } + + /*++ + Method: + CPalSynchronizationManager::ThreadPrepareForShutdown + + Used to hijack thread execution from known spots within the + Synchronization Manager in case a PAL shutdown is initiated + or the thread is being terminated by another thread. + --*/ + void CPalSynchronizationManager::ThreadPrepareForShutdown() + { + TRACE("The Synchronization Manager hijacked the current thread " + "for process shutdown or thread termination\n"); + while (true) + { + poll(NULL, 0, INFTIM); + sched_yield(); + } + + ASSERT("This code should never be executed\n"); + } + + /*++ + Method: + CPalSynchronizationManager::DoMonitorProcesses + + This method is called by the worker thread to execute one step of + monitoring for all the process currently registered for monitoring + --*/ + LONG CPalSynchronizationManager::DoMonitorProcesses( + CPalThread * pthrCurrent) + { + MonitoredProcessesListNode * pNode, * pPrev = NULL, * pNext; + LONG lInitialNodeCount; + LONG lRemovingCount = 0; + bool fLocalSynchLock = false; + bool fSharedSynchLock = false; + bool fMonitoredProcessesLock = false; + + // Note: we first need to grab the monitored processes lock to walk + // the list of monitored processes, and then, if there is any + // which exited, to grab the synchronization lock(s) to signal + // the process object. Anyway we cannot grab the synchronization + // lock(s) while holding the monitored processes lock; that + // would cause deadlock, since RegisterProcessForMonitoring and + // UnRegisterProcessForMonitoring call stacks grab the locks + // in the opposite order. Grabbing the synch lock(s) first (and + // therefore all the times) would cause unacceptable contention + // (process monitoring is done in polling mode). + // Therefore we need to remove list nodes for processes that + // exited copying them to the exited array, while holding only + // the monitored processes lock, and then to signal them from that + // array holding synch lock(s) and monitored processes lock, + // acquired in this order. Holding again the monitored processes + // lock is needed in order to support object promotion. + + // Grab the monitored processes lock + InternalEnterCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + fMonitoredProcessesLock = true; + + lInitialNodeCount = m_lMonitoredProcessesCount; + + pNode = m_pmplnMonitoredProcesses; + while (pNode) + { + pNext = pNode->pNext; + + if (HasProcessExited(pNode->dwPid, + &pNode->dwExitCode, + &pNode->fIsActualExitCode)) + { + TRACE("Process %u exited with return code %u\n", + pNode->dwPid, + pNode->fIsActualExitCode ? "actual" : "guessed", + pNode->dwExitCode); + + if (NULL != pPrev) + { + pPrev->pNext = pNext; + } + else + { + m_pmplnMonitoredProcesses = pNext; + } + + m_lMonitoredProcessesCount--; + + // Insert in the list of nodes for exited processes + pNode->pNext = m_pmplnExitedNodes; + m_pmplnExitedNodes = pNode; + lRemovingCount++; + } + else + { + pPrev = pNode; + } + + // Go to the next + pNode = pNext; + } + + // Release the monitored processes lock + InternalLeaveCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + fMonitoredProcessesLock = false; + + if (lRemovingCount > 0) + { + // First grab the local synch lock + AcquireLocalSynchLock(pthrCurrent); + fLocalSynchLock = true; + + // Acquire the monitored processes lock + InternalEnterCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + fMonitoredProcessesLock = true; + + if (!fSharedSynchLock) + { + bool fSharedSynchLockIsNeeded = false; + + // See if the shared lock is needed + pNode = m_pmplnExitedNodes; + while (pNode) + { + if (SharedObject == pNode->psdSynchData->GetObjectDomain()) + { + fSharedSynchLockIsNeeded = true; + break; + } + + pNode = pNode->pNext; + } + + if (fSharedSynchLockIsNeeded) + { + // Release the monitored processes lock + InternalLeaveCriticalSection(pthrCurrent, + &s_csMonitoredProcessesLock); + fMonitoredProcessesLock = false; + + // Acquire the shared synch lock + AcquireSharedSynchLock(pthrCurrent); + fSharedSynchLock = true; + + // Acquire again the monitored processes lock + InternalEnterCriticalSection(pthrCurrent, + &s_csMonitoredProcessesLock); + fMonitoredProcessesLock = true; + } + } + + // Start from the beginning of the exited processes list + pNode = m_pmplnExitedNodes; + + // Invalidate the list + m_pmplnExitedNodes = NULL; + + while (pNode) + { + pNext = pNode->pNext; + + TRACE("Process pid=%u exited with exitcode=%u\n", + pNode->dwPid, pNode->dwExitCode); + + // Store the exit code in the process local data + if (pNode->fIsActualExitCode) + { + pNode->pProcLocalData->dwExitCode = pNode->dwExitCode; + } + + // Set process status to PS_DONE + pNode->pProcLocalData->ps = PS_DONE; + + // Set signal count + pNode->psdSynchData->SetSignalCount(1); + + // Releasing all local waiters + // + // We just called directly in CSynchData::SetSignalCount(), so + // we need to take care of waking up waiting threads according + // to the Process object semantics (i.e. every thread must be + // awakend). Anyway if a process object is shared among two or + // more processes and threads from different processes are + // waiting on it, the object will be registered for monitoring + // in each of the processes. As result its signal count will + // be set to one more times (which is not a problem, given the + // process object semantics) and each worker thread will wake + // up waiting threads. Therefore we need to make sure that each + // worker wakes up only threads in its own process: we do that + // by calling ReleaseAllLocalWaiters + pNode->psdSynchData->ReleaseAllLocalWaiters(pthrCurrent); + + // We are done with pProcLocalData, so we can release the process object + pNode->pProcessObject->ReleaseReference(pthrCurrent); + + // Release the reference to the SynchData + pNode->psdSynchData->Release(pthrCurrent); + + // Delete the node + InternalDelete(pNode); + + // Go to the next + pNode = pNext; + } + } + + if (fMonitoredProcessesLock) + { + InternalLeaveCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + } + + if (fSharedSynchLock) + { + ReleaseSharedSynchLock(pthrCurrent); + } + + if (fLocalSynchLock) + { + ReleaseLocalSynchLock(pthrCurrent); + } + + return (lInitialNodeCount - lRemovingCount); + } + + /*++ + Method: + CPalSynchronizationManager::DiscardMonitoredProcesses + + This method is called at shutdown time to discard all the registration + for the processes currently monitored by the worker thread. + This method must be called at shutdown time, otherwise some shared memory + may be leaked at process shutdown. + --*/ + void CPalSynchronizationManager::DiscardMonitoredProcesses( + CPalThread * pthrCurrent) + { + MonitoredProcessesListNode * pNode; + + // Grab the monitored processes lock + InternalEnterCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + + while (m_pmplnMonitoredProcesses) + { + pNode = m_pmplnMonitoredProcesses; + m_pmplnMonitoredProcesses = pNode->pNext; + pNode->pProcessObject->ReleaseReference(pthrCurrent); + pNode->psdSynchData->Release(pthrCurrent); + InternalDelete(pNode); + } + + // Release the monitored processes lock + InternalLeaveCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + } + + /*++ + Method: + CPalSynchronizationManager::CreateProcessPipe + + Creates the process pipe for the current process + --*/ + bool CPalSynchronizationManager::CreateProcessPipe() + { + bool fRet = true; +#if HAVE_KQUEUE && !HAVE_BROKEN_FIFO_KEVENT + int iKq = -1; +#endif // HAVE_KQUEUE && !HAVE_BROKEN_FIFO_KEVENT + +#ifndef CORECLR + int iPipeRd = -1, iPipeWr = -1; + char szPipeFilename[MAX_PATH]; + + /* Create the blocking pipe */ + if (!GetProcessPipeName(szPipeFilename, MAX_PATH, gPID)) + { + ERROR("couldn't get process pipe's name\n"); + szPipeFilename[0] = 0; + fRet = false; + goto CPP_exit; + } + + /* create the pipe, with full access to the owner only */ + if (mkfifo(szPipeFilename, S_IRWXU) == -1) + { + if (errno == EEXIST) + { + /* Some how no one deleted the pipe, perhaps it was left behind + from a crash?? Delete the pipe and try again. */ + if (-1 == unlink(szPipeFilename)) + { + ERROR( "Unable to delete the process pipe that was left behind.\n" ); + fRet = false; + goto CPP_exit; + } + else + { + if (mkfifo(szPipeFilename, S_IRWXU) == -1) + { + ERROR( "Still unable to create the process pipe...giving up!\n" ); + fRet = false; + goto CPP_exit; + } + } + } + else + { + ERROR( "Unable to create the process pipe.\n" ); + fRet = false; + goto CPP_exit; + } + } + + iPipeRd = InternalOpen(szPipeFilename, O_RDONLY | O_NONBLOCK); + if (iPipeRd == -1) + { + ERROR("Unable to open the process pipe for read\n"); + fRet = false; + goto CPP_exit; + } + + iPipeWr = InternalOpen(szPipeFilename, O_WRONLY | O_NONBLOCK); + if (iPipeWr == -1) + { + ERROR("Unable to open the process pipe for write\n"); + fRet = false; + goto CPP_exit; + } +#else // !CORECLR + int rgiPipe[] = { -1, -1 }; + int pipeRv = +#if HAVE_PIPE2 + pipe2(rgiPipe, O_CLOEXEC); +#else + pipe(rgiPipe); +#endif // HAVE_PIPE2 + if (pipeRv == -1) + { + ERROR("Unable to create the process pipe\n"); + fRet = false; + goto CPP_exit; + } +#if !HAVE_PIPE2 + fcntl(rgiPipe[0], F_SETFD, FD_CLOEXEC); // make pipe non-inheritable, if possible + fcntl(rgiPipe[1], F_SETFD, FD_CLOEXEC); +#endif // !HAVE_PIPE2 +#endif // !CORECLR + +#if HAVE_KQUEUE && !HAVE_BROKEN_FIFO_KEVENT + iKq = kqueue(); + if (-1 == iKq) + { + ERROR("Failed to create kqueue associated to process pipe\n"); + fRet = false; + goto CPP_exit; + } +#endif // HAVE_KQUEUE + + CPP_exit: + if (fRet) + { + // Succeeded +#ifndef CORECLR + m_iProcessPipeRead = iPipeRd; + m_iProcessPipeWrite = iPipeWr; +#else // !CORECLR + m_iProcessPipeRead = rgiPipe[0]; + m_iProcessPipeWrite = rgiPipe[1]; +#endif // !CORECLR +#if HAVE_KQUEUE && !HAVE_BROKEN_FIFO_KEVENT + m_iKQueue = iKq; +#endif // HAVE_KQUEUE + } + else + { +#ifndef CORECLR + // Failed + if (0 != szPipeFilename[0]) + { + unlink(szPipeFilename); + } + if (-1 != iPipeRd) + { + close(iPipeRd); + } + if (-1 != iPipeWr) + { + close(iPipeWr); + } +#else // !CORECLR + if (-1 != rgiPipe[0]) + { + close(rgiPipe[0]); + close(rgiPipe[1]); + } +#endif // !CORECLR +#if HAVE_KQUEUE && !HAVE_BROKEN_FIFO_KEVENT + if (-1 != iKq) + { + close(iKq); + } +#endif // HAVE_KQUEUE + } + + return fRet; + } + + /*++ + Method: + CPalSynchronizationManager::ShutdownProcessPipe + + Shuts down the process pipe and removes the fifo so that other processes + can no longer open it. It also closes the local write end of the pipe (see + comment below). From this moment on the worker thread will process any + possible data already received in the pipe (but not yet consumed) and any + data written by processes that still have a opened write end of this pipe; + it will wait (with timeout) until the last remote process which has a write + end opened closes it, and then it will yield to process shutdown. + --*/ + PAL_ERROR CPalSynchronizationManager::ShutdownProcessPipe() + { + PAL_ERROR palErr = NO_ERROR; +#ifndef CORECLR + char szPipeFilename[MAX_PATH]; + + if (GetProcessPipeName(szPipeFilename, MAX_PATH, gPID)) + { + if (unlink(szPipeFilename) == -1) + { + ERROR("Unable to unlink the pipe file name errno=%d (%s)\n", + errno, strerror(errno)); + palErr = ERROR_INTERNAL_ERROR; + // go on anyway + } + } + else + { + ERROR("Couldn't get the process pipe's name\n"); + palErr = ERROR_INTERNAL_ERROR; + // go on anyway + } +#endif // CORECLR + + if (-1 != m_iProcessPipeWrite) + { + // Closing the write end of the process pipe. When the last process + // that still has a open write-fd on this pipe will close it, the + // worker thread will receive an EOF; the worker thread will wait + // for this EOF before shutting down, so to ensure to process any + // possible data already written to the pipe by other processes + // when the shutdown has been initiated in the current process. + // Note: no need here to worry about platforms where close(pipe) + // blocks on outstanding syscalls, since we are the only one using + // this fd. + TRACE("Closing the write end of process pipe\n"); + if (close(m_iProcessPipeWrite) == -1) + { + ERROR("Unable to close the write end of process pipe\n"); + palErr = ERROR_INTERNAL_ERROR; + } + + m_iProcessPipeWrite = -1; + } + + return palErr; + } + +#ifndef CORECLR + /*++ + Method: + CPalSynchronizationManager::GetProcessPipeName + + Returns the process pipe name for the target process (identified by its PID) + --*/ + bool CPalSynchronizationManager::GetProcessPipeName( + LPSTR pDest, + int iDestSize, + DWORD dwPid) + { + CHAR config_dir[MAX_PATH]; + int needed_size; + + _ASSERT_MSG(NULL != pDest, "Destination pointer is NULL!\n"); + _ASSERT_MSG(0 < iDestSize,"Invalid buffer size %d\n", iDestSize); + + if (!PALGetPalConfigDir(config_dir, MAX_PATH)) + { + ASSERT("Unable to determine the PAL config directory.\n"); + pDest[0] = '\0'; + return false; + } + needed_size = snprintf(pDest, iDestSize, "%s/%s-%u", config_dir, + PROCESS_PIPE_NAME_PREFIX, dwPid); + pDest[iDestSize-1] = 0; + if(needed_size >= iDestSize) + { + ERROR("threadpipe name needs %d characters, buffer only has room for " + "%d\n", needed_size, iDestSize+1); + return false; + } + return true; + } +#endif // !CORECLR + + /*++ + Method: + CPalSynchronizationManager::AcquireProcessLock + + Acquires the local Process Lock (which currently is the same as the + the local Process Synch Lock) + --*/ + void CPalSynchronizationManager::AcquireProcessLock(CPalThread * pthrCurrent) + { + AcquireLocalSynchLock(pthrCurrent); + } + + /*++ + Method: + CPalSynchronizationManager::ReleaseProcessLock + + Releases the local Process Lock (which currently is the same as the + the local Process Synch Lock) + --*/ + void CPalSynchronizationManager::ReleaseProcessLock(CPalThread * pthrCurrent) + { + ReleaseLocalSynchLock(pthrCurrent); + } + + /*++ + Method: + CPalSynchronizationManager::PromoteObjectSynchData + + Promotes an object's synchdata from local to shared + --*/ + PAL_ERROR CPalSynchronizationManager::PromoteObjectSynchData( + CPalThread *pthrCurrent, + VOID *pvLocalSynchData, + VOID **ppvSharedSynchData) + { + PAL_ERROR palError = NO_ERROR; + CSynchData *psdLocal = reinterpret_cast(pvLocalSynchData); + CSynchData *psdShared = NULL; + SharedID shridSynchData = NULL; + SharedID *rgshridWTLNodes = NULL; + CObjectType *pot = NULL; + ULONG ulcWaitingThreads; + + _ASSERTE(NULL != pthrCurrent); + _ASSERTE(NULL != pvLocalSynchData); + _ASSERTE(NULL != ppvSharedSynchData); + _ASSERTE(ProcessLocalObject == psdLocal->GetObjectDomain()); + +#if _DEBUG + + // + // TODO: Verify that the proper locks are held + // +#endif + + // + // Allocate shared memory CSynchData and map to local memory + // + + shridSynchData = m_cacheSHRSynchData.Get(pthrCurrent); + if (NULL == shridSynchData) + { + ERROR("Unable to allocate shared memory\n"); + palError = ERROR_NOT_ENOUGH_MEMORY; + goto POSD_exit; + } + + psdShared = SharedIDToTypePointer(CSynchData, shridSynchData); + _ASSERTE(NULL != psdShared); + + // + // Allocate shared memory WaitingThreadListNodes if there are + // any threads currently waiting on this object + // + + ulcWaitingThreads = psdLocal->GetWaitingThreadCount(); + if (0 < ulcWaitingThreads) + { + int i; + + rgshridWTLNodes = InternalNewArray(ulcWaitingThreads); + if (NULL == rgshridWTLNodes) + { + palError = ERROR_OUTOFMEMORY; + goto POSD_exit; + } + + i = m_cacheSHRWTListNodes.Get( + pthrCurrent, + ulcWaitingThreads, + rgshridWTLNodes + ); + + if (static_cast(i) != ulcWaitingThreads) + { + for (i -= 1; i >= 0; i -= 1) + { + m_cacheSHRWTListNodes.Add(pthrCurrent, rgshridWTLNodes[i]); + } + + palError = ERROR_OUTOFMEMORY; + goto POSD_exit; + } + } + + // + // If the synch data is for a process object we need to grab + // the monitored process list lock here + // + + pot = psdLocal->GetObjectType(); + _ASSERTE(NULL != pot); + + if (otiProcess == pot->GetId()) + { + InternalEnterCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + } + + // + // Copy pertinent CSynchData info to the shared memory version (and + // initialize other members) + // + + psdShared->SetSharedThis(shridSynchData); + psdShared->SetObjectDomain(SharedObject); + psdShared->SetObjectType(psdLocal->GetObjectType()); + psdShared->SetSignalCount(psdLocal->GetSignalCount()); + +#ifdef SYNCH_STATISTICS + psdShared->SetStatContentionCount(psdLocal->GetStatContentionCount()); + psdShared->SetStatWaitCount(psdLocal->GetStatWaitCount()); +#endif + + // + // Rebuild the waiting thread list, and update the wait domain + // for the waiting threads + // + + psdShared->SetWTLHeadShrPtr(NULL); + psdShared->SetWTLTailShrPtr(NULL); + + if (0 < ulcWaitingThreads) + { + WaitingThreadsListNode *pwtlnOld; + WaitingThreadsListNode *pwtlnNew; + int i = 0; + + for (pwtlnOld = psdLocal->GetWTLHeadPtr(); + pwtlnOld != NULL; + pwtlnOld = pwtlnOld->ptrNext.ptr, i += 1) + { + pwtlnNew = SharedIDToTypePointer( + WaitingThreadsListNode, + rgshridWTLNodes[i] + ); + + _ASSERTE(NULL != pwtlnNew); + + pwtlnNew->shridSHRThis = rgshridWTLNodes[i]; + pwtlnNew->ptrOwnerObjSynchData.shrid = shridSynchData; + + pwtlnNew->dwThreadId = pwtlnOld->dwThreadId; + pwtlnNew->dwProcessId = pwtlnOld->dwProcessId; + pwtlnNew->dwObjIndex = pwtlnOld->dwObjIndex; + pwtlnNew->dwFlags = pwtlnOld->dwFlags | WTLN_FLAG_OWNER_OBJECT_IS_SHARED; + pwtlnNew->shridWaitingState = pwtlnOld->shridWaitingState; + pwtlnNew->ptwiWaitInfo = pwtlnOld->ptwiWaitInfo; + + psdShared->SharedWaiterEnqueue(rgshridWTLNodes[i], false); + psdShared->AddRef(); + + _ASSERTE(pwtlnOld = pwtlnOld->ptwiWaitInfo->rgpWTLNodes[pwtlnOld->dwObjIndex]); + pwtlnNew->ptwiWaitInfo->rgpWTLNodes[pwtlnNew->dwObjIndex] = pwtlnNew; + + pwtlnNew->ptwiWaitInfo->lSharedObjCount += 1; + if (pwtlnNew->ptwiWaitInfo->lSharedObjCount + == pwtlnNew->ptwiWaitInfo->lObjCount) + { + pwtlnNew->ptwiWaitInfo->wdWaitDomain = SharedWait; + } + else + { + _ASSERTE(pwtlnNew->ptwiWaitInfo->lSharedObjCount + < pwtlnNew->ptwiWaitInfo->lObjCount); + + pwtlnNew->ptwiWaitInfo->wdWaitDomain = MixedWait; + } + } + + _ASSERTE(psdShared->GetWaitingThreadCount() == ulcWaitingThreads); + } + + // + // If the object tracks ownership and has a current owner update + // the OwnedObjectsListNode to point to the shared memory synch + // data + // + + if (CObjectType::OwnershipTracked == pot->GetOwnershipSemantics()) + { + OwnedObjectsListNode *pooln; + + pooln = psdLocal->GetOwnershipListNode(); + if (NULL != pooln) + { + pooln->pPalObjSynchData = psdShared; + psdShared->SetOwnershipListNode(pooln); + psdShared->AddRef(); + + // + // Copy over other ownership info. + // + + psdShared->SetOwner(psdLocal->GetOwnerThread()); + psdShared->SetOwnershipCount(psdLocal->GetOwnershipCount()); + _ASSERTE(!psdShared->IsAbandoned()); + } + else + { + _ASSERTE(0 == psdLocal->GetOwnershipCount()); + _ASSERTE(0 == psdShared->GetOwnershipCount()); + psdShared->SetAbandoned(psdLocal->IsAbandoned()); + } + } + + // + // If the synch data is for a process object update the monitored + // process list nodes to point to the shared memory object data, + // and release the monitored process list lock + // + + if (otiProcess == pot->GetId()) + { + MonitoredProcessesListNode *pmpn; + + pmpn = m_pmplnMonitoredProcesses; + while (NULL != pmpn) + { + if (psdLocal == pmpn->psdSynchData) + { + pmpn->psdSynchData = psdShared; + psdShared->AddRef(); + } + + pmpn = pmpn->pNext; + } + + pmpn = m_pmplnExitedNodes; + while (NULL != pmpn) + { + if (psdLocal == pmpn->psdSynchData) + { + pmpn->psdSynchData = psdShared; + psdShared->AddRef(); + } + + pmpn = pmpn->pNext; + } + + InternalLeaveCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + } + + *ppvSharedSynchData = reinterpret_cast(shridSynchData); + + // + // Free the local memory items to caches + // + + if (0 < ulcWaitingThreads) + { + WaitingThreadsListNode *pwtln; + + pwtln = psdLocal->GetWTLHeadPtr(); + while (NULL != pwtln) + { + WaitingThreadsListNode *pwtlnTemp; + + pwtlnTemp = pwtln; + pwtln = pwtln->ptrNext.ptr; + m_cacheWTListNodes.Add(pthrCurrent, pwtlnTemp); + } + } + + m_cacheSynchData.Add(pthrCurrent, psdLocal); + + POSD_exit: + + if (NULL != rgshridWTLNodes) + { + InternalDeleteArray(rgshridWTLNodes); + } + + return palError; + } + + + ///////////////////////////// + // // + // _ThreadNativeWaitData // + // // + ///////////////////////////// + + _ThreadNativeWaitData::~_ThreadNativeWaitData() + { + if (fInitialized) + { + fInitialized = false; + pthread_cond_destroy(&cond); + pthread_mutex_destroy(&mutex); + } + } + + + ////////////////////////////////// + // // + // CThreadSynchronizationInfo // + // // + ////////////////////////////////// + + CThreadSynchronizationInfo::CThreadSynchronizationInfo() : + m_tsThreadState(TS_IDLE), + m_shridWaitAwakened(NULL), + m_lLocalSynchLockCount(0), + m_lSharedSynchLockCount(0), + m_ownedNamedMutexListHead(nullptr) + { + InitializeListHead(&m_leOwnedObjsList); + InitializeCriticalSection(&m_ownedNamedMutexListLock); + +#ifdef SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + m_lPendingSignalingCount = 0; + InitializeListHead(&m_lePendingSignalingsOverflowList); +#endif // SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + } + + CThreadSynchronizationInfo::~CThreadSynchronizationInfo() + { + DeleteCriticalSection(&m_ownedNamedMutexListLock); + if (NULL != m_shridWaitAwakened) + { + free(m_shridWaitAwakened); + } + } + + void CThreadSynchronizationInfo::AcquireNativeWaitLock() + { +#if !SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + int iRet; + iRet = pthread_mutex_lock(&m_tnwdNativeData.mutex); + _ASSERT_MSG(0 == iRet, "pthread_mutex_lock failed with error=%d\n", iRet); +#endif // !SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + } + + void CThreadSynchronizationInfo::ReleaseNativeWaitLock() + { +#if !SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + int iRet; + iRet = pthread_mutex_unlock(&m_tnwdNativeData.mutex); + _ASSERT_MSG(0 == iRet, "pthread_mutex_unlock failed with error=%d\n", iRet); +#endif // !SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + } + + bool CThreadSynchronizationInfo::TryAcquireNativeWaitLock() + { + bool fRet = true; +#if !SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + int iRet; + iRet = pthread_mutex_trylock(&m_tnwdNativeData.mutex); + _ASSERT_MSG(0 == iRet || EBUSY == iRet, + "pthread_mutex_trylock failed with error=%d\n", iRet); + fRet = (0 == iRet); +#endif // !SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + return fRet; + } + + /*++ + Method: + CThreadSynchronizationInfo::InitializePreCreate + + Part of CThreadSynchronizationInfo's initialization to be carried out + before actual thread creation + --*/ + PAL_ERROR CThreadSynchronizationInfo::InitializePreCreate(void) + { + PAL_ERROR palErr = NO_ERROR; + DWORD * pdwWaitState = NULL; + int iRet; + const int MaxUnavailableResourceRetries = 10; + int iEagains; + pthread_condattr_t attrs; + pthread_condattr_t *attrsPtr = nullptr; + + m_shridWaitAwakened = malloc(sizeof(DWORD)); + if (NULL == m_shridWaitAwakened) + { + ERROR("Fail allocating thread wait status shared object\n"); + palErr = ERROR_NOT_ENOUGH_MEMORY; + goto IPrC_exit; + } + + pdwWaitState = SharedIDToTypePointer(DWORD, + m_shridWaitAwakened); + + _ASSERT_MSG(NULL != pdwWaitState, + "Unable to map shared wait state: bad shared ID [shrid=%p]\n", (VOID*)m_shridWaitAwakened); + + VolatileStore(pdwWaitState, TWS_ACTIVE); + m_tsThreadState = TS_STARTING; + +#if HAVE_CLOCK_MONOTONIC && HAVE_PTHREAD_CONDATTR_SETCLOCK + attrsPtr = &attrs; + iRet = pthread_condattr_init(&attrs); + if (0 != iRet) + { + ERROR("Failed to initialize thread synchronization condition attribute " + "[error=%d (%s)]\n", iRet, strerror(iRet)); + if (ENOMEM == iRet) + { + palErr = ERROR_NOT_ENOUGH_MEMORY; + } + else + { + palErr = ERROR_INTERNAL_ERROR; + } + goto IPrC_exit; + } + + // Ensure that the pthread_cond_timedwait will use CLOCK_MONOTONIC + iRet = pthread_condattr_setclock(&attrs, CLOCK_MONOTONIC); + if (0 != iRet) + { + ERROR("Failed set thread synchronization condition timed wait clock " + "[error=%d (%s)]\n", iRet, strerror(iRet)); + palErr = ERROR_INTERNAL_ERROR; + pthread_condattr_destroy(&attrs); + goto IPrC_exit; + } +#endif // HAVE_CLOCK_MONOTONIC && HAVE_PTHREAD_CONDATTR_SETCLOCK + + iEagains = 0; + Mutex_retry: + iRet = pthread_mutex_init(&m_tnwdNativeData.mutex, NULL); + if (0 != iRet) + { + ERROR("Failed creating thread synchronization mutex [error=%d (%s)]\n", iRet, strerror(iRet)); + if (EAGAIN == iRet && MaxUnavailableResourceRetries >= ++iEagains) + { + poll(NULL, 0, std::min(100,10*iEagains)); + goto Mutex_retry; + } + else if (ENOMEM == iRet) + { + palErr = ERROR_NOT_ENOUGH_MEMORY; + } + else + { + palErr = ERROR_INTERNAL_ERROR; + } + + goto IPrC_exit; + } + + iEagains = 0; + Cond_retry: + + iRet = pthread_cond_init(&m_tnwdNativeData.cond, attrsPtr); + + if (0 != iRet) + { + ERROR("Failed creating thread synchronization condition " + "[error=%d (%s)]\n", iRet, strerror(iRet)); + if (EAGAIN == iRet && MaxUnavailableResourceRetries >= ++iEagains) + { + poll(NULL, 0, std::min(100,10*iEagains)); + goto Cond_retry; + } + else if (ENOMEM == iRet) + { + palErr = ERROR_NOT_ENOUGH_MEMORY; + } + else + { + palErr = ERROR_INTERNAL_ERROR; + } + pthread_mutex_destroy(&m_tnwdNativeData.mutex); + goto IPrC_exit; + } + + m_tnwdNativeData.fInitialized = true; + + IPrC_exit: + if (attrsPtr != nullptr) + { + pthread_condattr_destroy(attrsPtr); + } + if (NO_ERROR != palErr) + { + m_tsThreadState = TS_FAILED; + } + return palErr; + } + + /*++ + Method: + CThreadSynchronizationInfo::InitializePostCreate + + Part of CThreadSynchronizationInfo's initialization to be carried out + after actual thread creation + --*/ + PAL_ERROR CThreadSynchronizationInfo::InitializePostCreate( + CPalThread *pthrCurrent, + SIZE_T threadId, + DWORD dwLwpId) + { + PAL_ERROR palErr = NO_ERROR; + + if (TS_FAILED == m_tsThreadState) + { + palErr = ERROR_INTERNAL_ERROR; + } + + m_twiWaitInfo.pthrOwner = pthrCurrent; + + return palErr; + } + + + /*++ + Method: + CThreadSynchronizationInfo::AddObjectToOwnedList + + Adds an object to the list of currently owned objects. + --*/ + void CThreadSynchronizationInfo::AddObjectToOwnedList(POwnedObjectsListNode pooln) + { + InsertTailList(&m_leOwnedObjsList, &pooln->Link); + } + + /*++ + Method: + CThreadSynchronizationInfo::RemoveObjectFromOwnedList + + Removes an object from the list of currently owned objects. + --*/ + void CThreadSynchronizationInfo::RemoveObjectFromOwnedList(POwnedObjectsListNode pooln) + { + RemoveEntryList(&pooln->Link); + } + + /*++ + Method: + CThreadSynchronizationInfo::RemoveFirstObjectFromOwnedList + + Removes the first object from the list of currently owned objects. + --*/ + POwnedObjectsListNode CThreadSynchronizationInfo::RemoveFirstObjectFromOwnedList() + { + OwnedObjectsListNode * poolnItem; + + if (IsListEmpty(&m_leOwnedObjsList)) + { + poolnItem = NULL; + } + else + { + PLIST_ENTRY pLink = RemoveHeadList(&m_leOwnedObjsList); + poolnItem = CONTAINING_RECORD(pLink, OwnedObjectsListNode, Link); + } + + return poolnItem; + } + + void CThreadSynchronizationInfo::AddOwnedNamedMutex(NamedMutexProcessData *processData) + { + _ASSERTE(processData != nullptr); + _ASSERTE(processData->GetNextInThreadOwnedNamedMutexList() == nullptr); + + EnterCriticalSection(&m_ownedNamedMutexListLock); + processData->SetNextInThreadOwnedNamedMutexList(m_ownedNamedMutexListHead); + m_ownedNamedMutexListHead = processData; + LeaveCriticalSection(&m_ownedNamedMutexListLock); + } + + void CThreadSynchronizationInfo::RemoveOwnedNamedMutex(NamedMutexProcessData *processData) + { + _ASSERTE(processData != nullptr); + + EnterCriticalSection(&m_ownedNamedMutexListLock); + if (m_ownedNamedMutexListHead == processData) + { + m_ownedNamedMutexListHead = processData->GetNextInThreadOwnedNamedMutexList(); + processData->SetNextInThreadOwnedNamedMutexList(nullptr); + } + else + { + bool found = false; + for (NamedMutexProcessData + *previous = m_ownedNamedMutexListHead, + *current = previous->GetNextInThreadOwnedNamedMutexList(); + current != nullptr; + previous = current, current = current->GetNextInThreadOwnedNamedMutexList()) + { + if (current == processData) + { + found = true; + previous->SetNextInThreadOwnedNamedMutexList(current->GetNextInThreadOwnedNamedMutexList()); + current->SetNextInThreadOwnedNamedMutexList(nullptr); + break; + } + } + _ASSERTE(found); + } + LeaveCriticalSection(&m_ownedNamedMutexListLock); + } + + NamedMutexProcessData *CThreadSynchronizationInfo::RemoveFirstOwnedNamedMutex() + { + EnterCriticalSection(&m_ownedNamedMutexListLock); + NamedMutexProcessData *processData = m_ownedNamedMutexListHead; + if (processData != nullptr) + { + m_ownedNamedMutexListHead = processData->GetNextInThreadOwnedNamedMutexList(); + processData->SetNextInThreadOwnedNamedMutexList(nullptr); + } + LeaveCriticalSection(&m_ownedNamedMutexListLock); + return processData; + } + + bool CThreadSynchronizationInfo::OwnsNamedMutex(NamedMutexProcessData *processData) + { + EnterCriticalSection(&m_ownedNamedMutexListLock); + bool found = false; + for (NamedMutexProcessData *current = m_ownedNamedMutexListHead; + current != nullptr; + current = current->GetNextInThreadOwnedNamedMutexList()) + { + if (current == processData) + { + found = true; + break; + } + } + LeaveCriticalSection(&m_ownedNamedMutexListLock); + return found; + } + +#if SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + + /*++ + Method: + CThreadSynchronizationInfo::RunDeferredThreadConditionSignalings + + Carries out all the pending condition signalings for the current thread. + --*/ + PAL_ERROR CThreadSynchronizationInfo::RunDeferredThreadConditionSignalings() + { + PAL_ERROR palErr = NO_ERROR; + + _ASSERTE(0 <= m_lPendingSignalingCount); + + if (0 < m_lPendingSignalingCount) + { + LONG lArrayPendingSignalingCount = std::min(PendingSignalingsArraySize, m_lPendingSignalingCount); + LONG lIdx = 0; + PAL_ERROR palTempErr; + + // Signal all the pending signalings from the array + for (lIdx = 0; lIdx < lArrayPendingSignalingCount; lIdx++) + { + // Do the actual signaling + palTempErr = CPalSynchronizationManager::SignalThreadCondition( + m_rgpthrPendingSignalings[lIdx]->synchronizationInfo.GetNativeData()); + if (NO_ERROR != palTempErr) + { + palErr = palTempErr; + } + + // Release the thread reference + m_rgpthrPendingSignalings[lIdx]->ReleaseThreadReference(); + } + + // Signal any pending signalings from the array overflow list + if (m_lPendingSignalingCount > PendingSignalingsArraySize) + { + PLIST_ENTRY pLink; + DeferredSignalingListNode * pdsln; + + while (!IsListEmpty(&m_lePendingSignalingsOverflowList)) + { + // Remove a node from the head of the queue + // Note: no need to synchronize the access to this list since + // it is meant to be accessed only by the owner thread. + pLink = RemoveHeadList(&m_lePendingSignalingsOverflowList); + pdsln = CONTAINING_RECORD(pLink, + DeferredSignalingListNode, + Link); + + // Do the actual signaling + palTempErr = CPalSynchronizationManager::SignalThreadCondition( + pdsln->pthrTarget->synchronizationInfo.GetNativeData()); + if (NO_ERROR != palTempErr) + { + palErr = palTempErr; + } + + // Release the thread reference + pdsln->pthrTarget->ReleaseThreadReference(); + + // Delete the node + InternalDelete(pdsln); + + lIdx += 1; + } + + _ASSERTE(lIdx == m_lPendingSignalingCount); + } + + // Reset the counter of pending signalings for this thread + m_lPendingSignalingCount = 0; + } + + return palErr; + } + +#endif // SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + + /*++ + Method: + CPalSynchronizationManager::HasProcessExited + + Tests whether or not a process has exited + --*/ + bool CPalSynchronizationManager::HasProcessExited( + DWORD dwPid, + DWORD * pdwExitCode, + bool * pfIsActualExitCode) + { + pid_t pidWaitRetval; + int iStatus; + bool fRet = false; + + TRACE("Looking for status of process; trying wait()\n"); + + while(1) + { + /* try to get state of process, using non-blocking call */ + pidWaitRetval = waitpid(dwPid, &iStatus, WNOHANG); + + if ((DWORD)pidWaitRetval == dwPid) + { + /* success; get the exit code */ + if (WIFEXITED(iStatus)) + { + *pdwExitCode = WEXITSTATUS(iStatus); + *pfIsActualExitCode = true; + TRACE("Exit code was %d\n", *pdwExitCode); + } + else + { + WARN("Process terminated without exiting; can't get exit " + "code. Assuming EXIT_FAILURE.\n"); + *pfIsActualExitCode = true; + *pdwExitCode = EXIT_FAILURE; + } + + fRet = true; + } + else if (0 == pidWaitRetval) + { + // The process is still running. + TRACE("Process %#x is still active.\n", dwPid); + } + else + { + // A legitimate cause of failure is EINTR; if this happens we + // have to try again. A second legitimate cause is ECHILD, which + // happens if we're trying to retrieve the status of a currently- + // running process that isn't a child of this process. + if(EINTR == errno) + { + TRACE("waitpid() failed with EINTR; re-waiting\n"); + continue; + } + else if (ECHILD == errno) + { + TRACE("waitpid() failed with ECHILD; calling kill instead\n"); + if (kill(dwPid, 0) != 0) + { + if (ESRCH == errno) + { + WARN("kill() failed with ESRCH, i.e. target " + "process exited and it wasn't a child, " + "so can't get the exit code, assuming " + "it was 0.\n"); + *pfIsActualExitCode = false; + *pdwExitCode = 0; + } + else + { + ERROR("kill(pid, 0) failed; errno is %d (%s)\n", + errno, strerror(errno)); + *pfIsActualExitCode = false; + *pdwExitCode = EXIT_FAILURE; + } + + fRet = true; + } + } + else + { + // Ignoring unexpected waitpid errno and assuming that + // the process is still running + ERROR("waitpid(pid=%u) failed with errno=%d (%s)\n", + dwPid, errno, strerror(errno)); + } + } + + // Break out of the loop in all cases except EINTR. + break; + } + + return fRet; + } + + /*++ + Method: + CPalSynchronizationManager::InterlockedAwaken + + Tries to change the target wait status to 'active' in an interlocked fashion + --*/ + bool CPalSynchronizationManager::InterlockedAwaken( + DWORD *pWaitState, + bool fAlertOnly) + { + DWORD dwPrevState; + + dwPrevState = InterlockedCompareExchange((LONG *)pWaitState, TWS_ACTIVE, TWS_ALERTABLE); + if (TWS_ALERTABLE != dwPrevState) + { + if (fAlertOnly) + { + return false; + } + + dwPrevState = InterlockedCompareExchange((LONG *)pWaitState, TWS_ACTIVE, TWS_WAITING); + if (TWS_WAITING == dwPrevState) + { + return true; + } + } + else + { + return true; + } + + return false; + } + + /*++ + Method: + CPalSynchronizationManager::GetAbsoluteTimeout + + Converts a relative timeout to an absolute one. + --*/ + PAL_ERROR CPalSynchronizationManager::GetAbsoluteTimeout(DWORD dwTimeout, struct timespec * ptsAbsTmo, BOOL fPreferMonotonicClock) + { + PAL_ERROR palErr = NO_ERROR; + int iRet; + +#if HAVE_CLOCK_MONOTONIC && HAVE_PTHREAD_CONDATTR_SETCLOCK + if (fPreferMonotonicClock) + { + iRet = clock_gettime(CLOCK_MONOTONIC, ptsAbsTmo); + } + else + { +#endif +#if HAVE_WORKING_CLOCK_GETTIME + // Not every platform implements a (working) clock_gettime + iRet = clock_gettime(CLOCK_REALTIME, ptsAbsTmo); +#elif HAVE_WORKING_GETTIMEOFDAY + // Not every platform implements a (working) gettimeofday + struct timeval tv; + iRet = gettimeofday(&tv, NULL); + if (0 == iRet) + { + ptsAbsTmo->tv_sec = tv.tv_sec; + ptsAbsTmo->tv_nsec = tv.tv_usec * tccMicroSecondsToNanoSeconds; + } +#else + #error "Don't know how to get hi-res current time on this platform" +#endif // HAVE_WORKING_CLOCK_GETTIME, HAVE_WORKING_GETTIMEOFDAY +#if HAVE_CLOCK_MONOTONIC && HAVE_PTHREAD_CONDATTR_SETCLOCK + } +#endif + if (0 == iRet) + { + ptsAbsTmo->tv_sec += dwTimeout / tccSecondsToMillieSeconds; + ptsAbsTmo->tv_nsec += (dwTimeout % tccSecondsToMillieSeconds) * tccMillieSecondsToNanoSeconds; + while (ptsAbsTmo->tv_nsec >= tccSecondsToNanoSeconds) + { + ptsAbsTmo->tv_sec += 1; + ptsAbsTmo->tv_nsec -= tccSecondsToNanoSeconds; + } + } + else + { + palErr = ERROR_INTERNAL_ERROR; + } + + return palErr; + } +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/synchmanager.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/synchmanager.hpp new file mode 100644 index 0000000..b9dd8ed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/synchmanager.hpp @@ -0,0 +1,1024 @@ +// 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: + + synchmanager.hpp + +Abstract: + Private header file for synchronization manager and + controllers implementation + + + +--*/ +#ifndef _SYNCHMANAGER_HPP_ +#define _SYNCHMANAGER_HPP_ + +#include "pal/synchobjects.hpp" +#include "pal/synchcache.hpp" +#include "pal/cs.hpp" +#include "pal/corunix.hpp" +#include "pal/thread.hpp" +#include "pal/procobj.hpp" +#include "pal/init.h" +#include "pal/process.h" + +#include +#include +#if HAVE_KQUEUE +#include +#endif // HAVE_KQUEUE +#include "pal/dbgmsg.h" + +#ifdef _DEBUG +// #define SYNCH_OBJECT_VALIDATION +// #define SYNCH_STATISTICS +#endif + +#ifdef SYNCH_OBJECT_VALIDATION +#define VALIDATEOBJECT(obj) ((obj)->ValidateObject()) +#else +#define VALIDATEOBJECT(obj) +#endif + +namespace CorUnix +{ + const DWORD WTLN_FLAG_OWNER_OBJECT_IS_SHARED = 1<<0; + const DWORD WTLN_FLAG_WAIT_ALL = 1<<1; + const DWORD WTLN_FLAG_DELEGATED_OBJECT_SIGNALING_IN_PROGRESS = 1<<2; + +#ifdef SYNCH_OBJECT_VALIDATION + const DWORD HeadSignature = 0x48454144; + const DWORD TailSignature = 0x5441494C; + const DWORD EmptySignature = 0xBAADF00D; +#endif + + enum THREAD_WAIT_STATE + { + TWS_ACTIVE, + TWS_WAITING, + TWS_ALERTABLE, + TWS_EARLYDEATH, + }; + + enum WaitCompletionState + { + WaitIsNotSatisfied, + WaitIsSatisfied, + WaitMayBeSatisfied + }; + + typedef union _SynchDataGenrPtr + { + SharedID shrid; + CSynchData * ptr; + } SynchDataGenrPtr; + + typedef union _WTLNodeGenrPtr + { + SharedID shrid; + struct _WaitingThreadsListNode * ptr; + } WTLNodeGenrPtr; + + typedef struct _WaitingThreadsListNode + { +#ifdef SYNCH_OBJECT_VALIDATION + DWORD dwDebugHeadSignature; +#endif + WTLNodeGenrPtr ptrNext; + WTLNodeGenrPtr ptrPrev; + SharedID shridSHRThis; + + // Data + DWORD dwThreadId; + DWORD dwProcessId; + DWORD dwObjIndex; + DWORD dwFlags; + + // Pointers to related objects + SharedID shridWaitingState; + SynchDataGenrPtr ptrOwnerObjSynchData; + struct _ThreadWaitInfo * ptwiWaitInfo; // valid only in the + // target process +#ifdef SYNCH_OBJECT_VALIDATION + _WaitingThreadsListNode(); + ~_WaitingThreadsListNode(); + void ValidateObject(void); + void ValidateEmptyObject(void); + void InvalidateObject(void); + + DWORD dwDebugTailSignature; +#endif + } WaitingThreadsListNode; + + typedef struct _DeferredSignalingListNode + { + LIST_ENTRY Link; + CPalThread * pthrTarget; + } DeferredSignalingListNode; + + typedef struct _OwnedObjectsListNode + { + LIST_ENTRY Link; + CSynchData * pPalObjSynchData; + } OwnedObjectsListNode; + + typedef struct _ThreadApcInfoNode + { + struct _ThreadApcInfoNode * pNext; + PAPCFUNC pfnAPC; + ULONG_PTR pAPCData; + } ThreadApcInfoNode; + + class CPalSynchronizationManager; // fwd declaration + class CProcProcessLocalData; // fwd declaration + + class CSynchData + { +#ifdef SYNCH_OBJECT_VALIDATION + DWORD m_dwDebugHeadSignature; +#endif + // NB: For perforformance purposes this class is supposed + // to have no virtual methods, and no destructor. + + WTLNodeGenrPtr m_ptrWTLHead; + WTLNodeGenrPtr m_ptrWTLTail; + ULONG m_ulcWaitingThreads; + SharedID m_shridThis; + ObjectDomain m_odObjectDomain; + PalObjectTypeId m_otiObjectTypeId; + LONG m_lRefCount; + LONG m_lSignalCount; + + // Ownership data + LONG m_lOwnershipCount; + DWORD m_dwOwnerPid; + DWORD m_dwOwnerTid; // used only by remote processes + // (thread ids may be recycled) + CPalThread * m_pOwnerThread; // valid only on the target process + OwnedObjectsListNode * m_poolnOwnedObjectListNode; + bool m_fAbandoned; + +#ifdef SYNCH_STATISTICS + ULONG m_lStatWaitCount; + ULONG m_lStatContentionCount; +#endif + + public: + CSynchData() + : m_ulcWaitingThreads(0), m_shridThis(NULL), m_lRefCount(1), + m_lSignalCount(0), m_lOwnershipCount(0), m_dwOwnerPid(0), + m_dwOwnerTid(0), m_pOwnerThread(NULL), + m_poolnOwnedObjectListNode(NULL), m_fAbandoned(false) + { + // m_ptrWTLHead, m_ptrWTLTail, m_odObjectDomain + // and m_otiObjectTypeId are initialized by + // CPalSynchronizationManager::AllocateObjectSynchData +#ifdef SYNCH_STATISTICS + m_lStatWaitCount = 0; + m_lStatContentionCount = 0; +#endif +#ifdef SYNCH_OBJECT_VALIDATION + ValidateEmptyObject(); + m_dwDebugHeadSignature = HeadSignature;; + m_dwDebugTailSignature = TailSignature; +#endif + } + + LONG AddRef() + { + return InterlockedIncrement(&m_lRefCount); + } + + LONG Release(CPalThread * pthrCurrent); + + bool CanWaiterWaitWithoutBlocking( + CPalThread * pWaiterThread, + bool * pfAbandoned); + + PAL_ERROR ReleaseWaiterWithoutBlocking( + CPalThread * pthrCurrent, + CPalThread * pthrTarget); + + void WaiterEnqueue(WaitingThreadsListNode * pwtlnNewNode, bool fPrioritize); + void SharedWaiterEnqueue(SharedID shridNewNode, bool fPrioritize); + + // Object Domain accessor methods + ObjectDomain GetObjectDomain(void) + { + return m_odObjectDomain; + } + void SetObjectDomain(ObjectDomain odObjectDomain) + { + m_odObjectDomain = odObjectDomain; + } + + // Object Type accessor methods + CObjectType * GetObjectType(void) + { + return CObjectType::GetObjectTypeById(m_otiObjectTypeId); + } + PalObjectTypeId GetObjectTypeId(void) + { + return m_otiObjectTypeId; + } + void SetObjectType(CObjectType * pot) + { + m_otiObjectTypeId = pot->GetId(); + } + void SetObjectType(PalObjectTypeId oti) + { + m_otiObjectTypeId = oti; + } + + // Object shared 'this' pointer accessor methods + SharedID GetSharedThis (void) + { + return m_shridThis; + } + void SetSharedThis (SharedID shridThis) + { + m_shridThis = shridThis; + } + + void Signal( + CPalThread * pthrCurrent, + LONG lSignalCount, + bool fWorkerThread); + + bool ReleaseFirstWaiter( + CPalThread * pthrCurrent, + bool * pfDelegated, + bool fWorkerThread); + + LONG ReleaseAllLocalWaiters( + CPalThread * pthrCurrent); + + WaitCompletionState IsRestOfWaitAllSatisfied( + WaitingThreadsListNode * pwtlnNode); + + // Object signal count accessor methods + LONG GetSignalCount(void) + { + _ASSERTE(m_lSignalCount >= 0); + return m_lSignalCount; + } + void SetSignalCount(LONG lSignalCount) + { + _ASSERTE(m_lSignalCount >= 0); + _ASSERTE(lSignalCount >= 0); + m_lSignalCount = lSignalCount; + } + LONG DecrementSignalCount(void) + { + _ASSERTE(m_lSignalCount > 0); + return --m_lSignalCount; + } + + // Object ownership accessor methods + void SetOwner(CPalThread * pOwnerThread); + void ResetOwnership(void); + PAL_ERROR AssignOwnershipToThread( + CPalThread * pthrCurrent, + CPalThread * pthrTarget); + DWORD GetOwnerProcessID(void) + { + return m_dwOwnerPid; + } + DWORD GetOwnerThreadID(void) + { + return m_dwOwnerTid; + } + CPalThread * GetOwnerThread(void) + { + return m_pOwnerThread; + } + OwnedObjectsListNode * GetOwnershipListNode(void) + { + return m_poolnOwnedObjectListNode; + } + void SetOwnershipListNode(OwnedObjectsListNode * pooln) + { + m_poolnOwnedObjectListNode = pooln; + } + + // Object ownership count accessor methods + LONG GetOwnershipCount(void) + { + return m_lOwnershipCount; + } + void SetOwnershipCount(LONG lOwnershipCount) + { + m_lOwnershipCount = lOwnershipCount; + } + + // Object abandoned flag accessor methods + void SetAbandoned(bool fAbandoned) + { m_fAbandoned = fAbandoned; } + bool IsAbandoned(void) { return m_fAbandoned; } + + void IncrementWaitingThreadCount(void) + { + m_ulcWaitingThreads += 1; + } + void DecrementWaitingThreadCount(void) + { + m_ulcWaitingThreads -= 1; + } + ULONG GetWaitingThreadCount(void) + { + return m_ulcWaitingThreads; + } + + +#ifdef SYNCH_STATISTICS + void IncrementStatWaitCount(void) + { + m_lStatWaitCount++; + } + LONG GetStatWaitCount(void) + { + return m_lStatWaitCount; + } + void IncrementStatContentionCount(void) + { + m_lStatContentionCount++; + } + LONG GetStatContentionCount(void) + { + return m_lStatContentionCount; + } +#endif + // + // Wating threads list access methods + // + WaitingThreadsListNode * GetWTLHeadPtr(void) + { + return m_ptrWTLHead.ptr; + } + WaitingThreadsListNode * GetWTLTailPtr(void) + { + return m_ptrWTLTail.ptr; + } + SharedID GetWTLHeadShmPtr(void) + { + return m_ptrWTLHead.shrid; + } + SharedID GetWTLTailShmPtr(void) + { + return m_ptrWTLTail.shrid; + } + void SetWTLHeadPtr(WaitingThreadsListNode * p) + { + m_ptrWTLHead.ptr = p; + } + void SetWTLTailPtr(WaitingThreadsListNode * p) + { + m_ptrWTLTail.ptr = p; + } + void SetWTLHeadShrPtr(SharedID shrid) + { + m_ptrWTLHead.shrid = shrid; + } + void SetWTLTailShrPtr(SharedID shrid) + { + m_ptrWTLTail.shrid = shrid; + } +#ifdef SYNCH_OBJECT_VALIDATION + ~CSynchData(); + void ValidateObject(bool fDestructor = false); + void ValidateEmptyObject(void); + void InvalidateObject(void); + + DWORD m_dwDebugTailSignature; +#endif + }; + + + class CSynchControllerBase + { + friend class CPalSynchronizationManager; + + // NB: For perforformance purposes this class is supposed + // to have no virtual methods, contructor and + // destructor + public: + enum ControllerType { WaitController, StateController }; + + protected: + CPalThread * m_pthrOwner; + ControllerType m_ctCtrlrType; + ObjectDomain m_odObjectDomain; + CObjectType * m_potObjectType; + CSynchData * m_psdSynchData; + WaitDomain m_wdWaitDomain; + + PAL_ERROR Init( + CPalThread * pthrCurrent, + ControllerType ctCtrlrType, + ObjectDomain odObjectDomain, + CObjectType *potObjectType, + CSynchData * psdSynchData, + WaitDomain wdWaitDomain); + + void Release(void); + + void SetSynchData(CSynchData * psdSynchData) + { + m_psdSynchData = psdSynchData; + } + CSynchData * GetSynchData() + { + return m_psdSynchData; + } + }; + + class CSynchWaitController : public CSynchControllerBase, + public ISynchWaitController + { + // Per-object-type specific data + // + // Process (otiProcess) + IPalObject *m_pProcessObject; // process that owns m_pProcLocalData, this is stored without a reference + CProcProcessLocalData * m_pProcLocalData; + + public: + CSynchWaitController() : m_pProcessObject(NULL), m_pProcLocalData(NULL) {} + virtual ~CSynchWaitController() = default; + + // + // ISynchWaitController methods + // + virtual PAL_ERROR CanThreadWaitWithoutBlocking( + bool * pfCanWaitWithoutBlocking, + bool * pfAbandoned); + + virtual PAL_ERROR ReleaseWaitingThreadWithoutBlocking(void); + + virtual PAL_ERROR RegisterWaitingThread( + WaitType wtWaitType, + DWORD dwIndex, + bool fAlertable, + bool fPrioritize); + + virtual void ReleaseController(void); + + CProcProcessLocalData * GetProcessLocalData(void); + + void SetProcessData(IPalObject* pProcessObject, CProcProcessLocalData * pProcLocalData); + }; + + class CSynchStateController : public CSynchControllerBase, + public ISynchStateController + { + public: + // NB: For perforformance purposes this class is supposed + // to have no constructor + virtual ~CSynchStateController() = default; + + // + // ISynchStateController methods + // + virtual PAL_ERROR GetSignalCount(LONG *plSignalCount); + virtual PAL_ERROR SetSignalCount(LONG lNewCount); + virtual PAL_ERROR IncrementSignalCount(LONG lAmountToIncrement); + virtual PAL_ERROR DecrementSignalCount(LONG lAmountToDecrement); + virtual PAL_ERROR SetOwner(CPalThread *pNewOwningThread); + virtual PAL_ERROR DecrementOwnershipCount(void); + virtual void ReleaseController(void); + }; + + class CPalSynchronizationManager : public IPalSynchronizationManager + { + friend class CPalSynchMgrController; + template friend T *CorUnix::InternalNew(); + + public: + // types + typedef CSynchCache CSynchWaitControllerCache; + typedef CSynchCache CSynchStateControllerCache; + typedef CSynchCache CSynchDataCache; + typedef CSHRSynchCache CSHRSynchDataCache; + typedef CSynchCache CWaitingThreadsListNodeCache; + typedef CSHRSynchCache CSHRWaitingThreadsListNodeCache; + typedef CSynchCache CThreadApcInfoNodeCache; + typedef CSynchCache COwnedObjectsListNodeCache; + + private: + // types + enum InitStatus + { + SynchMgrStatusIdle, + SynchMgrStatusInitializing, + SynchMgrStatusRunning, + SynchMgrStatusShuttingDown, + SynchMgrStatusReadyForProcessShutDown, + SynchMgrStatusError + }; + enum SynchWorkerCmd + { + SynchWorkerCmdNop, + SynchWorkerCmdRemoteSignal, + SynchWorkerCmdDelegatedObjectSignaling, + SynchWorkerCmdShutdown, + SynchWorkerCmdTerminationRequest, + SynchWorkerCmdLast + }; + + typedef struct _MonitoredProcessesListNode + { + struct _MonitoredProcessesListNode * pNext; + LONG lRefCount; + CSynchData * psdSynchData; + DWORD dwPid; + DWORD dwExitCode; + bool fIsActualExitCode; + + // Object that owns pProcLocalData. This is stored, with a reference, to + // ensure that pProcLocalData is not deleted. + IPalObject *pProcessObject; + CProcProcessLocalData * pProcLocalData; + } MonitoredProcessesListNode; + + // constants + static const int CtrlrsCacheMaxSize = 256; + static const int SynchDataCacheMaxSize = 256; + static const int WTListNodeCacheMaxSize = 256; + static const int ApcInfoNodeCacheMaxSize = 32; + static const int OwnedObjectsListCacheMaxSize = 16; + static const int MaxWorkerConsecutiveEintrs = 128; + static const int MaxConsecutiveEagains = 128; + static const int WorkerThreadProcMonitoringTimeout = 250; // ms + static const int WorkerThreadShuttingDownTimeout = 1000; // ms + static const int WorkerCmdCompletionTimeout = 250; // ms + static const DWORD SecondNativeWaitTimeout = INFINITE; + static const DWORD WorkerThreadTerminationTimeout = 2000; // ms + + // static members + static CPalSynchronizationManager * s_pObjSynchMgr; + static Volatile s_lInitStatus; + static CRITICAL_SECTION s_csSynchProcessLock; + static CRITICAL_SECTION s_csMonitoredProcessesLock; + + // members + DWORD m_dwWorkerThreadTid; + IPalObject * m_pipoThread; + CPalThread * m_pthrWorker; + int m_iProcessPipeRead; + int m_iProcessPipeWrite; +#if HAVE_KQUEUE + int m_iKQueue; + struct kevent m_keProcessPipeEvent; +#endif // HAVE_KQUEUE + + MonitoredProcessesListNode * m_pmplnMonitoredProcesses; + LONG m_lMonitoredProcessesCount; + MonitoredProcessesListNode * m_pmplnExitedNodes; + + // caches + CSynchWaitControllerCache m_cacheWaitCtrlrs; + CSynchStateControllerCache m_cacheStateCtrlrs; + CSynchDataCache m_cacheSynchData; + CSHRSynchDataCache m_cacheSHRSynchData; + CWaitingThreadsListNodeCache m_cacheWTListNodes; + CSHRWaitingThreadsListNodeCache m_cacheSHRWTListNodes; + CThreadApcInfoNodeCache m_cacheThreadApcInfoNodes; + COwnedObjectsListNodeCache m_cacheOwnedObjectsListNodes; + + // static methods + static PAL_ERROR Initialize(); + static DWORD PALAPI WorkerThread(LPVOID pArg); + + protected: + CPalSynchronizationManager(); + + PAL_ERROR GetSynchControllersForObjects( + CPalThread *pthrCurrent, + IPalObject *rgObjects[], + DWORD dwObjectCount, + void ** ppvControllers, + CSynchControllerBase::ControllerType ctCtrlrType); + + private: + static IPalSynchronizationManager * CreatePalSynchronizationManager(); + static PAL_ERROR StartWorker(CPalThread * pthrCurrent); + static PAL_ERROR PrepareForShutdown(void); + + public: + virtual ~CPalSynchronizationManager(); + + static CPalSynchronizationManager * GetInstance(void) + { + // No need here to check for NULL and in case create the + // singleton, since its creation is enforced by the PAL + // initialization code. + return s_pObjSynchMgr; + } + + // + // Inline utility methods + // + static void AcquireLocalSynchLock(CPalThread * pthrCurrent) + { + _ASSERTE(0 <= pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount); + + if (1 == ++pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount) + { + InternalEnterCriticalSection(pthrCurrent, &s_csSynchProcessLock); + } + } + static void ReleaseLocalSynchLock(CPalThread * pthrCurrent) + { + _ASSERTE(0 < pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount); + if (0 == --pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount) + { + InternalLeaveCriticalSection(pthrCurrent, &s_csSynchProcessLock); + +#if SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + pthrCurrent->synchronizationInfo.RunDeferredThreadConditionSignalings(); +#endif // SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + } + } + static LONG ResetLocalSynchLock(CPalThread * pthrCurrent) + { + LONG lRet = pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount; + + _ASSERTE(0 <= lRet); + if (0 < lRet) + { + pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount = 0; + InternalLeaveCriticalSection(pthrCurrent, &s_csSynchProcessLock); + +#if SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + pthrCurrent->synchronizationInfo.RunDeferredThreadConditionSignalings(); +#endif // SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING + } + return lRet; + } + static LONG GetLocalSynchLockCount(CPalThread * pthrCurrent) + { + _ASSERTE(0 <= pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount); + return pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount; + } + + static void AcquireSharedSynchLock(CPalThread * pthrCurrent) + { + _ASSERTE(0 <= pthrCurrent->synchronizationInfo.m_lSharedSynchLockCount); + _ASSERT_MSG(0 < pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount, + "The local synch lock should be acquired before grabbing the " + "shared one.\n"); + if (1 == ++pthrCurrent->synchronizationInfo.m_lSharedSynchLockCount) + { + SHMLock(); + } + } + static void ReleaseSharedSynchLock(CPalThread * pthrCurrent) + { + _ASSERTE(0 < pthrCurrent->synchronizationInfo.m_lSharedSynchLockCount); + if (0 == --pthrCurrent->synchronizationInfo.m_lSharedSynchLockCount) + { + _ASSERT_MSG(0 < pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount, + "Final release of the shared synch lock while not holding the " + "local one. Local synch lock should always be acquired first and " + "released last.\n"); + SHMRelease(); + } + } + static LONG ResetSharedSynchLock(CPalThread * pthrCurrent) + { + LONG lRet = pthrCurrent->synchronizationInfo.m_lSharedSynchLockCount; + + _ASSERTE(0 <= lRet); + _ASSERTE(0 == lRet || + 0 < pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount); + if (0 < lRet) + { + pthrCurrent->synchronizationInfo.m_lSharedSynchLockCount = 0; + SHMRelease(); + } + return lRet; + } + static LONG GetSharedSynchLockCount(CPalThread * pthrCurrent) + { + _ASSERTE(0 <= pthrCurrent->synchronizationInfo.m_lSharedSynchLockCount); + _ASSERTE(0 == pthrCurrent->synchronizationInfo.m_lSharedSynchLockCount || + 0 < pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount); + return pthrCurrent->synchronizationInfo.m_lSharedSynchLockCount; + } + + CSynchWaitController * CacheGetWaitCtrlr(CPalThread * pthrCurrent) + { + return m_cacheWaitCtrlrs.Get(pthrCurrent); + } + int CacheGetWaitCtrlr( + CPalThread * pthrCurrent, + int n, + CSynchWaitController * prgCtrlrs[]) + { + return m_cacheWaitCtrlrs.Get(pthrCurrent, n, prgCtrlrs); + } + void CacheAddWaitCtrlr( + CPalThread * pthrCurrent, + CSynchWaitController * pCtrlr) + { + m_cacheWaitCtrlrs.Add(pthrCurrent, pCtrlr); + } + CSynchStateController * CacheGetStateCtrlr(CPalThread * pthrCurrent) + { + return m_cacheStateCtrlrs.Get(pthrCurrent); + } + int CacheGetStateCtrlr( + CPalThread * pthrCurrent, + int n, + CSynchStateController * prgCtrlrs[]) + { + return m_cacheStateCtrlrs.Get(pthrCurrent, n, prgCtrlrs); + } + void CacheAddStateCtrlr( + CPalThread * pthrCurrent, + CSynchStateController * pCtrlr) + { + m_cacheStateCtrlrs.Add(pthrCurrent, pCtrlr); + } + + CSynchData * CacheGetLocalSynchData(CPalThread * pthrCurrent) + { + return m_cacheSynchData.Get(pthrCurrent); + } + void CacheAddLocalSynchData( + CPalThread * pthrCurrent, + CSynchData * psdSynchData) + { + m_cacheSynchData.Add(pthrCurrent, psdSynchData); + } + SharedID CacheGetSharedSynchData(CPalThread * pthrCurrent) + { + return m_cacheSHRSynchData.Get(pthrCurrent); + } + void CacheAddSharedSynchData( + CPalThread * pthrCurrent, + SharedID shridSData) + { + m_cacheSHRSynchData.Add(pthrCurrent, shridSData); + } + + WaitingThreadsListNode * CacheGetLocalWTListNode( + CPalThread * pthrCurrent) + { + return m_cacheWTListNodes.Get(pthrCurrent); + } + void CacheAddLocalWTListNode( + CPalThread * pthrCurrent, + WaitingThreadsListNode * pWTLNode) + { + m_cacheWTListNodes.Add(pthrCurrent, pWTLNode); + } + SharedID CacheGetSharedWTListNode(CPalThread * pthrCurrent) + { + return m_cacheSHRWTListNodes.Get(pthrCurrent); + } + void CacheAddSharedWTListNode( + CPalThread * pthrCurrent, + SharedID shridWTLNode) + { + m_cacheSHRWTListNodes.Add(pthrCurrent, shridWTLNode); + } + + ThreadApcInfoNode * CacheGetApcInfoNodes(CPalThread * pthrCurrent) + { + return m_cacheThreadApcInfoNodes.Get(pthrCurrent); + } + void CacheAddApcInfoNodes( + CPalThread * pthrCurrent, + ThreadApcInfoNode * pNode) + { + m_cacheThreadApcInfoNodes.Add(pthrCurrent, pNode); + } + + OwnedObjectsListNode * CacheGetOwnedObjsListNode( + CPalThread * pthrCurrent) + { + return m_cacheOwnedObjectsListNodes.Get(pthrCurrent); + } + void CacheAddOwnedObjsListNode( + CPalThread * pthrCurrent, + OwnedObjectsListNode * pNode) + { + m_cacheOwnedObjectsListNodes.Add(pthrCurrent, pNode); + } + + + // + // IPalSynchronizationManager methods + // + virtual PAL_ERROR BlockThread( + CPalThread *pthrCurrent, + DWORD dwTimeout, + bool fAlertable, + bool fIsSleep, + ThreadWakeupReason *ptwrWakeupReason, + DWORD *pdwSignaledObject); + + virtual PAL_ERROR AbandonObjectsOwnedByThread( + CPalThread *pthrCurrent, + CPalThread *pthrTarget); + + virtual PAL_ERROR GetSynchWaitControllersForObjects( + CPalThread *pthrCurrent, + IPalObject *rgObjects[], + DWORD dwObjectCount, + ISynchWaitController *rgControllers[]); + + virtual PAL_ERROR GetSynchStateControllersForObjects( + CPalThread *pthrCurrent, + IPalObject *rgObjects[], + DWORD dwObjectCount, + ISynchStateController *rgControllers[]); + + virtual PAL_ERROR AllocateObjectSynchData( + CObjectType *potObjectType, + ObjectDomain odObjectDomain, + VOID **ppvSynchData); + + virtual void FreeObjectSynchData( + CObjectType *potObjectType, + ObjectDomain odObjectDomain, + VOID *pvSynchData); + + virtual PAL_ERROR PromoteObjectSynchData( + CPalThread *pthrCurrent, + VOID *pvLocalSynchData, + VOID **ppvSharedSynchData); + + virtual PAL_ERROR CreateSynchStateController( + CPalThread *pthrCurrent, + CObjectType *potObjectType, + VOID *pvSynchData, + ObjectDomain odObjectDomain, + ISynchStateController **ppStateController); + + virtual PAL_ERROR CreateSynchWaitController( + CPalThread *pthrCurrent, + CObjectType *potObjectType, + VOID *pvSynchData, + ObjectDomain odObjectDomain, + ISynchWaitController **ppWaitController); + + virtual PAL_ERROR QueueUserAPC( + CPalThread * pthrCurrent, + CPalThread *pthrTarget, + PAPCFUNC pfnAPC, + ULONG_PTR uptrData); + + virtual PAL_ERROR SendTerminationRequestToWorkerThread(); + + virtual bool AreAPCsPending(CPalThread * pthrTarget); + + virtual PAL_ERROR DispatchPendingAPCs(CPalThread * pthrCurrent); + + virtual void AcquireProcessLock(CPalThread *pthrCurrent); + + virtual void ReleaseProcessLock(CPalThread *pthrCurrent); + + // + // Static helper methods + // + public: + static PAL_ERROR WakeUpLocalThread( + CPalThread * pthrCurrent, + CPalThread * pthrTarget, + ThreadWakeupReason twrWakeupReason, + DWORD dwObjectIndex); + + static PAL_ERROR SignalThreadCondition( + ThreadNativeWaitData * ptnwdNativeWaitData); + + static PAL_ERROR DeferThreadConditionSignaling( + CPalThread * pthrCurrent, + CPalThread * pthrTarget); + + static PAL_ERROR WakeUpRemoteThread( + SharedID shridWLNode); + + static PAL_ERROR DelegateSignalingToRemoteProcess( + CPalThread * pthrCurrent, + DWORD dwTargetProcessId, + SharedID shridSynchData); + + static PAL_ERROR SendMsgToRemoteWorker( + DWORD dwProcessId, + BYTE * pMsg, + int iMsgSize); + + static ThreadWaitInfo * GetThreadWaitInfo( + CPalThread * pthrCurrent); + + // + // The following methods must be called only by a Sync*Controller or + // while holding the required synchronization global locks + // + static void UnsignalRestOfLocalAwakeningWaitAll( + CPalThread * pthrCurrent, + CPalThread * pthrTarget, + WaitingThreadsListNode * pwtlnNode, + CSynchData * psdTgtObjectSynchData); + + static void MarkWaitForDelegatedObjectSignalingInProgress( + CPalThread * pthrCurrent, + WaitingThreadsListNode * pwtlnNode); + + static void UnmarkTWListForDelegatedObjectSignalingInProgress( + CSynchData * pTgtObjectSynchData); + + static PAL_ERROR ThreadNativeWait( + ThreadNativeWaitData * ptnwdNativeWaitData, + DWORD dwTimeout, + ThreadWakeupReason * ptwrWakeupReason, + DWORD * pdwSignaledObject); + + static void ThreadPrepareForShutdown(void); + +#ifndef CORECLR + static bool GetProcessPipeName( + LPSTR pDest, + int iDestSize, + DWORD dwPid); +#endif // !CORECLR + + // + // Non-static helper methods + // + private: + LONG DoMonitorProcesses(CPalThread * pthrCurrent); + + void DiscardMonitoredProcesses(CPalThread * pthrCurrent); + + PAL_ERROR ReadCmdFromProcessPipe( + int iPollTimeout, + SynchWorkerCmd * pswcWorkerCmd, + SharedID * pshridMarshaledData, + DWORD * pdwData); + + PAL_ERROR WakeUpLocalWorkerThread( + SynchWorkerCmd swcWorkerCmd); + + void DiscardAllPendingAPCs( + CPalThread * pthrCurrent, + CPalThread * pthrTarget); + + int ReadBytesFromProcessPipe( + int iTimeout, + BYTE * pRecvBuf, + LONG lBytes); + + bool CreateProcessPipe(); + + PAL_ERROR ShutdownProcessPipe(); + + public: + // + // The following methods must be called only by a Sync*Controller or + // while holding the required synchronization global locks + // + void UnRegisterWait( + CPalThread * pthrCurrent, + ThreadWaitInfo * ptwiWaitInfo, + bool fHaveSharedLock); + + PAL_ERROR RegisterProcessForMonitoring( + CPalThread * pthrCurrent, + CSynchData *psdSynchData, + IPalObject *pProcessObject, + CProcProcessLocalData * pProcLocalData); + + PAL_ERROR UnRegisterProcessForMonitoring( + CPalThread * pthrCurrent, + CSynchData *psdSynchData, + DWORD dwPid); + + // + // Utility static methods, no lock required + // + static bool HasProcessExited( + DWORD dwPid, + DWORD * pdwExitCode, + bool * pfIsActualExitCode); + + static bool InterlockedAwaken( + DWORD *pWaitState, + bool fAlertOnly); + + static PAL_ERROR GetAbsoluteTimeout( + DWORD dwTimeout, + struct timespec * ptsAbsTmo, + BOOL fPreferMonotonicClock); + }; +} + +#endif // _SYNCHMANAGER_HPP_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/wait.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/wait.cpp new file mode 100644 index 0000000..8d2de64 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchmgr/wait.cpp @@ -0,0 +1,896 @@ +// 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: + + wait.cpp + +Abstract: + + Implementation of waiting functions as described in + the WIN32 API + +Revision History: + + + +--*/ + +#include "pal/thread.hpp" +#include "pal/synchobjects.hpp" +#include "pal/handlemgr.hpp" +#include "pal/event.hpp" +#include "pal/mutex.hpp" +#include "pal/semaphore.hpp" +#include "pal/malloc.hpp" +#include "pal/dbgmsg.h" + +SET_DEFAULT_DEBUG_CHANNEL(SYNC); + +#define MAXIMUM_STACK_WAITOBJ_ARRAY_SIZE (MAXIMUM_WAIT_OBJECTS / 4) + +using namespace CorUnix; + +static PalObjectTypeId sg_rgWaitObjectsIds[] = + { + otiAutoResetEvent, + otiManualResetEvent, + otiMutex, + otiNamedMutex, + otiSemaphore, + otiProcess, + otiThread + }; +static CAllowedObjectTypes sg_aotWaitObject(sg_rgWaitObjectsIds, + sizeof(sg_rgWaitObjectsIds)/sizeof(sg_rgWaitObjectsIds[0])); + +static PalObjectTypeId sg_rgSignalableObjectIds[] = +{ + otiAutoResetEvent, + otiManualResetEvent, + otiMutex, + otiNamedMutex, + otiSemaphore +}; +static CAllowedObjectTypes sg_aotSignalableObject(sg_rgSignalableObjectIds, _countof(sg_rgSignalableObjectIds)); + +/*++ +Function: + WaitForSingleObject + +See MSDN doc. +--*/ +DWORD +PALAPI +WaitForSingleObject(IN HANDLE hHandle, + IN DWORD dwMilliseconds) +{ + DWORD dwRet; + + PERF_ENTRY(WaitForSingleObject); + ENTRY("WaitForSingleObject(hHandle=%p, dwMilliseconds=%u)\n", + hHandle, dwMilliseconds); + + CPalThread * pThread = InternalGetCurrentThread(); + + dwRet = InternalWaitForMultipleObjectsEx(pThread, 1, &hHandle, FALSE, + dwMilliseconds, FALSE); + + LOGEXIT("WaitForSingleObject returns DWORD %u\n", dwRet); + PERF_EXIT(WaitForSingleObject); + return dwRet; +} + + +/*++ +Function: + WaitForSingleObjectPrioritized + +Similar to WaitForSingleObject, except uses a LIFO release policy for waiting threads by prioritizing new waiters (registering +them at the beginning of the wait queue rather than at the end). +--*/ +DWORD +PALAPI +PAL_WaitForSingleObjectPrioritized(IN HANDLE hHandle, + IN DWORD dwMilliseconds) +{ + DWORD dwRet; + + PERF_ENTRY(PAL_WaitForSingleObjectPrioritized); + ENTRY("PAL_WaitForSingleObjectPrioritized(hHandle=%p, dwMilliseconds=%u)\n", + hHandle, dwMilliseconds); + + CPalThread * pThread = InternalGetCurrentThread(); + + dwRet = InternalWaitForMultipleObjectsEx(pThread, 1, &hHandle, FALSE, + dwMilliseconds, FALSE, TRUE /* bPrioritize */); + + LOGEXIT("PAL_WaitForSingleObjectPrioritized returns DWORD %u\n", dwRet); + PERF_EXIT(PAL_WaitForSingleObjectPrioritized); + return dwRet; +} + + +/*++ +Function: + WaitForSingleObjectEx + +See MSDN doc. +--*/ +DWORD +PALAPI +WaitForSingleObjectEx(IN HANDLE hHandle, + IN DWORD dwMilliseconds, + IN BOOL bAlertable) +{ + DWORD dwRet; + + PERF_ENTRY(WaitForSingleObjectEx); + ENTRY("WaitForSingleObjectEx(hHandle=%p, dwMilliseconds=%u, bAlertable=%s)\n", + hHandle, dwMilliseconds, bAlertable ? "TRUE" : "FALSE"); + + CPalThread * pThread = InternalGetCurrentThread(); + + dwRet = InternalWaitForMultipleObjectsEx(pThread, 1, &hHandle, FALSE, + dwMilliseconds, bAlertable); + + LOGEXIT("WaitForSingleObjectEx returns DWORD %u\n", dwRet); + PERF_EXIT(WaitForSingleObjectEx); + return dwRet; +} + + +/*++ +Function: + WaitForMultipleObjects + +See MSDN doc. + +--*/ +DWORD +PALAPI +WaitForMultipleObjects(IN DWORD nCount, + IN CONST HANDLE *lpHandles, + IN BOOL bWaitAll, + IN DWORD dwMilliseconds) +{ + DWORD dwRet; + + PERF_ENTRY(WaitForMultipleObjects); + ENTRY("WaitForMultipleObjects(nCount=%d, lpHandles=%p," + " bWaitAll=%d, dwMilliseconds=%u)\n", + nCount, lpHandles, bWaitAll, dwMilliseconds); + + CPalThread * pThread = InternalGetCurrentThread(); + + dwRet = InternalWaitForMultipleObjectsEx(pThread, nCount, lpHandles, + bWaitAll, dwMilliseconds, FALSE); + + LOGEXIT("WaitForMultipleObjects returns DWORD %u\n", dwRet); + PERF_EXIT(WaitForMultipleObjects); + return dwRet; +} + +/*++ +Function: + WaitForMultipleObjectsEx + +See MSDN doc for info about this function. +--*/ +DWORD +PALAPI +WaitForMultipleObjectsEx(IN DWORD nCount, + IN CONST HANDLE *lpHandles, + IN BOOL bWaitAll, + IN DWORD dwMilliseconds, + IN BOOL bAlertable) +{ + DWORD dwRet; + + PERF_ENTRY(WaitForMultipleObjectsEx); + ENTRY("WaitForMultipleObjectsEx(nCount=%d, lpHandles=%p," + " bWaitAll=%d, dwMilliseconds=%u, bAlertable=%s)\n", + nCount, lpHandles, bWaitAll, dwMilliseconds, bAlertable ? "TRUE" : "FALSE"); + + CPalThread * pThread = InternalGetCurrentThread(); + + dwRet = InternalWaitForMultipleObjectsEx(pThread, nCount, lpHandles, bWaitAll, + dwMilliseconds, bAlertable); + + LOGEXIT("WaitForMultipleObjectsEx returns DWORD %u\n", dwRet); + PERF_EXIT(WaitForMultipleObjectsEx); + return dwRet; +} + +/*++ +Function: + SignalObjectAndWait + +See MSDN doc for info about this function. +--*/ +DWORD +PALAPI +SignalObjectAndWait( + IN HANDLE hObjectToSignal, + IN HANDLE hObjectToWaitOn, + IN DWORD dwMilliseconds, + IN BOOL bAlertable) +{ + PERF_ENTRY(SignalObjectAndWait); + ENTRY( + "SignalObjectAndWait(hObjectToSignal=%p, hObjectToWaitOn=%p, dwMilliseconds=%u, bAlertable=%s)\n", + hObjectToSignal, + hObjectToWaitOn, + dwMilliseconds, + bAlertable ? "TRUE" : "FALSE"); + + CPalThread *thread = InternalGetCurrentThread(); + DWORD result = InternalSignalObjectAndWait(thread, hObjectToSignal, hObjectToWaitOn, dwMilliseconds, bAlertable); + + LOGEXIT("SignalObjectAndWait returns DWORD %u\n", result); + PERF_EXIT(SignalObjectAndWait); + return result; +} + +/*++ +Function: + Sleep + +See MSDN doc. +--*/ +VOID +PALAPI +Sleep(IN DWORD dwMilliseconds) +{ + PERF_ENTRY(Sleep); + ENTRY("Sleep(dwMilliseconds=%u)\n", dwMilliseconds); + + CPalThread * pThread = InternalGetCurrentThread(); + + DWORD internalSleepRet = InternalSleepEx(pThread, dwMilliseconds, FALSE); + + if (internalSleepRet != 0) + { + ERROR("Sleep(dwMilliseconds=%u) failed [error=%u]\n", dwMilliseconds, internalSleepRet); + pThread->SetLastError(internalSleepRet); + } + + LOGEXIT("Sleep returns VOID\n"); + PERF_EXIT(Sleep); +} + + +/*++ +Function: + SleepEx + +See MSDN doc. +--*/ +DWORD +PALAPI +SleepEx(IN DWORD dwMilliseconds, + IN BOOL bAlertable) +{ + DWORD dwRet; + + PERF_ENTRY(SleepEx); + ENTRY("SleepEx(dwMilliseconds=%u, bAlertable=%d)\n", dwMilliseconds, bAlertable); + + CPalThread * pThread = InternalGetCurrentThread(); + + dwRet = InternalSleepEx(pThread, dwMilliseconds, bAlertable); + + LOGEXIT("SleepEx returns DWORD %u\n", dwRet); + PERF_EXIT(SleepEx); + + return dwRet; +} + +/*++ +Function: + QueueUserAPC + +See MSDN doc. +--*/ +DWORD +PALAPI +QueueUserAPC( + PAPCFUNC pfnAPC, + HANDLE hThread, + ULONG_PTR dwData) +{ + CPalThread * pCurrentThread = NULL; + CPalThread * pTargetThread = NULL; + IPalObject * pTargetThreadObject = NULL; + PAL_ERROR palErr; + DWORD dwRet; + + PERF_ENTRY(QueueUserAPC); + ENTRY("QueueUserAPC(pfnAPC=%p, hThread=%p, dwData=%#x)\n", + pfnAPC, hThread, dwData); + + /* NOTE: Windows does not check the validity of pfnAPC, even if it is + NULL. It just does an access violation later on when the APC call + is attempted */ + + pCurrentThread = InternalGetCurrentThread(); + + palErr = InternalGetThreadDataFromHandle( + pCurrentThread, + hThread, + &pTargetThread, + &pTargetThreadObject + ); + + if (NO_ERROR != palErr) + { + ERROR("Unable to obtain thread data for handle %p (error %x)!\n", + hThread, palErr); + goto QueueUserAPC_exit; + } + + + palErr = g_pSynchronizationManager->QueueUserAPC(pCurrentThread, pTargetThread, + pfnAPC, dwData); + +QueueUserAPC_exit: + if (pTargetThreadObject) + { + pTargetThreadObject->ReleaseReference(pCurrentThread); + } + + dwRet = (NO_ERROR == palErr) ? 1 : 0; + + LOGEXIT("QueueUserAPC returns DWORD %d\n", dwRet); + PERF_EXIT(QueueUserAPC); + return dwRet; +} + +DWORD CorUnix::InternalWaitForMultipleObjectsEx( + CPalThread * pThread, + DWORD nCount, + CONST HANDLE *lpHandles, + BOOL bWaitAll, + DWORD dwMilliseconds, + BOOL bAlertable, + BOOL bPrioritize) +{ + DWORD dwRet = WAIT_FAILED; + PAL_ERROR palErr = NO_ERROR; + int i, iSignaledObjCount, iSignaledObjIndex = -1; + bool fWAll = (bool)bWaitAll, fNeedToBlock = false; + bool fAbandoned = false; + WaitType wtWaitType; + + IPalObject * pIPalObjStackArray[MAXIMUM_STACK_WAITOBJ_ARRAY_SIZE] = { NULL }; + ISynchWaitController * pISyncStackArray[MAXIMUM_STACK_WAITOBJ_ARRAY_SIZE] = { NULL }; + IPalObject ** ppIPalObjs = pIPalObjStackArray; + ISynchWaitController ** ppISyncWaitCtrlrs = pISyncStackArray; + + if ((nCount == 0) || (nCount > MAXIMUM_WAIT_OBJECTS)) + { + ppIPalObjs = NULL; // make delete at the end safe + ppISyncWaitCtrlrs = NULL; // make delete at the end safe + ERROR("Invalid object count=%d [range: 1 to %d]\n", + nCount, MAXIMUM_WAIT_OBJECTS) + pThread->SetLastError(ERROR_INVALID_PARAMETER); + goto WFMOExIntExit; + } + else if (nCount == 1) + { + fWAll = false; // makes no difference when nCount is 1 + wtWaitType = SingleObject; + } + else + { + wtWaitType = fWAll ? MultipleObjectsWaitAll : MultipleObjectsWaitOne; + if (nCount > MAXIMUM_STACK_WAITOBJ_ARRAY_SIZE) + { + ppIPalObjs = InternalNewArray(nCount); + ppISyncWaitCtrlrs = InternalNewArray(nCount); + if ((NULL == ppIPalObjs) || (NULL == ppISyncWaitCtrlrs)) + { + ERROR("Out of memory allocating internal structures\n"); + pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto WFMOExIntExit; + } + } + } + + palErr = g_pObjectManager->ReferenceMultipleObjectsByHandleArray(pThread, + (VOID **)lpHandles, + nCount, + &sg_aotWaitObject, + ppIPalObjs); + if (NO_ERROR != palErr) + { + ERROR("Unable to obtain object for some or all of the handles [error=%u]\n", + palErr); + if (palErr == ERROR_INVALID_HANDLE) + pThread->SetLastError(ERROR_INVALID_HANDLE); + else + pThread->SetLastError(ERROR_INTERNAL_ERROR); + goto WFMOExIntExit; + } + + if (nCount > 1) + { + // Check for any cross-process sync objects. "Wait for any" and "wait for all" operations are not supported on + // cross-process sync objects in the PAL. + for (DWORD i = 0; i < nCount; ++i) + { + if (ppIPalObjs[i]->GetObjectType()->GetId() == otiNamedMutex) + { + ERROR("Attempt to wait for any or all handles including a cross-process sync object", ERROR_NOT_SUPPORTED); + pThread->SetLastError(ERROR_NOT_SUPPORTED); + goto WFMOExIntCleanup; + } + } + } + else if (ppIPalObjs[0]->GetObjectType()->GetId() == otiNamedMutex) + { + SharedMemoryProcessDataHeader *processDataHeader = + SharedMemoryProcessDataHeader::PalObject_GetProcessDataHeader(ppIPalObjs[0]); + _ASSERTE(processDataHeader != nullptr); + try + { + MutexTryAcquireLockResult tryAcquireLockResult = + static_cast(processDataHeader->GetData())->TryAcquireLock(dwMilliseconds); + switch (tryAcquireLockResult) + { + case MutexTryAcquireLockResult::AcquiredLock: + dwRet = WAIT_OBJECT_0; + break; + + case MutexTryAcquireLockResult::AcquiredLockButMutexWasAbandoned: + dwRet = WAIT_ABANDONED_0; + break; + + case MutexTryAcquireLockResult::TimedOut: + dwRet = WAIT_TIMEOUT; + break; + + default: + _ASSERTE(false); + break; + } + } + catch (SharedMemoryException ex) + { + pThread->SetLastError(ex.GetErrorCode()); + } + goto WFMOExIntCleanup; + } + + if (fWAll) + { + // For a wait-all operation, check for duplicate wait objects in the array. This just uses a brute-force O(n^2) + // algorithm, but since MAXIMUM_WAIT_OBJECTS is small, the worst case is not so bad, and the average case would involve + // significantly fewer items. + for (DWORD i = 0; i < nCount - 1; ++i) + { + IPalObject *const objectToCheck = ppIPalObjs[i]; + for (DWORD j = i + 1; j < nCount; ++j) + { + if (ppIPalObjs[j] == objectToCheck) + { + ERROR("Duplicate handle provided for a wait-all operation [error=%u]\n", ERROR_INVALID_PARAMETER); + pThread->SetLastError(ERROR_INVALID_PARAMETER); + goto WFMOExIntCleanup; + } + } + } + } + + palErr = g_pSynchronizationManager->GetSynchWaitControllersForObjects( + pThread, ppIPalObjs, nCount, ppISyncWaitCtrlrs); + if (NO_ERROR != palErr) + { + ERROR("Unable to obtain ISynchWaitController interface for some or all " + "of the objects [error=%u]\n", palErr); + pThread->SetLastError(ERROR_INTERNAL_ERROR); + goto WFMOExIntCleanup; + } + + if (bAlertable) + { + // First check for pending APC. We need to do that while holding the global + // synch lock implicitely grabbed by GetSynchWaitControllersForObjects + if (g_pSynchronizationManager->AreAPCsPending(pThread)) + { + // If there is any pending APC we need to release the + // implicit global synch lock before calling into it + for (i = 0; (i < (int)nCount) && (NULL != ppISyncWaitCtrlrs[i]); i++) + { + ppISyncWaitCtrlrs[i]->ReleaseController(); + ppISyncWaitCtrlrs[i] = NULL; + } + palErr = g_pSynchronizationManager->DispatchPendingAPCs(pThread); + if (NO_ERROR == palErr) + { + dwRet = WAIT_IO_COMPLETION; + } + else + { + ASSERT("Awakened for APC, but no APC is pending\n"); + pThread->SetLastError(ERROR_INTERNAL_ERROR); + dwRet = WAIT_FAILED; + } + goto WFMOExIntCleanup; + } + } + + iSignaledObjCount = 0; + iSignaledObjIndex = -1; + for (i=0;i<(int)nCount;i++) + { + bool fValue, fWaitObjectAbandoned = false; + palErr = ppISyncWaitCtrlrs[i]->CanThreadWaitWithoutBlocking(&fValue, &fWaitObjectAbandoned); + if (NO_ERROR != palErr) + { + ERROR("ISynchWaitController::CanThreadWaitWithoutBlocking() failed for " + "%d-th object [handle=%p error=%u]\n", i, lpHandles[i], palErr); + pThread->SetLastError(ERROR_INTERNAL_ERROR); + goto WFMOExIntReleaseControllers; + } + if (fWaitObjectAbandoned) + { + fAbandoned = true; + } + if (fValue) + { + iSignaledObjCount++; + iSignaledObjIndex = i; + if (!fWAll) + break; + } + } + + fNeedToBlock = (iSignaledObjCount == 0) || (fWAll && (iSignaledObjCount < (int)nCount)); + if (!fNeedToBlock) + { + // At least one object signaled, or bWaitAll==TRUE and all object signaled. + // No need to wait, let's unsignal the object(s) and return without blocking + int iStartIdx, iEndIdx; + + if (fWAll) + { + iStartIdx = 0; + iEndIdx = nCount; + } + else + { + iStartIdx = iSignaledObjIndex; + iEndIdx = iStartIdx + 1; + } + + // Unsignal objects + if( iStartIdx < 0 ) + { + ERROR("Buffer underflow due to iStartIdx < 0"); + pThread->SetLastError(ERROR_INTERNAL_ERROR); + dwRet = WAIT_FAILED; + goto WFMOExIntCleanup; + } + for (i = iStartIdx; i < iEndIdx; i++) + { + palErr = ppISyncWaitCtrlrs[i]->ReleaseWaitingThreadWithoutBlocking(); + if (NO_ERROR != palErr) + { + ERROR("ReleaseWaitingThreadWithoutBlocking() failed for %d-th " + "object [handle=%p error=%u]\n", + i, lpHandles[i], palErr); + pThread->SetLastError(palErr); + goto WFMOExIntReleaseControllers; + } + } + + dwRet = (fAbandoned ? WAIT_ABANDONED_0 : WAIT_OBJECT_0); + } + else if (0 == dwMilliseconds) + { + // Not enough objects signaled, but timeout is zero: no actual wait + dwRet = WAIT_TIMEOUT; + fNeedToBlock = false; + } + else + { + // Register the thread for waiting on all objects + for (i=0;i<(int)nCount;i++) + { + palErr = ppISyncWaitCtrlrs[i]->RegisterWaitingThread( + wtWaitType, + i, + (TRUE == bAlertable), + bPrioritize != FALSE); + if (NO_ERROR != palErr) + { + ERROR("RegisterWaitingThread() failed for %d-th object " + "[handle=%p error=%u]\n", i, lpHandles[i], palErr); + pThread->SetLastError(palErr); + goto WFMOExIntReleaseControllers; + } + } + } + +WFMOExIntReleaseControllers: + // Release all controllers before going to sleep + for (i = 0; i < (int)nCount; i++) + { + ppISyncWaitCtrlrs[i]->ReleaseController(); + ppISyncWaitCtrlrs[i] = NULL; + } + if (NO_ERROR != palErr) + goto WFMOExIntCleanup; + + if (fNeedToBlock) + { + ThreadWakeupReason twrWakeupReason; + + // + // Going to sleep + // + palErr = g_pSynchronizationManager->BlockThread(pThread, + dwMilliseconds, + (TRUE == bAlertable), + false, + &twrWakeupReason, + (DWORD *)&iSignaledObjIndex); + // + // Awakened + // + if (NO_ERROR != palErr) + { + ERROR("IPalSynchronizationManager::BlockThread failed for thread " + "pThread=%p [error=%u]\n", pThread, palErr); + pThread->SetLastError(palErr); + goto WFMOExIntCleanup; + } + switch (twrWakeupReason) + { + case WaitSucceeded: + dwRet = WAIT_OBJECT_0; // offset added later + break; + case MutexAbondoned: + dwRet = WAIT_ABANDONED_0; // offset added later + break; + case WaitTimeout: + dwRet = WAIT_TIMEOUT; + break; + case Alerted: + _ASSERT_MSG(bAlertable, + "Awakened for APC from a non-alertable wait\n"); + + dwRet = WAIT_IO_COMPLETION; + palErr = g_pSynchronizationManager->DispatchPendingAPCs(pThread); + + _ASSERT_MSG(NO_ERROR == palErr, + "Awakened for APC, but no APC is pending\n"); + break; + case WaitFailed: + default: + ERROR("Thread %p awakened with some failure\n", pThread); + dwRet = WAIT_FAILED; + break; + } + } + + if (!fWAll && ((WAIT_OBJECT_0 == dwRet) || (WAIT_ABANDONED_0 == dwRet))) + { + _ASSERT_MSG(0 <= iSignaledObjIndex, + "Failed to identify signaled/abandoned object\n"); + _ASSERT_MSG(iSignaledObjIndex >= 0 && nCount > static_cast(iSignaledObjIndex), + "SignaledObjIndex object out of range " + "[index=%d obj_count=%u\n", + iSignaledObjCount, nCount); + + if (iSignaledObjIndex < 0) + { + pThread->SetLastError(ERROR_INTERNAL_ERROR); + dwRet = WAIT_FAILED; + goto WFMOExIntCleanup; + } + dwRet += iSignaledObjIndex; + } + +WFMOExIntCleanup: + for (i = 0; i < (int)nCount; i++) + { + ppIPalObjs[i]->ReleaseReference(pThread); + ppIPalObjs[i] = NULL; + } + +WFMOExIntExit: + if (nCount > MAXIMUM_STACK_WAITOBJ_ARRAY_SIZE) + { + InternalDeleteArray(ppIPalObjs); + InternalDeleteArray(ppISyncWaitCtrlrs); + } + + return dwRet; +} + +DWORD CorUnix::InternalSignalObjectAndWait( + CPalThread *thread, + HANDLE hObjectToSignal, + HANDLE hObjectToWaitOn, + DWORD dwMilliseconds, + BOOL bAlertable) +{ + DWORD result = WAIT_FAILED; + PAL_ERROR palError = NO_ERROR; + IPalObject *objectToSignal = nullptr; + IPalObject *objectToWaitOn = nullptr; + + // Validate and add a reference to the object to signal + palError = + g_pObjectManager->ReferenceObjectByHandle( + thread, + hObjectToSignal, + &sg_aotSignalableObject, + &objectToSignal); + if (palError != NO_ERROR) + { + ERROR("Unable to obtain object for handle %p (error %u)!\n", hObjectToSignal, palError); + goto InternalSignalObjectAndWait_Error; + } + + // Validate and add a reference to the object to wait on. Error checking is done before signaling. + palError = + g_pObjectManager->ReferenceObjectByHandle( + thread, + hObjectToWaitOn, + &sg_aotWaitObject, + &objectToWaitOn); + if (palError != NO_ERROR) + { + ERROR("Unable to obtain object for handle %p (error %u)!\n", hObjectToWaitOn, palError); + goto InternalSignalObjectAndWait_Error; + } + + // Signal + switch (objectToSignal->GetObjectType()->GetId()) + { + case otiAutoResetEvent: + case otiManualResetEvent: + palError = InternalSetEvent(thread, hObjectToSignal, true /* fSetEvent */); + break; + + case otiMutex: + case otiNamedMutex: + palError = InternalReleaseMutex(thread, hObjectToSignal); + break; + + case otiSemaphore: + palError = InternalReleaseSemaphore(thread, hObjectToSignal, 1 /* lReleaseCount */, nullptr /* lpPreviousCount */); + break; + + default: + palError = ERROR_INVALID_HANDLE; + break; + } + if (palError != NO_ERROR) + { + ERROR("Unable to signal object for handle %p (error %u)!\n", hObjectToSignal, palError); + goto InternalSignalObjectAndWait_Error; + } + objectToSignal->ReleaseReference(thread); + objectToSignal = nullptr; + + // Wait + result = + InternalWaitForMultipleObjectsEx( + thread, + 1 /* nCount */, + &hObjectToWaitOn, + false /* bWaitAll */, + dwMilliseconds, + bAlertable); + if (result == WAIT_FAILED) + { + ERROR("Unable to wait on object for handle %p (error %u)!\n", hObjectToWaitOn, palError); + goto InternalSignalObjectAndWait_Error; + } + objectToWaitOn->ReleaseReference(thread); + objectToWaitOn = nullptr; + + goto InternalSignalObjectAndWait_Exit; + +InternalSignalObjectAndWait_Error: + if (objectToSignal != nullptr) + { + objectToSignal->ReleaseReference(thread); + } + if (objectToWaitOn != nullptr) + { + objectToWaitOn->ReleaseReference(thread); + } + + if (palError != NO_ERROR) + { + _ASSERTE(result == WAIT_FAILED); + thread->SetLastError(palError); + } + +InternalSignalObjectAndWait_Exit: + LOGEXIT("InternalSignalObjectAndWait returns %u\n", result); + return result; +} + +DWORD CorUnix::InternalSleepEx ( + CPalThread * pThread, + DWORD dwMilliseconds, + BOOL bAlertable) +{ + PAL_ERROR palErr = NO_ERROR; + DWORD dwRet = WAIT_FAILED; + int iSignaledObjIndex; + + TRACE("Sleeping %u ms [bAlertable=%d]", dwMilliseconds, (int)bAlertable); + + if (bAlertable) + { + // In this case do not use AreAPCsPending. In fact, since we are + // not holding the synch lock(s) an APC posting may race with + // AreAPCsPending. + palErr = g_pSynchronizationManager->DispatchPendingAPCs(pThread); + if (NO_ERROR == palErr) + { + return WAIT_IO_COMPLETION; + } + } + + if (dwMilliseconds > 0) + { + ThreadWakeupReason twrWakeupReason; + palErr = g_pSynchronizationManager->BlockThread(pThread, + dwMilliseconds, + (TRUE == bAlertable), + true, + &twrWakeupReason, + (DWORD *)&iSignaledObjIndex); + if (NO_ERROR != palErr) + { + ERROR("IPalSynchronizationManager::BlockThread failed for thread " + "pThread=%p [error=%u]\n", pThread, palErr); + return dwRet; + } + + switch (twrWakeupReason) + { + case WaitSucceeded: + case WaitTimeout: + dwRet = 0; + break; + case Alerted: + _ASSERT_MSG(bAlertable, "Awakened for APC from a non-alertable wait\n"); + + dwRet = WAIT_IO_COMPLETION; + palErr = g_pSynchronizationManager->DispatchPendingAPCs(pThread); + _ASSERT_MSG(NO_ERROR == palErr, "Awakened for APC, but no APC is pending\n"); + + break; + case MutexAbondoned: + ASSERT("Thread %p awakened with reason=MutexAbondoned from a SleepEx\n", pThread); + break; + case WaitFailed: + default: + ERROR("Thread %p awakened with some failure\n", pThread); + break; + } + } + else + { + sched_yield(); + dwRet = 0; + } + + TRACE("Done sleeping %u ms [bAlertable=%d]", dwMilliseconds, (int)bAlertable); + return dwRet; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchobj/event.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchobj/event.cpp new file mode 100644 index 0000000..960ae6d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchobj/event.cpp @@ -0,0 +1,543 @@ +// 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: + + event.cpp + +Abstract: + + Implementation of event synchronization object as described in + the WIN32 API + +Revision History: + + + +--*/ + +#include "pal/event.hpp" +#include "pal/thread.hpp" +#include "pal/dbgmsg.h" + +using namespace CorUnix; + +/* ------------------- Definitions ------------------------------*/ +SET_DEFAULT_DEBUG_CHANNEL(SYNC); + +CObjectType CorUnix::otManualResetEvent( + otiManualResetEvent, + NULL, // No cleanup routine + NULL, // No initialization routine + 0, // No immutable data + NULL, // No immutable data copy routine + NULL, // No immutable data cleanup routine + 0, // No process local data + NULL, // No process local data cleanup routine + 0, // No shared data + EVENT_ALL_ACCESS, // Currently ignored (no Win32 security) + CObjectType::SecuritySupported, + CObjectType::SecurityInfoNotPersisted, + CObjectType::UnnamedObject, + CObjectType::LocalDuplicationOnly, + CObjectType::WaitableObject, + CObjectType::ObjectCanBeUnsignaled, + CObjectType::ThreadReleaseHasNoSideEffects, + CObjectType::NoOwner + ); + +CObjectType CorUnix::otAutoResetEvent( + otiAutoResetEvent, + NULL, // No cleanup routine + NULL, // No initialization routine + 0, // No immutable data + NULL, // No immutable data copy routine + NULL, // No immutable data cleanup routine + 0, // No process local data + NULL, // No process local data cleanup routine + 0, // No shared data + EVENT_ALL_ACCESS, // Currently ignored (no Win32 security) + CObjectType::SecuritySupported, + CObjectType::SecurityInfoNotPersisted, + CObjectType::UnnamedObject, + CObjectType::LocalDuplicationOnly, + CObjectType::WaitableObject, + CObjectType::ObjectCanBeUnsignaled, + CObjectType::ThreadReleaseAltersSignalCount, + CObjectType::NoOwner + ); + +PalObjectTypeId rgEventIds[] = {otiManualResetEvent, otiAutoResetEvent}; +CAllowedObjectTypes aotEvent(rgEventIds, sizeof(rgEventIds)/sizeof(rgEventIds[0])); + +/*++ +Function: + CreateEventA + +Note: + lpEventAttributes currentely ignored: + -- Win32 object security not supported + -- handles to event objects are not inheritable + +Parameters: + See MSDN doc. +--*/ + +HANDLE +PALAPI +CreateEventA( + IN LPSECURITY_ATTRIBUTES lpEventAttributes, + IN BOOL bManualReset, + IN BOOL bInitialState, + IN LPCSTR lpName) +{ + HANDLE hEvent = NULL; + CPalThread *pthr = NULL; + PAL_ERROR palError; + + PERF_ENTRY(CreateEventA); + ENTRY("CreateEventA(lpEventAttr=%p, bManualReset=%d, bInitialState=%d, lpName=%p (%s)\n", + lpEventAttributes, bManualReset, bInitialState, lpName, lpName?lpName:"NULL"); + + pthr = InternalGetCurrentThread(); + + if (lpName != nullptr) + { + ASSERT("lpName: Cross-process named objects are not supported in PAL"); + palError = ERROR_NOT_SUPPORTED; + } + else + { + palError = InternalCreateEvent( + pthr, + lpEventAttributes, + bManualReset, + bInitialState, + NULL, + &hEvent + ); + } + + // + // We always need to set last error, even on success: + // we need to protect ourselves from the situation + // where last error is set to ERROR_ALREADY_EXISTS on + // entry to the function + // + + pthr->SetLastError(palError); + + LOGEXIT("CreateEventA returns HANDLE %p\n", hEvent); + PERF_EXIT(CreateEventA); + return hEvent; +} + + +/*++ +Function: + CreateEventW + +Note: + lpEventAttributes currentely ignored: + -- Win32 object security not supported + -- handles to event objects are not inheritable + +Parameters: + See MSDN doc. +--*/ + +HANDLE +PALAPI +CreateEventW( + IN LPSECURITY_ATTRIBUTES lpEventAttributes, + IN BOOL bManualReset, + IN BOOL bInitialState, + IN LPCWSTR lpName) +{ + HANDLE hEvent = NULL; + PAL_ERROR palError; + CPalThread *pthr = NULL; + + PERF_ENTRY(CreateEventW); + ENTRY("CreateEventW(lpEventAttr=%p, bManualReset=%d, " + "bInitialState=%d, lpName=%p (%S)\n", lpEventAttributes, bManualReset, + bInitialState, lpName, lpName?lpName:W16_NULLSTRING); + + pthr = InternalGetCurrentThread(); + + palError = InternalCreateEvent( + pthr, + lpEventAttributes, + bManualReset, + bInitialState, + lpName, + &hEvent + ); + + // + // We always need to set last error, even on success: + // we need to protect ourselves from the situation + // where last error is set to ERROR_ALREADY_EXISTS on + // entry to the function + // + + pthr->SetLastError(palError); + + LOGEXIT("CreateEventW returns HANDLE %p\n", hEvent); + PERF_EXIT(CreateEventW); + return hEvent; +} + +/*++ +Function: + CreateEventExW + +Note: + lpEventAttributes and dwDesiredAccess are currently ignored: + -- Win32 object security not supported + -- handles to event objects are not inheritable + -- Access rights are not supported + +Parameters: + See MSDN doc. +--*/ + +HANDLE +PALAPI +CreateEventExW( + IN LPSECURITY_ATTRIBUTES lpEventAttributes, + IN LPCWSTR lpName, + IN DWORD dwFlags, + IN DWORD dwDesiredAccess) +{ + return + CreateEventW( + lpEventAttributes, + (dwFlags & CREATE_EVENT_MANUAL_RESET) != 0, + (dwFlags & CREATE_EVENT_INITIAL_SET) != 0, + lpName); +} + +/*++ +Function: + InternalCreateEvent + +Note: + lpEventAttributes currentely ignored: + -- Win32 object security not supported + -- handles to event objects are not inheritable + +Parameters: + pthr -- thread data for calling thread + phEvent -- on success, receives the allocated event handle + + See MSDN docs on CreateEvent for all other parameters +--*/ + +PAL_ERROR +CorUnix::InternalCreateEvent( + CPalThread *pthr, + LPSECURITY_ATTRIBUTES lpEventAttributes, + BOOL bManualReset, + BOOL bInitialState, + LPCWSTR lpName, + HANDLE *phEvent + ) +{ + CObjectAttributes oa(lpName, lpEventAttributes); + PAL_ERROR palError = NO_ERROR; + IPalObject *pobjEvent = NULL; + IPalObject *pobjRegisteredEvent = NULL; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != phEvent); + + ENTRY("InternalCreateEvent(pthr=%p, lpEventAttributes=%p, bManualReset=%i, " + "bInitialState=%i, lpName=%p, phEvent=%p)\n", + pthr, + lpEventAttributes, + bManualReset, + bInitialState, + lpName, + phEvent + ); + + if (lpName != nullptr) + { + ASSERT("lpName: Cross-process named objects are not supported in PAL"); + palError = ERROR_NOT_SUPPORTED; + goto InternalCreateEventExit; + } + + palError = g_pObjectManager->AllocateObject( + pthr, + bManualReset ? &otManualResetEvent : &otAutoResetEvent, + &oa, + &pobjEvent + ); + + if (NO_ERROR != palError) + { + goto InternalCreateEventExit; + } + + if (bInitialState) + { + ISynchStateController *pssc; + + palError = pobjEvent->GetSynchStateController( + pthr, + &pssc + ); + + if (NO_ERROR == palError) + { + palError = pssc->SetSignalCount(1); + pssc->ReleaseController(); + } + + if (NO_ERROR != palError) + { + ASSERT("Unable to set new event state (%d)\n", palError); + goto InternalCreateEventExit; + } + } + + palError = g_pObjectManager->RegisterObject( + pthr, + pobjEvent, + &aotEvent, + phEvent, + &pobjRegisteredEvent + ); + + // + // pobjEvent is invalidated by the call to RegisterObject, so NULL it + // out here to ensure that we don't try to release a reference on + // it down the line. + // + + pobjEvent = NULL; + +InternalCreateEventExit: + + if (NULL != pobjEvent) + { + pobjEvent->ReleaseReference(pthr); + } + + if (NULL != pobjRegisteredEvent) + { + pobjRegisteredEvent->ReleaseReference(pthr); + } + + LOGEXIT("InternalCreateEvent returns %i\n", palError); + + return palError; +} + + +/*++ +Function: + SetEvent + +See MSDN doc. +--*/ + +BOOL +PALAPI +SetEvent( + IN HANDLE hEvent) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pthr = NULL; + + PERF_ENTRY(SetEvent); + ENTRY("SetEvent(hEvent=%p)\n", hEvent); + + pthr = InternalGetCurrentThread(); + + palError = InternalSetEvent(pthr, hEvent, TRUE); + + if (NO_ERROR != palError) + { + pthr->SetLastError(palError); + } + + LOGEXIT("SetEvent returns BOOL %d\n", (NO_ERROR == palError)); + PERF_EXIT(SetEvent); + return (NO_ERROR == palError); +} + + +/*++ +Function: + ResetEvent + +See MSDN doc. +--*/ + +BOOL +PALAPI +ResetEvent( + IN HANDLE hEvent) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pthr = NULL; + + PERF_ENTRY(ResetEvent); + ENTRY("ResetEvent(hEvent=%p)\n", hEvent); + + pthr = InternalGetCurrentThread(); + + palError = InternalSetEvent(pthr, hEvent, FALSE); + + if (NO_ERROR != palError) + { + pthr->SetLastError(palError); + } + + LOGEXIT("ResetEvent returns BOOL %d\n", (NO_ERROR == palError)); + PERF_EXIT(ResetEvent); + return (NO_ERROR == palError); +} + +/*++ +Function: + InternalCreateEvent + +Parameters: + pthr -- thread data for calling thread + hEvent -- handle to the event to set + fSetEvent -- if TRUE, set the event; if FALSE, reset it +--*/ + +PAL_ERROR +CorUnix::InternalSetEvent( + CPalThread *pthr, + HANDLE hEvent, + BOOL fSetEvent + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pobjEvent = NULL; + ISynchStateController *pssc = NULL; + + _ASSERTE(NULL != pthr); + + ENTRY("InternalSetEvent(pthr=%p, hEvent=%p, fSetEvent=%i\n", + pthr, + hEvent, + fSetEvent + ); + + palError = g_pObjectManager->ReferenceObjectByHandle( + pthr, + hEvent, + &aotEvent, + &pobjEvent + ); + + if (NO_ERROR != palError) + { + ERROR("Unable to obtain object for handle %p (error %d)!\n", hEvent, palError); + goto InternalSetEventExit; + } + + palError = pobjEvent->GetSynchStateController( + pthr, + &pssc + ); + + if (NO_ERROR != palError) + { + ASSERT("Error %d obtaining synch state controller\n", palError); + goto InternalSetEventExit; + } + + palError = pssc->SetSignalCount(fSetEvent ? 1 : 0); + + if (NO_ERROR != palError) + { + ASSERT("Error %d setting event state\n", palError); + goto InternalSetEventExit; + } + +InternalSetEventExit: + + if (NULL != pssc) + { + pssc->ReleaseController(); + } + + if (NULL != pobjEvent) + { + pobjEvent->ReleaseReference(pthr); + } + + LOGEXIT("InternalSetEvent returns %d\n", palError); + + return palError; +} + +// TODO: Implementation of OpenEventA() doesn't exist, do we need it? More generally, do we need the A versions at all? + +/*++ +Function: + OpenEventW + +Note: + dwDesiredAccess is currently ignored (no Win32 object security support) + bInheritHandle is currently ignored (handles to events are not inheritable) + +Parameters: + See MSDN doc. +--*/ + +HANDLE +PALAPI +OpenEventW( + IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCWSTR lpName) +{ + HANDLE hEvent = NULL; + PAL_ERROR palError = NO_ERROR; + CPalThread *pthr = NULL; + + PERF_ENTRY(OpenEventW); + ENTRY("OpenEventW(dwDesiredAccess=%#x, bInheritHandle=%d, lpName=%p (%S))\n", + dwDesiredAccess, bInheritHandle, lpName, lpName?lpName:W16_NULLSTRING); + + pthr = InternalGetCurrentThread(); + + /* validate parameters */ + if (lpName == nullptr) + { + ERROR("name is NULL\n"); + palError = ERROR_INVALID_PARAMETER; + goto OpenEventWExit; + } + else + { + ASSERT("lpName: Cross-process named objects are not supported in PAL"); + palError = ERROR_NOT_SUPPORTED; + } + +OpenEventWExit: + + if (NO_ERROR != palError) + { + pthr->SetLastError(palError); + } + + LOGEXIT("OpenEventW returns HANDLE %p\n", hEvent); + PERF_EXIT(OpenEventW); + + return hEvent; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchobj/mutex.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchobj/mutex.cpp new file mode 100644 index 0000000..a4bb340 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchobj/mutex.cpp @@ -0,0 +1,1614 @@ +// 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: + + mutex.ccpp + +Abstract: + + Implementation of mutex synchroniztion object as described in + the WIN32 API + +Revision History: + + + +--*/ + +#include "pal/dbgmsg.h" + +SET_DEFAULT_DEBUG_CHANNEL(SYNC); // some headers have code with asserts, so do this first + +#include "pal/mutex.hpp" +#include "pal/file.hpp" +#include "pal/thread.hpp" + +#include "../synchmgr/synchmanager.hpp" + +#include +#include + +#include +#include +#include + +#include "pal/sharedmemory.inl" + +using namespace CorUnix; + +/* ------------------- Definitions ------------------------------*/ + +CObjectType CorUnix::otMutex( + otiMutex, + NULL, // No cleanup routine + NULL, // No initialization routine + 0, // No immutable data + NULL, // No immutable data copy routine + NULL, // No immutable data cleanup routine + 0, // No process local data + NULL, // No process local data cleanup routine + 0, // No shared data + 0, // Should be MUTEX_ALL_ACCESS; currently ignored (no Win32 security) + CObjectType::SecuritySupported, + CObjectType::SecurityInfoNotPersisted, + CObjectType::UnnamedObject, + CObjectType::LocalDuplicationOnly, + CObjectType::WaitableObject, + CObjectType::ObjectCanBeUnsignaled, + CObjectType::ThreadReleaseAltersSignalCount, + CObjectType::OwnershipTracked + ); + +static CAllowedObjectTypes aotMutex(otiMutex); + +CObjectType CorUnix::otNamedMutex( + otiNamedMutex, + &SharedMemoryProcessDataHeader::PalObject_Close, // Cleanup routine + NULL, // No initialization routine + sizeof(SharedMemoryProcessDataHeader *), // Immutable data + NULL, // No immutable data copy routine + NULL, // No immutable data cleanup routine + 0, // No process local data + NULL, // No process local data cleanup routine + 0, // No shared data + 0, // Should be MUTEX_ALL_ACCESS; currently ignored (no Win32 security) + CObjectType::SecuritySupported, + CObjectType::SecurityInfoNotPersisted, + CObjectType::UnnamedObject, // PAL's naming infrastructure is not used + CObjectType::LocalDuplicationOnly, + CObjectType::UnwaitableObject, // PAL's waiting infrastructure is not used + CObjectType::SignalingNotApplicable, // PAL's signaling infrastructure is not used + CObjectType::ThreadReleaseNotApplicable, // PAL's signaling infrastructure is not used + CObjectType::OwnershipNotApplicable // PAL's ownership infrastructure is not used + ); + +static CAllowedObjectTypes aotNamedMutex(otiNamedMutex); + +static PalObjectTypeId anyMutexTypeIds[] = {otiMutex, otiNamedMutex}; +static CAllowedObjectTypes aotAnyMutex(anyMutexTypeIds, _countof(anyMutexTypeIds)); + +/*++ +Function: + CreateMutexA + +Note: + lpMutexAttributes currentely ignored: + -- Win32 object security not supported + -- handles to mutex objects are not inheritable + +Parameters: + See MSDN doc. +--*/ + +HANDLE +PALAPI +CreateMutexA( + IN LPSECURITY_ATTRIBUTES lpMutexAttributes, + IN BOOL bInitialOwner, + IN LPCSTR lpName) +{ + HANDLE hMutex = NULL; + CPalThread *pthr = NULL; + PAL_ERROR palError; + + PERF_ENTRY(CreateMutexA); + ENTRY("CreateMutexA(lpMutexAttr=%p, bInitialOwner=%d, lpName=%p (%s)\n", + lpMutexAttributes, bInitialOwner, lpName, lpName?lpName:"NULL"); + + pthr = InternalGetCurrentThread(); + + palError = InternalCreateMutex( + pthr, + lpMutexAttributes, + bInitialOwner, + lpName, + &hMutex + ); + + // + // We always need to set last error, even on success: + // we need to protect ourselves from the situation + // where last error is set to ERROR_ALREADY_EXISTS on + // entry to the function + // + + pthr->SetLastError(palError); + + LOGEXIT("CreateMutexA returns HANDLE %p\n", hMutex); + PERF_EXIT(CreateMutexA); + return hMutex; +} + + +/*++ +Function: + CreateMutexW + +Note: + lpMutexAttributes currentely ignored: + -- Win32 object security not supported + -- handles to mutex objects are not inheritable + +Parameters: + See MSDN doc. +--*/ + +HANDLE +PALAPI +CreateMutexW( + IN LPSECURITY_ATTRIBUTES lpMutexAttributes, + IN BOOL bInitialOwner, + IN LPCWSTR lpName) +{ + HANDLE hMutex = NULL; + PAL_ERROR palError; + CPalThread *pthr = NULL; + char utf8Name[SHARED_MEMORY_MAX_NAME_CHAR_COUNT + 1]; + + PERF_ENTRY(CreateMutexW); + ENTRY("CreateMutexW(lpMutexAttr=%p, bInitialOwner=%d, lpName=%p (%S)\n", + lpMutexAttributes, bInitialOwner, lpName, lpName?lpName:W16_NULLSTRING); + + pthr = InternalGetCurrentThread(); + + if (lpName != nullptr) + { + int bytesWritten = WideCharToMultiByte(CP_ACP, 0, lpName, -1, utf8Name, _countof(utf8Name), nullptr, nullptr); + if (bytesWritten == 0) + { + DWORD errorCode = GetLastError(); + if (errorCode == ERROR_INSUFFICIENT_BUFFER) + { + palError = static_cast(SharedMemoryError::NameTooLong); + } + else + { + ASSERT("WideCharToMultiByte failed (%u)\n", errorCode); + palError = errorCode; + } + goto CreateMutexWExit; + } + } + + palError = InternalCreateMutex( + pthr, + lpMutexAttributes, + bInitialOwner, + lpName == nullptr ? nullptr : utf8Name, + &hMutex + ); + +CreateMutexWExit: + // + // We always need to set last error, even on success: + // we need to protect ourselves from the situation + // where last error is set to ERROR_ALREADY_EXISTS on + // entry to the function + // + + pthr->SetLastError(palError); + + LOGEXIT("CreateMutexW returns HANDLE %p\n", hMutex); + PERF_EXIT(CreateMutexW); + return hMutex; +} + +/*++ +Function: +CreateMutexW + +Note: +lpMutexAttributes currentely ignored: +-- Win32 object security not supported +-- handles to mutex objects are not inheritable + +Parameters: +See MSDN doc. +--*/ + +HANDLE +PALAPI +CreateMutexExW( + IN LPSECURITY_ATTRIBUTES lpMutexAttributes, + IN LPCWSTR lpName, + IN DWORD dwFlags, + IN DWORD dwDesiredAccess) +{ + return CreateMutexW(lpMutexAttributes, (dwFlags & CREATE_MUTEX_INITIAL_OWNER) != 0, lpName); +} + +/*++ +Function: + InternalCreateMutex + +Note: + lpMutexAttributes currentely ignored: + -- Win32 object security not supported + -- handles to mutex objects are not inheritable + +Parameters: + pthr -- thread data for calling thread + phEvent -- on success, receives the allocated mutex handle + + See MSDN docs on CreateMutex for all other parameters +--*/ + +PAL_ERROR +CorUnix::InternalCreateMutex( + CPalThread *pthr, + LPSECURITY_ATTRIBUTES lpMutexAttributes, + BOOL bInitialOwner, + LPCSTR lpName, + HANDLE *phMutex + ) +{ + CObjectAttributes oa(nullptr, lpMutexAttributes); + PAL_ERROR palError = NO_ERROR; + IPalObject *pobjMutex = NULL; + IPalObject *pobjRegisteredMutex = NULL; + ISynchStateController *pssc = NULL; + HANDLE hMutex = nullptr; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != phMutex); + + ENTRY("InternalCreateMutex(pthr=%p, lpMutexAttributes=%p, bInitialOwner=%d" + ", lpName=%p, phMutex=%p)\n", + pthr, + lpMutexAttributes, + bInitialOwner, + lpName, + phMutex + ); + + if (lpName != nullptr && lpName[0] == '\0') + { + // Empty name is treated as a request for an unnamed process-local mutex + lpName = nullptr; + } + + CObjectType *ot = lpName == nullptr ? &otMutex : &otNamedMutex; + CAllowedObjectTypes *aot = lpName == nullptr ? &aotMutex : &aotNamedMutex; + + palError = g_pObjectManager->AllocateObject( + pthr, + ot, + &oa, + &pobjMutex + ); + + if (NO_ERROR != palError) + { + goto InternalCreateMutexExit; + } + + if (lpName == nullptr) + { + palError = pobjMutex->GetSynchStateController( + pthr, + &pssc + ); + + if (NO_ERROR != palError) + { + ASSERT("Unable to create state controller (%d)\n", palError); + goto InternalCreateMutexExit; + } + + if (bInitialOwner) + { + palError = pssc->SetOwner(pthr); + } + else + { + palError = pssc->SetSignalCount(1); + } + + pssc->ReleaseController(); + + if (NO_ERROR != palError) + { + ASSERT("Unable to set initial mutex state (%d)\n", palError); + goto InternalCreateMutexExit; + } + } + + palError = g_pObjectManager->RegisterObject( + pthr, + pobjMutex, + aot, + &hMutex, + &pobjRegisteredMutex + ); + + if (palError != NO_ERROR) + { + _ASSERTE(palError != ERROR_ALREADY_EXISTS); // PAL's naming infrastructure is not used for named mutexes + _ASSERTE(pobjRegisteredMutex == nullptr); + _ASSERTE(hMutex == nullptr); + goto InternalCreateMutexExit; + } + + // Now that the object has been registered successfully, it would have a reference associated with the handle, so release + // the initial reference. Any errors from now on need to revoke the handle. + _ASSERTE(pobjRegisteredMutex == pobjMutex); + _ASSERTE(hMutex != nullptr); + pobjMutex->ReleaseReference(pthr); + pobjRegisteredMutex = nullptr; + + if (lpName != nullptr) + { + SharedMemoryProcessDataHeader *processDataHeader; + bool created = false; + try + { + processDataHeader = NamedMutexProcessData::CreateOrOpen(lpName, !!bInitialOwner, &created); + } + catch (SharedMemoryException ex) + { + palError = ex.GetErrorCode(); + goto InternalCreateMutexExit; + } + SharedMemoryProcessDataHeader::PalObject_SetProcessDataHeader(pobjMutex, processDataHeader); + + if (!created) + { + // Indicate to the caller that an existing mutex was opened, and hence the caller will not have initial ownership + // of the mutex if requested through bInitialOwner + palError = ERROR_ALREADY_EXISTS; + } + } + + *phMutex = hMutex; + hMutex = nullptr; + pobjMutex = nullptr; + +InternalCreateMutexExit: + + _ASSERTE(pobjRegisteredMutex == nullptr); + if (hMutex != nullptr) + { + g_pObjectManager->RevokeHandle(pthr, hMutex); + } + else if (NULL != pobjMutex) + { + pobjMutex->ReleaseReference(pthr); + } + + LOGEXIT("InternalCreateMutex returns %i\n", palError); + + return palError; +} + +/*++ +Function: + ReleaseMutex + +Parameters: + See MSDN doc. +--*/ + +BOOL +PALAPI +ReleaseMutex( IN HANDLE hMutex ) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pthr = NULL; + + PERF_ENTRY(ReleaseMutex); + ENTRY("ReleaseMutex(hMutex=%p)\n", hMutex); + + pthr = InternalGetCurrentThread(); + + palError = InternalReleaseMutex(pthr, hMutex); + + if (NO_ERROR != palError) + { + pthr->SetLastError(palError); + } + + LOGEXIT("ReleaseMutex returns BOOL %d\n", (NO_ERROR == palError)); + PERF_EXIT(ReleaseMutex); + return (NO_ERROR == palError); +} + +/*++ +Function: + InternalReleaseMutex + +Parameters: + pthr -- thread data for calling thread + + See MSDN docs on ReleaseMutex for all other parameters +--*/ + +PAL_ERROR +CorUnix::InternalReleaseMutex( + CPalThread *pthr, + HANDLE hMutex + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pobjMutex = NULL; + ISynchStateController *pssc = NULL; + PalObjectTypeId objectTypeId; + + _ASSERTE(NULL != pthr); + + ENTRY("InternalReleaseMutex(pthr=%p, hMutex=%p)\n", + pthr, + hMutex + ); + + palError = g_pObjectManager->ReferenceObjectByHandle( + pthr, + hMutex, + &aotAnyMutex, + &pobjMutex + ); + + if (NO_ERROR != palError) + { + ERROR("Unable to obtain object for handle %p (error %d)!\n", hMutex, palError); + goto InternalReleaseMutexExit; + } + + objectTypeId = pobjMutex->GetObjectType()->GetId(); + if (objectTypeId == otiMutex) + { + palError = pobjMutex->GetSynchStateController( + pthr, + &pssc + ); + + if (NO_ERROR != palError) + { + ASSERT("Error %d obtaining synch state controller\n", palError); + goto InternalReleaseMutexExit; + } + + palError = pssc->DecrementOwnershipCount(); + + if (NO_ERROR != palError) + { + ERROR("Error %d decrementing mutex ownership count\n", palError); + goto InternalReleaseMutexExit; + } + } + else + { + _ASSERTE(objectTypeId == otiNamedMutex); + + SharedMemoryProcessDataHeader *processDataHeader = + SharedMemoryProcessDataHeader::PalObject_GetProcessDataHeader(pobjMutex); + _ASSERTE(processDataHeader != nullptr); + try + { + static_cast(processDataHeader->GetData())->ReleaseLock(); + } + catch (SharedMemoryException ex) + { + palError = ex.GetErrorCode(); + goto InternalReleaseMutexExit; + } + } + +InternalReleaseMutexExit: + + if (NULL != pssc) + { + pssc->ReleaseController(); + } + + if (NULL != pobjMutex) + { + pobjMutex->ReleaseReference(pthr); + } + + LOGEXIT("InternalReleaseMutex returns %i\n", palError); + + return palError; +} + +/*++ +Function: + OpenMutexA + +Note: + dwDesiredAccess is currently ignored (no Win32 object security support) + bInheritHandle is currently ignored (handles to mutexes are not inheritable) + +See MSDN doc. +--*/ + +HANDLE +PALAPI +OpenMutexA ( + IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCSTR lpName) +{ + HANDLE hMutex = NULL; + CPalThread *pthr = NULL; + PAL_ERROR palError; + + PERF_ENTRY(OpenMutexA); + ENTRY("OpenMutexA(dwDesiredAccess=%#x, bInheritHandle=%d, lpName=%p (%s))\n", + dwDesiredAccess, bInheritHandle, lpName, lpName?lpName:"NULL"); + + pthr = InternalGetCurrentThread(); + + /* validate parameters */ + if (lpName == nullptr) + { + ERROR("name is NULL\n"); + palError = ERROR_INVALID_PARAMETER; + goto OpenMutexAExit; + } + + palError = InternalOpenMutex(pthr, lpName, &hMutex); + +OpenMutexAExit: + if (NO_ERROR != palError) + { + pthr->SetLastError(palError); + } + + LOGEXIT("OpenMutexA returns HANDLE %p\n", hMutex); + PERF_EXIT(OpenMutexA); + return hMutex; +} + +/*++ +Function: + OpenMutexW + +Note: + dwDesiredAccess is currently ignored (no Win32 object security support) + bInheritHandle is currently ignored (handles to mutexes are not inheritable) + +See MSDN doc. +--*/ + +HANDLE +PALAPI +OpenMutexW( + IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCWSTR lpName) +{ + HANDLE hMutex = NULL; + PAL_ERROR palError = NO_ERROR; + CPalThread *pthr = NULL; + char utf8Name[SHARED_MEMORY_MAX_NAME_CHAR_COUNT + 1]; + + PERF_ENTRY(OpenMutexW); + ENTRY("OpenMutexW(dwDesiredAccess=%#x, bInheritHandle=%d, lpName=%p (%S))\n", + dwDesiredAccess, bInheritHandle, lpName, lpName?lpName:W16_NULLSTRING); + + pthr = InternalGetCurrentThread(); + + /* validate parameters */ + if (lpName == nullptr) + { + ERROR("name is NULL\n"); + palError = ERROR_INVALID_PARAMETER; + goto OpenMutexWExit; + } + + { + int bytesWritten = WideCharToMultiByte(CP_ACP, 0, lpName, -1, utf8Name, _countof(utf8Name), nullptr, nullptr); + if (bytesWritten == 0) + { + DWORD errorCode = GetLastError(); + if (errorCode == ERROR_INSUFFICIENT_BUFFER) + { + palError = static_cast(SharedMemoryError::NameTooLong); + } + else + { + ASSERT("WideCharToMultiByte failed (%u)\n", errorCode); + palError = errorCode; + } + goto OpenMutexWExit; + } + } + + palError = InternalOpenMutex(pthr, lpName == nullptr ? nullptr : utf8Name, &hMutex); + +OpenMutexWExit: + if (NO_ERROR != palError) + { + pthr->SetLastError(palError); + } + + LOGEXIT("OpenMutexW returns HANDLE %p\n", hMutex); + PERF_EXIT(OpenMutexW); + + return hMutex; +} + +/*++ +Function: + InternalOpenMutex + +Parameters: + pthr -- thread data for calling thread + phEvent -- on success, receives the allocated mutex handle + + See MSDN docs on OpenMutex for all other parameters. +--*/ + +PAL_ERROR +CorUnix::InternalOpenMutex( + CPalThread *pthr, + LPCSTR lpName, + HANDLE *phMutex + ) +{ + CObjectAttributes oa; + PAL_ERROR palError = NO_ERROR; + IPalObject *pobjMutex = NULL; + IPalObject *pobjRegisteredMutex = NULL; + HANDLE hMutex = nullptr; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != lpName); + _ASSERTE(NULL != phMutex); + + ENTRY("InternalOpenMutex(pthr=%p, " + "lpName=%p, phMutex=%p)\n", + pthr, + lpName, + phMutex + ); + + palError = g_pObjectManager->AllocateObject( + pthr, + &otNamedMutex, + &oa, + &pobjMutex + ); + + if (NO_ERROR != palError) + { + goto InternalOpenMutexExit; + } + + palError = g_pObjectManager->RegisterObject( + pthr, + pobjMutex, + &aotNamedMutex, + &hMutex, + &pobjRegisteredMutex + ); + + if (palError != NO_ERROR) + { + _ASSERTE(palError != ERROR_ALREADY_EXISTS); // PAL's naming infrastructure is not used for named mutexes + _ASSERTE(pobjRegisteredMutex == nullptr); + _ASSERTE(hMutex == nullptr); + goto InternalOpenMutexExit; + } + + // Now that the object has been registered successfully, it would have a reference associated with the handle, so release + // the initial reference. Any errors from now on need to revoke the handle. + _ASSERTE(pobjRegisteredMutex == pobjMutex); + _ASSERTE(hMutex != nullptr); + pobjMutex->ReleaseReference(pthr); + pobjRegisteredMutex = nullptr; + + { + SharedMemoryProcessDataHeader *processDataHeader; + try + { + processDataHeader = NamedMutexProcessData::Open(lpName); + } + catch (SharedMemoryException ex) + { + palError = ex.GetErrorCode(); + goto InternalOpenMutexExit; + } + if (processDataHeader == nullptr) + { + palError = ERROR_FILE_NOT_FOUND; + goto InternalOpenMutexExit; + } + SharedMemoryProcessDataHeader::PalObject_SetProcessDataHeader(pobjMutex, processDataHeader); + } + + *phMutex = hMutex; + hMutex = nullptr; + pobjMutex = nullptr; + +InternalOpenMutexExit: + + _ASSERTE(pobjRegisteredMutex == nullptr); + if (hMutex != nullptr) + { + g_pObjectManager->RevokeHandle(pthr, hMutex); + } + else if (NULL != pobjMutex) + { + pobjMutex->ReleaseReference(pthr); + } + + LOGEXIT("InternalCreateMutex returns %i\n", palError); + + return palError; +} + + +/* Basic spinlock implementation */ +void SPINLOCKAcquire (LONG * lock, unsigned int flags) +{ + size_t loop_seed = 1, loop_count = 0; + + if (flags & SYNCSPINLOCK_F_ASYMMETRIC) + { + loop_seed = ((size_t)pthread_self() % 10) + 1; + } + while (InterlockedCompareExchange(lock, 1, 0)) + { + if (!(flags & SYNCSPINLOCK_F_ASYMMETRIC) || (++loop_count % loop_seed)) + { +#if PAL_IGNORE_NORMAL_THREAD_PRIORITY + struct timespec tsSleepTime; + tsSleepTime.tv_sec = 0; + tsSleepTime.tv_nsec = 1; + nanosleep(&tsSleepTime, NULL); +#else + sched_yield(); +#endif + } + } + +} + +void SPINLOCKRelease (LONG * lock) +{ + VolatileStore(lock, 0); +} + +DWORD SPINLOCKTryAcquire (LONG * lock) +{ + return InterlockedCompareExchange(lock, 1, 0); + // only returns 0 or 1. +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// MutexHelpers + +#if NAMED_MUTEX_USE_PTHREAD_MUTEX +void MutexHelpers::InitializeProcessSharedRobustRecursiveMutex(pthread_mutex_t *mutex) +{ + _ASSERTE(mutex != nullptr); + + struct AutoCleanup + { + pthread_mutexattr_t *m_mutexAttributes; + + AutoCleanup() : m_mutexAttributes(nullptr) + { + } + + ~AutoCleanup() + { + if (m_mutexAttributes != nullptr) + { + int error = pthread_mutexattr_destroy(m_mutexAttributes); + _ASSERTE(error == 0); + } + } + } autoCleanup; + + pthread_mutexattr_t mutexAttributes; + int error = pthread_mutexattr_init(&mutexAttributes); + if (error != 0) + { + throw SharedMemoryException(static_cast(SharedMemoryError::OutOfMemory)); + } + autoCleanup.m_mutexAttributes = &mutexAttributes; + + error = pthread_mutexattr_setpshared(&mutexAttributes, PTHREAD_PROCESS_SHARED); + _ASSERTE(error == 0); + + error = pthread_mutexattr_setrobust(&mutexAttributes, PTHREAD_MUTEX_ROBUST); + _ASSERTE(error == 0); + + error = pthread_mutexattr_settype(&mutexAttributes, PTHREAD_MUTEX_RECURSIVE); + _ASSERTE(error == 0); + + error = pthread_mutex_init(mutex, &mutexAttributes); + if (error != 0) + { + throw SharedMemoryException(static_cast(error == EPERM ? SharedMemoryError::IO : SharedMemoryError::OutOfMemory)); + } +} + +void MutexHelpers::DestroyMutex(pthread_mutex_t *mutex) +{ + _ASSERTE(mutex != nullptr); + + int error = pthread_mutex_destroy(mutex); + _ASSERTE(error == 0 || error == EBUSY); // the error will be EBUSY if the mutex is locked +} + +MutexTryAcquireLockResult MutexHelpers::TryAcquireLock(pthread_mutex_t *mutex, DWORD timeoutMilliseconds) +{ + _ASSERTE(mutex != nullptr); + + int lockResult; + switch (timeoutMilliseconds) + { + case static_cast(-1): + lockResult = pthread_mutex_lock(mutex); + break; + + case 0: + lockResult = pthread_mutex_trylock(mutex); + break; + + default: + { + struct timespec timeoutTime; + PAL_ERROR palError = CPalSynchronizationManager::GetAbsoluteTimeout(timeoutMilliseconds, &timeoutTime, /*fPreferMonotonicClock*/ FALSE); + _ASSERTE(palError == NO_ERROR); + lockResult = pthread_mutex_timedlock(mutex, &timeoutTime); + break; + } + } + + switch (lockResult) + { + case 0: + return MutexTryAcquireLockResult::AcquiredLock; + + case EBUSY: + _ASSERTE(timeoutMilliseconds == 0); + return MutexTryAcquireLockResult::TimedOut; + + case ETIMEDOUT: + _ASSERTE(timeoutMilliseconds != static_cast(-1)); + _ASSERTE(timeoutMilliseconds != 0); + return MutexTryAcquireLockResult::TimedOut; + + case EOWNERDEAD: + { + int setConsistentResult = pthread_mutex_consistent(mutex); + _ASSERTE(setConsistentResult == 0); + return MutexTryAcquireLockResult::AcquiredLockButMutexWasAbandoned; + } + + case EAGAIN: + throw SharedMemoryException(static_cast(NamedMutexError::MaximumRecursiveLocksReached)); + + default: + throw SharedMemoryException(static_cast(NamedMutexError::Unknown)); + } +} + +void MutexHelpers::ReleaseLock(pthread_mutex_t *mutex) +{ + _ASSERTE(mutex != nullptr); + + int unlockResult = pthread_mutex_unlock(mutex); + _ASSERTE(unlockResult == 0); +} +#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// NamedMutexSharedData + +NamedMutexSharedData::NamedMutexSharedData() + : +#if !NAMED_MUTEX_USE_PTHREAD_MUTEX + m_timedWaiterCount(0), +#endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX + m_lockOwnerProcessId(SharedMemoryHelpers::InvalidProcessId), + m_lockOwnerThreadId(SharedMemoryHelpers::InvalidSharedThreadId), + m_isAbandoned(false) +{ +#if !NAMED_MUTEX_USE_PTHREAD_MUTEX + static_assert_no_msg(sizeof(m_timedWaiterCount) == sizeof(LONG)); // for interlocked operations +#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX + + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + _ASSERTE(SharedMemoryManager::IsCreationDeletionFileLockAcquired()); + +#if NAMED_MUTEX_USE_PTHREAD_MUTEX + MutexHelpers::InitializeProcessSharedRobustRecursiveMutex(&m_lock); +#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX +} + +NamedMutexSharedData::~NamedMutexSharedData() +{ + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + _ASSERTE(SharedMemoryManager::IsCreationDeletionFileLockAcquired()); + +#if NAMED_MUTEX_USE_PTHREAD_MUTEX + MutexHelpers::DestroyMutex(&m_lock); +#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX +} + +#if NAMED_MUTEX_USE_PTHREAD_MUTEX +pthread_mutex_t *NamedMutexSharedData::GetLock() +{ + return &m_lock; +} +#else // !NAMED_MUTEX_USE_PTHREAD_MUTEX +bool NamedMutexSharedData::HasAnyTimedWaiters() const +{ + return + InterlockedCompareExchange( + const_cast(reinterpret_cast(&m_timedWaiterCount)), + -1 /* Exchange */, + -1 /* Comparand */) != 0; +} + +void NamedMutexSharedData::IncTimedWaiterCount() +{ + ULONG newValue = InterlockedIncrement(reinterpret_cast(&m_timedWaiterCount)); + if (newValue == 0) + { + throw SharedMemoryException(static_cast(SharedMemoryError::OutOfMemory)); + } +} + +void NamedMutexSharedData::DecTimedWaiterCount() +{ + ULONG newValue = InterlockedDecrement(reinterpret_cast(&m_timedWaiterCount)); + _ASSERTE(newValue + 1 != 0); +} +#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX + +bool NamedMutexSharedData::IsAbandoned() const +{ + _ASSERTE(IsLockOwnedByCurrentThread()); + return m_isAbandoned; +} + +void NamedMutexSharedData::SetIsAbandoned(bool isAbandoned) +{ + _ASSERTE(IsLockOwnedByCurrentThread()); + _ASSERTE(m_isAbandoned != isAbandoned); + + m_isAbandoned = isAbandoned; +} + +bool NamedMutexSharedData::IsLockOwnedByAnyThread() const +{ + return + m_lockOwnerProcessId != SharedMemoryHelpers::InvalidProcessId || + m_lockOwnerThreadId != SharedMemoryHelpers::InvalidSharedThreadId; +} + +bool NamedMutexSharedData::IsLockOwnedByCurrentThread() const +{ + return m_lockOwnerProcessId == GetCurrentProcessId() && m_lockOwnerThreadId == THREADSilentGetCurrentThreadId(); +} + +void NamedMutexSharedData::SetLockOwnerToCurrentThread() +{ + m_lockOwnerProcessId = GetCurrentProcessId(); + _ASSERTE(m_lockOwnerProcessId != SharedMemoryHelpers::InvalidProcessId); + m_lockOwnerThreadId = THREADSilentGetCurrentThreadId(); + _ASSERTE(m_lockOwnerThreadId != SharedMemoryHelpers::InvalidSharedThreadId); +} + +void NamedMutexSharedData::ClearLockOwner() +{ + _ASSERTE(IsLockOwnedByCurrentThread()); + + m_lockOwnerProcessId = SharedMemoryHelpers::InvalidProcessId; + m_lockOwnerThreadId = SharedMemoryHelpers::InvalidSharedThreadId; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// NamedMutexProcessData + +// This value should only be incremented if a non-backward-compatible change to the sync system is made. A process would fail to +// open a mutex created with a different sync system version. +const UINT8 NamedMutexProcessData::SyncSystemVersion = 1; + +const DWORD NamedMutexProcessData::PollLoopMaximumSleepMilliseconds = 100; + +SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen(LPCSTR name, bool acquireLockIfCreated, bool *createdRef) +{ + return CreateOrOpen(name, true /* createIfNotExist */, acquireLockIfCreated, createdRef); +} + +SharedMemoryProcessDataHeader *NamedMutexProcessData::Open(LPCSTR name) +{ + return CreateOrOpen(name, false /* createIfNotExist */, false /* acquireLockIfCreated */, nullptr /* createdRef */); +} + +SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen( + LPCSTR name, + bool createIfNotExist, + bool acquireLockIfCreated, + bool *createdRef) +{ + _ASSERTE(name != nullptr); + _ASSERTE(createIfNotExist || !acquireLockIfCreated); + +#if !NAMED_MUTEX_USE_PTHREAD_MUTEX + PathCharString lockFilePath; +#endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX + + struct AutoCleanup + { + bool m_acquiredCreationDeletionProcessLock; + bool m_acquiredCreationDeletionFileLock; + SharedMemoryProcessDataHeader *m_processDataHeader; + #if !NAMED_MUTEX_USE_PTHREAD_MUTEX + PathCharString *m_lockFilePath; + SIZE_T m_sessionDirectoryPathCharCount; + bool m_createdLockFile; + int m_lockFileDescriptor; + #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX + bool m_cancel; + + AutoCleanup() + : m_acquiredCreationDeletionProcessLock(false), + m_acquiredCreationDeletionFileLock(false), + m_processDataHeader(nullptr), + #if !NAMED_MUTEX_USE_PTHREAD_MUTEX + m_lockFilePath(nullptr), + m_sessionDirectoryPathCharCount(0), + m_createdLockFile(false), + m_lockFileDescriptor(-1), + #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX + m_cancel(false) + { + } + + ~AutoCleanup() + { + #if !NAMED_MUTEX_USE_PTHREAD_MUTEX + if (!m_cancel) + { + if (m_lockFileDescriptor != -1) + { + SharedMemoryHelpers::CloseFile(m_lockFileDescriptor); + } + + if (m_createdLockFile) + { + _ASSERTE(m_lockFilePath != nullptr); + unlink(*m_lockFilePath); + } + + if (m_sessionDirectoryPathCharCount != 0) + { + _ASSERTE(m_lockFilePath != nullptr); + m_lockFilePath->CloseBuffer(m_sessionDirectoryPathCharCount); + rmdir(*m_lockFilePath); + } + } + #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX + + if (m_acquiredCreationDeletionFileLock) + { + SharedMemoryManager::ReleaseCreationDeletionFileLock(); + } + + if (!m_cancel && m_processDataHeader != nullptr) + { + _ASSERTE(m_acquiredCreationDeletionProcessLock); + m_processDataHeader->DecRefCount(); + } + + if (m_acquiredCreationDeletionProcessLock) + { + SharedMemoryManager::ReleaseCreationDeletionProcessLock(); + } + } + } autoCleanup; + + SharedMemoryManager::AcquireCreationDeletionProcessLock(); + autoCleanup.m_acquiredCreationDeletionProcessLock = true; + + // Create or open the shared memory + bool created; + SharedMemoryProcessDataHeader *processDataHeader = + SharedMemoryProcessDataHeader::CreateOrOpen( + name, + SharedMemorySharedDataHeader(SharedMemoryType::Mutex, SyncSystemVersion), + sizeof(NamedMutexSharedData), + createIfNotExist, + &created); + if (createdRef != nullptr) + { + *createdRef = created; + } + if (created) + { + // If the shared memory file was created, the creation/deletion file lock would have been acquired so that we can + // initialize the shared data + _ASSERTE(SharedMemoryManager::IsCreationDeletionFileLockAcquired()); + autoCleanup.m_acquiredCreationDeletionFileLock = true; + } + if (processDataHeader == nullptr) + { + _ASSERTE(!createIfNotExist); + return nullptr; + } + autoCleanup.m_processDataHeader = processDataHeader; + + if (created) + { + // Initialize the shared data + new(processDataHeader->GetSharedDataHeader()->GetData()) NamedMutexSharedData; + } + + if (processDataHeader->GetData() == nullptr) + { + #if !NAMED_MUTEX_USE_PTHREAD_MUTEX + // Create the lock files directory + SharedMemoryHelpers::BuildSharedFilesPath(lockFilePath, SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME); + if (created) + { + SharedMemoryHelpers::EnsureDirectoryExists(lockFilePath, true /* isGlobalLockAcquired */); + } + + // Create the session directory + SharedMemoryId *id = processDataHeader->GetId(); + SharedMemoryHelpers::VerifyStringOperation(lockFilePath.Append('/')); + SharedMemoryHelpers::VerifyStringOperation(id->AppendSessionDirectoryName(lockFilePath)); + if (created) + { + SharedMemoryHelpers::EnsureDirectoryExists(lockFilePath, true /* isGlobalLockAcquired */); + autoCleanup.m_lockFilePath = &lockFilePath; + autoCleanup.m_sessionDirectoryPathCharCount = lockFilePath.GetCount(); + } + + // Create or open the lock file + SharedMemoryHelpers::VerifyStringOperation(lockFilePath.Append('/')); + SharedMemoryHelpers::VerifyStringOperation(lockFilePath.Append(id->GetName(), id->GetNameCharCount())); + int lockFileDescriptor = SharedMemoryHelpers::CreateOrOpenFile(lockFilePath, created); + if (lockFileDescriptor == -1) + { + _ASSERTE(!created); + if (createIfNotExist) + { + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + return nullptr; + } + autoCleanup.m_createdLockFile = created; + autoCleanup.m_lockFileDescriptor = lockFileDescriptor; + #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX + + // Create the process data + void *processDataBuffer = SharedMemoryHelpers::Alloc(sizeof(NamedMutexProcessData)); + AutoFreeBuffer autoFreeProcessDataBuffer(processDataBuffer); + NamedMutexProcessData *processData = + new(processDataBuffer) + NamedMutexProcessData( + processDataHeader + #if !NAMED_MUTEX_USE_PTHREAD_MUTEX + , + lockFileDescriptor + #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX + ); + autoFreeProcessDataBuffer.Cancel(); + processDataHeader->SetData(processData); + + // If the mutex was created and if requested, acquire the lock initially while holding the creation/deletion locks + if (created && acquireLockIfCreated) + { + MutexTryAcquireLockResult tryAcquireLockResult = processData->TryAcquireLock(0); + _ASSERTE(tryAcquireLockResult == MutexTryAcquireLockResult::AcquiredLock); + } + } + + autoCleanup.m_cancel = true; + return processDataHeader; +} + +NamedMutexProcessData::NamedMutexProcessData( + SharedMemoryProcessDataHeader *processDataHeader +#if !NAMED_MUTEX_USE_PTHREAD_MUTEX + , + int sharedLockFileDescriptor +#endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX +) + : + m_processDataHeader(processDataHeader), + m_lockCount(0), +#if !NAMED_MUTEX_USE_PTHREAD_MUTEX + m_sharedLockFileDescriptor(sharedLockFileDescriptor), +#endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX + m_lockOwnerThread(nullptr), + m_nextInThreadOwnedNamedMutexList(nullptr) +{ + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + _ASSERTE(processDataHeader != nullptr); + +#if !NAMED_MUTEX_USE_PTHREAD_MUTEX + _ASSERTE(sharedLockFileDescriptor != -1); + + m_processLockHandle = CreateMutex(nullptr /* lpMutexAttributes */, false /* bInitialOwner */, nullptr /* lpName */); + if (m_processLockHandle == nullptr) + { + throw SharedMemoryException(GetLastError()); + } +#endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX +} + +void NamedMutexProcessData::Close(bool isAbruptShutdown, bool releaseSharedData) +{ + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + _ASSERTE(!releaseSharedData || SharedMemoryManager::IsCreationDeletionFileLockAcquired()); + + // If the process is shutting down abruptly without having closed some mutexes, there could still be threads running with + // active references to the mutex. So when shutting down abruptly, don't clean up any object or global process-local state. + if (!isAbruptShutdown) + { + CPalThread *lockOwnerThread = m_lockOwnerThread; + if (lockOwnerThread != nullptr) + { + // The mutex was not released before it was closed. If the lock is owned by the current thread, abandon the mutex. + // In both cases, clean up the owner thread's list of owned mutexes. + lockOwnerThread->synchronizationInfo.RemoveOwnedNamedMutex(this); + if (lockOwnerThread == GetCurrentPalThread()) + { + Abandon(); + } + else + { + m_lockOwnerThread = nullptr; + } + } + + if (releaseSharedData) + { + GetSharedData()->~NamedMutexSharedData(); + } + +#if !NAMED_MUTEX_USE_PTHREAD_MUTEX + CloseHandle(m_processLockHandle); + SharedMemoryHelpers::CloseFile(m_sharedLockFileDescriptor); +#endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX + + } + +#if !NAMED_MUTEX_USE_PTHREAD_MUTEX + + if (!releaseSharedData) + { + return; + } + + try + { + // Delete the lock file, and the session directory if it's not empty + PathCharString path; + SharedMemoryHelpers::BuildSharedFilesPath(path, SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME); + SharedMemoryId *id = m_processDataHeader->GetId(); + SharedMemoryHelpers::VerifyStringOperation(path.Append('/')); + SharedMemoryHelpers::VerifyStringOperation(id->AppendSessionDirectoryName(path)); + SharedMemoryHelpers::VerifyStringOperation(path.Append('/')); + SIZE_T sessionDirectoryPathCharCount = path.GetCount(); + SharedMemoryHelpers::VerifyStringOperation(path.Append(id->GetName(), id->GetNameCharCount())); + unlink(path); + path.CloseBuffer(sessionDirectoryPathCharCount); + rmdir(path); + } + catch (SharedMemoryException) + { + // Ignore the error, just don't release shared data + } +#endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX +} + +NamedMutexSharedData *NamedMutexProcessData::GetSharedData() const +{ + return reinterpret_cast(m_processDataHeader->GetSharedDataHeader()->GetData()); +} + +void NamedMutexProcessData::SetLockOwnerThread(CorUnix::CPalThread *lockOwnerThread) +{ + _ASSERTE(lockOwnerThread == nullptr || lockOwnerThread == GetCurrentPalThread()); + _ASSERTE(GetSharedData()->IsLockOwnedByCurrentThread()); + + m_lockOwnerThread = lockOwnerThread; +} + +NamedMutexProcessData *NamedMutexProcessData::GetNextInThreadOwnedNamedMutexList() const +{ + return m_nextInThreadOwnedNamedMutexList; +} + +void NamedMutexProcessData::SetNextInThreadOwnedNamedMutexList(NamedMutexProcessData *next) +{ + m_nextInThreadOwnedNamedMutexList = next; +} + +MutexTryAcquireLockResult NamedMutexProcessData::TryAcquireLock(DWORD timeoutMilliseconds) +{ + NamedMutexSharedData *sharedData = GetSharedData(); + +#if NAMED_MUTEX_USE_PTHREAD_MUTEX + MutexTryAcquireLockResult result = MutexHelpers::TryAcquireLock(sharedData->GetLock(), timeoutMilliseconds); + if (result == MutexTryAcquireLockResult::TimedOut) + { + return result; + } + + // Check if a recursive lock was just taken. The recursion level is tracked manually so that the lock owner can be cleared + // at the appropriate time, see ReleaseLock(). + if (m_lockCount != 0) + { + _ASSERTE(sharedData->IsLockOwnedByCurrentThread()); // otherwise, this thread would not have acquired the lock + _ASSERTE(GetCurrentPalThread()->synchronizationInfo.OwnsNamedMutex(this)); + + if (m_lockCount + 1 < m_lockCount) + { + MutexHelpers::ReleaseLock(sharedData->GetLock()); + throw SharedMemoryException(static_cast(NamedMutexError::MaximumRecursiveLocksReached)); + } + ++m_lockCount; + + // The lock is released upon acquiring a recursive lock from the thread that already owns the lock + MutexHelpers::ReleaseLock(sharedData->GetLock()); + + _ASSERTE(result != MutexTryAcquireLockResult::AcquiredLockButMutexWasAbandoned); + _ASSERTE(!sharedData->IsAbandoned()); + return result; + } + + // The non-recursive case is handled below (skip the #else and see below that) +#else // !NAMED_MUTEX_USE_PTHREAD_MUTEX + // If a timeout is specified, determine the start time + DWORD startTime = 0; + if (timeoutMilliseconds != static_cast(-1) && timeoutMilliseconds != 0) + { + startTime = GetTickCount(); + } + + // Acquire the process lock. A file lock can only be acquired once per file descriptor, so to synchronize the threads of + // this process, the process lock is used. + while (true) + { + DWORD waitResult = WaitForSingleObject(m_processLockHandle, timeoutMilliseconds); + switch (waitResult) + { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: // abandoned state for the process lock is irrelevant, the shared lock will also have been abandoned + break; + + case WAIT_TIMEOUT: + return MutexTryAcquireLockResult::TimedOut; + + case WAIT_IO_COMPLETION: + continue; + + case WAIT_FAILED: + throw SharedMemoryException(GetLastError()); + + default: + _ASSERTE(false); + break; + } + break; + } + + struct AutoReleaseProcessLock + { + HANDLE m_processLockHandle; + bool m_cancel; + + AutoReleaseProcessLock(HANDLE processLockHandle) : m_processLockHandle(processLockHandle), m_cancel(false) + { + } + + ~AutoReleaseProcessLock() + { + if (!m_cancel) + { + ReleaseMutex(m_processLockHandle); + } + } + } autoReleaseProcessLock(m_processLockHandle); + + // Check if it's a recursive lock attempt + if (m_lockCount != 0) + { + _ASSERTE(sharedData->IsLockOwnedByCurrentThread()); // otherwise, this thread would not have acquired the process lock + _ASSERTE(GetCurrentPalThread()->synchronizationInfo.OwnsNamedMutex(this)); + + if (m_lockCount + 1 < m_lockCount) + { + throw SharedMemoryException(static_cast(NamedMutexError::MaximumRecursiveLocksReached)); + } + ++m_lockCount; + + // The process lock is released upon acquiring a recursive lock from the thread that already owns the lock + return MutexTryAcquireLockResult::AcquiredLock; + } + + switch (timeoutMilliseconds) + { + case static_cast(-1): + { + // The file lock API does not have a timeout on the wait, so timed waiters will poll the file lock in a loop, + // sleeping for a short duration in-between. Due to the polling nature of a timed wait, timed waiters will almost + // never acquire the file lock as long as there are also untimed waiters. So, in order to make the file lock + // acquisition reasonable, when there are timed waiters, have untimed waiters also use polling. + bool acquiredFileLock = false; + while (sharedData->HasAnyTimedWaiters()) + { + if (SharedMemoryHelpers::TryAcquireFileLock(m_sharedLockFileDescriptor, LOCK_EX | LOCK_NB)) + { + acquiredFileLock = true; + break; + } + Sleep(PollLoopMaximumSleepMilliseconds); + } + if (acquiredFileLock) + { + break; + } + + acquiredFileLock = SharedMemoryHelpers::TryAcquireFileLock(m_sharedLockFileDescriptor, LOCK_EX); + _ASSERTE(acquiredFileLock); + break; + } + + case 0: + if (!SharedMemoryHelpers::TryAcquireFileLock(m_sharedLockFileDescriptor, LOCK_EX | LOCK_NB)) + { + return MutexTryAcquireLockResult::TimedOut; + } + break; + + default: + { + // Try to acquire the file lock without waiting + if (SharedMemoryHelpers::TryAcquireFileLock(m_sharedLockFileDescriptor, LOCK_EX | LOCK_NB)) + { + break; + } + + // The file lock API does not have a timeout on the wait, so timed waiters need to poll the file lock in a loop, + // sleeping for a short duration in-between. Due to the polling nature of a timed wait, timed waiters will almost + // never acquire the file lock as long as there are also untimed waiters. So, in order to make the file lock + // acquisition reasonable, record that there is a timed waiter, to have untimed waiters also use polling. + sharedData->IncTimedWaiterCount(); + struct AutoDecTimedWaiterCount + { + NamedMutexSharedData *m_sharedData; + + AutoDecTimedWaiterCount(NamedMutexSharedData *sharedData) : m_sharedData(sharedData) + { + } + + ~AutoDecTimedWaiterCount() + { + m_sharedData->DecTimedWaiterCount(); + } + } autoDecTimedWaiterCount(sharedData); + + // Poll for the file lock + do + { + DWORD elapsedMilliseconds = GetTickCount() - startTime; + if (elapsedMilliseconds >= timeoutMilliseconds) + { + return MutexTryAcquireLockResult::TimedOut; + } + + DWORD remainingMilliseconds = timeoutMilliseconds - elapsedMilliseconds; + DWORD sleepMilliseconds = + remainingMilliseconds < PollLoopMaximumSleepMilliseconds + ? remainingMilliseconds + : PollLoopMaximumSleepMilliseconds; + Sleep(sleepMilliseconds); + } while (!SharedMemoryHelpers::TryAcquireFileLock(m_sharedLockFileDescriptor, LOCK_EX | LOCK_NB)); + break; + } + } + + // There cannot be any exceptions after this + autoReleaseProcessLock.m_cancel = true; + + // After acquiring the file lock, if we find that a lock owner is already designated, the process that previously owned the + // lock must have terminated while holding the lock. + MutexTryAcquireLockResult result = + sharedData->IsLockOwnedByAnyThread() + ? MutexTryAcquireLockResult::AcquiredLockButMutexWasAbandoned + : MutexTryAcquireLockResult::AcquiredLock; +#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX + + sharedData->SetLockOwnerToCurrentThread(); + m_lockCount = 1; + CPalThread *currentThread = GetCurrentPalThread(); + SetLockOwnerThread(currentThread); + currentThread->synchronizationInfo.AddOwnedNamedMutex(this); + + if (sharedData->IsAbandoned()) + { + // The thread that previously owned the lock did not release it before exiting + sharedData->SetIsAbandoned(false); + result = MutexTryAcquireLockResult::AcquiredLockButMutexWasAbandoned; + } + return result; +} + +void NamedMutexProcessData::ReleaseLock() +{ + if (!GetSharedData()->IsLockOwnedByCurrentThread()) + { + throw SharedMemoryException(static_cast(NamedMutexError::ThreadHasNotAcquiredMutex)); + } + + _ASSERTE(GetCurrentPalThread()->synchronizationInfo.OwnsNamedMutex(this)); + + _ASSERTE(m_lockCount != 0); + --m_lockCount; + if (m_lockCount != 0) + { + return; + } + + GetCurrentPalThread()->synchronizationInfo.RemoveOwnedNamedMutex(this); + SetLockOwnerThread(nullptr); + ActuallyReleaseLock(); +} + +void NamedMutexProcessData::Abandon() +{ + NamedMutexSharedData *sharedData = GetSharedData(); + _ASSERTE(sharedData->IsLockOwnedByCurrentThread()); + _ASSERTE(m_lockCount != 0); + + sharedData->SetIsAbandoned(true); + m_lockCount = 0; + SetLockOwnerThread(nullptr); + ActuallyReleaseLock(); +} + +void NamedMutexProcessData::ActuallyReleaseLock() +{ + NamedMutexSharedData *sharedData = GetSharedData(); + _ASSERTE(sharedData->IsLockOwnedByCurrentThread()); + _ASSERTE(!GetCurrentPalThread()->synchronizationInfo.OwnsNamedMutex(this)); + _ASSERTE(m_lockCount == 0); + + sharedData->ClearLockOwner(); + +#if NAMED_MUTEX_USE_PTHREAD_MUTEX + MutexHelpers::ReleaseLock(sharedData->GetLock()); +#else // !NAMED_MUTEX_USE_PTHREAD_MUTEX + SharedMemoryHelpers::ReleaseFileLock(m_sharedLockFileDescriptor); + ReleaseMutex(m_processLockHandle); +#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchobj/semaphore.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchobj/semaphore.cpp new file mode 100644 index 0000000..f079fe5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/synchobj/semaphore.cpp @@ -0,0 +1,597 @@ +// 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: + + semaphore.cpp + +Abstract: + + Implementation of the sempahore synchroniztion object as described in + the WIN32 API + +Revision History: + + + +--*/ + +#include "pal/semaphore.hpp" +#include "pal/thread.hpp" +#include "pal/dbgmsg.h" + +using namespace CorUnix; + +/* ------------------- Definitions ------------------------------*/ +SET_DEFAULT_DEBUG_CHANNEL(SYNC); + +CObjectType CorUnix::otSemaphore( + otiSemaphore, + NULL, // No cleanup routine + NULL, // No initialization routine + sizeof(SemaphoreImmutableData), + NULL, // No immutable data copy routine + NULL, // No immutable data cleanup routine + 0, // No process local data + NULL, // No process local data cleanup routine + 0, // No shared data + 0, // Should be SEMAPHORE_ALL_ACCESS; currently ignored (no Win32 security) + CObjectType::SecuritySupported, + CObjectType::SecurityInfoNotPersisted, + CObjectType::UnnamedObject, + CObjectType::LocalDuplicationOnly, + CObjectType::WaitableObject, + CObjectType::ObjectCanBeUnsignaled, + CObjectType::ThreadReleaseAltersSignalCount, + CObjectType::NoOwner + ); + +CAllowedObjectTypes aotSempahore(otiSemaphore); + +/*++ +Function: +CreateSemaphoreExA + +Note: +lpSemaphoreAttributes currently ignored: +-- Win32 object security not supported +-- handles to semaphore objects are not inheritable + +Parameters: +See MSDN doc. +--*/ + +HANDLE +PALAPI +CreateSemaphoreExA( + IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + IN LONG lInitialCount, + IN LONG lMaximumCount, + IN LPCSTR lpName, + IN /*_Reserved_*/ DWORD dwFlags, + IN DWORD dwDesiredAccess) +{ + // dwFlags is reserved and unused, and dwDesiredAccess is currently + // only ever used as SEMAPHORE_ALL_ACCESS. The other parameters + // all map to CreateSemaphoreA. + _ASSERTE(SEMAPHORE_ALL_ACCESS == dwDesiredAccess); + + return CreateSemaphoreA( + lpSemaphoreAttributes, + lInitialCount, + lMaximumCount, + lpName); +} + +/*++ +Function: + CreateSemaphoreA + +Note: + lpSemaphoreAttributes currently ignored: + -- Win32 object security not supported + -- handles to semaphore objects are not inheritable + +Parameters: + See MSDN doc. +--*/ + +HANDLE +PALAPI +CreateSemaphoreA( + IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + IN LONG lInitialCount, + IN LONG lMaximumCount, + IN LPCSTR lpName) +{ + HANDLE hSemaphore = NULL; + CPalThread *pthr = NULL; + PAL_ERROR palError; + + PERF_ENTRY(CreateSemaphoreA); + ENTRY("CreateSemaphoreA(lpSemaphoreAttributes=%p, lInitialCount=%d, " + "lMaximumCount=%d, lpName=%p (%s))\n", + lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName, lpName?lpName:"NULL"); + + pthr = InternalGetCurrentThread(); + + if (lpName != nullptr) + { + ASSERT("lpName: Cross-process named objects are not supported in PAL"); + palError = ERROR_NOT_SUPPORTED; + } + else + { + palError = InternalCreateSemaphore( + pthr, + lpSemaphoreAttributes, + lInitialCount, + lMaximumCount, + NULL, + &hSemaphore + ); + } + + // + // We always need to set last error, even on success: + // we need to protect ourselves from the situation + // where last error is set to ERROR_ALREADY_EXISTS on + // entry to the function + // + + pthr->SetLastError(palError); + + LOGEXIT("CreateSemaphoreA returns HANDLE %p\n", hSemaphore); + PERF_EXIT(CreateSemaphoreA); + return hSemaphore; +} + +/*++ +Function: +CreateSemaphoreExW + +Note: +lpSemaphoreAttributes currentely ignored: +-- Win32 object security not supported +-- handles to semaphore objects are not inheritable + +Parameters: +See MSDN doc. +--*/ + +HANDLE +PALAPI +CreateSemaphoreExW( + IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + IN LONG lInitialCount, + IN LONG lMaximumCount, + IN LPCWSTR lpName, + IN /*_Reserved_*/ DWORD dwFlags, + IN DWORD dwDesiredAccess) +{ + // dwFlags is reserved and unused + + return CreateSemaphoreW( + lpSemaphoreAttributes, + lInitialCount, + lMaximumCount, + lpName); +} + +/*++ +Function: + CreateSemaphoreW + +Note: + lpSemaphoreAttributes currentely ignored: + -- Win32 object security not supported + -- handles to semaphore objects are not inheritable + +Parameters: + See MSDN doc. +--*/ + +HANDLE +PALAPI +CreateSemaphoreW( + IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + IN LONG lInitialCount, + IN LONG lMaximumCount, + IN LPCWSTR lpName) +{ + HANDLE hSemaphore = NULL; + PAL_ERROR palError; + CPalThread *pthr = NULL; + + PERF_ENTRY(CreateSemaphoreW); + ENTRY("CreateSemaphoreW(lpSemaphoreAttributes=%p, lInitialCount=%d, " + "lMaximumCount=%d, lpName=%p (%S))\n", + lpSemaphoreAttributes, lInitialCount, lMaximumCount, + lpName, lpName?lpName:W16_NULLSTRING); + + pthr = InternalGetCurrentThread(); + + palError = InternalCreateSemaphore( + pthr, + lpSemaphoreAttributes, + lInitialCount, + lMaximumCount, + lpName, + &hSemaphore + ); + + // + // We always need to set last error, even on success: + // we need to protect ourselves from the situation + // where last error is set to ERROR_ALREADY_EXISTS on + // entry to the function + // + + pthr->SetLastError(palError); + + LOGEXIT("CreateSemaphoreW returns HANDLE %p\n", hSemaphore); + PERF_EXIT(CreateSemaphoreW); + return hSemaphore; +} + +/*++ +Function: + InternalCreateSemaphore + +Note: + lpSemaphoreAttributes currentely ignored: + -- Win32 object security not supported + -- handles to semaphore objects are not inheritable + +Parameters + pthr -- thread data for calling thread + phEvent -- on success, receives the allocated semaphore handle + + See MSDN docs on CreateSemaphore for all other parameters. +--*/ + +PAL_ERROR +CorUnix::InternalCreateSemaphore( + CPalThread *pthr, + LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + LONG lInitialCount, + LONG lMaximumCount, + LPCWSTR lpName, + HANDLE *phSemaphore + ) +{ + CObjectAttributes oa(lpName, lpSemaphoreAttributes); + PAL_ERROR palError = NO_ERROR; + IPalObject *pobjSemaphore = NULL; + IPalObject *pobjRegisteredSemaphore = NULL; + SemaphoreImmutableData *pSemaphoreData; + + _ASSERTE(NULL != pthr); + _ASSERTE(NULL != phSemaphore); + + ENTRY("InternalCreateSemaphore(pthr=%p, lpSemaphoreAttributes=%p, " + "lInitialCount=%d, lMaximumCount=%d, lpName=%p, phSemaphore=%p)\n", + pthr, + lpSemaphoreAttributes, + lInitialCount, + lMaximumCount, + lpName, + phSemaphore + ); + + if (lpName != nullptr) + { + ASSERT("lpName: Cross-process named objects are not supported in PAL"); + palError = ERROR_NOT_SUPPORTED; + goto InternalCreateSemaphoreExit; + } + + if (lMaximumCount <= 0) + { + ERROR("lMaximumCount is invalid (%d)\n", lMaximumCount); + palError = ERROR_INVALID_PARAMETER; + goto InternalCreateSemaphoreExit; + } + + if ((lInitialCount < 0) || (lInitialCount > lMaximumCount)) + { + ERROR("lInitialCount is invalid (%d)\n", lInitialCount); + palError = ERROR_INVALID_PARAMETER; + goto InternalCreateSemaphoreExit; + } + + palError = g_pObjectManager->AllocateObject( + pthr, + &otSemaphore, + &oa, + &pobjSemaphore + ); + + if (NO_ERROR != palError) + { + goto InternalCreateSemaphoreExit; + } + + palError = pobjSemaphore->GetImmutableData(reinterpret_cast(&pSemaphoreData)); + + if (NO_ERROR != palError) + { + ASSERT("Error %d obtaining object data\n", palError); + goto InternalCreateSemaphoreExit; + } + + pSemaphoreData->lMaximumCount = lMaximumCount; + + if (0 != lInitialCount) + { + ISynchStateController *pssc; + + palError = pobjSemaphore->GetSynchStateController( + pthr, + &pssc + ); + + if (NO_ERROR == palError) + { + palError = pssc->SetSignalCount(lInitialCount); + pssc->ReleaseController(); + } + + if (NO_ERROR != palError) + { + ASSERT("Unable to set new semaphore state (%d)\n", palError); + goto InternalCreateSemaphoreExit; + } + } + + palError = g_pObjectManager->RegisterObject( + pthr, + pobjSemaphore, + &aotSempahore, + phSemaphore, + &pobjRegisteredSemaphore + ); + + // + // pobjSemaphore is invalidated by the call to RegisterObject, so NULL it + // out here to ensure that we don't try to release a reference on + // it down the line. + // + + pobjSemaphore = NULL; + +InternalCreateSemaphoreExit: + + if (NULL != pobjSemaphore) + { + pobjSemaphore->ReleaseReference(pthr); + } + + if (NULL != pobjRegisteredSemaphore) + { + pobjRegisteredSemaphore->ReleaseReference(pthr); + } + + LOGEXIT("InternalCreateSemaphore returns %d\n", palError); + + return palError; +} + + +/*++ +Function: + ReleaseSemaphore + +Parameters: + See MSDN doc. +--*/ + +BOOL +PALAPI +ReleaseSemaphore( + IN HANDLE hSemaphore, + IN LONG lReleaseCount, + OUT LPLONG lpPreviousCount) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pthr = NULL; + + PERF_ENTRY(ReleaseSemaphore); + ENTRY("ReleaseSemaphore(hSemaphore=%p, lReleaseCount=%d, " + "lpPreviousCount=%p)\n", + hSemaphore, lReleaseCount, lpPreviousCount); + + pthr = InternalGetCurrentThread(); + + palError = InternalReleaseSemaphore( + pthr, + hSemaphore, + lReleaseCount, + lpPreviousCount + ); + + if (NO_ERROR != palError) + { + pthr->SetLastError(palError); + } + + LOGEXIT ("ReleaseSemaphore returns BOOL %d\n", (NO_ERROR == palError)); + PERF_EXIT(ReleaseSemaphore); + return (NO_ERROR == palError); +} + +/*++ +Function: + InternalReleaseSemaphore + +Parameters: + pthr -- thread data for calling thread + + See MSDN docs on ReleaseSemaphore for all other parameters +--*/ + +PAL_ERROR +CorUnix::InternalReleaseSemaphore( + CPalThread *pthr, + HANDLE hSemaphore, + LONG lReleaseCount, + LPLONG lpPreviousCount + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pobjSemaphore = NULL; + ISynchStateController *pssc = NULL; + SemaphoreImmutableData *pSemaphoreData; + LONG lOldCount; + + _ASSERTE(NULL != pthr); + + ENTRY("InternalReleaseSempahore(pthr=%p, hSemaphore=%p, lReleaseCount=%d, " + "lpPreviousCount=%p)\n", + pthr, + hSemaphore, + lReleaseCount, + lpPreviousCount + ); + + if (0 >= lReleaseCount) + { + palError = ERROR_INVALID_PARAMETER; + goto InternalReleaseSemaphoreExit; + } + + palError = g_pObjectManager->ReferenceObjectByHandle( + pthr, + hSemaphore, + &aotSempahore, + &pobjSemaphore + ); + + if (NO_ERROR != palError) + { + ERROR("Unable to obtain object for handle %p (error %d)!\n", hSemaphore, palError); + goto InternalReleaseSemaphoreExit; + } + + palError = pobjSemaphore->GetImmutableData(reinterpret_cast(&pSemaphoreData)); + + if (NO_ERROR != palError) + { + ASSERT("Error %d obtaining object data\n", palError); + goto InternalReleaseSemaphoreExit; + } + + palError = pobjSemaphore->GetSynchStateController( + pthr, + &pssc + ); + + if (NO_ERROR != palError) + { + ASSERT("Error %d obtaining synch state controller\n", palError); + goto InternalReleaseSemaphoreExit; + } + + palError = pssc->GetSignalCount(&lOldCount); + + if (NO_ERROR != palError) + { + ASSERT("Error %d obtaining current signal count\n", palError); + goto InternalReleaseSemaphoreExit; + } + + _ASSERTE(lOldCount <= pSemaphoreData->lMaximumCount); + if (lReleaseCount > pSemaphoreData->lMaximumCount - lOldCount) + { + palError = ERROR_TOO_MANY_POSTS; + goto InternalReleaseSemaphoreExit; + } + + palError = pssc->IncrementSignalCount(lReleaseCount); + + if (NO_ERROR != palError) + { + ASSERT("Error %d incrementing signal count\n", palError); + goto InternalReleaseSemaphoreExit; + } + + if (NULL != lpPreviousCount) + { + *lpPreviousCount = lOldCount; + } + +InternalReleaseSemaphoreExit: + + if (NULL != pssc) + { + pssc->ReleaseController(); + } + + if (NULL != pobjSemaphore) + { + pobjSemaphore->ReleaseReference(pthr); + } + + LOGEXIT("InternalReleaseSemaphore returns %d\n", palError); + + return palError; +} + +// TODO: Implementation of OpenSemaphoreA() doesn't exist, do we need it? More generally, do we need the A versions at all? + +/*++ +Function: + OpenSemaphoreW + +Note: + dwDesiredAccess is currently ignored (no Win32 object security support) + bInheritHandle is currently ignored (handles to semaphore are not inheritable) + +Parameters: + See MSDN doc. +--*/ + +HANDLE +PALAPI +OpenSemaphoreW( + IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCWSTR lpName) +{ + HANDLE hSemaphore = NULL; + PAL_ERROR palError = NO_ERROR; + CPalThread *pthr = NULL; + + PERF_ENTRY(OpenSemaphoreW); + ENTRY("OpenSemaphoreW(dwDesiredAccess=%#x, bInheritHandle=%d, lpName=%p (%S))\n", + dwDesiredAccess, bInheritHandle, lpName, lpName?lpName:W16_NULLSTRING); + + pthr = InternalGetCurrentThread(); + + /* validate parameters */ + if (lpName == nullptr) + { + ERROR("lpName is NULL\n"); + palError = ERROR_INVALID_PARAMETER; + } + else + { + ASSERT("lpName: Cross-process named objects are not supported in PAL"); + palError = ERROR_NOT_SUPPORTED; + } + + if (NO_ERROR != palError) + { + pthr->SetLastError(palError); + } + + LOGEXIT("OpenSemaphoreW returns HANDLE %p\n", hSemaphore); + PERF_EXIT(OpenSemaphoreW); + + return hSemaphore; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/context.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/context.cpp new file mode 100644 index 0000000..435b047 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/context.cpp @@ -0,0 +1,1426 @@ +// 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: + + context.c + +Abstract: + + Implementation of GetThreadContext/SetThreadContext/DebugBreak. + There are a lot of architecture specifics here. + + + +--*/ + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(THREAD); // some headers have code with asserts, so do this first + +#include "pal/palinternal.h" +#include "pal/context.h" +#include "pal/debug.h" +#include "pal/thread.hpp" +#include "pal/utils.h" +#include "pal/virtual.h" + +#if HAVE_SYS_PTRACE_H +#include +#endif +#include +#include + +extern PGET_GCMARKER_EXCEPTION_CODE g_getGcMarkerExceptionCode; + +#define CONTEXT_AREA_MASK 0xffff +#ifdef HOST_X86 +#define CONTEXT_ALL_FLOATING (CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS) +#elif defined(HOST_AMD64) +#define CONTEXT_ALL_FLOATING CONTEXT_FLOATING_POINT +#elif defined(HOST_ARM) +#define CONTEXT_ALL_FLOATING CONTEXT_FLOATING_POINT +#elif defined(HOST_ARM64) +#define CONTEXT_ALL_FLOATING CONTEXT_FLOATING_POINT +#else +#error Unexpected architecture. +#endif + +#if !HAVE_MACH_EXCEPTIONS + +#ifndef __GLIBC__ +typedef int __ptrace_request; +#endif + +#if HAVE_MACHINE_REG_H +#include +#endif // HAVE_MACHINE_REG_H +#if HAVE_MACHINE_NPX_H +#include +#endif // HAVE_MACHINE_NPX_H + +#if HAVE_PT_REGS +#include +#endif // HAVE_PT_REGS + +#ifdef HOST_AMD64 +#define ASSIGN_CONTROL_REGS \ + ASSIGN_REG(Rbp) \ + ASSIGN_REG(Rip) \ + ASSIGN_REG(SegCs) \ + ASSIGN_REG(EFlags) \ + ASSIGN_REG(Rsp) \ + +#define ASSIGN_INTEGER_REGS \ + ASSIGN_REG(Rdi) \ + ASSIGN_REG(Rsi) \ + ASSIGN_REG(Rbx) \ + ASSIGN_REG(Rdx) \ + ASSIGN_REG(Rcx) \ + ASSIGN_REG(Rax) \ + ASSIGN_REG(R8) \ + ASSIGN_REG(R9) \ + ASSIGN_REG(R10) \ + ASSIGN_REG(R11) \ + ASSIGN_REG(R12) \ + ASSIGN_REG(R13) \ + ASSIGN_REG(R14) \ + ASSIGN_REG(R15) \ + +#elif defined(HOST_X86) +#define ASSIGN_CONTROL_REGS \ + ASSIGN_REG(Ebp) \ + ASSIGN_REG(Eip) \ + ASSIGN_REG(SegCs) \ + ASSIGN_REG(EFlags) \ + ASSIGN_REG(Esp) \ + ASSIGN_REG(SegSs) \ + +#define ASSIGN_INTEGER_REGS \ + ASSIGN_REG(Edi) \ + ASSIGN_REG(Esi) \ + ASSIGN_REG(Ebx) \ + ASSIGN_REG(Edx) \ + ASSIGN_REG(Ecx) \ + ASSIGN_REG(Eax) \ + +#elif defined(HOST_ARM) +#define ASSIGN_CONTROL_REGS \ + ASSIGN_REG(Sp) \ + ASSIGN_REG(Lr) \ + ASSIGN_REG(Pc) \ + ASSIGN_REG(Cpsr) \ + +#define ASSIGN_INTEGER_REGS \ + ASSIGN_REG(R0) \ + ASSIGN_REG(R1) \ + ASSIGN_REG(R2) \ + ASSIGN_REG(R3) \ + ASSIGN_REG(R4) \ + ASSIGN_REG(R5) \ + ASSIGN_REG(R6) \ + ASSIGN_REG(R7) \ + ASSIGN_REG(R8) \ + ASSIGN_REG(R9) \ + ASSIGN_REG(R10) \ + ASSIGN_REG(R11) \ + ASSIGN_REG(R12) +#elif defined(HOST_ARM64) +#define ASSIGN_CONTROL_REGS \ + ASSIGN_REG(Cpsr) \ + ASSIGN_REG(Fp) \ + ASSIGN_REG(Sp) \ + ASSIGN_REG(Lr) \ + ASSIGN_REG(Pc) + +#define ASSIGN_INTEGER_REGS \ + ASSIGN_REG(X0) \ + ASSIGN_REG(X1) \ + ASSIGN_REG(X2) \ + ASSIGN_REG(X3) \ + ASSIGN_REG(X4) \ + ASSIGN_REG(X5) \ + ASSIGN_REG(X6) \ + ASSIGN_REG(X7) \ + ASSIGN_REG(X8) \ + ASSIGN_REG(X9) \ + ASSIGN_REG(X10) \ + ASSIGN_REG(X11) \ + ASSIGN_REG(X12) \ + ASSIGN_REG(X13) \ + ASSIGN_REG(X14) \ + ASSIGN_REG(X15) \ + ASSIGN_REG(X16) \ + ASSIGN_REG(X17) \ + ASSIGN_REG(X18) \ + ASSIGN_REG(X19) \ + ASSIGN_REG(X20) \ + ASSIGN_REG(X21) \ + ASSIGN_REG(X22) \ + ASSIGN_REG(X23) \ + ASSIGN_REG(X24) \ + ASSIGN_REG(X25) \ + ASSIGN_REG(X26) \ + ASSIGN_REG(X27) \ + ASSIGN_REG(X28) + +#else +#error "Don't know how to assign registers on this architecture" +#endif + +#define ASSIGN_ALL_REGS \ + ASSIGN_CONTROL_REGS \ + ASSIGN_INTEGER_REGS \ + +/*++ +Function: + CONTEXT_GetRegisters + +Abstract + retrieve the machine registers value of the indicated process. + +Parameter + processId: process ID + lpContext: context structure in which the machine registers value will be returned. +Return + returns TRUE if it succeeds, FALSE otherwise +--*/ +BOOL CONTEXT_GetRegisters(DWORD processId, LPCONTEXT lpContext) +{ +#if HAVE_BSD_REGS_T + int regFd = -1; +#endif // HAVE_BSD_REGS_T + BOOL bRet = FALSE; + + if (processId == GetCurrentProcessId()) + { + CONTEXT_CaptureContext(lpContext); + } + else + { + ucontext_t registers; +#if HAVE_PT_REGS + struct pt_regs ptrace_registers; + if (ptrace((__ptrace_request)PTRACE_GETREGS, processId, (caddr_t) &ptrace_registers, 0) == -1) +#elif HAVE_BSD_REGS_T + struct reg ptrace_registers; + if (PAL_PTRACE(PT_GETREGS, processId, &ptrace_registers, 0) == -1) +#endif + { + ASSERT("Failed ptrace(PT_GETREGS, processId:%d) errno:%d (%s)\n", + processId, errno, strerror(errno)); + } + +#if HAVE_PT_REGS +#define ASSIGN_REG(reg) MCREG_##reg(registers.uc_mcontext) = PTREG_##reg(ptrace_registers); +#elif HAVE_BSD_REGS_T +#define ASSIGN_REG(reg) MCREG_##reg(registers.uc_mcontext) = BSDREG_##reg(ptrace_registers); +#else +#define ASSIGN_REG(reg) + ASSERT("Don't know how to get the context of another process on this platform!"); + return bRet; +#endif + ASSIGN_ALL_REGS +#undef ASSIGN_REG + + CONTEXTFromNativeContext(®isters, lpContext, lpContext->ContextFlags); + } + + bRet = TRUE; +#if HAVE_BSD_REGS_T + if (regFd != -1) + { + close(regFd); + } +#endif // HAVE_BSD_REGS_T + return bRet; +} + +/*++ +Function: + GetThreadContext + +See MSDN doc. +--*/ +BOOL +CONTEXT_GetThreadContext( + DWORD dwProcessId, + pthread_t self, + LPCONTEXT lpContext) +{ + BOOL ret = FALSE; + + if (lpContext == NULL) + { + ERROR("Invalid lpContext parameter value\n"); + SetLastError(ERROR_NOACCESS); + goto EXIT; + } + + /* How to consider the case when self is different from the current + thread of its owner process. Machine registers values could be retreived + by a ptrace(pid, ...) call or from the "/proc/%pid/reg" file content. + Unfortunately, these two methods only depend on process ID, not on + thread ID. */ + + if (dwProcessId == GetCurrentProcessId()) + { + if (self != pthread_self()) + { + DWORD flags; + // There aren't any APIs for this. We can potentially get the + // context of another thread by using per-thread signals, but + // on FreeBSD signal handlers that are called as a result + // of signals raised via pthread_kill don't get a valid + // sigcontext or ucontext_t. But we need this to return TRUE + // to avoid an assertion in the CLR in code that manages to + // cope reasonably well without a valid thread context. + // Given that, we'll zero out our structure and return TRUE. + ERROR("GetThreadContext on a thread other than the current " + "thread is returning TRUE\n"); + flags = lpContext->ContextFlags; + memset(lpContext, 0, sizeof(*lpContext)); + lpContext->ContextFlags = flags; + ret = TRUE; + goto EXIT; + } + + } + + if (lpContext->ContextFlags & + (CONTEXT_CONTROL | CONTEXT_INTEGER) & CONTEXT_AREA_MASK) + { + if (CONTEXT_GetRegisters(dwProcessId, lpContext) == FALSE) + { + SetLastError(ERROR_INTERNAL_ERROR); + goto EXIT; + } + } + + ret = TRUE; + +EXIT: + return ret; +} + +/*++ +Function: + SetThreadContext + +See MSDN doc. +--*/ +BOOL +CONTEXT_SetThreadContext( + DWORD dwProcessId, + pthread_t self, + CONST CONTEXT *lpContext) +{ + BOOL ret = FALSE; + +#if HAVE_PT_REGS + struct pt_regs ptrace_registers; +#elif HAVE_BSD_REGS_T + struct reg ptrace_registers; +#endif + + if (lpContext == NULL) + { + ERROR("Invalid lpContext parameter value\n"); + SetLastError(ERROR_NOACCESS); + goto EXIT; + } + + /* How to consider the case when self is different from the current + thread of its owner process. Machine registers values could be retreived + by a ptrace(pid, ...) call or from the "/proc/%pid/reg" file content. + Unfortunately, these two methods only depend on process ID, not on + thread ID. */ + + if (dwProcessId == GetCurrentProcessId()) + { + // Need to implement SetThreadContext(current thread) for the IX architecture; look at common_signal_handler. + _ASSERT(FALSE); + + ASSERT("SetThreadContext should be called for cross-process only.\n"); + SetLastError(ERROR_INVALID_PARAMETER); + goto EXIT; + } + + if (lpContext->ContextFlags & + (CONTEXT_CONTROL | CONTEXT_INTEGER) & CONTEXT_AREA_MASK) + { +#if HAVE_PT_REGS + if (ptrace((__ptrace_request)PTRACE_GETREGS, dwProcessId, (caddr_t)&ptrace_registers, 0) == -1) +#elif HAVE_BSD_REGS_T + if (PAL_PTRACE(PT_GETREGS, dwProcessId, &ptrace_registers, 0) == -1) +#endif + { + ASSERT("Failed ptrace(PT_GETREGS, processId:%d) errno:%d (%s)\n", + dwProcessId, errno, strerror(errno)); + SetLastError(ERROR_INTERNAL_ERROR); + goto EXIT; + } + +#if HAVE_PT_REGS +#define ASSIGN_REG(reg) PTREG_##reg(ptrace_registers) = lpContext->reg; +#elif HAVE_BSD_REGS_T +#define ASSIGN_REG(reg) BSDREG_##reg(ptrace_registers) = lpContext->reg; +#else +#define ASSIGN_REG(reg) + ASSERT("Don't know how to set the context of another process on this platform!"); + return FALSE; +#endif + if (lpContext->ContextFlags & CONTEXT_CONTROL & CONTEXT_AREA_MASK) + { + ASSIGN_CONTROL_REGS + } + if (lpContext->ContextFlags & CONTEXT_INTEGER & CONTEXT_AREA_MASK) + { + ASSIGN_INTEGER_REGS + } +#undef ASSIGN_REG + +#if HAVE_PT_REGS + if (ptrace((__ptrace_request)PTRACE_SETREGS, dwProcessId, (caddr_t)&ptrace_registers, 0) == -1) +#elif HAVE_BSD_REGS_T + if (PAL_PTRACE(PT_SETREGS, dwProcessId, &ptrace_registers, 0) == -1) +#endif + { + ASSERT("Failed ptrace(PT_SETREGS, processId:%d) errno:%d (%s)\n", + dwProcessId, errno, strerror(errno)); + SetLastError(ERROR_INTERNAL_ERROR); + goto EXIT; + } + } + + ret = TRUE; + EXIT: + return ret; +} + +/*++ +Function : + CONTEXTToNativeContext + + Converts a CONTEXT record to a native context. + +Parameters : + CONST CONTEXT *lpContext : CONTEXT to convert + native_context_t *native : native context to fill in + +Return value : + None + +--*/ +void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native) +{ +#define ASSIGN_REG(reg) MCREG_##reg(native->uc_mcontext) = lpContext->reg; + if ((lpContext->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) + { + ASSIGN_CONTROL_REGS + } + + if ((lpContext->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) + { + ASSIGN_INTEGER_REGS + } +#undef ASSIGN_REG + +#if !HAVE_FPREGS_WITH_CW +#if HAVE_GREGSET_T || HAVE_GREGSET_T +#if HAVE_GREGSET_T + if (native->uc_mcontext.fpregs == nullptr) +#elif HAVE___GREGSET_T + if (native->uc_mcontext.__fpregs == nullptr) +#endif // HAVE_GREGSET_T + { + // If the pointer to the floating point state in the native context + // is not valid, we can't copy floating point registers regardless of + // whether CONTEXT_FLOATING_POINT is set in the CONTEXT's flags. + return; + } +#endif // HAVE_GREGSET_T || HAVE_GREGSET_T +#endif // !HAVE_FPREGS_WITH_CW + + if ((lpContext->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) + { +#ifdef HOST_AMD64 + FPREG_ControlWord(native) = lpContext->FltSave.ControlWord; + FPREG_StatusWord(native) = lpContext->FltSave.StatusWord; +#if HAVE_FPREGS_WITH_CW + FPREG_TagWord1(native) = lpContext->FltSave.TagWord >> 8; + FPREG_TagWord2(native) = lpContext->FltSave.TagWord & 0xff; +#else + FPREG_TagWord(native) = lpContext->FltSave.TagWord; +#endif + FPREG_ErrorOffset(native) = lpContext->FltSave.ErrorOffset; + FPREG_ErrorSelector(native) = lpContext->FltSave.ErrorSelector; + FPREG_DataOffset(native) = lpContext->FltSave.DataOffset; + FPREG_DataSelector(native) = lpContext->FltSave.DataSelector; + FPREG_MxCsr(native) = lpContext->FltSave.MxCsr; + FPREG_MxCsr_Mask(native) = lpContext->FltSave.MxCsr_Mask; + + for (int i = 0; i < 8; i++) + { + FPREG_St(native, i) = lpContext->FltSave.FloatRegisters[i]; + } + + for (int i = 0; i < 16; i++) + { + FPREG_Xmm(native, i) = lpContext->FltSave.XmmRegisters[i]; + } +#elif defined(HOST_ARM64) + fpsimd_context* fp = GetNativeSigSimdContext(native); + if (fp) + { + fp->fpsr = lpContext->Fpsr; + fp->fpcr = lpContext->Fpcr; + for (int i = 0; i < 32; i++) + { + *(NEON128*) &fp->vregs[i] = lpContext->V[i]; + } + } +#elif defined(HOST_ARM) + VfpSigFrame* fp = GetNativeSigSimdContext(native); + if (fp) + { + fp->Fpscr = lpContext->Fpscr; + for (int i = 0; i < 32; i++) + { + fp->D[i] = lpContext->D[i]; + } + } +#endif + } + + // TODO: Enable for all Unix systems +#if defined(HOST_AMD64) && defined(XSTATE_SUPPORTED) + if ((lpContext->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE) + { + _ASSERTE(FPREG_HasYmmRegisters(native)); + memcpy_s(FPREG_Xstate_Ymmh(native), sizeof(M128A) * 16, lpContext->VectorRegister, sizeof(M128A) * 16); + } +#endif //HOST_AMD64 && XSTATE_SUPPORTED +} + +/*++ +Function : + CONTEXTFromNativeContext + + Converts a native context to a CONTEXT record. + +Parameters : + const native_context_t *native : native context to convert + LPCONTEXT lpContext : CONTEXT to fill in + ULONG contextFlags : flags that determine which registers are valid in + native and which ones to set in lpContext + +Return value : + None + +--*/ +void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContext, + ULONG contextFlags) +{ + lpContext->ContextFlags = contextFlags; + +#define ASSIGN_REG(reg) lpContext->reg = MCREG_##reg(native->uc_mcontext); + if ((contextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) + { + ASSIGN_CONTROL_REGS +#if defined(HOST_ARM) + // WinContext assumes that the least bit of Pc is always 1 (denoting thumb) + // although the pc value retrived from native context might not have set the least bit. + // This becomes especially problematic if the context is on the JIT_WRITEBARRIER. + lpContext->Pc |= 0x1; +#endif + } + + if ((contextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) + { + ASSIGN_INTEGER_REGS + } +#undef ASSIGN_REG + +#if !HAVE_FPREGS_WITH_CW +#if HAVE_GREGSET_T || HAVE___GREGSET_T +#if HAVE_GREGSET_T + if (native->uc_mcontext.fpregs == nullptr) +#elif HAVE___GREGSET_T + if (native->uc_mcontext.__fpregs == nullptr) +#endif // HAVE_GREGSET_T + { + // Reset the CONTEXT_FLOATING_POINT bit(s) and the CONTEXT_XSTATE bit(s) so it's + // clear that the floating point and extended state data in the CONTEXT is not + // valid. Since these flags are defined as the architecture bit(s) OR'd with one + // or more other bits, we first get the bits that are unique to each by resetting + // the architecture bits. We determine what those are by inverting the union of + // CONTEXT_CONTROL and CONTEXT_INTEGER, both of which should also have the + // architecture bit(s) set. + const ULONG floatingPointFlags = CONTEXT_FLOATING_POINT & ~(CONTEXT_CONTROL & CONTEXT_INTEGER); + const ULONG xstateFlags = CONTEXT_XSTATE & ~(CONTEXT_CONTROL & CONTEXT_INTEGER); + + lpContext->ContextFlags &= ~(floatingPointFlags | xstateFlags); + + // Bail out regardless of whether the caller wanted CONTEXT_FLOATING_POINT or CONTEXT_XSTATE + return; + } +#endif // HAVE_GREGSET_T || HAVE___GREGSET_T +#endif // !HAVE_FPREGS_WITH_CW + + if ((contextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) + { +#ifdef HOST_AMD64 + lpContext->FltSave.ControlWord = FPREG_ControlWord(native); + lpContext->FltSave.StatusWord = FPREG_StatusWord(native); +#if HAVE_FPREGS_WITH_CW + lpContext->FltSave.TagWord = ((DWORD)FPREG_TagWord1(native) << 8) | FPREG_TagWord2(native); +#else + lpContext->FltSave.TagWord = FPREG_TagWord(native); +#endif + lpContext->FltSave.ErrorOffset = FPREG_ErrorOffset(native); + lpContext->FltSave.ErrorSelector = FPREG_ErrorSelector(native); + lpContext->FltSave.DataOffset = FPREG_DataOffset(native); + lpContext->FltSave.DataSelector = FPREG_DataSelector(native); + lpContext->FltSave.MxCsr = FPREG_MxCsr(native); + lpContext->FltSave.MxCsr_Mask = FPREG_MxCsr_Mask(native); + + for (int i = 0; i < 8; i++) + { + lpContext->FltSave.FloatRegisters[i] = FPREG_St(native, i); + } + + for (int i = 0; i < 16; i++) + { + lpContext->FltSave.XmmRegisters[i] = FPREG_Xmm(native, i); + } +#elif defined(HOST_ARM64) + const fpsimd_context* fp = GetConstNativeSigSimdContext(native); + if (fp) + { + lpContext->Fpsr = fp->fpsr; + lpContext->Fpcr = fp->fpcr; + for (int i = 0; i < 32; i++) + { + lpContext->V[i] = *(NEON128*) &fp->vregs[i]; + } + } +#elif defined(HOST_ARM) + const VfpSigFrame* fp = GetConstNativeSigSimdContext(native); + if (fp) + { + lpContext->Fpscr = fp->Fpscr; + for (int i = 0; i < 32; i++) + { + lpContext->D[i] = fp->D[i]; + } + } + else + { + // Floating point state is not valid + // Mark the context correctly + lpContext->ContextFlags &= ~(ULONG)CONTEXT_FLOATING_POINT; + } +#endif + } + +#ifdef HOST_AMD64 + if ((contextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE) + { + // TODO: Enable for all Unix systems +#if XSTATE_SUPPORTED + if (FPREG_HasYmmRegisters(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 // HOST_AMD64 +} + +/*++ +Function : + GetNativeContextPC + + Returns the program counter from the native context. + +Parameters : + const native_context_t *native : native context + +Return value : + The program counter from the native context. + +--*/ +LPVOID GetNativeContextPC(const native_context_t *context) +{ +#ifdef HOST_AMD64 + return (LPVOID)MCREG_Rip(context->uc_mcontext); +#elif defined(HOST_X86) + return (LPVOID) MCREG_Eip(context->uc_mcontext); +#elif defined(HOST_ARM) + return (LPVOID) MCREG_Pc(context->uc_mcontext); +#elif defined(HOST_ARM64) + return (LPVOID) MCREG_Pc(context->uc_mcontext); +#else +# error implement me for this architecture +#endif +} + +/*++ +Function : + GetNativeContextSP + + Returns the stack pointer from the native context. + +Parameters : + const native_context_t *native : native context + +Return value : + The stack pointer from the native context. + +--*/ +LPVOID GetNativeContextSP(const native_context_t *context) +{ +#ifdef HOST_AMD64 + return (LPVOID)MCREG_Rsp(context->uc_mcontext); +#elif defined(HOST_X86) + return (LPVOID) MCREG_Esp(context->uc_mcontext); +#elif defined(HOST_ARM) + return (LPVOID) MCREG_Sp(context->uc_mcontext); +#elif defined(HOST_ARM64) + return (LPVOID) MCREG_Sp(context->uc_mcontext); +#else +# error implement me for this architecture +#endif +} + + +/*++ +Function : + CONTEXTGetExceptionCodeForSignal + + Translates signal and context information to a Win32 exception code. + +Parameters : + const siginfo_t *siginfo : signal information from a signal handler + const native_context_t *context : context information + +Return value : + The Win32 exception code that corresponds to the signal and context + information. + +--*/ +#ifdef ILL_ILLOPC +// If si_code values are available for all signals, use those. +DWORD CONTEXTGetExceptionCodeForSignal(const siginfo_t *siginfo, + const native_context_t *context) +{ + // IMPORTANT NOTE: This function must not call any signal unsafe functions + // since it is called from signal handlers. + // That includes ASSERT and TRACE macros. + + switch (siginfo->si_signo) + { + case SIGILL: + switch (siginfo->si_code) + { + case ILL_ILLOPC: // Illegal opcode + case ILL_ILLOPN: // Illegal operand + case ILL_ILLADR: // Illegal addressing mode + case ILL_ILLTRP: // Illegal trap + case ILL_COPROC: // Co-processor error + return EXCEPTION_ILLEGAL_INSTRUCTION; + case ILL_PRVOPC: // Privileged opcode + case ILL_PRVREG: // Privileged register + return EXCEPTION_PRIV_INSTRUCTION; + case ILL_BADSTK: // Internal stack error + return EXCEPTION_STACK_OVERFLOW; + default: + break; + } + break; + case SIGFPE: + switch (siginfo->si_code) + { + case FPE_INTDIV: + return EXCEPTION_INT_DIVIDE_BY_ZERO; + case FPE_INTOVF: + return EXCEPTION_INT_OVERFLOW; + case FPE_FLTDIV: + return EXCEPTION_FLT_DIVIDE_BY_ZERO; + case FPE_FLTOVF: + return EXCEPTION_FLT_OVERFLOW; + case FPE_FLTUND: + return EXCEPTION_FLT_UNDERFLOW; + case FPE_FLTRES: + return EXCEPTION_FLT_INEXACT_RESULT; + case FPE_FLTINV: + return EXCEPTION_FLT_INVALID_OPERATION; + case FPE_FLTSUB: + return EXCEPTION_FLT_INVALID_OPERATION; + default: + break; + } + break; + case SIGSEGV: + switch (siginfo->si_code) + { + case SI_USER: // User-generated signal, sometimes sent + // for SIGSEGV under normal circumstances + case SEGV_MAPERR: // Address not mapped to object + case SEGV_ACCERR: // Invalid permissions for mapped object + return EXCEPTION_ACCESS_VIOLATION; + +#ifdef SI_KERNEL + case SI_KERNEL: + { + // Identify privileged instructions that are not identified as such by the system + if (g_getGcMarkerExceptionCode != nullptr) + { + DWORD exceptionCode = g_getGcMarkerExceptionCode(GetNativeContextPC(context)); + if (exceptionCode != 0) + { + return exceptionCode; + } + } + return EXCEPTION_ACCESS_VIOLATION; + } +#endif + default: + break; + } + break; + case SIGBUS: + switch (siginfo->si_code) + { + case BUS_ADRALN: // Invalid address alignment + return EXCEPTION_DATATYPE_MISALIGNMENT; + case BUS_ADRERR: // Non-existent physical address + return EXCEPTION_ACCESS_VIOLATION; + case BUS_OBJERR: // Object-specific hardware error + default: + break; + } + case SIGTRAP: + switch (siginfo->si_code) + { +#ifdef SI_KERNEL + case SI_KERNEL: +#endif + case SI_USER: + case TRAP_BRKPT: // Process breakpoint + return EXCEPTION_BREAKPOINT; + case TRAP_TRACE: // Process trace trap + return EXCEPTION_SINGLE_STEP; + default: + // Got unknown SIGTRAP signal with code siginfo->si_code; + return EXCEPTION_ILLEGAL_INSTRUCTION; + } + default: + break; + } + + // Got unknown signal number siginfo->si_signo with code siginfo->si_code; + return EXCEPTION_ILLEGAL_INSTRUCTION; +} +#else // ILL_ILLOPC +DWORD CONTEXTGetExceptionCodeForSignal(const siginfo_t *siginfo, + const native_context_t *context) +{ + // IMPORTANT NOTE: This function must not call any signal unsafe functions + // since it is called from signal handlers. + // That includes ASSERT and TRACE macros. + + int trap; + + if (siginfo->si_signo == SIGFPE) + { + // Floating point exceptions are mapped by their si_code. + switch (siginfo->si_code) + { + case FPE_INTDIV : + return EXCEPTION_INT_DIVIDE_BY_ZERO; + case FPE_INTOVF : + return EXCEPTION_INT_OVERFLOW; + case FPE_FLTDIV : + return EXCEPTION_FLT_DIVIDE_BY_ZERO; + case FPE_FLTOVF : + return EXCEPTION_FLT_OVERFLOW; + case FPE_FLTUND : + return EXCEPTION_FLT_UNDERFLOW; + case FPE_FLTRES : + return EXCEPTION_FLT_INEXACT_RESULT; + case FPE_FLTINV : + return EXCEPTION_FLT_INVALID_OPERATION; + case FPE_FLTSUB :/* subscript out of range */ + return EXCEPTION_FLT_INVALID_OPERATION; + default: + // Got unknown signal code siginfo->si_code; + return 0; + } + } + + trap = context->uc_mcontext.mc_trapno; + switch (trap) + { + case T_PRIVINFLT : /* privileged instruction */ + return EXCEPTION_PRIV_INSTRUCTION; + case T_BPTFLT : /* breakpoint instruction */ + return EXCEPTION_BREAKPOINT; + case T_ARITHTRAP : /* arithmetic trap */ + return 0; /* let the caller pick an exception code */ +#ifdef T_ASTFLT + case T_ASTFLT : /* system forced exception : ^C, ^\. SIGINT signal + handler shouldn't be calling this function, since + it doesn't need an exception code */ + // Trap code T_ASTFLT received, shouldn't get here; + return 0; +#endif // T_ASTFLT + case T_PROTFLT : /* protection fault */ + return EXCEPTION_ACCESS_VIOLATION; + case T_TRCTRAP : /* debug exception (sic) */ + return EXCEPTION_SINGLE_STEP; + case T_PAGEFLT : /* page fault */ + return EXCEPTION_ACCESS_VIOLATION; + case T_ALIGNFLT : /* alignment fault */ + return EXCEPTION_DATATYPE_MISALIGNMENT; + case T_DIVIDE : + return EXCEPTION_INT_DIVIDE_BY_ZERO; + case T_NMI : /* non-maskable trap */ + return EXCEPTION_ILLEGAL_INSTRUCTION; + case T_OFLOW : + return EXCEPTION_INT_OVERFLOW; + case T_BOUND : /* bound instruction fault */ + return EXCEPTION_ARRAY_BOUNDS_EXCEEDED; + case T_DNA : /* device not available fault */ + return EXCEPTION_ILLEGAL_INSTRUCTION; + case T_DOUBLEFLT : /* double fault */ + return EXCEPTION_ILLEGAL_INSTRUCTION; + case T_FPOPFLT : /* fp coprocessor operand fetch fault */ + return EXCEPTION_FLT_INVALID_OPERATION; + case T_TSSFLT : /* invalid tss fault */ + return EXCEPTION_ILLEGAL_INSTRUCTION; + case T_SEGNPFLT : /* segment not present fault */ + return EXCEPTION_ACCESS_VIOLATION; + case T_STKFLT : /* stack fault */ + return EXCEPTION_STACK_OVERFLOW; + case T_MCHK : /* machine check trap */ + return EXCEPTION_ILLEGAL_INSTRUCTION; + case T_RESERVED : /* reserved (unknown) */ + return EXCEPTION_ILLEGAL_INSTRUCTION; + default: + // Got unknown trap code trap; + break; + } + return EXCEPTION_ILLEGAL_INSTRUCTION; +} +#endif // ILL_ILLOPC + +#else // !HAVE_MACH_EXCEPTIONS + +#include +#include +#include "../exception/machexception.h" + +/*++ +Function: + CONTEXT_GetThreadContextFromPort + + Helper for GetThreadContext that uses a mach_port +--*/ +kern_return_t +CONTEXT_GetThreadContextFromPort( + mach_port_t Port, + LPCONTEXT lpContext) +{ + // Extract the CONTEXT from the Mach thread. + + kern_return_t MachRet = KERN_SUCCESS; + mach_msg_type_number_t StateCount; + thread_state_flavor_t StateFlavor; + + if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) & CONTEXT_AREA_MASK) + { + +#ifdef HOST_AMD64 + x86_thread_state64_t State; + StateFlavor = x86_THREAD_STATE64; +#else +#error Unexpected architecture. +#endif + 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(THREAD_STATE) failed: %d\n", MachRet); + goto exit; + } + + CONTEXT_GetThreadContextFromThreadState(StateFlavor, (thread_state_t)&State, lpContext); + } + + if (lpContext->ContextFlags & CONTEXT_ALL_FLOATING & CONTEXT_AREA_MASK) { + // The thread_get_state for floating point state can fail for some flavors when the processor is not + // in the right mode at the time we are taking the state. So we will try to get the AVX state first and + // if it fails, get the FLOAT state and if that fails, take AVX512 state. Both AVX and AVX512 states + // are supersets of the FLOAT state. + // 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(sizeof(x86_avx512_state64_t) > sizeof(x86_avx_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)); + static_assert_no_msg(offsetof(x86_avx512_state64_t, __fpu_fcw) == offsetof(x86_float_state64_t, __fpu_fcw)); + static_assert_no_msg(offsetof(x86_avx512_state64_t, __fpu_xmm0) == offsetof(x86_float_state64_t, __fpu_xmm0)); + + x86_avx512_state64_t State; + + StateFlavor = x86_AVX_STATE64; + StateCount = sizeof(x86_avx_state64_t) / sizeof(natural_t); + MachRet = thread_get_state(Port, StateFlavor, (thread_state_t)&State, &StateCount); + if (MachRet != KERN_SUCCESS) + { + // The AVX state is not available, try to get the AVX512 state. + StateFlavor = x86_AVX512_STATE64; + StateCount = sizeof(x86_avx512_state64_t) / sizeof(natural_t); + MachRet = thread_get_state(Port, StateFlavor, (thread_state_t)&State, &StateCount); + if (MachRet != KERN_SUCCESS) + { + // Neither the AVX nor the AVX512 state is not available, try to get at least the FLOAT state. + lpContext->ContextFlags &= ~(CONTEXT_XSTATE & CONTEXT_AREA_MASK); + + StateFlavor = x86_FLOAT_STATE64; + StateCount = sizeof(x86_float_state64_t) / sizeof(natural_t); + MachRet = thread_get_state(Port, StateFlavor, (thread_state_t)&State, &StateCount); + if (MachRet != KERN_SUCCESS) + { + // We were unable to get any floating point state. This case was observed on OSX with AVX512 capable processors. + lpContext->ContextFlags &= ~((CONTEXT_XSTATE | CONTEXT_ALL_FLOATING) & CONTEXT_AREA_MASK); + } + } + } + + CONTEXT_GetThreadContextFromThreadState(StateFlavor, (thread_state_t)&State, lpContext); + } + +exit: + return MachRet; +} + +/*++ +Function: + CONTEXT_GetThreadContextFromThreadState + +--*/ +void +CONTEXT_GetThreadContextFromThreadState( + thread_state_flavor_t threadStateFlavor, + thread_state_t threadState, + LPCONTEXT lpContext) +{ + switch (threadStateFlavor) + { +#ifdef HOST_AMD64 + case x86_THREAD_STATE64: + if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) & CONTEXT_AREA_MASK) + { + x86_thread_state64_t *pState = (x86_thread_state64_t *)threadState; + + lpContext->Rax = pState->__rax; + lpContext->Rbx = pState->__rbx; + lpContext->Rcx = pState->__rcx; + lpContext->Rdx = pState->__rdx; + lpContext->Rdi = pState->__rdi; + lpContext->Rsi = pState->__rsi; + lpContext->Rbp = pState->__rbp; + lpContext->Rsp = pState->__rsp; + lpContext->R8 = pState->__r8; + lpContext->R9 = pState->__r9; + lpContext->R10 = pState->__r10; + lpContext->R11 = pState->__r11; + lpContext->R12 = pState->__r12; + lpContext->R13 = pState->__r13; + lpContext->R14 = pState->__r14; + lpContext->R15 = pState->__r15; + lpContext->EFlags = pState->__rflags; + lpContext->Rip = pState->__rip; + lpContext->SegCs = pState->__cs; + // RtlRestoreContext uses the actual ss instead of this one + // to build the iret frame so just set it zero. + lpContext->SegSs = 0; + lpContext->SegDs = 0; + lpContext->SegEs = 0; + lpContext->SegFs = pState->__fs; + lpContext->SegGs = pState->__gs; + } + break; + + case x86_AVX_STATE64: + case x86_AVX512_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); + } + + // Intentional fall-through, the AVX states are supersets of the FLOAT state + + case x86_FLOAT_STATE64: + if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT & CONTEXT_AREA_MASK) + { + x86_float_state64_t *pState = (x86_float_state64_t *)threadState; + + lpContext->FltSave.ControlWord = *(DWORD*)&pState->__fpu_fcw; + lpContext->FltSave.StatusWord = *(DWORD*)&pState->__fpu_fsw; + lpContext->FltSave.TagWord = pState->__fpu_ftw; + lpContext->FltSave.ErrorOffset = pState->__fpu_ip; + lpContext->FltSave.ErrorSelector = pState->__fpu_cs; + lpContext->FltSave.DataOffset = pState->__fpu_dp; + lpContext->FltSave.DataSelector = pState->__fpu_ds; + lpContext->FltSave.MxCsr = pState->__fpu_mxcsr; + lpContext->FltSave.MxCsr_Mask = pState->__fpu_mxcsrmask; // note: we don't save the mask for x86 + + // Windows stores the floating point registers in a packed layout (each 10-byte register end to end + // for a total of 80 bytes). But Mach returns each register in an 16-bit structure (presumably for + // alignment purposes). So we can't just memcpy the registers over in a single block, we need to copy + // them individually. + for (int i = 0; i < 8; i++) + 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, 16 * 16); + } + break; +#else +#error Unexpected architecture. +#endif + case x86_THREAD_STATE: + { + x86_thread_state_t *pState = (x86_thread_state_t *)threadState; + CONTEXT_GetThreadContextFromThreadState((thread_state_flavor_t)pState->tsh.flavor, (thread_state_t)&pState->uts, lpContext); + } + break; + + case x86_FLOAT_STATE: + { + x86_float_state_t *pState = (x86_float_state_t *)threadState; + CONTEXT_GetThreadContextFromThreadState((thread_state_flavor_t)pState->fsh.flavor, (thread_state_t)&pState->ufs, lpContext); + } + break; + + default: + ASSERT("Invalid thread state flavor %d\n", threadStateFlavor); + break; + } +} + +/*++ +Function: + GetThreadContext + +See MSDN doc. +--*/ +BOOL +CONTEXT_GetThreadContext( + DWORD dwProcessId, + pthread_t self, + LPCONTEXT lpContext) +{ + BOOL ret = FALSE; + + if (lpContext == NULL) + { + ERROR("Invalid lpContext parameter value\n"); + SetLastError(ERROR_NOACCESS); + goto EXIT; + } + + if (GetCurrentProcessId() == dwProcessId) + { + if (self != pthread_self()) + { + // the target thread is in the current process, but isn't + // the current one: extract the CONTEXT from the Mach thread. + mach_port_t mptPort; + mptPort = pthread_mach_thread_np(self); + + ret = (CONTEXT_GetThreadContextFromPort(mptPort, lpContext) == KERN_SUCCESS); + } + else + { + CONTEXT_CaptureContext(lpContext); + ret = TRUE; + } + } + else + { + ASSERT("Cross-process GetThreadContext() is not supported on this platform\n"); + SetLastError(ERROR_NOACCESS); + } + +EXIT: + return ret; +} + +/*++ +Function: + SetThreadContextOnPort + + Helper for CONTEXT_SetThreadContext +--*/ +kern_return_t +CONTEXT_SetThreadContextOnPort( + mach_port_t Port, + IN CONST CONTEXT *lpContext) +{ + kern_return_t MachRet = KERN_SUCCESS; + mach_msg_type_number_t StateCount; + thread_state_flavor_t StateFlavor; + + if (lpContext->ContextFlags & (CONTEXT_CONTROL|CONTEXT_INTEGER) & CONTEXT_AREA_MASK) + { +#ifdef HOST_AMD64 + x86_thread_state64_t State; + StateFlavor = x86_THREAD_STATE64; + + State.__rax = lpContext->Rax; + State.__rbx = lpContext->Rbx; + State.__rcx = lpContext->Rcx; + State.__rdx = lpContext->Rdx; + State.__rdi = lpContext->Rdi; + State.__rsi = lpContext->Rsi; + State.__rbp = lpContext->Rbp; + State.__rsp = lpContext->Rsp; + State.__r8 = lpContext->R8; + State.__r9 = lpContext->R9; + State.__r10 = lpContext->R10; + State.__r11 = lpContext->R11; + State.__r12 = lpContext->R12; + State.__r13 = lpContext->R13; + State.__r14 = lpContext->R14; + State.__r15 = lpContext->R15; +// State.ss = lpContext->SegSs; + State.__rflags = lpContext->EFlags; + State.__rip = lpContext->Rip; + State.__cs = lpContext->SegCs; +// State.ds = lpContext->SegDs_PAL_Undefined; +// State.es = lpContext->SegEs_PAL_Undefined; + State.__fs = lpContext->SegFs; + State.__gs = lpContext->SegGs; +#else +#error Unexpected architecture. +#endif + + StateCount = sizeof(State) / sizeof(natural_t); + + MachRet = thread_set_state(Port, + StateFlavor, + (thread_state_t)&State, + StateCount); + if (MachRet != KERN_SUCCESS) + { + ASSERT("thread_set_state(THREAD_STATE) failed: %d\n", MachRet); + goto EXIT; + } + } + + if (lpContext->ContextFlags & CONTEXT_ALL_FLOATING & CONTEXT_AREA_MASK) + { + +#ifdef HOST_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 + + // 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 + // values first. + if ((lpContext->ContextFlags & CONTEXT_ALL_FLOATING) != + CONTEXT_ALL_FLOATING) + { + mach_msg_type_number_t StateCountGet = StateCount; + MachRet = thread_get_state(Port, + StateFlavor, + (thread_state_t)&State, + &StateCountGet); + if (MachRet != KERN_SUCCESS) + { + ASSERT("thread_get_state(FLOAT_STATE) failed: %d\n", MachRet); + goto EXIT; + } + _ASSERTE(StateCountGet == StateCount); + } + + if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT & CONTEXT_AREA_MASK) + { +#ifdef HOST_AMD64 + *(DWORD*)&State.__fpu_fcw = lpContext->FltSave.ControlWord; + *(DWORD*)&State.__fpu_fsw = lpContext->FltSave.StatusWord; + State.__fpu_ftw = lpContext->FltSave.TagWord; + State.__fpu_ip = lpContext->FltSave.ErrorOffset; + State.__fpu_cs = lpContext->FltSave.ErrorSelector; + State.__fpu_dp = lpContext->FltSave.DataOffset; + State.__fpu_ds = lpContext->FltSave.DataSelector; + State.__fpu_mxcsr = lpContext->FltSave.MxCsr; + State.__fpu_mxcsrmask = lpContext->FltSave.MxCsr_Mask; // note: we don't save the mask for x86 + + // Windows stores the floating point registers in a packed layout (each 10-byte register end to + // end for a total of 80 bytes). But Mach returns each register in an 16-bit structure (presumably + // for alignment purposes). So we can't just memcpy the registers over in a single block, we need + // to copy them individually. + 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, 16 * 16); +#else +#error Unexpected architecture. +#endif + } + +#if defined(HOST_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, + StateCount); + if (MachRet != KERN_SUCCESS) + { + ASSERT("thread_set_state(FLOAT_STATE) failed: %d\n", MachRet); + goto EXIT; + } + } + +EXIT: + return MachRet; +} + +/*++ +Function: + SetThreadContext + +See MSDN doc. +--*/ +BOOL +CONTEXT_SetThreadContext( + DWORD dwProcessId, + pthread_t self, + CONST CONTEXT *lpContext) +{ + BOOL ret = FALSE; + + if (lpContext == NULL) + { + ERROR("Invalid lpContext parameter value\n"); + SetLastError(ERROR_NOACCESS); + goto EXIT; + } + + if (dwProcessId != GetCurrentProcessId()) + { + // GetThreadContext() of a thread in another process + ASSERT("Cross-process GetThreadContext() is not supported\n"); + SetLastError(ERROR_NOACCESS); + goto EXIT; + } + + if (self != pthread_self()) + { + // hThread is in the current process, but isn't the current + // thread. Extract the CONTEXT from the Mach thread. + + mach_port_t mptPort; + + mptPort = pthread_mach_thread_np(self); + + ret = (CONTEXT_SetThreadContextOnPort(mptPort, lpContext) == KERN_SUCCESS); + } + else + { + MachSetThreadContext(const_cast(lpContext)); + ASSERT("MachSetThreadContext should never return\n"); + } + +EXIT: + return ret; +} + +#endif // !HAVE_MACH_EXCEPTIONS + +/*++ +Function: + DBG_FlushInstructionCache: processor-specific portion of + FlushInstructionCache + +See MSDN doc. +--*/ +BOOL +DBG_FlushInstructionCache( + IN LPCVOID lpBaseAddress, + IN SIZE_T dwSize) +{ +#ifndef HOST_ARM + // Intrinsic should do the right thing across all platforms (except Linux arm) + __builtin___clear_cache((char *)lpBaseAddress, (char *)((INT_PTR)lpBaseAddress + dwSize)); +#else // HOST_ARM + // On Linux/arm (at least on 3.10) we found that there is a problem with __do_cache_op (arch/arm/kernel/traps.c) + // implementing cacheflush syscall. cacheflush flushes only the first page in range [lpBaseAddress, lpBaseAddress + dwSize) + // and leaves other pages in undefined state which causes random tests failures (often due to SIGSEGV) with no particular pattern. + // + // As a workaround, we call __builtin___clear_cache on each page separately. + + const SIZE_T pageSize = GetVirtualPageSize(); + INT_PTR begin = (INT_PTR)lpBaseAddress; + const INT_PTR end = begin + dwSize; + + while (begin < end) + { + INT_PTR endOrNextPageBegin = ALIGN_UP(begin + 1, pageSize); + if (endOrNextPageBegin > end) + endOrNextPageBegin = end; + + __builtin___clear_cache((char *)begin, (char *)endOrNextPageBegin); + begin = endOrNextPageBegin; + } +#endif // HOST_ARM + return TRUE; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/process.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/process.cpp new file mode 100644 index 0000000..e002f23 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/process.cpp @@ -0,0 +1,5058 @@ +// 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: + + process.cpp + +Abstract: + + Implementation of process object and functions related to processes. + + + +--*/ + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(PROCESS); // some headers have code with asserts, so do this first + +#include "pal/procobj.hpp" +#include "pal/thread.hpp" +#include "pal/file.hpp" +#include "pal/handlemgr.hpp" +#include "pal/module.h" +#include "procprivate.hpp" +#include "pal/palinternal.h" +#include "pal/process.h" +#include "pal/init.h" +#include "pal/critsect.h" +#include "pal/debug.h" +#include "pal/utils.h" +#include "pal/environ.h" +#include "pal/virtual.h" +#include "pal/stackstring.hpp" + +#include +#if HAVE_POLL +#include +#else +#include "pal/fakepoll.h" +#endif // HAVE_POLL + +#include +#include +#include +#include +#include +#if HAVE_PRCTL_H +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#ifdef __linux__ +#include // __NR_membarrier +// Ensure __NR_membarrier is defined for portable builds. +# if !defined(__NR_membarrier) +# if defined(__amd64__) +# define __NR_membarrier 324 +# elif defined(__i386__) +# define __NR_membarrier 375 +# elif defined(__arm__) +# define __NR_membarrier 389 +# elif defined(__aarch64__) +# define __NR_membarrier 283 +# elif +# error Unknown architecture +# endif +# endif +#endif + +#ifdef __APPLE__ +#include +#include +#endif + +#ifdef __NetBSD__ +#include +#include +#include +#include +#endif + +extern char *g_szCoreCLRPath; + +using namespace CorUnix; + +CObjectType CorUnix::otProcess( + otiProcess, + NULL, // No cleanup routine + NULL, // No initialization routine + 0, // No immutable data + NULL, // No immutable data copy routine + NULL, // No immutable data cleanup routine + sizeof(CProcProcessLocalData), + NULL, // No process local data cleanup routine + 0, // No shared data + PROCESS_ALL_ACCESS, + CObjectType::SecuritySupported, + CObjectType::SecurityInfoNotPersisted, + CObjectType::UnnamedObject, + CObjectType::CrossProcessDuplicationAllowed, + CObjectType::WaitableObject, + CObjectType::SingleTransitionObject, + CObjectType::ThreadReleaseHasNoSideEffects, + CObjectType::NoOwner + ); + +// +// Helper membarrier function +// +#ifdef __NR_membarrier +# define membarrier(...) syscall(__NR_membarrier, __VA_ARGS__) +#else +# define membarrier(...) -ENOSYS +#endif + +enum membarrier_cmd +{ + MEMBARRIER_CMD_QUERY = 0, + MEMBARRIER_CMD_GLOBAL = (1 << 0), + MEMBARRIER_CMD_GLOBAL_EXPEDITED = (1 << 1), + MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED = (1 << 2), + MEMBARRIER_CMD_PRIVATE_EXPEDITED = (1 << 3), + MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED = (1 << 4), + MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE = (1 << 5), + MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE = (1 << 6) +}; + +// +// Tracks if the OS supports FlushProcessWriteBuffers using membarrier +// +static int s_flushUsingMemBarrier = 0; + +// +// Helper memory page used by the FlushProcessWriteBuffers +// +static int* s_helperPage = 0; + +// +// Mutex to make the FlushProcessWriteBuffersMutex thread safe +// +pthread_mutex_t flushProcessWriteBuffersMutex; + +CAllowedObjectTypes aotProcess(otiProcess); + +// +// The representative IPalObject for this process +// +IPalObject* CorUnix::g_pobjProcess; + +// +// Critical section that protects process data (e.g., the +// list of active threads)/ +// +CRITICAL_SECTION g_csProcess; + +// +// List and count of active threads +// +CPalThread* CorUnix::pGThreadList; +DWORD g_dwThreadCount; + +// +// The command line and app name for the process +// +LPWSTR g_lpwstrCmdLine = NULL; +LPWSTR g_lpwstrAppDir = NULL; + +// Thread ID of thread that has started the ExitProcess process +Volatile terminator = 0; + +// Process and session ID of this process. +DWORD gPID = (DWORD) -1; +DWORD gSID = (DWORD) -1; + +// Application group ID for this process +#ifdef __APPLE__ +LPCSTR gApplicationGroupId = nullptr; +int gApplicationGroupIdLength = 0; +#endif // __APPLE__ +PathCharString* gSharedFilesPath = nullptr; + +// The lowest common supported semaphore length, including null character +// NetBSD-7.99.25: 15 characters +// MacOSX 10.11: 31 -- Core 1.0 RC2 compatibility +#if defined(__NetBSD__) +#define CLR_SEM_MAX_NAMELEN 15 +#elif defined(__APPLE__) +#define CLR_SEM_MAX_NAMELEN PSEMNAMLEN +#elif defined(NAME_MAX) +#define CLR_SEM_MAX_NAMELEN (NAME_MAX - 4) +#else +// On Solaris, MAXNAMLEN is 512, which is higher than MAX_PATH defined by pal.h +#define CLR_SEM_MAX_NAMELEN MAX_PATH +#endif + +static_assert_no_msg(CLR_SEM_MAX_NAMELEN <= MAX_PATH); + +// Function to call during PAL/process shutdown/abort +Volatile g_shutdownCallback = nullptr; + +// Crash dump generating program arguments. Initialized in PROCAbortInitialize(). +char* g_argvCreateDump[8] = { nullptr }; + +// +// Key used for associating CPalThread's with the underlying pthread +// (through pthread_setspecific) +// +pthread_key_t CorUnix::thObjKey; + +static WCHAR W16_WHITESPACE[]= {0x0020, 0x0009, 0x000D, 0}; +static WCHAR W16_WHITESPACE_DQUOTE[]= {0x0020, 0x0009, 0x000D, '"', 0}; + +enum FILETYPE +{ + FILE_ERROR,/*ERROR*/ + FILE_UNIX, /*Unix Executable*/ + FILE_DIR /*Directory*/ +}; + +#pragma pack(push,1) +// When creating the semaphore name on Mac running in a sandbox, We reference this structure as a byte array +// in order to encode its data into a string. Its important to make sure there is no padding between the fields +// and also at the end of the buffer. Hence, this structure is defined inside a pack(1) +struct UnambiguousProcessDescriptor +{ + UnambiguousProcessDescriptor() + { + } + + UnambiguousProcessDescriptor(DWORD processId, UINT64 disambiguationKey) + { + Init(processId, disambiguationKey); + } + + void Init(DWORD processId, UINT64 disambiguationKey) + { + m_processId = processId; + m_disambiguationKey = disambiguationKey; + } + UINT64 m_disambiguationKey; + DWORD m_processId; +}; +#pragma pack(pop) + +static +DWORD +StartupHelperThread( + LPVOID p); + +static +BOOL +GetProcessIdDisambiguationKey( + IN DWORD processId, + OUT UINT64 *disambiguationKey); + +PAL_ERROR +PROCGetProcessStatus( + CPalThread *pThread, + HANDLE hProcess, + PROCESS_STATE *pps, + DWORD *pdwExitCode); + +static +void +CreateSemaphoreName( + char semName[CLR_SEM_MAX_NAMELEN], + LPCSTR semaphoreName, + const UnambiguousProcessDescriptor& unambiguousProcessDescriptor, + LPCSTR applicationGroupId); + +static BOOL getFileName(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, PathCharString& lpFileName); +static char ** buildArgv(LPCWSTR lpCommandLine, PathCharString& lpAppPath, UINT *pnArg); +static BOOL getPath(PathCharString& lpFileName, PathCharString& lpPathFileName); +static int checkFileType(LPCSTR lpFileName); +static BOOL PROCEndProcess(HANDLE hProcess, UINT uExitCode, BOOL bTerminateUnconditionally); + +ProcessModules *GetProcessModulesFromHandle(IN HANDLE hProcess, OUT LPDWORD lpCount); +ProcessModules *CreateProcessModules(IN DWORD dwProcessId, OUT LPDWORD lpCount); +void DestroyProcessModules(IN ProcessModules *listHead); + +/*++ +Function: + GetCurrentProcessId + +See MSDN doc. +--*/ +DWORD +PALAPI +GetCurrentProcessId( + VOID) +{ + PERF_ENTRY(GetCurrentProcessId); + ENTRY("GetCurrentProcessId()\n" ); + + LOGEXIT("GetCurrentProcessId returns DWORD %#x\n", gPID); + PERF_EXIT(GetCurrentProcessId); + return gPID; +} + + +/*++ +Function: + GetCurrentSessionId + +See MSDN doc. +--*/ +DWORD +PALAPI +GetCurrentSessionId( + VOID) +{ + PERF_ENTRY(GetCurrentSessionId); + ENTRY("GetCurrentSessionId()\n" ); + + LOGEXIT("GetCurrentSessionId returns DWORD %#x\n", gSID); + PERF_EXIT(GetCurrentSessionId); + return gSID; +} + + +/*++ +Function: + GetCurrentProcess + +See MSDN doc. +--*/ +HANDLE +PALAPI +GetCurrentProcess( + VOID) +{ + PERF_ENTRY(GetCurrentProcess); + ENTRY("GetCurrentProcess()\n" ); + + LOGEXIT("GetCurrentProcess returns HANDLE %p\n", hPseudoCurrentProcess); + PERF_EXIT(GetCurrentProcess); + + /* return a pseudo handle */ + return hPseudoCurrentProcess; +} + +/*++ +Function: + CreateProcessA + +Note: + Only Standard handles need to be inherited. + Security attributes parameters are not used. + +See MSDN doc. +--*/ +BOOL +PALAPI +CreateProcessA( + IN LPCSTR lpApplicationName, + IN LPSTR lpCommandLine, + IN LPSECURITY_ATTRIBUTES lpProcessAttributes, + IN LPSECURITY_ATTRIBUTES lpThreadAttributes, + IN BOOL bInheritHandles, + IN DWORD dwCreationFlags, + IN LPVOID lpEnvironment, + IN LPCSTR lpCurrentDirectory, + IN LPSTARTUPINFOA lpStartupInfo, + OUT LPPROCESS_INFORMATION lpProcessInformation) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pThread; + STARTUPINFOW StartupInfoW; + LPWSTR CommandLineW = NULL; + LPWSTR ApplicationNameW = NULL; + LPWSTR CurrentDirectoryW = NULL; + + int n; + + PERF_ENTRY(CreateProcessA); + ENTRY("CreateProcessA(lpAppName=%p (%s), lpCmdLine=%p (%s), lpProcessAttr=%p, " + "lpThreadAttr=%p, bInherit=%d, dwFlags=%#x, lpEnv=%p, " + "lpCurrentDir=%p (%s), lpStartupInfo=%p, lpProcessInfo=%p)\n", + lpApplicationName?lpApplicationName:"NULL", + lpApplicationName?lpApplicationName:"NULL", + lpCommandLine?lpCommandLine:"NULL", + lpCommandLine?lpCommandLine:"NULL", + lpProcessAttributes, lpThreadAttributes, bInheritHandles, + dwCreationFlags, lpEnvironment, + lpCurrentDirectory?lpCurrentDirectory:"NULL", + lpCurrentDirectory?lpCurrentDirectory:"NULL", + lpStartupInfo, lpProcessInformation); + + pThread = InternalGetCurrentThread(); + + if(lpStartupInfo == NULL) + { + ASSERT("lpStartupInfo is NULL!\n"); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + + /* convert parameters to Unicode */ + + if(lpApplicationName) + { + n = MultiByteToWideChar(CP_ACP, 0, lpApplicationName, -1, NULL, 0); + if(0 == n) + { + ASSERT("MultiByteToWideChar failed!\n"); + palError = ERROR_INTERNAL_ERROR; + goto done; + } + ApplicationNameW = (LPWSTR)InternalMalloc(sizeof(WCHAR)*n); + if(!ApplicationNameW) + { + ERROR("malloc() failed!\n"); + palError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + MultiByteToWideChar(CP_ACP, 0, lpApplicationName, -1, ApplicationNameW, + n); + } + + if(lpCommandLine) + { + n = MultiByteToWideChar(CP_ACP, 0, lpCommandLine, -1, NULL, 0); + if(0 == n) + { + ASSERT("MultiByteToWideChar failed!\n"); + palError = ERROR_INTERNAL_ERROR; + goto done; + } + CommandLineW = (LPWSTR)InternalMalloc(sizeof(WCHAR)*n); + if(!CommandLineW) + { + ERROR("malloc() failed!\n"); + palError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + MultiByteToWideChar(CP_ACP, 0, lpCommandLine, -1, CommandLineW, n); + } + + if(lpCurrentDirectory) + { + n = MultiByteToWideChar(CP_ACP, 0, lpCurrentDirectory, -1, NULL, 0); + if(0 == n) + { + ASSERT("MultiByteToWideChar failed!\n"); + palError = ERROR_INTERNAL_ERROR; + goto done; + } + CurrentDirectoryW = (LPWSTR)InternalMalloc(sizeof(WCHAR)*n); + if(!CurrentDirectoryW) + { + ERROR("malloc() failed!\n"); + palError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + MultiByteToWideChar(CP_ACP, 0, lpCurrentDirectory, -1, + CurrentDirectoryW, n); + } + + // lpEnvironment should remain ansi on the call to CreateProcessW + + StartupInfoW.cb = sizeof StartupInfoW; + StartupInfoW.dwFlags = lpStartupInfo->dwFlags; + StartupInfoW.hStdError = lpStartupInfo->hStdError; + StartupInfoW.hStdInput = lpStartupInfo->hStdInput; + StartupInfoW.hStdOutput = lpStartupInfo->hStdOutput; + /* all other members are PAL_Undefined, we can ignore them */ + + palError = InternalCreateProcess( + pThread, + ApplicationNameW, + CommandLineW, + lpProcessAttributes, + lpThreadAttributes, + dwCreationFlags, + lpEnvironment, + CurrentDirectoryW, + &StartupInfoW, + lpProcessInformation + ); +done: + free(ApplicationNameW); + free(CommandLineW); + free(CurrentDirectoryW); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("CreateProcessA returns BOOL %d\n", NO_ERROR == palError); + PERF_EXIT(CreateProcessA); + return NO_ERROR == palError; +} + + +/*++ +Function: + CreateProcessW + +Note: + Only Standard handles need to be inherited. + Security attributes parameters are not used. + +See MSDN doc. +--*/ +BOOL +PALAPI +CreateProcessW( + IN LPCWSTR lpApplicationName, + IN LPWSTR lpCommandLine, + IN LPSECURITY_ATTRIBUTES lpProcessAttributes, + IN LPSECURITY_ATTRIBUTES lpThreadAttributes, + IN BOOL bInheritHandles, + IN DWORD dwCreationFlags, + IN LPVOID lpEnvironment, + IN LPCWSTR lpCurrentDirectory, + IN LPSTARTUPINFOW lpStartupInfo, + OUT LPPROCESS_INFORMATION lpProcessInformation) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pThread; + + PERF_ENTRY(CreateProcessW); + ENTRY("CreateProcessW(lpAppName=%p (%S), lpCmdLine=%p (%S), lpProcessAttr=%p," + "lpThreadAttr=%p, bInherit=%d, dwFlags=%#x, lpEnv=%p," + "lpCurrentDir=%p (%S), lpStartupInfo=%p, lpProcessInfo=%p)\n", + lpApplicationName?lpApplicationName:W16_NULLSTRING, + lpApplicationName?lpApplicationName:W16_NULLSTRING, + lpCommandLine?lpCommandLine:W16_NULLSTRING, + lpCommandLine?lpCommandLine:W16_NULLSTRING,lpProcessAttributes, + lpThreadAttributes, bInheritHandles, dwCreationFlags,lpEnvironment, + lpCurrentDirectory?lpCurrentDirectory:W16_NULLSTRING, + lpCurrentDirectory?lpCurrentDirectory:W16_NULLSTRING, + lpStartupInfo, lpProcessInformation); + + pThread = InternalGetCurrentThread(); + + palError = InternalCreateProcess( + pThread, + lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("CreateProcessW returns BOOL %d\n", NO_ERROR == palError); + PERF_EXIT(CreateProcessW); + + return NO_ERROR == palError; +} + +PAL_ERROR +PrepareStandardHandle( + CPalThread *pThread, + HANDLE hFile, + IPalObject **ppobjFile, + int *piFd + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pobjFile = NULL; + IDataLock *pDataLock = NULL; + CFileProcessLocalData *pLocalData = NULL; + int iError = 0; + + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hFile, + &aotFile, + &pobjFile + ); + + if (NO_ERROR != palError) + { + ERROR("Bad handle passed through CreateProcess\n"); + goto PrepareStandardHandleExit; + } + + palError = pobjFile->GetProcessLocalData( + pThread, + ReadLock, + &pDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + ASSERT("Unable to access file data\n"); + goto PrepareStandardHandleExit; + } + + // + // The passed in file needs to be inheritable + // + + if (!pLocalData->inheritable) + { + ERROR("Non-inheritable handle passed through CreateProcess\n"); + palError = ERROR_INVALID_HANDLE; + goto PrepareStandardHandleExit; + } + + iError = fcntl(pLocalData->unix_fd, F_SETFD, 0); + if (-1 == iError) + { + ERROR("Unable to remove close-on-exec for file (errno %i)\n", errno); + palError = ERROR_INVALID_HANDLE; + goto PrepareStandardHandleExit; + } + + *piFd = pLocalData->unix_fd; + pDataLock->ReleaseLock(pThread, FALSE); + pDataLock = NULL; + + // + // Transfer pobjFile reference to out parameter + // + + *ppobjFile = pobjFile; + pobjFile = NULL; + +PrepareStandardHandleExit: + + if (NULL != pDataLock) + { + pDataLock->ReleaseLock(pThread, FALSE); + } + + if (NULL != pobjFile) + { + pobjFile->ReleaseReference(pThread); + } + + return palError; +} + +PAL_ERROR +CorUnix::InternalCreateProcess( + CPalThread *pThread, + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pobjProcess = NULL; + IPalObject *pobjProcessRegistered = NULL; + IDataLock *pLocalDataLock = NULL; + CProcProcessLocalData *pLocalData; + IDataLock *pSharedDataLock = NULL; + CPalThread *pDummyThread = NULL; + HANDLE hDummyThread = NULL; + HANDLE hProcess = NULL; + CObjectAttributes oa(NULL, lpProcessAttributes); + + IPalObject *pobjFileIn = NULL; + int iFdIn = -1; + IPalObject *pobjFileOut = NULL; + int iFdOut = -1; + IPalObject *pobjFileErr = NULL; + int iFdErr = -1; + + pid_t processId; + PathCharString lpFileNamePS; + char **lppArgv = NULL; + UINT nArg; + int iRet; + char **EnvironmentArray=NULL; + int child_blocking_pipe = -1; + int parent_blocking_pipe = -1; + + /* Validate parameters */ + + /* note : specs indicate lpApplicationName should always + be NULL; however support for it is already implemented. Leaving the code + in, specs can change; but rejecting non-NULL for now to conform to the + spec. */ + if( NULL != lpApplicationName ) + { + ASSERT("lpApplicationName should be NULL, but is %S instead\n", + lpApplicationName); + palError = ERROR_INVALID_PARAMETER; + goto InternalCreateProcessExit; + } + + if (0 != (dwCreationFlags & ~(CREATE_SUSPENDED|CREATE_NEW_CONSOLE))) + { + ASSERT("Unexpected creation flags (%#x)\n", dwCreationFlags); + palError = ERROR_INVALID_PARAMETER; + goto InternalCreateProcessExit; + } + + /* Security attributes parameters are ignored */ + if (lpProcessAttributes != NULL && + (lpProcessAttributes->lpSecurityDescriptor != NULL || + lpProcessAttributes->bInheritHandle != TRUE)) + { + ASSERT("lpProcessAttributes is invalid, parameter ignored (%p)\n", + lpProcessAttributes); + palError = ERROR_INVALID_PARAMETER; + goto InternalCreateProcessExit; + } + + if (lpThreadAttributes != NULL) + { + ASSERT("lpThreadAttributes parameter must be NULL (%p)\n", + lpThreadAttributes); + palError = ERROR_INVALID_PARAMETER; + goto InternalCreateProcessExit; + } + + /* note : Win32 crashes in this case */ + if(NULL == lpStartupInfo) + { + ERROR("lpStartupInfo is NULL\n"); + palError = ERROR_INVALID_PARAMETER; + goto InternalCreateProcessExit; + } + + /* Validate lpStartupInfo.cb field */ + if (lpStartupInfo->cb < sizeof(STARTUPINFOW)) + { + ASSERT("lpStartupInfo parameter structure size is invalid (%u)\n", + lpStartupInfo->cb); + palError = ERROR_INVALID_PARAMETER; + goto InternalCreateProcessExit; + } + + /* lpStartupInfo should be either zero or STARTF_USESTDHANDLES */ + if (lpStartupInfo->dwFlags & ~STARTF_USESTDHANDLES) + { + ASSERT("lpStartupInfo parameter invalid flags (%#x)\n", + lpStartupInfo->dwFlags); + palError = ERROR_INVALID_PARAMETER; + goto InternalCreateProcessExit; + } + + /* validate given standard handles if we have any */ + if (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES) + { + palError = PrepareStandardHandle( + pThread, + lpStartupInfo->hStdInput, + &pobjFileIn, + &iFdIn + ); + + if (NO_ERROR != palError) + { + goto InternalCreateProcessExit; + } + + palError = PrepareStandardHandle( + pThread, + lpStartupInfo->hStdOutput, + &pobjFileOut, + &iFdOut + ); + + if (NO_ERROR != palError) + { + goto InternalCreateProcessExit; + } + + palError = PrepareStandardHandle( + pThread, + lpStartupInfo->hStdError, + &pobjFileErr, + &iFdErr + ); + + if (NO_ERROR != palError) + { + goto InternalCreateProcessExit; + } + } + + if (!getFileName(lpApplicationName, lpCommandLine, lpFileNamePS)) + { + ERROR("Can't find executable!\n"); + palError = ERROR_FILE_NOT_FOUND; + goto InternalCreateProcessExit; + } + + /* check type of file */ + iRet = checkFileType(lpFileNamePS); + + switch (iRet) + { + case FILE_ERROR: /* file not found, or not an executable */ + WARN ("File is not valid (%s)", lpFileNamePS.GetString()); + palError = ERROR_FILE_NOT_FOUND; + goto InternalCreateProcessExit; + + case FILE_UNIX: /* Unix binary file */ + break; /* nothing to do */ + + case FILE_DIR:/*Directory*/ + WARN ("File is a Directory (%s)", lpFileNamePS.GetString()); + palError = ERROR_ACCESS_DENIED; + goto InternalCreateProcessExit; + break; + + default: /* not supposed to get here */ + ASSERT ("Invalid return type from checkFileType"); + palError = ERROR_FILE_NOT_FOUND; + goto InternalCreateProcessExit; + } + + /* build Argument list, lppArgv is allocated in buildArgv function and + requires to be freed */ + lppArgv = buildArgv(lpCommandLine, lpFileNamePS, &nArg); + + /* set the Environment variable */ + if (lpEnvironment != NULL) + { + unsigned i; + // Since CREATE_UNICODE_ENVIRONMENT isn't supported we know the string is ansi + unsigned EnvironmentEntries = 0; + // Convert the environment block to array of strings + // Count the number of entries + // Is it a string that contains null terminated string, the end is delimited + // by two null in a row. + for (i = 0; ((char *)lpEnvironment)[i]!='\0'; i++) + { + EnvironmentEntries ++; + for (;((char *)lpEnvironment)[i]!='\0'; i++) + { + } + } + EnvironmentEntries++; + EnvironmentArray = (char **)InternalMalloc(EnvironmentEntries * sizeof(char *)); + + EnvironmentEntries = 0; + // Convert the environment block to array of strings + // Count the number of entries + // Is it a string that contains null terminated string, the end is delimited + // by two null in a row. + for (i = 0; ((char *)lpEnvironment)[i]!='\0'; i++) + { + EnvironmentArray[EnvironmentEntries] = &((char *)lpEnvironment)[i]; + EnvironmentEntries ++; + for (;((char *)lpEnvironment)[i]!='\0'; i++) + { + } + } + EnvironmentArray[EnvironmentEntries] = NULL; + } + + // + // Allocate and register the process object for the new process + // + + palError = g_pObjectManager->AllocateObject( + pThread, + &otProcess, + &oa, + &pobjProcess + ); + + if (NO_ERROR != palError) + { + ERROR("Unable to allocate object for new proccess\n"); + goto InternalCreateProcessExit; + } + + palError = g_pObjectManager->RegisterObject( + pThread, + pobjProcess, + &aotProcess, + &hProcess, + &pobjProcessRegistered + ); + + // + // pobjProcess is invalidated by the above call, so + // NULL it out here + // + + pobjProcess = NULL; + + if (NO_ERROR != palError) + { + ERROR("Unable to register new process object\n"); + goto InternalCreateProcessExit; + } + + // + // Create a new "dummy" thread object + // + + palError = InternalCreateDummyThread( + pThread, + lpThreadAttributes, + &pDummyThread, + &hDummyThread + ); + + if (dwCreationFlags & CREATE_SUSPENDED) + { + int pipe_descs[2]; + + if (-1 == pipe(pipe_descs)) + { + ERROR("pipe() failed! error is %d (%s)\n", errno, strerror(errno)); + palError = ERROR_NOT_ENOUGH_MEMORY; + goto InternalCreateProcessExit; + } + + /* [0] is read end, [1] is write end */ + pDummyThread->suspensionInfo.SetBlockingPipe(pipe_descs[1]); + parent_blocking_pipe = pipe_descs[1]; + child_blocking_pipe = pipe_descs[0]; + } + + palError = pobjProcessRegistered->GetProcessLocalData( + pThread, + WriteLock, + &pLocalDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + ASSERT("Unable to obtain local data for new process object\n"); + goto InternalCreateProcessExit; + } + + + /* fork the new process */ + processId = fork(); + + if (processId == -1) + { + ASSERT("Unable to create a new process with fork()\n"); + if (-1 != child_blocking_pipe) + { + close(child_blocking_pipe); + close(parent_blocking_pipe); + } + + palError = ERROR_INTERNAL_ERROR; + goto InternalCreateProcessExit; + } + + /* From the time the child process begins running, to when it reaches execve, + the child process is not a real PAL process and does not own any PAL + resources, although it has access to the PAL resources of its parent process. + Thus, while the child process is in this window, it is dangerous for it to affect + its parent's PAL resources. As a consequence, no PAL code should be used + in this window; all code should make unix calls. Note the use of _exit + instead of exit to avoid calling PAL_Terminate and the lack of TRACE's and + ASSERT's. */ + + if (processId == 0) /* child process */ + { + // At this point, the PAL should be considered uninitialized for this child process. + + // Don't want to enter the init_critsec here since we're trying to avoid + // calling PAL functions. Furthermore, nothing should be changing + // the init_count in the child process at this point since this is the only + // thread executing. + init_count = 0; + + sigset_t sm; + + // + // Clear out the signal mask for the new process. + // + + sigemptyset(&sm); + iRet = sigprocmask(SIG_SETMASK, &sm, NULL); + if (iRet != 0) + { + _exit(EXIT_FAILURE); + } + + if (dwCreationFlags & CREATE_SUSPENDED) + { + BYTE resume_code = 0; + ssize_t read_ret; + + /* close the write end of the pipe, the child doesn't need it */ + close(parent_blocking_pipe); + + read_again: + /* block until ResumeThread writes something to the pipe */ + read_ret = read(child_blocking_pipe, &resume_code, sizeof(resume_code)); + if (sizeof(resume_code) != read_ret) + { + if (read_ret == -1 && EINTR == errno) + { + goto read_again; + } + else + { + /* note : read might return 0 (and return EAGAIN) if the other + end of the pipe gets closed - for example because the parent + process dies (very) abruptly */ + _exit(EXIT_FAILURE); + } + } + if (WAKEUPCODE != resume_code) + { + // resume_code should always equal WAKEUPCODE. + _exit(EXIT_FAILURE); + } + + close(child_blocking_pipe); + } + + /* Set the current directory */ + if (lpCurrentDirectory) + { + SetCurrentDirectoryW(lpCurrentDirectory); + } + + /* Set the standard handles to the incoming values */ + if (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES) + { + /* For each handle, we need to duplicate the incoming unix + fd to the corresponding standard one. The API that I use, + dup2, will copy the source to the destination, automatically + closing the existing destination, in an atomic way */ + if (dup2(iFdIn, STDIN_FILENO) == -1) + { + // Didn't duplicate standard in. + _exit(EXIT_FAILURE); + } + + if (dup2(iFdOut, STDOUT_FILENO) == -1) + { + // Didn't duplicate standard out. + _exit(EXIT_FAILURE); + } + + if (dup2(iFdErr, STDERR_FILENO) == -1) + { + // Didn't duplicate standard error. + _exit(EXIT_FAILURE); + } + + /* now close the original FDs, we don't need them anymore */ + close(iFdIn); + close(iFdOut); + close(iFdErr); + } + + /* execute the new process */ + + if (EnvironmentArray) + { + execve(lpFileNamePS, lppArgv, EnvironmentArray); + } + else + { + execve(lpFileNamePS, lppArgv, palEnvironment); + } + + /* if we get here, it means the execve function call failed so just exit */ + _exit(EXIT_FAILURE); + } + + /* parent process */ + + /* close the read end of the pipe, the parent doesn't need it */ + close(child_blocking_pipe); + + /* Set the process ID */ + pLocalData->dwProcessId = processId; + pLocalDataLock->ReleaseLock(pThread, TRUE); + pLocalDataLock = NULL; + + // + // Release file handle info; we don't need them anymore. Note that + // this must happen after we've released the data locks, as + // otherwise a deadlock could result. + // + + if (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES) + { + pobjFileIn->ReleaseReference(pThread); + pobjFileIn = NULL; + pobjFileOut->ReleaseReference(pThread); + pobjFileOut = NULL; + pobjFileErr->ReleaseReference(pThread); + pobjFileErr = NULL; + } + + /* fill PROCESS_INFORMATION strucutre */ + lpProcessInformation->hProcess = hProcess; + lpProcessInformation->hThread = hDummyThread; + lpProcessInformation->dwProcessId = processId; + lpProcessInformation->dwThreadId_PAL_Undefined = 0; + + + TRACE("New process created: id=%#x\n", processId); + +InternalCreateProcessExit: + + if (NULL != pLocalDataLock) + { + pLocalDataLock->ReleaseLock(pThread, FALSE); + } + + if (NULL != pSharedDataLock) + { + pSharedDataLock->ReleaseLock(pThread, FALSE); + } + + if (NULL != pobjProcess) + { + pobjProcess->ReleaseReference(pThread); + } + + if (NULL != pobjProcessRegistered) + { + pobjProcessRegistered->ReleaseReference(pThread); + } + + if (NO_ERROR != palError) + { + if (NULL != hProcess) + { + g_pObjectManager->RevokeHandle(pThread, hProcess); + } + + if (NULL != hDummyThread) + { + g_pObjectManager->RevokeHandle(pThread, hDummyThread); + } + } + + if (EnvironmentArray) + { + free(EnvironmentArray); + } + + /* if we still have the file structures at this point, it means we + encountered an error sometime between when we acquired them and when we + fork()ed. We not only have to release them, we have to give them back + their close-on-exec flag */ + if (NULL != pobjFileIn) + { + if(-1 == fcntl(iFdIn, F_SETFD, 1)) + { + WARN("couldn't restore close-on-exec flag to stdin descriptor! " + "errno is %d (%s)\n", errno, strerror(errno)); + } + pobjFileIn->ReleaseReference(pThread); + } + + if (NULL != pobjFileOut) + { + if(-1 == fcntl(iFdOut, F_SETFD, 1)) + { + WARN("couldn't restore close-on-exec flag to stdout descriptor! " + "errno is %d (%s)\n", errno, strerror(errno)); + } + pobjFileOut->ReleaseReference(pThread); + } + + if (NULL != pobjFileErr) + { + if(-1 == fcntl(iFdErr, F_SETFD, 1)) + { + WARN("couldn't restore close-on-exec flag to stderr descriptor! " + "errno is %d (%s)\n", errno, strerror(errno)); + } + pobjFileErr->ReleaseReference(pThread); + } + + /* free allocated memory */ + if (lppArgv) + { + free(*lppArgv); + free(lppArgv); + } + + return palError; +} + + +/*++ +Function: + GetExitCodeProcess + +See MSDN doc. +--*/ +BOOL +PALAPI +GetExitCodeProcess( + IN HANDLE hProcess, + IN LPDWORD lpExitCode) +{ + CPalThread *pThread; + PAL_ERROR palError = NO_ERROR; + DWORD dwExitCode; + PROCESS_STATE ps; + + PERF_ENTRY(GetExitCodeProcess); + ENTRY("GetExitCodeProcess(hProcess = %p, lpExitCode = %p)\n", + hProcess, lpExitCode); + + pThread = InternalGetCurrentThread(); + + if(NULL == lpExitCode) + { + WARN("Got NULL lpExitCode\n"); + palError = ERROR_INVALID_PARAMETER; + goto done; + } + + palError = PROCGetProcessStatus( + pThread, + hProcess, + &ps, + &dwExitCode + ); + + if (NO_ERROR != palError) + { + ASSERT("Couldn't get process status information!\n"); + goto done; + } + + if( PS_DONE == ps ) + { + *lpExitCode = dwExitCode; + } + else + { + *lpExitCode = STILL_ACTIVE; + } + +done: + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("GetExitCodeProcess returns BOOL %d\n", NO_ERROR == palError); + PERF_EXIT(GetExitCodeProcess); + + return NO_ERROR == palError; +} + +/*++ +Function: + ExitProcess + +See MSDN doc. +--*/ +PAL_NORETURN +VOID +PALAPI +ExitProcess( + IN UINT uExitCode) +{ + DWORD old_terminator; + + PERF_ENTRY_ONLY(ExitProcess); + ENTRY("ExitProcess(uExitCode=0x%x)\n", uExitCode ); + + old_terminator = InterlockedCompareExchange(&terminator, GetCurrentThreadId(), 0); + + if (GetCurrentThreadId() == old_terminator) + { + // This thread has already initiated termination. This can happen + // in two ways: + // 1) DllMain(DLL_PROCESS_DETACH) triggers a call to ExitProcess. + // 2) PAL_exit() is called after the last PALTerminate(). + // If the PAL is still initialized, we go straight through to + // PROCEndProcess. If it isn't, we simply exit. + if (!PALIsInitialized()) + { + exit(uExitCode); + ASSERT("exit has returned\n"); + } + else + { + WARN("thread re-called ExitProcess\n"); + PROCEndProcess(GetCurrentProcess(), uExitCode, FALSE); + } + } + else if (0 != old_terminator) + { + /* another thread has already initiated the termination process. we + could just block on the PALInitLock critical section, but then + PROCSuspendOtherThreads would hang... so sleep forever here, we're + terminating anyway + + Update: [TODO] PROCSuspendOtherThreads has been removed. Can this + code be changed? */ + WARN("termination already started from another thread; blocking.\n"); + poll(NULL, 0, INFTIM); + } + + /* ExitProcess may be called even if PAL is not initialized. + Verify if process structure exist + */ + if (PALInitLock() && PALIsInitialized()) + { + PROCEndProcess(GetCurrentProcess(), uExitCode, FALSE); + + /* Should not get here, because we terminate the current process */ + ASSERT("PROCEndProcess has returned\n"); + } + else + { + exit(uExitCode); + + /* Should not get here, because we terminate the current process */ + ASSERT("exit has returned\n"); + } + + /* this should never get executed */ + ASSERT("ExitProcess should not return!\n"); + for (;;); +} + +/*++ +Function: + TerminateProcess + +Note: + hProcess is a handle on the current process. + +See MSDN doc. +--*/ +BOOL +PALAPI +TerminateProcess( + IN HANDLE hProcess, + IN UINT uExitCode) +{ + BOOL ret; + + PERF_ENTRY(TerminateProcess); + ENTRY("TerminateProcess(hProcess=%p, uExitCode=%u)\n",hProcess, uExitCode ); + + ret = PROCEndProcess(hProcess, uExitCode, TRUE); + + LOGEXIT("TerminateProcess returns BOOL %d\n", ret); + PERF_EXIT(TerminateProcess); + return ret; +} + +/*++ +Function: + RaiseFailFastException + +See MSDN doc. +--*/ +VOID +PALAPI +RaiseFailFastException( + IN PEXCEPTION_RECORD pExceptionRecord, + IN PCONTEXT pContextRecord, + IN DWORD dwFlags) +{ + PERF_ENTRY(RaiseFailFastException); + ENTRY("RaiseFailFastException"); + + TerminateCurrentProcessNoExit(TRUE); + PROCAbort(); + + LOGEXIT("RaiseFailFastException"); + PERF_EXIT(RaiseFailFastException); +} + +/*++ +Function: + PROCEndProcess + + Called from TerminateProcess and ExitProcess. This does the work of + TerminateProcess, but also takes a flag that determines whether we + shut down unconditionally. If the flag is set, the PAL will do very + little extra work before exiting. Most importantly, it won't shut + down any DLLs that are loaded. + +--*/ +static BOOL PROCEndProcess(HANDLE hProcess, UINT uExitCode, BOOL bTerminateUnconditionally) +{ + DWORD dwProcessId; + BOOL ret = FALSE; + + dwProcessId = PROCGetProcessIDFromHandle(hProcess); + if (dwProcessId == 0) + { + SetLastError(ERROR_INVALID_HANDLE); + } + else if(dwProcessId != GetCurrentProcessId()) + { + if (uExitCode != 0) + WARN("exit code 0x%x ignored for external process.\n", uExitCode); + + if (kill(dwProcessId, SIGKILL) == 0) + { + ret = TRUE; + } + else + { + switch (errno) { + case ESRCH: + SetLastError(ERROR_INVALID_HANDLE); + break; + case EPERM: + SetLastError(ERROR_ACCESS_DENIED); + break; + default: + // Unexpected failure. + ASSERT(FALSE); + SetLastError(ERROR_INTERNAL_ERROR); + break; + } + } + } + else + { + // WARN/ERROR before starting the termination process and/or leaving the PAL. + if (bTerminateUnconditionally) + { + WARN("exit code 0x%x ignored for terminate.\n", uExitCode); + } + else if ((uExitCode & 0xff) != uExitCode) + { + // TODO: Convert uExitCodes into sysexits(3)? + ERROR("exit() only supports the lower 8-bits of an exit code. " + "status will only see error 0x%x instead of 0x%x.\n", uExitCode & 0xff, uExitCode); + } + + TerminateCurrentProcessNoExit(bTerminateUnconditionally); + + LOGEXIT("PROCEndProcess will not return\n"); + + if (bTerminateUnconditionally) + { + // abort() has the semantics that + // (1) it doesn't run atexit handlers + // (2) can invoke CrashReporter or produce a coredump, + // which is appropriate for TerminateProcess calls + PROCAbort(); + } + else + { + exit(uExitCode); + } + + ASSERT(FALSE); // we shouldn't get here + } + + return ret; +} + +/*++ +Function: + PAL_SetShutdownCallback + +Abstract: + Sets a callback that is executed when the PAL is shut down because of + ExitProcess, TerminateProcess or PAL_Shutdown but not PAL_Terminate/Ex. + + NOTE: Currently only one callback can be set at a time. +--*/ +PALIMPORT +VOID +PALAPI +PAL_SetShutdownCallback( + IN PSHUTDOWN_CALLBACK callback) +{ + _ASSERTE(g_shutdownCallback == nullptr); + g_shutdownCallback = callback; +} + +static bool IsCoreClrModule(const char* pModulePath) +{ + // Strip off everything up to and including the last slash in the path to get name + const char* pModuleName = pModulePath; + while (strchr(pModuleName, '/') != NULL) + { + pModuleName = strchr(pModuleName, '/'); + pModuleName++; // pass the slash + } + + return _stricmp(pModuleName, MAKEDLLNAME_A("coreclr")) == 0; +} + +// Build the semaphore names using the PID and a value that can be used for distinguishing +// between processes with the same PID (which ran at different times). This is to avoid +// cases where a prior process with the same PID exited abnormally without having a chance +// to clean up its semaphore. +// Note to anyone modifying these names in the future: Semaphore names on OS X are limited +// to SEM_NAME_LEN characters, including null. SEM_NAME_LEN is 31 (at least on OS X 10.11). +// NetBSD limits semaphore names to 15 characters, including null (at least up to 7.99.25). +// Keep 31 length for Core 1.0 RC2 compatibility +#if defined(__NetBSD__) +static const char* RuntimeSemaphoreNameFormat = "/clr%s%08llx"; +#else +static const char* RuntimeSemaphoreNameFormat = "/clr%s%08x%016llx"; +#endif + +static const char* RuntimeStartupSemaphoreName = "st"; +static const char* RuntimeContinueSemaphoreName = "co"; + +#if defined(__NetBSD__) +static uint64_t HashSemaphoreName(uint64_t a, uint64_t b) +{ + return (a ^ b) & 0xffffffff; +} +#else +#define HashSemaphoreName(a,b) a,b +#endif + +static const char *const TwoWayNamedPipePrefix = "clr-debug-pipe"; +static const char* IpcNameFormat = "%s-%d-%llu-%s"; + +class PAL_RuntimeStartupHelper +{ + LONG m_ref; + bool m_canceled; + PPAL_STARTUP_CALLBACK m_callback; + PVOID m_parameter; + DWORD m_threadId; + HANDLE m_threadHandle; + DWORD m_processId; +#ifdef __APPLE__ + char m_applicationGroupId[MAX_APPLICATION_GROUP_ID_LENGTH+1]; +#endif // __APPLE__ + char m_startupSemName[CLR_SEM_MAX_NAMELEN]; + char m_continueSemName[CLR_SEM_MAX_NAMELEN]; + + // A value that, used in conjunction with the process ID, uniquely identifies a process. + // See the format we use for debugger semaphore names for why this is necessary. + UINT64 m_processIdDisambiguationKey; + + // Debugger waits on this semaphore and the runtime signals it on startup. + sem_t *m_startupSem; + + // Debuggee waits on this semaphore and the debugger signals it after the startup callback + // registered (m_callback) returns. + sem_t *m_continueSem; + + LPCSTR GetApplicationGroupId() const + { +#ifdef __APPLE__ + return m_applicationGroupId[0] == '\0' ? nullptr : m_applicationGroupId; +#else // __APPLE__ + return nullptr; +#endif // __APPLE__ + } + +public: + PAL_RuntimeStartupHelper(DWORD dwProcessId, PPAL_STARTUP_CALLBACK pfnCallback, PVOID parameter) : + m_ref(1), + m_canceled(false), + m_callback(pfnCallback), + m_parameter(parameter), + m_threadId(0), + m_threadHandle(NULL), + m_processId(dwProcessId), + m_startupSem(SEM_FAILED), + m_continueSem(SEM_FAILED) + { + } + + ~PAL_RuntimeStartupHelper() + { + if (m_startupSem != SEM_FAILED) + { + sem_close(m_startupSem); + sem_unlink(m_startupSemName); + } + + if (m_continueSem != SEM_FAILED) + { + sem_close(m_continueSem); + sem_unlink(m_continueSemName); + } + + if (m_threadHandle != NULL) + { + CloseHandle(m_threadHandle); + } + } + + LONG AddRef() + { + LONG ref = InterlockedIncrement(&m_ref); + return ref; + } + + LONG Release() + { + LONG ref = InterlockedDecrement(&m_ref); + if (ref == 0) + { + InternalDelete(this); + } + return ref; + } + + PAL_ERROR GetSemError() + { + PAL_ERROR pe; + switch (errno) + { + case ENOENT: + pe = ERROR_NOT_FOUND; + break; + case EACCES: + pe = ERROR_INVALID_ACCESS; + break; + case EINVAL: + case ENAMETOOLONG: + pe = ERROR_INVALID_NAME; + break; + case ENOMEM: + pe = ERROR_OUTOFMEMORY; + break; + case EEXIST: + pe = ERROR_ALREADY_EXISTS; + break; + case ENOSPC: + pe = ERROR_TOO_MANY_SEMAPHORES; + break; + default: + pe = ERROR_INVALID_PARAMETER; + break; + } + return pe; + } + + PAL_ERROR Register(LPCWSTR lpApplicationGroupId) + { + CPalThread *pThread = InternalGetCurrentThread(); + PAL_ERROR pe = NO_ERROR; + BOOL ret; + UnambiguousProcessDescriptor unambiguousProcessDescriptor; + SIZE_T osThreadId = 0; + +#ifdef __APPLE__ + if (lpApplicationGroupId != NULL) + { + /* Convert to ASCII */ + int applicationGroupIdLength = WideCharToMultiByte(CP_ACP, 0, lpApplicationGroupId, -1, m_applicationGroupId, sizeof(m_applicationGroupId), NULL, NULL); + if (applicationGroupIdLength == 0) + { + pe = GetLastError(); + TRACE("applicationGroupId: Failed to convert to multibyte string (%u)\n", pe); + if (pe == ERROR_INSUFFICIENT_BUFFER) + { + pe = ERROR_BAD_LENGTH; + } + goto exit; + } + } + else + { + // Indicate that group ID is not being used + m_applicationGroupId[0] = '\0'; + } +#endif // __APPLE__ + + // See semaphore name format for details about this value. We store it so that + // it can be used by the cleanup code that removes the semaphore with sem_unlink. + ret = GetProcessIdDisambiguationKey(m_processId, &m_processIdDisambiguationKey); + + // If GetProcessIdDisambiguationKey failed for some reason, it should set the value + // to 0. We expect that anyone else opening the semaphore name will also fail and thus + // will also try to use 0 as the value. + _ASSERTE(ret == TRUE || m_processIdDisambiguationKey == 0); + + unambiguousProcessDescriptor.Init(m_processId, m_processIdDisambiguationKey); + CreateSemaphoreName(m_startupSemName, RuntimeStartupSemaphoreName, unambiguousProcessDescriptor, GetApplicationGroupId()); + CreateSemaphoreName(m_continueSemName, RuntimeContinueSemaphoreName, unambiguousProcessDescriptor, GetApplicationGroupId()); + + TRACE("PAL_RuntimeStartupHelper.Register creating startup '%s' continue '%s'\n", m_startupSemName, m_continueSemName); + + // Create the continue semaphore first so we don't race with PAL_NotifyRuntimeStarted. This open will fail if another + // debugger is trying to attach to this process because the name will already exist. + m_continueSem = sem_open(m_continueSemName, O_CREAT | O_EXCL, S_IRWXU, 0); + if (m_continueSem == SEM_FAILED) + { + TRACE("sem_open(continue) failed: errno is %d (%s)\n", errno, strerror(errno)); + pe = GetSemError(); + goto exit; + } + + // Create the debuggee startup semaphore so the runtime (debuggee) knows to wait for a debugger connection. + m_startupSem = sem_open(m_startupSemName, O_CREAT | O_EXCL, S_IRWXU, 0); + if (m_startupSem == SEM_FAILED) + { + TRACE("sem_open(startup) failed: errno is %d (%s)\n", errno, strerror(errno)); + pe = GetSemError(); + goto exit; + } + + // Add a reference for the thread handler + AddRef(); + pe = InternalCreateThread( + pThread, + NULL, + 0, + ::StartupHelperThread, + this, + 0, + UserCreatedThread, + &osThreadId, + &m_threadHandle); + + if (NO_ERROR != pe) + { + TRACE("InternalCreateThread failed %d\n", pe); + Release(); + goto exit; + } + m_threadId = (DWORD)osThreadId; + exit: + return pe; + } + + void Unregister() + { + m_canceled = true; + + // Tell the runtime to continue + if (sem_post(m_continueSem) != 0) + { + ASSERT("sem_post(continueSem) failed: errno is %d (%s)\n", errno, strerror(errno)); + } + + // Tell the worker thread to continue + if (sem_post(m_startupSem) != 0) + { + ASSERT("sem_post(startupSem) failed: errno is %d (%s)\n", errno, strerror(errno)); + } + + // Don't need to wait for the worker thread if unregister called on it + if (m_threadId != (DWORD)THREADSilentGetCurrentThreadId()) + { + // Wait for work thread to exit + if (WaitForSingleObject(m_threadHandle, INFINITE) != WAIT_OBJECT_0) + { + ASSERT("WaitForSingleObject\n"); + } + } + } + + // + // There are a couple race conditions that need to be considered here: + // + // * On launch, between the fork and execv in the PAL's CreateProcess where the target process + // may contain a coreclr module image if the debugger process is running managed code. This + // makes just checking if the coreclr module exists not enough. + // + // * On launch (after the execv) or attach when the coreclr is loaded but before the DAC globals + // table is initialized where it is too soon to use/initialize the DAC on the debugger side. + // + // They are both fixed by check if the one of transport pipe files has been created. + // + bool IsCoreClrProcessReady() + { + char pipeName[MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH]; + + PAL_GetTransportPipeName(pipeName, m_processId, GetApplicationGroupId(), "in"); + + struct stat buf; + if (stat(pipeName, &buf) == 0) + { + TRACE("IsCoreClrProcessReady: stat(%s) SUCCEEDED\n", pipeName); + return true; + } + TRACE("IsCoreClrProcessReady: stat(%s) FAILED: errno is %d (%s)\n", pipeName, errno, strerror(errno)); + return false; + } + + PAL_ERROR InvokeStartupCallback() + { + ProcessModules *listHead = NULL; + PAL_ERROR pe = NO_ERROR; + DWORD count; + + if (m_canceled) + { + goto exit; + } + + // Enumerate all the modules in the process and invoke the callback + // for the coreclr module if found. + listHead = CreateProcessModules(m_processId, &count); + if (listHead == NULL) + { + TRACE("CreateProcessModules failed for pid %d\n", m_processId); + pe = ERROR_INVALID_PARAMETER; + goto exit; + } + + for (ProcessModules *entry = listHead; entry != NULL; entry = entry->Next) + { + if (IsCoreClrModule(entry->Name)) + { + PAL_CPP_TRY + { + TRACE("InvokeStartupCallback executing callback %p %s\n", entry->BaseAddress, entry->Name); + m_callback(entry->Name, entry->BaseAddress, m_parameter); + } + PAL_CPP_CATCH_ALL + { + } + PAL_CPP_ENDTRY + + // Currently only the first coreclr module in a process is supported + break; + } + } + + exit: + // Wake up the runtime + if (sem_post(m_continueSem) != 0) + { + ASSERT("sem_post(continueSem) failed: errno is %d (%s)\n", errno, strerror(errno)); + } + if (listHead != NULL) + { + DestroyProcessModules(listHead); + } + return pe; + } + + void StartupHelperThread() + { + PAL_ERROR pe = NO_ERROR; + + if (IsCoreClrProcessReady()) + { + pe = InvokeStartupCallback(); + } + else { + TRACE("sem_wait(startup)\n"); + + // Wait until the coreclr runtime (debuggee) starts up + if (sem_wait(m_startupSem) == 0) + { + pe = InvokeStartupCallback(); + } + else + { + TRACE("sem_wait(startup) failed: errno is %d (%s)\n", errno, strerror(errno)); + pe = GetSemError(); + } + } + + // Invoke the callback on errors + if (pe != NO_ERROR && !m_canceled) + { + SetLastError(pe); + m_callback(NULL, NULL, m_parameter); + } + } +}; + +static +DWORD +StartupHelperThread(LPVOID p) +{ + TRACE("PAL's StartupHelperThread starting\n"); + + PAL_RuntimeStartupHelper *helper = (PAL_RuntimeStartupHelper *)p; + helper->StartupHelperThread(); + helper->Release(); + return 0; +} + +/*++ + PAL_RegisterForRuntimeStartup + +Parameters: + dwProcessId - process id of runtime process + lpApplicationGroupId - A string representing the application group ID of a sandboxed + process running in Mac. Pass NULL if the process is not + running in a sandbox and other platforms. + pfnCallback - function to callback for coreclr module found + parameter - data to pass to callback + ppUnregisterToken - pointer to put PAL_UnregisterForRuntimeStartup token. + +Return value: + PAL_ERROR + +Note: + If the modulePath or hModule is NULL when the callback is invoked, an error occured + and GetLastError() will return the Win32 error code. + + The callback is always invoked on a separate thread and this API returns immediately. + + Only the first coreclr module is currently supported. + +--*/ +DWORD +PALAPI +PAL_RegisterForRuntimeStartup( + IN DWORD dwProcessId, + IN LPCWSTR lpApplicationGroupId, + IN PPAL_STARTUP_CALLBACK pfnCallback, + IN PVOID parameter, + OUT PVOID *ppUnregisterToken) +{ + _ASSERTE(pfnCallback != NULL); + _ASSERTE(ppUnregisterToken != NULL); + + PAL_RuntimeStartupHelper *helper = InternalNew(dwProcessId, pfnCallback, parameter); + + // Create the debuggee startup semaphore so the runtime (debuggee) knows to wait for + // a debugger connection. + PAL_ERROR pe = helper->Register(lpApplicationGroupId); + if (NO_ERROR != pe) + { + helper->Release(); + helper = NULL; + } + + *ppUnregisterToken = helper; + return pe; +} + +/*++ + PAL_UnregisterForRuntimeStartup + + Stops/cancels startup notification. This API can be called in the startup callback. Otherwise, + it will block until the callback thread finishes and no more callbacks will be initiated after + this API returns. + +Parameters: + dwUnregisterToken - token from PAL_RegisterForRuntimeStartup or NULL. + +Return value: + PAL_ERROR +--*/ +DWORD +PALAPI +PAL_UnregisterForRuntimeStartup( + IN PVOID pUnregisterToken) +{ + if (pUnregisterToken != NULL) + { + PAL_RuntimeStartupHelper *helper = (PAL_RuntimeStartupHelper *)pUnregisterToken; + helper->Unregister(); + helper->Release(); + } + return NO_ERROR; +} + +/*++ + PAL_NotifyRuntimeStarted + + Signals the debugger waiting for runtime startup notification to continue and + waits until the debugger signals us to continue. + +Parameters: + None + +Return value: + TRUE - successfully launched by debugger, FALSE - not launched or some failure in the handshake +--*/ +BOOL +PALAPI +PAL_NotifyRuntimeStarted() +{ + char startupSemName[CLR_SEM_MAX_NAMELEN]; + char continueSemName[CLR_SEM_MAX_NAMELEN]; + sem_t *startupSem = SEM_FAILED; + sem_t *continueSem = SEM_FAILED; + BOOL launched = FALSE; + + UINT64 processIdDisambiguationKey = 0; + BOOL ret = GetProcessIdDisambiguationKey(gPID, &processIdDisambiguationKey); + + // If GetProcessIdDisambiguationKey failed for some reason, it should set the value + // to 0. We expect that anyone else making the semaphore name will also fail and thus + // will also try to use 0 as the value. + _ASSERTE(ret == TRUE || processIdDisambiguationKey == 0); + + UnambiguousProcessDescriptor unambiguousProcessDescriptor(gPID, processIdDisambiguationKey); + LPCSTR applicationGroupId = +#ifdef __APPLE__ + PAL_GetApplicationGroupId(); +#else + nullptr; +#endif + CreateSemaphoreName(startupSemName, RuntimeStartupSemaphoreName, unambiguousProcessDescriptor, applicationGroupId); + CreateSemaphoreName(continueSemName, RuntimeContinueSemaphoreName, unambiguousProcessDescriptor, applicationGroupId); + + TRACE("PAL_NotifyRuntimeStarted opening continue '%s' startup '%s'\n", continueSemName, startupSemName); + + // Open the debugger startup semaphore. If it doesn't exists, then we do nothing and return + startupSem = sem_open(startupSemName, 0); + if (startupSem == SEM_FAILED) + { + TRACE("sem_open(%s) failed: %d (%s)\n", startupSemName, errno, strerror(errno)); + goto exit; + } + + continueSem = sem_open(continueSemName, 0); + if (continueSem == SEM_FAILED) + { + ASSERT("sem_open(%s) failed: %d (%s)\n", continueSemName, errno, strerror(errno)); + goto exit; + } + + // Wake up the debugger waiting for startup + if (sem_post(startupSem) != 0) + { + ASSERT("sem_post(startupSem) failed: errno is %d (%s)\n", errno, strerror(errno)); + goto exit; + } + + // Now wait until the debugger's runtime startup notification is finished + if (sem_wait(continueSem) != 0) + { + ASSERT("sem_wait(continueSem) failed: errno is %d (%s)\n", errno, strerror(errno)); + goto exit; + } + + // Returns that the runtime was successfully launched for debugging + launched = TRUE; + +exit: + if (startupSem != SEM_FAILED) + { + sem_close(startupSem); + } + if (continueSem != SEM_FAILED) + { + sem_close(continueSem); + } + return launched; +} + +#ifdef __APPLE__ +LPCSTR +PALAPI +PAL_GetApplicationGroupId() +{ + return gApplicationGroupId; +} + +// We use 7bits from each byte, so this computes the extra size we need to encode a given byte count +constexpr int GetExtraEncodedAreaSize(UINT rawByteCount) +{ + return (rawByteCount+6)/7; +} +const int SEMAPHORE_ENCODED_NAME_EXTRA_LENGTH = GetExtraEncodedAreaSize(sizeof(UnambiguousProcessDescriptor)); +const int SEMAPHORE_ENCODED_NAME_LENGTH = + sizeof(UnambiguousProcessDescriptor) + /* For process ID + disambiguationKey */ + SEMAPHORE_ENCODED_NAME_EXTRA_LENGTH; /* For base 255 extra encoding space */ + +static_assert_no_msg(MAX_APPLICATION_GROUP_ID_LENGTH + + 1 /* For / */ + + 2 /* For ST/CO name prefix */ + + SEMAPHORE_ENCODED_NAME_LENGTH /* For encoded name string */ + + 1 /* For null terminator */ + <= CLR_SEM_MAX_NAMELEN); + +// In Apple we are limited by the length of the semaphore name. However, the characters which can be used in the +// name can be anything between 1 and 255 (since 0 will terminate the string). Thus, we encode each byte b in +// unambiguousProcessDescriptor as b ? b : 1, and mark an additional bit indicating if b is 0 or not. We use 7 bits +// out of each extra byte so 1 bit will always be '1'. This will ensure that our extra bytes are never 0 which are +// invalid characters. Thus we need an extra byte for each 7 input bytes. Hence, only extra 2 bytes for the name string. +void EncodeSemaphoreName(char *encodedSemName, const UnambiguousProcessDescriptor& unambiguousProcessDescriptor) +{ + const unsigned char *buffer = (const unsigned char *)&unambiguousProcessDescriptor; + char *extraEncodingBits = encodedSemName + sizeof(UnambiguousProcessDescriptor); + + // Reset the extra encoding bit area + for (int i=0; i 0 && length < CLR_SEM_MAX_NAMELEN); + + EncodeSemaphoreName(semName+length, unambiguousProcessDescriptor); + length += SEMAPHORE_ENCODED_NAME_LENGTH; + semName[length] = 0; + } + else +#endif // __APPLE__ + { + length = sprintf_s( + semName, + CLR_SEM_MAX_NAMELEN, + RuntimeSemaphoreNameFormat, + semaphoreName, + HashSemaphoreName(unambiguousProcessDescriptor.m_processId, unambiguousProcessDescriptor.m_disambiguationKey)); + } + + _ASSERTE(length > 0 && length < CLR_SEM_MAX_NAMELEN ); +} + +/*++ + Function: + GetProcessIdDisambiguationKey + + Get a numeric value that can be used to disambiguate between processes with the same PID, + provided that one of them is still running. The numeric value can mean different things + on different platforms, so it should not be used for any other purpose. Under the hood, + it is implemented based on the creation time of the process. +--*/ +BOOL +GetProcessIdDisambiguationKey(DWORD processId, UINT64 *disambiguationKey) +{ + if (disambiguationKey == nullptr) + { + _ASSERTE(!"disambiguationKey argument cannot be null!"); + return FALSE; + } + + *disambiguationKey = 0; + +#if defined(__APPLE__) + + // On OS X, we return the process start time expressed in Unix time (the number of seconds + // since the start of the Unix epoch). + struct kinfo_proc info = {}; + size_t size = sizeof(info); + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, processId }; + int ret = ::sysctl(mib, sizeof(mib)/sizeof(*mib), &info, &size, nullptr, 0); + + if (ret == 0) + { + timeval procStartTime = info.kp_proc.p_starttime; + long secondsSinceEpoch = procStartTime.tv_sec; + + *disambiguationKey = secondsSinceEpoch; + return TRUE; + } + else + { + _ASSERTE(!"Failed to get start time of a process."); + return FALSE; + } + +#elif defined(__NetBSD__) + + // On NetBSD, we return the process start time expressed in Unix time (the number of seconds + // since the start of the Unix epoch). + kvm_t *kd; + int cnt; + struct kinfo_proc2 *info; + + kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, "kvm_open"); + if (kd == nullptr) + { + _ASSERTE(!"Failed to get start time of a process."); + return FALSE; + } + + info = kvm_getproc2(kd, KERN_PROC_PID, processId, sizeof(struct kinfo_proc2), &cnt); + if (info == nullptr || cnt < 1) + { + kvm_close(kd); + _ASSERTE(!"Failed to get start time of a process."); + return FALSE; + } + + kvm_close(kd); + + long secondsSinceEpoch = info->p_ustart_sec; + *disambiguationKey = secondsSinceEpoch; + + return TRUE; + +#elif HAVE_PROCFS_STAT + + // Here we read /proc//stat file to get the start time for the process. + // We return this value (which is expressed in jiffies since boot time). + + // Making something like: /proc/123/stat + char statFileName[64]; + + INDEBUG(int chars = ) + snprintf(statFileName, sizeof(statFileName), "/proc/%d/stat", processId); + _ASSERTE(chars > 0 && chars <= (int)sizeof(statFileName)); + + FILE *statFile = fopen(statFileName, "r"); + if (statFile == nullptr) + { + TRACE("GetProcessIdDisambiguationKey: fopen() FAILED"); + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + char *line = nullptr; + size_t lineLen = 0; + if (getline(&line, &lineLen, statFile) == -1) + { + TRACE("GetProcessIdDisambiguationKey: getline() FAILED"); + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + unsigned long long starttime; + + // 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_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_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_s."); + return FALSE; + } + + free(line); + fclose(statFile); + + *disambiguationKey = starttime; + return TRUE; + +#else + // If this is not OS X and we don't have /proc, we just return FALSE. + WARN("GetProcessIdDisambiguationKey was called but is not implemented on this platform!"); + return FALSE; +#endif +} + +/*++ + Function: + PAL_GetTransportName + + Builds the transport IPC names from the process id. +--*/ +VOID +PALAPI +PAL_GetTransportName( + const unsigned int MAX_TRANSPORT_NAME_LENGTH, + OUT char *name, + IN const char *prefix, + IN DWORD id, + IN const char *applicationGroupId, + IN const char *suffix) +{ + *name = '\0'; + DWORD dwRetVal = 0; + UINT64 disambiguationKey = 0; + PathCharString formatBufferString; + BOOL ret = GetProcessIdDisambiguationKey(id, &disambiguationKey); + char *formatBuffer = formatBufferString.OpenStringBuffer(MAX_TRANSPORT_NAME_LENGTH-1); + if (formatBuffer == nullptr) + { + ERROR("Out Of Memory"); + return; + } + + // If GetProcessIdDisambiguationKey failed for some reason, it should set the value + // to 0. We expect that anyone else making the pipe name will also fail and thus will + // also try to use 0 as the value. + _ASSERTE(ret == TRUE || disambiguationKey == 0); +#ifdef __APPLE__ + if (nullptr != applicationGroupId) + { + // Verify the length of the application group ID + int applicationGroupIdLength = strlen(applicationGroupId); + if (applicationGroupIdLength > MAX_APPLICATION_GROUP_ID_LENGTH) + { + ERROR("The length of applicationGroupId is larger than MAX_APPLICATION_GROUP_ID_LENGTH"); + return; + } + + // In sandbox, all IPC files (locks, pipes) should be written to the application group + // container. The path returned by GetTempPathA will be unique for each process and cannot + // be used for IPC between two different processes + if (!GetApplicationContainerFolder(formatBufferString, applicationGroupId, applicationGroupIdLength)) + { + ERROR("Out Of Memory"); + return; + } + + // Verify the size of the path won't exceed maximum allowed size + if (formatBufferString.GetCount() >= MAX_TRANSPORT_NAME_LENGTH) + { + ERROR("GetApplicationContainerFolder returned a path that was larger than MAX_TRANSPORT_NAME_LENGTH"); + return; + } + } + else +#endif // __APPLE__ + { + // Get a temp file location + dwRetVal = ::GetTempPathA(MAX_TRANSPORT_NAME_LENGTH, formatBuffer); + if (dwRetVal == 0) + { + ERROR("GetTempPath failed (0x%08x)", ::GetLastError()); + return; + } + if (dwRetVal > MAX_TRANSPORT_NAME_LENGTH) + { + ERROR("GetTempPath returned a path that was larger than MAX_TRANSPORT_NAME_LENGTH"); + return; + } + } + + if (strncat_s(formatBuffer, MAX_TRANSPORT_NAME_LENGTH, IpcNameFormat, strlen(IpcNameFormat)) == STRUNCATE) + { + ERROR("TransportPipeName was larger than MAX_TRANSPORT_NAME_LENGTH"); + return; + } + + int chars = snprintf(name, MAX_TRANSPORT_NAME_LENGTH, formatBuffer, prefix, id, disambiguationKey, suffix); + _ASSERTE(chars > 0 && (unsigned int)chars < MAX_TRANSPORT_NAME_LENGTH); +} + +/*++ + Function: + PAL_GetTransportPipeName + + Builds the transport pipe names from the process id. +--*/ +VOID +PALAPI +PAL_GetTransportPipeName( + OUT char *name, + IN DWORD id, + IN const char *applicationGroupId, + IN const char *suffix) +{ + PAL_GetTransportName( + MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH, + name, + TwoWayNamedPipePrefix, + id, + applicationGroupId, + suffix); +} + +/*++ +Function: + GetProcessTimes + +See MSDN doc. +--*/ +BOOL +PALAPI +GetProcessTimes( + IN HANDLE hProcess, + OUT LPFILETIME lpCreationTime, + OUT LPFILETIME lpExitTime, + OUT LPFILETIME lpKernelTime, + OUT LPFILETIME lpUserTime) +{ + BOOL retval = FALSE; + struct rusage resUsage; + UINT64 calcTime; + const UINT64 SECS_TO_100NS = 10000000ULL; // 10^7 + const UINT64 USECS_TO_100NS = 10ULL; // 10 + const UINT64 EPOCH_DIFF = 11644473600ULL; // number of seconds from 1 Jan. 1601 00:00 to 1 Jan 1970 00:00 UTC + + PERF_ENTRY(GetProcessTimes); + ENTRY("GetProcessTimes(hProcess=%p, lpExitTime=%p, lpKernelTime=%p," + "lpUserTime=%p)\n", + hProcess, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime ); + + /* Make sure hProcess is the current process, this is the only supported + case */ + if(PROCGetProcessIDFromHandle(hProcess)!=GetCurrentProcessId()) + { + ASSERT("GetProcessTimes() does not work on a process other than the " + "current process.\n"); + SetLastError(ERROR_INVALID_HANDLE); + goto GetProcessTimesExit; + } + + /* First, we need to actually retrieve the relevant statistics from the + OS */ + if (getrusage (RUSAGE_SELF, &resUsage) == -1) + { + ASSERT("Unable to get resource usage information for the current " + "process\n"); + SetLastError(ERROR_INTERNAL_ERROR); + goto GetProcessTimesExit; + } + + TRACE ("getrusage User: %ld sec,%ld microsec. Kernel: %ld sec,%ld" + " microsec\n", + resUsage.ru_utime.tv_sec, resUsage.ru_utime.tv_usec, + resUsage.ru_stime.tv_sec, resUsage.ru_stime.tv_usec); + + if (lpCreationTime) + { + // The IBC profile data uses this, instead of the actual + // process creation time we just return the current time + + struct timeval tv; + if (gettimeofday(&tv, NULL) == -1) + { + ASSERT("gettimeofday() failed; errno is %d (%s)\n", errno, strerror(errno)); + + // Assign zero to lpCreationTime + lpCreationTime->dwLowDateTime = 0; + lpCreationTime->dwHighDateTime = 0; + } + else + { + calcTime = EPOCH_DIFF; + calcTime += (UINT64)tv.tv_sec; + calcTime *= SECS_TO_100NS; + calcTime += ((UINT64)tv.tv_usec * USECS_TO_100NS); + + // Assign the time into lpCreationTime + lpCreationTime->dwLowDateTime = (DWORD)calcTime; + lpCreationTime->dwHighDateTime = (DWORD)(calcTime >> 32); + } + } + + if (lpExitTime) + { + // Assign zero to lpExitTime + lpExitTime->dwLowDateTime = 0; + lpExitTime->dwHighDateTime = 0; + } + + if (lpUserTime) + { + /* Get the time of user mode execution, in 100s of nanoseconds */ + calcTime = (UINT64)resUsage.ru_utime.tv_sec * SECS_TO_100NS; + calcTime += (UINT64)resUsage.ru_utime.tv_usec * USECS_TO_100NS; + + /* Assign the time into lpUserTime */ + lpUserTime->dwLowDateTime = (DWORD)calcTime; + lpUserTime->dwHighDateTime = (DWORD)(calcTime >> 32); + } + + if (lpKernelTime) + { + /* Get the time of kernel mode execution, in 100s of nanoseconds */ + calcTime = (UINT64)resUsage.ru_stime.tv_sec * SECS_TO_100NS; + calcTime += (UINT64)resUsage.ru_stime.tv_usec * USECS_TO_100NS; + + /* Assign the time into lpUserTime */ + lpKernelTime->dwLowDateTime = (DWORD)calcTime; + lpKernelTime->dwHighDateTime = (DWORD)(calcTime >> 32); + } + + retval = TRUE; + + +GetProcessTimesExit: + LOGEXIT("GetProcessTimes returns BOOL %d\n", retval); + PERF_EXIT(GetProcessTimes); + return (retval); +} + +#define FILETIME_TO_ULONGLONG(f) \ + (((ULONGLONG)(f).dwHighDateTime << 32) | ((ULONGLONG)(f).dwLowDateTime)) + +/*++ +Function: + PAL_GetCPUBusyTime + +The main purpose of this function is to compute the overall CPU utilization +for the CLR thread pool to regulate the number of I/O completion port +worker threads. +Since there is no consistent API on Unix to get the CPU utilization +from a user process, getrusage and gettimeofday are used to +compute the current process's CPU utilization instead. +This function emulates the ThreadpoolMgr::GetCPUBusyTime_NT function in +win32threadpool.cpp of the CLR. + +See MSDN doc for GetSystemTimes. +--*/ +INT +PALAPI +PAL_GetCPUBusyTime( + IN OUT PAL_IOCP_CPU_INFORMATION *lpPrevCPUInfo) +{ + ULONGLONG nLastRecordedCurrentTime = 0; + ULONGLONG nLastRecordedUserTime = 0; + ULONGLONG nLastRecordedKernelTime = 0; + ULONGLONG nKernelTime = 0; + ULONGLONG nUserTime = 0; + ULONGLONG nCurrentTime = 0; + ULONGLONG nCpuBusyTime = 0; + ULONGLONG nCpuTotalTime = 0; + DWORD nReading = 0; + struct rusage resUsage; + struct timeval tv; + static DWORD dwNumberOfProcessors = 0; + + if (dwNumberOfProcessors <= 0) + { + SYSTEM_INFO SystemInfo; + GetSystemInfo(&SystemInfo); + dwNumberOfProcessors = SystemInfo.dwNumberOfProcessors; + if (dwNumberOfProcessors <= 0) + { + return 0; + } + + UINT cpuLimit; + if (PAL_GetCpuLimit(&cpuLimit) && cpuLimit < dwNumberOfProcessors) + { + dwNumberOfProcessors = cpuLimit; + } + } + + if (getrusage(RUSAGE_SELF, &resUsage) == -1) + { + ASSERT("getrusage() failed; errno is %d (%s)\n", errno, strerror(errno)); + return 0; + } + else + { + nKernelTime = (ULONGLONG)resUsage.ru_stime.tv_sec*tccSecondsTo100NanoSeconds + + resUsage.ru_stime.tv_usec*tccMicroSecondsTo100NanoSeconds; + nUserTime = (ULONGLONG)resUsage.ru_utime.tv_sec*tccSecondsTo100NanoSeconds + + resUsage.ru_utime.tv_usec*tccMicroSecondsTo100NanoSeconds; + } + + if (gettimeofday(&tv, NULL) == -1) + { + ASSERT("gettimeofday() failed; errno is %d (%s)\n", errno, strerror(errno)); + return 0; + } + else + { + nCurrentTime = (ULONGLONG)tv.tv_sec*tccSecondsTo100NanoSeconds + + tv.tv_usec*tccMicroSecondsTo100NanoSeconds; + } + + nLastRecordedCurrentTime = FILETIME_TO_ULONGLONG(lpPrevCPUInfo->LastRecordedTime.ftLastRecordedCurrentTime); + nLastRecordedUserTime = FILETIME_TO_ULONGLONG(lpPrevCPUInfo->ftLastRecordedUserTime); + nLastRecordedKernelTime = FILETIME_TO_ULONGLONG(lpPrevCPUInfo->ftLastRecordedKernelTime); + + if (nCurrentTime > nLastRecordedCurrentTime) + { + nCpuTotalTime = (nCurrentTime - nLastRecordedCurrentTime); +#if HAVE_THREAD_SELF || HAVE__LWP_SELF || HAVE_VM_READ + // For systems that run multiple threads of a process on multiple processors, + // the accumulated userTime and kernelTime of this process may exceed + // the elapsed time. In this case, the cpuTotalTime needs to be adjusted + // according to number of processors so that the cpu utilization + // will not be greater than 100. + nCpuTotalTime *= dwNumberOfProcessors; +#endif // HAVE_THREAD_SELF || HAVE__LWP_SELF || HAVE_VM_READ + } + + if (nUserTime >= nLastRecordedUserTime && + nKernelTime >= nLastRecordedKernelTime) + { + nCpuBusyTime = + (nUserTime - nLastRecordedUserTime)+ + (nKernelTime - nLastRecordedKernelTime); + } + + if (nCpuTotalTime > 0 && nCpuBusyTime > 0) + { + nReading = (DWORD)((nCpuBusyTime*100)/nCpuTotalTime); + TRACE("PAL_GetCPUBusyTime: nCurrentTime=%lld, nKernelTime=%lld, nUserTime=%lld, nReading=%d\n", + nCurrentTime, nKernelTime, nUserTime, nReading); + } + + if (nReading > 100) + { + ERROR("cpu utilization(%d) > 100\n", nReading); + } + + lpPrevCPUInfo->LastRecordedTime.ftLastRecordedCurrentTime.dwLowDateTime = (DWORD)nCurrentTime; + lpPrevCPUInfo->LastRecordedTime.ftLastRecordedCurrentTime.dwHighDateTime = (DWORD)(nCurrentTime >> 32); + + lpPrevCPUInfo->ftLastRecordedUserTime.dwLowDateTime = (DWORD)nUserTime; + lpPrevCPUInfo->ftLastRecordedUserTime.dwHighDateTime = (DWORD)(nUserTime >> 32); + + lpPrevCPUInfo->ftLastRecordedKernelTime.dwLowDateTime = (DWORD)nKernelTime; + lpPrevCPUInfo->ftLastRecordedKernelTime.dwHighDateTime = (DWORD)(nKernelTime >> 32); + + return (DWORD)nReading; +} + +/*++ +Function: + GetCommandLineW + +See MSDN doc. +--*/ +LPWSTR +PALAPI +GetCommandLineW( + VOID) +{ + PERF_ENTRY(GetCommandLineW); + ENTRY("GetCommandLineW()\n"); + + LPWSTR lpwstr = g_lpwstrCmdLine ? g_lpwstrCmdLine : (LPWSTR)W(""); + + LOGEXIT("GetCommandLineW returns LPWSTR %p (%S)\n", + g_lpwstrCmdLine, + lpwstr); + PERF_EXIT(GetCommandLineW); + + return lpwstr; +} + +/*++ +Function: + OpenProcess + +See MSDN doc. + +Notes : +dwDesiredAccess is ignored (all supported operations will be allowed) +bInheritHandle is ignored (no inheritance) +--*/ +HANDLE +PALAPI +OpenProcess( + DWORD dwDesiredAccess, + BOOL bInheritHandle, + DWORD dwProcessId) +{ + PAL_ERROR palError; + CPalThread *pThread; + IPalObject *pobjProcess = NULL; + IPalObject *pobjProcessRegistered = NULL; + IDataLock *pDataLock; + CProcProcessLocalData *pLocalData; + CObjectAttributes oa; + HANDLE hProcess = NULL; + + PERF_ENTRY(OpenProcess); + ENTRY("OpenProcess(dwDesiredAccess=0x%08x, bInheritHandle=%d, " + "dwProcessId = 0x%08x)\n", + dwDesiredAccess, bInheritHandle, dwProcessId ); + + pThread = InternalGetCurrentThread(); + + if (0 == dwProcessId) + { + palError = ERROR_INVALID_PARAMETER; + goto OpenProcessExit; + } + + palError = g_pObjectManager->AllocateObject( + pThread, + &otProcess, + &oa, + &pobjProcess + ); + + if (NO_ERROR != palError) + { + goto OpenProcessExit; + } + + palError = pobjProcess->GetProcessLocalData( + pThread, + WriteLock, + &pDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + goto OpenProcessExit; + } + + pLocalData->dwProcessId = dwProcessId; + pDataLock->ReleaseLock(pThread, TRUE); + + palError = g_pObjectManager->RegisterObject( + pThread, + pobjProcess, + &aotProcess, + &hProcess, + &pobjProcessRegistered + ); + + // + // pobjProcess was invalidated by the above call, so NULL + // it out here + // + + pobjProcess = NULL; + + // + // TODO: check to see if the process actually exists? + // + +OpenProcessExit: + + if (NULL != pobjProcess) + { + pobjProcess->ReleaseReference(pThread); + } + + if (NULL != pobjProcessRegistered) + { + pobjProcessRegistered->ReleaseReference(pThread); + } + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("OpenProcess returns HANDLE %p\n", hProcess); + PERF_EXIT(OpenProcess); + return hProcess; +} + +/*++ +Function: + EnumProcessModules + +Abstract + Returns a process's module list + +Return + TRUE if it succeeded, FALSE otherwise + +Notes + This API is tricky because the module handles are never closed/freed so there can't be any + allocations for the module handle or name strings, etc. The "handles" are actually the base + addresses of the modules. The module handles should only be used by GetModuleFileNameExW + below. +--*/ +BOOL +PALAPI +EnumProcessModules( + IN HANDLE hProcess, + OUT HMODULE *lphModule, + IN DWORD cb, + OUT LPDWORD lpcbNeeded) +{ + PERF_ENTRY(EnumProcessModules); + ENTRY("EnumProcessModules(hProcess=0x%08x, cb=%d)\n", hProcess, cb); + + BOOL result = TRUE; + DWORD count = 0; + ProcessModules *listHead = GetProcessModulesFromHandle(hProcess, &count); + if (listHead != NULL) + { + for (ProcessModules *entry = listHead; entry != NULL; entry = entry->Next) + { + if (cb <= 0) + { + break; + } + cb -= sizeof(HMODULE); + *lphModule = (HMODULE)entry->BaseAddress; + lphModule++; + } + } + else + { + result = FALSE; + } + + if (lpcbNeeded) + { + // This return value isn't exactly up to spec because it should return the actual + // number of modules in the process even if "cb" isn't big enough but for our use + // it works just fine. + (*lpcbNeeded) = count * sizeof(HMODULE); + } + + LOGEXIT("EnumProcessModules returns %d\n", result); + PERF_EXIT(EnumProcessModules); + return result; +} + +/*++ +Function: + GetModuleFileNameExW + + Used only with module handles returned from EnumProcessModule (for dbgshim). + +--*/ +DWORD +PALAPI +GetModuleFileNameExW( + IN HANDLE hProcess, + IN HMODULE hModule, + OUT LPWSTR lpFilename, + IN DWORD nSize +) +{ + DWORD result = 0; + DWORD count = 0; + + ProcessModules *listHead = GetProcessModulesFromHandle(hProcess, &count); + if (listHead != NULL) + { + for (ProcessModules *entry = listHead; entry != NULL; entry = entry->Next) + { + if ((HMODULE)entry->BaseAddress == hModule) + { + // Convert CHAR string into WCHAR string + result = MultiByteToWideChar(CP_ACP, 0, entry->Name, -1, lpFilename, nSize); + break; + } + } + } + + return result; +} + +/*++ +Function: + GetProcessModulesFromHandle + +Abstract + Returns a process's module list + +Return + ProcessModules * list + +--*/ +ProcessModules * +GetProcessModulesFromHandle( + IN HANDLE hProcess, + OUT LPDWORD lpCount) +{ + CPalThread* pThread = InternalGetCurrentThread(); + CProcProcessLocalData *pLocalData = NULL; + ProcessModules *listHead = NULL; + IPalObject *pobjProcess = NULL; + IDataLock *pDataLock = NULL; + PAL_ERROR palError = NO_ERROR; + DWORD dwProcessId = 0; + DWORD count = 0; + + _ASSERTE(lpCount != NULL); + + if (hPseudoCurrentProcess == hProcess) + { + pobjProcess = g_pobjProcess; + pobjProcess->AddReference(); + } + else + { + CAllowedObjectTypes aotProcess(otiProcess); + + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hProcess, + &aotProcess, + &pobjProcess); + + if (NO_ERROR != palError) + { + pThread->SetLastError(ERROR_INVALID_HANDLE); + goto exit; + } + } + + palError = pobjProcess->GetProcessLocalData( + pThread, + WriteLock, + &pDataLock, + reinterpret_cast(&pLocalData)); + + _ASSERTE(NO_ERROR == palError); + + dwProcessId = pLocalData->dwProcessId; + listHead = pLocalData->pProcessModules; + count = pLocalData->cProcessModules; + + // If the module list hasn't been created yet, create it now + if (listHead == NULL) + { + listHead = CreateProcessModules(dwProcessId, &count); + if (listHead == NULL) + { + pThread->SetLastError(ERROR_INVALID_PARAMETER); + goto exit; + } + + if (pLocalData != NULL) + { + pLocalData->pProcessModules = listHead; + pLocalData->cProcessModules = count; + } + } + +exit: + if (NULL != pDataLock) + { + pDataLock->ReleaseLock(pThread, TRUE); + } + if (NULL != pobjProcess) + { + pobjProcess->ReleaseReference(pThread); + } + + *lpCount = count; + return listHead; +} + +/*++ +Function: + CreateProcessModules + +Abstract + Returns a process's module list + +Return + ProcessModules * list + +--*/ +ProcessModules * +CreateProcessModules( + IN DWORD dwProcessId, + OUT LPDWORD lpCount) +{ + ProcessModules *listHead = NULL; + _ASSERTE(lpCount != NULL); + +#if defined(__APPLE__) + + // For OS X, the "vmmap" command outputs something similar to the /proc/*/maps file so popen the + // command and read the relevant lines: + // + // ... + // ==== regions for process 347 (non-writable and writable regions are interleaved) + // REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL + // __TEXT 000000010446d000-0000000104475000 [ 32K] r-x/rwx SM=COW /Users/mikem/coreclr/bin/Product/OSx.x64.Debug/corerun + // __DATA 0000000104475000-0000000104476000 [ 4K] rw-/rwx SM=PRV /Users/mikem/coreclr/bin/Product/OSx.x64.Debug/corerun + // __LINKEDIT 0000000104476000-000000010447a000 [ 16K] r--/rwx SM=COW /Users/mikem/coreclr/bin/Product/OSx.x64.Debug/corerun + // Kernel Alloc Once 000000010447a000-000000010447b000 [ 4K] rw-/rwx SM=PRV + // MALLOC (admin) 000000010447b000-000000010447c000 [ 4K] r--/rwx SM=ZER + // ... + // MALLOC (admin) 00000001044ab000-00000001044ac000 [ 4K] r--/rwx SM=PRV + // __TEXT 00000001044ac000-0000000104c84000 [ 8032K] r-x/rwx SM=COW /Users/mikem/coreclr/bin/Product/OSx.x64.Debug/libcoreclr.dylib + // __TEXT 0000000104c84000-0000000104c85000 [ 4K] rwx/rwx SM=PRV /Users/mikem/coreclr/bin/Product/OSx.x64.Debug/libcoreclr.dylib + // __TEXT 0000000104c85000-000000010513b000 [ 4824K] r-x/rwx SM=COW /Users/mikem/coreclr/bin/Product/OSx.x64.Debug/libcoreclr.dylib + // __TEXT 000000010513b000-000000010513c000 [ 4K] rwx/rwx SM=PRV /Users/mikem/coreclr/bin/Product/OSx.x64.Debug/libcoreclr.dylib + // __TEXT 000000010513c000-000000010516f000 [ 204K] r-x/rwx SM=COW /Users/mikem/coreclr/bin/Product/OSx.x64.Debug/libcoreclr.dylib + // __DATA 000000010516f000-00000001051ce000 [ 380K] rw-/rwx SM=COW /Users/mikem/coreclr/bin/Product/OSx.x64.Debug/libcoreclr.dylib + // __DATA 00000001051ce000-00000001051fa000 [ 176K] rw-/rwx SM=PRV /Users/mikem/coreclr/bin/Product/OSx.x64.Debug/libcoreclr.dylib + // __LINKEDIT 00000001051fa000-0000000105bac000 [ 9928K] r--/rwx SM=COW /Users/mikem/coreclr/bin/Product/OSx.x64.Debug/libcoreclr.dylib + // VM_ALLOCATE 0000000105bac000-0000000105bad000 [ 4K] r--/rw- SM=SHM + // MALLOC (admin) 0000000105bad000-0000000105bae000 [ 4K] r--/rwx SM=ZER + // MALLOC 0000000105bae000-0000000105baf000 [ 4K] rw-/rwx SM=ZER + + // OS X Sierra (10.12.4 Beta) + // REGION TYPE START - END [ VSIZE RSDNT DIRTY SWAP] PRT/MAX SHRMOD PURGE REGION DETAIL + // Stack 00007fff5a930000-00007fff5b130000 [ 8192K 32K 32K 0K] rw-/rwx SM=PRV thread 0 + // __TEXT 00007fffa4a0b000-00007fffa4a0d000 [ 8K 8K 0K 0K] r-x/r-x SM=COW /usr/lib/libSystem.B.dylib + // __TEXT 00007fffa4bbe000-00007fffa4c15000 [ 348K 348K 0K 0K] r-x/r-x SM=COW /usr/lib/libc++.1.dylib + + // NOTE: the module path can have spaces in the name + // __TEXT 0000000196220000-00000001965b4000 [ 3664K 2340K 0K 0K] r-x/rwx SM=COW /Volumes/Builds/builds/devmain/rawproduct/debug/build/out/Applications/Microsoft Excel.app/Contents/SharedSupport/PowerQuery/libcoreclr.dylib + char *line = NULL; + size_t lineLen = 0; + int count = 0; + ssize_t read; + + char vmmapCommand[100]; + int chars = snprintf(vmmapCommand, sizeof(vmmapCommand), "/usr/bin/vmmap -interleaved %d -wide", dwProcessId); + _ASSERTE(chars > 0 && chars <= sizeof(vmmapCommand)); + + FILE *vmmapFile = popen(vmmapCommand, "r"); + if (vmmapFile == NULL) + { + goto exit; + } + + // Reading maps file line by line + while ((read = getline(&line, &lineLen, vmmapFile)) != -1) + { + void *startAddress, *endAddress; + char moduleName[PATH_MAX]; + + if (sscanf_s(line, "__TEXT %p-%p [ %*[0-9K ]] %*[-/rwxsp] SM=%*[A-Z] %[^\n]", &startAddress, &endAddress, moduleName, _countof(moduleName)) == 3) + { + bool dup = false; + for (ProcessModules *entry = listHead; entry != NULL; entry = entry->Next) + { + if (strcmp(moduleName, entry->Name) == 0) + { + dup = true; + break; + } + } + + if (!dup) + { + int cbModuleName = strlen(moduleName) + 1; + ProcessModules *entry = (ProcessModules *)InternalMalloc(sizeof(ProcessModules) + cbModuleName); + if (entry == NULL) + { + DestroyProcessModules(listHead); + listHead = NULL; + count = 0; + break; + } + strcpy_s(entry->Name, cbModuleName, moduleName); + entry->BaseAddress = startAddress; + entry->Next = listHead; + listHead = entry; + count++; + } + } + } + + *lpCount = count; + + free(line); // We didn't allocate line, but as per contract of getline we should free it + pclose(vmmapFile); +exit: + +#elif HAVE_PROCFS_MAPS + + // Here we read /proc//maps file in order to parse it and figure out what it says + // about a library we are looking for. This file looks something like this: + // + // [address] [perms] [offset] [dev] [inode] [pathname] - HEADER is not preset in an actual file + // + // 35b1800000-35b1820000 r-xp 00000000 08:02 135522 /usr/lib64/ld-2.15.so + // 35b1a1f000-35b1a20000 r--p 0001f000 08:02 135522 /usr/lib64/ld-2.15.so + // 35b1a20000-35b1a21000 rw-p 00020000 08:02 135522 /usr/lib64/ld-2.15.so + // 35b1a21000-35b1a22000 rw-p 00000000 00:00 0 [heap] + // 35b1c00000-35b1dac000 r-xp 00000000 08:02 135870 /usr/lib64/libc-2.15.so + // 35b1dac000-35b1fac000 ---p 001ac000 08:02 135870 /usr/lib64/libc-2.15.so + // 35b1fac000-35b1fb0000 r--p 001ac000 08:02 135870 /usr/lib64/libc-2.15.so + // 35b1fb0000-35b1fb2000 rw-p 001b0000 08:02 135870 /usr/lib64/libc-2.15.so + + // Making something like: /proc/123/maps + char mapFileName[100]; + char *line = NULL; + size_t lineLen = 0; + int count = 0; + ssize_t read; + + INDEBUG(int chars = ) + snprintf(mapFileName, sizeof(mapFileName), "/proc/%d/maps", dwProcessId); + _ASSERTE(chars > 0 && chars <= (int)sizeof(mapFileName)); + + FILE *mapsFile = fopen(mapFileName, "r"); + if (mapsFile == NULL) + { + goto exit; + } + + // Reading maps file line by line + while ((read = getline(&line, &lineLen, mapsFile)) != -1) + { + void *startAddress, *endAddress, *offset; + int devHi, devLo, inode; + char moduleName[PATH_MAX]; + + 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) + { + bool dup = false; + for (ProcessModules *entry = listHead; entry != NULL; entry = entry->Next) + { + if (strcmp(moduleName, entry->Name) == 0) + { + dup = true; + break; + } + } + + if (!dup) + { + int cbModuleName = strlen(moduleName) + 1; + ProcessModules *entry = (ProcessModules *)InternalMalloc(sizeof(ProcessModules) + cbModuleName); + if (entry == NULL) + { + DestroyProcessModules(listHead); + listHead = NULL; + count = 0; + break; + } + strcpy_s(entry->Name, cbModuleName, moduleName); + entry->BaseAddress = startAddress; + entry->Next = listHead; + listHead = entry; + count++; + } + } + } + } + + *lpCount = count; + + free(line); // We didn't allocate line, but as per contract of getline we should free it + fclose(mapsFile); +exit: + +#else + _ASSERTE(!"Not implemented on this platform"); +#endif + return listHead; +} + +/*++ +Function: + DestroyProcessModules + +Abstract + Cleans up the process module table. + +Return + None + +--*/ +VOID +DestroyProcessModules(IN ProcessModules *listHead) +{ + for (ProcessModules *entry = listHead; entry != NULL; ) + { + ProcessModules *next = entry->Next; + free(entry); + entry = next; + } +} + +/*++ +Function + PROCNotifyProcessShutdown + + Calls the abort handler to do any shutdown cleanup. Call be called + from the unhandled native exception handler. + +(no return value) +--*/ +__attribute__((destructor)) +VOID +PROCNotifyProcessShutdown() +{ + // Call back into the coreclr to clean up the debugger transport pipes + PSHUTDOWN_CALLBACK callback = InterlockedExchangePointer(&g_shutdownCallback, NULL); + if (callback != NULL) + { + callback(); + } +} + +/*++ +Function + PROCBuildCreateDumpCommandLine + +Abstract + Builds the createdump command line from the arguments. + +Return + TRUE - succeeds, FALSE - fails + +--*/ +BOOL +PROCBuildCreateDumpCommandLine( + const char** argv, + char** pprogram, + char** ppidarg, + char* dumpName, + char* dumpType, + BOOL diag) +{ + if (g_szCoreCLRPath == nullptr) + { + return FALSE; + } + const char* DumpGeneratorName = "createdump"; + int programLen = strlen(g_szCoreCLRPath) + strlen(DumpGeneratorName) + 1; + char* program = *pprogram = (char*)InternalMalloc(programLen); + if (program == nullptr) + { + return FALSE; + } + if (strcpy_s(program, programLen, g_szCoreCLRPath) != SAFECRT_SUCCESS) + { + return FALSE; + } + char *last = strrchr(program, '/'); + if (last != nullptr) + { + *(last + 1) = '\0'; + } + else + { + program[0] = '\0'; + } + if (strcat_s(program, programLen, DumpGeneratorName) != SAFECRT_SUCCESS) + { + return FALSE; + } + char* pidarg = *ppidarg = (char*)InternalMalloc(128); + if (pidarg == nullptr) + { + return FALSE; + } + if (sprintf_s(pidarg, 128, "%d", gPID) == -1) + { + return FALSE; + } + *argv++ = program; + + if (dumpName != nullptr) + { + *argv++ = "--name"; + *argv++ = dumpName; + } + + if (dumpType != nullptr) + { + if (strcmp(dumpType, "1") == 0) + { + *argv++ = "--normal"; + } + else if (strcmp(dumpType, "2") == 0) + { + *argv++ = "--withheap"; + } + else if (strcmp(dumpType, "3") == 0) + { + *argv++ = "--triage"; + } + else if (strcmp(dumpType, "4") == 0) + { + *argv++ = "--full"; + } + } + + if (diag) + { + *argv++ = "--diag"; + } + + *argv++ = pidarg; + *argv = nullptr; + + return TRUE; +} + +/*++ +Function: + PROCCreateCrashDump + + Creates crash dump of the process. Can be called from the + unhandled native exception handler. + +(no return value) +--*/ +BOOL +PROCCreateCrashDump(char** argv) +{ +#if HAVE_PRCTL_H && HAVE_PR_SET_PTRACER + + // Fork the core dump child process. + pid_t childpid = fork(); + + // If error, write an error to trace log and abort + if (childpid == -1) + { + ERROR("PROCCreateCrashDump: fork() FAILED %d (%s)\n", errno, strerror(errno)); + return false; + } + else if (childpid == 0) + { + // Child process + if (execve(argv[0], argv, palEnvironment) == -1) + { + ERROR("PPROCCreateCrashDump: execve FAILED %d (%s)\n", errno, strerror(errno)); + return false; + } + } + else + { + // Gives the child process permission to use /proc//mem and ptrace + if (prctl(PR_SET_PTRACER, childpid, 0, 0, 0) == -1) + { + // Ignore any error because on some CentOS and OpenSUSE distros, it isn't + // supported but createdump works just fine. + ERROR("PPROCCreateCrashDump: prctl() FAILED %d (%s)\n", errno, strerror(errno)); + } + // Parent waits until the child process is done + int wstatus = 0; + int result = waitpid(childpid, &wstatus, 0); + if (result != childpid) + { + ERROR("PPROCCreateCrashDump: waitpid FAILED result %d wstatus %d errno %d (%s)\n", + result, wstatus, errno, strerror(errno)); + return false; + } + return !WIFEXITED(wstatus) || WEXITSTATUS(wstatus) == 0; + } +#endif // HAVE_PRCTL_H && HAVE_PR_SET_PTRACER + return true; +} + +/*++ +Function + PROCAbortInitialize() + +Abstract + Initialize the process abort crash dump program file path and + name. Doing all of this ahead of time so nothing is allocated + or copied in PROCAbort/signal handler. + +Return + TRUE - succeeds, FALSE - fails + +--*/ +BOOL +PROCAbortInitialize() +{ + char* enabled = getenv("COMPlus_DbgEnableMiniDump"); + if (enabled != nullptr && _stricmp(enabled, "1") == 0) + { + char* dumpName = getenv("COMPlus_DbgMiniDumpName"); + char* dumpType = getenv("COMPlus_DbgMiniDumpType"); + char* diagStr = getenv("COMPlus_CreateDumpDiagnostics"); + BOOL diag = diagStr != nullptr && strcmp(diagStr, "1") == 0; + char* program = nullptr; + char* pidarg = nullptr; + + if (!PROCBuildCreateDumpCommandLine((const char **)g_argvCreateDump, &program, &pidarg, dumpName, dumpType, diag)) + { + return FALSE; + } + } + return TRUE; +} + +/*++ +Function: + PAL_GenerateCoreDump + +Abstract: + Public entry point to create a crash dump of the process. + +Parameters: + dumpName + dumpType: + Normal = 1, + WithHeap = 2, + Triage = 3, + Full = 4 + diag + true - log createdump diagnostics to console + +Return: + TRUE success + FALSE failed +--*/ +BOOL +PAL_GenerateCoreDump( + LPCSTR dumpName, + INT dumpType, + BOOL diag) +{ + char* argvCreateDump[8] = { nullptr }; + char dumpTypeStr[16]; + + if (dumpType < 1 || dumpType > 4) + { + return FALSE; + } + if (_itoa_s(dumpType, dumpTypeStr, sizeof(dumpTypeStr), 10) != 0) + { + return FALSE; + } + if (dumpName != nullptr && dumpName[0] == '\0') + { + dumpName = nullptr; + } + char* program = nullptr; + char* pidarg = nullptr; + BOOL result = PROCBuildCreateDumpCommandLine((const char **)argvCreateDump, &program, &pidarg, (char*)dumpName, dumpTypeStr, diag); + if (result) + { + result = PROCCreateCrashDump(argvCreateDump); + } + free(program); + free(pidarg); + return result; +} + +/*++ +Function: + PROCCreateCrashDumpIfEnabled + + Creates crash dump of the process (if enabled). Can be + called from the unhandled native exception handler. + +(no return value) +--*/ +VOID +PROCCreateCrashDumpIfEnabled() +{ + // If enabled, launch the create minidump utility and wait until it completes + if (g_argvCreateDump[0] != nullptr) + { + PROCCreateCrashDump(g_argvCreateDump); + } +} + +/*++ +Function: + PROCAbort() + + Aborts the process after calling the shutdown cleanup handler. This function + should be called instead of calling abort() directly. + + Does not return +--*/ +PAL_NORETURN +VOID +PROCAbort() +{ + // Do any shutdown cleanup before aborting or creating a core dump + PROCNotifyProcessShutdown(); + + PROCCreateCrashDumpIfEnabled(); + + // Abort the process after waiting for the core dump to complete + abort(); +} + +/*++ +Function: + InitializeFlushProcessWriteBuffers + +Abstract + This function initializes data structures needed for the FlushProcessWriteBuffers +Return + TRUE if it succeeded, FALSE otherwise +--*/ +BOOL +InitializeFlushProcessWriteBuffers() +{ + _ASSERTE(s_helperPage == 0); + _ASSERTE(s_flushUsingMemBarrier == 0); + + // Starting with Linux kernel 4.14, process memory barriers can be generated + // using MEMBARRIER_CMD_PRIVATE_EXPEDITED. + int mask = membarrier(MEMBARRIER_CMD_QUERY, 0); + if (mask >= 0 && + mask & MEMBARRIER_CMD_PRIVATE_EXPEDITED) + { + // Register intent to use the private expedited command. + if (membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0) == 0) + { + s_flushUsingMemBarrier = TRUE; + return TRUE; + } + } + + s_helperPage = static_cast(mmap(0, GetVirtualPageSize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); + + if(s_helperPage == MAP_FAILED) + { + return FALSE; + } + + // Verify that the s_helperPage is really aligned to the GetVirtualPageSize() + _ASSERTE((((SIZE_T)s_helperPage) & (GetVirtualPageSize() - 1)) == 0); + + // Locking the page ensures that it stays in memory during the two mprotect + // calls in the FlushProcessWriteBuffers below. If the page was unmapped between + // those calls, they would not have the expected effect of generating IPI. + int status = mlock(s_helperPage, GetVirtualPageSize()); + + if (status != 0) + { + return FALSE; + } + + status = pthread_mutex_init(&flushProcessWriteBuffersMutex, NULL); + if (status != 0) + { + munlock(s_helperPage, GetVirtualPageSize()); + } + + return status == 0; +} + +#define FATAL_ASSERT(e, msg) \ + do \ + { \ + if (!(e)) \ + { \ + fprintf(stderr, "FATAL ERROR: " msg); \ + PROCAbort(); \ + } \ + } \ + while(0) + +/*++ +Function: + FlushProcessWriteBuffers + +See MSDN doc. +--*/ +VOID +PALAPI +FlushProcessWriteBuffers() +{ + if (s_flushUsingMemBarrier) + { + int status = membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED, 0); + FATAL_ASSERT(status == 0, "Failed to flush using membarrier"); + } + else + { + int status = pthread_mutex_lock(&flushProcessWriteBuffersMutex); + FATAL_ASSERT(status == 0, "Failed to lock the flushProcessWriteBuffersMutex lock"); + + // Changing a helper memory page protection from read / write to no access + // causes the OS to issue IPI to flush TLBs on all processors. This also + // results in flushing the processor buffers. + status = mprotect(s_helperPage, GetVirtualPageSize(), PROT_READ | PROT_WRITE); + FATAL_ASSERT(status == 0, "Failed to change helper page protection to read / write"); + + // Ensure that the page is dirty before we change the protection so that + // we prevent the OS from skipping the global TLB flush. + InterlockedIncrement(s_helperPage); + + status = mprotect(s_helperPage, GetVirtualPageSize(), PROT_NONE); + FATAL_ASSERT(status == 0, "Failed to change helper page protection to no access"); + + status = pthread_mutex_unlock(&flushProcessWriteBuffersMutex); + FATAL_ASSERT(status == 0, "Failed to unlock the flushProcessWriteBuffersMutex lock"); + } +} + +/*++ +Function: + PROCGetProcessIDFromHandle + +Abstract + Return the process ID from a process handle + +Parameter + hProcess: process handle + +Return + Return the process ID, or 0 if it's not a valid handle +--*/ +DWORD +PROCGetProcessIDFromHandle( + HANDLE hProcess) +{ + PAL_ERROR palError; + IPalObject *pobjProcess = NULL; + CPalThread *pThread = InternalGetCurrentThread(); + + DWORD dwProcessId = 0; + + if (hPseudoCurrentProcess == hProcess) + { + dwProcessId = gPID; + goto PROCGetProcessIDFromHandleExit; + } + + + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hProcess, + &aotProcess, + &pobjProcess + ); + + if (NO_ERROR == palError) + { + IDataLock *pDataLock; + CProcProcessLocalData *pLocalData; + + palError = pobjProcess->GetProcessLocalData( + pThread, + ReadLock, + &pDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR == palError) + { + dwProcessId = pLocalData->dwProcessId; + pDataLock->ReleaseLock(pThread, FALSE); + } + + pobjProcess->ReleaseReference(pThread); + } + +PROCGetProcessIDFromHandleExit: + + return dwProcessId; +} + +PAL_ERROR +CorUnix::InitializeProcessData( + void + ) +{ + PAL_ERROR palError = NO_ERROR; + bool fLockInitialized = FALSE; + + pGThreadList = NULL; + g_dwThreadCount = 0; + + InternalInitializeCriticalSection(&g_csProcess); + fLockInitialized = TRUE; + + if (NO_ERROR != palError) + { + if (fLockInitialized) + { + InternalDeleteCriticalSection(&g_csProcess); + } + } + + return palError; +} + +/*++ +Function + InitializeProcessCommandLine + +Abstract + Initializes (or re-initializes) the saved command line and exe path. + +Parameter + lpwstrCmdLine + lpwstrFullPath + +Return + PAL_ERROR + +Notes + This function takes ownership of lpwstrCmdLine, but not of lpwstrFullPath +--*/ + +PAL_ERROR +CorUnix::InitializeProcessCommandLine( + LPWSTR lpwstrCmdLine, + LPWSTR lpwstrFullPath +) +{ + PAL_ERROR palError = NO_ERROR; + LPWSTR initial_dir = NULL; + + // + // Save the command line and initial directory + // + + if (lpwstrFullPath) + { + LPWSTR lpwstr = PAL_wcsrchr(lpwstrFullPath, '/'); + lpwstr[0] = '\0'; + size_t n = PAL_wcslen(lpwstrFullPath) + 1; + + size_t iLen = n; + initial_dir = reinterpret_cast(InternalMalloc(iLen*sizeof(WCHAR))); + if (NULL == initial_dir) + { + ERROR("malloc() failed! (initial_dir) \n"); + palError = ERROR_NOT_ENOUGH_MEMORY; + goto exit; + } + + if (wcscpy_s(initial_dir, iLen, lpwstrFullPath) != SAFECRT_SUCCESS) + { + ERROR("wcscpy_s failed!\n"); + free(initial_dir); + palError = ERROR_INTERNAL_ERROR; + goto exit; + } + + lpwstr[0] = '/'; + + free(g_lpwstrAppDir); + g_lpwstrAppDir = initial_dir; + } + + free(g_lpwstrCmdLine); + g_lpwstrCmdLine = lpwstrCmdLine; + +exit: + return palError; +} + + +/*++ +Function: + CreateInitialProcessAndThreadObjects + +Abstract + Creates the IPalObjects that represent the current process + and the initial thread + +Parameter + pThread - the initial thread + +Return + PAL_ERROR +--*/ + +PAL_ERROR +CorUnix::CreateInitialProcessAndThreadObjects( + CPalThread *pThread + ) +{ + PAL_ERROR palError = NO_ERROR; + HANDLE hThread; + IPalObject *pobjProcess = NULL; + IDataLock *pDataLock; + CProcProcessLocalData *pLocalData; + CObjectAttributes oa; + HANDLE hProcess; + + // + // Create initial thread object + // + + palError = CreateThreadObject(pThread, pThread, &hThread); + if (NO_ERROR != palError) + { + goto CreateInitialProcessAndThreadObjectsExit; + } + + // + // This handle isn't needed + // + + (void) g_pObjectManager->RevokeHandle(pThread, hThread); + + // + // Create and initialize process object + // + + palError = g_pObjectManager->AllocateObject( + pThread, + &otProcess, + &oa, + &pobjProcess + ); + + if (NO_ERROR != palError) + { + ERROR("Unable to allocate process object"); + goto CreateInitialProcessAndThreadObjectsExit; + } + + palError = pobjProcess->GetProcessLocalData( + pThread, + WriteLock, + &pDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + ASSERT("Unable to access local data"); + goto CreateInitialProcessAndThreadObjectsExit; + } + + pLocalData->dwProcessId = gPID; + pLocalData->ps = PS_RUNNING; + pDataLock->ReleaseLock(pThread, TRUE); + + palError = g_pObjectManager->RegisterObject( + pThread, + pobjProcess, + &aotProcess, + &hProcess, + &g_pobjProcess + ); + + // + // pobjProcess is invalidated by the call to RegisterObject, so + // NULL it out here to prevent it from being released later + // + + pobjProcess = NULL; + + if (NO_ERROR != palError) + { + ASSERT("Failure registering process object"); + goto CreateInitialProcessAndThreadObjectsExit; + } + + // + // There's no need to keep this handle around, so revoke + // it now + // + + g_pObjectManager->RevokeHandle(pThread, hProcess); + +CreateInitialProcessAndThreadObjectsExit: + + if (NULL != pobjProcess) + { + pobjProcess->ReleaseReference(pThread); + } + + return palError; +} + + +/*++ +Function: + PROCCleanupInitialProcess + +Abstract + Cleanup all the structures for the initial process. + +Parameter + VOID + +Return + VOID + +--*/ +VOID +PROCCleanupInitialProcess(VOID) +{ + CPalThread *pThread = InternalGetCurrentThread(); + + InternalEnterCriticalSection(pThread, &g_csProcess); + + /* Free the application directory */ + free(g_lpwstrAppDir); + + /* Free the stored command line */ + free(g_lpwstrCmdLine); + + InternalLeaveCriticalSection(pThread, &g_csProcess); + + // + // Object manager shutdown will handle freeing the underlying + // thread and process data + // + +} + +/*++ +Function: + PROCAddThread + +Abstract + Add a thread to the thread list of the current process + +Parameter + pThread: Thread object + +--*/ +VOID +CorUnix::PROCAddThread( + CPalThread *pCurrentThread, + CPalThread *pTargetThread + ) +{ + /* protect the access of the thread list with critical section for + mutithreading access */ + InternalEnterCriticalSection(pCurrentThread, &g_csProcess); + + pTargetThread->SetNext(pGThreadList); + pGThreadList = pTargetThread; + g_dwThreadCount += 1; + + TRACE("Thread 0x%p (id %#x) added to the process thread list\n", + pTargetThread, pTargetThread->GetThreadId()); + + InternalLeaveCriticalSection(pCurrentThread, &g_csProcess); +} + + +/*++ +Function: + PROCRemoveThread + +Abstract + Remove a thread form the thread list of the current process + +Parameter + CPalThread *pThread : thread object to remove + +(no return value) +--*/ +VOID +CorUnix::PROCRemoveThread( + CPalThread *pCurrentThread, + CPalThread *pTargetThread + ) +{ + CPalThread *curThread, *prevThread; + + /* protect the access of the thread list with critical section for + mutithreading access */ + InternalEnterCriticalSection(pCurrentThread, &g_csProcess); + + curThread = pGThreadList; + + /* if thread list is empty */ + if (curThread == NULL) + { + ASSERT("Thread list is empty.\n"); + goto EXIT; + } + + /* do we remove the first thread? */ + if (curThread == pTargetThread) + { + pGThreadList = curThread->GetNext(); + TRACE("Thread 0x%p (id %#x) removed from the process thread list\n", + pTargetThread, pTargetThread->GetThreadId()); + goto EXIT; + } + + prevThread = curThread; + curThread = curThread->GetNext(); + /* find the thread to remove */ + while (curThread != NULL) + { + if (curThread == pTargetThread) + { + /* found, fix the chain list */ + prevThread->SetNext(curThread->GetNext()); + g_dwThreadCount -= 1; + TRACE("Thread %p removed from the process thread list\n", pTargetThread); + goto EXIT; + } + + prevThread = curThread; + curThread = curThread->GetNext(); + } + + WARN("Thread %p not removed (it wasn't found in the list)\n", pTargetThread); + +EXIT: + InternalLeaveCriticalSection(pCurrentThread, &g_csProcess); +} + + +/*++ +Function: + PROCGetNumberOfThreads + +Abstract + Return the number of threads in the thread list. + +Parameter + void + +Return + the number of threads. +--*/ +INT +CorUnix::PROCGetNumberOfThreads( + VOID) +{ + return g_dwThreadCount; +} + + +/*++ +Function: + PROCProcessLock + +Abstract + Enter the critical section associated to the current process + +Parameter + void + +Return + void +--*/ +VOID +PROCProcessLock( + VOID) +{ + CPalThread * pThread = + (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : NULL); + + InternalEnterCriticalSection(pThread, &g_csProcess); +} + + +/*++ +Function: + PROCProcessUnlock + +Abstract + Leave the critical section associated to the current process + +Parameter + void + +Return + void +--*/ +VOID +PROCProcessUnlock( + VOID) +{ + CPalThread * pThread = + (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : NULL); + + InternalLeaveCriticalSection(pThread, &g_csProcess); +} + +#if USE_SYSV_SEMAPHORES +/*++ +Function: + PROCCleanupThreadSemIds + +Abstract + Cleanup SysV semaphore ids for all threads + +(no parameters, no return value) +--*/ +VOID +PROCCleanupThreadSemIds(void) +{ + // + // When using SysV semaphores, the semaphore ids used by PAL threads must be removed + // so they can be used again. + // + + PROCProcessLock(); + + CPalThread *pTargetThread = pGThreadList; + while (NULL != pTargetThread) + { + pTargetThread->suspensionInfo.DestroySemaphoreIds(); + pTargetThread = pTargetThread->GetNext(); + } + + PROCProcessUnlock(); + +} +#endif // USE_SYSV_SEMAPHORES + +/*++ +Function: + TerminateCurrentProcessNoExit + +Abstract: + Terminate current Process, but leave the caller alive + +Parameters: + BOOL bTerminateUnconditionally - If this is set, the PAL will exit as + quickly as possible. In particular, it will not unload DLLs. + +Return value : + No return + +Note: + This function is used in ExitThread and TerminateProcess + +--*/ +VOID +CorUnix::TerminateCurrentProcessNoExit(BOOL bTerminateUnconditionally) +{ + BOOL locked; + DWORD old_terminator; + + old_terminator = InterlockedCompareExchange(&terminator, GetCurrentThreadId(), 0); + + if (0 != old_terminator && GetCurrentThreadId() != old_terminator) + { + /* another thread has already initiated the termination process. we + could just block on the PALInitLock critical section, but then + PROCSuspendOtherThreads would hang... so sleep forever here, we're + terminating anyway + + Update: [TODO] PROCSuspendOtherThreads has been removed. Can this + code be changed? */ + + /* note that if *this* thread has already started the termination + process, we want to proceed. the only way this can happen is if a + call to DllMain (from ExitProcess) brought us here (because DllMain + called ExitProcess, or TerminateProcess, or ExitThread); + TerminateProcess won't call DllMain, so there's no danger to get + caught in an infinite loop */ + WARN("termination already started from another thread; blocking.\n"); + poll(NULL, 0, INFTIM); + } + + /* Try to lock the initialization count to prevent multiple threads from + terminating/initializing the PAL simultaneously */ + + /* note : it's also important to take this lock before the process lock, + because Init/Shutdown take the init lock, and the functions they call + may take the process lock. We must do it in the same order to avoid + deadlocks */ + + locked = PALInitLock(); + if(locked && PALIsInitialized()) + { + PROCNotifyProcessShutdown(); + PALCommonCleanup(); + } +} + +/*++ +Function: + PROCGetProcessStatus + +Abstract: + Retrieve process state information (state & exit code). + +Parameters: + DWORD process_id : PID of process to retrieve state for + PROCESS_STATE *state : state of process (starting, running, done) + DWORD *exit_code : exit code of process (from ExitProcess, etc.) + +Return value : + TRUE on success +--*/ +PAL_ERROR +PROCGetProcessStatus( + CPalThread *pThread, + HANDLE hProcess, + PROCESS_STATE *pps, + DWORD *pdwExitCode + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pobjProcess = NULL; + IDataLock *pDataLock; + CProcProcessLocalData *pLocalData; + pid_t wait_retval; + int status; + + // + // First, check if we already know the status of this process. This will be + // the case if this function has already been called for the same process. + // + + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hProcess, + &aotProcess, + &pobjProcess + ); + + if (NO_ERROR != palError) + { + goto PROCGetProcessStatusExit; + } + + palError = pobjProcess->GetProcessLocalData( + pThread, + WriteLock, + &pDataLock, + reinterpret_cast(&pLocalData) + ); + + if (PS_DONE == pLocalData->ps) + { + TRACE("We already called waitpid() on process ID %#x; process has " + "terminated, exit code is %d\n", + pLocalData->dwProcessId, pLocalData->dwExitCode); + + *pps = pLocalData->ps; + *pdwExitCode = pLocalData->dwExitCode; + + pDataLock->ReleaseLock(pThread, FALSE); + + goto PROCGetProcessStatusExit; + } + + /* By using waitpid(), we can even retrieve the exit code of a non-PAL + process. However, note that waitpid() can only provide the low 8 bits + of the exit code. This is all that is required for the PAL spec. */ + TRACE("Looking for status of process; trying wait()"); + + while(1) + { + /* try to get state of process, using non-blocking call */ + wait_retval = waitpid(pLocalData->dwProcessId, &status, WNOHANG); + + if ( wait_retval == (pid_t) pLocalData->dwProcessId ) + { + /* success; get the exit code */ + if ( WIFEXITED( status ) ) + { + *pdwExitCode = WEXITSTATUS(status); + TRACE("Exit code was %d\n", *pdwExitCode); + } + else + { + WARN("process terminated without exiting; can't get exit " + "code. faking it.\n"); + *pdwExitCode = EXIT_FAILURE; + } + *pps = PS_DONE; + } + else if (0 == wait_retval) + { + // The process is still running. + TRACE("Process %#x is still active.\n", pLocalData->dwProcessId); + *pps = PS_RUNNING; + *pdwExitCode = 0; + } + else if (-1 == wait_retval) + { + // This might happen if waitpid() had already been called, but + // this shouldn't happen - we call waitpid once, store the + // result, and use that afterwards. + // One legitimate cause of failure is EINTR; if this happens we + // have to try again. A second legitimate cause is ECHILD, which + // happens if we're trying to retrieve the status of a currently- + // running process that isn't a child of this process. + if(EINTR == errno) + { + TRACE("waitpid() failed with EINTR; re-waiting"); + continue; + } + else if (ECHILD == errno) + { + TRACE("waitpid() failed with ECHILD; calling kill instead"); + if (kill(pLocalData->dwProcessId, 0) != 0) + { + if(ESRCH == errno) + { + WARN("kill() failed with ESRCH, i.e. target " + "process exited and it wasn't a child, " + "so can't get the exit code, assuming " + "it was 0.\n"); + *pdwExitCode = 0; + } + else + { + ERROR("kill(pid, 0) failed; errno is %d (%s)\n", + errno, strerror(errno)); + *pdwExitCode = EXIT_FAILURE; + } + *pps = PS_DONE; + } + else + { + *pps = PS_RUNNING; + *pdwExitCode = 0; + } + } + else + { + // Ignoring unexpected waitpid errno and assuming that + // the process is still running + ERROR("waitpid(pid=%u) failed with unexpected errno=%d (%s)\n", + pLocalData->dwProcessId, errno, strerror(errno)); + *pps = PS_RUNNING; + *pdwExitCode = 0; + } + } + else + { + ASSERT("waitpid returned unexpected value %d\n",wait_retval); + *pdwExitCode = EXIT_FAILURE; + *pps = PS_DONE; + } + // Break out of the loop in all cases except EINTR. + break; + } + + // Save the exit code for future reference (waitpid will only work once). + if(PS_DONE == *pps) + { + pLocalData->ps = PS_DONE; + pLocalData->dwExitCode = *pdwExitCode; + } + + TRACE( "State of process 0x%08x : %d (exit code %d)\n", + pLocalData->dwProcessId, *pps, *pdwExitCode ); + + pDataLock->ReleaseLock(pThread, TRUE); + +PROCGetProcessStatusExit: + + if (NULL != pobjProcess) + { + pobjProcess->ReleaseReference(pThread); + } + + return palError; +} + +#ifdef __APPLE__ +bool GetApplicationContainerFolder(PathCharString& buffer, const char *applicationGroupId, int applicationGroupIdLength) +{ + const char *homeDir = getpwuid(getuid())->pw_dir; + int homeDirLength = strlen(homeDir); + + // The application group container folder is defined as: + // /user/{loginname}/Library/Group Containers/{AppGroupId}/ + return buffer.Set(homeDir, homeDirLength) + && buffer.Append(APPLICATION_CONTAINER_BASE_PATH_SUFFIX) + && buffer.Append(applicationGroupId, applicationGroupIdLength) + && buffer.Append('/'); +} +#endif // __APPLE__ + +#ifdef _DEBUG +void PROCDumpThreadList() +{ + CPalThread *pThread; + + PROCProcessLock(); + + TRACE ("Threads:{\n"); + + pThread = pGThreadList; + while (NULL != pThread) + { + TRACE (" {pThr=0x%p tid=%#x lwpid=%#x state=%d finsusp=%d}\n", + pThread, (int)pThread->GetThreadId(), (int)pThread->GetLwpId(), + (int)pThread->synchronizationInfo.GetThreadState(), + (int)pThread->suspensionInfo.GetSuspendedForShutdown()); + + pThread = pThread->GetNext(); + } + TRACE ("Threads:}\n"); + + PROCProcessUnlock(); +} +#endif + +/* Internal function definitions **********************************************/ + +/*++ +Function: + getFileName + +Abstract: + Helper function for CreateProcessW, it retrieves the executable filename + from the application name, and the command line. + +Parameters: + IN lpApplicationName: first parameter from CreateProcessW (an unicode string) + IN lpCommandLine: second parameter from CreateProcessW (an unicode string) + OUT lpFileName: file to be executed (the new process) + +Return: + TRUE: if the file name is retrieved + FALSE: otherwise + +--*/ +static +BOOL +getFileName( + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + PathCharString& lpPathFileName) +{ + LPWSTR lpEnd; + WCHAR wcEnd; + char * lpFileName; + PathCharString lpFileNamePS; + char *lpTemp; + + if (lpApplicationName) + { + int length = WideCharToMultiByte(CP_ACP, 0, lpApplicationName, -1, + NULL, 0, NULL, NULL); + + /* if only a file name is specified, prefix it with "./" */ + if ((*lpApplicationName != '.') && (*lpApplicationName != '/') && + (*lpApplicationName != '\\')) + { + length += 2; + lpTemp = lpPathFileName.OpenStringBuffer(length); + + if (strcpy_s(lpTemp, length, "./") != SAFECRT_SUCCESS) + { + ERROR("strcpy_s failed!\n"); + return FALSE; + } + lpTemp+=2; + + } + else + { + lpTemp = lpPathFileName.OpenStringBuffer(length); + } + + /* Convert to ASCII */ + length = WideCharToMultiByte(CP_ACP, 0, lpApplicationName, -1, + lpTemp, length, NULL, NULL); + if (length == 0) + { + lpPathFileName.CloseBuffer(0); + ASSERT("WideCharToMultiByte failure\n"); + return FALSE; + } + + lpPathFileName.CloseBuffer(length -1); + + /* Replace '\' by '/' */ + FILEDosToUnixPathA(lpTemp); + + return TRUE; + } + else + { + /* use the Command line */ + + /* filename should be the first token of the command line */ + + /* first skip all leading whitespace */ + lpCommandLine = UTIL_inverse_wcspbrk(lpCommandLine,W16_WHITESPACE); + if(NULL == lpCommandLine) + { + ERROR("CommandLine contains only whitespace!\n"); + return FALSE; + } + + /* check if it is starting with a quote (") character */ + if (*lpCommandLine == 0x0022) + { + lpCommandLine++; /* skip the quote */ + + /* file name ends with another quote */ + lpEnd = PAL_wcschr(lpCommandLine+1, 0x0022); + + /* if no quotes found, set lpEnd to the end of the Command line */ + if (lpEnd == NULL) + lpEnd = lpCommandLine + PAL_wcslen(lpCommandLine); + } + else + { + /* filename is end out by a whitespace */ + lpEnd = PAL_wcspbrk(lpCommandLine, W16_WHITESPACE); + + /* if no whitespace found, set lpEnd to end of the Command line */ + if (lpEnd == NULL) + { + lpEnd = lpCommandLine + PAL_wcslen(lpCommandLine); + } + } + + if (lpEnd == lpCommandLine) + { + ERROR("application name and command line are both empty!\n"); + return FALSE; + } + + /* replace the last character by a null */ + wcEnd = *lpEnd; + *lpEnd = 0x0000; + + /* Convert to ASCII */ + int size = 0; + int length = (PAL_wcslen(lpCommandLine)+1) * sizeof(WCHAR); + lpFileName = lpFileNamePS.OpenStringBuffer(length); + if (NULL == lpFileName) + { + ERROR("Not Enough Memory!\n"); + return FALSE; + } + if (!(size = WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, + lpFileName, length, NULL, NULL))) + { + ASSERT("WideCharToMultiByte failure\n"); + return FALSE; + } + + lpFileNamePS.CloseBuffer(size - 1); + /* restore last character */ + *lpEnd = wcEnd; + + /* Replace '\' by '/' */ + FILEDosToUnixPathA(lpFileName); + if (!getPath(lpFileNamePS, lpPathFileName)) + { + /* file is not in the path */ + return FALSE; + } + } + return TRUE; +} + +/*++ +Function: + checkFileType + +Abstract: + Return the type of the file. + +Parameters: + IN lpFileName: file name + +Return: + FILE_DIR: Directory + FILE_UNIX: Unix executable file + FILE_ERROR: Error +--*/ +static +int +checkFileType( LPCSTR lpFileName) +{ + struct stat stat_data; + + /* check if the file exist */ + if ( access(lpFileName, F_OK) != 0 ) + { + return FILE_ERROR; + } + + /* if it's not a PE/COFF file, check if it is executable */ + if ( -1 != stat( lpFileName, &stat_data ) ) + { + if((stat_data.st_mode & S_IFMT) == S_IFDIR ) + { + /*The given file is a directory*/ + return FILE_DIR; + } + if ( UTIL_IsExecuteBitsSet( &stat_data ) ) + { + return FILE_UNIX; + } + else + { + return FILE_ERROR; + } + } + return FILE_ERROR; + +} + + +/*++ +Function: + buildArgv + +Abstract: + Helper function for CreateProcessW, it builds the array of argument in + a format than can be passed to execve function.lppArgv is allocated + in this function and must be freed by the caller. + +Parameters: + IN lpCommandLine: second parameter from CreateProcessW (an unicode string) + IN lpAppPath: cannonical name of the application to launched + OUT lppArgv: array of arguments to be passed to the new process + +Return: + the number of arguments + +note: this doesn't yet match precisely the behavior of Windows, but should be +sufficient. +what's here: +1) stripping nonquoted whitespace +2) handling of quoted parameters and quoted "parts" of parameters, removal of + doublequotes ( becomes ) +3) \" as an escaped doublequote, both within doublequoted sequences and out +what's known missing : +1) \\ as an escaped backslash, but only if the string of '\' + is followed by a " (escaped or not) +2) "alternate" escape sequence : double-doublequote within a double-quoted + argument (<"aaa a""aa aaa">) expands to a single-doublequote() +note that there may be other special cases +--*/ +static +char ** +buildArgv( + LPCWSTR lpCommandLine, + PathCharString& lpAppPath, + UINT *pnArg) +{ + CPalThread *pThread = NULL; + UINT iWlen; + char *lpAsciiCmdLine; + char *pChar; + char **lppArgv; + char **lppTemp; + UINT i,j; + + *pnArg = 0; + + iWlen = WideCharToMultiByte(CP_ACP,0,lpCommandLine,-1,NULL,0,NULL,NULL); + + if(0 == iWlen) + { + ASSERT("Can't determine length of command line\n"); + return NULL; + } + + pThread = InternalGetCurrentThread(); + /* make sure to allocate enough space, up for the worst case scenario */ + int iLength = (iWlen + lpAppPath.GetCount() + 2); + lpAsciiCmdLine = (char *) InternalMalloc(iLength); + + if (lpAsciiCmdLine == NULL) + { + ERROR("Unable to allocate memory\n"); + return NULL; + } + + pChar = lpAsciiCmdLine; + + /* put the cannonical name of the application as the first parameter */ + if ((strcpy_s(lpAsciiCmdLine, iLength, "\"") != SAFECRT_SUCCESS) || + (strcat_s(lpAsciiCmdLine, iLength, lpAppPath) != SAFECRT_SUCCESS) || + (strcat_s(lpAsciiCmdLine, iLength, "\"") != SAFECRT_SUCCESS) || + (strcat_s(lpAsciiCmdLine, iLength, " ") != SAFECRT_SUCCESS)) + { + ERROR("strcpy_s/strcat_s failed!\n"); + return NULL; + } + + pChar = lpAsciiCmdLine + strlen (lpAsciiCmdLine); + + /* let's skip the first argument in the command line */ + + /* strip leading whitespace; function returns NULL if there's only + whitespace, so the if statement below will work correctly */ + lpCommandLine = UTIL_inverse_wcspbrk((LPWSTR)lpCommandLine, W16_WHITESPACE); + + if (lpCommandLine) + { + LPCWSTR stringstart = lpCommandLine; + + do + { + /* find first whitespace or dquote character */ + lpCommandLine = PAL_wcspbrk(lpCommandLine,W16_WHITESPACE_DQUOTE); + if(NULL == lpCommandLine) + { + /* no whitespace or dquote found : first arg is only arg */ + break; + } + else if('"' == *lpCommandLine) + { + /* got a dquote; skip over it if it's escaped; make sure we + don't try to look before the first character in the + string */ + if(lpCommandLine > stringstart && '\\' == lpCommandLine[-1]) + { + lpCommandLine++; + continue; + } + + /* found beginning of dquoted sequence, run to the end */ + /* don't stop if we hit an escaped dquote */ + lpCommandLine++; + while( *lpCommandLine ) + { + lpCommandLine = PAL_wcschr(lpCommandLine, '"'); + if(NULL == lpCommandLine) + { + /* no ending dquote, arg runs to end of string */ + break; + } + if('\\' != lpCommandLine[-1]) + { + /* dquote is not escaped, dquoted sequence is over*/ + break; + } + lpCommandLine++; + } + if(NULL == lpCommandLine || '\0' == *lpCommandLine) + { + /* no terminating dquote */ + break; + } + + /* step over dquote, keep looking for end of arg */ + lpCommandLine++; + } + else + { + /* found whitespace : end of arg. */ + lpCommandLine++; + break; + } + }while(lpCommandLine); + } + + /* Convert to ASCII */ + if (lpCommandLine) + { + if (!WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, + pChar, iWlen+1, NULL, NULL)) + { + ASSERT("Unable to convert to a multibyte string\n"); + free(lpAsciiCmdLine); + return NULL; + } + } + + pChar = lpAsciiCmdLine; + + /* loops through all the arguments, to find out how many arguments there + are; while looping replace whitespace by \0 */ + + /* skip leading whitespace (and replace by '\0') */ + /* note : there shouldn't be any, command starts either with PE loader name + or computed application path, but this won't hurt */ + while (*pChar) + { + if (!isspace((unsigned char) *pChar)) + { + break; + } + WARN("unexpected whitespace in command line!\n"); + *pChar++ = '\0'; + } + + while (*pChar) + { + (*pnArg)++; + + /* find end of current arg */ + while(*pChar && !isspace((unsigned char) *pChar)) + { + if('"' == *pChar) + { + /* skip over dquote if it's escaped; make sure we don't try to + look before the start of the string for the \ */ + if(pChar > lpAsciiCmdLine && '\\' == pChar[-1]) + { + pChar++; + continue; + } + + /* found leading dquote : look for ending dquote */ + pChar++; + while (*pChar) + { + pChar = strchr(pChar,'"'); + if(NULL == pChar) + { + /* no ending dquote found : argument extends to the end + of the string*/ + break; + } + if('\\' != pChar[-1]) + { + /* found a dquote, and it's not escaped : quoted + sequence is over*/ + break; + } + /* found a dquote, but it was escaped : skip over it, keep + looking */ + pChar++; + } + if(NULL == pChar || '\0' == *pChar) + { + /* reached the end of the string : we're done */ + break; + } + } + pChar++; + } + if(NULL == pChar) + { + /* reached the end of the string : we're done */ + break; + } + /* reached end of arg; replace trailing whitespace by '\0', to split + arguments into separate strings */ + while (isspace((unsigned char) *pChar)) + { + *pChar++ = '\0'; + } + } + + /* allocate lppargv according to the number of arguments + in the command line */ + lppArgv = (char **) InternalMalloc((((*pnArg)+1) * sizeof(char *))); + + if (lppArgv == NULL) + { + free(lpAsciiCmdLine); + return NULL; + } + + lppTemp = lppArgv; + + /* at this point all parameters are separated by NULL + we need to fill the array of arguments; we must also remove all dquotes + from arguments (new process shouldn't see them) */ + for (i = *pnArg, pChar = lpAsciiCmdLine; i; i--) + { + /* skip NULLs */ + while (!*pChar) + { + pChar++; + } + + *lppTemp = pChar; + + /* go to the next parameter, removing dquotes as we go along */ + j = 0; + while (*pChar) + { + /* copy character if it's not a dquote */ + if('"' != *pChar) + { + /* if it's the \ of an escaped dquote, skip over it, we'll + copy the " instead */ + if( '\\' == pChar[0] && '"' == pChar[1] ) + { + pChar++; + } + (*lppTemp)[j++] = *pChar; + } + pChar++; + } + /* re-NULL terminate the argument */ + (*lppTemp)[j] = '\0'; + + lppTemp++; + } + + *lppTemp = NULL; + + return lppArgv; +} + + +/*++ +Function: + getPath + +Abstract: + Helper function for CreateProcessW, it looks in the path environment + variable to find where the process to executed is. + +Parameters: + IN lpFileName: file name to search in the path + OUT lpPathFileName: returned string containing the path and the filename + +Return: + TRUE if found + FALSE otherwise +--*/ +static +BOOL +getPath( + PathCharString& lpFileNameString, + PathCharString& lpPathFileName) +{ + LPSTR lpPath; + LPSTR lpNext; + LPSTR lpCurrent; + LPWSTR lpwstr; + INT n; + INT nextLen; + INT slashLen; + CPalThread *pThread = NULL; + LPCSTR lpFileName = lpFileNameString.GetString(); + + /* if a path is specified, only look there */ + if(strchr(lpFileName, '/')) + { + if (access (lpFileName, F_OK) == 0) + { + if (!lpPathFileName.Set(lpFileNameString)) + { + TRACE("Set of StackString failed!\n"); + return FALSE; + } + + TRACE("file %s exists\n", lpFileName); + return TRUE; + } + else + { + TRACE("file %s doesn't exist.\n", lpFileName); + return FALSE; + } + } + + /* first look in directory from which the application loaded */ + lpwstr = g_lpwstrAppDir; + + if (lpwstr) + { + /* convert path to multibyte, check buffer size */ + n = WideCharToMultiByte(CP_ACP, 0, lpwstr, -1, NULL, 0, + NULL, NULL); + + if (!lpPathFileName.Reserve(n + lpFileNameString.GetCount() + 1 )) + { + ERROR("StackString Reserve failed!\n"); + return FALSE; + } + + lpPath = lpPathFileName.OpenStringBuffer(n); + + n = WideCharToMultiByte(CP_ACP, 0, lpwstr, -1, lpPath, n, + NULL, NULL); + + if (n == 0) + { + lpPathFileName.CloseBuffer(0); + ASSERT("WideCharToMultiByte failure!\n"); + return FALSE; + } + + lpPathFileName.CloseBuffer(n - 1); + + lpPathFileName.Append("/", 1); + lpPathFileName.Append(lpFileNameString); + + if (access(lpPathFileName, F_OK) == 0) + { + TRACE("found %s in application directory (%s)\n", lpFileName, lpPathFileName.GetString()); + return TRUE; + } + } + + /* then try the current directory */ + if (!lpPathFileName.Reserve(lpFileNameString.GetCount() + 2)) + { + ERROR("StackString Reserve failed!\n"); + return FALSE; + } + + lpPathFileName.Set("./", 2); + lpPathFileName.Append(lpFileNameString); + + if (access (lpPathFileName, R_OK) == 0) + { + TRACE("found %s in current directory.\n", lpFileName); + return TRUE; + } + + pThread = InternalGetCurrentThread(); + + /* Then try to look in the path */ + lpPath = EnvironGetenv("PATH"); + + if (!lpPath) + { + ERROR("EnvironGetenv returned NULL for $PATH\n"); + return FALSE; + } + + lpNext = lpPath; + + /* search in every path directory */ + TRACE("looking for file %s in $PATH (%s)\n", lpFileName, lpPath); + while (lpNext) + { + /* skip all leading ':' */ + while(*lpNext==':') + { + lpNext++; + } + + /* search for ':' */ + lpCurrent = strchr(lpNext, ':'); + if (lpCurrent) + { + *lpCurrent++ = '\0'; + } + + nextLen = strlen(lpNext); + slashLen = (lpNext[nextLen-1] == '/') ? 0:1; + + if (!lpPathFileName.Reserve(nextLen + lpFileNameString.GetCount() + 1)) + { + free(lpPath); + ERROR("StackString ran out of memory for full path\n"); + return FALSE; + } + + lpPathFileName.Set(lpNext, nextLen); + + if( slashLen == 1) + { + /* append a '/' if there's no '/' at the end of the path */ + lpPathFileName.Append("/", 1); + } + + lpPathFileName.Append(lpFileNameString); + + if ( access (lpPathFileName, F_OK) == 0) + { + TRACE("Found %s in $PATH element %s\n", lpFileName, lpNext); + free(lpPath); + return TRUE; + } + + lpNext = lpCurrent; /* search in the next directory */ + } + + free(lpPath); + TRACE("File %s not found in $PATH\n", lpFileName); + return FALSE; +} + +/*++ +Function: + ~CProcProcessLocalData + +Process data destructor +--*/ +CorUnix::CProcProcessLocalData::~CProcProcessLocalData() +{ + if (pProcessModules != NULL) + { + DestroyProcessModules(pProcessModules); + } +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/procprivate.hpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/procprivate.hpp new file mode 100644 index 0000000..a1d085d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/procprivate.hpp @@ -0,0 +1,78 @@ +// 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: + + thread/procprivate.hpp + +Abstract: + + Private process structures and routines + +Revision History: + + + +--*/ + +#ifndef _PAL_PROCPRIVATE_HPP_ +#define _PAL_PROCPRIVATE_HPP_ + +#include "pal/thread.hpp" + +namespace CorUnix +{ + + /*++ + Function: + PROCAddThread + + Abstract + Add a thread to the thread list of the current process + --*/ + void PROCAddThread(CPalThread *pCurrentThread, CPalThread *pTargetThread); + + extern CPalThread *pGThreadList; + + /*++ + Function: + PROCRemoveThread + + Abstract + Remove a thread form the thread list of the current process + --*/ + void PROCRemoveThread(CPalThread *pCurrentThread, CPalThread *pTargetThread); + + /*++ + Function: + PROCGetNumberOfThreads + + Abstract + Return the number of threads in the thread list. + --*/ + INT PROCGetNumberOfThreads(void); + + + /*++ + Function: + TerminateCurrentProcessNoExit + + Parameters: + BOOL bTerminateUnconditionally - If this is set, the PAL will exit as + quickly as possible. In particular, it will not unload DLLs. + + Abstract: + Terminate Current Process, but leave the caller alive + --*/ + void TerminateCurrentProcessNoExit(BOOL bTerminateUnconditionally); + +} + +#endif //_PAL_PROCPRIVATE_HPP_ + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/thread.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/thread.cpp new file mode 100644 index 0000000..a6a14c2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/thread.cpp @@ -0,0 +1,2971 @@ +// 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: + + thread.cpp + +Abstract: + + Thread object and core APIs + + + +--*/ + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(THREAD); // some headers have code with asserts, so do this first + +#include "pal/corunix.hpp" +#include "pal/context.h" +#include "pal/thread.hpp" +#include "pal/mutex.hpp" +#include "pal/handlemgr.hpp" +#include "pal/cs.hpp" +#include "pal/seh.hpp" +#include "pal/signal.hpp" + +#include "procprivate.hpp" +#include "pal/process.h" +#include "pal/module.h" +#include "pal/environ.h" +#include "pal/init.h" +#include "pal/utils.h" +#include "pal/virtual.h" + +#if defined(__NetBSD__) && !HAVE_PTHREAD_GETCPUCLOCKID +#include +#include +#include +#include +#endif + +#include +#include +#if HAVE_PTHREAD_NP_H +#include +#endif +#include +#include +#include +#include +#include +#if HAVE_MACH_THREADS +#include +#endif // HAVE_MACH_THREADS +#if HAVE_POLL +#include +#else +#include "pal/fakepoll.h" +#endif // HAVE_POLL +#include +#include + +#if HAVE_SYS_LWP_H +#include +#endif +#if HAVE_LWP_H +#include +#endif +// If we don't have sys/lwp.h but do expect to use _lwp_self, declare it to silence compiler warnings +#if HAVE__LWP_SELF && !HAVE_SYS_LWP_H && !HAVE_LWP_H +extern "C" int _lwp_self (); +#endif + +#if HAVE_CPUSET_T +typedef cpuset_t cpu_set_t; +#endif + +using namespace CorUnix; + + +/* ------------------- Definitions ------------------------------*/ + +// Activation function that gets called when an activation is injected into a thread. +PAL_ActivationFunction g_activationFunction = NULL; +// Function to check if an activation can be safely injected at a specified context +PAL_SafeActivationCheckFunction g_safeActivationCheckFunction = NULL; + +void +ThreadCleanupRoutine( + CPalThread *pThread, + IPalObject *pObjectToCleanup, + bool fShutdown, + bool fCleanupSharedState + ); + +PAL_ERROR +ThreadInitializationRoutine( + CPalThread *pThread, + CObjectType *pObjectType, + void *pImmutableData, + void *pSharedData, + void *pProcessLocalData + ); + +CObjectType CorUnix::otThread( + otiThread, + ThreadCleanupRoutine, + ThreadInitializationRoutine, + 0, // sizeof(CThreadImmutableData), + NULL, // No immutable data copy routine + NULL, // No immutable data cleanup routine + sizeof(CThreadProcessLocalData), + NULL, // No process local data cleanup routine + 0, // sizeof(CThreadSharedData), + 0, // THREAD_ALL_ACCESS, + CObjectType::SecuritySupported, + CObjectType::SecurityInfoNotPersisted, + CObjectType::UnnamedObject, + CObjectType::LocalDuplicationOnly, + CObjectType::WaitableObject, + CObjectType::SingleTransitionObject, + CObjectType::ThreadReleaseHasNoSideEffects, + CObjectType::NoOwner + ); + +CAllowedObjectTypes aotThread(otiThread); + +/*++ +Function: + InternalEndCurrentThreadWrapper + + Destructor for the thread-specific data representing the current PAL thread. + Called from pthread_exit. (pthread_exit is not called from the thread on which + main() was first invoked. This is not a problem, though, since when main() + returns, this results in an implicit call to exit().) + + arg: the PAL thread +*/ +static void InternalEndCurrentThreadWrapper(void *arg) +{ + CPalThread *pThread = (CPalThread *) arg; + + // When pthread_exit calls us, it has already removed the PAL thread + // from TLS. Since InternalEndCurrentThread calls functions that assert + // that the current thread is known to this PAL, and that pThread + // actually is the current PAL thread, put it back in TLS temporarily. + pthread_setspecific(thObjKey, pThread); + + /* Call entry point functions of every attached modules to + indicate the thread is exiting */ + /* note : no need to enter a critical section for serialization, the loader + will lock its own critical section */ + LOADCallDllMain(DLL_THREAD_DETACH, NULL); + +#if !HAVE_MACH_EXCEPTIONS + pThread->FreeSignalAlternateStack(); +#endif // !HAVE_MACH_EXCEPTIONS + + // PAL_Leave will be called just before we release the thread reference + // in InternalEndCurrentThread. + InternalEndCurrentThread(pThread); + pthread_setspecific(thObjKey, NULL); +} + +/*++ +Function: + TLSInitialize + + Initialize the TLS subsystem +--*/ +BOOL TLSInitialize() +{ + /* Create the pthread key for thread objects, which we use + for fast access to the current thread object. */ + if (pthread_key_create(&thObjKey, InternalEndCurrentThreadWrapper)) + { + ERROR("Couldn't create the thread object key\n"); + return FALSE; + } + + return TRUE; +} + +/*++ +Function: + TLSCleanup + + Shutdown the TLS subsystem +--*/ +VOID TLSCleanup() +{ + pthread_key_delete(thObjKey); +} + +/*++ +Function: + AllocTHREAD + +Abstract: + Allocate CPalThread instance + +Return: + The fresh thread structure, NULL otherwise +--*/ +CPalThread* AllocTHREAD() +{ + return InternalNew(); +} + +/*++ +Function: + FreeTHREAD + +Abstract: + Free THREAD structure + +--*/ +static void FreeTHREAD(CPalThread *pThread) +{ + // + // Run the destructors for this object + // + + pThread->~CPalThread(); + +#ifdef _DEBUG + // Fill value so we can find code re-using threads after they're dead. We + // check against pThread->dwGuard when getting the current thread's data. + memset((void*)pThread, 0xcc, sizeof(*pThread)); +#endif + + free(pThread); +} + + +/*++ +Function: + THREADGetThreadProcessId + +returns the process owner ID of the indicated hThread +--*/ +DWORD +THREADGetThreadProcessId( + HANDLE hThread + // UNIXTODO Should take pThread parameter here (modify callers) + ) +{ + CPalThread *pThread; + CPalThread *pTargetThread; + IPalObject *pobjThread = NULL; + PAL_ERROR palError = NO_ERROR; + + DWORD dwProcessId = 0; + + pThread = InternalGetCurrentThread(); + + palError = InternalGetThreadDataFromHandle( + pThread, + hThread, + &pTargetThread, + &pobjThread + ); + + if (NO_ERROR != palError) + { + if (!pThread->IsDummy()) + { + dwProcessId = GetCurrentProcessId(); + } + else + { + ASSERT("Dummy thread passed to THREADGetProcessId\n"); + } + + if (NULL != pobjThread) + { + pobjThread->ReleaseReference(pThread); + } + } + else + { + ERROR("Couldn't retrieve the hThread:%p pid owner !\n", hThread); + } + + + return dwProcessId; +} + +/*++ +Function: + GetCurrentThreadId + +See MSDN doc. +--*/ +DWORD +PALAPI +GetCurrentThreadId( + VOID) +{ + DWORD dwThreadId; + + PERF_ENTRY(GetCurrentThreadId); + ENTRY("GetCurrentThreadId()\n"); + + // + // TODO: should do perf test to see how this compares + // with calling InternalGetCurrentThread (i.e., is our lookaside + // cache faster on average than pthread_self?) + // + + dwThreadId = (DWORD)THREADSilentGetCurrentThreadId(); + + LOGEXIT("GetCurrentThreadId returns DWORD %#x\n", dwThreadId); + PERF_EXIT(GetCurrentThreadId); + + return dwThreadId; +} + +/*++ +Function: + PAL_GetCurrentOSThreadId + +Returns the current thread's OS thread ID. +This API is functionally equivalent to GetCurrentThreadId, but does not truncate the return value to 32-bits. +This is needed to ensure that we can provide the correct OS thread ID on platforms such as OSX that have a 64-bit thread ID. +--*/ +size_t +PALAPI +PAL_GetCurrentOSThreadId( + VOID) +{ + size_t threadId; + + PERF_ENTRY(PAL_GetCurrentOSThreadId); + ENTRY("PAL_GetCurrentOSThreadId()\n"); + + threadId = THREADSilentGetCurrentThreadId(); + + LOGEXIT("PAL_GetCurrentOSThreadId returns %p\n", threadId); + PERF_EXIT(GetCurrentThreadId); + + return threadId; +} + + +/*++ +Function: + GetCurrentThread + +See MSDN doc. +--*/ +HANDLE +PALAPI +PAL_GetCurrentThread( + VOID) +{ + PERF_ENTRY(GetCurrentThread); + ENTRY("GetCurrentThread()\n"); + + LOGEXIT("GetCurrentThread returns HANDLE %p\n", hPseudoCurrentThread); + PERF_EXIT(GetCurrentThread); + + /* return a pseudo handle */ + return (HANDLE) hPseudoCurrentThread; +} + +/*++ +Function: + SwitchToThread + +See MSDN doc. +--*/ +BOOL +PALAPI +SwitchToThread( + VOID) +{ + BOOL ret; + + PERF_ENTRY(SwitchToThread); + ENTRY("SwitchToThread(VOID)\n"); + + /* sched_yield yields to another thread in the current process. This implementation + won't work well for cross-process synchronization. */ + ret = (sched_yield() == 0); + + LOGEXIT("SwitchToThread returns BOOL %d\n", ret); + PERF_EXIT(SwitchToThread); + + return ret; +} + +/*++ +Function: + CreateThread + +Note: + lpThreadAttributes could be ignored. + +See MSDN doc. + +--*/ +HANDLE +PALAPI +CreateThread( + IN LPSECURITY_ATTRIBUTES lpThreadAttributes, + IN DWORD dwStackSize, + IN LPTHREAD_START_ROUTINE lpStartAddress, + IN LPVOID lpParameter, + IN DWORD dwCreationFlags, + OUT LPDWORD lpThreadId) +{ + PAL_ERROR palError; + CPalThread *pThread; + HANDLE hNewThread = NULL; + + PERF_ENTRY(CreateThread); + ENTRY("CreateThread(lpThreadAttr=%p, dwStackSize=%u, lpStartAddress=%p, " + "lpParameter=%p, dwFlags=%#x, lpThreadId=%#x)\n", + lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, + dwCreationFlags, lpThreadId); + + pThread = InternalGetCurrentThread(); + SIZE_T osThreadId = 0; + palError = InternalCreateThread( + pThread, + lpThreadAttributes, + dwStackSize, + lpStartAddress, + lpParameter, + dwCreationFlags, + UserCreatedThread, + &osThreadId, + &hNewThread + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + if(lpThreadId != nullptr) + { + *lpThreadId = (DWORD)osThreadId; + } + LOGEXIT("CreateThread returns HANDLE %p\n", hNewThread); + PERF_EXIT(CreateThread); + + return hNewThread; +} + +/*++ +Function: + PAL_CreateThread64 + Similar to CreateThread but passes out a 64 bit thread id on platforms which use one. + +Note: + lpThreadAttributes could be ignored. + +See MSDN doc. + +--*/ +HANDLE +PALAPI +PAL_CreateThread64( + IN LPSECURITY_ATTRIBUTES lpThreadAttributes, + IN DWORD dwStackSize, + IN LPTHREAD_START_ROUTINE lpStartAddress, + IN LPVOID lpParameter, + IN DWORD dwCreationFlags, + OUT SIZE_T* pThreadId) +{ + PAL_ERROR palError; + CPalThread *pThread; + HANDLE hNewThread = NULL; + + PERF_ENTRY(PAL_CreateThread64); + ENTRY("PAL_CreateThread64(lpThreadAttr=%p, dwStackSize=%u, lpStartAddress=%p, " + "lpParameter=%p, dwFlags=%#x, pThreadId=%p)\n", + lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, + dwCreationFlags, pThreadId); + + pThread = InternalGetCurrentThread(); + palError = InternalCreateThread( + pThread, + lpThreadAttributes, + dwStackSize, + lpStartAddress, + lpParameter, + dwCreationFlags, + UserCreatedThread, + pThreadId, + &hNewThread + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("PAL_CreateThread64 returns HANDLE %p\n", hNewThread); + PERF_EXIT(PAL_CreateThread64); + + return hNewThread; +} + +PAL_ERROR +CorUnix::InternalCreateThread( + CPalThread *pThread, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + DWORD dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + PalThreadType eThreadType, + SIZE_T* pThreadId, + HANDLE *phThread + ) +{ + PAL_ERROR palError; + CPalThread *pNewThread = NULL; + CObjectAttributes oa; + bool fAttributesInitialized = FALSE; + bool fThreadDataAddedToProcessList = FALSE; + HANDLE hNewThread = NULL; + + pthread_t pthread; + pthread_attr_t pthreadAttr; + size_t pthreadStackSize; +#if PTHREAD_CREATE_MODIFIES_ERRNO + int storedErrno; +#endif // PTHREAD_CREATE_MODIFIES_ERRNO + BOOL fHoldingProcessLock = FALSE; + int iError = 0; + size_t alignedStackSize; + + if (0 != terminator) + { + // + // Since the PAL is in the middle of shutting down we don't want to + // create any new threads (since it's possible for that new thread + // to create another thread before the shutdown thread gets around + // to suspending it, and so on). We don't want to return an error + // here, though, as some programs (in particular, build) do not + // handle CreateThread errors properly -- instead, we just put + // the calling thread to sleep (unless it is the shutdown thread, + // which could occur if a DllMain PROCESS_DETACH handler tried to + // create a new thread for some odd reason). + // + + ERROR("process is terminating, can't create new thread.\n"); + + if (pThread->GetThreadId() != static_cast(terminator)) + { + while (true) + { + poll(NULL, 0, INFTIM); + sched_yield(); + } + } + else + { + // + // This is the shutdown thread, so just return an error + // + + palError = ERROR_PROCESS_ABORTED; + goto EXIT; + } + } + + /* Validate parameters */ + + if (lpThreadAttributes != NULL) + { + ASSERT("lpThreadAttributes parameter must be NULL (%p)\n", + lpThreadAttributes); + palError = ERROR_INVALID_PARAMETER; + goto EXIT; + } + + alignedStackSize = dwStackSize; + if (alignedStackSize != 0) + { + // Some systems require the stack size to be aligned to the page size + if (sizeof(alignedStackSize) <= sizeof(dwStackSize) && alignedStackSize + (GetVirtualPageSize() - 1) < alignedStackSize) + { + // When coming here from the public API surface, the incoming value is originally a nonnegative signed int32, so + // this shouldn't happen + ASSERT( + "Couldn't align the requested stack size (%Iu) to the page size because the stack size was too large\n", + alignedStackSize); + palError = ERROR_INVALID_PARAMETER; + goto EXIT; + } + alignedStackSize = ALIGN_UP(alignedStackSize, GetVirtualPageSize()); + } + + // Ignore the STACK_SIZE_PARAM_IS_A_RESERVATION flag + dwCreationFlags &= ~STACK_SIZE_PARAM_IS_A_RESERVATION; + + if ((dwCreationFlags != 0) && (dwCreationFlags != CREATE_SUSPENDED)) + { + ASSERT("dwCreationFlags parameter is invalid (%#x)\n", dwCreationFlags); + palError = ERROR_INVALID_PARAMETER; + goto EXIT; + } + + // + // Create the CPalThread for the thread + // + + pNewThread = AllocTHREAD(); + if (NULL == pNewThread) + { + palError = ERROR_OUTOFMEMORY; + goto EXIT; + } + + palError = pNewThread->RunPreCreateInitializers(); + if (NO_ERROR != palError) + { + goto EXIT; + } + + pNewThread->m_lpStartAddress = lpStartAddress; + pNewThread->m_lpStartParameter = lpParameter; + pNewThread->m_bCreateSuspended = (dwCreationFlags & CREATE_SUSPENDED) == CREATE_SUSPENDED; + pNewThread->m_eThreadType = eThreadType; + + if (0 != pthread_attr_init(&pthreadAttr)) + { + ERROR("couldn't initialize pthread attributes\n"); + palError = ERROR_INTERNAL_ERROR; + goto EXIT; + } + + fAttributesInitialized = TRUE; + + if (alignedStackSize == 0) + { + // The thread is to be created with default stack size. Use the default stack size + // override that was determined during the PAL initialization. + alignedStackSize = g_defaultStackSize; + } + + /* adjust the stack size if necessary */ + if (alignedStackSize != 0) + { +#ifdef PTHREAD_STACK_MIN + size_t MinStackSize = ALIGN_UP(PTHREAD_STACK_MIN, GetVirtualPageSize()); +#else // !PTHREAD_STACK_MIN + size_t MinStackSize = 64 * 1024; // this value is typically accepted by pthread_attr_setstacksize() +#endif // PTHREAD_STACK_MIN + if (alignedStackSize < MinStackSize) + { + // Adjust the stack size to a minimum value that is likely to be accepted by pthread_attr_setstacksize(). If this + // function fails, typically the caller will end up throwing OutOfMemoryException under the assumption that the + // requested stack size is too large or the system does not have sufficient memory to create a thread. Try to + // prevent failing just just because the stack size value is too low. + alignedStackSize = MinStackSize; + } + + TRACE("setting thread stack size to %Iu\n", alignedStackSize); + if (0 != pthread_attr_setstacksize(&pthreadAttr, alignedStackSize)) + { + ERROR("couldn't set pthread stack size to %Iu\n", alignedStackSize); + palError = ERROR_INTERNAL_ERROR; + goto EXIT; + } + } + else + { + TRACE("using the system default thread stack size\n"); + } + +#if HAVE_THREAD_SELF || HAVE__LWP_SELF + /* Create new threads as "bound", so each pthread is permanently bound + to an LWP. Get/SetThreadContext() depend on this 1:1 mapping. */ + pthread_attr_setscope(&pthreadAttr, PTHREAD_SCOPE_SYSTEM); +#endif // HAVE_THREAD_SELF || HAVE__LWP_SELF + + // + // We never call pthread_join, so create the new thread as detached + // + + iError = pthread_attr_setdetachstate(&pthreadAttr, PTHREAD_CREATE_DETACHED); + _ASSERTE(0 == iError); + + // + // Create the IPalObject for the thread and store it in the object + // + + palError = CreateThreadObject( + pThread, + pNewThread, + &hNewThread); + + if (NO_ERROR != palError) + { + goto EXIT; + } + + // + // Add the thread to the process list + // + + // + // We use the process lock to ensure that we're not interrupted + // during the creation process. After adding the CPalThread reference + // to the process list, we want to make sure the actual thread has been + // started. Otherwise, there's a window where the thread can be found + // in the process list but doesn't yet exist in the system. + // + + PROCProcessLock(); + fHoldingProcessLock = TRUE; + + PROCAddThread(pThread, pNewThread); + fThreadDataAddedToProcessList = TRUE; + + // + // Spawn the new pthread + // + +#if PTHREAD_CREATE_MODIFIES_ERRNO + storedErrno = errno; +#endif // PTHREAD_CREATE_MODIFIES_ERRNO + +#if HAVE_PTHREAD_ATTR_SETAFFINITY_NP && HAVE_SCHED_GETAFFINITY + { + // Threads inherit their parent's affinity mask on Linux. This is not desired, so we reset + // the current thread's affinity mask to the mask of the current process. + cpu_set_t cpuSet; + CPU_ZERO(&cpuSet); + + int st = sched_getaffinity(gPID, sizeof(cpu_set_t), &cpuSet); + if (st != 0) + { + ASSERT("sched_getaffinity failed!\n"); + // the sched_getaffinity should never fail for getting affinity of the current process + palError = ERROR_INTERNAL_ERROR; + goto EXIT; + } + + st = pthread_attr_setaffinity_np(&pthreadAttr, sizeof(cpu_set_t), &cpuSet); + if (st != 0) + { + if (st == ENOMEM) + { + palError = ERROR_NOT_ENOUGH_MEMORY; + } + else + { + ASSERT("pthread_attr_setaffinity_np failed!\n"); + // The pthread_attr_setaffinity_np should never fail except of OOM when + // passed the mask extracted using sched_getaffinity. + palError = ERROR_INTERNAL_ERROR; + } + goto EXIT; + } + } +#endif // HAVE_PTHREAD_GETAFFINITY_NP && HAVE_SCHED_GETAFFINITY + + iError = pthread_create(&pthread, &pthreadAttr, CPalThread::ThreadEntry, pNewThread); + +#if PTHREAD_CREATE_MODIFIES_ERRNO + if (iError == 0) + { + // Restore errno if pthread_create succeeded. + errno = storedErrno; + } +#endif // PTHREAD_CREATE_MODIFIES_ERRNO + + if (0 != iError) + { + ERROR("pthread_create failed, error is %d (%s)\n", iError, strerror(iError)); + palError = ERROR_NOT_ENOUGH_MEMORY; + goto EXIT; + } + + // + // Wait for the new thread to finish its initial startup tasks + // (i.e., the ones that might fail) + // + if (pNewThread->WaitForStartStatus()) + { + // + // Everything succeeded. Store the handle for the new thread and + // the thread's ID in the out params + // + *phThread = hNewThread; + + if (NULL != pThreadId) + { + *pThreadId = pNewThread->GetThreadId(); + } + } + else + { + ERROR("error occurred in THREADEntry, thread creation failed.\n"); + palError = ERROR_INTERNAL_ERROR; + goto EXIT; + } + + // + // If we're here, then we've locked the process list and both pthread_create + // and WaitForStartStatus succeeded. Thus, we can now unlock the process list. + // Since palError == NO_ERROR, we won't call this again in the exit block. + // + PROCProcessUnlock(); + fHoldingProcessLock = FALSE; + +EXIT: + + if (fAttributesInitialized) + { + if (0 != pthread_attr_destroy(&pthreadAttr)) + { + WARN("pthread_attr_destroy() failed\n"); + } + } + + if (NO_ERROR != palError) + { + // + // We either were not able to create the new thread, or a failure + // occurred in the new thread's entry routine. Free up the associated + // resources here + // + + if (fThreadDataAddedToProcessList) + { + PROCRemoveThread(pThread, pNewThread); + } + // + // Once we remove the thread from the process list, we can call + // PROCProcessUnlock. + // + if (fHoldingProcessLock) + { + PROCProcessUnlock(); + } + fHoldingProcessLock = FALSE; + } + + _ASSERT_MSG(!fHoldingProcessLock, "Exiting InternalCreateThread while still holding the process critical section.\n"); + + return palError; +} + + + +/*++ +Function: + ExitThread + +See MSDN doc. +--*/ +PAL_NORETURN +VOID +PALAPI +ExitThread( + IN DWORD dwExitCode) +{ + CPalThread *pThread; + + ENTRY("ExitThread(dwExitCode=%u)\n", dwExitCode); + PERF_ENTRY_ONLY(ExitThread); + + pThread = InternalGetCurrentThread(); + + /* store the exit code */ + pThread->SetExitCode(dwExitCode); + + /* kill the thread (itself), resulting in a call to InternalEndCurrentThread */ + pthread_exit(NULL); + + ASSERT("pthread_exit should not return!\n"); + for (;;); +} + +/*++ +Function: + InternalEndCurrentThread + +Does any necessary memory clean up, signals waiting threads, and then forces +the current thread to exit. +--*/ + +VOID +CorUnix::InternalEndCurrentThread( + CPalThread *pThread + ) +{ + PAL_ERROR palError = NO_ERROR; + ISynchStateController *pSynchStateController = NULL; + +#ifdef PAL_PERF + PERFDisableThreadProfile(UserCreatedThread != pThread->GetThreadType()); +#endif + + // + // Abandon any objects owned by this thread + // + + palError = g_pSynchronizationManager->AbandonObjectsOwnedByThread( + pThread, + pThread + ); + + if (NO_ERROR != palError) + { + ERROR("Failure abandoning owned objects"); + } + + // + // Need to synchronize setting the thread state to TS_DONE since + // this is checked for in InternalSuspendThreadFromData. + // TODO: Is this still needed after removing InternalSuspendThreadFromData? + // + + pThread->suspensionInfo.AcquireSuspensionLock(pThread); + pThread->synchronizationInfo.SetThreadState(TS_DONE); + pThread->suspensionInfo.ReleaseSuspensionLock(pThread); + + // + // Mark the thread object as signaled + // + + palError = pThread->GetThreadObject()->GetSynchStateController( + pThread, + &pSynchStateController + ); + + if (NO_ERROR == palError) + { + palError = pSynchStateController->SetSignalCount(1); + if (NO_ERROR != palError) + { + ASSERT("Unable to mark thread object as signaled"); + } + + pSynchStateController->ReleaseController(); + } + else + { + ASSERT("Unable to obtain state controller for thread"); + } + + // + // Add a reference to the thread data before releasing the + // thread object, so we can still use it + // + + pThread->AddThreadReference(); + + // + // Release the reference to the IPalObject for this thread + // + + pThread->GetThreadObject()->ReleaseReference(pThread); + + /* Remove thread for the thread list of the process + (don't do if this is the last thread -> gets handled by + TerminateProcess->PROCCleanupProcess->PROCTerminateOtherThreads) */ + + PROCRemoveThread(pThread, pThread); + + // Ensure that EH is disabled on the current thread + SEHDisable(pThread); + + // + // Now release our reference to the thread data. We cannot touch + // it after this point + // + + pThread->ReleaseThreadReference(); +} + +/*++ +Function: + GetThreadPriority + +See MSDN doc. +--*/ +int +PALAPI +GetThreadPriority( + IN HANDLE hThread) +{ + CPalThread *pThread; + PAL_ERROR palError; + int iPriority = THREAD_PRIORITY_ERROR_RETURN; + + PERF_ENTRY(GetThreadPriority); + ENTRY("GetThreadPriority(hThread=%p)\n", hThread); + + pThread = InternalGetCurrentThread(); + + palError = InternalGetThreadPriority( + pThread, + hThread, + &iPriority + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("GetThreadPriorityExit returns int %d\n", iPriority); + PERF_EXIT(GetThreadPriority); + + return iPriority; +} + +PAL_ERROR +CorUnix::InternalGetThreadPriority( + CPalThread *pThread, + HANDLE hThread, + int *piPriority + ) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pTargetThread; + IPalObject *pobjThread = NULL; + + palError = InternalGetThreadDataFromHandle( + pThread, + hThread, + &pTargetThread, + &pobjThread + ); + + if (NO_ERROR != palError) + { + goto InternalGetThreadPriorityExit; + } + + pTargetThread->Lock(pThread); + + *piPriority = pTargetThread->GetThreadPriority(); + + pTargetThread->Unlock(pThread); + +InternalGetThreadPriorityExit: + + if (NULL != pobjThread) + { + pobjThread->ReleaseReference(pThread); + } + + return palError; +} + + +/*++ +Function: + SetThreadPriority + +See MSDN doc. +--*/ +BOOL +PALAPI +SetThreadPriority( + IN HANDLE hThread, + IN int nPriority) +{ + CPalThread *pThread; + PAL_ERROR palError = NO_ERROR; + + PERF_ENTRY(SetThreadPriority); + ENTRY("SetThreadPriority(hThread=%p, nPriority=%#x)\n", hThread, nPriority); + + pThread = InternalGetCurrentThread(); + + palError = InternalSetThreadPriority( + pThread, + hThread, + nPriority + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("SetThreadPriority returns BOOL %d\n", NO_ERROR == palError); + PERF_EXIT(SetThreadPriority); + + return NO_ERROR == palError; +} + +PAL_ERROR +CorUnix::InternalSetThreadPriority( + CPalThread *pThread, + HANDLE hTargetThread, + int iNewPriority + ) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pTargetThread = NULL; + IPalObject *pobjThread = NULL; + + int st; + int policy; + struct sched_param schedParam; + int max_priority; + int min_priority; + float posix_priority; + + + palError = InternalGetThreadDataFromHandle( + pThread, + hTargetThread, + &pTargetThread, + &pobjThread + ); + + if (NO_ERROR != palError) + { + goto InternalSetThreadPriorityExit; + } + + pTargetThread->Lock(pThread); + + /* validate the requested priority */ + switch (iNewPriority) + { + case THREAD_PRIORITY_TIME_CRITICAL: /* fall through */ + case THREAD_PRIORITY_IDLE: + break; + + case THREAD_PRIORITY_HIGHEST: /* fall through */ + case THREAD_PRIORITY_ABOVE_NORMAL: /* fall through */ + case THREAD_PRIORITY_NORMAL: /* fall through */ + case THREAD_PRIORITY_BELOW_NORMAL: /* fall through */ + case THREAD_PRIORITY_LOWEST: +#if PAL_IGNORE_NORMAL_THREAD_PRIORITY + /* We aren't going to set the thread priority. Just record what it is, + and exit */ + pTargetThread->m_iThreadPriority = iNewPriority; + goto InternalSetThreadPriorityExit; +#endif + break; + + default: + ASSERT("Priority %d not supported\n", iNewPriority); + palError = ERROR_INVALID_PARAMETER; + goto InternalSetThreadPriorityExit; + } + + /* check if the thread is still running */ + if (TS_DONE == pTargetThread->synchronizationInfo.GetThreadState()) + { + /* the thread has exited, set the priority in the thread structure + and exit */ + pTargetThread->m_iThreadPriority = iNewPriority; + goto InternalSetThreadPriorityExit; + } + + /* get the previous thread schedule parameters. We need to know the + scheduling policy to determine the priority range */ + if (pthread_getschedparam( + pTargetThread->GetPThreadSelf(), + &policy, + &schedParam + ) != 0) + { + ASSERT("Unable to get current thread scheduling information\n"); + palError = ERROR_INTERNAL_ERROR; + goto InternalSetThreadPriorityExit; + } + +#if !HAVE_SCHED_OTHER_ASSIGNABLE + /* Defining thread priority for SCHED_OTHER is implementation defined. + Some platforms like NetBSD cannot reassign it as they are dynamic. + */ + if (policy == SCHED_OTHER) + { + TRACE("Pthread priority levels for SCHED_OTHER cannot be reassigned on this platform\n"); + goto InternalSetThreadPriorityExit; + } +#endif + +#if HAVE_SCHED_GET_PRIORITY + max_priority = sched_get_priority_max(policy); + min_priority = sched_get_priority_min(policy); + if( -1 == max_priority || -1 == min_priority) + { + ASSERT("sched_get_priority_min/max failed; error is %d (%s)\n", + errno, strerror(errno)); + palError = ERROR_INTERNAL_ERROR; + goto InternalSetThreadPriorityExit; + } +#else + max_priority = PAL_THREAD_PRIORITY_MAX; + min_priority = PAL_THREAD_PRIORITY_MIN; +#endif + + TRACE("Pthread priorities for policy %d must be in the range %d to %d\n", + policy, min_priority, max_priority); + + /* explanation for fancy maths below : + POSIX doesn't specify the range of thread priorities that can be used + with pthread_setschedparam. Instead, one must use sched_get_priority_min + and sched_get_priority_max to obtain the lower and upper bounds of this + range. Since the PAL also uses a range of values (from Idle [-15] to + Time Critical [+15]), we have to do a mapping from a known range to an + unknown (at compilation) range. + We do this by : + -substracting the minimal PAL priority from the desired priority. this + gives a value between 0 and the PAL priority range + -dividing this value by the PAL priority range. this allows us to + express the desired priority as a floating-point value between 0 and 1 + -multiplying this value by the PTHREAD priority range. This gives a + value between 0 and the PTHREAD priority range + -adding the minimal PTHREAD priority range. This will give us a value + between the minimal and maximla pthread priority, which should be + equivalent to the original PAL value. + + example : suppose a pthread range 100 to 200, and a desired priority + of 0 (halfway between PAL minimum and maximum) + 0 - (IDLE [-15]) = 15 + 15 / (TIMECRITICAL[15] - IDLE[-15]) = 0.5 + 0.5 * (pthreadmax[200]-pthreadmin[100]) = 50 + 50 + pthreadmin[100] = 150 -> halfway between pthread min and max + */ + posix_priority = (iNewPriority - THREAD_PRIORITY_IDLE); + posix_priority /= (THREAD_PRIORITY_TIME_CRITICAL - THREAD_PRIORITY_IDLE); + posix_priority *= (max_priority-min_priority); + posix_priority += min_priority; + + schedParam.sched_priority = (int)posix_priority; + + TRACE("PAL priority %d is mapped to pthread priority %d\n", + iNewPriority, schedParam.sched_priority); + + /* Finally, set the new priority into place */ + st = pthread_setschedparam(pTargetThread->GetPThreadSelf(), policy, &schedParam); + if (st != 0) + { +#if SET_SCHEDPARAM_NEEDS_PRIVS + if (EPERM == st) + { + // UNIXTODO: Should log a warning to the event log + TRACE("Caller does not have OS privileges to call pthread_setschedparam\n"); + pTargetThread->m_iThreadPriority = iNewPriority; + goto InternalSetThreadPriorityExit; + } +#endif + + ASSERT("Unable to set thread priority to %d (error %d)\n", (int)posix_priority, st); + palError = ERROR_INTERNAL_ERROR; + goto InternalSetThreadPriorityExit; + } + + pTargetThread->m_iThreadPriority = iNewPriority; + +InternalSetThreadPriorityExit: + + if (NULL != pTargetThread) + { + pTargetThread->Unlock(pThread); + } + + if (NULL != pobjThread) + { + pobjThread->ReleaseReference(pThread); + } + + return palError; +} + +BOOL +CorUnix::GetThreadTimesInternal( + IN HANDLE hThread, + OUT LPFILETIME lpKernelTime, + OUT LPFILETIME lpUserTime) +{ + __int64 calcTime; + BOOL retval = FALSE; + const __int64 SECS_TO_NS = 1000000000; /* 10^9 */ + const __int64 USECS_TO_NS = 1000; /* 10^3 */ + +#if HAVE_MACH_THREADS + thread_basic_info resUsage; + PAL_ERROR palError = NO_ERROR; + CPalThread *pthrCurrent = NULL; + CPalThread *pthrTarget = NULL; + IPalObject *pobjThread = NULL; + mach_msg_type_number_t resUsage_count = THREAD_BASIC_INFO_COUNT; + + pthrCurrent = InternalGetCurrentThread(); + palError = InternalGetThreadDataFromHandle( + pthrCurrent, + hThread, + &pthrTarget, + &pobjThread + ); + + if (palError != NO_ERROR) + { + ASSERT("Unable to get thread data from handle %p" + "thread\n", hThread); + SetLastError(ERROR_INTERNAL_ERROR); + goto SetTimesToZero; + } + + pthrTarget->Lock(pthrCurrent); + + mach_port_t mhThread; + mhThread = pthread_mach_thread_np(pthrTarget->GetPThreadSelf()); + + kern_return_t status; + status = thread_info( + mhThread, + THREAD_BASIC_INFO, + (thread_info_t)&resUsage, + &resUsage_count); + + pthrTarget->Unlock(pthrCurrent); + + if (status != KERN_SUCCESS) + { + ASSERT("Unable to get resource usage information for the current " + "thread\n"); + SetLastError(ERROR_INTERNAL_ERROR); + goto SetTimesToZero; + } + + /* Get the time of user mode execution, in nanoseconds */ + calcTime = (__int64)resUsage.user_time.seconds * SECS_TO_NS; + calcTime += (__int64)resUsage.user_time.microseconds * USECS_TO_NS; + /* Assign the time into lpUserTime */ + lpUserTime->dwLowDateTime = (DWORD)calcTime; + lpUserTime->dwHighDateTime = (DWORD)(calcTime >> 32); + + /* Get the time of kernel mode execution, in nanoseconds */ + calcTime = (__int64)resUsage.system_time.seconds * SECS_TO_NS; + calcTime += (__int64)resUsage.system_time.microseconds * USECS_TO_NS; + /* Assign the time into lpKernelTime */ + lpKernelTime->dwLowDateTime = (DWORD)calcTime; + lpKernelTime->dwHighDateTime = (DWORD)(calcTime >> 32); + + retval = TRUE; + + goto GetThreadTimesInternalExit; + +#elif defined(__NetBSD__) && !HAVE_PTHREAD_GETCPUCLOCKID /* Currently unimplemented */ + + PAL_ERROR palError; + CPalThread *pThread; + CPalThread *pTargetThread; + IPalObject *pobjThread = NULL; + kvm_t *kd; + int cnt, nlwps; + struct kinfo_lwp *klwp; + int i; + bool found = false; + + pThread = InternalGetCurrentThread(); + + palError = InternalGetThreadDataFromHandle( + pThread, + hThread, + &pTargetThread, + &pobjThread + ); + if (palError != NO_ERROR) + { + ASSERT("Unable to get thread data from handle %p" + "thread\n", hThread); + SetLastError(ERROR_INTERNAL_ERROR); + goto SetTimesToZero; + } + + kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open"); + if (kd == NULL) + { + ASSERT("kvm_open(3) error"); + SetLastError(ERROR_INTERNAL_ERROR); + goto SetTimesToZero; + } + + pTargetThread->Lock(pThread); + + klwp = kvm_getlwps(kd, getpid(), 0, sizeof(struct kinfo_lwp), &nlwps); + if (klwp == NULL || nlwps < 1) + { + kvm_close(kd); + ASSERT("Unable to get clock from %p thread\n", hThread); + SetLastError(ERROR_INTERNAL_ERROR); + pTargetThread->Unlock(pThread); + goto SetTimesToZero; + } + + for (i = 0; i < nlwps; i++) + { + if (klwp[i].l_lid == THREADSilentGetCurrentThreadId()) + { + found = true; + break; + } + } + + if (!found) + { + kvm_close(kd); + ASSERT("Unable to get clock from %p thread\n", hThread); + SetLastError(ERROR_INTERNAL_ERROR); + pTargetThread->Unlock(pThread); + goto SetTimesToZero; + } + + pTargetThread->Unlock(pThread); + + kvm_close(kd); + + calcTime = (__int64) klwp[i].l_rtime_sec * SECS_TO_NS; + calcTime += (__int64) klwp[i].l_rtime_usec * USECS_TO_NS; + lpUserTime->dwLowDateTime = (DWORD)calcTime; + lpUserTime->dwHighDateTime = (DWORD)(calcTime >> 32); + + /* NetBSD as of (7.0) doesn't differentiate used time in user/kernel for lwp */ + lpKernelTime->dwLowDateTime = 0; + lpKernelTime->dwHighDateTime = 0; + + retval = TRUE; + goto GetThreadTimesInternalExit; + +#else //HAVE_MACH_THREADS + + PAL_ERROR palError; + CPalThread *pThread; + CPalThread *pTargetThread; + IPalObject *pobjThread = NULL; + clockid_t cid; + + pThread = InternalGetCurrentThread(); + + palError = InternalGetThreadDataFromHandle( + pThread, + hThread, + &pTargetThread, + &pobjThread + ); + if (palError != NO_ERROR) + { + ASSERT("Unable to get thread data from handle %p" + "thread\n", hThread); + SetLastError(ERROR_INTERNAL_ERROR); + goto SetTimesToZero; + } + + pTargetThread->Lock(pThread); + +#if HAVE_PTHREAD_GETCPUCLOCKID + if (pthread_getcpuclockid(pTargetThread->GetPThreadSelf(), &cid) != 0) +#endif + { + ASSERT("Unable to get clock from thread\n", hThread); + SetLastError(ERROR_INTERNAL_ERROR); + pTargetThread->Unlock(pThread); + goto SetTimesToZero; + } + + struct timespec ts; + if (clock_gettime(cid, &ts) != 0) + { + ASSERT("clock_gettime() failed; errno is %d (%s)\n", errno, strerror(errno)); + SetLastError(ERROR_INTERNAL_ERROR); + pTargetThread->Unlock(pThread); + goto SetTimesToZero; + } + + pTargetThread->Unlock(pThread); + + /* Calculate time in nanoseconds and assign to user time */ + calcTime = (__int64) ts.tv_sec * SECS_TO_NS; + calcTime += (__int64) ts.tv_nsec; + lpUserTime->dwLowDateTime = (DWORD)calcTime; + lpUserTime->dwHighDateTime = (DWORD)(calcTime >> 32); + + /* Set kernel time to zero, for now */ + lpKernelTime->dwLowDateTime = 0; + lpKernelTime->dwHighDateTime = 0; + + retval = TRUE; + goto GetThreadTimesInternalExit; + +#endif //HAVE_MACH_THREADS + +SetTimesToZero: + + lpUserTime->dwLowDateTime = 0; + lpUserTime->dwHighDateTime = 0; + lpKernelTime->dwLowDateTime = 0; + lpKernelTime->dwHighDateTime = 0; + goto GetThreadTimesInternalExit; + +GetThreadTimesInternalExit: + return retval; +} + +/*++ +Function: + GetThreadTimes + +See MSDN doc. +--*/ +BOOL +PALAPI +GetThreadTimes( + IN HANDLE hThread, + OUT LPFILETIME lpCreationTime, + OUT LPFILETIME lpExitTime, + OUT LPFILETIME lpKernelTime, + OUT LPFILETIME lpUserTime) +{ + PERF_ENTRY(GetThreadTimes); + ENTRY("GetThreadTimes(hThread=%p, lpExitTime=%p, lpKernelTime=%p," + "lpUserTime=%p)\n", + hThread, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime ); + + FILETIME KernelTime, UserTime; + + BOOL retval = GetThreadTimesInternal(hThread, &KernelTime, &UserTime); + + /* Not sure if this still needs to be here */ + /* + TRACE ("thread_info User: %ld sec,%ld microsec. Kernel: %ld sec,%ld" + " microsec\n", + resUsage.user_time.seconds, resUsage.user_time.microseconds, + resUsage.system_time.seconds, resUsage.system_time.microseconds); + */ + + __int64 calcTime; + if (lpUserTime) + { + /* Produce the time in 100s of ns */ + calcTime = ((ULONG64)UserTime.dwHighDateTime << 32); + calcTime += (ULONG64)UserTime.dwLowDateTime; + calcTime /= 100; + lpUserTime->dwLowDateTime = (DWORD)calcTime; + lpUserTime->dwHighDateTime = (DWORD)(calcTime >> 32); + } + if (lpKernelTime) + { + /* Produce the time in 100s of ns */ + calcTime = ((ULONG64)KernelTime.dwHighDateTime << 32); + calcTime += (ULONG64)KernelTime.dwLowDateTime; + calcTime /= 100; + lpKernelTime->dwLowDateTime = (DWORD)calcTime; + lpKernelTime->dwHighDateTime = (DWORD)(calcTime >> 32); + } + //Set CreationTime and Exit time to zero for now - maybe change this later? + if (lpCreationTime) + { + lpCreationTime->dwLowDateTime = 0; + lpCreationTime->dwHighDateTime = 0; + } + + if (lpExitTime) + { + lpExitTime->dwLowDateTime = 0; + lpExitTime->dwHighDateTime = 0; + } + + LOGEXIT("GetThreadTimes returns BOOL %d\n", retval); + PERF_EXIT(GetThreadTimes); + return (retval); +} + +HRESULT +PALAPI +SetThreadDescription( + IN HANDLE hThread, + IN PCWSTR lpThreadDescription) +{ + CPalThread *pThread; + PAL_ERROR palError; + + PERF_ENTRY(SetThreadDescription); + ENTRY("SetThreadDescription(hThread=%p,lpThreadDescription=%p)\n", hThread, lpThreadDescription); + + pThread = InternalGetCurrentThread(); + + palError = InternalSetThreadDescription( + pThread, + hThread, + lpThreadDescription + ); + + if (NO_ERROR != palError) + { + pThread->SetLastError(palError); + } + + LOGEXIT("SetThreadDescription"); + PERF_EXIT(SetThreadDescription); + + return HRESULT_FROM_WIN32(palError); +} + +PAL_ERROR +CorUnix::InternalSetThreadDescription( + CPalThread *pThread, + HANDLE hTargetThread, + PCWSTR lpThreadDescription +) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pTargetThread = NULL; + IPalObject *pobjThread = NULL; + int error; + int nameSize; + char *nameBuf = NULL; + +// The exact API of pthread_setname_np varies very wildly depending on OS. +// For now, only Linux is implemented. +#if defined(__linux__) + + palError = InternalGetThreadDataFromHandle( + pThread, + hTargetThread, + &pTargetThread, + &pobjThread + ); + + if (NO_ERROR != palError) + { + goto InternalSetThreadDescriptionExit; + } + + pTargetThread->Lock(pThread); + + /* translate the wide char lpThreadDescription string to multibyte string */ + nameSize = WideCharToMultiByte(CP_ACP, 0, lpThreadDescription, -1, NULL, 0, NULL, NULL); + + if (0 == nameSize) + { + palError = ERROR_INTERNAL_ERROR; + goto InternalSetThreadDescriptionExit; + } + + nameBuf = (char *)PAL_malloc(nameSize); + if (nameBuf == NULL) + { + palError = ERROR_OUTOFMEMORY; + goto InternalSetThreadDescriptionExit; + } + + if (WideCharToMultiByte(CP_ACP, 0, lpThreadDescription, -1, nameBuf, nameSize, NULL, + NULL) != nameSize) + { + palError = ERROR_INTERNAL_ERROR; + goto InternalSetThreadDescriptionExit; + } + + // Null terminate early. + // pthread_setname_np only accepts up to 16 chars. + if (nameSize > 15) + { + nameBuf[15] = '\0'; + } + + error = pthread_setname_np(pTargetThread->GetPThreadSelf(), nameBuf); + + if (error != 0) + { + palError = ERROR_INTERNAL_ERROR; + } + +InternalSetThreadDescriptionExit: + + if (NULL != pTargetThread) + { + pTargetThread->Unlock(pThread); + } + + if (NULL != pobjThread) + { + pobjThread->ReleaseReference(pThread); + } + + if (NULL != nameBuf) { + PAL_free(nameBuf); + } + +#endif // defined(__linux__) + + return palError; +} + +void * +CPalThread::ThreadEntry( + void *pvParam + ) +{ + PAL_ERROR palError; + CPalThread *pThread; + PTHREAD_START_ROUTINE pfnStartRoutine; + LPVOID pvPar; + DWORD retValue; + + pThread = reinterpret_cast(pvParam); + + if (NULL == pThread) + { + ASSERT("THREAD pointer is NULL!\n"); + goto fail; + } + +#if !HAVE_MACH_EXCEPTIONS + if (!pThread->EnsureSignalAlternateStack()) + { + ASSERT("Cannot allocate alternate stack for SIGSEGV!\n"); + goto fail; + } +#endif // !HAVE_MACH_EXCEPTIONS + + pThread->m_threadId = THREADSilentGetCurrentThreadId(); + pThread->m_pthreadSelf = pthread_self(); +#if HAVE_MACH_THREADS + pThread->m_machPortSelf = pthread_mach_thread_np(pThread->m_pthreadSelf); +#endif +#if HAVE_THREAD_SELF + pThread->m_dwLwpId = (DWORD) thread_self(); +#elif HAVE__LWP_SELF + pThread->m_dwLwpId = (DWORD) _lwp_self(); +#else + pThread->m_dwLwpId = 0; +#endif + + palError = pThread->RunPostCreateInitializers(); + if (NO_ERROR != palError) + { + ASSERT("Error %i initializing thread data (post creation)\n", palError); + goto fail; + } + + // Check if the thread should be started suspended. + if (pThread->GetCreateSuspended()) + { + palError = pThread->suspensionInfo.InternalSuspendNewThreadFromData(pThread); + if (NO_ERROR != palError) + { + ASSERT("Error %i attempting to suspend new thread\n", palError); + goto fail; + } + + // + // We need to run any APCs that have already been queued for + // this thread. + // + + (void) g_pSynchronizationManager->DispatchPendingAPCs(pThread); + } + else + { + // + // All startup operations that might have failed have succeeded, + // so thread creation is successful. Let CreateThread return. + // + + pThread->SetStartStatus(TRUE); + } + + pThread->synchronizationInfo.SetThreadState(TS_RUNNING); + + if (UserCreatedThread == pThread->GetThreadType()) + { + /* Inform all loaded modules that a thread has been created */ + /* note : no need to take a critical section to serialize here; the loader + will take the module critical section */ + LOADCallDllMain(DLL_THREAD_ATTACH, NULL); + } + +#ifdef PAL_PERF + PERFAllocThreadInfo(); + PERFEnableThreadProfile(UserCreatedThread != pThread->GetThreadType()); +#endif + + /* call the startup routine */ + pfnStartRoutine = pThread->GetStartAddress(); + pvPar = pThread->GetStartParameter(); + + retValue = (*pfnStartRoutine)(pvPar); + + TRACE("Thread exited (%u)\n", retValue); + pThread->SetExitCode(retValue); + + return NULL; + +fail: + + // + // Notify InternalCreateThread that a failure occurred + // + + if (NULL != pThread) + { + pThread->synchronizationInfo.SetThreadState(TS_FAILED); + pThread->SetStartStatus(FALSE); + } + + /* do not call ExitThread : we don't want to call DllMain(), and the thread + isn't in a clean state (e.g. lpThread isn't in TLS). the cleanup work + above should release all resources */ + return NULL; +} + +/*++ +Function: + CreateThreadData + +Abstract: + Create the CPalThread for the startup thread + or another external thread entering the PAL + for the first time + +Parameters: + ppThread - on success, receives the CPalThread + +Return: + PAL_ERROR +--*/ + +PAL_ERROR +CorUnix::CreateThreadData( + CPalThread **ppThread + ) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pThread = NULL; + + /* Create the thread object */ + pThread = AllocTHREAD(); + + if (NULL == pThread) + { + palError = ERROR_OUTOFMEMORY; + goto CreateThreadDataExit; + } + + palError = pThread->RunPreCreateInitializers(); + + if (NO_ERROR != palError) + { + goto CreateThreadDataExit; + } + + pThread->SetLastError(0); + + pThread->m_threadId = THREADSilentGetCurrentThreadId(); + pThread->m_pthreadSelf = pthread_self(); +#if HAVE_MACH_THREADS + pThread->m_machPortSelf = pthread_mach_thread_np(pThread->m_pthreadSelf); +#endif +#if HAVE_THREAD_SELF + pThread->m_dwLwpId = (DWORD) thread_self(); +#elif HAVE__LWP_SELF + pThread->m_dwLwpId = (DWORD) _lwp_self(); +#else + pThread->m_dwLwpId = 0; +#endif + + palError = pThread->RunPostCreateInitializers(); + if (NO_ERROR != palError) + { + goto CreateThreadDataExit; + } + + *ppThread = pThread; + +CreateThreadDataExit: + + if (NO_ERROR != palError) + { + if (NULL != pThread) + { + pThread->ReleaseThreadReference(); + } + } + + return palError; +} + +/*++ +Function: + CreateThreadData + +Abstract: + Creates the IPalObject for a thread, storing + the reference in the CPalThread + +Parameters: + pThread - the thread data for the creating thread + pNewThread - the thread data for the thread being initialized + +Return: + PAL_ERROR +--*/ + +PAL_ERROR +CorUnix::CreateThreadObject( + CPalThread *pThread, + CPalThread *pNewThread, + HANDLE *phThread + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pobjThread = NULL; + IDataLock *pDataLock; + HANDLE hThread = NULL; + CThreadProcessLocalData *pLocalData = NULL; + CObjectAttributes oa; + BOOL fThreadDataStoredInObject = FALSE; + IPalObject *pobjRegisteredThread = NULL; + + // + // Create the IPalObject for the thread + // + + palError = g_pObjectManager->AllocateObject( + pThread, + &otThread, + &oa, + &pobjThread + ); + + if (NO_ERROR != palError) + { + goto CreateThreadObjectExit; + } + + // + // Store the CPalThread inside of the IPalObject + // + + palError = pobjThread->GetProcessLocalData( + pThread, + WriteLock, + &pDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + goto CreateThreadObjectExit; + } + + pLocalData->pThread = pNewThread; + pDataLock->ReleaseLock(pThread, TRUE); + fThreadDataStoredInObject = TRUE; + + // + // Register the IPalObject (obtaining a handle) + // + + palError = g_pObjectManager->RegisterObject( + pThread, + pobjThread, + &aotThread, + &hThread, + &pobjRegisteredThread + ); + + // + // pobjThread is invalidated by the call to RegisterObject, so NULL + // it out here to prevent it from being released + // + + pobjThread = NULL; + + if (NO_ERROR != palError) + { + goto CreateThreadObjectExit; + } + + // + // Store the registered object inside of the thread object, + // adding a reference for the thread itself + // + + pNewThread->m_pThreadObject = pobjRegisteredThread; + pNewThread->m_pThreadObject->AddReference(); + + *phThread = hThread; + +CreateThreadObjectExit: + + if (NO_ERROR != palError) + { + if (NULL != hThread) + { + g_pObjectManager->RevokeHandle(pThread, hThread); + } + + if (NULL != pNewThread->m_pThreadObject) + { + // + // Release the new thread's reference on the underlying thread + // object + // + + pNewThread->m_pThreadObject->ReleaseReference(pThread); + } + + if (!fThreadDataStoredInObject) + { + // + // The CPalThread for the new thread was never stored in + // an IPalObject instance, so we need to release the initial + // reference here. (If it has been stored it will get freed in + // the owning object's cleanup routine) + // + + pNewThread->ReleaseThreadReference(); + } + } + + if (NULL != pobjThread) + { + pobjThread->ReleaseReference(pThread); + } + + if (NULL != pobjRegisteredThread) + { + pobjRegisteredThread->ReleaseReference(pThread); + } + + return palError; +} + +PAL_ERROR +CorUnix::InternalCreateDummyThread( + CPalThread *pThread, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + CPalThread **ppDummyThread, + HANDLE *phThread + ) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pDummyThread = NULL; + IPalObject *pobjThread = NULL; + IPalObject *pobjThreadRegistered = NULL; + IDataLock *pDataLock; + CThreadProcessLocalData *pLocalData; + CObjectAttributes oa(NULL, lpThreadAttributes); + bool fThreadDataStoredInObject = FALSE; + + pDummyThread = AllocTHREAD(); + if (NULL == pDummyThread) + { + palError = ERROR_OUTOFMEMORY; + goto InternalCreateDummyThreadExit; + } + + pDummyThread->m_fIsDummy = TRUE; + + palError = g_pObjectManager->AllocateObject( + pThread, + &otThread, + &oa, + &pobjThread + ); + + if (NO_ERROR != palError) + { + goto InternalCreateDummyThreadExit; + } + + palError = pobjThread->GetProcessLocalData( + pThread, + WriteLock, + &pDataLock, + reinterpret_cast(&pLocalData) + ); + + if (NO_ERROR != palError) + { + goto InternalCreateDummyThreadExit; + } + + pLocalData->pThread = pDummyThread; + pDataLock->ReleaseLock(pThread, TRUE); + fThreadDataStoredInObject = TRUE; + + palError = g_pObjectManager->RegisterObject( + pThread, + pobjThread, + &aotThread, + phThread, + &pobjThreadRegistered + ); + + // + // pobjThread is invalidated by the above call, so NULL + // it out here + // + + pobjThread = NULL; + + if (NO_ERROR != palError) + { + goto InternalCreateDummyThreadExit; + } + + // + // Note the we do NOT store the registered object for the + // thread w/in pDummyThread. Since this thread is not actually + // executing that reference would never be released (and thus + // the thread object would never be cleaned up...) + // + + *ppDummyThread = pDummyThread; + +InternalCreateDummyThreadExit: + + if (NULL != pobjThreadRegistered) + { + pobjThreadRegistered->ReleaseReference(pThread); + } + + if (NULL != pobjThread) + { + pobjThread->ReleaseReference(pThread); + } + + if (NO_ERROR != palError + && NULL != pDummyThread + && !fThreadDataStoredInObject) + { + pDummyThread->ReleaseThreadReference(); + } + + return palError; +} + +PAL_ERROR +CorUnix::InternalGetThreadDataFromHandle( + CPalThread *pThread, + HANDLE hThread, + CPalThread **ppTargetThread, + IPalObject **ppobjThread + ) +{ + PAL_ERROR palError = NO_ERROR; + IPalObject *pobj; + IDataLock *pLock; + CThreadProcessLocalData *pData; + + *ppobjThread = NULL; + + if (hPseudoCurrentThread == hThread) + { + *ppTargetThread = pThread; + } + else + { + palError = g_pObjectManager->ReferenceObjectByHandle( + pThread, + hThread, + &aotThread, + &pobj + ); + + if (NO_ERROR == palError) + { + palError = pobj->GetProcessLocalData( + pThread, + ReadLock, + &pLock, + reinterpret_cast(&pData) + ); + + if (NO_ERROR == palError) + { + *ppTargetThread = pData->pThread; + pLock->ReleaseLock(pThread, FALSE); + + // + // Transfer object reference to out param + // + + *ppobjThread = pobj; + } + else + { + pobj->ReleaseReference(pThread); + } + } + } + + return palError; +} + +PAL_ERROR +CPalThread::RunPreCreateInitializers( + void + ) +{ + PAL_ERROR palError = NO_ERROR; + int iError; + + // + // First, perform initialization of CPalThread private members + // + + InternalInitializeCriticalSection(&m_csLock); + m_fLockInitialized = TRUE; + + iError = pthread_mutex_init(&m_startMutex, NULL); + if (0 != iError) + { + goto RunPreCreateInitializersExit; + } + + iError = pthread_cond_init(&m_startCond, NULL); + if (0 != iError) + { + pthread_mutex_destroy(&m_startMutex); + goto RunPreCreateInitializersExit; + } + + m_fStartItemsInitialized = TRUE; + + // + // Call the pre-create initializers for embedded classes + // + + palError = synchronizationInfo.InitializePreCreate(); + if (NO_ERROR != palError) + { + goto RunPreCreateInitializersExit; + } + + palError = suspensionInfo.InitializePreCreate(); + if (NO_ERROR != palError) + { + goto RunPreCreateInitializersExit; + } + + palError = apcInfo.InitializePreCreate(); + if (NO_ERROR != palError) + { + goto RunPreCreateInitializersExit; + } + + palError = crtInfo.InitializePreCreate(); + if (NO_ERROR != palError) + { + goto RunPreCreateInitializersExit; + } + +RunPreCreateInitializersExit: + + return palError; +} + +CPalThread::~CPalThread() +{ + // @UNIXTODO: This is our last chance to unlink our Mach exception handler from the pseudo-chain we're trying + // to maintain. Unfortunately we don't have enough data or control to do this at all well (and we can't + // guarantee that another component hasn't chained to us, about which we can do nothing). If the kernel or + // another component forwards an exception notification to us for this thread things will go badly (we'll + // terminate the process when trying to look up this CPalThread in order to find forwarding information). + // On the flip side I don't believe we'll get here currently unless the thread has been terminated (in + // which case it's not an issue). If we start supporting unload or early disposal of CPalThread objects + // (say when we return from an outer reverse p/invoke) then we'll need to revisit this. But hopefully by + // then we'll have an alternative design for handling hardware exceptions. + + if (m_fLockInitialized) + { + InternalDeleteCriticalSection(&m_csLock); + } + + if (m_fStartItemsInitialized) + { + int iError; + + iError = pthread_cond_destroy(&m_startCond); + _ASSERTE(0 == iError); + + iError = pthread_mutex_destroy(&m_startMutex); + _ASSERTE(0 == iError); + } +} + +void +CPalThread::AddThreadReference( + void + ) +{ + InterlockedIncrement(&m_lRefCount); +} + +void +CPalThread::ReleaseThreadReference( + void + ) +{ + LONG lRefCount = InterlockedDecrement(&m_lRefCount); + _ASSERT_MSG(lRefCount >= 0, "Released a thread and ended with a negative refcount (%ld)\n", lRefCount); + if (0 == lRefCount) + { + FreeTHREAD(this); + } + +} + +PAL_ERROR +CPalThread::RunPostCreateInitializers( + void + ) +{ + PAL_ERROR palError = NO_ERROR; + + // + // Call the post-create initializers for embedded classes + // + + if (pthread_setspecific(thObjKey, reinterpret_cast(this))) + { + ASSERT("Unable to set the thread object key's value\n"); + palError = ERROR_INTERNAL_ERROR; + goto RunPostCreateInitializersExit; + } + + palError = synchronizationInfo.InitializePostCreate(this, m_threadId, m_dwLwpId); + if (NO_ERROR != palError) + { + goto RunPostCreateInitializersExit; + } + + palError = suspensionInfo.InitializePostCreate(this, m_threadId, m_dwLwpId); + if (NO_ERROR != palError) + { + goto RunPostCreateInitializersExit; + } + + palError = apcInfo.InitializePostCreate(this, m_threadId, m_dwLwpId); + if (NO_ERROR != palError) + { + goto RunPostCreateInitializersExit; + } + + palError = crtInfo.InitializePostCreate(this, m_threadId, m_dwLwpId); + if (NO_ERROR != palError) + { + goto RunPostCreateInitializersExit; + } + + palError = SEHEnable(this); + if (NO_ERROR != palError) + { + goto RunPostCreateInitializersExit; + } + +RunPostCreateInitializersExit: + + return palError; +} + +void +CPalThread::SetStartStatus( + bool fStartSucceeded + ) +{ + int iError; + +#if _DEBUG + if (m_fStartStatusSet) + { + ASSERT("Multiple calls to CPalThread::SetStartStatus\n"); + } +#endif + + // + // This routine may get called from CPalThread::ThreadEntry + // + // If we've reached this point there are no further thread + // suspensions that happen at creation time, so reset + // m_bCreateSuspended + // + + m_bCreateSuspended = FALSE; + + iError = pthread_mutex_lock(&m_startMutex); + if (0 != iError) + { + ASSERT("pthread primitive failure\n"); + // bugcheck? + } + + m_fStartStatus = fStartSucceeded; + m_fStartStatusSet = TRUE; + + iError = pthread_cond_signal(&m_startCond); + if (0 != iError) + { + ASSERT("pthread primitive failure\n"); + // bugcheck? + } + + iError = pthread_mutex_unlock(&m_startMutex); + if (0 != iError) + { + ASSERT("pthread primitive failure\n"); + // bugcheck? + } +} + +bool +CPalThread::WaitForStartStatus( + void + ) +{ + int iError; + + iError = pthread_mutex_lock(&m_startMutex); + if (0 != iError) + { + ASSERT("pthread primitive failure\n"); + // bugcheck? + } + + while (!m_fStartStatusSet) + { + iError = pthread_cond_wait(&m_startCond, &m_startMutex); + if (0 != iError) + { + ASSERT("pthread primitive failure\n"); + // bugcheck? + } + } + + iError = pthread_mutex_unlock(&m_startMutex); + if (0 != iError) + { + ASSERT("pthread primitive failure\n"); + // bugcheck? + } + + return m_fStartStatus; +} + +#if !HAVE_MACH_EXCEPTIONS +/*++ +Function : + EnsureSignalAlternateStack + + Ensure that alternate stack for signal handling is allocated for the current thread + +Parameters : + None + +Return : + TRUE in case of a success, FALSE otherwise +--*/ +BOOL +CPalThread::EnsureSignalAlternateStack() +{ + int st = 0; + + if (g_registered_signal_handlers) + { + stack_t oss; + + // Query the current alternate signal stack + st = sigaltstack(NULL, &oss); + if ((st == 0) && (oss.ss_flags == SS_DISABLE)) + { + // There is no alternate stack for SIGSEGV handling installed yet so allocate one + + // We include the size of the SignalHandlerWorkerReturnPoint in the alternate stack size since the + // context contained in it is large and the SIGSTKSZ was not sufficient on ARM64 during testing. + int altStackSize = SIGSTKSZ + ALIGN_UP(sizeof(SignalHandlerWorkerReturnPoint), 16) + GetVirtualPageSize(); +#ifdef HAS_ASAN + // Asan also uses alternate stack so we increase its size on the SIGSTKSZ * 4 that enough for asan + // (see kAltStackSize in compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc) + altStackSize += SIGSTKSZ * 4; +#endif + altStackSize = ALIGN_UP(altStackSize, GetVirtualPageSize()); + int flags = MAP_ANONYMOUS | MAP_PRIVATE; +#ifdef MAP_STACK + flags |= MAP_STACK; +#endif + void* altStack = mmap(NULL, altStackSize, PROT_READ | PROT_WRITE, flags, -1, 0); + if (altStack != MAP_FAILED) + { + // create a guard page for the alternate stack + st = mprotect(altStack, GetVirtualPageSize(), PROT_NONE); + if (st == 0) + { + stack_t ss; + ss.ss_sp = (char*)altStack; + ss.ss_size = altStackSize; + ss.ss_flags = 0; + st = sigaltstack(&ss, NULL); + } + + if (st == 0) + { + m_alternateStack = altStack; + } + else + { + int st2 = munmap(altStack, altStackSize); + _ASSERTE(st2 == 0); + } + } + } + } + + return (st == 0); +} + +/*++ +Function : + FreeSignalAlternateStack + + Free alternate stack for signal handling + +Parameters : + None + +Return : + None +--*/ +void +CPalThread::FreeSignalAlternateStack() +{ + void *altstack = m_alternateStack; + m_alternateStack = nullptr; + + if (altstack != nullptr) + { + stack_t ss, oss; + // The man page for sigaltstack says that when the ss.ss_flags is set to SS_DISABLE, + // all other ss fields are ignored. However, MUSL implementation checks that the + // ss_size is >= MINSIGSTKSZ even in this case. + ss.ss_size = MINSIGSTKSZ; + ss.ss_flags = SS_DISABLE; + int st = sigaltstack(&ss, &oss); + if ((st == 0) && (oss.ss_flags != SS_DISABLE)) + { + // Make sure this altstack is this PAL's before freeing. + if (oss.ss_sp == altstack) + { + int st = munmap(oss.ss_sp, oss.ss_size); + _ASSERTE(st == 0); + } + } + } +} + +#endif // !HAVE_MACH_EXCEPTIONS + +void +ThreadCleanupRoutine( + CPalThread *pThread, + IPalObject *pObjectToCleanup, + bool fShutdown, + bool fCleanupSharedState + ) +{ + CThreadProcessLocalData *pThreadData = NULL; + CPalThread *pThreadToCleanup = NULL; + IDataLock *pDataLock = NULL; + PAL_ERROR palError = NO_ERROR; + + // + // Free the CPalThread data for the passed in thread + // + + palError = pObjectToCleanup->GetProcessLocalData( + pThread, + WriteLock, + &pDataLock, + reinterpret_cast(&pThreadData) + ); + + if (NO_ERROR == palError) + { + // + // Note that we may be cleaning up the data for the calling + // thread (i.e., pThread == pThreadToCleanup), so the release + // of the thread reference needs to be the last thing that + // we do (though in that case it's very likely that the person + // calling us will be holding an extra reference to allow + // for the thread data to be available while the rest of the + // object cleanup takes place). + // + + pThreadToCleanup = pThreadData->pThread; + pThreadData->pThread = NULL; + pDataLock->ReleaseLock(pThread, TRUE); + pThreadToCleanup->ReleaseThreadReference(); + } + else + { + ASSERT("Unable to obtain thread data"); + } + +} + +PAL_ERROR +ThreadInitializationRoutine( + CPalThread *pThread, + CObjectType *pObjectType, + void *pImmutableData, + void *pSharedData, + void *pProcessLocalData + ) +{ + return NO_ERROR; +} + +// Get base address of the current thread's stack +void * +CPalThread::GetStackBase() +{ + void* stackBase; +#ifdef TARGET_OSX + // This is a Mac specific method + stackBase = pthread_get_stackaddr_np(pthread_self()); +#else + pthread_attr_t attr; + void* stackAddr; + size_t stackSize; + int status; + + pthread_t thread = pthread_self(); + + status = pthread_attr_init(&attr); + _ASSERT_MSG(status == 0, "pthread_attr_init call failed"); + +#if HAVE_PTHREAD_ATTR_GET_NP + status = pthread_attr_get_np(thread, &attr); +#elif HAVE_PTHREAD_GETATTR_NP + status = pthread_getattr_np(thread, &attr); +#else +#error Dont know how to get thread attributes on this platform! +#endif + _ASSERT_MSG(status == 0, "pthread_getattr_np call failed"); + + status = pthread_attr_getstack(&attr, &stackAddr, &stackSize); + _ASSERT_MSG(status == 0, "pthread_attr_getstack call failed"); + + status = pthread_attr_destroy(&attr); + _ASSERT_MSG(status == 0, "pthread_attr_destroy call failed"); + + stackBase = (void*)((size_t)stackAddr + stackSize); +#endif + + return stackBase; +} + +// Get limit address of the current thread's stack +void * +CPalThread::GetStackLimit() +{ + void* stackLimit; +#ifdef TARGET_OSX + // This is a Mac specific method + stackLimit = ((BYTE *)pthread_get_stackaddr_np(pthread_self()) - + pthread_get_stacksize_np(pthread_self())); +#else + pthread_attr_t attr; + size_t stackSize; + int status; + + pthread_t thread = pthread_self(); + + status = pthread_attr_init(&attr); + _ASSERT_MSG(status == 0, "pthread_attr_init call failed"); + +#if HAVE_PTHREAD_ATTR_GET_NP + status = pthread_attr_get_np(thread, &attr); +#elif HAVE_PTHREAD_GETATTR_NP + status = pthread_getattr_np(thread, &attr); +#else +#error Dont know how to get thread attributes on this platform! +#endif + _ASSERT_MSG(status == 0, "pthread_getattr_np call failed"); + + status = pthread_attr_getstack(&attr, &stackLimit, &stackSize); + _ASSERT_MSG(status == 0, "pthread_attr_getstack call failed"); + + status = pthread_attr_destroy(&attr); + _ASSERT_MSG(status == 0, "pthread_attr_destroy call failed"); +#endif + + return stackLimit; +} + +// Get cached base address of this thread's stack +// Can be called only for the current thread. +void * +CPalThread::GetCachedStackBase() +{ + _ASSERT_MSG(this == InternalGetCurrentThread(), "CPalThread::GetStackBase called from foreign thread"); + + if (m_stackBase == NULL) + { + m_stackBase = GetStackBase(); + } + + return m_stackBase; +} + +// Get cached limit address of this thread's stack. +// Can be called only for the current thread. +void * +CPalThread::GetCachedStackLimit() +{ + _ASSERT_MSG(this == InternalGetCurrentThread(), "CPalThread::GetCachedStackLimit called from foreign thread"); + + if (m_stackLimit == NULL) + { + m_stackLimit = GetStackLimit(); + } + + return m_stackLimit; +} + +PVOID +PALAPI +PAL_GetStackBase() +{ + CPalThread* thread = InternalGetCurrentThread(); + return thread->GetCachedStackBase(); +} + +PVOID +PALAPI +PAL_GetStackLimit() +{ + CPalThread* thread = InternalGetCurrentThread(); + return thread->GetCachedStackLimit(); +} + +PAL_ERROR InjectActivationInternal(CorUnix::CPalThread* pThread); + +/*++ +Function: + PAL_SetActivationFunction + + Register an activation function that gets called when an activation is injected + into a thread. + +Parameters: + pActivationFunction - activation function + pSafeActivationCheckFunction - function to check if an activation can be safely + injected at a specified context +Return value: + None +--*/ +PALIMPORT +VOID +PALAPI +PAL_SetActivationFunction( + IN PAL_ActivationFunction pActivationFunction, + IN PAL_SafeActivationCheckFunction pSafeActivationCheckFunction) +{ + g_activationFunction = pActivationFunction; + g_safeActivationCheckFunction = pSafeActivationCheckFunction; +} + +/*++ +Function: +PAL_InjectActivation + +Interrupt the specified thread and have it call an activation function registered +using the PAL_SetActivationFunction + +Parameters: +hThread - handle of the target thread + +Return: +TRUE if it succeeded, FALSE otherwise. +--*/ +BOOL +PALAPI +PAL_InjectActivation( + IN HANDLE hThread) +{ + PERF_ENTRY(PAL_InjectActivation); + ENTRY("PAL_InjectActivation(hThread=%p)\n", hThread); + + CPalThread *pCurrentThread; + CPalThread *pTargetThread; + IPalObject *pobjThread = NULL; + + pCurrentThread = InternalGetCurrentThread(); + + PAL_ERROR palError = InternalGetThreadDataFromHandle( + pCurrentThread, + hThread, + &pTargetThread, + &pobjThread + ); + + if (palError == NO_ERROR) + { + palError = InjectActivationInternal(pTargetThread); + } + + if (palError != NO_ERROR) + { + pCurrentThread->SetLastError(palError); + } + + if (pobjThread != NULL) + { + pobjThread->ReleaseReference(pCurrentThread); + } + + BOOL success = (palError == NO_ERROR); + LOGEXIT("PAL_InjectActivation returns:d\n", success); + PERF_EXIT(PAL_InjectActivation); + + return success; +} + +#if HAVE_MACH_EXCEPTIONS + +extern mach_port_t s_ExceptionPort; + +// Get handler details for a given type of exception. If successful the structure pointed at by pHandler is +// filled in and true is returned. Otherwise false is returned. +bool CorUnix::CThreadMachExceptionHandlers::GetHandler(exception_type_t eException, CorUnix::MachExceptionHandler *pHandler) +{ + exception_mask_t bmExceptionMask = (1 << eException); + int idxHandler = GetIndexOfHandler(bmExceptionMask); + + // Did we find a handler? + if (idxHandler == -1) + return false; + + // Found one, so initialize the output structure with the details. + pHandler->m_mask = m_masks[idxHandler]; + pHandler->m_handler = m_handlers[idxHandler]; + pHandler->m_behavior = m_behaviors[idxHandler]; + pHandler->m_flavor = m_flavors[idxHandler]; + + return true; +} + +// Look for a handler for the given exception within the given handler node. Return its index if successful or +// -1 otherwise. +int CorUnix::CThreadMachExceptionHandlers::GetIndexOfHandler(exception_mask_t bmExceptionMask) +{ + // Check all handler entries for one handling the exception mask. + for (mach_msg_type_number_t i = 0; i < m_nPorts; i++) + { + // Entry covers this exception type and the handler isn't null + if (m_masks[i] & bmExceptionMask && m_handlers[i] != MACH_PORT_NULL) + { + _ASSERTE(m_handlers[i] != s_ExceptionPort); + + // One more check; has the target handler port become dead? + mach_port_type_t ePortType; + if (mach_port_type(mach_task_self(), m_handlers[i], &ePortType) == KERN_SUCCESS && !(ePortType & MACH_PORT_TYPE_DEAD_NAME)) + { + // Got a matching entry. + return i; + } + } + } + + // Didn't find a handler. + return -1; +} + +#endif // HAVE_MACH_EXCEPTIONS + +/*++ +Function: + PAL_SetCurrentThreadAffinity + +Abstract + Set affinity of the current thread to the specified processor. + +Parameters: + procNo - number of the processor to affinitize the current thread to + +Return value: + TRUE if the function was able to set the affinity, FALSE if it has failed. +--*/ +BOOL +PALAPI +PAL_SetCurrentThreadAffinity(WORD procNo) +{ +#if HAVE_PTHREAD_GETAFFINITY_NP + cpu_set_t cpuSet; + CPU_ZERO(&cpuSet); + + CPU_SET(procNo, &cpuSet); + int st = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuSet); + + return st == 0; +#else // HAVE_PTHREAD_GETAFFINITY_NP + // There is no API to manage thread affinity, so let's ignore the request + return FALSE; +#endif // HAVE_PTHREAD_GETAFFINITY_NP +} + +/*++ +Function: + PAL_SetCurrentThreadAffinity + +Abstract + Get affinity set of the current thread. The set is represented by an array of "size" entries of UINT_PTR type. + +Parameters: + size - number of entries in the "data" array + data - pointer to the data of the resulting set, the LSB of the first entry in the array represents processor 0 + +Return value: + TRUE if the function was able to get the affinity set, FALSE if it has failed. +--*/ +BOOL +PALAPI +PAL_GetCurrentThreadAffinitySet(SIZE_T size, UINT_PTR* data) +{ +#if HAVE_PTHREAD_GETAFFINITY_NP + cpu_set_t cpuSet; + CPU_ZERO(&cpuSet); + + int st = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuSet); + + if (st == 0) + { + const SIZE_T BitsPerBitsetEntry = 8 * sizeof(UINT_PTR); + + // Get info for as much processors as it is possible to fit into the resulting set + SIZE_T remainingCount = std::min(size * BitsPerBitsetEntry, (SIZE_T)CPU_SETSIZE); + SIZE_T i = 0; + while (remainingCount != 0) + { + UINT_PTR entry = 0; + SIZE_T bitsToCopy = std::min(remainingCount, BitsPerBitsetEntry); + SIZE_T cpuSetOffset = i * BitsPerBitsetEntry; + for (SIZE_T j = 0; j < bitsToCopy; j++) + { + if (CPU_ISSET(cpuSetOffset + j, &cpuSet)) + { + entry |= (UINT_PTR)1 << j; + } + } + remainingCount -= bitsToCopy; + data[i++] = entry; + } + } + + return st == 0; +#else // HAVE_PTHREAD_GETAFFINITY_NP + // There is no API to manage thread affinity, so let's ignore the request + return FALSE; +#endif // HAVE_PTHREAD_GETAFFINITY_NP +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/threadsusp.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/threadsusp.cpp new file mode 100644 index 0000000..af22fc1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/src/thread/threadsusp.cpp @@ -0,0 +1,1045 @@ +// 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: + + threadsusp.cpp + +Abstract: + + Implementation of functions related to threads. + +Revision History: + + + +--*/ + +#include "pal/corunix.hpp" +#include "pal/thread.hpp" +#include "pal/mutex.hpp" +#include "pal/seh.hpp" +#include "pal/init.h" +#include "pal/dbgmsg.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace CorUnix; + +/* ------------------- Definitions ------------------------------*/ +SET_DEFAULT_DEBUG_CHANNEL(THREAD); + +/* This code is written to the blocking pipe of a thread that was created + in suspended state in order to resume it. */ +CONST BYTE WAKEUPCODE=0x2A; + +// #define USE_GLOBAL_LOCK_FOR_SUSPENSION // Uncomment this define to use the global suspension lock. +/* The global suspension lock can be used in place of each thread having its own +suspension mutex or spinlock. The downside is that it restricts us to only +performing one suspension or resumption in the PAL at a time. */ +#ifdef USE_GLOBAL_LOCK_FOR_SUSPENSION +static LONG g_ssSuspensionLock = 0; +#endif + +/*++ +Function: + InternalSuspendNewThreadFromData + + On platforms where we use pipes for starting threads suspended, this + function sets the blocking pipe for the thread and blocks until the + wakeup code is written to the pipe by ResumeThread. + +--*/ +PAL_ERROR +CThreadSuspensionInfo::InternalSuspendNewThreadFromData( + CPalThread *pThread + ) +{ + PAL_ERROR palError = NO_ERROR; + + AcquireSuspensionLock(pThread); + pThread->suspensionInfo.SetSelfSusp(TRUE); + ReleaseSuspensionLock(pThread); + + int pipe_descs[2]; + int pipeRv = +#if HAVE_PIPE2 + pipe2(pipe_descs, O_CLOEXEC); +#else + pipe(pipe_descs); +#endif // HAVE_PIPE2 + if (pipeRv == -1) + { + ERROR("pipe() failed! error is %d (%s)\n", errno, strerror(errno)); + return ERROR_NOT_ENOUGH_MEMORY; + } +#if !HAVE_PIPE2 + fcntl(pipe_descs[0], F_SETFD, FD_CLOEXEC); // make pipe non-inheritable, if possible + fcntl(pipe_descs[1], F_SETFD, FD_CLOEXEC); +#endif // !HAVE_PIPE2 + + // [0] is the read end of the pipe, and [1] is the write end. + pThread->suspensionInfo.SetBlockingPipe(pipe_descs[1]); + pThread->SetStartStatus(TRUE); + + BYTE resume_code = 0; + ssize_t read_ret; + + // Block until ResumeThread writes something to the pipe + while ((read_ret = read(pipe_descs[0], &resume_code, sizeof(resume_code))) != sizeof(resume_code)) + { + if (read_ret != -1 || EINTR != errno) + { + // read might return 0 (with EAGAIN) if the other end of the pipe gets closed + palError = ERROR_INTERNAL_ERROR; + break; + } + } + + if (palError == NO_ERROR && resume_code != WAKEUPCODE) + { + // If we did read successfully but the byte didn't match WAKEUPCODE, we treat it as a failure. + palError = ERROR_INTERNAL_ERROR; + } + + if (palError == NO_ERROR) + { + AcquireSuspensionLock(pThread); + pThread->suspensionInfo.SetSelfSusp(FALSE); + ReleaseSuspensionLock(pThread); + } + + // Close the pipes regardless of whether we were successful. + close(pipe_descs[0]); + close(pipe_descs[1]); + + return palError; +} + +/*++ +Function: + + ResumeThread + +See MSDN doc. +--*/ +DWORD +PALAPI +ResumeThread( + IN HANDLE hThread + ) +{ + PAL_ERROR palError; + CPalThread *pthrResumer; + DWORD dwSuspendCount = (DWORD)-1; + + PERF_ENTRY(ResumeThread); + ENTRY("ResumeThread(hThread=%p)\n", hThread); + + pthrResumer = InternalGetCurrentThread(); + palError = InternalResumeThread( + pthrResumer, + hThread, + &dwSuspendCount + ); + + if (NO_ERROR != palError) + { + pthrResumer->SetLastError(palError); + dwSuspendCount = (DWORD) -1; + } + else + { + _ASSERT_MSG(dwSuspendCount != static_cast(-1), "InternalResumeThread returned success but dwSuspendCount did not change.\n"); + } + + LOGEXIT("ResumeThread returns DWORD %u\n", dwSuspendCount); + PERF_EXIT(ResumeThread); + return dwSuspendCount; +} + +/*++ +Function: + InternalResumeThread + +InternalResumeThread converts the handle of the target thread to a +CPalThread, and passes both the resumer and target thread references +to InternalResumeThreadFromData. A reference to the suspend count from +the resumption attempt is passed back to the caller of this function. +--*/ +PAL_ERROR +CorUnix::InternalResumeThread( + CPalThread *pthrResumer, + HANDLE hTargetThread, + DWORD *pdwSuspendCount + ) +{ + PAL_ERROR palError = NO_ERROR; + CPalThread *pthrTarget = NULL; + IPalObject *pobjThread = NULL; + + palError = InternalGetThreadDataFromHandle( + pthrResumer, + hTargetThread, + &pthrTarget, + &pobjThread + ); + + if (NO_ERROR == palError) + { + palError = pthrResumer->suspensionInfo.InternalResumeThreadFromData( + pthrResumer, + pthrTarget, + pdwSuspendCount + ); + } + + if (NULL != pobjThread) + { + pobjThread->ReleaseReference(pthrResumer); + } + + return palError; +} + +/*++ +Function: + InternalResumeThreadFromData + +InternalResumeThreadFromData resumes the target thread. First, the suspension +mutexes of the threads are acquired. Next, there's a check to ensure that the +target thread was actually suspended. Finally, the resume attempt is made +and the suspension mutexes are released. The suspend count of the +target thread is passed back to the caller of this function. + +Note that ReleaseSuspensionLock(s) is called before hitting ASSERTs in error +paths. Currently, this seems unnecessary since asserting within +InternalResumeThreadFromData will not cause cleanup to occur. However, +this may change since it would be preferable to perform cleanup. Thus, calls +to release suspension locks remain in the error paths. +--*/ +PAL_ERROR +CThreadSuspensionInfo::InternalResumeThreadFromData( + CPalThread *pthrResumer, + CPalThread *pthrTarget, + DWORD *pdwSuspendCount + ) +{ + PAL_ERROR palError = NO_ERROR; + + int nWrittenBytes = -1; + + if (SignalHandlerThread == pthrTarget->GetThreadType()) + { + ASSERT("Attempting to resume the signal handling thread, which can never be suspended.\n"); + palError = ERROR_INVALID_HANDLE; + goto InternalResumeThreadFromDataExit; + } + + // Acquire suspension mutex + AcquireSuspensionLocks(pthrResumer, pthrTarget); + + // Check target thread's state to ensure it hasn't died. + // Setting a thread's state to TS_DONE is protected by the + // target's suspension mutex. + if (pthrTarget->synchronizationInfo.GetThreadState() == TS_DONE) + { + palError = ERROR_INVALID_HANDLE; + ReleaseSuspensionLocks(pthrResumer, pthrTarget); + goto InternalResumeThreadFromDataExit; + } + + // If this is a dummy thread, then it represents a process that was created with CREATE_SUSPENDED + // and it should have a blocking pipe set. If GetBlockingPipe returns -1 for a dummy thread, then + // something is wrong - either CREATE_SUSPENDED wasn't used or the process was already resumed. + if (pthrTarget->IsDummy() && -1 == pthrTarget->suspensionInfo.GetBlockingPipe()) + { + palError = ERROR_INVALID_HANDLE; + ERROR("Tried to wake up dummy thread without a blocking pipe.\n"); + ReleaseSuspensionLocks(pthrResumer, pthrTarget); + goto InternalResumeThreadFromDataExit; + } + + // If there is a blocking pipe on this thread, resume it by writing the wake up code to that pipe. + if (-1 != pthrTarget->suspensionInfo.GetBlockingPipe()) + { + // If write() is interrupted by a signal before writing data, + // it returns -1 and sets errno to EINTR. In this case, we + // attempt the write() again. + writeAgain: + nWrittenBytes = write(pthrTarget->suspensionInfo.GetBlockingPipe(), &WAKEUPCODE, sizeof(WAKEUPCODE)); + + // The size of WAKEUPCODE is 1 byte. If write returns 0, we'll treat it as an error. + if (sizeof(WAKEUPCODE) != nWrittenBytes) + { + // If we are here during process creation, this is most likely caused by the target + // process dying before reaching this point and thus breaking the pipe. + if (nWrittenBytes == -1 && EPIPE == errno) + { + palError = ERROR_INVALID_HANDLE; + ReleaseSuspensionLocks(pthrResumer, pthrTarget); + ERROR("Write failed with EPIPE\n"); + goto InternalResumeThreadFromDataExit; + } + else if (nWrittenBytes == 0 || (nWrittenBytes == -1 && EINTR == errno)) + { + TRACE("write() failed with EINTR; re-attempting write\n"); + goto writeAgain; + } + else + { + // Some other error occurred; need to release suspension mutexes before leaving ResumeThread. + palError = ERROR_INTERNAL_ERROR; + ReleaseSuspensionLocks(pthrResumer, pthrTarget); + ASSERT("Write() failed; error is %d (%s)\n", errno, strerror(errno)); + goto InternalResumeThreadFromDataExit; + } + } + + // Reset blocking pipe to -1 since we're done using it. + pthrTarget->suspensionInfo.SetBlockingPipe(-1); + + ReleaseSuspensionLocks(pthrResumer, pthrTarget); + goto InternalResumeThreadFromDataExit; + } + else + { + *pdwSuspendCount = 0; + palError = ERROR_BAD_COMMAND; + } + +InternalResumeThreadFromDataExit: + + if (NO_ERROR == palError) + { + *pdwSuspendCount = 1; + } + + return palError; +} + +/*++ +Function: + TryAcquireSuspensionLock + +TryAcquireSuspensionLock is a utility function that tries to acquire a thread's +suspension mutex or spinlock. If it succeeds, the function returns TRUE. +Otherwise, it returns FALSE. This function is used in AcquireSuspensionLocks. +Note that the global lock cannot be acquired in this function since it makes +no sense to do so. A thread holding the global lock is the only thread that +can perform suspend or resume operations so it doesn't need to acquire +a second lock. +--*/ +BOOL +CThreadSuspensionInfo::TryAcquireSuspensionLock( + CPalThread* pthrTarget + ) +{ + int iPthreadRet = 0; +#if DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX +{ + iPthreadRet = SPINLOCKTryAcquire(pthrTarget->suspensionInfo.GetSuspensionSpinlock()); +} +#else // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX +{ + iPthreadRet = pthread_mutex_trylock(pthrTarget->suspensionInfo.GetSuspensionMutex()); + _ASSERT_MSG(iPthreadRet == 0 || iPthreadRet == EBUSY, "pthread_mutex_trylock returned %d\n", iPthreadRet); +} +#endif // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX + + // If iPthreadRet is 0, lock acquisition was successful. Otherwise, it failed. + return (iPthreadRet == 0); +} + +/*++ +Function: + AcquireSuspensionLock + +AcquireSuspensionLock acquires a thread's suspension mutex or spinlock. +If USE_GLOBAL_LOCK_FOR_SUSPENSION is defined, it will acquire the global lock. +A thread in this function blocks until it acquires +its lock, unlike in TryAcquireSuspensionLock. +--*/ +void +CThreadSuspensionInfo::AcquireSuspensionLock( + CPalThread* pthrCurrent + ) +{ +#ifdef USE_GLOBAL_LOCK_FOR_SUSPENSION +{ + SPINLOCKAcquire(&g_ssSuspensionLock, 0); +} +#else // USE_GLOBAL_LOCK_FOR_SUSPENSION +{ + #if DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX + { + SPINLOCKAcquire(&pthrCurrent->suspensionInfo.m_nSpinlock, 0); + } + #else // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX + { + INDEBUG(int iPthreadError = ) + pthread_mutex_lock(&pthrCurrent->suspensionInfo.m_ptmSuspmutex); + _ASSERT_MSG(iPthreadError == 0, "pthread_mutex_lock returned %d\n", iPthreadError); + } + #endif // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX +} +#endif // USE_GLOBAL_LOCK_FOR_SUSPENSION +} + +/*++ +Function: + ReleaseSuspensionLock + +ReleaseSuspensionLock is a function that releases a thread's suspension mutex +or spinlock. If USE_GLOBAL_LOCK_FOR_SUSPENSION is defined, +it will release the global lock. +--*/ +void +CThreadSuspensionInfo::ReleaseSuspensionLock( + CPalThread* pthrCurrent + ) +{ +#ifdef USE_GLOBAL_LOCK_FOR_SUSPENSION +{ + SPINLOCKRelease(&g_ssSuspensionLock); +} +#else // USE_GLOBAL_LOCK_FOR_SUSPENSION +{ + #if DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX + { + SPINLOCKRelease(&pthrCurrent->suspensionInfo.m_nSpinlock); + } + #else // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX + { + INDEBUG(int iPthreadError = ) + pthread_mutex_unlock(&pthrCurrent->suspensionInfo.m_ptmSuspmutex); + _ASSERT_MSG(iPthreadError == 0, "pthread_mutex_unlock returned %d\n", iPthreadError); + } + #endif // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX +} +#endif // USE_GLOBAL_LOCK_FOR_SUSPENSION +} + +/*++ +Function: + AcquireSuspensionLocks + +AcquireSuspensionLocks is used to acquire the suspension locks +of a suspender (or resumer) and target thread. The thread will +perform a blocking call to acquire its own suspension lock +and will then try to acquire the target thread's lock without blocking. +If it fails to acquire the target's lock, it releases its own lock +and the thread will try to acquire both locks again. The key +is that both locks must be acquired together. + +Originally, only blocking calls were used to acquire the suspender +and the target lock. However, this was problematic since a thread +could acquire its own lock and then block on acquiring the target +lock. In the meantime, the target could have already acquired its +own lock and be attempting to suspend the suspender thread. This +clearly causes deadlock. A second approach used locking hierarchies, +where locks were acquired use thread id ordering. This was better but +suffered from the scenario where thread A acquires thread B's +suspension mutex first. In the meantime, thread C acquires thread A's +suspension mutex and its own. Thus, thread A is suspended while +holding thread B's mutex. This is problematic if thread C now wants +to suspend thread B. The issue here is that a thread can be +suspended while holding someone else's mutex but not holding its own. +In the end, the correct approach is to always acquire your suspension +mutex first. This prevents you from being suspended while holding the +target's mutex. Then, attempt to acquire the target's mutex. If the mutex +cannot be acquired, release your own and try again. This all or nothing +approach is the safest and avoids nasty race conditions. + +If USE_GLOBAL_LOCK_FOR_SUSPENSION is defined, the calling thread +will acquire the global lock when possible. +--*/ +VOID +CThreadSuspensionInfo::AcquireSuspensionLocks( + CPalThread *pthrSuspender, + CPalThread *pthrTarget + ) +{ + BOOL fReacquire = FALSE; + +#ifdef USE_GLOBAL_LOCK_FOR_SUSPENSION + AcquireSuspensionLock(pthrSuspender); +#else // USE_GLOBAL_LOCK_FOR_SUSPENSION + do + { + fReacquire = FALSE; + AcquireSuspensionLock(pthrSuspender); + if (!TryAcquireSuspensionLock(pthrTarget)) + { + // pthread_mutex_trylock returned EBUSY so release the first lock and try again. + ReleaseSuspensionLock(pthrSuspender); + fReacquire = TRUE; + sched_yield(); + } + } while (fReacquire); +#endif // USE_GLOBAL_LOCK_FOR_SUSPENSION + + // Whenever the native implementation for the wait subsystem's thread + // blocking requires a lock as protection (as pthread conditions do with + // the associated mutex), we need to grab that lock to prevent the target + // thread from being suspended while holding the lock. + // Failing to do so can lead to a multiple threads deadlocking such as the + // one described in VSW 363793. + // In general, in similar scenarios, we need to grab the protecting lock + // every time suspension safety/unsafety is unbalanced on the two sides + // using the same condition (or any other native blocking support which + // needs an associated native lock), i.e. when either the signaling + // thread(s) is(are) signaling from an unsafe area and the waiting + // thread(s) is(are) waiting from a safe one, or vice versa (the scenario + // described in VSW 363793 is a good example of the first type of + // unbalanced suspension safety/unsafety). + // Instead, whenever signaling and waiting sides are both marked safe or + // unsafe, the deadlock cannot take place since either the suspending + // thread will suspend them anyway (regardless of the native lock), or it + // won't suspend any of them, since they are both marked unsafe. + // Such a balanced scenario applies, for instance, to critical sections + // where depending on whether the target CS is internal or not, both the + // signaling and the waiting side will access the mutex/condition from + // respectively an unsafe or safe region. + + pthrTarget->AcquireNativeWaitLock(); +} + +/*++ +Function: + ReleaseSuspensionLocks + +ReleaseSuspensionLocks releases both thread's suspension mutexes. +Note that the locks are released in the opposite order they're acquired. +This prevents a suspending or resuming thread from being suspended +while holding the target's lock. +If USE_GLOBAL_LOCK_FOR_SUSPENSION is defined, it simply releases the global lock. +--*/ +VOID +CThreadSuspensionInfo::ReleaseSuspensionLocks( + CPalThread *pthrSuspender, + CPalThread *pthrTarget + ) +{ + // See comment in AcquireSuspensionLocks + pthrTarget->ReleaseNativeWaitLock(); + +#ifdef USE_GLOBAL_LOCK_FOR_SUSPENSION + ReleaseSuspensionLock(pthrSuspender); +#else // USE_GLOBAL_LOCK_FOR_SUSPENSION + ReleaseSuspensionLock(pthrTarget); + ReleaseSuspensionLock(pthrSuspender); +#endif // USE_GLOBAL_LOCK_FOR_SUSPENSION +} + +/*++ +Function: + PostOnSuspendSemaphore + +PostOnSuspendSemaphore is a utility function for a thread +to post on its POSIX or SysV suspension semaphore. +--*/ +void +CThreadSuspensionInfo::PostOnSuspendSemaphore() +{ +#if USE_POSIX_SEMAPHORES + if (sem_post(&m_semSusp) == -1) + { + ASSERT("sem_post returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); + } +#elif USE_SYSV_SEMAPHORES + if (semop(m_nSemsuspid, &m_sbSempost, 1) == -1) + { + ASSERT("semop - post returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); + } +#elif USE_PTHREAD_CONDVARS + int status; + + // The suspending thread may not have entered the wait yet, in which case the cond var + // signal below will be a no-op. To prevent the race condition we set m_fSuspended to + // TRUE first (which the suspender will take as an indication that no wait is required). + // But the setting of the flag and the signal must appear atomic to the suspender (as + // reading the flag and potentially waiting must appear to us) to avoid the race + // condition where the suspender reads the flag as FALSE, we set it and signal and the + // suspender then waits. + + // Acquire the suspend mutex. Once we enter the critical section the suspender has + // either gotten there before us (and is waiting for our signal) or is yet to even + // check the flag (so we can set it here to stop them attempting a wait). + status = pthread_mutex_lock(&m_mutexSusp); + if (status != 0) + { + ASSERT("pthread_mutex_lock returned %d (%s)\n", status, strerror(status)); + } + + m_fSuspended = TRUE; + + status = pthread_cond_signal(&m_condSusp); + if (status != 0) + { + ASSERT("pthread_cond_signal returned %d (%s)\n", status, strerror(status)); + } + + status = pthread_mutex_unlock(&m_mutexSusp); + if (status != 0) + { + ASSERT("pthread_mutex_unlock returned %d (%s)\n", status, strerror(status)); + } +#endif // USE_POSIX_SEMAPHORES +} + +/*++ +Function: + WaitOnSuspendSemaphore + +WaitOnSuspendSemaphore is a utility function for a thread +to wait on its POSIX or SysV suspension semaphore. +--*/ +void +CThreadSuspensionInfo::WaitOnSuspendSemaphore() +{ +#if USE_POSIX_SEMAPHORES + while (sem_wait(&m_semSusp) == -1) + { + ASSERT("sem_wait returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); + } +#elif USE_SYSV_SEMAPHORES + while (semop(m_nSemsuspid, &m_sbSemwait, 1) == -1) + { + ASSERT("semop wait returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); + } +#elif USE_PTHREAD_CONDVARS + int status; + + // By the time we wait the target thread may have already signalled its suspension (in + // which case m_fSuspended will be TRUE and we shouldn't wait on the cond var). But we + // must check the flag and potentially wait atomically to avoid the race where we read + // the flag and the target thread sets it and signals before we have a chance to wait. + + status = pthread_mutex_lock(&m_mutexSusp); + if (status != 0) + { + ASSERT("pthread_mutex_lock returned %d (%s)\n", status, strerror(status)); + } + + // If the target has already acknowledged the suspend we shouldn't wait. + while (!m_fSuspended) + { + // We got here before the target could signal. Wait on them (which atomically releases + // the mutex during the wait). + status = pthread_cond_wait(&m_condSusp, &m_mutexSusp); + if (status != 0) + { + ASSERT("pthread_cond_wait returned %d (%s)\n", status, strerror(status)); + } + } + + status = pthread_mutex_unlock(&m_mutexSusp); + if (status != 0) + { + ASSERT("pthread_mutex_unlock returned %d (%s)\n", status, strerror(status)); + } +#endif // USE_POSIX_SEMAPHORES +} + +/*++ +Function: + PostOnResumeSemaphore + +PostOnResumeSemaphore is a utility function for a thread +to post on its POSIX or SysV resume semaphore. +--*/ +void +CThreadSuspensionInfo::PostOnResumeSemaphore() +{ +#if USE_POSIX_SEMAPHORES + if (sem_post(&m_semResume) == -1) + { + ASSERT("sem_post returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); + } +#elif USE_SYSV_SEMAPHORES + if (semop(m_nSemrespid, &m_sbSempost, 1) == -1) + { + ASSERT("semop - post returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); + } +#elif USE_PTHREAD_CONDVARS + int status; + + // The resuming thread may not have entered the wait yet, in which case the cond var + // signal below will be a no-op. To prevent the race condition we set m_fResumed to + // TRUE first (which the resumer will take as an indication that no wait is required). + // But the setting of the flag and the signal must appear atomic to the resumer (as + // reading the flag and potentially waiting must appear to us) to avoid the race + // condition where the resumer reads the flag as FALSE, we set it and signal and the + // resumer then waits. + + // Acquire the resume mutex. Once we enter the critical section the resumer has + // either gotten there before us (and is waiting for our signal) or is yet to even + // check the flag (so we can set it here to stop them attempting a wait). + status = pthread_mutex_lock(&m_mutexResume); + if (status != 0) + { + ASSERT("pthread_mutex_lock returned %d (%s)\n", status, strerror(status)); + } + + m_fResumed = TRUE; + + status = pthread_cond_signal(&m_condResume); + if (status != 0) + { + ASSERT("pthread_cond_signal returned %d (%s)\n", status, strerror(status)); + } + + status = pthread_mutex_unlock(&m_mutexResume); + if (status != 0) + { + ASSERT("pthread_mutex_unlock returned %d (%s)\n", status, strerror(status)); + } +#endif // USE_POSIX_SEMAPHORES +} + +/*++ +Function: + WaitOnResumeSemaphore + +WaitOnResumeSemaphore is a utility function for a thread +to wait on its POSIX or SysV resume semaphore. +--*/ +void +CThreadSuspensionInfo::WaitOnResumeSemaphore() +{ +#if USE_POSIX_SEMAPHORES + while (sem_wait(&m_semResume) == -1) + { + ASSERT("sem_wait returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); + } +#elif USE_SYSV_SEMAPHORES + while (semop(m_nSemrespid, &m_sbSemwait, 1) == -1) + { + ASSERT("semop wait returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); + } +#elif USE_PTHREAD_CONDVARS + int status; + + // By the time we wait the target thread may have already signalled its resumption (in + // which case m_fResumed will be TRUE and we shouldn't wait on the cond var). But we + // must check the flag and potentially wait atomically to avoid the race where we read + // the flag and the target thread sets it and signals before we have a chance to wait. + + status = pthread_mutex_lock(&m_mutexResume); + if (status != 0) + { + ASSERT("pthread_mutex_lock returned %d (%s)\n", status, strerror(status)); + } + + // If the target has already acknowledged the resume we shouldn't wait. + while (!m_fResumed) + { + // We got here before the target could signal. Wait on them (which atomically releases + // the mutex during the wait). + status = pthread_cond_wait(&m_condResume, &m_mutexResume); + if (status != 0) + { + ASSERT("pthread_cond_wait returned %d (%s)\n", status, strerror(status)); + } + } + + status = pthread_mutex_unlock(&m_mutexResume); + if (status != 0) + { + ASSERT("pthread_mutex_unlock returned %d (%s)\n", status, strerror(status)); + } +#endif // USE_POSIX_SEMAPHORES +} + +/*++ +Function: + InitializeSuspensionLock + +InitializeSuspensionLock initializes a thread's suspension spinlock +or suspension mutex. It is called from the CThreadSuspensionInfo +constructor. +--*/ +VOID +CThreadSuspensionInfo::InitializeSuspensionLock() +{ +#if DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX + SPINLOCKInit(&m_nSpinlock); +#else + int iError = pthread_mutex_init(&m_ptmSuspmutex, NULL); + if (0 != iError ) + { + ASSERT("pthread_mutex_init(&suspmutex) returned %d\n", iError); + return; + } + m_fSuspmutexInitialized = TRUE; +#endif // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX +} + +/*++ +Function: + InitializePreCreate + +InitializePreCreate initializes the semaphores and signal masks used +for thread suspension. At the end, it sets the calling thread's +signal mask to the default signal mask. +--*/ +PAL_ERROR +CThreadSuspensionInfo::InitializePreCreate() +{ + PAL_ERROR palError = ERROR_INTERNAL_ERROR; + int iError = 0; +#if SEM_INIT_MODIFIES_ERRNO + int nStoredErrno; +#endif // SEM_INIT_MODIFIES_ERRNO + +#if USE_POSIX_SEMAPHORES + +#if SEM_INIT_MODIFIES_ERRNO + nStoredErrno = errno; +#endif // SEM_INIT_MODIFIES_ERRNO + + // initialize suspension semaphore + iError = sem_init(&m_semSusp, 0, 0); + +#if SEM_INIT_MODIFIES_ERRNO + if (iError == 0) + { + // Restore errno if sem_init succeeded. + errno = nStoredErrno; + } +#endif // SEM_INIT_MODIFIES_ERRNO + + if (0 != iError ) + { + ASSERT("sem_init(&suspsem) returned %d\n", iError); + goto InitializePreCreateExit; + } + +#if SEM_INIT_MODIFIES_ERRNO + nStoredErrno = errno; +#endif // SEM_INIT_MODIFIES_ERRNO + + // initialize resume semaphore + iError = sem_init(&m_semResume, 0, 0); + +#if SEM_INIT_MODIFIES_ERRNO + if (iError == 0) + { + // Restore errno if sem_init succeeded. + errno = nStoredErrno; + } +#endif // SEM_INIT_MODIFIES_ERRNO + + if (0 != iError ) + { + ASSERT("sem_init(&suspsem) returned %d\n", iError); + sem_destroy(&m_semSusp); + goto InitializePreCreateExit; + } + + m_fSemaphoresInitialized = TRUE; + +#elif USE_SYSV_SEMAPHORES + // preparing to initialize the SysV semaphores. + union semun semunData; + m_nSemsuspid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666); + if (m_nSemsuspid == -1) + { + ASSERT("semget for suspension sem id returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); + goto InitializePreCreateExit; + } + + m_nSemrespid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666); + if (m_nSemrespid == -1) + { + ASSERT("semget for resumption sem id returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); + goto InitializePreCreateExit; + } + + if (m_nSemsuspid == m_nSemrespid) + { + ASSERT("Suspension and Resumption Semaphores have the same id\n"); + goto InitializePreCreateExit; + } + + semunData.val = 0; + iError = semctl(m_nSemsuspid, 0, SETVAL, semunData); + if (iError == -1) + { + ASSERT("semctl for suspension sem id returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); + goto InitializePreCreateExit; + } + + semunData.val = 0; + iError = semctl(m_nSemrespid, 0, SETVAL, semunData); + if (iError == -1) + { + ASSERT("semctl for resumption sem id returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); + goto InitializePreCreateExit; + } + + // initialize suspend semaphore + m_sbSemwait.sem_num = 0; + m_sbSemwait.sem_op = -1; + m_sbSemwait.sem_flg = 0; + + // initialize resume semaphore + m_sbSempost.sem_num = 0; + m_sbSempost.sem_op = 1; + m_sbSempost.sem_flg = 0; +#elif USE_PTHREAD_CONDVARS + iError = pthread_cond_init(&m_condSusp, NULL); + if (iError != 0) + { + ASSERT("pthread_cond_init for suspension returned %d (%s)\n", iError, strerror(iError)); + goto InitializePreCreateExit; + } + + iError = pthread_mutex_init(&m_mutexSusp, NULL); + if (iError != 0) + { + ASSERT("pthread_mutex_init for suspension returned %d (%s)\n", iError, strerror(iError)); + goto InitializePreCreateExit; + } + + iError = pthread_cond_init(&m_condResume, NULL); + if (iError != 0) + { + ASSERT("pthread_cond_init for resume returned %d (%s)\n", iError, strerror(iError)); + goto InitializePreCreateExit; + } + + iError = pthread_mutex_init(&m_mutexResume, NULL); + if (iError != 0) + { + ASSERT("pthread_mutex_init for resume returned %d (%s)\n", iError, strerror(iError)); + goto InitializePreCreateExit; + } + + m_fSemaphoresInitialized = TRUE; +#endif // USE_POSIX_SEMAPHORES + + // Initialization was successful. + palError = NO_ERROR; + +InitializePreCreateExit: + + if (NO_ERROR == palError && 0 != iError) + { + switch (iError) + { + case ENOMEM: + case EAGAIN: + { + palError = ERROR_OUTOFMEMORY; + break; + } + default: + { + ASSERT("A pthrSuspender init call returned %d (%s)\n", iError, strerror(iError)); + palError = ERROR_INTERNAL_ERROR; + } + } + } + + return palError; +} + +CThreadSuspensionInfo::~CThreadSuspensionInfo() +{ +#if !DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX + if (m_fSuspmutexInitialized) + { + INDEBUG(int iError = ) + pthread_mutex_destroy(&m_ptmSuspmutex); + _ASSERT_MSG(0 == iError, "pthread_mutex_destroy returned %d (%s)\n", iError, strerror(iError)); + } +#endif + +#if USE_POSIX_SEMAPHORES + if (m_fSemaphoresInitialized) + { + int iError; + + iError = sem_destroy(&m_semSusp); + _ASSERT_MSG(0 == iError, "sem_destroy failed and set errno to %d (%s)\n", errno, strerror(errno)); + + iError = sem_destroy(&m_semResume); + _ASSERT_MSG(0 == iError, "sem_destroy failed and set errno to %d (%s)\n", errno, strerror(errno)); + } +#elif USE_SYSV_SEMAPHORES + DestroySemaphoreIds(); +#elif USE_PTHREAD_CONDVARS + if (m_fSemaphoresInitialized) + { + int iError; + + iError = pthread_cond_destroy(&m_condSusp); + _ASSERT_MSG(0 == iError, "pthread_cond_destroy failed with %d (%s)\n", iError, strerror(iError)); + + iError = pthread_mutex_destroy(&m_mutexSusp); + _ASSERT_MSG(0 == iError, "pthread_mutex_destroy failed with %d (%s)\n", iError, strerror(iError)); + + iError = pthread_cond_destroy(&m_condResume); + _ASSERT_MSG(0 == iError, "pthread_cond_destroy failed with %d (%s)\n", iError, strerror(iError)); + + iError = pthread_mutex_destroy(&m_mutexResume); + _ASSERT_MSG(0 == iError, "pthread_mutex_destroy failed with %d (%s)\n", iError, strerror(iError)); + } +#endif // USE_POSIX_SEMAPHORES +} + +#if USE_SYSV_SEMAPHORES +/*++ +Function: + DestroySemaphoreIds + +DestroySemaphoreIds is called from the CThreadSuspensionInfo destructor and +from PROCCleanupThreadSemIds. If a thread exits before shutdown or is suspended +during shutdown, its destructor will be invoked and the semaphore ids destroyed. +In assert or exceptions situations that are suspension unsafe, +PROCCleanupThreadSemIds is called, which uses DestroySemaphoreIds. +--*/ +void +CThreadSuspensionInfo::DestroySemaphoreIds() +{ + union semun semunData; + if (m_nSemsuspid != 0) + { + semunData.val = 0; + if (0 != semctl(m_nSemsuspid, 0, IPC_RMID, semunData)) + { + ERROR("semctl(Semsuspid) failed and set errno to %d (%s)\n", errno, strerror(errno)); + } + else + { + m_nSemsuspid = 0; + } + } + if (this->m_nSemrespid) + { + semunData.val = 0; + if (0 != semctl(m_nSemrespid, 0, IPC_RMID, semunData)) + { + ERROR("semctl(Semrespid) failed and set errno to %d (%s)\n", errno, strerror(errno)); + } + else + { + m_nSemrespid = 0; + } + } +} +#endif // USE_SYSV_SEMAPHORES diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/CMakeLists.txt new file mode 100644 index 0000000..b6d9fe2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.14.2) + +# Compile options +add_definitions(-DLP64COMPATIBLE) +add_definitions(-DCORECLR) +add_definitions(-DPIC) + +# C++ emits errors and warnings for c-string literal fed into char* parameter +# this is just to take care of the warnings +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wno-writable-strings) +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + add_compile_options(-Wno-write-strings) +endif() + +add_compile_options(-Wno-empty-body) + +add_subdirectory(palsuite) + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/CMakeLists.txt new file mode 100644 index 0000000..902f125 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/CMakeLists.txt @@ -0,0 +1,44 @@ +project(PALTESTSUITE) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +include_directories(${PALTESTSUITE_SOURCE_DIR}/common) + +# All test will link against these libraries: +# pthread and m are part of the Android C library (bionic), +# so we don't need to link them seperately +if(NOT CLR_CMAKE_TARGET_ANDROID) + list(APPEND COMMON_TEST_LIBRARIES pthread) + list(APPEND COMMON_TEST_LIBRARIES m) +endif() + +list(APPEND COMMON_TEST_LIBRARIES coreclrpal) + +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wno-incompatible-pointer-types-discards-qualifiers) + add_compile_options(-Wno-int-to-void-pointer-cast) +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + add_compile_options(-Wno-sign-compare) + add_compile_options(-Wno-narrowing) + add_compile_options($<$:-fpermissive>) + add_compile_options(-Wno-int-to-pointer-cast) +endif() + +# TODO: make these tests compile +# add_subdirectory(composite) +add_subdirectory(exception_handling) + +add_subdirectory(c_runtime) +add_subdirectory(debug_api) +add_subdirectory(filemapping_memmgt) +add_subdirectory(file_io) +add_subdirectory(loader) +add_subdirectory(locale_info) +add_subdirectory(miscellaneous) +add_subdirectory(pal_specific) +add_subdirectory(samples) +add_subdirectory(threading) + +if(FEATURE_EVENT_TRACE) + add_subdirectory(eventprovider) +endif(FEATURE_EVENT_TRACE) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/DisabledTests.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/DisabledTests.txt new file mode 100644 index 0000000..babd443 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/DisabledTests.txt @@ -0,0 +1,51 @@ +Disabled Test Cases +~~~~~~~~~~~~~~~~~~~ + +Below is a list of all disabled test cases currently listed in +testconfig.dat and an explanation as to why they are disabled. + +debug_api/debugbreak/test1 +debug_api/outputdebugstringa/test1 +debug_api/outputdebugstringw/test1 +debug_api/writeprocessmemory/test1 +debug_api/writeprocessmemory/test3 +debug_api/writeprocessmemory/test4 +======================================= +The above testcases were disabled in the palsuite, because they depend heavily on +WaitForDebugEvent,DebugActiveProcess and ContinueDebugEvent, where these api's +have been removed from the PAL. + + +file_io/gettempfilenamea/test2 : +======================================= +This test takes longer than 60 seconds to run. The test creates +about 65000 files and then deletes them. The test that takes longer +than 60 seconds will be flagged as an error and so in such a case +the test will have to be run manually. + +file_io/gettempfilenamew/test2 : +======================================= +This test takes longer than 60 seconds to run. The test creates +about 65000 files and then deletes them. The test that takes longer +than 60 seconds will be flagged as an error and so in such a case +the test will have to be run manually. + +locale_info/getcpinfo/test2: +======================================= +This test will be useful in future versions for testing various +languages (code pages). Currently only U.S. English (tested by - +test1) is supported. + +locale_info/getcpinfo/test3: +======================================= +This test will be useful in future versions for testing various +languages (code pages). Currently only U.S. English (tested by - +test1) is supported. + +pal_specific/pal_get_stdin/test1 : +======================================= +This test case should be run manually. Requires user input. + +filemapping_memmgt\MapViewOfFile\test1 +======================================= +Refer this github issue https://github.com/dotnet/coreclr/issues/5176 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/README.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/README.txt new file mode 100644 index 0000000..eb180b3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/README.txt @@ -0,0 +1,116 @@ +; 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. + +=========================================================================== + + +1. ENVIRONMENT SETUP + +2. RUNNING THE SUITES + +3. ENVIRONMENT VARIABLES AND AUTOMATED TESTING SPECIFICS +3.1 PAL_DISABLE_MESSAGEBOX +3.2 Other Notes + +4. ADDITIONAL NOTES ON TESTING/SPECIFIC TEST CASE ISSUES + C_runtime: _fdopen testing issues + File_IO: getfilesize/test1, setfilepointer/test(5,6,7) + File_IO: gettempfilename(a,w)/test2 + File_IO: setfileattributesa/test(1,4), setfileattributesw/test(1,4) + Miscellaneous: messageboxw/test(1,2) + Pal_specific:: pal_get_stdin/test1, pal_get_stdout/test1, pal_get_stderr/test1 + Threading: setconsolectrlhandler/test(3,4) + + +=========================================================================== + +1. ENVIRONMENT SETUP +~~~~~~~~~~~~~~~~~~~~~ + +Within a Rotor build window (env.sh/env.csh/env.bat), no additional +configuration needs to be done. + + +2. RUNNING THE SUITES +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Run %ROTOR_DIR%\tests\pvtrun.pl to launch the test suites. It will +display information about each test as it runs, then report a +summary of the results upon completion. + +The results are logged to %ROTOR_DIR%\tests\pvtResults.log. + + +3. ENVIRONMENT VARIABLES AND AUTOMATED TESTING SPECIFICS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See notes in section 4 on the following test cases if running automated tests: + + Miscellaneous: messageboxw/test(1,2) + Threading: setconsolectrlhandler/test(3,4) + + +4. ADDITIONAL NOTES ON TESTING/SPECIFIC TEST CASE ISSUES +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +C Runtime: _fdopen testing issues + +There is a very specific manner in which _fdopen has been documented to work, +this will determine how the function will be tested. + +_fdopen takes a parameter of a c run-time file handle, to open a stream to the +file. This file handle can only be returned from the _open_osfhandle function. +The Rotor documentation states that _open_osfhandle will only return a +READ-ONLY file handle, from an operating-system file handle returned from +CreatePipe(). + +With these restrictions _fdopen will only be tested with a mode of read(r). +The other modes are not possible to test. _open_osfhandle returns an error +when attempting to open a write pipe handle in a mode of read-only. As well, +it is not possible to read and write to the same handle that is returned from +CreatePipe(). + +The modes that will not be tested are as follows: + + "w" - Opens an empty file for writing. + "a" - Opens for writing at the end of the file (appending). + "r+" - Opens for both reading and writing. + "w+" - Opens an empty file for both reading and writing. + "a+" - Opens for reading and appending. + + + +File_IO: getfilesize/test1, getfilesizeex/test1 setfilepointer/test(5,6,7) + +These tests cases create a large number of temporary files which require +ample disk space. On systems with less than 6Gb free disk space expect +these test cases to fail. + + +File_IO: gettempfilename(a,w)/test2 + +These test cases take longer than 60 seconds to run. Currently, the Test +Harness will timeout any test case that exceeds 60 seconds. + + +Miscellaneous: messageboxw/test(1,2) + +Setting PAL_MESSAGEBOX_DISABLE=1 for these test cases prevents message box pop +ups that occur during the tests' execution on Windows. For automated testing +where user interaction is not desired/possible, setting this environment +variable will prevent a pause in the automated test run. + + +ic: pal_get_stdin/test1, pal_get_stdout/test1, pal_get_stderr/test1 + +These test cases should be manually inspected to ensure the information being returned +is correct. The pal_get_stdin test case requires user input. The pal_get_stdout and +pal_get_stderr test cases do not require user input, but their output should be inspected +to verify that correct messages are being displayed. + + +Threading: setconsolectrlhandler/test(3,4) + +These test cases require user response in order to produce a meaningful results. +For automated testing, this test case is disabled. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/CMakeLists.txt new file mode 100644 index 0000000..95aa6ac --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/CMakeLists.txt @@ -0,0 +1,171 @@ +add_subdirectory(abs) +add_subdirectory(acos) +add_subdirectory(acosf) +add_subdirectory(acosh) +add_subdirectory(acoshf) +add_subdirectory(asin) +add_subdirectory(asinf) +add_subdirectory(asinh) +add_subdirectory(asinhf) +add_subdirectory(atan) +add_subdirectory(atan2) +add_subdirectory(atan2f) +add_subdirectory(atanf) +add_subdirectory(atanh) +add_subdirectory(atanhf) +add_subdirectory(atof) +add_subdirectory(atoi) +add_subdirectory(bsearch) +add_subdirectory(cbrt) +add_subdirectory(cbrtf) +add_subdirectory(ceil) +add_subdirectory(ceilf) +add_subdirectory(cos) +add_subdirectory(cosf) +add_subdirectory(cosh) +add_subdirectory(coshf) + +add_subdirectory(errno) +add_subdirectory(exit) +add_subdirectory(exp) +add_subdirectory(expf) +add_subdirectory(fabs) +add_subdirectory(fabsf) +add_subdirectory(fclose) +add_subdirectory(ferror) +add_subdirectory(fflush) +add_subdirectory(fgets) +add_subdirectory(floor) +add_subdirectory(floorf) +add_subdirectory(fma) +add_subdirectory(fmaf) +add_subdirectory(fmod) +add_subdirectory(fmodf) +add_subdirectory(fopen) +add_subdirectory(fprintf) +add_subdirectory(fputs) +add_subdirectory(fread) +add_subdirectory(free) +add_subdirectory(fseek) +add_subdirectory(ftell) +add_subdirectory(fwprintf) +add_subdirectory(fwrite) +add_subdirectory(getenv) +add_subdirectory(ilogb) +add_subdirectory(ilogbf) +add_subdirectory(isalnum) +add_subdirectory(isalpha) +add_subdirectory(isdigit) +add_subdirectory(islower) +add_subdirectory(isprint) +add_subdirectory(isspace) +add_subdirectory(isupper) +add_subdirectory(iswdigit) +add_subdirectory(iswspace) +add_subdirectory(iswupper) +add_subdirectory(isxdigit) +add_subdirectory(llabs) +add_subdirectory(log) +add_subdirectory(log2) +add_subdirectory(log2f) +add_subdirectory(log10) +add_subdirectory(log10f) +add_subdirectory(logf) +add_subdirectory(malloc) +add_subdirectory(memchr) +add_subdirectory(memcmp) +add_subdirectory(memcpy) +add_subdirectory(memmove) +add_subdirectory(memset) +add_subdirectory(modf) +add_subdirectory(modff) +add_subdirectory(pow) +add_subdirectory(powf) +add_subdirectory(printf) +add_subdirectory(qsort) +add_subdirectory(rand_srand) +add_subdirectory(realloc) +add_subdirectory(scalbn) +add_subdirectory(scalbnf) +add_subdirectory(sin) +add_subdirectory(sinf) +add_subdirectory(sinh) +add_subdirectory(sinhf) +add_subdirectory(sprintf_s) +add_subdirectory(sqrt) +add_subdirectory(sqrtf) +add_subdirectory(sscanf_s) +add_subdirectory(strcat) +add_subdirectory(strchr) +add_subdirectory(strcmp) +add_subdirectory(strcpy) +add_subdirectory(strcspn) +add_subdirectory(strlen) +add_subdirectory(strncat) +add_subdirectory(strncmp) +add_subdirectory(strncpy) +add_subdirectory(strpbrk) +add_subdirectory(strrchr) +add_subdirectory(strspn) +add_subdirectory(strstr) +add_subdirectory(strtod) +add_subdirectory(strtok) +add_subdirectory(strtoul) +add_subdirectory(swprintf) +add_subdirectory(swscanf) +add_subdirectory(tan) +add_subdirectory(tanf) +add_subdirectory(tanh) +add_subdirectory(tanhf) +add_subdirectory(time) +add_subdirectory(tolower) +add_subdirectory(toupper) +add_subdirectory(towlower) +add_subdirectory(towupper) +add_subdirectory(vfprintf) +add_subdirectory(vprintf) +add_subdirectory(vsprintf) +add_subdirectory(vswprintf) +add_subdirectory(wcscat) +add_subdirectory(wcschr) +add_subdirectory(wcscmp) +add_subdirectory(wcscpy) +add_subdirectory(wcslen) +add_subdirectory(wcsncmp) +add_subdirectory(wcsncpy) +add_subdirectory(wcspbrk) +add_subdirectory(wcsrchr) +add_subdirectory(wcsstr) +add_subdirectory(wcstod) +add_subdirectory(wcstok) +add_subdirectory(wcstoul) +add_subdirectory(wprintf) +add_subdirectory(_alloca) +add_subdirectory(_fdopen) +add_subdirectory(_finite) +add_subdirectory(_finitef) + +# TODO: make this test compile +# add_subdirectory(_gcvt) + +add_subdirectory(_isnan) +add_subdirectory(_isnanf) +add_subdirectory(_itow) +add_subdirectory(_mbsdec) +add_subdirectory(_mbsinc) +add_subdirectory(_mbsninc) +add_subdirectory(_putenv) +add_subdirectory(_rotl) +add_subdirectory(_rotr) +add_subdirectory(_snprintf_s) +add_subdirectory(_snwprintf_s) +add_subdirectory(_stricmp) +add_subdirectory(_strnicmp) +add_subdirectory(_vsnprintf_s) +add_subdirectory(_vsnwprintf_s) +add_subdirectory(_wcsicmp) +add_subdirectory(_wcslwr) +add_subdirectory(_wcsnicmp) +add_subdirectory(_wfopen) +add_subdirectory(_wtoi) +add_subdirectory(__iscsym) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/test1/CMakeLists.txt new file mode 100644 index 0000000..431b99e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + __iscsym.cpp +) + +add_executable(paltest_iscsym_test1 + ${SOURCES} +) + +add_dependencies(paltest_iscsym_test1 coreclrpal) + +target_link_libraries(paltest_iscsym_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/test1/__iscsym.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/test1/__iscsym.cpp new file mode 100644 index 0000000..9c8f1d0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/test1/__iscsym.cpp @@ -0,0 +1,93 @@ +// 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. + +/*============================================================= +** +** Source: __iscsym.c +** +** Purpose: Positive test the __iscsym API. +** Call __iscsym to letter, digit and underscore +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + int index; + char non_letter_set[]= + {'~','`','!','@','#','$','%','^','&','*','(',')',')', + '-','+','=','|','\\',';',':','"','\'','<','>', + ',','.','?','/','\0'}; + char errBuffer[200]; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*To check if the parameter passed in is a character*/ + for(index = 'a'; index <= 'z'; index++) + { + err = __iscsym(index); + if(0 == err) + { + Fail("\n__iscsym failed to recognize a " + "lower-case letter:%c!\n", index); + } + } + + /*To check if the parameter passed in is a character*/ + for(index = 'A'; index <= 'Z'; index++) + { + err = __iscsym(index); + if(0 == err) + { + Fail("\n__iscsym failed to recognize an " + "upper-case letter: %c!\n", index); + } + } + + /*To check if the parameter passed in is a digit*/ + for(index = '0'; index <= '9'; index++) + { + err = __iscsym(index); + if(0 == err) + { + Fail("\n__iscsym failed to recognize a digit %c!\n", + index); + } + } + + /*To check if the parameter passed in is a underscore*/ + err = __iscsym('_'); + if(0 == err) + { + Fail("\n__iscsym failed to recognize an underscore!\n"); + } + + memset(errBuffer, 0, 200); + + for(index = 0; non_letter_set[index]; index++) + { + err = __iscsym(non_letter_set[index]); + if(0 != err) + { + strncat(errBuffer, &non_letter_set[index], 1); + strcat(errBuffer, ", "); + } + } + + if(strlen(errBuffer) > 0) + { + Fail("\n__iscsym failed to identify the characters '%s' " + "as not letters, digits " + "or underscores\n", errBuffer); + } + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/test1/testinfo.dat new file mode 100644 index 0000000..e6668ed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/__iscsym/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = __iscsym +Name = Positive test for __iscsym to test letter, digit and underscore +TYPE = DEFAULT +EXE1 = __iscsym +Description +=Test the __iscsym to test letter, digit and underscore diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/test1/CMakeLists.txt new file mode 100644 index 0000000..41226ab --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_alloca_test1 + ${SOURCES} +) + +add_dependencies(paltest_alloca_test1 coreclrpal) + +target_link_libraries(paltest_alloca_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/test1/test1.cpp new file mode 100644 index 0000000..c533d84 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/test1/test1.cpp @@ -0,0 +1,62 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Checks that _alloca allocates memory, and that the memory is +** readable and writeable. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + + char *testA = NULL; + int i = 0; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + + /* check that _alloca really gives us addressable memory */ + testA = (char *)_alloca(20 * sizeof(char)); + if (testA == NULL) + { + Fail ("The call to _alloca failed\n"); + } + + memset(testA, 'a', 20); + + for (i = 0; i < 20; i++) + { + if (testA[i] != 'a') + { + Fail ("The memory returned by _alloca doesn't seem to be" + " properly allocated\n"); + } + } + + PAL_Terminate(); + return PASS; +} + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/test1/testinfo.dat new file mode 100644 index 0000000..e215621 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_alloca/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _alloca +Name = Positive Test for _alloca +TYPE = DEFAULT +EXE1 = test1 +Description += Checks that _alloca allocates memory, and that the memory is += readable and writeable. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/test1/CMakeLists.txt new file mode 100644 index 0000000..c4df126 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fdopen_test1 + ${SOURCES} +) + +add_dependencies(paltest_fdopen_test1 coreclrpal) + +target_link_libraries(paltest_fdopen_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/test1/test1.cpp new file mode 100644 index 0000000..b88267c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/test1/test1.cpp @@ -0,0 +1,112 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c (fdopen) +** +** Purpose: Tests the PAL implementation of the fdopen function. +** This will test fdopen in r (read) mode. This test +** creates and opens a test pipe, to write and read +** from. fdopen requires a file handle(int), therefore +** _open_osfhandle is used to get that handle. +** _open_osfhandle is only used with CreatePipe. The +** test will write and read from the pipe comparing +** the results. +** +** See /tests/palsuite/README.txt for more information. +** +** +**===================================================================*/ + +#include + +const char* cTestString = "one fish, two fish, read fish, blue fish."; + +int __cdecl main(int argc, char **argv) +{ + HANDLE hReadPipe = NULL; + HANDLE hWritePipe = NULL; + BOOL bRetVal = FALSE; + int iFiledes = 0; + DWORD dwBytesWritten; + char buffer[45]; + FILE *fp; + + SECURITY_ATTRIBUTES lpPipeAttributes; + + /*Initialize the PAL*/ + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/ + lpPipeAttributes.nLength = sizeof(lpPipeAttributes); + lpPipeAttributes.lpSecurityDescriptor = NULL; + lpPipeAttributes.bInheritHandle = TRUE; + + /*Create a Pipe*/ + bRetVal = CreatePipe(&hReadPipe, // read handle + &hWritePipe, // write handle + &lpPipeAttributes, // security attributes + 0); // pipe size + + if (bRetVal == FALSE) + { + Fail("ERROR: unable to create pipe"); + } + + /*Write to the write pipe handle*/ + bRetVal = WriteFile(hWritePipe, // handle to file + cTestString, // data buffer + (DWORD)strlen(cTestString), // number of bytes to write + &dwBytesWritten, // number of bytes written + NULL); // overlapped buffer + + if (bRetVal == FALSE) + { + Fail("ERROR: unable to write to pipe write handle " + "hWritePipe=0x%lx", hWritePipe); + } + + /*Get a file descriptor for the read pipe handle*/ + iFiledes = _open_osfhandle((long)hReadPipe, _O_RDONLY); + + if (iFiledes == -1) + { + Fail("ERROR: _open_osfhandle failed to open " + " hReadPipe=0x%lx", hReadPipe); + } + + /*Open read pipe handle in read mode*/ + fp = _fdopen(iFiledes, "r"); + + if (fp == NULL) + { + Fail("ERROR: unable to fdopen file descriptor" + " iFiledes=%d", iFiledes); + } + + /*Read from the read pipe handle*/ + if((fread(buffer, sizeof(char), strlen(cTestString), fp)) == 0) + { + Fail("ERROR: Unable to read from file stream fp=0x%lx\n", fp); + } + + /*Compare what was read with what was written.*/ + if ((memcmp(cTestString, buffer, strlen(cTestString))) != 0) + { + Fail("ERROR: read \"%s\" expected \"%s\" \n", buffer, cTestString); + } + + /*Close the file handle*/ + if (_close(iFiledes) != 0) + { + Fail("ERROR: Unable to close file handle iFiledes=%d\n", iFiledes); + } + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/test1/testinfo.dat new file mode 100644 index 0000000..89e48bb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_fdopen/test1/testinfo.dat @@ -0,0 +1,23 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fdopen +Name = test for fdopen and _close +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the fdopen function. += This will test fdopen in r (read) mode. This test += creates and opens a test pipe, to write and read += from. fdopen requires a file handle(int), therefore += _open_osfhandle is used to get that handle. += _open_osfhandle is only used with CreatePipe. The += test will write and read from the pipe comparing += the results. += As a secondary test, _close is tested since it needs += the handle returned by _open_osfhandle. The handle is += closed, then a read is attempted on the handle which += should fail. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finite/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finite/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finite/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finite/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finite/test1/CMakeLists.txt new file mode 100644 index 0000000..5540111 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finite/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_finite_test1 + ${SOURCES} +) + +add_dependencies(paltest_finite_test1 coreclrpal) + +target_link_libraries(paltest_finite_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finite/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finite/test1/test1.cpp new file mode 100644 index 0000000..c815055 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_finite/test1/test1.cpp @@ -0,0 +1,119 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Checks that _finite correctly classifies all types +** of floating point numbers (NaN, -Infinity, Infinity, +** finite nonzero, unnormalized, 0, and -0) +** +**==========================================================================*/ + +#include + +/* +The IEEE double precision floating point standard looks like this: + + S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 0 1 11 12 63 + +S is the sign bit. The E bits are the exponent, and the 52 F bits are +the fraction. These represent a value, V. + +If E=2047 and F is nonzero, then V=NaN ("Not a number") +If E=2047 and F is zero and S is 1, then V=-Infinity +If E=2047 and F is zero and S is 0, then V=Infinity +If 0 + +/* +The IEEE single precision floating point standard looks like this: + + S EEEEEEEE FFFFFFFFFFFFFFFFFFFFFFF + 0 1 8 9 31 + +S is the sign bit. The E bits are the exponent, and the 23 F bits are +the fraction. These represent a value, V. + +If E=255 and F is nonzero, then V=NaN ("Not a number") +If E=255 and F is zero and S is 1, then V=-Infinity +If E=255 and F is zero and S is 0, then V=Infinity +If 0 + +int __cdecl main(int argc, char *argv[]) +{ + int err; + double dValue = -3.1415926535; + char buffer[1024]; + char *pChar7 = "-3.141593"; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + + /* zero the buffer */ + memset(buffer, 0, 1024); + + + /* + + Testing + ======= + + To convert a floating-point value to + a string to save 7 significant digits + */ + _gcvt(dValue, 7, buffer); + if(strcmp(pChar7, buffer)) + { + Fail("\nFailed to call _gcvt to convert a floating-point value " + "to a string with 7 sigficants digits stored\n"); + } + + + /* + Clean up and exit + */ + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test1/testinfo.dat new file mode 100644 index 0000000..d527418 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _gcvt +Name = Positive test for _gcvt API to convert a floatable value to a string +TYPE = DEFAULT +EXE1 = _gcvt +Description +=Test the _gcvt to convert a floatable value to a string +=with specified sigficant digits stored diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test2/CMakeLists.txt new file mode 100644 index 0000000..87f84e3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_gcvt_test2 + ${SOURCES} +) + +add_dependencies(paltest_gcvt_test2 coreclrpal) + +target_link_libraries(paltest_gcvt_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test2/test2.cpp new file mode 100644 index 0000000..7ac9a4f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test2/test2.cpp @@ -0,0 +1,83 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Call the _gcvt function on a number of cases. Check that it +** handles negatives, exponents and hex digits properly. Also check that +** the 'digit' specification works. (And that it doesn't truncate negative +** signs or decimals) +** +** +**===================================================================*/ + +#include + +struct testCase +{ + double Value; + int Digits; + char WinCorrectResult[128]; + char BsdCorrectResult[128]; /* for the odd case where bsd sprintf + varies from windows sprintf */ +}; + +int __cdecl main(int argc, char **argv) +{ + char result[128]; + int i=0; + + struct testCase testCases[] = + { + {1234567, 7, "1234567"}, + {1234.123, 7, "1234.123"}, + {1234.1234, 7, "1234.123"}, + {12.325678e+2, 7, "1232.568"}, + {-12.3233333, 8, "-12.323333"}, + {-12.32, 8, "-12.32"}, + {-12.32e+2, 8, "-1232.", "-1232" }, + {0x21DDFABC, 8, "5.6819577e+008", "5.6819577e+08" }, + {123456789012345.0, 15, "123456789012345" }, + {12340000.0, 8, "12340000"}, + {12340000000000000.0, 15, "1.234e+016", "1.234e+16" }, + {12340000000000000.0, 17, "12340000000000000" }, + + }; + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Loop through each case. Call _gcvt on each test case and check the + result. + */ + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + _gcvt(testCases[i].Value, testCases[i].Digits, result); + + if (strcmp(testCases[i].WinCorrectResult, result) != 0 && + + ( testCases[i].BsdCorrectResult && + strcmp(testCases[i].BsdCorrectResult, result) != 0 ) ) + { + Fail("ERROR: _gcvt attempted to convert %f with %d digits " + "signifigant, which resulted in " + "the string '%s' instead of the correct(Win) string '%s' or the" + "correct(bsd) string '%s'.\n", + testCases[i].Value, + testCases[i].Digits, + result, + testCases[i].WinCorrectResult, + testCases[i].BsdCorrectResult); + } + + memset(result, '\0', 128); + } + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test2/testinfo.dat new file mode 100644 index 0000000..e9e1928 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_gcvt/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _gcvt +Name = Call _gcvt on normal values, negatives, exponents and hex digits. +TYPE = DEFAULT +EXE1 = test2 +Description += Call the _gcvt function on a number of cases. Check that it += handles negatives, exponents and hex digits properly. Also check that += the 'digit' specification works. (And that it doesn't truncate negative += signs or decimals) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/test1/CMakeLists.txt new file mode 100644 index 0000000..31a173c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_isnan_test1 + ${SOURCES} +) + +add_dependencies(paltest_isnan_test1 coreclrpal) + +target_link_libraries(paltest_isnan_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/test1/test1.cpp new file mode 100644 index 0000000..d793c9b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/test1/test1.cpp @@ -0,0 +1,115 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Test _isnan with a number of trivial values, to ensure they indicated that +** they are numbers. Then try with Positive/Negative Infinite, which should +** also be numbers. Finally set the least and most significant bits of +** the fraction to positive and negative, at which point it should return +** the true value. +** +**==========================================================================*/ + +#include + +#define TO_DOUBLE(x) (*((double*)((void*)&x))) +#define TO_I64(x) (*((INT64*)((void*)&x))) + +/* + * NaN: any double with maximum exponent (0x7ff) and non-zero fraction + */ +int __cdecl main(int argc, char *argv[]) +{ + /* + * Initialize the PAL and return FAIL if this fails + */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + /* + * Try some trivial values + */ + if (_isnan(0.0)) + { + Fail("_isnan() incorrectly identified %f as NaN!\n", 0.0); + } + + if (_isnan(1.23456)) + { + Fail("_isnan() incorrectly identified %f as NaN!\n", 1.234567); + } + + if (_isnan(42.0)) + { + Fail("_isnan() incorrectly identified %f as NaN!\n", 42.0); + } + + UINT64 lneginf = UI64(0xfff0000000000000); + UINT64 lposinf = UI64(0x7ff0000000000000); + + double neginf = TO_DOUBLE(lneginf); + double posinf = TO_DOUBLE(lposinf); + + /* + * Try positive and negative infinity + */ + if (_isnan(neginf)) + { + Fail("_isnan() incorrectly identified negative infinity as NaN!\n"); + } + + if (_isnan(posinf)) + { + Fail("_isnan() incorrectly identified infinity as NaN!\n"); + } + + /* + * Try setting the least significant bit of the fraction, + * positive and negative + */ + UINT64 lsnan = UI64(0xfff0000000000001); + double snan = TO_DOUBLE(lsnan); + + if (!_isnan(snan)) + { + Fail("_isnan() failed to identify %I64x as NaN!\n", lsnan); + } + + UINT64 lqnan = UI64(0x7ff0000000000001); + double qnan = TO_DOUBLE(lqnan); + + if (!_isnan(qnan)) + { + Fail("_isnan() failed to identify %I64x as NaN!\n", lqnan); + } + + /* + * Try setting the most significant bit of the fraction, + * positive and negative + */ + lsnan = UI64(0xfff8000000000000); + snan = TO_DOUBLE(lsnan); + + if (!_isnan(snan)) + { + Fail ("_isnan() failed to identify %I64x as NaN!\n", lsnan); + } + + lqnan = UI64(0x7ff8000000000000); + qnan = TO_DOUBLE(lqnan); + + if (!_isnan(qnan)) + { + Fail ("_isnan() failed to identify %I64x as NaN!\n", lqnan); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/test1/testinfo.dat new file mode 100644 index 0000000..d5de17e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnan/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _isnan +Name = Test #1 for _isnan +TYPE = DEFAULT +EXE1 = test1 +Description += Test _isnan with a number of trivial values, to ensure they indicated that += they are numbers. Then try with Positive/Negative Infinite, which should += also be numbers. Finally set the least and most significant bits of += the fraction to positive and negative, at which point it should return += the true value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/test1/CMakeLists.txt new file mode 100644 index 0000000..2189a70 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_isnanf_test1 + ${SOURCES} +) + +add_dependencies(paltest_isnanf_test1 coreclrpal) + +target_link_libraries(paltest_isnanf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/test1/test1.c new file mode 100644 index 0000000..9b75a72 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/test1/test1.c @@ -0,0 +1,115 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Test _isnanf with a number of trivial values, to ensure they indicated that +** they are numbers. Then try with Positive/Negative Infinite, which should +** also be numbers. Finally set the least and most significant bits of +** the fraction to positive and negative, at which point it should return +** the true value. +** +**==========================================================================*/ + +#include + +#define TO_FLOAT(x) (*((float*)((void*)&x))) +#define TO_I32(x) (*((INT32*)((void*)&x))) + +/* + * NaN: any float with maximum exponent (0x7f8) and non-zero fraction + */ +int __cdecl main(int argc, char *argv[]) +{ + /* + * Initialize the PAL and return FAIL if this fails + */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + /* + * Try some trivial values + */ + if (_isnanf(0.0f)) + { + Fail("_isnanf() incorrectly identified %f as NaN!\n", 0.0f); + } + + if (_isnanf(1.234567f)) + { + Fail("_isnanf() incorrectly identified %f as NaN!\n", 1.234567f); + } + + if (_isnanf(42.0f)) + { + Fail("_isnanf() incorrectly identified %f as NaN!\n", 42.0f); + } + + UINT32 lneginf = 0xff800000u; + UINT32 lposinf = 0x7f800000u; + + float neginf = TO_FLOAT(lneginf); + float posinf = TO_FLOAT(lposinf); + + /* + * Try positive and negative infinity + */ + if (_isnanf(neginf)) + { + Fail("_isnanf() incorrectly identified negative infinity as NaN!\n"); + } + + if (_isnanf(posinf)) + { + Fail("_isnanf() incorrectly identified infinity as NaN!\n"); + } + + /* + * Try setting the least significant bit of the fraction, + * positive and negative + */ + UINT32 lsnan = 0xff800001u; + float snan = TO_FLOAT(lsnan); + + if (!_isnanf(snan)) + { + Fail("_isnanf() failed to identify %I32x as NaN!\n", lsnan); + } + + UINT32 lqnan = 0x7f800001u; + float qnan = TO_FLOAT(lqnan); + + if (!_isnanf(qnan)) + { + Fail("_isnanf() failed to identify %I32x as NaN!\n", lqnan); + } + + /* + * Try setting the most significant bit of the fraction, + * positive and negative + */ + lsnan = 0xffc00000u; + snan = TO_FLOAT(lsnan); + + if (!_isnanf(snan)) + { + Fail ("_isnanf() failed to identify %I32x as NaN!\n", lsnan); + } + + lqnan = 0x7fc00000u; + qnan = TO_FLOAT(lqnan); + + if (!_isnanf(qnan)) + { + Fail ("_isnanf() failed to identify %I32x as NaN!\n", lqnan); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/test1/testinfo.dat new file mode 100644 index 0000000..22b0edb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_isnanf/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _isnanf +Name = Test #1 for _isnanf +TYPE = DEFAULT +EXE1 = test1 +Description += Test _isnanf with a number of trivial values, to ensure they indicated that += they are numbers. Then try with Positive/Negative Infinite, which should += also be numbers. Finally set the least and most significant bits of += the fraction to positive and negative, at which point it should return += the true value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/test1/CMakeLists.txt new file mode 100644 index 0000000..2c3d4ac --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_itow_test1 + ${SOURCES} +) + +add_dependencies(paltest_itow_test1 coreclrpal) + +target_link_libraries(paltest_itow_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/test1/test1.cpp new file mode 100644 index 0000000..c8167ed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/test1/test1.cpp @@ -0,0 +1,101 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the _itow_s function. +** Test a number of ints with different radix on each, +** to ensure that the string returned is correct. +** +** +**===================================================================*/ + +#define UNICODE + +#include + +struct testCase +{ + char16_t *CorrectResult; + int value; + int radix; +}; + +int __cdecl main(int argc, char **argv) +{ + + char16_t result[20]; + char16_t *pResult = NULL; + char *PrintResult = NULL; /* Use with convertC so we can */ + char *PrintCorrectResult = NULL; /* print out the results */ + int i = 0; + + WCHAR case1[] = {'5','0','\0'}; + WCHAR case2[] = {'5','5','5','\0'}; + WCHAR case3[] = {'1','0','1','0','\0'}; + WCHAR case4[] = {'2','2','\0'}; + WCHAR case5[] = {'a','\0'}; + WCHAR case6[] = {'c','g','\0'}; + + /* Correct Result, Value to Convert, Radix to use */ + struct testCase testCases[] = + { + {case1, 50, 10}, + {case2,555,10}, + {case3,10,2}, + {case4,10,4}, + {case5,10,16}, + {case6,400,32} + }; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Loop through each case. Convert the ints to strings. Check + to ensure they were converted properly. + */ + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + errno_t err = _itow_s(testCases[i].value, result, sizeof(result) / sizeof(result[0]), testCases[i].radix); + + if(err != 0) + { + Fail("ERROR: _itow_s didn't return success, error code %d.\n", err); + } + + if (0 != wcscmp(testCases[i].CorrectResult, result)) + { + PrintResult = convertC(pResult); + PrintCorrectResult = convertC(testCases[i].CorrectResult); + Fail("ERROR: _itow_s was called on %i, returning the string %s " + "when it should have returned the string %s.\n" + , testCases[i].value, PrintResult, PrintCorrectResult); + } + + } + + PAL_Terminate(); + return PASS; +} + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/test1/testinfo.dat new file mode 100644 index 0000000..91f0e62 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_itow/test1/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _itow_s +Name = Positive Test for _itow_s +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the _itow_s function. += Test a number of ints with different radix on each, to ensure that the += string returned is correct. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/CMakeLists.txt new file mode 100644 index 0000000..37d4768 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_mbsdec_test1 + ${SOURCES} +) + +add_dependencies(paltest_mbsdec_test1 coreclrpal) + +target_link_libraries(paltest_mbsdec_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/test1.cpp new file mode 100644 index 0000000..1cd7513 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/test1.cpp @@ -0,0 +1,77 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Ensure that this function moves the string pointer back one character. +** First do a basic test to check that the pointer gets moved back the one +** character, given str1 and str+1 as params. Then try with both +** params being the same pointer, which should return NULL. Also test +** when the first pointer is past the second pointer, which should +** return null. Finally try this function on an array of single bytes, +** which it assumes are characters and should work in the same fashion. +** +** +**==========================================================================*/ + +#include + +/* + * Note: it seems like these functions would only be useful if they + * didn't assume a character was equivalent to a single byte. Be that + * as it may, I haven't seen a way to get it to behave otherwise. + */ + +int __cdecl main(int argc, char *argv[]) +{ + unsigned char *str1 = (unsigned char*) "foo"; + unsigned char str2[] = {0xC0, 0x80, 0xC0, 0x80, 0}; + unsigned char str3[] = {0}; + unsigned char *ret = NULL; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + ret = _mbsdec(str1,str1+1); + if (ret != str1) + { + Fail ("ERROR: _mbsdec returned %p. Expected %p\n", ret, str1); + } + + ret = _mbsdec(str1,str1); + if (ret != NULL) + { + Fail ("ERROR: _mbsdec returned %p. Expected %p\n", ret, NULL); + } + + ret = _mbsdec(str1+100,str1); + if (ret != NULL) + { + Fail ("ERROR: _mbsdec returned %p. Expected %p\n", ret, NULL); + } + + ret = _mbsdec(str2,str2+1); + if (ret != str2) + { + Fail ("ERROR: _mbsdec returned %p. Expected %p\n", ret, str2+1); + } + + ret = _mbsdec(str3,str3+10); + if (ret != str3+9) + { + Fail ("ERROR: _mbsdec returned %p. Expected %p\n", ret, str3+9); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/testinfo.dat new file mode 100644 index 0000000..ce2aa29 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _mbsdec +Name = Positive Test for _mbsdec +TYPE = DEFAULT +EXE1 = test1 +Description += Ensure that this function moves the string pointer back one character. += First do a basic test to check that the pointer gets moved back the one += character, given str1 and str+1 as params. Then try with both += params being the same pointer, which should return NULL. Also test += when the first pointer is past the second pointer, which should += return null. Finally try this function on an array of single bytes, += which it assumes are characters and should work in the same fashion. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/CMakeLists.txt new file mode 100644 index 0000000..d5f7ad3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_mbsinc_test1 + ${SOURCES} +) + +add_dependencies(paltest_mbsinc_test1 coreclrpal) + +target_link_libraries(paltest_mbsinc_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/test1.cpp new file mode 100644 index 0000000..95a5041 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/test1.cpp @@ -0,0 +1,62 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Ensure that this function moves the string pointer ahead one character. +** First do a basic test to check that the pointer gets moved ahead the one +** character. Then try with an array of bytes and a NULL array. Each of +** these should still work by returning a pointer to thePointer+1. +** +** +**==========================================================================*/ + +#include + +/* + * Note: it seems like these functions would only be useful if they + * didn't assume a character was equivalent to a single byte. Be that + * as it may, I haven't seen a way to get it to behave otherwise. + */ + +int __cdecl main(int argc, char *argv[]) +{ + unsigned char *str1 = (unsigned char*) "foo"; + unsigned char str2[] = {0xC0, 0x80, 0xC0, 0x80, 0}; + unsigned char str3[] = {0}; + unsigned char *ret=NULL; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + ret = _mbsinc(str1); + if (ret != str1 + 1) + { + Fail ("ERROR: _mbsinc returned %p. Expected %p\n", ret, str1); + } + + ret = _mbsinc(str2); + if (ret != str2 + 1) + { + Fail ("ERROR: _mbsinc returned %p. Expected %p\n", ret, str1); + } + + ret = _mbsinc(str3); + if (ret != str3 + 1) + { + Fail ("ERROR: _mbsinc returned %p. Expected %p\n", ret, str1); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/testinfo.dat new file mode 100644 index 0000000..3f3883f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _mbsinc +Name = Positive Test for _mbsinc +TYPE = DEFAULT +EXE1 = test1 +Description += Ensure that this function moves the string pointer ahead one character. += First do a basic test to check that the pointer gets moved ahead the one += character. Then try with an array of bytes and a NULL array. Each of += these should still work by returning a pointer to thePointer+1. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/CMakeLists.txt new file mode 100644 index 0000000..523e862 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_mbsninc_test1 + ${SOURCES} +) + +add_dependencies(paltest_mbsninc_test1 coreclrpal) + +target_link_libraries(paltest_mbsninc_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/test1.cpp new file mode 100644 index 0000000..59ef50d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/test1.cpp @@ -0,0 +1,65 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Ensure that this functions increases a string pointer by n characters. +** Use a for loop, and increase the pointer by a different number of characters +** on each iteration, ensure that it is indeed pointing to the correct location +** each time. The second test checks to see if you attempt to increase the +** pointer past the end of the string, the pointer should just point at the +** last character. +** +** +**==========================================================================*/ + +#include + +/* + * Note: it seems like these functions would only be useful if they + * didn't assume a character was equivalent to a single byte. Be that + * as it may, I haven't seen a way to get it to behave otherwise. + */ + +int __cdecl main(int argc, char *argv[]) +{ + unsigned char str[] = {0xC0, 0x80, 0xC0, 0x80, 0}; + int i=0; + unsigned char *ret=NULL; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + for (i=0; i<5; i++) + { + ret = _mbsninc(str, i); + if (ret != str + i) + { + Fail ("ERROR: _mbsninc returned %p. Expected %p\n", ret, str+i); + } + } + + /* + * trying to advance past the end of the string should just + * return the end. + */ + ret = _mbsninc(str, 5); + if (ret != str + 4) + { + Fail ("ERROR: _mbsninc returned %p. Expected %p\n", ret, str+4); + } + + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/testinfo.dat new file mode 100644 index 0000000..b855222 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _mbsninc +Name = Positive Test for _mbsninc +TYPE = DEFAULT +EXE1 = test1 +Description += Ensure that this functions increases a string pointer by n characters. += Use a for loop, and increase the pointer by a different number of characters += on each iteration, ensure that it is indeed pointing to the correct location += each time. The second test checks to see if you attempt to increase the += pointer past the end of the string, the pointer should just point at the += last character. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/CMakeLists.txt new file mode 100644 index 0000000..070e421 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test1/CMakeLists.txt new file mode 100644 index 0000000..2d7d383 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_putenv_test1 + ${SOURCES} +) + +add_dependencies(paltest_putenv_test1 coreclrpal) + +target_link_libraries(paltest_putenv_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test1/test1.cpp new file mode 100644 index 0000000..2d096ad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test1/test1.cpp @@ -0,0 +1,99 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Create an environment variable with _putenv and then use getenv +** to check it. Check that we get the expected errors with invalid input. +** +** +**===================================================================*/ + +#include + +struct TestElement +{ + char _putenvString[1024]; /* argument string sent to putenv */ + char varName[1024]; /* variable component of argument string */ + char varValue[1024]; /* value component of argument string */ + BOOL bValidString; /* valid argument string identifier */ +}; + +struct TestElement TestCases[] = +{ + {"PalTestingEnvironmentVariable=A value", "PalTestingEnvironmentVariable", + "A value", TRUE}, + {"AnotherVariable=", "AnotherVariable", "", TRUE}, + {"YetAnotherVariable", "", "", FALSE}, + {"=ADifferentVariable", "", "ADifferentVariable", FALSE}, + {"", "", "", FALSE} + +}; + +int __cdecl main(int argc, char **argv) +{ + + int i; + char *variableValue; + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + for (i = 0; i < (sizeof(TestCases)/sizeof(struct TestElement)) ; i++) + { + if((_putenv(TestCases[i]._putenvString) == -1) && + ( TestCases[i].bValidString == TRUE)) + { + Fail("ERROR: _putenv failed to set an environment " + "variable with a valid format.\n Call was" + "_putenv(%s)\n", TestCases[i]._putenvString); + } + /* + * For valid _putenvString values, check to see the variable was set + */ + if (TestCases[i].bValidString == TRUE) + { + variableValue = getenv(TestCases[i].varName); + + if (variableValue == NULL) + { + if (*TestCases[i].varValue != '\0') + { + Fail("ERROR: getenv(%s) call returned NULL.\nThe call " + "should have returned \"%s\"\n", TestCases[i].varName + , TestCases[i].varValue); + } + } + else if ( strcmp(variableValue, TestCases[i].varValue) != 0) + { + Fail("ERROR: _putenv(%s)\nshould have set the variable " + "%s\n to \"%s\".\nA subsequent call to getenv(%s)\n" + "returned \"%s\" instead.\n", TestCases[i]._putenvString + , TestCases[i].varName, TestCases[i].varValue + , TestCases[i].varName, variableValue); + } + } + else + /* + * Check to see that putenv fails for malformed _putenvString values + */ + { + variableValue = getenv(TestCases[i].varName); + + if (variableValue != NULL) + { + Fail("ERROR: getenv(%s) call should have returned NULL.\n" + "Instead it returned \"%s\".\n", TestCases[i].varName + , TestCases[i].varValue); + } + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test1/testinfo.dat new file mode 100644 index 0000000..d097818 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _putenv +Name = Positive test for _putenv +TYPE = DEFAULT +EXE1 = test1 +Description += Create an environment variable with _putenv and then use getenv to += check it. Check that we get the expected errors with invalid input. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test2/CMakeLists.txt new file mode 100644 index 0000000..41a75fa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_putenv_test2 + ${SOURCES} +) + +add_dependencies(paltest_putenv_test2 coreclrpal) + +target_link_libraries(paltest_putenv_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test2/test2.cpp new file mode 100644 index 0000000..39be4f6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test2/test2.cpp @@ -0,0 +1,76 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Create an environment variable with _putenv and then use getenv +** to check it. This test resets an environment variable. +** +** +**===================================================================*/ + +#include + +const char *_putenvString0 = "AnUnusualVariable=AnUnusualValue"; +const char *_putenvString1 = "AnUnusualVariable="; +const char *variable = "AnUnusualVariable"; +const char *value = "AnUnusualValue"; + +int __cdecl main(int argc, char **argv) +{ + + char *variableValue; + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + if(_putenv(_putenvString0) == -1) + { + Fail("ERROR: _putenv failed to set an environment " + "variable with a valid format.\n Call was" + "_putenv(%s)\n", _putenvString0); + } + + variableValue = getenv(variable); + + if (variableValue == NULL) + { + Fail("ERROR: getenv(%s) call returned NULL\nThe call " + "should have returned '%s'\n", variable, value); + } + else + { + if ( strcmp(variableValue, value) != 0 ) + { + Fail("ERROR: _putenv(%s)\nshould have set the variable " + "'%s'\n to '%s'.\nA subsequent call to getenv(%s)\n" + "returned '%s' instead.\n", _putenvString0, + variable, value, variable, variableValue); + } + else + { + if(_putenv(_putenvString1) == -1) + { + Fail("ERROR: _putenv failed to set an environment " + "variable with a valid format.\n Call was" + "_putenv(%s)\n", _putenvString1); + } + + variableValue = getenv(variable); + + if (variableValue != NULL) + { + Fail("ERROR: getenv(%s) call did not return NULL.\nThe call " + "returned '%s'.\n", variable, value); + } + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test2/testinfo.dat new file mode 100644 index 0000000..8d3a6ce --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _putenv +Name = Positive test for _putenv +TYPE = DEFAULT +EXE1 = test2 +Description += Create an environment variable with _putenv and then use getenv to += check it. This test resets an environment variable. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test3/CMakeLists.txt new file mode 100644 index 0000000..a3bab40 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_putenv_test3 + ${SOURCES} +) + +add_dependencies(paltest_putenv_test3 coreclrpal) + +target_link_libraries(paltest_putenv_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test3/test3.cpp new file mode 100644 index 0000000..8aa6777 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test3/test3.cpp @@ -0,0 +1,102 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Create environment variables that differ only in Case, and +** verify that the BSD operating system treats the variables +** differently. +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ +#if WIN32 + + return PASS; + +#else + + const char* FirstVariable = "PalTestingEnvironmentVariable=The value"; + const char* SecondVariable = "PALTESTINGEnvironmentVariable=Different value"; + const char* FirstVarName = "PalTestingEnvironmentVariable"; + const char* FirstVarValue = "The value"; + char* result; + + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Use _putenv to set an environment variable. This ensures that the + variable we're testing on is always present. + */ + + if(_putenv(FirstVariable) != 0) + { + Fail("ERROR: _putenv failed to set an environment variable that " + "getenv will be using for testing.\n"); + } + + + /* Call getenv -- ensure it doesn't return NULL and the string it returns + is the value we set above. Also make sure that each environment variable, + differing only by case, returns it's own value. + */ + + result = getenv(FirstVarName); + if(result == NULL) + { + Fail("ERROR: The result of getenv on a valid Environment Variable " + "was NULL, which indicates the environment varaible was not " + "found.\n"); + } + + if(strcmp(result, FirstVarValue) != 0) + { + Fail("ERROR: The value obtained by getenv() was not equal to the " + "correct value of the environment variable. The correct " + "value is '%s' and the function returned '%s'.\n", + FirstVarValue, + result); + } + + /* Set the second environment variable, which only differs in Case */ + if(_putenv(SecondVariable) != 0) + { + Fail("ERROR: _putenv failed to set an environment variable that " + "getenv will be using for testing.\n"); + } + + /* Verify that the environment variables + */ + + result = getenv(FirstVarName); + if(result == NULL) + { + Fail("ERROR: The result of getenv on a valid Environment Variable " + "was NULL, which indicates the environment varaible was not " + "found.\n"); + } + + if(strcmp(result, FirstVarValue) != 0) + { + Fail("ERROR: The value obtained by getenv() was not equal to the " + "correct value of the environment variable. The correct " + "value is '%s' and the function returned '%s'.\n", + FirstVarValue, + result); + } + + PAL_Terminate(); + return PASS; + +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test3/testinfo.dat new file mode 100644 index 0000000..2c6af1b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _putenv +Name = Positive test for _putenv +TYPE = DEFAULT +EXE1 = test3 +Description += Create environment variables that only differ by case += and check that the BSD operating system treats them += as two separate variables. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test4/CMakeLists.txt new file mode 100644 index 0000000..78d1d70 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_putenv_test4 + ${SOURCES} +) + +add_dependencies(paltest_putenv_test4 coreclrpal) + +target_link_libraries(paltest_putenv_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test4/test4.cpp new file mode 100644 index 0000000..48d7ba9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test4/test4.cpp @@ -0,0 +1,75 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c +** +** Purpose: Create an environment variable and try to retrieve +** it using the same name but with different case. This +** is to show that the Win32 representation of _putenv +** is case insensitive. +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ +#if WIN32 + + const char* FirstVariable = "PalTestingEnvironmentVariable=The value"; + const char* ModifiedName = "PALTESTINGEnvironmentVariable"; + const char* FirstVarValue = "The value"; + char* result; + + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Use _putenv to set an environment variable. This ensures that the + variable we're testing on is always present. + */ + + if(_putenv(FirstVariable) != 0) + { + Fail("ERROR: _putenv failed to set an environment variable that " + "getenv will be using for testing.\n"); + } + + + /* Call getenv -- ensure it doesn't return NULL and the string it returns + is the value we set above. Also make sure that each environment variable, + differing only by case, doesn't affect the return value. + */ + + result = getenv(ModifiedName); + if(result == NULL) + { + Fail("ERROR: The result of getenv on a valid Environment Variable " + "was NULL, which indicates the environment varaible was not " + "found.\n"); + } + + if(strcmp(result, FirstVarValue) != 0) + { + Fail("ERROR: The value obtained by getenv() was not equal to the " + "correct value of the environment variable. The correct " + "value is '%s' and the function returned '%s'.\n", + FirstVarValue, + result); + } + + + PAL_Terminate(); + return PASS; + +#else + return PASS; + +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test4/testinfo.dat new file mode 100644 index 0000000..af1a01c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_putenv/test4/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _putenv +Name = Positive test for _putenv +TYPE = DEFAULT +EXE1 = test4 +Description += Create an environment variable and check += that trying to retrieve it using a name with different += case, returns the correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/test1/CMakeLists.txt new file mode 100644 index 0000000..bb04847 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_rotl_test1 + ${SOURCES} +) + +add_dependencies(paltest_rotl_test1 coreclrpal) + +target_link_libraries(paltest_rotl_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/test1/test1.cpp new file mode 100644 index 0000000..3a31388 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/test1/test1.cpp @@ -0,0 +1,55 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c (_rotl) +** +** Purpose: Tests the PAL implementation of the _rotl function. +** The _rotl function rotates the unsigned value. _rotl +** rotates the value left and "wraps" bits rotated off +** one end of value to the other end. +** This test compares the result to a previously determined +** value. +** +** +** +**===================================================================*/ +#include + +int __cdecl main(int argc, char **argv) +{ + unsigned results = 0; + int i,j; + + unsigned hTestNums[5][8] = { + {0x00ff, 0x01fe, 0x03fc, 0x07f8, 0x0ff0, 0x1fe0, 0x3fc0, 0x7f80}, + {0x0055, 0x00aa, 0x0154, 0x02a8, 0x0550, 0x0aa0, 0x1540, 0x2a80}, + {0x0099, 0x0132, 0x0264, 0x04c8, 0x0990, 0x1320, 0x2640, 0x4c80}, + {0x0036, 0x006c, 0x00d8, 0x01b0, 0x0360, 0x06c0, 0x0d80, 0x1b00}, + {0x008f, 0x011e, 0x023c, 0x0478, 0x08f0, 0x11e0, 0x23c0, 0x4780}}; + + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + /*Loop through expected test results*/ + for (j = 0; j <= 4; j++) + { + for(i = 1; i <= 7; i++) + { + results = _rotl(hTestNums[j][0], i); + if (results != hTestNums[j][i]) + { + Fail("ERROR: \"0x%4.4x\" rotated bits to the left %d times" + " gave \"0x%4.4x\", expected \"0x%4.4x\"\n", + hTestNums[j][0], i, results, hTestNums[j][i]) ; + } + } + } + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/test1/testinfo.dat new file mode 100644 index 0000000..9c87473 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotl/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _rtol +Name = Positive Test for _rotl +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the _rotl function. += The _rotl function rotates the unsigned value. _rotl += rotates the value left and "wraps" bits rotated off += one end of value to the other end. += This test compares the result to a previously determined += value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/test1/CMakeLists.txt new file mode 100644 index 0000000..c01bd98 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_rotr_test1 + ${SOURCES} +) + +add_dependencies(paltest_rotr_test1 coreclrpal) + +target_link_libraries(paltest_rotr_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/test1/test1.cpp new file mode 100644 index 0000000..cf461c0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/test1/test1.cpp @@ -0,0 +1,60 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c (_rotr) +** +** Purpose: Tests the PAL implementation of the _rotr function. +** The _rotr function rotates the unsigned value. _rotr +** rotates the value right and "wraps" bits rotated off +** one end of value to the other end. +** This test compares the result to a previously +** determined value. +** +** +**===================================================================*/ +#include + +int __cdecl main(int argc, char **argv) +{ + unsigned results = 0; + int i,j; + + unsigned hTestNums[5][8] = { + {0x00ff, 0x8000007f, 0xc000003f, 0xe000001f, + 0xf000000f, 0xf8000007, 0xfc000003, 0xfe000001}, + {0x0055, 0x8000002a, 0x40000015, 0xa000000a, + 0x50000005, 0xa8000002, 0x54000001, 0xaa000000}, + {0x0099, 0x8000004c, 0x40000026, 0x20000013, + 0x90000009, 0xc8000004, 0x64000002, 0x32000001}, + {0x0036, 0x001b, 0x8000000d, 0xc0000006, + 0x60000003, 0xb0000001, 0xd8000000, 0x6c000000}, + {0x008f, 0x80000047, 0xc0000023, 0xe0000011, + 0xf0000008, 0x78000004, 0x3c000002 ,0x1e000001}}; + + + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + /*Loop through expected test results*/ + for (j = 0; j <= 4; j++) + { + for(i = 1; i <= 7; i++) + { + results = _rotr(hTestNums[j][0], i); + if (results != hTestNums[j][i]) + { + Fail("ERROR: \"0x%4.4x\" rotated bits to the left %d times" + " gave \"0x%4.4x\", expected \"0x%4.4x\"\n", + hTestNums[j][0], i, results, hTestNums[j][i]) ; + } + } + } + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/test1/testinfo.dat new file mode 100644 index 0000000..915f467 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_rotr/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _rtor +Name = Positive Test for _rotr +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the _rotr function. += The _rotr function rotates the unsigned value. _rotr += rotates the value right and "wraps" bits rotated off += one end of value to the other end. += This test compares the result to a previously determined += value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/CMakeLists.txt new file mode 100644 index 0000000..b29c7c4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/CMakeLists.txt @@ -0,0 +1,19 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/_snprintf_s.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/_snprintf_s.h new file mode 100644 index 0000000..9ed5209 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/_snprintf_s.h @@ -0,0 +1,194 @@ +// 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. + +/*============================================================================ +** +** Source: sprintf_s.h +** +** Purpose: Containts common testing functions for sprintf_s +** +** +**==========================================================================*/ + +#ifndef __STRINGTEST_H__ +#define __STRINGTEST_H__ + +void DoStrTest(const char *formatstr, char* param, const char *checkstr) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, formatstr, checkstr, buf); + } +} + +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + convertC(param), formatstr, checkstr, buf); + } +} + + +void DoPointerTest(const char *formatstr, void* param, char* paramstr, char + *checkstr1) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", + paramstr, formatstr, checkstr1, buf); + } +} + +void DoCountTest(const char *formatstr, int param, const char *checkstr) +{ + char buf[512] = { 0 }; + int n = -1; + + sprintf_s(buf, 512, formatstr, &n); + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } +} + +void DoShortCountTest(const char *formatstr, int param, const char *checkstr) +{ + char buf[256] = { 0 }; + short int n = -1; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, &n); + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } +} + +void DoCharTest(const char *formatstr, char param, const char *checkstr) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, param, formatstr, checkstr, buf); + } +} + +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + (char)param, param, formatstr, checkstr, buf); + } +} + +void DoNumTest(const char *formatstr, int value, const char *checkstr) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, value); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert %#x into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + value, formatstr, checkstr, buf); + } +} + +void DoI64Test(const char *formatstr, INT64 value, char *valuestr, const char *checkstr1) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, value); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", + valuestr, formatstr, checkstr1, buf); + } +} + +void DoDoubleTest(const char *formatstr, double value, const char *checkstr1, char +*checkstr2) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, value); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 + && memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + value, formatstr, checkstr1, checkstr2, buf); + } +} + +void DoArgumentPrecTest(const char *formatstr, int precision, void *param, char +*paramstr, const char *checkstr1, const char *checkstr2) +{ + char buf[256]; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, precision, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + paramstr, formatstr, precision, checkstr1, checkstr2, buf); + } + +} + +void DoArgumentPrecDoubleTest(const char *formatstr, int precision, double param, +const char *checkstr1, const char *checkstr2) +{ + char buf[256]; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, precision, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + param, formatstr, precision, checkstr1, checkstr2, buf); + } + +} + +#endif + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/CMakeLists.txt new file mode 100644 index 0000000..0180290 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_snprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test1 coreclrpal) + +target_link_libraries(paltest_snprintf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/test1.cpp new file mode 100644 index 0000000..d180b05 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/test1.cpp @@ -0,0 +1,58 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: General test to see if sprintf_s works correctly +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + char checkstr[] = "hello world"; + char buf[256] = { 0 }; + int ret; + + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + _snprintf_s(buf, 256, _TRUNCATE, "hello world"); + if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0) + { + Fail("ERROR: expected \"%s\" (up to %d chars), got \"%s\"\n", + checkstr, 256, buf); + } + + _snprintf_s(buf, 256, _TRUNCATE, "xxxxxxxxxxxxxxxxx"); + ret = _snprintf_s(buf, 8, _TRUNCATE, "hello world"); + + if (ret >= 0) + { + Fail("ERROR: expected negative return value, got %d", ret); + } + if (memcmp(checkstr, buf, 7) != 0 || buf[7] != 0 || buf[8] != 'x') + { + Fail("ERROR: expected %s (up to %d chars), got %s\n", + checkstr, 8, buf); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/testinfo.dat new file mode 100644 index 0000000..255c534 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test1 +Description += General test to see if sprintf_s works correctly diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/CMakeLists.txt new file mode 100644 index 0000000..2378bee --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_snprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test10 coreclrpal) + +target_link_libraries(paltest_snprintf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/test10.cpp new file mode 100644 index 0000000..7ecb910 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/test10.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test10.c +** +** Purpose: Tests sprintf_s with octal numbers +** +** +**==========================================================================*/ + + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %o", pos, "foo 52"); + DoNumTest("foo %lo", 0xFFFF, "foo 177777"); + DoNumTest("foo %ho", 0xFFFF, "foo 177777"); + DoNumTest("foo %Lo", pos, "foo 52"); + DoI64Test("foo %I64o", l, "42", "foo 52"); + DoNumTest("foo %3o", pos, "foo 52"); + DoNumTest("foo %-3o", pos, "foo 52 "); + DoNumTest("foo %.1o", pos, "foo 52"); + DoNumTest("foo %.3o", pos, "foo 052"); + DoNumTest("foo %03o", pos, "foo 052"); + DoNumTest("foo %#o", pos, "foo 052"); + DoNumTest("foo %+o", pos, "foo 52"); + DoNumTest("foo % o", pos, "foo 52"); + DoNumTest("foo %+o", neg, "foo 37777777726"); + DoNumTest("foo % o", neg, "foo 37777777726"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/testinfo.dat new file mode 100644 index 0000000..25ed554 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test10 +Description += Tests sprintf_s with octal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/CMakeLists.txt new file mode 100644 index 0000000..0eea701 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_snprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test11 coreclrpal) + +target_link_libraries(paltest_snprintf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/test11.cpp new file mode 100644 index 0000000..c2ac015 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/test11.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test11.c +** +** Purpose: Tests sprintf_s with unsigned numbers +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %u", pos, "foo 42"); + DoNumTest("foo %lu", 0xFFFF, "foo 65535"); + DoNumTest("foo %hu", 0xFFFF, "foo 65535"); + DoNumTest("foo %Lu", pos, "foo 42"); + DoI64Test("foo %I64u", l, "42", "foo 42"); + DoNumTest("foo %3u", pos, "foo 42"); + DoNumTest("foo %-3u", pos, "foo 42 "); + DoNumTest("foo %.1u", pos, "foo 42"); + DoNumTest("foo %.3u", pos, "foo 042"); + DoNumTest("foo %03u", pos, "foo 042"); + DoNumTest("foo %#u", pos, "foo 42"); + DoNumTest("foo %+u", pos, "foo 42"); + DoNumTest("foo % u", pos, "foo 42"); + DoNumTest("foo %+u", neg, "foo 4294967254"); + DoNumTest("foo % u", neg, "foo 4294967254"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/testinfo.dat new file mode 100644 index 0000000..3144f12 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test11 +Description += Tests sprintf_s with unsigned numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/CMakeLists.txt new file mode 100644 index 0000000..5d82438 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_snprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test12 coreclrpal) + +target_link_libraries(paltest_snprintf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/test12.cpp new file mode 100644 index 0000000..5217183 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/test12.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Tests sprintf_s with hex numbers (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %x", pos, "foo 1234ab"); + DoNumTest("foo %lx", pos, "foo 1234ab"); + DoNumTest("foo %hx", pos, "foo 34ab"); + DoNumTest("foo %Lx", pos, "foo 1234ab"); + DoI64Test("foo %I64x", l, "0x1234567887654321", "foo 1234567887654321"); + DoNumTest("foo %7x", pos, "foo 1234ab"); + DoNumTest("foo %-7x", pos, "foo 1234ab "); + DoNumTest("foo %.1x", pos, "foo 1234ab"); + DoNumTest("foo %.7x", pos, "foo 01234ab"); + DoNumTest("foo %07x", pos, "foo 01234ab"); + DoNumTest("foo %#x", pos, "foo 0x1234ab"); + DoNumTest("foo %+x", pos, "foo 1234ab"); + DoNumTest("foo % x", pos, "foo 1234ab"); + DoNumTest("foo %+x", neg, "foo ffffffd6"); + DoNumTest("foo % x", neg, "foo ffffffd6"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/testinfo.dat new file mode 100644 index 0000000..ed91cec --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test12 +Description += Tests sprintf_s with hex numbers (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/CMakeLists.txt new file mode 100644 index 0000000..74d1bc8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_snprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test13 coreclrpal) + +target_link_libraries(paltest_snprintf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/test13.cpp new file mode 100644 index 0000000..15e4755 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/test13.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test13.c +** +** Purpose: Tests sprintf_s with hex numbers (uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234AB; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %X", pos, "foo 1234AB"); + DoNumTest("foo %lX", pos, "foo 1234AB"); + DoNumTest("foo %hX", pos, "foo 34AB"); + DoNumTest("foo %LX", pos, "foo 1234AB"); + DoI64Test("foo %I64X", l, "0x1234567887654321", "foo 1234567887654321"); + DoNumTest("foo %7X", pos, "foo 1234AB"); + DoNumTest("foo %-7X", pos, "foo 1234AB "); + DoNumTest("foo %.1X", pos, "foo 1234AB"); + DoNumTest("foo %.7X", pos, "foo 01234AB"); + DoNumTest("foo %07X", pos, "foo 01234AB"); + DoNumTest("foo %#X", pos, "foo 0X1234AB"); + DoNumTest("foo %+X", pos, "foo 1234AB"); + DoNumTest("foo % X", pos, "foo 1234AB"); + DoNumTest("foo %+X", neg, "foo FFFFFFD6"); + DoNumTest("foo % X", neg, "foo FFFFFFD6"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/testinfo.dat new file mode 100644 index 0000000..fd5f530 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test13 +Description += Tests sprintf_s with hex numbers (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/CMakeLists.txt new file mode 100644 index 0000000..b9592c9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_snprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test14 coreclrpal) + +target_link_libraries(paltest_snprintf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/test14.cpp new file mode 100644 index 0000000..331475e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/test14.cpp @@ -0,0 +1,57 @@ +// 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. + +/*============================================================================ +** +** Source: test14.c +** +** Purpose: Tests sprintf_s with exponential format doubles (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %14e", val, "foo 2.560000e+002", + "foo 2.560000e+02"); + DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", + "foo 2.560000e+02 "); + DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02"); + DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", + "foo 2.56000000e+02"); + DoDoubleTest("foo %014e", val, "foo 02.560000e+002", + "foo 002.560000e+02"); + DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02"); + DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/testinfo.dat new file mode 100644 index 0000000..23cf423 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test14 +Description += Tests sprintf_s with exponential format doubles (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/CMakeLists.txt new file mode 100644 index 0000000..fe37360 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_snprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test15 coreclrpal) + +target_link_libraries(paltest_snprintf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/test15.cpp new file mode 100644 index 0000000..d43613b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/test15.cpp @@ -0,0 +1,56 @@ +// 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. + +/*============================================================================ +** +** Source: test15.c +** +** Purpose: Tests sprintf_s with exponential format doubles (uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %14E", val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", + "foo 2.560000E+02 "); + DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02"); + DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", + "foo 2.56000000E+02"); + DoDoubleTest("foo %014E", val, "foo 02.560000E+002", + "foo 002.560000E+02"); + DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02"); + DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/testinfo.dat new file mode 100644 index 0000000..537e6d1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test15 +Description += Tests sprintf_s with exponential format doubles (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/CMakeLists.txt new file mode 100644 index 0000000..049abeb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_snprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test16 coreclrpal) + +target_link_libraries(paltest_snprintf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/test16.cpp new file mode 100644 index 0000000..21cbb1e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/test16.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================================ +** +** Source: test16.c +** +** Purpose: Test #15 for the sprintf_s function +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 "); + DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0"); + DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000"); + DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000"); + DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000"); + DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000"); + DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/testinfo.dat new file mode 100644 index 0000000..4e98ecc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test16 +Description += Tests sprintf_s with decimal point format doubles diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/CMakeLists.txt new file mode 100644 index 0000000..7bd8a42 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_snprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test17 coreclrpal) + +target_link_libraries(paltest_snprintf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/test17.cpp new file mode 100644 index 0000000..d161270 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/test17.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test17.c +** +** Purpose: Tests sprintf_s with compact format doubles (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03"); + DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03"); + DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/testinfo.dat new file mode 100644 index 0000000..5e41e20 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test17 +Description += Tests sprintf_s with compact format doubles (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/CMakeLists.txt new file mode 100644 index 0000000..d61038d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test18.cpp +) + +add_executable(paltest_snprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test18 coreclrpal) + +target_link_libraries(paltest_snprintf_test18 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/test18.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/test18.cpp new file mode 100644 index 0000000..46ec287 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/test18.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test18.c +** +** Purpose: Tests sprintf_s with compact format doubles (uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03"); + DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03"); + DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/testinfo.dat new file mode 100644 index 0000000..06ae3a6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test18 +Description += Tests sprintf_s with compact format doubles (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/CMakeLists.txt new file mode 100644 index 0000000..6d274d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test19.cpp +) + +add_executable(paltest_snprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test19 coreclrpal) + +target_link_libraries(paltest_snprintf_test19 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/test19.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/test19.cpp new file mode 100644 index 0000000..91b1dae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/test19.cpp @@ -0,0 +1,70 @@ +// 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. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose:Tests sprintf_s with argument specified precision +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoArgumentPrecTest("%.*s", 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest("%.*S", 2, (void*)convert("bar"), "bar", "ba", "ba"); + + DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42") ; + DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/testinfo.dat new file mode 100644 index 0000000..7064c01 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test19 +Description += Tests sprintf_s with argument specified precision diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/CMakeLists.txt new file mode 100644 index 0000000..5ce5648 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_snprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test2 coreclrpal) + +target_link_libraries(paltest_snprintf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/test2.cpp new file mode 100644 index 0000000..54ef80b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/test2.cpp @@ -0,0 +1,50 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose:Tests sprintf_s with strings +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoStrTest("foo %s", "bar", "foo bar"); + DoStrTest("foo %hs", "bar", "foo bar"); + DoWStrTest("foo %ls", convert("bar"), "foo bar"); + DoWStrTest("foo %ws", convert("bar"), "foo bar"); + DoStrTest("foo %Ls", "bar", "foo bar"); + DoStrTest("foo %I64s", "bar", "foo bar"); + DoStrTest("foo %5s", "bar", "foo bar"); + DoStrTest("foo %.2s", "bar", "foo ba"); + DoStrTest("foo %5.2s", "bar", "foo ba"); + DoStrTest("foo %-5s", "bar", "foo bar "); + DoStrTest("foo %05s", "bar", "foo 00bar"); + DoStrTest("foo %s", NULL, "foo (null)"); + DoStrTest("foo %hs", NULL, "foo (null)"); + DoWStrTest("foo %ls", NULL, "foo (null)"); + DoWStrTest("foo %ws", NULL, "foo (null)"); + DoStrTest("foo %Ls", NULL, "foo (null)"); + DoStrTest("foo %I64s", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/testinfo.dat new file mode 100644 index 0000000..cce2dc6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test2 +Description += Tests sprintf_s with strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/CMakeLists.txt new file mode 100644 index 0000000..ff4049e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_snprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test3 coreclrpal) + +target_link_libraries(paltest_snprintf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/test3.cpp new file mode 100644 index 0000000..99c25a6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/test3.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Tests sprintf_s with wide strings +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoWStrTest("foo %S", convert("bar"), "foo bar"); + DoStrTest("foo %hS", "bar", "foo bar"); + DoWStrTest("foo %lS", convert("bar"), "foo bar"); + DoWStrTest("foo %wS", convert("bar"), "foo bar"); + DoWStrTest("foo %LS", convert("bar"), "foo bar"); + DoWStrTest("foo %I64S", convert("bar"), "foo bar"); + DoWStrTest("foo %5S", convert("bar"), "foo bar"); + DoWStrTest("foo %.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %5.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %-5S", convert("bar"), "foo bar "); + DoWStrTest("foo %05S", convert("bar"), "foo 00bar"); + DoWStrTest("foo %S", NULL, "foo (null)"); + DoStrTest("foo %hS", NULL, "foo (null)"); + DoWStrTest("foo %lS", NULL, "foo (null)"); + DoWStrTest("foo %wS", NULL, "foo (null)"); + DoWStrTest("foo %LS", NULL, "foo (null)"); + DoWStrTest("foo %I64S", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/testinfo.dat new file mode 100644 index 0000000..cc8de0e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test3 +Description += Tests sprintf_s with wide strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/CMakeLists.txt new file mode 100644 index 0000000..2cbef27 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_snprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test4 coreclrpal) + +target_link_libraries(paltest_snprintf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/test4.cpp new file mode 100644 index 0000000..089e056 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/test4.cpp @@ -0,0 +1,69 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Tests sprintf_s with pointers +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + /* + ** Run only on 64 bit platforms + */ + #if defined(HOST_64BIT) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "0000000000000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); + #else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "00000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); + #endif //defined(HOST_64BIT) + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/testinfo.dat new file mode 100644 index 0000000..f53f784 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test4 +Description += Tests sprintf_s with pointers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/CMakeLists.txt new file mode 100644 index 0000000..2fdc664 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_snprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test6 coreclrpal) + +target_link_libraries(paltest_snprintf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/test6.cpp new file mode 100644 index 0000000..45c9e2b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/test6.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose: Tests sprintf_s with characters +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoCharTest("foo %c", 'b', "foo b"); + DoCharTest("foo %hc", 'b', "foo b"); + DoWCharTest("foo %lc", wc, "foo c"); + DoCharTest("foo %Lc", 'b', "foo b"); + DoCharTest("foo %I64c", 'b', "foo b"); + DoCharTest("foo %5c", 'b', "foo b"); + DoCharTest("foo %.0c", 'b', "foo b"); + DoCharTest("foo %-5c", 'b', "foo b "); + DoCharTest("foo %05c", 'b', "foo 0000b"); + DoCharTest("foo % c", 'b', "foo b"); + DoCharTest("foo %#c", 'b', "foo b"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/testinfo.dat new file mode 100644 index 0000000..06e31e8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name =Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test6 +Description += Tests sprintf_s with characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/CMakeLists.txt new file mode 100644 index 0000000..2e1636b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_snprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test7 coreclrpal) + +target_link_libraries(paltest_snprintf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/test7.cpp new file mode 100644 index 0000000..5c10fc8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/test7.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test7.c +** +** Purpose: Tests sprintf_s with wide characters +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wb = (WCHAR) 'b'; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoWCharTest("foo %C", wb, "foo b"); + DoWCharTest("foo %hC", wb, "foo b"); + DoCharTest("foo %lC", 'c', "foo c"); + DoWCharTest("foo %LC", wb, "foo b"); + DoWCharTest("foo %I64C", wb, "foo b"); + DoWCharTest("foo %5C", wb, "foo b"); + DoWCharTest("foo %.0C", wb, "foo b"); + DoWCharTest("foo %-5C", wb, "foo b "); + DoWCharTest("foo %05C", wb, "foo 0000b"); + DoWCharTest("foo % C", wb, "foo b"); + DoWCharTest("foo %#C", wb, "foo b"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/testinfo.dat new file mode 100644 index 0000000..647c9d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test7 +Description += Tests sprintf_s with wide characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/CMakeLists.txt new file mode 100644 index 0000000..cf43120 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_snprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test8 coreclrpal) + +target_link_libraries(paltest_snprintf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/test8.cpp new file mode 100644 index 0000000..416e357 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/test8.cpp @@ -0,0 +1,56 @@ +// 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. + +/*============================================================================ +** +** Source: test8.c +** +** Purpose: Tests sprintf_s with decimal numbers +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %d", pos, "foo 42"); + DoNumTest("foo %ld", 0xFFFF, "foo 65535"); + DoNumTest("foo %hd", 0xFFFF, "foo -1"); + DoNumTest("foo %Ld", pos, "foo 42"); + DoI64Test("foo %I64d", l, "42", "foo 42"); + DoNumTest("foo %3d", pos, "foo 42"); + DoNumTest("foo %-3d", pos, "foo 42 "); + DoNumTest("foo %.1d", pos, "foo 42"); + DoNumTest("foo %.3d", pos, "foo 042"); + DoNumTest("foo %03d", pos, "foo 042"); + DoNumTest("foo %#d", pos, "foo 42"); + DoNumTest("foo %+d", pos, "foo +42"); + DoNumTest("foo % d", pos, "foo 42"); + DoNumTest("foo %+d", neg, "foo -42"); + DoNumTest("foo % d", neg, "foo -42"); + + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/testinfo.dat new file mode 100644 index 0000000..524834e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test8 +Description += Tests sprintf_s with decimal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/CMakeLists.txt new file mode 100644 index 0000000..646c6de --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_snprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test9 coreclrpal) + +target_link_libraries(paltest_snprintf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/test9.cpp new file mode 100644 index 0000000..18b1cb7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/test9.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test9.c +** +** Purpose: Tests sprintf_s with integer numbers +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %i", pos, "foo 42"); + DoNumTest("foo %li", 0xFFFF, "foo 65535"); + DoNumTest("foo %hi", 0xFFFF, "foo -1"); + DoNumTest("foo %Li", pos, "foo 42"); + DoI64Test("foo %I64i", l, "42", "foo 42"); + DoNumTest("foo %3i", pos, "foo 42"); + DoNumTest("foo %-3i", pos, "foo 42 "); + DoNumTest("foo %.1i", pos, "foo 42"); + DoNumTest("foo %.3i", pos, "foo 042"); + DoNumTest("foo %03i", pos, "foo 042"); + DoNumTest("foo %#i", pos, "foo 42"); + DoNumTest("foo %+i", pos, "foo +42"); + DoNumTest("foo % i", pos, "foo 42"); + DoNumTest("foo %+i", neg, "foo -42"); + DoNumTest("foo % i", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/testinfo.dat new file mode 100644 index 0000000..7c51443 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test9 +Description += Tests sprintf_s with integer numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/CMakeLists.txt new file mode 100644 index 0000000..b29c7c4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/CMakeLists.txt @@ -0,0 +1,19 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/_snwprintf_s.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/_snwprintf_s.h new file mode 100644 index 0000000..19d1921 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/_snwprintf_s.h @@ -0,0 +1,199 @@ +// 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. + +/*============================================================================ +** +** Source: swprintf_s.h +** +** Purpose: Containts common testing functions for swprintf_s +** +** +**==========================================================================*/ + +#ifndef ___SNWPRINTF_H__ +#define ___SNWPRINTF_H__ + +void DoWStrTest(const WCHAR *formatstr, WCHAR *param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, param); + + if (memcmp(buf, checkstr, wcslen(checkstr) * 2 + 2) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", convertC(param), + convertC(formatstr), convertC(checkstr), convertC(buf)); + } +} + +void DoStrTest(const WCHAR *formatstr, char *param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, param); + + if (memcmp(buf, checkstr, wcslen(checkstr) * 2 + 2) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", + param, convertC(formatstr), convertC(checkstr), convertC(buf)); + } +} + +void DoPointerTest(const WCHAR *formatstr, void* param, const WCHAR *checkstr1) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0) + { + Fail("ERROR: failed to insert pointer to %#p into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", param, convertC(formatstr), + convertC(checkstr1), convertC(buf)); + } +} + +void DoCountTest(const WCHAR *formatstr, int param, const WCHAR *checkstr) +{ + WCHAR buf[512] = { 0 }; + int n = -1; + + swprintf_s(buf, 512, formatstr, &n); + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %d\n", + param, n); + } + + if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", + convertC(checkstr), convertC(buf)); + } +} + +void DoShortCountTest(const WCHAR *formatstr, int param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + short int n = -1; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, &n); + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %d\n", + param, n); + } + + if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", + convertC(checkstr), convertC(buf)); + } +} + +void DoCharTest(const WCHAR *formatstr, char param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0) + { + Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", param, param, + convertC(formatstr), convertC(checkstr), convertC(buf)); + } +} + +void DoWCharTest(const WCHAR *formatstr, WCHAR param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0) + { + Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", (char) param, param, + convertC(formatstr), convertC(checkstr), convertC(buf)); + } +} + +void DoNumTest(const WCHAR *formatstr, int value, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, value); + if (memcmp(buf, checkstr, wcslen(checkstr)* 2 + 2) != 0) + { + Fail("ERROR: failed to insert %#x into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", value, convertC(formatstr), + convertC(checkstr), convertC(buf)); + } +} + + +void DoI64Test(const WCHAR *formatstr, INT64 param, char *paramdesc, + const WCHAR *checkstr1) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", paramdesc, + convertC(formatstr), convertC(checkstr1), convertC(buf)); + } +} + +void DoDoubleTest(const WCHAR *formatstr, double value, const WCHAR *checkstr1, + const WCHAR *checkstr2) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, value); + if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2)*2 + 2) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + value, convertC(formatstr), convertC(checkstr1), + convertC(checkstr2), convertC(buf)); + } +} + +void DoArgumentPrecTest(const WCHAR *formatstr, int precision, void *param, + char *paramstr, const WCHAR *checkstr1, const WCHAR *checkstr2) +{ + WCHAR buf[256]; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, precision, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + paramstr, convertC(formatstr), precision, + convertC(checkstr1), convertC(checkstr2) ,convertC(buf)); + } +} + +void DoArgumentPrecDoubleTest(const WCHAR *formatstr, int precision, double param, + const WCHAR *checkstr) +{ + WCHAR buf[256]; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, precision, param); + if (memcmp(buf, checkstr, wcslen(checkstr) + 2) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\", got \"%s\".\n", param, convertC(formatstr), + precision, convertC(checkstr), convertC(buf)); + } +} + +#endif + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/CMakeLists.txt new file mode 100644 index 0000000..9650c18 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_snwprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test1 coreclrpal) + +target_link_libraries(paltest_snwprintf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/test1.cpp new file mode 100644 index 0000000..ba85103 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/test1.cpp @@ -0,0 +1,62 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: General test to see if swprintf_s works correctly +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR *checkstr; + WCHAR buf[256] = { 0 }; + int ret; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + checkstr = convert("hello world"); + _snwprintf_s(buf, 256, _TRUNCATE, checkstr); + if (memcmp(checkstr, buf, wcslen(checkstr)*2+2) != 0) + { + Fail("ERROR: Expected \"%s\", got \"%s\"\n", + convertC(checkstr), convertC(buf)); + } + + _snwprintf_s(buf, 256, _TRUNCATE, convert("xxxxxxxxxxxxxxxxx")); + ret = _snwprintf_s(buf, 8, _TRUNCATE, checkstr); + if ((memcmp(checkstr, buf, 14) != 0) || (buf[7] != 0)) + { + Fail("ERROR: Expected \"%8s\", got \"%8s\"\n", + convertC(checkstr), convertC(buf)); + } + if (ret >= 0) + { + Fail("ERROR: Expected negative return value, got %d.\n", ret); + } + if (buf[8] != (WCHAR) 'x') + { + Fail("ERROR: buffer overflow using \"%s\" with length 8.\n", + convertC(checkstr)); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/testinfo.dat new file mode 100644 index 0000000..96d7914 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test1 +Description += General test to see if swprintf_s works correctly diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/CMakeLists.txt new file mode 100644 index 0000000..aa799bd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_snwprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test10 coreclrpal) + +target_link_libraries(paltest_snwprintf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/test10.cpp new file mode 100644 index 0000000..298f82b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/test10.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test10.c +** +** Purpose: Tests swprintf_s with octal numbers +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %o"), pos, convert("foo 52")); + DoNumTest(convert("foo %lo"), 0xFFFF, convert("foo 177777")); + DoNumTest(convert("foo %ho"), 0xFFFF, convert("foo 177777")); + DoNumTest(convert("foo %Lo"), pos, convert("foo 52")); + DoI64Test(convert("foo %I64o"), l, "42", convert("foo 52")); + DoNumTest(convert("foo %3o"), pos, convert("foo 52")); + DoNumTest(convert("foo %-3o"), pos, convert("foo 52 ")); + DoNumTest(convert("foo %.1o"), pos, convert("foo 52")); + DoNumTest(convert("foo %.3o"), pos, convert("foo 052")); + DoNumTest(convert("foo %03o"), pos, convert("foo 052")); + DoNumTest(convert("foo %#o"), pos, convert("foo 052")); + DoNumTest(convert("foo %+o"), pos, convert("foo 52")); + DoNumTest(convert("foo % o"), pos, convert("foo 52")); + DoNumTest(convert("foo %+o"), neg, convert("foo 37777777726")); + DoNumTest(convert("foo % o"), neg, convert("foo 37777777726")); + + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/testinfo.dat new file mode 100644 index 0000000..887bbf7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test10 +Description += Tests swprintf_s with octal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/CMakeLists.txt new file mode 100644 index 0000000..7e2ef00 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_snwprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test11 coreclrpal) + +target_link_libraries(paltest_snwprintf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/test11.cpp new file mode 100644 index 0000000..5196687 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/test11.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test11.c +** +** Purpose: Tests swprintf_s with unsigned numbers +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %u"), pos, convert("foo 42")); + DoNumTest(convert("foo %lu"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hu"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %Lu"), pos, convert("foo 42")); + DoI64Test(convert("foo %I64u"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3u"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3u"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1u"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3u"), pos, convert("foo 042")); + DoNumTest(convert("foo %03u"), pos, convert("foo 042")); + DoNumTest(convert("foo %#u"), pos, convert("foo 42")); + DoNumTest(convert("foo %+u"), pos, convert("foo 42")); + DoNumTest(convert("foo % u"), pos, convert("foo 42")); + DoNumTest(convert("foo %+u"), neg, convert("foo 4294967254")); + DoNumTest(convert("foo % u"), neg, convert("foo 4294967254")); + + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/testinfo.dat new file mode 100644 index 0000000..3bda85e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test11 +Description += Tests swprintf_s with unsigned numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/CMakeLists.txt new file mode 100644 index 0000000..e43e347 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_snwprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test12 coreclrpal) + +target_link_libraries(paltest_snwprintf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/test12.cpp new file mode 100644 index 0000000..52780af --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/test12.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Tests swprintf_s with hex numbers (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %lx"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %hx"), pos, convert("foo 34ab")); + DoNumTest(convert("foo %Lx"), pos, convert("foo 1234ab")); + DoI64Test(convert("foo %I64x"), l, "0x1234567887654321", + convert("foo 1234567887654321")); + DoNumTest(convert("foo %7x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %-7x"), pos, convert("foo 1234ab ")); + DoNumTest(convert("foo %.1x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %.7x"), pos, convert("foo 01234ab")); + DoNumTest(convert("foo %07x"), pos, convert("foo 01234ab")); + DoNumTest(convert("foo %#x"), pos, convert("foo 0x1234ab")); + DoNumTest(convert("foo %+x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo % x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %+x"), neg, convert("foo ffffffd6")); + DoNumTest(convert("foo % x"), neg, convert("foo ffffffd6")); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/testinfo.dat new file mode 100644 index 0000000..d808a3b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test12 +Description += Tests swprintf_s with hex numbers (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/CMakeLists.txt new file mode 100644 index 0000000..a1bb54c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_snwprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test13 coreclrpal) + +target_link_libraries(paltest_snwprintf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/test13.cpp new file mode 100644 index 0000000..fa948b3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/test13.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test13.c +** +** Purpose: Tests swprintf_s with hex numbers (uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %lX"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %hX"), pos, convert("foo 34AB")); + DoNumTest(convert("foo %LX"), pos, convert("foo 1234AB")); + DoI64Test(convert("foo %I64X"), l, "0x1234567887654321", + convert("foo 1234567887654321")); + DoNumTest(convert("foo %7X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %-7X"), pos, convert("foo 1234AB ")); + DoNumTest(convert("foo %.1X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %.7X"), pos, convert("foo 01234AB")); + DoNumTest(convert("foo %07X"), pos, convert("foo 01234AB")); + DoNumTest(convert("foo %#X"), pos, convert("foo 0X1234AB")); + DoNumTest(convert("foo %+X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo % X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %+X"), neg, convert("foo FFFFFFD6")); + DoNumTest(convert("foo % X"), neg, convert("foo FFFFFFD6")); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/testinfo.dat new file mode 100644 index 0000000..2e5800e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test13 +Description += Tests swprintf_s with hex numbers (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/CMakeLists.txt new file mode 100644 index 0000000..c6811a5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_snwprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test14 coreclrpal) + +target_link_libraries(paltest_snwprintf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/test14.cpp new file mode 100644 index 0000000..aea289d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/test14.cpp @@ -0,0 +1,66 @@ +// 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. + +/*============================================================================ +** +** Source: test14.c +** +** Purpose: Tests swprintf_s with exponential format doubles (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %le"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %he"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %Le"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %I64e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %14e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %-14e"), val, convert("foo 2.560000e+002 "), + convert("foo 2.560000e+02 ")); + DoDoubleTest(convert("foo %.1e"), val, convert("foo 2.6e+002"), + convert("foo 2.6e+02")); + DoDoubleTest(convert("foo %.8e"), val, convert("foo 2.56000000e+002"), + convert("foo 2.56000000e+02")); + DoDoubleTest(convert("foo %014e"), val, convert("foo 02.560000e+002"), + convert("foo 002.560000e+02")); + DoDoubleTest(convert("foo %#e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %+e"), val, convert("foo +2.560000e+002"), + convert("foo +2.560000e+02")); + DoDoubleTest(convert("foo % e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %+e"), neg, convert("foo -2.560000e+002"), + convert("foo -2.560000e+02")); + DoDoubleTest(convert("foo % e"), neg, convert("foo -2.560000e+002"), + convert("foo -2.560000e+02")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/testinfo.dat new file mode 100644 index 0000000..25bd509 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test14 +Description += Tests swprintf_s with exponential format doubles (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/CMakeLists.txt new file mode 100644 index 0000000..2f68205 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_snwprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test15 coreclrpal) + +target_link_libraries(paltest_snwprintf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/test15.cpp new file mode 100644 index 0000000..14db14b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/test15.cpp @@ -0,0 +1,67 @@ +// 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. + +/*============================================================================ +** +** Source: test15.c +** +** Purpose: Tests swprintf_s with exponential format doubles (uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %lE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %hE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %LE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %I64E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %14E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %-14E"), val, convert("foo 2.560000E+002 "), + convert("foo 2.560000E+02 ")); + DoDoubleTest(convert("foo %.1E"), val, convert("foo 2.6E+002"), + convert("foo 2.6E+02")); + DoDoubleTest(convert("foo %.8E"), val, convert("foo 2.56000000E+002"), + convert("foo 2.56000000E+02")); + DoDoubleTest(convert("foo %014E"), val, convert("foo 02.560000E+002"), + convert("foo 002.560000E+02")); + DoDoubleTest(convert("foo %#E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %+E"), val, convert("foo +2.560000E+002"), + convert("foo +2.560000E+02")); + DoDoubleTest(convert("foo % E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %+E"), neg, convert("foo -2.560000E+002"), + convert("foo -2.560000E+02")); + DoDoubleTest(convert("foo % E"), neg, convert("foo -2.560000E+002"), + convert("foo -2.560000E+02")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/testinfo.dat new file mode 100644 index 0000000..95d90e8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test15 +Description += Tests swprintf_s with exponential format doubles (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/CMakeLists.txt new file mode 100644 index 0000000..f2c44ff --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_snwprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test16 coreclrpal) + +target_link_libraries(paltest_snwprintf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/test16.cpp new file mode 100644 index 0000000..4d9a717 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/test16.cpp @@ -0,0 +1,65 @@ +// 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. + +/*============================================================================ +** +** Source: test16.c +** +** Purpose: Tests swprintf_s with decimal point format doubles +** +** +**==========================================================================*/ + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %lf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %hf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %Lf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %I64f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %12f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %-12f"), val, convert("foo 2560.001000 "), + convert("foo 2560.001000 ")); + DoDoubleTest(convert("foo %.1f"), val, convert("foo 2560.0"), + convert("foo 2560.0")); + DoDoubleTest(convert("foo %.8f"), val, convert("foo 2560.00100000"), + convert("foo 2560.00100000")); + DoDoubleTest(convert("foo %012f"), val, convert("foo 02560.001000"), + convert("foo 02560.001000")); + DoDoubleTest(convert("foo %#f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %+f"), val, convert("foo +2560.001000"), + convert("foo +2560.001000")); + DoDoubleTest(convert("foo % f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %+f"), neg, convert("foo -2560.001000"), + convert("foo -2560.001000")); + DoDoubleTest(convert("foo % f"), neg, convert("foo -2560.001000"), + convert("foo -2560.001000")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/testinfo.dat new file mode 100644 index 0000000..b81c847 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test16 +Description += Tests swprintf_s with decimal point format doubles diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/CMakeLists.txt new file mode 100644 index 0000000..285b750 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_snwprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test17 coreclrpal) + +target_link_libraries(paltest_snwprintf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/test17.cpp new file mode 100644 index 0000000..6af1815 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/test17.cpp @@ -0,0 +1,68 @@ +// 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. + +/*============================================================================ +** +** Source: test17.c +** +** Purpose: Tests swprintf_s with compact format doubles (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %lg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %hg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %Lg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %I64g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %5g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %-5g"), val, convert("foo 2560 "), + convert("foo 2560 ")); + DoDoubleTest(convert("foo %.1g"), val, convert("foo 3e+003"), + convert("foo 3e+03")); + DoDoubleTest(convert("foo %.2g"), val, convert("foo 2.6e+003"), + convert("foo 2.6e+03")); + DoDoubleTest(convert("foo %.12g"), val, convert("foo 2560.001"), + convert("foo 2560.001")); + DoDoubleTest(convert("foo %06g"), val, convert("foo 002560"), + convert("foo 002560")); + DoDoubleTest(convert("foo %#g"), val, convert("foo 2560.00"), + convert("foo 2560.00")); + DoDoubleTest(convert("foo %+g"), val, convert("foo +2560"), + convert("foo +2560")); + DoDoubleTest(convert("foo % g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %+g"), neg, convert("foo -2560"), + convert("foo -2560")); + DoDoubleTest(convert("foo % g"), neg, convert("foo -2560"), + convert("foo -2560")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/testinfo.dat new file mode 100644 index 0000000..d643667 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test17 +Description += Tests swprintf_s with compact format doubles (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/CMakeLists.txt new file mode 100644 index 0000000..4b51cbd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test18.cpp +) + +add_executable(paltest_snwprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test18 coreclrpal) + +target_link_libraries(paltest_snwprintf_test18 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/test18.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/test18.cpp new file mode 100644 index 0000000..020a885 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/test18.cpp @@ -0,0 +1,69 @@ +// 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. + +/*============================================================================ +** +** Source: test18.c +** +** Purpose: Tests swprintf_s with compact format doubles (uppercase) +** +** +**==========================================================================*/ + + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %lG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %hG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %LG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %I64G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %5G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %-5G"), val, convert("foo 2560 "), + convert("foo 2560 ")); + DoDoubleTest(convert("foo %.1G"), val, convert("foo 3E+003"), + convert("foo 3E+03")); + DoDoubleTest(convert("foo %.2G"), val, convert("foo 2.6E+003"), + convert("foo 2.6E+03")); + DoDoubleTest(convert("foo %.12G"), val, convert("foo 2560.001"), + convert("foo 2560.001")); + DoDoubleTest(convert("foo %06G"), val, convert("foo 002560"), + convert("foo 002560")); + DoDoubleTest(convert("foo %#G"), val, convert("foo 2560.00"), + convert("foo 2560.00")); + DoDoubleTest(convert("foo %+G"), val, convert("foo +2560"), + convert("foo +2560")); + DoDoubleTest(convert("foo % G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %+G"), neg, convert("foo -2560"), + convert("foo -2560")); + DoDoubleTest(convert("foo % G"), neg, convert("foo -2560"), + convert("foo -2560")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/testinfo.dat new file mode 100644 index 0000000..dfc2cd5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test18 +Description += Tests swprintf_s with compact format doubles (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/CMakeLists.txt new file mode 100644 index 0000000..966fbb8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test19.cpp +) + +add_executable(paltest_snwprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test19 coreclrpal) + +target_link_libraries(paltest_snwprintf_test19 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/test19.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/test19.cpp new file mode 100644 index 0000000..d335d1d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/test19.cpp @@ -0,0 +1,82 @@ +// 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. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose: Tests swprintf_s with argument specified precision +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoArgumentPrecTest(convert("%.*s"), 2, (void*)convert("bar"), "bar", + convert("ba"), convert("ba")); + DoArgumentPrecTest(convert("%.*S"), 2, (void*)"bar", "bar", + convert("ba"), convert("ba")); + DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', "a", + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', "a", + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', "a", + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', "a", + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, "42", + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, "42", + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, "42", + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, "42", + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, "42", + convert("52"), convert("52")); + DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, "42", + convert("052"), convert("052")); + DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, "42", + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, "42", + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, "0x42", + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, "0x42", + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, "0x42", + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, "0x42", + convert("042"), convert("042")); + DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000")); + DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000")); + DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000")); + DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000")); + DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0")); + DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010")); + DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002")); + DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01")); + DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002")); + DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01")); + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/testinfo.dat new file mode 100644 index 0000000..95269cd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test19 +Description += Tests swprintf_s with argument specified precision diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/CMakeLists.txt new file mode 100644 index 0000000..b4d3844 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_snwprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test2 coreclrpal) + +target_link_libraries(paltest_snwprintf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/test2.cpp new file mode 100644 index 0000000..7d8dd65 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/test2.cpp @@ -0,0 +1,50 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose:Tests swprintf_s with strings +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoWStrTest(convert("foo %s"), convert("bar"), convert("foo bar")); + DoStrTest(convert("foo %hs"), "bar", convert("foo bar")); + DoWStrTest(convert("foo %ls"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %ws"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %Ls"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %I64s"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %5s"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %.2s"), convert("bar"), convert("foo ba")); + DoWStrTest(convert("foo %5.2s"), convert("bar"), convert("foo ba")); + DoWStrTest(convert("foo %-5s"), convert("bar"), convert("foo bar ")); + DoWStrTest(convert("foo %05s"), convert("bar"), convert("foo 00bar")); + DoWStrTest(convert("foo %s"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %hs"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %ls"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %ws"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %Ls"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %I64s"), NULL, convert("foo (null)")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/testinfo.dat new file mode 100644 index 0000000..88f1981 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test2 +Description += Tests swprintf_s with strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/CMakeLists.txt new file mode 100644 index 0000000..115f0d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_snwprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test3 coreclrpal) + +target_link_libraries(paltest_snwprintf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/test3.cpp new file mode 100644 index 0000000..b4a4a32 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/test3.cpp @@ -0,0 +1,50 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Tests swprintf_s with wide strings +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoStrTest(convert("foo %S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %hS"), "bar", convert("foo bar")); + DoWStrTest(convert("foo %lS"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %wS"), convert("bar"), convert("foo bar")); + DoStrTest(convert("foo %LS"), "bar", convert("foo bar")); + DoStrTest(convert("foo %I64S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %5S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %.2S"), "bar", convert("foo ba")); + DoStrTest(convert("foo %5.2S"), "bar", convert("foo ba")); + DoStrTest(convert("foo %-5S"), "bar", convert("foo bar ")); + DoStrTest(convert("foo %05S"), "bar", convert("foo 00bar")); + DoStrTest(convert("foo %S"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %hS"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %lS"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %wS"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %LS"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %I64S"), NULL, convert("foo (null)")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/testinfo.dat new file mode 100644 index 0000000..5ed59e6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test3 +Description += Tests swprintf_s with wide strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/CMakeLists.txt new file mode 100644 index 0000000..27d9761 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_snwprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test4 coreclrpal) + +target_link_libraries(paltest_snwprintf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/test4.cpp new file mode 100644 index 0000000..cdf2728 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/test4.cpp @@ -0,0 +1,71 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Tests swprintf_s with pointers +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest(convert("%p"), NULL, convert("0000000000000000")); + DoPointerTest(convert("%p"), ptr, convert("0000000000123456")); + DoPointerTest(convert("%17p"), ptr, convert(" 0000000000123456")); + DoPointerTest(convert("%17p"), ptr, convert(" 0000000000123456")); + DoPointerTest(convert("%-17p"), ptr, convert("0000000000123456 ")); + DoPointerTest(convert("%+p"), ptr, convert("0000000000123456")); + DoPointerTest(convert("% p"), ptr, convert("0000000000123456")); + DoPointerTest(convert("%#p"), ptr, convert("0X0000000000123456")); + DoPointerTest(convert("%lp"), ptr, convert("00123456")); + DoPointerTest(convert("%hp"), ptr, convert("00003456")); + DoPointerTest(convert("%Lp"), ptr, convert("00123456")); + DoI64Test(convert("%I64p"), lptr, "1234567887654321", + convert("1234567887654321")); +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest(convert("%p"), NULL, convert("00000000")); + DoPointerTest(convert("%p"), ptr, convert("00123456")); + DoPointerTest(convert("%9p"), ptr, convert(" 00123456")); + DoPointerTest(convert("%09p"), ptr, convert(" 00123456")); + DoPointerTest(convert("%-9p"), ptr, convert("00123456 ")); + DoPointerTest(convert("%+p"), ptr, convert("00123456")); + DoPointerTest(convert("% p"), ptr, convert("00123456")); + DoPointerTest(convert("%#p"), ptr, convert("0X00123456")); + DoPointerTest(convert("%lp"), ptr, convert("00123456")); + DoPointerTest(convert("%hp"), ptr, convert("00003456")); + DoPointerTest(convert("%Lp"), ptr, convert("00123456")); + DoI64Test(convert("%I64p"), lptr, "1234567887654321", + convert("1234567887654321")); +#endif + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/testinfo.dat new file mode 100644 index 0000000..2b35f2d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test4 +Description += Tests swprintf_s with pointers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/CMakeLists.txt new file mode 100644 index 0000000..45d428f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_snwprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test6 coreclrpal) + +target_link_libraries(paltest_snwprintf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/test6.cpp new file mode 100644 index 0000000..576e061 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/test6.cpp @@ -0,0 +1,46 @@ +// 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. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose: Tests swprintf_s with characters +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoWCharTest(convert("foo %c"), wc, convert("foo c")); + DoCharTest(convert("foo %hc"), 'b', convert("foo b")); + DoWCharTest(convert("foo %lc"), wc, convert("foo c")); + DoWCharTest(convert("foo %Lc"), wc, convert("foo c")); + DoWCharTest(convert("foo %I64c"), wc, convert("foo c")); + DoWCharTest(convert("foo %5c"), wc, convert("foo c")); + DoWCharTest(convert("foo %.0c"), wc, convert("foo c")); + DoWCharTest(convert("foo %-5c"), wc, convert("foo c ")); + DoWCharTest(convert("foo %05c"), wc, convert("foo 0000c")); + DoWCharTest(convert("foo % c"), wc, convert("foo c")); + DoWCharTest(convert("foo %#c"), wc, convert("foo c")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/testinfo.dat new file mode 100644 index 0000000..d8db7f8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test6 +Description += Tests swprintf_s with characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/CMakeLists.txt new file mode 100644 index 0000000..09a2acf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_snwprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test7 coreclrpal) + +target_link_libraries(paltest_snwprintf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/test7.cpp new file mode 100644 index 0000000..54dd32b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/test7.cpp @@ -0,0 +1,46 @@ +// 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. + +/*============================================================================ +** +** Source: test7.c +** +** Purpose: Tests swprintf_s with wide characters +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoCharTest(convert("foo %C"), 'b', convert("foo b")); + DoWCharTest(convert("foo %hC"), wc, convert("foo c")); + DoCharTest(convert("foo %lC"), 'b', convert("foo b")); + DoCharTest(convert("foo %LC"), 'b', convert("foo b")); + DoCharTest(convert("foo %I64C"), 'b', convert("foo b")); + DoCharTest(convert("foo %5C"), 'b', convert("foo b")); + DoCharTest(convert("foo %.0C"), 'b', convert("foo b")); + DoCharTest(convert("foo %-5C"), 'b', convert("foo b ")); + DoCharTest(convert("foo %05C"), 'b', convert("foo 0000b")); + DoCharTest(convert("foo % C"), 'b', convert("foo b")); + DoCharTest(convert("foo %#C"), 'b', convert("foo b")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/testinfo.dat new file mode 100644 index 0000000..fa5bd30 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test7 +Description += Tests swprintf_s with wide characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/CMakeLists.txt new file mode 100644 index 0000000..ab283e6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_snwprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test8 coreclrpal) + +target_link_libraries(paltest_snwprintf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/test8.cpp new file mode 100644 index 0000000..9f1b555 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/test8.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test8.c +** +** Purpose: Tests swprintf_s with decimal numbers +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %d"), pos, convert("foo 42")); + DoNumTest(convert("foo %ld"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hd"), 0xFFFF, convert("foo -1")); + DoNumTest(convert("foo %Ld"), pos, convert("foo 42")); + DoI64Test(convert("foo %I64d"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3d"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3d"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1d"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3d"), pos, convert("foo 042")); + DoNumTest(convert("foo %03d"), pos, convert("foo 042")); + DoNumTest(convert("foo %#d"), pos, convert("foo 42")); + DoNumTest(convert("foo %+d"), pos, convert("foo +42")); + DoNumTest(convert("foo % d"), pos, convert("foo 42")); + DoNumTest(convert("foo %+d"), neg, convert("foo -42")); + DoNumTest(convert("foo % d"), neg, convert("foo -42")); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/testinfo.dat new file mode 100644 index 0000000..d76a421 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test8 +Description += Tests swprintf_s with decimal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/CMakeLists.txt new file mode 100644 index 0000000..d714bd9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_snwprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test9 coreclrpal) + +target_link_libraries(paltest_snwprintf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/test9.cpp new file mode 100644 index 0000000..76d6063 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/test9.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test9.c +** +** Purpose: Tests swprintf_s with integer numbers +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %i"), pos, convert("foo 42")); + DoNumTest(convert("foo %li"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hi"), 0xFFFF, convert("foo -1")); + DoNumTest(convert("foo %Li"), pos, convert("foo 42")); + DoI64Test(convert("foo %I64i"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3i"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3i"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1i"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3i"), pos, convert("foo 042")); + DoNumTest(convert("foo %03i"), pos, convert("foo 042")); + DoNumTest(convert("foo %#i"), pos, convert("foo 42")); + DoNumTest(convert("foo %+i"), pos, convert("foo +42")); + DoNumTest(convert("foo % i"), pos, convert("foo 42")); + DoNumTest(convert("foo %+i"), neg, convert("foo -42")); + DoNumTest(convert("foo % i"), neg, convert("foo -42")); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/testinfo.dat new file mode 100644 index 0000000..b2a038d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test9 +Description += Tests swprintf_s with integer numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/test1/CMakeLists.txt new file mode 100644 index 0000000..03585f6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_stricmp_test1 + ${SOURCES} +) + +add_dependencies(paltest_stricmp_test1 coreclrpal) + +target_link_libraries(paltest_stricmp_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/test1/test1.cpp new file mode 100644 index 0000000..60e2f9e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/test1/test1.cpp @@ -0,0 +1,70 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Do a lower case compare. Check two strings, only different +** because they have different capitalization, and they should return 0. Try +** two strings which will return less than 0 (one is smaller than the other). +** Also try the opposite, to get a return value greater than 0. +** +** +**==========================================================================*/ + +#include + +/* + * Note: The _stricmp is dependent on the LC_CTYPE category of the locale, + * and this is ignored by these tests. + */ +int __cdecl main(int argc, char *argv[]) +{ + char *str1 = "foo"; + char *str2 = "fOo"; + char *str3 = "foo_bar"; + char *str4 = "foobar"; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + if (_stricmp(str1, str2) != 0) + { + Fail ("ERROR: _stricmp returning incorrect value:\n" + "_stricmp(\"%s\", \"%s\") != 0\n", str1, str2); + } + + if (_stricmp(str2, str3) >= 0) + { + Fail ("ERROR: _stricmp returning incorrect value:\n" + "_stricmp(\"%s\", \"%s\") >= 0\n", str2, str3); + } + + if (_stricmp(str3, str4) >= 0) + { + Fail ("ERROR: _stricmp returning incorrect value:\n" + "_stricmp(\"%s\", \"%s\") >= 0\n", str3, str4); + } + + if (_stricmp(str4, str1) <= 0) + { + Fail ("ERROR: _stricmp returning incorrect value:\n" + "_stricmp(\"%s\", \"%s\") <= 0\n", str4, str1); + } + + if (_stricmp(str3, str2) <= 0) + { + Fail ("ERROR: _stricmp returning incorrect value:\n" + "_stricmp(\"%s\", \"%s\") <= 0\n", str2, str3); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/test1/testinfo.dat new file mode 100644 index 0000000..89d4e0f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_stricmp/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _stricmp +Name = Positive Test for _stricmp +TYPE = DEFAULT +EXE1 = test1 +Description += Do a lower case compare. Check two strings, only different because they += have different capitalization, and they should return 0. Try two strings += which will return less than 0 (one is smaller than the other). Also try += the opposite, to get a return value greater than 0. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/CMakeLists.txt new file mode 100644 index 0000000..6d0e196 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_strnicmp_test1 + ${SOURCES} +) + +add_dependencies(paltest_strnicmp_test1 coreclrpal) + +target_link_libraries(paltest_strnicmp_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/test1.cpp new file mode 100644 index 0000000..3c915dc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/test1.cpp @@ -0,0 +1,85 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Test #1 for the _strnicmp function +** +** +**==========================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + char str1[] = "foo"; + char str2[] = "foox"; + char str3[] = "fOo"; + char str4[] = "ABCDE"; + char str5[] = "ABCD["; + char str6[] = "abcde"; + char str7[] = "abcd^"; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + if (_strnicmp(str1, str2, strlen(str2)) >= 0) + { + Fail ("ERROR: _strnicmp(\"%s\", \"%s\", %d) returned >= 0\n", + str1, str2, strlen(str2)); + } + + if (_strnicmp(str2, str1, strlen(str2)) <= 0) + { + Fail ("ERROR: _strnicmp(\"%s\", \"%s\", %d) returned <= 0\n", + str2, str1, strlen(str2)); + } + + if (_strnicmp(str1, str2, strlen(str1)) != 0) + { + Fail ("ERROR: _strnicmp(\"%s\", \"%s\", %d) returned != 0\n", + str1, str2, strlen(str1)); + } + + if (_strnicmp(str1, str3, strlen(str1)) != 0) + { + Fail ("ERROR: _strnicmp(\"%s\", \"%s\", %d) returned != 0\n", + str1, str3, strlen(str3)); + } + + if (_strnicmp(str3, str1, strlen(str1)) != 0) + { + Fail ("ERROR: _strnicmp(\"%s\", \"%s\", %d) returned != 0\n", + str3, str1, strlen(str1)); + } + + /* new testing */ + + /* str4 should be greater than str5 */ + if (_strnicmp(str4, str5, strlen(str4)) <= 0) + { + Fail ("ERROR: _strnicmp(\"%s\", \"%s\", %d) returned >= 0\n", + str4, str5, strlen(str4)); + } + + /* str6 should be greater than str7 */ + if (_strnicmp(str6, str7, strlen(str6)) <= 0) + { + Fail ("ERROR: _strnicmp(\"%s\", \"%s\", %d) returned <= 0\n", + str6, str7, strlen(str6)); + } + + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/testinfo.dat new file mode 100644 index 0000000..86744c0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _strnicmp +Name = Test #1 for _strnicmp +TYPE = DEFAULT +EXE1 = test1 +Description += Take two strings and compare them, giving different lengths. += Comparing str1 and str2 with str2 length, should return <0 += Comparing str2 and str1 with str2 length, should return >0 += Comparing str1 and str2 with str1 lenght, should return 0 += Bring in str3, which has a capital, but this function is doing a lower += case compare. Just ensure that two strings which differ only by capitals += return 0. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/CMakeLists.txt new file mode 100644 index 0000000..b29c7c4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/CMakeLists.txt @@ -0,0 +1,19 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/_vsnprintf_s.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/_vsnprintf_s.h new file mode 100644 index 0000000..d549bbe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/_vsnprintf_s.h @@ -0,0 +1,124 @@ +// 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. + +/*============================================================================ +** +** Source: _vsnprintf_s.h +** +** Purpose: Contains common testing functions for _vsnprintf +** +** +**==========================================================================*/ + +#ifndef __STRINGTEST_H__ +#define __STRINGTEST_H__ + +/* These functions leaks memory a lot. C'est la vie. */ +int Testvsnprintf(char* buf, size_t count, const char* format, ...) +{ + int retVal; + va_list arglist; + + va_start(arglist, format); + retVal = _vsnprintf_s(buf, count, _TRUNCATE, format, arglist); + va_end(arglist); + + return (retVal); +} + + +void DoStrTest(const char *formatstr, char* param, const char *checkstr) +{ + char buf[256] = { 0 }; + + Testvsnprintf(buf, 256, formatstr, param); + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, formatstr, checkstr, buf); + } +} + +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) +{ + char buf[256] = { 0 }; + + Testvsnprintf(buf, 256, formatstr, param); + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + convertC(param), formatstr, checkstr, buf); + } +} + + +void DoCharTest(const char *formatstr, char param, const char *checkstr) +{ + char buf[256] = { 0 }; + + Testvsnprintf(buf, 256, formatstr, param); + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, param, formatstr, checkstr, buf); + } +} + +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) +{ + char buf[256] = { 0 }; + + Testvsnprintf(buf, 256, formatstr, param); + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + (char)param, param, formatstr, checkstr, buf); + } +} + +void DoNumTest(const char *formatstr, int value, const char *checkstr) +{ + char buf[256] = { 0 }; + + Testvsnprintf(buf, 256, formatstr, value); + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert %#x into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + value, formatstr, checkstr, buf); + } +} + +void DoI64Test(const char *formatstr, INT64 value, char *valuestr, const char *checkstr) +{ + char buf[256] = { 0 }; + + Testvsnprintf(buf, 256, formatstr, value); + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + valuestr, formatstr, checkstr, buf); + } +} +void DoDoubleTest(const char *formatstr, double value, const char *checkstr1, char + *checkstr2) +{ + char buf[256] = { 0 }; + + Testvsnprintf(buf,256, formatstr, value); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + value, formatstr, checkstr1, checkstr2, buf); + } +} + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test1/CMakeLists.txt new file mode 100644 index 0000000..ebd4ae1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_vsnprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test1 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test1/test1.cpp new file mode 100644 index 0000000..db70f56 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test1/test1.cpp @@ -0,0 +1,55 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Test #1 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + char checkstr[] = "hello world"; + char buf[256] = { 0 }; + int ret; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + Testvsnprintf(buf, 256, "hello world"); + + if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0) + { + Fail("ERROR: expected \"%s\" (up to %d chars), got \"%s\"\n", + checkstr, 256, buf); + } + + Testvsnprintf(buf, 256, "xxxxxxxxxxxxxxxxx"); + + ret = Testvsnprintf(buf, 8, "hello world"); + + if (ret >= 0) + { + Fail("ERROR: expected negative return value, got %d", ret); + } + if (memcmp(checkstr, buf, 7) != 0 || buf[7] != 0) + { + Fail("ERROR: expected %s (up to %d chars), got %s\n", checkstr, 8, buf); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test1/testinfo.dat new file mode 100644 index 0000000..f96bf08 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the _vsnprintf function. += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test10/CMakeLists.txt new file mode 100644 index 0000000..58ac92e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_vsnprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test10 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test10/test10.cpp new file mode 100644 index 0000000..707a91c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test10/test10.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test10.c +** +** Purpose: Test #10 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest("foo %o", pos, "foo 52"); + DoNumTest("foo %lo", 0xFFFF, "foo 177777"); + DoNumTest("foo %ho", 0xFFFF, "foo 177777"); + DoNumTest("foo %Lo", pos, "foo 52"); + DoI64Test("foo %I64o", l, "42", "foo 52"); + DoNumTest("foo %3o", pos, "foo 52"); + DoNumTest("foo %-3o", pos, "foo 52 "); + DoNumTest("foo %.1o", pos, "foo 52"); + DoNumTest("foo %.3o", pos, "foo 052"); + DoNumTest("foo %03o", pos, "foo 052"); + DoNumTest("foo %#o", pos, "foo 052"); + DoNumTest("foo %+o", pos, "foo 52"); + DoNumTest("foo % o", pos, "foo 52"); + DoNumTest("foo %+o", neg, "foo 37777777726"); + DoNumTest("foo % o", neg, "foo 37777777726"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test10/testinfo.dat new file mode 100644 index 0000000..a3d8eca --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test10/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test10 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with octal numbers. += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test11/CMakeLists.txt new file mode 100644 index 0000000..e278c6e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_vsnprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test11 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test11/test11.cpp new file mode 100644 index 0000000..4c710e5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test11/test11.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test11.c +** +** Purpose: Test #11 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest("foo %u", pos, "foo 42"); + DoNumTest("foo %lu", 0xFFFF, "foo 65535"); + DoNumTest("foo %hu", 0xFFFF, "foo 65535"); + DoNumTest("foo %Lu", pos, "foo 42"); + DoI64Test("foo %I64u", l, "42", "foo 42"); + DoNumTest("foo %3u", pos, "foo 42"); + DoNumTest("foo %-3u", pos, "foo 42 "); + DoNumTest("foo %.1u", pos, "foo 42"); + DoNumTest("foo %.3u", pos, "foo 042"); + DoNumTest("foo %03u", pos, "foo 042"); + DoNumTest("foo %#u", pos, "foo 42"); + DoNumTest("foo %+u", pos, "foo 42"); + DoNumTest("foo % u", pos, "foo 42"); + DoNumTest("foo %+u", neg, "foo 4294967254"); + DoNumTest("foo % u", neg, "foo 4294967254"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test11/testinfo.dat new file mode 100644 index 0000000..17e9f04 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test11/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test11 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with unsigned numbers. += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test12/CMakeLists.txt new file mode 100644 index 0000000..5541c2b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_vsnprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test12 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test12/test12.cpp new file mode 100644 index 0000000..528e658 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test12/test12.cpp @@ -0,0 +1,52 @@ +// 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. + +/*===================================================================== +** +** Source: test12.c +** +** Purpose: Test #12 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return (FAIL); + } + + DoNumTest("foo %x", pos, "foo 1234ab"); + DoNumTest("foo %lx", pos, "foo 1234ab"); + DoNumTest("foo %hx", pos, "foo 34ab"); + DoNumTest("foo %Lx", pos, "foo 1234ab"); + DoI64Test("foo %I64x", l, "0x1234567887654321", + "foo 1234567887654321"); + DoNumTest("foo %7x", pos, "foo 1234ab"); + DoNumTest("foo %-7x", pos, "foo 1234ab "); + DoNumTest("foo %.1x", pos, "foo 1234ab"); + DoNumTest("foo %.7x", pos, "foo 01234ab"); + DoNumTest("foo %07x", pos, "foo 01234ab"); + DoNumTest("foo %#x", pos, "foo 0x1234ab"); + DoNumTest("foo %+x", pos, "foo 1234ab"); + DoNumTest("foo % x", pos, "foo 1234ab"); + DoNumTest("foo %+x", neg, "foo ffffffd6"); + DoNumTest("foo % x", neg, "foo ffffffd6"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test12/testinfo.dat new file mode 100644 index 0000000..82f58e4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test12/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test12 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with hex numbers (lowercase). += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test13/CMakeLists.txt new file mode 100644 index 0000000..1a17849 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_vsnprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test13 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test13/test13.cpp new file mode 100644 index 0000000..645a118 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test13/test13.cpp @@ -0,0 +1,52 @@ +// 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. + +/*===================================================================== +** +** Source: test13.c +** +** Purpose: Test #13 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234AB; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest("foo %X", pos, "foo 1234AB"); + DoNumTest("foo %lX", pos, "foo 1234AB"); + DoNumTest("foo %hX", pos, "foo 34AB"); + DoNumTest("foo %LX", pos, "foo 1234AB"); + DoI64Test("foo %I64X", l, "0x1234567887654321", + "foo 1234567887654321"); + DoNumTest("foo %7X", pos, "foo 1234AB"); + DoNumTest("foo %-7X", pos, "foo 1234AB "); + DoNumTest("foo %.1X", pos, "foo 1234AB"); + DoNumTest("foo %.7X", pos, "foo 01234AB"); + DoNumTest("foo %07X", pos, "foo 01234AB"); + DoNumTest("foo %#X", pos, "foo 0X1234AB"); + DoNumTest("foo %+X", pos, "foo 1234AB"); + DoNumTest("foo % X", pos, "foo 1234AB"); + DoNumTest("foo %+X", neg, "foo FFFFFFD6"); + DoNumTest("foo % X", neg, "foo FFFFFFD6"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test13/testinfo.dat new file mode 100644 index 0000000..d308edf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test13/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test13 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with hex numbers (uppercase). += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test14/CMakeLists.txt new file mode 100644 index 0000000..831b5f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_vsnprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test14 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test14/test14.cpp new file mode 100644 index 0000000..05965f0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test14/test14.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test14.c +** +** Purpose: Test #14 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", "foo 2.560000e+02 "); + DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02"); + DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", "foo 2.56000000e+02"); + DoDoubleTest("foo %014e", val, "foo 02.560000e+002", "foo 002.560000e+02"); + DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02"); + DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test14/testinfo.dat new file mode 100644 index 0000000..8d11b1d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test14/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test14 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with exponential format doubles (lowercase). += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test15/CMakeLists.txt new file mode 100644 index 0000000..437a16a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_vsnprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test15 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test15/test15.cpp new file mode 100644 index 0000000..cd34f74 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test15/test15.cpp @@ -0,0 +1,49 @@ +// 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. + +/*===================================================================== +** +** Source: test15.c +** +** Purpose: Test #15 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %14E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", "foo 2.560000E+02 "); + DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02"); + DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", "foo 2.56000000E+02"); + DoDoubleTest("foo %014E", val, "foo 02.560000E+002", "foo 002.560000E+02"); + DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02"); + DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test15/testinfo.dat new file mode 100644 index 0000000..9139125 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test15/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test15 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with exponential format doubles (uppercase). += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test16/CMakeLists.txt new file mode 100644 index 0000000..991e9f1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_vsnprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test16 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test16/test16.cpp new file mode 100644 index 0000000..de9b74f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test16/test16.cpp @@ -0,0 +1,49 @@ +// 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. + +/*===================================================================== +** +** Source: test16.c +** +** Purpose: Test #16 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 "); + DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0"); + DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000"); + DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000"); + DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000"); + DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000"); + DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test16/testinfo.dat new file mode 100644 index 0000000..fc2f130 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test16/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test16 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with decimal point format doubles. += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test17/CMakeLists.txt new file mode 100644 index 0000000..381620e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_vsnprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test17 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test17/test17.cpp new file mode 100644 index 0000000..3304eda --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test17/test17.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test17.c +** +** Purpose: Test #17 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest("foo %g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03"); + DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03"); + DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test17/testinfo.dat new file mode 100644 index 0000000..aeb9244 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test17/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test17 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with compact format doubles (lowercase). += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test18/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test18/CMakeLists.txt new file mode 100644 index 0000000..ebaa896 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test18/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test18.cpp +) + +add_executable(paltest_vsnprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test18 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test18 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test18/test18.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test18/test18.cpp new file mode 100644 index 0000000..14ad8f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test18/test18.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test18.c +** +** Purpose: Test #18 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest("foo %G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03"); + DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03"); + DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test18/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test18/testinfo.dat new file mode 100644 index 0000000..57aaed5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test18/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test18 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with compact format doubles (uppercase). += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test19/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test19/CMakeLists.txt new file mode 100644 index 0000000..cd9a2ba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test19/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test19.cpp +) + +add_executable(paltest_vsnprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test19 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test19 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test19/test19.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test19/test19.cpp new file mode 100644 index 0000000..6f2aefa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test19/test19.cpp @@ -0,0 +1,103 @@ +// 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. + +/*===================================================================== +** +** Source: test19.c +** +** Purpose: Test #19 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +#define DOTEST(a,b,c,d,e) DoTest(a,b,(void*)c,d,e) + +void DoArgumentPrecTest(char *formatstr, int precision, void *param, + char *paramstr, char *checkstr1, char *checkstr2) +{ + char buf[256]; + + Testvsnprintf(buf,256,formatstr, precision, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + paramstr, formatstr, precision, checkstr1, checkstr2, buf); + } + +} + +void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param, + char *checkstr1, char *checkstr2) +{ + char buf[256]; + + Testvsnprintf(buf,256,formatstr, precision, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + param, formatstr, precision, checkstr1, checkstr2, buf); + } + +} + + + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + + DoArgumentPrecTest("%.*s", 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest("%.*S", 2, (void*)convert("bar"), "bar", "ba", "ba"); + DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test19/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test19/testinfo.dat new file mode 100644 index 0000000..cda8966 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test19/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test19 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with argument specified precision. += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test2/CMakeLists.txt new file mode 100644 index 0000000..c44669c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_vsnprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test2 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test2/test2.cpp new file mode 100644 index 0000000..e5808f3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test2/test2.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Test #2 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR szwStr[] = {'b','a','r','\0'}; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoStrTest("foo %s", "bar", "foo bar"); + DoStrTest("foo %hs", "bar", "foo bar"); + DoWStrTest("foo %ls", szwStr, "foo bar"); + DoWStrTest("foo %ws", szwStr, "foo bar"); + DoStrTest("foo %Ls", "bar", "foo bar"); + DoStrTest("foo %I64s", "bar", "foo bar"); + DoStrTest("foo %5s", "bar", "foo bar"); + DoStrTest("foo %.2s", "bar", "foo ba"); + DoStrTest("foo %5.2s", "bar", "foo ba"); + DoStrTest("foo %-5s", "bar", "foo bar "); + DoStrTest("foo %05s", "bar", "foo 00bar"); + DoStrTest("foo %s", NULL, "foo (null)"); + DoStrTest("foo %hs", NULL, "foo (null)"); + DoWStrTest("foo %ls", NULL, "foo (null)"); + DoWStrTest("foo %ws", NULL, "foo (null)"); + DoStrTest("foo %Ls", NULL, "foo (null)"); + DoStrTest("foo %I64s", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test2/testinfo.dat new file mode 100644 index 0000000..6e8f03e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test2 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with strings. += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test3/CMakeLists.txt new file mode 100644 index 0000000..29f08e6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_vsnprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test3 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test3/test3.cpp new file mode 100644 index 0000000..bb8b153 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test3/test3.cpp @@ -0,0 +1,49 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Test #3 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoWStrTest("foo %S", convert("bar"), "foo bar"); + DoStrTest("foo %hS", "bar", "foo bar"); + DoWStrTest("foo %lS", convert("bar"), "foo bar"); + DoWStrTest("foo %wS", convert("bar"), "foo bar"); + DoWStrTest("foo %LS", convert("bar"), "foo bar"); + DoWStrTest("foo %I64S", convert("bar"), "foo bar"); + DoWStrTest("foo %5S", convert("bar"), "foo bar"); + DoWStrTest("foo %.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %5.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %-5S", convert("bar"), "foo bar "); + DoWStrTest("foo %05S", convert("bar"), "foo 00bar"); + DoWStrTest("foo %S", NULL, "foo (null)"); + DoStrTest("foo %hS", NULL, "foo (null)"); + DoWStrTest("foo %lS", NULL, "foo (null)"); + DoWStrTest("foo %wS", NULL, "foo (null)"); + DoWStrTest("foo %LS", NULL, "foo (null)"); + DoWStrTest("foo %I64S", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test3/testinfo.dat new file mode 100644 index 0000000..638cef6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test3 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with wide strings. += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test4/CMakeLists.txt new file mode 100644 index 0000000..f81e261 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_vsnprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test4 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test4/test4.cpp new file mode 100644 index 0000000..f795c0d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test4/test4.cpp @@ -0,0 +1,98 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c +** +** Purpose: Test #4 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +static void DoPointerTest(char *formatstr, void* param, char* paramstr, + char *checkstr1) +{ + char buf[256] = { 0 }; + + Testvsnprintf(buf,256, formatstr, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + paramstr, formatstr, checkstr1, buf); + } +} + +static void DoI64DoubleTest(char *formatstr, INT64 value, char *valuestr, char +*checkstr1) +{ + char buf[256] = { 0 }; + + Testvsnprintf(buf,256,formatstr, value); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", + valuestr, formatstr, checkstr1, buf); + } +} + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + + /* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "0000000000000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64DoubleTest("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); + +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "00000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64DoubleTest("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); +#endif + + + + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test4/testinfo.dat new file mode 100644 index 0000000..03ff293 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test4/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test4 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with pointers. += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test6/CMakeLists.txt new file mode 100644 index 0000000..cdd8b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_vsnprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test6 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test6/test6.cpp new file mode 100644 index 0000000..cbcead8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test6/test6.cpp @@ -0,0 +1,44 @@ +// 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. + +/*===================================================================== +** +** Source: test6.c +** +** Purpose: Test #6 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoCharTest("foo %c", 'b', "foo b"); + DoCharTest("foo %hc", 'b', "foo b"); + DoWCharTest("foo %lc", wc, "foo c"); + DoCharTest("foo %Lc", 'b', "foo b"); + DoCharTest("foo %I64c", 'b', "foo b"); + DoCharTest("foo %5c", 'b', "foo b"); + DoCharTest("foo %.0c", 'b', "foo b"); + DoCharTest("foo %-5c", 'b', "foo b "); + DoCharTest("foo %05c", 'b', "foo 0000b"); + DoCharTest("foo % c", 'b', "foo b"); + DoCharTest("foo %#c", 'b', "foo b"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test6/testinfo.dat new file mode 100644 index 0000000..e375f92 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test6/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test6 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with characters. += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test7/CMakeLists.txt new file mode 100644 index 0000000..d28f938 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_vsnprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test7 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test7/test7.cpp new file mode 100644 index 0000000..4843d27 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test7/test7.cpp @@ -0,0 +1,44 @@ +// 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. + +/*===================================================================== +** +** Source: test7.c +** +** Purpose: Test #7 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wb = (WCHAR) 'b'; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoWCharTest("foo %c", wb, "foo b"); + DoWCharTest("foo %hc", wb, "foo b"); + DoCharTest("foo %lc", 'c', "foo c"); + DoWCharTest("foo %Lc", wb, "foo b"); + DoWCharTest("foo %I64c", wb, "foo b"); + DoWCharTest("foo %5c", wb, "foo b"); + DoWCharTest("foo %.0c", wb, "foo b"); + DoWCharTest("foo %-5c", wb, "foo b "); + DoWCharTest("foo %05c", wb, "foo 0000b"); + DoWCharTest("foo % c", wb, "foo b"); + DoWCharTest("foo %#c", wb, "foo b"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test7/testinfo.dat new file mode 100644 index 0000000..09eb481 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test7/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test7 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with wide characters. += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test8/CMakeLists.txt new file mode 100644 index 0000000..39ea287 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_vsnprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test8 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test8/test8.cpp new file mode 100644 index 0000000..8021a79 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test8/test8.cpp @@ -0,0 +1,52 @@ +// 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. + +/*===================================================================== +** +** Source: test8.c +** +** Purpose: Test #8 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest("foo %d", pos, "foo 42"); + DoNumTest("foo %ld", 0xFFFF, "foo 65535"); + DoNumTest("foo %hd", 0xFFFF, "foo -1"); + DoNumTest("foo %Ld", pos, "foo 42"); + DoI64Test("foo %I64d", l, "42", "foo 42"); + DoNumTest("foo %3d", pos, "foo 42"); + DoNumTest("foo %-3d", pos, "foo 42 "); + DoNumTest("foo %.1d", pos, "foo 42"); + DoNumTest("foo %.3d", pos, "foo 042"); + DoNumTest("foo %03d", pos, "foo 042"); + DoNumTest("foo %#d", pos, "foo 42"); + DoNumTest("foo %+d", pos, "foo +42"); + DoNumTest("foo % d", pos, "foo 42"); + DoNumTest("foo %+d", neg, "foo -42"); + DoNumTest("foo % d", neg, "foo -42"); + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test8/testinfo.dat new file mode 100644 index 0000000..1bdf411 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test8/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test8 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with decimal numbers. += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test9/CMakeLists.txt new file mode 100644 index 0000000..9eb5316 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_vsnprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_vsnprintf_test9 coreclrpal) + +target_link_libraries(paltest_vsnprintf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test9/test9.cpp new file mode 100644 index 0000000..d36846e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test9/test9.cpp @@ -0,0 +1,51 @@ +// 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. + +/*===================================================================== +** +** Source: test9.c +** +** Purpose: Test #9 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest("foo %i", pos, "foo 42"); + DoNumTest("foo %li", 0xFFFF, "foo 65535"); + DoNumTest("foo %hi", 0xFFFF, "foo -1"); + DoNumTest("foo %Li", pos, "foo 42"); + DoI64Test("foo %I64i", l, "42", "foo 42"); + DoNumTest("foo %3i", pos, "foo 42"); + DoNumTest("foo %-3i", pos, "foo 42 "); + DoNumTest("foo %.1i", pos, "foo 42"); + DoNumTest("foo %.3i", pos, "foo 042"); + DoNumTest("foo %03i", pos, "foo 042"); + DoNumTest("foo %#i", pos, "foo 42"); + DoNumTest("foo %+i", pos, "foo +42"); + DoNumTest("foo % i", pos, "foo 42"); + DoNumTest("foo %+i", neg, "foo -42"); + DoNumTest("foo % i", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test9/testinfo.dat new file mode 100644 index 0000000..bdaae87 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnprintf_s/test9/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnprintf +Name = Positive Test for _vsnprintf +TYPE = DEFAULT +EXE1 = test9 +Description += Tests the PAL implementation of the _vsnprintf function. += Tests _vsnprintf with integer numbers. += This test is modeled after sprintf_s. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/CMakeLists.txt new file mode 100644 index 0000000..b29c7c4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/CMakeLists.txt @@ -0,0 +1,19 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/_vsnwprintf_s.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/_vsnwprintf_s.h new file mode 100644 index 0000000..bca63b4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/_vsnwprintf_s.h @@ -0,0 +1,133 @@ +// 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. + +/*============================================================================ +** +** Source: _vsnwprintf_s.h +** +** Purpose: Containts common testing functions for _vsnwprintf_s +** +** +**==========================================================================*/ + +#ifndef ___VSNWPRINTF_H__ +#define ___VSNWPRINTF_H__ + +/* These functions leaks memory a lot. C'est la vie. */ +int TestVsnwprintf_s(char16_t* buf, size_t count, const char16_t* format, ...) +{ + int retVal = 0; + va_list arglist; + + va_start(arglist, format); + retVal = _vsnwprintf_s(buf, count, _TRUNCATE, format, arglist); + va_end(arglist); + + return( retVal); +} + + +void DoWStrTest(const WCHAR *formatstr, WCHAR *param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, param); + + if (memcmp(buf, checkstr, wcslen(buf) * 2 + 2) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", + convertC(param), convertC(formatstr), + convertC(checkstr), convertC(buf)); + } +} + +void DoStrTest(const WCHAR *formatstr, char *param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, param); + + if (memcmp(buf, checkstr, wcslen(buf) * 2 + 2) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", + param, convertC(formatstr), convertC(checkstr), + convertC(buf)); + } +} + +void DoCharTest(const WCHAR *formatstr, char param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, param); + if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0) + { + Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, param, convertC(formatstr), convertC(checkstr), + convertC(buf)); + } +} + +void DoWCharTest(const WCHAR *formatstr, WCHAR param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, param); + if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0) + { + Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + (char) param, param, convertC(formatstr), + convertC(checkstr), convertC(buf)); + } +} + +void DoNumTest(const WCHAR *formatstr, int value, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, value); + if (memcmp(buf, checkstr, wcslen(buf)* 2 + 2) != 0) + { + Fail("ERROR: failed to insert %#x into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", value, convertC(formatstr), + convertC(checkstr), convertC(buf)); + } +} + +void DoI64NumTest(const WCHAR *formatstr, INT64 value, char *valuestr, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, value); + if (memcmp(buf, checkstr, wcslen(buf)* 2 + 2) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", valuestr, convertC(formatstr), + convertC(checkstr), convertC(buf)); + } +} +void DoDoubleTest(const WCHAR *formatstr, double value, + const WCHAR *checkstr1, const WCHAR *checkstr2) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, value); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + value, + convertC(formatstr), + convertC(checkstr1), + convertC(checkstr2), + convertC(buf)); + } +} + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/CMakeLists.txt new file mode 100644 index 0000000..de610ed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_vsnwprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test1 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/test1.cpp new file mode 100644 index 0000000..4a7a02e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/test1.cpp @@ -0,0 +1,60 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Test #1 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR *checkstr; + WCHAR buf[256] = { 0 }; + int ret; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + checkstr = convert("hello world"); + TestVsnwprintf_s(buf, 256, checkstr); + if (memcmp(checkstr, buf, wcslen(checkstr)*2+2) != 0) + { + Fail("ERROR: Expected \"%s\", got \"%s\"\n", + convertC(checkstr), convertC(buf)); + } + + TestVsnwprintf_s(buf, 256, convert("xxxxxxxxxxxxxxxxx")); + ret = TestVsnwprintf_s(buf, 8, checkstr); + if ((memcmp(checkstr, buf, 14)) != 0 || (buf[7] != 0)) + { + Fail("ERROR: Expected \"%8s\", got \"%8s\"\n", + convertC(checkstr), convertC(buf)); + } + if (ret >= 0) + { + Fail("ERROR: Expected negative return value, got %d.\n", ret); + } + if (buf[8] != (WCHAR) 'x') + { + Fail("ERROR: buffer overflow using \"%s\" with length 8.\n", + convertC(checkstr)); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/testinfo.dat new file mode 100644 index 0000000..450c5b9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += General test to see if _vsnwprintf_s works correctly. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/CMakeLists.txt new file mode 100644 index 0000000..d67ddba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_vsnwprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test10 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/test10.cpp new file mode 100644 index 0000000..e33f228 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/test10.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test10.c +** +** Purpose: Test #10 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %o"), pos, convert("foo 52")); + DoNumTest(convert("foo %lo"), 0xFFFF, convert("foo 177777")); + DoNumTest(convert("foo %ho"), 0xFFFF, convert("foo 177777")); + DoNumTest(convert("foo %Lo"), pos, convert("foo 52")); + DoI64NumTest(convert("foo %I64o"), l, "42", convert("foo 52")); + DoNumTest(convert("foo %3o"), pos, convert("foo 52")); + DoNumTest(convert("foo %-3o"), pos, convert("foo 52 ")); + DoNumTest(convert("foo %.1o"), pos, convert("foo 52")); + DoNumTest(convert("foo %.3o"), pos, convert("foo 052")); + DoNumTest(convert("foo %03o"), pos, convert("foo 052")); + DoNumTest(convert("foo %#o"), pos, convert("foo 052")); + DoNumTest(convert("foo %+o"), pos, convert("foo 52")); + DoNumTest(convert("foo % o"), pos, convert("foo 52")); + DoNumTest(convert("foo %+o"), neg, convert("foo 37777777726")); + DoNumTest(convert("foo % o"), neg, convert("foo 37777777726")); + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/testinfo.dat new file mode 100644 index 0000000..59af082 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test10 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with octal numbers. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/CMakeLists.txt new file mode 100644 index 0000000..f237ff3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_vsnwprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test11 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/test11.cpp new file mode 100644 index 0000000..4e860bb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/test11.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test11.c +** +** Purpose: Test #11 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %u"), pos, convert("foo 42")); + DoNumTest(convert("foo %lu"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hu"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %Lu"), pos, convert("foo 42")); + DoI64NumTest(convert("foo %I64u"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3u"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3u"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1u"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3u"), pos, convert("foo 042")); + DoNumTest(convert("foo %03u"), pos, convert("foo 042")); + DoNumTest(convert("foo %#u"), pos, convert("foo 42")); + DoNumTest(convert("foo %+u"), pos, convert("foo 42")); + DoNumTest(convert("foo % u"), pos, convert("foo 42")); + DoNumTest(convert("foo %+u"), neg, convert("foo 4294967254")); + DoNumTest(convert("foo % u"), neg, convert("foo 4294967254")); + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/testinfo.dat new file mode 100644 index 0000000..10c0014 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test11 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with unsigned numbers. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/CMakeLists.txt new file mode 100644 index 0000000..6f2b3da --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_vsnwprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test12 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/test12.cpp new file mode 100644 index 0000000..2dcfcf5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/test12.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test12.c +** +** Purpose: Test #12 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %lx"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %hx"), pos, convert("foo 34ab")); + DoNumTest(convert("foo %Lx"), pos, convert("foo 1234ab")); + DoI64NumTest(convert("foo %I64x"), l, "0x1234567887654321", + convert("foo 1234567887654321")); + DoNumTest(convert("foo %7x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %-7x"), pos, convert("foo 1234ab ")); + DoNumTest(convert("foo %.1x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %.7x"), pos, convert("foo 01234ab")); + DoNumTest(convert("foo %07x"), pos, convert("foo 01234ab")); + DoNumTest(convert("foo %#x"), pos, convert("foo 0x1234ab")); + DoNumTest(convert("foo %+x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo % x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %+x"), neg, convert("foo ffffffd6")); + DoNumTest(convert("foo % x"), neg, convert("foo ffffffd6")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/testinfo.dat new file mode 100644 index 0000000..de08989 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test12 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with hex numbers (lowercase). += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/CMakeLists.txt new file mode 100644 index 0000000..b5e07b3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_vsnwprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test13 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/test13.cpp new file mode 100644 index 0000000..c95278a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/test13.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test13.c +** +** Purpose: Test #13 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %lX"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %hX"), pos, convert("foo 34AB")); + DoNumTest(convert("foo %LX"), pos, convert("foo 1234AB")); + DoI64NumTest(convert("foo %I64X"), l, "0x1234567887654321", + convert("foo 1234567887654321")); + DoNumTest(convert("foo %7X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %-7X"), pos, convert("foo 1234AB ")); + DoNumTest(convert("foo %.1X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %.7X"), pos, convert("foo 01234AB")); + DoNumTest(convert("foo %07X"), pos, convert("foo 01234AB")); + DoNumTest(convert("foo %#X"), pos, convert("foo 0X1234AB")); + DoNumTest(convert("foo %+X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo % X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %+X"), neg, convert("foo FFFFFFD6")); + DoNumTest(convert("foo % X"), neg, convert("foo FFFFFFD6")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/testinfo.dat new file mode 100644 index 0000000..94479d5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test13 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with hex numbers (uppercase). += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/CMakeLists.txt new file mode 100644 index 0000000..7759262 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_vsnwprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test14 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/test14.cpp new file mode 100644 index 0000000..cab1b24 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/test14.cpp @@ -0,0 +1,63 @@ +// 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. + +/*===================================================================== +** +** Source: test14.c +** +** Purpose: Test #14 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %le"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %he"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %Le"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %I64e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %14e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %-14e"), val, convert("foo 2.560000e+002 "), + convert("foo 2.560000e+02 ")); + DoDoubleTest(convert("foo %.1e"), val, convert("foo 2.6e+002"), + convert("foo 2.6e+02")); + DoDoubleTest(convert("foo %.8e"), val, convert("foo 2.56000000e+002"), + convert("foo 2.56000000e+02")); + DoDoubleTest(convert("foo %014e"), val, convert("foo 02.560000e+002"), + convert("foo 002.560000e+02")); + DoDoubleTest(convert("foo %#e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %+e"), val, convert("foo +2.560000e+002"), + convert("foo +2.560000e+02")); + DoDoubleTest(convert("foo % e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %+e"), neg, convert("foo -2.560000e+002"), + convert("foo -2.560000e+02")); + DoDoubleTest(convert("foo % e"), neg, convert("foo -2.560000e+002"), + convert("foo -2.560000e+02")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/testinfo.dat new file mode 100644 index 0000000..0d46d97 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test14 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with exponential format doubles (lowercase). += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/CMakeLists.txt new file mode 100644 index 0000000..bceb26c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_vsnwprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test15 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/test15.cpp new file mode 100644 index 0000000..d573899 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/test15.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. + +/*===================================================================== +** +** Source: test15.c +** +** Purpose: Test #15 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %lE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %hE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %LE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %I64E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %14E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %-14E"), val, convert("foo 2.560000E+002 "), + convert("foo 2.560000E+02 ")); + DoDoubleTest(convert("foo %.1E"), val, convert("foo 2.6E+002"), + convert("foo 2.6E+02")); + DoDoubleTest(convert("foo %.8E"), val, convert("foo 2.56000000E+002"), + convert("foo 2.56000000E+02")); + DoDoubleTest(convert("foo %014E"), val, convert("foo 02.560000E+002"), + convert("foo 002.560000E+02")); + DoDoubleTest(convert("foo %#E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %+E"), val, convert("foo +2.560000E+002"), + convert("foo +2.560000E+02")); + DoDoubleTest(convert("foo % E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %+E"), neg, convert("foo -2.560000E+002"), + convert("foo -2.560000E+02")); + DoDoubleTest(convert("foo % E"), neg, convert("foo -2.560000E+002"), + convert("foo -2.560000E+002")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/testinfo.dat new file mode 100644 index 0000000..7737f49 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test15 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with exponential format doubles (uppercase). += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/CMakeLists.txt new file mode 100644 index 0000000..fb0c75e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_vsnwprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test16 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/test16.cpp new file mode 100644 index 0000000..72c546e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/test16.cpp @@ -0,0 +1,63 @@ +// 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. + +/*===================================================================== +** +** Source: test16.c +** +** Purpose: Test #16 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %lf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %hf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %Lf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %I64f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %12f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %-12f"), val, convert("foo 2560.001000 "), + convert("foo 2560.001000 ")); + DoDoubleTest(convert("foo %.1f"), val, convert("foo 2560.0"), + convert("foo 2560.0")); + DoDoubleTest(convert("foo %.8f"), val, convert("foo 2560.00100000"), + convert("foo 2560.00100000")); + DoDoubleTest(convert("foo %012f"), val, convert("foo 02560.001000"), + convert("foo 02560.001000")); + DoDoubleTest(convert("foo %#f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %+f"), val, convert("foo +2560.001000"), + convert("foo +2560.001000")); + DoDoubleTest(convert("foo % f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %+f"), neg, convert("foo -2560.001000"), + convert("foo -2560.001000")); + DoDoubleTest(convert("foo % f"), neg, convert("foo -2560.001000"), + convert("foo -2560.001000")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/testinfo.dat new file mode 100644 index 0000000..9aec1c0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test16 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with decimal point format doubles. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/CMakeLists.txt new file mode 100644 index 0000000..41e35b4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_vsnwprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test17 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/test17.cpp new file mode 100644 index 0000000..e6860b9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/test17.cpp @@ -0,0 +1,65 @@ +// 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. + +/*===================================================================== +** +** Source: test17.c +** +** Purpose: Test #17 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %lg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %hg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %Lg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %I64g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %5g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %-5g"), val, convert("foo 2560 "), + convert("foo 2560 ")); + DoDoubleTest(convert("foo %.1g"), val, convert("foo 3e+003"), + convert("foo 3e+03")); + DoDoubleTest(convert("foo %.2g"), val, convert("foo 2.6e+003"), + convert("foo 2.6e+03")); + DoDoubleTest(convert("foo %.12g"), val, convert("foo 2560.001"), + convert("foo 2560.001")); + DoDoubleTest(convert("foo %06g"), val, convert("foo 002560"), + convert("foo 002560")); + DoDoubleTest(convert("foo %#g"), val, convert("foo 2560.00"), + convert("foo 2560.00")); + DoDoubleTest(convert("foo %+g"), val, convert("foo +2560"), + convert("foo +2560")); + DoDoubleTest(convert("foo % g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %+g"), neg, convert("foo -2560"), + convert("foo -2560")); + DoDoubleTest(convert("foo % g"), neg, convert("foo -2560"), + convert("foo -2560")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/testinfo.dat new file mode 100644 index 0000000..1487b7a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test17 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with compact format doubles (lowercase). += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/CMakeLists.txt new file mode 100644 index 0000000..0c99b55 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test18.cpp +) + +add_executable(paltest_vsnwprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test18 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test18 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/test18.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/test18.cpp new file mode 100644 index 0000000..a164edb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/test18.cpp @@ -0,0 +1,65 @@ +// 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. + +/*===================================================================== +** +** Source: test18.c +** +** Purpose: Test #18 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %lG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %hG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %LG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %I64G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %5G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %-5G"), val, convert("foo 2560 "), + convert("foo 2560 ")); + DoDoubleTest(convert("foo %.1G"), val, convert("foo 3E+003"), + convert("foo 3E+03")); + DoDoubleTest(convert("foo %.2G"), val, convert("foo 2.6E+003"), + convert("foo 2.6E+03")); + DoDoubleTest(convert("foo %.12G"), val, convert("foo 2560.001"), + convert("foo 2560.001")); + DoDoubleTest(convert("foo %06G"), val, convert("foo 002560"), + convert("foo 002560")); + DoDoubleTest(convert("foo %#G"), val, convert("foo 2560.00"), + convert("foo 2560.00")); + DoDoubleTest(convert("foo %+G"), val, convert("foo +2560"), + convert("foo +2560")); + DoDoubleTest(convert("foo % G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %+G"), neg, convert("foo -2560"), + convert("foo -2560")); + DoDoubleTest(convert("foo % G"), neg, convert("foo -2560"), + convert("foo -2560")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/testinfo.dat new file mode 100644 index 0000000..54c4e87 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test18 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with compact format doubles (uppercase). += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/CMakeLists.txt new file mode 100644 index 0000000..f4b0562 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test19.cpp +) + +add_executable(paltest_vsnwprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test19 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test19 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/test19.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/test19.cpp new file mode 100644 index 0000000..c2a8547 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/test19.cpp @@ -0,0 +1,139 @@ +// 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. + +/*===================================================================== +** +** Source: test18.c +** +** Purpose: Test #18 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +#define DOTEST(a,b,c,d,e) DoTest(a,b,(void*)c,d,e) + +void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param, + WCHAR *paramstr, WCHAR *checkstr1, WCHAR *checkstr2) +{ + WCHAR buf[256]; + + TestVsnwprintf_s(buf, 256, formatstr, precision, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + paramstr, + convertC(formatstr), + precision, + convertC(checkstr1), + convertC(checkstr2), + convertC(buf)); + } +} +void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param, + WCHAR *checkstr1, WCHAR *checkstr2) +{ + WCHAR buf[256]; + + TestVsnwprintf_s(buf, 256, formatstr, precision, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + param, convertC(formatstr), + precision, + convertC(checkstr1), + convertC(checkstr2), + convertC(buf)); + } +} + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoArgumentPrecTest(convert("%.*s"), 2, (void*)convert("bar"), convert("bar"), + convert("ba"), convert("ba")); + DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, convert("42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, convert("42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, convert("42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, convert("42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, convert("42"), + convert("52"), convert("52")); + DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, convert("42"), + convert("052"), convert("052")); + DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, convert("42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, convert("42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, convert("0x42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, convert("0x42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, convert("0x42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, convert("0x42"), + convert("042"), convert("042")); + + + DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000"), + convert("2.0e+00")); + DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000"), + convert("2.010e+00")); + DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000"), + convert("2.0E+00")); + DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000"), + convert("2.010E+00")); + DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0"), + convert("2.0")); + DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010"), + convert("2.010")); + DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002"), + convert("3e+02")); + DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01"), + convert("256.01")); + DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002"), + convert("3E+02")); + DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01"), + convert("256.01")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/testinfo.dat new file mode 100644 index 0000000..2913e30 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test19 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with argument specified precision. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/CMakeLists.txt new file mode 100644 index 0000000..d283814 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_vsnwprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test2 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/test2.cpp new file mode 100644 index 0000000..b2958df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/test2.cpp @@ -0,0 +1,46 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Test #2 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoWStrTest(convert("foo %s"), convert("bar"), convert("foo bar")); + DoStrTest(convert("foo %hs"), "bar", convert("foo bar")); + DoWStrTest(convert("foo %ls"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %ws"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %Ls"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %I64s"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %5s"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %.2s"), convert("bar"), convert("foo ba")); + DoWStrTest(convert("foo %5.2s"), convert("bar"), convert("foo ba")); + DoWStrTest(convert("foo %-5s"), convert("bar"), convert("foo bar ")); + DoWStrTest(convert("foo %05s"), convert("bar"), convert("foo 00bar")); + DoWStrTest(convert("foo %s"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %hs"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %ls"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %ws"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %Ls"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %I64s"), NULL, convert("foo (null)")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/testinfo.dat new file mode 100644 index 0000000..5b9b629 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test2 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with strings. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/CMakeLists.txt new file mode 100644 index 0000000..8c2c5c9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_vsnwprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test3 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/test3.cpp new file mode 100644 index 0000000..657a911 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/test3.cpp @@ -0,0 +1,46 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Test #3 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoStrTest(convert("foo %S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %hS"), "bar", convert("foo bar")); + DoWStrTest(convert("foo %lS"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %wS"), convert("bar"), convert("foo bar")); + DoStrTest(convert("foo %LS"), "bar", convert("foo bar")); + DoStrTest(convert("foo %I64S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %5S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %.2S"), "bar", convert("foo ba")); + DoStrTest(convert("foo %5.2S"), "bar", convert("foo ba")); + DoStrTest(convert("foo %-5S"), "bar", convert("foo bar ")); + DoStrTest(convert("foo %05S"), "bar", convert("foo 00bar")); + DoStrTest(convert("foo %S"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %hS"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %lS"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %wS"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %LS"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %I64S"), NULL, convert("foo (null)")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/testinfo.dat new file mode 100644 index 0000000..6216069 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test3 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with wide strings. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/CMakeLists.txt new file mode 100644 index 0000000..eafb079 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_vsnwprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test4 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/test4.cpp new file mode 100644 index 0000000..acf9aba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/test4.cpp @@ -0,0 +1,121 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c +** +** Purpose: Test #4 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ +static void DoPointerTest(WCHAR *formatstr, void* param, WCHAR* paramstr, + WCHAR *checkstr1) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0) + + { + Fail("ERROR: failed to insert pointer to %#p into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + paramstr, + convertC(formatstr), + convertC(checkstr1), + convertC(buf)); + } +} + +static void DoI64DoubleTest(WCHAR *formatstr, INT64 value, WCHAR *valuestr, + WCHAR *checkstr1) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, value); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", + value, + convertC(formatstr), + convertC(checkstr1), + convertC(buf)); + } +} + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest(convert("%p"), NULL, convert("NULL"), convert("00000000")); + DoPointerTest(convert("%p"), ptr, convert("pointer to 0x123456"), + convert("0000000000123456")); + DoPointerTest(convert("%17p"), ptr, convert("pointer to 0x123456"), + convert(" 0000000000123456")); + DoPointerTest(convert("%17p"), ptr, convert("pointer to 0x123456"), + convert(" 0000000000123456")); + DoPointerTest(convert("%-17p"), ptr, convert("pointer to 0x123456"), + convert("0000000000123456 ")); + DoPointerTest(convert("%+p"), ptr, convert("pointer to 0x123456"), + convert("0000000000123456")); + DoPointerTest(convert("%#p"), ptr, convert("pointer to 0x123456"), + convert("0X0000000000123456")); + DoPointerTest(convert("%lp"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoPointerTest(convert("%hp"), ptr, convert("pointer to 0x123456"), + convert("00003456")); + DoPointerTest(convert("%Lp"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoI64DoubleTest(convert("%I64p"), lptr, + convert("pointer to 0x1234567887654321"), + convert("1234567887654321")); + +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest(convert("%p"), NULL, convert("NULL"), convert("00000000")); + DoPointerTest(convert("%p"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoPointerTest(convert("%9p"), ptr, convert("pointer to 0x123456"), + convert(" 00123456")); + DoPointerTest(convert("%09p"), ptr, convert("pointer to 0x123456"), + convert(" 00123456")); + DoPointerTest(convert("%-9p"), ptr, convert("pointer to 0x123456"), + convert("00123456 ")); + DoPointerTest(convert("%+p"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoPointerTest(convert("%#p"), ptr, convert("pointer to 0x123456"), + convert("0X00123456")); + DoPointerTest(convert("%lp"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoPointerTest(convert("%hp"), ptr, convert("pointer to 0x123456"), + convert("00003456")); + DoPointerTest(convert("%Lp"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoI64DoubleTest(convert("%I64p"), lptr, + convert("pointer to 0x1234567887654321"), + convert("1234567887654321")); +#endif + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/testinfo.dat new file mode 100644 index 0000000..9fbfcba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test4 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with pointers. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/CMakeLists.txt new file mode 100644 index 0000000..98faea5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_vsnwprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test6 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/test6.cpp new file mode 100644 index 0000000..ecba585 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/test6.cpp @@ -0,0 +1,43 @@ +// 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. + +/*===================================================================== +** +** Source: test6.c +** +** Purpose: Test #6 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoWCharTest(convert("foo %c"), wc, convert("foo c")); + DoCharTest(convert("foo %hc"), 'b', convert("foo b")); + DoWCharTest(convert("foo %lc"), wc, convert("foo c")); + DoWCharTest(convert("foo %Lc"), wc, convert("foo c")); + DoWCharTest(convert("foo %I64c"), wc, convert("foo c")); + DoWCharTest(convert("foo %5c"), wc, convert("foo c")); + DoWCharTest(convert("foo %.0c"), wc, convert("foo c")); + DoWCharTest(convert("foo %-5c"), wc, convert("foo c ")); + DoWCharTest(convert("foo %05c"), wc, convert("foo 0000c")); + DoWCharTest(convert("foo % c"), wc, convert("foo c")); + DoWCharTest(convert("foo %#c"), wc, convert("foo c")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/testinfo.dat new file mode 100644 index 0000000..1b411d7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test6 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with characters. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/CMakeLists.txt new file mode 100644 index 0000000..d36a9ff --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_vsnwprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test7 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/test7.cpp new file mode 100644 index 0000000..519657a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/test7.cpp @@ -0,0 +1,43 @@ +// 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. + +/*===================================================================== +** +** Source: test7.c +** +** Purpose: Test #7 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoCharTest(convert("foo %C"), 'b', convert("foo b")); + DoWCharTest(convert("foo %hC"), wc, convert("foo c")); + DoCharTest(convert("foo %lC"), 'b', convert("foo b")); + DoCharTest(convert("foo %LC"), 'b', convert("foo b")); + DoCharTest(convert("foo %I64C"), 'b', convert("foo b")); + DoCharTest(convert("foo %5C"), 'b', convert("foo b")); + DoCharTest(convert("foo %.0C"), 'b', convert("foo b")); + DoCharTest(convert("foo %-5C"), 'b', convert("foo b ")); + DoCharTest(convert("foo %05C"), 'b', convert("foo 0000b")); + DoCharTest(convert("foo % C"), 'b', convert("foo b")); + DoCharTest(convert("foo %#C"), 'b', convert("foo b")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/testinfo.dat new file mode 100644 index 0000000..8f2ccf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test7 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with wide characters. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/CMakeLists.txt new file mode 100644 index 0000000..0c0440d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_vsnwprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test8 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/test8.cpp new file mode 100644 index 0000000..15641f7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/test8.cpp @@ -0,0 +1,49 @@ +// 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. + +/*===================================================================== +** +** Source: test8.c +** +** Purpose: Test #8 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %d"), pos, convert("foo 42")); + DoNumTest(convert("foo %ld"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hd"), 0xFFFF, convert("foo -1")); + DoNumTest(convert("foo %Ld"), pos, convert("foo 42")); + DoI64NumTest(convert("foo %I64d"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3d"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3d"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1d"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3d"), pos, convert("foo 042")); + DoNumTest(convert("foo %03d"), pos, convert("foo 042")); + DoNumTest(convert("foo %#d"), pos, convert("foo 42")); + DoNumTest(convert("foo %+d"), pos, convert("foo +42")); + DoNumTest(convert("foo % d"), pos, convert("foo 42")); + DoNumTest(convert("foo %+d"), neg, convert("foo -42")); + DoNumTest(convert("foo % d"), neg, convert("foo -42")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/testinfo.dat new file mode 100644 index 0000000..905740c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test8 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with decimal numbers. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/CMakeLists.txt new file mode 100644 index 0000000..e8117b5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_vsnwprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test9 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/test9.cpp new file mode 100644 index 0000000..38f6be2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/test9.cpp @@ -0,0 +1,49 @@ +// 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. + +/*===================================================================== +** +** Source: test9.c +** +** Purpose: Test #9 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %i"), pos, convert("foo 42")); + DoNumTest(convert("foo %li"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hi"), 0xFFFF, convert("foo -1")); + DoNumTest(convert("foo %Li"), pos, convert("foo 42")); + DoI64NumTest(convert("foo %I64i"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3i"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3i"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1i"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3i"), pos, convert("foo 042")); + DoNumTest(convert("foo %03i"), pos, convert("foo 042")); + DoNumTest(convert("foo %#i"), pos, convert("foo 42")); + DoNumTest(convert("foo %+i"), pos, convert("foo +42")); + DoNumTest(convert("foo % i"), pos, convert("foo 42")); + DoNumTest(convert("foo %+i"), neg, convert("foo -42")); + DoNumTest(convert("foo % i"), neg, convert("foo -42")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/testinfo.dat new file mode 100644 index 0000000..974efdb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test9 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with integer numbers += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/CMakeLists.txt new file mode 100644 index 0000000..b3f3107 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcsicmp_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcsicmp_test1 coreclrpal) + +target_link_libraries(paltest_wcsicmp_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.cpp new file mode 100644 index 0000000..dd4bb54 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.cpp @@ -0,0 +1,68 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests that _wcsicmp correctly compares two strings with +** case insensitivity. +** +** +**==========================================================================*/ + +#include + +/* + * Note: The _wcsicmp is dependent on the LC_CTYPE category of the locale, + * and this is ignored by these tests. + */ +int __cdecl main(int argc, char *argv[]) +{ + WCHAR str1[] = {'f','o','o',0}; + WCHAR str2[] = {'f','O','o',0}; + WCHAR str3[] = {'f','o','o','_','b','a','r',0}; + WCHAR str4[] = {'f','o','o','b','a','r',0}; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + if (_wcsicmp(str1, str2) != 0) + { + Fail ("ERROR: _wcsicmp returning incorrect value:\n" + "_wcsicmp(\"%S\", \"%S\") != 0\n", str1, str2); + } + + if (_wcsicmp(str2, str3) >= 0) + { + Fail ("ERROR: _wcsicmp returning incorrect value:\n" + "_wcsicmp(\"%S\", \"%S\") >= 0\n", str2, str3); + } + + if (_wcsicmp(str3, str4) >= 0) + { + Fail ("ERROR: _wcsicmp returning incorrect value:\n" + "_wcsicmp(\"%S\", \"%S\") >= 0\n", str3, str4); + } + + if (_wcsicmp(str4, str1) <= 0) + { + Fail ("ERROR: _wcsicmp returning incorrect value:\n" + "_wcsicmp(\"%S\", \"%S\") <= 0\n", str4, str1); + } + + if (_wcsicmp(str3, str2) <= 0) + { + Fail ("ERROR: _wcsicmp returning incorrect value:\n" + "_wcsicmp(\"%S\", \"%S\") <= 0\n", str2, str3); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/testinfo.dat new file mode 100644 index 0000000..9351a15 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = _wcsicmp +Name = Test #1 for _wcsicmp +TYPE = DEFAULT +EXE1 = test1 +Description += Tests that _wcsicmp correctly compares two strings with case insensitivity. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/CMakeLists.txt new file mode 100644 index 0000000..c2ed309 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcslwr_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcslwr_test1 coreclrpal) + +target_link_libraries(paltest_wcslwr_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/test1.cpp new file mode 100644 index 0000000..3a758de --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/test1.cpp @@ -0,0 +1,50 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Using memcmp to check the result, convert a wide character string +** with capitals, to all lowercase using this function. Test #1 for the +** wcslwr function +** +** +**==========================================================================*/ + +#include + +/* uses memcmp,wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR *test_str = NULL; + WCHAR *expect_str = NULL; + WCHAR *result_str = NULL; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + test_str = convert("aSdF 1#"); + expect_str = convert("asdf 1#"); + + result_str = _wcslwr(test_str); + if (memcmp(result_str, expect_str, wcslen(expect_str)*2 + 2) != 0) + { + Fail ("ERROR: Expected to get \"%s\", got \"%s\".\n", + convertC(expect_str), convertC(result_str)); + } + + free(result_str); + free(expect_str); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/testinfo.dat new file mode 100644 index 0000000..5d691d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _wcslwr +Name = Positive Test for _wcslwr +TYPE = DEFAULT +EXE1 = test1 +Description += Using memcmp to check the result, convert a wide character string += with capitals, to all lowercase using this function. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/CMakeLists.txt new file mode 100644 index 0000000..692e0d3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcsnicmp_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcsnicmp_test1 coreclrpal) + +target_link_libraries(paltest_wcsnicmp_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.cpp new file mode 100644 index 0000000..0271bcc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.cpp @@ -0,0 +1,95 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Take two wide strings and compare them, giving different lengths. +** Comparing str1 and str2 with str2 length, should return <0 +** Comparing str2 and str1 with str2 length, should return >0 +** Comparing str1 and str2 with str1 lenght, should return 0 +** Bring in str3, which has a capital, but this function is doing a lower +** case compare. Just ensure that two strings which differ only by capitals +** return 0. +** +** +**==========================================================================*/ + +#include + +/* + * Notes: uses wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR str1[] = {'f','o','o',0}; + WCHAR str2[] = {'f','o','o','x',0}; + WCHAR str3[] = {'f','O','o',0}; + WCHAR str4[] = {'A','B','C','D','E',0}; + WCHAR str5[] = {'A','B','C','D',']',0}; + WCHAR str6[] = {'a','b','c','d','e',0}; + WCHAR str7[] = {'a','b','c','d',']',0}; + char cstr1[] = "foo"; + char cstr2[] = "foox"; + char cstr3[] = "fOo"; + char cstr4[] = "ABCDE"; + char cstr5[] = "ABCD]"; + char cstr6[] = "abcde"; + char cstr7[] = "abcd]"; + + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + if (_wcsnicmp(str1, str2, wcslen(str2)) >= 0) + { + Fail ("ERROR: wcsnicmp(\"%s\", \"%s\", %d) returned >= 0\n", cstr1, + cstr2, wcslen(str2)); + } + + if (_wcsnicmp(str2, str1, wcslen(str2)) <= 0) + { + Fail ("ERROR: wcsnicmp(\"%s\", \"%s\", %d) returned <= 0\n", cstr2, + cstr1, wcslen(str2)); + } + + if (_wcsnicmp(str1, str2, wcslen(str1)) != 0) + { + Fail ("ERROR: wcsnicmp(\"%s\", \"%s\", %d) returned != 0\n", cstr1, + cstr2, wcslen(str1)); + } + + if (_wcsnicmp(str1, str3, wcslen(str1)) != 0) + { + Fail ("ERROR: wcsnicmp(\"%s\", \"%s\", %d) returned != 0\n", cstr1, + cstr3, wcslen(str1)); + } + + /* new testing */ + + /* str4 should be greater than str5 */ + if (_wcsnicmp(str4, str5, wcslen(str4)) <= 0) + { + Fail ("ERROR: _wcsnicmp(\"%s\", \"%s\", %d) returned >= 0\n", + cstr4, cstr5, wcslen(str4)); + } + + /* str6 should be greater than str7 */ + if (_wcsnicmp(str6, str7, wcslen(str6)) <= 0) + { + Fail ("ERROR: _wcsnicmp(\"%s\", \"%s\", %d) returned <= 0\n", + cstr6, cstr7, wcslen(str6)); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/testinfo.dat new file mode 100644 index 0000000..df49cc1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _wcsnicmp +Name = Positive Test for _wcsnicmp +TYPE = DEFAULT +EXE1 = test1 +Description += Take two wide strings and compare them, giving different lengths. += Comparing str1 and str2 with str2 length, should return <0 += Comparing str2 and str1 with str2 length, should return >0 += Comparing str1 and str2 with str1 lenght, should return 0 += Bring in str3, which has a capital, but this function is doing a lower += case compare. Just ensure that two strings which differ only by capitals += return 0. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/CMakeLists.txt new file mode 100644 index 0000000..7cd88f8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/CMakeLists.txt @@ -0,0 +1,8 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test1/CMakeLists.txt new file mode 100644 index 0000000..505ed84 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wfopen_test1 + ${SOURCES} +) + +add_dependencies(paltest_wfopen_test1 coreclrpal) + +target_link_libraries(paltest_wfopen_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test1/test1.cpp new file mode 100644 index 0000000..93fdb01 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test1/test1.cpp @@ -0,0 +1,79 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the _wfopen function. +** This test simply attempts to open a number of files with +** different modes. It checks to ensure a valid file +** pointer is returned. It doesn't do any checking to +** ensure the mode is really what it claims. +** + +** +**===================================================================*/ + + +#define UNICODE +#include + +struct testCase +{ + int CorrectResult; + WCHAR mode[20]; +}; + +int __cdecl main(int argc, char **argv) +{ + + FILE *fp; + WCHAR name[128]; + WCHAR base[] = {'t','e','s','t','f','i','l','e','s','\0'}; + char * PrintResult; + int i; + + struct testCase testCases[] = + { + {0, {'r','\0' }}, {1, {'w','\0'}}, {1, {'a','\0'}}, + {0, {'r','+','\0'}}, {1, {'w','+','\0'}}, {1, {'a','+','\0'}}, + {1, {'w','t','\0'}}, {1, {'w','b','\0'}}, {1, {'w','S','\0'}}, + {1, {'w','c','\0'}}, {1, {'w','n','\0'}}, {1, {'w', 'R','\0'}}, + {1, {'w','T','\0'}}, {0, {'t','w','\0'}}, {0, {'.','\0'}} + }; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + wcscpy(name,base); + wcscat(name,testCases[i].mode); + + fp = _wfopen(name,testCases[i].mode); + + if ((fp == 0 && testCases[i].CorrectResult != 0) || + (testCases[i].CorrectResult == 0 && fp != 0) ) + { + PrintResult = convertC(testCases[i].mode); + Fail("ERROR: fopen returned incorrectly " + "opening a file in %s mode. Perhaps it opened a " + "read only file which didn't exist and returned a correct " + "pointer?",PrintResult); + free(PrintResult); + } + + memset(name, '\0', 128 * sizeof(name[0])); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test1/testinfo.dat new file mode 100644 index 0000000..6514137 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _wfopen +Name = Positive Test for _wfopen +TYPE = DEFAULT +EXE1 = test1 +Description += This test simply attempts to open a number of files with different += modes. It checks to ensure a valid file pointer is returned. It += doesn't do any checking to ensure the mode is really what it claims. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test2/CMakeLists.txt new file mode 100644 index 0000000..427988b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_wfopen_test2 + ${SOURCES} +) + +add_dependencies(paltest_wfopen_test2 coreclrpal) + +target_link_libraries(paltest_wfopen_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test2/test2.cpp new file mode 100644 index 0000000..921ffef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test2/test2.cpp @@ -0,0 +1,68 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Tests the PAL implementation of the _wfopen function. +** Test to ensure that you can write to a 'w' mode file. +** And that you can't read from a 'w' mode file. +** +** Depends: +** fprintf +** fseek +** fgets +** + +** +**===================================================================*/ + +#define UNICODE +#include + +int __cdecl main(int argc, char **argv) +{ + + FILE *fp; + char buffer[128]; + WCHAR filename[] = {'t','e','s','t','f','i','l','e','\0'}; + WCHAR write[] = {'w','\0'}; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + if( (fp = _wfopen( filename, write )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'w' mode.\n" ); + } + + /* Test that you can write */ + if(fprintf(fp,"%s","some text") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'w' mode " + "but fprintf failed. Either fopen or fprintf have problems."); + } + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + /* Test that you can't read */ + if(fgets(buffer,10,fp) != NULL) + { + Fail("ERROR: Tried to READ from a file with only 'w' mode set. " + "This should fail, but fgets didn't return NULL. " + "Either fgets or fopen is broken."); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test2/testinfo.dat new file mode 100644 index 0000000..3ed2e3b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _wfopen +Name = Positive Test for _wfopen +TYPE = DEFAULT +EXE1 = test2 +Description += Test to ensure that you can write to a 'w' mode file. And that you can't += read from a 'w' mode file. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test3/CMakeLists.txt new file mode 100644 index 0000000..fb3c532 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_wfopen_test3 + ${SOURCES} +) + +add_dependencies(paltest_wfopen_test3 coreclrpal) + +target_link_libraries(paltest_wfopen_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test3/test3.cpp new file mode 100644 index 0000000..3b67818 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test3/test3.cpp @@ -0,0 +1,70 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Tests the PAL implementation of the _wfopen function. +** Test to ensure that you can write to a 'w+' mode file. +** And that you can read from a 'w+' mode file. +** +** Depends: +** fprintf +** fseek +** fgets +** + +** +**===================================================================*/ + +#define UNICODE + +#include + +int __cdecl main(int argc, char **argv) +{ + + FILE *fp; + char buffer[128]; + WCHAR filename[] = {'t','e','s','t','f','i','l','e','\0'}; + WCHAR writeplus[] = {'w','+','\0'}; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Open a file with 'w+' mode */ + if( (fp = _wfopen( filename, writeplus )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'w+' mode.\n" ); + } + + /* Write some text to the file */ + if(fprintf(fp,"%s","some text") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'w+' mode " + "but fprintf failed. Either fopen or fprintf have problems."); + } + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + /* Attempt to read from the 'w+' only file, should pass */ + if(fgets(buffer,10,fp) == NULL) + { + Fail("ERROR: Tried to READ from a file with 'w+' mode set. " + "This should succeed, but fgets returned NULL. Either fgets " + "or fopen is broken."); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test3/testinfo.dat new file mode 100644 index 0000000..3dd23e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test3/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _wfopen +Name = Positive Test for _wfopen +TYPE = DEFAULT +EXE1 = test3 +Description += Test to ensure that you can write to a 'w+' mode file. And that you can += read from a 'w+' mode file. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test4/CMakeLists.txt new file mode 100644 index 0000000..3f7839c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_wfopen_test4 + ${SOURCES} +) + +add_dependencies(paltest_wfopen_test4 coreclrpal) + +target_link_libraries(paltest_wfopen_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test4/test4.cpp new file mode 100644 index 0000000..0948fa1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test4/test4.cpp @@ -0,0 +1,87 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c +** +** Purpose: Tests the PAL implementation of the _wfopen function. +** Test to ensure that you can't write to a 'r' mode file. +** And that you can read from a 'r' mode file. +** +** Depends: +** fprintf +** fclose +** fgets +** + +** +**===================================================================*/ + +#define UNICODE + +#include + +int __cdecl main(int argc, char **argv) +{ + + FILE *fp; + char buffer[128]; + WCHAR filename[] = {'t','e','s','t','f','i','l','e','\0'}; + WCHAR write[] = {'w','\0'}; + WCHAR read[] = {'r','\0'}; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Open a file with 'w' mode */ + if( (fp = _wfopen( filename, write )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'w' mode.\n" ); + } + + /* Write some text to the file */ + if(fprintf(fp,"%s","some text") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'w' mode " + "but fprintf failed. Either fopen or fprintf have problems."); + } + + if(fclose(fp)) + { + Fail("ERROR: Attempted to close a file, but fclose failed. " + "This test depends upon it."); + } + + /* Open a file with 'r' mode */ + if( (fp = _wfopen( filename, read )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'r' mode.\n" ); + } + + /* Attempt to read from the 'r' only file, should pass */ + if(fgets(buffer,10,fp) == NULL) + { + Fail("ERROR: Tried to READ from a file with 'r' mode set. " + "This should succeed, but fgets returned NULL. Either fgets " + "or fopen is broken."); + } + + /* Write some text to the file */ + if(fprintf(fp,"%s","some text") > 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'r' mode " + "but fprintf succeeded It should have failed. " + "Either fopen or fprintf have problems."); + } + + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test4/testinfo.dat new file mode 100644 index 0000000..de41d77 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test4/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _wfopen +Name = Positive Test for _wfopen +TYPE = DEFAULT +EXE1 = test4 +Description += Test to ensure that you can't write to a 'r' mode file. And that you can += read from a 'r' mode file. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test5/CMakeLists.txt new file mode 100644 index 0000000..00e4a07 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_wfopen_test5 + ${SOURCES} +) + +add_dependencies(paltest_wfopen_test5 coreclrpal) + +target_link_libraries(paltest_wfopen_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test5/test5.cpp new file mode 100644 index 0000000..21e5ec8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test5/test5.cpp @@ -0,0 +1,82 @@ +// 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. + +/*===================================================================== +** +** Source: test5.c +** +** Purpose: Tests the PAL implementation of the _wfopen function. +** Test to ensure that you can write to a 'r+' mode file. +** And that you can read from a 'r+' mode file. +** +** Depends: +** fprintf +** fclose +** fgets +** fseek +** + +** +**===================================================================*/ +#define UNICODE + +#include + +int __cdecl main(int argc, char **argv) +{ + + FILE *fp; + char buffer[128]; + WCHAR filename[] = {'t','e','s','t','f','i','l','e','\0'}; + WCHAR write[] = {'w','\0'}; + WCHAR readplus[] = {'r','+','\0'}; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Open a file with 'w' mode */ + if( (fp = _wfopen( filename,write )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'w' mode.\n" ); + } + + if(fclose(fp)) + { + Fail("ERROR: Attempted to close a file, but fclose failed. " + "This test depends upon it."); + } + + if( (fp = _wfopen( filename, readplus )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'r+' mode.\n" ); + } + + /* Write some text to the file */ + if(fprintf(fp,"%s","some text") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'r+' mode " + "but fprintf failed. Either fopen or fprintf have problems."); + } + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + /* Attempt to read from the 'r+' only file, should pass */ + if(fgets(buffer,10,fp) == NULL) + { + Fail("ERROR: Tried to READ from a file with 'r+' mode set. " + "This should succeed, but fgets returned NULL. Either fgets " + "or fopen is broken."); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test5/testinfo.dat new file mode 100644 index 0000000..6be33cb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test5/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _wfopen +Name = Positive Test for _wfopen +TYPE = DEFAULT +EXE1 = test5 +Description += Test to ensure that you can write to a 'r+' mode file. And that you can += read from a 'r+' mode file. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test6/CMakeLists.txt new file mode 100644 index 0000000..1eb7eca --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_wfopen_test6 + ${SOURCES} +) + +add_dependencies(paltest_wfopen_test6 coreclrpal) + +target_link_libraries(paltest_wfopen_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test6/test6.cpp new file mode 100644 index 0000000..17d36a0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test6/test6.cpp @@ -0,0 +1,152 @@ +// 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. + +/*===================================================================== +** +** Source: test6.c +** +** Purpose: Tests the PAL implementation of the _wfopen function. +** Test to ensure that you can write to an 'a' mode file. +** And that you can't read from a 'a' mode file. +** +** Depends: +** fprintf +** fgets +** fseek +** + +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + FILE *fp; + char buffer[128]; + WCHAR filename[] = {'t','e','s','t','f','i','l','e','\0'}; + WCHAR filename2[] = {'t','e','s','t','f','i','l','e','2','\0'}; + WCHAR append[] = {'a','\0'}; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Open a file with 'a' mode */ + if( (fp = _wfopen( filename, append )) == NULL ) + { + Fail( "ERROR: file failed to open with 'a' mode.\n" ); + } + + /* Write some text to the file */ + if(fprintf(fp,"%s","some text") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'a' mode " + "but fprintf failed. Either fopen or fprintf have problems."); + } + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + /* Attempt to read from the 'a' only file, should fail */ + if(fgets(buffer,10,fp) != NULL) + { + Fail("ERROR: Tried to READ from a file with 'a' mode set. " + "This should fail, but fgets returned success. Either fgets " + "or fopen is broken."); + } + + // Delete the file now that we're done with it. + if (fclose(fp) != 0) + { + Fail("ERROR: fclose failed to close \"testfile\".\n"); + } + + if (!DeleteFileA("testfile")) + { + Fail("ERROR: Failed to delete \"testfile\".\n" + " Error is %d\n", + GetLastError()); + } + + /* Attempt to write to a file after using 'a' and fseek */ + fp = _wfopen(filename2, append); + if(fp == NULL) + { + Fail("ERROR: _wfopen failed to be created with 'a' mode.\n"); + } + + /* write text to the file initially */ + if(fprintf(fp,"%s","abcd") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'a' mode " + "but fprintf failed. Either fopen or fprintf have problems.\n"); + } + + /* set the pointer to the front of the file */ + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it.\n"); + } + + /* using 'a' should still write to the end of the file, not the front */ + if(fputs("efgh", fp) < 0) + { + Fail("ERROR: Attempt to WRITE with fputs to the beginning of a file " + "opened with 'a' mode succeeded.\n"); + } + + /* set the pointer to the front of the file */ + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it.\n"); + } + + /* a file with 'a' mode can only write, so close the file before reading */ + if(fclose(fp)) + { + Fail("ERROR: fclose failed when it should have succeeded.\n"); + } + + /* open the file again to read */ + fp = fopen("testfile2","r"); + if(fp == NULL) + { + Fail("ERROR: fopen failed to open the file using 'r' mode"); + } + + /* Attempt to read from the 'a' only file, should succeed */ + if(fgets(buffer,10,fp) == NULL) + { + Fail("ERROR: Tried to READ from a file with 'a' mode set. " + "This should pass, but fgets returned failure. Either fgets " + "or fopen is broken.\n"); + } + + /* Compare what was read and what should have been in the file */ + if(memcmp(buffer,"abcdefgh",8)) + { + Fail("ERROR: The string read should have equaled 'abcdefgh' " + "but instead it is %s\n", buffer); + } + + // Delete the file now that we're done with it. + if (fclose(fp) != 0) + { + Fail("ERROR: fclose failed to close \"testfile\".\n"); + } + + if (!DeleteFileA("testfile2")) + { + Fail("ERROR: Failed to delete \"testfile2\".\n"); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test6/testinfo.dat new file mode 100644 index 0000000..832f102 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test6/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _wfopen +Name = Positive Test for _wfopen +TYPE = DEFAULT +EXE1 = test6 +Description += Test to ensure that you can write to a 'a' mode file. And that you can't += read from a 'a' mode file. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test7/CMakeLists.txt new file mode 100644 index 0000000..9afa997 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_wfopen_test7 + ${SOURCES} +) + +add_dependencies(paltest_wfopen_test7 coreclrpal) + +target_link_libraries(paltest_wfopen_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test7/test7.cpp new file mode 100644 index 0000000..0a889ad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test7/test7.cpp @@ -0,0 +1,119 @@ +// 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. + +/*===================================================================== +** +** Source: test7.c +** +** Purpose: Tests the PAL implementation of the _wfopen function. +** Test to ensure that you can write to an 'a+' mode file. +** And that you can read from a 'a+' mode file. +** +** Depends: +** fprintf +** fgets +** fseek +** + +** +**===================================================================*/ +#define UNICODE + +#include + +int __cdecl main(int argc, char **argv) +{ + + FILE *fp; + char buffer[128]; + WCHAR filename[] = {'t','e','s','t','f','i','l','e','\0'}; + WCHAR filename2[] = {'t','e','s','t','f','i','l','e','2','\0'}; + WCHAR appendplus[] = {'a','+','\0'}; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Open a file with 'a+' mode */ + if( (fp = _wfopen( filename, appendplus )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'a+' mode.\n" ); + } + + /* Write some text to the file */ + if(fprintf(fp,"%s","some text") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'a+' mode " + "but fprintf failed. Either fopen or fprintf have problems."); + } + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + /* Attempt to read from the 'a+' only file, should succeed */ + if(fgets(buffer,10,fp) == NULL) + { + Fail("ERROR: Tried to READ from a file with 'a+' mode set. " + "This should pass, but fgets returned failure. Either fgets " + "or fopen is broken."); + } + + + /* Attempt to write to a file after using 'a+' and fseek */ + fp = _wfopen(filename2, appendplus); + if(fp == NULL) + { + Fail("ERROR: _wfopen failed to be created with 'a+' mode.\n"); + } + + /* write text to the file initially */ + if(fprintf(fp,"%s","abcd") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'a+' mode " + "but fprintf failed. Either fopen or fprintf have problems.\n"); + } + + /* set the pointer to the front of the file */ + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it.\n"); + } + + /* using 'a+' should still write to the end of the file, not the front */ + if(fputs("efgh",fp) < 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'a+' mode " + "but fputs failed.\n"); + } + + /* set the pointer to the front of the file */ + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it.\n"); + } + + /* Attempt to read from the 'a+' only file, should succeed */ + if(fgets(buffer,10,fp) == NULL) + { + Fail("ERROR: Tried to READ from a file with 'a+' mode set. " + "This should pass, but fgets returned failure. Either fgets " + "or fopen is broken.\n"); + } + + /* Compare what was read and what should have been in the file */ + if(memcmp(buffer,"abcdefgh",8)) + { + Fail("ERROR: The string read should have equaled 'abcdefgh' " + "but instead it is %s\n", buffer); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test7/testinfo.dat new file mode 100644 index 0000000..0c50efb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wfopen/test7/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _wfopen +Name = Positive Test for _wfopen +TYPE = DEFAULT +EXE1 = test7 +Description += Test to ensure that you can write to a 'a+' mode file. And that you can += read from a 'a+' mode file. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/test1/CMakeLists.txt new file mode 100644 index 0000000..a7243e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wtoi_test1 + ${SOURCES} +) + +add_dependencies(paltest_wtoi_test1 coreclrpal) + +target_link_libraries(paltest_wtoi_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.cpp new file mode 100644 index 0000000..0b14ded --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.cpp @@ -0,0 +1,79 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the _wtoi function. +** Check to ensure that the different ints are handled properly. +** Exponents and decimals should be treated as invalid characters, +** causing the conversion to quit. Whitespace before the int is valid. +** Check would-be octal/hex digits to ensure they're treated no +** differently than other strings. +** +** +**===================================================================*/ + +#include + + +struct testCase +{ + int IntValue; + char avalue[20]; +}; + +int __cdecl main(int argc, char **argv) +{ + + int result=0; + int i=0; + WCHAR* temp; + + struct testCase testCases[] = + { + {1234, "1234"}, + {-1234, "-1234"}, + {1234, "+1234"}, + {1234, "1234.44"}, + {1234, "1234e-5"}, + {1234, "1234e+5"}, + {1234, "1234E5"}, + {1234, "\t1234"}, + {0, "0x21"}, + {17, "017"}, + {1234, "1234.657e-8"}, + {1234567, " 1234567e-8 foo"}, + {0, "foo 32 bar"} + }; + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Loop through each case. Convert the wide string to an int + and then compare to ensure that it is the correct value. + */ + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + /* Convert to a wide string, then call _wtoi to convert to an int */ + temp = convert(testCases[i].avalue); + result = _wtoi(temp); + free(temp); + if (testCases[i].IntValue != result) + { + Fail("ERROR: _wtoi misinterpreted \"%s\" as %i instead of %i.\n", + testCases[i].avalue, + result, + testCases[i].IntValue); + } + + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/test1/testinfo.dat new file mode 100644 index 0000000..4a1f21d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/_wtoi/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = _wtoi +Name = Test _wtoi on valid and invalid ints in a variety of formats +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the _wtoi function. += Check to ensure that the different ints are handled properly. += Exponents and decimals should be treated as invalid characters, += causing the conversion to quit. Whitespace before the int is valid. += Check would-be octal/hex digits to ensure they're treated no += differently than other strings. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/test1/CMakeLists.txt new file mode 100644 index 0000000..89bccbb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + abs.cpp +) + +add_executable(paltest_abs_test1 + ${SOURCES} +) + +add_dependencies(paltest_abs_test1 coreclrpal) + +target_link_libraries(paltest_abs_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/test1/abs.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/test1/abs.cpp new file mode 100644 index 0000000..233a5dc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/test1/abs.cpp @@ -0,0 +1,54 @@ +// 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. + +/*===================================================================== +** +** Source: abs.c (test 1) +** +** Purpose: Tests the PAL implementation of the abs function. +** +** +**===================================================================*/ + +#include + +struct TESTS +{ + int nTest; + int nResult; +}; + +int __cdecl main(int argc, char *argv[]) +{ + int i = 0; + int nRc = 0; + struct TESTS testCase[] = + { + {0, 0}, + {1, 1}, + {-1, 1} + }; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + for (i = 0; i < (sizeof(testCase)/sizeof(struct TESTS)); i++) + { + nRc = abs(testCase[i].nTest); + if (nRc != testCase[i].nResult) + { + Fail("abs: ERROR -> abs(%d) returned %d " + "when it was expected to return %d \n", + testCase[i].nTest, + nRc, + testCase[i].nResult); + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/test1/testinfo.dat new file mode 100644 index 0000000..98e2af2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/abs/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C runtime +Function = abs +Name = test for abs (test 1) +Type = DEFAULT +EXE1 = abs +Description += Test abs by passing a list of values and ensuring the += proper absolute value is returned. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/test1/CMakeLists.txt new file mode 100644 index 0000000..e654dc3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_acos_test1 + ${SOURCES} +) + +add_dependencies(paltest_acos_test1 coreclrpal) + +target_link_libraries(paltest_acos_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/test1/test1.cpp new file mode 100644 index 0000000..c6ed069 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/test1/test1.cpp @@ -0,0 +1,130 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that acos return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = acos(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("acos(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = acos(value); + + if (!_isnan(result)) + { + Fail("acos(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { -1, 3.1415926535897932, PAL_EPSILON * 10 }, // expected: pi + { -0.91173391478696510, 2.7182818284590452, PAL_EPSILON * 10 }, // expected: e + { -0.66820151019031295, 2.3025850929940457, PAL_EPSILON * 10 }, // expected: ln(10) + { 0, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2 + { 0.12775121753523991, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e) + { 0.15594369476537447, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2) + { 0.42812514788535792, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi) + { 0.54030230586813972, 1, PAL_EPSILON * 10 }, + { 0.70710678118654752, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrt(2) + { 0.76024459707563015, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2) + { 0.76923890136397213, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2) + { 0.80410982822879171, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi + { 0.90716712923909839, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e) + { 0.94976571538163866, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi + { 1, 0, PAL_EPSILON }, + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/test1/testinfo.dat new file mode 100644 index 0000000..4b43982 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acos/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = acos +Name = Positive Test for acos +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the acos() function, += checking each for the expected result. Also checks += for proper handling of out-of-range values. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/test1/CMakeLists.txt new file mode 100644 index 0000000..2952068 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_acosf_test1 + ${SOURCES} +) + +add_dependencies(paltest_acosf_test1 coreclrpal) + +target_link_libraries(paltest_acosf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/test1/test1.c new file mode 100644 index 0000000..3d8668c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/test1/test1.c @@ -0,0 +1,129 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that acosf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = acosf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("acosf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = acosf(value); + + if (!_isnanf(result)) + { + Fail("acosf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { -1, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi + { -0.911733915f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { -0.668201510f, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10) + { 0, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { 0.127751218f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 0.155943695f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 0.428125148f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 0.540302306f, 1, PAL_EPSILON * 10 }, + { 0.707106781f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrtf(2) + { 0.760244597f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 0.769238901f, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 0.804109828f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 0.907167129f, 0.434294482f, PAL_EPSILON }, // expected: logf10f(e) + { 0.949765715f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 1, 0, PAL_EPSILON }, + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/test1/testinfo.dat new file mode 100644 index 0000000..41cead3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosf/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = acosf +Name = Positive Test for acosf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the acosf() function, += checking each for the expfected result. Also checks += for proper handling of out-of-range values. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/test1/CMakeLists.txt new file mode 100644 index 0000000..dfd0405 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_acosh_test1 + ${SOURCES} +) + +add_dependencies(paltest_acosh_test1 coreclrpal) + +target_link_libraries(paltest_acosh_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/test1/test1.cpp new file mode 100644 index 0000000..14ff430 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/test1/test1.cpp @@ -0,0 +1,129 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that acosh return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = acosh(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("acosh(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = acosh(value); + + if (!_isnan(result)) + { + Fail("acosh(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 1, 0, PAL_EPSILON }, + { 1.0510897883672876, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi + { 1.0957974645564909, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e) + { 1.2095794864199787, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi + { 1.25, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2) + { 1.2605918365213561, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2) + { 1.3246090892520058, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4 + { 1.5430806348152438, 1, PAL_EPSILON * 10 }, + { 1.7071001431069344, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi) + { 2.1781835566085709, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2) + { 2.2341880974508023, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e) + { 2.5091784786580568, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2 + { 5.05, 2.3025850929940457, PAL_EPSILON * 10 }, // expected: ln(10) + { 7.6101251386622884, 2.7182818284590452, PAL_EPSILON * 10 }, // expected: e + { 11.591953275521521, 3.1415926535897932, PAL_EPSILON * 10 }, // expected: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/test1/testinfo.dat new file mode 100644 index 0000000..32d69ee --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acosh/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = acosh +Name = Positive Test for acosh +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the acosh() function, += checking each for the expected result. Also checks += for proper handling of out-of-range values. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/test1/CMakeLists.txt new file mode 100644 index 0000000..3b692e3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_acoshf_test1 + ${SOURCES} +) + +add_dependencies(paltest_acoshf_test1 coreclrpal) + +target_link_libraries(paltest_acoshf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/test1/test1.c new file mode 100644 index 0000000..2209999 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/test1/test1.c @@ -0,0 +1,128 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that acoshf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = acoshf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("acoshf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = acoshf(value); + + if (!_isnanf(result)) + { + Fail("acoshf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 1, 0, PAL_EPSILON }, + { 1.05108979f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 1.09579746f, 0.434294482f, PAL_EPSILON }, // expected: log10f(e) + { 1.20957949f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 1.25f, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 1.26059184f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 1.32460909f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { 1.54308063f, 1, PAL_EPSILON * 10 }, + { 1.70710014f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 2.17818356f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 2.23418810f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 2.50917848f, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { 5.05f, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10) + { 7.61012514f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { 11.5919533f, 3.14159265f, PAL_EPSILON * 100 }, // expected: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/test1/testinfo.dat new file mode 100644 index 0000000..07d78ad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/acoshf/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = acoshf +Name = Positive Test for acoshf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the acoshf() function, += checking each for the expfected result. Also checks += for proper handling of out-of-range values. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/test1/CMakeLists.txt new file mode 100644 index 0000000..92ba845 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_asin_test1 + ${SOURCES} +) + +add_dependencies(paltest_asin_test1 coreclrpal) + +target_link_libraries(paltest_asin_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/test1/test1.cpp new file mode 100644 index 0000000..0a63356 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/test1/test1.cpp @@ -0,0 +1,146 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that asin return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = asin(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("asin(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = asin(value); + + if (!_isnan(result)) + { + Fail("asin(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * validate + * + * test validation function for values returning +INF + */ +void __cdecl validate_isinf_positive(double value) +{ + double result = asin(value); + + if (result != PAL_POSINF) + { + Fail("asin(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_POSINF); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.31296179620778659, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi + { 0.41078129050290870, 0.42331082513074800, PAL_EPSILON }, // expected: pi - e + { 0.42077048331375735, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e) + { 0.59448076852482208, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi + { 0.63896127631363480, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2) + { 0.64963693908006244, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2) + { 0.70710678118654752, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrt(2) + { 0.74398033695749319, 0.83900756059574755, PAL_EPSILON }, // expected: pi - ln(10) + { 0.84147098480789651, 1, PAL_EPSILON * 10 }, + { 0.90371945743584630, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi) + { 0.98776594599273553, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2) + { 0.99180624439366372, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e) + { 1, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2 + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/test1/testinfo.dat new file mode 100644 index 0000000..fba9f95 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asin/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = asin +Name = Positive Test for asin +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the asin() function, += checking each for the expected result. Also checks += for proper handling of out-of-range values. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/test1/CMakeLists.txt new file mode 100644 index 0000000..178bbe7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_asinf_test1 + ${SOURCES} +) + +add_dependencies(paltest_asinf_test1 coreclrpal) + +target_link_libraries(paltest_asinf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/test1/test1.c new file mode 100644 index 0000000..773015e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/test1/test1.c @@ -0,0 +1,145 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that asinf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = asinf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("asinf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = asinf(value); + + if (!_isnanf(result)) + { + Fail("asinf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * validate + * + * test validation function for values returning +INF + */ +void __cdecl validate_isinf_positive(float value) +{ + float result = asinf(value); + + if (result != PAL_POSINF) + { + Fail("asinf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_POSINF); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.312961796f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 0.410781291f, 0.423310825f, PAL_EPSILON }, // expected: pi - e + { 0.420770483f, 0.434294482f, PAL_EPSILON }, // expected: logf10f(e) + { 0.594480769f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 0.638961276f, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 0.649636939f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 0.707106781f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrtf(2) + { 0.743980337f, 0.839007561f, PAL_EPSILON }, // expected: pi - ln(10) + { 0.841470985f, 1, PAL_EPSILON * 10 }, + { 0.903719457f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 0.987765946f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 0.991806244f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 1, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/test1/testinfo.dat new file mode 100644 index 0000000..ca2dd42 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinf/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = asinf +Name = Positive Test for asinf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the asinf() function, += checking each for the expected result. Also checks += for proper handling of out-of-range values. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/test1/CMakeLists.txt new file mode 100644 index 0000000..c1b9f95 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_asinh_test1 + ${SOURCES} +) + +add_dependencies(paltest_asinh_test1 coreclrpal) + +target_link_libraries(paltest_asinh_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/test1/test1.cpp new file mode 100644 index 0000000..64c1e4a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/test1/test1.cpp @@ -0,0 +1,146 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that asinh return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = asinh(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("asinh(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = asinh(value); + + if (!_isnan(result)) + { + Fail("asinh(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * validate + * + * test validation function for values returning +INF + */ +void __cdecl validate_isinf_positive(double value) +{ + double result = asinh(value); + + if (result != PAL_POSINF) + { + Fail("asinh(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_POSINF); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.32371243907207108, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi + { 0.44807597941469025, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e) + { 0.68050167815224332, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi + { 0.75, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2) + { 0.76752314512611633, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2) + { 0.86867096148600961, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4 + { 1.1752011936438015, 1, PAL_EPSILON * 10 }, + { 1.3835428792038633, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi) + { 1.9350668221743567, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2) + { 1.9978980091062796, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e) + { 2.3012989023072949, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2 + { 4.95, 2.3025850929940457, PAL_EPSILON * 10 }, // expected: ln(10) + { 7.5441371028169758, 2.7182818284590452, PAL_EPSILON * 10 }, // expected: e + { 11.548739357257748, 3.1415926535897932, PAL_EPSILON * 10 }, // expected: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/test1/testinfo.dat new file mode 100644 index 0000000..c5e9530 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinh/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = asinh +Name = Positive Test for asinh +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the asinh() function, += checking each for the expected result. Also checks += for proper handling of out-of-range values. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/test1/CMakeLists.txt new file mode 100644 index 0000000..92df683 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_asinhf_test1 + ${SOURCES} +) + +add_dependencies(paltest_asinhf_test1 coreclrpal) + +target_link_libraries(paltest_asinhf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/test1/test1.c new file mode 100644 index 0000000..6ecb8d9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/test1/test1.c @@ -0,0 +1,145 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that asinhf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = asinhf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("asinhf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = asinhf(value); + + if (!_isnanf(result)) + { + Fail("asinhf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * validate + * + * test validation function for values returning +INF + */ +void __cdecl validate_isinf_positive(float value) +{ + float result = asinhf(value); + + if (result != PAL_POSINF) + { + Fail("asinhf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_POSINF); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.323712439f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 0.448075979f, 0.434294482f, PAL_EPSILON }, // expected: log10f(e) + { 0.680501678f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 0.75, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 0.767523145f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 0.868670961f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { 1.17520119f, 1, PAL_EPSILON * 10 }, + { 1.38354288f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 1.93506682f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 1.99789801f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 2.30129890f, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { 4.95f, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10) + { 7.54413710f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { 11.5487394f, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/test1/testinfo.dat new file mode 100644 index 0000000..023796b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/asinhf/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = asinhf +Name = Positive Test for asinhf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the asinhf() function, += checking each for the expected result. Also checks += for proper handling of out-of-range values. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/test1/CMakeLists.txt new file mode 100644 index 0000000..5829060 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_atan_test1 + ${SOURCES} +) + +add_dependencies(paltest_atan_test1 coreclrpal) + +target_link_libraries(paltest_atan_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/test1/test1.cpp new file mode 100644 index 0000000..6840d46 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/test1/test1.cpp @@ -0,0 +1,128 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that atan return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = atan(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("atan(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = atan(value); + + if (!_isnan(result)) + { + Fail("atan(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.32951473309607836, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi + { 0.45054953406980750, 0.42331082513074800, PAL_EPSILON }, // expected: pi - e + { 0.46382906716062964, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e) + { 0.73930295048660405, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi + { 0.83064087786078395, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2) + { 0.85451043200960189, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2) + { 1, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4 + { 1.1134071468135374, 0.83900756059574755, PAL_EPSILON }, // expected: pi - ln(10) + { 1.5574077246549022, 1, PAL_EPSILON * 10 }, + { 2.1108768356626451, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi) + { 6.3341191670421916, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2) + { 7.7635756709721848, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e) + { PAL_POSINF, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2 + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/test1/testinfo.dat new file mode 100644 index 0000000..8a181b8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = atan +Name = Positive Test for atan +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the atan() function, += checking each for the expected result. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/test1/CMakeLists.txt new file mode 100644 index 0000000..655c701 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_atan2_test1 + ${SOURCES} +) + +add_dependencies(paltest_atan2_test1 coreclrpal) + +target_link_libraries(paltest_atan2_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/test1/test1.cpp new file mode 100644 index 0000000..15aa8f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/test1/test1.cpp @@ -0,0 +1,148 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that atan2 returns correct values for a subset of values. +** Tests with positive and negative values of x and y to ensure +** atan2 is returning results from the correct quadrant. +** +**===================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +struct test +{ + double y; /* second component of the value to test the function with */ + double x; /* first component of the value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double y, double x, double expected, double variance) +{ + double result = atan2(y, x); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("atan2(%g, %g) returned %20.17g when it should have returned %20.17g", + y, x, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double y, double x) +{ + double result = atan2(y, x); + + if (!_isnan(result)) + { + Fail("atan2(%g, %g) returned %20.17g when it should have returned %20.17g", + y, x, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* y x expected variance */ + { 0, PAL_POSINF, 0, PAL_EPSILON }, + { 0, 0, 0, PAL_EPSILON }, + { 0.31296179620778659, 0.94976571538163866, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi + { 0.42077048331375735, 0.90716712923909839, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e) + { 0.59448076852482208, 0.80410982822879171, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi + { 0.63896127631363480, 0.76923890136397213, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2) + { 0.64963693908006244, 0.76024459707563015, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2) + { 0.70710678118654752, 0.70710678118654752, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrt(2) + { 1, 1, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4 + { PAL_POSINF, PAL_POSINF, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4 + { 0.84147098480789651, 0.54030230586813972, 1, PAL_EPSILON * 10 }, + { 0.90371945743584630, 0.42812514788535792, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi) + { 0.98776594599273553, 0.15594369476537447, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2) + { 0.99180624439366372, 0.12775121753523991, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e) + { 1, 0, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2 + { PAL_POSINF, 0, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2 + { PAL_POSINF, 1, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2 + { 0.74398033695749319, -0.66820151019031295, 2.3025850929940457, PAL_EPSILON * 10 }, // expected: ln(10) + { 0.41078129050290870, -0.91173391478696510, 2.7182818284590452, PAL_EPSILON * 10 }, // expected: e + { 0, -1, 3.1415926535897932, PAL_EPSILON * 10 }, // expected: pi + { 1, PAL_POSINF, 0, PAL_EPSILON }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + const double pi = 3.1415926535897932; + + validate( tests[i].y, tests[i].x, tests[i].expected, tests[i].variance); + validate(-tests[i].y, tests[i].x, -tests[i].expected, tests[i].variance); + validate( tests[i].y, -tests[i].x, pi - tests[i].expected, tests[i].variance); + validate(-tests[i].y, -tests[i].x, tests[i].expected - pi, tests[i].variance); + } + + validate_isnan(PAL_NEGINF, PAL_NAN); + validate_isnan(PAL_NAN, PAL_NEGINF); + validate_isnan(PAL_NAN, PAL_POSINF); + validate_isnan(PAL_POSINF, PAL_NAN); + + validate_isnan(PAL_NAN, -1); + validate_isnan(PAL_NAN, -0.0); + validate_isnan(PAL_NAN, 0); + validate_isnan(PAL_NAN, 1); + + validate_isnan(-1, PAL_NAN); + validate_isnan(-0.0, PAL_NAN); + validate_isnan( 0, PAL_NAN); + validate_isnan( 1, PAL_NAN); + + validate_isnan(PAL_NAN, PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/test1/testinfo.dat new file mode 100644 index 0000000..78fb091 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = atan2 +Name = Test #1 for atan2 +Type = DEFAULT +EXE1 = test1 +Description +=Tests that atan2 returns correct values for a subset of values. +=Tests with positive and negative values of x and y to ensure +=atan2 is returning results from the correct quadrant. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/test1/CMakeLists.txt new file mode 100644 index 0000000..d5b28ce --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_atan2f_test1 + ${SOURCES} +) + +add_dependencies(paltest_atan2f_test1 coreclrpal) + +target_link_libraries(paltest_atan2f_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/test1/test1.c new file mode 100644 index 0000000..2ee641e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/test1/test1.c @@ -0,0 +1,147 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that atan2f returns correct values for a subset of values. +** Tests with positive and negative values of x and y to ensure +** atan2f is returning results from the correct quadrant. +** +**===================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +struct test +{ + float y; /* second component of the value to test the function with */ + float x; /* first component of the value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float y, float x, float expected, float variance) +{ + float result = atan2f(y, x); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("atan2f(%g, %g) returned %10.9g when it should have returned %10.9g", + y, x, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float y, float x) +{ + float result = atan2f(y, x); + + if (!_isnanf(result)) + { + Fail("atan2f(%g, %g) returned %10.9g when it should have returned %10.9g", + y, x, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* y x expected variance */ + { 0, PAL_POSINF, 0, PAL_EPSILON }, + { 0, 0, 0, PAL_EPSILON }, + { 0.312961796f, 0.949765715f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 0.420770483f, 0.907167129f, 0.434294482f, PAL_EPSILON }, // expected: logf10f(e) + { 0.594480769f, 0.804109828f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 0.638961276f, 0.769238901f, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 0.649636939f, 0.760244597f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 0.707106781f, 0.707106781f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrtf(2) + { 1, 1, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { PAL_POSINF, PAL_POSINF, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { 0.841470985f, 0.540302306f, 1, PAL_EPSILON * 10 }, + { 0.903719457f, 0.428125148f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 0.987765946f, 0.155943695f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 0.991806244f, 0.127751218f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 1, 0, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { PAL_POSINF, 0, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { PAL_POSINF, 1, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { 0.743980337f, -0.668201510f, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10) + { 0.410781291f, -0.911733915f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { 0, -1, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi + { 1, PAL_POSINF, 0, PAL_EPSILON }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + const float pi = 3.14159265f; + + validate( tests[i].y, tests[i].x, tests[i].expected, tests[i].variance); + validate(-tests[i].y, tests[i].x, -tests[i].expected, tests[i].variance); + validate( tests[i].y, -tests[i].x, pi - tests[i].expected, tests[i].variance); + validate(-tests[i].y, -tests[i].x, tests[i].expected - pi, tests[i].variance); + } + + validate_isnan(PAL_NEGINF, PAL_NAN); + validate_isnan(PAL_NAN, PAL_NEGINF); + validate_isnan(PAL_NAN, PAL_POSINF); + validate_isnan(PAL_POSINF, PAL_NAN); + + validate_isnan(PAL_NAN, -1); + validate_isnan(PAL_NAN, -0.0f); + validate_isnan(PAL_NAN, 0); + validate_isnan(PAL_NAN, 1); + + validate_isnan(-1, PAL_NAN); + validate_isnan(-0.0f, PAL_NAN); + validate_isnan( 0, PAL_NAN); + validate_isnan( 1, PAL_NAN); + + validate_isnan(PAL_NAN, PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/test1/testinfo.dat new file mode 100644 index 0000000..bd9a9d9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atan2f/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = atan2f +Name = Test #1 for atan2f +Type = DEFAULT +EXE1 = test1 +Description +=Tests that atan2f returns correct values for a subset of values. +=Tests with positive and negative values of x and y to ensure +=atan2f is returning results from the correct quadrant. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/test1/CMakeLists.txt new file mode 100644 index 0000000..70df46a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_atanf_test1 + ${SOURCES} +) + +add_dependencies(paltest_atanf_test1 coreclrpal) + +target_link_libraries(paltest_atanf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/test1/test1.c new file mode 100644 index 0000000..543a0a8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/test1/test1.c @@ -0,0 +1,127 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that atanf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = atanf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("atanf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = atanf(value); + + if (!_isnanf(result)) + { + Fail("atanf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.329514733f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 0.450549534f, 0.423310825f, PAL_EPSILON }, // expected: pi - e + { 0.463829067f, 0.434294482f, PAL_EPSILON }, // expected: logf10f(e) + { 0.739302950f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 0.830640878f, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 0.854510432f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 1, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { 1.11340715f, 0.839007561f, PAL_EPSILON }, // expected: pi - ln(10) + { 1.55740772f, 1, PAL_EPSILON * 10 }, + { 2.11087684f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 6.33411917f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 7.76357567f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { PAL_POSINF, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/test1/testinfo.dat new file mode 100644 index 0000000..0d18427 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = atanf +Name = Positive Test for atanf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the atanf() function, += checking each for the expected result. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/test1/CMakeLists.txt new file mode 100644 index 0000000..e55fc35 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_atanh_test1 + ${SOURCES} +) + +add_dependencies(paltest_atanh_test1 coreclrpal) + +target_link_libraries(paltest_atanh_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/test1/test1.cpp new file mode 100644 index 0000000..d454f32 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/test1/test1.cpp @@ -0,0 +1,130 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that atanh return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = atanh(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("atanh(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = atanh(value); + + if (!_isnan(result)) + { + Fail("atanh(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.30797791269089433, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi + { 0.40890401183401433, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e) + { 0.56259360033158334, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi + { 0.6, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2) + { 0.60885936501391381, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2) + { 0.65579420263267244, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4 + { 0.76159415595576489, 1, PAL_EPSILON * 10 }, + { 0.81046380599898809, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi) + { 0.88838556158566054, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2) + { 0.89423894585503855, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e) + { 0.91715233566727435, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2 + { 0.98019801980198020, 2.3025850929940457, PAL_EPSILON * 10 }, // expected: ln(10) + { 0.99132891580059984, 2.7182818284590452, PAL_EPSILON * 10 }, // expected: e + { 0.99627207622074994, 3.1415926535897932, PAL_EPSILON * 10 }, // expected: pi + { 1, PAL_POSINF, PAL_EPSILON * 10 } + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/test1/testinfo.dat new file mode 100644 index 0000000..55e1db7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanh/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = atanh +Name = Positive Test for atanh +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the atanh() function, += checking each for the expected result. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/test1/CMakeLists.txt new file mode 100644 index 0000000..88e7a36 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_atanhf_test1 + ${SOURCES} +) + +add_dependencies(paltest_atanhf_test1 coreclrpal) + +target_link_libraries(paltest_atanhf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/test1/test1.c new file mode 100644 index 0000000..3fd3ab8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/test1/test1.c @@ -0,0 +1,129 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that atanhf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = atanhf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("atanhf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = atanhf(value); + + if (!_isnanf(result)) + { + Fail("atanhf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.307977913f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 0.408904012f, 0.434294482f, PAL_EPSILON }, // expected: log10f(e) + { 0.562593600f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 0.6f, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 0.608859365f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 0.655794203f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { 0.761594156f, 1, PAL_EPSILON * 10 }, + { 0.810463806f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 0.888385562f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 0.894238946f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 0.917152336f, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { 0.980198020f, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10) + { 0.991328916f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { 0.996272076f, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi + { 1, PAL_POSINF, PAL_EPSILON * 10 } + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/test1/testinfo.dat new file mode 100644 index 0000000..842c0d9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atanhf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = atanhf +Name = Positive Test for atanhf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the atanhf() function, += checking each for the expected result. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/test1/CMakeLists.txt new file mode 100644 index 0000000..dbc898a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_atof_test1 + ${SOURCES} +) + +add_dependencies(paltest_atof_test1 coreclrpal) + +target_link_libraries(paltest_atof_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/test1/test1.cpp new file mode 100644 index 0000000..a973133 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/test1/test1.cpp @@ -0,0 +1,75 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Passes to atof() a series of strings containing floats, +** checking that each one is correctly extracted. +** +** +**==========================================================================*/ + +#include +#include + +struct testCase +{ + float fvalue; + char avalue[20]; +}; + +int __cdecl main(int argc, char **argv) +{ + int i = 0; + double f = 0; + struct testCase testCases[] = + { + {1234, "1234"}, + {-1234, "-1234"}, + {1234e-5, "1234e-5"}, + {1234e+5, "1234e+5"}, + {1234e5, "1234E5"}, + {1234.567e-8, "1234.567e-8"}, + {1234.567e-8, " 1234.567e-8 foo"}, + {0,"a12"} + }; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + /*Convert the string to a float.*/ + f = atof(testCases[i].avalue); + double result = f - testCases[i].fvalue; + + if (fabs(result) > FLT_EPSILON) + { + Fail ("atof misinterpreted \"%s\" as %g instead of %g. result %g fabs %g\n", + testCases[i].avalue, f, testCases[i].fvalue, result, fabs(result)); + } + } + PAL_Terminate(); + return PASS; +} + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/test1/testinfo.dat new file mode 100644 index 0000000..7f37aff --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atof/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = atof +Name = Positive Test for atof +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to atof() a series of strings containing floats, checking that += each one is correctly extracted. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/test1/CMakeLists.txt new file mode 100644 index 0000000..92426e1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_atoi_test1 + ${SOURCES} +) + +add_dependencies(paltest_atoi_test1 coreclrpal) + +target_link_libraries(paltest_atoi_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/test1/test1.cpp new file mode 100644 index 0000000..2554d4c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/test1/test1.cpp @@ -0,0 +1,86 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the atoi function. +** Check to ensure that the different ints (normal, +** negative, decimal,exponent), all work as expected with +** this function. +** +** +**===================================================================*/ + +#include + + +struct testCase +{ + int IntValue; + char avalue[20]; +}; + +int __cdecl main(int argc, char **argv) +{ + + int result=0; + int i=0; + + struct testCase testCases[] = + { + {1234, "1234"}, + {-1234, "-1234"}, + {1234, "1234.44"}, + {1234, "1234e-5"}, + {1234, "1234e+5"}, + {1234, "1234E5"}, + {1234, "1234.657e-8"}, + {1234567, " 1234567e-8 foo"}, + {0, "aaa 32 test"} + }; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Loop through each case. Convert the string to an int + and then compare to ensure that it is the correct value. + */ + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + /*Convert the string to an int.*/ + result = atoi(testCases[i].avalue); + + if (testCases[i].IntValue != result) + { + Fail("ERROR: atoi misinterpreted \"%s\" as %i instead of %i.\n" + , testCases[i].avalue, result, testCases[i].IntValue); + } + + } + + + PAL_Terminate(); + return PASS; +} + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/test1/testinfo.dat new file mode 100644 index 0000000..36a1a44 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/atoi/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = atoi +Name = Positive Test for atoi +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the atoi function. += Check to ensure that the different ints (normal, negative, decimal, += exponent), all work as expected with this function. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test1/CMakeLists.txt new file mode 100644 index 0000000..c24a88c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_bsearch_test1 + ${SOURCES} +) + +add_dependencies(paltest_bsearch_test1 coreclrpal) + +target_link_libraries(paltest_bsearch_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test1/test1.cpp new file mode 100644 index 0000000..c4b9173 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test1/test1.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Calls bsearch to find a character in a sorted buffer, and +** verifies that the correct position is returned. +** +** +**==========================================================================*/ + +#include + +int __cdecl charcmp(const void *pa, const void *pb) +{ + return memcmp(pa, pb, 1); +} + +int __cdecl main(int argc, char **argv) +{ + + const char array[] = "abcdefghij"; + char * found=NULL; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + found = (char *)bsearch(&"d", array, sizeof(array) - 1, (sizeof(char)) + , charcmp); + if (found != array + 3) + { + Fail ("bsearch was unable to find a specified character in a " + "sorted list.\n"); + } + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test1/testinfo.dat new file mode 100644 index 0000000..3eb7369 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = bsearch +Name = Positive Test for bsearch +TYPE = DEFAULT +EXE1 = test1 +Description += Calls bsearch to find a character in a sorted buffer, and += verifies that the correct position is returned. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test2/CMakeLists.txt new file mode 100644 index 0000000..3f86291 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_bsearch_test2 + ${SOURCES} +) + +add_dependencies(paltest_bsearch_test2 coreclrpal) + +target_link_libraries(paltest_bsearch_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test2/test2.cpp new file mode 100644 index 0000000..6de1b3f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test2/test2.cpp @@ -0,0 +1,57 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Calls bsearch to find a character in a sorted buffer, +** that does not exist. +** +** +**==========================================================================*/ + +#include + +int __cdecl charcmp(const void *pa, const void *pb) +{ + return *(const char *)pa - *(const char *)pb; +} + +int __cdecl main(int argc, char **argv) +{ + + const char array[] = "abcefghij"; + const char missing[] = "0dz"; + char * found=NULL; + const char * candidate = missing; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + while (*candidate) { + found = (char *)bsearch(candidate, array, sizeof(array) - 1, + (sizeof(char)), charcmp); + if (found != NULL) + { + Fail ("ERROR: bsearch was able to find a specified character '%c' " + "in a sorted list '%s' as '%c' " + "even though the character is not in the list.\n", + *candidate, array, *found); + } + + candidate++; + } + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test2/testinfo.dat new file mode 100644 index 0000000..faa9dc1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/bsearch/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = bsearch +Name = Negative Test for bsearch +TYPE = DEFAULT +EXE1 = test2 +Description += Calls bsearch to find a character in a sorted buffer, += that does not exist. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/test1/CMakeLists.txt new file mode 100644 index 0000000..e538454 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_cbrt_test1 + ${SOURCES} +) + +add_dependencies(paltest_cbrt_test1 coreclrpal) + +target_link_libraries(paltest_cbrt_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/test1/test1.cpp new file mode 100644 index 0000000..471b6a4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/test1/test1.cpp @@ -0,0 +1,123 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Call the cbrt function on a positive value, a positive value +** with a decimal and on the maxium possible double value. +** +** +**===================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = cbrt(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("cbrt(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = cbrt(value); + + if (!_isnan(result)) + { + Fail("cbrt(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0.31830988618379067, 0.68278406325529568, PAL_EPSILON }, // value: 1 / pi + { 0.43429448190325183, 0.75728863133090766, PAL_EPSILON }, // value: log10(e) + { 0.63661977236758134, 0.86025401382809963, PAL_EPSILON }, // value: 2 / pi + { 0.69314718055994531, 0.88499704450051772, PAL_EPSILON }, // value: ln(2) + { 0.70710678118654752, 0.89089871814033930, PAL_EPSILON }, // value: 1 / sqrt(2) + { 0.78539816339744831, 0.92263507432201421, PAL_EPSILON }, // value: pi / 4 + { 1, 1, PAL_EPSILON * 10 }, + { 1.1283791670955126, 1.0410821966965807, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi) + { 1.4142135623730950, 1.1224620483093730, PAL_EPSILON * 10 }, // value: sqrt(2) + { 1.4426950408889634, 1.1299472763373901, PAL_EPSILON * 10 }, // value: log2(e) + { 1.5707963267948966, 1.1624473515096265, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.3025850929940457, 1.3205004784536852, PAL_EPSILON * 10 }, // value: ln(10) + { 2.7182818284590452, 1.3956124250860895, PAL_EPSILON * 10 }, // value: e + { 3.1415926535897932, 1.4645918875615233, PAL_EPSILON * 10 }, // value: pi + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + validate(-0.0, -0.0, PAL_EPSILON); + validate( 0.0, 0.0, PAL_EPSILON); + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/test1/testinfo.dat new file mode 100644 index 0000000..ddb926a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrt/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = cbrt +Name = Call cbrt on positive values and zero. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the cbrt function on a positive value, a positive value += with a decimal and on the maxium possible double value. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/test1/CMakeLists.txt new file mode 100644 index 0000000..1d909e0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_cbrtf_test1 + ${SOURCES} +) + +add_dependencies(paltest_cbrtf_test1 coreclrpal) + +target_link_libraries(paltest_cbrtf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/test1/test1.c new file mode 100644 index 0000000..b13d829 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/test1/test1.c @@ -0,0 +1,122 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Call the cbrtf function on a positive value, a positive value +** with a decimal and on the maxium possible float value. +** +** +**===================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = cbrtf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("cbrtf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = cbrtf(value); + + if (!_isnanf(result)) + { + Fail("cbrtf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0.318309886f, 0.682784063f, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0.757288631f, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0.860254014f, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0.884997045f, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0.890898718f, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 0.922635074f, PAL_EPSILON }, // value: pi / 4 + { 1, 1, PAL_EPSILON * 10 }, + { 1.12837917f, 1.04108220f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 1.12246205f, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 1.12994728f, PAL_EPSILON * 10 }, // value: logf2(e) + { 1.57079633f, 1.16244735f, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 1.32050048f, PAL_EPSILON * 10 }, // value: ln(10) + { 2.71828183f, 1.39561243f, PAL_EPSILON * 10 }, // value: e + { 3.14159265f, 1.46459189f, PAL_EPSILON * 10 }, // value: pi + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + validate(-0.0f, -0.0f, PAL_EPSILON); + validate( 0.0f, 0.0f, PAL_EPSILON); + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/test1/testinfo.dat new file mode 100644 index 0000000..e42cf26 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cbrtf/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = cbrtf +Name = Call cbrtf on positive values and zero. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the cbrtf function on a positive value, a positive value += with a decimal and on the maxium possible float value. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/test1/CMakeLists.txt new file mode 100644 index 0000000..10c9045 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_ceil_test1 + ${SOURCES} +) + +add_dependencies(paltest_ceil_test1 coreclrpal) + +target_link_libraries(paltest_ceil_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/test1/test1.cpp new file mode 100644 index 0000000..e6e36e6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/test1/test1.cpp @@ -0,0 +1,132 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests ceil with simple positive and negative values. Also tests +** extreme cases like extremely small values and positive and +** negative infinity. Makes sure that calling ceil on NaN returns +** NaN +** +**==========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = ceil(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("ceil(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = ceil(value); + + if (!_isnan(result)) + { + Fail("ceil(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char *argv[]) +{ + struct test tests[] = + { + /* value expected variance */ + { 0.31830988618379067, 1, PAL_EPSILON * 10 }, // value: 1 / pi + { 0.43429448190325183, 1, PAL_EPSILON * 10 }, // value: log10(e) + { 0.63661977236758134, 1, PAL_EPSILON * 10 }, // value: 2 / pi + { 0.69314718055994531, 1, PAL_EPSILON * 10 }, // value: ln(2) + { 0.70710678118654752, 1, PAL_EPSILON * 10 }, // value: 1 / sqrt(2) + { 0.78539816339744831, 1, PAL_EPSILON * 10 }, // value: pi / 4 + { 1.1283791670955126, 2, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi) + { 1.4142135623730950, 2, PAL_EPSILON * 10 }, // value: sqrt(2) + { 1.4426950408889634, 2, PAL_EPSILON * 10 }, // value: log2(e) + { 1.5707963267948966, 2, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.3025850929940457, 3, PAL_EPSILON * 10 }, // value: ln(10) + { 2.7182818284590452, 3, PAL_EPSILON * 10 }, // value: e + { 3.1415926535897932, 4, PAL_EPSILON * 10 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 } + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + validate( 0, 0, PAL_EPSILON); + validate(-0.0, 0, PAL_EPSILON); + + validate( 1, 1, PAL_EPSILON * 10); + validate(-1.0, -1, PAL_EPSILON * 10); + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, 1 - tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/test1/testinfo.dat new file mode 100644 index 0000000..84e80a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceil/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = ceil +Name = Test #1 for ceil +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests ceil with simple positive and negative values. Also tests +=extreme cases like extremely small values and positive and negative +=infinity. Makes sure that calling ceil on NaN returns NaN diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/test1/CMakeLists.txt new file mode 100644 index 0000000..ecfef17 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_ceilf_test1 + ${SOURCES} +) + +add_dependencies(paltest_ceilf_test1 coreclrpal) + +target_link_libraries(paltest_ceilf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/test1/test1.c new file mode 100644 index 0000000..4939fb7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/test1/test1.c @@ -0,0 +1,131 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests ceilf with simple positive and negative values. Also tests +** extreme cases like extremely small values and positive and +** negative infinity. Makes sure that calling ceilf on NaN returns +** NaN +** +**==========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = ceilf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("ceilf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = ceilf(value); + + if (!_isnanf(result)) + { + Fail("ceilf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char *argv[]) +{ + struct test tests[] = + { + /* value expected variance */ + { 0.318309886f, 1, PAL_EPSILON * 10 }, // value: 1 / pi + { 0.434294482f, 1, PAL_EPSILON * 10 }, // value: log10f(e) + { 0.636619772f, 1, PAL_EPSILON * 10 }, // value: 2 / pi + { 0.693147181f, 1, PAL_EPSILON * 10 }, // value: ln(2) + { 0.707106781f, 1, PAL_EPSILON * 10 }, // value: 1 / sqrtf(2) + { 0.785398163f, 1, PAL_EPSILON * 10 }, // value: pi / 4 + { 1.12837917f, 2, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 2, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 2, PAL_EPSILON * 10 }, // value: logf2(e) + { 1.57079633f, 2, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 3, PAL_EPSILON * 10 }, // value: ln(10) + { 2.71828183f, 3, PAL_EPSILON * 10 }, // value: e + { 3.14159265f, 4, PAL_EPSILON * 10 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 } + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + validate( 0, 0, PAL_EPSILON); + validate(-0.0f, 0, PAL_EPSILON); + + validate( 1, 1, PAL_EPSILON * 10); + validate(-1.0f, -1, PAL_EPSILON * 10); + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, 1 - tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/test1/testinfo.dat new file mode 100644 index 0000000..095b8b2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ceilf/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = ceilf +Name = Test #1 for ceilf +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests ceilf with simple positive and negative values. Also tests +=extreme cases like extremely small values and positive and negative +=infinity. Makes sure that calling ceilf on NaN returns NaN diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/test1/CMakeLists.txt new file mode 100644 index 0000000..6ca4bef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_cos_test1 + ${SOURCES} +) + +add_dependencies(paltest_cos_test1 coreclrpal) + +target_link_libraries(paltest_cos_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/test1/test1.cpp new file mode 100644 index 0000000..8c1c730 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/test1/test1.cpp @@ -0,0 +1,131 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that cos return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = cos(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("cos(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = cos(value); + + if (!_isnan(result)) + { + Fail("cos(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 1, PAL_EPSILON * 10 }, + { 0.31830988618379067, 0.94976571538163866, PAL_EPSILON }, // value: 1 / pi + { 0.43429448190325183, 0.90716712923909839, PAL_EPSILON }, // value: log10(e) + { 0.63661977236758134, 0.80410982822879171, PAL_EPSILON }, // value: 2 / pi + { 0.69314718055994531, 0.76923890136397213, PAL_EPSILON }, // value: ln(2) + { 0.70710678118654752, 0.76024459707563015, PAL_EPSILON }, // value: 1 / sqrt(2) + { 0.78539816339744831, 0.70710678118654752, PAL_EPSILON }, // value: pi / 4, expected: 1 / sqrt(2) + { 1, 0.54030230586813972, PAL_EPSILON }, + { 1.1283791670955126, 0.42812514788535792, PAL_EPSILON }, // value: 2 / sqrt(pi) + { 1.4142135623730950, 0.15594369476537447, PAL_EPSILON }, // value: sqrt(2) + { 1.4426950408889634, 0.12775121753523991, PAL_EPSILON }, // value: log2(e) + { 1.5707963267948966, 0, PAL_EPSILON }, // value: pi / 2 + { 2.3025850929940457, -0.66820151019031295, PAL_EPSILON }, // value: ln(10) + { 2.7182818284590452, -0.91173391478696510, PAL_EPSILON }, // value: e + { 3.1415926535897932, -1, PAL_EPSILON * 10 }, // value: pi + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/test1/testinfo.dat new file mode 100644 index 0000000..9e57b7f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cos/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = cos +Name = Positive Test for cos +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to cos() a series of angle value, checking that += each one return the correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/test1/CMakeLists.txt new file mode 100644 index 0000000..bf3756c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_cosf_test1 + ${SOURCES} +) + +add_dependencies(paltest_cosf_test1 coreclrpal) + +target_link_libraries(paltest_cosf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/test1/test1.c new file mode 100644 index 0000000..210851a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/test1/test1.c @@ -0,0 +1,130 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that cosf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = cosf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("cosf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = cosf(value); + + if (!_isnanf(result)) + { + Fail("cosf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 1, PAL_EPSILON * 10 }, + { 0.318309886f, 0.949765715f, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0.907167129f, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0.804109828f, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0.769238901f, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0.760244597f, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 0.707106781f, PAL_EPSILON }, // value: pi / 4, expected: 1 / sqrtf(2) + { 1, 0.540302306f, PAL_EPSILON }, + { 1.12837917f, 0.428125148f, PAL_EPSILON }, // value: 2 / sqrtf(pi) + { 1.41421356f, 0.155943695f, PAL_EPSILON }, // value: sqrtf(2) + { 1.44269504f, 0.127751218f, PAL_EPSILON }, // value: logf2(e) + { 1.57079633f, 0, PAL_EPSILON }, // value: pi / 2 + { 2.30258509f, -0.668201510f, PAL_EPSILON }, // value: ln(10) + { 2.71828183f, -0.911733918f, PAL_EPSILON }, // value: e + { 3.14159265f, -1, PAL_EPSILON * 10 }, // value: pi + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/test1/testinfo.dat new file mode 100644 index 0000000..a0265ad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = cosf +Name = Positive Test for cosf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to cosf() a series of angle value, checking that += each one return the correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/test1/CMakeLists.txt new file mode 100644 index 0000000..daa88d2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_cosh_test1 + ${SOURCES} +) + +add_dependencies(paltest_cosh_test1 coreclrpal) + +target_link_libraries(paltest_cosh_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/test1/test1.cpp new file mode 100644 index 0000000..40c2fca --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/test1/test1.cpp @@ -0,0 +1,130 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that cosh return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = cosh(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("cosh(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning PAL_NAN + */ +void __cdecl validate_isnan(double value) +{ + double result = cosh(value); + + if (!_isnan(result)) + { + Fail("cosh(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 1, PAL_EPSILON * 10 }, + { 0.31830988618379067, 1.0510897883672876, PAL_EPSILON * 10 }, // value: 1 / pi + { 0.43429448190325183, 1.0957974645564909, PAL_EPSILON * 10 }, // value: log10(e) + { 0.63661977236758134, 1.2095794864199787, PAL_EPSILON * 10 }, // value: 2 / pi + { 0.69314718055994531, 1.25, PAL_EPSILON * 10 }, // value: ln(2) + { 0.70710678118654752, 1.2605918365213561, PAL_EPSILON * 10 }, // value: 1 / sqrt(2) + { 0.78539816339744831, 1.3246090892520058, PAL_EPSILON * 10 }, // value: pi / 4 + { 1, 1.5430806348152438, PAL_EPSILON * 10 }, + { 1.1283791670955126, 1.7071001431069344, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi) + { 1.4142135623730950, 2.1781835566085709, PAL_EPSILON * 10 }, // value: sqrt(2) + { 1.4426950408889634, 2.2341880974508023, PAL_EPSILON * 10 }, // value: log2(e) + { 1.5707963267948966, 2.5091784786580568, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.3025850929940457, 5.05, PAL_EPSILON * 10 }, // value: ln(10) + { 2.7182818284590452, 7.6101251386622884, PAL_EPSILON * 10 }, // value: e + { 3.1415926535897932, 11.591953275521521, PAL_EPSILON * 100 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/test1/testinfo.dat new file mode 100644 index 0000000..1315122 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/cosh/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = cosh +Name = Positive Test for cosh +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to cosh() a series of angle value, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/test1/CMakeLists.txt new file mode 100644 index 0000000..0754fad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_coshf_test1 + ${SOURCES} +) + +add_dependencies(paltest_coshf_test1 coreclrpal) + +target_link_libraries(paltest_coshf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/test1/test1.c new file mode 100644 index 0000000..e1ab745 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/test1/test1.c @@ -0,0 +1,129 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that coshf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = coshf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("coshf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning PAL_NAN + */ +void __cdecl validate_isnan(float value) +{ + float result = coshf(value); + + if (!_isnanf(result)) + { + Fail("coshf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 1, PAL_EPSILON * 10 }, + { 0.318309886f, 1.05108979f, PAL_EPSILON * 10 }, // value: 1 / pi + { 0.434294482f, 1.09579746f, PAL_EPSILON * 10 }, // value: log10f(e) + { 0.636619772f, 1.20957949f, PAL_EPSILON * 10 }, // value: 2 / pi + { 0.693147181f, 1.25f, PAL_EPSILON * 10 }, // value: ln(2) + { 0.707106781f, 1.26059184f, PAL_EPSILON * 10 }, // value: 1 / sqrtf(2) + { 0.785398163f, 1.32460909f, PAL_EPSILON * 10 }, // value: pi / 4 + { 1, 1.54308063f, PAL_EPSILON * 10 }, + { 1.12837917f, 1.70710014f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 2.17818356f, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 2.23418810f, PAL_EPSILON * 10 }, // value: logf2(e) + { 1.57079633f, 2.50917848f, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 5.05f, PAL_EPSILON * 10 }, // value: ln(10) + { 2.71828183f, 7.61012514f, PAL_EPSILON * 10 }, // value: e + { 3.14159265f, 11.5919533f, PAL_EPSILON * 100 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/test1/testinfo.dat new file mode 100644 index 0000000..814ed98 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/coshf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = coshf +Name = Positive Test for coshf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to coshf() a series of angle value, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test1/CMakeLists.txt new file mode 100644 index 0000000..d5968e0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_errno_test1 + ${SOURCES} +) + +add_dependencies(paltest_errno_test1 coreclrpal) + +target_link_libraries(paltest_errno_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test1/test1.cpp new file mode 100644 index 0000000..e1dd4a6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test1/test1.cpp @@ -0,0 +1,43 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Test that errno begins as 0, and sets to ERANGE when that +** error is forced with wcstoul. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR overstr[] = {'4','2','9','4','9','6','7','2','9','6',0}; + WCHAR *end; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* + The only value that must be supported is + ERANGE, in the event that wcstoul() fails due to overflow. + */ + + wcstoul(overstr, &end, 10); + + if (errno != ERANGE) + { + Fail("ERROR: wcstoul did not set errno to ERANGE. Instead " + "the value of errno is %d\n", errno); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test1/testinfo.dat new file mode 100644 index 0000000..3291dbc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = errno +Name = Positive Test for errno +TYPE = DEFAULT +EXE1 = test1 +Description += Test that errno begins as 0, and sets to ERANGE when that += error is forced with wcstoul. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test2/CMakeLists.txt new file mode 100644 index 0000000..ebb4b65 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_errno_test2 + ${SOURCES} +) + +add_dependencies(paltest_errno_test2 coreclrpal) + +target_link_libraries(paltest_errno_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test2/test2.cpp new file mode 100644 index 0000000..f418d2f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test2/test2.cpp @@ -0,0 +1,76 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Test that errno is 'per-thread' as noted in the documentation. +** +** +**==========================================================================*/ + +#include + +/* + This thread function just checks that errno is initially 0 and then sets + it to a new value before returning. +*/ +DWORD PALAPI ThreadFunc( LPVOID lpParam ) +{ + + if(errno != 0) + { + *((DWORD*)lpParam) = 1; + } + + errno = 20; + + return 0; +} + + +int __cdecl main(int argc, char *argv[]) +{ + DWORD dwThreadId, dwThrdParam = 0; + HANDLE hThread; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Set errno to a value within this thread */ + + errno = 50; + + hThread = CreateThread(NULL, 0, ThreadFunc, &dwThrdParam, 0, &dwThreadId); + + if (hThread == NULL) + { + Fail("ERROR: CreateThread failed to create a thread. " + "GetLastError() returned %d.\n",GetLastError()); + } + + WaitForSingleObject(hThread, INFINITE); + + /* This checks the result of calling the thread */ + if(dwThrdParam) + { + Fail("ERROR: errno was not set to 0 in the new thread. Each " + "thread should have its own value for errno.\n"); + } + + /* Check to make sure errno is still set to 50 */ + if(errno != 50) + { + Fail("ERROR: errno should be 50 in the main thread, even though " + "it was set to 20 in another thread. Currently it is %d.\n", + errno); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test2/testinfo.dat new file mode 100644 index 0000000..90c2328 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/errno/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = errno +Name = Positive Test for errno +TYPE = DEFAULT +EXE1 = test2 +Description += Test that errno is 'per-thread' as noted in the documentation. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test1/CMakeLists.txt new file mode 100644 index 0000000..0bfd0d0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_exit_test1 + ${SOURCES} +) + +add_dependencies(paltest_exit_test1 coreclrpal) + +target_link_libraries(paltest_exit_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test1/test1.cpp new file mode 100644 index 0000000..87c9d22 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test1/test1.cpp @@ -0,0 +1,37 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Calls exit, and verifies that it actually stops program execution. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /*should return 0*/ + exit(0); + + Fail ("Exit didn't actually stop execution.\n"); + + return FAIL; +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test1/testinfo.dat new file mode 100644 index 0000000..3d9583b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = exit +Name = Positive Test for exit +TYPE = DEFAULT +EXE1 = test1 +Description += Calls exit, and verifies that it actually stops program execution. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test2/CMakeLists.txt new file mode 100644 index 0000000..216befb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_exit_test2 + ${SOURCES} +) + +add_dependencies(paltest_exit_test2 coreclrpal) + +target_link_libraries(paltest_exit_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test2/test2.cpp new file mode 100644 index 0000000..16fbdfe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test2/test2.cpp @@ -0,0 +1,38 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Calls exit on fail, and verifies that it actually +** stops program execution and return 1. + +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /*should return 1*/ + exit(1); + +} + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test2/testinfo.dat new file mode 100644 index 0000000..6887f27 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exit/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = exit +Name = Positive Test for exit +TYPE = DEFAULT +EXE1 = test2 +Description += Calls exit on fail, and verifies that it actually stops program execution, += and return 1. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/test1/CMakeLists.txt new file mode 100644 index 0000000..1830cc2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_exp_test1 + ${SOURCES} +) + +add_dependencies(paltest_exp_test1 coreclrpal) + +target_link_libraries(paltest_exp_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/test1/test1.cpp new file mode 100644 index 0000000..20e071a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/test1/test1.cpp @@ -0,0 +1,138 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests exp with a normal set of values. +** +**===================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = exp(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("exp(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = exp(value); + + if (!_isnan(result)) + { + Fail("exp(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { PAL_NEGINF, 0, PAL_EPSILON }, + { -3.1415926535897932, 0.043213918263772250, PAL_EPSILON / 10 }, // value: -(pi) + { -2.7182818284590452, 0.065988035845312537, PAL_EPSILON / 10 }, // value: -(e) + { -2.3025850929940457, 0.1, PAL_EPSILON }, // value: -(ln(10)) + { -1.5707963267948966, 0.20787957635076191, PAL_EPSILON }, // value: -(pi / 2) + { -1.4426950408889634, 0.23629008834452270, PAL_EPSILON }, // value: -(log2(e)) + { -1.4142135623730950, 0.24311673443421421, PAL_EPSILON }, // value: -(sqrt(2)) + { -1.1283791670955126, 0.32355726390307110, PAL_EPSILON }, // value: -(2 / sqrt(pi)) + { -1, 0.36787944117144232, PAL_EPSILON }, // value: -(1) + { -0.78539816339744831, 0.45593812776599624, PAL_EPSILON }, // value: -(pi / 4) + { -0.70710678118654752, 0.49306869139523979, PAL_EPSILON }, // value: -(1 / sqrt(2)) + { -0.69314718055994531, 0.5, PAL_EPSILON }, // value: -(ln(2)) + { -0.63661977236758134, 0.52907780826773535, PAL_EPSILON }, // value: -(2 / pi) + { -0.43429448190325183, 0.64772148514180065, PAL_EPSILON }, // value: -(log10(e)) + { -0.31830988618379067, 0.72737734929521647, PAL_EPSILON }, // value: -(1 / pi) + { 0, 1, PAL_EPSILON * 10 }, + { 0.31830988618379067, 1.3748022274393586, PAL_EPSILON * 10 }, // value: 1 / pi + { 0.43429448190325183, 1.5438734439711811, PAL_EPSILON * 10 }, // value: log10(e) + { 0.63661977236758134, 1.8900811645722220, PAL_EPSILON * 10 }, // value: 2 / pi + { 0.69314718055994531, 2, PAL_EPSILON * 10 }, // value: ln(2) + { 0.70710678118654752, 2.0281149816474725, PAL_EPSILON * 10 }, // value: 1 / sqrt(2) + { 0.78539816339744831, 2.1932800507380155, PAL_EPSILON * 10 }, // value: pi / 4 + { 1, 2.7182818284590452, PAL_EPSILON * 10 }, // expected: e + { 1.1283791670955126, 3.0906430223107976, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi) + { 1.4142135623730950, 4.1132503787829275, PAL_EPSILON * 10 }, // value: sqrt(2) + { 1.4426950408889634, 4.2320861065570819, PAL_EPSILON * 10 }, // value: log2(e) + { 1.5707963267948966, 4.8104773809653517, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.3025850929940457, 10, PAL_EPSILON * 100 }, // value: ln(10) + { 2.7182818284590452, 15.154262241479264, PAL_EPSILON * 100 }, // value: e + { 3.1415926535897932, 23.140692632779269, PAL_EPSILON * 100 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/test1/testinfo.dat new file mode 100644 index 0000000..65fc192 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/exp/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = exp +Name = Test #1 for exp +Type = DEFAULT +EXE1 = test1 +Description +=Tests exp with a normal set of values. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/test1/CMakeLists.txt new file mode 100644 index 0000000..f598831 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_expf_test1 + ${SOURCES} +) + +add_dependencies(paltest_expf_test1 coreclrpal) + +target_link_libraries(paltest_expf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/test1/test1.c new file mode 100644 index 0000000..32f4e8d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/test1/test1.c @@ -0,0 +1,137 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests expf with a normal set of values. +** +**===================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = expf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("expf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = expf(value); + + if (!_isnanf(result)) + { + Fail("expf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { PAL_NEGINF, 0, PAL_EPSILON }, + { -3.14159265f, 0.0432139183f, PAL_EPSILON / 10 }, // value: -(pi) + { -2.71828183f, 0.0659880358f, PAL_EPSILON / 10 }, // value: -(e) + { -2.30258509f, 0.1f, PAL_EPSILON }, // value: -(ln(10)) + { -1.57079633f, 0.207879576f, PAL_EPSILON }, // value: -(pi / 2) + { -1.44269504f, 0.236290088f, PAL_EPSILON }, // value: -(logf2(e)) + { -1.41421356f, 0.243116734f, PAL_EPSILON }, // value: -(sqrtf(2)) + { -1.12837917f, 0.323557264f, PAL_EPSILON }, // value: -(2 / sqrtf(pi)) + { -1, 0.367879441f, PAL_EPSILON }, // value: -(1) + { -0.785398163f, 0.455938128f, PAL_EPSILON }, // value: -(pi / 4) + { -0.707106781f, 0.493068691f, PAL_EPSILON }, // value: -(1 / sqrtf(2)) + { -0.693147181f, 0.5f, PAL_EPSILON }, // value: -(ln(2)) + { -0.636619772f, 0.529077808f, PAL_EPSILON }, // value: -(2 / pi) + { -0.434294482f, 0.647721485f, PAL_EPSILON }, // value: -(log10f(e)) + { -0.318309886f, 0.727377349f, PAL_EPSILON }, // value: -(1 / pi) + { 0, 1, PAL_EPSILON * 10 }, + { 0.318309886f, 1.37480223f, PAL_EPSILON * 10 }, // value: 1 / pi + { 0.434294482f, 1.54387344f, PAL_EPSILON * 10 }, // value: log10f(e) + { 0.636619772f, 1.89008116f, PAL_EPSILON * 10 }, // value: 2 / pi + { 0.693147181f, 2, PAL_EPSILON * 10 }, // value: ln(2) + { 0.707106781f, 2.02811498f, PAL_EPSILON * 10 }, // value: 1 / sqrtf(2) + { 0.785398163f, 2.19328005f, PAL_EPSILON * 10 }, // value: pi / 4 + { 1, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { 1.12837917f, 3.09064302f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 4.11325038f, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 4.23208611f, PAL_EPSILON * 10 }, // value: logf2(e) + { 1.57079633f, 4.81047738f, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 10, PAL_EPSILON * 100 }, // value: ln(10) + { 2.71828183f, 15.1542622f, PAL_EPSILON * 100 }, // value: e + { 3.14159265f, 23.1406926f, PAL_EPSILON * 100 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/test1/testinfo.dat new file mode 100644 index 0000000..c359285 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/expf/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = expf +Name = Test #1 for expf +Type = DEFAULT +EXE1 = test1 +Description +=Tests expf with a normal set of values. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/test1/CMakeLists.txt new file mode 100644 index 0000000..c3d4d81 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fabs_test1 + ${SOURCES} +) + +add_dependencies(paltest_fabs_test1 coreclrpal) + +target_link_libraries(paltest_fabs_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/test1/test1.cpp new file mode 100644 index 0000000..0a74d5c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/test1/test1.cpp @@ -0,0 +1,130 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that fabs return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = fabs(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("fabs(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = fabs(value); + + if (!_isnan(result)) + { + Fail("fabs(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +INT __cdecl main(INT argc, CHAR **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { PAL_NEGINF, PAL_POSINF, 0 }, + { -3.1415926535897932, 3.1415926535897932, PAL_EPSILON * 10 }, // value: -(pi) expected: pi + { -2.7182818284590452, 2.7182818284590452, PAL_EPSILON * 10 }, // value: -(e) expected: e + { -2.3025850929940457, 2.3025850929940457, PAL_EPSILON * 10 }, // value: -(ln(10)) expected: ln(10) + { -1.5707963267948966, 1.5707963267948966, PAL_EPSILON * 10 }, // value: -(pi / 2) expected: pi / 2 + { -1.4426950408889634, 1.4426950408889634, PAL_EPSILON * 10 }, // value: -(log2(e)) expected: log2(e) + { -1.4142135623730950, 1.4142135623730950, PAL_EPSILON * 10 }, // value: -(sqrt(2)) expected: sqrt(2) + { -1.1283791670955126, 1.1283791670955126, PAL_EPSILON * 10 }, // value: -(2 / sqrt(pi)) expected: 2 / sqrt(pi) + { -1, 1, PAL_EPSILON * 10 }, + { -0.78539816339744831, 0.78539816339744831, PAL_EPSILON }, // value: -(pi / 4) expected: pi / 4 + { -0.70710678118654752, 0.70710678118654752, PAL_EPSILON }, // value: -(1 / sqrt(2)) expected: 1 / sqrt(2) + { -0.69314718055994531, 0.69314718055994531, PAL_EPSILON }, // value: -(ln(2)) expected: ln(2) + { -0.63661977236758134, 0.63661977236758134, PAL_EPSILON }, // value: -(2 / pi) expected: 2 / pi + { -0.43429448190325183, 0.43429448190325183, PAL_EPSILON }, // value: -(log10(e)) expected: log10(e) + { -0.31830988618379067, 0.31830988618379067, PAL_EPSILON }, // value: -(1 / pi) expected: 1 / pi + { -0.0, 0, PAL_EPSILON }, + }; + + + // PAL initialization + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/test1/testinfo.dat new file mode 100644 index 0000000..d5b2321 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabs/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fabs +Name = Positive Test for fabs +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to fabs() a series of values, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/test1/CMakeLists.txt new file mode 100644 index 0000000..df01190 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fabsf_test1 + ${SOURCES} +) + +add_dependencies(paltest_fabsf_test1 coreclrpal) + +target_link_libraries(paltest_fabsf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/test1/test1.cpp new file mode 100644 index 0000000..0b02072 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/test1/test1.cpp @@ -0,0 +1,130 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that fabsf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = fabsf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("fabsf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = fabsf(value); + + if (!_isnan(result)) + { + Fail("fabsf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +INT __cdecl main(INT argc, CHAR **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { PAL_NEGINF, PAL_POSINF, 0 }, + { -3.14159265f, 3.14159265f, PAL_EPSILON * 10 }, // value: -(pi) expected: pi + { -2.71828183f, 2.71828183f, PAL_EPSILON * 10 }, // value: -(e) expected: e + { -2.30258509f, 2.30258509f, PAL_EPSILON * 10 }, // value: -(ln(10)) expected: ln(10) + { -1.57079633f, 1.57079633f, PAL_EPSILON * 10 }, // value: -(pi / 2) expected: pi / 2 + { -1.44269504f, 1.44269504f, PAL_EPSILON * 10 }, // value: -(log2(e)) expected: log2(e) + { -1.41421356f, 1.41421356f, PAL_EPSILON * 10 }, // value: -(sqrt(2)) expected: sqrt(2) + { -1.12837917f, 1.12837917f, PAL_EPSILON * 10 }, // value: -(2 / sqrt(pi)) expected: 2 / sqrt(pi) + { -1, 1, PAL_EPSILON * 10 }, + { -0.785398163f, 0.785398163f, PAL_EPSILON }, // value: -(pi / 4) expected: pi / 4 + { -0.707106781f, 0.707106781f, PAL_EPSILON }, // value: -(1 / sqrt(2)) expected: 1 / sqrt(2) + { -0.693147181f, 0.693147181f, PAL_EPSILON }, // value: -(ln(2)) expected: ln(2) + { -0.636619772f, 0.636619772f, PAL_EPSILON }, // value: -(2 / pi) expected: 2 / pi + { -0.434294482f, 0.434294482f, PAL_EPSILON }, // value: -(log10(e)) expected: log10(e) + { -0.318309886f, 0.318309886f, PAL_EPSILON }, // value: -(1 / pi) expected: 1 / pi + { -0.0f, 0, PAL_EPSILON }, + }; + + + // PAL initialization + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/test1/testinfo.dat new file mode 100644 index 0000000..a927f1e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fabsf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fabsf +Name = Positive Test for fabsf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to fabsf() a series of values, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test1/CMakeLists.txt new file mode 100644 index 0000000..907694b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fclose_test1 + ${SOURCES} +) + +add_dependencies(paltest_fclose_test1 coreclrpal) + +target_link_libraries(paltest_fclose_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test1/test1.cpp new file mode 100644 index 0000000..0a84638 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test1/test1.cpp @@ -0,0 +1,79 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c (fclose) +** +** Purpose: Tests the PAL implementation of the fclose function. +** This test will use fdopen to create a file stream, +** that will be used to test fclose. fclose will also +** be passed a closed file handle to make sure it handle +** it accordingly. +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + HANDLE hReadPipe = NULL; + HANDLE hWritePipe = NULL; + BOOL bRetVal = FALSE; + int iFiledes = 0; + FILE *fp; + + SECURITY_ATTRIBUTES lpPipeAttributes; + + /*Initialize the PAL*/ + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/ + lpPipeAttributes.nLength = sizeof(lpPipeAttributes); + lpPipeAttributes.lpSecurityDescriptor = NULL; + lpPipeAttributes.bInheritHandle = TRUE; + + /*Create a Pipe*/ + bRetVal = CreatePipe(&hReadPipe, // read handle + &hWritePipe, // write handle + &lpPipeAttributes,// security attributes + 0); // pipe size + + if (bRetVal == FALSE) + { + Fail("ERROR: Unable to create pipe; returned error code %ld" + , GetLastError()); + } + + /*Get a file descriptor for the read pipe handle*/ + iFiledes = _open_osfhandle((long)hReadPipe,_O_RDONLY); + + if (iFiledes == -1) + { + Fail("ERROR: _open_osfhandle failed to open " + " hReadPipe=0x%lx", hReadPipe); + } + + /*Open read pipe handle in read mode*/ + fp = _fdopen(iFiledes, "r"); + + if (fp == NULL) + { + Fail("ERROR: unable to fdopen file descriptor" + " iFiledes=%d", iFiledes); + } + + /*Attempt to close the file stream*/ + if (fclose(fp) != 0) + { + Fail("ERROR: Unable to fclose file stream fp=0x%lx\n",fp); + } + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test1/testinfo.dat new file mode 100644 index 0000000..0904c4f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test1/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fclose +Name = Test for fclose +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the fclose function. += This test will use fdopen to create a file stream, += that will be used to test fclose. fclose will also += be passed a closed file handle to make sure it handle += it accordingly. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test2/CMakeLists.txt new file mode 100644 index 0000000..e3cf723 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_fclose_test2 + ${SOURCES} +) + +add_dependencies(paltest_fclose_test2 coreclrpal) + +target_link_libraries(paltest_fclose_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test2/test2.cpp new file mode 100644 index 0000000..f4da535 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test2/test2.cpp @@ -0,0 +1,77 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c (fclose) +** +** Purpose: Tests the PAL implementation of the fclose function. +** fclose will be passed a closed file handle to make +** sure it handles it accordingly. +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + HANDLE hReadPipe = NULL; + HANDLE hWritePipe = NULL; + BOOL bRetVal = FALSE; + int iFiledes = 0; + FILE *fp; + + SECURITY_ATTRIBUTES lpPipeAttributes; + + /*Initialize the PAL*/ + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/ + lpPipeAttributes.nLength = sizeof(lpPipeAttributes); + lpPipeAttributes.lpSecurityDescriptor = NULL; + lpPipeAttributes.bInheritHandle = TRUE; + + /*Create a Pipe*/ + bRetVal = CreatePipe(&hReadPipe, /* read handle */ + &hWritePipe, /* write handle */ + &lpPipeAttributes,/* security attributes */ + 0); /* pipe size */ + + if (bRetVal == FALSE) + { + Fail("ERROR: Unable to create pipe; returned error code %ld" + , GetLastError()); + } + + /*Get a file descriptor for the read pipe handle*/ + iFiledes = _open_osfhandle((long)hReadPipe,_O_RDONLY); + + if (iFiledes == -1) + { + Fail("ERROR: _open_osfhandle failed to open " + " hReadPipe=0x%lx", hReadPipe); + } + + /*Open read pipe handle in read mode*/ + fp = _fdopen(iFiledes, "r"); + + if (fp == NULL) + { + Fail("ERROR: unable to fdopen file descriptor" + " iFiledes=%d", iFiledes); + } + + /*Attempt to close the file stream*/ + if (fclose(fp) != 0) + { + Fail("ERROR: Unable to fclose file stream fp=0x%lx\n", fp); + } + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test2/testinfo.dat new file mode 100644 index 0000000..192b8d2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fclose/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fclose +Name = Test for fclose +TYPE = DEFAULT +EXE1 = test2 +LANG = cpp +Description += Tests the PAL implementation of the fclose function. += fclose will be passed a closed file handle to += make sure it handles it accordingly. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/CMakeLists.txt new file mode 100644 index 0000000..a492a64 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_ferror_test1 + ${SOURCES} +) + +add_dependencies(paltest_ferror_test1 coreclrpal) + +target_link_libraries(paltest_ferror_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/test1.cpp new file mode 100644 index 0000000..516f253 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/test1.cpp @@ -0,0 +1,74 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the ferror function. +** +** Depends: +** fopen +** fread +** fclose +** +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + const char filename[] = "testfile"; + char buffer[128]; + FILE * fp = NULL; + int result; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Open a file in READ mode */ + + if((fp = fopen(filename, "r")) == NULL) + { + Fail("Unable to open a file for reading. Is the file " + "in the directory? It should be."); + } + + /* Read 10 characters from the file. The file has 15 + characters in it. + */ + + if((result = fread(buffer,1,10,fp)) == 0) + { + Fail("ERROR: Zero characters read from the file. It should have " + "read 10 character in from a 15 character file."); + } + + if(ferror(fp) != 0) + { + Fail("ERROR: ferror returned a value not equal to 0. The read " + "operation shouldn't have caused an error, and ferror should " + "return 0 still."); + } + + /* + Close the open file and end the test. + */ + + if(fclose(fp) != 0) + { + Fail("ERROR: fclose failed when trying to close a file pointer. " + "This test depends on fclose working properly."); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/testfile b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/testfile new file mode 100644 index 0000000..273c1a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/testfile @@ -0,0 +1 @@ +This is a test. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/testinfo.dat new file mode 100644 index 0000000..32e55a3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = ferror +Name = Positive Test for ferror +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the ferror function. += Open a file, and read some characters. Check that ferror states that += no error has occurred. Then close the file pointer. Attempt to read += some more. Check ferror now, and it should indicate that an error has += occurred. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/CMakeLists.txt new file mode 100644 index 0000000..313ad09 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_ferror_test2 + ${SOURCES} +) + +add_dependencies(paltest_ferror_test2 coreclrpal) + +target_link_libraries(paltest_ferror_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/test2.cpp new file mode 100644 index 0000000..fdf9e03 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/test2.cpp @@ -0,0 +1,69 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Open a read-only file and attempt to write some data to it. +** Check to ensure that an ferror occurs. +** +** Depends: +** fopen +** fwrite +** fclose +** +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + const char filename[] = "testfile"; + FILE * fp = NULL; + int result; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Open a file in READONLY mode */ + + if((fp = fopen(filename, "r")) == NULL) + { + Fail("Unable to open a file for reading."); + } + + /* Attempt to write 14 characters to the file. */ + + if((result = fwrite("This is a test",1,14,fp)) != 0) + { + Fail("ERROR: %d characters written. 0 characters should " + "have been written, since this file is read-only.", result); + } + + if(ferror(fp) == 0) + { + Fail("ERROR: ferror should have generated an error when " + "write was called on a read-only file. But, it " + "retured 0, indicating no error.\n"); + } + + /* Close the file. */ + + if(fclose(fp) != 0) + { + Fail("ERROR: fclose failed when trying to close a file pointer. " + "This test depends on fclose working properly."); + } + + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/testfile b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/testfile new file mode 100644 index 0000000..0135842 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/testfile @@ -0,0 +1 @@ +This is a test file. This needs to be kept in CVS. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/testinfo.dat new file mode 100644 index 0000000..d724a4c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ferror/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = ferror +Name = Positive Test for ferror, call write on a readonly file. +TYPE = DEFAULT +EXE1 = test2 +Description += Open a read-only file and attempt to write some data to it. += Check to ensure that an ferror occurs. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/test1/CMakeLists.txt new file mode 100644 index 0000000..807a5c3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fflush_test1 + ${SOURCES} +) + +add_dependencies(paltest_fflush_test1 coreclrpal) + +target_link_libraries(paltest_fflush_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/test1/test1.cpp new file mode 100644 index 0000000..7baf9ba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/test1/test1.cpp @@ -0,0 +1,80 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests to see that fflush is working properly. Flushes a couple +** buffers and checks the return value. Can't figure out a way to test +** and ensure it is really dropping the buffers, since the system +** does this automatically most of the time ... +** +** +**==========================================================================*/ + +/* This function is really tough to test. Right now it just tests + a bunch of return values. No solid way to ensure that it is really + flushing a buffer or not -- might have to be a manual test someday. +*/ + +#include + + +int __cdecl main(int argc, char **argv) +{ + + int TheReturn; + FILE* TheFile; + FILE* AnotherFile = NULL; + + PAL_Initialize(argc,argv); + + TheFile = fopen("theFile","w+"); + + if(TheFile == NULL) + { + Fail("ERROR: fopen failed. Test depends on this function."); + } + + TheReturn = fwrite("foo",3,3,TheFile); + + if(TheReturn != 3) + { + Fail("ERROR: fwrite failed. Test depends on this function."); + } + + /* Test to see that FlushFileBuffers returns a success value */ + TheReturn = fflush(TheFile); + + if(TheReturn != 0) + { + Fail("ERROR: The fflush function returned non-zero, which " + "indicates failure, when trying to flush a buffer."); + } + + /* Test to see that FlushFileBuffers returns a success value */ + TheReturn = fflush(NULL); + + if(TheReturn != 0) + { + Fail("ERROR: The fflush function returned non-zero, which " + "indicates failure, when trying to flush all buffers."); + } + + /* Test to see that FlushFileBuffers returns a success value */ + TheReturn = fflush(AnotherFile); + + if(TheReturn != 0) + { + Fail("ERROR: The fflush function returned non-zero, which " + "indicates failure, when trying to flush a stream not " + "associated with a file."); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/test1/testinfo.dat new file mode 100644 index 0000000..1cff5a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fflush/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fflush +Name = Positive Test for fflush +TYPE = DEFAULT +EXE1 = test1 +Description += Tests to see that fflush is working properly. Flushes a couple += buffers and checks the return value. Can't figure out a way to test += and ensure it is really dropping the buffers, since the system += does this automatically most of the time ... diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test1/CMakeLists.txt new file mode 100644 index 0000000..3fc2acb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fgets_test1 + ${SOURCES} +) + +add_dependencies(paltest_fgets_test1 coreclrpal) + +target_link_libraries(paltest_fgets_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test1/test1.cpp new file mode 100644 index 0000000..5e0e62d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test1/test1.cpp @@ -0,0 +1,102 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Writes a simple file and calls fgets() to get a string shorter +** than the first line of the file. Verifies that the correct +** string is returned. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + const char outBuf1[] = "This is a test.\n"; + const char outBuf2[] = "This is too."; + char inBuf[sizeof(outBuf1) + sizeof(outBuf2)]; + const char filename[] = "testfile.tmp"; + const int offset = 5; /* value chosen arbitrarily */ + int actualLen; + int expectedLen; + FILE * fp; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /*write the file that we will use to test */ + fp = fopen(filename, "w"); + if (fp == NULL) + { + Fail("Unable to open file for write.\n"); + } + + fwrite(outBuf1, sizeof(outBuf1[0]), sizeof(outBuf1), fp); + fwrite(outBuf2, sizeof(outBuf2[0]), sizeof(outBuf2), fp); + + if (fclose(fp) != 0) + { + Fail("Error closing a file opened for write.\n"); + } + + + /*now read back the entire first string*/ + fp = fopen(filename, "r"); + if (fp == NULL) + { + Fail("Unable to open file for read.\n"); + } + + /*note: +1 because strlen() returns the length of a string _not_ + including the NULL, while fgets() returns a string of specified + maximum length _including_ the NULL.*/ + if (fgets(inBuf, strlen(outBuf1) - offset + 1, fp) != inBuf) + { + Fail("Error reading from file using fgets.\n"); + } + + + expectedLen = strlen(outBuf1) - offset; + actualLen = strlen(inBuf); + + if (actualLen < expectedLen) + { + Fail("fgets() was asked to read a one-line string and given the " + "length of the string as a parameter. The string it has " + "read is too short.\n"); + } + if (actualLen > expectedLen) + { + Fail("fgets() was asked to read a one-line string and given the " + "length of the string as a parameter. The string it has " + "read is too long.\n"); + } + if (memcmp(inBuf, outBuf1, actualLen) != 0) + { + /*We didn't read back exactly outBuf1*/ + Fail("fgets() was asked to read a one-line string, and given the " + "length of the string as an parameter. It has returned a " + "string of the correct length, but the contents are not " + "correct.\n"); + } + + if (fclose(fp) != 0) + { + Fail("Error closing file after using fgets().\n"); + } + + + PAL_Terminate(); + return PASS; + +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test1/testinfo.dat new file mode 100644 index 0000000..70ea669 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fgets +Name = Positive Test for fgets +TYPE = DEFAULT +EXE1 = test1 +Description += Writes a simple file and calls fgets() to get a string shorter than += the first line of the file. Verifies that the correct string is += returned. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test2/CMakeLists.txt new file mode 100644 index 0000000..240ec61 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_fgets_test2 + ${SOURCES} +) + +add_dependencies(paltest_fgets_test2 coreclrpal) + +target_link_libraries(paltest_fgets_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test2/test2.cpp new file mode 100644 index 0000000..fa37cdb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test2/test2.cpp @@ -0,0 +1,97 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Calls fgets to read a full line from a file. A maximum length +** parameter greater than the length of the line is passed. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + const char outBuf1[] = "This is a test.\n"; + const char outBuf2[] = "This is too."; + + char inBuf[sizeof(outBuf1) + sizeof(outBuf2)]; + const char filename[] = "testfile.tmp"; + const int offset = 5; /*value chosen arbitrarily*/ + int expectedLen; + int actualLen; + + FILE * fp; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /*write the file that we will use to test */ + fp = fopen(filename, "w"); + if (fp == NULL) + { + Fail("Unable to open file for write.\n"); + } + + fwrite(outBuf1, sizeof(outBuf1[0]), sizeof(outBuf1), fp); + fwrite(outBuf2, sizeof(outBuf2[0]), sizeof(outBuf2), fp); + + if (fclose(fp) != 0) + { + Fail("error closing stream opened for write.\n"); + } + + /*Read until the first linebreak*/ + fp = fopen(filename, "r"); + if (fp == NULL) + { + Fail("Unable to open file for read.\n"); + } + + + if (fgets(inBuf, sizeof(outBuf1) + offset , fp) != inBuf) + { + Fail("Error reading from file using fgets.\n"); + } + + /*note: -1 because strlen returns the length of a string _not_ + including the NULL, while fgets returns a string of specified + maximum length _including_ the NULL.*/ + expectedLen = strlen(outBuf1); + actualLen = strlen(inBuf); + if (actualLen > expectedLen) + { + Fail("fgets() was asked to read the first line of a file, but did " + "not stop at the end of the line.\n"); + } + else if (actualLen < expectedLen) + { + Fail("fgets() was asked to read the first line of a file, but did " + "not read the entire line.\n"); + } + else if (memcmp(inBuf, outBuf1, actualLen) != 0) + { + /*We didn't read back exactly outBuf1*/ + Fail("fgets() was asked to read the first line of a file. It " + "has read back a string of the correct length, but the" + " contents are not correct.\n"); + } + + if (fclose(fp) != 0) + { + Fail("Error closing file after using fgets().\n"); + } + + PAL_Terminate(); + return PASS; + +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test2/testinfo.dat new file mode 100644 index 0000000..d282dba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fgets +Name = Positive Test for fgets +TYPE = DEFAULT +EXE1 = test2 +Description += Calls fgets to read a full line from a file. A maximum length += parameter greater than the length of the line is passed. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test3/CMakeLists.txt new file mode 100644 index 0000000..57e774e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_fgets_test3 + ${SOURCES} +) + +add_dependencies(paltest_fgets_test3 coreclrpal) + +target_link_libraries(paltest_fgets_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test3/test3.cpp new file mode 100644 index 0000000..525ba93 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test3/test3.cpp @@ -0,0 +1,73 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Tries to read from an empty file using fgets(), to verify +** handling of EOF condition. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + char inBuf[10]; + const char filename[] = "testfile.tmp"; + + FILE * fp; + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /*write the empty file that we will use to test */ + fp = fopen(filename, "w"); + if (fp == NULL) + { + Fail("Unable to open file for write.\n"); + } + + /*Don't write anything*/ + + if (fclose(fp) != 0) + { + Fail("Error closing stream opened for write.\n"); + } + + + /*Open the file and try to read.*/ + fp = fopen(filename, "r"); + if (fp == NULL) + { + Fail("Unable to open file for read.\n"); + } + + + if (fgets(inBuf, sizeof(inBuf) , fp) != NULL) + { + /*NULL could also mean an error condition, but since the PAL + doesn't supply feof or ferror, we can't distinguish between + the two.*/ + Fail("fgets doesn't handle EOF properly. When asked to read from " + "an empty file, it didn't return NULL as it should have.\n"); + } + + if (fclose(fp) != 0) + { + Fail("Error closing an empty file after trying to use fgets().\n"); + } + PAL_Terminate(); + return PASS; + +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test3/testinfo.dat new file mode 100644 index 0000000..e10cf89 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fgets/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fgets +Name = Positive Test for fgets +TYPE = DEFAULT +EXE1 = test3 +Description += Tries to read from an empty file using fgets(), to verify handling of += EOF condition. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/test1/CMakeLists.txt new file mode 100644 index 0000000..4a76315 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_floor_test1 + ${SOURCES} +) + +add_dependencies(paltest_floor_test1 coreclrpal) + +target_link_libraries(paltest_floor_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/test1/test1.cpp new file mode 100644 index 0000000..dba3209 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/test1/test1.cpp @@ -0,0 +1,132 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests floor with simple positive and negative values. Also tests +** extreme cases like extremely small values and positive and +** negative infinity. Makes sure that calling floor on NaN returns +** NaN +** +**==========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = floor(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("floor(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = floor(value); + + if (!_isnan(result)) + { + Fail("floor(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char *argv[]) +{ + struct test tests[] = + { + /* value expected variance */ + { 0.31830988618379067, 0, PAL_EPSILON }, // value: 1 / pi + { 0.43429448190325183, 0, PAL_EPSILON }, // value: log10(e) + { 0.63661977236758134, 0, PAL_EPSILON }, // value: 2 / pi + { 0.69314718055994531, 0, PAL_EPSILON }, // value: ln(2) + { 0.70710678118654752, 0, PAL_EPSILON }, // value: 1 / sqrt(2) + { 0.78539816339744831, 0, PAL_EPSILON }, // value: pi / 4 + { 1.1283791670955126, 1, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi) + { 1.4142135623730950, 1, PAL_EPSILON * 10 }, // value: sqrt(2) + { 1.4426950408889634, 1, PAL_EPSILON * 10 }, // value: log2(e) + { 1.5707963267948966, 1, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.3025850929940457, 2, PAL_EPSILON * 10 }, // value: ln(10) + { 2.7182818284590452, 2, PAL_EPSILON * 10 }, // value: e + { 3.1415926535897932, 3, PAL_EPSILON * 10 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 } + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + validate( 0, 0, PAL_EPSILON); + validate(-0.0, 0, PAL_EPSILON); + + validate( 1, 1, PAL_EPSILON * 10); + validate(-1.0, -1, PAL_EPSILON * 10); + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -(tests[i].expected + 1), tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/test1/testinfo.dat new file mode 100644 index 0000000..90543ea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floor/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = floor +Name = Positive Test for floor +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to floor() a series of value, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/test1/CMakeLists.txt new file mode 100644 index 0000000..3741156 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_floorf_test1 + ${SOURCES} +) + +add_dependencies(paltest_floorf_test1 coreclrpal) + +target_link_libraries(paltest_floorf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/test1/test1.c new file mode 100644 index 0000000..57dca21 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/test1/test1.c @@ -0,0 +1,131 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests floorf with simple positive and negative values. Also tests +** extreme cases like extremely small values and positive and +** negative infinity. Makes sure that calling floorf on NaN returns +** NaN +** +**==========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = floorf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("floorf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = floorf(value); + + if (!_isnanf(result)) + { + Fail("floorf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char *argv[]) +{ + struct test tests[] = + { + /* value expected variance */ + { 0.318309886f, 0, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 0, PAL_EPSILON }, // value: pi / 4 + { 1.12837917f, 1, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 1, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 1, PAL_EPSILON * 10 }, // value: logf2(e) + { 1.57079633f, 1, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 2, PAL_EPSILON * 10 }, // value: ln(10) + { 2.71828183f, 2, PAL_EPSILON * 10 }, // value: e + { 3.14159265f, 3, PAL_EPSILON * 10 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 } + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + validate( 0, 0, PAL_EPSILON); + validate(-0.0f, 0, PAL_EPSILON); + + validate( 1, 1, PAL_EPSILON * 10); + validate(-1.0f, -1, PAL_EPSILON * 10); + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -(tests[i].expected + 1), tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/test1/testinfo.dat new file mode 100644 index 0000000..0065401 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/floorf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = floorf +Name = Positive Test for floorf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to floorf() a series of value, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/test1/CMakeLists.txt new file mode 100644 index 0000000..0bb96a3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fma_test1 + ${SOURCES} +) + +add_dependencies(paltest_fma_test1 coreclrpal) + +target_link_libraries(paltest_fma_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/test1/test1.cpp new file mode 100644 index 0000000..b7d515d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/test1/test1.cpp @@ -0,0 +1,146 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that fma returns correct values for a subset of values. +** Tests with positive and negative values of x, y, and z to ensure +** fmaf is returning correct results. +** +**===================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double x; /* first component of the value to test the function with */ + double y; /* second component of the value to test the function with */ + double z; /* third component of the value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double x, double y, double z, double expected, double variance) +{ + double result = fma(x, y, z); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("fma(%g, %g, %g) returned %20.17g when it should have returned %20.17g", + x, y, z, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double x, double y, double z) +{ + double result = fma(x, y, z); + + if (!_isnan(result)) + { + Fail("fma(%g, %g, %g) returned %20.17g when it should have returned %20.17g", + x, y, z, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* x y z expected variance */ + { PAL_NEGINF, PAL_NEGINF, PAL_NEGINF, PAL_NEGINF, 0 }, + { -1e308, 2, 1e308, -1e308, 0 }, + { 1e308, 2, -1e308, 1e308, 0 }, + { PAL_POSINF, PAL_POSINF, PAL_POSINF, PAL_POSINF, 0 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].x, tests[i].y, tests[i].z, tests[i].expected, tests[i].variance); + } + + // Returns NaN if x or y is infinite, the other is zero, and z is NaN + validate_isnan(PAL_NEGINF, 0, PAL_NAN); + validate_isnan(PAL_POSINF, 0, PAL_NAN); + validate_isnan(0, PAL_NEGINF, PAL_NAN); + validate_isnan(0, PAL_POSINF, PAL_NAN); + + // Returns NaN if x or y is infinite, the other is zero, and z is not-NaN + validate_isnan(PAL_POSINF, 0, PAL_NEGINF); + validate_isnan(PAL_NEGINF, 0, PAL_NEGINF); + validate_isnan(0, PAL_POSINF, PAL_NEGINF); + validate_isnan(0, PAL_NEGINF, PAL_NEGINF); + + validate_isnan(PAL_POSINF, 0, 0); + validate_isnan(PAL_NEGINF, 0, 0); + validate_isnan(0, PAL_POSINF, 0); + validate_isnan(0, PAL_NEGINF, 0); + + validate_isnan(PAL_POSINF, 0, PAL_POSINF); + validate_isnan(PAL_NEGINF, 0, PAL_POSINF); + validate_isnan(0, PAL_POSINF, PAL_POSINF); + validate_isnan(0, PAL_NEGINF, PAL_POSINF); + + // Returns NaN if (x * y) is infinite, and z is an infinite of the opposite sign + validate_isnan(PAL_POSINF, PAL_POSINF, PAL_NEGINF); + validate_isnan(PAL_NEGINF, PAL_NEGINF, PAL_NEGINF); + validate_isnan(PAL_POSINF, PAL_NEGINF, PAL_POSINF); + validate_isnan(PAL_NEGINF, PAL_POSINF, PAL_POSINF); + + validate_isnan(PAL_POSINF, 1, PAL_NEGINF); + validate_isnan(PAL_NEGINF, 1, PAL_POSINF); + validate_isnan(1, PAL_POSINF, PAL_NEGINF); + validate_isnan(1, PAL_NEGINF, PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/test1/testinfo.dat new file mode 100644 index 0000000..22bf0e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fma/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fma +Name = Call fma with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the fma function with various num/exponent pairs += that should produce std answers. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/test1/CMakeLists.txt new file mode 100644 index 0000000..3d6be05 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_fmaf_test1 + ${SOURCES} +) + +add_dependencies(paltest_fmaf_test1 coreclrpal) + +target_link_libraries(paltest_fmaf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/test1/test1.c new file mode 100644 index 0000000..6c48d56 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/test1/test1.c @@ -0,0 +1,145 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that fmaf returns correct values for a subset of values. +** Tests with positive and negative values of x, y, and z to ensure +** fmaf is returning correct results. +** +**===================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float x; /* first component of the value to test the function with */ + float y; /* second component of the value to test the function with */ + float z; /* third component of the value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float x, float y, float z, float expected, float variance) +{ + float result = fmaf(x, y, z); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("fmaf(%g, %g, %g) returned %10.9g when it should have returned %10.9g", + x, y, z, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float x, float y, float z) +{ + float result = fmaf(x, y, z); + + if (!_isnanf(result)) + { + Fail("fmaf(%g, %g, %g) returned %10.9g when it should have returned %10.9g", + x, y, z, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* x y z expected variance */ + { PAL_NEGINF, PAL_NEGINF, PAL_NEGINF, PAL_NEGINF, 0 }, + { -1e38, 2, 1e38, -1e38, 0 }, + { 1e38, 2, -1e38, 1e38, 0 }, + { PAL_POSINF, PAL_POSINF, PAL_POSINF, PAL_POSINF, 0 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].x, tests[i].y, tests[i].z, tests[i].expected, tests[i].variance); + } + + // Returns NaN if x or y is infinite, the other is zero, and z is NaN + validate_isnan(PAL_NEGINF, 0, PAL_NAN); + validate_isnan(PAL_POSINF, 0, PAL_NAN); + validate_isnan(0, PAL_NEGINF, PAL_NAN); + validate_isnan(0, PAL_POSINF, PAL_NAN); + + // Returns NaN if x or y is infinite, the other is zero, and z is not-NaN + validate_isnan(PAL_POSINF, 0, PAL_NEGINF); + validate_isnan(PAL_NEGINF, 0, PAL_NEGINF); + validate_isnan(0, PAL_POSINF, PAL_NEGINF); + validate_isnan(0, PAL_NEGINF, PAL_NEGINF); + + validate_isnan(PAL_POSINF, 0, 0); + validate_isnan(PAL_NEGINF, 0, 0); + validate_isnan(0, PAL_POSINF, 0); + validate_isnan(0, PAL_NEGINF, 0); + + validate_isnan(PAL_POSINF, 0, PAL_POSINF); + validate_isnan(PAL_NEGINF, 0, PAL_POSINF); + validate_isnan(0, PAL_POSINF, PAL_POSINF); + validate_isnan(0, PAL_NEGINF, PAL_POSINF); + + // Returns NaN if (x * y) is infinite, and z is an infinite of the opposite sign + validate_isnan(PAL_POSINF, PAL_POSINF, PAL_NEGINF); + validate_isnan(PAL_NEGINF, PAL_NEGINF, PAL_NEGINF); + validate_isnan(PAL_POSINF, PAL_NEGINF, PAL_POSINF); + validate_isnan(PAL_NEGINF, PAL_POSINF, PAL_POSINF); + + validate_isnan(PAL_POSINF, 1, PAL_NEGINF); + validate_isnan(PAL_NEGINF, 1, PAL_POSINF); + validate_isnan(1, PAL_POSINF, PAL_NEGINF); + validate_isnan(1, PAL_NEGINF, PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/test1/testinfo.dat new file mode 100644 index 0000000..8ca9fb7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmaf/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fmaf +Name = Call fmaf with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the fmaf function with various num/expfonent pairs += that should produce std answers. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/test1/CMakeLists.txt new file mode 100644 index 0000000..099b098 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fmod_test1 + ${SOURCES} +) + +add_dependencies(paltest_fmod_test1 coreclrpal) + +target_link_libraries(paltest_fmod_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/test1/test1.cpp new file mode 100644 index 0000000..fd69ca5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/test1/test1.cpp @@ -0,0 +1,157 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that fmod return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double numerator; /* second component of the value to test the function with */ + double denominator; /* first component of the value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double numerator, double denominator, double expected, double variance) +{ + double result = fmod(numerator, denominator); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("fmod(%g, %g) returned %20.17g when it should have returned %20.17g", + numerator, denominator, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double numerator, double denominator) +{ + double result = fmod(numerator, denominator); + + if (!_isnan(result)) + { + Fail("fmod(%g, %g) returned %20.17g when it should have returned %20.17g", + numerator, denominator, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +INT __cdecl main(INT argc, CHAR **argv) +{ + struct test tests[] = + { + /* numerator denominator expected variance */ + { 0, PAL_POSINF, 0, PAL_EPSILON }, + { 0.31296179620778659, 0.94976571538163866, 0.31296179620778658, PAL_EPSILON }, + { 0.42077048331375735, 0.90716712923909839, 0.42077048331375733, PAL_EPSILON }, + { 0.59448076852482208, 0.80410982822879171, 0.59448076852482212, PAL_EPSILON }, + { 0.63896127631363480, 0.76923890136397213, 0.63896127631363475, PAL_EPSILON }, + { 0.64963693908006244, 0.76024459707563015, 0.64963693908006248, PAL_EPSILON }, + { 0.70710678118654752, 0.70710678118654752, 0, PAL_EPSILON }, + { 1, 1, 0, PAL_EPSILON }, + { 0.84147098480789651, 0.54030230586813972, 0.30116867893975674, PAL_EPSILON }, + { 0.90371945743584630, 0.42812514788535792, 0.047469161665130377, PAL_EPSILON / 10 }, + { 0.98776594599273553, 0.15594369476537447, 0.052103777400488605, PAL_EPSILON / 10 }, + { 0.99180624439366372, 0.12775121753523991, 0.097547721646984359, PAL_EPSILON / 10 }, + { 0.74398033695749319, -0.66820151019031295, 0.075778826767180285, PAL_EPSILON / 10 }, + { 0.41078129050290870, -0.91173391478696510, 0.41078129050290868, PAL_EPSILON }, + { 0, -1, 0, PAL_EPSILON }, + { 1, PAL_POSINF, 1, PAL_EPSILON * 10 }, + }; + + + // PAL initialization + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].numerator, tests[i].denominator, tests[i].expected, tests[i].variance); + validate(-tests[i].numerator, tests[i].denominator, -tests[i].expected, tests[i].variance); + validate( tests[i].numerator, -tests[i].denominator, tests[i].expected, tests[i].variance); + validate(-tests[i].numerator, -tests[i].denominator, -tests[i].expected, tests[i].variance); + } + + validate_isnan( 0, 0); + validate_isnan(-0.0, 0); + validate_isnan( 0, -0.0); + validate_isnan(-0.0, -0.0); + + validate_isnan( 1, 0); + validate_isnan(-1.0, 0); + validate_isnan( 1, -0.0); + validate_isnan(-1.0, -0.0); + + validate_isnan(PAL_POSINF, PAL_POSINF); + validate_isnan(PAL_NEGINF, PAL_POSINF); + validate_isnan(PAL_POSINF, PAL_NEGINF); + validate_isnan(PAL_NEGINF, PAL_NEGINF); + + validate_isnan(PAL_POSINF, 0); + validate_isnan(PAL_NEGINF, 0); + validate_isnan(PAL_POSINF, -0.0); + validate_isnan(PAL_NEGINF, -0.0); + + validate_isnan(PAL_POSINF, 1); + validate_isnan(PAL_NEGINF, 1); + validate_isnan(PAL_POSINF, -1.0); + validate_isnan(PAL_NEGINF, -1.0); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/test1/testinfo.dat new file mode 100644 index 0000000..0a81fd8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmod/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fmod +Name = Positive Test for fmod +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to fmod() a series of values, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/test1/CMakeLists.txt new file mode 100644 index 0000000..ac125ab --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fmodf_test1 + ${SOURCES} +) + +add_dependencies(paltest_fmodf_test1 coreclrpal) + +target_link_libraries(paltest_fmodf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/test1/test1.cpp new file mode 100644 index 0000000..31b45d3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/test1/test1.cpp @@ -0,0 +1,156 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that fmodf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabsf +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + float numerator; /* second component of the value to test the function with */ + float denominator; /* first component of the value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float numerator, float denominator, float expected, float variance) +{ + float result = fmodf(numerator, denominator); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("fmodf(%g, %g) returned %10.9g when it should have returned %10.9g", + numerator, denominator, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float numerator, float denominator) +{ + float result = fmodf(numerator, denominator); + + if (!_isnan(result)) + { + Fail("fmodf(%g, %g) returned %10.9g when it should have returned %10.9g", + numerator, denominator, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +INT __cdecl main(INT argc, CHAR **argv) +{ + struct test tests[] = + { + /* numerator denominator expected variance */ + { 0, PAL_POSINF, 0, PAL_EPSILON }, + { 0.312961796f, 0.949765715f, 0.312961796f, PAL_EPSILON }, + { 0.420770483f, 0.907167129f, 0.420770483f, PAL_EPSILON }, + { 0.594480769f, 0.804109828f, 0.594480769f, PAL_EPSILON }, + { 0.638961276f, 0.769238901f, 0.638961276f, PAL_EPSILON }, + { 0.649636939f, 0.760244597f, 0.649636939f, PAL_EPSILON }, + { 0.707106781f, 0.707106781f, 0, PAL_EPSILON }, + { 1, 1, 0, PAL_EPSILON }, + { 0.841470985f, 0.540302306f, 0.301168679f, PAL_EPSILON }, + { 0.903719457f, 0.428125148f, 0.0474691617f, PAL_EPSILON / 10 }, + { 0.987765946f, 0.155943695f, 0.0521037774f, PAL_EPSILON / 10 }, + { 0.991806244f, 0.127751218f, 0.0975477216f, PAL_EPSILON / 10 }, + { 0.743980337f, -0.668201510f, 0.0757788268f, PAL_EPSILON / 10 }, + { 0.410781291f, -0.911733915f, 0.410781291f, PAL_EPSILON }, + { 0, -1, 0, PAL_EPSILON }, + { 1, PAL_POSINF, 1, PAL_EPSILON * 10 }, + }; + + + // PAL initialization + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].numerator, tests[i].denominator, tests[i].expected, tests[i].variance); + validate(-tests[i].numerator, tests[i].denominator, -tests[i].expected, tests[i].variance); + validate( tests[i].numerator, -tests[i].denominator, tests[i].expected, tests[i].variance); + validate(-tests[i].numerator, -tests[i].denominator, -tests[i].expected, tests[i].variance); + } + + validate_isnan( 0, 0); + validate_isnan(-0.0f, 0); + validate_isnan( 0, -0.0f); + validate_isnan(-0.0f, -0.0f); + + validate_isnan( 1, 0); + validate_isnan(-1, 0); + validate_isnan( 1, -0.0f); + validate_isnan(-1, -0.0f); + + validate_isnan(PAL_POSINF, PAL_POSINF); + validate_isnan(PAL_NEGINF, PAL_POSINF); + validate_isnan(PAL_POSINF, PAL_NEGINF); + validate_isnan(PAL_NEGINF, PAL_NEGINF); + + validate_isnan(PAL_POSINF, 0); + validate_isnan(PAL_NEGINF, 0); + validate_isnan(PAL_POSINF, -0.0f); + validate_isnan(PAL_NEGINF, -0.0f); + + validate_isnan(PAL_POSINF, 1); + validate_isnan(PAL_NEGINF, 1); + validate_isnan(PAL_POSINF, -1); + validate_isnan(PAL_NEGINF, -1); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/test1/testinfo.dat new file mode 100644 index 0000000..11c7978 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fmodf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fmodf +Name = Positive Test for fmodf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to fmodf() a series of values, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/CMakeLists.txt new file mode 100644 index 0000000..7cd88f8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/CMakeLists.txt @@ -0,0 +1,8 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test1/CMakeLists.txt new file mode 100644 index 0000000..b0bae9f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fopen_test1 + ${SOURCES} +) + +add_dependencies(paltest_fopen_test1 coreclrpal) + +target_link_libraries(paltest_fopen_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test1/test1.cpp new file mode 100644 index 0000000..565b4eb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test1/test1.cpp @@ -0,0 +1,82 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the fopen function. +** This test simply attempts to open a number of files +** with different modes. It checks to ensure a valid +** file pointer is returned. It doesn't do any checking +** to ensure the mode is really what it claims. And checks +** for a NULL pointer when attempts to open a directory. +** + +** +**===================================================================*/ + +#include + +struct testCase +{ + int CorrectResult; + char mode[20]; +}; + +int __cdecl main(int argc, char **argv) +{ + + FILE *fp; + char name[128]; + int i; + + struct testCase testCases[] = + { + {0, "r"}, {1, "w"}, {1, "a"}, + {0, "r+"}, {1, "w+"}, {1, "a+"}, + {1, "wt"}, {1, "wb"}, {1, "wS"}, + {1, "w+c"}, {1, "w+n"}, {1, "wR"}, + {1, "wT"}, {0, "tw"} + }; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + strcpy(name,"testfiles"); + strcat(name,testCases[i].mode); + + fp = fopen(name,testCases[i].mode); + + if ((fp == 0 && testCases[i].CorrectResult != 0) || + (testCases[i].CorrectResult == 0 && fp != 0) ) + { + Fail("ERROR: fopen returned incorrectly " + "opening a file in %s mode. Perhaps it opened a " + "read only file which didn't exist and returned a correct " + "pointer?",testCases[i].mode); + } + + memset(name, '\0', 128); + + } + + /* When attempt to open a directory fopen should returned NULL */ + if ( fopen(".", "r") != NULL) + { + Fail("ERROR: fopen returned non-NULL when trying to open a directory" + " the returned value was %d\n", fp); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test1/testinfo.dat new file mode 100644 index 0000000..d990854 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fopen +Name = Positive Test for fopen +TYPE = DEFAULT +EXE1 = test1 +Description += This test simply attempts to open a number of files with different += modes. It checks to ensure a valid file pointer is returned. It += doesn't do any checking to ensure the mode is really what it claims. += Checks for returned value when attempts to open a directory. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test2/CMakeLists.txt new file mode 100644 index 0000000..a3efc88 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_fopen_test2 + ${SOURCES} +) + +add_dependencies(paltest_fopen_test2 coreclrpal) + +target_link_libraries(paltest_fopen_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test2/test2.cpp new file mode 100644 index 0000000..4026efe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test2/test2.cpp @@ -0,0 +1,65 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Tests the PAL implementation of the fopen function. +** Test to ensure that you can write to a 'w' mode file. +** And that you can't read from a 'w' mode file. +** +** Depends: +** fprintf +** fseek +** fgets +** + +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + + FILE *fp; + char buffer[128]; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + if( (fp = fopen( "testfile", "w" )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'w' mode.\n" ); + } + + /* Test that you can write */ + if(fprintf(fp,"%s","some text") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'w' mode " + "but fprintf failed. Either fopen or fprintf have problems."); + } + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + /* Test that you can't read */ + if(fgets(buffer,10,fp) != NULL) + { + Fail("ERROR: Tried to READ from a file with only 'w' mode set. " + "This should fail, but fgets didn't return NULL. Either " + "fgets or fopen is broken."); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test2/testinfo.dat new file mode 100644 index 0000000..4c1a009 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fopen +Name = Positive Test for fopen +TYPE = DEFAULT +EXE1 = test2 +Description += Test to ensure that you can write to a 'w' mode file. And that you can't += read from a 'w' mode file. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test3/CMakeLists.txt new file mode 100644 index 0000000..c6686ac --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_fopen_test3 + ${SOURCES} +) + +add_dependencies(paltest_fopen_test3 coreclrpal) + +target_link_libraries(paltest_fopen_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test3/test3.cpp new file mode 100644 index 0000000..f3af42d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test3/test3.cpp @@ -0,0 +1,66 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Tests the PAL implementation of the fopen function. +** Test to ensure that you can write to a 'w+' mode file. +** And that you can read from a 'w+' mode file. +** +** Depends: +** fprintf +** fseek +** fgets +** + +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + + FILE *fp; + char buffer[128]; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Open a file with 'w+' mode */ + if( (fp = fopen( "testfile", "w+" )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'w+' mode.\n" ); + } + + /* Write some text to the file */ + if(fprintf(fp,"%s","some text") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'w+' mode " + "but fprintf failed. Either fopen or fprintf have problems."); + } + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + /* Attempt to read from the 'w+' only file, should pass */ + if(fgets(buffer,10,fp) == NULL) + { + Fail("ERROR: Tried to READ from a file with 'w+' mode set. " + "This should succeed, but fgets returned NULL. Either fgets " + "or fopen is broken."); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test3/testinfo.dat new file mode 100644 index 0000000..c458c11 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test3/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fopen +Name = Positive Test for fopen +TYPE = DEFAULT +EXE1 = test3 +Description += Test to ensure that you can write to a 'w+' mode file. And that you can += read from a 'w+' mode file. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test4/CMakeLists.txt new file mode 100644 index 0000000..ab92939 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_fopen_test4 + ${SOURCES} +) + +add_dependencies(paltest_fopen_test4 coreclrpal) + +target_link_libraries(paltest_fopen_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test4/test4.cpp new file mode 100644 index 0000000..04683d5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test4/test4.cpp @@ -0,0 +1,82 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c +** +** Purpose: Tests the PAL implementation of the fopen function. +** Test to ensure that you can't write to a 'r' mode file. +** And that you can read from a 'r' mode file. +** +** Depends: +** fprintf +** fclose +** fgets +** + +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + + FILE *fp; + char buffer[128]; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Open a file with 'w' mode */ + if( (fp = fopen( "testfile", "w" )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'w' mode.\n" ); + } + + /* Write some text to the file */ + if(fprintf(fp,"%s","some text") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'w' mode " + "but fprintf failed. Either fopen or fprintf have problems."); + } + + if(fclose(fp)) + { + Fail("ERROR: Attempted to close a file, but fclose failed. " + "This test depends upon it."); + } + + /* Open a file with 'r' mode */ + if( (fp = fopen( "testfile", "r" )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'r' mode.\n" ); + } + + /* Attempt to read from the 'r' only file, should pass */ + if(fgets(buffer,10,fp) == NULL) + { + Fail("ERROR: Tried to READ from a file with 'r' mode set. " + "This should succeed, but fgets returned NULL. Either fgets " + "or fopen is broken."); + } + + /* Write some text to the file */ + if(fprintf(fp,"%s","some text") > 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'r' mode " + "but fprintf succeeded It should have failed. " + "Either fopen or fprintf have problems."); + } + + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test4/testinfo.dat new file mode 100644 index 0000000..a1ecaf9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test4/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fopen +Name = Positive Test for fopen +TYPE = DEFAULT +EXE1 = test4 +Description += Test to ensure that you can't write to a 'r' mode file. And that you can += read from a 'r' mode file. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test5/CMakeLists.txt new file mode 100644 index 0000000..ccbce5d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_fopen_test5 + ${SOURCES} +) + +add_dependencies(paltest_fopen_test5 coreclrpal) + +target_link_libraries(paltest_fopen_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test5/test5.cpp new file mode 100644 index 0000000..0a76031 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test5/test5.cpp @@ -0,0 +1,78 @@ +// 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. + +/*===================================================================== +** +** Source: test5.c +** +** Purpose: Tests the PAL implementation of the fopen function. +** Test to ensure that you can write to a 'r+' mode file. +** And that you can read from a 'r+' mode file. +** +** Depends: +** fprintf +** fclose +** fgets +** fseek +** + +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + + FILE *fp; + char buffer[128]; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Open a file with 'w' mode */ + if( (fp = fopen( "testfile", "w" )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'w' mode.\n" ); + } + + if(fclose(fp)) + { + Fail("ERROR: Attempted to close a file, but fclose failed. " + "This test depends upon it."); + } + + if( (fp = fopen( "testfile", "r+" )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'r+' mode.\n" ); + } + + /* Write some text to the file */ + if(fprintf(fp,"%s","some text") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'r+' mode " + "but fprintf failed. Either fopen or fprintf have problems."); + } + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + /* Attempt to read from the 'r+' only file, should pass */ + if(fgets(buffer,10,fp) == NULL) + { + Fail("ERROR: Tried to READ from a file with 'r+' mode set. " + "This should succeed, but fgets returned NULL. Either fgets " + "or fopen is broken."); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test5/testinfo.dat new file mode 100644 index 0000000..8f8f5d9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test5/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fopen +Name = Positive Test for fopen +TYPE = DEFAULT +EXE1 = test5 +Description += Test to ensure that you can write to a 'r+' mode file. And that you can += read from a 'r+' mode file. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test6/CMakeLists.txt new file mode 100644 index 0000000..7e373e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_fopen_test6 + ${SOURCES} +) + +add_dependencies(paltest_fopen_test6 coreclrpal) + +target_link_libraries(paltest_fopen_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test6/test6.cpp new file mode 100644 index 0000000..03b6067 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test6/test6.cpp @@ -0,0 +1,131 @@ +// 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. + +/*===================================================================== +** +** Source: test6.c +** +** Purpose: Tests the PAL implementation of the fopen function. +** Test to ensure that you can write to an 'a' mode file. +** And that you can't read from a 'a' mode file. Also ensure +** that you can use fseek and still write to the end of a file. +** +** Depends: +** fprintf +** fgets +** fseek +** fclose +** + +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + + FILE *fp; + char buffer[128]; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Open a file with 'a+' mode */ + if( (fp = fopen( "testfile", "a" )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'a' mode.\n" ); + } + + /* Write some text to the file */ + if(fprintf(fp,"%s","some text") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'a' mode " + "but fprintf failed. Either fopen or fprintf have problems."); + } + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + /* Attempt to read from the 'a' only file, should fail */ + if(fgets(buffer,10,fp) != NULL) + { + Fail("ERROR: Tried to READ from a file with 'a' mode set. " + "This should fail, but fgets returned success. Either fgets " + "or fopen is broken."); + } + + + /* Attempt to write to a file after using 'a' and fseek */ + fp = fopen("testfile2", "a"); + if(fp == NULL) + { + Fail("ERROR: The file failed to be created with 'a' mode.\n"); + } + + /* write text to the file initially */ + if(fprintf(fp,"%s","abcd") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'a' mode " + "but fprintf failed. Either fopen or fprintf have problems.\n"); + } + + /* set the pointer to the front of the file */ + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it.\n"); + } + + /* using 'a' should still write to the end of the file, not the front */ + if(fputs("efgh",fp) < 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'a' mode " + "but fputs failed.\n"); + } + + /* set the pointer to the front of the file */ + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it.\n"); + } + + /* a file with 'a' mode can only write, so close the file before reading */ + if(fclose(fp)) + { + Fail("ERROR: fclose failed when it should have succeeded.\n"); + } + + /* open the file again to read */ + fp = fopen("testfile2","r"); + if(fp == NULL) + { + Fail("ERROR: fopen failed to open the file using 'r' mode"); + } + + /* Attempt to read from the 'a' only file, should succeed */ + if(fgets(buffer,10,fp) == NULL) + { + Fail("ERROR: Tried to READ from a file with 'a' mode set. " + "This should pass, but fgets returned failure. Either fgets " + "or fopen is broken.\n"); + } + + /* Compare what was read and what should have been in the file */ + if(memcmp(buffer,"abcdefgh",8)) + { + Fail("ERROR: The string read should have equaled 'abcdefgh' " + "but instead it is %s\n", buffer); + } + + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test6/testinfo.dat new file mode 100644 index 0000000..5edd944 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test6/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fopen +Name = Positive Test for fopen +TYPE = DEFAULT +EXE1 = test6 +Description += Test to ensure that you can write to a 'a' mode file. And that you can't += read from a 'a' mode file. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test7/CMakeLists.txt new file mode 100644 index 0000000..8c8d1c2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_fopen_test7 + ${SOURCES} +) + +add_dependencies(paltest_fopen_test7 coreclrpal) + +target_link_libraries(paltest_fopen_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test7/test7.cpp new file mode 100644 index 0000000..3ef8602 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test7/test7.cpp @@ -0,0 +1,117 @@ +// 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. + +/*===================================================================== +** +** Source: test7.c +** +** Purpose: Tests the PAL implementation of the fopen function. +** Test to ensure that you can write to an 'a+' mode file. +** And that you can read from a 'a+' mode file. Also ensure +** that you can use fseek and still write to the end of a file. +** +** Depends: +** fprintf +** fgets +** fseek +** fclose +** + +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + + FILE *fp; + char buffer[128]; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Open a file with 'a+' mode */ + if( (fp = fopen( "testfile", "a+" )) == NULL ) + { + Fail( "ERROR: The file failed to open with 'a+' mode.\n" ); + } + + /* Write some text to the file */ + if(fprintf(fp,"%s","some text") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'a+' mode " + "but fprintf failed. Either fopen or fprintf have problems.\n"); + } + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it.\n"); + } + + /* Attempt to read from the 'a+' only file, should succeed */ + if(fgets(buffer,10,fp) == NULL) + { + Fail("ERROR: Tried to READ from a file with 'a+' mode set. " + "This should pass, but fgets returned failure. Either fgets " + "or fopen is broken.\n"); + } + + + /* Attempt to write to a file after using 'a+' and fseek */ + fp = fopen("testfile2", "a+"); + if(fp == NULL) + { + Fail("ERROR: The file failed to be created with 'a+' mode.\n"); + } + + /* write text to the file initially */ + if(fprintf(fp,"%s","abcd") <= 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'a+' mode " + "but fprintf failed. Either fopen or fprintf have problems.\n"); + } + + /* set the pointer to the front of the file */ + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it.\n"); + } + + /* using 'a+' should still write to the end of the file, not the front */ + if(fputs("efgh",fp) < 0) + { + Fail("ERROR: Attempted to WRITE to a file opened with 'a+' mode " + "but fputs failed.\n"); + } + + /* set the pointer to the front of the file */ + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it.\n"); + } + + /* Attempt to read from the 'a+' only file, should succeed */ + if(fgets(buffer,10,fp) == NULL) + { + Fail("ERROR: Tried to READ from a file with 'a+' mode set. " + "This should pass, but fgets returned failure. Either fgets " + "or fopen is broken.\n"); + } + + /* Compare what was read and what should have been in the file */ + if(memcmp(buffer,"abcdefgh",8)) + { + Fail("ERROR: The string read should have equaled 'abcdefgh' " + "but instead it is %s\n", buffer); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test7/testinfo.dat new file mode 100644 index 0000000..e4bc99c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fopen/test7/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fopen +Name = Positive Test for fopen +TYPE = DEFAULT +EXE1 = test7 +Description += Test to ensure that you can write to a 'a+' mode file. And that you can += read from a 'a+' mode file. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/CMakeLists.txt new file mode 100644 index 0000000..256753a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/CMakeLists.txt @@ -0,0 +1,20 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/fprintf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/fprintf.h new file mode 100644 index 0000000..87ee0d1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/fprintf.h @@ -0,0 +1,177 @@ +// 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. + +/*NOTE: +The creation of the test file within each function is because the FILE +structure is not defined within pal.h. Therefore, unable to have +function with this as a return type. +*/ + +#ifndef __FPRINTF_H__ +#define __FPRINTF_H__ + +void DoStrTest(const char *formatstr, char* param, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + Fail("ERROR: fopen failed to create testfile\n"); + if ((fprintf(fp, formatstr, param)) < 0) + Fail("ERROR: fprintf failed\n"); + if ((fseek(fp, 0, SEEK_SET)) != 0) + Fail("ERROR: fseek failed\n"); + if ((fgets(buf, 100, fp)) == NULL) + Fail("ERROR: fseek failed\n"); + + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, formatstr, checkstr, buf); + } + fclose(fp); +} + +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + Fail("ERROR: fopen failed to create testfile\n"); + if ((fprintf(fp, formatstr, param)) < 0) + Fail("ERROR: fprintf failed\n"); + if ((fseek(fp, 0, SEEK_SET)) != 0) + Fail("ERROR: fseek failed\n"); + if ((fgets(buf, 100, fp)) == NULL) + Fail("ERROR: fseek failed\n"); + + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + convertC(param), formatstr, checkstr, buf); + } + fclose(fp); +} + + +void DoCharTest(const char *formatstr, char param, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + Fail("ERROR: fopen failed to create testfile\n"); + if ((fprintf(fp, formatstr, param)) < 0) + Fail("ERROR: fprintf failed\n"); + if ((fseek(fp, 0, SEEK_SET)) != 0) + Fail("ERROR: fseek failed\n"); + if ((fgets(buf, 100, fp)) == NULL) + Fail("ERROR: fseek failed\n"); + + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, param, formatstr, checkstr, buf); + } + fclose(fp); +} + +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + Fail("ERROR: fopen failed to create testfile\n"); + if ((fprintf(fp, formatstr, param)) < 0) + Fail("ERROR: fprintf failed\n"); + if ((fseek(fp, 0, SEEK_SET)) != 0) + Fail("ERROR: fseek failed\n"); + if ((fgets(buf, 100, fp)) == NULL) + Fail("ERROR: fseek failed\n"); + + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + (char)param, param, formatstr, checkstr, buf); + } + fclose(fp); +} + +void DoNumTest(const char *formatstr, int value, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + Fail("ERROR: fopen failed to create testfile\n"); + if ((fprintf(fp, formatstr, value)) < 0) + Fail("ERROR: fprintf failed\n"); + if ((fseek(fp, 0, SEEK_SET)) != 0) + Fail("ERROR: fseek failed\n"); + if ((fgets(buf, 100, fp)) == NULL) + Fail("ERROR: fseek failed\n"); + + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert %#x into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + value, formatstr, checkstr, buf); + } + fclose(fp); +} + +void DoI64Test(const char *formatstr, INT64 value, char *valuestr, const char *checkstr1, const char *checkstr2) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + Fail("ERROR: fopen failed to create testfile\n"); + if ((fprintf(fp, formatstr, value)) < 0) + Fail("ERROR: fprintf failed\n"); + if ((fseek(fp, 0, SEEK_SET)) != 0) + Fail("ERROR: fseek failed\n"); + if ((fgets(buf, 100, fp)) == NULL) + Fail("ERROR: fseek failed\n"); + + if (memcmp(buf, checkstr1, strlen(buf) + 1) != 0 && + memcmp(buf, checkstr2, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + valuestr, formatstr, checkstr1, checkstr2, buf); + } + fclose(fp); +} + +void DoDoubleTest(const char *formatstr, double value, const char *checkstr1, const char *checkstr2) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + Fail("ERROR: fopen failed to create testfile\n"); + if ((fprintf(fp, formatstr, value)) < 0) + Fail("ERROR: fprintf failed\n"); + if ((fseek(fp, 0, SEEK_SET)) != 0) + Fail("ERROR: fseek failed\n"); + if ((fgets(buf, 100, fp)) == NULL) + Fail("ERROR: fseek failed\n"); + + if (memcmp(buf, checkstr1, strlen(buf) + 1) != 0 && + memcmp(buf, checkstr2, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + value, formatstr, checkstr1, checkstr2, buf); + } + fclose(fp); +} +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test1/CMakeLists.txt new file mode 100644 index 0000000..c092aaf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test1 coreclrpal) + +target_link_libraries(paltest_fprintf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test1/test1.cpp new file mode 100644 index 0000000..d55fc25 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test1/test1.cpp @@ -0,0 +1,80 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c (fprintf) +** +** Purpose: A single, basic, test case with no formatting. +** Test modeled after the sprintf series. +** + +** +**==========================================================================*/ + +#include + +/* + * Depends on memcmp, strlen, fopen, fgets, fseek and fclose. + */ + +int __cdecl main(int argc, char *argv[]) +{ + FILE *fp; + char testfile[] = "testfile.txt"; + char checkstr[] = "hello world"; + char buf[256]; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + if ((fp = fopen(testfile, "w+")) == NULL) + { + Fail("ERROR: fopen failed to create \"%s\"\n", testfile); + } + + if ((fprintf(fp, "hello world")) < 0) + { + Fail("ERROR: fprintf failed to print to \"%s\"\n", testfile); + } + + if ((fseek( fp, 0, SEEK_SET)) != 0) + + { + + Fail("ERROR: Fseek failed to set pointer to beginning of file\n" ); + + } + + + + if ((fgets( buf, 100, fp )) == NULL) + + { + + Fail("ERROR: fgets failed\n"); + + } + + + if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0) + { + Fail("ERROR: expected %s, got %s\n", checkstr, buf); + } + + + + if ((fclose( fp )) != 0) + + { + + Fail("ERROR: fclose failed to close \"%s\"\n", testfile); + + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test1/testinfo.dat new file mode 100644 index 0000000..be3bf4b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test1 +Description += A single, basic, test case with no formatting. += Test modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test10/CMakeLists.txt new file mode 100644 index 0000000..c095555 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_fprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test10 coreclrpal) + +target_link_libraries(paltest_fprintf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test10/test10.cpp new file mode 100644 index 0000000..5988e8d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test10/test10.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test10.c (fprintf) +** +** Purpose: Tests the octal specifier (%o). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoNumTest("foo %o", pos, "foo 52"); + DoNumTest("foo %lo", 0xFFFF, "foo 177777"); + DoNumTest("foo %ho", 0xFFFF, "foo 177777"); + DoNumTest("foo %Lo", pos, "foo 52"); + DoI64Test("foo %I64o", l, "42", "foo 52", "foo 52"); + DoNumTest("foo %3o", pos, "foo 52"); + DoNumTest("foo %-3o", pos, "foo 52 "); + DoNumTest("foo %.1o", pos, "foo 52"); + DoNumTest("foo %.3o", pos, "foo 052"); + DoNumTest("foo %03o", pos, "foo 052"); + DoNumTest("foo %#o", pos, "foo 052"); + DoNumTest("foo %+o", pos, "foo 52"); + DoNumTest("foo % o", pos, "foo 52"); + DoNumTest("foo %+o", neg, "foo 37777777726"); + DoNumTest("foo % o", neg, "foo 37777777726"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test10/testinfo.dat new file mode 100644 index 0000000..7afffea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test10/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test10 +Description += Tests the octal specifier (%o). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test11/CMakeLists.txt new file mode 100644 index 0000000..32559bf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_fprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test11 coreclrpal) + +target_link_libraries(paltest_fprintf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test11/test11.cpp new file mode 100644 index 0000000..0188055 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test11/test11.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test11.c (fprintf) +** +** Purpose: Test the unsigned int specifier (%u). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoNumTest("foo %u", pos, "foo 42"); + DoNumTest("foo %lu", 0xFFFF, "foo 65535"); + DoNumTest("foo %hu", 0xFFFF, "foo 65535"); + DoNumTest("foo %Lu", pos, "foo 42"); + DoI64Test("foo %I64u", l, "42", "foo 42", "foo 42"); + DoNumTest("foo %3u", pos, "foo 42"); + DoNumTest("foo %-3u", pos, "foo 42 "); + DoNumTest("foo %.1u", pos, "foo 42"); + DoNumTest("foo %.3u", pos, "foo 042"); + DoNumTest("foo %03u", pos, "foo 042"); + DoNumTest("foo %#u", pos, "foo 42"); + DoNumTest("foo %+u", pos, "foo 42"); + DoNumTest("foo % u", pos, "foo 42"); + DoNumTest("foo %+u", neg, "foo 4294967254"); + DoNumTest("foo % u", neg, "foo 4294967254"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test11/testinfo.dat new file mode 100644 index 0000000..8275f0f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test11/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test11 +Description += Test the unsigned int specifier (%u). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test12/CMakeLists.txt new file mode 100644 index 0000000..1ee3cb2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_fprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test12 coreclrpal) + +target_link_libraries(paltest_fprintf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test12/test12.cpp new file mode 100644 index 0000000..0292e15 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test12/test12.cpp @@ -0,0 +1,50 @@ +// 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. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Tests the (lowercase) hexadecimal specifier (%x). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoNumTest("foo %x", pos, "foo 1234ab"); + DoNumTest("foo %lx", pos, "foo 1234ab"); + DoNumTest("foo %hx", pos, "foo 34ab"); + DoNumTest("foo %Lx", pos, "foo 1234ab"); + DoI64Test("foo %I64x", l, "0x1234567887654321", + "foo 1234567887654321", "foo 0x1234567887654321"); + DoNumTest("foo %7x", pos, "foo 1234ab"); + DoNumTest("foo %-7x", pos, "foo 1234ab "); + DoNumTest("foo %.1x", pos, "foo 1234ab"); + DoNumTest("foo %.7x", pos, "foo 01234ab"); + DoNumTest("foo %07x", pos, "foo 01234ab"); + DoNumTest("foo %#x", pos, "foo 0x1234ab"); + DoNumTest("foo %+x", pos, "foo 1234ab"); + DoNumTest("foo % x", pos, "foo 1234ab"); + DoNumTest("foo %+x", neg, "foo ffffffd6"); + DoNumTest("foo % x", neg, "foo ffffffd6"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test12/testinfo.dat new file mode 100644 index 0000000..4b44cfc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test12/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test12 +Description += Tests the (lowercase) hexadecimal specifier (%x). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test13/CMakeLists.txt new file mode 100644 index 0000000..1c4049e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_fprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test13 coreclrpal) + +target_link_libraries(paltest_fprintf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test13/test13.cpp new file mode 100644 index 0000000..e171aea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test13/test13.cpp @@ -0,0 +1,50 @@ +// 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. + +/*============================================================================ +** +** Source: test13.c (fprintf) +** +** Purpose: Tests the (uppercase) hexadecimal specifier (%X). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234AB; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoNumTest("foo %X", pos, "foo 1234AB"); + DoNumTest("foo %lX", pos, "foo 1234AB"); + DoNumTest("foo %hX", pos, "foo 34AB"); + DoNumTest("foo %LX", pos, "foo 1234AB"); + DoI64Test("foo %I64X", l, "0x1234567887654321", + "foo 1234567887654321", "foo 0x1234567887654321"); + DoNumTest("foo %7X", pos, "foo 1234AB"); + DoNumTest("foo %-7X", pos, "foo 1234AB "); + DoNumTest("foo %.1X", pos, "foo 1234AB"); + DoNumTest("foo %.7X", pos, "foo 01234AB"); + DoNumTest("foo %07X", pos, "foo 01234AB"); + DoNumTest("foo %#X", pos, "foo 0X1234AB"); + DoNumTest("foo %+X", pos, "foo 1234AB"); + DoNumTest("foo % X", pos, "foo 1234AB"); + DoNumTest("foo %+X", neg, "foo FFFFFFD6"); + DoNumTest("foo % X", neg, "foo FFFFFFD6"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test13/testinfo.dat new file mode 100644 index 0000000..ae983ec --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test13/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test13 +Description += Tests the (uppercase) hexadecimal specifier (%X). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test14/CMakeLists.txt new file mode 100644 index 0000000..3266d84 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_fprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test14 coreclrpal) + +target_link_libraries(paltest_fprintf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test14/test14.cpp new file mode 100644 index 0000000..5d7d773 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test14/test14.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test14.c (fprintf) +** +** Purpose: Tests the lowercase exponential +** notation double specifier (%e). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", "foo 2.560000e+02 "); + DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02"); + DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", "foo 2.56000000e+02"); + DoDoubleTest("foo %014e", val, "foo 02.560000e+002", "foo 002.560000e+02"); + DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02"); + DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test14/testinfo.dat new file mode 100644 index 0000000..f0a843f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test14/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test14 +Description += Tests the lowercase exponential += notation double specifier (%e). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test15/CMakeLists.txt new file mode 100644 index 0000000..51e7444 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_fprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test15 coreclrpal) + +target_link_libraries(paltest_fprintf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test15/test15.cpp new file mode 100644 index 0000000..d024bdb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test15/test15.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test15.c (fprintf) +** +** Purpose: Tests the uppercase exponential +** notation double specifier (%E). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %14E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", "foo 2.560000E+02 "); + DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02"); + DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", "foo 2.56000000E+02"); + DoDoubleTest("foo %014E", val, "foo 02.560000E+002", "foo 002.560000E+02"); + DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02"); + DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test15/testinfo.dat new file mode 100644 index 0000000..fedabca --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test15/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test15 +Description += Tests the uppercase exponential += notation double specifier (%E). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test16/CMakeLists.txt new file mode 100644 index 0000000..388ff21 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_fprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test16 coreclrpal) + +target_link_libraries(paltest_fprintf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test16/test16.cpp new file mode 100644 index 0000000..079faea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test16/test16.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================================ +** +** Source: test16.c (fprintf) +** +** Purpose: Tests the decimal notation double specifier (%f). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 "); + DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0"); + DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000"); + DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000"); + DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000"); + DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000"); + DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test16/testinfo.dat new file mode 100644 index 0000000..ef93c7c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test16/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test16 +Description += Tests the decimal notation double specifier (%f). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test17/CMakeLists.txt new file mode 100644 index 0000000..b2f46f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_fprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test17 coreclrpal) + +target_link_libraries(paltest_fprintf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test17/test17.cpp new file mode 100644 index 0000000..7bd817d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test17/test17.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test17.c (fprintf) +** +** Purpose: Tests the lowercase shorthand notation double specifier (%g). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoDoubleTest("foo %g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03"); + DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03"); + DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test17/testinfo.dat new file mode 100644 index 0000000..420703c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test17/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test17 +Description += Tests the lowercase shorthand notation double specifier (%g). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test18/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test18/CMakeLists.txt new file mode 100644 index 0000000..65a2329 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test18/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test18.cpp +) + +add_executable(paltest_fprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test18 coreclrpal) + +target_link_libraries(paltest_fprintf_test18 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test18/test18.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test18/test18.cpp new file mode 100644 index 0000000..6582c41 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test18/test18.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test18.c (fprintf) +** +** Purpose: Tests the uppercase shorthand notation double specifier (%G). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoDoubleTest("foo %G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03"); + DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03"); + DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test18/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test18/testinfo.dat new file mode 100644 index 0000000..129febe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test18/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test18 +Description += Tests the uppercase shorthand notation double specifier (%G). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test19/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test19/CMakeLists.txt new file mode 100644 index 0000000..9342858 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test19/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test19.cpp +) + +add_executable(paltest_fprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test19 coreclrpal) + +target_link_libraries(paltest_fprintf_test19 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test19/test19.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test19/test19.cpp new file mode 100644 index 0000000..9d9a28c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test19/test19.cpp @@ -0,0 +1,153 @@ +// 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. + +/*============================================================================ +** +** Source: test19.c (fprintf) +** +** Purpose: Tests the variable length precision argument. +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +#define DOTEST(a,b,c,d,e,f) DoTest(a,b,(void*)c,d,e,f) + +void DoTest(char *formatstr, int precision, void *param, + char *paramstr, char *checkstr1, char *checkstr2) +{ + FILE *fp; + char buf[256]; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((fprintf(fp, formatstr, precision, param)) < 0) + { + Fail("ERROR: fprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (memcmp(buf, checkstr1, strlen(buf) + 1) != 0 && + memcmp(buf, checkstr2, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", paramstr, formatstr, + precision, + checkstr1, checkstr2, buf); + } + + if ((fclose( fp )) != 0) + + { + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + } + +} + +void DoublePrecTest(char *formatstr, int precision, + double param, char *checkstr1, char *checkstr2) +{ + FILE *fp; + char buf[256]; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((fprintf(fp, formatstr, precision, param)) < 0) + { + Fail("ERROR: fprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (memcmp(buf, checkstr1, strlen(buf) + 1) != 0 && + memcmp(buf, checkstr2, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + param, formatstr, precision, checkstr1, checkstr2, buf); + } + + if ((fclose( fp )) != 0) + { + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + } + +} + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DOTEST("%.*s", 2, "bar", "bar", "ba", "ba"); + DOTEST("%.*S", 2, convert("bar"), "bar", "ba", "ba"); + + //DOTEST("%.*n", 4, 2, "2", "0002"); + DOTEST("%.*c", 0, 'a', "a", "a", "a"); + DOTEST("%.*c", 4, 'a', "a", "a", "a"); + DOTEST("%.*C", 0, (WCHAR)'a', "a", "a", "a"); + DOTEST("%.*C", 4, (WCHAR)'a', "a", "a", "a"); + DOTEST("%.*d", 1, 42, "42", "42", "42"); + DOTEST("%.*d", 3, 42, "42", "042", "042"); + DOTEST("%.*i", 1, 42, "42", "42", "42"); + DOTEST("%.*i", 3, 42, "42", "042", "042"); + DOTEST("%.*o", 1, 42, "42", "52", "52"); + DOTEST("%.*o", 3, 42, "42", "052", "052"); + DOTEST("%.*u", 1, 42, "42", "42", "42"); + DOTEST("%.*u", 3, 42, "42", "042", "042"); + DOTEST("%.*x", 1, 0x42, "0x42", "42", "42"); + DOTEST("%.*x", 3, 0x42, "0x42", "042", "042"); + DOTEST("%.*X", 1, 0x42, "0x42", "42", "42"); + DOTEST("%.*X", 3, 0x42, "0x42", "042", "042"); + + + DoublePrecTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoublePrecTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoublePrecTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoublePrecTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoublePrecTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoublePrecTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoublePrecTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoublePrecTest("%.*g", 3, 256.01, "256", "256"); + DoublePrecTest("%.*g", 4, 256.01, "256", "256"); + DoublePrecTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoublePrecTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoublePrecTest("%.*G", 3, 256.01, "256", "256"); + DoublePrecTest("%.*G", 4, 256.01, "256", "256"); + DoublePrecTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test19/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test19/testinfo.dat new file mode 100644 index 0000000..25025b9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test19/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test19 +Description += Tests the variable length precision argument. += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test2/CMakeLists.txt new file mode 100644 index 0000000..daa9a5f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_fprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test2 coreclrpal) + +target_link_libraries(paltest_fprintf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test2/test2.cpp new file mode 100644 index 0000000..1441827 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test2/test2.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c (fprintf) +** +** Purpose: Tests the string specifier (%s). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoStrTest("foo %s", "bar", "foo bar"); + DoStrTest("foo %hs", "bar", "foo bar"); + DoWStrTest("foo %ls", convert("bar"), "foo bar"); + DoWStrTest("foo %ws", convert("bar"), "foo bar"); + DoStrTest("foo %Ls", "bar", "foo bar"); + DoStrTest("foo %I64s", "bar", "foo bar"); + DoStrTest("foo %5s", "bar", "foo bar"); + DoStrTest("foo %.2s", "bar", "foo ba"); + DoStrTest("foo %5.2s", "bar", "foo ba"); + DoStrTest("foo %-5s", "bar", "foo bar "); + DoStrTest("foo %05s", "bar", "foo 00bar"); + DoStrTest("foo %s", NULL, "foo (null)"); + DoStrTest("foo %hs", NULL, "foo (null)"); + DoWStrTest("foo %ls", NULL, "foo (null)"); + DoWStrTest("foo %ws", NULL, "foo (null)"); + DoStrTest("foo %Ls", NULL, "foo (null)"); + DoStrTest("foo %I64s", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test2/testinfo.dat new file mode 100644 index 0000000..d4c7dbf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test2 +Description += Tests the string specifier (%s). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test3/CMakeLists.txt new file mode 100644 index 0000000..7b3ed7b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_fprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test3 coreclrpal) + +target_link_libraries(paltest_fprintf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test3/test3.cpp new file mode 100644 index 0000000..dd34c08 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test3/test3.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c (fprintf) +** +** Purpose: Tests the wide string specifier (%S). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoWStrTest("foo %S", convert("bar"), "foo bar"); + DoStrTest("foo %hS", "bar", "foo bar"); + DoWStrTest("foo %lS", convert("bar"), "foo bar"); + DoWStrTest("foo %wS", convert("bar"), "foo bar"); + DoWStrTest("foo %LS", convert("bar"), "foo bar"); + DoWStrTest("foo %I64S", convert("bar"), "foo bar"); + DoWStrTest("foo %5S", convert("bar"), "foo bar"); + DoWStrTest("foo %.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %5.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %-5S", convert("bar"), "foo bar "); + DoWStrTest("foo %05S", convert("bar"), "foo 00bar"); + DoWStrTest("foo %S", NULL, "foo (null)"); + DoStrTest("foo %hS", NULL, "foo (null)"); + DoWStrTest("foo %lS", NULL, "foo (null)"); + DoWStrTest("foo %wS", NULL, "foo (null)"); + DoWStrTest("foo %LS", NULL, "foo (null)"); + DoWStrTest("foo %I64S", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test3/testinfo.dat new file mode 100644 index 0000000..88a1b03 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test3/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test3 +Description += Tests the wide string specifier (%S). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test4/CMakeLists.txt new file mode 100644 index 0000000..10a3c94 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_fprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test4 coreclrpal) + +target_link_libraries(paltest_fprintf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test4/test4.cpp new file mode 100644 index 0000000..4af4d1a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test4/test4.cpp @@ -0,0 +1,110 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c (fprintf) +** +** Purpose: Tests the pointer specifier (%p). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +static void DoTest(char *formatstr, void* param, char* paramstr, + char *checkstr1, char *checkstr2) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((fprintf(fp, formatstr, param)) < 0) + { + Fail("ERROR: fprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (memcmp(buf, checkstr1, strlen(buf) + 1) != 0 && + memcmp(buf, checkstr2, strlen(buf) + 1) != 0 ) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\" or \"%s\" got \"%s\".\n", + paramstr, formatstr, checkstr1, checkstr2, buf); + } + + if ((fclose( fp )) != 0) + + { + + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + + } +} + + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + Trace("Testing for 64 Bit Platforms \n"); + DoTest("%p", NULL, "NULL", "0000000000000000", "0x0"); + DoTest("%p", ptr, "pointer to 0x123456", "0000000000123456", "0x123456"); + DoTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456", " 0x123456"); + DoTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456", "0x0123456"); + DoTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 ", "0x123456 "); + DoTest("%+p", ptr, "pointer to 0x123456", "0000000000123456", "0x123456"); + DoTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456", "0x123456"); + DoTest("%lp", ptr, "pointer to 0x123456", "00123456", "0x123456"); + DoTest("%hp", ptr, "pointer to 0x123456", "00003456", "0x3456"); + DoTest("%Lp", ptr, "pointer to 0x123456", "00123456", "0x123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321", "0x1234567887654321"); +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoTest("%p", NULL, "NULL", "00000000", "0x0"); + DoTest("%p", ptr, "pointer to 0x123456", "00123456", "0x123456"); + DoTest("%9p", ptr, "pointer to 0x123456", " 00123456", " 0x123456"); + DoTest("%09p", ptr, "pointer to 0x123456", " 00123456", "0x0123456"); + DoTest("%-9p", ptr, "pointer to 0x123456", "00123456 ", "0x123456 "); + DoTest("%+p", ptr, "pointer to 0x123456", "00123456", "0x123456"); + DoTest("%#p", ptr, "pointer to 0x123456", "0X00123456", "0x123456"); + DoTest("%lp", ptr, "pointer to 0x123456", "00123456", "0x123456"); + DoTest("%hp", ptr, "pointer to 0x123456", "00003456", "0x3456"); + DoTest("%Lp", ptr, "pointer to 0x123456", "00123456", "0x123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321", "0x1234567887654321"); +#endif + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test4/testinfo.dat new file mode 100644 index 0000000..5f373ac --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test4/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test4 +Description += Tests the pointer specifier (%p). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test5/CMakeLists.txt new file mode 100644 index 0000000..8753661 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_fprintf_test5 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test5 coreclrpal) + +target_link_libraries(paltest_fprintf_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test5/test5.cpp new file mode 100644 index 0000000..c53e3f4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test5/test5.cpp @@ -0,0 +1,131 @@ +// 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. + +/*============================================================================ +** +** Source: test5.c (fprintf) +** +** Purpose: Tests the count specifier (%n). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +static void DoTest(char *formatstr, int param, char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + int n = -1; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((fprintf(fp, formatstr, &n)) < 0) + { + Fail("ERROR: fprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } + + + if ((fclose( fp )) != 0) + + { + + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + + } +} + +static void DoShortTest(char *formatstr, int param, char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + short int n = -1; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((fprintf(fp, formatstr, &n)) < 0) + { + Fail("ERROR: fprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } + + if ((fclose( fp )) != 0) + { + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + } +} + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoTest("foo %n bar", 4, "foo bar"); + DoTest("foo %#n bar", 4, "foo bar"); + DoTest("foo % n bar", 4, "foo bar"); + DoTest("foo %+n bar", 4, "foo bar"); + DoTest("foo %-n bar", 4, "foo bar"); + DoTest("foo %0n bar", 4, "foo bar"); + DoShortTest("foo %hn bar", 4, "foo bar"); + DoTest("foo %ln bar", 4, "foo bar"); + DoTest("foo %Ln bar", 4, "foo bar"); + DoTest("foo %I64n bar", 4, "foo bar"); + DoTest("foo %20.3n bar", 4, "foo bar"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test5/testinfo.dat new file mode 100644 index 0000000..b4d0e81 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test5/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test5 +Description += Tests the count specifier (%n). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test6/CMakeLists.txt new file mode 100644 index 0000000..8c7253c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_fprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test6 coreclrpal) + +target_link_libraries(paltest_fprintf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test6/test6.cpp new file mode 100644 index 0000000..0a8bc6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test6/test6.cpp @@ -0,0 +1,46 @@ +// 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. + +/*============================================================================ +** +** Source: test6.c (fprintf) +** +** Purpose: Tests the char specifier (%c). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoCharTest("foo %c", 'b', "foo b"); + DoCharTest("foo %hc", 'b', "foo b"); + DoWCharTest("foo %lc", wc, "foo c"); + DoCharTest("foo %Lc", 'b', "foo b"); + DoCharTest("foo %I64c", 'b', "foo b"); + DoCharTest("foo %5c", 'b', "foo b"); + DoCharTest("foo %.0c", 'b', "foo b"); + DoCharTest("foo %-5c", 'b', "foo b "); + DoCharTest("foo %05c", 'b', "foo 0000b"); + DoCharTest("foo % c", 'b', "foo b"); + DoCharTest("foo %#c", 'b', "foo b"); + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test6/testinfo.dat new file mode 100644 index 0000000..a8a071c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test6/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test6 +Description += Tests the char specifier (%c). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test7/CMakeLists.txt new file mode 100644 index 0000000..7e803e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_fprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test7 coreclrpal) + +target_link_libraries(paltest_fprintf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test7/test7.cpp new file mode 100644 index 0000000..088e328 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test7/test7.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================================ +** +** Source: test7.c (fprintf) +** +** Purpose: Tests the wide char specifier (%C). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wb = (WCHAR) 'b'; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoWCharTest("foo %C", wb, "foo b"); + DoWCharTest("foo %hC", wb, "foo b"); + DoCharTest("foo %lC", 'c', "foo c"); + DoWCharTest("foo %LC", wb, "foo b"); + DoWCharTest("foo %I64C", wb, "foo b"); + DoWCharTest("foo %5C", wb, "foo b"); + DoWCharTest("foo %.0C", wb, "foo b"); + DoWCharTest("foo %-5C", wb, "foo b "); + DoWCharTest("foo %05C", wb, "foo 0000b"); + DoWCharTest("foo % C", wb, "foo b"); + DoWCharTest("foo %#C", wb, "foo b"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test7/testinfo.dat new file mode 100644 index 0000000..fc12718 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test7/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test7 +Description += Tests the wide char specifier (%C). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test8/CMakeLists.txt new file mode 100644 index 0000000..0dd9501 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_fprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test8 coreclrpal) + +target_link_libraries(paltest_fprintf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test8/test8.cpp new file mode 100644 index 0000000..c781abc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test8/test8.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test8.c (fprintf) +** +** Purpose: Tests the decimal specifier (%d). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoNumTest("foo %d", pos, "foo 42"); + DoNumTest("foo %ld", 0xFFFF, "foo 65535"); + DoNumTest("foo %hd", 0xFFFF, "foo -1"); + DoNumTest("foo %Ld", pos, "foo 42"); + DoI64Test("foo %I64d", l, "42", "foo 42", "foo 42"); + DoNumTest("foo %3d", pos, "foo 42"); + DoNumTest("foo %-3d", pos, "foo 42 "); + DoNumTest("foo %.1d", pos, "foo 42"); + DoNumTest("foo %.3d", pos, "foo 042"); + DoNumTest("foo %03d", pos, "foo 042"); + DoNumTest("foo %#d", pos, "foo 42"); + DoNumTest("foo %+d", pos, "foo +42"); + DoNumTest("foo % d", pos, "foo 42"); + DoNumTest("foo %+d", neg, "foo -42"); + DoNumTest("foo % d", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test8/testinfo.dat new file mode 100644 index 0000000..2609260 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test8/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test8 +Description += Tests the decimal specifier (%d). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test9/CMakeLists.txt new file mode 100644 index 0000000..60ad749 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_fprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_fprintf_test9 coreclrpal) + +target_link_libraries(paltest_fprintf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test9/test9.cpp new file mode 100644 index 0000000..3b06dae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test9/test9.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test9.c (fprintf) +** +** Purpose: Tests the integer specifier (%i). +** This test is modeled after the fprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoNumTest("foo %i", pos, "foo 42"); + DoNumTest("foo %li", 0xFFFF, "foo 65535"); + DoNumTest("foo %hi", 0xFFFF, "foo -1"); + DoNumTest("foo %Li", pos, "foo 42"); + DoI64Test("foo %I64i", l, "42", "foo 42", "foo 42"); + DoNumTest("foo %3i", pos, "foo 42"); + DoNumTest("foo %-3i", pos, "foo 42 "); + DoNumTest("foo %.1i", pos, "foo 42"); + DoNumTest("foo %.3i", pos, "foo 042"); + DoNumTest("foo %03i", pos, "foo 042"); + DoNumTest("foo %#i", pos, "foo 42"); + DoNumTest("foo %+i", pos, "foo +42"); + DoNumTest("foo % i", pos, "foo 42"); + DoNumTest("foo %+i", neg, "foo -42"); + DoNumTest("foo % i", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test9/testinfo.dat new file mode 100644 index 0000000..e502af7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fprintf/test9/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fprintf +Name = Positive Test for fprintf +TYPE = DEFAULT +EXE1 = test9 +Description += Tests the integer specifier (%i). += This test is modeled after the fprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test1/CMakeLists.txt new file mode 100644 index 0000000..1a9ccfa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fputs_test1 + ${SOURCES} +) + +add_dependencies(paltest_fputs_test1 coreclrpal) + +target_link_libraries(paltest_fputs_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test1/test1.cpp new file mode 100644 index 0000000..b90ea08 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test1/test1.cpp @@ -0,0 +1,100 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Call fputs twice and write two strings to a file. Then +** call fread on the file and check that the data which was written is what +** we expect it to be. +** + +** +**===================================================================*/ + + +#include + + +int __cdecl main(int argc, char **argv) +{ + + FILE* TheFile; + char* StringOne = "FooBar"; + char* StringTwo = "BarFoo"; + char* CompleteString = "FooBarBarFoo"; + char ReadBuffer[64]; + int ret; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Open the file that we'll be working with */ + + TheFile = fopen("TestFile", "w+"); + + if(TheFile == NULL) + { + Fail("ERROR: fopen failed to open the file 'TestFile' in read/write " + "mode.\n"); + } + + /* Call fputs twice to write two strings to the file stream */ + + if(fputs(StringOne, TheFile) < 0) + { + Fail("ERROR: fputs returned a negative value when attempting to " + "put the string '%s' to the file.\n",StringOne); + } + + if(fputs(StringTwo, TheFile) < 0) + { + Fail("ERROR: fputs returned a negative value when attempting to " + "put the string '%s' to the file.\n",StringTwo); + } + + /* Flush the buffers */ + if(fflush(TheFile) != 0) + { + Fail("ERROR: fflush failed to properly flush the buffers.\n"); + } + + /* Now read from the file to ensure the data was written correctly. + Note: We read more than what was written to make sure nothing extra + was written. + */ + + if(fseek(TheFile, 0, SEEK_SET) != 0) + { + Fail("ERROR: fseek failed to set the file pointer back to the start " + "of the file.\n"); + } + + + if((ret = fread(ReadBuffer, 1, 20, TheFile)) != 12) + { + Fail("ERROR: fread should have returned that it read in 12 characters " + "from the file, but instead it returned %d.\n", ret); + } + + ReadBuffer[ret] = '\0'; + + if(strcmp(ReadBuffer, CompleteString) != 0) + { + Fail("ERROR: The data read back from the file is not exactly the same " + "as the data that was written by fputs. The file contains '%s' " + "instead of '%s'.\n",ReadBuffer, CompleteString); + } + + if(fclose(TheFile) != 0) + { + Fail("ERROR: fclose failed to close the file stream.\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test1/testinfo.dat new file mode 100644 index 0000000..bdef09c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fputs +Name = Check that fputs writes correctly to a valid stream +TYPE = DEFAULT +EXE1 = test1 +Description += Call fputs twice and write two strings to a file. Then += call fread on the file and check that the data which was written is what += we expect it to be. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test2/CMakeLists.txt new file mode 100644 index 0000000..261b420 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_fputs_test2 + ${SOURCES} +) + +add_dependencies(paltest_fputs_test2 coreclrpal) + +target_link_libraries(paltest_fputs_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test2/test2.cpp new file mode 100644 index 0000000..b8e2f41 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test2/test2.cpp @@ -0,0 +1,88 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Check to see that fputs fails and returns EOF when called on +** a closed file stream and a read-only file stream. +** + +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + + FILE* TheFile; + char* StringOne = "FooBar"; + int ret; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a file with read/write access */ + + TheFile = fopen("TestFile", "w+"); + + if(TheFile == NULL) + { + Fail("ERROR: fopen failed to open the file 'TestFile' in read/write " + "mode.\n"); + } + + /* Then close that file we just opened */ + + if(fclose(TheFile) != 0) + { + Fail("ERROR: fclose failed to close the file.\n"); + } + + /* Check that calling fputs on this closed file stream fails. */ + + if((ret = fputs(StringOne, TheFile)) >= 0) + { + Fail("ERROR: fputs should have failed to write to a closed " + "file stream, but it didn't return a negative value.\n"); + } + + if(ret != EOF) + { + Fail("ERROR: fputs should have returned EOF on an error, but instead " + "returned %d.\n",ret); + } + + /* Open a file as Readonly */ + + TheFile = fopen("TestFile", "r"); + + if(TheFile == NULL) + { + Fail("ERROR: fopen failed to open the file 'TestFile' in read/write " + "mode.\n"); + } + + /* Check that fputs fails when trying to write to a read-only stream */ + + if((ret = fputs(StringOne, TheFile)) >= 0) + { + Fail("ERROR: fputs should have failed to write to a read-only " + "file stream, but it didn't return a negative value.\n"); + } + + if(ret != EOF) + { + Fail("ERROR: fputs should have returned EOF when writing to a " + "read-only filestream, but instead " + "returned %d.\n",ret); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test2/testinfo.dat new file mode 100644 index 0000000..0e2abbd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fputs/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fputs +Name = Check that fputs returns EOF when called on closed/readonly streams +TYPE = DEFAULT +EXE1 = test2 +Description += Check to see that fputs fails and returns EOF when called on += a closed file stream and a read-only file stream. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/CMakeLists.txt new file mode 100644 index 0000000..a4e54c4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fread_test1 + ${SOURCES} +) + +add_dependencies(paltest_fread_test1 coreclrpal) + +target_link_libraries(paltest_fread_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/test1.cpp new file mode 100644 index 0000000..b706b2e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/test1.cpp @@ -0,0 +1,135 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the fread function. +** Open a file in READ mode, and then try to read all +** the characters, more than all the characters, +** 0 characters and 0 sized characters and check that +** the return values are correct. +** +** Depends: +** fopen +** fseek +** fclose +** +** +**===================================================================*/ + +/* Note: testfile should exist in the directory with 15 characters + in it ... something got lost if it isn't here. +*/ + +/* Note: Under win32, fread() crashes when passed NULL. The test to ensure that + it returns 0 has been removed to reflect this. +*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + const char filename[] = "testfile"; + char buffer[128]; + FILE * fp = NULL; + int result; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Open a file in READ mode */ + + if((fp = fopen(filename, "r")) == NULL) + { + Fail("Unable to open a file for reading. Is the file " + "in the directory? It should be."); + } + + /* Read 15 characters from the file. The file has exactly this many + in it. + */ + if((result = fread(buffer,1,15,fp)) == 0) + { + Fail("ERROR: Zero characters read from the file. It should have " + "15 characters in it."); + } + + if(result != 15) + { + Fail("ERROR: The fread function should have returned that it read " + "in 15 characters from the file. But it indicates having " + "read %i characters.",result); + } + + /* Go back to the start of the file */ + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + /* Attempt to read 17 characters, the return should still be 15 */ + + if((result = fread(buffer,1,17,fp)) == 0) + { + Fail("ERROR: Zero characters read from the file. It should have " + "15 characters in it. Though, it attempted to read 17."); + } + + if(result != 15) + { + Fail("ERROR: The fread function should have returned that it read " + "in 15 characters from the file. " + "But it indicates having read %i characters.",result); + } + + /* Back to the start of the file */ + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + /* Read 0 characters and ensure the function returns 0 */ + + if((result = fread(buffer,1,0,fp)) != 0) + { + Fail("ERROR: The return value should be 0, as we attempted to " + "read 0 characters."); + } + + /* Read characters of 0 size and ensure the return value is 0 */ + + if((result = fread(buffer,0,5,fp)) != 0) + { + Fail("ERROR: The return value should be 0, as we attempted to " + "read 0 sized data."); + } + + /* Close the file */ + + if(fclose(fp)) + { + Fail("ERROR: fclose failed. Test depends on it."); + } + + /* Read 5 characters of 1 size from a closed file pointer + and ensure the return value is 0 + */ + + if((result = fread(buffer,1,5,fp)) != 0) + { + Fail("ERROR: The return value should be 0, as we attempted to " + "read data from a closed file pointer."); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/testfile b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/testfile new file mode 100644 index 0000000..273c1a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/testfile @@ -0,0 +1 @@ +This is a test. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/testinfo.dat new file mode 100644 index 0000000..0f8b860 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fread +Name = Positive Test for fread +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the fread function. += Open a file in READ mode, and then try to read all the characters, += more than all the characters, 0 characters and 0 sized characters and += check that the return values are correct. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/CMakeLists.txt new file mode 100644 index 0000000..01fd7c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_fread_test2 + ${SOURCES} +) + +add_dependencies(paltest_fread_test2 coreclrpal) + +target_link_libraries(paltest_fread_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/test2.cpp new file mode 100644 index 0000000..d7262a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/test2.cpp @@ -0,0 +1,143 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Tests the PAL implementation of the fread function. +** Open a file in READ mode, and then try to read all +** the characters, more than all the characters, +** 0 characters and 0 sized characters and check that +** the strings read in are correct. +** +** Depends: +** fopen +** fseek +** fclose +** strcmp +** memset +** +** +**===================================================================*/ + +/* Note: testfile should exist in the directory with 15 characters + in it ... something got lost if it isn't here. +*/ + +/* Note: The behaviour in win32 is to crash if a NULL pointer is passed to + fread, so the test to check that it returns 0 has been removed. +*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + const char filename[] = "testfile"; + char buffer[128]; + FILE * fp = NULL; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Open a file in READ mode */ + + if((fp = fopen(filename, "r")) == NULL) + { + Fail("Unable to open a file for reading. Is the file " + "in the directory? It should be."); + } + + /* Read 15 characters from the file. The file has exactly this many + in it. Then check to see that the data read in is correct. + Note: The 'testfile' should have "This is a test." written in it. + */ + memset(buffer,'\0',128); + fread(buffer,1,15,fp); + + if(strcmp(buffer,"This is a test.") != 0) + { + Fail("ERROR: The data read in should have been " + "'This is a test.' but, the buffer contains '%s'.", + buffer); + } + + /* Go back to the start of the file */ + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + /* Attempt to read 17 characters. The same 15 characters should + be in the buffer. + */ + + memset(buffer,'\0',128); + fread(buffer,1,17,fp); + + if(strcmp(buffer,"This is a test.") != 0) + { + Fail("ERROR: The data read in should have been " + "'This is a test.' but, the buffer contains '%s'.", + buffer); + } + + /* Back to the start of the file */ + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + /* Read 0 characters and ensure the buffer is empty */ + + memset(buffer,'\0',128); + fread(buffer,1,0,fp); + + if(strcmp(buffer,"\0") != 0) + { + Fail("ERROR: The data read in should have been " + "NULL but, the buffer contains '%s'.", + buffer); + } + + /* Read characters of 0 size and ensure the buffer is empty */ + + memset(buffer,'\0',128); + fread(buffer,0,5,fp); + + if(strcmp(buffer,"\0") != 0) + { + Fail("ERROR: The data read in should have been " + "NULL but, the buffer contains '%s'.", + buffer); + } + + /* Close the file */ + + if(fclose(fp)) + { + Fail("ERROR: fclose failed. Test depends on it."); + } + + /* Read 5 characters of 1 size from a closed file pointer + and ensure the buffer is empty + */ + memset(buffer,'\0',128); + fread(buffer,1,5,fp); + if(strcmp(buffer,"\0") != 0) + { + Fail("ERROR: The data read in should have been " + "NULL but, the buffer contains '%s'.", + buffer); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/testfile b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/testfile new file mode 100644 index 0000000..273c1a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/testfile @@ -0,0 +1 @@ +This is a test. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/testinfo.dat new file mode 100644 index 0000000..a73c0ec --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test2/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fread +Name = Positive Test for fread +TYPE = DEFAULT +EXE1 = test2 +Description += Tests the PAL implementation of the fread function. += Open a file in READ mode, and then try to read all += the characters, more than all the characters, += 0 characters and 0 sized characters and check that += the strings read in are correct. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/CMakeLists.txt new file mode 100644 index 0000000..07615a3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_fread_test3 + ${SOURCES} +) + +add_dependencies(paltest_fread_test3 coreclrpal) + +target_link_libraries(paltest_fread_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/test3.cpp new file mode 100644 index 0000000..8c79bee --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/test3.cpp @@ -0,0 +1,131 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Tests the PAL implementation of the fread function. +** Open a file in READ mode, then try to read from the file with +** different 'size' params. Check to ensure the return values and +** the text in the buffer is correct. +** +** Depends: +** fopen +** fseek +** strcmp +** memset +** +** +**===================================================================*/ + +/* Note: testfile should exist in the directory with 15 characters + in it ... something got lost if it isn't here. +*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + const char filename[] = "testfile"; + char buffer[128]; + FILE * fp = NULL; + int result; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Open a file in READ mode */ + + if((fp = fopen(filename, "r")) == NULL) + { + Fail("Unable to open a file for reading. Is the file " + "in the directory? It should be."); + } + + memset(buffer,'x',128); + + /* Put the null one character past the end of the text that was read + in, to ensure that it wasn't reading in 0 + */ + + buffer[16] = '\0'; + + /* Attempt to read in 5 bytes at a time. This should return 3 and + contain the full string in the buffer. + */ + + if((result = fread(buffer,5,3,fp)) != 3) + { + Fail("ERROR: Attempted to read in data of size 5. The file has " + "15 bytes in it so 3 items should have been read. But the value " + "returned was %d.",result); + } + + if(strcmp(buffer, "This is a test.x") != 0) + { + Fail("ERROR: The buffer should have contained the text " + "'This is a test.x' but instead contained '%s'.",buffer); + } + + memset(buffer,'x',128); + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + buffer[16] = '\0'; + + /* Attempt to read in 6 bytes at a time. The return should be 2. The + full string should still be in the buffer. + */ + + if((result = fread(buffer,6,3,fp)) != 2) + { + Fail("ERROR: Attempted to read in data of size 6. The file has " + "15 bytes in it, so 2 items should have been read. But the " + "value returned was %d.",result); + } + + if(strcmp(buffer, "This is a test.x") != 0) + { + Fail("ERROR: The buffer should have contained the text " + "'This is a test.x' but instead contained '%s'.",buffer); + } + + memset(buffer,'x',128); + + buffer[7] = '\0'; + + if(fseek(fp, 0, SEEK_SET)) + { + Fail("ERROR: fseek failed, and this test depends on it."); + } + + /* Attempt to read in 6 bytes at a time but only one item max. + The return should be 1. The first 6 characters should be in the + buffer. + */ + + if((result = fread(buffer,6,1,fp)) != 1) + { + Fail("ERROR: Attempted to read in data of size 6 with a max count " + "of 1. Thus, one item should have been read, but the " + "value returned was %d.",result); + } + + if(strcmp(buffer, "This ix") != 0) + { + Fail("ERROR: The buffer should have contained the text " + "'This ix.' but instead contained '%s'.",buffer); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/testfile b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/testfile new file mode 100644 index 0000000..273c1a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/testfile @@ -0,0 +1 @@ +This is a test. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/testinfo.dat new file mode 100644 index 0000000..95bc30e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fread/test3/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fread +Name = Positive Test for fread +TYPE = DEFAULT +EXE1 = test3 +Description += Tests the PAL implementation of the fread function. += Open a file in READ mode, then try to read from the file with += different 'size' params. Check to ensure the return values and += the text in the buffer is correct diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/test1/CMakeLists.txt new file mode 100644 index 0000000..c8c5aa9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_free_test1 + ${SOURCES} +) + +add_dependencies(paltest_free_test1 coreclrpal) + +target_link_libraries(paltest_free_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/test1/test1.cpp new file mode 100644 index 0000000..4ff8dfb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/test1/test1.cpp @@ -0,0 +1,62 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Repeatedly allocates and frees a chunk of memory, to verify +** that free is really returning memory to the heap +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + + char *testA; + + long i; + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* check that free really returns memory to the heap. */ + for(i=1; i<1000000; i++) + { + testA = (char *)malloc(1000*sizeof(char)); + if (testA==NULL) + { + Fail("Either free is failing to return memory to the heap, or" + " the system is running out of memory for some other " + "reason.\n"); + } + free(testA); + } + + free(NULL); /*should do nothing*/ + PAL_Terminate(); + return PASS; +} + + + + + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/test1/testinfo.dat new file mode 100644 index 0000000..5bf400c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/free/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = free +Name = Positive Test for free +TYPE = DEFAULT +EXE1 = test1 +Description += Repeatedly allocates and frees a chunk of memory, to verify that free += is really returning memory to the heap + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/test1/CMakeLists.txt new file mode 100644 index 0000000..b175d42 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fseek_test1 + ${SOURCES} +) + +add_dependencies(paltest_fseek_test1 coreclrpal) + +target_link_libraries(paltest_fseek_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/test1/test1.cpp new file mode 100644 index 0000000..dd1e87e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/test1/test1.cpp @@ -0,0 +1,193 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Call fseek to move a file pointer to the start of a file, +** a position offset from the start, a position offset from the +** current position, and a position offset from the end of the +** file. Check that the file pointer is at the correct position +** after each seek. +** +** +**==========================================================================*/ + +#include + +const char filename[] = "testfile.txt"; + +static BOOL Cleanup(HANDLE hFile) +{ + BOOL result= TRUE; + + if (fclose((PAL_FILE*)hFile)) + { + Trace("fseek: ERROR -> Unable to close file \"%s\".\n", + filename); + result= FALSE; + } + if (!DeleteFileA(filename)) + { + result= FALSE; + Trace("fseek: ERROR -> Unable to delete file \"%s\". ", + "GetLastError returned %u.\n", + filename, + GetLastError()); + } + return result; +} + +int __cdecl main(int argc, char **argv) +{ + char outBuf[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + char inBuf[20]; + FILE * fp; + int size = ( sizeof(outBuf)/sizeof(char) ) - 1; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /*create the file*/ + fp = fopen(filename, "w"); + if (fp == NULL) + { + Fail("Unable to open a file for write.\n"); + } + if(fprintf(fp, outBuf) != size) + { + Trace("Unable to write to %s.\n", filename); + Cleanup(fp); + Fail(""); + } + + if (fclose(fp) != 0) + { + Trace("Unable to close newly written file.\n"); + if (!DeleteFileA(filename)) + { + Trace("fseek: ERROR -> Unable to delete file \"%s\". ", + "GetLastError returned %u.\n", + filename, + GetLastError()); + } + Fail(""); + } + + fp = fopen(filename, "r"); + if (fp == NULL) + { + if (!DeleteFileA(filename)) + { + Trace("_putw: ERROR -> Unable to delete file \"%s\". ", + "GetLastError returned %u.\n", + filename, + GetLastError()); + } + Fail("Unable to open a file for read.\n"); + } + + /*seek to the start*/ + if (fseek(fp, 0, SEEK_SET) != 0) + { + Cleanup(fp); + Fail("fseek failed when seeking the start of a file.\n"); + } + if (fgets(inBuf, 11, fp) != inBuf) + { + Cleanup(fp); + Fail("Unable to read from file after using fseek to move to the start.\n"); + } + if (strncmp(inBuf, outBuf, 10) != 0) + { + Cleanup(fp); + Fail("fseek was asked to seek the start of a file," + "but didn't get there.\n"); + } + + /*Seek with an offset from the start*/ + + if (fseek(fp, 10, SEEK_SET) != 0) + { + Cleanup(fp); + Fail("fseek failed when called with SEEK_SET and a positive offset.\n"); + } + + if (fgets(inBuf, 6, fp) != inBuf) + { + Cleanup(fp); + Fail("fgets failed after feek was called with SEEK_SET" + "and a positive offset.\n"); + } + + + if (strncmp(inBuf, "ABCDE", 5) != 0) + { + Cleanup(fp); + Fail("fseek did not move to the correct position when passed SEEK_SET" + " and a positive offset.\n"); + } + + /*now move backwards and read the same string*/ + if (fseek(fp, -5, SEEK_CUR) != 0) + { + Cleanup(fp); + Fail("fseek failed when passed SEEK_CUR and a negative offset.\n"); + } + + if (fgets(inBuf, 6, fp) != inBuf) + { + Cleanup(fp); + Fail("fgets failed after fseek was called with SEEK_CUR and a " + "negative offset.\n"); + } + + if (strncmp(inBuf, "ABCDE", 5) != 0) + { + Cleanup(fp); + Fail("fseek did not move to the correct position when called with" + " SEEK_CUR and a negative offset.\n"); + } + + /*Try seeking relative to the end of the file.*/ + if (fseek(fp, -10, SEEK_END) != 0) + { + Cleanup(fp); + Fail("fseek failed when called with SEEK_END and a negative" + " offset.\n"); + } + if (fgets(inBuf, 2, fp) != inBuf) + { + Cleanup(fp); + Fail("fgets failed after fseek was called with SEEK_END and a " + "negative offset\n"); + } + + if (strncmp(inBuf, "Q", 1) != 0) + { + Cleanup(fp); + Fail("fseek did not move to the correct position when called with " + "SEEK_END and a negative offset.\n"); + } + + + /*close the file*/ + if(!Cleanup(fp)) + { + Fail(""); + } + + PAL_Terminate(); + return PASS; +} + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/test1/testinfo.dat new file mode 100644 index 0000000..788f8d4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fseek/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fseek +Name = Positive Test for fseek +TYPE = DEFAULT +EXE1 = test1 +Description += Call seek to move a file pointer to the start of a file, a position += offset from the start, a position offset from the current position, and += a position offset from the end of the file. Check that the file += pointer is at the correct position after each seek. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/CMakeLists.txt new file mode 100644 index 0000000..4167741 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + ftell.cpp +) + +add_executable(paltest_ftell_test1 + ${SOURCES} +) + +add_dependencies(paltest_ftell_test1 coreclrpal) + +target_link_libraries(paltest_ftell_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/ftell.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/ftell.cpp new file mode 100644 index 0000000..66e0854 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/ftell.cpp @@ -0,0 +1,145 @@ +// 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. + +/*===================================================================== +** +** Source: ftell.c (test 1) +** +** Purpose: Tests the PAL implementation of the ftell function. +** +** +**===================================================================*/ + +#include + +FILE* pFile; +struct TESTS +{ + long lDist; + int nFrom; + long lPosition; +}; + + +/************************************************* +** +** Validate +** +** Purpose: +** Tests whether the move was successful. If +** it passes, it returns TRUE. If it fails +** it outputs some error messages and returns +** FALSE. +** +*************************************************/ +BOOL Validate(long lExpected) +{ + long lPos = -2; + + if (((lPos = ftell(pFile)) == -1) || (lPos != lExpected)) + { + Trace("ftell: ERROR -> ftell returned %ld when expecting %ld.\n", + lPos, + lExpected); + if (fclose(pFile) != 0) + { + Trace("ftell: ERROR -> fclose failed to close the file.\n"); + } + return FALSE; + } + return TRUE; +} + + +/************************************************* +** +** MovePointer +** +** Purpose: +** Accepts the distance to move and the +** distance and calls fseek to move the file +** pointer. If the fseek fails, error messages +** are displayed and FALSE is returned. TRUE +** is returned on a successful fseek. +** +*************************************************/ +BOOL MovePointer(long lDist, int nFrom) +{ + /* move the file pointer*/ + if (fseek(pFile, lDist, nFrom) != 0) + { + Trace("ftell: ERROR -> fseek failed to move the file pointer " + "%l characters.\n", + lDist); + if (fclose(pFile) != 0) + { + Trace("ftell: ERROR -> fclose failed to close the file.\n"); + } + return FALSE; + } + return TRUE; +} + + + +int __cdecl main(int argc, char *argv[]) +{ + const char szFileName[] = {"testfile.txt"}; + long lPos = -1; + int i; + char szTempBuffer[256]; + struct TESTS testCase[] = + { + {0, SEEK_SET, 0}, + {10, SEEK_CUR, 10}, + {-5, SEEK_CUR, 5}, + {-2, SEEK_END, 50} + }; + + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + memset(szTempBuffer, 0, 256); + + + /* open the test file */ + pFile = fopen(szFileName, "r"); + if (pFile == NULL) + { + Fail("ftell: ERROR -> fopen failed to open the file \"%s\".\n"); + } + + /* loop through the test cases */ + for (i = 0; i < (sizeof(testCase)/sizeof(struct TESTS)); i++) + { + if (MovePointer(testCase[i].lDist, testCase[i].nFrom) != TRUE) + { + Fail(""); + } + else if (Validate(testCase[i].lPosition) != TRUE) + { + Fail(""); + } + } + + if (fclose(pFile) != 0) + { + Fail("ftell: ERROR -> fclose failed to close the file.\n"); + } + + /* lets just see if we can find out where we are in a closed stream... */ + if ((lPos = ftell(pFile)) != -1) + { + Fail("ftell: ERROR -> ftell returned a valid position (%ld) on a " + "closed file handle\n", + lPos); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/testfile.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/testfile.txt new file mode 100644 index 0000000..dd0fe15 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/testfile.txt @@ -0,0 +1 @@ +The quick brown fox jumped over the lazy dog's back. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/testinfo.dat new file mode 100644 index 0000000..c17ec9a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ftell/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = c_runtime +Function = ftell +Name = test for ftell (test 1) +Type = DEFAULT +EXE1 = ftell +Description += Use fseek and a static list of distances to move, direction += to move and expected results to test the ftell function. A typical += test will move the file pointer with fseek then call ftell. The += results from ftell will then be compared to the expected result to += determine whether the test passed or failed. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/CMakeLists.txt new file mode 100644 index 0000000..256753a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/CMakeLists.txt @@ -0,0 +1,20 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/fwprintf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/fwprintf.h new file mode 100644 index 0000000..eed0e76 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/fwprintf.h @@ -0,0 +1,453 @@ +// 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. + +/*============================================================================ +** +** Source: fwprintf.h +** +** Purpose: Containts common testing functions for fwprintf +** +** +**==========================================================================*/ + +#ifndef __fwprintf_H__ +#define __fwprintf_H__ + +void DoStrTest(const WCHAR *formatstr, char* param, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + if ((fwprintf(fp, formatstr, param)) < 0) + { + Fail("ERROR: fwprintf failed\n"); + } + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert string \"%\" into \"%S\"\n" + "Expected \"%s\" got \"%s\".\n", + param, formatstr, checkstr, buf); + } + fclose(fp); +} + +void DoWStrTest(const WCHAR *formatstr, WCHAR* param, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + if ((fwprintf(fp, formatstr, param)) < 0) + { + Fail("ERROR: fwprintf failed\n"); + } + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%S\"\n" + "Expected \"%s\" got \"%s\".\n", + convertC(param), formatstr, checkstr, buf); + } + fclose(fp); +} + + +void DoPointerTest(const WCHAR *formatstr, void* param, char* paramstr, + const char *checkstr1, const char *checkstr2) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((fwprintf(fp, formatstr, param)) < 0) + { + Fail("ERROR: fwprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0 ) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\" or \"%s\" got \"%s\".\n", + paramstr, formatstr, checkstr1, checkstr2, buf); + } + + if ((fclose( fp )) != 0) + { + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + } +} + + + +void DoCountTest(const WCHAR *formatstr, int param, const char *checkstr) +{ + FILE *fp; + char buf[512] = { 0 }; + int n = -1; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((fwprintf(fp, formatstr, &n)) < 0) + { + Fail("ERROR: fwprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, sizeof(buf), fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } + + if ((fclose( fp )) != 0) + { + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + } +} + +void DoShortCountTest(const WCHAR *formatstr, int param, const char *checkstr) +{ + FILE *fp; + char buf[512] = { 0 }; + short int n = -1; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((fwprintf(fp, formatstr, &n)) < 0) + { + Fail("ERROR: fwprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } + + if ((fclose( fp )) != 0) + { + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + } +} + + +void DoCharTest(const WCHAR *formatstr, char param, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + if ((fwprintf(fp, formatstr, param)) < 0) + { + Fail("ERROR: fwprintf failed\n"); + } + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert char \'%c\' (%d) into \"%S\"\n" + "Expected \"%s\" got \"%s\".\n", + param, param, formatstr, checkstr, buf); + } + fclose(fp); +} + +void DoWCharTest(const WCHAR *formatstr, WCHAR param, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + if ((fwprintf(fp, formatstr, param)) < 0) + { + Fail("ERROR: fwprintf failed\n"); + } + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%S\"\n" + "Expected \"%s\" got \"%s\".\n", + (char)param, param, formatstr, checkstr, buf); + } + fclose(fp); +} + +void DoNumTest(const WCHAR *formatstr, int value, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + if ((fwprintf(fp, formatstr, value)) < 0) + { + Fail("ERROR: fwprintf failed\n"); + } + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert %#x into \"%S\"\n" + "Expected \"%s\" got \"%s\".\n", + value, formatstr, checkstr, buf); + } + fclose(fp); +} + +void DoI64Test(const WCHAR *formatstr, INT64 value, char *valuestr, const char *checkstr1, + const char *checkstr2) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + if ((fwprintf(fp, formatstr, value)) < 0) + { + Fail("ERROR: fwprintf failed\n"); + } + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%S\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + valuestr, formatstr, checkstr1, checkstr2, buf); + } + fclose(fp); +} + +void DoDoubleTest(const WCHAR *formatstr, double value, const char *checkstr1, + const char *checkstr2) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((fwprintf(fp, formatstr, value)) < 0) + { + Fail("ERROR: fwprintf failed\n"); + } + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%S\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + value, formatstr, checkstr1, checkstr2, buf); + } + fclose(fp); +} + + +void DoArgumentPrecTest(const WCHAR *formatstr, int precision, void *param, + char *paramstr, const char *checkstr1, const char *checkstr2) +{ + FILE *fp; + char buf[256]; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((fwprintf(fp, formatstr, precision, param)) < 0) + { + Fail("ERROR: fwprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", paramstr, formatstr, + precision, checkstr1, checkstr2, buf); + } + + + if ((fclose( fp )) != 0) + { + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + } + +} + +void DoArgumentPrecDoubleTest(const WCHAR *formatstr, int precision, double param, + const char *checkstr1, const char *checkstr2) +{ + FILE *fp; + char buf[256]; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((fwprintf(fp, formatstr, precision, param)) < 0) + { + Fail("ERROR: fwprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fseek failed\n"); + } + + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", param, formatstr, + precision, checkstr1, checkstr2, buf); + } + + if ((fclose( fp )) != 0) + { + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + } + +} + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test1/CMakeLists.txt new file mode 100644 index 0000000..b337d8a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fwprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test1 coreclrpal) + +target_link_libraries(paltest_fwprintf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test1/test1.cpp new file mode 100644 index 0000000..8a171db --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test1/test1.cpp @@ -0,0 +1,71 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: A single, basic, test case with no formatting. +** Test modeled after the sprintf series. +** + +** +**==========================================================================*/ + +#include + +/* + * Depends on memcmp, strlen, fopen, fgets, fseek and fclose. + */ + +int __cdecl main(int argc, char *argv[]) +{ + FILE *fp; + char testfile[] = "testfile.txt"; + + WCHAR *outstr; + char checkstr[] = "hello world"; + char buf[256]; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + outstr = convert(checkstr); + if ((fp = fopen(testfile, "w+")) == NULL) + { + Fail("ERROR: fopen failed to create \"%s\"\n", testfile); + } + + if ((fwprintf(fp, outstr)) < 0) + { + Fail("ERROR: fwprintf failed to print to \"%s\"\n", testfile); + } + + if ((fseek( fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: Fseek failed to set pointer to beginning of file\n" ); + } + + + if ((fgets( buf, 100, fp )) == NULL) + { + Fail("ERROR: fgets failed\n"); + } + + if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0) + { + Fail("ERROR: expected %s, got %s\n", checkstr, buf); + } + + + if ((fclose( fp )) != 0) + { + Fail("ERROR: fclose failed to close \"%s\"\n", testfile); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test1/testinfo.dat new file mode 100644 index 0000000..3bef5c6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test1 +Description += A single, basic, test case with no formatting. += Test modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test10/CMakeLists.txt new file mode 100644 index 0000000..a17b964 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_fwprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test10 coreclrpal) + +target_link_libraries(paltest_fwprintf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test10/test10.cpp new file mode 100644 index 0000000..3aa2c45 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test10/test10.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test10.c +** +** Purpose: Tests the octal specifier (%o). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %o"), pos, "foo 52"); + DoNumTest(convert("foo %lo"), 0xFFFF, "foo 177777"); + DoNumTest(convert("foo %ho"), 0xFFFF, "foo 177777"); + DoNumTest(convert("foo %Lo"), pos, "foo 52"); + DoI64Test(convert("foo %I64o"), l, "42", "foo 52", "foo 52"); + DoNumTest(convert("foo %3o"), pos, "foo 52"); + DoNumTest(convert("foo %-3o"), pos, "foo 52 "); + DoNumTest(convert("foo %.1o"), pos, "foo 52"); + DoNumTest(convert("foo %.3o"), pos, "foo 052"); + DoNumTest(convert("foo %03o"), pos, "foo 052"); + DoNumTest(convert("foo %#o"), pos, "foo 052"); + DoNumTest(convert("foo %+o"), pos, "foo 52"); + DoNumTest(convert("foo % o"), pos, "foo 52"); + DoNumTest(convert("foo %+o"), neg, "foo 37777777726"); + DoNumTest(convert("foo % o"), neg, "foo 37777777726"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test10/testinfo.dat new file mode 100644 index 0000000..17902cb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test10/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test10 +Description += Tests the octal specifier (%o). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test11/CMakeLists.txt new file mode 100644 index 0000000..9ba381f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_fwprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test11 coreclrpal) + +target_link_libraries(paltest_fwprintf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test11/test11.cpp new file mode 100644 index 0000000..5867cd6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test11/test11.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test11.c +** +** Purpose: Test the unsigned int specifier (%u). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %u"), pos, "foo 42"); + DoNumTest(convert("foo %lu"), 0xFFFF, "foo 65535"); + DoNumTest(convert("foo %hu"), 0xFFFF, "foo 65535"); + DoNumTest(convert("foo %Lu"), pos, "foo 42"); + DoI64Test(convert("foo %I64u"), l, "42", "foo 42", "foo 42"); + DoNumTest(convert("foo %3u"), pos, "foo 42"); + DoNumTest(convert("foo %-3u"), pos, "foo 42 "); + DoNumTest(convert("foo %.1u"), pos, "foo 42"); + DoNumTest(convert("foo %.3u"), pos, "foo 042"); + DoNumTest(convert("foo %03u"), pos, "foo 042"); + DoNumTest(convert("foo %#u"), pos, "foo 42"); + DoNumTest(convert("foo %+u"), pos, "foo 42"); + DoNumTest(convert("foo % u"), pos, "foo 42"); + DoNumTest(convert("foo %+u"), neg, "foo 4294967254"); + DoNumTest(convert("foo % u"), neg, "foo 4294967254"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test11/testinfo.dat new file mode 100644 index 0000000..beda0cc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test11/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test11 +Description += Test the unsigned int specifier (%u). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test12/CMakeLists.txt new file mode 100644 index 0000000..da0f985 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_fwprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test12 coreclrpal) + +target_link_libraries(paltest_fwprintf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test12/test12.cpp new file mode 100644 index 0000000..48a6123 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test12/test12.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Tests the (lowercase) hexadecimal specifier (%x). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %x"), pos, "foo 1234ab"); + DoNumTest(convert("foo %lx"), pos, "foo 1234ab"); + DoNumTest(convert("foo %hx"), pos, "foo 34ab"); + DoNumTest(convert("foo %Lx"), pos, "foo 1234ab"); + DoI64Test(convert("foo %I64x"), l, "0x1234567887654321", + "foo 1234567887654321", "foo 0x1234567887654321"); + DoNumTest(convert("foo %7x"), pos, "foo 1234ab"); + DoNumTest(convert("foo %-7x"), pos, "foo 1234ab "); + DoNumTest(convert("foo %.1x"), pos, "foo 1234ab"); + DoNumTest(convert("foo %.7x"), pos, "foo 01234ab"); + DoNumTest(convert("foo %07x"), pos, "foo 01234ab"); + DoNumTest(convert("foo %#x"), pos, "foo 0x1234ab"); + DoNumTest(convert("foo %+x"), pos, "foo 1234ab"); + DoNumTest(convert("foo % x"), pos, "foo 1234ab"); + DoNumTest(convert("foo %+x"), neg, "foo ffffffd6"); + DoNumTest(convert("foo % x"), neg, "foo ffffffd6"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test12/testinfo.dat new file mode 100644 index 0000000..3d0bf4c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test12/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test12 +Description += Tests the (lowercase) hexadecimal specifier (%x). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test13/CMakeLists.txt new file mode 100644 index 0000000..08c287a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_fwprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test13 coreclrpal) + +target_link_libraries(paltest_fwprintf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test13/test13.cpp new file mode 100644 index 0000000..6eabec6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test13/test13.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================================ +** +** Source: test13.c +** +** Purpose: Tests the (uppercase) hexadecimal specifier (%X). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234AB; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %X"), pos, "foo 1234AB"); + DoNumTest(convert("foo %lX"), pos, "foo 1234AB"); + DoNumTest(convert("foo %hX"), pos, "foo 34AB"); + DoNumTest(convert("foo %LX"), pos, "foo 1234AB"); + DoI64Test(convert("foo %I64X"), l, "0x1234567887654321", + "foo 1234567887654321", "foo 0x1234567887654321"); + DoNumTest(convert("foo %7X"), pos, "foo 1234AB"); + DoNumTest(convert("foo %-7X"), pos, "foo 1234AB "); + DoNumTest(convert("foo %.1X"), pos, "foo 1234AB"); + DoNumTest(convert("foo %.7X"), pos, "foo 01234AB"); + DoNumTest(convert("foo %07X"), pos, "foo 01234AB"); + DoNumTest(convert("foo %#X"), pos, "foo 0X1234AB"); + DoNumTest(convert("foo %+X"), pos, "foo 1234AB"); + DoNumTest(convert("foo % X"), pos, "foo 1234AB"); + DoNumTest(convert("foo %+X"), neg, "foo FFFFFFD6"); + DoNumTest(convert("foo % X"), neg, "foo FFFFFFD6"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test13/testinfo.dat new file mode 100644 index 0000000..c3222e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test13/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test13 +Description += Tests the (uppercase) hexadecimal specifier (%X). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test14/CMakeLists.txt new file mode 100644 index 0000000..dacbfea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_fwprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test14 coreclrpal) + +target_link_libraries(paltest_fwprintf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test14/test14.cpp new file mode 100644 index 0000000..001cf72 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test14/test14.cpp @@ -0,0 +1,66 @@ +// 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. + +/*============================================================================ +** +** Source: test14.c +** +** Purpose: Tests the lowercase exponential +** notation double specifier (%e). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %e"), val, "foo 2.560000e+002", + "foo 2.560000e+02"); + DoDoubleTest(convert("foo %le"), val, "foo 2.560000e+002", + "foo 2.560000e+02"); + DoDoubleTest(convert("foo %he"), val, "foo 2.560000e+002", + "foo 2.560000e+02"); + DoDoubleTest(convert("foo %Le"), val, "foo 2.560000e+002", + "foo 2.560000e+02"); + DoDoubleTest(convert("foo %I64e"), val, "foo 2.560000e+002", + "foo 2.560000e+02"); + DoDoubleTest(convert("foo %14e"), val, "foo 2.560000e+002", + "foo 2.560000e+02"); + DoDoubleTest(convert("foo %-14e"), val, "foo 2.560000e+002 ", + "foo 2.560000e+02 "); + DoDoubleTest(convert("foo %.1e"), val, "foo 2.6e+002", + "foo 2.6e+02"); + DoDoubleTest(convert("foo %.8e"), val, "foo 2.56000000e+002", + "foo 2.56000000e+02"); + DoDoubleTest(convert("foo %014e"), val, "foo 02.560000e+002", + "foo 002.560000e+02"); + DoDoubleTest(convert("foo %#e"), val, "foo 2.560000e+002", + "foo 2.560000e+02"); + DoDoubleTest(convert("foo %+e"), val, "foo +2.560000e+002", + "foo +2.560000e+02"); + DoDoubleTest(convert("foo % e"), val, "foo 2.560000e+002", + "foo 2.560000e+02"); + DoDoubleTest(convert("foo %+e"), neg, "foo -2.560000e+002", + "foo -2.560000e+02"); + DoDoubleTest(convert("foo % e"), neg, "foo -2.560000e+002", + "foo -2.560000e+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test14/testinfo.dat new file mode 100644 index 0000000..a723f76 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test14/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test14 +Description += Tests the lowercase exponential += notation double specifier (%e). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test15/CMakeLists.txt new file mode 100644 index 0000000..4d42e73 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_fwprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test15 coreclrpal) + +target_link_libraries(paltest_fwprintf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test15/test15.cpp new file mode 100644 index 0000000..9dfe82e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test15/test15.cpp @@ -0,0 +1,66 @@ +// 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. + +/*============================================================================ +** +** Source: test15.c +** +** Purpose: Tests the uppercase exponential +** notation double specifier (%E). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %E"), val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest(convert("foo %lE"), val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest(convert("foo %hE"), val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest(convert("foo %LE"), val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest(convert("foo %I64E"), val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest(convert("foo %14E"), val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest(convert("foo %-14E"), val, "foo 2.560000E+002 ", + "foo 2.560000E+02 "); + DoDoubleTest(convert("foo %.1E"), val, "foo 2.6E+002", + "foo 2.6E+02"); + DoDoubleTest(convert("foo %.8E"), val, "foo 2.56000000E+002", + "foo 2.56000000E+02"); + DoDoubleTest(convert("foo %014E"), val, "foo 02.560000E+002", + "foo 002.560000E+02"); + DoDoubleTest(convert("foo %#E"), val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest(convert("foo %+E"), val, "foo +2.560000E+002", + "foo +2.560000E+02"); + DoDoubleTest(convert("foo % E"), val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest(convert("foo %+E"), neg, "foo -2.560000E+002", + "foo -2.560000E+02"); + DoDoubleTest(convert("foo % E"), neg, "foo -2.560000E+002", + "foo -2.560000E+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test15/testinfo.dat new file mode 100644 index 0000000..246072f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test15/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test15 +Description += Tests the uppercase exponential += notation double specifier (%E). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test16/CMakeLists.txt new file mode 100644 index 0000000..2b47be5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_fwprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test16 coreclrpal) + +target_link_libraries(paltest_fwprintf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test16/test16.cpp new file mode 100644 index 0000000..1969be1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test16/test16.cpp @@ -0,0 +1,65 @@ +// 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. + +/*============================================================================ +** +** Source: test16.c +** +** Purpose: Tests the decimal notation double specifier (%f). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %f"), val, "foo 2560.001000", + "foo 2560.001000"); + DoDoubleTest(convert("foo %lf"), val, "foo 2560.001000", + "foo 2560.001000"); + DoDoubleTest(convert("foo %hf"), val, "foo 2560.001000", + "foo 2560.001000"); + DoDoubleTest(convert("foo %Lf"), val, "foo 2560.001000", + "foo 2560.001000"); + DoDoubleTest(convert("foo %I64f"), val, "foo 2560.001000", + "foo 2560.001000"); + DoDoubleTest(convert("foo %12f"), val, "foo 2560.001000", + "foo 2560.001000"); + DoDoubleTest(convert("foo %-12f"), val, "foo 2560.001000 ", + "foo 2560.001000 "); + DoDoubleTest(convert("foo %.1f"), val, "foo 2560.0", + "foo 2560.0"); + DoDoubleTest(convert("foo %.8f"), val, "foo 2560.00100000", + "foo 2560.00100000"); + DoDoubleTest(convert("foo %012f"), val, "foo 02560.001000", + "foo 02560.001000"); + DoDoubleTest(convert("foo %#f"), val, "foo 2560.001000", + "foo 2560.001000"); + DoDoubleTest(convert("foo %+f"), val, "foo +2560.001000", + "foo +2560.001000"); + DoDoubleTest(convert("foo % f"), val, "foo 2560.001000", + "foo 2560.001000"); + DoDoubleTest(convert("foo %+f"), neg, "foo -2560.001000", + "foo -2560.001000"); + DoDoubleTest(convert("foo % f"), neg, "foo -2560.001000", + "foo -2560.001000"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test16/testinfo.dat new file mode 100644 index 0000000..9e5faf9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test16/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test16 +Description += Tests the decimal notation double specifier (%f). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test17/CMakeLists.txt new file mode 100644 index 0000000..89e557b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_fwprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test17 coreclrpal) + +target_link_libraries(paltest_fwprintf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test17/test17.cpp new file mode 100644 index 0000000..66b1271 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test17/test17.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test17.c +** +** Purpose: Tests the lowercase shorthand notation double specifier (%g). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %g"), val, "foo 2560", "foo 2560"); + DoDoubleTest(convert("foo %lg"), val, "foo 2560", "foo 2560"); + DoDoubleTest(convert("foo %hg"), val, "foo 2560", "foo 2560"); + DoDoubleTest(convert("foo %Lg"), val, "foo 2560", "foo 2560"); + DoDoubleTest(convert("foo %I64g"), val, "foo 2560", "foo 2560"); + DoDoubleTest(convert("foo %5g"), val, "foo 2560", "foo 2560"); + DoDoubleTest(convert("foo %-5g"), val, "foo 2560 ", "foo 2560 "); + DoDoubleTest(convert("foo %.1g"), val, "foo 3e+003", "foo 3e+03"); + DoDoubleTest(convert("foo %.2g"), val, "foo 2.6e+003", "foo 2.6e+03"); + DoDoubleTest(convert("foo %.12g"), val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest(convert("foo %06g"), val, "foo 002560", "foo 002560"); + DoDoubleTest(convert("foo %#g"), val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest(convert("foo %+g"), val, "foo +2560", "foo +2560"); + DoDoubleTest(convert("foo % g"), val, "foo 2560", "foo 2560"); + DoDoubleTest(convert("foo %+g"), neg, "foo -2560", "foo -2560"); + DoDoubleTest(convert("foo % g"), neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test17/testinfo.dat new file mode 100644 index 0000000..fe637d7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test17/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test17 +Description += Tests the lowercase shorthand notation double specifier (%g). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test18/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test18/CMakeLists.txt new file mode 100644 index 0000000..8e677c9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test18/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test18.cpp +) + +add_executable(paltest_fwprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test18 coreclrpal) + +target_link_libraries(paltest_fwprintf_test18 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test18/test18.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test18/test18.cpp new file mode 100644 index 0000000..a33dea3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test18/test18.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test18.c +** +** Purpose: Tests the uppercase shorthand notation double specifier (%G). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %G"), val, "foo 2560", "foo 2560"); + DoDoubleTest(convert("foo %lG"), val, "foo 2560", "foo 2560"); + DoDoubleTest(convert("foo %hG"), val, "foo 2560", "foo 2560"); + DoDoubleTest(convert("foo %LG"), val, "foo 2560", "foo 2560"); + DoDoubleTest(convert("foo %I64G"), val, "foo 2560", "foo 2560"); + DoDoubleTest(convert("foo %5G"), val, "foo 2560", "foo 2560"); + DoDoubleTest(convert("foo %-5G"), val, "foo 2560 ", "foo 2560 "); + DoDoubleTest(convert("foo %.1G"), val, "foo 3E+003", "foo 3E+03"); + DoDoubleTest(convert("foo %.2G"), val, "foo 2.6E+003", "foo 2.6E+03"); + DoDoubleTest(convert("foo %.12G"), val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest(convert("foo %06G"), val, "foo 002560", "foo 002560"); + DoDoubleTest(convert("foo %#G"), val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest(convert("foo %+G"), val, "foo +2560", "foo +2560"); + DoDoubleTest(convert("foo % G"), val, "foo 2560", "foo 2560"); + DoDoubleTest(convert("foo %+G"), neg, "foo -2560", "foo -2560"); + DoDoubleTest(convert("foo % G"), neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test18/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test18/testinfo.dat new file mode 100644 index 0000000..23f6217 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test18/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test18 +Description += Tests the uppercase shorthand notation double specifier (%G). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test19/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test19/CMakeLists.txt new file mode 100644 index 0000000..0d0c420 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test19/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test19.cpp +) + +add_executable(paltest_fwprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test19 coreclrpal) + +target_link_libraries(paltest_fwprintf_test19 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.cpp new file mode 100644 index 0000000..a407c9f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.cpp @@ -0,0 +1,81 @@ +// 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. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose: Tests the variable length precision argument. +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + + + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoArgumentPrecTest(convert("%.*s"), 2, (void*)convert("bar"), "bar", "ba", "ba"); + DoArgumentPrecTest(convert("%.*S"), 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest(convert("foo %.*n"), 3, (void*)&n, "pointer to int", "foo ", + "foo "); + if (n != 4) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + 4, n); + } + + DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, "2.010e+000", + "2.010e+00"); + DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, "2.010E+000", + "2.010E+00"); + DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test19/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test19/testinfo.dat new file mode 100644 index 0000000..24aa877 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test19/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test19 +Description += Tests the variable length precision argument. += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test2/CMakeLists.txt new file mode 100644 index 0000000..308d58e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_fwprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test2 coreclrpal) + +target_link_libraries(paltest_fwprintf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test2/test2.cpp new file mode 100644 index 0000000..1e03147 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test2/test2.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Tests the string specifier (%s). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoWStrTest(convert("foo %s"), convert("bar"), "foo bar"); + DoStrTest(convert("foo %hs"), "bar", "foo bar"); + DoWStrTest(convert("foo %ls"), convert("bar"), "foo bar"); + DoWStrTest(convert("foo %ws"), convert("bar"), "foo bar"); + DoWStrTest(convert("foo %Ls"), convert("bar"), "foo bar"); + DoWStrTest(convert("foo %I64s"), convert("bar"), "foo bar"); + DoWStrTest(convert("foo %5s"), convert("bar"), "foo bar"); + DoWStrTest(convert("foo %.2s"), convert("bar"), "foo ba"); + DoWStrTest(convert("foo %5.2s"), convert("bar"), "foo ba"); + DoWStrTest(convert("foo %-5s"), convert("bar"), "foo bar "); + DoWStrTest(convert("foo %05s"), convert("bar"), "foo 00bar"); + DoWStrTest(convert("foo %s"), NULL, "foo (null)"); + DoStrTest(convert("foo %hs"), NULL, "foo (null)"); + DoWStrTest(convert("foo %ls"), NULL, "foo (null)"); + DoWStrTest(convert("foo %ws"), NULL, "foo (null)"); + DoWStrTest(convert("foo %Ls"), NULL, "foo (null)"); + DoWStrTest(convert("foo %I64s"), NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test2/testinfo.dat new file mode 100644 index 0000000..1933682 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test2 +Description += Tests the string specifier (%s). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test3/CMakeLists.txt new file mode 100644 index 0000000..ac5531e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_fwprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test3 coreclrpal) + +target_link_libraries(paltest_fwprintf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test3/test3.cpp new file mode 100644 index 0000000..ff24aa7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test3/test3.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Tests the wide string specifier (%S). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoStrTest(convert("foo %S"), "bar", "foo bar"); + DoStrTest(convert("foo %hS"), "bar", "foo bar"); + DoWStrTest(convert("foo %lS"), convert("bar"), "foo bar"); + DoWStrTest(convert("foo %wS"), convert("bar"), "foo bar"); + DoStrTest(convert("foo %LS"), "bar", "foo bar"); + DoStrTest(convert("foo %I64S"), "bar", "foo bar"); + DoStrTest(convert("foo %5S"), "bar", "foo bar"); + DoStrTest(convert("foo %.2S"), "bar", "foo ba"); + DoStrTest(convert("foo %5.2S"),"bar", "foo ba"); + DoStrTest(convert("foo %-5S"), "bar", "foo bar "); + DoStrTest(convert("foo %05S"), "bar", "foo 00bar"); + DoStrTest(convert("foo %S"), NULL, "foo (null)"); + DoStrTest(convert("foo %hS"), NULL, "foo (null)"); + DoWStrTest(convert("foo %lS"), NULL, "foo (null)"); + DoWStrTest(convert("foo %wS"), NULL, "foo (null)"); + DoStrTest(convert("foo %LS"), NULL, "foo (null)"); + DoStrTest(convert("foo %I64S"), NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test3/testinfo.dat new file mode 100644 index 0000000..fa8a0bc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test3/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test3 +Description += Tests the wide string specifier (%S). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test4/CMakeLists.txt new file mode 100644 index 0000000..61b49df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_fwprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test4 coreclrpal) + +target_link_libraries(paltest_fwprintf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test4/test4.cpp new file mode 100644 index 0000000..ba0cafb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test4/test4.cpp @@ -0,0 +1,85 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Tests the pointer specifier (%p). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest(convert("%p"), NULL, "NULL", "0000000000000000", "0x0"); + DoPointerTest(convert("%p"), ptr, "pointer to 0x123456", "0000000000123456", + "0x123456"); + DoPointerTest(convert("%17p"), ptr, "pointer to 0x123456", " 0000000000123456", + " 0x123456"); + DoPointerTest(convert("%17p"), ptr, "pointer to 0x123456", " 0000000000123456", + "0x0123456"); + DoPointerTest(convert("%-17p"), ptr, "pointer to 0x123456", "0000000000123456 ", + "0x123456 "); + DoPointerTest(convert("%+p"), ptr, "pointer to 0x123456", "0000000000123456", + "0x123456"); + DoPointerTest(convert("%#p"), ptr, "pointer to 0x123456", "0X0000000000123456", + "0x123456"); + DoPointerTest(convert("%lp"), ptr, "pointer to 0x123456", "00123456", + "0x123456"); + DoPointerTest(convert("%hp"), ptr, "pointer to 0x123456", "00003456", + "0x3456"); + DoPointerTest(convert("%Lp"), ptr, "pointer to 0x123456", "00123456", + "0x123456"); + DoI64Test(convert("%I64p"), lptr, "pointer to 0x1234567887654321", + "1234567887654321", "0x1234567887654321"); +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest(convert("%p"), NULL, "NULL", "00000000", "0x0"); + DoPointerTest(convert("%p"), ptr, "pointer to 0x123456", "00123456", + "0x123456"); + DoPointerTest(convert("%9p"), ptr, "pointer to 0x123456", " 00123456", + " 0x123456"); + DoPointerTest(convert("%09p"), ptr, "pointer to 0x123456", " 00123456", + "0x0123456"); + DoPointerTest(convert("%-9p"), ptr, "pointer to 0x123456", "00123456 ", + "0x123456 "); + DoPointerTest(convert("%+p"), ptr, "pointer to 0x123456", "00123456", + "0x123456"); + DoPointerTest(convert("%#p"), ptr, "pointer to 0x123456", "0X00123456", + "0x123456"); + DoPointerTest(convert("%lp"), ptr, "pointer to 0x123456", "00123456", + "0x123456"); + DoPointerTest(convert("%hp"), ptr, "pointer to 0x123456", "00003456", + "0x3456"); + DoPointerTest(convert("%Lp"), ptr, "pointer to 0x123456", "00123456", + "0x123456"); + DoI64Test(convert("%I64p"), lptr, "pointer to 0x1234567887654321", + "1234567887654321", "0x1234567887654321"); +#endif + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test4/testinfo.dat new file mode 100644 index 0000000..92140c2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test4/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test4 +Description += Tests the pointer specifier (%p). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test5/CMakeLists.txt new file mode 100644 index 0000000..d136abd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_fwprintf_test5 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test5 coreclrpal) + +target_link_libraries(paltest_fwprintf_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test5/test5.cpp new file mode 100644 index 0000000..9d95989 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test5/test5.cpp @@ -0,0 +1,63 @@ +// 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. + +/*============================================================================ +** +** Source: test5.c +** +** Purpose: Tests the count specifier (%n). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR *longStr; + char *longResult = + "really-long-string-that-just-keeps-going-on-and-on-and-on.." + "..................useless-filler.................................." + "..................useless-filler.................................." + "..................useless-filler.................................." + " bar"; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + longStr = + convert("really-long-string-that-just-keeps-going-on-and-on-and-on.." + "..................useless-filler.................................." + "..................useless-filler.................................." + "..................useless-filler.................................." + "%n bar"); + DoCountTest(convert("foo %n bar"), 4, "foo bar"); + DoCountTest(longStr, 257, longResult); + DoCountTest(convert("fo%n bar"), 2, "fo bar"); + DoCountTest(convert("%n foo"), 0, " foo"); + DoCountTest(convert("foo %#n bar"), 4, "foo bar"); + DoCountTest(convert("foo % n bar"), 4, "foo bar"); + DoCountTest(convert("foo %+n bar"), 4, "foo bar"); + DoCountTest(convert("foo %-n bar"), 4, "foo bar"); + DoCountTest(convert("foo %0n bar"), 4, "foo bar"); + DoShortCountTest(convert("foo %hn bar"), 4, "foo bar"); + DoCountTest(convert("foo %ln bar"), 4, "foo bar"); + DoCountTest(convert("foo %Ln bar"), 4, "foo bar"); + DoCountTest(convert("foo %I64n bar"), 4, "foo bar"); + DoCountTest(convert("foo %20.3n bar"), 4, "foo bar"); + + PAL_Terminate(); + + free(longStr); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test5/testinfo.dat new file mode 100644 index 0000000..152f563 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test5/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test5 +Description += Tests the count specifier (%n). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test6/CMakeLists.txt new file mode 100644 index 0000000..128ec07 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_fwprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test6 coreclrpal) + +target_link_libraries(paltest_fwprintf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test6/test6.cpp new file mode 100644 index 0000000..160ff52 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test6/test6.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose: Tests the char specifier (%c). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wb = (WCHAR) 'b'; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoWCharTest(convert("foo %c"), wb, "foo b"); + DoCharTest(convert("foo %hc"), 'c', "foo c"); + DoWCharTest(convert("foo %lc"), wb, "foo b"); + DoWCharTest(convert("foo %Lc"), wb, "foo b"); + DoWCharTest(convert("foo %I64c"), wb, "foo b"); + DoWCharTest(convert("foo %5c"), wb, "foo b"); + DoWCharTest(convert("foo %.0c"), wb, "foo b"); + DoWCharTest(convert("foo %-5c"), wb, "foo b "); + DoWCharTest(convert("foo %05c"), wb, "foo 0000b"); + DoWCharTest(convert("foo % c"), wb, "foo b"); + DoWCharTest(convert("foo %#c"), wb, "foo b"); + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test6/testinfo.dat new file mode 100644 index 0000000..cc968bd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test6/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test6 +Description += Tests the char specifier (%c). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test7/CMakeLists.txt new file mode 100644 index 0000000..85d45bf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_fwprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test7 coreclrpal) + +target_link_libraries(paltest_fwprintf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test7/test7.cpp new file mode 100644 index 0000000..c5515a8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test7/test7.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test7.c +** +** Purpose: Tests the wide char specifier (%C). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wb = (WCHAR) 'b'; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoCharTest(convert("foo %C"), 'c', "foo c"); + DoWCharTest(convert("foo %hc"), wb, "foo b"); + DoCharTest(convert("foo %lC"), 'c', "foo c"); + DoCharTest(convert("foo %LC"), 'c', "foo c"); + DoCharTest(convert("foo %I64C"), 'c', "foo c"); + DoCharTest(convert("foo %5C"), 'c', "foo c"); + DoCharTest(convert("foo %.0C"), 'c', "foo c"); + DoCharTest(convert("foo %-5C"), 'c', "foo c "); + DoCharTest(convert("foo %05C"), 'c', "foo 0000c"); + DoCharTest(convert("foo % C"), 'c', "foo c"); + DoCharTest(convert("foo %#C"), 'c', "foo c"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test7/testinfo.dat new file mode 100644 index 0000000..46cb35c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test7/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test7 +Description += Tests the wide char specifier (%C). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test8/CMakeLists.txt new file mode 100644 index 0000000..3d0ecc2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_fwprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test8 coreclrpal) + +target_link_libraries(paltest_fwprintf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test8/test8.cpp new file mode 100644 index 0000000..efc81a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test8/test8.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test8.c +** +** Purpose: Tests the decimal specifier (%d). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %d"), pos, "foo 42"); + DoNumTest(convert("foo %ld"), 0xFFFF, "foo 65535"); + DoNumTest(convert("foo %hd"), 0xFFFF, "foo -1"); + DoNumTest(convert("foo %Ld"), pos, "foo 42"); + DoI64Test(convert("foo %I64d"), l, "42", "foo 42", "foo 42"); + DoNumTest(convert("foo %3d"), pos, "foo 42"); + DoNumTest(convert("foo %-3d"), pos, "foo 42 "); + DoNumTest(convert("foo %.1d"), pos, "foo 42"); + DoNumTest(convert("foo %.3d"), pos, "foo 042"); + DoNumTest(convert("foo %03d"), pos, "foo 042"); + DoNumTest(convert("foo %#d"), pos, "foo 42"); + DoNumTest(convert("foo %+d"), pos, "foo +42"); + DoNumTest(convert("foo % d"), pos, "foo 42"); + DoNumTest(convert("foo %+d"), neg, "foo -42"); + DoNumTest(convert("foo % d"), neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test8/testinfo.dat new file mode 100644 index 0000000..c8ce33a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test8/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test8 +Description += Tests the decimal specifier (%d). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test9/CMakeLists.txt new file mode 100644 index 0000000..502acf3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_fwprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_fwprintf_test9 coreclrpal) + +target_link_libraries(paltest_fwprintf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test9/test9.cpp new file mode 100644 index 0000000..23db2d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test9/test9.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test9.c +** +** Purpose: Tests the integer specifier (%i). +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %i"), pos, "foo 42"); + DoNumTest(convert("foo %li"), 0xFFFF, "foo 65535"); + DoNumTest(convert("foo %hi"), 0xFFFF, "foo -1"); + DoNumTest(convert("foo %Li"), pos, "foo 42"); + DoI64Test(convert("foo %I64i"), l, "42", "foo 42", "foo 42"); + DoNumTest(convert("foo %3i"), pos, "foo 42"); + DoNumTest(convert("foo %-3i"), pos, "foo 42 "); + DoNumTest(convert("foo %.1i"), pos, "foo 42"); + DoNumTest(convert("foo %.3i"), pos, "foo 042"); + DoNumTest(convert("foo %03i"), pos, "foo 042"); + DoNumTest(convert("foo %#i"), pos, "foo 42"); + DoNumTest(convert("foo %+i"), pos, "foo +42"); + DoNumTest(convert("foo % i"), pos, "foo 42"); + DoNumTest(convert("foo %+i"), neg, "foo -42"); + DoNumTest(convert("foo % i"), neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test9/testinfo.dat new file mode 100644 index 0000000..5c2ec25 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwprintf/test9/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = fwprintf +Name = Positive Test for fwprintf +TYPE = DEFAULT +EXE1 = test9 +Description += Tests the integer specifier (%i). += This test is modeled after the sprintf series. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/test1/CMakeLists.txt new file mode 100644 index 0000000..7ed1e9a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_fwrite_test1 + ${SOURCES} +) + +add_dependencies(paltest_fwrite_test1 coreclrpal) + +target_link_libraries(paltest_fwrite_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/test1/test1.cpp new file mode 100644 index 0000000..3925228 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/test1/test1.cpp @@ -0,0 +1,104 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Write a short string to a file and check that it was written +** properly. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + const char filename[] = "testfile.tmp"; + const char outBuffer[] = "This is a test."; + char inBuffer[sizeof(outBuffer) + 10]; + int itemsExpected; + int itemsWritten; + FILE * fp = NULL; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + if((fp = fopen(filename, "w")) == NULL) + { + Fail("Unable to open a file for write.\n"); + } + + itemsExpected = sizeof(outBuffer); + itemsWritten = fwrite(outBuffer, + sizeof(outBuffer[0]), + sizeof(outBuffer), + fp); + + if (itemsWritten == 0) + { + if(fclose(fp) != 0) + { + Fail("fwrite: Error occurred during the closing of a file.\n"); + } + + Fail("fwrite() couldn't write to a stream at all\n"); + } + else if (itemsWritten != itemsExpected) + { + if(fclose(fp) != 0) + { + Fail("fwrite: Error occurred during the closing of a file.\n"); + } + + Fail("fwrite() produced errors writing to a stream.\n"); + } + + if(fclose(fp) != 0) + { + Fail("fwrite: Error occurred during the closing of a file.\n"); + } + + /* open the file to verify what was written to the file */ + if ((fp = fopen(filename, "r")) == NULL) + { + Fail("Couldn't open newly written file for read.\n"); + } + + if (fgets(inBuffer, sizeof(inBuffer), fp) == NULL) + { + if(fclose(fp) != 0) + { + Fail("fwrite: Error occurred during the closing of a file.\n"); + } + + Fail("We wrote something to a file using fwrite() and got errors" + " when we tried to read it back using fgets(). Either " + "fwrite() or fgets() is broken.\n"); + } + + if (strcmp(inBuffer, outBuffer) != 0) + { + if(fclose(fp) != 0) + { + Fail("fwrite: Error occurred during the closing of a file.\n"); + } + + Fail("fwrite() (or fgets()) is broken. The string read back from" + " the file does not match the string written.\n"); + } + + if(fclose(fp) != 0) + { + Fail("fwrite: Error occurred during the closing of a file.\n"); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/test1/testinfo.dat new file mode 100644 index 0000000..75ad9ed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/fwrite/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = fwrite +Name = Positive Test for fwrite +TYPE = DEFAULT +EXE1 = test1 +Description += Write a short string to a file and check that it was written properly. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test1/CMakeLists.txt new file mode 100644 index 0000000..70ae0e1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_getenv_test1 + ${SOURCES} +) + +add_dependencies(paltest_getenv_test1 coreclrpal) + +target_link_libraries(paltest_getenv_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test1/test1.cpp new file mode 100644 index 0000000..0fb9025 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test1/test1.cpp @@ -0,0 +1,78 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Create an environment variable and then use getenv to get +** a pointer to it. Check that the pointer is valid and that the string +** is what we expected. Also check that searching for a non-existent +** variable will cause getenv to return NULL. Also check that function +** passes when the parameter has it's casing changed (e.g upper case) +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + + const char* SetVariable = "PalTestingEnvironmentVariable=The value"; + const char* VariableName = "PalTestingEnvironmentVariable"; + const char* VariableValue = "The value"; + char* result; + + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Use _putenv to set an environment variable. This ensures that the + variable we're testing on is always present. + */ + + if(_putenv(SetVariable) == -1) + { + Fail("ERROR: _putenv failed to set an environment variable that " + "getenv will be using for testing.\n"); + } + + /* Call getenv -- ensure it doesn't return NULL and the string it returns + is the value we set above. + */ + + result = getenv(VariableName); + if(result == NULL) + { + Fail("ERROR: The result of getenv on a valid Environment Variable " + "was NULL, which indicates the environment varaible was not " + "found.\n"); + } + + if(strcmp(result, VariableValue) != 0) + { + Fail("ERROR: The value obtained by getenv() was not equal to the " + "correct value of the environment variable. The correct " + "value is '%s' and the function returned '%s'.\n", + VariableValue, + result); + } + + /* Try calling getenv on an environment variable which doesn't + exist. + */ + result = getenv("SomeEnvironmentVariableThatReallyDoesNotExist"); + + if(result != NULL) + { + Fail("ERROR: Called getenv on an environment variable which " + "doesn't exist and it returned '%s' instead of NULL.\n",result); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test1/testinfo.dat new file mode 100644 index 0000000..b9cbf71 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = getenv +Name = Test retrieval of variables correctly, and failure if they don't exist +TYPE = DEFAULT +EXE1 = test1 +Description += Create an environment variable and then use getenv to get += a pointer to it. Check that the pointer is valid and that the string += is what we expected. Also check that searching for a non-existent += variable will cause getenv to return NULL. Also check that changing += the case (upper or lower) of a variable does not effect functionality. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test2/CMakeLists.txt new file mode 100644 index 0000000..a5ebccd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_getenv_test2 + ${SOURCES} +) + +add_dependencies(paltest_getenv_test2 coreclrpal) + +target_link_libraries(paltest_getenv_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test2/test2.cpp new file mode 100644 index 0000000..26f245f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test2/test2.cpp @@ -0,0 +1,101 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Create environment variables that differ only in Case, and +** verify that the BSD operating system treats the variables +** differently. +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ +#if WIN32 + + return PASS; + +#else + + const char* FirstVariable = "PalTestingEnvironmentVariable=The value"; + const char* SecondVariable = "PALTESTINGEnvironmentVariable=Different value"; + const char* FirstVarName = "PalTestingEnvironmentVariable"; + const char* SecondVarName = "PALTESTINGEnvironmentVariable"; + const char* FirstVarValue = "The value"; + const char* SecondVarValue = "Different value"; + char* result; + + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Use _putenv to set the environment variables. This ensures that the + variables we're testing with are always present. + */ + if(_putenv(FirstVariable) != 0) + { + Fail("ERROR: _putenv failed to set an environment variable that " + "getenv will be using for testing.\n"); + } + + if(_putenv(SecondVariable) != 0) + { + Fail("ERROR: _putenv failed to set an environment variable that " + "getenv will be using for testing.\n"); + } + + + /* Call getenv -- ensure it doesn't return NULL and the string it returns + is the value we set above. Also make sure that each environment variable, + differing only by case, returns it's own value. + */ + + result = getenv(FirstVarName); + if(result == NULL) + { + Fail("ERROR: The result of getenv on a valid Environment Variable " + "was NULL, which indicates the environment varaible was not " + "found.\n"); + } + + if(strcmp(result, FirstVarValue) != 0) + { + Fail("ERROR: The value obtained by getenv() was not equal to the " + "correct value of the environment variable. The correct " + "value is '%s' and the function returned '%s'.\n", + FirstVarValue, + result); + } + + + result = getenv(SecondVarName); + if(result == NULL) + { + Fail("ERROR: The result of getenv on a valid Environment Variable " + "was NULL, which indicates the environment varaible was not " + "found.\n"); + } + + if(strcmp(result, SecondVarValue) != 0) + { + Fail("ERROR: The value obtained by getenv() was not equal to the " + "correct value of the environment variable. The correct " + "value is '%s' and the function returned '%s'.\n", + SecondVarValue, + result); + } + + + PAL_Terminate(); + return PASS; + +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test2/testinfo.dat new file mode 100644 index 0000000..90a4ac5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = getenv +Name = Test retrieval of variables differing only by case. +TYPE = DEFAULT +EXE1 = test2 +Description += Check that environment variables differing only by their += case are interpreted as separate variables by the BSD Operationg += System. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test3/CMakeLists.txt new file mode 100644 index 0000000..a0e620d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_getenv_test3 + ${SOURCES} +) + +add_dependencies(paltest_getenv_test3 coreclrpal) + +target_link_libraries(paltest_getenv_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test3/test3.cpp new file mode 100644 index 0000000..1eefd9d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test3/test3.cpp @@ -0,0 +1,75 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Create an environment variable and try to retrieve +** it using the same name but with different case. This +** is to show that the Win32 representation of getenv +** is case insensitive. +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ +#if WIN32 + + const char* FirstVariable = "PalTestingEnvironmentVariable=The value"; + const char* ModifiedName = "PALTESTINGEnvironmentVariable"; + const char* FirstVarValue = "The value"; + char* result; + + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Use _putenv to set an environment variable. This ensures that the + variable we're testing on is always present. + */ + + if(_putenv(FirstVariable) != 0) + { + Fail("ERROR: _putenv failed to set an environment variable that " + "getenv will be using for testing.\n"); + } + + + /* Call getenv -- ensure it doesn't return NULL and the string it returns + is the value we set above. Also make sure that each environment variable, + differing only by case, doesn't affect the return value. + */ + + result = getenv(ModifiedName); + if(result == NULL) + { + Fail("ERROR: The result of getenv on a valid Environment Variable " + "was NULL, which indicates the environment varaible was not " + "found.\n"); + } + + if(strcmp(result, FirstVarValue) != 0) + { + Fail("ERROR: The value obtained by getenv() was not equal to the " + "correct value of the environment variable. The correct " + "value is '%s' and the function returned '%s'.\n", + FirstVarValue, + result); + } + + + PAL_Terminate(); + return PASS; + +#else + return PASS; + +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test3/testinfo.dat new file mode 100644 index 0000000..6e12fc4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/getenv/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = getenv +Name = Test retrieval of variables differing only by case. +TYPE = DEFAULT +EXE1 = test3 +Description += Check that environment variables differing only by their += case are interpreted as the same variables in the WIN32 += platform. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/test1/CMakeLists.txt new file mode 100644 index 0000000..d6485d9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_ilogb_test1 + ${SOURCES} +) + +add_dependencies(paltest_ilogb_test1 coreclrpal) + +target_link_libraries(paltest_ilogb_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/test1/test1.cpp new file mode 100644 index 0000000..0757e4e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/test1/test1.cpp @@ -0,0 +1,101 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that ilogb returns correct values. +** +**===================================================================*/ + +#include + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + int expected; /* expected result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, int expected) +{ + int result = ilogb(value); + + if (result != expected) + { + Fail("ilogb(%g) returned %d when it should have returned %d", + value, result, expected); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected */ + { PAL_NEGINF, 2147483647 }, + { 0, -2147483648 }, + { PAL_POSINF, 2147483647 }, + { 0.11331473229676087, -4 }, // expected: -(pi) + { 0.15195522325791297, -3 }, // expected: -(e) + { 0.20269956628651730, -3 }, // expected: -(ln(10)) + { 0.33662253682241906, -2 }, // expected: -(pi / 2) + { 0.36787944117144232, -2 }, // expected: -(log2(e)) + { 0.37521422724648177, -2 }, // expected: -(sqrt(2)) + { 0.45742934732229695, -2 }, // expected: -(2 / sqrt(pi)) + { 0.5, -1 }, // expected: -(1) + { 0.58019181037172444, -1 }, // expected: -(pi / 4) + { 0.61254732653606592, -1 }, // expected: -(1 / sqrt(2)) + { 0.61850313780157598, -1 }, // expected: -(ln(2)) + { 0.64321824193300488, -1 }, // expected: -(2 / pi) + { 0.74005557395545179, -1 }, // expected: -(log10(e)) + { 0.80200887896145195, -1 }, // expected: -(1 / pi) + { 1, 0 }, + { 1.2468689889006383, 0 }, // expected: 1 / pi + { 1.3512498725672678, 0 }, // expected: log10(e) + { 1.5546822754821001, 0 }, // expected: 2 / pi + { 1.6168066722416747, 0 }, // expected: ln(2) + { 1.6325269194381528, 0 }, // expected: 1 / sqrt(2) + { 1.7235679341273495, 0 }, // expected: pi / 4 + { 2, 1 }, + { 2.1861299583286618, 1 }, // expected: 2 / sqrt(pi) + { 2.6651441426902252, 1 }, // expected: sqrt(2) + { 2.7182818284590452, 1 }, // expected: log2(e) value: e + { 2.9706864235520193, 1 }, // expected: pi / 2 + { 4.9334096679145963, 2 }, // expected: ln(10) + { 6.5808859910179210, 2 }, // expected: e + { 8.8249778270762876, 3 }, // expected: pi + { PAL_NAN, 2147483647 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/test1/testinfo.dat new file mode 100644 index 0000000..05549db --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogb/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = ilogb +Name = Call ilogb with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the ilogb function with various num/exponent pairs += that should produce std answers. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/test1/CMakeLists.txt new file mode 100644 index 0000000..634ad8d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_ilogbf_test1 + ${SOURCES} +) + +add_dependencies(paltest_ilogbf_test1 coreclrpal) + +target_link_libraries(paltest_ilogbf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/test1/test1.cpp new file mode 100644 index 0000000..faa9f26 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/test1/test1.cpp @@ -0,0 +1,101 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that ilogbf returns correct values. +** +**===================================================================*/ + +#include + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + int expected; /* expected result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, int expected) +{ + int result = ilogbf(value); + + if (result != expected) + { + Fail("ilogbf(%g) returned %d when it should have returned %d", + value, result, expected); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected */ + { PAL_NEGINF, 2147483647 }, + { 0, -2147483648 }, + { PAL_POSINF, 2147483647 }, + { 0.113314732f, -4 }, // expected: -(pi) + { 0.151955223f, -3 }, // expected: -(e) + { 0.202699566f, -3 }, // expected: -(ln(10)) + { 0.336622537f, -2 }, // expected: -(pi / 2) + { 0.367879441f, -2 }, // expected: -(log2(e)) + { 0.375214227f, -2 }, // expected: -(sqrt(2)) + { 0.457429347f, -2 }, // expected: -(2 / sqrt(pi)) + { 0.5f, -1 }, // expected: -(1) + { 0.580191810f, -1 }, // expected: -(pi / 4) + { 0.612547327f, -1 }, // expected: -(1 / sqrt(2)) + { 0.618503138f, -1 }, // expected: -(ln(2)) + { 0.643218242f, -1 }, // expected: -(2 / pi) + { 0.740055574f, -1 }, // expected: -(log10(e)) + { 0.802008879f, -1 }, // expected: -(1 / pi) + { 1, 0 }, + { 1.24686899f, 0 }, // expected: 1 / pi + { 1.35124987f, 0 }, // expected: log10(e) + { 1.55468228f, 0 }, // expected: 2 / pi + { 1.61680667f, 0 }, // expected: ln(2) + { 1.63252692f, 0 }, // expected: 1 / sqrt(2) + { 1.72356793f, 0 }, // expected: pi / 4 + { 2, 1 }, + { 2.18612996f, 1 }, // expected: 2 / sqrt(pi) + { 2.66514414f, 1 }, // expected: sqrt(2) + { 2.71828183f, 1 }, // expected: log2(e) value: e + { 2.97068642f, 1 }, // expected: pi / 2 + { 4.93340967f, 2 }, // expected: ln(10) + { 6.58088599f, 2 }, // expected: e + { 8.82497783f, 3 }, // expected: pi + { PAL_NAN, 2147483647 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/test1/testinfo.dat new file mode 100644 index 0000000..8337bba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/ilogbf/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = ilogbf +Name = Call ilogbf with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the ilogbf function with various num/expfonent pairs += that should produce std answers. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/test1/CMakeLists.txt new file mode 100644 index 0000000..d8b68ab --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_isalnum_test1 + ${SOURCES} +) + +add_dependencies(paltest_isalnum_test1 coreclrpal) + +target_link_libraries(paltest_isalnum_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/test1/test1.cpp new file mode 100644 index 0000000..d9cdfca --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/test1/test1.cpp @@ -0,0 +1,88 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the isalnum function +** Check that a number of characters return the correct +** values for whether they are alpha/numeric or not. +** +** +**===================================================================*/ + +#include + + +struct testCase +{ + int CorrectResult; + int character; +}; + +int __cdecl main(int argc, char **argv) +{ + + int result; + int i; + + struct testCase testCases[] = + { + {1, 'a'}, + {1, 'z'}, + {1, 'B'}, + {1, '5'}, + {1, '0'}, + {0, '?'}, + {0, 230} + }; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Loop through each case. Check to see if each is alpha/numeric or + not. + */ + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + + result = isalnum(testCases[i].character); + + /* The return value is 'non-zero' for success. This if condition + * will still work if that non-zero isn't just 1 + */ + if ( ((testCases[i].CorrectResult == 1) && (result == 0)) || + ( (testCases[i].CorrectResult == 0) && (result != 0) )) + { + Fail("ERROR: isalnum returned %i instead of %i for character " + " %c.\n", + result, + testCases[i].CorrectResult, + testCases[i].character); + } + + } + + + PAL_Terminate(); + return PASS; +} + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/test1/testinfo.dat new file mode 100644 index 0000000..ba8f07a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalnum/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = isalnum +Name = Positive Test for isalnum +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the isalnum function += Check that a number of characters return the correct values for whether += they are alpha/numeric or not. + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/test1/CMakeLists.txt new file mode 100644 index 0000000..5d5170d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_isalpha_test1 + ${SOURCES} +) + +add_dependencies(paltest_isalpha_test1 coreclrpal) + +target_link_libraries(paltest_isalpha_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/test1/test1.cpp new file mode 100644 index 0000000..b494d14 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/test1/test1.cpp @@ -0,0 +1,86 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the isalpha function +** Check that a number of characters return the correct +** values for whether they are alpha or not. +** +** +**===================================================================*/ + +#include + +struct testCase +{ + int CorrectResult; + int character; +}; + +int __cdecl main(int argc, char **argv) +{ + + int result; + int i; + + struct testCase testCases[] = + { + {1, 'a'}, + {1, 'z'}, + {1, 'B'}, + {0, '5'}, + {0, '?'}, + {0, 230} + }; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Loop through each case. Check to see if each is alpha or + not. + */ + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + + result = isalpha(testCases[i].character); + + /* The return value is 'non-zero' for success. This if condition + * will still work if that non-zero isn't just 1 + */ + if ( ((testCases[i].CorrectResult == 1) && (result == 0)) || + ( (testCases[i].CorrectResult == 0) && (result != 0) )) + { + Fail("ERROR: isalpha returned %i instead of %i for character " + "%c.\n", + result, + testCases[i].CorrectResult, + testCases[i].character); + } + + } + + + PAL_Terminate(); + return PASS; +} + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/test1/testinfo.dat new file mode 100644 index 0000000..7d50836 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isalpha/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = isalpha +Name = Positive Test for isalpha +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the isalpha function += Check that a number of characters return the correct values for whether += they are alpha or not. + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/test1/CMakeLists.txt new file mode 100644 index 0000000..94b4075 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_isdigit_test1 + ${SOURCES} +) + +add_dependencies(paltest_isdigit_test1 coreclrpal) + +target_link_libraries(paltest_isdigit_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/test1/test1.cpp new file mode 100644 index 0000000..ad23448 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/test1/test1.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Checks every character against the known range of digits. +** +** +**==========================================================================*/ + + +#include + +int __cdecl main(int argc, char *argv[]) +{ + int i; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + for (i=0; i<256; i++) + { + if (isdigit(i)) + { + if (i < '0' || i > '9') + { + Fail("ERROR: isdigit returned true for '%c' (%d)!\n", i, i); + } + } + else + { + if (i >= '0' && i <= '9') + { + Fail("ERROR: isdigit returned false for '%c' (%d)!\n", i, i); + } + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/test1/testinfo.dat new file mode 100644 index 0000000..eb23739 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isdigit/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = isdigit +Name = Test #1 for isdigit +TYPE = DEFAULT +EXE1 = test1 +Description +=Checks every character against the known range of digits. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/test1/CMakeLists.txt new file mode 100644 index 0000000..e0b01f7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_islower_test1 + ${SOURCES} +) + +add_dependencies(paltest_islower_test1 coreclrpal) + +target_link_libraries(paltest_islower_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/test1/test1.cpp new file mode 100644 index 0000000..c8e877b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/test1/test1.cpp @@ -0,0 +1,85 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the islower function +** Check that a number of characters return the correct +** values for whether they are lower case or not. +** +** +**===================================================================*/ + +#include + +struct testCase +{ + int CorrectResult; + int character; +}; + +int __cdecl main(int argc, char **argv) +{ + + int result; + int i; + + struct testCase testCases[] = + { + {1, 'a'}, /* Basic cases */ + {1, 'z'}, + {0, 'B'}, /* Lower case */ + {0, '?'}, /* Characters without case */ + {0, 230}, + {0, '5'} + }; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Loop through each case. Check to see if each is lower case or + not. + */ + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + + result = islower(testCases[i].character); + + /* The return value is 'non-zero' for success. This if condition + * will still work if that non-zero isn't just 1 + */ + if ( ((testCases[i].CorrectResult == 1) && (result == 0)) || + ( (testCases[i].CorrectResult == 0) && (result != 0) )) + { + Fail("ERROR: islower returned %i instead of %i for " + "character %c.\n", + result, testCases[i].CorrectResult, + testCases[i].character); + } + + } + + + PAL_Terminate(); + return PASS; +} + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/test1/testinfo.dat new file mode 100644 index 0000000..49a6fb7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/islower/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = islower +Name = Positive Test for islower +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the islower function += Check that a number of characters return the correct values for whether += they are lower case or not. + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test1/CMakeLists.txt new file mode 100644 index 0000000..58505f1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + isprint.cpp +) + +add_executable(paltest_isprint_test1 + ${SOURCES} +) + +add_dependencies(paltest_isprint_test1 coreclrpal) + +target_link_libraries(paltest_isprint_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test1/isprint.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test1/isprint.cpp new file mode 100644 index 0000000..54db666 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test1/isprint.cpp @@ -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. + +/*============================================================= +** +** Source: isprint.c +** +** Purpose: Positive test the isprint API. +** Call isprint to test if a character is printable +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + int index; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*check if the character is printable*/ + for(index = 0x20; index<=0x7E;index++) + { + err = isprint(index); + if(0 == err) + { + Fail("\nFailed to call isprint API to check " + "printable character from 0x20 to 0x7E!\n"); + } + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test1/testinfo.dat new file mode 100644 index 0000000..c9b9ec0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = miscellaneous +Function = isprint +Name = Positive test for isprint API to check if a character is printable +TYPE = DEFAULT +EXE1 = isprint +Description +=Test the isprint to check if a character is printable diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test2/CMakeLists.txt new file mode 100644 index 0000000..d06c0d3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_isprint_test2 + ${SOURCES} +) + +add_dependencies(paltest_isprint_test2 coreclrpal) + +target_link_libraries(paltest_isprint_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test2/test2.cpp new file mode 100644 index 0000000..2170c47 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test2/test2.cpp @@ -0,0 +1,59 @@ +// 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. + +/*============================================================= +** +** Source: isprint.c +** +** Purpose: Negative test for the isprint API. Call isprint +** to test if out of range characters are +** not printable. +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*check that function fails for values that are not printable*/ + err = isprint(0x15); + if(err) + { + Fail("\nSucceeded when it should have failed because 0x15 " + "is not in the range of printable characters\n"); + } + + err = isprint(0xAA); + if(err) + { + Fail("\nSucceeded when it should have failed because 0xAA " + "is not in the range of printable characters\n"); + } + + /* check carriage return */ + if(0 != isprint(0x0d)) + { + Fail("\nSucceeded when it should have failed because 0x0d " + "is not in the range of printable characters\n"); + } + + /* check line feed */ + if(0 != isprint(0x0a)) + { + Fail("\nSucceeded when it should have failed because 0x0a " + "is not in the range of printable characters\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test2/testinfo.dat new file mode 100644 index 0000000..e115278 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isprint/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = miscellaneous +Function = isprint +Name = Test isprint API to check if out of range characters are not printable. +TYPE = DEFAULT +EXE1 = test2 +Description +=Test the isprint function to verify that out of range characters +=are not printable. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isspace/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isspace/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isspace/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isspace/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isspace/test1/CMakeLists.txt new file mode 100644 index 0000000..678ea87 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isspace/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_isspace_test1 + ${SOURCES} +) + +add_dependencies(paltest_isspace_test1 coreclrpal) + +target_link_libraries(paltest_isspace_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isspace/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isspace/test1/test1.cpp new file mode 100644 index 0000000..6cd1ce8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isspace/test1/test1.cpp @@ -0,0 +1,82 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Test #1 for the isspace function +** +** +**==========================================================================*/ + + + +#include + +struct testCase +{ + long result; + char avalue; +}; + + + +int __cdecl main(int argc, char *argv[]) +{ + int i=0; + long result = 0; + + /* + * A structures of the testcases to be tested with + * isspace function + */ + struct testCase testCases[] = + { + {1,'\n'}, + {1,'\t'}, + {1,'\r'}, + {1,'\v'}, + {1,'\f'}, + {1,' '}, + {0,'a'}, + {0,'A'}, + {0,'z'}, + {0,'Z'}, + {0,'r'}, + {0,'R'}, + {0,'0'}, + {0,'*'}, + {0,3} + }; + + /* + * Initialize the PAL + */ + if ( 0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Loop through the testcases */ + for (i=0; i0, check through a list of the known space characters to ensure that it += is really a space. Also, when it returns <=0, ensure that that character += isn't a space. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/test1/CMakeLists.txt new file mode 100644 index 0000000..0eded6e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_isupper_test1 + ${SOURCES} +) + +add_dependencies(paltest_isupper_test1 coreclrpal) + +target_link_libraries(paltest_isupper_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/test1/test1.cpp new file mode 100644 index 0000000..b88bcc4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/test1/test1.cpp @@ -0,0 +1,88 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the isupper function +** Check that a number of characters return the correct +** values for whether they are upper case or not. +** +** +**===================================================================*/ + +#include + +struct testCase +{ + int CorrectResult; + int character; +}; + +int __cdecl main(int argc, char **argv) +{ + + int result; + int i; + + /* Note: 1 iff char = A..Z + 0 iff char =~ A..Z + */ + + struct testCase testCases[] = + { + {1, 'A'}, /* Basic cases */ + {1, 'Z'}, + {0, 'b'}, /* Lower case */ + {0, '?'}, /* Characters without case */ + {0, 230}, + {0, '5'} + }; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Loop through each case. Check to see if each is upper case or + not. + */ + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + result = isupper(testCases[i].character); + + /* The return value is 'non-zero' for success. This if condition + * will still work if that non-zero isn't just 1 + */ + if ( ((testCases[i].CorrectResult == 1) && (result == 0)) || + ( (testCases[i].CorrectResult == 0) && (result != 0) )) + { + Fail("ERROR: isupper returned %i instead of %i for " + "character %c.\n", + result,testCases[i].CorrectResult, + testCases[i].character); + } + + } + + + PAL_Terminate(); + return PASS; +} + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/test1/testinfo.dat new file mode 100644 index 0000000..fb2648a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isupper/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = isupper +Name = Positive Test for isupper +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the isupper function += Check that a number of characters return the correct values for whether += they are upper case or not. + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/test1/CMakeLists.txt new file mode 100644 index 0000000..dce86a1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_iswdigit_test1 + ${SOURCES} +) + +add_dependencies(paltest_iswdigit_test1 coreclrpal) + +target_link_libraries(paltest_iswdigit_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/test1/test1.cpp new file mode 100644 index 0000000..b4fe3b3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/test1/test1.cpp @@ -0,0 +1,69 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c (iswdigit) +** +** Purpose: Tests the PAL implementation of the iswdigit function. +** Tests the passed parameter to iswdigit for being a +** digit ('0' - '9'). Also passes non-digits to make sure +** iswdigit picks them up. +** NOTE: There are three ASCII values that under Windows, +** iswdigit will return non-zero, indicating a digit. +** These values are quite apparently not digits: +** 178, 179, 185. +** These are not tested. +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + + int result; + int i; + + char16_t passTestCases[] = {'1','2','3','4','5','6','7','8','9'}; + char16_t failTestCases[] = {'a','b','p','$','?',234}; + + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + /* Loop through each case. Testing if each is a digit. */ + for(i = 0; i < sizeof(passTestCases) / sizeof(char16_t); i++) + { + result = iswdigit(passTestCases[i]); + + /* The return value is 'non-zero' indicates digit*/ + if (result == 0) + { + Fail("ERROR: iswdigit returned \"%d\" instead indicating" + " \"%c\" is not a digit\n", + result, + passTestCases[i]); + } + } + + /* Loop through each case. Testing if each is a not a digit. */ + for(i = 0; i < sizeof(failTestCases) / sizeof(char16_t); i++) + { + result = iswdigit(failTestCases[i]); + + /* The return value is 'zero' indicates non-digit*/ + if (result != 0) + { + Fail("ERROR: iswdigit returned \"%d\", indicating" + " \"%c\" is a digit\n", + result, + failTestCases[i]); + } + } + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/test1/testinfo.dat new file mode 100644 index 0000000..345c9d5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswdigit/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = iswdigit +Name = Positive Test for iswdigit +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the iswdigit function. += Tests the passed parameter to iswdigit for being a += digit ('0' - '9'). Also passes non-digits to make sure += iswdigit picks them up. += NOTE: There are three ASCII values that under Windows, += iswdigit will return non-zero, indicating a digit. += These values are quite apparently not digits: += 178, 179, 185. These are not tested. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/test1/CMakeLists.txt new file mode 100644 index 0000000..8605249 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_iswprint_test1 + ${SOURCES} +) + +add_dependencies(paltest_iswprint_test1 coreclrpal) + +target_link_libraries(paltest_iswprint_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/test1/test1.cpp new file mode 100644 index 0000000..08a985b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/test1/test1.cpp @@ -0,0 +1,59 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests iswprint with all wide characters, ensuring they are +** consistent with GetStringTypeExW. +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + WORD Info; + int ret; + int i; + WCHAR ch; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + for (i=0; i<=0xFFFF; i++) + { + ch = i; + ret = GetStringTypeExW(LOCALE_USER_DEFAULT, CT_CTYPE1, &ch, 1, &Info); + if (!ret) + { + Fail("GetStringTypeExW failed to get information for %#X!\n", ch); + } + + ret = iswprint(ch); + if (Info & (C1_BLANK|C1_PUNCT|C1_ALPHA|C1_DIGIT)) + { + if (!ret) + { + Fail("iswprint returned incorrect results for %#X: " + "expected printable\n", ch); + } + } + else + { + if (ret) + { + Fail("iswprint returned incorrect results for %#X: " + "expected non-printable\n", ch); + } + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/test1/testinfo.dat new file mode 100644 index 0000000..c425967 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswprint/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = iswprint +Name = Positive Test for iswprint +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests iswprint with all wide characters, ensuring they are +=consistent with GetStringTypeExW. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/test1/CMakeLists.txt new file mode 100644 index 0000000..f5eef10 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_iswspace_test1 + ${SOURCES} +) + +add_dependencies(paltest_iswspace_test1 coreclrpal) + +target_link_libraries(paltest_iswspace_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/test1/test1.cpp new file mode 100644 index 0000000..c589978 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/test1/test1.cpp @@ -0,0 +1,78 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests iswspace with a range of wide characters. +** +** +** +**==========================================================================*/ + + + +#include + +int __cdecl main(int argc, char *argv[]) +{ + int ret; + int i; + + struct testChars + { + WCHAR charValue; + int result; + }; + + /* create an array of chars that test the range of possible characters */ + struct testChars testChars1[] = + { + {0x00,0}, /* null */ + {0x09,1}, /* open circle */ + {0x0D,1}, /* musical note */ + {0x20,1}, /* space */ + {0x3F,0}, /* ? */ + {0x5E,0}, /* ^ */ + {0x7B,0}, /* { */ + {0x86,0}, /* a with circle on top */ + {0x9F,0}, /* slanted f */ + {0xC4,0}, /* long dash */ + {0xE5,0} /* sigma */ + }; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + for (i = 0; i < (sizeof(testChars1) / sizeof(struct testChars)); i++) + { + + ret = iswspace(testChars1[i].charValue); + + if((ret==0) && (testChars1[i].result != 0)) + { + Fail("ERROR: wide character %#X IS considered a space, " + "but iswspace did NOT indicate it was one with error %u.\n", + testChars1[i].charValue, + GetLastError()); + } + + if((ret!=0) && (testChars1[i].result == 0)) + { + Fail("ERROR: wide character %#X is NOT considered a space, " + "but iswspace DID indicate it was a space with error %u.\n", + testChars1[i].charValue, + GetLastError()); + } + } + + + PAL_Terminate(); + + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/test1/testinfo.dat new file mode 100644 index 0000000..0368052 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswspace/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = iswspace +Name = Positive Test for iswspace +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests iswspace with a range of wide characters. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/test1/CMakeLists.txt new file mode 100644 index 0000000..94c0caf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_iswupper_test1 + ${SOURCES} +) + +add_dependencies(paltest_iswupper_test1 coreclrpal) + +target_link_libraries(paltest_iswupper_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/test1/test1.cpp new file mode 100644 index 0000000..a01686b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/test1/test1.cpp @@ -0,0 +1,91 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the iswupper function +** Check that a number of characters return the correct +** values for whether they are upper case or not. +** +** +**===================================================================*/ + +#define UNICODE +#include + + +struct testCase +{ + int CorrectResult; + WCHAR character; +}; + +int __cdecl main(int argc, char **argv) +{ + + int result; + int i; + + /* Note: 1 iff char = A..Z + 0 iff char =~ A..Z + */ + + struct testCase testCases[] = + { + {1, 'A'}, /* Basic cases */ + {1, 'Z'}, + {0, 'b'}, /* Lower case */ + {0, '?'}, /* Characters without case */ + {0, 230} + }; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Loop through each case. Check to see if each is upper case or + not. + */ + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + + result = iswupper(testCases[i].character); + + /* The return value is 'non-zero' for success. This if condition + * will still work if that non-zero isn't just 1 + */ + if ( ((testCases[i].CorrectResult == 1) && (result == 0)) || + ( (testCases[i].CorrectResult == 0) && (result != 0) )) + { + Fail("ERROR: iswupper returned %i instead of %i for " + "character %c.\n", + result, + testCases[i].CorrectResult, + testCases[i].character); + } + + } + + + PAL_Terminate(); + return PASS; +} + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/test1/testinfo.dat new file mode 100644 index 0000000..22131e4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/iswupper/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = isupper +Name = Positive Test for iswupper +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the iswupper function += Check that a number of characters return the correct values for whether += they are upper case or not. + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/test1/CMakeLists.txt new file mode 100644 index 0000000..95a78d4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_isxdigit_test1 + ${SOURCES} +) + +add_dependencies(paltest_isxdigit_test1 coreclrpal) + +target_link_libraries(paltest_isxdigit_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/test1/test1.cpp new file mode 100644 index 0000000..be25af2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/test1/test1.cpp @@ -0,0 +1,58 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Run through every possible character. For each time that +** isxdigit returns: +** 1, check through a list of the known hex characters to ensure that it +** is really a hex char. Also, when it returns 0, ensure that that character +** isn't a hex character. +** +** +**==========================================================================*/ + + + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + int i; + + /* Initialize the PAL */ + if ( 0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Loop through each character and call isxdigit for each character */ + for (i=1; i<256; i++) + { + + if (isxdigit(i) == 0) + { + if( ((i>=48) && (i<=57)) || ((i>=97) && (i<=102)) || + ((i>=65) && (i<=70)) ) + { + Fail("ERROR: isxdigit() returns true for '%c' (%d)\n", i, i); + } + } + else + { + if( ((i<48) && (i>58)) || ((i<97) && (i>102)) || + ((i<65) && (i>70)) ) + { + Fail("ERROR: isxdigit() returns false for '%c' (%d)\n", i, i); + } + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/test1/testinfo.dat new file mode 100644 index 0000000..fd031f0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/isxdigit/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = isxdigit +Name = Positive Test for isxdigit +TYPE = DEFAULT +EXE1 = test1 +Description += Run through every possible character. For each time that isxdigit returns += 1, check through a list of the known hex characters to ensure that it += is really a hex char. Also, when it returns 0, ensure that that character += isn't a hex character. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/test1/CMakeLists.txt new file mode 100644 index 0000000..1255c58 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_llabs_test1 + ${SOURCES} +) + +add_dependencies(paltest_llabs_test1 coreclrpal) + +target_link_libraries(paltest_llabs_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/test1/test1.cpp new file mode 100644 index 0000000..044e22f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/test1/test1.cpp @@ -0,0 +1,65 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Call llabs on a series of values -- negative, positive, +** zero, and the largest negative value of an __int64. Ensure that +** they are all changed properly to their absoulte value. +** +** +**===================================================================*/ + +#include + +struct testCase +{ + __int64 LongLongValue; + __int64 AbsoluteLongLongValue; +}; + +int __cdecl main(int argc, char **argv) +{ + + __int64 result=0; + int i=0; + + struct testCase testCases[] = + { + {1234, 1234}, + {-1234, 1234}, + {0, 0}, + {-9223372036854775807LL, 9223372036854775807LL}, /* Max value to abs */ + {9223372036854775807LL, 9223372036854775807LL} + }; + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Loop through each case. Call llabs on each __int64 and ensure that + the resulting value is correct. + */ + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + /* Absolute value on an __int64 */ + result = llabs(testCases[i].LongLongValue); + + if (testCases[i].AbsoluteLongLongValue != result) + { + Fail("ERROR: llabs took the absoulte value of '%d' to be '%d' " + "instead of %d.\n", + testCases[i].LongLongValue, + result, + testCases[i].AbsoluteLongLongValue); + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/test1/testinfo.dat new file mode 100644 index 0000000..b1b7637 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/llabs/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = labs +Name = Series of tests for labs: positive, negative, zero, maximum __int64 value. +TYPE = DEFAULT +EXE1 = test1 +Description += Call llabs on a series of values -- negative, positive, zero, += and the largest negative value of an __int64. Ensure that they are all += changed properly to their absoulte value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/test1/CMakeLists.txt new file mode 100644 index 0000000..75092a2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_log10_test1 + ${SOURCES} +) + +add_dependencies(paltest_log10_test1 coreclrpal) + +target_link_libraries(paltest_log10_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/test1/test1.cpp new file mode 100644 index 0000000..13711a7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/test1/test1.cpp @@ -0,0 +1,146 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that log10 returns correct values. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** _isnan +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = log10(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("log10(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = log10(value); + + if (!_isnan(result)) + { + Fail("log10(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, PAL_NEGINF, 0 }, + { 0.00072178415907472774, -3.1415926535897932, PAL_EPSILON * 10 }, // expected: -(pi) + { 0.0019130141022243176, -2.7182818284590452, PAL_EPSILON * 10 }, // expected: -(e) + { 0.0049821282964407206, -2.3025850929940457, PAL_EPSILON * 10 }, // expected: -(ln(10)) + { 0.026866041001136132, -1.5707963267948966, PAL_EPSILON * 10 }, // expected: -(pi / 2) + { 0.036083192820787210, -1.4426950408889634, PAL_EPSILON * 10 }, // expected: -(log2(e)) + { 0.038528884700322026, -1.4142135623730950, PAL_EPSILON * 10 }, // expected: -(sqrt(2)) + { 0.074408205860642723, -1.1283791670955126, PAL_EPSILON * 10 }, // expected: -(2 / sqrt(pi)) + { 0.1, -1, PAL_EPSILON * 10 }, // expected: -(1) + { 0.16390863613957665, -0.78539816339744831, PAL_EPSILON }, // expected: -(pi / 4) + { 0.19628775993505562, -0.70710678118654752, PAL_EPSILON }, // expected: -(1 / sqrt(2)) + { 0.20269956628651730, -0.69314718055994531, PAL_EPSILON }, // expected: -(ln(2)) + { 0.23087676451600055, -0.63661977236758134, PAL_EPSILON }, // expected: -(2 / pi) + { 0.36787944117144232, -0.43429448190325183, PAL_EPSILON }, // expected: -(log10(e)) + { 0.48049637305186868, -0.31830988618379067, PAL_EPSILON }, // expected: -(1 / pi) + { 1, 0, PAL_EPSILON }, + { 2.0811811619898573, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi + { 2.7182818284590452, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e) value: e + { 4.3313150290214525, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi + { 4.9334096679145963, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2) + { 5.0945611704512962, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2) + { 6.1009598002416937, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4 + { 10, 1, PAL_EPSILON * 10 }, + { 13.439377934644400, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi) + { 25.954553519470081, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2) + { 27.713733786437790, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e) + { 37.221710484165167, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2 + { 200.71743249053009, 2.3025850929940457, PAL_EPSILON * 10 }, // expected: ln(10) + { 522.73529967043665, 2.7182818284590452, PAL_EPSILON * 10 }, // expected: e + { 1385.4557313670111, 3.1415926535897932, PAL_EPSILON * 10 }, // expected: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/test1/testinfo.dat new file mode 100644 index 0000000..887bace --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = log10 +Name = Positive Test for log10 +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the log10() function, += checking each for the expected result. Also checks += for proper handling of out-of-range values. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/test1/CMakeLists.txt new file mode 100644 index 0000000..4c03508 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_log10f_test1 + ${SOURCES} +) + +add_dependencies(paltest_log10f_test1 coreclrpal) + +target_link_libraries(paltest_log10f_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/test1/test1.c new file mode 100644 index 0000000..e7c8c2f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/test1/test1.c @@ -0,0 +1,144 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that log10f returns correct values. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** _isnanf +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = log10f(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("log10f(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = log10f(value); + + if (!_isnanf(result)) + { + Fail("log10f(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, PAL_NEGINF, 0 }, + { 0.000721784159f, -3.14159265f, PAL_EPSILON * 10 }, // expected: -(pi) + { 0.00191301410f, -2.71828183f, PAL_EPSILON * 10 }, // expected: -(e) + { 0.00498212830f, -2.30258509f, PAL_EPSILON * 10 }, // expected: -(ln(10)) + { 0.0268660410f, -1.57079633f, PAL_EPSILON * 10 }, // expected: -(pi / 2) + { 0.0360831928f, -1.44269504f, PAL_EPSILON * 10 }, // expected: -(logf2(e)) + { 0.0385288847f, -1.41421356f, PAL_EPSILON * 10 }, // expected: -(sqrtf(2)) + { 0.0744082059f, -1.12837917f, PAL_EPSILON * 10 }, // expected: -(2 / sqrtf(pi)) + { 0.1f, -1, PAL_EPSILON * 10 }, // expected: -(1) + { 0.163908636f, -0.785398163f, PAL_EPSILON }, // expected: -(pi / 4) + { 0.196287760f, -0.707106781f, PAL_EPSILON }, // expected: -(1 / sqrtf(2)) + { 0.202699566f, -0.693147181f, PAL_EPSILON }, // expected: -(ln(2)) + { 0.230876765f, -0.636619772f, PAL_EPSILON }, // expected: -(2 / pi) + { 0.367879441f, -0.434294482f, PAL_EPSILON }, // expected: -(log10f(e)) + { 0.480496373f, -0.318309886f, PAL_EPSILON }, // expected: -(1 / pi) + { 1, 0, PAL_EPSILON }, + { 2.08118116f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 2.71828183f, 0.434294482f, PAL_EPSILON }, // expected: log10f(e) value: e + { 4.33131503f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 4.93340967f, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 5.09456117f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 6.10095980f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { 10, 1, PAL_EPSILON * 10 }, + { 13.4393779f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 25.9545535f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 27.7137338f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 37.2217105f, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { 200.717432f, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10) + { 522.735300f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { 1385.45573f, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/test1/testinfo.dat new file mode 100644 index 0000000..175ee3a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log10f/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = log10f +Name = Positive Test for log10f +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the log10f() function, += checking each for the expected result. Also checks += for proper handling of out-of-range values. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/test1/CMakeLists.txt new file mode 100644 index 0000000..efee18b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_log2_test1 + ${SOURCES} +) + +add_dependencies(paltest_log2_test1 coreclrpal) + +target_link_libraries(paltest_log2_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/test1/test1.cpp new file mode 100644 index 0000000..0f73fa1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/test1/test1.cpp @@ -0,0 +1,139 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that log2 returns correct values. +** +**===================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = log2(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("log2(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = log2(value); + + if (!_isnan(result)) + { + Fail("log2(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, PAL_NEGINF, 0 }, + { 0.11331473229676087, -3.1415926535897932, PAL_EPSILON * 10 }, // expected: -(pi) + { 0.15195522325791297, -2.7182818284590452, PAL_EPSILON * 10 }, // expected: -(e) + { 0.20269956628651730, -2.3025850929940457, PAL_EPSILON * 10 }, // expected: -(ln(10)) + { 0.33662253682241906, -1.5707963267948966, PAL_EPSILON * 10 }, // expected: -(pi / 2) + { 0.36787944117144232, -1.4426950408889634, PAL_EPSILON * 10 }, // expected: -(log2(e)) + { 0.37521422724648177, -1.4142135623730950, PAL_EPSILON * 10 }, // expected: -(sqrt(2)) + { 0.45742934732229695, -1.1283791670955126, PAL_EPSILON * 10 }, // expected: -(2 / sqrt(pi)) + { 0.5, -1, PAL_EPSILON * 10 }, // expected: -(1) + { 0.58019181037172444, -0.78539816339744831, PAL_EPSILON }, // expected: -(pi / 4) + { 0.61254732653606592, -0.70710678118654752, PAL_EPSILON }, // expected: -(1 / sqrt(2)) + { 0.61850313780157598, -0.69314718055994531, PAL_EPSILON }, // expected: -(ln(2)) + { 0.64321824193300488, -0.63661977236758134, PAL_EPSILON }, // expected: -(2 / pi) + { 0.74005557395545179, -0.43429448190325183, PAL_EPSILON }, // expected: -(log10(e)) + { 0.80200887896145195, -0.31830988618379067, PAL_EPSILON }, // expected: -(1 / pi) + { 1, 0, PAL_EPSILON }, + { 1.2468689889006383, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi + { 1.3512498725672678, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e) + { 1.5546822754821001, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi + { 1.6168066722416747, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2) + { 1.6325269194381528, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2) + { 1.7235679341273495, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4 + { 2, 1, PAL_EPSILON * 10 }, + { 2.1861299583286618, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi) + { 2.6651441426902252, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2) + { 2.7182818284590452, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e) value: e + { 2.9706864235520193, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2 + { 4.9334096679145963, 2.3025850929940457, PAL_EPSILON * 10 }, // expected: ln(10) + { 6.5808859910179210, 2.7182818284590452, PAL_EPSILON * 10 }, // expected: e + { 8.8249778270762876, 3.1415926535897932, PAL_EPSILON * 10 }, // expected: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/test1/testinfo.dat new file mode 100644 index 0000000..ef6268e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = log2 +Name = Call log2 with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the log2 function with various num/exponent pairs += that should produce std answers. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/test1/CMakeLists.txt new file mode 100644 index 0000000..6002cf7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_log2f_test1 + ${SOURCES} +) + +add_dependencies(paltest_log2f_test1 coreclrpal) + +target_link_libraries(paltest_log2f_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/test1/test1.c new file mode 100644 index 0000000..ed62e63 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/test1/test1.c @@ -0,0 +1,138 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that log2f returns correct values. +** +**===================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = log2f(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("log2f(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = log2f(value); + + if (!_isnanf(result)) + { + Fail("log2f(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, PAL_NEGINF, 0 }, + { 0.113314732f, -3.14159265f, PAL_EPSILON * 10 }, // expected: -(pi) + { 0.151955223f, -2.71828183f, PAL_EPSILON * 10 }, // expected: -(e) + { 0.202699566f, -2.30258509f, PAL_EPSILON * 10 }, // expected: -(ln(10)) + { 0.336622537f, -1.57079633f, PAL_EPSILON * 10 }, // expected: -(pi / 2) + { 0.367879441f, -1.44269504f, PAL_EPSILON * 10 }, // expected: -(logf2(e)) + { 0.375214227f, -1.41421356f, PAL_EPSILON * 10 }, // expected: -(sqrtf(2)) + { 0.457429347f, -1.12837917f, PAL_EPSILON * 10 }, // expected: -(2 / sqrtf(pi)) + { 0.5f, -1, PAL_EPSILON * 10 }, // expected: -(1) + { 0.580191810f, -0.785398163f, PAL_EPSILON }, // expected: -(pi / 4) + { 0.612547327f, -0.707106781f, PAL_EPSILON }, // expected: -(1 / sqrtf(2)) + { 0.618503138f, -0.693147181f, PAL_EPSILON }, // expected: -(ln(2)) + { 0.643218242f, -0.636619772f, PAL_EPSILON }, // expected: -(2 / pi) + { 0.740055574f, -0.434294482f, PAL_EPSILON }, // expected: -(log10f(e)) + { 0.802008879f, -0.318309886f, PAL_EPSILON }, // expected: -(1 / pi) + { 1, 0, PAL_EPSILON }, + { 1.24686899f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 1.35124987f, 0.434294482f, PAL_EPSILON }, // expected: log10f(e) value: e + { 1.55468228f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 1.61680667f, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 1.63252692f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 1.72356793f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { 2, 1, PAL_EPSILON * 10 }, + { 2.18612996f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 2.66514414f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 2.71828183f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 2.97068642f, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { 4.93340967f, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10) + { 6.58088599f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { 8.82497783f, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/test1/testinfo.dat new file mode 100644 index 0000000..7627c82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/log2f/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = log2f +Name = Call log2f with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the log2f function with various num/expfonent pairs += that should produce std answers. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/test1/CMakeLists.txt new file mode 100644 index 0000000..5cb727d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_logf_test1 + ${SOURCES} +) + +add_dependencies(paltest_logf_test1 coreclrpal) + +target_link_libraries(paltest_logf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/test1/test1.c new file mode 100644 index 0000000..499778e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/test1/test1.c @@ -0,0 +1,139 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests logf with a normal set of values. +** +**===================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = logf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("logf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = logf(value); + + if (!_isnanf(result)) + { + Fail("logf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, PAL_NEGINF, 0 }, + { 0.0432139183f, -3.14159265f, PAL_EPSILON * 10 }, // expected: -(pi) + { 0.0659880358f, -2.71828183f, PAL_EPSILON * 10 }, // expected: -(e) + { 0.1f, -2.30258509f, PAL_EPSILON * 10 }, // expected: -(ln(10)) + { 0.207879576f, -1.57079633f, PAL_EPSILON * 10 }, // expected: -(pi / 2) + { 0.236290088f, -1.44269504f, PAL_EPSILON * 10 }, // expected: -(logf2(e)) + { 0.243116734f, -1.41421356f, PAL_EPSILON * 10 }, // expected: -(sqrtf(2)) + { 0.323557264f, -1.12837917f, PAL_EPSILON * 10 }, // expected: -(2 / sqrtf(pi)) + { 0.367879441f, -1, PAL_EPSILON * 10 }, // expected: -(1) + { 0.455938128f, -0.785398163f, PAL_EPSILON }, // expected: -(pi / 4) + { 0.493068691f, -0.707106781f, PAL_EPSILON }, // expected: -(1 / sqrtf(2)) + { 0.5f, -0.693147181f, PAL_EPSILON }, // expected: -(ln(2)) + { 0.529077808f, -0.636619772f, PAL_EPSILON }, // expected: -(2 / pi) + { 0.647721485f, -0.434294482f, PAL_EPSILON }, // expected: -(log10f(e)) + { 0.727377349f, -0.318309886f, PAL_EPSILON }, // expected: -(1 / pi) + { 1, 0, PAL_EPSILON }, + { 1.37480223f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 1.54387344f, 0.434294482f, PAL_EPSILON }, // expected: log10f(e) + { 1.89008116f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 2, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 2.02811498f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 2.19328005f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { 2.71828183f, 1, PAL_EPSILON * 10 }, // value: e + { 3.09064302f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 4.11325038f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 4.23208611f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 4.81047738f, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { 10, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10) + { 15.1542622f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { 23.1406926f, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/test1/testinfo.dat new file mode 100644 index 0000000..aadfee6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/logf/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = logf +Name = Positive Test for logf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the logf() function, += checking each for the expected result. Also checks += for proper handling of out-of-range values. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test1/CMakeLists.txt new file mode 100644 index 0000000..198ff68 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_malloc_test1 + ${SOURCES} +) + +add_dependencies(paltest_malloc_test1 coreclrpal) + +target_link_libraries(paltest_malloc_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test1/test1.cpp new file mode 100644 index 0000000..7ea4dd0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test1/test1.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Test that malloc returns useable memory +** +** +**==========================================================================*/ + +#include + + +int __cdecl main(int argc, char **argv) +{ + + char *testA; + int i; + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* check that malloc really gives us addressable memory */ + testA = (char *)malloc(20 * sizeof(char)); + if (testA == NULL) + { + Fail("Call to malloc failed.\n"); + } + for (i = 0; i < 20; i++) + { + testA[i] = 'a'; + } + for (i = 0; i < 20; i++) + { + if (testA[i] != 'a') + { + Fail("The memory doesn't seem to be properly allocated.\n"); + } + } + free(testA); + + PAL_Terminate(); + + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test1/testinfo.dat new file mode 100644 index 0000000..9060bc6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = malloc +Name = Positive Test for malloc +TYPE = DEFAULT +EXE1 = test1 +Description += Tests that malloc properly allocates memory. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test2/CMakeLists.txt new file mode 100644 index 0000000..03b0648 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_malloc_test2 + ${SOURCES} +) + +add_dependencies(paltest_malloc_test2 coreclrpal) + +target_link_libraries(paltest_malloc_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test2/test2.cpp new file mode 100644 index 0000000..5deee0e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test2/test2.cpp @@ -0,0 +1,41 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Test that malloc(0) returns non-zero value +** +**==========================================================================*/ + +#include + + +int __cdecl main(int argc, char **argv) +{ + + char *testA; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* check that malloc(0) returns non-zero value */ + testA = (char *)malloc(0); + if (testA == NULL) + { + Fail("Call to malloc(0) failed.\n"); + } + + free(testA); + + PAL_Terminate(); + + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test2/testinfo.dat new file mode 100644 index 0000000..1212a8f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/malloc/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = malloc +Name = Positive Test for malloc +TYPE = DEFAULT +EXE1 = test2 +Description += Test that malloc(0) returns non-zero value diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/test1/CMakeLists.txt new file mode 100644 index 0000000..9fcc083 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_memchr_test1 + ${SOURCES} +) + +add_dependencies(paltest_memchr_test1 coreclrpal) + +target_link_libraries(paltest_memchr_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/test1/test1.cpp new file mode 100644 index 0000000..043a678 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/test1/test1.cpp @@ -0,0 +1,122 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the memchr function. +** Create a string buffer, and check for a number of +** characters in it. Test to ensure it returns NULL if +** it can't find the character, and that the size argument +** works properly. +** +** +**===================================================================*/ + +#include + +struct testCase +{ + char *result; + char string[50]; + int character; + int length; +}; + + +int __cdecl main(int argc, char *argv[]) +{ + int i = 0; + char *result = NULL; + + /* + * this structure includes several strings to be tested with + * memchr function and the expected results + */ + + struct testCase testCases[]= + { + {"st","corn cup cat cream coast",'s',23}, + /* single instance of char */ + {"st","corn cup cat cream coast",'s',24}, + /* single inst, inst< exact length */ + {"q","corn cup cat cream coastq",'q',25}, + /* single inst at end, inst=exact length */ + {"q","corn cup cat cream coastq",'q',26}, + /* single inst at end, instlen(string) */ + {"st","corn cup cat cream coast",115,24}, + /* single int inst, instlength */ + }; + + + /* Initialize the PAL */ + if ( 0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Loop through the testcases in the structure */ + for (i=0; i< sizeof(testCases)/sizeof(struct testCase); i++) + { + /* Need to type cast function in order to compare the result */ + result = (char *)memchr(testCases[i].string, + testCases[i].character,testCases[i].length); + + if (result==NULL) + { + if (testCases[i].result != NULL) + { + Fail("ERROR: Expected memcmp to return \"%s\" instead of" + " NULL\n", testCases[i].result); + } + } + else + { + if (strcmp(result,testCases[i].result)!=0 ) + + { + Fail("ERROR: Expected memcmp to return \"%s\" instead of" + " \"%s\"\n", testCases[i].result, result); + } + + } + } + + PAL_Terminate(); + + return PASS; +} + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/test1/testinfo.dat new file mode 100644 index 0000000..fc2a8e9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memchr/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = memchr +Name = Positive Test for memchr +TYPE = DEFAULT +EXE1 = test1 +Description += Create a string buffer, and check for a number of characters in it. += Test to ensure it returns NULL if it can't find the character, and that += the size argument works properly. + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/test1/CMakeLists.txt new file mode 100644 index 0000000..f48bac8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_memcmp_test1 + ${SOURCES} +) + +add_dependencies(paltest_memcmp_test1 coreclrpal) + +target_link_libraries(paltest_memcmp_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/test1/test1.cpp new file mode 100644 index 0000000..7b63173 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/test1/test1.cpp @@ -0,0 +1,57 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Check that memcmp find identical buffers to be identical, +** and that it correctly orders different buffers. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + + char testA[] = "aaaaaaaaaaaaaaaaaaaa"; + char testB[] = "aaaaaaaaaaaaaaaaaaaa"; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + if (!(memcmp(testA, testB, 20) == 0)) + { + Fail("memcmp compared two identical buffers and found them to " + "differ.\n"); + } + testB[3] = 'b'; + + if (!(memcmp(testA, testB, 20) < 0) + || !(memcmp(testB, testA, 20) >0 )) + { + Fail("memcmp compared two buffers with different contents, and" + " did not order them correctly.\n"); + } + + if (memcmp(testA, testB, 0) != 0) + { + Fail("memcmp didn't return 0 when comparing buffers of length 0.\n"); + } + + PAL_Terminate(); + return PASS; +} + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/test1/testinfo.dat new file mode 100644 index 0000000..2de36b2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcmp/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = memcmp +Name = Positive Test for memcmp +TYPE = DEFAULT +EXE1 = test1 +Description += Check that memcmp find identical buffers to be identical, += and that it correctly orders different buffers. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/test1/CMakeLists.txt new file mode 100644 index 0000000..d7471ac --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_memcpy_test1 + ${SOURCES} +) + +add_dependencies(paltest_memcpy_test1 coreclrpal) + +target_link_libraries(paltest_memcpy_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/test1/test1.cpp new file mode 100644 index 0000000..9da98d6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/test1/test1.cpp @@ -0,0 +1,87 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Calls memcpy and verifies that the buffer was copied correctly. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + char testA[20]; + char testB[20]; + void *retVal; + long i; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + memset(testA, 'a', 20); + memset(testB, 'b', 20); + + retVal = (char *)memcpy(testB, testA, 0); + if (retVal != testB) + { + Fail("memcpy should return a pointer to the destination buffer, " + "but doesn't.\n"); + } + for(i = 0; i<20; i++) + { + if (testB[i]!= 'b') + { + Fail("The destination buffer overflowed by memcpy.\n"); + } + } + + retVal = (char *)memcpy(testB+1, testA, 18); + if (retVal != testB+1) + { + Fail("memcpy should return a pointer to the destination buffer, " + "but doesn't.\n"); + } + + if (testB[0] != 'b' || testB[19] != 'b') + { + Fail("The destination buffer was written out of bounds by memcpy!\n"); + } + + for(i = 1; i<19; i++) + { + if (testB[i]!= 'a') + { + Fail("The destination buffer copied to by memcpy doesn't match " + "the source buffer.\n"); + } + } + + PAL_Terminate(); + + return PASS; +} + + + + + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/test1/testinfo.dat new file mode 100644 index 0000000..157da6c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memcpy/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = memcpy +Name = Positive Test for memcpy +TYPE = DEFAULT +EXE1 = test1 +Description += Calls memcpy and verifies that the buffer was copied correctly. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/test1/CMakeLists.txt new file mode 100644 index 0000000..b5f8d4c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_memmove_test1 + ${SOURCES} +) + +add_dependencies(paltest_memmove_test1 coreclrpal) + +target_link_libraries(paltest_memmove_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/test1/test1.cpp new file mode 100644 index 0000000..8279d67 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/test1/test1.cpp @@ -0,0 +1,116 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Test that memmove correctly copies text from one buffer +** to another even when the buffers overlap. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + char testA[11] = "abcdefghij"; + char testB[15] = "aabbccddeeffgg"; + char testC[15] = "aabbccddeeffgg"; + char testD[15] = "aabbccddeeffgg"; + char insString[4] = "zzz"; + char *retVal; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* move a string onto itself */ + retVal = (char *)memmove(testA + 2, testA, 8); + if (retVal != testA + 2) + { + Fail("The return value should have been the value of the destination" + "pointer, but wasn't\n"); + } + + /*Check the most likely error*/ + if (memcmp(testA, "ababababab", 11) == 0) + { + Fail("memmove should have saved the characters in the region of" + " overlap between source and destination, but didn't.\n"); + } + + if (memcmp(testA, "ababcdefgh", 11) != 0) + { + /* not sure what exactly went wrong. */ + Fail("memmove was called on a region containing the characters" + " \"abcdefghij\". It was to move the first 8 positions to" + " the last 8 positions, giving the result \"ababcdefgh\". " + " Instead, it gave the result \"%s\".\n", testA); + } + + /* move a string to the front of testB */ + retVal = (char *)memmove(testB, insString, 3); + if(retVal != testB) + { + Fail("memmove: The function did not return the correct " + "string.\n"); + } + + if(memcmp(testB, "zzzbccddeeffgg",15) != 0) + { + Fail("memmove: The function failed to move the string " + "correctly.\n"); + } + + + /* move a string to the middle of testC */ + retVal = (char*)memmove(testC+5, insString, 3); + if(retVal != testC+5) + { + Fail("memmove: The function did not return the correct " + "string.\n"); + } + + if(memcmp(testC, "aabbczzzeeffgg",15) != 0) + { + Fail("memmove: The function failed to move the string " + "correctly.\n"); + } + + + /* move a string to the end of testD */ + retVal = (char*)memmove(testD+11, insString, 3); + if(retVal != testD+11) + { + Fail("memmove: The function did not return the correct " + "string.\n"); + } + + if(memcmp(testD, "aabbccddeefzzz",15) != 0) + { + Fail("memmove: The function failed to move the string " + "correctly.\n"); + } + + PAL_Terminate(); + return PASS; + +} + + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/test1/testinfo.dat new file mode 100644 index 0000000..d8d4c0e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memmove/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = memmove +Name = Positive Test for memmove +TYPE = DEFAULT +EXE1 = test1 +Description += Test that memmove correctly copies text from one buffer to another += even when the buffers overlap. + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/test1/CMakeLists.txt new file mode 100644 index 0000000..bc24ed8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_memset_test1 + ${SOURCES} +) + +add_dependencies(paltest_memset_test1 coreclrpal) + +target_link_libraries(paltest_memset_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/test1/test1.cpp new file mode 100644 index 0000000..67cde87 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/test1/test1.cpp @@ -0,0 +1,60 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Check that memset correctly fills a destination buffer +** without overflowing it. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + + char testA[22] = "bbbbbbbbbbbbbbbbbbbbb"; + char *retVal; + + int i; + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + retVal = (char *)memset(testA, 'a', 20); + if (retVal != testA) + { + Fail("memset should have returned the value of the destination" + "pointer, but didn't"); + } + + for(i = 0; i<20; i++) + { + if (testA[i]!= 'a') + { + Fail("memset didn't set the destination bytes.\n"); + } + } + if (testA[20] == 'a') + { + Fail("memset overfilled the destination buffer.\n"); + } + + PAL_Terminate(); + return PASS; +} + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/test1/testinfo.dat new file mode 100644 index 0000000..cab02fb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/memset/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = memset +Name = Positive Test for memset +TYPE = DEFAULT +EXE1 = test1 +Description += Check that memset correctly fills a destination buffer without overflowing it. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/test1/CMakeLists.txt new file mode 100644 index 0000000..bc9e887 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_modf_test1 + ${SOURCES} +) + +add_dependencies(paltest_modf_test1 coreclrpal) + +target_link_libraries(paltest_modf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/test1/test1.cpp new file mode 100644 index 0000000..389d079 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/test1/test1.cpp @@ -0,0 +1,136 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c (modf) +** +** Purpose: Test to ensure that modf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ + double expected_intpart; /* expected result */ + double variance_intpart; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance, double expected_intpart, double variance_intpart) +{ + double result_intpart; + double result = modf(value, &result_intpart); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + double delta_intpart = fabs(result_intpart - expected_intpart); + + if ((delta > variance) || (delta_intpart > variance_intpart)) + { + Fail("modf(%g) returned %20.17g with an intpart of %20.17g when it should have returned %20.17g with an intpart of %20.17g", + value, result, result_intpart, expected, expected_intpart); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result_intpart; + double result = modf(value, &result_intpart); + + if (!_isnan(result) || !_isnan(result_intpart)) + { + Fail("modf(%g) returned %20.17g with an intpart of %20.17g when it should have returned %20.17g with an intpart of %20.17g", + value, result, result_intpart, PAL_NAN, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance expected_intpart variance_intpart */ + { 0, 0, PAL_EPSILON, 0, PAL_EPSILON }, + { 0.31830988618379067, 0.31830988618379067, PAL_EPSILON, 0, PAL_EPSILON }, // value: 1 / pi + { 0.43429448190325183, 0.43429448190325183, PAL_EPSILON, 0, PAL_EPSILON }, // value: log10(e) + { 0.63661977236758134, 0.63661977236758134, PAL_EPSILON, 0, PAL_EPSILON }, // value: 2 / pi + { 0.69314718055994531, 0.69314718055994531, PAL_EPSILON, 0, PAL_EPSILON }, // value: ln(2) + { 0.70710678118654752, 0.70710678118654752, PAL_EPSILON, 0, PAL_EPSILON }, // value: 1 / sqrt(2) + { 0.78539816339744831, 0.78539816339744831, PAL_EPSILON, 0, PAL_EPSILON }, // value: pi / 4 + { 1, 0, PAL_EPSILON, 1, PAL_EPSILON * 10 }, + { 1.1283791670955126, 0.1283791670955126, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi) + { 1.4142135623730950, 0.4142135623730950, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: sqrt(2) + { 1.4426950408889634, 0.4426950408889634, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: log2(e) + { 1.5707963267948966, 0.5707963267948966, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.3025850929940457, 0.3025850929940457, PAL_EPSILON, 2, PAL_EPSILON * 10 }, // value: ln(10) + { 2.7182818284590452, 0.7182818284590452, PAL_EPSILON, 2, PAL_EPSILON * 10 }, // value: e + { 3.1415926535897932, 0.1415926535897932, PAL_EPSILON, 3, PAL_EPSILON * 10 }, // value: pi + { PAL_POSINF, 0, PAL_EPSILON, PAL_POSINF, 0 } + + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance, tests[i].expected_intpart, tests[i].variance_intpart); + validate(-tests[i].value, -tests[i].expected, tests[i].variance, -tests[i].expected_intpart, tests[i].variance_intpart); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/test1/testinfo.dat new file mode 100644 index 0000000..203b553 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modf/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = modf +Name = Positive Test for modf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to modf() a series of values, checking that += each one return to correct value. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/test1/CMakeLists.txt new file mode 100644 index 0000000..a86d7e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_modff_test1 + ${SOURCES} +) + +add_dependencies(paltest_modff_test1 coreclrpal) + +target_link_libraries(paltest_modff_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/test1/test1.cpp new file mode 100644 index 0000000..6b7a50b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/test1/test1.cpp @@ -0,0 +1,135 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c (modf) +** +** Purpose: Test to ensure that modf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ + float expected_intpart; /* expected result */ + float variance_intpart; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance, float expected_intpart, float variance_intpart) +{ + float result_intpart; + float result = modff(value, &result_intpart); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + float delta_intpart = fabsf(result_intpart - expected_intpart); + + if ((delta > variance) || (delta_intpart > variance_intpart)) + { + Fail("modff(%g) returned %10.9g with an intpart of %10.9g when it should have returned %10.9g with an intpart of %10.9g", + value, result, result_intpart, expected, expected_intpart); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result_intpart; + float result = modff(value, &result_intpart); + + if (!_isnan(result) || !_isnan(result_intpart)) + { + Fail("modff(%g) returned %10.9g with an intpart of %10.9g when it should have returned %10.9g with an intpart of %10.9g", + value, result, result_intpart, PAL_NAN, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance expected_intpart variance_intpart */ + { 0, 0, PAL_EPSILON, 0, PAL_EPSILON }, + { 0.318309886f, 0.318309886f, PAL_EPSILON, 0, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0.434294482f, PAL_EPSILON, 0, PAL_EPSILON }, // value: log10(e) + { 0.636619772f, 0.636619772f, PAL_EPSILON, 0, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0.693147181f, PAL_EPSILON, 0, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0.707106781f, PAL_EPSILON, 0, PAL_EPSILON }, // value: 1 / sqrt(2) + { 0.785398163f, 0.785398163f, PAL_EPSILON, 0, PAL_EPSILON }, // value: pi / 4 + { 1, 0, PAL_EPSILON, 1, PAL_EPSILON * 10 }, + { 1.12837917f, 0.128379167f, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi) + { 1.41421356f, 0.414213562f, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: sqrt(2) + { 1.44269504f, 0.442695041f, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: log2(e) + { 1.57079633f, 0.570796327f, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 0.302585093f, PAL_EPSILON, 2, PAL_EPSILON * 10 }, // value: ln(10) + { 2.71828183f, 0.718281828f, PAL_EPSILON, 2, PAL_EPSILON * 10 }, // value: e + { 3.14159265f, 0.141592654f, PAL_EPSILON, 3, PAL_EPSILON * 10 }, // value: pi + { PAL_POSINF, 0, PAL_EPSILON, PAL_POSINF, 0 } + + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance, tests[i].expected_intpart, tests[i].variance_intpart); + validate(-tests[i].value, -tests[i].expected, tests[i].variance, -tests[i].expected_intpart, tests[i].variance_intpart); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/test1/testinfo.dat new file mode 100644 index 0000000..392491e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/modff/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = modff +Name = Positive Test for modff +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to modff() a series of values, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/test1/CMakeLists.txt new file mode 100644 index 0000000..86ae740 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_pow_test1 + ${SOURCES} +) + +add_dependencies(paltest_pow_test1 coreclrpal) + +target_link_libraries(paltest_pow_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/test1/test1.cpp new file mode 100644 index 0000000..7eea316 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/test1/test1.cpp @@ -0,0 +1,230 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that atan2 returns correct values for a subset of values. +** Tests with positive and negative values of x and y to ensure +** atan2 is returning results from the correct quadrant. +** +**===================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double x; /* first component of the value to test the function with */ + double y; /* second component of the value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double x, double y, double expected, double variance) +{ + double result = pow(x, y); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("pow(%g, %g) returned %20.17g when it should have returned %20.17g", + x, y, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double x, double y) +{ + double result = pow(x, y); + + if (!_isnan(result)) + { + Fail("pow(%g, %g) returned %20.17g when it should have returned %20.17g", + x, y, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* x y expected variance */ + { PAL_NEGINF, PAL_NEGINF, 0, PAL_EPSILON }, + { PAL_NEGINF, PAL_POSINF, PAL_POSINF, 0 }, + + { -10, PAL_NEGINF, 0, PAL_EPSILON }, + { -10, -1, -0.1, PAL_EPSILON }, + { -10, 0, 1, PAL_EPSILON * 10 }, + { -10, 1, -10, PAL_EPSILON * 100 }, + { -10, PAL_POSINF, PAL_POSINF, 0 }, + + { -2.7182818284590452, PAL_NEGINF, 0, PAL_EPSILON }, // x: -(e) + { -2.7182818284590452, -1, -0.36787944117144232, PAL_EPSILON }, // x: -(e) + { -2.7182818284590452, 0, 1, PAL_EPSILON * 10 }, // x: -(e) + { -2.7182818284590452, 1, -2.7182818284590452, PAL_EPSILON * 10 }, // x: -(e) expected: e + { -2.7182818284590452, PAL_POSINF, PAL_POSINF, 0 }, // x: -(e) + + { -1.0, PAL_NEGINF, 1.0, PAL_EPSILON * 10 }, + { -1.0, PAL_POSINF, 1.0, PAL_EPSILON * 10 }, + + { -0.0, PAL_NEGINF, PAL_POSINF, 0 }, + { -0.0, -1, PAL_NEGINF, 0 }, + { -0.0, -0.0, 1, PAL_EPSILON * 10 }, + { -0.0, 0, 1, PAL_EPSILON * 10 }, + { -0.0, 1, -0.0, PAL_EPSILON }, + { -0.0, PAL_POSINF, 0, PAL_EPSILON }, + + { PAL_NAN, -0.0, 1.0, PAL_EPSILON * 10 }, + { PAL_NAN, 0, 1.0, PAL_EPSILON * 10 }, + + { 0.0, PAL_NEGINF, PAL_POSINF, 0 }, + { 0.0, -1, PAL_POSINF, 0 }, + { 0, -0.0, 1, PAL_EPSILON * 10 }, + { 0, 0, 1, PAL_EPSILON * 10 }, + { 0.0, 1, 0, PAL_EPSILON }, + { 0.0, PAL_POSINF, 0, PAL_EPSILON }, + + { 1, PAL_NEGINF, 1, PAL_EPSILON * 10 }, + { 1, PAL_POSINF, 1, PAL_EPSILON * 10 }, + + { 2.7182818284590452, PAL_NEGINF, 0, PAL_EPSILON }, + { 2.7182818284590452, -3.1415926535897932, 0.043213918263772250, PAL_EPSILON / 10 }, // x: e y: -(pi) + { 2.7182818284590452, -2.7182818284590452, 0.065988035845312537, PAL_EPSILON / 10 }, // x: e y: -(e) + { 2.7182818284590452, -2.3025850929940457, 0.1, PAL_EPSILON }, // x: e y: -(ln(10)) + { 2.7182818284590452, -1.5707963267948966, 0.20787957635076191, PAL_EPSILON }, // x: e y: -(pi / 2) + { 2.7182818284590452, -1.4426950408889634, 0.23629008834452270, PAL_EPSILON }, // x: e y: -(log2(e)) + { 2.7182818284590452, -1.4142135623730950, 0.24311673443421421, PAL_EPSILON }, // x: e y: -(sqrt(2)) + { 2.7182818284590452, -1.1283791670955126, 0.32355726390307110, PAL_EPSILON }, // x: e y: -(2 / sqrt(pi)) + { 2.7182818284590452, -1, 0.36787944117144232, PAL_EPSILON }, // x: e y: -(1) + { 2.7182818284590452, -0.78539816339744831, 0.45593812776599624, PAL_EPSILON }, // x: e y: -(pi / 4) + { 2.7182818284590452, -0.70710678118654752, 0.49306869139523979, PAL_EPSILON }, // x: e y: -(1 / sqrt(2)) + { 2.7182818284590452, -0.69314718055994531, 0.5, PAL_EPSILON }, // x: e y: -(ln(2)) + { 2.7182818284590452, -0.63661977236758134, 0.52907780826773535, PAL_EPSILON }, // x: e y: -(2 / pi) + { 2.7182818284590452, -0.43429448190325183, 0.64772148514180065, PAL_EPSILON }, // x: e y: -(log10(e)) + { 2.7182818284590452, -0.31830988618379067, 0.72737734929521647, PAL_EPSILON }, // x: e y: -(1 / pi) + { 2.7182818284590452, 0, 1, PAL_EPSILON * 10 }, // x: e + { 2.7182818284590452, 0.31830988618379067, 1.3748022274393586, PAL_EPSILON * 10 }, // x: e y: 1 / pi + { 2.7182818284590452, 0.43429448190325183, 1.5438734439711811, PAL_EPSILON * 10 }, // x: e y: log10(e) + { 2.7182818284590452, 0.63661977236758134, 1.8900811645722220, PAL_EPSILON * 10 }, // x: e y: 2 / pi + { 2.7182818284590452, 0.69314718055994531, 2, PAL_EPSILON * 10 }, // x: e y: ln(2) + { 2.7182818284590452, 0.70710678118654752, 2.0281149816474725, PAL_EPSILON * 10 }, // x: e y: 1 / sqrt(2) + { 2.7182818284590452, 0.78539816339744831, 2.1932800507380155, PAL_EPSILON * 10 }, // x: e y: pi / 4 + { 2.7182818284590452, 1, 2.7182818284590452, PAL_EPSILON * 10 }, // x: e expected: e + { 2.7182818284590452, 1.1283791670955126, 3.0906430223107976, PAL_EPSILON * 10 }, // x: e y: 2 / sqrt(pi) + { 2.7182818284590452, 1.4142135623730950, 4.1132503787829275, PAL_EPSILON * 10 }, // x: e y: sqrt(2) + { 2.7182818284590452, 1.4426950408889634, 4.2320861065570819, PAL_EPSILON * 10 }, // x: e y: log2(e) + { 2.7182818284590452, 1.5707963267948966, 4.8104773809653517, PAL_EPSILON * 10 }, // x: e y: pi / 2 + { 2.7182818284590452, 2.3025850929940457, 10, PAL_EPSILON * 100 }, // x: e y: ln(10) + { 2.7182818284590452, 2.7182818284590452, 15.154262241479264, PAL_EPSILON * 100 }, // x: e y: e + { 2.7182818284590452, 3.1415926535897932, 23.140692632779269, PAL_EPSILON * 100 }, // x: e y: pi + { 2.7182818284590452, PAL_POSINF, PAL_POSINF, 0 }, // x: e + + { 10, PAL_NEGINF, 0, 0 }, + { 10, -3.1415926535897932, 0.00072178415907472774, PAL_EPSILON / 1000 }, // y: -(pi) + { 10, -2.7182818284590452, 0.0019130141022243176, PAL_EPSILON / 100 }, // y: -(e) + { 10, -2.3025850929940457, 0.0049821282964407206, PAL_EPSILON / 100 }, // y: -(ln(10)) + { 10, -1.5707963267948966, 0.026866041001136132, PAL_EPSILON / 10 }, // y: -(pi / 2) + { 10, -1.4426950408889634, 0.036083192820787210, PAL_EPSILON / 10 }, // y: -(log2(e)) + { 10, -1.4142135623730950, 0.038528884700322026, PAL_EPSILON / 10 }, // y: -(sqrt(2)) + { 10, -1.1283791670955126, 0.074408205860642723, PAL_EPSILON / 10 }, // y: -(2 / sqrt(pi)) + { 10, -1, 0.1, PAL_EPSILON }, // y: -(1) + { 10, -0.78539816339744831, 0.16390863613957665, PAL_EPSILON }, // y: -(pi / 4) + { 10, -0.70710678118654752, 0.19628775993505562, PAL_EPSILON }, // y: -(1 / sqrt(2)) + { 10, -0.69314718055994531, 0.20269956628651730, PAL_EPSILON }, // y: -(ln(2)) + { 10, -0.63661977236758134, 0.23087676451600055, PAL_EPSILON }, // y: -(2 / pi) + { 10, -0.43429448190325183, 0.36787944117144232, PAL_EPSILON }, // y: -(log10(e)) + { 10, -0.31830988618379067, 0.48049637305186868, PAL_EPSILON }, // y: -(1 / pi) + { 10, 0, 1, PAL_EPSILON * 10 }, + { 10, 0.31830988618379067, 2.0811811619898573, PAL_EPSILON * 10 }, // y: 1 / pi + { 10, 0.43429448190325183, 2.7182818284590452, PAL_EPSILON * 10 }, // y: log10(e) expected: e + { 10, 0.63661977236758134, 4.3313150290214525, PAL_EPSILON * 10 }, // y: 2 / pi + { 10, 0.69314718055994531, 4.9334096679145963, PAL_EPSILON * 10 }, // y: ln(2) + { 10, 0.70710678118654752, 5.0945611704512962, PAL_EPSILON * 10 }, // y: 1 / sqrt(2) + { 10, 0.78539816339744831, 6.1009598002416937, PAL_EPSILON * 10 }, // y: pi / 4 + { 10, 1, 10, PAL_EPSILON * 100 }, + { 10, 1.1283791670955126, 13.439377934644400, PAL_EPSILON * 100 }, // y: 2 / sqrt(pi) + { 10, 1.4142135623730950, 25.954553519470081, PAL_EPSILON * 100 }, // y: sqrt(2) + { 10, 1.4426950408889634, 27.713733786437790, PAL_EPSILON * 100 }, // y: log2(e) + { 10, 1.5707963267948966, 37.221710484165167, PAL_EPSILON * 100 }, // y: pi / 2 + { 10, 2.3025850929940457, 200.71743249053009, PAL_EPSILON * 1000 }, // y: ln(10) + { 10, 2.7182818284590452, 522.73529967043665, PAL_EPSILON * 1000 }, // y: e + { 10, 3.1415926535897932, 1385.4557313670111, PAL_EPSILON * 10000 }, // y: pi + { 10, PAL_POSINF, PAL_POSINF, 0 }, + + { PAL_POSINF, PAL_NEGINF, 0, PAL_EPSILON }, + { PAL_POSINF, PAL_POSINF, PAL_POSINF, 0 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].x, tests[i].y, tests[i].expected, tests[i].variance); + } + + validate_isnan(-10, -1.5707963267948966); // y: -(pi / 2) + validate_isnan(-10, -0.78539816339744828); // y: -(pi / 4) + validate_isnan(-10, 0.78539816339744828); // y: pi / 4 + validate_isnan(-10, 1.5707963267948966); // y: pi / 2 + + validate_isnan(-2.7182818284590452, -1.5707963267948966); // x: -(e) y: -(pi / 2) + validate_isnan(-2.7182818284590452, -0.78539816339744828); // x: -(e) y: -(pi / 4) + validate_isnan(-2.7182818284590452, 0.78539816339744828); // x: -(e) y: pi / 4 + validate_isnan(-2.7182818284590452, 1.5707963267948966); // x: -(e) y: pi / 2 + + validate_isnan(PAL_NEGINF, PAL_NAN); + validate_isnan(PAL_NAN, PAL_NEGINF); + + validate_isnan(PAL_POSINF, PAL_NAN); + validate_isnan(PAL_NAN, PAL_POSINF); + + validate_isnan(PAL_NAN, PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/test1/testinfo.dat new file mode 100644 index 0000000..cf106d9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/pow/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = pow +Name = Call pow with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the pow function with various num/exponent pairs += that should produce std answers. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/test1/CMakeLists.txt new file mode 100644 index 0000000..53443f1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_powf_test1 + ${SOURCES} +) + +add_dependencies(paltest_powf_test1 coreclrpal) + +target_link_libraries(paltest_powf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/test1/test1.c new file mode 100644 index 0000000..e8933c5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/test1/test1.c @@ -0,0 +1,229 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that atan2f returns correct values for a subset of values. +** Tests with positive and negative values of x and y to ensure +** atan2f is returning results from the correct quadrant. +** +**===================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float x; /* first component of the value to test the function with */ + float y; /* second component of the value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float x, float y, float expected, float variance) +{ + float result = powf(x, y); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("powf(%g, %g) returned %10.9g when it should have returned %10.9g", + x, y, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float x, float y) +{ + float result = powf(x, y); + + if (!_isnanf(result)) + { + Fail("powf(%g, %g) returned %10.9g when it should have returned %10.9g", + x, y, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* x y expected variance */ + { PAL_NEGINF, PAL_NEGINF, 0, PAL_EPSILON }, + { PAL_NEGINF, PAL_POSINF, PAL_POSINF, 0 }, + + { -10, PAL_NEGINF, 0, PAL_EPSILON }, + { -10, -1, -0.1f, PAL_EPSILON }, + { -10, 0, 1, PAL_EPSILON * 10 }, + { -10, 1, -10, PAL_EPSILON * 100 }, + { -10, PAL_POSINF, PAL_POSINF, 0 }, + + { -2.71828183f, PAL_NEGINF, 0, PAL_EPSILON }, // x: -(e) + { -2.71828183f, -1, -0.367879441f, PAL_EPSILON }, // x: -(e) + { -2.71828183f, 0, 1, PAL_EPSILON * 10 }, // x: -(e) + { -2.71828183f, 1, -2.71828183f, PAL_EPSILON * 10 }, // x: -(e) expected: e + { -2.71828183f, PAL_POSINF, PAL_POSINF, 0 }, // x: -(e) + + { -1.0, PAL_NEGINF, 1.0, PAL_EPSILON * 10 }, + { -1.0, PAL_POSINF, 1.0, PAL_EPSILON * 10 }, + + { -0.0, PAL_NEGINF, PAL_POSINF, 0 }, + { -0.0, -1, PAL_NEGINF, 0 }, + { -0.0f, -0.0f, 1, PAL_EPSILON * 10 }, + { -0.0f, 0, 1, PAL_EPSILON * 10 }, + { -0.0, 1, -0.0, PAL_EPSILON }, + { -0.0, PAL_POSINF, 0, PAL_EPSILON }, + + { PAL_NAN, -0.0, 1.0, PAL_EPSILON * 10 }, + { PAL_NAN, 0, 1.0, PAL_EPSILON * 10 }, + + { 0.0, PAL_NEGINF, PAL_POSINF, 0 }, + { 0.0, -1, PAL_POSINF, 0 }, + { 0, -0.0f, 1, PAL_EPSILON * 10 }, + { 0, 0, 1, PAL_EPSILON * 10 }, + { 0.0, 1, 0, PAL_EPSILON }, + { 0.0, PAL_POSINF, 0, PAL_EPSILON }, + + { 1, PAL_NEGINF, 1, PAL_EPSILON * 10 }, + { 1, PAL_POSINF, 1, PAL_EPSILON * 10 }, + + { 2.71828183f, PAL_NEGINF, 0, PAL_EPSILON }, + { 2.71828183f, -3.14159265f, 0.0432139183f, PAL_EPSILON / 10 }, // x: e y: -(pi) + { 2.71828183f, -2.71828183f, 0.0659880358f, PAL_EPSILON / 10 }, // x: e y: -(e) + { 2.71828183f, -2.30258509f, 0.1f, PAL_EPSILON }, // x: e y: -(ln(10)) + { 2.71828183f, -1.57079633f, 0.207879576f, PAL_EPSILON }, // x: e y: -(pi / 2) + { 2.71828183f, -1.44269504f, 0.236290088f, PAL_EPSILON }, // x: e y: -(logf2(e)) + { 2.71828183f, -1.41421356f, 0.243116734f, PAL_EPSILON }, // x: e y: -(sqrtf(2)) + { 2.71828183f, -1.12837917f, 0.323557264f, PAL_EPSILON }, // x: e y: -(2 / sqrtf(pi)) + { 2.71828183f, -1, 0.367879441f, PAL_EPSILON }, // x: e y: -(1) + { 2.71828183f, -0.785398163f, 0.455938128f, PAL_EPSILON }, // x: e y: -(pi / 4) + { 2.71828183f, -0.707106781f, 0.493068691f, PAL_EPSILON }, // x: e y: -(1 / sqrtf(2)) + { 2.71828183f, -0.693147181f, 0.5f, PAL_EPSILON }, // x: e y: -(ln(2)) + { 2.71828183f, -0.636619772f, 0.529077808f, PAL_EPSILON }, // x: e y: -(2 / pi) + { 2.71828183f, -0.434294482f, 0.647721485f, PAL_EPSILON }, // x: e y: -(log10f(e)) + { 2.71828183f, -0.318309886f, 0.727377349f, PAL_EPSILON }, // x: e y: -(1 / pi) + { 2.71828183f, 0, 1, PAL_EPSILON * 10 }, // x: e + { 2.71828183f, 0.318309886f, 1.37480223f, PAL_EPSILON * 10 }, // x: e y: 1 / pi + { 2.71828183f, 0.434294482f, 1.54387344f, PAL_EPSILON * 10 }, // x: e y: log10f(e) + { 2.71828183f, 0.636619772f, 1.89008116f, PAL_EPSILON * 10 }, // x: e y: 2 / pi + { 2.71828183f, 0.693147181f, 2, PAL_EPSILON * 10 }, // x: e y: ln(2) + { 2.71828183f, 0.707106781f, 2.02811498f, PAL_EPSILON * 10 }, // x: e y: 1 / sqrtf(2) + { 2.71828183f, 0.785398163f, 2.19328005f, PAL_EPSILON * 10 }, // x: e y: pi / 4 + { 2.71828183f, 1, 2.71828183f, PAL_EPSILON * 10 }, // x: e expected: e + { 2.71828183f, 1.12837917f, 3.09064302f, PAL_EPSILON * 10 }, // x: e y: 2 / sqrtf(pi) + { 2.71828183f, 1.41421356f, 4.11325038f, PAL_EPSILON * 10 }, // x: e y: sqrtf(2) + { 2.71828183f, 1.44269504f, 4.23208611f, PAL_EPSILON * 10 }, // x: e y: logf2(e) + { 2.71828183f, 1.57079633f, 4.81047738f, PAL_EPSILON * 10 }, // x: e y: pi / 2 + { 2.71828183f, 2.30258509f, 10, PAL_EPSILON * 100 }, // x: e y: ln(10) + { 2.71828183f, 2.71828183f, 15.1542622f, PAL_EPSILON * 100 }, // x: e y: e + { 2.71828183f, 3.14159265f, 23.1406926f, PAL_EPSILON * 100 }, // x: e y: pi + { 2.71828183f, PAL_POSINF, PAL_POSINF, 0 }, // x: e + + { 10, PAL_NEGINF, 0, 0 }, + { 10, -3.14159265f, 0.000721784159f, PAL_EPSILON / 1000 }, // y: -(pi) + { 10, -2.71828183f, 0.00191301410f, PAL_EPSILON / 100 }, // y: -(e) + { 10, -2.30258509f, 0.00498212830f, PAL_EPSILON / 100 }, // y: -(ln(10)) + { 10, -1.57079633f, 0.0268660410f, PAL_EPSILON / 10 }, // y: -(pi / 2) + { 10, -1.44269504f, 0.0360831928f, PAL_EPSILON / 10 }, // y: -(logf2(e)) + { 10, -1.41421356f, 0.0385288847f, PAL_EPSILON / 10 }, // y: -(sqrtf(2)) + { 10, -1.12837917f, 0.0744082059f, PAL_EPSILON / 10 }, // y: -(2 / sqrtf(pi)) + { 10, -1, 0.1f, PAL_EPSILON }, // y: -(1) + { 10, -0.785398163f, 0.163908636f, PAL_EPSILON }, // y: -(pi / 4) + { 10, -0.707106781f, 0.196287760f, PAL_EPSILON }, // y: -(1 / sqrtf(2)) + { 10, -0.693147181f, 0.202699566f, PAL_EPSILON }, // y: -(ln(2)) + { 10, -0.636619772f, 0.230876765f, PAL_EPSILON }, // y: -(2 / pi) + { 10, -0.434294482f, 0.367879441f, PAL_EPSILON }, // y: -(log10f(e)) + { 10, -0.318309886f, 0.480496373f, PAL_EPSILON }, // y: -(1 / pi) + { 10, 0, 1, PAL_EPSILON * 10 }, + { 10, 0.318309886f, 2.08118116f, PAL_EPSILON * 10 }, // y: 1 / pi + { 10, 0.434294482f, 2.71828183f, PAL_EPSILON * 10 }, // y: log10f(e) expected: e + { 10, 0.636619772f, 4.33131503f, PAL_EPSILON * 10 }, // y: 2 / pi + { 10, 0.693147181f, 4.93340967f, PAL_EPSILON * 10 }, // y: ln(2) + { 10, 0.707106781f, 5.09456117f, PAL_EPSILON * 10 }, // y: 1 / sqrtf(2) + { 10, 0.785398163f, 6.10095980f, PAL_EPSILON * 10 }, // y: pi / 4 + { 10, 1, 10, PAL_EPSILON * 100 }, + { 10, 1.12837917f, 13.4393779f, PAL_EPSILON * 100 }, // y: 2 / sqrtf(pi) + { 10, 1.41421356f, 25.9545535f, PAL_EPSILON * 100 }, // y: sqrtf(2) + { 10, 1.44269504f, 27.7137338f, PAL_EPSILON * 100 }, // y: logf2(e) + { 10, 1.57079633f, 37.2217105f, PAL_EPSILON * 100 }, // y: pi / 2 + { 10, 2.30258509f, 200.717432f, PAL_EPSILON * 1000 }, // y: ln(10) + { 10, 2.71828183f, 522.735300f, PAL_EPSILON * 1000 }, // y: e + { 10, 3.14159265f, 1385.45573f, PAL_EPSILON * 10000 }, // y: pi + { 10, PAL_POSINF, PAL_POSINF, 0 }, + + { PAL_POSINF, PAL_NEGINF, 0, PAL_EPSILON }, + { PAL_POSINF, PAL_POSINF, PAL_POSINF, 0 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].x, tests[i].y, tests[i].expected, tests[i].variance); + } + + validate_isnan(-10, -1.57079633f); // y: -(pi / 2) + validate_isnan(-10, -0.785398163f); // y: -(pi / 4) + validate_isnan(-10, 0.785398163f); // y: pi / 4 + validate_isnan(-10, 1.57079633f); // y: pi / 2 + + validate_isnan(-2.71828183f, -1.57079633f); // x: -(e) y: -(pi / 2) + validate_isnan(-2.71828183f, -0.785398163f); // x: -(e) y: -(pi / 4) + validate_isnan(-2.71828183f, 0.785398163f); // x: -(e) y: pi / 4 + validate_isnan(-2.71828183f, 1.57079633f); // x: -(e) y: pi / 2 + + validate_isnan(PAL_NEGINF, PAL_NAN); + validate_isnan(PAL_NAN, PAL_NEGINF); + + validate_isnan(PAL_POSINF, PAL_NAN); + validate_isnan(PAL_NAN, PAL_POSINF); + + validate_isnan(PAL_NAN, PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/test1/testinfo.dat new file mode 100644 index 0000000..778c042 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/powf/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = powf +Name = Call powf with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the powf function with various num/expfonent pairs += that should produce std answers. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/CMakeLists.txt new file mode 100644 index 0000000..256753a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/CMakeLists.txt @@ -0,0 +1,20 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/printf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/printf.h new file mode 100644 index 0000000..8ef725f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/printf.h @@ -0,0 +1,182 @@ +// 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. + +/*============================================================================ +** +** Source: printf.h +** +** Purpose: Containts common testing functions for printf +** +** +**==========================================================================*/ + +#ifndef __printf_H__ +#define __printf_H__ + +void DoStrTest(const char *formatstr, char* param, const char *checkstr) +{ + int ret; + + ret = printf(formatstr, param); + if (ret != strlen(checkstr)) + { + Fail("Expected printf to return %d, got %d.\n", + strlen(checkstr), ret); + } +} + +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) +{ + int ret; + + ret = printf(formatstr, param); + if (ret != strlen(checkstr)) + { + Fail("Expected printf to return %d, got %d.\n", + strlen(checkstr), ret); + } +} + +void DoPointerTest(const char *formatstr, void* param, char* paramstr, + const char *checkstr1) +{ + int ret; + + ret = printf(formatstr, param); + if (ret != strlen(checkstr1)) + { + Fail("Expected printf to return %d, got %d.\n", + strlen(checkstr1), ret); + } +} + +void DoCountTest(const char *formatstr, int param, const char *checkstr) +{ + int ret; + int n = -1; + + ret = printf(formatstr, &n); + + if (n != param) + { + Fail("Expected count parameter to resolve to %d, got %d\n", param, n); + } + + if (ret != strlen(checkstr)) + { + Fail("Expected printf to return %d, got %d.\n", + strlen(checkstr), ret); + } +} + +void DoShortCountTest(const char *formatstr, int param, const char *checkstr) +{ + int ret; + short int n = -1; + + ret = printf(formatstr, &n); + + if (n != param) + { + Fail("Expected count parameter to resolve to %d, got %d\n", param, n); + } + + if (ret != strlen(checkstr)) + { + Fail("Expected printf to return %d, got %d.\n", + strlen(checkstr), ret); + } +} + + +void DoCharTest(const char *formatstr, char param, const char *checkstr) +{ + int ret; + + ret = printf(formatstr, param); + if (ret != strlen(checkstr)) + { + Fail("Expected printf to return %d, got %d.\n", + strlen(checkstr), ret); + } +} + +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) +{ + int ret; + + ret = printf(formatstr, param); + if (ret != strlen(checkstr)) + { + Fail("Expected printf to return %d, got %d.\n", + strlen(checkstr), ret); + } +} + +void DoNumTest(const char *formatstr, int param, const char *checkstr) +{ + int ret; + + ret = printf(formatstr, param); + if (ret != strlen(checkstr)) + { + Fail("Expected printf to return %d, got %d.\n", + strlen(checkstr), ret); + } +} + +void DoI64Test(const char *formatstr, INT64 param, char *valuestr, + const char *checkstr1) +{ + int ret; + + ret = printf(formatstr, param); + if (ret != strlen(checkstr1)) + { + Fail("Expected printf to return %d, got %d.\n", + strlen(checkstr1), ret); + } +} + +void DoDoubleTest(const char *formatstr, double param, + const char *checkstr1, const char *checkstr2) +{ + int ret; + + ret = printf(formatstr, param); + if (ret != strlen(checkstr1) && ret != strlen(checkstr2)) + { + Fail("Expected printf to return %d or %d, got %d.\n", + strlen(checkstr1), strlen(checkstr2), ret); + } +} + +void DoArgumentPrecTest(const char *formatstr, int precision, void *param, + char *paramstr, const char *checkstr1, const char *checkstr2) +{ + int ret; + + ret = printf(formatstr, precision, param); + if (ret != strlen(checkstr1) && ret != strlen(checkstr2)) + { + Fail("Expected printf to return %d or %d, got %d.\n", + strlen(checkstr1), strlen(checkstr2), ret); + } +} + +void DoArgumentPrecDoubleTest(const char *formatstr, int precision, double param, + const char *checkstr1, const char *checkstr2) +{ + int ret; + + ret = printf(formatstr, precision, param); + if (ret != strlen(checkstr1) && ret != strlen(checkstr2)) + { + Fail("Expected printf to return %d or %d, got %d.\n", + strlen(checkstr1), strlen(checkstr2), ret); + } +} + +#endif + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test1/CMakeLists.txt new file mode 100644 index 0000000..f3cce9c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_printf_test1 + ${SOURCES} +) + +add_dependencies(paltest_printf_test1 coreclrpal) + +target_link_libraries(paltest_printf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test1/test1.cpp new file mode 100644 index 0000000..31b7014 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test1/test1.cpp @@ -0,0 +1,43 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Test #1 for the printf function. A single, basic, test +** case with no formatting. +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + +int __cdecl main(int argc, char *argv[]) +{ + char checkstr[] = "hello world"; + int ret; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + ret = printf("hello world"); + + if (ret != strlen(checkstr)) + { + Fail("Expected printf to return %d, got %d.\n", + strlen(checkstr), ret); + + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test1/testinfo.dat new file mode 100644 index 0000000..fe8bee6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test1 +Description += General test to see if printf works correctly diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test10/CMakeLists.txt new file mode 100644 index 0000000..5fa2311 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_printf_test10 + ${SOURCES} +) + +add_dependencies(paltest_printf_test10 coreclrpal) + +target_link_libraries(paltest_printf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test10/test10.cpp new file mode 100644 index 0000000..5e69175 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test10/test10.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================================ +** +** Source: test10.c +** +** Purpose: Test #10 for the printf function. Tests the octal specifier +** (%o). +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %o", pos, "foo 52"); + DoNumTest("foo %lo", 0xFFFF, "foo 177777"); + DoNumTest("foo %ho", 0xFFFF, "foo 177777"); + DoNumTest("foo %Lo", pos, "foo 52"); + DoI64Test("foo %I64o", l, "42", "foo 52"); + DoNumTest("foo %3o", pos, "foo 52"); + DoNumTest("foo %-3o", pos, "foo 52 "); + DoNumTest("foo %.1o", pos, "foo 52"); + DoNumTest("foo %.3o", pos, "foo 052"); + DoNumTest("foo %03o", pos, "foo 052"); + DoNumTest("foo %#o", pos, "foo 052"); + DoNumTest("foo %+o", pos, "foo 52"); + DoNumTest("foo % o", pos, "foo 52"); + DoNumTest("foo %+o", neg, "foo 37777777726"); + DoNumTest("foo % o", neg, "foo 37777777726"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test10/testinfo.dat new file mode 100644 index 0000000..7667a0f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test10/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test10 +Description += Tests printf with octal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test11/CMakeLists.txt new file mode 100644 index 0000000..52b7202 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_printf_test11 + ${SOURCES} +) + +add_dependencies(paltest_printf_test11 coreclrpal) + +target_link_libraries(paltest_printf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test11/test11.cpp new file mode 100644 index 0000000..788be8b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test11/test11.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test11.c +** +** Purpose: Test #11 for the printf function. Test the unsigned int +** specifier (%u). +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %u", pos, "foo 42"); + DoNumTest("foo %lu", 0xFFFF, "foo 65535"); + DoNumTest("foo %hu", 0xFFFF, "foo 65535"); + DoNumTest("foo %Lu", pos, "foo 42"); + DoI64Test("foo %I64u", l, "42", "foo 42"); + DoNumTest("foo %3u", pos, "foo 42"); + DoNumTest("foo %-3u", pos, "foo 42 "); + DoNumTest("foo %.1u", pos, "foo 42"); + DoNumTest("foo %.3u", pos, "foo 042"); + DoNumTest("foo %03u", pos, "foo 042"); + DoNumTest("foo %#u", pos, "foo 42"); + DoNumTest("foo %+u", pos, "foo 42"); + DoNumTest("foo % u", pos, "foo 42"); + DoNumTest("foo %+u", neg, "foo 4294967254"); + DoNumTest("foo % u", neg, "foo 4294967254"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test11/testinfo.dat new file mode 100644 index 0000000..a88e0d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test11/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test11 +Description += Tests printf with unsigned numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test12/CMakeLists.txt new file mode 100644 index 0000000..aa19c4b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_printf_test12 + ${SOURCES} +) + +add_dependencies(paltest_printf_test12 coreclrpal) + +target_link_libraries(paltest_printf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test12/test12.cpp new file mode 100644 index 0000000..b4006f2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test12/test12.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Test #12 for the printf function. Tests the (lowercase) +** hexadecimal specifier (%x) +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %x", pos, "foo 1234ab"); + DoNumTest("foo %lx", pos, "foo 1234ab"); + DoNumTest("foo %hx", pos, "foo 34ab"); + DoNumTest("foo %Lx", pos, "foo 1234ab"); + DoI64Test("foo %I64x", l, "0x1234567887654321", + "foo 1234567887654321"); + DoNumTest("foo %7x", pos, "foo 1234ab"); + DoNumTest("foo %-7x", pos, "foo 1234ab "); + DoNumTest("foo %.1x", pos, "foo 1234ab"); + DoNumTest("foo %.7x", pos, "foo 01234ab"); + DoNumTest("foo %07x", pos, "foo 01234ab"); + DoNumTest("foo %#x", pos, "foo 0x1234ab"); + DoNumTest("foo %+x", pos, "foo 1234ab"); + DoNumTest("foo % x", pos, "foo 1234ab"); + DoNumTest("foo %+x", neg, "foo ffffffd6"); + DoNumTest("foo % x", neg, "foo ffffffd6"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test12/testinfo.dat new file mode 100644 index 0000000..a6e317f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test12/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test12 +Description += Tests printf with hex numbers (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test13/CMakeLists.txt new file mode 100644 index 0000000..e715bdd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_printf_test13 + ${SOURCES} +) + +add_dependencies(paltest_printf_test13 coreclrpal) + +target_link_libraries(paltest_printf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test13/test13.cpp new file mode 100644 index 0000000..ccd16b5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test13/test13.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test13.c +** +** Purpose: Test #13 for the printf function. Tests the (uppercase) +** hexadecimal specifier (%X) +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234AB; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %X", pos, "foo 1234AB"); + DoNumTest("foo %lX", pos, "foo 1234AB"); + DoNumTest("foo %hX", pos, "foo 34AB"); + DoNumTest("foo %LX", pos, "foo 1234AB"); + DoI64Test("foo %I64X", l, "0x1234567887654321", + "foo 1234567887654321"); + DoNumTest("foo %7X", pos, "foo 1234AB"); + DoNumTest("foo %-7X", pos, "foo 1234AB "); + DoNumTest("foo %.1X", pos, "foo 1234AB"); + DoNumTest("foo %.7X", pos, "foo 01234AB"); + DoNumTest("foo %07X", pos, "foo 01234AB"); + DoNumTest("foo %#X", pos, "foo 0X1234AB"); + DoNumTest("foo %+X", pos, "foo 1234AB"); + DoNumTest("foo % X", pos, "foo 1234AB"); + DoNumTest("foo %+X", neg, "foo FFFFFFD6"); + DoNumTest("foo % X", neg, "foo FFFFFFD6"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test13/testinfo.dat new file mode 100644 index 0000000..e814040 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test13/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test13 +Description += Tests printf with hex numbers (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test14/CMakeLists.txt new file mode 100644 index 0000000..878392a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_printf_test14 + ${SOURCES} +) + +add_dependencies(paltest_printf_test14 coreclrpal) + +target_link_libraries(paltest_printf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test14/test14.cpp new file mode 100644 index 0000000..10577db --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test14/test14.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test14.c +** +** Purpose: Test #14 for the printf function. Tests the lowercase +** exponential notation double specifier (%e) +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", + "foo 2.560000e+02 "); + DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02"); + DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", + "foo 2.56000000e+02"); + DoDoubleTest("foo %014e", val, "foo 02.560000e+002", + "foo 002.560000e+02"); + DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02"); + DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test14/testinfo.dat new file mode 100644 index 0000000..5cb22c1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test14/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test14 +Description += Tests printf with exponential format doubles (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test15/CMakeLists.txt new file mode 100644 index 0000000..7630cbb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_printf_test15 + ${SOURCES} +) + +add_dependencies(paltest_printf_test15 coreclrpal) + +target_link_libraries(paltest_printf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test15/test15.cpp new file mode 100644 index 0000000..2acfc43 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test15/test15.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test15.c +** +** Purpose: Test #15 for the printf function. Tests the uppercase +** exponential notation double specifier (%E) +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %14E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", + "foo 2.560000E+02 "); + DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02"); + DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", + "foo 2.56000000E+02"); + DoDoubleTest("foo %014E", val, "foo 02.560000E+002", + "foo 002.560000E+02"); + DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02"); + DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test15/testinfo.dat new file mode 100644 index 0000000..bdfa2cc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test15/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test15 +Description += Tests printf with exponential format doubles (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test16/CMakeLists.txt new file mode 100644 index 0000000..6d4082e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_printf_test16 + ${SOURCES} +) + +add_dependencies(paltest_printf_test16 coreclrpal) + +target_link_libraries(paltest_printf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test16/test16.cpp new file mode 100644 index 0000000..50c952f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test16/test16.cpp @@ -0,0 +1,50 @@ +// 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. + +/*============================================================================ +** +** Source: test16.c +** +** Purpose: Test #16 for the printf function. Tests the decimal notation +** double specifier (%f) +** +** +**==========================================================================*/ + + +#include +#include "../printf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 "); + DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0"); + DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000"); + DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000"); + DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000"); + DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000"); + DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test16/testinfo.dat new file mode 100644 index 0000000..afb9a21 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test16/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test16 +Description += Tests printf with decimal point format doubles diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test17/CMakeLists.txt new file mode 100644 index 0000000..3873af8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_printf_test17 + ${SOURCES} +) + +add_dependencies(paltest_printf_test17 coreclrpal) + +target_link_libraries(paltest_printf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test17/test17.cpp new file mode 100644 index 0000000..96ddd5c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test17/test17.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================================ +** +** Source: test17.c +** +** Purpose: Test #17 for the printf function. Tests the lowercase +** shorthand notation double specifier (%g) +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03"); + DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03"); + DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test17/testinfo.dat new file mode 100644 index 0000000..a8545d9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test17/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test17 +Description += Tests printf with compact format doubles (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test18/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test18/CMakeLists.txt new file mode 100644 index 0000000..7579135 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test18/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test18.cpp +) + +add_executable(paltest_printf_test18 + ${SOURCES} +) + +add_dependencies(paltest_printf_test18 coreclrpal) + +target_link_libraries(paltest_printf_test18 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test18/test18.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test18/test18.cpp new file mode 100644 index 0000000..6c05e40 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test18/test18.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test18.c +** +** Purpose: Test #18 for the printf function. Tests the uppercase +** shorthand notation double specifier (%G) +** +** +**==========================================================================*/ + + +#include +#include "../printf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03"); + DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03"); + DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test18/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test18/testinfo.dat new file mode 100644 index 0000000..bd5c90b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test18/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test18 +Description += Tests printf with compact format doubles (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test19/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test19/CMakeLists.txt new file mode 100644 index 0000000..98321bc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test19/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test19.cpp +) + +add_executable(paltest_printf_test19 + ${SOURCES} +) + +add_dependencies(paltest_printf_test19 coreclrpal) + +target_link_libraries(paltest_printf_test19 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test19/test19.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test19/test19.cpp new file mode 100644 index 0000000..a3ce0e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test19/test19.cpp @@ -0,0 +1,76 @@ +// 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. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose: Test #19 for the printf function. Tests the variable length +** precision argument. +** +** +**==========================================================================*/ + + +#include +#include "../printf.h" + + + + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoArgumentPrecTest("%.*s", 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest("%.*S", 2, (void*)convert("bar"), "bar", "ba", "ba"); + + DoArgumentPrecTest("%.*n", 3, (void*)&n, "pointer to int", "", ""); + if (n != 0) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + 0, n); + } + + DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test19/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test19/testinfo.dat new file mode 100644 index 0000000..6ad18f7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test19/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test19 +Description += Tests printf with argument specified precision diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test2/CMakeLists.txt new file mode 100644 index 0000000..7208d56 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_printf_test2 + ${SOURCES} +) + +add_dependencies(paltest_printf_test2 coreclrpal) + +target_link_libraries(paltest_printf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test2/test2.cpp new file mode 100644 index 0000000..1c61b1d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test2/test2.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Test #2 for the printf function. Tests the string specifier +** (%s). +** +** +**==========================================================================*/ + + +#include +#include "../printf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoStrTest("foo %s", "bar", "foo bar"); + DoStrTest("foo %hs", "bar", "foo bar"); + DoWStrTest("foo %ls", convert("bar"), "foo bar"); + DoWStrTest("foo %ws", convert("bar"), "foo bar"); + DoStrTest("foo %Ls", "bar", "foo bar"); + DoStrTest("foo %I64s", "bar", "foo bar"); + DoStrTest("foo %5s", "bar", "foo bar"); + DoStrTest("foo %.2s", "bar", "foo ba"); + DoStrTest("foo %5.2s", "bar", "foo ba"); + DoStrTest("foo %-5s", "bar", "foo bar "); + DoStrTest("foo %05s", "bar", "foo 00bar"); + DoStrTest("foo %s", NULL, "foo (null)"); + DoStrTest("foo %hs", NULL, "foo (null)"); + DoWStrTest("foo %ls", NULL, "foo (null)"); + DoWStrTest("foo %ws", NULL, "foo (null)"); + DoStrTest("foo %Ls", NULL, "foo (null)"); + DoStrTest("foo %I64s", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test2/testinfo.dat new file mode 100644 index 0000000..3ff71c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test2 +Description += Tests printf with strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test3/CMakeLists.txt new file mode 100644 index 0000000..b75a50e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_printf_test3 + ${SOURCES} +) + +add_dependencies(paltest_printf_test3 coreclrpal) + +target_link_libraries(paltest_printf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test3/test3.cpp new file mode 100644 index 0000000..79fe721 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test3/test3.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Test #3 for the printf function. Tests the wide string +** specifier (%S). +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoWStrTest("foo %S", convert("bar"), "foo bar"); + DoStrTest("foo %hS", "bar", "foo bar"); + DoWStrTest("foo %lS", convert("bar"), "foo bar"); + DoWStrTest("foo %wS", convert("bar"), "foo bar"); + DoWStrTest("foo %LS", convert("bar"), "foo bar"); + DoWStrTest("foo %I64S", convert("bar"), "foo bar"); + DoWStrTest("foo %5S", convert("bar"), "foo bar"); + DoWStrTest("foo %.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %5.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %-5S", convert("bar"), "foo bar "); + DoWStrTest("foo %05S", convert("bar"), "foo 00bar"); + DoWStrTest("foo %S", NULL, "foo (null)"); + DoStrTest("foo %hS", NULL, "foo (null)"); + DoWStrTest("foo %lS", NULL, "foo (null)"); + DoWStrTest("foo %wS", NULL, "foo (null)"); + DoWStrTest("foo %LS", NULL, "foo (null)"); + DoWStrTest("foo %I64S", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test3/testinfo.dat new file mode 100644 index 0000000..295c172 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test3 +Description += Tests printf with wide strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test4/CMakeLists.txt new file mode 100644 index 0000000..6ce2801 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_printf_test4 + ${SOURCES} +) + +add_dependencies(paltest_printf_test4 coreclrpal) + +target_link_libraries(paltest_printf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test4/test4.cpp new file mode 100644 index 0000000..ba2fa58 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test4/test4.cpp @@ -0,0 +1,66 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Test #4 for the printf function. Tests the pointer +** specifier (%p). +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "0000000000000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "00000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); + +#endif + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test4/testinfo.dat new file mode 100644 index 0000000..0c55e0e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test4/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test4 +Description += Tests printf with pointers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test5/CMakeLists.txt new file mode 100644 index 0000000..885448a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_printf_test5 + ${SOURCES} +) + +add_dependencies(paltest_printf_test5 coreclrpal) + +target_link_libraries(paltest_printf_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test5/test5.cpp new file mode 100644 index 0000000..9f8baa7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test5/test5.cpp @@ -0,0 +1,60 @@ +// 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. + +/*============================================================================ +** +** Source: test5.c +** +** Purpose: Test #5 for the printf function. Tests the count specifier (%n). +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + + + + +int __cdecl main(int argc, char *argv[]) +{ + char *longStr = + "really-long-string-that-just-keeps-going-on-and-on-and-on.." + "..................useless-filler.................................." + "..................useless-filler.................................." + "..................useless-filler.................................." + "%n bar"; + char *longResult = + "really-long-string-that-just-keeps-going-on-and-on-and-on.." + "..................useless-filler.................................." + "..................useless-filler.................................." + "..................useless-filler.................................." + " bar"; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoCountTest("foo %n bar", 4, "foo bar"); + DoCountTest(longStr, 257, longResult); + DoCountTest("fo%n bar", 2, "fo bar"); + DoCountTest("%n", 0, ""); + DoCountTest("foo %#n bar", 4, "foo bar"); + DoCountTest("foo % n bar", 4, "foo bar"); + DoCountTest("foo %+n bar", 4, "foo bar"); + DoCountTest("foo %-n bar", 4, "foo bar"); + DoCountTest("foo %0n bar", 4, "foo bar"); + DoShortCountTest("foo %hn bar", 4, "foo bar"); + DoCountTest("foo %ln bar", 4, "foo bar"); + DoCountTest("foo %Ln bar", 4, "foo bar"); + DoCountTest("foo %I64n bar", 4, "foo bar"); + DoCountTest("foo %20.3n bar", 4, "foo bar"); + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test5/testinfo.dat new file mode 100644 index 0000000..a7c7400 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test5/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test5 +Description += Tests printf with the count specifier diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test6/CMakeLists.txt new file mode 100644 index 0000000..21224fd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_printf_test6 + ${SOURCES} +) + +add_dependencies(paltest_printf_test6 coreclrpal) + +target_link_libraries(paltest_printf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test6/test6.cpp new file mode 100644 index 0000000..edc65b6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test6/test6.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose: Test #6 for the printf function. Tests the char specifier (%c). +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoCharTest("foo %c", 'b', "foo b"); + DoCharTest("foo %hc", 'b', "foo b"); + DoWCharTest("foo %lc", wc, "foo c"); + DoCharTest("foo %Lc", 'b', "foo b"); + DoCharTest("foo %I64c", 'b', "foo b"); + DoCharTest("foo %5c", 'b', "foo b"); + DoCharTest("foo %.0c", 'b', "foo b"); + DoCharTest("foo %-5c", 'b', "foo b "); + DoCharTest("foo %05c", 'b', "foo 0000b"); + DoCharTest("foo % c", 'b', "foo b"); + DoCharTest("foo %#c", 'b', "foo b"); + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test6/testinfo.dat new file mode 100644 index 0000000..fd8a985 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test6/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test6 +Description += Tests printf with characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test7/CMakeLists.txt new file mode 100644 index 0000000..3a8f15e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_printf_test7 + ${SOURCES} +) + +add_dependencies(paltest_printf_test7 coreclrpal) + +target_link_libraries(paltest_printf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test7/test7.cpp new file mode 100644 index 0000000..3aeb58f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test7/test7.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test7.c +** +** Purpose: Test #7 for the printf function. Tests the wide char +** specifier (%C). +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wb = (WCHAR) 'b'; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoWCharTest("foo %C", wb, "foo b"); + DoWCharTest("foo %hC", wb, "foo b"); + DoCharTest("foo %lC", 'c', "foo c"); + DoWCharTest("foo %LC", wb, "foo b"); + DoWCharTest("foo %I64C", wb, "foo b"); + DoWCharTest("foo %5C", wb, "foo b"); + DoWCharTest("foo %.0C", wb, "foo b"); + DoWCharTest("foo %-5C", wb, "foo b "); + DoWCharTest("foo %05C", wb, "foo 0000b"); + DoWCharTest("foo % C", wb, "foo b"); + DoWCharTest("foo %#C", wb, "foo b"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test7/testinfo.dat new file mode 100644 index 0000000..6d2b1cf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test7/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test7 +Description += Tests printf with wide characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test8/CMakeLists.txt new file mode 100644 index 0000000..b79c169 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_printf_test8 + ${SOURCES} +) + +add_dependencies(paltest_printf_test8 coreclrpal) + +target_link_libraries(paltest_printf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test8/test8.cpp new file mode 100644 index 0000000..daa4674 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test8/test8.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test8.c +** +** Purpose: Test #8 for the printf function. Tests the decimal +** specifier (%d). +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %d", pos, "foo 42"); + DoNumTest("foo %ld", 0xFFFF, "foo 65535"); + DoNumTest("foo %hd", 0xFFFF, "foo -1"); + DoNumTest("foo %Ld", pos, "foo 42"); + DoI64Test("foo %I64d", l, "42", "foo 42"); + DoNumTest("foo %3d", pos, "foo 42"); + DoNumTest("foo %-3d", pos, "foo 42 "); + DoNumTest("foo %.1d", pos, "foo 42"); + DoNumTest("foo %.3d", pos, "foo 042"); + DoNumTest("foo %03d", pos, "foo 042"); + DoNumTest("foo %#d", pos, "foo 42"); + DoNumTest("foo %+d", pos, "foo +42"); + DoNumTest("foo % d", pos, "foo 42"); + DoNumTest("foo %+d", neg, "foo -42"); + DoNumTest("foo % d", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test8/testinfo.dat new file mode 100644 index 0000000..6367235 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test8/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test8 +Description += Tests printf with decimal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test9/CMakeLists.txt new file mode 100644 index 0000000..f7aea68 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_printf_test9 + ${SOURCES} +) + +add_dependencies(paltest_printf_test9 coreclrpal) + +target_link_libraries(paltest_printf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test9/test9.cpp new file mode 100644 index 0000000..22c60d0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test9/test9.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test9.c +** +** Purpose: Test #9 for the printf function. Tests the integer +** specifier (%i). +** +** +**==========================================================================*/ + + + +#include +#include "../printf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %i", pos, "foo 42"); + DoNumTest("foo %li", 0xFFFF, "foo 65535"); + DoNumTest("foo %hi", 0xFFFF, "foo -1"); + DoNumTest("foo %Li", pos, "foo 42"); + DoI64Test("foo %I64i", l, "42", "foo 42"); + DoNumTest("foo %3i", pos, "foo 42"); + DoNumTest("foo %-3i", pos, "foo 42 "); + DoNumTest("foo %.1i", pos, "foo 42"); + DoNumTest("foo %.3i", pos, "foo 042"); + DoNumTest("foo %03i", pos, "foo 042"); + DoNumTest("foo %#i", pos, "foo 42"); + DoNumTest("foo %+i", pos, "foo +42"); + DoNumTest("foo % i", pos, "foo 42"); + DoNumTest("foo %+i", neg, "foo -42"); + DoNumTest("foo % i", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test9/testinfo.dat new file mode 100644 index 0000000..3208cb4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/printf/test9/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = printf +Name = Positive Test for printf +TYPE = DEFAULT +EXE1 = test9 +Description += Tests printf with integer numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test1/CMakeLists.txt new file mode 100644 index 0000000..56e2de2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_qsort_test1 + ${SOURCES} +) + +add_dependencies(paltest_qsort_test1 coreclrpal) + +target_link_libraries(paltest_qsort_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test1/test1.cpp new file mode 100644 index 0000000..c65fb18 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test1/test1.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Calls qsort to sort a buffer, and verifies that it has done +** the job correctly. +** +** +**==========================================================================*/ + +#include + +int __cdecl charcmp(const void *pa, const void *pb) +{ + return memcmp(pa, pb, 1); +} + +int __cdecl main(int argc, char **argv) +{ + char before[] = "cgaiehdbjf"; + const char after[] = "abcdefghij"; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + qsort(before, sizeof(before) - 1, sizeof(char), charcmp); + + if (memcmp(before, after, sizeof(before)) != 0) + { + Fail("qsort did not correctly sort an array of characters.\n"); + } + + PAL_Terminate(); + return PASS; + +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test1/testinfo.dat new file mode 100644 index 0000000..7e3b4b8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = qsort +Name = Positive Test for qsort +TYPE = DEFAULT +EXE1 = test1 +Description += Calls qsort to sort a buffer, and verifies that it has done the job correctly. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test2/CMakeLists.txt new file mode 100644 index 0000000..f3f8993 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_qsort_test2 + ${SOURCES} +) + +add_dependencies(paltest_qsort_test2 coreclrpal) + +target_link_libraries(paltest_qsort_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test2/test2.cpp new file mode 100644 index 0000000..8110dcd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test2/test2.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Calls qsort to sort a buffer, and verifies that it has done +** the job correctly. +** +** +**==========================================================================*/ + +#include + +int __cdecl twocharcmp(const void *pa, const void *pb) +{ + return memcmp(pa, pb, 2); +} + +int __cdecl main(int argc, char **argv) +{ + char before[] = "ccggaaiieehhddbbjjff"; + const char after[] = "aabbccddeeffgghhiijj"; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + qsort(before, (sizeof(before) - 1) / 2, 2 * sizeof(char), twocharcmp); + + if (memcmp(before, after, sizeof(before)) != 0) + { + Fail("qsort did not correctly sort an array of 2-character " + "buffers.\n"); + } + + PAL_Terminate(); + return PASS; + +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test2/testinfo.dat new file mode 100644 index 0000000..35f5f06 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/qsort/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = qsort +Name = Positive Test for qsort +TYPE = DEFAULT +EXE1 = test2 +Description += Calls qsort to sort a buffer, and verifies that it has done the job correctly. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/test1/CMakeLists.txt new file mode 100644 index 0000000..fd44b33 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_rand_srand_test1 + ${SOURCES} +) + +add_dependencies(paltest_rand_srand_test1 coreclrpal) + +target_link_libraries(paltest_rand_srand_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/test1/test1.cpp new file mode 100644 index 0000000..34154cb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/test1/test1.cpp @@ -0,0 +1,100 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that srand provide random +** number to rand. Also make sure that rand result from a +** srand with seed 1 and no call to srand are the same. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** srand() +** + +** +**===========================================================================*/ + +#include + + +int __cdecl main(int argc, char **argv) +{ + int RandNumber[10]; + int TempRandNumber; + int i; + int SRAND_SEED; + int SRAND_REINIT = 1; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + SRAND_SEED = time(NULL); + + /* does not initialize srand and call rand. */ + for (i=0; i<10; i++) + { + /* keep the value in a array */ + RandNumber[i]=rand(); + if (RandNumber[i] < 0 || RandNumber[i] > RAND_MAX) + { + Fail("1) ERROR: random generated an invalid value: %d", RandNumber[i]); + } + } + + + /* initialize random generator */ + srand(SRAND_SEED); + + + /* choose 10 numbers with a different seed. + the numbers should be different than + those the previously generated one */ + for(i = 0; i < 10; i++) + { + TempRandNumber=rand(); + if (TempRandNumber < 0 || TempRandNumber > RAND_MAX) + { + Fail("2) ERROR: random generated an invalid value: %d", TempRandNumber); + } + } + + + + /* renitialize the srand with 1 */ + srand(SRAND_REINIT); + + + + /* choose 10 numbers with seed 1, + the number should be the same as those we kept in the array. */ + for( i = 0; i < 10;i++ ) + { + /* pick the random number*/ + TempRandNumber=rand(); + /* test if it is the same number generated in the first sequences*/ + if(RandNumber[i]!=TempRandNumber) + { + Fail ("ERROR: rand should return the same value when srand " + "is initialized with 1 or not initialized at all"); + } + if (TempRandNumber < 0 || TempRandNumber > RAND_MAX) + { + Fail("3) ERROR: random generated an invalid value: %d", TempRandNumber); + } + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/test1/testinfo.dat new file mode 100644 index 0000000..cf1b42d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/rand_srand/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = rand and srand +Name = Positive Test for rand and srand +TYPE = DEFAULT +EXE1 = test1 +Description += Call rand without srand and get 10 random number batch 1. += call srand with seed 2, get 10 other random number and verify += that numbers are different from the batch 1. += Set the seed to 1, get 10 other random number and verify += that the generated number are the same as batch 1. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/test1/CMakeLists.txt new file mode 100644 index 0000000..b57d84b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_realloc_test1 + ${SOURCES} +) + +add_dependencies(paltest_realloc_test1 coreclrpal) + +target_link_libraries(paltest_realloc_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/test1/test1.cpp new file mode 100644 index 0000000..64a9270 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/test1/test1.cpp @@ -0,0 +1,66 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Uses realloc to allocate and realloate memory, checking +** that memory contents are copied when the memory is reallocated. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + char *testA; + const int len1 = 10; + const char str1[] = "aaaaaaaaaa"; + + const int len2 = 20; + const char str2[] = "bbbbbbbbbbbbbbbbbbbb"; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* this should work like malloc */ + testA = (char *)realloc(NULL, len1*sizeof(char)); + memcpy(testA, str1, len1); + if (testA == NULL) + { + Fail("We ran out of memory (unlikely), or realloc is broken.\n"); + } + + if (memcmp(testA, str1, len1) != 0) + { + Fail("realloc doesn't properly allocate new memory.\n"); + } + + testA = (char *)realloc(testA, len2*sizeof(char)); + if (memcmp(testA, str1, len1) != 0) + { + Fail("realloc doesn't move the contents of the original memory " + "block to the newly allocated block.\n"); + } + + memcpy(testA, str2, len2); + if (memcmp(testA, str2, len2) != 0) + { + Fail("Couldn't write to memory allocated by realloc.\n"); + } + + /* free the buffer */ + testA = (char*)realloc(testA, 0); + if (testA != NULL) + { + Fail("Realloc didn't return NULL when called with a length " + "of zero.\n"); + } + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/test1/testinfo.dat new file mode 100644 index 0000000..5d2a322 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/realloc/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = realloc +Name = Positive Test for realloc +TYPE = DEFAULT +EXE1 = test1 +Description += Uses realloc to allocate and realloate memory, checking that memory += contents are copied when the memory is reallocated. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/test1/CMakeLists.txt new file mode 100644 index 0000000..96abef4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_scalbn_test1 + ${SOURCES} +) + +add_dependencies(paltest_scalbn_test1 coreclrpal) + +target_link_libraries(paltest_scalbn_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/test1/test1.cpp new file mode 100644 index 0000000..9507cc4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/test1/test1.cpp @@ -0,0 +1,140 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that scalbn returns correct values. +** +**===================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + int exponent; /* exponent to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, int exponent, double expected, double variance) +{ + double result = scalbn(value, exponent); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("scalbn(%g, %d) returned %20.17g when it should have returned %20.17g\n", + value, exponent, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value, int exponent) +{ + double result = scalbn(value, exponent); + + if (!_isnan(result)) + { + Fail("scalbn(%g, %d) returned %20.17g when it should have returned %20.17g\n", + value, exponent, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value exponent expected variance */ + { PAL_NEGINF, 0x80000000, PAL_NEGINF, 0 }, + { 0, 0x80000000, 0, 0 }, + { 0.11331473229676087, -3, 0.014164341537095108, PAL_EPSILON / 10 }, + { 0.15195522325791297, -2, 0.037988805814478242, PAL_EPSILON / 10 }, + { 0.20269956628651730, -2, 0.050674891571629327, PAL_EPSILON / 10 }, + { 0.33662253682241906, -1, 0.16831126841120952, PAL_EPSILON }, + { 0.36787944117144232, -1, 0.18393972058572117, PAL_EPSILON }, + { 0.37521422724648177, -1, 0.1876071136232409, PAL_EPSILON }, + { 0.45742934732229695, -1, 0.22871467366114848, PAL_EPSILON }, + { 0.5, -1, 0.25, PAL_EPSILON }, + { 0.58019181037172444, 0, 0.5801918103717244, PAL_EPSILON }, + { 0.61254732653606592, 0, 0.61254732653606592, PAL_EPSILON }, + { 0.61850313780157598, 0, 0.61850313780157595, PAL_EPSILON }, + { 0.64321824193300488, 0, 0.64321824193300492, PAL_EPSILON }, + { 0.74005557395545179, 0, 0.74005557395545174, PAL_EPSILON }, + { 0.80200887896145195, 0, 0.8020088789614519, PAL_EPSILON }, + { 1, 0, 1, PAL_EPSILON * 10 }, + { 1.2468689889006383, 0, 1.2468689889006384, PAL_EPSILON * 10 }, + { 1.3512498725672678, 0, 1.3512498725672677, PAL_EPSILON * 10 }, + { 1.5546822754821001, 0, 1.5546822754821001, PAL_EPSILON * 10 }, + { 1.6168066722416747, 0, 1.6168066722416747, PAL_EPSILON * 10 }, + { 1.6325269194381528, 0, 1.6325269194381529, PAL_EPSILON * 10 }, + { 1.7235679341273495, 0, 1.7235679341273495, PAL_EPSILON * 10 }, + { 2, 1, 4, PAL_EPSILON * 10 }, + { 2.1861299583286618, 1, 4.3722599166573239, PAL_EPSILON * 10 }, + { 2.6651441426902252, 1, 5.3302882853804503, PAL_EPSILON * 10 }, + { 2.7182818284590452, 1, 5.4365636569180902, PAL_EPSILON * 10 }, + { 2.9706864235520193, 1, 5.9413728471040388, PAL_EPSILON * 10 }, + { 4.9334096679145963, 2, 19.733638671658387, PAL_EPSILON * 100 }, + { 6.5808859910179210, 2, 26.323543964071686, PAL_EPSILON * 100 }, + { 8.8249778270762876, 3, 70.599822616610297, PAL_EPSILON * 100 }, + { PAL_POSINF, 0x80000000, PAL_POSINF, 0 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].exponent, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN, 2147483647); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/test1/testinfo.dat new file mode 100644 index 0000000..ce98062 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbn/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = scalbn +Name = Call scalbn with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the scalbn function with various num/exponent pairs += that should produce std answers. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/test1/CMakeLists.txt new file mode 100644 index 0000000..c5a1dc2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_scalbnf_test1 + ${SOURCES} +) + +add_dependencies(paltest_scalbnf_test1 coreclrpal) + +target_link_libraries(paltest_scalbnf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/test1/test1.c new file mode 100644 index 0000000..88f00a2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/test1/test1.c @@ -0,0 +1,139 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that scalbnf returns correct values. +** +**===================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + int exponent; /* exponent to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, int exponent, float expected, float variance) +{ + float result = scalbnf(value, exponent); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("scalbnf(%g, %g) returned %10.9g when it should have returned %10.9g", + value, exponent, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value, int exponent) +{ + float result = scalbnf(value, exponent); + + if (!_isnanf(result)) + { + Fail("scalbnf(%g, %g) returned %10.9g when it should have returned %10.9g", + value, exponent, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value exponent expected variance */ + { PAL_NEGINF, 0x80000000, PAL_NEGINF, 0 }, + { 0, 0x80000000, 0, 0 }, + { 0.113314732f, -3, 0.0141643415f, PAL_EPSILON / 10 }, + { 0.151955223f, -2, 0.0379888058f, PAL_EPSILON / 10 }, + { 0.202699566f, -2, 0.0506748916f, PAL_EPSILON / 10 }, + { 0.336622537f, -1, 0.168311268f, PAL_EPSILON }, + { 0.367879441f, -1, 0.183939721f, PAL_EPSILON }, + { 0.375214227f, -1, 0.187607114f, PAL_EPSILON }, + { 0.457429347f, -1, 0.228714674f, PAL_EPSILON }, + { 0.5f, -1, 0.25f, PAL_EPSILON }, + { 0.580191810f, 0, 0.580191810f, PAL_EPSILON }, + { 0.612547327f, 0, 0.612547327f, PAL_EPSILON }, + { 0.618503138f, 0, 0.618503138f, PAL_EPSILON }, + { 0.643218242f, 0, 0.643218242f, PAL_EPSILON }, + { 0.740055574f, 0, 0.740055574f, PAL_EPSILON }, + { 0.802008879f, 0, 0.802008879f, PAL_EPSILON }, + { 1, 0, 1, PAL_EPSILON * 10 }, + { 1.24686899f, 0, 1.24686899f, PAL_EPSILON * 10 }, + { 1.35124987f, 0, 1.35124987f, PAL_EPSILON * 10 }, + { 1.55468228f, 0, 1.55468228f, PAL_EPSILON * 10 }, + { 1.61680667f, 0, 1.61680667f, PAL_EPSILON * 10 }, + { 1.63252692f, 0, 1.63252692f, PAL_EPSILON * 10 }, + { 1.72356793f, 0, 1.72356793f, PAL_EPSILON * 10 }, + { 2, 1, 4, PAL_EPSILON * 10 }, + { 2.18612996f, 1, 4.37225992f, PAL_EPSILON * 10 }, + { 2.66514414f, 1, 5.33028829f, PAL_EPSILON * 10 }, + { 2.71828183f, 1, 5.43656366f, PAL_EPSILON * 10 }, + { 2.97068642f, 1, 5.94137285f, PAL_EPSILON * 10 }, + { 4.93340967f, 2, 19.7336387f, PAL_EPSILON * 100 }, + { 6.58088599f, 2, 26.3235440f, PAL_EPSILON * 100 }, + { 8.82497783f, 3, 70.5998226f, PAL_EPSILON * 100 }, + { PAL_POSINF, 0x80000000, PAL_POSINF, 0 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].exponent, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN, 2147483647); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/test1/testinfo.dat new file mode 100644 index 0000000..728fafa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/scalbnf/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = scalbnf +Name = Call scalbnf with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the scalbnf function with various num/expfonent pairs += that should produce std answers. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/test1/CMakeLists.txt new file mode 100644 index 0000000..6a7549a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_sin_test1 + ${SOURCES} +) + +add_dependencies(paltest_sin_test1 coreclrpal) + +target_link_libraries(paltest_sin_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/test1/test1.cpp new file mode 100644 index 0000000..bec58d4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/test1/test1.cpp @@ -0,0 +1,131 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that sin return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = sin(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("sin(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = sin(value); + + if (!_isnan(result)) + { + Fail("sin(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.31830988618379067, 0.31296179620778659, PAL_EPSILON }, // value: 1 / pi + { 0.43429448190325183, 0.42077048331375735, PAL_EPSILON }, // value: log10(e) + { 0.63661977236758134, 0.59448076852482208, PAL_EPSILON }, // value: 2 / pi + { 0.69314718055994531, 0.63896127631363480, PAL_EPSILON }, // value: ln(2) + { 0.70710678118654752, 0.64963693908006244, PAL_EPSILON }, // value: 1 / sqrt(2) + { 0.78539816339744831, 0.70710678118654752, PAL_EPSILON }, // value: pi / 4, expected: 1 / sqrt(2) + { 1, 0.84147098480789651, PAL_EPSILON }, + { 1.1283791670955126, 0.90371945743584630, PAL_EPSILON }, // value: 2 / sqrt(pi) + { 1.4142135623730950, 0.98776594599273553, PAL_EPSILON }, // value: sqrt(2) + { 1.4426950408889634, 0.99180624439366372, PAL_EPSILON }, // value: log2(e) + { 1.5707963267948966, 1, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.3025850929940457, 0.74398033695749319, PAL_EPSILON }, // value: ln(10) + { 2.7182818284590452, 0.41078129050290870, PAL_EPSILON }, // value: e + { 3.1415926535897932, 0, PAL_EPSILON }, // value: pi + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/test1/testinfo.dat new file mode 100644 index 0000000..57eae6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sin/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = sin +Name = Positive Test for sin +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to sin() a series of angle value, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/test1/CMakeLists.txt new file mode 100644 index 0000000..76ceb1e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_sinf_test1 + ${SOURCES} +) + +add_dependencies(paltest_sinf_test1 coreclrpal) + +target_link_libraries(paltest_sinf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/test1/test1.c new file mode 100644 index 0000000..d5bd248 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/test1/test1.c @@ -0,0 +1,130 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that sinf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = sinf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("sinf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = sinf(value); + + if (!_isnanf(result)) + { + Fail("sinf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.318309886f, 0.312961796f, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0.420770483f, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0.594480769f, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0.638961276f, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0.649636939f, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 0.707106781f, PAL_EPSILON }, // value: pi / 4, expected: 1 / sqrtf(2) + { 1, 0.841470985f, PAL_EPSILON }, + { 1.12837917f, 0.903719457f, PAL_EPSILON }, // value: 2 / sqrtf(pi) + { 1.41421356f, 0.987765946f, PAL_EPSILON }, // value: sqrtf(2) + { 1.44269504f, 0.991806244f, PAL_EPSILON }, // value: logf2(e) + { 1.57079633f, 1, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 0.743980337f, PAL_EPSILON }, // value: ln(10) + { 2.71828183f, 0.410781291f, PAL_EPSILON }, // value: e + { 3.14159265f, 0, PAL_EPSILON }, // value: pi + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/test1/testinfo.dat new file mode 100644 index 0000000..08ff602 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = sinf +Name = Positive Test for sinf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to sinf() a series of angle value, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/test1/CMakeLists.txt new file mode 100644 index 0000000..bd74171 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_sinh_test1 + ${SOURCES} +) + +add_dependencies(paltest_sinh_test1 coreclrpal) + +target_link_libraries(paltest_sinh_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/test1/test1.cpp new file mode 100644 index 0000000..e790b16 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/test1/test1.cpp @@ -0,0 +1,130 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that sinh return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = sinh(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("sinh(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = sinh(value); + + if (!_isnan(result)) + { + Fail("sinh(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.31830988618379067, 0.32371243907207108, PAL_EPSILON }, // value: 1 / pi + { 0.43429448190325183, 0.44807597941469025, PAL_EPSILON }, // value: log10(e) + { 0.63661977236758134, 0.68050167815224332, PAL_EPSILON }, // value: 2 / pi + { 0.69314718055994531, 0.75, PAL_EPSILON }, // value: ln(2) + { 0.70710678118654752, 0.76752314512611633, PAL_EPSILON }, // value: 1 / sqrt(2) + { 0.78539816339744831, 0.86867096148600961, PAL_EPSILON }, // value: pi / 4 + { 1, 1.1752011936438015, PAL_EPSILON * 10 }, + { 1.1283791670955126, 1.3835428792038633, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi) + { 1.4142135623730950, 1.9350668221743567, PAL_EPSILON * 10 }, // value: sqrt(2) + { 1.4426950408889634, 1.9978980091062796, PAL_EPSILON * 10 }, // value: log2(e) + { 1.5707963267948966, 2.3012989023072949, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.3025850929940457, 4.95, PAL_EPSILON * 10 }, // value: ln(10) + { 2.7182818284590452, 7.5441371028169758, PAL_EPSILON * 10 }, // value: e + { 3.1415926535897932, 11.548739357257748, PAL_EPSILON * 100 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/test1/testinfo.dat new file mode 100644 index 0000000..f7aee40 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinh/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = sinh +Name = Positive Test for sinh +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to sinh() a series of angle value, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/test1/CMakeLists.txt new file mode 100644 index 0000000..811324b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_sinhf_test1 + ${SOURCES} +) + +add_dependencies(paltest_sinhf_test1 coreclrpal) + +target_link_libraries(paltest_sinhf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/test1/test1.c new file mode 100644 index 0000000..4e706a2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/test1/test1.c @@ -0,0 +1,129 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that sinhf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = sinhf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("sinhf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = sinhf(value); + + if (!_isnanf(result)) + { + Fail("sinhf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.318309886f, 0.323712439f, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0.448075979f, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0.680501678f, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0.75, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0.767523145f, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 0.868670961f, PAL_EPSILON }, // value: pi / 4 + { 1, 1.17520119f, PAL_EPSILON * 10 }, + { 1.12837917f, 1.38354288f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 1.93506682f, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 1.99789801f, PAL_EPSILON * 10 }, // value: logf2(e) + { 1.57079633f, 2.30129890f, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 4.95f, PAL_EPSILON * 10 }, // value: ln(10) + { 2.71828183f, 7.54413710f, PAL_EPSILON * 10 }, // value: e + { 3.14159265f, 11.5487394f, PAL_EPSILON * 100 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/test1/testinfo.dat new file mode 100644 index 0000000..cfb27f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sinhf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = sinhf +Name = Positive Test for sinhf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to sinhf() a series of angle value, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/CMakeLists.txt new file mode 100644 index 0000000..b29c7c4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/CMakeLists.txt @@ -0,0 +1,19 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/sprintf_s.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/sprintf_s.h new file mode 100644 index 0000000..129b9db --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/sprintf_s.h @@ -0,0 +1,195 @@ +// 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. + +/*============================================================================ +** +** Source: sprintf_s.h +** +** Purpose: Containts common testing functions for sprintf_s +** +** +**==========================================================================*/ + +#ifndef __SPRINTF_S_H__ +#define __SPRINTF_S_H__ + +void DoStrTest(const char *formatstr, char* param, const char *checkstr) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, formatstr, checkstr, buf); + } +} + +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + convertC(param), formatstr, checkstr, buf); + } +} + +void DoPointerTest(const char *formatstr, void* param, char* paramstr, + const char *checkstr1) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + paramstr, formatstr, checkstr1, buf); + } +} + +void DoCountTest(const char *formatstr, int param, const char *checkstr) +{ + char buf[512] = { 0 }; + int n = -1; + + sprintf_s(buf, _countof(buf), formatstr, &n); + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } +} + +void DoShortCountTest(const char *formatstr, int param, const char *checkstr) +{ + char buf[256] = { 0 }; + short int n = -1; + + sprintf_s(buf, _countof(buf), formatstr, &n); + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } +} + + +void DoCharTest(const char *formatstr, char param, const char *checkstr) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, param, formatstr, checkstr, buf); + } +} + +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + (char)param, param, formatstr, checkstr, buf); + } +} + +void DoNumTest(const char *formatstr, int value, const char *checkstr) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, value); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert %#x into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + value, formatstr, checkstr, buf); + } +} + +void DoI64Test(const char *formatstr, INT64 value, char *valuestr, const char *checkstr1) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, value); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", + valuestr, formatstr, checkstr1, buf); + } +} + +void DoDoubleTest(const char *formatstr, double value, const char *checkstr1, + const char *checkstr2) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, value); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + value, formatstr, checkstr1, checkstr2, buf); + } +} + +void DoArgumentPrecTest(const char *formatstr, int precision, void *param, + char *paramstr, const char *checkstr1, const char *checkstr2) +{ + char buf[256]; + + sprintf_s(buf, _countof(buf), formatstr, precision, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", paramstr, formatstr, + precision, checkstr1, checkstr2, buf); + } + +} + +void DoArgumentPrecDoubleTest(const char *formatstr, int precision, double param, + const char *checkstr1, const char *checkstr2) +{ + char buf[256]; + + sprintf_s(buf, _countof(buf), formatstr, precision, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", param, formatstr, + precision, checkstr1, checkstr2, buf); + } + +} + +#endif + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/CMakeLists.txt new file mode 100644 index 0000000..d190fd7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_sprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test1 coreclrpal) + +target_link_libraries(paltest_sprintf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/test1.cpp new file mode 100644 index 0000000..a289c07 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/test1.cpp @@ -0,0 +1,45 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Test #1 for the sprintf_s function. A single, basic, test +** case with no formatting. +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + char checkstr[] = "hello world"; + char buf[256]; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + sprintf_s(buf, _countof(buf), "hello world"); + + if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0) + { + Fail("ERROR: expected %s, got %s\n", checkstr, buf); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/testinfo.dat new file mode 100644 index 0000000..255c534 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test1 +Description += General test to see if sprintf_s works correctly diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/CMakeLists.txt new file mode 100644 index 0000000..6ebb555 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_sprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test10 coreclrpal) + +target_link_libraries(paltest_sprintf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/test10.cpp new file mode 100644 index 0000000..bbda15a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/test10.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test10.c +** +** Purpose: Test #10 for the sprintf_s function. Tests the octal specifier +** (%o). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %o", pos, "foo 52"); + DoNumTest("foo %lo", 0xFFFF, "foo 177777"); + DoNumTest("foo %ho", 0xFFFF, "foo 177777"); + DoNumTest("foo %Lo", pos, "foo 52"); + DoI64Test("foo %I64o", l, "42", "foo 52"); + DoNumTest("foo %3o", pos, "foo 52"); + DoNumTest("foo %-3o", pos, "foo 52 "); + DoNumTest("foo %.1o", pos, "foo 52"); + DoNumTest("foo %.3o", pos, "foo 052"); + DoNumTest("foo %03o", pos, "foo 052"); + DoNumTest("foo %#o", pos, "foo 052"); + DoNumTest("foo %+o", pos, "foo 52"); + DoNumTest("foo % o", pos, "foo 52"); + DoNumTest("foo %+o", neg, "foo 37777777726"); + DoNumTest("foo % o", neg, "foo 37777777726"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/testinfo.dat new file mode 100644 index 0000000..25ed554 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test10 +Description += Tests sprintf_s with octal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/CMakeLists.txt new file mode 100644 index 0000000..417db26 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_sprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test11 coreclrpal) + +target_link_libraries(paltest_sprintf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/test11.cpp new file mode 100644 index 0000000..7f4fca9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/test11.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test11.c +** +** Purpose: Test #11 for the sprintf_s function. Test the unsigned int +** specifier (%u). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %u", pos, "foo 42"); + DoNumTest("foo %lu", 0xFFFF, "foo 65535"); + DoNumTest("foo %hu", 0xFFFF, "foo 65535"); + DoNumTest("foo %Lu", pos, "foo 42"); + DoI64Test("foo %I64u", l, "42", "foo 42"); + DoNumTest("foo %3u", pos, "foo 42"); + DoNumTest("foo %-3u", pos, "foo 42 "); + DoNumTest("foo %.1u", pos, "foo 42"); + DoNumTest("foo %.3u", pos, "foo 042"); + DoNumTest("foo %03u", pos, "foo 042"); + DoNumTest("foo %#u", pos, "foo 42"); + DoNumTest("foo %+u", pos, "foo 42"); + DoNumTest("foo % u", pos, "foo 42"); + DoNumTest("foo %+u", neg, "foo 4294967254"); + DoNumTest("foo % u", neg, "foo 4294967254"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/testinfo.dat new file mode 100644 index 0000000..3144f12 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test11 +Description += Tests sprintf_s with unsigned numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/CMakeLists.txt new file mode 100644 index 0000000..c9c1025 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_sprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test12 coreclrpal) + +target_link_libraries(paltest_sprintf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/test12.cpp new file mode 100644 index 0000000..759a411 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/test12.cpp @@ -0,0 +1,56 @@ +// 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. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Test #12 for the sprintf_s function. Tests the (lowercase) +** hexadecimal specifier (%x) +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %x", pos, "foo 1234ab"); + DoNumTest("foo %lx", pos, "foo 1234ab"); + DoNumTest("foo %hx", pos, "foo 34ab"); + DoNumTest("foo %Lx", pos, "foo 1234ab"); + DoI64Test("foo %I64x", l, "0x1234567887654321", + "foo 1234567887654321"); + DoNumTest("foo %7x", pos, "foo 1234ab"); + DoNumTest("foo %-7x", pos, "foo 1234ab "); + DoNumTest("foo %.1x", pos, "foo 1234ab"); + DoNumTest("foo %.7x", pos, "foo 01234ab"); + DoNumTest("foo %07x", pos, "foo 01234ab"); + DoNumTest("foo %#x", pos, "foo 0x1234ab"); + DoNumTest("foo %+x", pos, "foo 1234ab"); + DoNumTest("foo % x", pos, "foo 1234ab"); + DoNumTest("foo %+x", neg, "foo ffffffd6"); + DoNumTest("foo % x", neg, "foo ffffffd6"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/testinfo.dat new file mode 100644 index 0000000..ed91cec --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test12 +Description += Tests sprintf_s with hex numbers (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/CMakeLists.txt new file mode 100644 index 0000000..7c5c014 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_sprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test13 coreclrpal) + +target_link_libraries(paltest_sprintf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/test13.cpp new file mode 100644 index 0000000..76250d0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/test13.cpp @@ -0,0 +1,56 @@ +// 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. + +/*============================================================================ +** +** Source: test13.c +** +** Purpose: Test #13 for the sprintf_s function. Tests the (uppercase) +** hexadecimal specifier (%X) +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234AB; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %X", pos, "foo 1234AB"); + DoNumTest("foo %lX", pos, "foo 1234AB"); + DoNumTest("foo %hX", pos, "foo 34AB"); + DoNumTest("foo %LX", pos, "foo 1234AB"); + DoI64Test("foo %I64X", l, "0x1234567887654321", + "foo 1234567887654321"); + DoNumTest("foo %7X", pos, "foo 1234AB"); + DoNumTest("foo %-7X", pos, "foo 1234AB "); + DoNumTest("foo %.1X", pos, "foo 1234AB"); + DoNumTest("foo %.7X", pos, "foo 01234AB"); + DoNumTest("foo %07X", pos, "foo 01234AB"); + DoNumTest("foo %#X", pos, "foo 0X1234AB"); + DoNumTest("foo %+X", pos, "foo 1234AB"); + DoNumTest("foo % X", pos, "foo 1234AB"); + DoNumTest("foo %+X", neg, "foo FFFFFFD6"); + DoNumTest("foo % X", neg, "foo FFFFFFD6"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/testinfo.dat new file mode 100644 index 0000000..fd5f530 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test13 +Description += Tests sprintf_s with hex numbers (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/CMakeLists.txt new file mode 100644 index 0000000..f85869a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_sprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test14 coreclrpal) + +target_link_libraries(paltest_sprintf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/test14.cpp new file mode 100644 index 0000000..668edda --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/test14.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test14.c +** +** Purpose: Test #14 for the sprintf_s function. Tests the lowercase +** exponential notation double specifier (%e) +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", "foo 2.560000e+02 "); + DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02"); + DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", "foo 2.56000000e+02"); + DoDoubleTest("foo %014e", val, "foo 02.560000e+002", "foo 002.560000e+02"); + DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02"); + DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/testinfo.dat new file mode 100644 index 0000000..23cf423 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test14 +Description += Tests sprintf_s with exponential format doubles (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/CMakeLists.txt new file mode 100644 index 0000000..99bd4cf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_sprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test15 coreclrpal) + +target_link_libraries(paltest_sprintf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/test15.cpp new file mode 100644 index 0000000..61e0e36 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/test15.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test15.c +** +** Purpose: Test #15 for the sprintf_s function. Tests the uppercase +** exponential notation double specifier (%E) +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %14E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", "foo 2.560000E+02 "); + DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02"); + DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", "foo 2.56000000E+02"); + DoDoubleTest("foo %014E", val, "foo 02.560000E+002", "foo 002.560000E+02"); + DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02"); + DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/testinfo.dat new file mode 100644 index 0000000..537e6d1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test15 +Description += Tests sprintf_s with exponential format doubles (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/CMakeLists.txt new file mode 100644 index 0000000..1d57f81 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_sprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test16 coreclrpal) + +target_link_libraries(paltest_sprintf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/test16.cpp new file mode 100644 index 0000000..b237c98 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/test16.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================================ +** +** Source: test16.c +** +** Purpose: Test #16 for the sprintf_s function. Tests the decimal notation +** double specifier (%f) +** +** +**==========================================================================*/ + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 "); + DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0"); + DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000"); + DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000"); + DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000"); + DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000"); + DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/testinfo.dat new file mode 100644 index 0000000..4e98ecc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test16 +Description += Tests sprintf_s with decimal point format doubles diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/CMakeLists.txt new file mode 100644 index 0000000..336639a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_sprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test17 coreclrpal) + +target_link_libraries(paltest_sprintf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/test17.cpp new file mode 100644 index 0000000..220555e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/test17.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test17.c +** +** Purpose: Test #17 for the sprintf_s function. Tests the lowercase +** shorthand notation double specifier (%g) +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03"); + DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03"); + DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/testinfo.dat new file mode 100644 index 0000000..5e41e20 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test17 +Description += Tests sprintf_s with compact format doubles (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/CMakeLists.txt new file mode 100644 index 0000000..abf9549 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test18.cpp +) + +add_executable(paltest_sprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test18 coreclrpal) + +target_link_libraries(paltest_sprintf_test18 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/test18.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/test18.cpp new file mode 100644 index 0000000..2135a6f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/test18.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test18.c +** +** Purpose: Test #18 for the sprintf_s function. Tests the uppercase +** shorthand notation double specifier (%G) +** +** +**==========================================================================*/ + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03"); + DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03"); + DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/testinfo.dat new file mode 100644 index 0000000..06ae3a6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test18 +Description += Tests sprintf_s with compact format doubles (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/CMakeLists.txt new file mode 100644 index 0000000..79d22af --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test19.cpp +) + +add_executable(paltest_sprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test19 coreclrpal) + +target_link_libraries(paltest_sprintf_test19 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/test19.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/test19.cpp new file mode 100644 index 0000000..483c716 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/test19.cpp @@ -0,0 +1,71 @@ +// 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. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose: Test #19 for the sprintf_s function. Tests the variable length +** precision argument. +** +** +**==========================================================================*/ + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoArgumentPrecTest("%.*s", 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest("%.*S", 2, (void*)convert("bar"), "bar", "ba", "ba"); + + DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/testinfo.dat new file mode 100644 index 0000000..7064c01 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test19 +Description += Tests sprintf_s with argument specified precision diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/CMakeLists.txt new file mode 100644 index 0000000..da08f52 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_sprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test2 coreclrpal) + +target_link_libraries(paltest_sprintf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/test2.cpp new file mode 100644 index 0000000..a3eb71d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/test2.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Test #2 for the sprintf_s function. Tests the string specifier +** (%s). +** +** +**==========================================================================*/ + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoStrTest("foo %s", "bar", "foo bar"); + DoStrTest("foo %hs", "bar", "foo bar"); + DoWStrTest("foo %ls", convert("bar"), "foo bar"); + DoWStrTest("foo %ws", convert("bar"), "foo bar"); + DoStrTest("foo %Ls", "bar", "foo bar"); + DoStrTest("foo %I64s", "bar", "foo bar"); + DoStrTest("foo %5s", "bar", "foo bar"); + DoStrTest("foo %.2s", "bar", "foo ba"); + DoStrTest("foo %5.2s", "bar", "foo ba"); + DoStrTest("foo %-5s", "bar", "foo bar "); + DoStrTest("foo %05s", "bar", "foo 00bar"); + DoStrTest("foo %s", NULL, "foo (null)"); + DoStrTest("foo %hs", NULL, "foo (null)"); + DoWStrTest("foo %ls", NULL, "foo (null)"); + DoWStrTest("foo %ws", NULL, "foo (null)"); + DoStrTest("foo %Ls", NULL, "foo (null)"); + DoStrTest("foo %I64s", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/testinfo.dat new file mode 100644 index 0000000..cce2dc6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test2 +Description += Tests sprintf_s with strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/CMakeLists.txt new file mode 100644 index 0000000..5a298ed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_sprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test3 coreclrpal) + +target_link_libraries(paltest_sprintf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/test3.cpp new file mode 100644 index 0000000..dd6e590 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/test3.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Test #3 for the sprintf_s function. Tests the wide string +** specifier (%S). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoWStrTest("foo %S", convert("bar"), "foo bar"); + DoStrTest("foo %hS", "bar", "foo bar"); + DoWStrTest("foo %lS", convert("bar"), "foo bar"); + DoWStrTest("foo %wS", convert("bar"), "foo bar"); + DoWStrTest("foo %LS", convert("bar"), "foo bar"); + DoWStrTest("foo %I64S", convert("bar"), "foo bar"); + DoWStrTest("foo %5S", convert("bar"), "foo bar"); + DoWStrTest("foo %.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %5.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %-5S", convert("bar"), "foo bar "); + DoWStrTest("foo %05S", convert("bar"), "foo 00bar"); + DoWStrTest("foo %S", NULL, "foo (null)"); + DoStrTest("foo %hS", NULL, "foo (null)"); + DoWStrTest("foo %lS", NULL, "foo (null)"); + DoWStrTest("foo %wS", NULL, "foo (null)"); + DoWStrTest("foo %LS", NULL, "foo (null)"); + DoWStrTest("foo %I64S", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/testinfo.dat new file mode 100644 index 0000000..cc8de0e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test3 +Description += Tests sprintf_s with wide strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/CMakeLists.txt new file mode 100644 index 0000000..ad30608 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_sprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test4 coreclrpal) + +target_link_libraries(paltest_sprintf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/test4.cpp new file mode 100644 index 0000000..7234970 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/test4.cpp @@ -0,0 +1,69 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Test #4 for the sprintf_s function. Tests the pointer +** specifier (%p). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "0000000000000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "00000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); +#endif + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/testinfo.dat new file mode 100644 index 0000000..f53f784 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test4 +Description += Tests sprintf_s with pointers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/CMakeLists.txt new file mode 100644 index 0000000..6312829 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_sprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test6 coreclrpal) + +target_link_libraries(paltest_sprintf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/test6.cpp new file mode 100644 index 0000000..c5fc804 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/test6.cpp @@ -0,0 +1,50 @@ +// 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. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose: Test #6 for the sprintf_s function. Tests the char specifier (%c). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoCharTest("foo %c", 'b', "foo b"); + DoCharTest("foo %hc", 'b', "foo b"); + DoWCharTest("foo %lc", wc, "foo c"); + DoCharTest("foo %Lc", 'b', "foo b"); + DoCharTest("foo %I64c", 'b', "foo b"); + DoCharTest("foo %5c", 'b', "foo b"); + DoCharTest("foo %.0c", 'b', "foo b"); + DoCharTest("foo %-5c", 'b', "foo b "); + DoCharTest("foo %05c", 'b', "foo 0000b"); + DoCharTest("foo % c", 'b', "foo b"); + DoCharTest("foo %#c", 'b', "foo b"); + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/testinfo.dat new file mode 100644 index 0000000..c5b93fc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test6 +Description += Tests sprintf_s with characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/CMakeLists.txt new file mode 100644 index 0000000..c4261ef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_sprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test7 coreclrpal) + +target_link_libraries(paltest_sprintf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/test7.cpp new file mode 100644 index 0000000..fd46ae9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/test7.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test7.c +** +** Purpose: Test #7 for the sprintf_s function. Tests the wide char +** specifier (%C). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wb = (WCHAR) 'b'; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoWCharTest("foo %C", wb, "foo b"); + DoWCharTest("foo %hC", wb, "foo b"); + DoCharTest("foo %lC", 'c', "foo c"); + DoWCharTest("foo %LC", wb, "foo b"); + DoWCharTest("foo %I64C", wb, "foo b"); + DoWCharTest("foo %5C", wb, "foo b"); + DoWCharTest("foo %.0C", wb, "foo b"); + DoWCharTest("foo %-5C", wb, "foo b "); + DoWCharTest("foo %05C", wb, "foo 0000b"); + DoWCharTest("foo % C", wb, "foo b"); + DoWCharTest("foo %#C", wb, "foo b"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/testinfo.dat new file mode 100644 index 0000000..647c9d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test7 +Description += Tests sprintf_s with wide characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/CMakeLists.txt new file mode 100644 index 0000000..dc12c5d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_sprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test8 coreclrpal) + +target_link_libraries(paltest_sprintf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/test8.cpp new file mode 100644 index 0000000..db02627 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/test8.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test8.c +** +** Purpose: Test #8 for the sprintf_s function. Tests the decimal +** specifier (%d). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %d", pos, "foo 42"); + DoNumTest("foo %ld", 0xFFFF, "foo 65535"); + DoNumTest("foo %hd", 0xFFFF, "foo -1"); + DoNumTest("foo %Ld", pos, "foo 42"); + DoI64Test("foo %I64d", l, "42", "foo 42"); + DoNumTest("foo %3d", pos, "foo 42"); + DoNumTest("foo %-3d", pos, "foo 42 "); + DoNumTest("foo %.1d", pos, "foo 42"); + DoNumTest("foo %.3d", pos, "foo 042"); + DoNumTest("foo %03d", pos, "foo 042"); + DoNumTest("foo %#d", pos, "foo 42"); + DoNumTest("foo %+d", pos, "foo +42"); + DoNumTest("foo % d", pos, "foo 42"); + DoNumTest("foo %+d", neg, "foo -42"); + DoNumTest("foo % d", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/testinfo.dat new file mode 100644 index 0000000..524834e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test8 +Description += Tests sprintf_s with decimal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/CMakeLists.txt new file mode 100644 index 0000000..28f2802 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_sprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test9 coreclrpal) + +target_link_libraries(paltest_sprintf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/test9.cpp new file mode 100644 index 0000000..2e1c78c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/test9.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test9.c +** +** Purpose: Test #9 for the sprintf_s function. Tests the integer +** specifier (%i). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %i", pos, "foo 42"); + DoNumTest("foo %li", 0xFFFF, "foo 65535"); + DoNumTest("foo %hi", 0xFFFF, "foo -1"); + DoNumTest("foo %Li", pos, "foo 42"); + DoI64Test("foo %I64i", l, "42", "foo 42"); + DoNumTest("foo %3i", pos, "foo 42"); + DoNumTest("foo %-3i", pos, "foo 42 "); + DoNumTest("foo %.1i", pos, "foo 42"); + DoNumTest("foo %.3i", pos, "foo 042"); + DoNumTest("foo %03i", pos, "foo 042"); + DoNumTest("foo %#i", pos, "foo 42"); + DoNumTest("foo %+i", pos, "foo +42"); + DoNumTest("foo % i", pos, "foo 42"); + DoNumTest("foo %+i", neg, "foo -42"); + DoNumTest("foo % i", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/testinfo.dat new file mode 100644 index 0000000..7c51443 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test9 +Description += Tests sprintf_s with integer numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/test1/CMakeLists.txt new file mode 100644 index 0000000..2af8b93 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_sqrt_test1 + ${SOURCES} +) + +add_dependencies(paltest_sqrt_test1 coreclrpal) + +target_link_libraries(paltest_sqrt_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/test1/test1.cpp new file mode 100644 index 0000000..62d2251 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/test1/test1.cpp @@ -0,0 +1,123 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Call the sqrt function on a positive value, a positive value +** with a decimal and on the maxium possible double value. +** +** +**===================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = sqrt(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("sqrt(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = sqrt(value); + + if (!_isnan(result)) + { + Fail("sqrt(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0.31830988618379067, 0.56418958354775629, PAL_EPSILON }, // value: 1 / pi + { 0.43429448190325183, 0.65901022898226081, PAL_EPSILON }, // value: log10(e) + { 0.63661977236758134, 0.79788456080286536, PAL_EPSILON }, // value: 2 / pi + { 0.69314718055994531, 0.83255461115769776, PAL_EPSILON }, // value: ln(2) + { 0.70710678118654752, 0.84089641525371454, PAL_EPSILON }, // value: 1 / sqrt(2) + { 0.78539816339744831, 0.88622692545275801, PAL_EPSILON }, // value: pi / 4 + { 1, 1, PAL_EPSILON * 10 }, + { 1.1283791670955126, 1.0622519320271969, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi) + { 1.4142135623730950, 1.1892071150027211, PAL_EPSILON * 10 }, // value: sqrt(2) + { 1.4426950408889634, 1.2011224087864498, PAL_EPSILON * 10 }, // value: log2(e) + { 1.5707963267948966, 1.2533141373155003, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.3025850929940457, 1.5174271293851464, PAL_EPSILON * 10 }, // value: ln(10) + { 2.7182818284590452, 1.6487212707001281, PAL_EPSILON * 10 }, // value: e + { 3.1415926535897932, 1.7724538509055160, PAL_EPSILON * 10 }, // value: pi + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + validate(-0.0, -0.0, PAL_EPSILON); + validate( 0.0, 0.0, PAL_EPSILON); + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + validate_isnan(-tests[i].value); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/test1/testinfo.dat new file mode 100644 index 0000000..804fef0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrt/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = sqrt +Name = Call sqrt on positive values and zero. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the sqrt function on a positive value, a positive value += with a decimal and on the maxium possible double value. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/test1/CMakeLists.txt new file mode 100644 index 0000000..5790f70 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_sqrtf_test1 + ${SOURCES} +) + +add_dependencies(paltest_sqrtf_test1 coreclrpal) + +target_link_libraries(paltest_sqrtf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/test1/test1.c new file mode 100644 index 0000000..cb1ac9e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/test1/test1.c @@ -0,0 +1,122 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Call the sqrtf function on a positive value, a positive value +** with a decimal and on the maxium possible float value. +** +** +**===================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = sqrtf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("sqrtf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = sqrtf(value); + + if (!_isnanf(result)) + { + Fail("sqrtf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0.318309886f, 0.564189584f, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0.659010229f, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0.797884561f, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0.832554611f, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0.840896415f, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 0.886226925f, PAL_EPSILON }, // value: pi / 4 + { 1, 1, PAL_EPSILON * 10 }, + { 1.12837917f, 1.06225193f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 1.18920712f, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 1.20112241f, PAL_EPSILON * 10 }, // value: logf2(e) + { 1.57079633f, 1.25331414f, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 1.51742713f, PAL_EPSILON * 10 }, // value: ln(10) + { 2.71828183f, 1.64872127f, PAL_EPSILON * 10 }, // value: e + { 3.14159265f, 1.77245385F, PAL_EPSILON * 10 }, // value: pi + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + validate(-0.0f, -0.0f, PAL_EPSILON); + validate( 0.0f, 0.0f, PAL_EPSILON); + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + validate_isnan(-tests[i].value); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/test1/testinfo.dat new file mode 100644 index 0000000..00d8ab2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sqrtf/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = sqrtf +Name = Call sqrtf on positive values and zero. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the sqrtf function on a positive value, a positive value += with a decimal and on the maxium possible float value. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/CMakeLists.txt new file mode 100644 index 0000000..56b4848 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/CMakeLists.txt @@ -0,0 +1,18 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/sscanf_s.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/sscanf_s.h new file mode 100644 index 0000000..8a99d87 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/sscanf_s.h @@ -0,0 +1,246 @@ +// 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. + +/*============================================================================ +** +** Source: sscanf_s.h +** +** Purpose: Contains common testing functions for sscanf_s +** +** +**==========================================================================*/ + +#ifndef __SSCANF_S_H__ +#define __SSCANF_S_H__ + +void DoVoidTest(char *inputstr, const char *formatstr) +{ + char buf[256] = { 0 }; + int i; + int ret; + + ret = sscanf_s(inputstr, formatstr, buf); + if (ret != 0) + { + Fail("ERROR: Expected sscanf_s to return 0, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + for (i=0; i<256; i++) + { + if (buf[i] != 0) + { + Fail("ERROR: Parameter unexpectedly modified scanning \"%s\" " + "using \"%s\".\n", inputstr, formatstr); + } + } + +} + +void DoStrTest(char *inputstr, const char *formatstr, const char *checkstr) +{ + char buf[256] = { 0 }; + int ret; + + ret = sscanf_s(inputstr, formatstr, buf, _countof(buf)); + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (memcmp(checkstr, buf, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: scanned string incorrectly from \"%s\" using \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", inputstr, formatstr, checkstr, + buf); + } + +} + +void DoWStrTest(char *inputstr, const char *formatstr, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + int ret; + + ret = sscanf_s(inputstr, formatstr, buf, _countof(buf)); + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (memcmp(checkstr, buf, wcslen(checkstr)*2 + 2) != 0) + { + Fail("ERROR: scanned wide string incorrectly from \"%s\" using \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", inputstr, formatstr, + convertC(checkstr), convertC(buf)); + } + +} + +void DoNumTest(char *inputstr, const char *formatstr, int checknum) +{ + int num; + int ret; + + ret = sscanf_s(inputstr, formatstr, &num); + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (checknum != num) + { + Fail("ERROR: scanned number incorrectly from \"%s\" using \"%s\".\n" + "Expected %d, got %d.\n", inputstr, formatstr, checknum, num); + } +} + +void DoShortNumTest(char *inputstr, const char *formatstr, short checknum) +{ + short num; + int ret; + + ret = sscanf_s(inputstr, formatstr, &num); + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (checknum != num) + { + Fail("ERROR: scanned number incorrectly from \"%s\" using \"%s\".\n" + "Expected %hd, got %hd.\n", inputstr, formatstr, checknum, num); + } +} + +void DoI64NumTest(char *inputstr, const char *formatstr, INT64 checknum) +{ + char buf[256]; + char check[256]; + INT64 num; + int ret; + + ret = sscanf_s(inputstr, formatstr, &num); + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (checknum != num) + { + sprintf_s(buf, _countof(buf), "%I64d", num); + sprintf_s(check, _countof(check), "%I64d", checknum); + Fail("ERROR: scanned I64 number incorrectly from \"%s\" using \"%s\".\n" + "Expected %s, got %s.\n", inputstr, formatstr, check, buf); + } +} + +void DoCharTest(char *inputstr, const char *formatstr, char* checkchars, int numchars) +{ + char buf[256]; + int ret; + int i; + + for (i=0; i<256; i++) + buf[i] = (char)-1; + + ret = sscanf_s(inputstr, formatstr, buf, _countof(buf)); + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (memcmp(buf, checkchars, numchars) != 0) + { + buf[numchars] = 0; + + Fail("ERROR: scanned character(s) incorrectly from \"%s\" using \"%s\".\n" + "Expected %s, got %s.\n", inputstr, formatstr, checkchars, + buf); + } + + if (buf[numchars] != (char)-1) + { + Fail("ERROR: overflow occurred in scanning character(s) from \"%s\" " + "using \"%s\".\nExpected %d character(s)\n", inputstr, formatstr, + numchars); + } +} + +void DoWCharTest(char *inputstr, const char *formatstr, WCHAR* checkchars, int numchars) +{ + WCHAR buf[256]; + int ret; + int i; + + for (i=0; i<256; i++) + buf[i] = (WCHAR)-1; + + ret = sscanf_s(inputstr, formatstr, buf, _countof(buf)); + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (memcmp(buf, checkchars, numchars) != 0) + { + buf[numchars] = 0; + + Fail("ERROR: scanned wide character(s) incorrectly from \"%s\" using \"%s\".\n" + "Expected %s, got %s.\n", inputstr, formatstr, convertC(checkchars), + convertC(buf)); + } + + if (buf[numchars] != (WCHAR)-1) + { + Fail("ERROR: overflow occurred in scanning wide character(s) from \"%s\" " + "using \"%s\".\nExpected %d character(s)\n", inputstr, formatstr, + numchars); + } +} + + +void DoFloatTest(char *inputstr, const char *formatstr, float checkval) +{ + char buf[256] = { 0 }; + float val; + int ret; + int i; + + for (i=0; i<256; i++) + buf[i] = (char)-1; + + ret = sscanf_s(inputstr, formatstr, buf); + val = *(float*)buf; + + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (val != checkval) + { + Fail("ERROR: scanned float incorrectly from \"%s\" using \"%s\".\n" + "Expected \"%f\", got \"%f\".\n", inputstr, formatstr, checkval, + val); + } + + if (buf[4] != (char)-1) + { + Fail("ERROR: overflow occurred in scanning float from \"%s\" " + "using \"%s\".\n", inputstr, formatstr); + + } +} + + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/CMakeLists.txt new file mode 100644 index 0000000..6069fc8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_sscanf_test1 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test1 coreclrpal) + +target_link_libraries(paltest_sscanf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/test1.cpp new file mode 100644 index 0000000..6131314 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/test1.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: General test of sscanf_s +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int num; + int ret; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoVoidTest("foo bar", "foo "); + DoVoidTest("foo bar", "baz"); + DoVoidTest("foo bar", "foo %*s"); + + DoStrTest("foo % bar", "foo %% %s", "bar"); + DoStrTest("foo bar baz", "foo %bar %s", "baz"); + + DoVoidTest("foo bar baz", "foo % bar %s"); + DoVoidTest("foo baz bar", "foo% baz %s"); + + ret = sscanf_s("foo bar baz", "foo bar %n", &num); + if (ret != 0 || num != 8) + { + Fail("ERROR: Got incorrect values in scanning \"%s\" using \"%s\".\n" + "Expected to get a value of %d with return value of %d, " + "got %d with return %d\n", "foo bar baz", "foo bar %n", 8, 0, + num, ret); + + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/testinfo.dat new file mode 100644 index 0000000..76f5927 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test1 +Description += General test of sscanf_s diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/CMakeLists.txt new file mode 100644 index 0000000..ba3dbad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_sscanf_test10 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test10 coreclrpal) + +target_link_libraries(paltest_sscanf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/test10.cpp new file mode 100644 index 0000000..0c63c86 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/test10.cpp @@ -0,0 +1,37 @@ +// 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. + +/*============================================================================ +** +** Source: test10.c +** +** Purpose: Tests sscanf_s with wide characters +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoWCharTest("1234d", "%C", convert("1"), 1); + DoWCharTest("1234d", "%C", convert("1"), 1); + DoWCharTest("abc", "%2C", convert("ab"), 2); + DoWCharTest(" ab", "%C", convert(" "), 1); + DoCharTest("ab", "%hC", "a", 1); + DoWCharTest("ab", "%lC", convert("a"), 1); + DoWCharTest("ab", "%LC", convert("a"), 1); + DoWCharTest("ab", "%I64C", convert("a"), 1); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/testinfo.dat new file mode 100644 index 0000000..e048e70 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test10 +Description += Tests sscanf_s with wide characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/CMakeLists.txt new file mode 100644 index 0000000..69f2125 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_sscanf_test11 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test11 coreclrpal) + +target_link_libraries(paltest_sscanf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/test11.cpp new file mode 100644 index 0000000..8279f4b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/test11.cpp @@ -0,0 +1,36 @@ +// 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. + +/*============================================================================ +** +** Source: test11.c +** +** Purpose: Tests sscanf_s with strings +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoStrTest("foo bar", "foo %s", "bar"); + DoStrTest("foo bar", "foo %2s", "ba"); + DoStrTest("foo bar", "foo %hs", "bar"); + DoWStrTest("foo bar", "foo %ls", convert("bar")); + DoStrTest("foo bar", "foo %Ls", "bar"); + DoStrTest("foo bar", "foo %I64s", "bar"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/testinfo.dat new file mode 100644 index 0000000..5a906dd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test11 +Description += Tests sscanf_s with strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/CMakeLists.txt new file mode 100644 index 0000000..21dbb42 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_sscanf_test12 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test12 coreclrpal) + +target_link_libraries(paltest_sscanf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/test12.cpp new file mode 100644 index 0000000..e599534 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/test12.cpp @@ -0,0 +1,35 @@ +// 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. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Tests sscanf_s with wide strings +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoWStrTest("foo bar", "foo %S", convert("bar")); + DoWStrTest("foo bar", "foo %2S", convert("ba")); + DoStrTest("foo bar", "foo %hS", "bar"); + DoWStrTest("foo bar", "foo %lS", convert("bar")); + DoWStrTest("foo bar", "foo %LS", convert("bar")); + DoWStrTest("foo bar", "foo %I64S", convert("bar")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/testinfo.dat new file mode 100644 index 0000000..569be98 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test12 +Description += Tests sscanf_s with wide strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/CMakeLists.txt new file mode 100644 index 0000000..56a1adc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_sscanf_test13 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test13 coreclrpal) + +target_link_libraries(paltest_sscanf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/test13.cpp new file mode 100644 index 0000000..4fc12bb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/test13.cpp @@ -0,0 +1,37 @@ +// 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. + +/*============================================================================ +** +** Source: test13.c +** +** Purpose: Tests sscanf_s with floats (decimal notation) +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest("123.0", "%f", 123.0f); + DoFloatTest("123.0", "%2f", 12.0f); + DoFloatTest("10E1", "%f", 100.0f); + DoFloatTest("-12.01e-2", "%f", -0.1201f); + DoFloatTest("+12.01e-2", "%f", 0.1201f); + DoFloatTest("-12.01e+2", "%f", -1201.0f); + DoFloatTest("+12.01e+2", "%f", 1201.0f); + DoFloatTest("1234567890.0123456789f", "%f", 1234567936); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/testinfo.dat new file mode 100644 index 0000000..651577b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test13 +Description += Tests sscanf_s with floats (decimal notation) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/CMakeLists.txt new file mode 100644 index 0000000..17cc710 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_sscanf_test14 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test14 coreclrpal) + +target_link_libraries(paltest_sscanf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/test14.cpp new file mode 100644 index 0000000..fc2fa2e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/test14.cpp @@ -0,0 +1,36 @@ +// 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. + +/*============================================================================ +** +** Source: test14.c +** +** Purpose: Tests sscanf_s with floats (exponential notation, lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest("123.0", "%e", 123.0f); + DoFloatTest("123.0", "%2e", 12.0f); + DoFloatTest("10E1", "%e", 100.0f); + DoFloatTest("-12.01e-2", "%e", -0.1201f); + DoFloatTest("+12.01e-2", "%e", 0.1201f); + DoFloatTest("-12.01e+2", "%e", -1201.0f); + DoFloatTest("+12.01e+2", "%e", 1201.0f); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/testinfo.dat new file mode 100644 index 0000000..8e7338f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test14 +Description += Tests sscanf_s with floats (exponential notation, lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/CMakeLists.txt new file mode 100644 index 0000000..d33cbb7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_sscanf_test15 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test15 coreclrpal) + +target_link_libraries(paltest_sscanf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/test15.cpp new file mode 100644 index 0000000..1eff995 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/test15.cpp @@ -0,0 +1,36 @@ +// 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. + +/*============================================================================ +** +** Source: test15.c +** +** Purpose: Tests sscanf_s with floats (exponential notation, uppercase +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest("123.0", "%E", 123.0f); + DoFloatTest("123.0", "%2E", 12.0f); + DoFloatTest("10E1", "%E", 100.0f); + DoFloatTest("-12.01e-2", "%E", -0.1201f); + DoFloatTest("+12.01e-2", "%E", 0.1201f); + DoFloatTest("-12.01e+2", "%E", -1201.0f); + DoFloatTest("+12.01e+2", "%E", 1201.0f); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/testinfo.dat new file mode 100644 index 0000000..d713a73 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test15 +Description += Tests sscanf_s with floats (exponential notation, uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/CMakeLists.txt new file mode 100644 index 0000000..fc8d924 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_sscanf_test16 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test16 coreclrpal) + +target_link_libraries(paltest_sscanf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/test16.cpp new file mode 100644 index 0000000..f202767 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/test16.cpp @@ -0,0 +1,37 @@ +// 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. + +/*============================================================================ +** +** Source: test16.c +** +** Purpose:Tests sscanf_s with floats (compact notation, lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest("123.0", "%g", 123.0f); + DoFloatTest("123.0", "%2g", 12.0f); + DoFloatTest("10E1", "%g", 100.0f); + DoFloatTest("-12.01e-2", "%g", -0.1201f); + DoFloatTest("+12.01e-2", "%g", 0.1201f); + DoFloatTest("-12.01e+2", "%g", -1201.0f); + DoFloatTest("+12.01e+2", "%g", 1201.0f); + DoFloatTest("1234567890.0123456789g", "%g", 1234567936); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/testinfo.dat new file mode 100644 index 0000000..6696119 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test16 +Description += Tests sscanf_s with floats (compact notation, lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/CMakeLists.txt new file mode 100644 index 0000000..8f8f02f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_sscanf_test17 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test17 coreclrpal) + +target_link_libraries(paltest_sscanf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/test17.cpp new file mode 100644 index 0000000..a18c3ca --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/test17.cpp @@ -0,0 +1,37 @@ +// 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. + +/*============================================================================ +** +** Source: test17.c +** +** Purpose: Tests sscanf_s with floats (compact notation, uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest("123.0", "%G", 123.0f); + DoFloatTest("123.0", "%2G", 12.0f); + DoFloatTest("10E1", "%G", 100.0f); + DoFloatTest("-12.01e-2", "%G", -0.1201f); + DoFloatTest("+12.01e-2", "%G", 0.1201f); + DoFloatTest("-12.01e+2", "%G", -1201.0f); + DoFloatTest("+12.01e+2", "%G", 1201.0f); + DoFloatTest("1234567890.0123456789G", "%G", 1234567936); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/testinfo.dat new file mode 100644 index 0000000..8ce4e93 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test17 +Description += Tests sscanf_s with floats (compact notation, uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/CMakeLists.txt new file mode 100644 index 0000000..26b23fd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_sscanf_test2 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test2 coreclrpal) + +target_link_libraries(paltest_sscanf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/test2.cpp new file mode 100644 index 0000000..c9c79f6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/test2.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Test to see if sscanf_s handles whitespace correctly +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + + +/* + * Tests out how it handles whitespace. Seems to accept anything that qualifies + * as isspace (space, tab, vertical tab, line feed, carriage return and form + * feed), even if it says it only wants spaces tabs and newlines. + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoStrTest("foo bar", "foo %s", "bar"); + DoStrTest("foo\tbar", "foo %s", "bar"); + DoStrTest("foo\nbar", "foo %s", "bar"); + DoStrTest("foo\rbar", "foo %s", "bar"); + DoStrTest("foo\vbar", "foo %s", "bar"); + DoStrTest("foo\fbar", "foo %s", "bar"); + DoStrTest("foo \t\n\r\v\fbar", "foo %s", "bar"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/testinfo.dat new file mode 100644 index 0000000..85fed24 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test2 +Description += Test to see if sscanf_s handles whitespace correctly diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/CMakeLists.txt new file mode 100644 index 0000000..030b000 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_sscanf_test3 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test3 coreclrpal) + +target_link_libraries(paltest_sscanf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/test3.cpp new file mode 100644 index 0000000..e1e45bd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/test3.cpp @@ -0,0 +1,35 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Tests sscanf_s with bracketed set strings +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoStrTest("bar1", "%[a-z]", "bar"); + DoStrTest("bar1", "%[z-a]", "bar"); + DoStrTest("bar1", "%[ab]", "ba"); + DoStrTest("bar1", "%[ar1b]", "bar1"); + DoStrTest("bar1", "%[^4]", "bar1"); + DoStrTest("bar1", "%[^4a]", "b"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/testinfo.dat new file mode 100644 index 0000000..523d31e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test3 +Description += Tests sscanf_s with bracketed set strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/CMakeLists.txt new file mode 100644 index 0000000..a9fa199 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_sscanf_test4 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test4 coreclrpal) + +target_link_libraries(paltest_sscanf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/test4.cpp new file mode 100644 index 0000000..f8413ea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/test4.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Tests sscanf_s with decimal numbers +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest("1234d", "%d", 1234); + DoNumTest("1234d", "%2d", 12); + DoNumTest("-1", "%d", -1); + DoNumTest("0x1234", "%d", 0); + DoNumTest("012", "%d", 12); + DoShortNumTest("-1", "%hd", n65535); + DoShortNumTest("65536", "%hd", 0); + DoNumTest("-1", "%ld", -1); + DoNumTest("65536", "%ld", 65536); + DoNumTest("-1", "%Ld", -1); + DoNumTest("65536", "%Ld", 65536); + DoI64NumTest("4294967296", "%I64d", I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/testinfo.dat new file mode 100644 index 0000000..2065f2b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test4 +Description += Tests sscanf_s with decimal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/CMakeLists.txt new file mode 100644 index 0000000..7041168 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_sscanf_test5 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test5 coreclrpal) + +target_link_libraries(paltest_sscanf_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/test5.cpp new file mode 100644 index 0000000..cdfefd8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/test5.cpp @@ -0,0 +1,43 @@ +// 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. + +/*============================================================================ +** +** Source: test5.c +** +** Purpose: Tests sscanf_s with integer numbers +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest("1234d", "%i", 1234); + DoNumTest("1234d", "%2i", 12); + DoNumTest("-1", "%i", -1); + DoNumTest("0x1234", "%i", 0x1234); + DoNumTest("012", "%i", 10); + DoShortNumTest("-1", "%hi", n65535); + DoShortNumTest("65536", "%hi", 0); + DoNumTest("-1", "%li", -1); + DoNumTest("65536", "%li", 65536); + DoNumTest("-1", "%Li", -1); + DoNumTest("65536", "%Li", 65536); + DoI64NumTest("4294967296", "%I64i", I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/testinfo.dat new file mode 100644 index 0000000..cb687c1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test5 +Description += Tests sscanf_s with integer numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/CMakeLists.txt new file mode 100644 index 0000000..7c18d13 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_sscanf_test6 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test6 coreclrpal) + +target_link_libraries(paltest_sscanf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/test6.cpp new file mode 100644 index 0000000..507b100 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/test6.cpp @@ -0,0 +1,43 @@ +// 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. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose: Tests sscanf_s with octal numbers +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest("1234d", "%o", 668); + DoNumTest("1234d", "%2o", 10); + DoNumTest("-1", "%o", -1); + DoNumTest("0x1234", "%o", 0); + DoNumTest("012", "%o", 10); + DoShortNumTest("-1", "%ho", n65535); + DoShortNumTest("200000", "%ho", 0); + DoNumTest("-1", "%lo", -1); + DoNumTest("200000", "%lo", 65536); + DoNumTest("-1", "%Lo", -1); + DoNumTest("200000", "%Lo", 65536); + DoI64NumTest("40000000000", "%I64o", I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/testinfo.dat new file mode 100644 index 0000000..9e518dd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test6 +Description += Tests sscanf_s with octal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/CMakeLists.txt new file mode 100644 index 0000000..d80c138 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_sscanf_test7 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test7 coreclrpal) + +target_link_libraries(paltest_sscanf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/test7.cpp new file mode 100644 index 0000000..4093e00 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/test7.cpp @@ -0,0 +1,43 @@ +// 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. + +/*============================================================================ +** +** Source: test7.c +** +** Purpose: Tests sscanf_s with hex numbers (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest("1234i", "%x", 0x1234); + DoNumTest("1234i", "%2x", 0x12); + DoNumTest("-1", "%x", -1); + DoNumTest("0x1234", "%x", 0x1234); + DoNumTest("012", "%x", 0x12); + DoShortNumTest("-1", "%hx", n65535); + DoShortNumTest("10000", "%hx", 0); + DoNumTest("-1", "%lx", -1); + DoNumTest("10000", "%lx", 65536); + DoNumTest("-1", "%Lx", -1); + DoNumTest("10000", "%Lx", 65536); + DoI64NumTest("100000000", "%I64x", I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/testinfo.dat new file mode 100644 index 0000000..8d6c182 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test7 +Description += Tests sscanf_s with hex numbers (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/CMakeLists.txt new file mode 100644 index 0000000..d9759d9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_sscanf_test8 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test8 coreclrpal) + +target_link_libraries(paltest_sscanf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/test8.cpp new file mode 100644 index 0000000..23ef22a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/test8.cpp @@ -0,0 +1,43 @@ +// 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. + +/*============================================================================ +** +** Source: test8.c +** +** Purpose:Tests sscanf_s with unsigned number +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest("1234d", "%u", 1234); + DoNumTest("1234d", "%2u", 12); + DoNumTest("-1", "%u", -1); + DoNumTest("0x1234", "%u", 0); + DoNumTest("012", "%u", 12); + DoShortNumTest("-1", "%hu", n65535); + DoShortNumTest("65536", "%hu", 0); + DoNumTest("-1", "%lu", -1); + DoNumTest("65536", "%lu", 65536); + DoNumTest("-1", "%Lu", -1); + DoNumTest("65536", "%Lu", 65536); + DoI64NumTest("4294967296", "%I64u", I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/testinfo.dat new file mode 100644 index 0000000..0287a49 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test8 +Description += Tests sscanf_s with unsigned numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/CMakeLists.txt new file mode 100644 index 0000000..37b4ad8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_sscanf_test9 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test9 coreclrpal) + +target_link_libraries(paltest_sscanf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/test9.cpp new file mode 100644 index 0000000..2c99c40 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/test9.cpp @@ -0,0 +1,38 @@ +// 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. + +/*============================================================================ +** +** Source: test9.c +** +** Purpose: Tests sscanf_s with characters +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoCharTest("1234d", "%c", "1", 1); + DoCharTest("1234d", "%c", "1", 1); + DoCharTest("abc", "%2c", "ab", 2); + DoCharTest(" ab", "%c", " ", 1); + DoCharTest("ab", "%hc", "a", 1); + DoWCharTest("ab", "%lc", convert("a"), 1); + DoCharTest("ab", "%Lc", "a", 1); + DoCharTest("ab", "%I64c", "a", 1); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/testinfo.dat new file mode 100644 index 0000000..95f6c74 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/testinfo.dat @@ -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. + +Version = 1.0 +Section =C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test9 +Description += Tests sscanf_s with characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/test1/CMakeLists.txt new file mode 100644 index 0000000..a08cb2b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_strcat_test1 + ${SOURCES} +) + +add_dependencies(paltest_strcat_test1 coreclrpal) + +target_link_libraries(paltest_strcat_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/test1/test1.cpp new file mode 100644 index 0000000..532d846 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/test1/test1.cpp @@ -0,0 +1,66 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Concatenate three strings into one string. Each time, check to ensure +** the pointer returned was what we expected. When finished, compare the +** newly formed string to what it should be to ensure no characters were +** lost. +** +** +**==========================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + char dest[80]; + char *test = "foo bar baz"; + char *str1 = "foo "; + char *str2 = "bar "; + char *str3 = "baz"; + char *ptr; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + dest[0] = 0; + + ptr = strcat(dest, str1); + if (ptr != dest) + { + Fail("ERROR: Expected strcat to return ptr to %p, got %p", dest, ptr); + } + + ptr = strcat(dest, str2); + if (ptr != dest) + { + Fail("ERROR: Expected strcat to return ptr to %p, got %p", dest, ptr); + } + + ptr = strcat(dest, str3); + if (ptr != dest) + { + Fail("ERROR: Expected strcat to return ptr to %p, got %p", dest, ptr); + } + + if (strcmp(dest, test) != 0) + { + Fail("ERROR: Expected strcat to give \"%s\", got \"%s\"\n", + test, dest); + } + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/test1/testinfo.dat new file mode 100644 index 0000000..6d67ffa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcat/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = strcat +Name = Test #1 for strcat +TYPE = DEFAULT +EXE1 = test1 +Description += Concatenate three strings into one string. Each time, check to ensure += the pointer returned was what we expected. When finished, compare the += newly formed string to what it should be to ensure no characters were += lost. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/test1/CMakeLists.txt new file mode 100644 index 0000000..a3e6cf8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_strchr_test1 + ${SOURCES} +) + +add_dependencies(paltest_strchr_test1 coreclrpal) + +target_link_libraries(paltest_strchr_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/test1/test1.cpp new file mode 100644 index 0000000..9190c4f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/test1/test1.cpp @@ -0,0 +1,86 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Test this on a character which is in a string, and ensure the pointer +** points to that character. Then check the string for the null character, +** which the return pointer should point to. Then search for a character not +** in the string and check that the return value is NULL. +** +** +**==========================================================================*/ + +#include + +struct testCase +{ + int result; + char string[50]; + int character; +}; + + + +int __cdecl main(int argc, char *argv[]) +{ + int i = 0; + char *result; + + /* + * this structure includes several strings to be tested with + * strchr function and the expected results + */ + + struct testCase testCases[]= + { + {22,"corn cup cat cream coast",'s'}, + {10,"corn cup cat cream coast",'a'}, + {2,"This is a test",'i'}, + {10,"This is a test",'t'}, + {'\0',"This is a test",'b'},/* zero used instead of NULL */ + {'\0',"This is a test",121},/* zero used instead of NULL */ + {4,"This is a test of the function",' '}, + {25,"This is a test of the function",'c'}, + {'\0',"This is a test of the function",'C'}, + {24,"corn cup cat cream coast", '\0'}/* zero used instead of NULL */ + }; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Loop through the structure and test each case */ + + for (i=0; i< sizeof(testCases)/sizeof(struct testCase); i++) + { + result = strchr(testCases[i].string,testCases[i].character); + if (result==NULL) + { + if (testCases[i].result != (int) NULL) + { + Fail("Expected strchr() to return \"%s\" instead of NULL!\n", + testCases[i].string + testCases[i].result); + } + } + else + { + if (result != testCases[i].string + testCases[i].result) + { + Fail("Expected strchr() to return \"%s\" instead of \"%s\"!\n", + testCases[i].string + testCases[i].result, result); + } + } + + } + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/test1/testinfo.dat new file mode 100644 index 0000000..4985c47 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strchr/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = strchr +Name = Test #1 for strchr +TYPE = DEFAULT +EXE1 = test1 +Description += Test this on a character which is in a string, and ensure the pointer += points to that character. Then check the string for the null character, += which the return pointer should point to. Then search for a character not += in the string and check that the return value is NULL. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/test1/CMakeLists.txt new file mode 100644 index 0000000..74d260c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_strcmp_test1 + ${SOURCES} +) + +add_dependencies(paltest_strcmp_test1 coreclrpal) + +target_link_libraries(paltest_strcmp_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/test1/test1.cpp new file mode 100644 index 0000000..49428fd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/test1/test1.cpp @@ -0,0 +1,73 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Compare a number of different strings against each other, ensure that the +** three return values are given at the appropriate times. +** +** +**==========================================================================*/ + +#include + +typedef struct +{ + int result; + char string1[50]; + char string2[50]; +} testCase; + +testCase testCases[]= +{ + {0,"Hello","Hello"}, + {1,"hello","Hello"}, + {-1,"Hello","hello"}, + {0,"0Test","0Test"}, + {0,"***???","***???"}, + {0,"Testing the string for string comparison","Testing the string for " + "string comparison"}, + {-1,"Testing the string for string comparison","Testing the string for " + "string comparsioa"}, + {1,"Testing the string for string comparison","Testing the string for " + "comparison"}, + {-1,"aaaabbbbb","aabcdefeccg"} +}; + +int __cdecl main(int argc, char *argv[]) +{ + int i = 0; + int result = 0; + + /* + * Initialize the PAL + */ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Loop through structure and test each case */ + for (i=0; i < sizeof(testCases)/sizeof(testCase); i++) + { + result = strcmp(testCases[i].string1,testCases[i].string2); + + /* Compare returned value */ + if( ((result == 0) && (testCases[i].result !=0)) || + ((result <0) && (testCases[i].result !=-1)) || + ((result >0) && (testCases[i].result !=1)) ) + { + Fail("ERROR: strcmp returned %d instead of %d\n", + result, testCases[i].result); + } + + } + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/test1/testinfo.dat new file mode 100644 index 0000000..174cb4b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcmp/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = strcmp +Name = Test #1 for strcmp +TYPE = DEFAULT +EXE1 = test1 +Description += Compare a number of different strings against each other, ensure that the += three return values are given at the appropriate times. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/test1/CMakeLists.txt new file mode 100644 index 0000000..3fc0bfc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_strcpy_test1 + ${SOURCES} +) + +add_dependencies(paltest_strcpy_test1 coreclrpal) + +target_link_libraries(paltest_strcpy_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/test1/test1.cpp new file mode 100644 index 0000000..43069e5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/test1/test1.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Call the function to copy into an empty buffer. Check that the return value +** is pointing at the destination buffer. Also compare the string copied to +** the origional string, to ensure they are the same. +** +** +**==========================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + char dest[80]; + char *result = "foo"; + char str[] = {'f','o','o',0,'b','a','r',0}; + char *ret; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + ret = strcpy(dest, str); + + if (ret != dest) + { + Fail("Expected strcpy to return %p, got %p!\n", dest, ret); + + } + + if (strcmp(dest, result) != 0) + { + Fail("Expected strcpy to give \"%s\", got \"%s\"!\n", result, dest); + } + + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/test1/testinfo.dat new file mode 100644 index 0000000..700b124 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcpy/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = strcpy +Name = Test #1 for strcpy +TYPE = DEFAULT +EXE1 = test1 +Description += Call the function to copy into an empty buffer. Check that the return value += is pointing at the destination buffer. Also compare the string copied to += the origional string, to ensure they are the same. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcspn/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcspn/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcspn/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcspn/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcspn/test1/CMakeLists.txt new file mode 100644 index 0000000..f2fe19a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcspn/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_strcspn_test1 + ${SOURCES} +) + +add_dependencies(paltest_strcspn_test1 coreclrpal) + +target_link_libraries(paltest_strcspn_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcspn/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcspn/test1/test1.cpp new file mode 100644 index 0000000..ddc5667 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strcspn/test1/test1.cpp @@ -0,0 +1,59 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests strcspn with a character set that should give an index into +** the middle of the original string. Also tests with character sets +** that are not in the string at all, and character sets that match +** with the very first character. +** +** +**==========================================================================*/ + +#include + +struct testCase +{ + long result; + char *string1; + char *string2; +}; + +int __cdecl main(int argc, char *argv[]) +{ + int i=0; + long TheResult = 0; + + struct testCase testCases[]= + { + {4,"abcdefg12345678hijklmnopqrst","t8m1sBe"}, + {23,"This is a test, testing", "X\tylM"}, + {0,"foobar","tzkfb"}, + }; + + /* + * Initialize the PAL + */ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + for (i=0; i + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + if (strlen("foo") != 3) + Fail("ERROR: strlen(\"foo\") != 3\n"); + + if (strlen("") != 0) + Fail("ERROR: strlen(\"\") != 0\n"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strlen/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strlen/test1/testinfo.dat new file mode 100644 index 0000000..ac5c3ae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strlen/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = strlen +Name = Positive Test for strlen +TYPE = DEFAULT +EXE1 = test1 +Description += Check the length of a string and the length of a 0 character string to += see that this function returns the correct values for each. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/test1/CMakeLists.txt new file mode 100644 index 0000000..7221b15 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_strncat_test1 + ${SOURCES} +) + +add_dependencies(paltest_strncat_test1 coreclrpal) + +target_link_libraries(paltest_strncat_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/test1/test1.cpp new file mode 100644 index 0000000..000d168 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/test1/test1.cpp @@ -0,0 +1,77 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Concatenate a few strings together, setting different lengths to be +** used for each one. Check to ensure the pointers which are returned are +** correct, and that the final string is what was expected. +** +** +**==========================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + char dest[80]; + char *test = "foo barbaz"; + char *str1 = "foo "; + char *str2 = "bar "; + char *str3 = "baz"; + char *ptr; + int i; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + dest[0] = 0; + for (i=1; i<80; i++) + { + dest[i] = 'x'; + } + + ptr = strncat(dest, str1, strlen(str1)); + if (ptr != dest) + { + Fail("ERROR: Expected strncat to return ptr to %p, got %p", dest, ptr); + } + + ptr = strncat(dest, str2, 3); + if (ptr != dest) + { + Fail("ERROR: Expected strncat to return ptr to %p, got %p", dest, ptr); + } + if (dest[7] != 0) + { + Fail("ERROR: strncat did not place a terminating NULL!"); + } + + ptr = strncat(dest, str3, 20); + if (ptr != dest) + { + Fail("ERROR: Expected strncat to return ptr to %p, got %p", dest, ptr); + } + if (strcmp(dest, test) != 0) + { + Fail("ERROR: Expected strncat to give \"%s\", got \"%s\"\n", + test, dest); + } + if (dest[strlen(test)+1] != 'x') + { + Fail("strncat went out of bounds!\n"); + } + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/test1/testinfo.dat new file mode 100644 index 0000000..4aaedbf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncat/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = strncat +Name = Test #1 for strncat +TYPE = DEFAULT +EXE1 = test1 +Description += Concatenate a few strings together, setting different lengths to be += used for each one. Check to ensure the pointers which are returned are += correct, and that the final string is what was expected. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/test1/CMakeLists.txt new file mode 100644 index 0000000..3787d50 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_strncmp_test1 + ${SOURCES} +) + +add_dependencies(paltest_strncmp_test1 coreclrpal) + +target_link_libraries(paltest_strncmp_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/test1/test1.cpp new file mode 100644 index 0000000..7326c3b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/test1/test1.cpp @@ -0,0 +1,80 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Test to ensure all three possible return values are given under the +** appropriate circumstance. Also, uses different sizes, to only compare +** portions of strings, checking to make sure these return the correct value. +** +** +**==========================================================================*/ + +#include + +typedef struct +{ + int result; + char string1[50]; + char string2[50]; + int number; +} testCase; + +testCase testCases[]= +{ + {0,"Hello","Hello",5}, + {1,"hello","Hello",3}, + {-1,"Hello","hello",5}, + {0,"heLLo","heLLo",5}, + {1,"hello","heLlo",5}, + {-1,"heLlo","hello",5}, + {0,"0Test","0Test",5}, + {0,"***???","***???",6}, + {0,"Testing the string for string comparison","Testing the string for " + "string comparison",40}, + {-1,"Testing the string for string comparison","Testing the string for " + "string comparsioa",40}, + {1,"Testing the string for string comparison","Testing the string for " + "comparison",34}, + {0,"aaaabbbbb","aabcdefeccg",2}, + {0,"abcd","abcd",10} +}; + + +int __cdecl main(int argc, char *argv[]) +{ + int i=0; + int iresult=0; + + /* + * Initialize the PAL + */ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + for (i=0; i< sizeof(testCases)/sizeof(testCase); i++) + { + iresult = strncmp(testCases[i].string1,testCases[i].string2, + testCases[i].number); + + if( ((iresult == 0) && (testCases[i].result !=0)) || + ((iresult <0) && (testCases[i].result !=-1)) || + ((iresult >0) && (testCases[i].result !=1)) ) + + { + Fail("ERROR: strncmp returned %d instead of %d\n", + iresult, testCases[i].result); + } + + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/test1/testinfo.dat new file mode 100644 index 0000000..8e95311 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncmp/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = strncmp +Name = Test #1 for strncmp +TYPE = DEFAULT +EXE1 = test1 +Description += Test to ensure all three possible return values are given under the += appropriate circumstance. Also, uses different sizes, to only compare += portions of strings, checking to make sure these return the correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/test1/CMakeLists.txt new file mode 100644 index 0000000..fac1004 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_strncpy_test1 + ${SOURCES} +) + +add_dependencies(paltest_strncpy_test1 coreclrpal) + +target_link_libraries(paltest_strncpy_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/test1/test1.cpp new file mode 100644 index 0000000..62baf61 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/test1/test1.cpp @@ -0,0 +1,85 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Test to see that you can copy a portion of a string into a new buffer. +** Also check that the strncpy function doesn't overflow when it is used. +** Finally check that if the number of characters given is greater than the +** amount to copy, that the destination buffer is padded with NULLs. +** +** +**==========================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + char dest[80]; + char *result = "foobar"; + char *str = "foobar\0baz"; + char *ret; + int i; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + for (i=0; i<80; i++) + { + dest[i] = 'x'; + } + + ret = strncpy(dest, str, 3); + if (ret != dest) + { + Fail("Expected strncpy to return %p, got %p!\n", dest, ret); + } + + if (strncmp(dest, result, 3) != 0) + { + Fail("Expected strncpy to give \"%s\", got \"%s\"!\n", result, dest); + } + + if (dest[3] != 'x') + { + Fail("strncpy overflowed!\n"); + } + + ret = strncpy(dest, str, 40); + if (ret != dest) + { + Fail("Expected strncpy to return %p, got %p!\n", dest, ret); + } + + if (strcmp(dest, result) != 0) + { + Fail("Expected strncpy to give \"%s\", got \"%s\"!\n", result, dest); + } + + for (i=strlen(str); i<40; i++) + { + if (dest[i] != 0) + { + Fail("strncpy failed to pad the destination with NULLs!\n"); + } + } + + if (dest[40] != 'x') + { + Fail("strncpy overflowed!\n"); + } + + + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/test1/testinfo.dat new file mode 100644 index 0000000..c402adb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strncpy/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = strncpy +Name = Test #1 for strncpy +TYPE = DEFAULT +EXE1 = test1 +Description += Test to see that you can copy a portion of a string into a new buffer. += Also check that the strncpy function doesn't overflow when it is used. += Finally check that if the number of characters given is greater than the += amount to copy, that the destination buffer is padded with NULLs. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/test1/CMakeLists.txt new file mode 100644 index 0000000..6748bea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_strpbrk_test1 + ${SOURCES} +) + +add_dependencies(paltest_strpbrk_test1 coreclrpal) + +target_link_libraries(paltest_strpbrk_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/test1/test1.cpp new file mode 100644 index 0000000..cf81c58 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/test1/test1.cpp @@ -0,0 +1,85 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Search a string for characters in a given character set and ensure the +** pointer returned points to the first occurrence. Check to see that the +** function returns NULL if the character is not found. +** +** +**==========================================================================*/ + +#include + +struct testCase +{ + char *result; + char *string1; + char *string2; +}; + +int __cdecl main(int argc, char *argv[]) +{ + char *ptr = NULL; + int i = 0; + + /* + * this structure includes several strings to be tested with + * strpbk function and the expected results + */ + + struct testCase testCases[] = + { + {"t cream coast","corn cup cat cream coast","sit"}, + {"eam coast","corn cup cat cream coast","like"}, + {"is is a test","This is a test","circle"}, + {"a test","This is a test","way"}, + {NULL,"This is a test","boo"}, + {NULL,"This is a test","123"}, + {" is a test of the function","This is a test of the function", + "zzz xx"} + }; + + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* A loop to go through the testcases in the structure */ + + for (i=0; i< sizeof(testCases)/sizeof(struct testCase); i++) + { + ptr = strpbrk(testCases[i].string1,testCases[i].string2); + if (ptr==NULL) + { + if (testCases[i].result != NULL) + { + Fail("Expected strpbrk() to return %s, got NULL!\n", + testCases[i].result); + } + } + else + { + if (strcmp(ptr,testCases[i].result)!=0 ) + + { + Fail("Expected strpbrk() to return %s, got %s!\n", + testCases[i].result,ptr); + } + + } + + } + + + PAL_Terminate(); + + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/test1/testinfo.dat new file mode 100644 index 0000000..d4fb958 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strpbrk/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = strpbrk +Name = Test #1 for strpbrk +TYPE = DEFAULT +EXE1 = test1 +Description += Search a string for characters in a given character set and ensure the += pointer returned points to the first occurrence. Check to see that the += function returns NULL if the character is not found. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/test1/CMakeLists.txt new file mode 100644 index 0000000..25e8916 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_strrchr_test1 + ${SOURCES} +) + +add_dependencies(paltest_strrchr_test1 coreclrpal) + +target_link_libraries(paltest_strrchr_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/test1/test1.cpp new file mode 100644 index 0000000..a5c147e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/test1/test1.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: \ +** Search a string for a given character. Search for a character contained +** in the string, and ensure the pointer returned points to it. Then search +** for the null character, and ensure the pointer points to that. Finally +** search for a character which is not in the string and ensure that it +** returns NULL. +** +** +**==========================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + char *str = "foo bar baz"; + char *ptr; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + ptr = strrchr(str, 'b'); + if (ptr != str + 8) + { + Fail("Expected strrchr() to return %p, got %p!\n", str + 8, ptr); + } + + ptr = strrchr(str, 0); + if (ptr != str + 11) + { + Fail("Expected strrchr() to return %p, got %p!\n", str + 11, ptr); + } + + ptr = strrchr(str, 'x'); + if (ptr != NULL) + { + Fail("Expected strrchr() to return NULL, got %p!\n", ptr); + } + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/test1/testinfo.dat new file mode 100644 index 0000000..45b27ae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strrchr/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = strrchr +Name = Test #1 for strrchr +TYPE = DEFAULT +EXE1 = test1 +Description += Search a string for a given character. Search for a character contained += in the string, and ensure the pointer returned points to it. Then search += for the null character, and ensure the pointer points to that. Finally += search for a character which is not in the string and ensure that it += returns NULL. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strspn/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strspn/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strspn/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strspn/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strspn/test1/CMakeLists.txt new file mode 100644 index 0000000..e984a6e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strspn/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_strspn_test1 + ${SOURCES} +) + +add_dependencies(paltest_strspn_test1 coreclrpal) + +target_link_libraries(paltest_strspn_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strspn/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strspn/test1/test1.cpp new file mode 100644 index 0000000..78d2488 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strspn/test1/test1.cpp @@ -0,0 +1,60 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Check a character set against a string to see that the function returns +** the length of the substring which consists of all characters in the string. +** Also check that if the character set doesn't match the string at all, that +** the value is 0. +** +** +**==========================================================================*/ + +#include + +struct testCase +{ + long result; + char *string1; + char *string2; +}; + +int __cdecl main(int argc, char *argv[]) +{ + int i=0; + long TheResult = 0; + + struct testCase testCases[]= + { + {4,"abcdefg12345678hijklmnopqrst","a2bjk341cd"}, + {14,"This is a test, testing", "aeioTts rh"}, + {0,"foobar","kpzt"} + }; + + /* + * Initialize the PAL + */ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + for (i=0; i + + +struct testCase +{ + char *result; + char *string1; + char *string2; + +}; + +int __cdecl main(int argc, char *argv[]) +{ + int i=0; + char *ptr=NULL; + + struct testCase testCases[]= + { + {"is is a test", "This is a test","is"}, + {"fghijkl","abcdefghijkl","fgh"}, + {NULL,"aabbccddeeffgg","h"}, + {NULL,"aabb", "eeeeeee"}, + {"AAA", "BBddfdaaaaAAA","A"}, + {"fdaaaaAAA", "BBddfdaaaaAAA","f"}, + {"aadfsadfas","aadfsadfas",""}, + {NULL,"","ccc"} + }; + + /* + * Initialize the PAL + */ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + for (i=0; i + + +struct testCase +{ + double CorrectResult; /* The returned double value */ + char ResultString[20]; /* The remainder string */ + char string[20]; /* The test string */ +}; + + +int __cdecl main(int argc, char **argv) +{ + + char * endptr; + double result; + int i; + + struct testCase testCases[] = + { + {1234,"","1234"}, + {-1234,"","-1234"}, + {1234.44,"","1234.44"}, + {1234e-5,"","1234e-5"}, + {1234e+5,"","1234e+5"}, + {12345E5,"","12345e5"}, + {1234.657e-8,"","1234.657e-8"}, + {1234567e-8,"foo","1234567e-8foo"}, + {999,"foo","999 foo"}, + {7,"foo"," 7foo"}, + {0,"a7","a7"}, + {-777777,"z zz","-777777z zz"} + }; + + /* + * Initialize the PAL + */ + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* Loop through the structure to test each case */ + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + result = strtod(testCases[i].string,&endptr); + + /* need to check the result and the endptr result */ + if ((testCases[i].CorrectResult != result) && + (strcmp(testCases[i].ResultString,endptr)!=0)) + { + Fail("ERROR: strtod returned %f instead of %f and " + "\"%s\" instead of \"%s\" for the test of \"%s\"\n", + result, + testCases[i].CorrectResult, + endptr, + testCases[i].ResultString, + testCases[i].string); + } + + } + + PAL_Terminate(); + return PASS; +} + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test1/testinfo.dat new file mode 100644 index 0000000..2c98d2e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = strtod +Name = Positive Test for strtod +TYPE = DEFAULT +EXE1 = test1 +Description += Purpose: Tests the PAL implementation of the strtod function. += Convert a number of strings to doubles. Ensure they convert correctly. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test2/CMakeLists.txt new file mode 100644 index 0000000..aabfd18 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_strtod_test2 + ${SOURCES} +) + +add_dependencies(paltest_strtod_test2 coreclrpal) + +target_link_libraries(paltest_strtod_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test2/test2.cpp new file mode 100644 index 0000000..0eaf4f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test2/test2.cpp @@ -0,0 +1,65 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Tests strtod with overflows +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + /* Representation of positive infinty for a IEEE 64-bit double */ + INT64 PosInifity = (INT64)(0x7ff00000) << 32; + double HugeVal = *(double*) &PosInifity; + char *PosStr = "1E+10000"; + char *NegStr = "-1E+10000"; + double result; + + + if (PAL_Initialize(argc,argv)) + { + return FAIL; + } + + result = strtod(PosStr, NULL); + + if (result != HugeVal) + { + Fail("ERROR: wcstod interpreted \"%s\" as %g instead of %g\n", + PosStr, result, HugeVal); + } + + result = strtod(NegStr, NULL); + + if (result != -HugeVal) + { + Fail("ERROR: wcstod interpreted \"%s\" as %g instead of %g\n", + NegStr, result, -HugeVal); + } + + PAL_Terminate(); + + return PASS; +} + + + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test2/testinfo.dat new file mode 100644 index 0000000..a50c07b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtod/test2/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = strtod +Name = Negative test for strtod with overflows +TYPE = DEFAULT +EXE1 = test2 +Description += Test strtod with overflows. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/test1/CMakeLists.txt new file mode 100644 index 0000000..322203c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_strtok_test1 + ${SOURCES} +) + +add_dependencies(paltest_strtok_test1 coreclrpal) + +target_link_libraries(paltest_strtok_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/test1/test1.cpp new file mode 100644 index 0000000..f1dec70 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/test1/test1.cpp @@ -0,0 +1,78 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Search for a number of tokens within strings. Check that the return values +** are what is expect, and also that the strings match up with our expected +** results. +** +** +**==========================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + char str[] = "foo bar baz"; + char *result1= "foo \0ar baz"; + char *result2= "foo \0a\0 baz"; + int len = strlen(str) + 1; + char *ptr; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + ptr = strtok(str, "bz"); + if (ptr != str) + { + Fail("Expected strtok() to return %p, got %p!\n", str, ptr); + } + if (memcmp(str, result1, len) != 0) + { + Fail("strtok altered the string in an unexpeced way!\n"); + } + + ptr = strtok(NULL, "r "); + if (ptr != str + 5) + { + Fail("Expected strtok() to return %p, got %p!\n", str+5, ptr); + } + if (memcmp(str, result2, len) != 0) + { + Fail("strtok altered the string in an unexpeced way!\n"); + } + + + ptr = strtok(NULL, "X"); + if (ptr != str + 7) + { + Fail("Expected strtok() to return %p, got %p!\n", str + 7, ptr); + } + if (memcmp(str, result2, len) != 0) + { + Fail("strtok altered the string in an unexpeced way!\n"); + } + + ptr = strtok(NULL, "X"); + if (ptr != NULL) + { + Fail("Expected strtok() to return %p, got %p!\n", NULL, ptr); + } + if (memcmp(str, result2, len) != 0) + { + Fail("strtok altered the string in an unexpeced way!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/test1/testinfo.dat new file mode 100644 index 0000000..f377351 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtok/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = strtok +Name = Test #1 for strtok +TYPE = DEFAULT +EXE1 = test1 +Description += Search for a number of tokens within strings. Check that the return values += are what is expect, and also that the strings match up with our expected += results. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtoul/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtoul/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtoul/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtoul/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtoul/test1/CMakeLists.txt new file mode 100644 index 0000000..4d58d74 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtoul/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_strtoul_test1 + ${SOURCES} +) + +add_dependencies(paltest_strtoul_test1 coreclrpal) + +target_link_libraries(paltest_strtoul_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtoul/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtoul/test1/test1.cpp new file mode 100644 index 0000000..344671b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/strtoul/test1/test1.cpp @@ -0,0 +1,73 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Tests stroul with different bases and overflows, as well as valid input. +** Makes sure that the end pointer is correct. +** +** +**==========================================================================*/ + +#include + +char teststr1[] = "12345"; +char teststr2[] = "Z"; +char teststr3[] = "4294967295"; +char teststr4[] = "4294967296"; + +typedef struct +{ + char *str; + char *end; + int base; + ULONG result; +} TestCase; + +TestCase TestCases[] = +{ + { teststr1, teststr1 + 3, 4, 27}, + { teststr1, teststr1 + 5, 10, 12345}, + { teststr2, teststr2, 10, 0}, + { teststr3, teststr3+10, 10, 4294967295ul}, + { teststr4, teststr4+10, 10, 4294967295ul} +}; + +int NumCases = sizeof(TestCases) / sizeof(TestCases[0]); + + +int __cdecl main(int argc, char *argv[]) +{ + char *end; + ULONG l; + int i; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + for (i=0; i +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR *checkstr; + WCHAR buf[256]; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + checkstr = convert("hello world"); + swprintf_s(buf, _countof(buf), convert("hello world")); + + if (memcmp(checkstr, buf, wcslen(checkstr)*2+2) != 0) + { + Fail("ERROR: Expected \"%s\", got \"%s\".\n", "hello world", + convertC(buf)); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test1/testinfo.dat new file mode 100644 index 0000000..f43d462 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test1 +Description += General test to see if swprintf works correctly diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test10/CMakeLists.txt new file mode 100644 index 0000000..23190da --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_swprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test10 coreclrpal) + +target_link_libraries(paltest_swprintf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test10/test10.cpp new file mode 100644 index 0000000..61aef59 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test10/test10.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test10.c +** +** Purpose:Tests swprintf with octal numbers +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %o"), pos, convert("foo 52")); + DoNumTest(convert("foo %lo"), 0xFFFF, convert("foo 177777")); + DoNumTest(convert("foo %ho"), 0xFFFF, convert("foo 177777")); + DoNumTest(convert("foo %Lo"), pos, convert("foo 52")); + DoI64Test(convert("foo %I64o"), l, "0x0000000000000042", + convert("foo 52")); + DoNumTest(convert("foo %3o"), pos, convert("foo 52")); + DoNumTest(convert("foo %-3o"), pos, convert("foo 52 ")); + DoNumTest(convert("foo %.1o"), pos, convert("foo 52")); + DoNumTest(convert("foo %.3o"), pos, convert("foo 052")); + DoNumTest(convert("foo %03o"), pos, convert("foo 052")); + DoNumTest(convert("foo %#o"), pos, convert("foo 052")); + DoNumTest(convert("foo %+o"), pos, convert("foo 52")); + DoNumTest(convert("foo % o"), pos, convert("foo 52")); + DoNumTest(convert("foo %+o"), neg, convert("foo 37777777726")); + DoNumTest(convert("foo % o"), neg, convert("foo 37777777726")); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test10/testinfo.dat new file mode 100644 index 0000000..e860bb2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test10/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test10 +Description += Tests swprintf with octal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test11/CMakeLists.txt new file mode 100644 index 0000000..f18db33 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_swprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test11 coreclrpal) + +target_link_libraries(paltest_swprintf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test11/test11.cpp new file mode 100644 index 0000000..216f9ac --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test11/test11.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test11.c +** +** Purpose: Tests swprintf with unsigned numbers +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %u"), pos, convert("foo 42")); + DoNumTest(convert("foo %lu"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hu"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %Lu"), pos, convert("foo 42")); + DoI64Test(convert("foo %I64u"), l, "0x0000000000000042", + convert("foo 42")); + DoNumTest(convert("foo %3u"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3u"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1u"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3u"), pos, convert("foo 042")); + DoNumTest(convert("foo %03u"), pos, convert("foo 042")); + DoNumTest(convert("foo %#u"), pos, convert("foo 42")); + DoNumTest(convert("foo %+u"), pos, convert("foo 42")); + DoNumTest(convert("foo % u"), pos, convert("foo 42")); + DoNumTest(convert("foo %+u"), neg, convert("foo 4294967254")); + DoNumTest(convert("foo % u"), neg, convert("foo 4294967254")); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test11/testinfo.dat new file mode 100644 index 0000000..430a777 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test11/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test11 +Description += Tests swprintf with unsigned numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test12/CMakeLists.txt new file mode 100644 index 0000000..23d4177 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_swprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test12 coreclrpal) + +target_link_libraries(paltest_swprintf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test12/test12.cpp new file mode 100644 index 0000000..a41b0dd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test12/test12.cpp @@ -0,0 +1,56 @@ +// 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. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Tests swprintf with hex numbers (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %lx"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %hx"), pos, convert("foo 34ab")); + DoNumTest(convert("foo %Lx"), pos, convert("foo 1234ab")); + DoI64Test(convert("foo %I64x"), l, "0x1234567887654321", + convert("foo 1234567887654321")); + DoNumTest(convert("foo %7x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %-7x"), pos, convert("foo 1234ab ")); + DoNumTest(convert("foo %.1x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %.7x"), pos, convert("foo 01234ab")); + DoNumTest(convert("foo %07x"), pos, convert("foo 01234ab")); + DoNumTest(convert("foo %#x"), pos, convert("foo 0x1234ab")); + DoNumTest(convert("foo %+x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo % x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %+x"), neg, convert("foo ffffffd6")); + DoNumTest(convert("foo % x"), neg, convert("foo ffffffd6")); + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test12/testinfo.dat new file mode 100644 index 0000000..d535826 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test12/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test12 +Description += Tests swprintf with hex numbers (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test13/CMakeLists.txt new file mode 100644 index 0000000..828270f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_swprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test13 coreclrpal) + +target_link_libraries(paltest_swprintf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test13/test13.cpp new file mode 100644 index 0000000..b99232f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test13/test13.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test13.c +** +** Purpose: Tests swprintf with hex numbers (uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %lX"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %hX"), pos, convert("foo 34AB")); + DoNumTest(convert("foo %LX"), pos, convert("foo 1234AB")); + DoI64Test(convert("foo %I64X"), l, "0X1234567887654321", + convert("foo 1234567887654321")); + DoNumTest(convert("foo %7X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %-7X"), pos, convert("foo 1234AB ")); + DoNumTest(convert("foo %.1X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %.7X"), pos, convert("foo 01234AB")); + DoNumTest(convert("foo %07X"), pos, convert("foo 01234AB")); + DoNumTest(convert("foo %#X"), pos, convert("foo 0X1234AB")); + DoNumTest(convert("foo %+X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo % X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %+X"), neg, convert("foo FFFFFFD6")); + DoNumTest(convert("foo % X"), neg, convert("foo FFFFFFD6")); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test13/testinfo.dat new file mode 100644 index 0000000..1ce1724 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test13/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test13 +Description += Tests swprintf with hex numbers (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test14/CMakeLists.txt new file mode 100644 index 0000000..a3caec6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_swprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test14 coreclrpal) + +target_link_libraries(paltest_swprintf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test14/test14.cpp new file mode 100644 index 0000000..bcfd6a7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test14/test14.cpp @@ -0,0 +1,67 @@ +// 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. + +/*============================================================================ +** +** Source: test14.c +** +** Purpose: Tests swprintf with exponential format doubles (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %le"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %he"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %Le"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %I64e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %14e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %-14e"), val, convert("foo 2.560000e+002 "), + convert("foo 2.560000e+02 ")); + DoDoubleTest(convert("foo %.1e"), val, convert("foo 2.6e+002"), + convert("foo 2.6e+02")); + DoDoubleTest(convert("foo %.8e"), val, convert("foo 2.56000000e+002"), + convert("foo 2.56000000e+02")); + DoDoubleTest(convert("foo %014e"), val, convert("foo 02.560000e+002"), + convert("foo 002.560000e+02")); + DoDoubleTest(convert("foo %#e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %+e"), val, convert("foo +2.560000e+002"), + convert("foo +2.560000e+02")); + DoDoubleTest(convert("foo % e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %+e"), neg, convert("foo -2.560000e+002"), + convert("foo -2.560000e+02")); + DoDoubleTest(convert("foo % e"), neg, convert("foo -2.560000e+002"), + convert("foo -2.560000e+02")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test14/testinfo.dat new file mode 100644 index 0000000..7f34518 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test14/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test14 +Description += Tests swprintf with exponential format doubles (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test15/CMakeLists.txt new file mode 100644 index 0000000..62cdc8d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_swprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test15 coreclrpal) + +target_link_libraries(paltest_swprintf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test15/test15.cpp new file mode 100644 index 0000000..215afbe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test15/test15.cpp @@ -0,0 +1,67 @@ +// 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. + +/*============================================================================ +** +** Source: test15.c +** +** Purpose:Tests swprintf with exponential format doubles (uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %lE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %hE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %LE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %I64E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %14E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %-14E"), val, convert("foo 2.560000E+002 "), + convert("foo 2.560000E+02 ")); + DoDoubleTest(convert("foo %.1E"), val, convert("foo 2.6E+002"), + convert("foo 2.6E+02")); + DoDoubleTest(convert("foo %.8E"), val, convert("foo 2.56000000E+002"), + convert("foo 2.56000000E+02")); + DoDoubleTest(convert("foo %014E"), val, convert("foo 02.560000E+002"), + convert("foo 002.560000E+02")); + DoDoubleTest(convert("foo %#E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %+E"), val, convert("foo +2.560000E+002"), + convert("foo +2.560000E+02")); + DoDoubleTest(convert("foo % E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %+E"), neg, convert("foo -2.560000E+002"), + convert("foo -2.560000E+02")); + DoDoubleTest(convert("foo % E"), neg, convert("foo -2.560000E+002"), + convert("foo -2.560000E+02")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test15/testinfo.dat new file mode 100644 index 0000000..a6044e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test15/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test15 +Description += Tests swprintf with exponential format doubles (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test16/CMakeLists.txt new file mode 100644 index 0000000..19773af --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_swprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test16 coreclrpal) + +target_link_libraries(paltest_swprintf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test16/test16.cpp new file mode 100644 index 0000000..859afed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test16/test16.cpp @@ -0,0 +1,67 @@ +// 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. + +/*============================================================================ +** +** Source: test16.c +** +** Purpose:Tests swprintf with decimal point format doubles +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %lf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %hf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %Lf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %I64f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %12f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %-12f"), val, convert("foo 2560.001000 "), + convert("foo 2560.001000 ")); + DoDoubleTest(convert("foo %.1f"), val, convert("foo 2560.0"), + convert("foo 2560.0")); + DoDoubleTest(convert("foo %.8f"), val, convert("foo 2560.00100000"), + convert("foo 2560.00100000")); + DoDoubleTest(convert("foo %012f"), val, convert("foo 02560.001000"), + convert("foo 02560.001000")); + DoDoubleTest(convert("foo %#f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %+f"), val, convert("foo +2560.001000"), + convert("foo +2560.001000")); + DoDoubleTest(convert("foo % f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %+f"), neg, convert("foo -2560.001000"), + convert("foo -2560.001000")); + DoDoubleTest(convert("foo % f"), neg, convert("foo -2560.001000"), + convert("foo -2560.001000")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test16/testinfo.dat new file mode 100644 index 0000000..d2f9a12 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test16/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test16 +Description += Tests swprintf with decimal point format doubles diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test17/CMakeLists.txt new file mode 100644 index 0000000..745cebc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_swprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test17 coreclrpal) + +target_link_libraries(paltest_swprintf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test17/test17.cpp new file mode 100644 index 0000000..480f2b2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test17/test17.cpp @@ -0,0 +1,69 @@ +// 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. + +/*============================================================================ +** +** Source: test17.c +** +** Purpose:Tests swprintf with compact format doubles (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %lg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %hg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %Lg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %I64g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %5g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %-5g"), val, convert("foo 2560 "), + convert("foo 2560 ")); + DoDoubleTest(convert("foo %.1g"), val, convert("foo 3e+003"), + convert("foo 3e+03")); + DoDoubleTest(convert("foo %.2g"), val, convert("foo 2.6e+003"), + convert("foo 2.6e+03")); + DoDoubleTest(convert("foo %.12g"), val, convert("foo 2560.001"), + convert("foo 2560.001")); + DoDoubleTest(convert("foo %06g"), val, convert("foo 002560"), + convert("foo 002560")); + DoDoubleTest(convert("foo %#g"), val, convert("foo 2560.00"), + convert("foo 2560.00")); + DoDoubleTest(convert("foo %+g"), val, convert("foo +2560"), + convert("foo +2560")); + DoDoubleTest(convert("foo % g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %+g"), neg, convert("foo -2560"), + convert("foo -2560")); + DoDoubleTest(convert("foo % g"), neg, convert("foo -2560"), + convert("foo -2560")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test17/testinfo.dat new file mode 100644 index 0000000..f26029c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test17/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test17 +Description += Tests swprintf with compact format doubles (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test18/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test18/CMakeLists.txt new file mode 100644 index 0000000..d225743 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test18/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test18.cpp +) + +add_executable(paltest_swprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test18 coreclrpal) + +target_link_libraries(paltest_swprintf_test18 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test18/test18.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test18/test18.cpp new file mode 100644 index 0000000..1ed8cd0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test18/test18.cpp @@ -0,0 +1,69 @@ +// 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. + +/*============================================================================ +** +** Source: test18.c +** +** Purpose: Tests swprintf with compact format doubles (uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %lG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %hG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %LG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %I64G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %5G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %-5G"), val, convert("foo 2560 "), + convert("foo 2560 ")); + DoDoubleTest(convert("foo %.1G"), val, convert("foo 3E+003"), + convert("foo 3E+03")); + DoDoubleTest(convert("foo %.2G"), val, convert("foo 2.6E+003"), + convert("foo 2.6E+03")); + DoDoubleTest(convert("foo %.12G"), val, convert("foo 2560.001"), + convert("foo 2560.001")); + DoDoubleTest(convert("foo %06G"), val, convert("foo 002560"), + convert("foo 002560")); + DoDoubleTest(convert("foo %#G"), val, convert("foo 2560.00"), + convert("foo 2560.00")); + DoDoubleTest(convert("foo %+G"), val, convert("foo +2560"), + convert("foo +2560")); + DoDoubleTest(convert("foo % G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %+G"), neg, convert("foo -2560"), + convert("foo -2560")); + DoDoubleTest(convert("foo % G"), neg, convert("foo -2560"), + convert("foo -2560")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test18/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test18/testinfo.dat new file mode 100644 index 0000000..6a8ca70 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test18/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test18 +Description += Tests swprintf with compact format doubles (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test19/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test19/CMakeLists.txt new file mode 100644 index 0000000..0e125d7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test19/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test19.cpp +) + +add_executable(paltest_swprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test19 coreclrpal) + +target_link_libraries(paltest_swprintf_test19 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.cpp new file mode 100644 index 0000000..0967bc8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.cpp @@ -0,0 +1,101 @@ +// 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. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose: Tests swprintf with argument specified precision +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoArgumentPrecTest(convert("%.*s"), 2, (void*)convert("bar"), "bar", + convert("ba"), convert("ba")); + DoArgumentPrecTest(convert("%.*S"), 2, (void*)"bar", "bar", convert("ba"), + convert("ba")); + DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', "a", convert("a"), + convert("a")); + DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', "a", convert("a"), + convert("a")); + DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', "a", convert("a"), + convert("a")); + DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', "a", convert("a"), + convert("a")); + DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, "42", convert("42"), + convert("42")); + DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, "42", convert("042"), + convert("042")); + DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, "42", convert("42"), + convert("42")); + DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, "42", convert("042"), + convert("042")); + DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, "42", convert("52"), + convert("52")); + DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, "42", convert("052"), + convert("052")); + DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, "42", convert("42"), + convert("42")); + DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, "42", convert("042"), + convert("042")); + DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, "0x42", convert("42"), + convert("42")); + DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, "0x42", convert("042"), + convert("042")); + DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, "0x42", convert("42"), + convert("42")); + DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, "0x42", convert("042"), + convert("042")); + + + DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000"), + convert("2.0e+000")); + DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000"), + convert("2.010e+000")); + DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000"), + convert("2.0E+000")); + DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000"), + convert("2.010E+000")); + DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0"), + convert("2.0")); + DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010"), + convert("2.010")); + DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002"), + convert("3e+002")); + DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01"), + convert("256.01")); + DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002"), + convert("3E+002")); + DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01"), + convert("256.01")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test19/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test19/testinfo.dat new file mode 100644 index 0000000..cbd572a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test19/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test19 +Description += Tests swprintf with argument specified precision diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test2/CMakeLists.txt new file mode 100644 index 0000000..cd04e49 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_swprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test2 coreclrpal) + +target_link_libraries(paltest_swprintf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test2/test2.cpp new file mode 100644 index 0000000..1c2f420 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test2/test2.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Tests swprintf with strings +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoWStrTest(convert("foo %s"), convert("bar"), convert("foo bar")); + DoStrTest(convert("foo %hs"), "bar", convert("foo bar")); + DoWStrTest(convert("foo %ws"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %ls"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %Ls"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %I64s"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %5s"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %.2s"), convert("bar"), convert("foo ba")); + DoWStrTest(convert("foo %5.2s"), convert("bar"), convert("foo ba")); + DoWStrTest(convert("foo %-5s"), convert("bar"), convert("foo bar ")); + DoWStrTest(convert("foo %05s"), convert("bar"), convert("foo 00bar")); + DoWStrTest(convert("foo %s"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %hs"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %ls"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %ws"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %Ls"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %I64s"), NULL, convert("foo (null)")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test2/testinfo.dat new file mode 100644 index 0000000..d93fa7b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test2 +Description += Tests swprintf with strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test3/CMakeLists.txt new file mode 100644 index 0000000..47ee916 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_swprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test3 coreclrpal) + +target_link_libraries(paltest_swprintf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test3/test3.cpp new file mode 100644 index 0000000..8c6c38c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test3/test3.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Tests swprintf with wide strings +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoStrTest(convert("foo %S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %hS"), "bar", convert("foo bar")); + DoWStrTest(convert("foo %lS"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %wS"), convert("bar"), convert("foo bar")); + DoStrTest(convert("foo %LS"), "bar", convert("foo bar")); + DoStrTest(convert("foo %I64S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %5S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %.2S"), "bar", convert("foo ba")); + DoStrTest(convert("foo %5.2S"),"bar", convert("foo ba")); + DoStrTest(convert("foo %-5S"), "bar", convert("foo bar ")); + DoStrTest(convert("foo %05S"), "bar", convert("foo 00bar")); + DoStrTest(convert("foo %S"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %hS"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %lS"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %wS"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %LS"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %I64S"), NULL, convert("foo (null)")); + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test3/testinfo.dat new file mode 100644 index 0000000..923a8f0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test3 +Description += Tests swprintf with wide strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test4/CMakeLists.txt new file mode 100644 index 0000000..d33c2d2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_swprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test4 coreclrpal) + +target_link_libraries(paltest_swprintf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test4/test4.cpp new file mode 100644 index 0000000..04bfca3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test4/test4.cpp @@ -0,0 +1,71 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Tests swprintf with pointers +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest(convert("%p"), NULL, convert("0000000000000000")); + DoPointerTest(convert("%p"), ptr, convert("0000000000123456")); + DoPointerTest(convert("%17p"), ptr, convert(" 0000000000123456")); + DoPointerTest(convert("%17p"), ptr, convert(" 0000000000123456")); + DoPointerTest(convert("%-17p"), ptr, convert("0000000000123456 ")); + DoPointerTest(convert("%+p"), ptr, convert("0000000000123456")); + DoPointerTest(convert("% p"), ptr, convert("0000000000123456")); + DoPointerTest(convert("%#p"), ptr, convert("0X0000000000123456")); + DoPointerTest(convert("%lp"), ptr, convert("00123456")); + DoPointerTest(convert("%hp"), ptr, convert("00003456")); + DoPointerTest(convert("%Lp"), ptr, convert("00123456")); + DoI64Test(convert("%I64p"), lptr, "pointer to 0X1234567887654321", + convert("1234567887654321")); +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest(convert("%p"), NULL, convert("00000000")); + DoPointerTest(convert("%p"), ptr, convert("00123456")); + DoPointerTest(convert("%9p"), ptr, convert(" 00123456")); + DoPointerTest(convert("%09p"), ptr, convert(" 00123456")); + DoPointerTest(convert("%-9p"), ptr, convert("00123456 ")); + DoPointerTest(convert("%+p"), ptr, convert("00123456")); + DoPointerTest(convert("% p"), ptr, convert("00123456")); + DoPointerTest(convert("%#p"), ptr, convert("0X00123456")); + DoPointerTest(convert("%lp"), ptr, convert("00123456")); + DoPointerTest(convert("%hp"), ptr, convert("00003456")); + DoPointerTest(convert("%Lp"), ptr, convert("00123456")); + DoI64Test(convert("%I64p"), lptr, "pointer to 0X1234567887654321", + convert("1234567887654321")); +#endif + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test4/testinfo.dat new file mode 100644 index 0000000..dc481d3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test4/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test4 +Description += Tests swprintf with pointers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test6/CMakeLists.txt new file mode 100644 index 0000000..2ff88fc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_swprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test6 coreclrpal) + +target_link_libraries(paltest_swprintf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test6/test6.cpp new file mode 100644 index 0000000..ecd6374 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test6/test6.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose: Tests swprintf with character +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wb = (WCHAR) 'b'; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoWCharTest(convert("foo %c"), wb, convert("foo b")); + DoCharTest(convert("foo %hc"), 'c', convert("foo c")); + DoWCharTest(convert("foo %lc"), wb, convert("foo b")); + DoWCharTest(convert("foo %Lc"), wb, convert("foo b")); + DoWCharTest(convert("foo %I64c"), wb, convert("foo b")); + DoWCharTest(convert("foo %5c"), wb, convert("foo b")); + DoWCharTest(convert("foo %.0c"), wb, convert("foo b")); + DoWCharTest(convert("foo %-5c"), wb, convert("foo b ")); + DoWCharTest(convert("foo %05c"), wb, convert("foo 0000b")); + DoWCharTest(convert("foo % c"), wb, convert("foo b")); + DoWCharTest(convert("foo %#c"), wb, convert("foo b")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test6/testinfo.dat new file mode 100644 index 0000000..4224d19 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test6/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test6 +Description += Tests swprintf with characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test7/CMakeLists.txt new file mode 100644 index 0000000..2845484 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_swprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test7 coreclrpal) + +target_link_libraries(paltest_swprintf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test7/test7.cpp new file mode 100644 index 0000000..e231ada --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test7/test7.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================================ +** +** Source: test7.c +** +** Purpose: Tests swprintf with wide characters +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wb = (WCHAR) 'b'; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoCharTest(convert("foo %C"), 'c', convert("foo c")); + DoWCharTest(convert("foo %hc"), wb, convert("foo b")); + DoCharTest(convert("foo %lC"), 'c', convert("foo c")); + DoCharTest(convert("foo %LC"), 'c', convert("foo c")); + DoCharTest(convert("foo %I64C"), 'c', convert("foo c")); + DoCharTest(convert("foo %5C"), 'c', convert("foo c")); + DoCharTest(convert("foo %.0C"), 'c', convert("foo c")); + DoCharTest(convert("foo %-5C"), 'c', convert("foo c ")); + DoCharTest(convert("foo %05C"), 'c', convert("foo 0000c")); + DoCharTest(convert("foo % C"), 'c', convert("foo c")); + DoCharTest(convert("foo %#C"), 'c', convert("foo c")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test7/testinfo.dat new file mode 100644 index 0000000..7facc90 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test7/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test7 +Description += Tests swprintf with wide characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test8/CMakeLists.txt new file mode 100644 index 0000000..72c922c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_swprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test8 coreclrpal) + +target_link_libraries(paltest_swprintf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test8/test8.cpp new file mode 100644 index 0000000..b4be28e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test8/test8.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test8.c +** +** Purpose: Tests swprintf with decimal numbers +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %d"), pos, convert("foo 42")); + DoNumTest(convert("foo %ld"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hd"), 0xFFFF, convert("foo -1")); + DoNumTest(convert("foo %Ld"), pos, convert("foo 42")); + DoI64Test(convert("foo %I64d"), l, "0x0000000000000042", + convert("foo 42")); + DoNumTest(convert("foo %3d"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3d"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1d"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3d"), pos, convert("foo 042")); + DoNumTest(convert("foo %03d"), pos, convert("foo 042")); + DoNumTest(convert("foo %#d"), pos, convert("foo 42")); + DoNumTest(convert("foo %+d"), pos, convert("foo +42")); + DoNumTest(convert("foo % d"), pos, convert("foo 42")); + DoNumTest(convert("foo %+d"), neg, convert("foo -42")); + DoNumTest(convert("foo % d"), neg, convert("foo -42")); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test8/testinfo.dat new file mode 100644 index 0000000..d5858b2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test8/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test8 +Description += Tests swprintf with decimal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test9/CMakeLists.txt new file mode 100644 index 0000000..7236065 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_swprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_swprintf_test9 coreclrpal) + +target_link_libraries(paltest_swprintf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test9/test9.cpp new file mode 100644 index 0000000..2f5429e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test9/test9.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test9.c +** +** Purpose: Tests swprintf with integer numbers +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %i"), pos, convert("foo 42")); + DoNumTest(convert("foo %li"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hi"), 0xFFFF, convert("foo -1")); + DoNumTest(convert("foo %Li"), pos, convert("foo 42")); + DoI64Test(convert("foo %I64i"), l, "0x0000000000000042", + convert("foo 42")); + DoNumTest(convert("foo %3i"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3i"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1i"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3i"), pos, convert("foo 042")); + DoNumTest(convert("foo %03i"), pos, convert("foo 042")); + DoNumTest(convert("foo %#i"), pos, convert("foo 42")); + DoNumTest(convert("foo %+i"), pos, convert("foo +42")); + DoNumTest(convert("foo % i"), pos, convert("foo 42")); + DoNumTest(convert("foo %+i"), neg, convert("foo -42")); + DoNumTest(convert("foo % i"), neg, convert("foo -42")); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test9/testinfo.dat new file mode 100644 index 0000000..7ef9eed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swprintf/test9/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swprintf +Name = Positive Test for swprintf +TYPE = DEFAULT +EXE1 = test9 +Description += Tests swprintf with integer numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/CMakeLists.txt new file mode 100644 index 0000000..56b4848 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/CMakeLists.txt @@ -0,0 +1,18 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/swscanf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/swscanf.h new file mode 100644 index 0000000..6349b7d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/swscanf.h @@ -0,0 +1,262 @@ +// 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. + +/*============================================================================ +** +** Source: swscanf.h +** +** Purpose: Contains common testing functions for swscanf.h +** +** +**==========================================================================*/ + +#ifndef __SWSCANF_H__ +#define __SWSCANF_H__ + +void DoVoidTest(WCHAR *inputstr, const WCHAR *formatstr) +{ + char buf[256] = { 0 }; + int i; + int ret; + + ret = swscanf(inputstr, formatstr, buf); + if (ret != 0) + { + Fail("ERROR: Expected sscanf to return 0, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr), + convertC(formatstr)); + } + + for (i=0; i<256; i++) + { + if (buf[i] != 0) + { + Fail("ERROR: Parameter unexpectedly modified scanning \"%s\" " + "using \"%s\".\n", convertC(inputstr), + convertC(formatstr)); + } + } + +} + +void DoStrTest(WCHAR *inputstr, const WCHAR *formatstr, const char *checkstr) +{ + char buf[256] = { 0 }; + int ret; + + ret = swscanf(inputstr, formatstr, buf); + if (ret != 1) + { + Fail("ERROR: Expected swscanf to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr), + convertC(formatstr)); + } + + if (memcmp(checkstr, buf, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: scanned string incorrectly from \"%s\" using \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", convertC(inputstr), + convertC(formatstr), checkstr, + buf); + } + +} + +void DoWStrTest(WCHAR *inputstr, const WCHAR *formatstr, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + int ret; + + ret = swscanf(inputstr, formatstr, buf); + if (ret != 1) + { + Fail("ERROR: Expected swscanf to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr), + convertC(formatstr)); + } + + if (memcmp(checkstr, buf, wcslen(checkstr)*2 + 2) != 0) + { + Fail("ERROR: scanned wide string incorrectly from \"%s\" using \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", convertC(inputstr), + convertC(formatstr), convertC(checkstr), + convertC(buf)); + } + +} + +void DoNumTest(WCHAR *inputstr, const WCHAR *formatstr, int checknum) +{ + int num = 0; + int ret; + + ret = swscanf(inputstr, formatstr, &num); + if (ret != 1) + { + Fail("ERROR: Expected swscanf to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr), + convertC(formatstr)); + } + + if (checknum != num) + { + Fail("ERROR: scanned number incorrectly from \"%s\" using \"%s\".\n" + "Expected %d, got %d.\n", convertC(inputstr), + convertC(formatstr), checknum, num); + } +} + +void DoShortNumTest(WCHAR *inputstr, const WCHAR *formatstr, short checknum) +{ + short num = 0; + int ret; + + ret = swscanf(inputstr, formatstr, &num); + if (ret != 1) + { + Fail("ERROR: Expected swscanf to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr), + convertC(formatstr)); + } + + if (checknum != num) + { + Fail("ERROR: scanned number incorrectly from \"%s\" using \"%s\".\n" + "Expected %hd, got %hd.\n", convertC(inputstr), + convertC(formatstr), checknum, num); + } +} + +void DoI64NumTest(WCHAR *inputstr, const WCHAR *formatstr, INT64 checknum) +{ + char buf[256]; + char check[256]; + INT64 num; + int ret; + + ret = swscanf(inputstr, formatstr, &num); + if (ret != 1) + { + Fail("ERROR: Expected swscanf to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr), + convertC(formatstr)); + } + + if (checknum != num) + { + sprintf_s(buf, _countof(buf), "%I64d", num); + sprintf_s(check, _countof(check), "%I64d", checknum); + Fail("ERROR: scanned I64 number incorrectly from \"%s\" using \"%s\".\n" + "Expected %s, got %s.\n", convertC(inputstr), + convertC(formatstr), check, buf); + } +} + +void DoCharTest(WCHAR *inputstr, const WCHAR *formatstr, char* checkchars, int numchars) +{ + char buf[256]; + int ret; + int i; + + for (i=0; i<256; i++) + buf[i] = (char)-1; + + ret = swscanf(inputstr, formatstr, buf); + if (ret != 1) + { + Fail("ERROR: Expected swscanf to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr), + convertC(formatstr)); + } + + if (memcmp(buf, checkchars, numchars) != 0) + { + buf[numchars] = 0; + + Fail("ERROR: scanned character(s) incorrectly from \"%s\" using \"%s\".\n" + "Expected %s, got %s.\n", convertC(inputstr), + convertC(formatstr), checkchars, buf); + } + + if (buf[numchars] != (char)-1) + { + Fail("ERROR: overflow occurred in scanning character(s) from \"%s\" " + "using \"%s\".\nExpected %d character(s)\n", + convertC(inputstr), convertC(formatstr), numchars); + } +} + +void DoWCharTest(WCHAR *inputstr, const WCHAR *formatstr, const WCHAR *checkchars, int numchars) +{ + WCHAR buf[256]; + int ret; + int i; + + for (i=0; i<256; i++) + buf[i] = (WCHAR)-1; + + ret = swscanf(inputstr, formatstr, buf); + if (ret != 1) + { + Fail("ERROR: Expected swscanf to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr), + convertC(formatstr)); + } + + if (memcmp(buf, checkchars, numchars*2) != 0) + { + buf[numchars] = 0; + + Fail("ERROR: scanned wide character(s) incorrectly from \"%s\" using \"%s\".\n" + "Expected %s, got %s.\n", convertC(inputstr), + convertC(formatstr), convertC(checkchars), + convertC(buf)); + } + + if (buf[numchars] != (WCHAR)-1) + { + Fail("ERROR: overflow occurred in scanning wide character(s) from \"%s\" " + "using \"%s\".\nExpected %d character(s)\n", + convertC(inputstr), convertC(formatstr), numchars); + } +} + + +void DoFloatTest(WCHAR *inputstr, const WCHAR *formatstr, float checkval) +{ + char buf[256] = { 0 }; + float val; + int ret; + int i; + + for (i=0; i<256; i++) + buf[i] = (char)-1; + + ret = swscanf(inputstr, formatstr, buf); + val = *(float*)buf; + + if (ret != 1) + { + Fail("ERROR: Expected swscanf to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr), + convertC(formatstr)); + } + + if (val != checkval) + { + Fail("ERROR: scanned float incorrectly from \"%s\" using \"%s\".\n" + "Expected \"%f\", got \"%f\".\n", convertC(inputstr), + convertC(formatstr), checkval, val); + } + + if (buf[4] != (char)-1) + { + Fail("ERROR: overflow occurred in scanning float from \"%s\" " + "using \"%s\".\n", convertC(inputstr), convertC(formatstr)); + + } +} + + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test1/CMakeLists.txt new file mode 100644 index 0000000..ce24b1e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_swscanf_test1 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test1 coreclrpal) + +target_link_libraries(paltest_swscanf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test1/test1.cpp new file mode 100644 index 0000000..66136e5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test1/test1.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: General test of swscanf +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int num; + int ret; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoVoidTest(convert("foo bar"), convert("foo")); + DoVoidTest(convert("foo bar"), convert("baz")); + DoVoidTest(convert("foo bar"), convert("foo %*s")); + + DoStrTest(convert("foo % bar"), convert("foo %% %S"), "bar"); + DoStrTest(convert("foo bar baz"), convert("foo %bar %S"), "baz"); + + DoVoidTest(convert("foo bar baz"), convert("foo % bar %S")); + DoVoidTest(convert("foo bar baz"), convert("foo% bar %S")); + + + ret = swscanf(convert("foo bar baz"), convert("foo bar %n"), &num); + if (ret != 0 || num != 8) + { + Fail("ERROR: Got incorrect values in scanning \"%s\" using \"%s\".\n" + "Expected to get a value of %d with return value of %d, " + "got %d with return %d\n", "foo bar baz", "foo bar %n", 8, 0, + num, ret); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test1/testinfo.dat new file mode 100644 index 0000000..b6366a7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test1 +Description += General test of swscanf diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test10/CMakeLists.txt new file mode 100644 index 0000000..f250da5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_swscanf_test10 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test10 coreclrpal) + +target_link_libraries(paltest_swscanf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test10/test10.cpp new file mode 100644 index 0000000..a8628e0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test10/test10.cpp @@ -0,0 +1,36 @@ +// 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. + +/*============================================================================ +** +** Source: test10.c +** +** Purpose:Tests swscanf with wide characters +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoCharTest(convert("1234"), convert("%C"), "1", 1); + DoCharTest(convert("abc"), convert("%2C"), "ab", 2); + DoCharTest(convert(" ab"), convert("%C"), " ", 1); + DoCharTest(convert("ab"), convert("%hC"), "a", 1); + DoWCharTest(convert("ab"), convert("%lC"), convert("a"), 1); + DoCharTest(convert("ab"), convert("%LC"), "a", 1); + DoCharTest(convert("ab"), convert("%I64C"), "a", 1); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test10/testinfo.dat new file mode 100644 index 0000000..2f8890d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test10/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test10 +Description += Tests swscanf with wide characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test11/CMakeLists.txt new file mode 100644 index 0000000..c5fed9e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_swscanf_test11 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test11 coreclrpal) + +target_link_libraries(paltest_swscanf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test11/test11.cpp new file mode 100644 index 0000000..f7eb4af --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test11/test11.cpp @@ -0,0 +1,35 @@ +// 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. + +/*============================================================================ +** +** Source: test11.c +** +** Purpose: Tests swscanf with strings +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoWStrTest(convert("foo bar"), convert("foo %s"), convert("bar")); + DoWStrTest(convert("foo bar"), convert("foo %2s"), convert("ba")); + DoStrTest(convert("foo bar"), convert("foo %hs"), "bar"); + DoWStrTest(convert("foo bar"), convert("foo %ls"), convert("bar")); + DoWStrTest(convert("foo bar"), convert("foo %Ls"), convert("bar")); + DoWStrTest(convert("foo bar"), convert("foo %I64s"), convert("bar")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test11/testinfo.dat new file mode 100644 index 0000000..5bbc2e4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test11/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test11 +Description += Tests swscanf with strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test12/CMakeLists.txt new file mode 100644 index 0000000..33e2949 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_swscanf_test12 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test12 coreclrpal) + +target_link_libraries(paltest_swscanf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test12/test12.cpp new file mode 100644 index 0000000..f5f8bbd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test12/test12.cpp @@ -0,0 +1,35 @@ +// 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. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Tests swscanf with wide strings +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoStrTest(convert("foo bar"), convert("foo %S"), "bar"); + DoStrTest(convert("foo bar"), convert("foo %2S"), "ba"); + DoStrTest(convert("foo bar"), convert("foo %hS"), "bar"); + DoWStrTest(convert("foo bar"), convert("foo %lS"), convert("bar")); + DoStrTest(convert("foo bar"), convert("foo %LS"), "bar"); + DoStrTest(convert("foo bar"), convert("foo %I64S"), "bar"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test12/testinfo.dat new file mode 100644 index 0000000..06bf26a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test12/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test12 +Description += Tests swscanf with wide strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test13/CMakeLists.txt new file mode 100644 index 0000000..5dc8b64 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_swscanf_test13 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test13 coreclrpal) + +target_link_libraries(paltest_swscanf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test13/test13.cpp new file mode 100644 index 0000000..1bb0b7b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test13/test13.cpp @@ -0,0 +1,37 @@ +// 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. + +/*============================================================================ +** +** Source: test13.c +** +** Purpose: Tests swscanf with floats (decimal notation) +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest(convert("123.0"), convert("%f"), 123.0f); + DoFloatTest(convert("123.0"), convert("%2f"), 12.0f); + DoFloatTest(convert("10E1"), convert("%f"), 100.0f); + DoFloatTest(convert("-12.01e-2"), convert("%f"), -0.1201f); + DoFloatTest(convert("+12.01e-2"), convert("%f"), 0.1201f); + DoFloatTest(convert("-12.01e+2"), convert("%f"), -1201.0f); + DoFloatTest(convert("+12.01e+2"), convert("%f"), 1201.0f); + DoFloatTest(convert("1234567890.0123456789f"), convert("%f"), 1234567936); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test13/testinfo.dat new file mode 100644 index 0000000..a3c01c5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test13/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test13 +Description += Tests swscanf with floats (decimal notation) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test14/CMakeLists.txt new file mode 100644 index 0000000..ca37751 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_swscanf_test14 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test14 coreclrpal) + +target_link_libraries(paltest_swscanf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test14/test14.cpp new file mode 100644 index 0000000..80581b7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test14/test14.cpp @@ -0,0 +1,38 @@ +// 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. + +/*============================================================================ +** +** Source: test14.c +** +** Purpose: Tests swscanf with floats (exponential notation, lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest(convert("123.0"), convert("%e"), 123.0f); + DoFloatTest(convert("123.0"), convert("%2e"), 12.0f); + DoFloatTest(convert("10E1"), convert("%e"), 100.0f); + DoFloatTest(convert("-12.01e-2"), convert("%e"), -0.1201f); + DoFloatTest(convert("+12.01e-2"), convert("%e"), 0.1201f); + DoFloatTest(convert("-12.01e+2"), convert("%e"), -1201.0f); + DoFloatTest(convert("+12.01e+2"), convert("%e"), 1201.0f); + DoFloatTest(convert("1234567890.0123456789f"), convert("%e"), 1234567936); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test14/testinfo.dat new file mode 100644 index 0000000..184a3e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test14/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test14 +Description += Tests swscanf with floats (exponential notation, lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test15/CMakeLists.txt new file mode 100644 index 0000000..4b56b9a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_swscanf_test15 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test15 coreclrpal) + +target_link_libraries(paltest_swscanf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test15/test15.cpp new file mode 100644 index 0000000..9b7d277 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test15/test15.cpp @@ -0,0 +1,37 @@ +// 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. + +/*============================================================================ +** +** Source: test15.c +** +** Purpose: Tests swscanf with floats (exponential notation, uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest(convert("123.0"), convert("%E"), 123.0f); + DoFloatTest(convert("123.0"), convert("%2E"), 12.0f); + DoFloatTest(convert("10E1"), convert("%E"), 100.0f); + DoFloatTest(convert("-12.01e-2"), convert("%E"), -0.1201f); + DoFloatTest(convert("+12.01e-2"), convert("%E"), 0.1201f); + DoFloatTest(convert("-12.01e+2"), convert("%E"), -1201.0f); + DoFloatTest(convert("+12.01e+2"), convert("%E"), 1201.0f); + DoFloatTest(convert("1234567890.0123456789f"), convert("%E"), 1234567936); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test15/testinfo.dat new file mode 100644 index 0000000..ab20463 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test15/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test15 +Description += Tests swscanf with floats (exponential notation, uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test16/CMakeLists.txt new file mode 100644 index 0000000..6004b38 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_swscanf_test16 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test16 coreclrpal) + +target_link_libraries(paltest_swscanf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test16/test16.cpp new file mode 100644 index 0000000..c83b644 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test16/test16.cpp @@ -0,0 +1,37 @@ +// 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. + +/*============================================================================ +** +** Source: test16.c +** +** Purpose: Tests swscanf with floats (compact notation, lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest(convert("123.0"), convert("%g"), 123.0f); + DoFloatTest(convert("123.0"), convert("%2g"), 12.0f); + DoFloatTest(convert("10E1"), convert("%g"), 100.0f); + DoFloatTest(convert("-12.01e-2"), convert("%g"), -0.1201f); + DoFloatTest(convert("+12.01e-2"), convert("%g"), 0.1201f); + DoFloatTest(convert("-12.01e+2"), convert("%g"), -1201.0f); + DoFloatTest(convert("+12.01e+2"), convert("%g"), 1201.0f); + DoFloatTest(convert("1234567890.0123456789f"), convert("%g"), 1234567936); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test16/testinfo.dat new file mode 100644 index 0000000..0cfa37d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test16/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test16 +Description += Tests swscanf with floats (compact notation, lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test17/CMakeLists.txt new file mode 100644 index 0000000..70226c2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_swscanf_test17 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test17 coreclrpal) + +target_link_libraries(paltest_swscanf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test17/test17.cpp new file mode 100644 index 0000000..9023f70 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test17/test17.cpp @@ -0,0 +1,37 @@ +// 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. + +/*============================================================================ +** +** Source: test17.c +** +** Purpose: Tests swscanf with floats (compact notation, uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest(convert("123.0"), convert("%G"), 123.0f); + DoFloatTest(convert("123.0"), convert("%2G"), 12.0f); + DoFloatTest(convert("10E1"), convert("%G"), 100.0f); + DoFloatTest(convert("-12.01e-2"), convert("%G"), -0.1201f); + DoFloatTest(convert("+12.01e-2"), convert("%G"), 0.1201f); + DoFloatTest(convert("-12.01e+2"), convert("%G"), -1201.0f); + DoFloatTest(convert("+12.01e+2"), convert("%G"), 1201.0f); + DoFloatTest(convert("1234567890.0123456789f"), convert("%G"), 1234567936); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test17/testinfo.dat new file mode 100644 index 0000000..f0489df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test17/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test17 +Description += Tests swscanf with floats (compact notation, uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test2/CMakeLists.txt new file mode 100644 index 0000000..42c2d6c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_swscanf_test2 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test2 coreclrpal) + +target_link_libraries(paltest_swscanf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test2/test2.cpp new file mode 100644 index 0000000..8fbd3f8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test2/test2.cpp @@ -0,0 +1,43 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Test to see if swscanf handles whitespace correctly +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + +/* + * Tests out how it handles whitespace. Seems to accept anything that qualifies + * as isspace (space, tab, vertical tab, line feed, carriage return and form + * feed), even if it says it only wants spaces tabs and newlines. + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoStrTest(convert("foo bar"), convert("foo %S"), "bar"); + DoStrTest(convert("foo\tbar"), convert("foo %S"), "bar"); + DoStrTest(convert("foo\nbar"), convert("foo %S"), "bar"); + DoStrTest(convert("foo\rbar"), convert("foo %S"), "bar"); + DoStrTest(convert("foo\vbar"), convert("foo %S"), "bar"); + DoStrTest(convert("foo\fbar"), convert("foo %S"), "bar"); + DoStrTest(convert("foo \t\n\r\v\fbar"), convert("foo %S"), "bar"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test2/testinfo.dat new file mode 100644 index 0000000..88768ca --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test2 +Description += Test to see if swscanf handles whitespace correctly diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test3/CMakeLists.txt new file mode 100644 index 0000000..3777c35 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_swscanf_test3 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test3 coreclrpal) + +target_link_libraries(paltest_swscanf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test3/test3.cpp new file mode 100644 index 0000000..8b05df2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test3/test3.cpp @@ -0,0 +1,36 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Tests swscanf with bracketed set strings +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoWStrTest(convert("bar1"), convert("%[a-z]"), convert("bar")); + DoWStrTest(convert("bar1"), convert("%[z-a]"), convert("bar")); + DoWStrTest(convert("bar1"), convert("%[ab]"), convert("ba")); + DoWStrTest(convert("bar1"), convert("%[ar1b]"), convert("bar1")); + DoWStrTest(convert("bar1"), convert("%[^4]"), convert("bar1")); + DoWStrTest(convert("bar1"), convert("%[^4a]"), convert("b")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test3/testinfo.dat new file mode 100644 index 0000000..998cba8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test3 +Description += Tests swscanf with bracketed set strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test4/CMakeLists.txt new file mode 100644 index 0000000..e17b9be --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_swscanf_test4 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test4 coreclrpal) + +target_link_libraries(paltest_swscanf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test4/test4.cpp new file mode 100644 index 0000000..d63d25b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test4/test4.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose:Tests swscanf with decimal numbers +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest(convert("1234d"), convert("%d"), 1234); + DoNumTest(convert("1234d"), convert("%2d"), 12); + DoNumTest(convert("-1"), convert("%d"), -1); + DoNumTest(convert("0x1234"), convert("%d"), 0); + DoNumTest(convert("012"), convert("%d"), 12); + DoShortNumTest(convert("-1"), convert("%hd"), n65535); + DoShortNumTest(convert("65536"), convert("%hd"), 0); + DoNumTest(convert("-1"), convert("%ld"), -1); + DoNumTest(convert("65536"), convert("%ld"), 65536); + DoNumTest(convert("-1"), convert("%Ld"), -1); + DoNumTest(convert("65536"), convert("%Ld"), 65536); + DoI64NumTest(convert("4294967296"), convert("%I64d"), I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test4/testinfo.dat new file mode 100644 index 0000000..e610287 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test4/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test4 +Description += Tests swscanf with decimal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test5/CMakeLists.txt new file mode 100644 index 0000000..736ce11 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_swscanf_test5 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test5 coreclrpal) + +target_link_libraries(paltest_swscanf_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test5/test5.cpp new file mode 100644 index 0000000..8ae2d81 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test5/test5.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================================ +** +** Source: test5.c +** +** Purpose: Tests swscanf with integer numbers +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest(convert("1234d"), convert("%i"), 1234); + DoNumTest(convert("1234d"), convert("%2i"), 12); + DoNumTest(convert("-1"), convert("%i"), -1); + DoNumTest(convert("0x1234"), convert("%i"), 0x1234); + DoNumTest(convert("012"), convert("%i"), 10); + DoShortNumTest(convert("-1"), convert("%hi"), n65535); + DoShortNumTest(convert("65536"), convert("%hi"), 0); + DoNumTest(convert("-1"), convert("%li"), -1); + DoNumTest(convert("65536"), convert("%li"), 65536); + DoNumTest(convert("-1"), convert("%Li"), -1); + DoNumTest(convert("65536"), convert("%Li"), 65536); + DoI64NumTest(convert("4294967296"), convert("%I64i"), I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test5/testinfo.dat new file mode 100644 index 0000000..9991286 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test5/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test5 +Description += Tests swscanf with integer numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test6/CMakeLists.txt new file mode 100644 index 0000000..48c2750 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_swscanf_test6 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test6 coreclrpal) + +target_link_libraries(paltest_swscanf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test6/test6.cpp new file mode 100644 index 0000000..982f799 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test6/test6.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose:Tests swscanf with octal numbers +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest(convert("1234d"), convert("%o"), 668); + DoNumTest(convert("1234d"), convert("%2o"), 10); + DoNumTest(convert("-1"), convert("%o"), -1); + DoNumTest(convert("0x1234"), convert("%o"), 0); + DoNumTest(convert("012"), convert("%o"), 10); + DoShortNumTest(convert("-1"), convert("%ho"), n65535); + DoShortNumTest(convert("200000"), convert("%ho"), 0); + DoNumTest(convert("-1"), convert("%lo"), -1); + DoNumTest(convert("200000"), convert("%lo"), 65536); + DoNumTest(convert("-1"), convert("%Lo"), -1); + DoNumTest(convert("200000"), convert("%Lo"), 65536); + DoI64NumTest(convert("40000000000"), convert("%I64o"), I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test6/testinfo.dat new file mode 100644 index 0000000..ca7870e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test6/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test6 +Description += Tests swscanf with octal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test7/CMakeLists.txt new file mode 100644 index 0000000..4453e24 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_swscanf_test7 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test7 coreclrpal) + +target_link_libraries(paltest_swscanf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test7/test7.cpp new file mode 100644 index 0000000..45e9400 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test7/test7.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================================ +** +** Source: test7.c +** +** Purpose: Test #6 for the swscanf function +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest(convert("1234d"), convert("%x"), 0x1234d); + DoNumTest(convert("1234d"), convert("%2x"), 0x12); + DoNumTest(convert("-1"), convert("%x"), -1); + DoNumTest(convert("0x1234"), convert("%x"), 0x1234); + DoNumTest(convert("012"), convert("%x"), 0x12); + DoShortNumTest(convert("-1"), convert("%hx"), n65535); + DoShortNumTest(convert("10000"), convert("%hx"), 0); + DoNumTest(convert("-1"), convert("%lx"), -1); + DoNumTest(convert("10000"), convert("%lx"), 65536); + DoNumTest(convert("-1"), convert("%Lx"), -1); + DoNumTest(convert("10000"), convert("%Lx"), 65536); + DoI64NumTest(convert("100000000"), convert("%I64x"), I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test7/testinfo.dat new file mode 100644 index 0000000..43ff810 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test7/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test7 +Description += Tests swscanf with hex numbers (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test8/CMakeLists.txt new file mode 100644 index 0000000..8d4e51b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_swscanf_test8 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test8 coreclrpal) + +target_link_libraries(paltest_swscanf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test8/test8.cpp new file mode 100644 index 0000000..a244de7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test8/test8.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================================ +** +** Source: test8.c +** +** Purpose: Tests swscanf with unsigned numbers +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest(convert("1234d"), convert("%u"), 1234); + DoNumTest(convert("1234d"), convert("%2u"), 12); + DoNumTest(convert("-1"), convert("%u"), -1); + DoNumTest(convert("0x1234"), convert("%u"), 0); + DoNumTest(convert("012"), convert("%u"), 12); + DoShortNumTest(convert("-1"), convert("%hu"), n65535); + DoShortNumTest(convert("65536"), convert("%hu"), 0); + DoNumTest(convert("-1"), convert("%lu"), -1); + DoNumTest(convert("65536"), convert("%lu"), 65536); + DoNumTest(convert("-1"), convert("%Lu"), -1); + DoNumTest(convert("65536"), convert("%Lu"), 65536); + DoI64NumTest(convert("4294967296"), convert("%I64u"), I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test8/testinfo.dat new file mode 100644 index 0000000..0edefb0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test8/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test8 +Description += Tests swscanf with unsigned numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test9/CMakeLists.txt new file mode 100644 index 0000000..4b5e4c5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_swscanf_test9 + ${SOURCES} +) + +add_dependencies(paltest_swscanf_test9 coreclrpal) + +target_link_libraries(paltest_swscanf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test9/test9.cpp new file mode 100644 index 0000000..e289d26 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test9/test9.cpp @@ -0,0 +1,37 @@ +// 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. + +/*============================================================================ +** +** Source: test9.c +** +** Purpose: Tests swscanf with characters +** +** +**==========================================================================*/ + + + +#include +#include "../swscanf.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoWCharTest(convert("1234"), convert("%c"), convert("1"), 1); + DoWCharTest(convert("1234"), convert("%c"), convert("1"), 1); + DoWCharTest(convert("abc"), convert("%2c"), convert("ab"), 2); + DoWCharTest(convert(" ab"), convert("%c"), convert(" "), 1); + DoCharTest(convert("ab"), convert("%hc"), "a", 1); + DoWCharTest(convert("ab"), convert("%lc"), convert("a"), 1); + DoWCharTest(convert("ab"), convert("%Lc"), convert("a"), 1); + DoWCharTest(convert("ab"), convert("%I64c"), convert("a"), 1); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test9/testinfo.dat new file mode 100644 index 0000000..955b62b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/swscanf/test9/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = swscanf +Name = Positive Test for swscanf +TYPE = DEFAULT +EXE1 = test9 +Description += Tests swscanf with characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/test1/CMakeLists.txt new file mode 100644 index 0000000..c7bffa5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_tan_test1 + ${SOURCES} +) + +add_dependencies(paltest_tan_test1 coreclrpal) + +target_link_libraries(paltest_tan_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/test1/test1.cpp new file mode 100644 index 0000000..443e5da --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/test1/test1.cpp @@ -0,0 +1,137 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that tan return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = tan(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("tan(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = tan(value); + + if (!_isnan(result)) + { + Fail("tan(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.31830988618379067, 0.32951473309607836, PAL_EPSILON }, // value: 1 / pi + { 0.43429448190325183, 0.46382906716062964, PAL_EPSILON }, // value: log10(e) + { 0.63661977236758134, 0.73930295048660405, PAL_EPSILON }, // value: 2 / pi + { 0.69314718055994531, 0.83064087786078395, PAL_EPSILON }, // value: ln(2) + { 0.70710678118654752, 0.85451043200960189, PAL_EPSILON }, // value: 1 / sqrt(2) + { 0.78539816339744831, 1, PAL_EPSILON * 10 }, // value: pi / 4 + { 1, 1.5574077246549022, PAL_EPSILON * 10 }, + { 1.1283791670955126, 2.1108768356626451, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi) + { 1.4142135623730950, 6.3341191670421916, PAL_EPSILON * 10 }, // value: sqrt(2) + { 1.4426950408889634, 7.7635756709721848, PAL_EPSILON * 10 }, // value: log2(e) + // SEE BELOW -- { 1.5707963267948966, PAL_POSINF, 0 }, // value: pi / 2 + { 2.3025850929940457, -1.1134071468135374, PAL_EPSILON * 10 }, // value: ln(10) + { 2.7182818284590452, -0.45054953406980750, PAL_EPSILON }, // value: e + { 3.1415926535897932, 0, PAL_EPSILON }, // value: pi + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + // -- SPECIAL CASE -- + // Normally, tan(pi / 2) would return PAL_POSINF (atan2(PAL_POSINF) does return (pi / 2)). + // However, it seems instead (on all supported systems), we get a different number entirely. + validate( 1.5707963267948966, 16331239353195370.0, 0); + validate(-1.5707963267948966, -16331239353195370.0, 0); + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/test1/testinfo.dat new file mode 100644 index 0000000..05d6cfe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tan/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = tan +Name = Positive Test for tan +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to tan() a series of angle value, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/test1/CMakeLists.txt new file mode 100644 index 0000000..e6a4ee5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_tanf_test1 + ${SOURCES} +) + +add_dependencies(paltest_tanf_test1 coreclrpal) + +target_link_libraries(paltest_tanf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/test1/test1.c new file mode 100644 index 0000000..18d5c4e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/test1/test1.c @@ -0,0 +1,136 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that tanf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = tanf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("tanf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = tanf(value); + + if (!_isnanf(result)) + { + Fail("tanf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.318309886f, 0.329514733f, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0.463829067f, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0.739302950f, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0.830640878f, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0.854510432f, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 1, PAL_EPSILON * 10 }, // value: pi / 4 + { 1, 1.55740772f, PAL_EPSILON * 10 }, + { 1.12837917f, 2.11087684f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 6.33411917f, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 7.76357567f, PAL_EPSILON * 10 }, // value: logf2(e) + // SEE BELOW -- { 1.57079633f, PAL_POSINF, 0 }, // value: pi / 2 + { 2.30258509f, -1.11340715f, PAL_EPSILON * 10 }, // value: ln(10) + { 2.71828183f, -0.450549534f, PAL_EPSILON }, // value: e + { 3.14159265f, 0, PAL_EPSILON }, // value: pi + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + // -- SPECIAL CASE -- + // Normally, tanf(pi / 2) would return PAL_POSINF (atan2f(PAL_POSINF) does return (pi / 2)). + // However, it seems instead (on all supported systems), we get a different number entirely. + validate( 1.57079633f, -22877332.0, PAL_EPSILON * 100000000); + validate(-1.57079633f, 22877332.0, PAL_EPSILON * 100000000); + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/test1/testinfo.dat new file mode 100644 index 0000000..aa33232 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = tanf +Name = Positive Test for tanf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to tanf() a series of angle value, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/test1/CMakeLists.txt new file mode 100644 index 0000000..ee8f76a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_tanh_test1 + ${SOURCES} +) + +add_dependencies(paltest_tanh_test1 coreclrpal) + +target_link_libraries(paltest_tanh_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/test1/test1.cpp new file mode 100644 index 0000000..3b8f879 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/test1/test1.cpp @@ -0,0 +1,130 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that tanh return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = tanh(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("tanh(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = tanh(value); + + if (!_isnan(result)) + { + Fail("tanh(%g) returned %20.17g when it should have returned %20.17g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.31830988618379067, 0.30797791269089433, PAL_EPSILON }, // value: 1 / pi + { 0.43429448190325183, 0.40890401183401433, PAL_EPSILON }, // value: log10(e) + { 0.63661977236758134, 0.56259360033158334, PAL_EPSILON }, // value: 2 / pi + { 0.69314718055994531, 0.6, PAL_EPSILON }, // value: ln(2) + { 0.70710678118654752, 0.60885936501391381, PAL_EPSILON }, // value: 1 / sqrt(2) + { 0.78539816339744831, 0.65579420263267244, PAL_EPSILON }, // value: pi / 4 + { 1, 0.76159415595576489, PAL_EPSILON }, + { 1.1283791670955126, 0.81046380599898809, PAL_EPSILON }, // value: 2 / sqrt(pi) + { 1.4142135623730950, 0.88838556158566054, PAL_EPSILON }, // value: sqrt(2) + { 1.4426950408889634, 0.89423894585503855, PAL_EPSILON }, // value: log2(e) + { 1.5707963267948966, 0.91715233566727435, PAL_EPSILON }, // value: pi / 2 + { 2.3025850929940457, 0.98019801980198020, PAL_EPSILON }, // value: ln(10) + { 2.7182818284590452, 0.99132891580059984, PAL_EPSILON }, // value: e + { 3.1415926535897932, 0.99627207622074994, PAL_EPSILON }, // value: pi + { PAL_POSINF, 1, PAL_EPSILON * 10 } + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/test1/testinfo.dat new file mode 100644 index 0000000..1b2bc91 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanh/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = tanh +Name = Positive Test for tanh +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to tanh() a series of angle value, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/test1/CMakeLists.txt new file mode 100644 index 0000000..5ee8f06 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.c +) + +add_executable(paltest_tanhf_test1 + ${SOURCES} +) + +add_dependencies(paltest_tanhf_test1 coreclrpal) + +target_link_libraries(paltest_tanhf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/test1/test1.c b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/test1/test1.c new file mode 100644 index 0000000..904729a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/test1/test1.c @@ -0,0 +1,129 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that tanhf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = tanhf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("tanhf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = tanhf(value); + + if (!_isnanf(result)) + { + Fail("tanhf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.318309886f, 0.307977913f, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0.408904012f, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0.562593600f, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0.6f, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0.608859365f, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 0.655794203f, PAL_EPSILON }, // value: pi / 4 + { 1, 0.761594156f, PAL_EPSILON }, + { 1.12837917f, 0.810463806f, PAL_EPSILON }, // value: 2 / sqrtf(pi) + { 1.41421356f, 0.888385562f, PAL_EPSILON }, // value: sqrtf(2) + { 1.44269504f, 0.894238946f, PAL_EPSILON }, // value: logf2(e) + { 1.57079633f, 0.917152336f, PAL_EPSILON }, // value: pi / 2 + { 2.30258509f, 0.980198020f, PAL_EPSILON }, // value: ln(10) + { 2.71828183f, 0.991328916f, PAL_EPSILON }, // value: e + { 3.14159265f, 0.996272076f, PAL_EPSILON }, // value: pi + { PAL_POSINF, 1, PAL_EPSILON * 10 } + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/test1/testinfo.dat new file mode 100644 index 0000000..6c7594f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tanhf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = tanhf +Name = Positive Test for tanhf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to tanhf() a series of angle value, checking that += each one return to correct value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/test1/CMakeLists.txt new file mode 100644 index 0000000..7b43d7a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_time_test1 + ${SOURCES} +) + +add_dependencies(paltest_time_test1 coreclrpal) + +target_link_libraries(paltest_time_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/test1/test1.cpp new file mode 100644 index 0000000..c668bf3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/test1/test1.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Calls the time function and verifies that the time returned +** is at least a positive value. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + time_t t = 0; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + time(&t); + /*I was going to test that the time returned didn't exceed some + reasonable value, but decided not to, for fear of creating my own + little Y2K-style disaster.*/ + + if (t <= 0) + { + Fail("time() function doesn't return a time.\n"); + } + t = 0; + t = time(NULL); + if (t <= 0) + { + Fail("time() function doesn't return a time.\n"); + } + PAL_Terminate(); + return PASS; +} + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/test1/testinfo.dat new file mode 100644 index 0000000..40134c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/time/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = time +Name = Positive Test for time +TYPE = DEFAULT +EXE1 = test1 +Description += Calls the time function and verifies that the time returned is at += least a positive value. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/test1/CMakeLists.txt new file mode 100644 index 0000000..8fb5390 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_tolower_test1 + ${SOURCES} +) + +add_dependencies(paltest_tolower_test1 coreclrpal) + +target_link_libraries(paltest_tolower_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/test1/test1.cpp new file mode 100644 index 0000000..cab623d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/test1/test1.cpp @@ -0,0 +1,79 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the tolower function. +** Check that the tolower function makes capital character +** lower case. Also check that it has no effect on lower +** case letters and special characters. +** +** +**===================================================================*/ + +#include + +struct testCase +{ + int lower; + int start; +}; + +int __cdecl main(int argc, char **argv) +{ + + int result; + int i; + + struct testCase testCases[] = + { + {'a', 'A'}, /* Basic cases */ + {'z', 'Z'}, + {'b', 'b'}, /* Lower case */ + {'?', '?'}, /* Characters without case */ + {230, 230} + }; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Loop through each case. Convert each character to lower case + and then compare to ensure that it is the correct value. + */ + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + /*Convert to lower case*/ + result = tolower(testCases[i].start); + + if (testCases[i].lower != result) + { + Fail("ERROR: tolower lowered \"%i\" to %i instead of %i.\n", + testCases[i].start, result, testCases[i].lower); + } + + } + + + PAL_Terminate(); + return PASS; +} + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/test1/testinfo.dat new file mode 100644 index 0000000..90f1c72 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/tolower/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = tolower +Name = Positive Test for tolower +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the tolower function. += Check that the tolower function makes capital character lower case. += Also check that it has no effect on lower case letters and special += characters. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/test1/CMakeLists.txt new file mode 100644 index 0000000..68541eb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_toupper_test1 + ${SOURCES} +) + +add_dependencies(paltest_toupper_test1 coreclrpal) + +target_link_libraries(paltest_toupper_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/test1/test1.cpp new file mode 100644 index 0000000..c580699 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/test1/test1.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. + +/*===================================================================== +** +** Source: test1.c (toupper) +** +** +** Purpose: Tests the PAL implementation of the toupper function. +** Check that the toupper function makes lower case +** character a capital. Also check that it has no effect +** on upper case letters and special characters. +** +** +**===================================================================*/ + +#include + +struct testCase +{ + int upper; + int start; +}; + +int __cdecl main(int argc, char **argv) +{ + + int result; + int i; + + struct testCase testCases[] = + { + {'A', 'a'}, /* Basic cases */ + {'Z', 'z'}, + {'B', 'B'}, /* Upper case */ + {'%', '%'}, /* Characters without case */ + {157, 157} + }; + + if ((PAL_Initialize(argc, argv)) != 0) + { + return FAIL; + } + + + /* Loop through each case. Convert each character to upper case + and then compare to ensure that it is the correct value. + */ + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + /*Convert to upper case*/ + result = toupper(testCases[i].start); + + if (testCases[i].upper != result) + { + Fail("ERROR: toupper capitalized \"%c\" to %c instead of %c.\n", + testCases[i].start, result, testCases[i].upper); + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/test1/testinfo.dat new file mode 100644 index 0000000..bde7aff --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/toupper/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = toupper +Name = Positive Test for toupper +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the toupper function. += Check that the toupper function makes lower case character a capital. += Also check that it has no effect on upper case letters and special += characters. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/test1/CMakeLists.txt new file mode 100644 index 0000000..279882d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_towlower_test1 + ${SOURCES} +) + +add_dependencies(paltest_towlower_test1 coreclrpal) + +target_link_libraries(paltest_towlower_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/test1/test1.cpp new file mode 100644 index 0000000..5f2457a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/test1/test1.cpp @@ -0,0 +1,79 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the towlower function. +** Check that the tolower function makes capital character +** lower case. Also check that it has no effect on lower +** case letters and special characters. +** +** +**===================================================================*/ + +#include + +struct testCase +{ + WCHAR lower; + WCHAR start; +}; + +int __cdecl main(int argc, char **argv) +{ + + int result; + int i; + + struct testCase testCases[] = + { + {'a', 'A'}, /* Basic cases */ + {'z', 'Z'}, + {'b', 'b'}, /* Lower case */ + {'?', '?'}, /* Characters without case */ + {230, 230} + }; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Loop through each case. Convert each character to lower case + and then compare to ensure that it is the correct value. + */ + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + /*Convert to lower case*/ + result = towlower(testCases[i].start); + + if (testCases[i].lower != result) + { + Fail("ERROR: towlower lowered \"%c\" to %c instead of %c.\n", + testCases[i].start, result, testCases[i].lower); + } + + } + + + PAL_Terminate(); + return PASS; +} + + + + + + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/test1/testinfo.dat new file mode 100644 index 0000000..2df179a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towlower/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = towlower +Name = Positive Test for towlower +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the towlower function. += Check that the tolower function makes capital character lower case. += Also check that it has no effect on lower case letters and special += characters. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/test1/CMakeLists.txt new file mode 100644 index 0000000..95df931 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_towupper_test1 + ${SOURCES} +) + +add_dependencies(paltest_towupper_test1 coreclrpal) + +target_link_libraries(paltest_towupper_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/test1/test1.cpp new file mode 100644 index 0000000..63f051f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/test1/test1.cpp @@ -0,0 +1,65 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c(towupper) +** +** +** Purpose: Tests the PAL implementation of the towupper function. +** Check that the towupper function makes lower case +** character a capital. Also check that it has no effect +** on upper case letters and special characters. +** +** +**===================================================================*/ + +#include + +struct testCase +{ + WCHAR upper; + WCHAR start; +}; + +int __cdecl main(int argc, char **argv) +{ + + int result; + int i; + + struct testCase testCases[] = + { + {'A', 'a'}, /* Basic cases */ + {'Z', 'z'}, + {'B', 'B'}, /* Upper case */ + {'%', '%'}, /* Characters without case */ + {157, 157} + }; + + if ((PAL_Initialize(argc, argv)) != 0) + { + return FAIL; + } + + + /* Loop through each case. Convert each character to upper case + and then compare to ensure that it is the correct value. + */ + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + /*Convert to upper case*/ + result = towupper(testCases[i].start); + + if (testCases[i].upper != result) + { + Fail("ERROR: towupper capitalized \"%c\" to %c instead of %c.\n", + testCases[i].start, result, testCases[i].upper); + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/test1/testinfo.dat new file mode 100644 index 0000000..40b6fad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/towupper/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = towupper +Name = Positive Test for towupper +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the towupper function. += Check that the towupper function makes lower case character a capital. += Also check that it has no effect on upper case letters and special += characters. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/CMakeLists.txt new file mode 100644 index 0000000..256753a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/CMakeLists.txt @@ -0,0 +1,20 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test1/CMakeLists.txt new file mode 100644 index 0000000..2bc1d34 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_vfprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test1 coreclrpal) + +target_link_libraries(paltest_vfprintf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test1/test1.cpp new file mode 100644 index 0000000..302c914 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test1/test1.cpp @@ -0,0 +1,68 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Test #1 for the vfprintf function. A single, basic, test +** case with no formatting. +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + +int __cdecl main(int argc, char *argv[]) +{ + FILE *fp; + char testfile[] = "testfile.txt"; + char buf[256]; + char checkstr[] = "hello world"; + int ret; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + if ((fp = fopen(testfile, "w+")) == NULL) + { + Fail("ERROR: fopen failed to create \"%s\"\n", testfile); + } + + ret = DoVfprintf(fp, "hello world"); + + if (ret != strlen(checkstr)) + { + Fail("Expected vfprintf to return %d, got %d.\n", + strlen(checkstr), ret); + + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: Fseek failed to set pointer to beginning of file\n" ); + } + + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fgets failed\n"); + } + if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0) + { + Fail("ERROR: expected %s, got %s\n", checkstr, buf); + } + if ((fclose(fp)) != 0) + { + Fail("ERROR: fclose failed to close \"%s\"\n", testfile); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test1/testinfo.dat new file mode 100644 index 0000000..8359de8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test1 +Description += General test to see if vfprintf works correctly diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test10/CMakeLists.txt new file mode 100644 index 0000000..f15dcfe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_vfprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test10 coreclrpal) + +target_link_libraries(paltest_vfprintf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test10/test10.cpp new file mode 100644 index 0000000..ecb4b03 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test10/test10.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================================ +** +** Source: test10.c +** +** Purpose: Test #10 for the vfprintf function. Tests the octal specifier +** (%o). +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %o", pos, "foo 52"); + DoNumTest("foo %lo", 0xFFFF, "foo 177777"); + DoNumTest("foo %ho", 0xFFFF, "foo 177777"); + DoNumTest("foo %Lo", pos, "foo 52"); + DoI64Test("foo %I64o", l, "42", "foo 52"); + DoNumTest("foo %3o", pos, "foo 52"); + DoNumTest("foo %-3o", pos, "foo 52 "); + DoNumTest("foo %.1o", pos, "foo 52"); + DoNumTest("foo %.3o", pos, "foo 052"); + DoNumTest("foo %03o", pos, "foo 052"); + DoNumTest("foo %#o", pos, "foo 052"); + DoNumTest("foo %+o", pos, "foo 52"); + DoNumTest("foo % o", pos, "foo 52"); + DoNumTest("foo %+o", neg, "foo 37777777726"); + DoNumTest("foo % o", neg, "foo 37777777726"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test10/testinfo.dat new file mode 100644 index 0000000..034610a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test10/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test10 +Description += Tests vfprintf with octal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test11/CMakeLists.txt new file mode 100644 index 0000000..fdefd96 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_vfprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test11 coreclrpal) + +target_link_libraries(paltest_vfprintf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test11/test11.cpp new file mode 100644 index 0000000..5f7bc11 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test11/test11.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test11.c +** +** Purpose: Test #11 for the vfprintf function. Test the unsigned int +** specifier (%u). +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %u", pos, "foo 42"); + DoNumTest("foo %lu", 0xFFFF, "foo 65535"); + DoNumTest("foo %hu", 0xFFFF, "foo 65535"); + DoNumTest("foo %Lu", pos, "foo 42"); + DoI64Test("foo %I64u", l, "42", "foo 42"); + DoNumTest("foo %3u", pos, "foo 42"); + DoNumTest("foo %-3u", pos, "foo 42 "); + DoNumTest("foo %.1u", pos, "foo 42"); + DoNumTest("foo %.3u", pos, "foo 042"); + DoNumTest("foo %03u", pos, "foo 042"); + DoNumTest("foo %#u", pos, "foo 42"); + DoNumTest("foo %+u", pos, "foo 42"); + DoNumTest("foo % u", pos, "foo 42"); + DoNumTest("foo %+u", neg, "foo 4294967254"); + DoNumTest("foo % u", neg, "foo 4294967254"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test11/testinfo.dat new file mode 100644 index 0000000..4050bd6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test11/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test11 +Description += Tests vfprintf with unsigned numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test12/CMakeLists.txt new file mode 100644 index 0000000..d53b2c1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_vfprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test12 coreclrpal) + +target_link_libraries(paltest_vfprintf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test12/test12.cpp new file mode 100644 index 0000000..0bf61d3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test12/test12.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Test #12 for the vfprintf function. Tests the (lowercase) +** hexadecimal specifier (%x) +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %x", pos, "foo 1234ab"); + DoNumTest("foo %lx", pos, "foo 1234ab"); + DoNumTest("foo %hx", pos, "foo 34ab"); + DoNumTest("foo %Lx", pos, "foo 1234ab"); + DoI64Test("foo %I64x", l, "0x1234567887654321", + "foo 1234567887654321"); + DoNumTest("foo %7x", pos, "foo 1234ab"); + DoNumTest("foo %-7x", pos, "foo 1234ab "); + DoNumTest("foo %.1x", pos, "foo 1234ab"); + DoNumTest("foo %.7x", pos, "foo 01234ab"); + DoNumTest("foo %07x", pos, "foo 01234ab"); + DoNumTest("foo %#x", pos, "foo 0x1234ab"); + DoNumTest("foo %+x", pos, "foo 1234ab"); + DoNumTest("foo % x", pos, "foo 1234ab"); + DoNumTest("foo %+x", neg, "foo ffffffd6"); + DoNumTest("foo % x", neg, "foo ffffffd6"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test12/testinfo.dat new file mode 100644 index 0000000..640af62 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test12/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test12 +Description += Tests vfprintf with hex numbers (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test13/CMakeLists.txt new file mode 100644 index 0000000..7e07a50 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_vfprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test13 coreclrpal) + +target_link_libraries(paltest_vfprintf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test13/test13.cpp new file mode 100644 index 0000000..1e42ce9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test13/test13.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test13.c +** +** Purpose: Test #13 for the vfprintf function. Tests the (uppercase) +** hexadecimal specifier (%X) +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234AB; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %X", pos, "foo 1234AB"); + DoNumTest("foo %lX", pos, "foo 1234AB"); + DoNumTest("foo %hX", pos, "foo 34AB"); + DoNumTest("foo %LX", pos, "foo 1234AB"); + DoI64Test("foo %I64X", l, "0x1234567887654321", + "foo 1234567887654321"); + DoNumTest("foo %7X", pos, "foo 1234AB"); + DoNumTest("foo %-7X", pos, "foo 1234AB "); + DoNumTest("foo %.1X", pos, "foo 1234AB"); + DoNumTest("foo %.7X", pos, "foo 01234AB"); + DoNumTest("foo %07X", pos, "foo 01234AB"); + DoNumTest("foo %#X", pos, "foo 0X1234AB"); + DoNumTest("foo %+X", pos, "foo 1234AB"); + DoNumTest("foo % X", pos, "foo 1234AB"); + DoNumTest("foo %+X", neg, "foo FFFFFFD6"); + DoNumTest("foo % X", neg, "foo FFFFFFD6"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test13/testinfo.dat new file mode 100644 index 0000000..26c7db0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test13/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test13 +Description += Tests vfprintf with hex numbers (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test14/CMakeLists.txt new file mode 100644 index 0000000..eea6912 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_vfprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test14 coreclrpal) + +target_link_libraries(paltest_vfprintf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test14/test14.cpp new file mode 100644 index 0000000..82f2474 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test14/test14.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test14.c +** +** Purpose: Test #14 for the vfprintf function. Tests the lowercase +** exponential notation double specifier (%e) +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", + "foo 2.560000e+02 "); + DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02"); + DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", + "foo 2.56000000e+02"); + DoDoubleTest("foo %014e", val, "foo 02.560000e+002", + "foo 002.560000e+02"); + DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02"); + DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test14/testinfo.dat new file mode 100644 index 0000000..fa36319 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test14/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test14 +Description += Tests vfprintf with exponential format doubles (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test15/CMakeLists.txt new file mode 100644 index 0000000..1e88f42 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_vfprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test15 coreclrpal) + +target_link_libraries(paltest_vfprintf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test15/test15.cpp new file mode 100644 index 0000000..53cc2ce --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test15/test15.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test15.c +** +** Purpose: Test #15 for the vfprintf function. Tests the uppercase +** exponential notation double specifier (%E) +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %14E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", + "foo 2.560000E+02 "); + DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02"); + DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", + "foo 2.56000000E+02"); + DoDoubleTest("foo %014E", val, "foo 02.560000E+002", + "foo 002.560000E+02"); + DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02"); + DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test15/testinfo.dat new file mode 100644 index 0000000..f51f72c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test15/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test15 +Description += Tests vfprintf with exponential format doubles (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test16/CMakeLists.txt new file mode 100644 index 0000000..d34097b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_vfprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test16 coreclrpal) + +target_link_libraries(paltest_vfprintf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test16/test16.cpp new file mode 100644 index 0000000..2b7674b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test16/test16.cpp @@ -0,0 +1,50 @@ +// 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. + +/*============================================================================ +** +** Source: test16.c +** +** Purpose: Test #16 for the vfprintf function. Tests the decimal notation +** double specifier (%f) +** +** +**==========================================================================*/ + + +#include +#include "../vfprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 "); + DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0"); + DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000"); + DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000"); + DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000"); + DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000"); + DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test16/testinfo.dat new file mode 100644 index 0000000..f91d9f4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test16/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test16 +Description += Tests vfprintf with decimal point format doubles diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test17/CMakeLists.txt new file mode 100644 index 0000000..15c53b8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_vfprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test17 coreclrpal) + +target_link_libraries(paltest_vfprintf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test17/test17.cpp new file mode 100644 index 0000000..956be15 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test17/test17.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================================ +** +** Source: test17.c +** +** Purpose: Test #17 for the vfprintf function. Tests the lowercase +** shorthand notation double specifier (%g) +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03"); + DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03"); + DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test17/testinfo.dat new file mode 100644 index 0000000..6238464 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test17/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test17 +Description += Tests vfprintf with compact format doubles (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test18/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test18/CMakeLists.txt new file mode 100644 index 0000000..1e91c5e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test18/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test18.cpp +) + +add_executable(paltest_vfprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test18 coreclrpal) + +target_link_libraries(paltest_vfprintf_test18 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test18/test18.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test18/test18.cpp new file mode 100644 index 0000000..c61c8cb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test18/test18.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test18.c +** +** Purpose: Test #18 for the vfprintf function. Tests the uppercase +** shorthand notation double specifier (%G) +** +** +**==========================================================================*/ + + +#include +#include "../vfprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03"); + DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03"); + DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test18/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test18/testinfo.dat new file mode 100644 index 0000000..44ddab3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test18/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test18 +Description += Tests vfprintf with compact format doubles (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test19/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test19/CMakeLists.txt new file mode 100644 index 0000000..4131553 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test19/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test19.cpp +) + +add_executable(paltest_vfprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test19 coreclrpal) + +target_link_libraries(paltest_vfprintf_test19 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.cpp new file mode 100644 index 0000000..d8e8f93 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.cpp @@ -0,0 +1,76 @@ +// 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. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose: Test #19 for the vfprintf function. Tests the variable length +** precision argument. +** +** +**==========================================================================*/ + + +#include +#include "../vfprintf.h" + + + + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoArgumentPrecTest("%.*s", 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest("%.*S", 2, (void*)convert("bar"), "bar", "ba", "ba"); + + DoArgumentPrecTest("%.*n ", 3, (void*)&n, "pointer to int", " ", " "); + if (n != 0) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + 0, n); + } + + DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test19/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test19/testinfo.dat new file mode 100644 index 0000000..729c279 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test19/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test19 +Description += Tests vfprintf with argument specified precision diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test2/CMakeLists.txt new file mode 100644 index 0000000..3c2c738 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_vfprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test2 coreclrpal) + +target_link_libraries(paltest_vfprintf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test2/test2.cpp new file mode 100644 index 0000000..0228734 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test2/test2.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Test #2 for the vfprintf function. Tests the string specifier +** (%s). +** +** +**==========================================================================*/ + + +#include +#include "../vfprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoStrTest("foo %s", "bar", "foo bar"); + DoStrTest("foo %hs", "bar", "foo bar"); + DoWStrTest("foo %ls", convert("bar"), "foo bar"); + DoWStrTest("foo %ws", convert("bar"), "foo bar"); + DoStrTest("foo %Ls", "bar", "foo bar"); + DoStrTest("foo %I64s", "bar", "foo bar"); + DoStrTest("foo %5s", "bar", "foo bar"); + DoStrTest("foo %.2s", "bar", "foo ba"); + DoStrTest("foo %5.2s", "bar", "foo ba"); + DoStrTest("foo %-5s", "bar", "foo bar "); + DoStrTest("foo %05s", "bar", "foo 00bar"); + DoStrTest("foo %s", NULL, "foo (null)"); + DoStrTest("foo %hs", NULL, "foo (null)"); + DoStrTest("foo %ls", NULL, "foo (null)"); + DoStrTest("foo %ws", NULL, "foo (null)"); + DoStrTest("foo %Ls", NULL, "foo (null)"); + DoStrTest("foo %I64s", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test2/testinfo.dat new file mode 100644 index 0000000..6d2f231 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test2 +Description += Tests vfprintf with strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test3/CMakeLists.txt new file mode 100644 index 0000000..85a4265 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_vfprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test3 coreclrpal) + +target_link_libraries(paltest_vfprintf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test3/test3.cpp new file mode 100644 index 0000000..879446f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test3/test3.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Test #3 for the vfprintf function. Tests the wide string +** specifier (%S). +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoWStrTest("foo %S", convert("bar"), "foo bar"); + DoStrTest("foo %hS", "bar", "foo bar"); + DoWStrTest("foo %lS", convert("bar"), "foo bar"); + DoWStrTest("foo %wS", convert("bar"), "foo bar"); + DoWStrTest("foo %LS", convert("bar"), "foo bar"); + DoWStrTest("foo %I64S", convert("bar"), "foo bar"); + DoWStrTest("foo %5S", convert("bar"), "foo bar"); + DoWStrTest("foo %.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %5.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %-5S", convert("bar"), "foo bar "); + DoWStrTest("foo %05S", convert("bar"), "foo 00bar"); + DoWStrTest("foo %S", NULL, "foo (null)"); + DoStrTest("foo %hS", NULL, "foo (null)"); + DoWStrTest("foo %lS", NULL, "foo (null)"); + DoWStrTest("foo %wS", NULL, "foo (null)"); + DoWStrTest("foo %LS", NULL, "foo (null)"); + DoWStrTest("foo %I64S", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test3/testinfo.dat new file mode 100644 index 0000000..b5aa1e2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test3 +Description += Tests vfprintf with wide strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test4/CMakeLists.txt new file mode 100644 index 0000000..5907a8d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_vfprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test4 coreclrpal) + +target_link_libraries(paltest_vfprintf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test4/test4.cpp new file mode 100644 index 0000000..d1376f1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test4/test4.cpp @@ -0,0 +1,70 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Test #4 for the vfprintf function. Tests the pointer +** specifier (%p). +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "0000000000000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); + +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "00000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); + +#endif + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test4/testinfo.dat new file mode 100644 index 0000000..d08928a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test4/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test4 +Description += Tests vfprintf with pointers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test5/CMakeLists.txt new file mode 100644 index 0000000..97e5e4b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_vfprintf_test5 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test5 coreclrpal) + +target_link_libraries(paltest_vfprintf_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test5/test5.cpp new file mode 100644 index 0000000..44f21b6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test5/test5.cpp @@ -0,0 +1,60 @@ +// 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. + +/*============================================================================ +** +** Source: test5.c +** +** Purpose: Test #5 for the vfprintf function. Tests the count specifier (%n). +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + + + + +int __cdecl main(int argc, char *argv[]) +{ + char *longStr = + "really-long-string-that-just-keeps-going-on-and-on-and-on.." + "..................useless-filler.................................." + "..................useless-filler.................................." + "..................useless-filler.................................." + "%n bar"; + char *longResult = + "really-long-string-that-just-keeps-going-on-and-on-and-on.." + "..................useless-filler.................................." + "..................useless-filler.................................." + "..................useless-filler.................................." + " bar"; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoCountTest("foo %n bar", 4, "foo bar"); + DoCountTest(longStr, 257, longResult); + DoCountTest("fo%n bar", 2, "fo bar"); + DoCountTest("%n ", 0, " "); + DoCountTest("foo %#n bar", 4, "foo bar"); + DoCountTest("foo % n bar", 4, "foo bar"); + DoCountTest("foo %+n bar", 4, "foo bar"); + DoCountTest("foo %-n bar", 4, "foo bar"); + DoCountTest("foo %0n bar", 4, "foo bar"); + DoShortCountTest("foo %hn bar", 4, "foo bar"); + DoCountTest("foo %ln bar", 4, "foo bar"); + DoCountTest("foo %Ln bar", 4, "foo bar"); + DoCountTest("foo %I64n bar", 4, "foo bar"); + DoCountTest("foo %20.3n bar", 4, "foo bar"); + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test5/testinfo.dat new file mode 100644 index 0000000..73feaa0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test5/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test5 +Description += Tests vfprintf with the count specifier diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test6/CMakeLists.txt new file mode 100644 index 0000000..afe4f1a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_vfprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test6 coreclrpal) + +target_link_libraries(paltest_vfprintf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test6/test6.cpp new file mode 100644 index 0000000..36c6fe5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test6/test6.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose: Test #6 for the vfprintf function. Tests the char specifier (%c). +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoCharTest("foo %c", 'b', "foo b"); + DoCharTest("foo %hc", 'b', "foo b"); + DoWCharTest("foo %lc", wc, "foo c"); + DoCharTest("foo %Lc", 'b', "foo b"); + DoCharTest("foo %I64c", 'b', "foo b"); + DoCharTest("foo %5c", 'b', "foo b"); + DoCharTest("foo %.0c", 'b', "foo b"); + DoCharTest("foo %-5c", 'b', "foo b "); + DoCharTest("foo %05c", 'b', "foo 0000b"); + DoCharTest("foo % c", 'b', "foo b"); + DoCharTest("foo %#c", 'b', "foo b"); + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test6/testinfo.dat new file mode 100644 index 0000000..cb1337d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test6/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test6 +Description += Tests vfprintf with characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test7/CMakeLists.txt new file mode 100644 index 0000000..e528033 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_vfprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test7 coreclrpal) + +target_link_libraries(paltest_vfprintf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test7/test7.cpp new file mode 100644 index 0000000..a9cfe31 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test7/test7.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test7.c +** +** Purpose: Test #7 for the vfprintf function. Tests the wide char +** specifier (%C). +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wb = (WCHAR) 'b'; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoWCharTest("foo %C", wb, "foo b"); + DoWCharTest("foo %hC", wb, "foo b"); + DoCharTest("foo %lC", 'c', "foo c"); + DoWCharTest("foo %LC", wb, "foo b"); + DoWCharTest("foo %I64C", wb, "foo b"); + DoWCharTest("foo %5C", wb, "foo b"); + DoWCharTest("foo %.0C", wb, "foo b"); + DoWCharTest("foo %-5C", wb, "foo b "); + DoWCharTest("foo %05C", wb, "foo 0000b"); + DoWCharTest("foo % C", wb, "foo b"); + DoWCharTest("foo %#C", wb, "foo b"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test7/testinfo.dat new file mode 100644 index 0000000..c861344 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test7/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test7 +Description += Tests vfprintf with wide characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test8/CMakeLists.txt new file mode 100644 index 0000000..d131025 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_vfprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test8 coreclrpal) + +target_link_libraries(paltest_vfprintf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test8/test8.cpp new file mode 100644 index 0000000..5cef997 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test8/test8.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test8.c +** +** Purpose: Test #8 for the vfprintf function. Tests the decimal +** specifier (%d). +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %d", pos, "foo 42"); + DoNumTest("foo %ld", 0xFFFF, "foo 65535"); + DoNumTest("foo %hd", 0xFFFF, "foo -1"); + DoNumTest("foo %Ld", pos, "foo 42"); + DoI64Test("foo %I64d", l, "42", "foo 42"); + DoNumTest("foo %3d", pos, "foo 42"); + DoNumTest("foo %-3d", pos, "foo 42 "); + DoNumTest("foo %.1d", pos, "foo 42"); + DoNumTest("foo %.3d", pos, "foo 042"); + DoNumTest("foo %03d", pos, "foo 042"); + DoNumTest("foo %#d", pos, "foo 42"); + DoNumTest("foo %+d", pos, "foo +42"); + DoNumTest("foo % d", pos, "foo 42"); + DoNumTest("foo %+d", neg, "foo -42"); + DoNumTest("foo % d", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test8/testinfo.dat new file mode 100644 index 0000000..e967233 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test8/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test8 +Description += Tests vfprintf with decimal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test9/CMakeLists.txt new file mode 100644 index 0000000..68c0717 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_vfprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_vfprintf_test9 coreclrpal) + +target_link_libraries(paltest_vfprintf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test9/test9.cpp new file mode 100644 index 0000000..45d0dc7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test9/test9.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test9.c +** +** Purpose: Test #9 for the vfprintf function. Tests the integer +** specifier (%i). +** +** +**==========================================================================*/ + + + +#include +#include "../vfprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %i", pos, "foo 42"); + DoNumTest("foo %li", 0xFFFF, "foo 65535"); + DoNumTest("foo %hi", 0xFFFF, "foo -1"); + DoNumTest("foo %Li", pos, "foo 42"); + DoI64Test("foo %I64i", l, "42", "foo 42"); + DoNumTest("foo %3i", pos, "foo 42"); + DoNumTest("foo %-3i", pos, "foo 42 "); + DoNumTest("foo %.1i", pos, "foo 42"); + DoNumTest("foo %.3i", pos, "foo 042"); + DoNumTest("foo %03i", pos, "foo 042"); + DoNumTest("foo %#i", pos, "foo 42"); + DoNumTest("foo %+i", pos, "foo +42"); + DoNumTest("foo % i", pos, "foo 42"); + DoNumTest("foo %+i", neg, "foo -42"); + DoNumTest("foo % i", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test9/testinfo.dat new file mode 100644 index 0000000..4862177 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/test9/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vfprintf +Name = Positive Test for vfprintf +TYPE = DEFAULT +EXE1 = test9 +Description += Tests vfprintf with integer numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/vfprintf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/vfprintf.h new file mode 100644 index 0000000..7901b08 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vfprintf/vfprintf.h @@ -0,0 +1,463 @@ +// 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. + +/*============================================================================ +** +** Source: vfprintf.h +** +** Purpose: Contains common testing functions for vfprintf +** +** +**==========================================================================*/ + +#ifndef __vfprintf_H__ +#define __vfprintf_H__ + +int DoVfprintf(FILE *fp, const char *format, ...) +{ + int retVal; + va_list arglist; + + va_start(arglist, format); + retVal = vfprintf(fp, format, arglist); + va_end(arglist); + + return (retVal); +} + +void DoStrTest(const char *formatstr, char* param, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + if ((DoVfprintf(fp, formatstr, param)) < 0) + { + Fail("ERROR: vfprintf failed\n"); + } + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fgets failed\n"); + } + + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, formatstr, checkstr, buf); + } + fclose(fp); +} + +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + if ((DoVfprintf(fp, formatstr, param)) < 0) + { + Fail("ERROR: vfprintf failed\n"); + } + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fgets failed\n"); + } + + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert wide string \"%S\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, formatstr, checkstr, buf); + } + fclose(fp); +} + + +void DoPointerTest(const char *formatstr, void* param, char* paramstr, + const char *checkstr1) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((DoVfprintf(fp, formatstr, param)) < 0) + { + Fail("ERROR: vfprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fgets failed\n"); + } + + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + paramstr, formatstr, checkstr1, buf); + } + + if ((fclose( fp )) != 0) + { + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + } +} + + + +void DoCountTest(const char *formatstr, int param, const char *checkstr) +{ + FILE *fp; + char buf[512] = { 0 }; + int n = -1; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((DoVfprintf(fp, formatstr, &n)) < 0) + { + Fail("ERROR: vfprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, sizeof(buf), fp)) == NULL) + { + Fail("ERROR: fgets failed\n"); + } + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } + + if ((fclose( fp )) != 0) + { + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + } +} + +void DoShortCountTest(const char *formatstr, int param, const char *checkstr) +{ + FILE *fp; + char buf[512] = { 0 }; + short int n = -1; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((DoVfprintf(fp, formatstr, &n)) < 0) + { + Fail("ERROR: vfprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fgets failed\n"); + } + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } + + if ((fclose( fp )) != 0) + { + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + } +} + + +void DoCharTest(const char *formatstr, char param, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + if ((DoVfprintf(fp, formatstr, param)) < 0) + { + Fail("ERROR: vfprintf failed\n"); + } + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fgets failed\n"); + } + + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, param, formatstr, checkstr, buf); + } + fclose(fp); +} + +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + if ((DoVfprintf(fp, formatstr, param)) < 0) + { + Fail("ERROR: vfprintf failed\n"); + } + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fgets failed\n"); + } + + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + (char)param, param, formatstr, checkstr, buf); + } + fclose(fp); +} + +void DoNumTest(const char *formatstr, int value, const char *checkstr) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + if ((DoVfprintf(fp, formatstr, value)) < 0) + { + Fail("ERROR: vfprintf failed\n"); + } + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fgets failed\n"); + } + + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert %#x into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + value, formatstr, checkstr, buf); + } + fclose(fp); +} + +void DoI64Test(const char *formatstr, INT64 value, char *valuestr, const char *checkstr1) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + if ((DoVfprintf(fp, formatstr, value)) < 0) + { + Fail("ERROR: vfprintf failed\n"); + } + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fgets failed\n"); + } + + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", + valuestr, formatstr, checkstr1, buf); + } + fclose(fp); +} + +void DoDoubleTest(const char *formatstr, double value, const char *checkstr1, + const char *checkstr2) +{ + FILE *fp; + char buf[256] = { 0 }; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((DoVfprintf(fp, formatstr, value)) < 0) + { + Fail("ERROR: vfprintf failed\n"); + } + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fgets failed\n"); + } + + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + value, formatstr, checkstr1, checkstr2, buf); + } + fclose(fp); +} + + +void DoArgumentPrecTest(const char *formatstr, int precision, void *param, + char *paramstr, const char *checkstr1, const char *checkstr2) +{ + FILE *fp; + char buf[256]; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((DoVfprintf(fp, formatstr, precision, param)) < 0) + { + Fail("ERROR: vfprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fgets failed\n"); + } + + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", paramstr, formatstr, + precision, checkstr1, checkstr2, buf); + } + + + if ((fclose( fp )) != 0) + { + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + } + +} + +void DoArgumentPrecDoubleTest(const char *formatstr, int precision, double param, + const char *checkstr1, const char *checkstr2) +{ + FILE *fp; + char buf[256]; + + if ((fp = fopen("testfile.txt", "w+")) == NULL ) + { + Fail("ERROR: fopen failed to create testfile\n"); + } + + if ((DoVfprintf(fp, formatstr, precision, param)) < 0) + { + Fail("ERROR: vfprintf failed\n"); + } + + if ((fseek(fp, 0, SEEK_SET)) != 0) + { + Fail("ERROR: fseek failed\n"); + } + + if ((fgets(buf, 100, fp)) == NULL) + { + Fail("ERROR: fgets failed\n"); + } + + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", param, formatstr, + precision, checkstr1, checkstr2, buf); + } + + if ((fclose( fp )) != 0) + { + Fail("ERROR: fclose failed to close \"testfile.txt\"\n"); + } + +} + +#endif + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/CMakeLists.txt new file mode 100644 index 0000000..1201665 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/CMakeLists.txt @@ -0,0 +1,21 @@ +# This test fails to build on ARM +#add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test1/CMakeLists.txt new file mode 100644 index 0000000..12e210b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_vprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test1 coreclrpal) + +target_link_libraries(paltest_vprintf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test1/test1.cpp new file mode 100644 index 0000000..404d7a0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test1/test1.cpp @@ -0,0 +1,43 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Test #1 for the vprintf function. A single, basic, test +** case with no formatting. +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + +int __cdecl main(int argc, char *argv[]) +{ + char checkstr[] = "hello world"; + int ret; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + ret = vprintf("hello world", NULL); + + if (ret != strlen(checkstr)) + { + Fail("Expected vprintf to return %d, got %d.\n", + strlen(checkstr), ret); + + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test1/testinfo.dat new file mode 100644 index 0000000..ac5de86 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test1 +Description += General test to see if vprintf works correctly diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test10/CMakeLists.txt new file mode 100644 index 0000000..debfd71 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_vprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test10 coreclrpal) + +target_link_libraries(paltest_vprintf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test10/test10.cpp new file mode 100644 index 0000000..b363d7c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test10/test10.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================================ +** +** Source: test10.c +** +** Purpose: Test #10 for the vprintf function. Tests the octal specifier +** (%o). +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %o", pos, "foo 52"); + DoNumTest("foo %lo", 0xFFFF, "foo 177777"); + DoNumTest("foo %ho", 0xFFFF, "foo 177777"); + DoNumTest("foo %Lo", pos, "foo 52"); + DoI64Test("foo %I64o", l, "42", "foo 52"); + DoNumTest("foo %3o", pos, "foo 52"); + DoNumTest("foo %-3o", pos, "foo 52 "); + DoNumTest("foo %.1o", pos, "foo 52"); + DoNumTest("foo %.3o", pos, "foo 052"); + DoNumTest("foo %03o", pos, "foo 052"); + DoNumTest("foo %#o", pos, "foo 052"); + DoNumTest("foo %+o", pos, "foo 52"); + DoNumTest("foo % o", pos, "foo 52"); + DoNumTest("foo %+o", neg, "foo 37777777726"); + DoNumTest("foo % o", neg, "foo 37777777726"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test10/testinfo.dat new file mode 100644 index 0000000..4494024 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test10/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test10 +Description += Tests vprintf with octal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test11/CMakeLists.txt new file mode 100644 index 0000000..55d59ef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_vprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test11 coreclrpal) + +target_link_libraries(paltest_vprintf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test11/test11.cpp new file mode 100644 index 0000000..f5157ac --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test11/test11.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test11.c +** +** Purpose: Test #11 for the vprintf function. Test the unsigned int +** specifier (%u). +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %u", pos, "foo 42"); + DoNumTest("foo %lu", 0xFFFF, "foo 65535"); + DoNumTest("foo %hu", 0xFFFF, "foo 65535"); + DoNumTest("foo %Lu", pos, "foo 42"); + DoI64Test("foo %I64u", l, "42", "foo 42"); + DoNumTest("foo %3u", pos, "foo 42"); + DoNumTest("foo %-3u", pos, "foo 42 "); + DoNumTest("foo %.1u", pos, "foo 42"); + DoNumTest("foo %.3u", pos, "foo 042"); + DoNumTest("foo %03u", pos, "foo 042"); + DoNumTest("foo %#u", pos, "foo 42"); + DoNumTest("foo %+u", pos, "foo 42"); + DoNumTest("foo % u", pos, "foo 42"); + DoNumTest("foo %+u", neg, "foo 4294967254"); + DoNumTest("foo % u", neg, "foo 4294967254"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test11/testinfo.dat new file mode 100644 index 0000000..c504c70 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test11/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test11 +Description += Tests vprintf with unsigned numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test12/CMakeLists.txt new file mode 100644 index 0000000..1211a7d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_vprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test12 coreclrpal) + +target_link_libraries(paltest_vprintf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test12/test12.cpp new file mode 100644 index 0000000..703a8c4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test12/test12.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Test #12 for the vprintf function. Tests the (lowercase) +** hexadecimal specifier (%x) +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %x", pos, "foo 1234ab"); + DoNumTest("foo %lx", pos, "foo 1234ab"); + DoNumTest("foo %hx", pos, "foo 34ab"); + DoNumTest("foo %Lx", pos, "foo 1234ab"); + DoI64Test("foo %I64x", l, "0x1234567887654321", + "foo 1234567887654321"); + DoNumTest("foo %7x", pos, "foo 1234ab"); + DoNumTest("foo %-7x", pos, "foo 1234ab "); + DoNumTest("foo %.1x", pos, "foo 1234ab"); + DoNumTest("foo %.7x", pos, "foo 01234ab"); + DoNumTest("foo %07x", pos, "foo 01234ab"); + DoNumTest("foo %#x", pos, "foo 0x1234ab"); + DoNumTest("foo %+x", pos, "foo 1234ab"); + DoNumTest("foo % x", pos, "foo 1234ab"); + DoNumTest("foo %+x", neg, "foo ffffffd6"); + DoNumTest("foo % x", neg, "foo ffffffd6"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test12/testinfo.dat new file mode 100644 index 0000000..558ce37 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test12/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test12 +Description += Tests vprintf with hex numbers (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test13/CMakeLists.txt new file mode 100644 index 0000000..0d7943d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_vprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test13 coreclrpal) + +target_link_libraries(paltest_vprintf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test13/test13.cpp new file mode 100644 index 0000000..ecb83ba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test13/test13.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test13.c +** +** Purpose: Test #13 for the vprintf function. Tests the (uppercase) +** hexadecimal specifier (%X) +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234AB; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %X", pos, "foo 1234AB"); + DoNumTest("foo %lX", pos, "foo 1234AB"); + DoNumTest("foo %hX", pos, "foo 34AB"); + DoNumTest("foo %LX", pos, "foo 1234AB"); + DoI64Test("foo %I64X", l, "0x1234567887654321", + "foo 1234567887654321"); + DoNumTest("foo %7X", pos, "foo 1234AB"); + DoNumTest("foo %-7X", pos, "foo 1234AB "); + DoNumTest("foo %.1X", pos, "foo 1234AB"); + DoNumTest("foo %.7X", pos, "foo 01234AB"); + DoNumTest("foo %07X", pos, "foo 01234AB"); + DoNumTest("foo %#X", pos, "foo 0X1234AB"); + DoNumTest("foo %+X", pos, "foo 1234AB"); + DoNumTest("foo % X", pos, "foo 1234AB"); + DoNumTest("foo %+X", neg, "foo FFFFFFD6"); + DoNumTest("foo % X", neg, "foo FFFFFFD6"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test13/testinfo.dat new file mode 100644 index 0000000..3382295 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test13/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test13 +Description += Tests vprintf with hex numbers (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test14/CMakeLists.txt new file mode 100644 index 0000000..abf5443 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_vprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test14 coreclrpal) + +target_link_libraries(paltest_vprintf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test14/test14.cpp new file mode 100644 index 0000000..536c195 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test14/test14.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test14.c +** +** Purpose: Test #14 for the vprintf function. Tests the lowercase +** exponential notation double specifier (%e) +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", + "foo 2.560000e+02 "); + DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02"); + DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", + "foo 2.56000000e+02"); + DoDoubleTest("foo %014e", val, "foo 02.560000e+002", + "foo 002.560000e+02"); + DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02"); + DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test14/testinfo.dat new file mode 100644 index 0000000..d2633fc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test14/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test14 +Description += Tests vprintf with exponential format doubles (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test15/CMakeLists.txt new file mode 100644 index 0000000..51e3c55 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_vprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test15 coreclrpal) + +target_link_libraries(paltest_vprintf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test15/test15.cpp new file mode 100644 index 0000000..9aff6e4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test15/test15.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test15.c +** +** Purpose: Test #15 for the vprintf function. Tests the uppercase +** exponential notation double specifier (%E) +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %14E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", + "foo 2.560000E+02 "); + DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02"); + DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", + "foo 2.56000000E+02"); + DoDoubleTest("foo %014E", val, "foo 02.560000E+002", + "foo 002.560000E+02"); + DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02"); + DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test15/testinfo.dat new file mode 100644 index 0000000..c1e0052 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test15/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test15 +Description += Tests vprintf with exponential format doubles (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test16/CMakeLists.txt new file mode 100644 index 0000000..54588ed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_vprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test16 coreclrpal) + +target_link_libraries(paltest_vprintf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test16/test16.cpp new file mode 100644 index 0000000..66e9afe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test16/test16.cpp @@ -0,0 +1,50 @@ +// 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. + +/*============================================================================ +** +** Source: test16.c +** +** Purpose: Test #16 for the vprintf function. Tests the decimal notation +** double specifier (%f) +** +** +**==========================================================================*/ + + +#include +#include "../vprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 "); + DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0"); + DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000"); + DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000"); + DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000"); + DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000"); + DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test16/testinfo.dat new file mode 100644 index 0000000..8b17d2f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test16/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test16 +Description += Tests vprintf with decimal point format doubles diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test17/CMakeLists.txt new file mode 100644 index 0000000..657a41c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_vprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test17 coreclrpal) + +target_link_libraries(paltest_vprintf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test17/test17.cpp new file mode 100644 index 0000000..d36a084 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test17/test17.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================================ +** +** Source: test17.c +** +** Purpose: Test #17 for the vprintf function. Tests the lowercase +** shorthand notation double specifier (%g) +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03"); + DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03"); + DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test17/testinfo.dat new file mode 100644 index 0000000..9f40fb0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test17/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test17 +Description += Tests vprintf with compact format doubles (lowercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test18/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test18/CMakeLists.txt new file mode 100644 index 0000000..d0ad8fc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test18/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test18.cpp +) + +add_executable(paltest_vprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test18 coreclrpal) + +target_link_libraries(paltest_vprintf_test18 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test18/test18.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test18/test18.cpp new file mode 100644 index 0000000..6fde79b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test18/test18.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test18.c +** +** Purpose: Test #18 for the vprintf function. Tests the uppercase +** shorthand notation double specifier (%G) +** +** +**==========================================================================*/ + + +#include +#include "../vprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoDoubleTest("foo %G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03"); + DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03"); + DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test18/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test18/testinfo.dat new file mode 100644 index 0000000..b41f8c6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test18/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test18 +Description += Tests vprintf with compact format doubles (uppercase) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test19/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test19/CMakeLists.txt new file mode 100644 index 0000000..f07d236 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test19/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test19.cpp +) + +add_executable(paltest_vprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test19 coreclrpal) + +target_link_libraries(paltest_vprintf_test19 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.cpp new file mode 100644 index 0000000..a3e0877 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.cpp @@ -0,0 +1,76 @@ +// 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. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose: Test #19 for the vprintf function. Tests the variable length +** precision argument. +** +** +**==========================================================================*/ + + +#include +#include "../vprintf.h" + + + + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoArgumentPrecTest("%.*s", 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest("%.*S", 2, (void*)convert("bar"), "bar", "ba", "ba"); + + DoArgumentPrecTest("%.*n", 3, (void*)&n, "pointer to int", "", ""); + if (n != 0) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + 0, n); + } + + DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test19/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test19/testinfo.dat new file mode 100644 index 0000000..03c3afa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test19/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test19 +Description += Tests vprintf with argument specified precision diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test2/CMakeLists.txt new file mode 100644 index 0000000..13edb26 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_vprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test2 coreclrpal) + +target_link_libraries(paltest_vprintf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test2/test2.cpp new file mode 100644 index 0000000..72b79e5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test2/test2.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Test #2 for the vprintf function. Tests the string specifier +** (%s). +** +** +**==========================================================================*/ + + +#include +#include "../vprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoStrTest("foo %s", "bar", "foo bar"); + DoStrTest("foo %hs", "bar", "foo bar"); + DoWStrTest("foo %ls", convert("bar"), "foo bar"); + DoWStrTest("foo %ws", convert("bar"), "foo bar"); + DoStrTest("foo %Ls", "bar", "foo bar"); + DoStrTest("foo %I64s", "bar", "foo bar"); + DoStrTest("foo %5s", "bar", "foo bar"); + DoStrTest("foo %.2s", "bar", "foo ba"); + DoStrTest("foo %5.2s", "bar", "foo ba"); + DoStrTest("foo %-5s", "bar", "foo bar "); + DoStrTest("foo %05s", "bar", "foo 00bar"); + DoStrTest("foo %s", NULL, "foo (null)"); + DoStrTest("foo %hs", NULL, "foo (null)"); + DoWStrTest("foo %ls", NULL, "foo (null)"); + DoWStrTest("foo %ws", NULL, "foo (null)"); + DoStrTest("foo %Ls", NULL, "foo (null)"); + DoStrTest("foo %I64s", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test2/testinfo.dat new file mode 100644 index 0000000..32c1d70 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test2 +Description += Tests vprintf with strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test3/CMakeLists.txt new file mode 100644 index 0000000..c704c2f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_vprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test3 coreclrpal) + +target_link_libraries(paltest_vprintf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test3/test3.cpp new file mode 100644 index 0000000..66cd509 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test3/test3.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Test #3 for the vprintf function. Tests the wide string +** specifier (%S). +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoWStrTest("foo %S", convert("bar"), "foo bar"); + DoStrTest("foo %hS", "bar", "foo bar"); + DoWStrTest("foo %lS", convert("bar"), "foo bar"); + DoWStrTest("foo %wS", convert("bar"), "foo bar"); + DoWStrTest("foo %LS", convert("bar"), "foo bar"); + DoWStrTest("foo %I64S", convert("bar"), "foo bar"); + DoWStrTest("foo %5S", convert("bar"), "foo bar"); + DoWStrTest("foo %.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %5.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %-5S", convert("bar"), "foo bar "); + DoWStrTest("foo %05S", convert("bar"), "foo 00bar"); + DoWStrTest("foo %S", NULL, "foo (null)"); + DoStrTest("foo %hS", NULL, "foo (null)"); + DoWStrTest("foo %lS", NULL, "foo (null)"); + DoWStrTest("foo %wS", NULL, "foo (null)"); + DoWStrTest("foo %LS", NULL, "foo (null)"); + DoWStrTest("foo %I64S", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test3/testinfo.dat new file mode 100644 index 0000000..c3b385e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test3 +Description += Tests vprintf with wide strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test4/CMakeLists.txt new file mode 100644 index 0000000..fdb5acd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_vprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test4 coreclrpal) + +target_link_libraries(paltest_vprintf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test4/test4.cpp new file mode 100644 index 0000000..2469cb5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test4/test4.cpp @@ -0,0 +1,70 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Test #4 for the vprintf function. Tests the pointer +** specifier (%p). +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + + + + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "0000000000000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); + +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "00000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); + +#endif + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test4/testinfo.dat new file mode 100644 index 0000000..74c4ce9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test4/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test4 +Description += Tests vprintf with pointers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test5/CMakeLists.txt new file mode 100644 index 0000000..13c660c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_vprintf_test5 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test5 coreclrpal) + +target_link_libraries(paltest_vprintf_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test5/test5.cpp new file mode 100644 index 0000000..c9e2901 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test5/test5.cpp @@ -0,0 +1,60 @@ +// 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. + +/*============================================================================ +** +** Source: test5.c +** +** Purpose: Test #5 for the vprintf function. Tests the count specifier (%n). +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + + + + +int __cdecl main(int argc, char *argv[]) +{ + char *longStr = + "really-long-string-that-just-keeps-going-on-and-on-and-on.." + "..................useless-filler.................................." + "..................useless-filler.................................." + "..................useless-filler.................................." + "%n bar"; + char *longResult = + "really-long-string-that-just-keeps-going-on-and-on-and-on.." + "..................useless-filler.................................." + "..................useless-filler.................................." + "..................useless-filler.................................." + " bar"; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoCountTest("foo %n bar", 4, "foo bar"); + DoCountTest(longStr, 257, longResult); + DoCountTest("fo%n bar", 2, "fo bar"); + DoCountTest("%n", 0, ""); + DoCountTest("foo %#n bar", 4, "foo bar"); + DoCountTest("foo % n bar", 4, "foo bar"); + DoCountTest("foo %+n bar", 4, "foo bar"); + DoCountTest("foo %-n bar", 4, "foo bar"); + DoCountTest("foo %0n bar", 4, "foo bar"); + DoShortCountTest("foo %hn bar", 4, "foo bar"); + DoCountTest("foo %ln bar", 4, "foo bar"); + DoCountTest("foo %Ln bar", 4, "foo bar"); + DoCountTest("foo %I64n bar", 4, "foo bar"); + DoCountTest("foo %20.3n bar", 4, "foo bar"); + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test5/testinfo.dat new file mode 100644 index 0000000..01ff864 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test5/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test5 +Description += Tests vprintf with the count specifier diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test6/CMakeLists.txt new file mode 100644 index 0000000..df9ec19 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_vprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test6 coreclrpal) + +target_link_libraries(paltest_vprintf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test6/test6.cpp new file mode 100644 index 0000000..6a83ccc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test6/test6.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose: Test #6 for the vprintf function. Tests the char specifier (%c). +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoCharTest("foo %c", 'b', "foo b"); + DoCharTest("foo %hc", 'b', "foo b"); + DoWCharTest("foo %lc", wc, "foo c"); + DoCharTest("foo %Lc", 'b', "foo b"); + DoCharTest("foo %I64c", 'b', "foo b"); + DoCharTest("foo %5c", 'b', "foo b"); + DoCharTest("foo %.0c", 'b', "foo b"); + DoCharTest("foo %-5c", 'b', "foo b "); + DoCharTest("foo %05c", 'b', "foo 0000b"); + DoCharTest("foo % c", 'b', "foo b"); + DoCharTest("foo %#c", 'b', "foo b"); + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test6/testinfo.dat new file mode 100644 index 0000000..ce45018 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test6/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test6 +Description += Tests vprintf with characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test7/CMakeLists.txt new file mode 100644 index 0000000..d0086a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_vprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test7 coreclrpal) + +target_link_libraries(paltest_vprintf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test7/test7.cpp new file mode 100644 index 0000000..5096ace --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test7/test7.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test7.c +** +** Purpose: Test #7 for the vprintf function. Tests the wide char +** specifier (%C). +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wb = (WCHAR) 'b'; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoWCharTest("foo %C", wb, "foo b"); + DoWCharTest("foo %hC", wb, "foo b"); + DoCharTest("foo %lC", 'c', "foo c"); + DoWCharTest("foo %LC", wb, "foo b"); + DoWCharTest("foo %I64C", wb, "foo b"); + DoWCharTest("foo %5C", wb, "foo b"); + DoWCharTest("foo %.0C", wb, "foo b"); + DoWCharTest("foo %-5C", wb, "foo b "); + DoWCharTest("foo %05C", wb, "foo 0000b"); + DoWCharTest("foo % C", wb, "foo b"); + DoWCharTest("foo %#C", wb, "foo b"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test7/testinfo.dat new file mode 100644 index 0000000..254e31e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test7/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test7 +Description += Tests vprintf with wide characters diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test8/CMakeLists.txt new file mode 100644 index 0000000..c47e2cf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_vprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test8 coreclrpal) + +target_link_libraries(paltest_vprintf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test8/test8.cpp new file mode 100644 index 0000000..2683339 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test8/test8.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test8.c +** +** Purpose: Test #8 for the vprintf function. Tests the decimal +** specifier (%d). +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %d", pos, "foo 42"); + DoNumTest("foo %ld", 0xFFFF, "foo 65535"); + DoNumTest("foo %hd", 0xFFFF, "foo -1"); + DoNumTest("foo %Ld", pos, "foo 42"); + DoI64Test("foo %I64d", l, "42", "foo 42"); + DoNumTest("foo %3d", pos, "foo 42"); + DoNumTest("foo %-3d", pos, "foo 42 "); + DoNumTest("foo %.1d", pos, "foo 42"); + DoNumTest("foo %.3d", pos, "foo 042"); + DoNumTest("foo %03d", pos, "foo 042"); + DoNumTest("foo %#d", pos, "foo 42"); + DoNumTest("foo %+d", pos, "foo +42"); + DoNumTest("foo % d", pos, "foo 42"); + DoNumTest("foo %+d", neg, "foo -42"); + DoNumTest("foo % d", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test8/testinfo.dat new file mode 100644 index 0000000..73f287b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test8/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test8 +Description += Tests vprintf with decimal numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test9/CMakeLists.txt new file mode 100644 index 0000000..521e354 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_vprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_vprintf_test9 coreclrpal) + +target_link_libraries(paltest_vprintf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test9/test9.cpp new file mode 100644 index 0000000..8545bc7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test9/test9.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================================ +** +** Source: test9.c +** +** Purpose: Test #9 for the vprintf function. Tests the integer +** specifier (%i). +** +** +**==========================================================================*/ + + + +#include +#include "../vprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoNumTest("foo %i", pos, "foo 42"); + DoNumTest("foo %li", 0xFFFF, "foo 65535"); + DoNumTest("foo %hi", 0xFFFF, "foo -1"); + DoNumTest("foo %Li", pos, "foo 42"); + DoI64Test("foo %I64i", l, "42", "foo 42"); + DoNumTest("foo %3i", pos, "foo 42"); + DoNumTest("foo %-3i", pos, "foo 42 "); + DoNumTest("foo %.1i", pos, "foo 42"); + DoNumTest("foo %.3i", pos, "foo 042"); + DoNumTest("foo %03i", pos, "foo 042"); + DoNumTest("foo %#i", pos, "foo 42"); + DoNumTest("foo %+i", pos, "foo +42"); + DoNumTest("foo % i", pos, "foo 42"); + DoNumTest("foo %+i", neg, "foo -42"); + DoNumTest("foo % i", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test9/testinfo.dat new file mode 100644 index 0000000..c4c77b9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/test9/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = vprintf +Name = Positive Test for vprintf +TYPE = DEFAULT +EXE1 = test9 +Description += Tests vprintf with integer numbers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/vprintf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/vprintf.h new file mode 100644 index 0000000..fcd8f80 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vprintf/vprintf.h @@ -0,0 +1,193 @@ +// 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. + +/*============================================================================ +** +** Source: vprintf.h +** +** Purpose: Containts common testing functions for vprintf +** +** +**==========================================================================*/ + +#ifndef __vprintf_H__ +#define __vprintf_H__ + +int DoVprintf(const char *format, ...) +{ + int retVal; + va_list arglist; + + va_start(arglist, format); + retVal = vprintf(format, arglist); + va_end(arglist); + + return (retVal); +} + +void DoStrTest(const char *formatstr, char* param, const char *checkstr) +{ + int ret; + + ret = DoVprintf(formatstr, param); + if (ret != strlen(checkstr)) + { + Fail("Expected vprintf to return %d, got %d.\n", + strlen(checkstr), ret); + } +} + +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) +{ + int ret; + + ret = DoVprintf(formatstr, param); + if (ret != strlen(checkstr)) + { + Fail("Expected vprintf to return %d, got %d.\n", + strlen(checkstr), ret); + } +} + +void DoPointerTest(const char *formatstr, void* param, char* paramstr, + const char *checkstr1) +{ + int ret; + + ret = DoVprintf(formatstr, param); + if (ret != strlen(checkstr1)) + { + Fail("Expected vprintf to return %d, got %d.\n", + strlen(checkstr1), ret); + } +} + +void DoCountTest(const char *formatstr, int param, const char *checkstr) +{ + int ret; + int n = -1; + + ret = DoVprintf(formatstr, &n); + + if (n != param) + { + Fail("Expected count parameter to resolve to %d, got %d\n", param, n); + } + + if (ret != strlen(checkstr)) + { + Fail("Expected vprintf to return %d, got %d.\n", + strlen(checkstr), ret); + } +} + +void DoShortCountTest(const char *formatstr, int param, const char *checkstr) +{ + int ret; + short int n = -1; + + ret = DoVprintf(formatstr, &n); + + if (n != param) + { + Fail("Expected count parameter to resolve to %d, got %d\n", param, n); + } + + if (ret != strlen(checkstr)) + { + Fail("Expected vprintf to return %d, got %d.\n", + strlen(checkstr), ret); + } +} + + +void DoCharTest(const char *formatstr, char param, const char *checkstr) +{ + int ret; + + ret = DoVprintf(formatstr, param); + if (ret != strlen(checkstr)) + { + Fail("Expected vprintf to return %d, got %d.\n", + strlen(checkstr), ret); + } +} + +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) +{ + int ret; + + ret = DoVprintf(formatstr, param); + if (ret != strlen(checkstr)) + { + Fail("Expected vprintf to return %d, got %d.\n", + strlen(checkstr), ret); + } +} + +void DoNumTest(const char *formatstr, int param, const char *checkstr) +{ + int ret; + + ret = DoVprintf(formatstr, param); + if (ret != strlen(checkstr)) + { + Fail("Expected vprintf to return %d, got %d.\n", + strlen(checkstr), ret); + } +} + +void DoI64Test(const char *formatstr, INT64 param, char *valuestr, const char *checkstr1) +{ + int ret; + + ret = DoVprintf(formatstr, param); + if (ret != strlen(checkstr1)) + { + Fail("Expected vprintf to return %d, got %d.\n", + strlen(checkstr1), ret); + } +} + +void DoDoubleTest(const char *formatstr, double param, const char *checkstr1, + const char *checkstr2) +{ + int ret; + + ret = DoVprintf(formatstr, param); + if (ret != strlen(checkstr1) && ret != strlen(checkstr2)) + { + Fail("Expected vprintf to return %d or %d, got %d.\n", + strlen(checkstr1), strlen(checkstr2), ret); + } +} + +void DoArgumentPrecTest(const char *formatstr, int precision, void *param, + char *paramstr, const char *checkstr1, const char *checkstr2) +{ + int ret; + + ret = DoVprintf(formatstr, precision, param); + if (ret != strlen(checkstr1) && ret != strlen(checkstr2)) + { + Fail("Expected vprintf to return %d or %d, got %d.\n", + strlen(checkstr1), strlen(checkstr2), ret); + } +} + +void DoArgumentPrecDoubleTest(const char *formatstr, int precision, double param, + const char *checkstr1, const char *checkstr2) +{ + int ret; + + ret = DoVprintf(formatstr, precision, param); + if (ret != strlen(checkstr1) && ret != strlen(checkstr2)) + { + Fail("Expected vprintf to return %d or %d, got %d.\n", + strlen(checkstr1), strlen(checkstr2), ret); + } +} + +#endif + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/CMakeLists.txt new file mode 100644 index 0000000..b29c7c4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/CMakeLists.txt @@ -0,0 +1,19 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test1/CMakeLists.txt new file mode 100644 index 0000000..cc1afb7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_vsprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test1 coreclrpal) + +target_link_libraries(paltest_vsprintf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test1/test1.cpp new file mode 100644 index 0000000..18c8c0e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test1/test1.cpp @@ -0,0 +1,55 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Test #1 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + char checkstr[] = "hello world"; + char buf[256] = { 0 }; + int ret; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + testvsp(buf, _countof(buf), "hello world"); + + if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0) + { + Fail("ERROR: expected \"%s\" (up to %d chars), got \"%s\"\n", + checkstr, 256, buf); + } + + testvsp(buf, _countof(buf), "xxxxxxxxxxxxxxxxx"); + ret = testvsp(buf, _countof(buf), "hello world"); + + if (ret != strlen(checkstr)) + { + Fail("ERROR: expected negative return value, got %d", ret); + } + + if (memcmp(checkstr, buf, ret) != 0) + { + Fail("ERROR: expected %s, got %s\n", checkstr, buf); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test1/testinfo.dat new file mode 100644 index 0000000..996364f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the vsprintf function. += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test10/CMakeLists.txt new file mode 100644 index 0000000..2ef1be6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_vsprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test10 coreclrpal) + +target_link_libraries(paltest_vsprintf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test10/test10.cpp new file mode 100644 index 0000000..791213f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test10/test10.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test10.c +** +** Purpose: Test #10 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest("foo %o", pos, "foo 52"); + DoNumTest("foo %lo", 0xFFFF, "foo 177777"); + DoNumTest("foo %ho", 0xFFFF, "foo 177777"); + DoNumTest("foo %Lo", pos, "foo 52"); + DoI64Test("foo %I64o", l, "42", "foo 52"); + DoNumTest("foo %3o", pos, "foo 52"); + DoNumTest("foo %-3o", pos, "foo 52 "); + DoNumTest("foo %.1o", pos, "foo 52"); + DoNumTest("foo %.3o", pos, "foo 052"); + DoNumTest("foo %03o", pos, "foo 052"); + DoNumTest("foo %#o", pos, "foo 052"); + DoNumTest("foo %+o", pos, "foo 52"); + DoNumTest("foo % o", pos, "foo 52"); + DoNumTest("foo %+o", neg, "foo 37777777726"); + DoNumTest("foo % o", neg, "foo 37777777726"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test10/testinfo.dat new file mode 100644 index 0000000..1a1f4ef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test10/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test10 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with octal numbers. += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test11/CMakeLists.txt new file mode 100644 index 0000000..8082540 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_vsprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test11 coreclrpal) + +target_link_libraries(paltest_vsprintf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test11/test11.cpp new file mode 100644 index 0000000..e0af949 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test11/test11.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test11.c +** +** Purpose: Test #11 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest("foo %u", pos, "foo 42"); + DoNumTest("foo %lu", 0xFFFF, "foo 65535"); + DoNumTest("foo %hu", 0xFFFF, "foo 65535"); + DoNumTest("foo %Lu", pos, "foo 42"); + DoI64Test("foo %I64u", l, "42", "foo 42"); + DoNumTest("foo %3u", pos, "foo 42"); + DoNumTest("foo %-3u", pos, "foo 42 "); + DoNumTest("foo %.1u", pos, "foo 42"); + DoNumTest("foo %.3u", pos, "foo 042"); + DoNumTest("foo %03u", pos, "foo 042"); + DoNumTest("foo %#u", pos, "foo 42"); + DoNumTest("foo %+u", pos, "foo 42"); + DoNumTest("foo % u", pos, "foo 42"); + DoNumTest("foo %+u", neg, "foo 4294967254"); + DoNumTest("foo % u", neg, "foo 4294967254"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test11/testinfo.dat new file mode 100644 index 0000000..d44167e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test11/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test11 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with unsigned numbers. += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test12/CMakeLists.txt new file mode 100644 index 0000000..4f84c43 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_vsprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test12 coreclrpal) + +target_link_libraries(paltest_vsprintf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test12/test12.cpp new file mode 100644 index 0000000..f86ddca --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test12/test12.cpp @@ -0,0 +1,52 @@ +// 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. + +/*===================================================================== +** +** Source: test12.c +** +** Purpose: Test #12 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return (FAIL); + } + + DoNumTest("foo %x", pos, "foo 1234ab"); + DoNumTest("foo %lx", pos, "foo 1234ab"); + DoNumTest("foo %hx", pos, "foo 34ab"); + DoNumTest("foo %Lx", pos, "foo 1234ab"); + DoI64Test("foo %I64x", l, "0x1234567887654321", + "foo 1234567887654321"); + DoNumTest("foo %7x", pos, "foo 1234ab"); + DoNumTest("foo %-7x", pos, "foo 1234ab "); + DoNumTest("foo %.1x", pos, "foo 1234ab"); + DoNumTest("foo %.7x", pos, "foo 01234ab"); + DoNumTest("foo %07x", pos, "foo 01234ab"); + DoNumTest("foo %#x", pos, "foo 0x1234ab"); + DoNumTest("foo %+x", pos, "foo 1234ab"); + DoNumTest("foo % x", pos, "foo 1234ab"); + DoNumTest("foo %+x", neg, "foo ffffffd6"); + DoNumTest("foo % x", neg, "foo ffffffd6"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test12/testinfo.dat new file mode 100644 index 0000000..781fb9c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test12/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test12 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with hex numbers (lowercase). += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test13/CMakeLists.txt new file mode 100644 index 0000000..53779dc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_vsprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test13 coreclrpal) + +target_link_libraries(paltest_vsprintf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test13/test13.cpp new file mode 100644 index 0000000..36e7825 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test13/test13.cpp @@ -0,0 +1,52 @@ +// 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. + +/*===================================================================== +** +** Source: test13.c +** +** Purpose: Test #13 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234AB; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest("foo %X", pos, "foo 1234AB"); + DoNumTest("foo %lX", pos, "foo 1234AB"); + DoNumTest("foo %hX", pos, "foo 34AB"); + DoNumTest("foo %LX", pos, "foo 1234AB"); + DoI64Test("foo %I64X", l, "0x1234567887654321", + "foo 1234567887654321"); + DoNumTest("foo %7X", pos, "foo 1234AB"); + DoNumTest("foo %-7X", pos, "foo 1234AB "); + DoNumTest("foo %.1X", pos, "foo 1234AB"); + DoNumTest("foo %.7X", pos, "foo 01234AB"); + DoNumTest("foo %07X", pos, "foo 01234AB"); + DoNumTest("foo %#X", pos, "foo 0X1234AB"); + DoNumTest("foo %+X", pos, "foo 1234AB"); + DoNumTest("foo % X", pos, "foo 1234AB"); + DoNumTest("foo %+X", neg, "foo FFFFFFD6"); + DoNumTest("foo % X", neg, "foo FFFFFFD6"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test13/testinfo.dat new file mode 100644 index 0000000..7b28a91 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test13/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test13 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with hex numbers (uppercase). += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test14/CMakeLists.txt new file mode 100644 index 0000000..d08d606 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_vsprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test14 coreclrpal) + +target_link_libraries(paltest_vsprintf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test14/test14.cpp new file mode 100644 index 0000000..360fafc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test14/test14.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test14.c +** +** Purpose: Test #14 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", "foo 2.560000e+02 "); + DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02"); + DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", "foo 2.56000000e+02"); + DoDoubleTest("foo %014e", val, "foo 02.560000e+002", "foo 002.560000e+02"); + DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02"); + DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test14/testinfo.dat new file mode 100644 index 0000000..a093409 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test14/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test14 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with exponential format doubles (lowercase). += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test15/CMakeLists.txt new file mode 100644 index 0000000..f45c768 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_vsprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test15 coreclrpal) + +target_link_libraries(paltest_vsprintf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test15/test15.cpp new file mode 100644 index 0000000..a5b4c94 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test15/test15.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. + +/*===================================================================== +** +** Source: test15.c +** +** Purpose: Test #15 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest("foo %E", val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest("foo %lE", val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest("foo %hE", val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest("foo %LE", val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest("foo %14E", val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", + "foo 2.560000E+02 "); + DoDoubleTest("foo %.1E", val, "foo 2.6E+002", + "foo 2.6E+02"); + DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", + "foo 2.56000000E+02"); + DoDoubleTest("foo %014E", val, "foo 02.560000E+002", + "foo 002.560000E+02"); + DoDoubleTest("foo %#E", val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest("foo %+E", val, "foo +2.560000E+002", + "foo +2.560000E+02"); + DoDoubleTest("foo % E", val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", + "foo -2.560000E+02"); + DoDoubleTest("foo % E", neg, "foo -2.560000E+002", + "foo -2.560000E+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test15/testinfo.dat new file mode 100644 index 0000000..c3b8ebd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test15/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test15 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with exponential format doubles (uppercase). += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test16/CMakeLists.txt new file mode 100644 index 0000000..c80de47 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_vsprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test16 coreclrpal) + +target_link_libraries(paltest_vsprintf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test16/test16.cpp new file mode 100644 index 0000000..a7258db --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test16/test16.cpp @@ -0,0 +1,49 @@ +// 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. + +/*===================================================================== +** +** Source: test16.c +** +** Purpose: Test #16 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 "); + DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0"); + DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000"); + DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000"); + DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000"); + DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000"); + DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test16/testinfo.dat new file mode 100644 index 0000000..d29634e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test16/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test16 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with decimal point format doubles. += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test17/CMakeLists.txt new file mode 100644 index 0000000..6eceb5b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_vsprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test17 coreclrpal) + +target_link_libraries(paltest_vsprintf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test17/test17.cpp new file mode 100644 index 0000000..0ad246a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test17/test17.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test17.c +** +** Purpose: Test #17 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest("foo %g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03"); + DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03"); + DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test17/testinfo.dat new file mode 100644 index 0000000..0dcd3c8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test17/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test17 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with compact format doubles (lowercase). += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test18/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test18/CMakeLists.txt new file mode 100644 index 0000000..2fd06bc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test18/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test18.cpp +) + +add_executable(paltest_vsprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test18 coreclrpal) + +target_link_libraries(paltest_vsprintf_test18 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test18/test18.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test18/test18.cpp new file mode 100644 index 0000000..9a45305 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test18/test18.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test18.c +** +** Purpose: Test #18 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest("foo %G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03"); + DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03"); + DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test18/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test18/testinfo.dat new file mode 100644 index 0000000..4329996 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test18/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test18 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with compact format doubles (uppercase). += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test19/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test19/CMakeLists.txt new file mode 100644 index 0000000..ed09206 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test19/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test19.cpp +) + +add_executable(paltest_vsprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test19 coreclrpal) + +target_link_libraries(paltest_vsprintf_test19 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.cpp new file mode 100644 index 0000000..698ff36 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.cpp @@ -0,0 +1,67 @@ +// 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. + +/*===================================================================== +** +** Source: test19.c +** +** Purpose: Test #19 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + + DoArgumentPrecTest("%.*s", 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest("%.*S", 2, (void*)convert("bar"), "bar", "ba", "ba"); + DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test19/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test19/testinfo.dat new file mode 100644 index 0000000..1e7bc76 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test19/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test19 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with argument specified precision. += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test2/CMakeLists.txt new file mode 100644 index 0000000..ccc24cd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_vsprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test2 coreclrpal) + +target_link_libraries(paltest_vsprintf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test2/test2.cpp new file mode 100644 index 0000000..fc9163e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test2/test2.cpp @@ -0,0 +1,48 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Test #2 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoStrTest("foo %s", "bar", "foo bar"); + DoStrTest("foo %hs", "bar", "foo bar"); + DoWStrTest("foo %ls", convert("bar"), "foo bar"); + DoWStrTest("foo %ws", convert("bar"), "foo bar"); + DoStrTest("foo %Ls", "bar", "foo bar"); + DoStrTest("foo %I64s", "bar", "foo bar"); + DoStrTest("foo %5s", "bar", "foo bar"); + DoStrTest("foo %.2s", "bar", "foo ba"); + DoStrTest("foo %5.2s", "bar", "foo ba"); + DoStrTest("foo %-5s", "bar", "foo bar "); + DoStrTest("foo %05s", "bar", "foo 00bar"); + DoStrTest("foo %s", NULL, "foo (null)"); + DoStrTest("foo %hs", NULL, "foo (null)"); + DoWStrTest("foo %ls", NULL, "foo (null)"); + DoWStrTest("foo %ws", NULL, "foo (null)"); + DoStrTest("foo %Ls", NULL, "foo (null)"); + DoStrTest("foo %I64s", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test2/testinfo.dat new file mode 100644 index 0000000..7958c1a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test2 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with strings. += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test3/CMakeLists.txt new file mode 100644 index 0000000..1643677 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_vsprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test3 coreclrpal) + +target_link_libraries(paltest_vsprintf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test3/test3.cpp new file mode 100644 index 0000000..4656bf3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test3/test3.cpp @@ -0,0 +1,49 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Test #3 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoWStrTest("foo %S", convert("bar"), "foo bar"); + DoStrTest("foo %hS", "bar", "foo bar"); + DoWStrTest("foo %lS", convert("bar"), "foo bar"); + DoWStrTest("foo %wS", convert("bar"), "foo bar"); + DoWStrTest("foo %LS", convert("bar"), "foo bar"); + DoWStrTest("foo %I64S", convert("bar"), "foo bar"); + DoWStrTest("foo %5S", convert("bar"), "foo bar"); + DoWStrTest("foo %.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %5.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %-5S", convert("bar"), "foo bar "); + DoWStrTest("foo %05S", convert("bar"), "foo 00bar"); + DoWStrTest("foo %S", NULL, "foo (null)"); + DoStrTest("foo %hS", NULL, "foo (null)"); + DoWStrTest("foo %lS", NULL, "foo (null)"); + DoWStrTest("foo %wS", NULL, "foo (null)"); + DoWStrTest("foo %LS", NULL, "foo (null)"); + DoWStrTest("foo %I64S", NULL, "foo (null)"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test3/testinfo.dat new file mode 100644 index 0000000..afeb7da --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test3 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with wide strings. += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test4/CMakeLists.txt new file mode 100644 index 0000000..b53a17b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_vsprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test4 coreclrpal) + +target_link_libraries(paltest_vsprintf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test4/test4.cpp new file mode 100644 index 0000000..513b0dd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test4/test4.cpp @@ -0,0 +1,72 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c +** +** Purpose: Test #4 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "0000000000000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64DoubleTest("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "00000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64DoubleTest("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); +#endif + + + + + + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test4/testinfo.dat new file mode 100644 index 0000000..7331c20 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test4/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test4 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with pointers. += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test6/CMakeLists.txt new file mode 100644 index 0000000..3e2d95a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_vsprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test6 coreclrpal) + +target_link_libraries(paltest_vsprintf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test6/test6.cpp new file mode 100644 index 0000000..0d38a3a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test6/test6.cpp @@ -0,0 +1,44 @@ +// 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. + +/*===================================================================== +** +** Source: test6.c +** +** Purpose: Test #6 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoCharTest("foo %c", 'b', "foo b"); + DoCharTest("foo %hc", 'b', "foo b"); + DoWCharTest("foo %lc", wc, "foo c"); + DoCharTest("foo %Lc", 'b', "foo b"); + DoCharTest("foo %I64c", 'b', "foo b"); + DoCharTest("foo %5c", 'b', "foo b"); + DoCharTest("foo %.0c", 'b', "foo b"); + DoCharTest("foo %-5c", 'b', "foo b "); + DoCharTest("foo %05c", 'b', "foo 0000b"); + DoCharTest("foo % c", 'b', "foo b"); + DoCharTest("foo %#c", 'b', "foo b"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test6/testinfo.dat new file mode 100644 index 0000000..d76c5bf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test6/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test6 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with characters. += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test7/CMakeLists.txt new file mode 100644 index 0000000..740a1dc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_vsprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test7 coreclrpal) + +target_link_libraries(paltest_vsprintf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test7/test7.cpp new file mode 100644 index 0000000..c9f87d4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test7/test7.cpp @@ -0,0 +1,44 @@ +// 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. + +/*===================================================================== +** +** Source: test7.c +** +** Purpose: Test #7 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wb = (WCHAR) 'b'; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoWCharTest("foo %c", wb, "foo b"); + DoWCharTest("foo %hc", wb, "foo b"); + DoCharTest("foo %lc", 'c', "foo c"); + DoWCharTest("foo %Lc", wb, "foo b"); + DoWCharTest("foo %I64c", wb, "foo b"); + DoWCharTest("foo %5c", wb, "foo b"); + DoWCharTest("foo %.0c", wb, "foo b"); + DoWCharTest("foo %-5c", wb, "foo b "); + DoWCharTest("foo %05c", wb, "foo 0000b"); + DoWCharTest("foo % c", wb, "foo b"); + DoWCharTest("foo %#c", wb, "foo b"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test7/testinfo.dat new file mode 100644 index 0000000..facf60d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test7/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test7 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with wide characters. += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test8/CMakeLists.txt new file mode 100644 index 0000000..455311c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_vsprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test8 coreclrpal) + +target_link_libraries(paltest_vsprintf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test8/test8.cpp new file mode 100644 index 0000000..e741d1d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test8/test8.cpp @@ -0,0 +1,52 @@ +// 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. + +/*===================================================================== +** +** Source: test8.c +** +** Purpose: Test #8 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest("foo %d", pos, "foo 42"); + DoNumTest("foo %ld", 0xFFFF, "foo 65535"); + DoNumTest("foo %hd", 0xFFFF, "foo -1"); + DoNumTest("foo %Ld", pos, "foo 42"); + DoI64Test("foo %I64d", l, "42", "foo 42"); + DoNumTest("foo %3d", pos, "foo 42"); + DoNumTest("foo %-3d", pos, "foo 42 "); + DoNumTest("foo %.1d", pos, "foo 42"); + DoNumTest("foo %.3d", pos, "foo 042"); + DoNumTest("foo %03d", pos, "foo 042"); + DoNumTest("foo %#d", pos, "foo 42"); + DoNumTest("foo %+d", pos, "foo +42"); + DoNumTest("foo % d", pos, "foo 42"); + DoNumTest("foo %+d", neg, "foo -42"); + DoNumTest("foo % d", neg, "foo -42"); + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test8/testinfo.dat new file mode 100644 index 0000000..05f84f4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test8/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test8 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with decimal numbers. += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test9/CMakeLists.txt new file mode 100644 index 0000000..7c5fc6c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_vsprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_vsprintf_test9 coreclrpal) + +target_link_libraries(paltest_vsprintf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test9/test9.cpp new file mode 100644 index 0000000..e1f7c84 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test9/test9.cpp @@ -0,0 +1,51 @@ +// 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. + +/*===================================================================== +** +** Source: test9.c +** +** Purpose: Test #9 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest("foo %i", pos, "foo 42"); + DoNumTest("foo %li", 0xFFFF, "foo 65535"); + DoNumTest("foo %hi", 0xFFFF, "foo -1"); + DoNumTest("foo %Li", pos, "foo 42"); + DoI64Test("foo %I64i", l, "42", "foo 42"); + DoNumTest("foo %3i", pos, "foo 42"); + DoNumTest("foo %-3i", pos, "foo 42 "); + DoNumTest("foo %.1i", pos, "foo 42"); + DoNumTest("foo %.3i", pos, "foo 042"); + DoNumTest("foo %03i", pos, "foo 042"); + DoNumTest("foo %#i", pos, "foo 42"); + DoNumTest("foo %+i", pos, "foo +42"); + DoNumTest("foo % i", pos, "foo 42"); + DoNumTest("foo %+i", neg, "foo -42"); + DoNumTest("foo % i", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test9/testinfo.dat new file mode 100644 index 0000000..3bc0057 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/test9/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vsprintf +Name = Positive Test for vsprintf +TYPE = DEFAULT +EXE1 = test9 +Description += Tests the PAL implementation of the vsprintf function. += Tests vsprintf with integer numbers. += This test is modeled after _snprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/vsprintf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/vsprintf.h new file mode 100644 index 0000000..d027562 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vsprintf/vsprintf.h @@ -0,0 +1,218 @@ +// 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. + +/*===================================================================== +** +** Source: vsprintf.h +** +** Purpose: Helper functions for the vsprintf tests. +** +** +**===================================================================*/ +#ifndef __VSPRINTF_H__ +#define __VSPRINTF_H__ + +/* These functions leaks memory a lot. C'est la vie. */ +int testvsp(char* buf, size_t buffSize, const char* format, ...) +{ + int retVal; + va_list arglist; + + va_start(arglist, format); + retVal = _vsnprintf_s(buf, buffSize, _TRUNCATE, format, arglist); + va_end(arglist); + + return (retVal); +} + +void DoStrTest(const char *formatstr, char* param, const char *checkstr) +{ + char buf[256] = { 0 }; + + testvsp(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, formatstr, checkstr, buf); + } +} + +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) +{ + char buf[256] = { 0 }; + + testvsp(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + convertC(param), formatstr, checkstr, buf); + } +} + + +void DoCharTest(const char *formatstr, char param, const char *checkstr) +{ + char buf[256] = { 0 }; + + testvsp(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, param, formatstr, checkstr, buf); + } +} + +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) +{ + char buf[256] = { 0 }; + + testvsp(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + (char)param, param, formatstr, checkstr, buf); + } +} + +void DoNumTest(const char *formatstr, int value, const char *checkstr) +{ + char buf[256] = { 0 }; + + testvsp(buf, _countof(buf), formatstr, value); + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert %#x into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + value, formatstr, checkstr, buf); + } +} + +void DoI64Test(const char *formatstr, INT64 value, char *valuestr, const char *checkstr) +{ + char buf[256] = { 0 }; + + testvsp(buf, _countof(buf), formatstr, value); + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + valuestr, formatstr, checkstr, buf); + } +} +void DoDoubleTest(const char *formatstr, double value, const char *checkstr1, char +*checkstr2) +{ + char buf[256] = { 0 }; + + testvsp(buf, _countof(buf), formatstr, value); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + value, formatstr, checkstr1, checkstr2, buf); + } +} +/*FROM TEST 9*/ +void DoArgumentPrecTest(const char *formatstr, int precision, void *param, + char *paramstr, const char *checkstr1, const char *checkstr2) +{ + char buf[256]; + + testvsp(buf, _countof(buf), formatstr, precision, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", paramstr, formatstr, + precision, checkstr1, checkstr2, buf); + } + +} + +void DoArgumentPrecDoubleTest(const char *formatstr, int precision, double param, + const char *checkstr1, const char *checkstr2) +{ + char buf[256]; + + testvsp(buf, _countof(buf), formatstr, precision, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", param, formatstr, + precision, checkstr1, checkstr2, buf); + } +} +/*FROM TEST4*/ +void DoPointerTest(const char *formatstr, void* param, char* paramstr, + const char *checkstr1) +{ + char buf[256] = { 0 }; + + testvsp(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1)) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + paramstr, formatstr, checkstr1, buf); + } +} + +void DoI64DoubleTest(const char *formatstr, INT64 value, char *valuestr, + const char *checkstr1) +{ + char buf[256] = { 0 }; + + testvsp(buf, _countof(buf), formatstr, value); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", + valuestr, formatstr, checkstr1, buf); + } +} + +void DoTest(const char *formatstr, int param, const char *checkstr) +{ + char buf[256] = { 0 }; + int n = -1; + + testvsp(buf, _countof(buf), formatstr, &n); + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } +} + +void DoShortTest(const char *formatstr, int param, const char *checkstr) +{ + char buf[256] = { 0 }; + short int n = -1; + + testvsp(buf, _countof(buf), formatstr, &n); + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + if (memcmp(buf, checkstr, strlen(buf) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } +} + +#endif + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/CMakeLists.txt new file mode 100644 index 0000000..b29c7c4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/CMakeLists.txt @@ -0,0 +1,19 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test1/CMakeLists.txt new file mode 100644 index 0000000..3bb7e5f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_vswprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test1 coreclrpal) + +target_link_libraries(paltest_vswprintf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test1/test1.cpp new file mode 100644 index 0000000..8d69c82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test1/test1.cpp @@ -0,0 +1,40 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Test #1 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR *checkstr = NULL; + WCHAR buf[256] = { 0 }; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + checkstr = convert("hello world"); + testvswp(buf, _countof(buf), checkstr); + + if (memcmp(checkstr, buf, wcslen(checkstr)*2+2) != 0) + { + Fail("ERROR: Expected \"%s\", got \"%s\"\n", + convertC(checkstr), convertC(buf)); + } + + free(checkstr); + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test1/testinfo.dat new file mode 100644 index 0000000..6161190 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the vswprintf function. += General test to see if vswprintf works correctly. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test10/CMakeLists.txt new file mode 100644 index 0000000..3a17ef2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_vswprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test10 coreclrpal) + +target_link_libraries(paltest_vswprintf_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test10/test10.cpp new file mode 100644 index 0000000..7f316e2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test10/test10.cpp @@ -0,0 +1,48 @@ +// 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. + +/*===================================================================== +** +** Source: test10.c +** +** Purpose: Test #10 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoNumTest(convert("foo %o"), pos, convert("foo 52")); + DoNumTest(convert("foo %lo"), 0xFFFF, convert("foo 177777")); + DoNumTest(convert("foo %ho"), 0xFFFF, convert("foo 177777")); + DoNumTest(convert("foo %Lo"), pos, convert("foo 52")); + DoI64NumTest(convert("foo %I64o"), l, "42", convert("foo 52")); + DoNumTest(convert("foo %3o"), pos, convert("foo 52")); + DoNumTest(convert("foo %-3o"), pos, convert("foo 52 ")); + DoNumTest(convert("foo %.1o"), pos, convert("foo 52")); + DoNumTest(convert("foo %.3o"), pos, convert("foo 052")); + DoNumTest(convert("foo %03o"), pos, convert("foo 052")); + DoNumTest(convert("foo %#o"), pos, convert("foo 052")); + DoNumTest(convert("foo %+o"), pos, convert("foo 52")); + DoNumTest(convert("foo % o"), pos, convert("foo 52")); + DoNumTest(convert("foo %+o"), neg, convert("foo 37777777726")); + DoNumTest(convert("foo % o"), neg, convert("foo 37777777726")); + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test10/testinfo.dat new file mode 100644 index 0000000..81fbce5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test10/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test10 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with octal numbers. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test11/CMakeLists.txt new file mode 100644 index 0000000..7040c2e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test11.cpp +) + +add_executable(paltest_vswprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test11 coreclrpal) + +target_link_libraries(paltest_vswprintf_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test11/test11.cpp new file mode 100644 index 0000000..608069f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test11/test11.cpp @@ -0,0 +1,48 @@ +// 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. + +/*===================================================================== +** +** Source: test11.c +** +** Purpose: Test #11 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoNumTest(convert("foo %u"), pos, convert("foo 42")); + DoNumTest(convert("foo %lu"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hu"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %Lu"), pos, convert("foo 42")); + DoI64NumTest(convert("foo %I64u"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3u"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3u"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1u"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3u"), pos, convert("foo 042")); + DoNumTest(convert("foo %03u"), pos, convert("foo 042")); + DoNumTest(convert("foo %#u"), pos, convert("foo 42")); + DoNumTest(convert("foo %+u"), pos, convert("foo 42")); + DoNumTest(convert("foo % u"), pos, convert("foo 42")); + DoNumTest(convert("foo %+u"), neg, convert("foo 4294967254")); + DoNumTest(convert("foo % u"), neg, convert("foo 4294967254")); + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test11/testinfo.dat new file mode 100644 index 0000000..13585cc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test11/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test11 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with unsigned numbers. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test12/CMakeLists.txt new file mode 100644 index 0000000..40778fa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_vswprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test12 coreclrpal) + +target_link_libraries(paltest_vswprintf_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test12/test12.cpp new file mode 100644 index 0000000..36b2038 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test12/test12.cpp @@ -0,0 +1,48 @@ +// 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. + +/*===================================================================== +** +** Source: test12.c +** +** Purpose: Test #12 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoNumTest(convert("foo %x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %lx"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %hx"), pos, convert("foo 34ab")); + DoNumTest(convert("foo %Lx"), pos, convert("foo 1234ab")); + DoI64NumTest(convert("foo %I64x"), l, "0x1234567887654321", + convert("foo 1234567887654321")); + DoNumTest(convert("foo %7x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %-7x"), pos, convert("foo 1234ab ")); + DoNumTest(convert("foo %.1x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %.7x"), pos, convert("foo 01234ab")); + DoNumTest(convert("foo %07x"), pos, convert("foo 01234ab")); + DoNumTest(convert("foo %#x"), pos, convert("foo 0x1234ab")); + DoNumTest(convert("foo %+x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo % x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %+x"), neg, convert("foo ffffffd6")); + DoNumTest(convert("foo % x"), neg, convert("foo ffffffd6")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test12/testinfo.dat new file mode 100644 index 0000000..d42e9a1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test12/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test12 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with hex numbers (lowercase). += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test13/CMakeLists.txt new file mode 100644 index 0000000..26b8580 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test13.cpp +) + +add_executable(paltest_vswprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test13 coreclrpal) + +target_link_libraries(paltest_vswprintf_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test13/test13.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test13/test13.cpp new file mode 100644 index 0000000..63dc36a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test13/test13.cpp @@ -0,0 +1,48 @@ +// 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. + +/*===================================================================== +** +** Source: test13.c +** +** Purpose: Test #13 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoNumTest(convert("foo %X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %lX"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %hX"), pos, convert("foo 34AB")); + DoNumTest(convert("foo %LX"), pos, convert("foo 1234AB")); + DoI64NumTest(convert("foo %I64X"), l, "0x1234567887654321", + convert("foo 1234567887654321")); + DoNumTest(convert("foo %7X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %-7X"), pos, convert("foo 1234AB ")); + DoNumTest(convert("foo %.1X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %.7X"), pos, convert("foo 01234AB")); + DoNumTest(convert("foo %07X"), pos, convert("foo 01234AB")); + DoNumTest(convert("foo %#X"), pos, convert("foo 0X1234AB")); + DoNumTest(convert("foo %+X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo % X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %+X"), neg, convert("foo FFFFFFD6")); + DoNumTest(convert("foo % X"), neg, convert("foo FFFFFFD6")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test13/testinfo.dat new file mode 100644 index 0000000..f7c6756 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test13/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test13 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with hex numbers (uppercase). += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test14/CMakeLists.txt new file mode 100644 index 0000000..0e5366e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test14.cpp +) + +add_executable(paltest_vswprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test14 coreclrpal) + +target_link_libraries(paltest_vswprintf_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test14/test14.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test14/test14.cpp new file mode 100644 index 0000000..bb4ab16 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test14/test14.cpp @@ -0,0 +1,61 @@ +// 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. + +/*===================================================================== +** +** Source: test14.c +** +** Purpose: Test #14 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoDoubleTest(convert("foo %e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %le"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %he"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %Le"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %I64e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %14e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %-14e"), val, convert("foo 2.560000e+002 "), + convert("foo 2.560000e+02 ")); + DoDoubleTest(convert("foo %.1e"), val, convert("foo 2.6e+002"), + convert("foo 2.6e+02")); + DoDoubleTest(convert("foo %.8e"), val, convert("foo 2.56000000e+002"), + convert("foo 2.56000000e+02")); + DoDoubleTest(convert("foo %014e"), val, convert("foo 02.560000e+002"), + convert("foo 002.560000e+02")); + DoDoubleTest(convert("foo %#e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %+e"), val, convert("foo +2.560000e+002"), + convert("foo +2.560000e+02")); + DoDoubleTest(convert("foo % e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %+e"), neg, convert("foo -2.560000e+002"), + convert("foo -2.560000e+02")); + DoDoubleTest(convert("foo % e"), neg, convert("foo -2.560000e+002"), + convert("foo -2.560000e+02")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test14/testinfo.dat new file mode 100644 index 0000000..e9615f9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test14/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test14 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with exponential format doubles (lowercase). += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test15/CMakeLists.txt new file mode 100644 index 0000000..23e9595 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test15.cpp +) + +add_executable(paltest_vswprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test15 coreclrpal) + +target_link_libraries(paltest_vswprintf_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test15/test15.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test15/test15.cpp new file mode 100644 index 0000000..6296220 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test15/test15.cpp @@ -0,0 +1,62 @@ +// 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. + +/*===================================================================== +** +** Source: test15.c +** +** Purpose: Test #15 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoDoubleTest(convert("foo %E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %lE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %hE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %LE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %I64E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %14E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %-14E"), val, convert("foo 2.560000E+002 "), + convert("foo 2.560000E+02 ")); + DoDoubleTest(convert("foo %.1E"), val, convert("foo 2.6E+002"), + convert("foo 2.6E+02")); + DoDoubleTest(convert("foo %.8E"), val, convert("foo 2.56000000E+002"), + convert("foo 2.56000000E+02")); + DoDoubleTest(convert("foo %014E"), val, convert("foo 02.560000E+002"), + convert("foo 002.560000E+02")); + DoDoubleTest(convert("foo %#E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %+E"), val, convert("foo +2.560000E+002"), + convert("foo +2.560000E+02")); + DoDoubleTest(convert("foo % E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %+E"), neg, convert("foo -2.560000E+002"), + convert("foo -2.560000E+02")); + DoDoubleTest(convert("foo % E"), neg, convert("foo -2.560000E+002"), + convert("foo -2.560000E+002")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test15/testinfo.dat new file mode 100644 index 0000000..24ff03b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test15/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test15 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with exponential format doubles (uppercase). += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test16/CMakeLists.txt new file mode 100644 index 0000000..b398fdc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test16.cpp +) + +add_executable(paltest_vswprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test16 coreclrpal) + +target_link_libraries(paltest_vswprintf_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test16/test16.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test16/test16.cpp new file mode 100644 index 0000000..3a2059a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test16/test16.cpp @@ -0,0 +1,61 @@ +// 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. + +/*===================================================================== +** +** Source: test16.c +** +** Purpose: Test #16 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoDoubleTest(convert("foo %f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %lf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %hf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %Lf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %I64f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %12f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %-12f"), val, convert("foo 2560.001000 "), + convert("foo 2560.001000 ")); + DoDoubleTest(convert("foo %.1f"), val, convert("foo 2560.0"), + convert("foo 2560.0")); + DoDoubleTest(convert("foo %.8f"), val, convert("foo 2560.00100000"), + convert("foo 2560.00100000")); + DoDoubleTest(convert("foo %012f"), val, convert("foo 02560.001000"), + convert("foo 02560.001000")); + DoDoubleTest(convert("foo %#f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %+f"), val, convert("foo +2560.001000"), + convert("foo +2560.001000")); + DoDoubleTest(convert("foo % f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %+f"), neg, convert("foo -2560.001000"), + convert("foo -2560.001000")); + DoDoubleTest(convert("foo % f"), neg, convert("foo -2560.001000"), + convert("foo -2560.001000")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test16/testinfo.dat new file mode 100644 index 0000000..6dc45f4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test16/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test16 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with decimal point format doubles. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test17/CMakeLists.txt new file mode 100644 index 0000000..8b505de --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test17.cpp +) + +add_executable(paltest_vswprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test17 coreclrpal) + +target_link_libraries(paltest_vswprintf_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test17/test17.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test17/test17.cpp new file mode 100644 index 0000000..95e3bd9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test17/test17.cpp @@ -0,0 +1,63 @@ +// 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. + +/*===================================================================== +** +** Source: test17.c +** +** Purpose: Test #17 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoDoubleTest(convert("foo %g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %lg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %hg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %Lg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %I64g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %5g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %-5g"), val, convert("foo 2560 "), + convert("foo 2560 ")); + DoDoubleTest(convert("foo %.1g"), val, convert("foo 3e+003"), + convert("foo 3e+03")); + DoDoubleTest(convert("foo %.2g"), val, convert("foo 2.6e+003"), + convert("foo 2.6e+03")); + DoDoubleTest(convert("foo %.12g"), val, convert("foo 2560.001"), + convert("foo 2560.001")); + DoDoubleTest(convert("foo %06g"), val, convert("foo 002560"), + convert("foo 002560")); + DoDoubleTest(convert("foo %#g"), val, convert("foo 2560.00"), + convert("foo 2560.00")); + DoDoubleTest(convert("foo %+g"), val, convert("foo +2560"), + convert("foo +2560")); + DoDoubleTest(convert("foo % g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %+g"), neg, convert("foo -2560"), + convert("foo -2560")); + DoDoubleTest(convert("foo % g"), neg, convert("foo -2560"), + convert("foo -2560")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test17/testinfo.dat new file mode 100644 index 0000000..815e57d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test17/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test17 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with compact format doubles (lowercase). += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test18/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test18/CMakeLists.txt new file mode 100644 index 0000000..0fc1f0d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test18/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test18.cpp +) + +add_executable(paltest_vswprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test18 coreclrpal) + +target_link_libraries(paltest_vswprintf_test18 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test18/test18.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test18/test18.cpp new file mode 100644 index 0000000..ae7ae4c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test18/test18.cpp @@ -0,0 +1,63 @@ +// 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. + +/*===================================================================== +** +** Source: test18.c +** +** Purpose: Test #18 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoDoubleTest(convert("foo %G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %lG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %hG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %LG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %I64G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %5G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %-5G"), val, convert("foo 2560 "), + convert("foo 2560 ")); + DoDoubleTest(convert("foo %.1G"), val, convert("foo 3E+003"), + convert("foo 3E+03")); + DoDoubleTest(convert("foo %.2G"), val, convert("foo 2.6E+003"), + convert("foo 2.6E+03")); + DoDoubleTest(convert("foo %.12G"), val, convert("foo 2560.001"), + convert("foo 2560.001")); + DoDoubleTest(convert("foo %06G"), val, convert("foo 002560"), + convert("foo 002560")); + DoDoubleTest(convert("foo %#G"), val, convert("foo 2560.00"), + convert("foo 2560.00")); + DoDoubleTest(convert("foo %+G"), val, convert("foo +2560"), + convert("foo +2560")); + DoDoubleTest(convert("foo % G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %+G"), neg, convert("foo -2560"), + convert("foo -2560")); + DoDoubleTest(convert("foo % G"), neg, convert("foo -2560"), + convert("foo -2560")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test18/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test18/testinfo.dat new file mode 100644 index 0000000..b516599 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test18/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test18 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with compact format doubles (uppercase). += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test19/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test19/CMakeLists.txt new file mode 100644 index 0000000..b974935 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test19/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test19.cpp +) + +add_executable(paltest_vswprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test19 coreclrpal) + +target_link_libraries(paltest_vswprintf_test19 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.cpp new file mode 100644 index 0000000..12f2b7b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.cpp @@ -0,0 +1,137 @@ +// 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. + +/*===================================================================== +** +** Source: test18.c +** +** Purpose: Test #18 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +#define DOTEST(a,b,c,d,e) DoTest(a,b,(void*)c,d,e) + +void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param, + WCHAR *paramstr, WCHAR *checkstr1, WCHAR *checkstr2) +{ + WCHAR buf[256]; + + testvswp(buf, _countof(buf), formatstr, precision, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + paramstr, + convertC(formatstr), + precision, + convertC(checkstr1), + convertC(checkstr2), + convertC(buf)); + } +} +void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param, + WCHAR *checkstr1, WCHAR *checkstr2) +{ + WCHAR buf[256]; + + testvswp(buf, _countof(buf), formatstr, precision, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + param, convertC(formatstr), + precision, + convertC(checkstr1), + convertC(checkstr2), + convertC(buf)); + } +} + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoArgumentPrecTest(convert("%.*s"), 2, (void*)convert("bar"), convert("bar"), + convert("ba"), convert("ba")); + DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, convert("42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, convert("42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, convert("42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, convert("42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, convert("42"), + convert("52"), convert("52")); + DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, convert("42"), + convert("052"), convert("052")); + DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, convert("42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, convert("42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, convert("0x42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, convert("0x42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, convert("0x42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, convert("0x42"), + convert("042"), convert("042")); + + + DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000"), + convert("2.0e+00")); + DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000"), + convert("2.010e+00")); + DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000"), + convert("2.0E+00")); + DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000"), + convert("2.010E+00")); + DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0"), + convert("2.0")); + DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010"), + convert("2.010")); + DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002"), + convert("3e+02")); + DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01"), + convert("256.01")); + DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002"), + convert("3E+02")); + DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01"), + convert("256.01")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test19/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test19/testinfo.dat new file mode 100644 index 0000000..ccc08cd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test19/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test19 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with argument specified precision. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test2/CMakeLists.txt new file mode 100644 index 0000000..78550ca --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_vswprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test2 coreclrpal) + +target_link_libraries(paltest_vswprintf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test2/test2.cpp new file mode 100644 index 0000000..a7b1b3a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test2/test2.cpp @@ -0,0 +1,46 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Test #2 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoWStrTest(convert("foo %s"), convert("bar"), convert("foo bar")); + DoStrTest(convert("foo %hs"), "bar", convert("foo bar")); + DoWStrTest(convert("foo %ls"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %ws"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %Ls"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %I64s"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %5s"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %.2s"), convert("bar"), convert("foo ba")); + DoWStrTest(convert("foo %5.2s"), convert("bar"), convert("foo ba")); + DoWStrTest(convert("foo %-5s"), convert("bar"), convert("foo bar ")); + DoWStrTest(convert("foo %05s"), convert("bar"), convert("foo 00bar")); + DoWStrTest(convert("foo %s"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %hs"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %ls"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %ws"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %Ls"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %I64s"), NULL, convert("foo (null)")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test2/testinfo.dat new file mode 100644 index 0000000..d6d7c3e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test2 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with strings. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test3/CMakeLists.txt new file mode 100644 index 0000000..95247ce --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_vswprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test3 coreclrpal) + +target_link_libraries(paltest_vswprintf_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test3/test3.cpp new file mode 100644 index 0000000..40c7d2a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test3/test3.cpp @@ -0,0 +1,46 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Test #3 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoStrTest(convert("foo %S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %hS"), "bar", convert("foo bar")); + DoWStrTest(convert("foo %lS"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %wS"), convert("bar"), convert("foo bar")); + DoStrTest(convert("foo %LS"), "bar", convert("foo bar")); + DoStrTest(convert("foo %I64S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %5S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %.2S"), "bar", convert("foo ba")); + DoStrTest(convert("foo %5.2S"), "bar", convert("foo ba")); + DoStrTest(convert("foo %-5S"), "bar", convert("foo bar ")); + DoStrTest(convert("foo %05S"), "bar", convert("foo 00bar")); + DoStrTest(convert("foo %S"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %hS"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %lS"), NULL, convert("foo (null)")); + DoWStrTest(convert("foo %wS"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %LS"), NULL, convert("foo (null)")); + DoStrTest(convert("foo %I64S"), NULL, convert("foo (null)")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test3/testinfo.dat new file mode 100644 index 0000000..8fb9dc8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test3 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with wide strings. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test4/CMakeLists.txt new file mode 100644 index 0000000..dbaa6ac --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_vswprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test4 coreclrpal) + +target_link_libraries(paltest_vswprintf_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test4/test4.cpp new file mode 100644 index 0000000..2d61137 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test4/test4.cpp @@ -0,0 +1,118 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c +** +** Purpose: Test #4 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ +static void DoPointerTest(WCHAR *formatstr, void* param, WCHAR* paramstr, + WCHAR *checkstr1) +{ + WCHAR buf[256] = { 0 }; + + testvswp(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0) + + { + Fail("ERROR: failed to insert pointer to %#p into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + paramstr, + convertC(formatstr), + convertC(checkstr1), + convertC(buf)); + } +} + +static void DoI64DoubleTest(WCHAR *formatstr, INT64 value, WCHAR *valuestr, + WCHAR *checkstr1) +{ + WCHAR buf[256] = { 0 }; + + testvswp(buf, _countof(buf), formatstr, value); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", + value, + convertC(formatstr), + convertC(checkstr1), + convertC(buf)); + } +} + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest(convert("%p"), NULL, convert("NULL"), convert("0000000000000000")); + DoPointerTest(convert("%p"), ptr, convert("pointer to 0x123456"), + convert("0000000000123456")); + DoPointerTest(convert("%17p"), ptr, convert("pointer to 0x123456"), + convert(" 0000000000123456")); + DoPointerTest(convert("%17p"), ptr, convert("pointer to 0x123456"), + convert(" 0000000000123456")); + DoPointerTest(convert("%-17p"), ptr, convert("pointer to 0x123456"), + convert("0000000000123456 ")); + DoPointerTest(convert("%+p"), ptr, convert("pointer to 0x123456"), + convert("0000000000123456")); + DoPointerTest(convert("%#p"), ptr, convert("pointer to 0x123456"), + convert("0X0000000000123456")); + DoPointerTest(convert("%lp"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoPointerTest(convert("%hp"), ptr, convert("pointer to 0x123456"), + convert("00003456")); + DoPointerTest(convert("%Lp"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoI64DoubleTest(convert("%I64p"), lptr, + convert("pointer to 0x1234567887654321"), convert("1234567887654321")); + +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest(convert("%p"), NULL, convert("NULL"), convert("00000000")); + DoPointerTest(convert("%p"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoPointerTest(convert("%9p"), ptr, convert("pointer to 0x123456"), + convert(" 00123456")); + DoPointerTest(convert("%09p"), ptr, convert("pointer to 0x123456"), + convert(" 00123456")); + DoPointerTest(convert("%-9p"), ptr, convert("pointer to 0x123456"), + convert("00123456 ")); + DoPointerTest(convert("%+p"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoPointerTest(convert("%#p"), ptr, convert("pointer to 0x123456"), + convert("0X00123456")); + DoPointerTest(convert("%lp"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoPointerTest(convert("%hp"), ptr, convert("pointer to 0x123456"), + convert("00003456")); + DoPointerTest(convert("%Lp"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoI64DoubleTest(convert("%I64p"), lptr, + convert("pointer to 0x1234567887654321"), convert("1234567887654321")); + +#endif + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test4/testinfo.dat new file mode 100644 index 0000000..435f970 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test4/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test4 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with pointers. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test6/CMakeLists.txt new file mode 100644 index 0000000..40b3b50 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_vswprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test6 coreclrpal) + +target_link_libraries(paltest_vswprintf_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test6/test6.cpp new file mode 100644 index 0000000..51e9926 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test6/test6.cpp @@ -0,0 +1,41 @@ +// 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. + +/*===================================================================== +** +** Source: test6.c +** +** Purpose: Test #6 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoWCharTest(convert("foo %c"), wc, convert("foo c")); + DoCharTest(convert("foo %hc"), 'b', convert("foo b")); + DoWCharTest(convert("foo %lc"), wc, convert("foo c")); + DoWCharTest(convert("foo %Lc"), wc, convert("foo c")); + DoWCharTest(convert("foo %I64c"), wc, convert("foo c")); + DoWCharTest(convert("foo %5c"), wc, convert("foo c")); + DoWCharTest(convert("foo %.0c"), wc, convert("foo c")); + DoWCharTest(convert("foo %-5c"), wc, convert("foo c ")); + DoWCharTest(convert("foo %05c"), wc, convert("foo 0000c")); + DoWCharTest(convert("foo % c"), wc, convert("foo c")); + DoWCharTest(convert("foo %#c"), wc, convert("foo c")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test6/testinfo.dat new file mode 100644 index 0000000..f4ad2e9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test6/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test6 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with characters. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test7/CMakeLists.txt new file mode 100644 index 0000000..96ef505 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_vswprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test7 coreclrpal) + +target_link_libraries(paltest_vswprintf_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test7/test7.cpp new file mode 100644 index 0000000..6037cb0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test7/test7.cpp @@ -0,0 +1,41 @@ +// 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. + +/*===================================================================== +** +** Source: test7.c +** +** Purpose: Test #7 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoCharTest(convert("foo %C"), 'b', convert("foo b")); + DoWCharTest(convert("foo %hC"), wc, convert("foo c")); + DoCharTest(convert("foo %lC"), 'b', convert("foo b")); + DoCharTest(convert("foo %LC"), 'b', convert("foo b")); + DoCharTest(convert("foo %I64C"), 'b', convert("foo b")); + DoCharTest(convert("foo %5C"), 'b', convert("foo b")); + DoCharTest(convert("foo %.0C"), 'b', convert("foo b")); + DoCharTest(convert("foo %-5C"), 'b', convert("foo b ")); + DoCharTest(convert("foo %05C"), 'b', convert("foo 0000b")); + DoCharTest(convert("foo % C"), 'b', convert("foo b")); + DoCharTest(convert("foo %#C"), 'b', convert("foo b")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test7/testinfo.dat new file mode 100644 index 0000000..ed0a474 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test7/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test7 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with wide characters. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test8/CMakeLists.txt new file mode 100644 index 0000000..2fb6548 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_vswprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test8 coreclrpal) + +target_link_libraries(paltest_vswprintf_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test8/test8.cpp new file mode 100644 index 0000000..baba524 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test8/test8.cpp @@ -0,0 +1,47 @@ +// 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. + +/*===================================================================== +** +** Source: test8.c +** +** Purpose: Test #8 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoNumTest(convert("foo %d"), pos, convert("foo 42")); + DoNumTest(convert("foo %ld"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hd"), 0xFFFF, convert("foo -1")); + DoNumTest(convert("foo %Ld"), pos, convert("foo 42")); + DoI64NumTest(convert("foo %I64d"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3d"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3d"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1d"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3d"), pos, convert("foo 042")); + DoNumTest(convert("foo %03d"), pos, convert("foo 042")); + DoNumTest(convert("foo %#d"), pos, convert("foo 42")); + DoNumTest(convert("foo %+d"), pos, convert("foo +42")); + DoNumTest(convert("foo % d"), pos, convert("foo 42")); + DoNumTest(convert("foo %+d"), neg, convert("foo -42")); + DoNumTest(convert("foo % d"), neg, convert("foo -42")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test8/testinfo.dat new file mode 100644 index 0000000..4c5114b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test8/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test8 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with decimal numbers. += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test9/CMakeLists.txt new file mode 100644 index 0000000..ef38e3c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_vswprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_vswprintf_test9 coreclrpal) + +target_link_libraries(paltest_vswprintf_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test9/test9.cpp new file mode 100644 index 0000000..5de004f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test9/test9.cpp @@ -0,0 +1,47 @@ +// 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. + +/*===================================================================== +** +** Source: test9.c +** +** Purpose: Test #9 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoNumTest(convert("foo %i"), pos, convert("foo 42")); + DoNumTest(convert("foo %li"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hi"), 0xFFFF, convert("foo -1")); + DoNumTest(convert("foo %Li"), pos, convert("foo 42")); + DoI64NumTest(convert("foo %I64i"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3i"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3i"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1i"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3i"), pos, convert("foo 042")); + DoNumTest(convert("foo %03i"), pos, convert("foo 042")); + DoNumTest(convert("foo %#i"), pos, convert("foo 42")); + DoNumTest(convert("foo %+i"), pos, convert("foo +42")); + DoNumTest(convert("foo % i"), pos, convert("foo 42")); + DoNumTest(convert("foo %+i"), neg, convert("foo -42")); + DoNumTest(convert("foo % i"), neg, convert("foo -42")); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test9/testinfo.dat new file mode 100644 index 0000000..3c2bcdf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/test9/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = vswprintf +Name = Positive Test for vswprintf +TYPE = DEFAULT +EXE1 = test9 +Description += Tests the PAL implementation of the vswprintf function. += Tests vswprintf with integer numbers += This test is modeled after _snwprintf. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/vswprintf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/vswprintf.h new file mode 100644 index 0000000..3454d28 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/vswprintf/vswprintf.h @@ -0,0 +1,132 @@ +// 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. + +/*============================================================================ +** +** Source: vswprintf.h +** +** Purpose: Containts common testing functions for vswprintf +** +** +**==========================================================================*/ + +#ifndef __vswprintf_H__ +#define __vswprintf_H__ + +/* These functions leaks memory a lot. C'est la vie. */ +int testvswp(char16_t* buf, size_t buffSize, const char16_t* format, ...) +{ + int retVal = 0; + va_list arglist; + + va_start(arglist, format); + retVal = _vsnwprintf_s(buf, buffSize, _TRUNCATE, format, arglist); + va_end(arglist); + + return( retVal); +} + +void DoWStrTest(const WCHAR *formatstr, WCHAR *param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + testvswp(buf, _countof(buf), formatstr, param); + + if (memcmp(buf, checkstr, wcslen(buf) * 2 + 2) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", + convertC(param), convertC(formatstr), + convertC(checkstr), convertC(buf)); + } +} + +void DoStrTest(const WCHAR *formatstr, char *param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + testvswp(buf, _countof(buf), formatstr, param); + + if (memcmp(buf, checkstr, wcslen(buf) * 2 + 2) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", + param, convertC(formatstr), convertC(checkstr), + convertC(buf)); + } +} + +void DoCharTest(const WCHAR *formatstr, char param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + testvswp(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0) + { + Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, param, convertC(formatstr), convertC(checkstr), + convertC(buf)); + } +} + +void DoWCharTest(const WCHAR *formatstr, WCHAR param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + testvswp(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0) + { + Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + (char) param, param, convertC(formatstr), convertC(checkstr), + convertC(buf)); + } +} + +void DoNumTest(const WCHAR *formatstr, int value, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + testvswp(buf, _countof(buf), formatstr, value); + if (memcmp(buf, checkstr, wcslen(buf)* 2 + 2) != 0) + { + Fail("ERROR: failed to insert %#x into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", value, convertC(formatstr), + convertC(checkstr), convertC(buf)); + } +} + +void DoI64NumTest(const WCHAR *formatstr, INT64 value, char *valuestr, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + testvswp(buf, _countof(buf), formatstr, value); + if (memcmp(buf, checkstr, wcslen(buf)* 2 + 2) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", valuestr, convertC(formatstr), + convertC(checkstr), convertC(buf)); + } +} +void DoDoubleTest(const WCHAR *formatstr, double value, const WCHAR *checkstr1, WCHAR + *checkstr2) +{ + WCHAR buf[256] = { 0 }; + + testvswp(buf, _countof(buf), formatstr, value); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + value, + convertC(formatstr), + convertC(checkstr1), + convertC(checkstr2), + convertC(buf)); + } +} + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/test1/CMakeLists.txt new file mode 100644 index 0000000..08cd49f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcscat_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcscat_test1 coreclrpal) + +target_link_libraries(paltest_wcscat_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.cpp new file mode 100644 index 0000000..e9a79d3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.cpp @@ -0,0 +1,71 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Test to that wcscat correctly concatanates wide strings, including placing +** null pointers. +** +** +**==========================================================================*/ + + + +#include + +/* + * Notes: uses memcmp and the (pal) sprintf_s + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR dest[80]; + WCHAR test[] = {'f','o','o',' ','b','a','r',' ','b','a','z',0}; + WCHAR str1[] = {'f','o','o',' ',0}; + WCHAR str2[] = {'b','a','r',' ',0}; + WCHAR str3[] = {'b','a','z',0}; + WCHAR *ptr; + char buffer[256]; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + dest[0] = 0; + + ptr = wcscat(dest, str1); + if (ptr != dest) + { + Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr); + } + + ptr = wcscat(dest, str2); + if (ptr != dest) + { + Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr); + } + + ptr = wcscat(dest, str3); + if (ptr != dest) + { + Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr); + } + + if (memcmp(dest, test, sizeof(test)) != 0) + { + sprintf_s(buffer, _countof(buffer), "%S", dest); + Fail("ERROR: Expected wcscat to give \"%s\", got \"%s\"\n", + "foo bar baz", buffer); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/test1/testinfo.dat new file mode 100644 index 0000000..878c446 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscat/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = wcscat +Name = Positive Test for wcscat +TYPE = DEFAULT +EXE1 = test1 +Description += Test to that wcscat correctly concatanates wide strings, including placing += null pointers diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/test1/CMakeLists.txt new file mode 100644 index 0000000..1687e57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcschr_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcschr_test1 coreclrpal) + +target_link_libraries(paltest_wcschr_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/test1/test1.cpp new file mode 100644 index 0000000..a496367 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/test1/test1.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Tests that wcschr correctly finds the first occurrence of a character in a +** string +** +** +**==========================================================================*/ + + + +#include + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR str[] = {'f','o','o',' ','b','a','r',' ',0}; + WCHAR c = (WCHAR)' '; + WCHAR c2 = (WCHAR)'$'; + WCHAR *ptr; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + ptr = wcschr(str, c); + if (ptr != str + 3) + { + Fail("ERROR: expected wcschr to return pointer to %p, got %p\n", + str + 3, ptr); + } + + ptr = wcschr(str, c2); + if (ptr != NULL) + { + Fail("ERROR: expected wcschr to return pointer to %p, got %p\n", + NULL, ptr); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/test1/testinfo.dat new file mode 100644 index 0000000..40a166d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcschr/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = wcschr +Name = Positive Test for wcschr +TYPE = DEFAULT +EXE1 = test1 +Description += Tests that wcschr correctly finds the first occurrence of a character in a += string. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/test1/CMakeLists.txt new file mode 100644 index 0000000..a556133 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcscmp_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcscmp_test1 coreclrpal) + +target_link_libraries(paltest_wcscmp_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.cpp new file mode 100644 index 0000000..1c38dd6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.cpp @@ -0,0 +1,57 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests that wcscmp correctly compares two strings with +** case sensitivity. +** +** +**==========================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR str1[] = {'f','o','o',0}; + WCHAR str2[] = {'f','o','o','x',0}; + WCHAR str3[] = {'f','O','o',0}; + char cstr1[] = "foo"; + char cstr2[] = "foox"; + char cstr3[] = "fOo"; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + + if (wcscmp(str1, str2) >= 0) + { + Fail("ERROR: wcscmp(\"%s\", \"%s\") returned >= 0\n", cstr1, cstr2); + } + + if (wcscmp(str2, str1) <= 0) + { + Fail("ERROR: wcscmp(\"%s\", \"%s\") returned <= 0\n", cstr2, cstr1); + } + + if (wcscmp(str1, str3) <= 0) + { + Fail("ERROR: wcscmp(\"%s\", \"%s\") returned >= 0\n", cstr1, cstr3); + } + + if (wcscmp(str3, str1) >= 0) + { + Fail("ERROR: wcscmp(\"%s\", \"%s\") returned >= 0\n", cstr3, cstr1); + } + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/test1/testinfo.dat new file mode 100644 index 0000000..0fe696f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscmp/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = wcscmp +Name = Test #1 for wcscmp +TYPE = DEFAULT +EXE1 = test1 +Description += Tests that wcscmp correctly compares two strings with case sensitivity. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/test1/CMakeLists.txt new file mode 100644 index 0000000..8a00408 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcscpy_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcscpy_test1 coreclrpal) + +target_link_libraries(paltest_wcscpy_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.cpp new file mode 100644 index 0000000..2ecafa8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests that wcscpy correctly copies a null-terminated wide string. +** +** +**==========================================================================*/ + + +#include + +/* + * Notes: uses memcmp and sprintf_s. + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR str[] = {'f','o','o',0,'b','a','r',0}; + WCHAR dest[80]; + WCHAR result[] = {'f','o','o',0}; + WCHAR *ret; + char buffer[256]; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + ret = wcscpy(dest, str); + + if (ret != dest || memcmp(dest, result, sizeof(result)) != 0) + { + sprintf_s(buffer, _countof(buffer), "%S", dest); + Fail("Expected wcscpy to give \"%s\" with a return value of %p, got \"%s\" " + "with a return value of %p.\n", "foo", dest, buffer, ret); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/test1/testinfo.dat new file mode 100644 index 0000000..ef9c58e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcscpy/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = wcscpy +Name = Positive Test for wcscpy +TYPE = DEFAULT +EXE1 = test1 +Description += Tests that wcscpy correctly copies a null-terminated wide string. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/test1/CMakeLists.txt new file mode 100644 index 0000000..474f226 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcslen_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcslen_test1 coreclrpal) + +target_link_libraries(paltest_wcslen_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/test1/test1.cpp new file mode 100644 index 0000000..17d0327 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/test1/test1.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Tests that wcslen correctly returns the length (in wide characters, +** not byte) of a wide string +** +** +**==========================================================================*/ + + + +#include + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR str1[] = {'f','o','o',' ',0}; + WCHAR str2[] = {0}; + int ret; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + ret = wcslen(str1); + if (ret != 4) + { + Fail("ERROR: Expected wcslen of \"foo \" to be 4, got %d\n", ret); + } + + ret = wcslen(str2); + if (ret != 0) + { + Fail("ERROR: Expected wcslen of \"\" to be 0, got %d\n", ret); + } + + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/test1/testinfo.dat new file mode 100644 index 0000000..cfdef48 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcslen/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = wcslen +Name = Positive Test for wcslen +TYPE = DEFAULT +EXE1 = test1 +Description += Tests that wcslen correctly returns the length (in wide characters, not byte) += of a wide string diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/CMakeLists.txt new file mode 100644 index 0000000..b730673 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcsncmp_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcsncmp_test1 coreclrpal) + +target_link_libraries(paltest_wcsncmp_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.cpp new file mode 100644 index 0000000..4e4488f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.cpp @@ -0,0 +1,73 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Tests that wcsncmp case-sensitively compares wide strings, making sure that +** the count argument is handled correctly. +** +** +**==========================================================================*/ + + + +#include + +/* + * Notes: uses wcslen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR str1[] = {'f','o','o',0}; + WCHAR str2[] = {'f','o','o','x',0}; + WCHAR str3[] = {'f','O','o',0}; + char cstr1[] = "foo"; + char cstr2[] = "foox"; + char cstr3[] = "fOo"; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + + if (wcsncmp(str1, str2, wcslen(str2)) >= 0) + { + Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned >= 0\n", cstr1, + cstr2, wcslen(str2)); + } + + if (wcsncmp(str2, str1, wcslen(str2)) <= 0) + { + Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned <= 0\n", cstr2, + cstr1, wcslen(str2)); + } + + if (wcsncmp(str1, str2, wcslen(str1)) != 0) + { + Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned != 0\n", cstr1, + cstr2, wcslen(str1)); + } + + if (wcsncmp(str1, str3, wcslen(str1)) <= 0) + { + Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned >= 0\n", cstr1, + cstr3, wcslen(str1)); + } + + if (wcsncmp(str3, str1, wcslen(str1)) >= 0) + { + Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned >= 0\n", cstr3, + cstr1, wcslen(str1)); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/testinfo.dat new file mode 100644 index 0000000..1f8b508 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = wcsncmp +Name = Positive Test for wcsncmp +TYPE = DEFAULT +EXE1 = test1 +Description += Tests that wcsncmp case-sensitively compares wide strings, making sure that += the count argument is handled correctly. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/CMakeLists.txt new file mode 100644 index 0000000..8c70fdf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcsncpy_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcsncpy_test1 coreclrpal) + +target_link_libraries(paltest_wcsncpy_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.cpp new file mode 100644 index 0000000..50d97b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.cpp @@ -0,0 +1,84 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Tests to see that wcsncpy correctly copies wide strings, including handling +** the count argument correctly (copying no more that count characters, not +** automatically adding a null, and padding if necessary). +** +** +**==========================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR dest[80]; + WCHAR result[] = {'f','o','o','b','a','r',0}; + WCHAR str[] = {'f','o','o','b','a','r',0,'b','a','z',0}; + WCHAR *ret; + int i; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + for (i=0; i<80; i++) + { + dest[i] = 'x'; + } + + ret = wcsncpy(dest, str, 3); + if (ret != dest) + { + Fail("Expected wcsncpy to return %p, got %p!\n", dest, ret); + } + + if (wcsncmp(dest, result, 3) != 0) + { + Fail("Expected wcsncpy to give \"%S\", got \"%S\"!\n", result, dest); + } + + if (dest[3] != (WCHAR)'x') + { + Fail("wcsncpy overflowed!\n"); + } + + ret = wcsncpy(dest, str, 40); + if (ret != dest) + { + Fail("Expected wcsncpy to return %p, got %p!\n", dest, ret); + } + + if (wcscmp(dest, result) != 0) + { + Fail("Expected wcsncpy to give \"%S\", got \"%S\"!\n", result, dest); + } + + for (i=wcslen(str); i<40; i++) + { + if (dest[i] != 0) + { + Fail("wcsncpy failed to pad the destination with NULLs!\n"); + } + } + + if (dest[40] != (WCHAR)'x') + { + Fail("wcsncpy overflowed!\n"); + } + + + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/testinfo.dat new file mode 100644 index 0000000..b8b0ddb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = wcsncpy +Name = Test #1 for wcsncpy +TYPE = DEFAULT +EXE1 = test1 +Description += Tests to see that wcsncpy correctly copies wide strings, including handling += the count argument correctly (copying no more that count characters, not += automatically adding a null, and padding if necessary). + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/CMakeLists.txt new file mode 100644 index 0000000..d2f75ea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcspbrk_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcspbrk_test1 coreclrpal) + +target_link_libraries(paltest_wcspbrk_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/test1.cpp new file mode 100644 index 0000000..b0432f7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/test1.cpp @@ -0,0 +1,61 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Tests that wcspbrk returns a pointer to the first element in the first +** string that matches a character in the second (or NULL). +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR *string; + WCHAR *key1; + WCHAR *key2; + WCHAR key3[] = {0}; + WCHAR *result; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + string = convert("foo bar baz bar"); + key1 = convert("z "); + key2 = convert("Q"); + + result = wcspbrk(string, key1); + if (result != string + 3) + { + Fail("ERROR: Got incorrect result in scanning \"%s\" with the set \"%s\".\n" + "Expected to get pointer to %#p, got %#p\n", convertC(string), + convertC(key1), string + 3, result); + } + + result = wcspbrk(string, key2); + if (result != NULL) + { + Fail("ERROR: Got incorrect result in scanning \"%s\" with the set \"%s\".\n" + "Expected to get pointer to %#p, got %#p\n", convertC(string), + convertC(key2), NULL, result); + } + + result = wcspbrk(string, key3); + if (result != NULL) + { + Fail("ERROR: Got incorrect result in scanning \"%s\" with the set \"%s\".\n" + "Expected to get pointer to %#p, got %#p\n", convertC(string), + convertC(key3), NULL, result); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/testinfo.dat new file mode 100644 index 0000000..7044197 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = wcspbrk +Name = Positive Test for wcspbrk +TYPE = DEFAULT +EXE1 = test1 +Description += Tests that wcspbrk returns a pointer to the first element in the first += string that matches a character in the second (or NULL). diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/CMakeLists.txt new file mode 100644 index 0000000..931dcc0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcsrchr_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcsrchr_test1 coreclrpal) + +target_link_libraries(paltest_wcsrchr_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.cpp new file mode 100644 index 0000000..ae87657 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.cpp @@ -0,0 +1,50 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Tests to see that wcsrchr correctly returns a pointer to the last occurence +** of a character in a a string. +** +** +**==========================================================================*/ + + + +#include + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR str[] = {'f','o','o',' ','b','a','r',' ','b','a','z',0}; + WCHAR c = (WCHAR)' '; + WCHAR c2 = (WCHAR)'$'; + WCHAR *ptr; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + ptr = wcsrchr(str, c); + if (ptr != str + 7) + { + Fail("ERROR: expected wcsrchr to return pointer to %p, got %p\n", + str + 7, ptr); + } + + ptr = wcsrchr(str, c2); + if (ptr != NULL) + { + Fail("ERROR: expected wcsrchr to return pointer to %p, got %p\n", + NULL, ptr); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/testinfo.dat new file mode 100644 index 0000000..984df9a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = wcsrchr +Name = Positive Test for wcsrchr +TYPE = DEFAULT +EXE1 = test1 +Description += Tests to see that wcsrchr correctly returns a pointer to the last occurence += of a character in a a string. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/test1/CMakeLists.txt new file mode 100644 index 0000000..2da56d9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcsstr_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcsstr_test1 coreclrpal) + +target_link_libraries(paltest_wcsstr_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.cpp new file mode 100644 index 0000000..16005a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.cpp @@ -0,0 +1,72 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Tests that wcsstr correctly find substrings in wide stings, including +** returning NULL when the substring can't be found. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR *string; + WCHAR *key1; + WCHAR *key2; + WCHAR key3[] = { 0 }; + WCHAR *key4; + WCHAR *result; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + string = convert("foo bar baz bar"); + key1 = convert("bar"); + key2 = convert("Bar"); + key4 = convert("arggggh!"); + + result = wcsstr(string, key1); + if (result != string + 4) + { + Fail("ERROR: Got incorrect result in scanning \"%s\" for \"%s\".\n" + "Expected to get pointer to %#p, got %#p\n", convertC(string), + convertC(key1), string + 4, result); + } + + + result = wcsstr(string, key2); + if (result != NULL) + { + Fail("ERROR: Got incorrect result in scanning \"%s\" for \"%s\".\n" + "Expected to get pointer to %#p, got %#p\n", convertC(string), + convertC(key2), NULL, result); + } + + result = wcsstr(string, key3); + if (result != string) + { + Fail("ERROR: Got incorrect result in scanning \"%s\" for \"%s\".\n" + "Expected to get pointer to %#p, got %#p\n", convertC(string), + convertC(key3), string, result); + } + + result = wcsstr(string, key4); + if (result != nullptr) + { + Fail("ERROR: Got incorrect result in scanning \"%s\" for \"%s\".\n" + "Expected to get pointer to null, got %#p\n", convertC(string), + convertC(key4), result); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/test1/testinfo.dat new file mode 100644 index 0000000..e42fd8c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcsstr/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = wcsstr +Name = Positive Test for wcsstr +TYPE = DEFAULT +EXE1 = test1 +Description += Tests that wcsstr correctly find substrings in wide stings, including += returning NULL when the substring can't be found. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test1/CMakeLists.txt new file mode 100644 index 0000000..1087e11 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcstod_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcstod_test1 coreclrpal) + +target_link_libraries(paltest_wcstod_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test1/test1.cpp new file mode 100644 index 0000000..e41e92e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test1/test1.cpp @@ -0,0 +1,79 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests wcstod with a number of sample strings. +** +** +**===================================================================*/ + +#include + +struct testCase +{ + double CorrectResult; + char string[20]; + int stopChar; +}; + +struct testCase testCases[] = +{ + {1234,"1234", 4}, + {-1234,"-1234", 5}, + {1234.44,"1234.44", 7}, + {1234e-5,"1234e-5", 7}, + {1234e+5,"1234e+5", 7}, + {1234E5,"1234E5", 6}, + {1234.657e-8, "1234.657e-8", 11}, + {0, "1e-800", 6}, + {0, "-1e-800", 7}, + {1234567e-8, " 1234567e-8 foo", 13}, + {0, " foo 32 bar", 0}, +}; + +int __cdecl main(int argc, char **argv) +{ + WCHAR *wideStr; + WCHAR *endptr; + double result; + int i; + + if (PAL_Initialize(argc,argv)) + { + return FAIL; + } + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + wideStr = convert(testCases[i].string); + result = wcstod(wideStr, &endptr); + + if (testCases[i].CorrectResult != result) + { + free(wideStr); + Fail("ERROR: wcstod misinterpreted \"%s\" as %g instead of " + "%g.\n", + testCases[i].string, + result, + testCases[i].CorrectResult); + } + + if (endptr != wideStr + testCases[i].stopChar) + { + free(wideStr); + Fail("ERROR: wcstod stopped scanning \"%s\" at %p, " + "instead of %p!\n", testCases[i].string, endptr, + wideStr + testCases[i].stopChar); + } + + free(wideStr); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test1/testinfo.dat new file mode 100644 index 0000000..19da0b5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = wcstod +Name = Positive Test for wcstod +TYPE = DEFAULT +EXE1 = test1 +Description += Tests wcstod with a number of sample strings. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test2/CMakeLists.txt new file mode 100644 index 0000000..7684032 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_wcstod_test2 + ${SOURCES} +) + +add_dependencies(paltest_wcstod_test2 coreclrpal) + +target_link_libraries(paltest_wcstod_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test2/test2.cpp new file mode 100644 index 0000000..8f9b5cb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test2/test2.cpp @@ -0,0 +1,59 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Tests wcstod with overflows +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + /* Representation of positive infinty for a IEEE 64-bit double */ + INT64 PosInifity = (INT64)(0x7ff00000) << 32; + double HugeVal = *(double*) &PosInifity; + char *PosStr = "1E+10000"; + char *NegStr = "-1E+10000"; + WCHAR *wideStr; + double result; + + + if (PAL_Initialize(argc,argv)) + { + return FAIL; + } + + wideStr = convert(PosStr); + result = wcstod(wideStr, NULL); + free(wideStr); + + if (result != HugeVal) + { + Fail("ERROR: wcstod interpreted \"%s\" as %g instead of %g\n", + PosStr, result, HugeVal); + } + + + + wideStr = convert(NegStr); + result = wcstod(wideStr, NULL); + free(wideStr); + + if (result != -HugeVal) + { + Fail("ERROR: wcstod interpreted \"%s\" as %g instead of %g\n", + NegStr, result, -HugeVal); + } + + + PAL_Terminate(); + + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test2/testinfo.dat new file mode 100644 index 0000000..bf41e97 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstod/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = wcstod +Name = Positive Test for wcstod +TYPE = DEFAULT +EXE1 = test2 +Description += Tests wcstod with overflows + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/test1/CMakeLists.txt new file mode 100644 index 0000000..5e30ed3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcstok_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcstok_test1 coreclrpal) + +target_link_libraries(paltest_wcstok_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/test1/test1.cpp new file mode 100644 index 0000000..76d7dc0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/test1/test1.cpp @@ -0,0 +1,114 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Search for a number of tokens within strings. Check that the return values +** are what is expected, and also that the strings match up with our expected +** results. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + /* foo bar baz */ + WCHAR str[] = {'f','o','o',' ','b','a','r',' ','b','a','z','\0'}; + + /* foo \0ar baz */ + WCHAR result1[] = {'f','o','o',' ','\0','a','r',' ','b','a','z','\0'}; + + /* foo \0a\0 baz */ + WCHAR result2[] = {'f','o','o',' ','\0','a','\0',' ','b','a','z','\0'}; + + WCHAR* tempString; + int len = 0; + WCHAR *ptr; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + len = (wcslen(str)*sizeof(WCHAR)) + 2; + + /* Tokenize 'str'. It will hit the 'b' delimiter first. Check to see + that the ptr is pointing to the start of the string and do a compare + to ensure the tokenized string is what we expected. + */ + + tempString = convert("bz"); + ptr = wcstok(str, tempString); + free(tempString); + + if (ptr != str) + { + Fail("ERROR: Expected wcstok() to return %p, got %p!\n", str, ptr); + } + + if (memcmp(str, result1, len) != 0) + { + Fail("ERROR: wcstok altered the string in an unexpected fashion."); + } + + /* If NULL is passed as the first parameter, wcstok will continue + tokenizing the same string. Test that this works properly. + */ + tempString = convert("r "); + ptr = wcstok(NULL, tempString); + free(tempString); + + if (ptr != str + 5) + { + Fail("ERROR: Expected wcstok() to return %p, got %p!\n", str+5, ptr); + } + + if (memcmp(str, result2, len) != 0) + { + Fail("ERROR: wcstok altered the string in an unexpected fashion."); + } + + /* Continue onward, and search for 'X' now, which won't be found. The + pointer should point just after the last NULL in the string. And + the string itself shouldn't have changed. + */ + tempString = convert("X"); + ptr = wcstok(NULL, tempString); + free(tempString); + + if (ptr != str + 7) + { + Fail("ERROR: Expected wcstok() to return %p, got %p!\n", str + 7, ptr); + } + + if (memcmp(str, result2, len) != 0) + { + Fail("ERROR: wcstok altered the string in an unexpeced fashion.\n"); + } + + /* Call wcstok again. Now the ptr should point to the end of the + string at NULL. And the string itself shouldn't have changed. + */ + tempString = convert("X"); + ptr = wcstok(NULL, tempString); + free(tempString); + + if (ptr != NULL) + { + Fail("ERROR: Expected wcstok() to return %p, got %p!\n", NULL, ptr); + } + + if (memcmp(str, result2, len) != 0) + { + Fail("ERROR: wcstok altered the string in an unexpeced fashion.\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/test1/testinfo.dat new file mode 100644 index 0000000..cc00844 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstok/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = wcstok +Name = wcstok test- tokenize a string and ensure the string takes correct form. +TYPE = DEFAULT +EXE1 = test1 +Description += Search for a number of tokens within strings. Check that the return values += are what is expect, and also that the strings match up with our expected += results. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/CMakeLists.txt new file mode 100644 index 0000000..828a287 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/CMakeLists.txt @@ -0,0 +1,7 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test1/CMakeLists.txt new file mode 100644 index 0000000..7157a2a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wcstoul_test1 + ${SOURCES} +) + +add_dependencies(paltest_wcstoul_test1 coreclrpal) + +target_link_libraries(paltest_wcstoul_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.cpp new file mode 100644 index 0000000..5274905 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Test #1 for the wcstoul function +** +** +**==========================================================================*/ +#include + +/* + * Notes: wcstoul should depend on the current locale's LC_NUMERIC category, + * this is not currently tested. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR teststr[] = {'1','2','3','4','5',0}; + WCHAR *end; + ULONG result = 27; + ULONG l; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + l = wcstoul(teststr, &end, 4); + + if (l != result) + { + Fail("ERROR: Expected wcstoul to return %u, got %u\n", result, l); + } + + if (end != teststr + 3) + { + Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", + teststr + 3, end); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test1/testinfo.dat new file mode 100644 index 0000000..af4fb7e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = wcstoul +Name = Positive Test for wcstoul +TYPE = DEFAULT +EXE1 = test1 +Description += Tests wcstoul with base 4 and a string that includes some invalid characters. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test2/CMakeLists.txt new file mode 100644 index 0000000..3044234 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_wcstoul_test2 + ${SOURCES} +) + +add_dependencies(paltest_wcstoul_test2 coreclrpal) + +target_link_libraries(paltest_wcstoul_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.cpp new file mode 100644 index 0000000..07a020e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Test #2 for the wcstoul function +** +** +**==========================================================================*/ +#include + +/* + * Notes: wcstoul should depend on the current locale's LC_NUMERIC category, + * this is not currently tested. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR teststr[] = {'1','2','3','4','5',0}; + WCHAR *end; + ULONG result = 12345; + ULONG l; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + l = wcstoul((char16_t*)teststr, &end, 10); + + if (l != result) + { + Fail("ERROR: Expected wcstoul to return %u, got %u\n", result, l); + } + + if (end != teststr + 5) + { + Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", + teststr + 5, end); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test2/testinfo.dat new file mode 100644 index 0000000..b7e301f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = wcstoul +Name = Positive Test for wcstoul +TYPE = DEFAULT +EXE1 = test2 +Description += Tests wcstoul with base 10 and a completely valid string. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test3/CMakeLists.txt new file mode 100644 index 0000000..30de231 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_wcstoul_test3 + ${SOURCES} +) + +add_dependencies(paltest_wcstoul_test3 coreclrpal) + +target_link_libraries(paltest_wcstoul_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.cpp new file mode 100644 index 0000000..eac4661 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Test #3 for the wcstoul function +** +** +**==========================================================================*/ +#include + +/* + * Notes: wcstoul should depend on the current locale's LC_NUMERIC category, + * this is not currently tested. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR str[] = {'Z',0}; + WCHAR *end; + ULONG l; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + l = wcstoul(str, &end, 10); + + if (l != 0) + { + Fail("ERROR: Expected wcstoul to return %u, got %u\n", 0, l); + } + + if (end != str) + { + Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", + str, end); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test3/testinfo.dat new file mode 100644 index 0000000..f7f6302 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = wcstoul +Name = Positive Test for wcstoul +TYPE = DEFAULT +EXE1 = test3 +Description += Tests wcstoul with a completely invalid string (base 10). diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test4/CMakeLists.txt new file mode 100644 index 0000000..1be7efd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_wcstoul_test4 + ${SOURCES} +) + +add_dependencies(paltest_wcstoul_test4 coreclrpal) + +target_link_libraries(paltest_wcstoul_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.cpp new file mode 100644 index 0000000..0261da4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Test #4 for the wcstoul function +** +** +**==========================================================================*/ +#include + +/* + * Notes: wcstoul should depend on the current locale's LC_NUMERIC category, + * this is not currently tested. + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR maxstr[] = {'4','2','9','4','9','6','7','2','9','5',0}; + ULONG max = 4294967295ul; + WCHAR *end; + ULONG l; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + errno = 0; + + l = wcstoul(maxstr, &end, 10); + if (l != max) + { + Fail("ERROR: Expected wcstoul to return %u, got %u\n", max, l); + } + if (end != maxstr + 10) + { + Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", + maxstr + 10, end); + } + if (errno != 0) + { + Fail("ERROR: wcstoul set errno to non-zero (%d)\n", errno); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test4/testinfo.dat new file mode 100644 index 0000000..301178b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test4/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = wcstoul +Name = Positive Test for wcstoul +TYPE = DEFAULT +EXE1 = test4 +Description += Tests wcstoul with base 10 and the highest possible value. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test5/CMakeLists.txt new file mode 100644 index 0000000..fde5be4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_wcstoul_test5 + ${SOURCES} +) + +add_dependencies(paltest_wcstoul_test5 coreclrpal) + +target_link_libraries(paltest_wcstoul_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.cpp new file mode 100644 index 0000000..a24123a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.cpp @@ -0,0 +1,69 @@ +// 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. + +/*============================================================================ +** +** Source: test5.c +** +** Purpose: Test #5 for the wcstoul function +** +** +**==========================================================================*/ +#include + +/* + * Notes: wcstoul should depend on the current locale's LC_NUMERIC category, + * this is not currently tested. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR overstr[] = {'4','2','9','4','9','6','7','2','9','6',0}; + WCHAR understr[] = {'-','1',0}; + WCHAR *end; + ULONG l; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + errno = 0; + l = wcstoul(overstr, &end, 10); + + if (l != _UI32_MAX) + { + Fail("ERROR: Expected wcstoul to return %u, got %u\n", _UI32_MAX, l); + } + if (end != overstr + 10) + { + Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", + overstr + 10, end); + } + if (errno != ERANGE) + { + Fail("ERROR: wcstoul did not set errno to ERANGE (%d)\n", errno); + } + + errno = 0; + l = wcstoul(understr, &end, 10); + + if (l != _UI32_MAX) + { + Fail("ERROR: Expected wcstoul to return %u, got %u\n", _UI32_MAX, l); + } + if (end != understr + 2) + { + Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", + understr + 2, end); + } + if (errno != 0) + { + Fail("ERROR: wcstoul set errno to non-zero (%d)\n", errno); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test5/testinfo.dat new file mode 100644 index 0000000..bf7b2b6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test5/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = wcstoul +Name = Positive Test for wcstoul +TYPE = DEFAULT +EXE1 = test5 +Description += Tests wcstoul (base 10) with underflowing and overflowing. += Chesks that errno gets set to ERANGE. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test6/CMakeLists.txt new file mode 100644 index 0000000..199744c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_wcstoul_test6 + ${SOURCES} +) + +add_dependencies(paltest_wcstoul_test6 coreclrpal) + +target_link_libraries(paltest_wcstoul_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.cpp new file mode 100644 index 0000000..28397ec --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.cpp @@ -0,0 +1,83 @@ +// 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. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose: Test #6 for the wcstoul function. Tests strings with octal/hex +** number specifers +** +** +**==========================================================================*/ +#include + + +/* + * Notes: wcstoul should depend on the current locale's LC_NUMERIC category, + * this is not currently tested. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR test1[] = {'0','x','1','2', 0}; + WCHAR test2[] = {'0','1','2',0}; + WCHAR *end; + ULONG l; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + l = wcstoul(test1, &end, 16); + if (l != 0x12) + { + Fail("ERROR: Expected wcstoul to return %u, got %u\n", 0x12, l); + } + if (end != test1 + 4) + { + Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", + test1 + 4, end); + } + + l = wcstoul(test1, &end, 10); + if (l != 0) + { + Fail("ERROR: Expected wcstoul to return %u, got %u\n", 0, l); + } + if (end != test1+1) + { + Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", + test1+1, end); + } + + l = wcstoul(test2, &end, 8); + if (l != 10) + { + Fail("ERROR: Expected wcstoul to return %u, got %u\n", 10, l); + } + if (end != test2 + 3) + { + Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", + test2 + 3, end); + } + + l = wcstoul(test2, &end, 10); + if (l != 12) + { + Fail("ERROR: Expected wcstoul to return %u, got %u\n", 12, l); + } + + if (end != test2 + 3) + { + Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", + test2 + 3, end); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test6/testinfo.dat new file mode 100644 index 0000000..40e18d5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wcstoul/test6/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = wcstoul +Name = Positive Test for wcstoul +TYPE = DEFAULT +EXE1 = test6 +Description += Tests wcstoul with hex and octal strings, with different bases. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test1/CMakeLists.txt new file mode 100644 index 0000000..63b44d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_wprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_wprintf_test1 coreclrpal) + +target_link_libraries(paltest_wprintf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test1/test1.cpp new file mode 100644 index 0000000..d99dc8c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test1/test1.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Test #1 for the wprintf function. A single, basic, test +** case with no formatting. +** +** +**==========================================================================*/ + + + +#include +#include "../wprintf.h" + +int __cdecl main(int argc, char *argv[]) +{ + char checkstr[] = "hello world"; + WCHAR *wcheckstr; + int ret; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + wcheckstr = convert(checkstr); + + ret = wprintf(wcheckstr); + + if (ret != wcslen(wcheckstr)) + { + Fail("Expected wprintf to return %d, got %d.\n", + wcslen(wcheckstr), ret); + + } + + free(wcheckstr); + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test1/testinfo.dat new file mode 100644 index 0000000..0294636 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = wprintf +Name = Positive Test for wprintf +TYPE = DEFAULT +EXE1 = test1 +Description += General test to see if wprintf works correctly diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test2/CMakeLists.txt new file mode 100644 index 0000000..bd529b7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_wprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_wprintf_test2 coreclrpal) + +target_link_libraries(paltest_wprintf_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test2/test2.cpp new file mode 100644 index 0000000..4e54d45 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test2/test2.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Test #2 for the wprintf function. Tests the string specifier +** (%s). +** +** +**==========================================================================*/ + + +#include +#include "../wprintf.h" + + + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoStrTest(u"foo %s", u"bar", u"foo bar"); + DoStrTest(u"foo %ws", u"bar", u"foo bar"); + DoStrTest(u"foo %ls", u"bar", u"foo bar"); + DoStrTest(u"foo %ws", u"bar", u"foo bar"); + DoStrTest(u"foo %Ls", u"bar", u"foo bar"); + DoStrTest(u"foo %I64s", u"bar", u"foo bar"); + DoStrTest(u"foo %5s", u"bar", u"foo bar"); + DoStrTest(u"foo %.2s", u"bar", u"foo ba"); + DoStrTest(u"foo %5.2s", u"bar", u"foo ba"); + DoStrTest(u"foo %-5s", u"bar", u"foo bar "); + DoStrTest(u"foo %05s", u"bar", u"foo 00bar"); + DoStrTest(u"foo %s", NULL, u"foo (null)"); + DoStrTest(u"foo %hs", NULL, u"foo (null)"); + DoStrTest(u"foo %ls", NULL, u"foo (null)"); + DoStrTest(u"foo %ws", NULL, u"foo (null)"); + DoStrTest(u"foo %Ls", NULL, u"foo (null)"); + DoStrTest(u"foo %I64s", NULL, u"foo (null)"); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test2/testinfo.dat new file mode 100644 index 0000000..7808c06 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = C Runtime +Function = wprintf +Name = Positive Test for wprintf +TYPE = DEFAULT +EXE1 = test2 +Description += Tests wprintf with strings diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/wprintf.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/wprintf.h new file mode 100644 index 0000000..3a96248 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/c_runtime/wprintf/wprintf.h @@ -0,0 +1,171 @@ +// 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. + +/*============================================================================ +** +** Source: wprintf.h +** +** Purpose: Containts common testing functions for wprintf +** +** +**==========================================================================*/ + +#ifndef __wprintf_H__ +#define __wprintf_H__ + +void DoStrTest(const WCHAR *formatstr, const WCHAR *param, const WCHAR *checkstr) +{ + int ret; + + ret = wprintf(formatstr, param); + if (ret != wcslen(checkstr)) + { + Fail("DoStrTest:Expected wprintf to return %d, got %d.\n", + wcslen(checkstr), ret); + } +} + + +void DoPointerTest(const WCHAR *formatstr, void* param, WCHAR* paramstr, + const WCHAR *checkstr1) +{ + int ret; + + ret = wprintf(formatstr, param); + if (ret != wcslen(checkstr1)) + { + Fail("DoPointerTest:Expected wprintf to return %d, got %d.\n", + wcslen(checkstr1), ret); + } +} + +void DoCountTest(const WCHAR *formatstr, int param, const WCHAR *checkstr) +{ + int ret; + int n = -1; + + ret = wprintf(formatstr, &n); + + if (n != param) + { + Fail("DoCountTest:Expected count parameter to resolve to %d, got %d\n", param, n); + } + + if (ret != wcslen(checkstr)) + { + Fail("DoCountTest:Expected wprintf to return %d, got %d.\n", + wcslen(checkstr), ret); + } +} + +void DoShortCountTest(const WCHAR *formatstr, int param, const WCHAR *checkstr) +{ + int ret; + short int n = -1; + + ret = wprintf(formatstr, &n); + + if (n != param) + { + Fail("DoShortCountTest:Expected count parameter to resolve to %d, got %d\n", param, n); + } + + if (ret != wcslen(checkstr)) + { + Fail("DoShortCountTest:Expected wprintf to return %d, got %d.\n", + wcslen(checkstr), ret); + } +} + + +void DoCharTest(const WCHAR *formatstr, WCHAR param, const WCHAR *checkstr) +{ + int ret; + + ret = wprintf(formatstr, param); + if (ret != wcslen(checkstr)) + { + Fail("DoCharTest:Expected wprintf to return %d, got %d.\n", + wcslen(checkstr), ret); + } +} + +void DoWCharTest(const WCHAR *formatstr, WCHAR param, const WCHAR *checkstr) +{ + int ret; + + ret = wprintf(formatstr, param); + if (ret != wcslen(checkstr)) + { + Fail("DoWCharTest:Expected wprintf to return %d, got %d.\n", + wcslen(checkstr), ret); + } +} + +void DoNumTest(const WCHAR *formatstr, int param, const WCHAR *checkstr) +{ + int ret; + + ret = wprintf(formatstr, param); + if (ret != wcslen(checkstr)) + { + Fail("DoNumTest:Expected wprintf to return %d, got %d.\n", + wcslen(checkstr), ret); + } +} + +void DoI64Test(const WCHAR *formatstr, INT64 param, const WCHAR *valuestr, + const WCHAR *checkstr1) +{ + int ret; + + ret = wprintf(formatstr, param); + if (ret != wcslen(checkstr1)) + { + Fail("DoI64Test:Expected wprintf to return %d, got %d.\n", + wcslen(checkstr1), ret); + } +} + +void DoDoubleTest(const WCHAR *formatstr, double param, + const WCHAR *checkstr1, const WCHAR *checkstr2) +{ + int ret; + + ret = wprintf(formatstr, param); + if (ret != wcslen(checkstr1) && ret != wcslen(checkstr2)) + { + Fail("DoDoubleTest:Expected wprintf to return %d or %d, got %d.\n", + wcslen(checkstr1), wcslen(checkstr2), ret); + } +} + +void DoArgumentPrecTest(const WCHAR *formatstr, int precision, void *param, + WCHAR *paramstr, const WCHAR *checkstr1, const WCHAR *checkstr2) +{ + int ret; + + ret = wprintf(formatstr, precision, param); + if (ret != wcslen(checkstr1) && ret != wcslen(checkstr2)) + { + Fail("DoArgumentPrecTest:Expected wprintf to return %d or %d, got %d.\n", + wcslen(checkstr1), wcslen(checkstr2), ret); + } +} + +void DoArgumentPrecDoubleTest(const WCHAR *formatstr, int precision, double param, + const WCHAR *checkstr1, const WCHAR *checkstr2) +{ + int ret; + + ret = wprintf(formatstr, precision, param); + if (ret != wcslen(checkstr1) && ret != wcslen(checkstr2)) + { + Fail("DoArgumentPrecDoubleTest:Expected wprintf to return %d or %d, got %d.\n", + wcslen(checkstr1), wcslen(checkstr2), ret); + } +} + +#endif + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/ResultBuffer.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/ResultBuffer.cpp new file mode 100644 index 0000000..e38c324 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/ResultBuffer.cpp @@ -0,0 +1,69 @@ +// 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. + +//#include "stdafx.h" +#include "resultbuffer.h" +// +//#using +// +//using namespace System; + + +ResultBuffer:: ResultBuffer(int ThreadCount, int ThreadLogSize) + { + // Declare an internal status variable + int Status=0; + + // Update the maximum thread count + MaxThreadCount = ThreadCount; + + // Allocate the memory buffer based on the passed in thread and process counts + // and the specified size of the thread specific buffer + buffer = NULL; + buffer = (char*)malloc(ThreadCount*ThreadLogSize); + // Check to see if the buffer memory was allocated + if (buffer == NULL) + Status = -1; + // Initialize the buffer to 0 to prevent bogus data + memset(buffer,0,ThreadCount*ThreadLogSize); + + // The ThreadOffset is equal to the total number of bytes that will be stored per thread + ThreadOffset = ThreadLogSize; + + } + + + int ResultBuffer::LogResult(int Thread, char* Data) + { + // Declare an internal status flad + int status = 0; + + // Declare an object to store the offset address into the buffer + int Offset; + + // Check to make sure the Thread index is not out of range + if(Thread > MaxThreadCount) + { + Trace("Thread index is out of range, Value of Thread[%d], Value of MaxThreadCount[%d]\n", Thread, MaxThreadCount); + status = -1; + return(status); + } + + // Caculate the offset into the shared buffer based on the process and thread indices + Offset = (Thread)*ThreadOffset; + + // Write the passed in data to the reserved buffer + memcpy(buffer+Offset,Data,ThreadOffset); + + return(status); + } + + + char* ResultBuffer::getResultBuffer(int threadId) + { + + return (buffer + threadId*ThreadOffset); + + } + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/ResultBuffer.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/ResultBuffer.h new file mode 100644 index 0000000..c59d421 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/ResultBuffer.h @@ -0,0 +1,43 @@ +// 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. + +//#include +//#include +//#include +#ifndef _RESULT_BUFFER_H_ +#define _RESULT_BUFFER_H_ + +#include + +struct ResultData +{ + int value; + int size; +// ResultData* NextResult; +}; + + class ResultBuffer +{ + // Declare a pointer to a memory buffer to store the logged results + char* buffer; + // Declare an object to store the maximum Thread count + int MaxThreadCount; + // Declare and internal data object to store the calculated offset between adjacent threads data sets + int ThreadOffset; + + // Declare a linked list object to store the parameter values +public: + + // Declare a constructor for the single process case + ResultBuffer(int ThreadCount, int ThreadLogSize); + // Declare a method to log data for the single process instance + int LogResult(int Thread, char* Data); + + char* getResultBuffer(int threadId); +}; + +#include "resultbuffer.cpp" +#endif // _RESULT_BUFFER_H_ + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/ResultTime.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/ResultTime.h new file mode 100644 index 0000000..82daeb8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/ResultTime.h @@ -0,0 +1,83 @@ +// 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. + +#ifndef _RESULT_TIME_H_ +#define _RESULT_TIME_H_ + +#include + +#define DWORD_MAX ((DWORD) 0xFFFFFFFF) +const char *szDotNetInstallEnvVar = "DOTNET_INSTALL"; +const char *szQASupportDirEnvVar = "QA_SUPPORT_DIR"; + +#define SEPERATOR "/" +char *getBuildNumber() +{ + char *szBuildFileName = "buildinfo.txt"; + char *pDirectoryName = NULL; + char szBuildFileLoc[256]; + + char szTemp[100]; + // buildinfo.txt contains information in key/value pair + char szTempKey[100]; + char *szTempValue; + FILE *fp; + + szTempValue = (char *) malloc (sizeof(char) *100); + if (szTempValue == NULL) + { + Fail("ERROR: Couldn't allocate enough memory to potentially store build number\n"); + } + + pDirectoryName = getenv(szQASupportDirEnvVar); + if (pDirectoryName == NULL) + { + Trace("WARNING: Coriolis Test Environment may not be setup correctly. Variable QA_SUPPORT_DIR not set\n"); + _snprintf(szTempValue, 99, "0000.00"); + return szTempValue; + } + + // To avoid buffer overruns for pDirectoryName + _snprintf(szBuildFileLoc, MAX_PATH, "%s/../1.0%s%s", pDirectoryName, SEPERATOR, szBuildFileName); + fp = fopen( szBuildFileLoc, "r"); + if( fp == NULL) + { + Trace("WARNING: Couldn't open szBuildFileLoc [%s]\n", szBuildFileLoc); + _snprintf(szTempValue, 99, "0000.00"); + return szTempValue; + } + + while( fgets( szTemp, 100, fp ) != NULL) + { + sscanf(szTemp, "%s %s\n", szTempKey, szTempValue); + if(strcmp(szTempKey, "Build-Number:") == 0) + { + fclose(fp); + return szTempValue; + } + } + + fclose(fp); + return szTempValue; + +} + +DWORD GetTimeDiff( DWORD dwStartTime) +{ + DWORD dwDiffTime = 0; + DWORD dwEndTime = GetTickCount(); + + if( dwEndTime < dwStartTime) + { + // To account for overflow, we add one + dwDiffTime = dwEndTime + (DWORD_MAX - dwStartTime) + 1; + } + else + { + dwDiffTime = dwEndTime - dwStartTime; + } + + return dwDiffTime; +} +#endif // _RESULT_TIME_H_ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/pal_stdclib.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/pal_stdclib.h new file mode 100644 index 0000000..61963db --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/pal_stdclib.h @@ -0,0 +1,24 @@ +// 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. + +/*============================================================================ +** +** Source: pal_stdlib.h +** +** Purpose: +** +** +**==========================================================================*/ + + +#ifndef __PAL_STDCLIB_H__ +#define __PAL_STDCLIB_H__ + +/* + * definitions & functions + */ + +#define EOF (-1) + +#endif // __PAL_STDCLIB_H__ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/palsuite.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/palsuite.h new file mode 100644 index 0000000..8cc5018 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/common/palsuite.h @@ -0,0 +1,186 @@ +// 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. + +/*============================================================================ +** +** Source: palsuite.h +** +** Purpose: Define constants and implement functions that are useful to +** multiple function categories. If common functions are useful +** only amongst the test cases for a particular function, a separate +** header file is placed in the root of those test cases. +** +** +**==========================================================================*/ + +#ifndef __PALSUITE_H__ +#define __PALSUITE_H__ + +#ifndef __cplusplus +typedef unsigned short char16_t; +#endif + +#include +#include +#include + +enum +{ + PASS = 0, + FAIL = 1 +}; + + +void Trace(const char *format, ...) +{ + va_list arglist; + + va_start(arglist, format); + + vprintf(format, arglist); + + va_end(arglist); +} + +void Fail(const char *format, ...) +{ + va_list arglist; + + va_start(arglist, format); + + vprintf(format, arglist); + + va_end(arglist); + printf("\n"); + + // This will exit the test process + PAL_TerminateEx(FAIL); +} + +#ifdef PAL_PERF + +int __cdecl Test_Main(int argc, char **argv); +int PAL_InitializeResult = 0; +static const char PALTEST_LOOP_ENV[]="PALTEST_LOOP_COUNT"; + +int __cdecl main(int argc, char **argv) +{ + int lastMainResult=0; + + int loopCount=1; // default: run the test's main once + int loopIndex=0; + char *szPerfLoopEnv = NULL; + + // Run PAL_Initialize once, save off the result. Any failures here + // will be detected later by calls to PAL_Initialize in the test's main. + PAL_InitializeResult = PAL_Initialize(argc, argv); + + // Check the environment to see if we need to run the test's main + // multiple times. Ideally, we want to do this before PAL_Initialize so + // that the overhead of checking the environment is not included in the + // time between PAL_Initialize and PAL_Terminate. However, getenv in PAL + // can be run only after PAL_Initialize. + szPerfLoopEnv = getenv(PALTEST_LOOP_ENV); + if (szPerfLoopEnv != NULL) + { + loopCount = atoi(szPerfLoopEnv); + if (loopCount <= 0) loopCount = 1; + } + + // call the test's actual main in a loop + for(loopIndex=0; loopIndex> 24) | + ((x & 0x00FF0000L) >> 8) | + ((x & 0x0000FF00L) << 8) | + ((x & 0x000000FFL) << 24) ); +} +#define th_htons(w) (w) +#else // BIGENDIAN +#define VAL32(x) (x) +#define th_htons(w) (((w) >> 8) | ((w) << 8)) +#endif // BIGENDIAN + +#define _countof(_array) (sizeof(_array)/sizeof(_array[0])) + +WCHAR* convert(const char * aString) +{ + int size; + WCHAR* wideBuffer; + + size = MultiByteToWideChar(CP_ACP,0,aString,-1,NULL,0); + wideBuffer = (WCHAR*) malloc(size*sizeof(WCHAR)); + if (wideBuffer == NULL) + { + Fail("ERROR: Unable to allocate memory!\n"); + } + MultiByteToWideChar(CP_ACP,0,aString,-1,wideBuffer,size); + return wideBuffer; +} + +char* convertC(const WCHAR * wString) +{ + int size; + char * MultiBuffer = NULL; + + size = WideCharToMultiByte(CP_ACP,0,wString,-1,MultiBuffer,0,NULL,NULL); + MultiBuffer = (char*) malloc(size); + if (MultiBuffer == NULL) + { + Fail("ERROR: Unable to allocate memory!\n"); + } + WideCharToMultiByte(CP_ACP,0,wString,-1,MultiBuffer,size,NULL,NULL); + return MultiBuffer; +} + +UINT64 GetHighPrecisionTimeStamp(LARGE_INTEGER performanceFrequency) +{ + LARGE_INTEGER ts; + if (!QueryPerformanceCounter(&ts)) + { + Fail("ERROR: Unable to query performance counter!\n"); + } + + return ts.QuadPart / (performanceFrequency.QuadPart / 1000); +} + +#endif + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/CMakeLists.txt new file mode 100644 index 0000000..17d0105 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(object_management) +add_subdirectory(synchronization) +add_subdirectory(threading) +add_subdirectory(wfmo) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/CMakeLists.txt new file mode 100644 index 0000000..1786ba3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(event) +add_subdirectory(mutex) +add_subdirectory(semaphore) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/CMakeLists.txt new file mode 100644 index 0000000..4eeff15 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(nonshared) +add_subdirectory(shared) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/nonshared/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/nonshared/CMakeLists.txt new file mode 100644 index 0000000..666e5e8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/nonshared/CMakeLists.txt @@ -0,0 +1,15 @@ +set(SOURCES + event.cpp + main.cpp +) + +add_executable(paltest_event_nonshared + ${SOURCES} +) + +add_dependencies(paltest_event_nonshared coreclrpal) + +target_link_libraries(paltest_event_nonshared + ${COMMON_TEST_LIBRARIES} + rt +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/nonshared/event.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/nonshared/event.cpp new file mode 100644 index 0000000..69ad9a3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/nonshared/event.cpp @@ -0,0 +1,358 @@ +// 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. + +/*============================================================ +** +** Source Code: main.c and event.c +** main.c creates process and waits for all processes to get over +** event.c creates a event and then calls threads which will contend for the event +** +** This test is for Object Management Test case for event where Object type is shareable. +** Algorithm +** o Main Process Creates OBJECT_TYPE Object +** o Create PROCESS_COUNT processes aware of the Shared Object +** +** Author: ShamitP +** +** +**============================================================ +*/ + +#include +#include "resultbuffer.h" +#include "resulttime.h" + +#define TIMEOUT 5000 +/* Test Input Variables */ +unsigned int USE_PROCESS_COUNT = 0; +unsigned int THREAD_COUNT = 0; +unsigned int REPEAT_COUNT = 0; +unsigned int RELATION_ID= 0; + +/* Event variables */ +//unsigned long lInitialCount = 1; /* Signaled */ +//unsigned long lMaximumCount = 1; /* Maximum value of 1 */ + +/* Capture statistics at per thread basis */ +struct statistics{ + unsigned int processId; + unsigned int operationsFailed; + unsigned int operationsPassed; + unsigned int operationsTotal; + DWORD operationTime; + unsigned int relationId; +}; + +struct ProcessStats{ + unsigned int processId; + DWORD operationTime; + unsigned int relationId; +}; + +HANDLE StartTestsEvHandle = NULL; +HANDLE hEventHandle = NULL; + +/* Results Buffer */ +ResultBuffer *resultBuffer = NULL; + +int testStatus; + +const char sTmpEventName[MAX_PATH_FNAME] = "StartTestEvent"; + +void PALAPI Run_Thread(LPVOID lpParam); + +int GetParameters( int argc, char **argv) +{ + if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Object Management Event Test\n"); + printf("Usage:\n"); + printf("Event\n\t[USE_PROCESS_COUNT [greater than 1] \n"); + printf("\t[THREAD_COUNT [greater than 1] \n"); + printf("\t[REPEAT_COUNT [greater than 1]\n"); + printf("\t[RELATION_ID [greater than or Equal to 1]\n"); + + return -1; + } + + // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]); + + USE_PROCESS_COUNT = atoi(argv[1]); + if( USE_PROCESS_COUNT < 0) + { + printf("\nInvalid USE_PROCESS_COUNT number, Pass greater than 1\n"); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hThread[MAXIMUM_WAIT_OBJECTS]; + DWORD threadId[MAXIMUM_WAIT_OBJECTS]; + int returnCode = 0; + + DWORD dwParam = 0; + + /* Variables to capture the file name and the file pointer at thread level*/ + char fileName[MAX_LONGPATH]; + FILE *pFile = NULL; + struct statistics* buffer = NULL; + int statisticsSize = 0; + + /* Variables to capture the file name and the file pointer at process level*/ + char processFileName[MAX_LONGPATH]; + FILE *pProcessFile = NULL; + struct ProcessStats processStats; + DWORD dwStartTime; + + testStatus = PASS; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } +// Trace("Process created, value of process count is [%d]\n", USE_PROCESS_COUNT); + + /* Register the start time */ + dwStartTime = GetTickCount(); + processStats.relationId = RELATION_ID; + processStats.processId = USE_PROCESS_COUNT; + + _snprintf(processFileName, MAX_LONGPATH, "%d_process_event_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); + pProcessFile = fopen(processFileName, "w+"); + if(pProcessFile == NULL) + { + Fail("Error in opening process File file for write for process [%d]\n", USE_PROCESS_COUNT); + } + + statisticsSize = sizeof(struct statistics); + + _snprintf(fileName, MAX_LONGPATH, "%d_thread_event_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); + pFile = fopen(fileName, "w+"); + + if(pFile == NULL) + { + Fail("Error in opening thread File for write for process [%d]\n", USE_PROCESS_COUNT); + } + // For each thread we will log operations failed (int), passed (int), total (int) + // and number of ticks (DWORD) for the operations + resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize); + + StartTestsEvHandle = CreateEvent( + NULL, /* lpEventAttributes*/ + TRUE, /* bManualReset */ + FALSE, /* bInitialState */ + NULL /* name of Event */ + ); + + if( StartTestsEvHandle == NULL ) + { + Fail("Error:%d: Unexpected failure " + "to create %s Event for process count %d\n", GetLastError(), sTmpEventName, USE_PROCESS_COUNT ); + + } + + /* Create StartTest Event */ + + hEventHandle = CreateEvent( + NULL, /* lpEventAttributes, inheritable to child processes*/ + TRUE, /* bAutomaticReset */ + TRUE, /* bInitialState */ + NULL + ); + + if( hEventHandle == NULL) + { + Fail("Unable to create Event handle for process id [%d], returned error [%d]\n", i, GetLastError()); + } + /* We already assume that the Event was created previously*/ + + for( i = 0; i < THREAD_COUNT; i++ ) + { + dwParam = (int) i; + //Create thread + hThread[i] = CreateThread( + NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */ + (LPVOID)dwParam, /* argument to thread function */ + 0, /* use default creation flags */ + &threadId[i] /* returns the thread identifier*/ + ); + + + if(hThread[i] == NULL) + { + Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError()); + } + + } + + if (!SetEvent(StartTestsEvHandle)) + { + Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError()); + } + /* Test running */ + returnCode = WaitForMultipleObjects( THREAD_COUNT, hThread, TRUE, INFINITE); + + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError()); + testStatus = FAIL; + } + + processStats.operationTime = GetTimeDiff(dwStartTime); + + /* Write to a file*/ + if(pFile!= NULL) + { + for( i = 0; i < THREAD_COUNT; i++ ) + { + buffer = (struct statistics *)resultBuffer->getResultBuffer(i); + returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); + //Trace("Iteration %d over\n", i); + + } + } + if(fclose(pFile)) + { + Trace("Error: fclose failed for pFile\n"); + testStatus = FAIL; + } + + fprintf(pProcessFile, "%d,%d,%d\n", USE_PROCESS_COUNT, processStats.operationTime, processStats.relationId ); + if(fclose(pProcessFile)) + { + Trace("Error: fclose failed for pProcessFile at Process %d\n", USE_PROCESS_COUNT); + testStatus = FAIL; + } + + /* Logging for the test case over, clean up the handles */ + +// Trace("Test Thread %d done\n", USE_PROCESS_COUNT); + /* Clean Up */ + for( i = 0; i < THREAD_COUNT; i++ ) + { + if(!CloseHandle(hThread[i]) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i); + testStatus = FAIL; + } + } + + if(!CloseHandle(StartTestsEvHandle)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT); + testStatus = FAIL; + } + + if(!CloseHandle(hEventHandle)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hEventHandle\n", GetLastError(), USE_PROCESS_COUNT); + testStatus = FAIL; + } + + PAL_Terminate(); + return testStatus; + +} + +void PALAPI Run_Thread (LPVOID lpParam) +{ + unsigned int i = 0; + DWORD dwWaitResult; + + struct statistics stats; + DWORD dwStartTime; + + stats.relationId = RELATION_ID; + stats.processId = USE_PROCESS_COUNT; + stats.operationsFailed = 0; + stats.operationsPassed = 0; + stats.operationsTotal = 0; + stats.operationTime = 0; + + int Id=(int)lpParam; + + dwWaitResult = WaitForSingleObject( + StartTestsEvHandle, // handle to start test handle + TIMEOUT); + + if(dwWaitResult != WAIT_OBJECT_0) + { + Fail("Error while waiting for StartTest Event@ thread %d, RC is %d, Error is %d\n", Id, dwWaitResult, GetLastError()); + } + + dwStartTime = GetTickCount(); + + for( i = 0; i < REPEAT_COUNT; i++ ) + { + dwWaitResult = WaitForSingleObject( + hEventHandle, // handle to Event + TIMEOUT); + + if(dwWaitResult != WAIT_OBJECT_0) + { +// Trace("Error while waiting for onject @ thread %d, # iter %d, RC is %d, Error is %d\n", Id, i, dwWaitResult, GetLastError()); + stats.operationsFailed += 1; + stats.operationsTotal += 1; + testStatus = FAIL; + continue; + } + + if (! SetEvent(hEventHandle)) + { + // Deal with error. +// Trace("Error while setting Event @ thread %d # iter %d\n", Id, i); + stats.operationsFailed += 1; + stats.operationsTotal += 1; + // Do we need to have while true loop to attempt to set event? + testStatus = FAIL; + continue; + } + + stats.operationsTotal += 1; + stats.operationsPassed += 1; +// Trace("Successs while setting Event @ iteration %d -> thread %d -> Process %d\n", i, Id, USE_PROCESS_COUNT); + + } + + stats.operationTime = GetTimeDiff(dwStartTime); + if(resultBuffer->LogResult(Id, (char *)&stats)) + { + Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT); + } + //Trace("Thread %d over for process %d\n", Id, USE_PROCESS_COUNT); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/nonshared/main.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/nonshared/main.cpp new file mode 100644 index 0000000..7b61e91 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/nonshared/main.cpp @@ -0,0 +1,228 @@ +// 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. + +/*============================================================ +** +** Source Code: main.c and event.c +** main.c creates process and waits for all processes to get over +** event.c creates a event and then calls threads which will contend for the event +** +** This test is for Object Management Test case for event where Object type is not shareable. +** Algorithm +** o Create PROCESS_COUNT processes. +** o Main Thread of each process creates OBJECT_TYPE Object +** +** Author: ShamitP +**============================================================ +*/ + +#include +#include "resulttime.h" + +/* Test Input Variables */ +unsigned int PROCESS_COUNT = 10; +unsigned int THREAD_COUNT = 20; +unsigned int REPEAT_COUNT = 20000; +unsigned int RELATION_ID = 1001; + + +struct TestStats{ + DWORD operationTime; + unsigned int relationId; + unsigned int processCount; + unsigned int threadCount; + unsigned int repeatCount; + char* buildNumber; + +}; + + +int GetParameters( int argc, char **argv) +{ + if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Object Management event Test\n"); + printf("Usage:\n"); + printf("main\n\t[PROCESS_COUNT [greater than 1] \n"); + printf("\t[THREAD_COUNT [greater than 1] \n"); + printf("\t[REPEAT_COUNT [greater than 1]\n"); + printf("\t[RELATION_ID [greater than or Equal to 1]\n"); + return -1; + } + + PROCESS_COUNT = atoi(argv[1]); + if( (PROCESS_COUNT < 1) || (PROCESS_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 1 and less than PROCESS_COUNT %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hProcess[MAXIMUM_WAIT_OBJECTS]; + + STARTUPINFO si[MAXIMUM_WAIT_OBJECTS]; + PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS]; + + char lpCommandLine[MAX_LONGPATH] = ""; + const char *ObjName = "Event"; + + int returnCode = 0; + DWORD processReturnCode = 0; + int testReturnCode = PASS; + + char fileName[MAX_LONGPATH]; + FILE *pFile = NULL; + DWORD dwStartTime = 0; + struct TestStats testStats; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } + + /* Register the start time */ + dwStartTime = GetTickCount(); + testStats.relationId = RELATION_ID; + testStats.processCount = PROCESS_COUNT; + testStats.threadCount = THREAD_COUNT; + testStats.repeatCount = REPEAT_COUNT; + testStats.buildNumber = getBuildNumber(); + + + _snprintf(fileName, MAX_LONGPATH, "main_event_%d_.txt", RELATION_ID); + pFile = fopen(fileName, "w+"); + if(pFile == NULL) + { + Fail("Error in opening main file for write\n"); + } + + for( i = 0; i < PROCESS_COUNT; i++ ) + { + + ZeroMemory( lpCommandLine, MAX_PATH ); + if ( _snprintf( lpCommandLine, MAX_LONGPATH-1, "event %d %d %d %d", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID) < 0 ) + { + Fail ("Error: Insufficient Event name string length for %s for iteration [%d]\n", ObjName, i); + } + + /* Zero the data structure space */ + ZeroMemory ( &pi[i], sizeof(pi[i]) ); + ZeroMemory ( &si[i], sizeof(si[i]) ); + + /* Set the process flags and standard io handles */ + si[i].cb = sizeof(si[i]); + + //Create Process + if(!CreateProcess( NULL, /* lpApplicationName*/ + lpCommandLine, /* lpCommandLine */ + NULL, /* lpProcessAttributes */ + NULL, /* lpThreadAttributes */ + TRUE, /* bInheritHandles */ + 0, /* dwCreationFlags, */ + NULL, /* lpEnvironment */ + NULL, /* pCurrentDirectory */ + &si[i], /* lpStartupInfo */ + &pi[i] /* lpProcessInformation */ + )) + { + Fail("Process Not created for [%d], the error code is [%d]\n", i, GetLastError()); + } + else + { + hProcess[i] = pi[i].hProcess; + //Trace("Process created for [%d]\n", i); + + } + + } + + returnCode = WaitForMultipleObjects( PROCESS_COUNT, hProcess, TRUE, INFINITE); + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", PROCESS_COUNT, returnCode, GetLastError()); + testReturnCode = FAIL; + } + + for( i = 0; i < PROCESS_COUNT; i++ ) + { + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) ) + { + Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n", + i, GetLastError() ); + + testReturnCode = FAIL; + } + + if(processReturnCode == FAIL) + { + Trace( "Process [%d] failed and returned FAIL\n", i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hThread)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hProcess) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i); + testReturnCode = FAIL; + } + } + + testStats.operationTime = GetTimeDiff(dwStartTime); + fprintf(pFile, "%d,%d,%d,%d,%d,%s\n", testStats.operationTime, testStats.relationId, testStats.processCount, testStats.threadCount, testStats.repeatCount, testStats.buildNumber); + if(fclose(pFile)) + { + Trace("Error: fclose failed for pFile\n"); + testReturnCode = FAIL; + } + + if( testReturnCode == PASS) + { + Trace("Test Passed\n"); + } + else + { + Trace("Test Failed\n"); + } + PAL_Terminate(); + return testReturnCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/shared/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/shared/CMakeLists.txt new file mode 100644 index 0000000..008739c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/shared/CMakeLists.txt @@ -0,0 +1,15 @@ +set(SOURCES + event.cpp + main.cpp +) + +add_executable(paltest_event_shared + ${SOURCES} +) + +add_dependencies(paltest_event_shared coreclrpal) + +target_link_libraries(paltest_event_shared + ${COMMON_TEST_LIBRARIES} + rt +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/shared/event.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/shared/event.cpp new file mode 100644 index 0000000..83d5fce --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/shared/event.cpp @@ -0,0 +1,373 @@ +// 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. + +/*============================================================ +** +** Source Code: main.c and event.c +** main.c creates process and waits for all processes to get over +** event.c creates a event and then calls threads which will contend for the event +** +** This test is for Object Management Test case for event where Object type is shareable. +** Algorithm +** o Main Process Creates OBJECT_TYPE Object +** o Create PROCESS_COUNT processes aware of the Shared Object +** +** Author: ShamitP +** Author: ShamitP +** +** +**============================================================ +*/ + +#include +#include "resultbuffer.h" +#include "resulttime.h" + +#define TIMEOUT 5000 +/* Test Input Variables */ +unsigned int USE_PROCESS_COUNT = 0; +unsigned int THREAD_COUNT = 0; +unsigned int REPEAT_COUNT = 0; +unsigned int RELATION_ID = 0; + +/* Capture statistics at per thread basis */ +struct statistics{ + unsigned int processId; + unsigned int operationsFailed; + unsigned int operationsPassed; + unsigned int operationsTotal; + DWORD operationTime; + unsigned int relationId; +}; + +struct ProcessStats{ + unsigned int processId; + DWORD operationTime; + unsigned int relationId; +}; + +HANDLE StartTestsEvHandle = NULL; +HANDLE hEventHandle = NULL; + +/* Results Buffer */ +ResultBuffer *resultBuffer= NULL; + +int testStatus; + +const char sTmpEventName[MAX_PATH] = "StartTestEvent"; +char objectSuffix[MAX_PATH]; + +void PALAPI Run_Thread(LPVOID lpParam); + +int GetParameters( int argc, char **argv) +{ + if( (!((argc == 5) || (argc == 6) ) )|| ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Object Management event Test\n"); + printf("Usage:\n"); + printf("main\n\t[USE_PROCESS_COUNT (greater than 1)] \n"); + printf("\t[THREAD_COUNT (greater than 1)] \n"); + printf("\t[REPEAT_COUNT (greater than 1)]\n"); + printf("\t[RELATION_ID [greater than or equal to 1]\n"); + printf("\t[Object Name Suffix]\n"); + + return -1; + } + + // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]); + + USE_PROCESS_COUNT = atoi(argv[1]); + if( USE_PROCESS_COUNT < 0) + { + printf("\nInvalid USE_PROCESS_COUNT number, Pass greater than 1\n"); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + if(argc == 6) + { + strncpy(objectSuffix, argv[5], MAX_PATH-1); + } + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hThread[MAXIMUM_WAIT_OBJECTS]; + DWORD threadId[MAXIMUM_WAIT_OBJECTS]; + + WCHAR *wcObjName = NULL; + + char ObjName[MAX_PATH] = "SHARED_EVENT"; + DWORD dwParam = 0; + + int returnCode = 0; + + /* Variables to capture the file name and the file pointer at thread level*/ + char fileName[MAX_PATH]; + FILE *pFile = NULL; + struct statistics* buffer = NULL; + int statisticsSize = 0; + + /* Variables to capture the file name and the file pointer at process level*/ + char processFileName[MAX_PATH]; + FILE *pProcessFile = NULL; + struct ProcessStats processStats; + DWORD dwStartTime; + + testStatus = PASS; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + ZeroMemory( objectSuffix, MAX_PATH ); + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } +// Trace("Process created, value of process count is [%d]\n", USE_PROCESS_COUNT); + + if(argc == 5) + { + strncat(ObjName, objectSuffix, MAX_PATH - (sizeof(ObjName) + 1) ); + } + + /* Register the start time */ + dwStartTime = GetTickCount(); + processStats.relationId = RELATION_ID; + processStats.processId = USE_PROCESS_COUNT; + + _snprintf(processFileName, MAX_PATH, "%d_process_event_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); + pProcessFile = fopen(processFileName, "w+"); + if(pProcessFile == NULL) + { + Fail("Error:%d: in opening Process File for write for process [%d]\n", GetLastError(), USE_PROCESS_COUNT); + } + + statisticsSize = sizeof(struct statistics); + + _snprintf(fileName, MAX_PATH, "%d_thread_event_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); + pFile = fopen(fileName, "w+"); + + if(pFile == NULL) + { + Fail("Error:%d: in opening thread file for write for process [%d]\n", GetLastError(), USE_PROCESS_COUNT); + } + // For each thread we will log operations failed (int), passed (int), total (int) + // and number of ticks (DWORD) for the operations + resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize); + + wcObjName = convert(ObjName); + + StartTestsEvHandle = CreateEvent( NULL, /* lpEventAttributes*/ + TRUE, /* bManualReset */ + FALSE, /* bInitialState */ + NULL); /* name of Event */ + + if( StartTestsEvHandle == NULL ) + { + Fail("Error:%d: Unexpected failure " + "to create %s Event for process count %d\n", GetLastError(), sTmpEventName, USE_PROCESS_COUNT ); + + } + + /* Create StartTest Event */ + + hEventHandle = OpenEventW( + EVENT_ALL_ACCESS, /* lpEventAttributes, inheritable to child processes*/ + FALSE, /* bAutomaticReset */ + wcObjName + ); + + if( hEventHandle == NULL) + { + Fail("Unable to create Event handle for process id [%d], returned error [%d]\n", i, GetLastError()); + } + /* We already assume that the Event was created previously*/ + + for( i = 0; i < THREAD_COUNT; i++ ) + { + dwParam = (int) i; + //Create thread + hThread[i] = CreateThread( + NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */ + (LPVOID)dwParam, /* argument to thread function */ + 0, /* use default creation flags */ + &threadId[i] /* returns the thread identifier*/ + ); + + if(hThread[i] == NULL) + { + Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError()); + } + + } + + if (!SetEvent(StartTestsEvHandle)) + { + Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError()); + } + + /* Test running */ + returnCode = WaitForMultipleObjects( THREAD_COUNT, hThread, TRUE, INFINITE); + + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError()); + testStatus = FAIL; + } + + processStats.operationTime = GetTimeDiff(dwStartTime); + + /* Write to a file*/ + if(pFile!= NULL) + { + for( i = 0; i < THREAD_COUNT; i++ ) + { + buffer = (struct statistics *)resultBuffer->getResultBuffer(i); + returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); +// Trace("Iteration %d over\n", i); + + } + } + + if(fclose(pFile)) + { + Trace("Error: fclose failed for pFile at Process %d\n", USE_PROCESS_COUNT); + testStatus = FAIL; + } + + fprintf(pProcessFile, "%d,%d,%d\n", USE_PROCESS_COUNT, processStats.operationTime, processStats.relationId ); + if(fclose(pProcessFile)) + { + Trace("Error: fclose failed for pProcessFile at Process %d\n", USE_PROCESS_COUNT); + testStatus = FAIL; + } + /* Logging for the test case over, clean up the handles */ + +// Trace("Test Thread %d done\n", USE_PROCESS_COUNT); + + for( i = 0; i < THREAD_COUNT; i++ ) + { + if(!CloseHandle(hThread[i]) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i); + testStatus = FAIL; + } + } + + if(!CloseHandle(StartTestsEvHandle)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT); + testStatus = FAIL; + } + + if(!CloseHandle(hEventHandle)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hEventHandle\n", GetLastError(), USE_PROCESS_COUNT); + testStatus = FAIL; + } + + free(wcObjName); + PAL_Terminate(); + return testStatus; +} + +void PALAPI Run_Thread (LPVOID lpParam) +{ + unsigned int i = 0; + DWORD dwWaitResult; + + struct statistics stats; + DWORD dwStartTime; + + stats.relationId = RELATION_ID; + stats.processId = USE_PROCESS_COUNT; + stats.operationsFailed = 0; + stats.operationsPassed = 0; + stats.operationsTotal = 0; + stats.operationTime = 0; + + int Id=(int)lpParam; + + dwWaitResult = WaitForSingleObject( + StartTestsEvHandle, // handle to start test handle + TIMEOUT); + + if(dwWaitResult != WAIT_OBJECT_0) + { + Trace("Error:%d: while waiting for StartTest Event@ thread %d\n", GetLastError(), Id); + testStatus = FAIL; + } + + dwStartTime = GetTickCount(); + + for( i = 0; i < REPEAT_COUNT; i++ ) + { + dwWaitResult = WaitForSingleObject( + hEventHandle, // handle to Event + TIMEOUT); + + if(dwWaitResult != WAIT_OBJECT_0) + { + //Trace("Error:%d: while waiting for onject @ thread %d, # iter %d\n", GetLastError(), Id, i); + stats.operationsFailed += 1; + stats.operationsTotal += 1; + testStatus = FAIL; + continue; + } + + if (! SetEvent(hEventHandle)) + { + // Deal with error. +// Trace("Error while setting Event @ thread %d # iter %d\n", Id, i); + stats.operationsFailed += 1; + stats.operationsTotal += 1; + // do we need to have while true loop to attempt to set event...? + testStatus = FAIL; + continue; + } + + stats.operationsTotal += 1; + stats.operationsPassed += 1; + // Trace("Successs while setting Event @ iteration %d -> thread %d -> Process %d for handle %d\n", i, Id, USE_PROCESS_COUNT, hEventHandle); + + } + + stats.operationTime = GetTimeDiff(dwStartTime); + //Trace("OPeration time is %d", stats.operationTime ); + if(resultBuffer->LogResult(Id, (char *)&stats)) + { + Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT); + } + //Trace("Thread %d over for process %d\n", Id, USE_PROCESS_COUNT); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/shared/main.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/shared/main.cpp new file mode 100644 index 0000000..c4a4067 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/event/shared/main.cpp @@ -0,0 +1,265 @@ +// 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. + +/*============================================================ +** +** Source Code: main.c and event.c +** main.c creates process and waits for all processes to get over +** event.c creates a event and then calls threads which will contend for the event +** +** This test is for Object Management Test case for event where Object type is shareable. +** Algorithm +** o Main Process Creates OBJECT_TYPE Object +** o Create PROCESS_COUNT processes aware of the Shared Object +** +** Author: ShamitP +** +** +**============================================================ +*/ +#include +#include "resulttime.h" + +/* Test Input Variables */ +unsigned int PROCESS_COUNT = 2; +unsigned int THREAD_COUNT = 20; +unsigned int REPEAT_COUNT = 200; +unsigned int RELATION_ID = 1001; + + +char objectSuffix[MAX_PATH_FNAME]; + +struct TestStats{ + DWORD operationTime; + unsigned int relationId; + unsigned int processCount; + unsigned int threadCount; + unsigned int repeatCount; + char* buildNumber; + +}; + +int GetParameters( int argc, char **argv) +{ + if( (!((argc == 5) || (argc == 6) ) )|| ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Object Management event Test\n"); + printf("Usage:\n"); + printf("main\n\t[PROCESS_COUNT (greater than 1)] \n"); + printf("\t[THREAD_COUNT (greater than 1)] \n"); + printf("\t[REPEAT_COUNT (greater than 1)]\n"); + printf("\t[RELATION_ID [greater than or equal to 1]\n"); + printf("\t[Object Name Suffix]\n"); + return -1; + } + + PROCESS_COUNT = atoi(argv[1]); + if( (PROCESS_COUNT < 1) || (PROCESS_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 1 and less than PROCESS_COUNT %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + + if(argc == 6) + { + strncpy(objectSuffix, argv[5], MAX_PATH_FNAME-1); + } + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hProcess[MAXIMUM_WAIT_OBJECTS]; + HANDLE hEventHandle; + + STARTUPINFO si[MAXIMUM_WAIT_OBJECTS]; + PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS]; + + char lpCommandLine[MAX_LONGPATH] = ""; + char ObjName[MAX_PATH_FNAME] = "SHARED_EVENT"; + + int returnCode = 0; + DWORD processReturnCode = 0; + int testReturnCode = PASS; + + char fileName[MAX_PATH_FNAME]; + FILE *pFile = NULL; + DWORD dwStartTime; + struct TestStats testStats; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + ZeroMemory( objectSuffix, MAX_PATH_FNAME ); + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } + + if(argc == 5) + { + strncat(ObjName, objectSuffix, MAX_PATH_FNAME - (sizeof(ObjName) + 1) ); + } + + /* Register the start time */ + dwStartTime = GetTickCount(); + testStats.relationId = RELATION_ID; + testStats.processCount = PROCESS_COUNT; + testStats.threadCount = THREAD_COUNT; + testStats.repeatCount = REPEAT_COUNT; + testStats.buildNumber = getBuildNumber(); + + + _snprintf(fileName, MAX_PATH_FNAME, "main_event_%d_.txt", RELATION_ID); + pFile = fopen(fileName, "w+"); + if(pFile == NULL) + { + Fail("Error in opening main file for write\n"); + } + + hEventHandle = CreateEvent( + NULL, /* lpEventAttributes, inheritable to child processes*/ + TRUE, /* bAutomaticReset */ + TRUE, /* bInitialState */ + ObjName + ); + + if( hEventHandle == NULL) + { + Fail("Unable to create Event handle, returned error [%d]\n", GetLastError()); + } + + for( i = 0; i < PROCESS_COUNT; i++ ) + { + + ZeroMemory( lpCommandLine, MAX_PATH_FNAME ); + if ( _snprintf( lpCommandLine, MAX_PATH_FNAME-1, "event %d %d %d %d %s", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID, objectSuffix) < 0 ) + { + Fail ("Error: Insufficient Event name string length for %s for iteration [%d]\n", ObjName, i); + } + + /* Zero the data structure space */ + ZeroMemory ( &pi[i], sizeof(pi[i]) ); + ZeroMemory ( &si[i], sizeof(si[i]) ); + + /* Set the process flags and standard io handles */ + si[i].cb = sizeof(si[i]); + + if(!CreateProcess( NULL, /* lpApplicationName*/ + lpCommandLine, /* lpCommandLine */ + NULL, /* lpProcessAttributes */ + NULL, /* lpThreadAttributes */ + TRUE, /* bInheritHandles */ + 0, /* dwCreationFlags, */ + NULL, /* lpEnvironment */ + NULL, /* pCurrentDirectory */ + &si[i], /* lpStartupInfo */ + &pi[i] /* lpProcessInformation */ + )) + { + Fail("Process Not created for [%d], the error code is [%d]\n", i, GetLastError()); + } + else + { + hProcess[i] = pi[i].hProcess; +// Trace("Process created for [%d]\n", i); + + } + + //Create Process + + } + + returnCode = WaitForMultipleObjects( PROCESS_COUNT, hProcess, TRUE, INFINITE); + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", PROCESS_COUNT, returnCode, GetLastError()); + testReturnCode = FAIL; + } + +// Trace("Test over\n"); + for( i = 0; i < PROCESS_COUNT; i++ ) + { + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) ) + { + Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n", + i, GetLastError() ); + + testReturnCode = FAIL; + } + + if(processReturnCode == FAIL) + { + Trace( "Process [%d] failed and returned FAIL\n", i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hThread)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hProcess) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i); + testReturnCode = FAIL; + } + } + + testStats.operationTime = GetTimeDiff(dwStartTime); + fprintf(pFile, "%d,%d,%d,%d,%d,%s\n", testStats.operationTime, testStats.relationId, testStats.processCount, testStats.threadCount, testStats.repeatCount, testStats.buildNumber); + if(fclose(pFile)) + { + Trace("Error: fclose failed for pFile\n"); + testReturnCode = FAIL; + } + + if(!CloseHandle(hEventHandle)) + { + Trace("Error:%d: CloseHandle failed for hEventHandle\n", GetLastError()); + testReturnCode = FAIL; + } + + if( testReturnCode == PASS) + { + Trace("Test Passed\n"); + } + else + { + Trace("Test Failed\n"); + } + + PAL_Terminate(); + return testReturnCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/CMakeLists.txt new file mode 100644 index 0000000..4eeff15 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(nonshared) +add_subdirectory(shared) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/CMakeLists.txt new file mode 100644 index 0000000..87932ff --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/CMakeLists.txt @@ -0,0 +1,15 @@ +set(SOURCES + main.cpp + mutex.cpp +) + +add_executable(paltest_mutex_nonshared + ${SOURCES} +) + +add_dependencies(paltest_mutex_nonshared coreclrpal) + +target_link_libraries(paltest_mutex_nonshared + ${COMMON_TEST_LIBRARIES} + rt +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/main.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/main.cpp new file mode 100644 index 0000000..80f31aa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/main.cpp @@ -0,0 +1,230 @@ +// 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. + +/*============================================================ +** +** Source Code: main.c and mutex.c +** main.c creates process and waits for all processes to get over +** mutex.c creates a mutex and then calls threads which will contend for the mutex +** +** This test is for Object Management Test case for Mutex where Object type is not shareable. +** Algorithm +** o Create PROCESS_COUNT processes. +** o Main Thread of each process creates OBJECT_TYPE Object +** +** Author: ShamitP +**============================================================ +*/ + +#include +#include "resulttime.h" + +/* Test Input Variables */ +unsigned int PROCESS_COUNT = 2; +unsigned int THREAD_COUNT = 20; +unsigned int REPEAT_COUNT = 4000; +unsigned int RELATION_ID = 1001; + + +struct TestStats{ + DWORD operationTime; + unsigned int relationId; + unsigned int processCount; + unsigned int threadCount; + unsigned int repeatCount; + char* buildNumber; + +}; + +int GetParameters( int argc, char **argv) +{ + if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Object Management Mutex Test\n"); + printf("Usage:\n"); + printf("main\n\t[PROCESS_COUNT [greater than 1] \n"); + printf("\t[THREAD_COUNT [greater than 1] \n"); + printf("\t[REPEAT_COUNT [greater than 1]\n"); + printf("\t[RELATION_ID [greater than 1]\n"); + + + return -1; + } + + PROCESS_COUNT = atoi(argv[1]); + if( (PROCESS_COUNT < 1) || (PROCESS_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 1 and less than PROCESS_COUNT %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hProcess[MAXIMUM_WAIT_OBJECTS]; + HANDLE hMutexHandle[MAXIMUM_WAIT_OBJECTS]; + + STARTUPINFO si[MAXIMUM_WAIT_OBJECTS]; + PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS]; + + const char *ObjName = "Mutex"; + char lpCommandLine[MAX_PATH] = ""; + + int returnCode = 0; + DWORD processReturnCode = 0; + int testReturnCode = PASS; + + char fileName[MAX_PATH]; + FILE *pFile = NULL; + DWORD dwStartTime; + struct TestStats testStats; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } + + /* Register the start time */ + dwStartTime = GetTickCount(); + testStats.relationId = RELATION_ID; + testStats.processCount = PROCESS_COUNT; + testStats.threadCount = THREAD_COUNT; + testStats.repeatCount = REPEAT_COUNT; + testStats.buildNumber = getBuildNumber(); + + + _snprintf(fileName, MAX_PATH, "main_mutex_%d_.txt", RELATION_ID); + pFile = fopen(fileName, "w+"); + if(pFile == NULL) + { + Fail("Error in opening main file for write\n"); + } + + for( i = 0; i < PROCESS_COUNT; i++ ) + { + ZeroMemory( lpCommandLine, MAX_PATH ); + if ( _snprintf( lpCommandLine, MAX_PATH-1, "mutex %d %d %d %d", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID) < 0 ) + { + Fail("Error Insufficient mutex name string length for %s for iteration [%d]\n", ObjName, i); + } + + /* Zero the data structure space */ + ZeroMemory ( &pi[i], sizeof(pi[i]) ); + ZeroMemory ( &si[i], sizeof(si[i]) ); + + /* Set the process flags and standard io handles */ + si[i].cb = sizeof(si[i]); + + if(!CreateProcess( NULL, /* lpApplicationName*/ + lpCommandLine, /* lpCommandLine */ + NULL, /* lpProcessAttributes */ + NULL, /* lpThreadAttributes */ + TRUE, /* bInheritHandles */ + 0, /* dwCreationFlags, */ + NULL, /* lpEnvironment */ + NULL, /* pCurrentDirectory */ + &si[i], /* lpStartupInfo */ + &pi[i] /* lpProcessInformation */ + )) + { + Fail("Process Not created for [%d], the error code is [%d]\n", i, GetLastError()); + } + else + { + hProcess[i] = pi[i].hProcess; +// Trace("Process created for [%d]\n", i); + + } + + //Create Process + + } + + returnCode = WaitForMultipleObjects( PROCESS_COUNT, hProcess, TRUE, INFINITE); + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", PROCESS_COUNT, returnCode, GetLastError()); + testReturnCode = FAIL; + } + + for( i = 0; i < PROCESS_COUNT; i++ ) + { + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) ) + { + Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n", + i, GetLastError() ); + + testReturnCode = FAIL; + } + + if(processReturnCode == FAIL) + { + Trace( "Process [%d] failed and returned FAIL\n", i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hThread)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hProcess) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i); + testReturnCode = FAIL; + } + } + + testStats.operationTime = GetTimeDiff(dwStartTime); + fprintf(pFile, "%d,%d,%d,%d,%d,%s\n", testStats.operationTime, testStats.relationId, testStats.processCount, testStats.threadCount, testStats.repeatCount, testStats.buildNumber); + if(fclose(pFile)) + { + Trace("Error: fclose failed for pFile\n"); + testReturnCode = FAIL; + } + + if( testReturnCode == PASS) + { + Trace("Test Passed\n"); + } + else + { + Trace("Test Failed\n"); + } + + PAL_Terminate(); + return testReturnCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/mutex.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/mutex.cpp new file mode 100644 index 0000000..7f1f659 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/mutex.cpp @@ -0,0 +1,340 @@ +// 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. + +/*============================================================ +** +** Source Code: main.c and mutex.c +** main.c creates process and waits for all processes to get over +** mutex.c creates a mutex and then calls threads which will contend for the mutex +** +** This test is for Object Management Test case for Mutex where Object type is not shareable. +** Algorithm +** o Create PROCESS_COUNT processes. +** o Main Thread of each process creates OBJECT_TYPE Object +** +** Author: ShamitP +**============================================================ +*/ + +#include +#include "resultbuffer.h" +#include "resulttime.h" + +#define TIMEOUT 5000 +/* Test Input Variables */ +unsigned int USE_PROCESS_COUNT = 0; +unsigned int THREAD_COUNT = 0; +unsigned int REPEAT_COUNT = 0; +unsigned int RELATION_ID = 1001; + +/* Capture statistics at per thread basis */ +struct statistics{ + unsigned int processId; + unsigned int operationsFailed; + unsigned int operationsPassed; + unsigned int operationsTotal; + DWORD operationTime; + unsigned int relationId; +}; + +struct ProcessStats{ + unsigned int processId; + DWORD operationTime; + unsigned int relationId; +}; + +HANDLE StartTestsEvHandle = NULL; +HANDLE hMutexHandle = NULL; + +/* Results Buffer */ +ResultBuffer *resultBuffer = NULL; + +int testStatus; + +void PALAPI Run_Thread(LPVOID lpParam); + +int GetParameters( int argc, char **argv) +{ + if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Object Management Mutex Test\n"); + printf("Usage:\n"); + printf("mutex\n\t[USE_PROCESS_COUNT ( greater than 1] \n"); + printf("\t[THREAD_COUNT ( greater than 1] \n"); + printf("\t[REPEAT_COUNT ( greater than 1]\n"); + printf("\t[RELATION_ID [greater than 1]\n"); + return -1; + } + + // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]); + + USE_PROCESS_COUNT = atoi(argv[1]); + if( USE_PROCESS_COUNT < 0) + { + printf("\nInvalid USE_PROCESS_COUNT number, Pass greater than 1\n"); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hThread[MAXIMUM_WAIT_OBJECTS]; + DWORD threadId[MAXIMUM_WAIT_OBJECTS]; + + const char sTmpEventName[MAX_PATH] = "StartTestEvent"; + + DWORD dwParam = 0; + + int returnCode = 0; + + /* Variables to capture the file name and the file pointer at thread level*/ + char fileName[MAX_PATH]; + FILE *pFile = NULL; + struct statistics* buffer = NULL; + int statisticsSize = 0; + + /* Variables to capture the file name and the file pointer at process level*/ + char processFileName[MAX_PATH]; + FILE *pProcessFile = NULL; + struct ProcessStats processStats; + DWORD dwStartTime; + + testStatus = PASS; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } +// Trace("Process created, value of process count is [%d]\n", USE_PROCESS_COUNT); + + /* Register the start time */ + dwStartTime = GetTickCount(); + processStats.relationId = RELATION_ID; + processStats.processId = USE_PROCESS_COUNT; + + _snprintf(processFileName, MAX_PATH, "%d_process_mutex_%d_.txt", USE_PROCESS_COUNT,RELATION_ID); + pProcessFile = fopen(processFileName, "w+"); + if(pProcessFile == NULL) + { + Fail("Error in opening process File file for write for process [%d]\n", USE_PROCESS_COUNT); + } + + statisticsSize = sizeof(struct statistics); + + _snprintf(fileName, MAX_PATH, "%d_thread_mutex_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); + pFile = fopen(fileName, "w+"); + if(pFile == NULL) + { + Fail("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT); + } + // For each thread we will log operations failed (int), passed (int), total (int) + // and number of ticks (DWORD) for the operations + resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize); + + StartTestsEvHandle = CreateEvent( NULL, /* lpEventAttributes*/ + TRUE, /* bManualReset */ + FALSE, /* bInitialState */ + NULL + ); /* name of Event */ + + if( StartTestsEvHandle == NULL ) + { + Fail("Error:%d: Unexpected failure " + "to create %s Event for process count %d\n", GetLastError(), sTmpEventName, USE_PROCESS_COUNT ); + + } + + /* Create StartTest Event */ + + hMutexHandle = CreateMutex( + NULL, + FALSE, /* bInitialOwner, owns initially */ + NULL + ); + + if( hMutexHandle == NULL) + { + Fail("Unable to create Mutex handle for process id [%d], returned error [%d]\n", i, GetLastError()); + } + /* We already assume that the mutex was created previously*/ + + for( i = 0; i < THREAD_COUNT; i++ ) + { + dwParam = (int) i; + //Create thread + hThread[i] = CreateThread( + NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */ + (LPVOID)dwParam, /* argument to thread function */ + 0, /* use default creation flags */ + &threadId[i] /* returns the thread identifier*/ + ); + + if(hThread[i] == NULL) + { + Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError()); + } + + } + + if (!SetEvent(StartTestsEvHandle)) + { + Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError()); + } + + /* Test running */ + returnCode = WaitForMultipleObjects( THREAD_COUNT, hThread, TRUE, INFINITE); + + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError()); + testStatus = FAIL; + } + + processStats.operationTime = GetTimeDiff(dwStartTime); + + /* Write to a file*/ + if(pFile!= NULL) + { + for( i = 0; i < THREAD_COUNT; i++ ) + { + buffer = (struct statistics *)resultBuffer->getResultBuffer(i); + returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); +// Trace("Iteration %d over\n", i); + + } + } + fclose(pFile); + + fprintf(pProcessFile, "%d,%d,%d\n", USE_PROCESS_COUNT, processStats.operationTime, processStats.relationId ); + fclose(pProcessFile); + + /* Logging for the test case over, clean up the handles */ + +// Trace("Test Thread %d done\n", USE_PROCESS_COUNT); + + + for( i = 0; i < THREAD_COUNT; i++ ) + { + if(!CloseHandle(hThread[i]) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i); + testStatus = FAIL; + } + } + + if(!CloseHandle(StartTestsEvHandle)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT); + testStatus = FAIL; + } + + if(!CloseHandle(hMutexHandle)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hMutexHandle\n", GetLastError(), USE_PROCESS_COUNT); + testStatus = FAIL; + } + + PAL_Terminate(); + return testStatus; +} + +void PALAPI Run_Thread (LPVOID lpParam) +{ + unsigned int i = 0; + DWORD dwWaitResult; + + struct statistics stats; + DWORD dwStartTime; + + stats.relationId = RELATION_ID; + stats.processId = USE_PROCESS_COUNT; + stats.operationsFailed = 0; + stats.operationsPassed = 0; + stats.operationsTotal = 0; + stats.operationTime = 0; + + int Id=(int)lpParam; + + dwWaitResult = WaitForSingleObject( + StartTestsEvHandle, // handle to mutex + TIMEOUT); + + if(dwWaitResult != WAIT_OBJECT_0) + { + Trace("Error while waiting for StartTest Event@ thread %d\n", Id); + testStatus = FAIL; + } + + dwStartTime = GetTickCount(); + + for( i = 0; i < REPEAT_COUNT; i++ ) + { + dwWaitResult = WaitForSingleObject( + hMutexHandle, // handle to mutex + TIMEOUT); + + if(dwWaitResult != WAIT_OBJECT_0) + { +// Trace("Error while waiting for onject @ thread %d, # iter %d\n", Id, i); + stats.operationsFailed += 1; + stats.operationsTotal += 1; + testStatus = FAIL; + continue; + } + if (! ReleaseMutex(hMutexHandle)) + { + // Deal with error. +// Trace("Error while releasing mutex @ thread %d # iter %d\n", Id, i); + stats.operationsFailed += 1; + stats.operationsTotal += 1; + // Probably need to have while true loop to attempt to release mutex... + testStatus = FAIL; + continue; + } + + stats.operationsTotal += 1; + stats.operationsPassed += 1; + // Trace("Successs while releasing mutex @ iteration %d -> thread %d -> Process %d\n", i, Id, USE_PROCESS_COUNT); + + } + + stats.operationTime = GetTimeDiff(dwStartTime); + //Trace("OPeration time is %d", stats.operationTime ); + if(resultBuffer->LogResult(Id, (char *)&stats)) + { + Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT); + } +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/shared/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/shared/CMakeLists.txt new file mode 100644 index 0000000..d058c44 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/shared/CMakeLists.txt @@ -0,0 +1,15 @@ +set(SOURCES + main.cpp + mutex.cpp +) + +add_executable(paltest_mutex_shared + ${SOURCES} +) + +add_dependencies(paltest_mutex_shared coreclrpal) + +target_link_libraries(paltest_mutex_shared + ${COMMON_TEST_LIBRARIES} + rt +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/shared/main.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/shared/main.cpp new file mode 100644 index 0000000..aa98855 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/shared/main.cpp @@ -0,0 +1,265 @@ +// 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. + +/*============================================================ +** +** This test is for Object Management Test case for Mutex where Object type is shareable. +** +** Source Code: main.c and mutex.c +** main.c creates a mutex, creates processes and waits for all processes to get over +** mutex.c create threads which will contend for the mutex +** +** This test is for Object Management Test case for Mutex where Object type is not shareable. +** Algorithm +** o Main Process Creates OBJECT_TYPE Object +** o Create PROCESS_COUNT processes aware of the Shared Object +** +** Author: ShamitP +** +** +**============================================================ +*/ + +#include +#include "resulttime.h" + +/* Test Input Variables */ +unsigned int PROCESS_COUNT = 2; +unsigned int THREAD_COUNT = 2; +unsigned int REPEAT_COUNT = 40000; +unsigned int RELATION_ID = 1001; + + +char objectSuffix[MAX_PATH]; + +struct TestStats{ + DWORD operationTime; + unsigned int relationId; + unsigned int processCount; + unsigned int threadCount; + unsigned int repeatCount; + char* buildNumber; + +}; + +int GetParameters( int argc, char **argv) +{ + if( (!((argc == 5) || (argc == 6) ) )|| ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Object Management event Test\n"); + printf("Usage:\n"); + printf("main\n\t[PROCESS_COUNT (greater than 1)] \n"); + printf("\t[THREAD_COUNT (greater than 1)] \n"); + printf("\t[REPEAT_COUNT (greater than 1)]\n"); + printf("\t[RELATION_ID [greater than 1]\n"); + printf("\t[Object Name Suffix]\n"); + return -1; + } + + PROCESS_COUNT = atoi(argv[1]); + if( (PROCESS_COUNT < 1) || (PROCESS_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 1 and less than PROCESS_COUNT %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + if(argc == 6) + { + strncpy(objectSuffix, argv[5], MAX_PATH-1); + } + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hProcess[MAXIMUM_WAIT_OBJECTS]; + HANDLE hMutexHandle; + + STARTUPINFO si[MAXIMUM_WAIT_OBJECTS]; + PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS]; + + char ObjName[MAX_PATH] = "SHARED_MUTEX"; + char lpCommandLine[MAX_PATH] = ""; + + int returnCode = 0; + DWORD processReturnCode = 0; + int testReturnCode = PASS; + + char fileName[MAX_PATH]; + FILE *pFile = NULL; + DWORD dwStartTime; + struct TestStats testStats; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + ZeroMemory( objectSuffix, MAX_PATH ); + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } + + if(argc == 5) + { + strncat(ObjName, objectSuffix, MAX_PATH - (sizeof(ObjName) + 1) ); + } + + /* Register the start time */ + dwStartTime = GetTickCount(); + testStats.relationId = RELATION_ID; + testStats.processCount = PROCESS_COUNT; + testStats.threadCount = THREAD_COUNT; + testStats.repeatCount = REPEAT_COUNT; + testStats.buildNumber = getBuildNumber(); + + + _snprintf(fileName, MAX_PATH, "main_mutex_%d_.txt", RELATION_ID); + pFile = fopen(fileName, "w+"); + if(pFile == NULL) + { + Fail("Error in opening main file for write\n"); + } + + hMutexHandle = CreateMutex( + NULL, + FALSE, /* bInitialOwner, owns initially */ + ObjName + ); + + if( hMutexHandle == NULL) + { + Fail("Unable to create Mutex handle for Main thread returned error [%d]\n", GetLastError()); + } + + for( i = 0; i < PROCESS_COUNT; i++ ) + { + ZeroMemory( lpCommandLine, MAX_PATH ); + if ( _snprintf( lpCommandLine, MAX_PATH-1, "mutex %d %d %d %d %s", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID, objectSuffix) < 0 ) + { + Fail ("Error Insufficient mutex name string length for %s for iteration [%d]\n", ObjName, i); + } + + + /* Zero the data structure space */ + ZeroMemory ( &pi[i], sizeof(pi[i]) ); + ZeroMemory ( &si[i], sizeof(si[i]) ); + + /* Set the process flags and standard io handles */ + si[i].cb = sizeof(si[i]); + + //Create Process + if(!CreateProcess( NULL, /* lpApplicationName*/ + lpCommandLine, /* lpCommandLine */ + NULL, /* lpProcessAttributes */ + NULL, /* lpThreadAttributes */ + TRUE, /* bInheritHandles */ + 0, /* dwCreationFlags, */ + NULL, /* lpEnvironment */ + NULL, /* pCurrentDirectory */ + &si[i], /* lpStartupInfo */ + &pi[i] /* lpProcessInformation */ + )) + { + Fail("Process Not created for [%d], the error code is [%d]\n", i, GetLastError()); + } + else + { + hProcess[i] = pi[i].hProcess; +// Trace("Process created for [%d]\n", i); + + } + } + + returnCode = WaitForMultipleObjects( PROCESS_COUNT, hProcess, TRUE, INFINITE); + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", PROCESS_COUNT, returnCode, GetLastError()); + testReturnCode = FAIL; + } + + for( i = 0; i < PROCESS_COUNT; i++ ) + { + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) ) + { + Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n", + i, GetLastError() ); + + testReturnCode = FAIL; + } + + if(processReturnCode == FAIL) + { + Trace( "Process [%d] failed and returned FAIL\n", i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hThread)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hProcess) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i); + testReturnCode = FAIL; + } + } + + testStats.operationTime = GetTimeDiff(dwStartTime); + fprintf(pFile, "%d,%d,%d,%d,%d,%s\n", testStats.operationTime, testStats.relationId, testStats.processCount, testStats.threadCount, testStats.repeatCount, testStats.buildNumber ); + if(fclose(pFile)) + { + Trace("Error: fclose failed for pFile\n"); + testReturnCode = FAIL; + } + + if(!CloseHandle(hMutexHandle)) + { + Trace("Error:%d: CloseHandle failed for hMutexHandle\n", GetLastError()); + testReturnCode = FAIL; + + } + + if( testReturnCode == PASS) + { + Trace("Test Passed\n"); + } + else + { + Trace("Test Failed\n"); + } + + PAL_Terminate(); + return testReturnCode; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/shared/mutex.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/shared/mutex.cpp new file mode 100644 index 0000000..ec5d9b3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/mutex/shared/mutex.cpp @@ -0,0 +1,354 @@ +// 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. + +/*============================================================ +** +** This test is for Object Management Test case for Mutex where Object type is shareable. +** +** Source Code: main.c and mutex.c +** main.c creates a mutex, creates processes and waits for all processes to get over +** mutex.c create threads which will contend for the mutex +** +** This test is for Object Management Test case for Mutex where Object type is not shareable. +** Algorithm +** o Main Process Creates OBJECT_TYPE Object +** o Create PROCESS_COUNT processes aware of the Shared Object +** +** Author: ShamitP +** +** +**============================================================ +*/ + +#include +#include "resultbuffer.h" +#include "resulttime.h" + +#define TIMEOUT 5000 +/* Test Input Variables */ +unsigned int USE_PROCESS_COUNT = 0; +unsigned int THREAD_COUNT = 0; +unsigned int REPEAT_COUNT = 0; +unsigned int RELATION_ID = 0; + + +/* Capture statistics at per thread basis */ +struct statistics{ + unsigned int processId; + unsigned int operationsFailed; + unsigned int operationsPassed; + unsigned int operationsTotal; + DWORD operationTime; + unsigned int relationId; +}; + +struct ProcessStats{ + unsigned int processId; + DWORD operationTime; + unsigned int relationId; +}; + +HANDLE StartTestsEvHandle = NULL; +HANDLE hMutexHandle = NULL; + +/* Results Buffer */ +ResultBuffer *resultBuffer = NULL; + +int testStatus; + +const char sTmpEventName[MAX_PATH] = "StartTestEvent"; +char objectSuffix[MAX_PATH]; + +void PALAPI Run_Thread(LPVOID lpParam); + +int GetParameters( int argc, char **argv) +{ + if( (!((argc == 5) || (argc == 6) ) )|| ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Object Management event Test\n"); + printf("Usage:\n"); + printf("main\n\t[USE_PROCESS_COUNT (greater than 1)] \n"); + printf("\t[THREAD_COUNT (greater than 1)] \n"); + printf("\t[REPEAT_COUNT (greater than 1)]\n"); + printf("\t[RELATION_ID [greater than 1]\n"); + printf("\t[Object Name Suffix]\n"); + + return -1; + } + + // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]); + + USE_PROCESS_COUNT = atoi(argv[1]); + if( USE_PROCESS_COUNT < 0) + { + printf("\nInvalid USE_PROCESS_COUNT number, Pass greater than 1\n"); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + if(argc == 6) + { + strncpy(objectSuffix, argv[5], MAX_PATH-1); + } + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hThread[MAXIMUM_WAIT_OBJECTS]; + DWORD threadId[MAXIMUM_WAIT_OBJECTS]; + + char ObjName[MAX_PATH] = "SHARED_MUTEX"; + DWORD dwParam = 0; + + int returnCode = 0; + + /* Variables to capture the file name and the file pointer*/ + char fileName[MAX_PATH]; + FILE *pFile = NULL; + struct statistics* buffer = NULL; + int statisticsSize = 0; + + /* Variables to capture the file name and the file pointer at process level*/ + char processFileName[MAX_PATH]; + FILE *pProcessFile = NULL; + struct ProcessStats processStats; + DWORD dwStartTime; + + testStatus = PASS; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + ZeroMemory( objectSuffix, MAX_PATH ); + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } +// Trace("Process created, value of process count is [%d]\n", USE_PROCESS_COUNT); + + if(argc == 5) + { + strncat(ObjName, objectSuffix, MAX_PATH - (sizeof(ObjName) + 1) ); + } + + /* Register the start time */ + dwStartTime = GetTickCount(); + processStats.relationId = RELATION_ID; + processStats.processId = USE_PROCESS_COUNT; + + _snprintf(processFileName, MAX_PATH, "%d_process_mutex_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); + pProcessFile = fopen(processFileName, "w+"); + if(pProcessFile == NULL) + { + Fail("Error in opening process File file for write for process [%d]\n", USE_PROCESS_COUNT); + } statisticsSize = sizeof(struct statistics); + + _snprintf(fileName, MAX_PATH, "%d_thread_mutex_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); + pFile = fopen(fileName, "w+"); + if(pFile == NULL) + { + Fail("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT); + } + // For each thread we will log operations failed (int), passed (int), total (int) + // and number of ticks (DWORD) for the operations + resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize); + + /* Create StartTest Event */ + StartTestsEvHandle = CreateEvent( NULL, /* lpEventAttributes*/ + TRUE, /* bManualReset */ + FALSE, /* bInitialState */ + NULL); /* name of Event */ + + if( StartTestsEvHandle == NULL ) + { + Fail("Error:%d: Unexpected failure " + "to create %s Event for process count %d\n", GetLastError(), sTmpEventName, USE_PROCESS_COUNT ); + + } + + hMutexHandle = CreateMutex( + NULL, + FALSE, /* bInitialOwner, owns initially */ + ObjName + ); + + if( (hMutexHandle == NULL)|| (GetLastError() != ERROR_ALREADY_EXISTS)) + { + Fail("Unable to create Mutex handle for process id [%d], returned error [%d], expected ERROR_ALREADY_EXISTS\n", i, GetLastError()); + } + /* We already assume that the mutex was created previously*/ + + for( i = 0; i < THREAD_COUNT; i++ ) + { + dwParam = (int) i; + //Create thread + hThread[i] = CreateThread( + NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */ + (LPVOID)dwParam, /* argument to thread function */ + 0, /* use default creation flags */ + &threadId[i] /* returns the thread identifier*/ + ); + + if(hThread[i] == NULL) + { + Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError()); + } + + } + + if (!SetEvent(StartTestsEvHandle)) + { + Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError()); + } + + /* Test running */ + returnCode = WaitForMultipleObjects( THREAD_COUNT, hThread, TRUE, INFINITE); + + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError()); + testStatus = FAIL; + } + + processStats.operationTime = GetTimeDiff(dwStartTime); + + /* Write to a file*/ + if(pFile!= NULL) + { + for( i = 0; i < THREAD_COUNT; i++ ) + { + buffer = (struct statistics *)resultBuffer->getResultBuffer(i); + returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); +// Trace("Iteration %d over\n", i); + + } + } + fclose(pFile); + + fprintf(pProcessFile, "%d,%d,%d\n", USE_PROCESS_COUNT, processStats.operationTime, processStats.relationId ); + fclose(pProcessFile); + + /* Logging for the test case over, clean up the handles */ + +// Trace("Process Count %d over\n",USE_PROCESS_COUNT); + + for( i = 0; i < THREAD_COUNT; i++ ) + { + if(!CloseHandle(hThread[i]) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i); + testStatus = FAIL; + } + } + + if(!CloseHandle(StartTestsEvHandle)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT); + testStatus = FAIL; + } + + if(!CloseHandle(hMutexHandle)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hMutexHandle\n", GetLastError(), USE_PROCESS_COUNT); + testStatus = FAIL; + } + + PAL_Terminate(); + return testStatus; +} + +void PALAPI Run_Thread (LPVOID lpParam) +{ + unsigned int i = 0; + DWORD dwWaitResult; + + struct statistics stats; + DWORD dwStartTime; + + stats.relationId = RELATION_ID; + stats.processId = USE_PROCESS_COUNT; + stats.operationsFailed = 0; + stats.operationsPassed = 0; + stats.operationsTotal = 0; + stats.operationTime = 0; + + int Id=(int)lpParam; + + dwWaitResult = WaitForSingleObject( + StartTestsEvHandle, // handle to mutex + TIMEOUT); + + if(dwWaitResult != WAIT_OBJECT_0) + { + Trace("Error while waiting for StartTest Event@ thread %d\n", Id); + testStatus = FAIL; + } + + dwStartTime = GetTickCount(); + + for( i = 0; i < REPEAT_COUNT; i++ ) + { + dwWaitResult = WaitForSingleObject( + hMutexHandle, // handle to mutex + TIMEOUT); + + if(dwWaitResult != WAIT_OBJECT_0) + { +// Trace("Error while waiting for onject @ thread %d, # iter %d, Error Returned [%d]\n", Id, i, GetLastError()); + stats.operationsFailed += 1; + stats.operationsTotal += 1; + testStatus = FAIL; + continue; + } + if (! ReleaseMutex(hMutexHandle)) + { + // Deal with error. +// Trace("Error while releasing mutex @ thread %d # iter %d\n", Id, i); + stats.operationsFailed += 1; + stats.operationsTotal += 1; + // Probably need to have while true loop to attempt to release mutex... + testStatus = FAIL; + continue; + } + + stats.operationsTotal += 1; + stats.operationsPassed += 1; +// Trace("Successs while releasing mutex @ iteration %d -> thread %d -> Process count %d\n", i, Id, USE_PROCESS_COUNT); + + } + stats.operationTime = GetTimeDiff(dwStartTime); + if(resultBuffer->LogResult(Id, (char *)&stats)) + { + Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT); + } +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/readme.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/readme.txt new file mode 100644 index 0000000..6bae5f1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/readme.txt @@ -0,0 +1,29 @@ +To compile: + +1) create a dat file (say object_management.dat) with contents: + +PAL,Composite,palsuite\composite\object_management\mutex\nonshared,mutex=main.c mutex.c,,, +PAL,Composite,palsuite\composite\object_management\mutex\shared,mutex=main.c mutex.c,,, +PAL,Composite,palsuite\composite\object_management\semaphore\nonshared,semaphore=main.c semaphore.c,,, +PAL,Composite,palsuite\composite\object_management\semaphore\shared,semaphore=main.c semaphore.c,,, +PAL,Composite,palsuite\composite\object_management\event\nonshared,event=main.c event.c,,, +PAL,Composite,palsuite\composite\object_management\event\shared,event=main.c event.c,,, + + +2) perl rrunmod.pl -r object_management.dat + + +To execute: +For each of the test cases, +main [PROCESS_COUNT] [THREAD_COUNT] [REPEAT_COUNT] + + +Output: +The performance numbers will be in _[event|semaphore|mutex].txt +(will be at palsuite\composite\object_management\[mutex|event|semaphore]\[shared|nonshared]\obj[r|c|d] directory if u use rrunmod.pl) + +So if process_count is 3, you will have files 0_mutex.txt, 1_mutex.txt and so on… + +For each process txt file created, +each row represents a thread data (process id, number of failures, number of pass, total number of repeated operations and an integer that will be used to identify a run +(currently zero)). diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/CMakeLists.txt new file mode 100644 index 0000000..4eeff15 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(nonshared) +add_subdirectory(shared) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/CMakeLists.txt new file mode 100644 index 0000000..4b35e86 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/CMakeLists.txt @@ -0,0 +1,15 @@ +set(SOURCES + main.cpp + semaphore.cpp +) + +add_executable(paltest_semaphore_nonshared + ${SOURCES} +) + +add_dependencies(paltest_semaphore_nonshared coreclrpal) + +target_link_libraries(paltest_semaphore_nonshared + ${COMMON_TEST_LIBRARIES} + rt +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/main.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/main.cpp new file mode 100644 index 0000000..854809c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/main.cpp @@ -0,0 +1,228 @@ +// 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. + +/*============================================================ +** +** Source Code: main.c and semaphore.c +** main.c creates process and waits for all processes to get over +** semaphore.c creates a semaphore and then calls threads which will contend for the semaphore +** +** This test is for Object Management Test case for semaphore where Object type is not shareable. +** Algorithm +** o Create PROCESS_COUNT processes. +** o Main Thread of each process creates OBJECT_TYPE Object +** +** Author: ShamitP +** +** +**============================================================ +*/ + +#include +#include "resulttime.h" + +/* Test Input Variables */ +unsigned int PROCESS_COUNT = 2; +unsigned int THREAD_COUNT = 15; +unsigned int REPEAT_COUNT = 40000; +unsigned int RELATION_ID = 1001; + + + +struct TestStats{ + DWORD operationTime; + unsigned int relationId; + unsigned int processCount; + unsigned int threadCount; + unsigned int repeatCount; + char* buildNumber; +}; + +int GetParameters( int argc, char **argv) +{ + if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Object Management Semaphore Test\n"); + printf("Usage:\n"); + printf("main\n\t[PROCESS_COUNT [greater than 1] \n"); + printf("\t[THREAD_COUNT [greater than 1] \n"); + printf("\t[REPEAT_COUNT [greater than 1]\n"); + printf("\t[RELATION_ID [greater than 1]\n"); + return -1; + } + + PROCESS_COUNT = atoi(argv[1]); + if( (PROCESS_COUNT < 1) || (PROCESS_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 1 and less than PROCESS_COUNT %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than or Equal to 1\n"); + return -1; + } + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hProcess[MAXIMUM_WAIT_OBJECTS]; + HANDLE hSemaphoreHandle[MAXIMUM_WAIT_OBJECTS]; + + STARTUPINFO si[MAXIMUM_WAIT_OBJECTS]; + PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS]; + + const char *ObjName = "Semaphore"; + char lpCommandLine[MAX_PATH] = ""; + + int returnCode = 0; + DWORD processReturnCode = 0; + int testReturnCode = PASS; + + char fileName[MAX_PATH]; + FILE *pFile = NULL; + DWORD dwStartTime; + struct TestStats testStats; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } + + /* Register the start time */ + dwStartTime = GetTickCount(); + testStats.relationId = RELATION_ID; + testStats.processCount = PROCESS_COUNT; + testStats.threadCount = THREAD_COUNT; + testStats.repeatCount = REPEAT_COUNT; + testStats.buildNumber = getBuildNumber(); + + + _snprintf(fileName, MAX_PATH, "main_semaphore_%d_.txt", RELATION_ID); + pFile = fopen(fileName, "w+"); + if(pFile == NULL) + { + Fail("Error in opening main file for write\n"); + } + + for( i = 0; i < PROCESS_COUNT; i++ ) + { + ZeroMemory( lpCommandLine, MAX_PATH ); + if ( _snprintf( lpCommandLine, MAX_PATH-1, "semaphore %d %d %d %d", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID) < 0 ) + { + Fail("Error Insufficient semaphore name string length for %s for iteration [%d]\n", ObjName, i); + } + + /* Zero the data structure space */ + ZeroMemory ( &pi[i], sizeof(pi[i]) ); + ZeroMemory ( &si[i], sizeof(si[i]) ); + + /* Set the process flags and standard io handles */ + si[i].cb = sizeof(si[i]); + + //Create Process + if(!CreateProcess( NULL, /* lpApplicationName*/ + lpCommandLine, /* lpCommandLine */ + NULL, /* lpProcessAttributes */ + NULL, /* lpThreadAttributes */ + TRUE, /* bInheritHandles */ + 0, /* dwCreationFlags, */ + NULL, /* lpEnvironment */ + NULL, /* pCurrentDirectory */ + &si[i], /* lpStartupInfo */ + &pi[i] /* lpProcessInformation */ + )) + { + Fail("Process Not created for [%d], the error code is [%d]\n", i, GetLastError()); + } + else + { + hProcess[i] = pi[i].hProcess; +// Trace("Process created for [%d]\n", i); + + } + } + + returnCode = WaitForMultipleObjects( PROCESS_COUNT, hProcess, TRUE, INFINITE); + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", PROCESS_COUNT, returnCode, GetLastError()); + testReturnCode = FAIL; + } + + for( i = 0; i < PROCESS_COUNT; i++ ) + { + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) ) + { + Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n", + i, GetLastError() ); + + testReturnCode = FAIL; + } + + if(processReturnCode == FAIL) + { + Trace( "Process [%d] failed and returned FAIL\n", i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hThread)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hProcess) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i); + testReturnCode = FAIL; + } + } + + testStats.operationTime = GetTimeDiff(dwStartTime); + fprintf(pFile, "%d,%d,%d,%d,%d,%s\n", testStats.operationTime, testStats.relationId,testStats.processCount, testStats.threadCount, testStats.repeatCount, testStats.buildNumber ); + if(fclose(pFile)) + { + Trace("Error: fclose failed for pFile\n"); + testReturnCode = FAIL; + } + + if( testReturnCode == PASS) + { + Trace("Test Passed\n"); + } + else + { + Trace("Test Failed\n"); + } + + PAL_Terminate(); + return testReturnCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/semaphore.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/semaphore.cpp new file mode 100644 index 0000000..0e487f2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/semaphore.cpp @@ -0,0 +1,342 @@ +// 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. + +/*============================================================ +** +** Source Code: main.c and semaphore.c +** main.c creates process and waits for all processes to get over +** semaphore.c creates a semaphore and then calls threads which will contend for the semaphore +** +** This test is for Object Management Test case for semaphore where Object type is not shareable. +** Algorithm +** o Create PROCESS_COUNT processes. +** o Main Thread of each process creates OBJECT_TYPE Object +** +** Author: ShamitP +** +** +**============================================================ +*/ + +#include +#include "resultbuffer.h" +#include "resulttime.h" + +#define TIMEOUT 5000 +/* Test Input Variables */ +unsigned int USE_PROCESS_COUNT = 0; +unsigned int THREAD_COUNT = 0; +unsigned int REPEAT_COUNT = 0; +unsigned int RELATION_ID = 0; + +/* Capture statistics at per thread basis */ +struct statistics{ + unsigned int processId; + unsigned int operationsFailed; + unsigned int operationsPassed; + unsigned int operationsTotal; + DWORD operationTime; + unsigned int relationId; +}; + +struct ProcessStats{ + unsigned int processId; + DWORD operationTime; + unsigned int relationId; +}; + +/* Semaphore variables */ +unsigned long lInitialCount = 1; /* Signaled */ +unsigned long lMaximumCount = 1; /* Maximum value of 1 */ + +HANDLE StartTestsEvHandle = NULL; +HANDLE hSemaphoreHandle = NULL; + +/* Results Buffer */ +ResultBuffer *resultBuffer = NULL; + +int testStatus; + +const char sTmpEventName[MAX_PATH] = "StartTestEvent"; + +void PALAPI Run_Thread(LPVOID lpParam); + +int GetParameters( int argc, char **argv) +{ + if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Object Management Semaphore Test\n"); + printf("Usage:\n"); + printf("semaphore\n\t[USE_PROCESS_COUNT ( greater than 1] \n"); + printf("\t[THREAD_COUNT ( greater than 1] \n"); + printf("\t[REPEAT_COUNT ( greater than 1]\n"); + printf("\t[RELATION_ID [greater than 1]\n"); + return -1; + } + + // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]); + + USE_PROCESS_COUNT = atoi(argv[1]); + if( USE_PROCESS_COUNT < 0) + { + printf("\nInvalid USE_PROCESS_COUNT number, Pass greater than 1\n"); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than or Equal to 1\n"); + return -1; + } + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hThread[MAXIMUM_WAIT_OBJECTS]; + DWORD threadId[MAXIMUM_WAIT_OBJECTS]; + + const char *ObjName = "Semaphore"; + + DWORD dwParam = 0; + + int returnCode = 0; + + /* Variables to capture the file name and the file pointer at thread level*/ + char fileName[MAX_PATH]; + FILE *pFile = NULL; + struct statistics* buffer = NULL; + int statisticsSize = 0; + + /* Variables to capture the file name and the file pointer at process level*/ + char processFileName[MAX_PATH]; + FILE *pProcessFile = NULL; + struct ProcessStats processStats; + DWORD dwStartTime; + + testStatus = PASS; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } + // Trace("Process created, value of process count is [%d]\n", USE_PROCESS_COUNT); + + /* Register the start time */ + dwStartTime = GetTickCount(); + processStats.relationId = RELATION_ID; + processStats.processId = USE_PROCESS_COUNT; + + _snprintf(processFileName, MAX_PATH, "%d_process_semaphore_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); + pProcessFile = fopen(processFileName, "w+"); + if(pProcessFile == NULL) + { + Fail("Error in opening process File file for write for process [%d]\n", USE_PROCESS_COUNT); + } + + statisticsSize = sizeof(struct statistics); + + _snprintf(fileName, MAX_PATH, "%d_thread_semaphore_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); + pFile = fopen(fileName, "w+"); + if(pFile == NULL) + { + Fail("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT); + } + // For each thread we will log operations failed (int), passed (int), total (int) + // and number of ticks (DWORD) for the operations + resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize); + + StartTestsEvHandle = CreateEvent( NULL, /* lpEventAttributes*/ + TRUE, /* bManualReset */ + FALSE, /* bInitialState */ + NULL); /* name of Event */ + + if( StartTestsEvHandle == NULL ) + { + Fail("Error:%d: Unexpected failure " + "to create %s Event for process count %d\n", GetLastError(), sTmpEventName, USE_PROCESS_COUNT ); + + } + + /* Create StartTest Event */ + hSemaphoreHandle = CreateSemaphore( + NULL, /* lpSemaphoreAttributes */ + lInitialCount, /*lInitialCount*/ + lMaximumCount, /*lMaximumCount */ + NULL + ); + + if( hSemaphoreHandle == NULL) + { + Fail("Unable to create Semaphore handle for process id [%d], returned error [%d]\n", i, GetLastError()); + } + /* We already assume that the Semaphore was created previously*/ + + for( i = 0; i < THREAD_COUNT; i++ ) + { + dwParam = (int) i; + //Create thread + hThread[i] = CreateThread( + NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */ + (LPVOID)dwParam, /* argument to thread function */ + 0, /* use default creation flags */ + &threadId[i] /* returns the thread identifier*/ + ); + + + if(hThread[i] == NULL) + { + Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError()); + } + + } + + if (!SetEvent(StartTestsEvHandle)) + { + Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError()); + } + + /* Test running */ + returnCode = WaitForMultipleObjects( THREAD_COUNT, hThread, TRUE, INFINITE); + + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError()); + testStatus = FAIL; + } + + processStats.operationTime = GetTimeDiff(dwStartTime); + + /* Write to a file*/ + if(pFile!= NULL) + { + for( i = 0; i < THREAD_COUNT; i++ ) + { + buffer = (struct statistics *)resultBuffer->getResultBuffer(i); + returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); + //Trace("Iteration %d over\n", i); + + } + } + fclose(pFile); + /* Logging for the test case over, clean up the handles */ + +// Trace("Test Thread %d done\n", USE_PROCESS_COUNT); + + for( i = 0; i < THREAD_COUNT; i++ ) + { + if(!CloseHandle(hThread[i]) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i); + testStatus = FAIL; + } + } + + if(!CloseHandle(StartTestsEvHandle)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT); + testStatus = FAIL; + } + + if(!CloseHandle(hSemaphoreHandle)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hSemaphoreHandle\n", GetLastError(), USE_PROCESS_COUNT); + testStatus = FAIL; + } + + PAL_Terminate(); + return PASS; +} + +void PALAPI Run_Thread (LPVOID lpParam) +{ + unsigned int i = 0; + DWORD dwWaitResult; + + int Id=(int)lpParam; + + struct statistics stats; + DWORD dwStartTime; + + stats.relationId = RELATION_ID; + stats.processId = USE_PROCESS_COUNT; + stats.operationsFailed = 0; + stats.operationsPassed = 0; + stats.operationsTotal = 0; + stats.operationTime = 0; + + dwWaitResult = WaitForSingleObject( + StartTestsEvHandle, // handle to start test handle + TIMEOUT); + + if(dwWaitResult != WAIT_OBJECT_0) + { + Fail("Error while waiting for StartTest Event@ thread %d, RC is %d, Error is %d\n", Id, dwWaitResult, GetLastError()); + } + + dwStartTime = GetTickCount(); + + for( i = 0; i < REPEAT_COUNT; i++ ) + { + dwWaitResult = WaitForSingleObject( + hSemaphoreHandle, // handle to Semaphore + TIMEOUT); + + if(dwWaitResult != WAIT_OBJECT_0) + { +// Trace("Error while waiting for onject @ thread %d, # iter %d, RC is %d, Error is %d\n", Id, i, dwWaitResult, GetLastError()); + stats.operationsFailed += 1; + stats.operationsTotal += 1; + testStatus = FAIL; + continue; + } + if (! ReleaseSemaphore(hSemaphoreHandle, 1, NULL)) + { + // Deal with error. + // Trace("Error while releasing Semaphore @ thread %d # iter %d\n", Id, i); + stats.operationsFailed += 1; + stats.operationsTotal += 1; + // Probably need to have while true loop to attempt to release semaphore... + testStatus = FAIL; + continue; + } + + stats.operationsTotal += 1; + stats.operationsPassed += 1; +// Trace("Successs while releasing Semaphore @ iteration %d -> thread %d -> Process %d\n", i, Id, USE_PROCESS_COUNT); + + } + + stats.operationTime = GetTimeDiff(dwStartTime); + if(resultBuffer->LogResult(Id, (char *)&stats)) + { + Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT); + } + // Trace("Thread %d over for process %d\n", Id, USE_PROCESS_COUNT); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/shared/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/shared/CMakeLists.txt new file mode 100644 index 0000000..92fb32a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/shared/CMakeLists.txt @@ -0,0 +1,15 @@ +set(SOURCES + main.cpp + semaphore.cpp +) + +add_executable(paltest_semaphore_shared + ${SOURCES} +) + +add_dependencies(paltest_semaphore_shared coreclrpal) + +target_link_libraries(paltest_semaphore_shared + ${COMMON_TEST_LIBRARIES} + rt +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/shared/main.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/shared/main.cpp new file mode 100644 index 0000000..d3cfa76 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/shared/main.cpp @@ -0,0 +1,275 @@ +// 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. + +/*============================================================ +** +** Source Code: main.c and semaphore.c +** main.c creates process and waits for all processes to get over +** semaphore.c creates a semaphore and then calls threads which will contend for the semaphore +** +** This test is for Object Management Test case for semaphore where Object type is shareable. +** Algorithm +** o Main Process Creates OBJECT_TYPE Object +** o Create PROCESS_COUNT processes aware of the Shared Object +** +** +** +**============================================================ +*/ + +#include +#include "resulttime.h" + +/* Test Input Variables */ +unsigned int PROCESS_COUNT = 1; +unsigned int THREAD_COUNT = 1; +unsigned int REPEAT_COUNT = 4; +unsigned int RELATION_ID = 1001; + + +unsigned long lInitialCount = 1; /* Signaled */ +unsigned long lMaximumCount = 1; /* Maximum value of 1 */ + +char objectSuffix[MAX_PATH]; + +struct TestStats{ + DWORD operationTime; + unsigned int relationId; + unsigned int processCount; + unsigned int threadCount; + unsigned int repeatCount; + char* buildNumber; + +}; + +int GetParameters( int argc, char **argv) +{ + if( (!((argc == 5) || (argc == 6) ) )|| ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Object Management event Test\n"); + printf("Usage:\n"); + printf("main\n\t[PROCESS_COUNT (greater than 1)] \n"); + printf("\t[THREAD_COUNT (greater than 1)] \n"); + printf("\t[REPEAT_COUNT (greater than 1)]\n"); + printf("\t[RELATION_ID [greater than or equal to 1]\n"); + printf("\t[Object Name Suffix]\n"); + return -1; + } + + PROCESS_COUNT = atoi(argv[1]); + if( (PROCESS_COUNT < 1) || (PROCESS_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 1 and less than PROCESS_COUNT %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + + if(argc == 6) + { + strncpy(objectSuffix, argv[5], MAX_PATH-1); + } + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hProcess[MAXIMUM_WAIT_OBJECTS]; + HANDLE hSemaphoreHandle; + + STARTUPINFO si[MAXIMUM_WAIT_OBJECTS]; + PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS]; + + char lpCommandLine[MAX_PATH] = ""; + char ObjName[MAX_PATH] = "SHARED_SEMAPHORE"; + + int returnCode = 0; + DWORD processReturnCode = 0; + int testReturnCode = PASS; + + char fileName[MAX_PATH]; + FILE *pFile = NULL; + DWORD dwStartTime; + struct TestStats testStats; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + +/* +"While the new PAL does support named semaphore it's unclear +if we should change the Windows PAL, since we share that w/ Rotor +and they are still using the old PAL. For the time being it may +make the most sense to just skip the named semaphore test on Windows +- from an object management perspective it doesn't really gain +us anything over what we already have." +*/ + ZeroMemory( objectSuffix, MAX_PATH ); + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } + + if(argc == 6) + { + strncat(ObjName, objectSuffix, MAX_PATH - (sizeof(ObjName) + 1) ); + } + + /* Register the start time */ + dwStartTime = GetTickCount(); + testStats.relationId = RELATION_ID; + testStats.processCount = PROCESS_COUNT; + testStats.threadCount = THREAD_COUNT; + testStats.repeatCount = REPEAT_COUNT; + testStats.buildNumber = getBuildNumber(); + + _snprintf(fileName, MAX_PATH, "main_semaphore_%d_.txt", RELATION_ID); + pFile = fopen(fileName, "w+"); + if(pFile == NULL) + { + Fail("Error in opening main file for write\n"); + } + + hSemaphoreHandle = CreateSemaphore( + NULL, /* lpSemaphoreAttributes */ + lInitialCount, /*lInitialCount*/ + lMaximumCount, /*lMaximumCount */ + ObjName + ); + + if( hSemaphoreHandle == NULL) + { + Fail("Unable to create shared Semaphore handle @ Main returned error [%d]\n", GetLastError()); + } + + for( i = 0; i < PROCESS_COUNT; i++ ) + { + + + ZeroMemory( lpCommandLine, MAX_PATH ); + if ( _snprintf( lpCommandLine, MAX_PATH-1, "semaphore %d %d %d %d %s", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID, objectSuffix) < 0 ) + { + Fail("Error: Insufficient semaphore name string length for %s for iteration [%d]\n", ObjName, i); + } + + + /* Zero the data structure space */ + ZeroMemory ( &pi[i], sizeof(pi[i]) ); + ZeroMemory ( &si[i], sizeof(si[i]) ); + + /* Set the process flags and standard io handles */ + si[i].cb = sizeof(si[i]); + + if(!CreateProcess( NULL, /* lpApplicationName*/ + lpCommandLine, /* lpCommandLine */ + NULL, /* lpProcessAttributes */ + NULL, /* lpThreadAttributes */ + TRUE, /* bInheritHandles */ + 0, /* dwCreationFlags, */ + NULL, /* lpEnvironment */ + NULL, /* pCurrentDirectory */ + &si[i], /* lpStartupInfo */ + &pi[i] /* lpProcessInformation */ + )) + { + Fail("Process Not created for [%d], the error code is [%d]\n", i, GetLastError()); + } + else + { + hProcess[i] = pi[i].hProcess; +// Trace("Process created for [%d]\n", i); + + } + + } + + returnCode = WaitForMultipleObjects( PROCESS_COUNT, hProcess, TRUE, INFINITE); + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", PROCESS_COUNT, returnCode, GetLastError()); + testReturnCode = FAIL; + } + + for( i = 0; i < PROCESS_COUNT; i++ ) + { + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) ) + { + Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n", + i, GetLastError() ); + + testReturnCode = FAIL; + } + + if(processReturnCode == FAIL) + { + Trace( "Process [%d] failed and returned FAIL\n", i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hThread)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hProcess) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i); + testReturnCode = FAIL; + } + } + + testStats.operationTime = GetTimeDiff(dwStartTime); + fprintf(pFile, "%d,%d,%d,%d,%d,%s\n", testStats.operationTime, testStats.relationId, testStats.processCount, testStats.threadCount, testStats.repeatCount, testStats.buildNumber); + if(fclose(pFile)) + { + Trace("Error: fclose failed for pFile\n"); + testReturnCode = FAIL; + }; + + if(!CloseHandle(hSemaphoreHandle)) + { + Trace("Error:%d: CloseHandle failed for hSemaphoreHandle\n", GetLastError()); + testReturnCode = FAIL; + + } + + if( testReturnCode == PASS) + { + Trace("Test Passed\n"); + } + else + { + Trace("Test Failed\n"); + } + + PAL_Terminate(); + return testReturnCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/shared/semaphore.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/shared/semaphore.cpp new file mode 100644 index 0000000..5143c55 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/object_management/semaphore/shared/semaphore.cpp @@ -0,0 +1,351 @@ +// 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. + +/*============================================================ +** +** Source Code: main.c and semaphore.c +** main.c creates process and waits for all processes to get over +** semaphore.c creates a semaphore and then calls threads which will contend for the semaphore +** +** This test is for Object Management Test case for semaphore where Object type is shareable. +** Algorithm +** o Main Process Creates OBJECT_TYPE Object +** o Create PROCESS_COUNT processes aware of the Shared Object +** +** +** +**============================================================ +*/ + +#include +#include "resultbuffer.h" +#include "resulttime.h" + +#define TIMEOUT 5000 +/* Test Input Variables */ +unsigned int USE_PROCESS_COUNT = 0; +unsigned int THREAD_COUNT = 0; +unsigned int REPEAT_COUNT = 0; +unsigned int RELATION_ID= 0; + +/* Capture statistics at per thread basis */ +struct statistics{ + unsigned int processId; + unsigned int operationsFailed; + unsigned int operationsPassed; + unsigned int operationsTotal; + DWORD operationTime; + unsigned int relationId; +}; + +struct ProcessStats{ + unsigned int processId; + DWORD operationTime; + unsigned int relationId; +}; + +/* Semaphore variables */ +unsigned long lInitialCount = 1; /* Signaled */ +unsigned long lMaximumCount = 1; /* Maximum value of 1 */ + +HANDLE StartTestsEvHandle = NULL; +HANDLE hSemaphoreHandle = NULL; + +/* Results Buffer */ +ResultBuffer *resultBuffer = NULL; + +int testStatus; + +const char sTmpEventName[MAX_PATH] = "StartTestEvent"; +char objectSuffix[MAX_PATH]; + +void PALAPI Run_Thread(LPVOID lpParam); + +int GetParameters( int argc, char **argv) +{ + if( (!((argc == 5) || (argc == 6) ) )|| ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Object Management event Test\n"); + printf("Usage:\n"); + printf("main\n\t[PROCESS_COUNT (greater than 1)] \n"); + printf("\t[THREAD_COUNT (greater than 1)] \n"); + printf("\t[REPEAT_COUNT (greater than 1)]\n"); + printf("\t[RELATION_ID [greater than or equal to 1]\n"); + printf("\t[Object Name Suffix]\n"); + return -1; + } + + USE_PROCESS_COUNT = atoi(argv[1]); + if(USE_PROCESS_COUNT < 0) + { + printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 0 \n"); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + if(argc == 6) + { + strncpy(objectSuffix, argv[5], MAX_PATH-1); + } + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hThread[MAXIMUM_WAIT_OBJECTS]; + DWORD threadId[MAXIMUM_WAIT_OBJECTS]; + + char ObjName[MAX_PATH] = "SHARED_SEMAPHORE"; + DWORD dwParam = 0; + + int returnCode = 0; + + /* Variables to capture the file name and the file pointer at thread level*/ + char fileName[MAX_PATH]; + FILE *pFile = NULL; + struct statistics* buffer = NULL; + int statisticsSize = 0; + + /* Variables to capture the file name and the file pointer at process level*/ + char processFileName[MAX_PATH]; + FILE *pProcessFile = NULL; + struct ProcessStats processStats; + DWORD dwStartTime; + + testStatus = PASS; + + ZeroMemory( objectSuffix, MAX_PATH ); + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } +// Trace("Process created, value of process count is [%d]\n", USE_PROCESS_COUNT); + + if(argc == 6) + { + strncat(ObjName , objectSuffix, MAX_PATH - (sizeof(ObjName) + 1) ); + } + + /* Register the start time */ + dwStartTime = GetTickCount(); + processStats.relationId = RELATION_ID; + processStats.processId = USE_PROCESS_COUNT; + + _snprintf(processFileName, MAX_PATH, "%d_process_semaphore_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); + pProcessFile = fopen(processFileName, "w+"); + if(pProcessFile == NULL) + { + Fail("Error in opening process File file for write for process [%d]\n", USE_PROCESS_COUNT); + } + + statisticsSize = sizeof(struct statistics); + + _snprintf(fileName, MAX_PATH, "%d_thread_semaphore_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); + pFile = fopen(fileName, "w+"); + if(pFile == NULL) + { + Fail("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT); + } + // For each thread we will log operations failed (int), passed (int), total (int) + // and number of ticks (DWORD) for the operations + resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize); + + /* Create Start Tests event */ + StartTestsEvHandle = CreateEvent( NULL, /* lpEventAttributes*/ + TRUE, /* bManualReset */ + FALSE, /* bInitialState */ + NULL); /* name of Event */ + + if( StartTestsEvHandle == NULL ) + { + Fail("Error:%d: Unexpected failure " + "to create %s Event for process count %d\n", GetLastError(), sTmpEventName, USE_PROCESS_COUNT ); + + } + + hSemaphoreHandle = CreateSemaphore( + NULL, /* lpSemaphoreAttributes */ + lInitialCount, /*lInitialCount*/ + lMaximumCount, /*lMaximumCount */ + ObjName + ); + + + if( (hSemaphoreHandle == NULL) || (GetLastError() != ERROR_ALREADY_EXISTS) ) + { + Fail("Unable to create Semaphore handle for process id [%d], returned error [%d], expected ERROR_ALREADY_EXISTS\n", i, GetLastError()); + } + + /* We already assume that the Semaphore was created previously*/ + + for( i = 0; i < THREAD_COUNT; i++ ) + { + dwParam = (int) i; + //Create thread + hThread[i] = CreateThread( + NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */ + (LPVOID)dwParam, /* argument to thread function */ + 0, /* use default creation flags */ + &threadId[i] /* returns the thread identifier*/ + ); + + if(hThread[i] == NULL) + { + Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError()); + } + } + + if (!SetEvent(StartTestsEvHandle)) + { + Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError()); + } + + /* Test running */ + returnCode = WaitForMultipleObjects( THREAD_COUNT, hThread, TRUE, INFINITE); + + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError()); + testStatus = FAIL; + } + + processStats.operationTime = GetTimeDiff(dwStartTime); + + /* Write to a file*/ + if(pFile!= NULL) + { + for( i = 0; i < THREAD_COUNT; i++ ) + { + buffer = (struct statistics *)resultBuffer->getResultBuffer(i); + returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); +// Trace("Iteration %d over\n", i); + + } + } + fclose(pFile); + /* Logging for the test case over, clean up the handles */ + +// Trace("Test Thread %d done\n", USE_PROCESS_COUNT); + for( i = 0; i < THREAD_COUNT; i++ ) + { + if(!CloseHandle(hThread[i]) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i); + testStatus = FAIL; + } + } + + if(!CloseHandle(StartTestsEvHandle)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT); + testStatus = FAIL; + } + + if(!CloseHandle(hSemaphoreHandle)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hSemaphoreHandle\n", GetLastError(), USE_PROCESS_COUNT); + testStatus = FAIL; + } + + PAL_Terminate(); + return PASS; +} + +void PALAPI Run_Thread (LPVOID lpParam) +{ + unsigned int i = 0; + DWORD dwWaitResult; + + int Id=(int)lpParam; + + struct statistics stats; + DWORD dwStartTime; + + stats.relationId = RELATION_ID; + stats.processId = USE_PROCESS_COUNT; + stats.operationsFailed = 0; + stats.operationsPassed = 0; + stats.operationsTotal = 0; + stats.operationTime = 0; + + dwWaitResult = WaitForSingleObject( + StartTestsEvHandle, // handle to start test handle + TIMEOUT); + + if(dwWaitResult != WAIT_OBJECT_0) + { + Fail("Error while waiting for StartTest Event@ thread %d, RC is %d, Error is %d\n", Id, dwWaitResult, GetLastError()); + } + + dwStartTime = GetTickCount(); + + for( i = 0; i < REPEAT_COUNT; i++ ) + { + dwWaitResult = WaitForSingleObject( + hSemaphoreHandle, // handle to Semaphore + TIMEOUT); + + if(dwWaitResult != WAIT_OBJECT_0) + { +// Trace("Error while waiting for onject @ thread %d, # iter %d, RC is %d, Error is %d\n", Id, i, dwWaitResult, GetLastError()); + stats.operationsFailed += 1; + stats.operationsTotal += 1; + testStatus = FAIL; + continue; + } + if (! ReleaseSemaphore(hSemaphoreHandle, 1, NULL)) + { + // Deal with error. + // Trace("Error while releasing Semaphore @ thread %d # iter %d\n", Id, i); + stats.operationsFailed += 1; + stats.operationsTotal += 1; + // Probably need to have while true loop to attempt to release semaphore.. + testStatus = FAIL; + continue; + } + + stats.operationsTotal += 1; + stats.operationsPassed += 1; +// Trace("Successs while releasing Semaphore @ iteration %d -> thread %d -> Process %d\n", i, Id, USE_PROCESS_COUNT); + + } + + stats.operationTime = GetTimeDiff(dwStartTime); + if(resultBuffer->LogResult(Id, (char *)&stats)) + { + Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT); + } + // Trace("Thread %d over for process %d\n", Id, USE_PROCESS_COUNT); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/CMakeLists.txt new file mode 100644 index 0000000..e21f4d3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(criticalsection) +add_subdirectory(nativecriticalsection) +add_subdirectory(nativecs_interlocked) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/CMakeLists.txt new file mode 100644 index 0000000..8b7b607 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/CMakeLists.txt @@ -0,0 +1,14 @@ +set(SOURCES + criticalsection.cpp + mainWrapper.cpp +) + +add_executable(paltest_synchronization_criticalsection + ${SOURCES} +) + +add_dependencies(paltest_synchronization_criticalsection coreclrpal) + +target_link_libraries(paltest_synchronization_criticalsection + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.cpp new file mode 100644 index 0000000..2fcd363 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.cpp @@ -0,0 +1,418 @@ +// 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. + +/*============================================================ +** +** Source: criticalsection.c +** +** Purpose: Test Critical Section Reengineering PAL Effort +** +** PseudoCode: + Preparation: + Create PROCESS_COUNT processes. + In each process create a Critical Section + + Test: + Create THREAD_COUNT threads. + In a loop repeated REPEAT_COUNT times: + Enter Critical Section + Do Work + Leave Critical Section + The main thread waits for all of the created threads to exit (WFMO wait all on the created thread handles) and call DeleteCriticalSection + + Parameters: + PROCESS_COUNT: Number of processes + THREAD_COUNT: Number of threads in each process + REPEAT_COUNT: The number of times to execute the loop.. + + Statistics Captured: + Total elapsed time + MTBF + + Scenario: + Single Process with Multiple threads. Main thread creates critical section. + All other threads call EnterCriticalSection. When thread enters critical section + it does some work and leaves critical section. + +** Dependencies: + CreateThread +** InitializeCriticalSection +** EnterCriticalSection +** LeaveCriticalSection +** DeleteCriticalSection +** WaitForSingleObject +** +** Author: rameshg +** +** +**=========================================================*/ + +#include +#include "resultbuffer.h" + +//Global Variables +DWORD dwThreadId; +long long GLOBAL_COUNTER ; +HANDLE g_hEvent; + +/* Test Input Variables */ +unsigned int USE_PROCESS_COUNT = 0; +unsigned int THREAD_COUNT = 0; +unsigned int REPEAT_COUNT = 0; +unsigned int SLEEP_LENGTH = 0; +unsigned int RELATION_ID = 0; + + +CRITICAL_SECTION CriticalSectionM; /* Critical Section Object (used as mutex) */ + + +/* Capture statistics for each worker thread */ +struct statistics{ + unsigned int processId; + unsigned int operationsFailed; + unsigned int operationsPassed; + unsigned int operationsTotal; + DWORD operationTime; //Milliseconds + unsigned int relationId; +}; + + +/*Capture Statistics at a Process level*/ +struct processStatistics{ + unsigned int processId; + DWORD operationTime; //Milliseconds + unsigned int relationId; +}; + + +ResultBuffer *resultBuffer; + +//function declarations +int GetParameters( int , char **); +void setup (void); +void cleanup(void); +void incrementCounter(void); +DWORD PALAPI enterandleavecs( LPVOID ); + + +/* +*Setup for the test case +*/ + +VOID +setup(VOID) +{ + +g_hEvent = CreateEvent(NULL,TRUE,FALSE, NULL); +if(g_hEvent == NULL) +{ + Fail("Create Event Failed\n" + "GetLastError returned %d\n", GetLastError()); +} + +GLOBAL_COUNTER=0; +/* +* Create mutual exclusion mechanisms +*/ +InitializeCriticalSection ( &CriticalSectionM ); + +} + + +/* +* Cleanup for the test case +*/ +VOID +cleanup(VOID) +{ + /* + * Clean up Critical Section object + */ + DeleteCriticalSection(&CriticalSectionM); + PAL_Terminate(); +} + + +/*function that increments a counter*/ +VOID +incrementCounter(VOID) +{ + + if (INT_MAX==GLOBAL_COUNTER) + GLOBAL_COUNTER=0; + + GLOBAL_COUNTER++; + +} + +/* + * Enter and Leave Critical Section + */ +DWORD +PALAPI +enterandleavecs( LPVOID lpParam ) +{ + + struct statistics stats; + int loopcount = REPEAT_COUNT; + int i; + DWORD dwStart =0; + + int Id=(int)lpParam; + + //initialize strucutre to hold thread level statistics + stats.relationId = RELATION_ID; + stats.processId = USE_PROCESS_COUNT; + stats.operationsFailed = 0; + stats.operationsPassed = 0; + stats.operationsTotal = 0; + stats.operationTime = 0; + + //Wait for main thread to signal event + if (WAIT_OBJECT_0 != WaitForSingleObject(g_hEvent,INFINITE)) + { + Fail ("readfile: Wait for Single Object (g_hEvent) failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + //Collect operation start time + dwStart = GetTickCount(); + + //Operation starts loopcount times + for(i = 0; i < loopcount; i++) + { + + EnterCriticalSection(&CriticalSectionM); + /* + *Do Some Thing once you enter critical section + */ + incrementCounter(); + LeaveCriticalSection(&CriticalSectionM); + + stats.operationsPassed++; + stats.operationsTotal++; + } + //collect operation end time + stats.operationTime = GetTickCount() - dwStart; + + /*Trace("\n\n\n\nOperation Time %d\n", stats.operationTime); + Trace("Operation Passed %d\n", stats.operationsPassed); + Trace("Operation Total %d\n", stats.operationsTotal); + Trace("Operation Failed %d\n", stats.operationsFailed); */ + + if(resultBuffer->LogResult(Id, (char *)&stats)) + { + Fail("Error while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", Id, USE_PROCESS_COUNT); + } + + + return 0; +} + + +int __cdecl main (int argc, char **argv) +{ + +/* +* Parameter to the threads that will be created +*/ +DWORD dwThrdParam = 0; +HANDLE hThread[64]; +unsigned int i = 0; +DWORD dwStart; + +/* Variables to capture the file name and the file pointer*/ +char fileName[MAX_PATH_FNAME]; +char processFileName[MAX_PATH_FNAME]; +FILE *hFile,*hProcessFile; +struct processStatistics processStats; + +struct statistics* buffer; +int statisticsSize = 0; + +/* +* PAL Initialize +*/ +if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + +if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } + + +/*setup file for process result collection */ +_snprintf(processFileName, MAX_PATH_FNAME, "%d_process_criticalsection_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); +hProcessFile = fopen(processFileName, "w+"); +if(hProcessFile == NULL) + { + Fail("Error in opening file to write process results for process [%d]\n", USE_PROCESS_COUNT); + } + +//Initialize Process Stats Variables +processStats.operationTime = 0; +processStats.processId = USE_PROCESS_COUNT; +processStats.relationId = RELATION_ID; //Will change later + +//Start Process Time Capture +dwStart = GetTickCount(); + +//setup file for thread result collection +statisticsSize = sizeof(struct statistics); +_snprintf(fileName, MAX_PATH_FNAME, "%d_thread_criticalsection_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); +hFile = fopen(fileName, "w+"); +if(hFile == NULL) +{ + Fail("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT); +} + +// For each thread we will log operations failed (int), passed (int), total (int) +// and number of ticks (DWORD) for the operations +resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize); + +/* +* Call the Setup Routine +*/ +setup(); + +//Create Thread Count Worker Threads + +while (i< THREAD_COUNT) +{ + dwThrdParam = i; + + hThread[i] = CreateThread( + NULL, + 0, + enterandleavecs, + (LPVOID)dwThrdParam, + 0, + &dwThreadId); + + if ( NULL == hThread[i] ) + { + Fail ( "CreateThread() returned NULL. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + i++; +} + +/* +* Set Event to signal all threads to start using the CS +*/ + +if (0==SetEvent(g_hEvent)) +{ + Fail ( "SetEvent returned Zero. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); +} + +/* + * Wait for worker threads to complete + * + */ +if ( WAIT_OBJECT_0 != WaitForMultipleObjects (THREAD_COUNT,hThread,TRUE, INFINITE)) +{ + Fail ( "WaitForMultipleObject Failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); +} + + +//Get the end time of the process +processStats.operationTime = GetTickCount() - dwStart; + +//Write Process Result Contents to File +if(hProcessFile!= NULL) + { + fprintf(hProcessFile, "%d,%lu,%d\n", processStats.processId, processStats.operationTime, processStats.relationId ); + } + +if (0!=fclose(hProcessFile)) +{ + Fail("Unable to write process results to file" + "GetLastError returned %d\n", GetLastError()); +} + + +/*Write Threads Results to a file*/ +if(hFile!= NULL) +{ + for( i = 0; i < THREAD_COUNT; i++ ) + { + buffer = (struct statistics *)resultBuffer->getResultBuffer(i); + fprintf(hFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); + //Trace("Iteration %d over\n", i); + } +} + +if (0!=fclose(hFile)) +{ + Fail("Unable to write thread results to file" + "GetLastError returned %d\n", GetLastError()); +} + + /* Logging for the test case over, clean up the handles */ + //Trace("Contents of the buffer are [%s]\n", resultBuffer->getResultBuffer()); + + +//Call Cleanup for Test Case +cleanup(); + +//Trace("Value of GLOBAL COUNTER %d \n", GLOBAL_COUNTER); +return (PASS); + +} + + +int GetParameters( int argc, char **argv) +{ + + if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Critical Section Test\n"); + printf("Usage:\n"); + printf("\t[PROCESS_COUNT] Greater than or Equal to 1 \n"); + printf("\t[WORKER_THREAD_MULTIPLIER_COUNT] Greater than or Equal to 1 and Less than or Equal to 64 \n"); + printf("\t[REPEAT_COUNT] Greater than or Equal to 1\n"); + printf("\t[RELATION_ID [Greater than or Equal to 1]\n"); + return -1; + } + +// Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]); + + USE_PROCESS_COUNT = atoi(argv[1]); + if( USE_PROCESS_COUNT < 0) + { + printf("\nPROCESS_COUNT to greater than or equal to 1\n"); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( THREAD_COUNT < 1 || THREAD_COUNT > 64) + { + printf("\nTHREAD_COUNT to be greater than or equal to 1 or less than or equal to 64\n"); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nREPEAT_COUNT to greater than or equal to 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + return 0; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.cpp new file mode 100644 index 0000000..4bc2f3d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.cpp @@ -0,0 +1,255 @@ +// 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. + +/* +Source Code: mainWrapper.c + +mainWrapper.c creates Composite Test Case Processes and waits for all processes to get over + +Algorithm +o Create PROCESS_COUNT processes. + +Author: RameshG +*/ + +#include +#include "resulttime.h" + +/* Test Input Variables */ +unsigned int USE_PROCESS_COUNT = 0; //default +unsigned int THREAD_COUNT = 0; //default +unsigned int REPEAT_COUNT = 0; //default +unsigned int SLEEP_LENGTH = 0; //default +unsigned int RELATION_ID = 1001; + + +//Strucuture to capture application wide statistics +struct applicationStatistics{ + DWORD operationTime; + unsigned int relationId; + unsigned int processCount; + unsigned int threadCount; + unsigned int repeatCount; + char* buildNumber; + +}; + + +//Get parameters from the commandline +int GetParameters( int argc, char **argv) +{ + + if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("Main Wrapper PAL -Composite Critical Section Test\n"); + printf("Usage:\n"); + printf("\t[PROCESS_COUNT] Greater than or Equal to 1 \n"); + printf("\t[THREAD_COUNT] Greater than or Equal to 1 and Less than or Equal to 64 \n"); + printf("\t[REPEAT_COUNT] Greater than or Equal to 1\n"); + printf("\t[RELATION_ID [Greater than or Equal to 1]\n"); + + return -1; + } + + USE_PROCESS_COUNT = atoi(argv[1]); + if( USE_PROCESS_COUNT < 0) + { + printf("\nPROCESS_COUNT to greater than or equal to 1\n"); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( THREAD_COUNT < 1 || THREAD_COUNT > 64) + { + printf("\nTHREAD_COUNT to be greater than or equal to 1 or less than or equal to 64\n"); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nREPEAT_COUNT to greater than or equal to 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + + + + return 0; +} + +//Main entry point for the application + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hProcess[MAXIMUM_WAIT_OBJECTS]; //Array to hold Process handles + DWORD processReturnCode = 0; + int testReturnCode = PASS; + STARTUPINFO si[MAXIMUM_WAIT_OBJECTS]; + PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS]; + FILE *hFile; //handle to application results file + char fileName[MAX_PATH]; //file name of the application results file + struct applicationStatistics appStats; + DWORD dwStart=0; //to store the tick count + char lpCommandLine[MAX_PATH] = ""; + int returnCode = 0; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + + + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } + + //Initialize Application Statistics Strucuture + appStats.operationTime=0; + appStats.relationId = RELATION_ID; + appStats.processCount = USE_PROCESS_COUNT; + appStats.threadCount = THREAD_COUNT; + appStats.repeatCount = REPEAT_COUNT; + appStats.buildNumber = getBuildNumber(); + + +_snprintf(fileName, MAX_PATH, "main_criticalsection_%d_.txt", RELATION_ID); + +hFile = fopen(fileName, "w+"); + +if(hFile == NULL) + { + Fail("Error in opening file to write application results for Critical Section Test, and error code is %d\n", GetLastError()); + } + +//Start Process Time Capture +dwStart = GetTickCount(); + +for( i = 0; i < USE_PROCESS_COUNT; i++ ) + { + + ZeroMemory( lpCommandLine, MAX_PATH ); + if ( _snprintf( lpCommandLine, MAX_PATH-1, "criticalsection %d %d %d %d", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID) < 0 ) + { + Trace ("Error: Insufficient commandline string length for for iteration [%d]\n", i); + } + + /* Zero the data structure space */ + ZeroMemory ( &pi[i], sizeof(pi[i]) ); + ZeroMemory ( &si[i], sizeof(si[i]) ); + + /* Set the process flags and standard io handles */ + si[i].cb = sizeof(si[i]); + + //Printing the Command Line + //Trace("Command Line \t %s \n", lpCommandLine); + + //Create Process + if(!CreateProcess( NULL, /* lpApplicationName*/ + lpCommandLine, /* lpCommandLine */ + NULL, /* lpProcessAttributes */ + NULL, /* lpThreadAttributes */ + TRUE, /* bInheritHandles */ + 0, /* dwCreationFlags, */ + NULL, /* lpEnvironment */ + NULL, /* pCurrentDirectory */ + &si[i], /* lpStartupInfo */ + &pi[i] /* lpProcessInformation */ + )) + { + Fail("Process Not created for [%d] and failed with error code %d\n", i, GetLastError()); + } + else + { + hProcess[i] = pi[i].hProcess; + //Trace("Process created for [%d]\n", i); + } + + } + + returnCode = WaitForMultipleObjects( USE_PROCESS_COUNT, hProcess, TRUE, INFINITE); + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError()); + testReturnCode = FAIL; + } + + for( i = 0; i < USE_PROCESS_COUNT; i++ ) + { + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) ) + { + Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n", + i, GetLastError() ); + + testReturnCode = FAIL; + } + + if(processReturnCode == FAIL) + { + Trace( "Process [%d] failed and returned FAIL\n", i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hThread)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hProcess) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i); + testReturnCode = FAIL; + } + } + +//Get the end time of the process +appStats.operationTime = GetTickCount() - dwStart; + +if( testReturnCode == PASS) + { + Trace("Test Passed\n"); + + } + else + { + Fail("Test Failed\n"); + + } + +//Write Process Result Contents to File +if(hFile!= NULL) + { + fprintf(hFile, "%lu,%d,%d,%d,%d,%s\n", appStats.operationTime, appStats.relationId,appStats.processCount, appStats.threadCount, appStats.repeatCount, appStats.buildNumber); + } + +if (0!=fclose(hFile)) +{ + Trace("Error:%d: fclose failed for file %s\n", GetLastError(), fileName); +} + + PAL_Terminate(); + +if( testReturnCode == PASS) +{ + return PASS; +} +else +{ + return FAIL; +} + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/readme.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/readme.txt new file mode 100644 index 0000000..af6ef5d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/criticalsection/readme.txt @@ -0,0 +1,11 @@ +To compile: + +1) create a dat file (say criticalsection.dat) with contents: +PAL,Composite,palsuite\composite\syncronization\criticalsection,criticalsection=mainWrapper.c,criticalsection.c,,, + +2) perl rrunmod.pl -r criticalsection.dat + + +To execute: +mainwrapper [PROCESS_COUNT] [WORKER_THREAD_MULTIPLIER_COUNT] [REPEAT_COUNT] + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/CMakeLists.txt new file mode 100644 index 0000000..6ba5852 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/CMakeLists.txt @@ -0,0 +1,15 @@ +set(SOURCES + mtx_critsect.cpp + pal_composite_native_cs.cpp + resultbuffer.cpp +) + +add_executable(paltest_synchronization_nativecriticalsection + ${SOURCES} +) + +add_dependencies(paltest_synchronization_nativecriticalsection coreclrpal) + +target_link_libraries(paltest_synchronization_nativecriticalsection + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.cpp new file mode 100644 index 0000000..790c89f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.cpp @@ -0,0 +1,111 @@ +// 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. + +//#include +#include +#include "mtx_critsect.h" + +CsWaiterReturnState MTXWaitOnCS(LPCRITICAL_SECTION lpCriticalSection); +void MTXDoActualWait(LPCRITICAL_SECTION lpCriticalSection); +void MTXWakeUpWaiter(LPCRITICAL_SECTION lpCriticalSection); + +/*extern "C" { + LONG InterlockedCompareExchange( + LONG volatile *Destination, + LONG Exchange, + LONG Comperand); +} +*/ +int MTXInitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + int retcode = 0; + + lpCriticalSection->DebugInfo = NULL; + lpCriticalSection->LockCount = 0; + lpCriticalSection->RecursionCount = 0; + lpCriticalSection->SpinCount = 0; + lpCriticalSection->OwningThread = NULL; + + lpCriticalSection->LockSemaphore = (HANDLE)&lpCriticalSection->NativeData; + + if (0!= pthread_mutex_init(&lpCriticalSection->NativeData.Mutex, NULL)) + { + printf("Error Initializing Critical Section\n"); + retcode = -1; + } + + + lpCriticalSection->InitCount = CS_INITIALIZED; + return retcode; +} + +int MTXDeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + int retcode = 0; + + if (lpCriticalSection->InitCount == CS_INITIALIZED) + { + + if (0!=pthread_mutex_destroy(&lpCriticalSection->NativeData.Mutex)) + { + printf("Error Deleting Critical Section\n"); + retcode = -1; + } + } + + lpCriticalSection->InitCount = CS_NOT_INIZIALIZED; + return retcode; +} + +int MTXEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + + DWORD thread_id; + int retcode = 0; + + thread_id = (DWORD)THREADSilentGetCurrentThreadId(); + + /* check if the current thread already owns the criticalSection */ + if (lpCriticalSection->OwningThread == (HANDLE)thread_id) + { + lpCriticalSection->RecursionCount++; + //Check if this is a failure condition + return 0; + } + + if (0!= pthread_mutex_lock(&lpCriticalSection->NativeData.Mutex)) + { + //Error Condition + printf("Error Entering Critical Section\n"); + retcode = -1; + } + else + { + lpCriticalSection->OwningThread = (HANDLE)thread_id; + lpCriticalSection->RecursionCount = 1; + } + + return retcode; +} + +int MTXLeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + int retcode = 0; + + if (--lpCriticalSection->RecursionCount > 0) + //*****check this ***** + return 0; + + lpCriticalSection->OwningThread = 0; + + if (0!= pthread_mutex_unlock(&lpCriticalSection->NativeData.Mutex)) + { + //Error Condition + printf("Error Leaving Critical Section\n"); + retcode = -1; + } + + return retcode; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.h new file mode 100644 index 0000000..bc44ad8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.h @@ -0,0 +1,51 @@ +// 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. + +#include + +typedef void VOID; +typedef unsigned long DWORD; +typedef long LONG; +typedef unsigned long ULONG; +typedef void* HANDLE; +typedef unsigned long ULONG_PTR; + +#define FALSE 0 +#define TRUE 1 + +#define CSBIT_CS_IS_LOCKED 1 +#define CSBIT_NEW_WAITER 2 + +typedef enum CsInitState { CS_NOT_INIZIALIZED, CS_INITIALIZED, CS_FULLY_INITIALIZED } CsInitState; +typedef enum _CsWaiterReturnState { CS_WAITER_WOKEN_UP, CS_WAITER_DIDNT_WAIT } CsWaiterReturnState; + +typedef struct _CRITICAL_SECTION_DEBUG_INFO { + LONG volatile ContentionCount; + LONG volatile InternalContentionCount; + ULONG volatile AcquireCount; + ULONG volatile EnterCount; +} CRITICAL_SECTION_DEBUG_INFO, *PCRITICAL_SECTION_DEBUG_INFO; + +typedef struct _CRITICAL_SECTION_NATIVE_DATA { + pthread_mutex_t Mutex; +} CRITICAL_SECTION_NATIVE_DATA, *PCRITICAL_SECTION_NATIVE_DATA; + +typedef struct _CRITICAL_SECTION { + + CsInitState InitCount; + PCRITICAL_SECTION_DEBUG_INFO DebugInfo; + LONG LockCount; + LONG RecursionCount; + HANDLE OwningThread; + HANDLE LockSemaphore; + ULONG_PTR SpinCount; + CRITICAL_SECTION_NATIVE_DATA NativeData; + +} CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION; + +int MTXInitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); +int MTXDeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection); +int MTXEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); +int MTXLeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection); + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.cpp new file mode 100644 index 0000000..0ccd5c9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.cpp @@ -0,0 +1,467 @@ +// 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. + +#include +#include +#include +#include +#include +//#include +#include "mtx_critsect.cpp" +//#include "mtx_critsect.h" +#include "resultbuffer.h" + + + +#define LONGLONG long long +#define ULONGLONG unsigned LONGLONG +/*Defining Global Variables*/ + +int THREAD_COUNT=0; +int REPEAT_COUNT=0; +int GLOBAL_COUNTER=0; +int USE_PROCESS_COUNT = 0; +int RELATION_ID =0; +int g_counter = 0; +int MAX_PATH = 256; +LONGLONG callibrationValue = 0; + +pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t g_cv = PTHREAD_COND_INITIALIZER; +pthread_cond_t g_cv2 = PTHREAD_COND_INITIALIZER; +CRITICAL_SECTION g_cs; + +/* Capture statistics for each worker thread */ +struct statistics{ + unsigned int processId; + unsigned int operationsFailed; + unsigned int operationsPassed; + unsigned int operationsTotal; + DWORD operationTime; + unsigned int relationId; +}; + + +struct applicationStatistics{ + DWORD operationTime; + unsigned int relationId; + unsigned int processCount; + unsigned int threadCount; + unsigned int repeatCount; + char* buildNumber; + +}; + +ResultBuffer *resultBuffer; + + +void* waitforworkerthreads(void*); +void starttests(int); +int setuptest(void); +int cleanuptest(void); +int GetParameters( int , char **); +void incrementCounter(void); +ULONGLONG GetTicks(void); +ULONGLONG getPerfCallibrationValue(void); + + + +extern int main(int argc, char **argv) + { + //Variable Declaration + pthread_t pthreads[640]; + int threadID[640]; + int i=0; + int j=0; + int rtn=0; + ULONGLONG startTicks = 0; + + /* Variables to capture the file name and the file pointer*/ + char fileName[MAX_PATH]; + FILE *hFile; + struct statistics* buffer; + int statisticsSize = 0; + + /*Variable to Captutre Information at the Application Level*/ + struct applicationStatistics appStats; + char mainFileName[MAX_PATH]; + FILE *hMainFile; + + //Get perfCallibrationValue + + callibrationValue = getPerfCallibrationValue(); + printf("Callibration Value for this Platform %llu \n", callibrationValue); + + + //Get Parameters + if(GetParameters(argc, argv)) + { + printf("Error in obtaining the parameters\n"); + exit(-1); + } + + //Assign Values to Application Statistics Members + appStats.relationId=RELATION_ID; + appStats.operationTime=0; + appStats.buildNumber = "999.99"; + appStats.processCount = USE_PROCESS_COUNT; + appStats.threadCount = THREAD_COUNT; + appStats.repeatCount = REPEAT_COUNT; + + printf("RELATION ID : %d\n", appStats.relationId); + printf("Process Count : %d\n", appStats.processCount); + printf("Thread Count : %d\n", appStats.threadCount); + printf("Repeat Count : %d\n", appStats.repeatCount); + + + //Open file for Application Statistics Collection + snprintf(mainFileName, MAX_PATH, "main_nativecriticalsection_%d_.txt",appStats.relationId); + hMainFile = fopen(mainFileName, "w+"); + + if(hMainFile == NULL) + { + printf("Error in opening main file for write\n"); + } + + + for (i=0;igetResultBuffer(i); + fprintf(hFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); + //printf("Iteration %d over\n", i); + } + } + fclose(hFile); + + + + //Call Test Case Cleanup Routine + if (0!=cleanuptest()) + { + //Error Condition + printf("Error Cleaning up Test Case"); + exit(-1); + } + + + if(hMainFile!= NULL) + { + printf("Writing to Main File \n"); + fprintf(hMainFile, "%lu,%d,%d,%d,%d,%s\n", appStats.operationTime, appStats.relationId, appStats.processCount, appStats.threadCount, appStats.repeatCount, appStats.buildNumber); + + } + fclose(hMainFile); + return 0; + } + +void * waitforworkerthreads(void * threadId) +{ + + int *threadParam = (int*) threadId; + +// printf("Thread ID : %d \n", *threadParam); + + //Accquire Lock + if (0!=pthread_mutex_lock(&g_mutex)) + { + //Error Condition + printf("Error Accquiring Mutex Lock in Wait for Worker Thread\n"); + exit(-1); + } + + //Increment Global Counter + GLOBAL_COUNTER++; + + + //If global counter is equal to thread count then signal main thread + if (GLOBAL_COUNTER == THREAD_COUNT) + { + if (0!=pthread_cond_signal(&g_cv2)) + { + //Error Condition + printf("Error in setting conditional variable\n"); + exit(-1); + } + } + + //Wait for main thread to signal + if (0!=pthread_cond_wait(&g_cv,&g_mutex)) + { + //Error Condition + printf("Error waiting on conditional variable in Worker Thread\n"); + exit(-1); + } + + //Release the mutex lock + if (0!=pthread_mutex_unlock(&g_mutex)) + { + //Error Condition + printf("Error Releasing Mutex Lock in Worker Thread\n"); + exit(-1); + } + + //Start the test + starttests(*threadParam); + +} + +void starttests(int threadID) +{ + /*All threads beign executing tests cases*/ + int i = 0; + int Id = threadID; + struct statistics stats; + ULONGLONG startTime = 0; + ULONGLONG endTime = 0; + + + stats.relationId = RELATION_ID; + stats.processId = USE_PROCESS_COUNT; + stats.operationsFailed = 0; + stats.operationsPassed = 0; + stats.operationsTotal = 0; + stats.operationTime = 0; + + //Enter and Leave Critical Section in a loop REPEAT_COUNT Times + + startTime = GetTicks(); + + for (i=0;iLogResult(Id, (char *)&stats)) + { + printf("Error while writing to shared memory, Thread Id is[??] and Process id is [%d]\n", USE_PROCESS_COUNT); + } + +} + +int setuptest(void) +{ + + //Initalize Critical Section + if (0!=MTXInitializeCriticalSection( &g_cs)) + { + return -1; + } + return 0; +} + +int cleanuptest(void) +{ + + //Delete Critical Section + if (0!=MTXDeleteCriticalSection(&g_cs)) + { + return -1; + } + return 0; +} + +int GetParameters( int argc, char **argv) +{ + + if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Native Critical Section Test\n"); + printf("Usage:\n"); + printf("\t[PROCESS_ID ( greater than 1] \n"); + printf("\t[THREAD_COUNT ( greater than 1] \n"); + printf("\t[REPEAT_COUNT ( greater than 1]\n"); + printf("\t[RELATION_ID [greater than or Equal to 1]\n"); + return -1; + } + + + USE_PROCESS_COUNT = atoi(argv[1]); + if( USE_PROCESS_COUNT < 0) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n"); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( THREAD_COUNT < 1) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n"); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nInvalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + + return 0; +} + +void incrementCounter(void) +{ + g_counter ++; +} + + +//Implementation borrowed from pertrace.c +ULONGLONG GetTicks(void) +{ +#ifdef i386 + unsigned long a, d; + asm volatile("rdtsc":"=a" (a), "=d" (d)); + return ((ULONGLONG)((unsigned int)(d)) << 32) | (unsigned int)(a); +#else + // #error Don''t know how to get ticks on this platform + return (ULONGLONG)gethrtime(); +#endif // i386 +} + + +/**/ +ULONGLONG getPerfCallibrationValue(void) +{ + ULONGLONG startTicks; + ULONGLONG endTicks; + + startTicks = GetTicks(); + sleep(1); + endTicks = GetTicks(); + + return ((endTicks-startTicks)/1000); //Return number of Ticks in One Milliseconds + +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/readme.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/readme.txt new file mode 100644 index 0000000..8d83bf7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/readme.txt @@ -0,0 +1,19 @@ +To compile: + +For FReeBSD Platform use the following to compile: +gcc -pthread -lm -lgcc -lstdc++ -xc++ -Di386 pal_composite_native_cs.c + +For Solaris Platform use the following to compile: +gcc -lpthread -lm -lgcc -lstdc++ -xc++ -D__sparc__ pal_composite_native_cs.c + +For HPUX Platform use the following to compile: +gcc -lpthread -mlp64 -lm -lgcc -lstdc++ -xc++ -D_HPUX_ -D__ia64__ pal_composite_native_cs.c + +To execute: +./a.out [PROCESS_COUNT] [THREAD_COUNT] [REPEAT_COUNT] + + + ./a.out 1 32 1000000 4102406 + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.cpp new file mode 100644 index 0000000..c9ed943 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.cpp @@ -0,0 +1,69 @@ +// 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. + +//#include "stdafx.h" +#include "resultbuffer.h" +// +//#using +// +//using namespace System; + + +ResultBuffer:: ResultBuffer(int ThreadCount, int ThreadLogSize) + { + // Declare an internal status variable + int Status=0; + + // Update the maximum thread count + MaxThreadCount = ThreadCount; + + // Allocate the memory buffer based on the passed in thread and process counts + // and the specified size of the thread specific buffer + buffer = NULL; + buffer = (char*)malloc(ThreadCount*ThreadLogSize); + // Check to see if the buffer memory was allocated + if (buffer == NULL) + Status = -1; + // Initialize the buffer to 0 to prevent bogus data + memset(buffer,0,ThreadCount*ThreadLogSize); + + // The ThreadOffset is equal to the total number of bytes that will be stored per thread + ThreadOffset = ThreadLogSize; + + } + + + int ResultBuffer::LogResult(int Thread, char* Data) + { + // Declare an internal status flad + int status = 0; + + // Declare an object to store the offset address into the buffer + int Offset; + + // Check to make sure the Thread index is not out of range + if(Thread > MaxThreadCount) + { + printf("Thread index is out of range, Value of Thread[%d], Value of MaxThreadCount[%d]\n", Thread, MaxThreadCount); + status = -1; + return(status); + } + + // Caculate the offset into the shared buffer based on the process and thread indices + Offset = (Thread)*ThreadOffset; + + // Write the passed in data to the reserved buffer + memcpy(buffer+Offset,Data,ThreadOffset); + + return(status); + } + + + char* ResultBuffer::getResultBuffer(int threadId) + { + + return (buffer + threadId*ThreadOffset); + + } + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.h new file mode 100644 index 0000000..8920958 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.h @@ -0,0 +1,43 @@ +// 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. + +#include +#include +//#include +#ifndef _RESULT_BUFFER_H_ +#define _RESULT_BUFFER_H_ + +//#include + +struct ResultData +{ + int value; + int size; +// ResultData* NextResult; +}; + + class ResultBuffer +{ + // Declare a pointer to a memory buffer to store the logged results + char* buffer; + // Declare an object to store the maximum Thread count + int MaxThreadCount; + // Declare and internal data object to store the calculated offset between adjacent threads data sets + int ThreadOffset; + + // Declare a linked list object to store the parameter values +public: + + // Declare a constructor for the single process case + ResultBuffer(int ThreadCount, int ThreadLogSize); + // Declare a method to log data for the single process instance + int LogResult(int Thread, char* Data); + + char* getResultBuffer(int threadId); +}; + +#include "resultbuffer.cpp" +#endif // _RESULT_BUFFER_H_ + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/CMakeLists.txt new file mode 100644 index 0000000..90f52dd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/CMakeLists.txt @@ -0,0 +1,16 @@ +set(SOURCES + interlocked.cpp + mtx_critsect.cpp + pal_composite_native_cs.cpp + resultbuffer.cpp +) + +add_executable(paltest_synchronization_nativecs_interlocked + ${SOURCES} +) + +add_dependencies(paltest_synchronization_nativecs_interlocked coreclrpal) + +target_link_libraries(paltest_synchronization_nativecs_interlocked + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/hpitinterlock.s b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/hpitinterlock.s new file mode 100644 index 0000000..062f4eb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/hpitinterlock.s @@ -0,0 +1,168 @@ +// 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: + + interlock.s + +Abstract: + + Implementation of Interlocked functions (32 and 64 bits) for the HPUX/Itanium + platform. These functions are processor dependent. + See the i386 implementations for more information. + +--*/ + .file "interlock.s" + .section .text, "ax", "progbits" + .align 16 + .global InterlockedExchangeAdd# + .proc InterlockedExchangeAdd# +InterlockedExchangeAdd: + .body + ld4.nt1 r8 = [r32] + ;; +Iea10: + mov ar.ccv = r8 + add r15 = r33, r8 + mov r14 = r8 + ;; + cmpxchg4.acq r8 = [r32], r15, ar.ccv + ;; + cmp.ne p6,p7 = r8, r14 // check if the target changes? +(p6)br.cond.spnt.few Iea10 // if yes, go back to do it again +(p7)br.ret.sptk.clr b0 + ;; + .endp InterlockedExchangeAdd# + + .align 16 + .global InterlockedIncrement# + .proc InterlockedIncrement# +InterlockedIncrement: + .body + fetchadd4.acq r8 = [r32], 1 + ;; + adds r8 = 1, r8 + br.ret.sptk b0 + ;; + .endp InterlockedIncrement# + + .align 16 + .global InterlockedIncrement64# + .proc InterlockedIncrement64# +InterlockedIncrement64: + .body + fetchadd8.acq r8 = [r32], 1 + ;; + adds r8 = 1, r8 + br.ret.sptk b0 + ;; + .endp InterlockedIncrement64# + + .align 16 + .global InterlockedDecrement# + .proc InterlockedDecrement# +InterlockedDecrement: + .body + fetchadd4.acq r8 = [r32], -1 + ;; + adds r8 = -1, r8 + br.ret.sptk b0 + ;; + .endp InterlockedDecrement# + + .align 16 + .global InterlockedDecrement64# + .proc InterlockedDecrement64# +InterlockedDecrement64: + .body + fetchadd8.acq r8 = [r32], -1 + ;; + adds r8 = -1, r8 + br.ret.sptk b0 + ;; + .endp InterlockedDecrement64# + + .align 16 + .global InterlockedExchange# + .proc InterlockedExchange# +InterlockedExchange: + .body + mf + zxt4 r33 = r33 // sanitize the upper 32 bits + ;; + xchg4 r8 = [r32], r33 + br.ret.sptk b0 + ;; + .endp InterlockedExchange# + + .align 16 + .global InterlockedExchange64# + .proc InterlockedExchange64# +InterlockedExchange64: + .body + mf + xchg8 r8 = [r32], r33 + br.ret.sptk b0 + ;; + .endp InterlockedExchange64# + + .align 16 + .global InterlockedCompareExchange# + .proc InterlockedCompareExchange# +InterlockedCompareExchange: + .body + mf + zxt4 r33 = r33 // sanitize the upper 32 bits + zxt4 r34 = r34 // sanitize the upper 32 bits + ;; + mov ar.ccv = r34 + ;; + cmpxchg4.acq r8 = [r32], r33, ar.ccv + br.ret.sptk.clr b0 + ;; + .endp InterlockedCompareExchange# + + .align 16 + .global InterlockedCompareExchange64# + .proc InterlockedCompareExchange64# +InterlockedCompareExchange64: + .body + mf + mov ar.ccv = r34 + ;; + cmpxchg8.acq r8 = [r32], r33, ar.ccv + br.ret.sptk.clr b0 + ;; + .endp InterlockedCompareExchange64# + +/*++ + DBG_DebugBreak is extracted from DbgBreakPoint function + in debugstb.s from win64. +--*/ + BREAKPOINT_STOP = 0x80016 + .align 16 + .global DBG_DebugBreak# + .proc DBG_DebugBreak# +DBG_DebugBreak: + .body + flushrs + ;; + break.i BREAKPOINT_STOP + br.ret.sptk.clr b0 + ;; + .endp DBG_DebugBreak# + + .align 16 + .global MemoryBarrier# + .proc MemoryBarrier# +MemoryBarrier: + .body + mf + br.ret.sptk.clr b0 + ;; + .endp MemoryBarrier# diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/interlocked.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/interlocked.cpp new file mode 100644 index 0000000..b6c1dd7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/interlocked.cpp @@ -0,0 +1,27 @@ +// 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. + + +typedef long LONG; + +extern "C" { +LONG InterlockedCompareExchange( + LONG volatile *Destination, + LONG Exchange, + LONG Comperand) +{ +#ifdef i386 + LONG result; + + __asm__ __volatile__( + "lock; cmpxchgl %2,(%1)" + : "=a" (result) + : "r" (Destination), "r" (Exchange), "0" (Comperand) + : "memory" + ); + + return result; +#endif +} +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/makefile b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/makefile new file mode 100644 index 0000000..98daf0d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/makefile @@ -0,0 +1,70 @@ +# +# Use gmake to build this project +# + + +OSNAME=$(shell uname -s) +OSVER=$(shell uname -r | cut -c1-3) +BASEOBJDIR=./obj +TGTDIR=$(BASEOBJDIR)/$(shell uname -m) +COMP=gcc +DEBUGOPT=-D_DEBUG -g +# DEBUGOPT=-DNDEBUG + + +ifeq ($(OSNAME),SunOS) +COPT=-DSUNOS -O2 -finline-functions $(DEBUGOPT) -xc++ +LOPT=-lpthread -lrt -O2 -finline-functions $(DEBUGOPT) +INTERLOCK_OBJ=sparcinterloc.o +else + ifeq ($(OSNAME),FreeBSD) + ifeq ($(OSVER),5.2) + COMP=g++ + COPT=-DFREEBSD -Di386 -O2 -finline-functions $(DEBUGOPT) -xc++ + LOPT=-lkse -O2 -finline-functions $(DEBUGOPT) + else + COPT=-DFREEBSD -Di386 -O2 -finline-functions $(DEBUGOPT) + LOPT=-pthread -O2 -finline-functions $(DEBUGOPT) + endif + INTERLOCK_OBJ=interlocked.o + else + ifeq ($(OSNAME),HP-UX) + COMP=g++ + INTERLOCK_OBJ=hpitinterlock.o + COPT=-DHPUX -O2 -mlp64 -finline -fPIC -DPIC -DHOST_64BIT -DHOST_64BIT -DLP64COMPATIBLE \ + -D_POSIX_C_SOURCE=199506L -D_HPUX_ -D_XOPEN_SOURCE_EXTENDED -DHOST_64BIT \ + -DBIGENDIAN -DHOST_64BIT $(DEBUGOPT) -xc++ + LOPT=-O2 -mlp64 -DHOST_64BIT -DHOST_64BIT -lgcc -lpthread /usr/lib/hpux64/libunwind.so + endif + endif +endif + + +TARGET0=$(TGTDIR)/native_cs_interlocked + +all: dirs $(TARGET0) $(TARGET1) $(TARGET2) $(TARGET3) $(TARGET4) + +dirs: + @echo Target dir: $(TGTDIR) + @if [ \! -d $(BASEOBJDIR) ]; then mkdir $(BASEOBJDIR); fi + @if [ \! -d $(TGTDIR) ]; then mkdir $(TGTDIR); fi + +$(TGTDIR)/native_cs_interlocked: $(TGTDIR)/$(INTERLOCK_OBJ) $(TGTDIR)/native_cs_interlocked.o + $(COMP) $(LOPT) -o $(TARGET0) $(TGTDIR)/native_cs_interlocked.o $(TGTDIR)/$(INTERLOCK_OBJ) + +$(TGTDIR)/native_cs_interlocked.o: pal_composite_native_cs.c + $(COMP) $(COPT) -DFULL_CSIMPL -o $(TGTDIR)/native_cs_interlocked.o -c pal_composite_native_cs.c + +$(TGTDIR)/interlocked.o: interlocked.cpp + $(COMP) $(COPT) -c -o $(TGTDIR)/interlocked.o interlocked.cpp + +$(TGTDIR)/sparcinterloc.o: sparcinterloc.s + $(COMP) -x assembler-with-cpp -c -Wa,-Av9 -o $(TGTDIR)/sparcinterloc.o sparcinterloc.s + +$(TGTDIR)/hpitinterlock.o: hpitinterlock.s + $(COMP) $(COPT) -x assembler-with-cpp -c -fno-strict-aliasing -o $(TGTDIR)/hpitinterlock.o hpitinterlock.s + +clean: + @echo Cleaning + @rm -f $(TGTDIR)/*.o $(TARGET0) $(TARGET1) $(TARGET2) $(TARGET3) $(TARGET4) + @if [ -d $(TGTDIR) ]; then rmdir $(TGTDIR); fi diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.cpp new file mode 100644 index 0000000..69c10e9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.cpp @@ -0,0 +1,112 @@ +// 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. + +#include + +#include +#include "mtx_critsect.h" + +CsWaiterReturnState MTXWaitOnCS(LPCRITICAL_SECTION lpCriticalSection); +void MTXDoActualWait(LPCRITICAL_SECTION lpCriticalSection); +void MTXWakeUpWaiter(LPCRITICAL_SECTION lpCriticalSection); + +/*extern "C" { + LONG InterlockedCompareExchange( + LONG volatile *Destination, + LONG Exchange, + LONG Comperand); +} +*/ +int MTXInitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + int retcode = 0; + + lpCriticalSection->DebugInfo = NULL; + lpCriticalSection->LockCount = 0; + lpCriticalSection->RecursionCount = 0; + lpCriticalSection->SpinCount = 0; + lpCriticalSection->OwningThread = NULL; + + lpCriticalSection->LockSemaphore = (HANDLE)&lpCriticalSection->NativeData; + + if (0!= pthread_mutex_init(&lpCriticalSection->NativeData.Mutex, NULL)) + { + printf("Error Initializing Critical Section\n"); + retcode = -1; + } + + + lpCriticalSection->InitCount = CS_INITIALIZED; + return retcode; +} + +int MTXDeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + int retcode = 0; + + if (lpCriticalSection->InitCount == CS_INITIALIZED) + { + + if (0!=pthread_mutex_destroy(&lpCriticalSection->NativeData.Mutex)) + { + printf("Error Deleting Critical Section\n"); + retcode = -1; + } + } + + lpCriticalSection->InitCount = CS_NOT_INIZIALIZED; + return retcode; +} + +int MTXEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + + DWORD thread_id; + int retcode = 0; + + thread_id = (DWORD)THREADSilentGetCurrentThreadId(); + + /* check if the current thread already owns the criticalSection */ + if (lpCriticalSection->OwningThread == (HANDLE)thread_id) + { + lpCriticalSection->RecursionCount++; + //Check if this is a failure condition + return 0; + } + + if (0!= pthread_mutex_lock(&lpCriticalSection->NativeData.Mutex)) + { + //Error Condition + printf("Error Entering Critical Section\n"); + retcode = -1; + } + else + { + lpCriticalSection->OwningThread = (HANDLE)thread_id; + lpCriticalSection->RecursionCount = 1; + } + + return retcode; +} + +int MTXLeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + int retcode = 0; + + if (--lpCriticalSection->RecursionCount > 0) + //*****check this ***** + return 0; + + lpCriticalSection->OwningThread = 0; + + if (0!= pthread_mutex_unlock(&lpCriticalSection->NativeData.Mutex)) + { + //Error Condition + printf("Error Leaving Critical Section\n"); + retcode = -1; + } + + return retcode; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.h new file mode 100644 index 0000000..becbf6f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.h @@ -0,0 +1,67 @@ +// 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. + +#include + +typedef void VOID; +typedef void* HANDLE; +typedef unsigned long ULONG_PTR; + +#ifdef HPUX + typedef unsigned int DWORD; + typedef int LONG; + typedef unsigned int ULONG; +#else + typedef unsigned long DWORD; + typedef long LONG; + typedef unsigned long ULONG; +#endif + + + + +#define FALSE 0 +#define TRUE 1 + +#define CSBIT_CS_IS_LOCKED 1 +#define CSBIT_NEW_WAITER 2 + +typedef enum CsInitState { CS_NOT_INIZIALIZED, CS_INITIALIZED, CS_FULLY_INITIALIZED } CsInitState; +typedef enum _CsWaiterReturnState { CS_WAITER_WOKEN_UP, CS_WAITER_DIDNT_WAIT } CsWaiterReturnState; + +typedef struct _CRITICAL_SECTION_DEBUG_INFO { + LONG volatile ContentionCount; + LONG volatile InternalContentionCount; + ULONG volatile AcquireCount; + ULONG volatile EnterCount; +} CRITICAL_SECTION_DEBUG_INFO, *PCRITICAL_SECTION_DEBUG_INFO; + +typedef struct _CRITICAL_SECTION_NATIVE_DATA { + pthread_mutex_t Mutex; +} CRITICAL_SECTION_NATIVE_DATA, *PCRITICAL_SECTION_NATIVE_DATA; + +typedef struct _CRITICAL_SECTION { + + CsInitState InitCount; + PCRITICAL_SECTION_DEBUG_INFO DebugInfo; + LONG LockCount; + LONG RecursionCount; + HANDLE OwningThread; + HANDLE LockSemaphore; + ULONG_PTR SpinCount; + CRITICAL_SECTION_NATIVE_DATA NativeData; + +} CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION; + +int MTXInitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); +int MTXDeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection); +int MTXEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); +int MTXLeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection); + +extern "C" { + LONG InterlockedCompareExchange( + LONG volatile *Destination, + LONG Exchange, + LONG Comperand); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/notes.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/notes.txt new file mode 100644 index 0000000..4882c3b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/notes.txt @@ -0,0 +1,15 @@ +gcc -O2 -finline-functions -D_DEBUG -g -DFULL_CSIMPL -o ./obj/sun4u/critsecttest.o -c critsecttest.cpp +gcc -O2 -finline-functions -D_DEBUG -g -c -o ./obj/sun4u/cs.o cs.cpp +gcc -x assembler-with-cpp -c -Wa,-Av9 -o ./obj/sun4u/sparcinterloc.o sparcinterloc.s +gcc -lpthread -lrt -O2 -finline-functions -D_DEBUG -g -o ./obj/sun4u/critsecttest ./obj/sun4u/critsecttest.o ./obj/sun4u/cs.o ./obj/sun4u/sparcinterloc.o +gcc -O2 -finline-functions -D_DEBUG -g -DCXNG_CSIMPL -o ./obj/sun4u/cxngtest.o -c critsecttest.cpp +gcc -O2 -finline-functions -D_DEBUG -g -c -o ./obj/sun4u/cxng_critsect.o cxng_critsect.cpp +gcc -lpthread -lrt -O2 -finline-functions -D_DEBUG -g -o ./obj/sun4u/cxngtest ./obj/sun4u/cxngtest.o ./obj/sun4u/cxng_critsect.o ./obj/sun4u/sparcinterloc.o +gcc -O2 -finline-functions -D_DEBUG -g -DMTX_CSIMPL -o ./obj/sun4u/mtxtest.o -c critsecttest.cpp +gcc -O2 -finline-functions -D_DEBUG -g -c -o ./obj/sun4u/mtx_critsect.o mtx_critsect.cpp +gcc -lpthread -lrt -O2 -finline-functions -D_DEBUG -g -o ./obj/sun4u/mtxtest ./obj/sun4u/mtxtest.o ./obj/sun4u/mtx_critsect.o ./obj/sun4u/sparcinterloc.o +gcc -O2 -finline-functions -D_DEBUG -g -DRECMTX_CSIMPL -o ./obj/sun4u/recmtxtest.o -c critsecttest.cpp +gcc -O2 -finline-functions -D_DEBUG -g -c -o ./obj/sun4u/recmtx_critsect.o recmtx_critsect.cpp +gcc -lpthread -lrt -O2 -finline-functions -D_DEBUG -g -o ./obj/sun4u/recmtxtest ./obj/sun4u/recmtxtest.o ./obj/sun4u/recmtx_critsect.o ./obj/sun4u/sparcinterloc.o +gcc -O2 -finline-functions -D_DEBUG -g -DINLRECMTX_CSIMPL -o ./obj/sun4u/inlrecmtxtest.o -c critsecttest.cpp +gcc -lpthread -lrt -O2 -finline-functions -D_DEBUG -g -o ./obj/sun4u/inlrecmtxtest ./obj/sun4u/inlrecmtxtest.o ./obj/sun4u/sparcinterloc.o diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.cpp new file mode 100644 index 0000000..ec5c1c3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.cpp @@ -0,0 +1,471 @@ +// 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. + +#include +#include +#include +#include +#include +//#include +//#include "mtx_critsect.cpp" +#include "mtx_critsect.h" +#include "resultbuffer.h" + + + +#define LONGLONG long long +#define ULONGLONG unsigned LONGLONG +/*Defining Global Variables*/ + +int THREAD_COUNT=0; +int REPEAT_COUNT=0; +int GLOBAL_COUNTER=0; +int USE_PROCESS_COUNT = 0; +int RELATION_ID =0; +int g_counter = 0; +int MAX_PATH = 256; +LONGLONG callibrationValue = 0; + +pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t g_cv = PTHREAD_COND_INITIALIZER; +pthread_cond_t g_cv2 = PTHREAD_COND_INITIALIZER; +CRITICAL_SECTION g_cs; + +/* Capture statistics for each worker thread */ +struct statistics{ + unsigned int processId; + unsigned int operationsFailed; + unsigned int operationsPassed; + unsigned int operationsTotal; + DWORD operationTime; + unsigned int relationId; +}; + + +struct applicationStatistics{ + DWORD operationTime; + unsigned int relationId; + unsigned int processCount; + unsigned int threadCount; + unsigned int repeatCount; + char* buildNumber; + +}; + +ResultBuffer *resultBuffer; + + +void* waitforworkerthreads(void*); +void starttests(int); +int setuptest(void); +int cleanuptest(void); +int GetParameters( int , char **); +void incrementCounter(void); +ULONGLONG GetTicks(void); +ULONGLONG getPerfCallibrationValue(void); + + + +extern int main(int argc, char **argv) + { + //Variable Declaration + pthread_t pthreads[640]; + int threadID[640]; + int i=0; + int j=0; + int rtn=0; + ULONGLONG startTicks = 0; + + /* Variables to capture the file name and the file pointer*/ + char fileName[MAX_PATH]; + FILE *hFile; + struct statistics* buffer; + int statisticsSize = 0; + + /*Variable to Captutre Information at the Application Level*/ + struct applicationStatistics appStats; + char mainFileName[MAX_PATH]; + FILE *hMainFile; + + //Get perfCallibrationValue + + callibrationValue = getPerfCallibrationValue(); + printf("Callibration Value for this Platform %llu \n", callibrationValue); + + + //Get Parameters + if(GetParameters(argc, argv)) + { + printf("Error in obtaining the parameters\n"); + exit(-1); + } + + //Assign Values to Application Statistics Members + appStats.relationId=RELATION_ID; + appStats.operationTime=0; + appStats.buildNumber = "999.99"; + appStats.processCount = USE_PROCESS_COUNT; + appStats.threadCount = THREAD_COUNT; + appStats.repeatCount = REPEAT_COUNT; + + printf("RELATION ID : %d\n", appStats.relationId); + printf("Process Count : %d\n", appStats.processCount); + printf("Thread Count : %d\n", appStats.threadCount); + printf("Repeat Count : %d\n", appStats.repeatCount); + + + //Open file for Application Statistics Collection + snprintf(mainFileName, MAX_PATH, "main_nativecriticalsection_%d_.txt",appStats.relationId); + hMainFile = fopen(mainFileName, "w+"); + + if(hMainFile == NULL) + { + printf("Error in opening main file for write\n"); + } + + + for (i=0;igetResultBuffer(i); + fprintf(hFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); + //printf("Iteration %d over\n", i); + } + } + fclose(hFile); + + + + //Call Test Case Cleanup Routine + if (0!=cleanuptest()) + { + //Error Condition + printf("Error Cleaning up Test Case"); + exit(-1); + } + + + if(hMainFile!= NULL) + { + printf("Writing to Main File \n"); + fprintf(hMainFile, "%lu,%d,%d,%d,%d,%s\n", appStats.operationTime, appStats.relationId, appStats.processCount, appStats.threadCount, appStats.repeatCount, appStats.buildNumber); + + } + fclose(hMainFile); + return 0; + } + +void * waitforworkerthreads(void * threadId) +{ + + int *threadParam = (int*) threadId; + +// printf("Thread ID : %d \n", *threadParam); + + //Accquire Lock + if (0!=pthread_mutex_lock(&g_mutex)) + { + //Error Condition + printf("Error Accquiring Mutex Lock in Wait for Worker Thread\n"); + exit(-1); + } + + //Increment Global Counter + GLOBAL_COUNTER++; + + + //If global counter is equal to thread count then signal main thread + if (GLOBAL_COUNTER == THREAD_COUNT) + { + if (0!=pthread_cond_signal(&g_cv2)) + { + //Error Condition + printf("Error in setting conditional variable\n"); + exit(-1); + } + } + + //Wait for main thread to signal + if (0!=pthread_cond_wait(&g_cv,&g_mutex)) + { + //Error Condition + printf("Error waiting on conditional variable in Worker Thread\n"); + exit(-1); + } + + //Release the mutex lock + if (0!=pthread_mutex_unlock(&g_mutex)) + { + //Error Condition + printf("Error Releasing Mutex Lock in Worker Thread\n"); + exit(-1); + } + + //Start the test + starttests(*threadParam); + +} + +void starttests(int threadID) +{ + /*All threads beign executing tests cases*/ + int i = 0; + int Id = threadID; + struct statistics stats; + ULONGLONG startTime = 0; + ULONGLONG endTime = 0; + + LONG volatile Destination; + LONG Exchange; + LONG Comperand; + LONG result; + + stats.relationId = RELATION_ID; + stats.processId = USE_PROCESS_COUNT; + stats.operationsFailed = 0; + stats.operationsPassed = 0; + stats.operationsTotal = 0; + stats.operationTime = 0; + + //Enter and Leave Critical Section in a loop REPEAT_COUNT Times + + + startTime = GetTicks(); + + for (i=0;iLogResult(Id, (char *)&stats)) + { + printf("Error while writing to shared memory, Thread Id is[??] and Process id is [%d]\n", USE_PROCESS_COUNT); + } + +} + +int setuptest(void) +{ + + //Initalize Critical Section + /* + if (0!=MTXInitializeCriticalSection( &g_cs)) + { + return -1; + } + */ + return 0; +} + +int cleanuptest(void) +{ + + //Delete Critical Section + /* + if (0!=MTXDeleteCriticalSection(&g_cs)) + { + return -1; + } + */ + return 0; +} + +int GetParameters( int argc, char **argv) +{ + + if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Native Critical Section Test\n"); + printf("Usage:\n"); + printf("\t[PROCESS_ID ( greater than 1] \n"); + printf("\t[THREAD_COUNT ( greater than 1] \n"); + printf("\t[REPEAT_COUNT ( greater than 1]\n"); + printf("\t[RELATION_ID [greater than or Equal to 1]\n"); + return -1; + } + + + USE_PROCESS_COUNT = atoi(argv[1]); + if( USE_PROCESS_COUNT < 0) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n"); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( THREAD_COUNT < 1) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n"); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nInvalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + + return 0; +} + +void incrementCounter(void) +{ + g_counter ++; +} + + +//Implementation borrowed from pertrace.c +ULONGLONG GetTicks(void) +{ +#ifdef i386 + unsigned long a, d; + asm volatile("rdtsc":"=a" (a), "=d" (d)); + return ((ULONGLONG)((unsigned int)(d)) << 32) | (unsigned int)(a); +#else + // #error Don''t know how to get ticks on this platform + return (ULONGLONG)gethrtime(); +#endif // i386 +} + + +/**/ +ULONGLONG getPerfCallibrationValue(void) +{ + ULONGLONG startTicks; + ULONGLONG endTicks; + + startTicks = GetTicks(); + sleep(1); + endTicks = GetTicks(); + + return ((endTicks-startTicks)/1000); //Return number of Ticks in One Milliseconds + +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/readme.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/readme.txt new file mode 100644 index 0000000..a407e9f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/readme.txt @@ -0,0 +1,39 @@ +To compile: + +For FReeBSD Platform use the following to compile: +gcc -pthread -lm -lgcc -lstdc++ -xc++ -Di386 pal_composite_native_cs.c + + +-------------------------------------------------------- +For Solaris Platform use the following to compile: + gcc -lpthread -lm -lgcc -lstdc++ -xc++ -D__sparc__ -mimpure-text -shared -o critsect.so mtx_critsect.cpp interlock.s +gcc -lpthread -lm -lgcc -lstdc++ -xc++ -D__sparc__ pal_composite_native_cs.c + + +setenv LD_LIBRARY_PATH /usr/lib/lwp:/usr/local/lib:/usr/lib:/opt/sfw/lib:. + gcc -lpthread -lm -lgcc -lstdc++ -lcritsect -xc++ -D__sparc__ pal_composite_native_cs.c + gcc -lpthread -lm -lgcc -lstdc++ -xc++ -D__sparc__ -mimpure-text -shared -o critsect.so mtx_critsect.cpp + +(pts/2):{4}% ldd critsect.so + libpthread.so.1 => /usr/lib/libpthread.so.1 + libm.so.1 => /usr/lib/libm.so.1 + libstdc++.so.2.10.0 => /usr/local/lib/libstdc++.so.2.10.0 + libc.so.1 => /usr/lib/libc.so.1 + libdl.so.1 => /usr/lib/libdl.so.1 + libthread.so.1 => /usr/lib/libthread.so.1 + /usr/platform/SUNW,Serverblade1/lib/libc_psr.so.1 + + +-------------------------------------------------------- +For HPUX Platform use the following to compile: +gcc -lpthread -mlp64 -lm -lgcc -lstdc++ -xc++ -D_HPUX_ -D__ia64__ pal_composite_native_cs.c + +-------------------------------------------------------- +To execute: +./a.out [PROCESS_COUNT] [THREAD_COUNT] [REPEAT_COUNT] + + + ./a.out 1 32 1000000 4102406 + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.cpp new file mode 100644 index 0000000..c9ed943 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.cpp @@ -0,0 +1,69 @@ +// 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. + +//#include "stdafx.h" +#include "resultbuffer.h" +// +//#using +// +//using namespace System; + + +ResultBuffer:: ResultBuffer(int ThreadCount, int ThreadLogSize) + { + // Declare an internal status variable + int Status=0; + + // Update the maximum thread count + MaxThreadCount = ThreadCount; + + // Allocate the memory buffer based on the passed in thread and process counts + // and the specified size of the thread specific buffer + buffer = NULL; + buffer = (char*)malloc(ThreadCount*ThreadLogSize); + // Check to see if the buffer memory was allocated + if (buffer == NULL) + Status = -1; + // Initialize the buffer to 0 to prevent bogus data + memset(buffer,0,ThreadCount*ThreadLogSize); + + // The ThreadOffset is equal to the total number of bytes that will be stored per thread + ThreadOffset = ThreadLogSize; + + } + + + int ResultBuffer::LogResult(int Thread, char* Data) + { + // Declare an internal status flad + int status = 0; + + // Declare an object to store the offset address into the buffer + int Offset; + + // Check to make sure the Thread index is not out of range + if(Thread > MaxThreadCount) + { + printf("Thread index is out of range, Value of Thread[%d], Value of MaxThreadCount[%d]\n", Thread, MaxThreadCount); + status = -1; + return(status); + } + + // Caculate the offset into the shared buffer based on the process and thread indices + Offset = (Thread)*ThreadOffset; + + // Write the passed in data to the reserved buffer + memcpy(buffer+Offset,Data,ThreadOffset); + + return(status); + } + + + char* ResultBuffer::getResultBuffer(int threadId) + { + + return (buffer + threadId*ThreadOffset); + + } + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.h new file mode 100644 index 0000000..8920958 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.h @@ -0,0 +1,43 @@ +// 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. + +#include +#include +//#include +#ifndef _RESULT_BUFFER_H_ +#define _RESULT_BUFFER_H_ + +//#include + +struct ResultData +{ + int value; + int size; +// ResultData* NextResult; +}; + + class ResultBuffer +{ + // Declare a pointer to a memory buffer to store the logged results + char* buffer; + // Declare an object to store the maximum Thread count + int MaxThreadCount; + // Declare and internal data object to store the calculated offset between adjacent threads data sets + int ThreadOffset; + + // Declare a linked list object to store the parameter values +public: + + // Declare a constructor for the single process case + ResultBuffer(int ThreadCount, int ThreadLogSize); + // Declare a method to log data for the single process instance + int LogResult(int Thread, char* Data); + + char* getResultBuffer(int threadId); +}; + +#include "resultbuffer.cpp" +#endif // _RESULT_BUFFER_H_ + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/sparcinterloc.s b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/sparcinterloc.s new file mode 100644 index 0000000..b9708bc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/sparcinterloc.s @@ -0,0 +1,73 @@ +// 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: + + interlock.s + +Abstract: + + Implementation of Interlocked functions for the SPARC + platform. These functions are processor dependent. + See the i386 implementations for more information. + + --*/ + + // A handy macro for declaring a public function + // The first argument is the function name. + #define ASMFUNC(n,typename); \ + .align 4 ; \ + .global n ; \ + .type n,typename ; \ +n: ; + + .text + ASMFUNC(InterlockedIncrement,#function) + ld [%o0], %o1 +loopI: + mov %o1, %o2 + add %o1, 1, %o1 + cas [%o0], %o2, %o1 + cmp %o2, %o1 + bne loopI + nop + retl + add %o1, 1, %o0 + + + ASMFUNC(InterlockedDecrement,#function) + ld [%o0], %o1 +loopD: + mov %o1, %o2 + sub %o1, 1, %o1 + cas [%o0], %o2, %o1 + cmp %o2, %o1 + bne loopD + nop + retl + sub %o1, 1, %o0 + + + ASMFUNC(InterlockedExchange,#function) + swap [%o0], %o1 + retl + mov %o1, %o0 + + ASMFUNC(InterlockedCompareExchange,#function) + cas [%o0], %o2, %o1 + retl + mov %o1, %o0 + + ASMFUNC(MemoryBarrier,#function) + // ROTORTODO: SPARC + retl + nop + + ASMFUNC(YieldProcessor,#function) + retl + nop diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/CMakeLists.txt new file mode 100644 index 0000000..2b4f0ea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(threadsuspension) +add_subdirectory(threadsuspension_switchthread) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/CMakeLists.txt new file mode 100644 index 0000000..a931f97 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/CMakeLists.txt @@ -0,0 +1,14 @@ +set(SOURCES + mainWrapper.cpp + threadsuspension.cpp +) + +add_executable(paltest_threading_threadsuspension + ${SOURCES} +) + +add_dependencies(paltest_threading_threadsuspension coreclrpal) + +target_link_libraries(paltest_threading_threadsuspension + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/mainWrapper.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/mainWrapper.cpp new file mode 100644 index 0000000..05a7119 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/mainWrapper.cpp @@ -0,0 +1,274 @@ +// 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. + +/* +Source Code: mainWrapper.c + +mainWrapper.c creates Composite Test Case Processes and waits for all processes to get over + +Algorithm +o Create PROCESS_COUNT processes. + +Author: RameshG +*/ + +#include +#include "resulttime.h" + +/* Test Input Variables */ +unsigned int USE_PROCESS_COUNT = 0; //default +unsigned int WORKER_THREAD_MULTIPLIER_COUNT = 0; //default +unsigned int REPEAT_COUNT = 0; //default +unsigned int SLEEP_LENGTH = 0; //default +unsigned int RELATION_ID = 0;//default +unsigned int THREAD_COUNT = 1; //There is only one suspender and resume thread for this test case + +char *testCaseName; + + +struct applicationStatistics{ + DWORD operationTime; + unsigned int relationId; + unsigned int processCount; + unsigned int threadCount; + unsigned int repeatCount; + char* buildNumber; + +}; + + +int GetParameters( int argc, char **argv) +{ + + if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Thread Suspension Test\n"); + printf("Usage:\n"); + printf("\t[PROCESS_COUNT] Greater than or Equal to 1 \n"); + printf("\t[WORKER_THREAD_MULTIPLIER_COUNT] Greater than or Equal to 1 and Less than or Equal to %d \n", MAXIMUM_WAIT_OBJECTS); + printf("\t[REPEAT_COUNT] Greater than or Equal to 1\n"); + printf("\t[RELATION_ID [greater than or Equal to 1]\n"); + return -1; + } + + // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]); + + USE_PROCESS_COUNT = atoi(argv[1]); + if( USE_PROCESS_COUNT < 0) + { + printf("\nPROCESS_COUNT to greater than or equal to 1\n"); + return -1; + } + + WORKER_THREAD_MULTIPLIER_COUNT = atoi(argv[2]); + if( WORKER_THREAD_MULTIPLIER_COUNT < 1 || WORKER_THREAD_MULTIPLIER_COUNT > 64) + { + printf("\nWORKER_THREAD_MULTIPLIER_COUNT to be greater than or equal to 1 or less than or equal to 64\n"); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nREPEAT_COUNT to greater than or equal to 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nRELATION_ID to be greater than or equal to 1\n"); + return -1; + } + + + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hProcess[MAXIMUM_WAIT_OBJECTS]; + DWORD processReturnCode = 0; + int testReturnCode = PASS; + STARTUPINFO si[MAXIMUM_WAIT_OBJECTS]; + PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS]; + + FILE *hFile; + char fileName[MAX_PATH]; + struct applicationStatistics appStats; + + DWORD dwStart=0; + + char lpCommandLine[MAX_PATH] = ""; + + char build[] ="0000.00"; + int returnCode = 0; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + //Initialize Application Statistics Strucuture + appStats.relationId=RELATION_ID; + appStats.operationTime=0; + appStats.buildNumber = getBuildNumber(); + //appStats.buildNumber = build; + appStats.processCount = 0; + appStats.threadCount = 0; + appStats.repeatCount = 0; + + + + + +//Start Process Time Capture +dwStart = GetTickCount(); + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } + +//Assign Correct Values to the Application Stats Structure + appStats.relationId=RELATION_ID; + appStats.processCount = USE_PROCESS_COUNT; + appStats.threadCount = THREAD_COUNT ; + appStats.repeatCount = REPEAT_COUNT; + + Trace("Relation ID: %d \n", RELATION_ID); + Trace("USE_PROCESS_COUNT: %d \n", USE_PROCESS_COUNT); + Trace("WORKER_THREAD_MULTIPLIER_COUNT: %d \n", WORKER_THREAD_MULTIPLIER_COUNT); + Trace("REPEAT_COUNT: %d \n", REPEAT_COUNT); + + +_snprintf(fileName, MAX_PATH, "main_threadsuspension_%d_.txt",appStats.relationId); + + hFile = fopen(fileName, "w+"); +if(hFile == NULL) + { + Fail("Error in opening file to write application results for Thread Suspension Test with error code %d \n", GetLastError() ); + } + + + + for( i = 0; i < USE_PROCESS_COUNT; i++ ) + { + + ZeroMemory( lpCommandLine, MAX_PATH ); + if ( _snprintf( lpCommandLine, MAX_PATH-1, "threadsuspension %d %d %d %d", i, WORKER_THREAD_MULTIPLIER_COUNT, REPEAT_COUNT, RELATION_ID) < 0 ) + { + Trace ("Error: Insufficient commandline string length for for iteration [%d]\n", i); + } + + /* Zero the data structure space */ + ZeroMemory ( &pi[i], sizeof(pi[i]) ); + ZeroMemory ( &si[i], sizeof(si[i]) ); + + /* Set the process flags and standard io handles */ + si[i].cb = sizeof(si[i]); + + //Printing the Command Line + //Trace("Command Line \t %s \n", lpCommandLine); + + //Create Process + if(!CreateProcess( NULL, /* lpApplicationName*/ + lpCommandLine, /* lpCommandLine */ + NULL, /* lpProcessAttributes */ + NULL, /* lpThreadAttributes */ + TRUE, /* bInheritHandles */ + 0, /* dwCreationFlags, */ + NULL, /* lpEnvironment */ + NULL, /* pCurrentDirectory */ + &si[i], /* lpStartupInfo */ + &pi[i] /* lpProcessInformation */ + )) + { + Fail("Process Not created for [%d] and GetLastError value is %d\n", i, GetLastError()); + + } + else + { + hProcess[i] = pi[i].hProcess; + //Trace("Process created for [%d]\n", i); + } + + } + + returnCode = WaitForMultipleObjects( USE_PROCESS_COUNT, hProcess, TRUE, INFINITE); + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError()); + testReturnCode = FAIL; + } + + for( i = 0; i < USE_PROCESS_COUNT; i++ ) + { + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) ) + { + Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n", + i, GetLastError() ); + + testReturnCode = FAIL; + } + + if(processReturnCode == FAIL) + { + Trace( "Process [%d] failed and returned FAIL\n", i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hThread)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hProcess) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i); + testReturnCode = FAIL; + } + } + +//Get the end time of the process +appStats.operationTime = GetTickCount() - dwStart; + +if( testReturnCode == PASS) + { + Trace("Test Passed\n"); + } + else + { + Trace("Test Failed\n"); + } + +//Write Process Result Contents to File +if(hFile!= NULL) + { + fprintf(hFile, "%lu,%d,%d,%d,%d,%s\n", appStats.operationTime, appStats.relationId, appStats.processCount, appStats.threadCount, appStats.repeatCount, appStats.buildNumber); + } + +if (0!=fclose(hFile)) +{ + Trace("Error:%d: fclose failed for file %s\n", GetLastError(), fileName); +} + PAL_Terminate(); + + +if( testReturnCode == PASS) + { + return PASS; + } + else + { + return FAIL; + + } + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/readme.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/readme.txt new file mode 100644 index 0000000..d722f1d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/readme.txt @@ -0,0 +1,11 @@ +To compile: + +1) create a dat file (say threadsuspension.dat) with contents: +PAL,Composite,palsuite\composite\threading\threadsuspension,wfmo=mainWrapper.c threadsuspension.c,,, + +2) perl rrunmod.pl -r threadsuspension.dat + + +To execute: +mainWrapper [PROCESS_COUNT] [THREAD_COUNT] [REPEAT_COUNT] + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/samplefile.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/samplefile.dat new file mode 100644 index 0000000..d6505f2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/samplefile.dat @@ -0,0 +1,5124 @@ +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense blackasdf dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/threadsuspension.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/threadsuspension.cpp new file mode 100644 index 0000000..86ee4e2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension/threadsuspension.cpp @@ -0,0 +1,907 @@ +// 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. + +/*============================================================ +** +** Source: \composite\threading\threadsuspension\threadsuspension.c +** +** Purpose: To verify Thread Suspension Reegneering effort for this milestone + + PsedoCode: + + Preparation: + Create PROCESS_COUNT processes. + Test: + Create Worker Thread + Start Reading and writing to a File + + Create Worker Thread + In an infinite loop do the following + Enter Critical Section + Increment Counter + Leave Critical Section + + Create Worker Thread + Allocate Memory and Free Memory + + Create Worker Thread + In a tight loop add numbers + + In a loop repeated REPEAT_COUNT times + + Create Thread + + Suspend all worker threads + Resume all worker threads + + At the end of the loop call PAL_Shutdown + + Parameters: + PROCESS_COUNT: Number of processes + WORKER_THREAD_MULTIPLIER_COUNT: Number of instances of worker threads in each process + REPEAT_COUNT: The number of times to execute the loop. + + Statistics Captured: + Total elapsed time + MTBF + + + Scenario: +** + One thread suspends all remaining threads which are in the middle of doing some work and resume all threads + Thread 1: Reading and Writing File + Thread 2: Enter and Leave Critical Section + Thread 3: Allocating chunks of memory + Thread 4: Perform Unsafe Operation (printf, malloc) + Thread 5: Suspends Thread 1 to Thread 4 and resumes them + +** +** +** +** Dependencies: +** +** + +** +**=========================================================*/ + +#include +#include "resultbuffer.h" + +#define BUFSIZE 4096 +#define NUMBER_OF_WORKER_THREAD_TYPES 4 +#define THREAD_MAX 64 + +#define TEST_FAIL 1 +#define TEST_PASS 0 + + +DWORD GLOBAL_COUNTER ; +DWORD UNIQUE_FILE_NUMBER=0; +HANDLE g_hEvent; + +bool failFlag = false; //To Track failure at the Operation Level + +// 2 dimensional array to hold thread handles for each worker thread +HANDLE hThread[NUMBER_OF_WORKER_THREAD_TYPES][THREAD_MAX]; + +/*unsigned int g_readfileoperation; +unsigned int g_enterleavecsoperation; +unsigned int g_allocatefreeoperation; +unsigned int g_doworintightloop; +*/ + +int TYPES_OF_WORKER_THREAD = NUMBER_OF_WORKER_THREAD_TYPES; + +int testStatus=TEST_PASS; //Indicates test failure + + +struct statistics{ + unsigned int processId; + unsigned int operationsFailed; + unsigned int operationsPassed; + unsigned int operationsTotal; + DWORD operationTime; + unsigned int relationId; +}; + +struct processStatistics{ + unsigned int processId; + DWORD operationTime; + unsigned int relationId; +}; + +/* Results Buffer */ +ResultBuffer *resultBuffer; + + +/* Test Input Variables */ +unsigned int USE_PROCESS_COUNT = 0; //Identifies the Process number. There could potentially +unsigned int WORKER_THREAD_MULTIPLIER_COUNT = 0; //In this test case this represents the number of worker thread instances +unsigned int REPEAT_COUNT = 0; //Number of Suspend Resume operation of worker threads +unsigned int RELATION_ID = 0; + + + +CRITICAL_SECTION CriticalSectionM; /* Critical Section Object (used as mutex) */ +CRITICAL_SECTION g_csUniqueFileName; + +void PALAPI setup(void); +void PALAPI cleanup(void); +void PALAPI incrementCounter(void); +DWORD PALAPI readfile( LPVOID); +DWORD PALAPI enterandleave_cs( LPVOID); +DWORD PALAPI allocateandfree_memory( LPVOID); +DWORD PALAPI doworkintightloop_cs( LPVOID); +DWORD PALAPI suspendandresumethreads( LPVOID); +int GetParameters(int, char * *); + + +//Main Entry for the Thread Suspension Test Case +int __cdecl main (int argc, char **argv) +{ + +/* +* Parameter to the threads that will be created +*/ + + +DWORD dwThrdParam = 0; +DWORD dwStart; + +/* Variables to capture the file name and the file pointer*/ +char fileName[MAX_PATH]; +char processFileName[MAX_PATH]; + +FILE *hFile, *hProcessFile; +struct statistics* buffer; +struct processStatistics *processBuffer; + +struct processStatistics processStats; + +struct statistics* tmpBuf = NULL; +int statisticsSize = 0; + +DWORD dwThreadId=0; +HANDLE hMainThread; +unsigned int i = 0; +int j = 0; + + +/* +* PAL Initialize +*/ + +if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + +//Get Parameters +if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } + + +//Setup for Process Result Collection +statisticsSize = sizeof(struct statistics); +_snprintf(processFileName, MAX_PATH, "%d_process_threadsuspension_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); +hProcessFile = fopen(processFileName, "w+"); + +if(hProcessFile == NULL) + { + Fail("Error in opening file to write process results for process [%d]\n", USE_PROCESS_COUNT); + } + +//Initialize Process Stats Variables +processStats.operationTime = 0; +processStats.processId = USE_PROCESS_COUNT; +processStats.relationId = RELATION_ID; + +//Start Process Time Capture +dwStart = GetTickCount(); + +//Setup for Thread Result Collection +statisticsSize = sizeof(struct statistics); +_snprintf(fileName, MAX_PATH, "%d_thread_threadsuspension_%d_.txt", USE_PROCESS_COUNT,RELATION_ID); +hFile = fopen(fileName, "w+"); + +if(hFile == NULL) + { + Fail("Error in opening file to write thread results for process [%d]\n", USE_PROCESS_COUNT); + } + +// For each thread we will log relationid (int), processid (int), operations failed (int), passed (int), total (int) +// and number of ticks (DWORD) for the operations +resultBuffer = new ResultBuffer( 1, statisticsSize); + +/* +* Call the Setup Routine +*/ +setup(); + +Trace("WORKER_THREAD_MULTIPLIER_COUNT: %d \n", WORKER_THREAD_MULTIPLIER_COUNT); + +//Create WORKER_THREAD_MULTIPLIER_COUNT Instances of each type of worker thread +for (i=0;igetResultBuffer(i); + fprintf(hFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); + } + } + +if (0!=fclose(hFile)) +{ + Fail("Unable to write thread results to file" + "GetLastError returned %d\n", GetLastError()); +} + +cleanup(); + +if (failFlag == TRUE) +{ + return FAIL; +} +else +{ + return PASS; +} +} + + +/* +* Setup for the test case +*/ + +VOID +setup(VOID) +{ + /*Delete All Temporary Files Created by the previous execution of the test case*/ + HANDLE hSearch; + BOOL fFinished = FALSE; + WIN32_FIND_DATA FileData; + + //Start searching for .tmp files in the current directory. + hSearch = FindFirstFile("*.tmp*", &FileData); + if (hSearch == INVALID_HANDLE_VALUE) + { + //No Files That Matched Criteria + fFinished = TRUE; + } + + //Delete all files that match the pattern + while (!fFinished) + { + if (!DeleteFile(FileData.cFileName)) + { + Trace("Setup: Could not delete temporary file %s\n",FileData.cFileName ); + Fail ("GetLastError returned %d\n", GetLastError()); + } + if (!FindNextFile(hSearch, &FileData)) + { + if (GetLastError() == ERROR_NO_MORE_FILES) + { + fFinished = TRUE; + } + else + { + Fail("Unable to Delete Temporary Files, GetLastError is %d \n", GetLastError()); + } + } + } + + // Close the search handle, only if HANDLE is Valid + if (hSearch != INVALID_HANDLE_VALUE) + { + if (!FindClose(hSearch)) + { + Trace("Setup: Could not close search handle \n"); + Fail ("GetLastError returned %d\n", GetLastError()); + } + } + + g_hEvent = CreateEvent(NULL,TRUE,FALSE, NULL); + if(g_hEvent == NULL) + { + Fail("Create Event Failed\n" + "GetLastError returned %d\n", GetLastError()); + } + + InitializeCriticalSection ( &g_csUniqueFileName); +} + +/* +* Cleanup for the test case +*/ + +VOID +cleanup(VOID) +{ + //DeleteCriticalSection(&g_csUniqueFileName); + PAL_Terminate(); +} + + +VOID +incrementCounter(VOID) +{ + + if (INT_MAX == GLOBAL_COUNTER) + { + GLOBAL_COUNTER = 0; + } + + GLOBAL_COUNTER++; +} + +/* + * Worker Thread + * Read File: Read from a file and write to a temporary file and then delete the temp file + */ +DWORD +PALAPI +readfile( LPVOID lpParam ) +{ + + // Declaring Local Variables + HANDLE hFile,hTempfile; + char buffer[BUFSIZE]; + DWORD dwBytesRead, dwBytesWritten, dwBufSize=BUFSIZE; + DWORD dwWaitResult=0; + char filename[MAX_PATH]; + + //Wait for event to signal to start test + dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE); + if (WAIT_OBJECT_0 != dwWaitResult) + { + Fail ("readfile: Wait for Single Object (g_hEvent) failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + + /*Start Operation*/ + + // Open the existing file. + while(TRUE) + { + + hFile = CreateFile("samplefile.dat", // file name + GENERIC_READ, // open for reading + FILE_SHARE_READ, // Share the file for read + NULL, // default security + OPEN_EXISTING, // existing file only + FILE_ATTRIBUTE_NORMAL, // normal file + NULL); // no template + + if (hFile == INVALID_HANDLE_VALUE) + { + Trace("Could not open file \n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + + //Generate Unique File Name to Write + //Enter CS + EnterCriticalSection(&g_csUniqueFileName); + + //Increment Number and assign to local variable + UNIQUE_FILE_NUMBER++; + _snprintf(filename, MAX_PATH, "%d_%d_tempfile.tmp", USE_PROCESS_COUNT,UNIQUE_FILE_NUMBER); + //filename = itoa(UNIQUE_FILE_NUMBER); + //Leave CS + LeaveCriticalSection(&g_csUniqueFileName); + + + // Create a temporary file with name generate above + hTempfile = CreateFile(filename, // file name + GENERIC_WRITE, // open for read/write + 0, // do not share + NULL, // default security + CREATE_ALWAYS, // overwrite existing file + FILE_ATTRIBUTE_NORMAL, // normal file + NULL); // no template + + + if (hTempfile == INVALID_HANDLE_VALUE) + { + Trace("Could not create temporary file\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + + // Read 4K blocks to the buffer. + // Change all characters in the buffer to upper case. + // Write the buffer to the temporary file. + + do + { + if (ReadFile(hFile, buffer, 4096, + &dwBytesRead, NULL)) + { + + WriteFile(hTempfile, buffer, dwBytesRead, + &dwBytesWritten, NULL); + } + } while (dwBytesRead == BUFSIZE); + + + + // Close both files. + if (0==CloseHandle(hFile)) + { + Trace("Could not handle hFile\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + + if (0==CloseHandle(hTempfile)) + { + Trace("Could not handle hTempFile\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + + //Delete the file that was created + if (!DeleteFile(filename)) + { + Trace("Could not delete temporary file %s\n", filename); + Fail ( "GetLastError returned %d\n", GetLastError()); + + } + + //g_readfileoperation++; + } + +/*End Operation*/ + + return 0; +} + + +/* Worker Thread + * Enter and Leave Nested Critical Sections + */ +DWORD +PALAPI +enterandleave_cs( LPVOID lpParam ) +{ + + //Declare Local Variables + + CRITICAL_SECTION lcs; + CRITICAL_SECTION lcsNested; + + DWORD dwWaitResult; + + //Intialize Critical Section Structures + InitializeCriticalSection ( &lcs); + InitializeCriticalSection ( &lcsNested); + + + //Wait for event to signal to start test + dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE); + if (WAIT_OBJECT_0 != dwWaitResult) + { + Fail ("enterandleave_cs: Wait for Single Object (g_hEvent) failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + //Trace("Critical Section Started\n"); + + while(TRUE) + { + EnterCriticalSection(&lcs); + + EnterCriticalSection(&lcsNested); + + incrementCounter(); + + LeaveCriticalSection(&lcsNested); + + LeaveCriticalSection(&lcs); + //g_enterleavecsoperation++; + } + + //Delete Critical Section Structures + + DeleteCriticalSection(&lcs); + DeleteCriticalSection(&lcsNested); + + + return 0; +} + + +/* + * Allocate and Free Memory + */ +DWORD +PALAPI +allocateandfree_memory( LPVOID lpParam ) +{ + + + int i; + char *textArrPtr[64]; + DWORD dwWaitResult; + + //Wait for event to signal to start test + dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE); + if (WAIT_OBJECT_0 != dwWaitResult) + { + Fail ("allocateandfree_memory: Wait for Single Object (g_hEvent) failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + + while(TRUE) + { + + //do allocate and free operation + + for (i=0;i<64;i++) + { + textArrPtr[i] = (char*) malloc(BUFSIZE); + if (textArrPtr[i] == NULL) + { + Fail("Insufficient Memory Available, GetLastError is %d \n", GetLastError()); + testStatus = TEST_FAIL; + } + } + + for (i=0;i<64;i++) + { + free(textArrPtr[i]); + } + //g_allocatefreeoperation++; + } + + + + + return 0; +} + +/* + * Do work in a tight loop + */ +DWORD +PALAPI +doworkintightloop_cs( LPVOID lpParam ) +{ + + unsigned int i; + DWORD dwWaitResult; + + //Wait for event to signal to start test + dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE); + if (WAIT_OBJECT_0 != dwWaitResult) + { + Fail ("doworkintightloop_cs: Wait for Single Object (g_hEvent) failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + i= 0; + while (TRUE) + { + + if (INT_MAX == i) + i =0; + i++; + //g_doworintightloop++; + } + + return 0; +} + + +/* + * Main Test Case worker thread which will suspend and resume all other worker threads + */ +DWORD +PALAPI +suspendandresumethreads( LPVOID lpParam ) +{ + + unsigned int loopcount = REPEAT_COUNT; + int Id=(int)lpParam; + unsigned int i,j,k; + DWORD dwStart; + DWORD dwWaitResult=0; + DWORD dwLastError = 0; + struct statistics stats; + struct statistics* buffer; + + + + //Initialize the Statistics Structure + stats.relationId = RELATION_ID; + stats.processId = USE_PROCESS_COUNT; + stats.operationsFailed = 0; + stats.operationsPassed = 0; + stats.operationsTotal = 0; + stats.operationTime = 0; + + + + //Wait for event to signal to start test + WaitForSingleObject(g_hEvent,INFINITE); + if (WAIT_OBJECT_0 != dwWaitResult) + { + Fail ("suspendandresumethreads: Wait for Single Object (g_hEvent) failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + + //Capture Start Import + dwStart = GetTickCount(); + + for(i = 0; i < loopcount; i++) + { + + failFlag = false; + + //Suspend Worker Threads + for (k=0;kLogResult(Id, (char *)&stats)) + { + Fail("Error while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", Id, USE_PROCESS_COUNT); + } + + buffer = (struct statistics *)resultBuffer->getResultBuffer(Id); + //Trace("\n%d,%d,%d,%lu\n", buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime ); + + + return 0; +} + + + +int GetParameters( int argc, char **argv) +{ + + if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + Trace("PAL -Composite Thread Suspension Test\n"); + Trace("Usage:\n"); + Trace("\t[PROCESS_COUNT] Greater than or Equal to 1 \n"); + Trace("\t[WORKER_THREAD_MULTIPLIER_COUNT] Greater than or Equal to 1 and Less than or Equal to 64 \n"); + Trace("\t[REPEAT_COUNT] Greater than or Equal to 1\n"); + Trace("\t[RELATION_ID [greater than or Equal to 1]\n"); + return -1; + } + +// Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]); + + USE_PROCESS_COUNT = atoi(argv[1]); + if( USE_PROCESS_COUNT < 0) + { + Trace("\nPROCESS_COUNT to greater than or equal to 1\n"); + return -1; + } + + WORKER_THREAD_MULTIPLIER_COUNT = atoi(argv[2]); + if( WORKER_THREAD_MULTIPLIER_COUNT < 1 || WORKER_THREAD_MULTIPLIER_COUNT > 64) + { + Trace("\nWORKER_THREAD_MULTIPLIER_COUNT to be greater than or equal to 1 or less than or equal to 64\n"); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + Trace("\nREPEAT_COUNT to greater than or equal to 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + Trace("\nRELATION_ID to be greater than or equal to 1\n"); + return -1; + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/CMakeLists.txt new file mode 100644 index 0000000..0d6a8fb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/CMakeLists.txt @@ -0,0 +1,14 @@ +set(SOURCES + mainWrapper.cpp + threadsuspension.cpp +) + +add_executable(paltest_threading_threadsuspension_switchthread + ${SOURCES} +) + +add_dependencies(paltest_threading_threadsuspension_switchthread coreclrpal) + +target_link_libraries(paltest_threading_threadsuspension_switchthread + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/mainWrapper.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/mainWrapper.cpp new file mode 100644 index 0000000..05a7119 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/mainWrapper.cpp @@ -0,0 +1,274 @@ +// 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. + +/* +Source Code: mainWrapper.c + +mainWrapper.c creates Composite Test Case Processes and waits for all processes to get over + +Algorithm +o Create PROCESS_COUNT processes. + +Author: RameshG +*/ + +#include +#include "resulttime.h" + +/* Test Input Variables */ +unsigned int USE_PROCESS_COUNT = 0; //default +unsigned int WORKER_THREAD_MULTIPLIER_COUNT = 0; //default +unsigned int REPEAT_COUNT = 0; //default +unsigned int SLEEP_LENGTH = 0; //default +unsigned int RELATION_ID = 0;//default +unsigned int THREAD_COUNT = 1; //There is only one suspender and resume thread for this test case + +char *testCaseName; + + +struct applicationStatistics{ + DWORD operationTime; + unsigned int relationId; + unsigned int processCount; + unsigned int threadCount; + unsigned int repeatCount; + char* buildNumber; + +}; + + +int GetParameters( int argc, char **argv) +{ + + if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite Thread Suspension Test\n"); + printf("Usage:\n"); + printf("\t[PROCESS_COUNT] Greater than or Equal to 1 \n"); + printf("\t[WORKER_THREAD_MULTIPLIER_COUNT] Greater than or Equal to 1 and Less than or Equal to %d \n", MAXIMUM_WAIT_OBJECTS); + printf("\t[REPEAT_COUNT] Greater than or Equal to 1\n"); + printf("\t[RELATION_ID [greater than or Equal to 1]\n"); + return -1; + } + + // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]); + + USE_PROCESS_COUNT = atoi(argv[1]); + if( USE_PROCESS_COUNT < 0) + { + printf("\nPROCESS_COUNT to greater than or equal to 1\n"); + return -1; + } + + WORKER_THREAD_MULTIPLIER_COUNT = atoi(argv[2]); + if( WORKER_THREAD_MULTIPLIER_COUNT < 1 || WORKER_THREAD_MULTIPLIER_COUNT > 64) + { + printf("\nWORKER_THREAD_MULTIPLIER_COUNT to be greater than or equal to 1 or less than or equal to 64\n"); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nREPEAT_COUNT to greater than or equal to 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + printf("\nRELATION_ID to be greater than or equal to 1\n"); + return -1; + } + + + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hProcess[MAXIMUM_WAIT_OBJECTS]; + DWORD processReturnCode = 0; + int testReturnCode = PASS; + STARTUPINFO si[MAXIMUM_WAIT_OBJECTS]; + PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS]; + + FILE *hFile; + char fileName[MAX_PATH]; + struct applicationStatistics appStats; + + DWORD dwStart=0; + + char lpCommandLine[MAX_PATH] = ""; + + char build[] ="0000.00"; + int returnCode = 0; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + //Initialize Application Statistics Strucuture + appStats.relationId=RELATION_ID; + appStats.operationTime=0; + appStats.buildNumber = getBuildNumber(); + //appStats.buildNumber = build; + appStats.processCount = 0; + appStats.threadCount = 0; + appStats.repeatCount = 0; + + + + + +//Start Process Time Capture +dwStart = GetTickCount(); + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } + +//Assign Correct Values to the Application Stats Structure + appStats.relationId=RELATION_ID; + appStats.processCount = USE_PROCESS_COUNT; + appStats.threadCount = THREAD_COUNT ; + appStats.repeatCount = REPEAT_COUNT; + + Trace("Relation ID: %d \n", RELATION_ID); + Trace("USE_PROCESS_COUNT: %d \n", USE_PROCESS_COUNT); + Trace("WORKER_THREAD_MULTIPLIER_COUNT: %d \n", WORKER_THREAD_MULTIPLIER_COUNT); + Trace("REPEAT_COUNT: %d \n", REPEAT_COUNT); + + +_snprintf(fileName, MAX_PATH, "main_threadsuspension_%d_.txt",appStats.relationId); + + hFile = fopen(fileName, "w+"); +if(hFile == NULL) + { + Fail("Error in opening file to write application results for Thread Suspension Test with error code %d \n", GetLastError() ); + } + + + + for( i = 0; i < USE_PROCESS_COUNT; i++ ) + { + + ZeroMemory( lpCommandLine, MAX_PATH ); + if ( _snprintf( lpCommandLine, MAX_PATH-1, "threadsuspension %d %d %d %d", i, WORKER_THREAD_MULTIPLIER_COUNT, REPEAT_COUNT, RELATION_ID) < 0 ) + { + Trace ("Error: Insufficient commandline string length for for iteration [%d]\n", i); + } + + /* Zero the data structure space */ + ZeroMemory ( &pi[i], sizeof(pi[i]) ); + ZeroMemory ( &si[i], sizeof(si[i]) ); + + /* Set the process flags and standard io handles */ + si[i].cb = sizeof(si[i]); + + //Printing the Command Line + //Trace("Command Line \t %s \n", lpCommandLine); + + //Create Process + if(!CreateProcess( NULL, /* lpApplicationName*/ + lpCommandLine, /* lpCommandLine */ + NULL, /* lpProcessAttributes */ + NULL, /* lpThreadAttributes */ + TRUE, /* bInheritHandles */ + 0, /* dwCreationFlags, */ + NULL, /* lpEnvironment */ + NULL, /* pCurrentDirectory */ + &si[i], /* lpStartupInfo */ + &pi[i] /* lpProcessInformation */ + )) + { + Fail("Process Not created for [%d] and GetLastError value is %d\n", i, GetLastError()); + + } + else + { + hProcess[i] = pi[i].hProcess; + //Trace("Process created for [%d]\n", i); + } + + } + + returnCode = WaitForMultipleObjects( USE_PROCESS_COUNT, hProcess, TRUE, INFINITE); + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError()); + testReturnCode = FAIL; + } + + for( i = 0; i < USE_PROCESS_COUNT; i++ ) + { + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) ) + { + Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n", + i, GetLastError() ); + + testReturnCode = FAIL; + } + + if(processReturnCode == FAIL) + { + Trace( "Process [%d] failed and returned FAIL\n", i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hThread)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hProcess) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i); + testReturnCode = FAIL; + } + } + +//Get the end time of the process +appStats.operationTime = GetTickCount() - dwStart; + +if( testReturnCode == PASS) + { + Trace("Test Passed\n"); + } + else + { + Trace("Test Failed\n"); + } + +//Write Process Result Contents to File +if(hFile!= NULL) + { + fprintf(hFile, "%lu,%d,%d,%d,%d,%s\n", appStats.operationTime, appStats.relationId, appStats.processCount, appStats.threadCount, appStats.repeatCount, appStats.buildNumber); + } + +if (0!=fclose(hFile)) +{ + Trace("Error:%d: fclose failed for file %s\n", GetLastError(), fileName); +} + PAL_Terminate(); + + +if( testReturnCode == PASS) + { + return PASS; + } + else + { + return FAIL; + + } + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/readme.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/readme.txt new file mode 100644 index 0000000..d722f1d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/readme.txt @@ -0,0 +1,11 @@ +To compile: + +1) create a dat file (say threadsuspension.dat) with contents: +PAL,Composite,palsuite\composite\threading\threadsuspension,wfmo=mainWrapper.c threadsuspension.c,,, + +2) perl rrunmod.pl -r threadsuspension.dat + + +To execute: +mainWrapper [PROCESS_COUNT] [THREAD_COUNT] [REPEAT_COUNT] + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/samplefile.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/samplefile.dat new file mode 100644 index 0000000..d6505f2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/samplefile.dat @@ -0,0 +1,5124 @@ +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense blackasdf dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. +By Patricia Reaney +LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said. + +Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas. + +Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours. + +The planet will appear as an intense black dot on the solar disc. + +Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth. + +"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England. + +Scientists recommend some form of indirect projection as the safest way to observe the phenomenon. + +"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh. + +"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said. + +Internet sites will be covering the transit and observatories around the world have organized viewings. + +"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine." + +German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639. + +The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again. + +The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/threadsuspension.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/threadsuspension.cpp new file mode 100644 index 0000000..a117b86 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/threadsuspension.cpp @@ -0,0 +1,914 @@ +// 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. + +/*============================================================ +** +** Source: \composite\threading\threadsuspension\threadsuspension.c +** +** Purpose: To verify Thread Suspension Reegneering effort for this milestone + + PsedoCode: + + Preparation: + Create PROCESS_COUNT processes. + Test: + Create Worker Thread + Start Reading and writing to a File + + Create Worker Thread + In an infinite loop do the following + Enter Critical Section + Increment Counter + Leave Critical Section + + Create Worker Thread + Allocate Memory and Free Memory + + Create Worker Thread + In a tight loop add numbers + + In a loop repeated REPEAT_COUNT times + + Create Thread + + Suspend all worker threads + Resume all worker threads + + At the end of the loop call PAL_Shutdown + + Parameters: + PROCESS_COUNT: Number of processes + WORKER_THREAD_MULTIPLIER_COUNT: Number of instances of worker threads in each process + REPEAT_COUNT: The number of times to execute the loop. + + Statistics Captured: + Total elapsed time + MTBF + + + Scenario: +** + One thread suspends all remaining threads which are in the middle of doing some work and resume all threads + Thread 1: Reading and Writing File + Thread 2: Enter and Leave Critical Section + Thread 3: Allocating chunks of memory + Thread 4: Perform Unsafe Operation (printf, malloc) + Thread 5: Suspends Thread 1 to Thread 4 and resumes them + +** +** +** +** Dependencies: +** +** + +** +**=========================================================*/ + +#include +#include "resultbuffer.h" + +#define BUFSIZE 4096 +#define NUMBER_OF_WORKER_THREAD_TYPES 4 +#define THREAD_MAX 64 + +#define TEST_FAIL 1 +#define TEST_PASS 0 + + +DWORD GLOBAL_COUNTER ; +DWORD UNIQUE_FILE_NUMBER=0; +HANDLE g_hEvent; + +bool failFlag = false; //To Track failure at the Operation Level + +// 2 dimensional array to hold thread handles for each worker thread +HANDLE hThread[NUMBER_OF_WORKER_THREAD_TYPES][THREAD_MAX]; + +/*unsigned int g_readfileoperation; +unsigned int g_enterleavecsoperation; +unsigned int g_allocatefreeoperation; +unsigned int g_doworintightloop; +*/ + +int TYPES_OF_WORKER_THREAD = NUMBER_OF_WORKER_THREAD_TYPES; + +int testStatus=TEST_PASS; //Indicates test failure + + +struct statistics{ + unsigned int processId; + unsigned int operationsFailed; + unsigned int operationsPassed; + unsigned int operationsTotal; + DWORD operationTime; + unsigned int relationId; +}; + +struct processStatistics{ + unsigned int processId; + DWORD operationTime; + unsigned int relationId; +}; + +/* Results Buffer */ +ResultBuffer *resultBuffer; + + +/* Test Input Variables */ +unsigned int USE_PROCESS_COUNT = 0; //Identifies the Process number. There could potentially +unsigned int WORKER_THREAD_MULTIPLIER_COUNT = 0; //In this test case this represents the number of worker thread instances +unsigned int REPEAT_COUNT = 0; //Number of Suspend Resume operation of worker threads +unsigned int RELATION_ID = 0; + + + +CRITICAL_SECTION CriticalSectionM; /* Critical Section Object (used as mutex) */ +CRITICAL_SECTION g_csUniqueFileName; + +void PALAPI setup(void); +void PALAPI cleanup(void); +void PALAPI incrementCounter(void); +DWORD PALAPI readfile( LPVOID); +DWORD PALAPI enterandleave_cs( LPVOID); +DWORD PALAPI allocateandfree_memory( LPVOID); +DWORD PALAPI doworkintightloop_cs( LPVOID); +DWORD PALAPI suspendandresumethreads( LPVOID); +int GetParameters(int, char * *); + + +//Main Entry for the Thread Suspension Test Case +int __cdecl main (int argc, char **argv) +{ + +/* +* Parameter to the threads that will be created +*/ + + +DWORD dwThrdParam = 0; +DWORD dwStart; + +/* Variables to capture the file name and the file pointer*/ +char fileName[MAX_PATH]; +char processFileName[MAX_PATH]; + +FILE *hFile, *hProcessFile; +struct statistics* buffer; +struct processStatistics *processBuffer; + +struct processStatistics processStats; + +struct statistics* tmpBuf = NULL; +int statisticsSize = 0; + +DWORD dwThreadId=0; +HANDLE hMainThread; +unsigned int i = 0; +int j = 0; + + +/* +* PAL Initialize +*/ + +if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + +//Get Parameters +if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } + + +//Setup for Process Result Collection +statisticsSize = sizeof(struct statistics); +_snprintf(processFileName, MAX_PATH, "%d_process_threadsuspension_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); +hProcessFile = fopen(processFileName, "w+"); + +if(hProcessFile == NULL) + { + Fail("Error in opening file to write process results for process [%d]\n", USE_PROCESS_COUNT); + } + +//Initialize Process Stats Variables +processStats.operationTime = 0; +processStats.processId = USE_PROCESS_COUNT; +processStats.relationId = RELATION_ID; + +//Start Process Time Capture +dwStart = GetTickCount(); + +//Setup for Thread Result Collection +statisticsSize = sizeof(struct statistics); +_snprintf(fileName, MAX_PATH, "%d_thread_threadsuspension_%d_.txt", USE_PROCESS_COUNT,RELATION_ID); +hFile = fopen(fileName, "w+"); + +if(hFile == NULL) + { + Fail("Error in opening file to write thread results for process [%d]\n", USE_PROCESS_COUNT); + } + +// For each thread we will log relationid (int), processid (int), operations failed (int), passed (int), total (int) +// and number of ticks (DWORD) for the operations +resultBuffer = new ResultBuffer( 1, statisticsSize); + +/* +* Call the Setup Routine +*/ +setup(); + +Trace("WORKER_THREAD_MULTIPLIER_COUNT: %d \n", WORKER_THREAD_MULTIPLIER_COUNT); + +//Create WORKER_THREAD_MULTIPLIER_COUNT Instances of each type of worker thread +for (i=0;igetResultBuffer(i); + fprintf(hFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); + } + } + +if (0!=fclose(hFile)) +{ + Fail("Unable to write thread results to file" + "GetLastError returned %d\n", GetLastError()); +} + +cleanup(); + +if (failFlag == TRUE) +{ + return FAIL; +} +else +{ + return PASS; +} +} + + +/* +* Setup for the test case +*/ + +VOID +setup(VOID) +{ + /*Delete All Temporary Files Created by the previous execution of the test case*/ + HANDLE hSearch; + BOOL fFinished = FALSE; + WIN32_FIND_DATA FileData; + + //Start searching for .tmp files in the current directory. + hSearch = FindFirstFile("*.tmp*", &FileData); + if (hSearch == INVALID_HANDLE_VALUE) + { + //No Files That Matched Criteria + fFinished = TRUE; + } + + //Delete all files that match the pattern + while (!fFinished) + { + if (!DeleteFile(FileData.cFileName)) + { + Trace("Setup: Could not delete temporary file %s\n",FileData.cFileName ); + Fail ("GetLastError returned %d\n", GetLastError()); + } + if (!FindNextFile(hSearch, &FileData)) + { + if (GetLastError() == ERROR_NO_MORE_FILES) + { + fFinished = TRUE; + } + else + { + Fail("Unable to Delete Temporary Files, GetLastError is %d \n", GetLastError()); + } + } + } + + // Close the search handle, only if HANDLE is Valid + if (hSearch != INVALID_HANDLE_VALUE) + { + if (!FindClose(hSearch)) + { + Trace("Setup: Could not close search handle \n"); + Fail ("GetLastError returned %d\n", GetLastError()); + } + } + + g_hEvent = CreateEvent(NULL,TRUE,FALSE, NULL); + if(g_hEvent == NULL) + { + Fail("Create Event Failed\n" + "GetLastError returned %d\n", GetLastError()); + } + + InitializeCriticalSection ( &g_csUniqueFileName); +} + +/* +* Cleanup for the test case +*/ + +VOID +cleanup(VOID) +{ + //DeleteCriticalSection(&g_csUniqueFileName); + PAL_Terminate(); +} + + +VOID +incrementCounter(VOID) +{ + + if (INT_MAX == GLOBAL_COUNTER) + { + GLOBAL_COUNTER = 0; + } + + GLOBAL_COUNTER++; +} + +/* + * Worker Thread + * Read File: Read from a file and write to a temporary file and then delete the temp file + */ +DWORD +PALAPI +readfile( LPVOID lpParam ) +{ + + // Declaring Local Variables + HANDLE hFile,hTempfile; + char buffer[BUFSIZE]; + DWORD dwBytesRead, dwBytesWritten, dwBufSize=BUFSIZE; + DWORD dwWaitResult=0; + char filename[MAX_PATH]; + + //Wait for event to signal to start test + dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE); + if (WAIT_OBJECT_0 != dwWaitResult) + { + Fail ("readfile: Wait for Single Object (g_hEvent) failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + + /*Start Operation*/ + + // Open the existing file. + while(TRUE) + { + + hFile = CreateFile("samplefile.dat", // file name + GENERIC_READ, // open for reading + FILE_SHARE_READ, // Share the file for read + NULL, // default security + OPEN_EXISTING, // existing file only + FILE_ATTRIBUTE_NORMAL, // normal file + NULL); // no template + + if (hFile == INVALID_HANDLE_VALUE) + { + Trace("Could not open file \n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + + //Generate Unique File Name to Write + //Enter CS + EnterCriticalSection(&g_csUniqueFileName); + + //Increment Number and assign to local variable + UNIQUE_FILE_NUMBER++; + _snprintf(filename, MAX_PATH, "%d_%d_tempfile.tmp", USE_PROCESS_COUNT,UNIQUE_FILE_NUMBER); + //filename = itoa(UNIQUE_FILE_NUMBER); + //Leave CS + LeaveCriticalSection(&g_csUniqueFileName); + + + // Create a temporary file with name generate above + hTempfile = CreateFile(filename, // file name + GENERIC_WRITE, // open for read/write + 0, // do not share + NULL, // default security + CREATE_ALWAYS, // overwrite existing file + FILE_ATTRIBUTE_NORMAL, // normal file + NULL); // no template + + + if (hTempfile == INVALID_HANDLE_VALUE) + { + Trace("Could not create temporary file\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + + // Read 4K blocks to the buffer. + // Change all characters in the buffer to upper case. + // Write the buffer to the temporary file. + + do + { + if (ReadFile(hFile, buffer, 4096, + &dwBytesRead, NULL)) + { + + WriteFile(hTempfile, buffer, dwBytesRead, + &dwBytesWritten, NULL); + } + } while (dwBytesRead == BUFSIZE); + + + + // Close both files. + if (0==CloseHandle(hFile)) + { + Trace("Could not handle hFile\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + + if (0==CloseHandle(hTempfile)) + { + Trace("Could not handle hTempFile\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + + //Delete the file that was created + if (!DeleteFile(filename)) + { + Trace("Could not delete temporary file %s\n", filename); + Fail ( "GetLastError returned %d\n", GetLastError()); + + } + + SwitchToThread(); + //g_readfileoperation++; + } + +/*End Operation*/ + + return 0; +} + + +/* Worker Thread + * Enter and Leave Nested Critical Sections + */ +DWORD +PALAPI +enterandleave_cs( LPVOID lpParam ) +{ + + //Declare Local Variables + + CRITICAL_SECTION lcs; + CRITICAL_SECTION lcsNested; + + DWORD dwWaitResult; + + //Intialize Critical Section Structures + InitializeCriticalSection ( &lcs); + InitializeCriticalSection ( &lcsNested); + + + //Wait for event to signal to start test + dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE); + if (WAIT_OBJECT_0 != dwWaitResult) + { + Fail ("enterandleave_cs: Wait for Single Object (g_hEvent) failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + //Trace("Critical Section Started\n"); + + while(TRUE) + { + EnterCriticalSection(&lcs); + + EnterCriticalSection(&lcsNested); + + incrementCounter(); + + LeaveCriticalSection(&lcsNested); + + LeaveCriticalSection(&lcs); + + SwitchToThread(); + //g_enterleavecsoperation++; + } + + //Delete Critical Section Structures + + DeleteCriticalSection(&lcs); + DeleteCriticalSection(&lcsNested); + + + return 0; +} + + +/* + * Allocate and Free Memory + */ +DWORD +PALAPI +allocateandfree_memory( LPVOID lpParam ) +{ + + + int i; + char *textArrPtr[64]; + DWORD dwWaitResult; + + //Wait for event to signal to start test + dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE); + if (WAIT_OBJECT_0 != dwWaitResult) + { + Fail ("allocateandfree_memory: Wait for Single Object (g_hEvent) failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + + while(TRUE) + { + + //do allocate and free operation + + for (i=0;i<64;i++) + { + textArrPtr[i] = (char*) malloc(BUFSIZE); + if (textArrPtr[i] == NULL) + { + Fail("Insufficient Memory Available, GetLastError is %d \n", GetLastError()); + testStatus = TEST_FAIL; + } + } + + for (i=0;i<64;i++) + { + free(textArrPtr[i]); + } + + SwitchToThread(); + //g_allocatefreeoperation++; + } + + + + + return 0; +} + +/* + * Do work in a tight loop + */ +DWORD +PALAPI +doworkintightloop_cs( LPVOID lpParam ) +{ + + unsigned int i; + DWORD dwWaitResult; + + //Wait for event to signal to start test + dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE); + if (WAIT_OBJECT_0 != dwWaitResult) + { + Fail ("doworkintightloop_cs: Wait for Single Object (g_hEvent) failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + i= 0; + while (TRUE) + { + + if (INT_MAX == i) + i =0; + i++; + //g_doworintightloop++; + + SwitchToThread(); + } + + return 0; +} + + +/* + * Main Test Case worker thread which will suspend and resume all other worker threads + */ +DWORD +PALAPI +suspendandresumethreads( LPVOID lpParam ) +{ + + unsigned int loopcount = REPEAT_COUNT; + int Id=(int)lpParam; + unsigned int i,j,k; + DWORD dwStart; + DWORD dwWaitResult=0; + DWORD dwLastError = 0; + struct statistics stats; + struct statistics* buffer; + + + + //Initialize the Statistics Structure + stats.relationId = RELATION_ID; + stats.processId = USE_PROCESS_COUNT; + stats.operationsFailed = 0; + stats.operationsPassed = 0; + stats.operationsTotal = 0; + stats.operationTime = 0; + + + + //Wait for event to signal to start test + WaitForSingleObject(g_hEvent,INFINITE); + if (WAIT_OBJECT_0 != dwWaitResult) + { + Fail ("suspendandresumethreads: Wait for Single Object (g_hEvent) failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + + //Capture Start Import + dwStart = GetTickCount(); + + for(i = 0; i < loopcount; i++) + { + + failFlag = false; + + //Suspend Worker Threads + for (k=0;kLogResult(Id, (char *)&stats)) + { + Fail("Error while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", Id, USE_PROCESS_COUNT); + } + + buffer = (struct statistics *)resultBuffer->getResultBuffer(Id); + //Trace("\n%d,%d,%d,%lu\n", buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime ); + + + return 0; +} + + + +int GetParameters( int argc, char **argv) +{ + + if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + Trace("PAL -Composite Thread Suspension Test\n"); + Trace("Usage:\n"); + Trace("\t[PROCESS_COUNT] Greater than or Equal to 1 \n"); + Trace("\t[WORKER_THREAD_MULTIPLIER_COUNT] Greater than or Equal to 1 and Less than or Equal to 64 \n"); + Trace("\t[REPEAT_COUNT] Greater than or Equal to 1\n"); + Trace("\t[RELATION_ID [greater than or Equal to 1]\n"); + return -1; + } + +// Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]); + + USE_PROCESS_COUNT = atoi(argv[1]); + if( USE_PROCESS_COUNT < 0) + { + Trace("\nPROCESS_COUNT to greater than or equal to 1\n"); + return -1; + } + + WORKER_THREAD_MULTIPLIER_COUNT = atoi(argv[2]); + if( WORKER_THREAD_MULTIPLIER_COUNT < 1 || WORKER_THREAD_MULTIPLIER_COUNT > 64) + { + Trace("\nWORKER_THREAD_MULTIPLIER_COUNT to be greater than or equal to 1 or less than or equal to 64\n"); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + Trace("\nREPEAT_COUNT to greater than or equal to 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[4]); + if( RELATION_ID < 1) + { + Trace("\nRELATION_ID to be greater than or equal to 1\n"); + return -1; + } + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/CMakeLists.txt new file mode 100644 index 0000000..11cc571 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/CMakeLists.txt @@ -0,0 +1,15 @@ +set(SOURCES + main.cpp + mutex.cpp +) + +add_executable(paltest_composite_wfmo + ${SOURCES} +) + +add_dependencies(paltest_composite_wfmo coreclrpal) + +target_link_libraries(paltest_composite_wfmo + ${COMMON_TEST_LIBRARIES} + rt +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/main.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/main.cpp new file mode 100644 index 0000000..d186aa7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/main.cpp @@ -0,0 +1,239 @@ +// 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. + +/*============================================================ +** Source Code: main.c and mutex.c +** main.c creates process and waits for all processes to get over +** mutex.c creates a mutex and then calls threads which will contend for the mutex +** +** This test is for WFMO Test case for Mutex +** Algorithm +** o Create PROCESS_COUNT processes. +** o Main Thread of each process creates OBJECT_TYPE Object +** +** Author: ShamitP +** +** +**============================================================ +*/ + +#include +#include "resulttime.h" + +/* Test Input Variables */ +unsigned int PROCESS_COUNT = 3; +unsigned int THREAD_COUNT = 30; +unsigned int REPEAT_COUNT = 40; +unsigned int SLEEP_LENGTH = 4; +unsigned int RELATION_ID = 1001; + + + +struct TestStats{ + DWORD operationTime; + unsigned int relationId; + unsigned int processCount; + unsigned int threadCount; + unsigned int repeatCount; + char* buildNumber; + +}; + +int GetParameters( int argc, char **argv) +{ + if( (argc != 6) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite WFMO Test\n"); + printf("Usage:\n"); + printf("main\n\t[PROCESS_COUNT [greater than 0] \n"); + printf("\t[THREAD_COUNT [greater than 0] \n"); + printf("\t[REPEAT_COUNT [greater than 0]\n"); + printf("\t[SLEEP_LENGTH [greater than 0]\n"); + printf("\t[RELATION_ID [greater than 0]\n"); + + + + return -1; + } + + PROCESS_COUNT = atoi(argv[1]); + if( (PROCESS_COUNT < 1) || (PROCESS_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 1 and less than PROCESS_COUNT %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + SLEEP_LENGTH = atoi(argv[4]); + if( SLEEP_LENGTH < 1) + { + printf("\nMain Process:Invalid SLEEP_LENGTH number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[5]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hProcess[MAXIMUM_WAIT_OBJECTS]; + + STARTUPINFO si[MAXIMUM_WAIT_OBJECTS]; + PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS]; + + char lpCommandLine[MAX_PATH] = ""; + + int returnCode = 0; + DWORD processReturnCode = 0; + int testReturnCode = PASS; + + char fileName[MAX_PATH]; + FILE *pFile = NULL; + DWORD dwStartTime; + struct TestStats testStats; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } + + /* Register the start time */ + dwStartTime = GetTickCount(); + testStats.relationId = 0; + testStats.relationId = RELATION_ID; + testStats.processCount = PROCESS_COUNT; + testStats.threadCount = THREAD_COUNT; + testStats.repeatCount = REPEAT_COUNT; + testStats.buildNumber = getBuildNumber(); + + + + _snprintf(fileName, MAX_PATH, "main_wfmo_%d_.txt",testStats.relationId); + pFile = fopen(fileName, "w+"); + if(pFile == NULL) + { + Fail("Error in opening main file for write\n"); + } + + for( i = 0; i < PROCESS_COUNT; i++ ) + { + + ZeroMemory( lpCommandLine, MAX_PATH ); + if ( _snprintf( lpCommandLine, MAX_PATH-1, "mutex %d %d %d %d %d", i, THREAD_COUNT, REPEAT_COUNT, SLEEP_LENGTH, RELATION_ID) < 0 ) + { + Trace ("Error: Insufficient commandline string length for for iteration [%d]\n", i); + } + + /* Zero the data structure space */ + ZeroMemory ( &pi[i], sizeof(pi[i]) ); + ZeroMemory ( &si[i], sizeof(si[i]) ); + + /* Set the process flags and standard io handles */ + si[i].cb = sizeof(si[i]); + + //Create Process + if(!CreateProcess( NULL, /* lpApplicationName*/ + lpCommandLine, /* lpCommandLine */ + NULL, /* lpProcessAttributes */ + NULL, /* lpThreadAttributes */ + TRUE, /* bInheritHandles */ + 0, /* dwCreationFlags, */ + NULL, /* lpEnvironment */ + NULL, /* pCurrentDirectory */ + &si[i], /* lpStartupInfo */ + &pi[i] /* lpProcessInformation */ + )) + { + Fail("Process Not created for [%d], the error code is [%d]\n", i, GetLastError()); + } + else + { + hProcess[i] = pi[i].hProcess; + // Trace("Process created for [%d]\n", i); + } + + } + + returnCode = WaitForMultipleObjects( PROCESS_COUNT, hProcess, TRUE, INFINITE); + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", PROCESS_COUNT, returnCode, GetLastError()); + } + + for( i = 0; i < PROCESS_COUNT; i++ ) + { + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) ) + { + Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n", + i, GetLastError() ); + + testReturnCode = FAIL; + } + + if(processReturnCode == FAIL) + { + Trace( "Process [%d] failed and returned FAIL\n", i); + testReturnCode = FAIL; + } + + if(!CloseHandle(pi[i].hThread)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i); + } + + if(!CloseHandle(pi[i].hProcess) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i); + } + } + + testStats.operationTime = GetTimeDiff(dwStartTime); + fprintf(pFile, "%d,%d,%d,%d,%d,%s\n", testStats.operationTime, testStats.relationId, testStats.processCount, testStats.threadCount, testStats.repeatCount, testStats.buildNumber); + if(fclose(pFile)) + { + Trace("Error: fclose failed for pFile\n"); + testReturnCode = FAIL; + } + + if( testReturnCode == PASS) + { + Trace("Test Passed\n"); + } + else + { + Trace("Test Failed\n"); + } + PAL_Terminate(); + return testReturnCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/mutex.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/mutex.cpp new file mode 100644 index 0000000..c8ed014 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/mutex.cpp @@ -0,0 +1,365 @@ +// 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. + +/*============================================================ +**Source Code: main.c and mutex.c +** main.c creates process and waits for all processes to get over +** mutex.c creates a mutex and then calls threads which will +** contend for the mutex +** +** This test is for WFMO Test case for Mutex +** Algorithm +** o Create PROCESS_COUNT processes. +** o Main Thread of each process creates OBJECT_TYPE Object +** +** Author: ShamitP +** +** +**============================================================ +*/ + +#include +#include "resultbuffer.h" +#include "resulttime.h" + +/* Test Input Variables */ +unsigned int USE_PROCESS_COUNT = 0; +unsigned int THREAD_COUNT = 0; +unsigned int REPEAT_COUNT = 0; +unsigned int SLEEP_LENGTH = 0; +unsigned int RELATION_ID = 1001; + + +/* Capture statistics at per thread basis */ +struct statistics{ + unsigned int processId; + unsigned int operationsFailed; + unsigned int operationsPassed; + unsigned int operationsTotal; + DWORD operationTime; + unsigned int relationId; + +}; + +struct ProcessStats{ + unsigned int processId; + DWORD operationTime; + unsigned int relationId; +}; + +/* Handle to signal threads to start the tests */ +HANDLE StartTestsEvHandle = NULL; +/* Handle to mutex which will be contended by threads */ +HANDLE hMutexHandle = NULL; +/* Results Buffer */ +ResultBuffer *resultBuffer = NULL; + +int testStatus; + +void PALAPI Run_Thread(LPVOID lpParam); + +int GetParameters( int argc, char **argv) +{ + if( (argc != 6) || ((argc == 1) && !strcmp(argv[1],"/?")) + || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) + { + printf("PAL -Composite WFMO Test\n"); + printf("Usage:\n"); + printf("mutex\n\t[USE_PROCESS_COUNT [greater than 0] \n"); + printf("\t[THREAD_COUNT [greater than 0] \n"); + printf("\t[REPEAT_COUNT [greater than 0]\n"); + printf("\t[SLEEP_LENGTH [greater than 0]\n"); + printf("\t[RELATION_ID [greater than 0]\n"); + + + return -1; + } + + // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]); + + USE_PROCESS_COUNT = atoi(argv[1]); + if( USE_PROCESS_COUNT < 0) + { + printf("\nInvalid USE_PROCESS_COUNT number, Pass greater than 1\n"); + return -1; + } + + THREAD_COUNT = atoi(argv[2]); + if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) ) + { + printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS); + return -1; + } + + REPEAT_COUNT = atoi(argv[3]); + if( REPEAT_COUNT < 1) + { + printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n"); + return -1; + } + + SLEEP_LENGTH = atoi(argv[4]); + if( SLEEP_LENGTH < 1) + { + printf("\nMain Process:Invalid SLEEP_LENGTH number, Pass greater than 1\n"); + return -1; + } + + RELATION_ID = atoi(argv[5]); + if( RELATION_ID < 1) + { + printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); + return -1; + } + + return 0; +} + + int __cdecl main(INT argc, CHAR **argv) +{ + unsigned int i = 0; + HANDLE hThread[MAXIMUM_WAIT_OBJECTS]; + DWORD threadId[MAXIMUM_WAIT_OBJECTS]; + int returnCode = 0; + + DWORD dwParam = 0; + + /* Variables to capture the file name and the file pointer at thread level*/ + char fileName[MAX_PATH]; + FILE *pFile = NULL; + struct statistics* buffer = NULL; + int statisticsSize = 0; + + /* Variables to capture the file name and the file pointer at process level*/ + char processFileName[MAX_PATH]; + FILE *pProcessFile = NULL; + struct ProcessStats processStats; + DWORD dwStartTime; + + testStatus = PASS; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(GetParameters(argc, argv)) + { + Fail("Error in obtaining the parameters\n"); + } +// Trace("Process created, value of process count is [%d] and no. of threads is [%d]\n", USE_PROCESS_COUNT, THREAD_COUNT); + + /* Register the start time */ + dwStartTime = GetTickCount(); + processStats.relationId = RELATION_ID; + processStats.processId = USE_PROCESS_COUNT; + + _snprintf(processFileName, MAX_PATH, "%d_process_wfmo_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); + pProcessFile = fopen(processFileName, "w+"); + if(pProcessFile == NULL) + { + Fail("Error:%d: in opening Process File for write for process [%d]\n", GetLastError(), USE_PROCESS_COUNT); + } + + statisticsSize = sizeof(struct statistics); + + _snprintf(fileName, MAX_PATH, "%d_thread_wfmo_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); + pFile = fopen(fileName, "w+"); + if(pFile == NULL) + { + Fail("Error in opening file for write for process [%d], error [%d]\n", USE_PROCESS_COUNT, GetLastError()); + } + // For each thread we will log operations failed (int), passed (int), total (int) + // and number of ticks (DWORD) for the operations + resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize); + + StartTestsEvHandle = CreateEvent( NULL, /* lpEventAttributes*/ + TRUE, /* bManualReset */ + FALSE, /* bInitialState */ + NULL); /* name of Event */ + + if( StartTestsEvHandle == NULL ) + { + Fail("Error:%d: Unexpected failure " + "to create start tests Event for process count %d\n", GetLastError(), USE_PROCESS_COUNT ); + + } + + /* Create StartTest Event */ + hMutexHandle = CreateMutex( + NULL, + FALSE, /* bInitialOwner, owns initially */ + NULL + ); + + if( hMutexHandle == NULL) + { + Fail("Unable to create Mutex handle for process id [%d], returned error [%d]\n", i, GetLastError()); + } + + /* We already assume that the mutex was created previously*/ + for( i = 0; i < THREAD_COUNT; i++ ) + { + dwParam = (int) i; + //Create thread + hThread[i] = CreateThread( + NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */ + (LPVOID)dwParam, /* argument to thread function */ + 0, /* use default creation flags */ + &threadId[i] /* returns the thread identifier*/ + ); + + if(hThread[i] == NULL) + { + Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError()); + } + + } + + if (!SetEvent(StartTestsEvHandle)) + { + Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError()); + } + /* Test running */ + + if( THREAD_COUNT != 1 ) + { + returnCode = WaitForMultipleObjects(THREAD_COUNT, hThread, TRUE, INFINITE); + } + else + { + returnCode = WaitForSingleObject(hThread[0], INFINITE); + } + + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError()); + testStatus = FAIL; + } + + processStats.operationTime = GetTimeDiff(dwStartTime); + + /* Write to a file*/ + if(pFile!= NULL) + { + for( i = 0; i < THREAD_COUNT; i++ ) + { + buffer = (struct statistics *)resultBuffer->getResultBuffer(i); + returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); + //Trace("Iteration %d over\n", i); + + } + } + if(fclose(pFile)) + { + Trace("Error: fclose failed for pFile at Process %d\n", USE_PROCESS_COUNT); + testStatus = FAIL; + } + + fprintf(pProcessFile, "%d,%d,%d\n", USE_PROCESS_COUNT, processStats.operationTime, processStats.relationId ); + if(fclose(pProcessFile)) + { + Trace("Error: fclose failed for pProcessFile at Process %d\n", USE_PROCESS_COUNT); + testStatus = FAIL; + } + + /* Logging for the test case over, clean up the handles */ + // Trace("Test Process %d done\n", USE_PROCESS_COUNT); + //Trace("Contents of the buffer are [%s]\n", resultBuffer->getResultBuffer()); + for( i = 0; i < THREAD_COUNT; i++ ) + { + if(!CloseHandle(hThread[i]) ) + { + Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i); + testStatus = FAIL; + } + } + + if(!CloseHandle(StartTestsEvHandle)) + { + Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT); + testStatus = FAIL; + } + + PAL_Terminate(); + return testStatus; +} + +void PALAPI Run_Thread (LPVOID lpParam) +{ + unsigned int i = 0; + struct statistics stats; + + DWORD dwWaitResult; + DWORD dwStartTime; + + stats.relationId = RELATION_ID; + stats.processId = USE_PROCESS_COUNT; + stats.operationsFailed = 0; + stats.operationsPassed = 0; + stats.operationsTotal = 0; + stats.operationTime = 0; + + int Id=(int)lpParam; + + dwWaitResult = WaitForSingleObject( + StartTestsEvHandle, // handle to mutex + INFINITE); + + if(dwWaitResult != WAIT_OBJECT_0) + { + Trace("Error:%d: while waiting for StartTest Event@ thread %d\n", GetLastError(), Id); + testStatus = FAIL; + } + + /* Register the start time */ + dwStartTime = GetTickCount(); + + /* Run the tests repeat count times */ + for( i = 0; i < REPEAT_COUNT; i++ ) + { + dwWaitResult = WaitForSingleObject( + hMutexHandle, // handle to mutex + INFINITE); + + if(dwWaitResult != WAIT_OBJECT_0) + { + Trace("Error:%d: while waiting for onject @ thread %d, # iter %d\n", GetLastError(), Id, i); + stats.operationsFailed += 1; + stats.operationsTotal += 1; + testStatus = FAIL; + continue; + } + + Sleep(SLEEP_LENGTH); + + if (!ReleaseMutex(hMutexHandle)) + { + // Deal with error. + Trace("Error:%d: while releasing mutex @ thread %d # iter %d\n", GetLastError(), Id, i); + stats.operationsFailed += 1; + stats.operationsTotal += 1; + // do we need to have while true loop to attempt to release mutex...? + testStatus = FAIL; + continue; + } + + stats.operationsTotal += 1; + stats.operationsPassed += 1; + +// Trace("Successs while releasing mutex @ iteration %d -> thread %d -> Process %d\n", i, Id, USE_PROCESS_COUNT); + + } + + stats.operationTime = GetTimeDiff(dwStartTime); + // Trace("Operation Time %lu, Process Count [%d], ThreadCount[%d]\n", stats.operationTime, USE_PROCESS_COUNT, Id); + + if(resultBuffer->LogResult(Id, (char *)&stats)) + { + Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT); + } + // Trace("Contents of the buffer are after thread [%d]\n", Id); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/readme.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/readme.txt new file mode 100644 index 0000000..6be55d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/composite/wfmo/readme.txt @@ -0,0 +1,22 @@ +To compile: + +1) create a dat file (say wfmo.dat) with contents: +PAL,Composite,palsuite\composite\wfmo,wfmo=main.c mutex.c,,, + +2) perl rrunmod.pl -r wfmo.dat + + +To execute: +main [PROCESS_COUNT] [THREAD_COUNT] [REPEAT_COUNT] [SLEEP_LENGTH] + +Output: +The performance numbers will be in _wfmo.txt +(will be at palsuite\composite\wfmo\obj[r|c|d] directory if u use rrunmod.pl) + +So if process_count is 3, you will have files 0_wfmo.txt, 1_wfmo.txt and so on… + +For each process txt file created, +each row represents a thread data (process id, number of failures, number of pass, total number of repeated operations and an integer that will be used to identify a run +(currently zero)). + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/CMakeLists.txt new file mode 100644 index 0000000..62493c1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/CMakeLists.txt @@ -0,0 +1,7 @@ +# TODO: make these tests compile +# add_subdirectory(DebugBreak) +# add_subdirectory(WriteProcessMemory) + +add_subdirectory(OutputDebugStringA) +add_subdirectory(OutputDebugStringW) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/test1/CMakeLists.txt new file mode 100644 index 0000000..0614c48 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_debugbreak_test1 + ${SOURCES} +) + +add_dependencies(paltest_debugbreak_test1 coreclrpal) + +target_link_libraries(paltest_debugbreak_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/test1/test1.cpp new file mode 100644 index 0000000..2b10b9a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/test1/test1.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================= +** +** Source: test1.c +** +** Purpose: Tests that DebugBreak works in the grossest fashion. +** +** +**============================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bTry = FALSE; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + PAL_TRY + { + DebugBreak(); + if (!bTry) + { + Fail("DebugBreak: Continued in Try block.\n"); + } + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + bTry = TRUE; + } + PAL_ENDTRY; + + if (!bTry) + { + Fail("DebugBreak: Did not reach the exception block.\n"); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/test1/testinfo.dat new file mode 100644 index 0000000..25c480e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/DebugBreak/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Debug +Function = DebugBreak +Name = DebugBreak test #1 +TYPE = DEFAULT +EXE1 = test1 +Description += Tests that DebugBreak "works". This will require case by case += manual interpretation. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/CMakeLists.txt new file mode 100644 index 0000000..20b49a0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/CMakeLists.txt @@ -0,0 +1,30 @@ +set(TESTSOURCES + test1.cpp +) + +add_executable(paltest_outputdebugstringa_test1 + ${TESTSOURCES} +) + +add_dependencies(paltest_outputdebugstringa_test1 coreclrpal) + +target_link_libraries(paltest_outputdebugstringa_test1 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + helper.cpp +) + +add_executable(paltest_outputdebugstringa_test1_helper + ${HELPERSOURCES} +) + +add_dependencies(paltest_outputdebugstringa_test1_helper coreclrpal) + +target_link_libraries(paltest_outputdebugstringa_test1_helper + ${COMMON_TEST_LIBRARIES} +) + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/helper.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/helper.cpp new file mode 100644 index 0000000..90073df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/helper.cpp @@ -0,0 +1,35 @@ +// 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. + +/*============================================================= +** +** Source: helper.c +** +** Purpose: Intended to be the child process of a debugger. Calls +** OutputDebugStringA once with a normal string, once with an empty +** string +** +** +**============================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + OutputDebugStringA("Foo!\n"); + + OutputDebugStringA(""); + + /* give a chance to the debugger process to read the debug string before + exiting */ + Sleep(1000); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/test1.cpp new file mode 100644 index 0000000..080c6ac --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/test1.cpp @@ -0,0 +1,94 @@ +// 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. + +/*============================================================= +** +** Source: test1.c +** +** Purpose: Debugs the helper application. Checks that certain events, in +** particular the OUTPUT_DEBUG_STRING_EVENT, is generated correctly +** and gives the correct values. +** +** +**============================================================*/ + +#include + +const int DELAY_MS = 2000; + +struct OutputCheck +{ + DWORD ExpectedEventCode; + DWORD ExpectedUnicode; + char *ExpectedStr; +}; + +int __cdecl main(int argc, char *argv[]) +{ + + PROCESS_INFORMATION pi; + STARTUPINFO si; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + /* Create a new process. This is the process to be Debugged */ + if(!CreateProcess( NULL, "helper", NULL, NULL, + FALSE, 0, NULL, NULL, &si, &pi)) + { + Fail("ERROR: CreateProcess failed to load executable 'helper'. " + "GetLastError() returned %d.\n",GetLastError()); + } + + /* This is the main loop. It exits when the process which is being + debugged is finished executing. + */ + + while(1) + { + DWORD dwRet = 0; + dwRet = WaitForSingleObject(pi.hProcess, + DELAY_MS /* Wait for 2 seconds max*/ + ); + + if (dwRet != WAIT_OBJECT_0) + { + Trace("WaitForSingleObjectTest:WaitForSingleObject " + "failed (%x) after waiting %d seconds for the helper\n", + GetLastError(), DELAY_MS / 1000); + } + else + { + DWORD dwExitCode; + + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) + { + DWORD dwError; + + dwError = GetLastError(); + CloseHandle ( pi.hProcess ); + CloseHandle ( pi.hThread ); + Fail( "GetExitCodeProcess call failed with error code %d\n", + dwError ); + } + + if(dwExitCode != STILL_ACTIVE) { + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + break; + } + Trace("still executing %d..\n", dwExitCode); + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/testinfo.dat new file mode 100644 index 0000000..d49e904 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Debug +Function = OutputDebugStringA +Name = OutputDebugStringA test #1 +TYPE = DEFAULT +EXE1 = test1 +EXE2 = helper +Description +=Tests that OutputDebugString generates the correct debugging event behaviour. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/CMakeLists.txt new file mode 100644 index 0000000..c23befa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_outputdebugstringw_test1 + ${SOURCES} +) + +add_dependencies(paltest_outputdebugstringw_test1 coreclrpal) + +target_link_libraries(paltest_outputdebugstringw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/test1.cpp new file mode 100644 index 0000000..88b5542 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/test1.cpp @@ -0,0 +1,41 @@ +// 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. + +/*============================================================= +** +** Source: test1.c +** +** Purpose: Intended to be the child process of a debugger. Calls +** OutputDebugStringW once with a normal string, once with an empty +** string +** +** +**============================================================*/ + +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR *str1; + WCHAR *str2; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + str1 = convert("Foo!"); + str2 = convert(""); + + OutputDebugStringW(str1); + + OutputDebugStringW(str2); + + free(str1); + free(str2); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/testinfo.dat new file mode 100644 index 0000000..d6bc4ac --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = Debug +Function = OutputDebugStringW +Name = OutputDebugStringW test #1 +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests that OutputDebugString generates the correct debugging event behaviour. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/CMakeLists.txt new file mode 100644 index 0000000..dd5da44 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test3) +add_subdirectory(test4) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/CMakeLists.txt new file mode 100644 index 0000000..e2d9766 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + test1.cpp +) + +add_executable(paltest_writeprocessmemory_test1 + ${TESTSOURCES} +) + +add_dependencies(paltest_writeprocessmemory_test1 coreclrpal) + +target_link_libraries(paltest_writeprocessmemory_test1 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + helper.cpp +) + +add_executable(paltest_writeprocessmemory_test1_helper + ${HELPERSOURCES} +) + +add_dependencies(paltest_writeprocessmemory_test1_helper coreclrpal) + +target_link_libraries(paltest_writeprocessmemory_test1_helper + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/commonconsts.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/commonconsts.h new file mode 100644 index 0000000..eb7d511 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/commonconsts.h @@ -0,0 +1,46 @@ +// 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. + +/*============================================================= +** +** Source: commonconsts.h +** +** +**============================================================*/ + +#ifndef _COMMONCONSTS_H_ +#define _COMMONCONSTS_H_ + +#include + +const int TIMEOUT = 40000; + +const WCHAR szcToHelperEvName[] = { 'T', 'o', '\0' }; +const WCHAR szcFromHelperEvName[] = { 'F', 'r', 'o', 'm', '\0' }; + +const char initialValue = '-'; +const char nextValue = '|'; +const char guardValue = '*'; +const char *commsFileName = "AddrNLen.dat"; + +/* PEDANTIC and PEDANTIC0 is a helper macro that just grumps about any + * zero return codes in a generic way. with little typing */ +#define PEDANTIC(function, parameters) \ +{ \ + if (! (function parameters) ) \ + { \ + Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \ + __FILE__, #function, #parameters, GetLastError(), errno); \ + } \ +} +#define PEDANTIC1(function, parameters) \ +{ \ + if ( (function parameters) ) \ + { \ + Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \ + __FILE__, #function, #parameters, GetLastError(), errno); \ + } \ +} + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.cpp new file mode 100644 index 0000000..d965ca7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.cpp @@ -0,0 +1,243 @@ +// 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. + +/*============================================================= +** +** Source: helper.c +** +** Purpose: This helper process sets up a several blocks of memory, +** then uses a file to tell its parent process where that memory is +** So it can do a WriteProcessMemory on it. When the parent process is done +** we check here that it was written properly. +** +** +**============================================================*/ + +#include "commonconsts.h" + +#include + +struct allhandles_t +{ + HANDLE hEvToHelper; + HANDLE hEvFromHelper; + char *valuesFileName; +}; + + +/* function: wpmDoIt + * + * This is a general WriteProcessMemory testing function that sets up + * the RAM pointed to and tells the companion process on the other end + * of the handles in 'Comms' to attempt to alter 'lenDest' bytes at + * '*pDest'. + * + * '*pBuffer'[0..'lenBuffer'] is expected to be a guard region + * surrounding the '*pDest'[0..'lenDest'] region so that this function + * can verify that only the proper bytes were altered. + */ + +int wpmDoIt(struct allhandles_t Comms, + char * pBuffer, unsigned int lenBuffer, + char * pDest, unsigned int lenDest, + const char* storageDescription) +{ + char *pCurr; + FILE *commsFile; + DWORD dwRet; + + if (pBuffer > pDest || lenDest > lenBuffer) + { + Trace("WriteProcessMemory::DoIt() test implementation: " + "(pBuffer > pDest || lenDest > lenBuffer)\n"); + return FALSE; + } + + /* set up the storage */ + memset(pBuffer, guardValue, lenBuffer); + memset(pDest, initialValue, lenDest); + + /* tell the parent what RAM to adjust */ + if(!(commsFile = fopen(Comms.valuesFileName, "w"))) + { + Trace("WriteProcessMemory: fopen of '%S' failed (%u). \n", + Comms.valuesFileName, GetLastError()); + return FALSE; + } + if (!fprintf(commsFile, "%u %u '%s'\n", + pDest, lenDest, storageDescription)) + { + Trace("WriteProcessMemory: fprintf to '%S' failed (%u). \n", + Comms.valuesFileName, GetLastError()); + return FALSE; + } + PEDANTIC1(fclose, (commsFile)); + + /* Tell the parent the data is ready for it to adjust */ + PEDANTIC(ResetEvent, (Comms.hEvToHelper)); + PEDANTIC(SetEvent, (Comms.hEvFromHelper)); + + dwRet = WaitForSingleObject(Comms.hEvToHelper, TIMEOUT); /* parent is done */ + if (dwRet != WAIT_OBJECT_0) + { + Trace("helper WaitForSingleObjectTest: WaitForSingleObject " + "failed (%u)\n", GetLastError()); + return FALSE; + } + + /* check the stuff that SHOULD have changed */ + for (pCurr = pDest; pCurr < (pDest + lenDest); pCurr++) + { + if ( *pCurr != nextValue) + { + Trace("When testing '%s': alteration test failed " + "at %u offset %u. Found '%c' instead of '%c'\n.", + storageDescription, pDest, pCurr - pDest, *pCurr, nextValue); + Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); + return FALSE; + } + } + /* check the stuff that should NOT have changed */ + for (pCurr = pBuffer; pCurr < pDest; pCurr++ ) + { + if ( *pCurr != guardValue) + { + Trace("When testing '%s': leading guard zone test failed " + "at %u offset %u. Found '%c' instead of '%c'\n.", + storageDescription, pDest, pCurr - pBuffer, *pCurr, guardValue); + Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); + return FALSE; + } + } + for (pCurr = pDest + lenDest; pCurr < (pBuffer + lenBuffer); pCurr++ ) + { + if ( *pCurr != guardValue) + { + Trace("When testing '%s': trailing guard zone test failed " + "at %u offset %u. Found '%c' instead of '%c'\n.", + storageDescription, pDest + lenDest, pCurr - pBuffer, *pCurr, guardValue); + Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); + return FALSE; + } + } + + return TRUE; +} + +int __cdecl main(int argc, char *argv[]) +{ + + BOOL success = TRUE; /* assume success */ + struct allhandles_t Comms = {0,0,0} ; + + /* variables to track storage to alter */ + char *pTarget = NULL; + unsigned int sizeTarget; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* hook up with the events created by the parent */ + Comms.hEvToHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcToHelperEvName); + if (!Comms.hEvToHelper) + { + Fail("WriteProcessMemory: OpenEvent of '%S' failed (%u). " + "(the event should already exist!)\n", + szcToHelperEvName, GetLastError()); + } + Comms.hEvFromHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcFromHelperEvName); + if (!Comms.hEvToHelper) + { + Trace("WriteProcessMemory: OpenEvent of '%S' failed (%u). " + "(the event should already exist!)\n", + szcFromHelperEvName, GetLastError()); + success = FALSE; + goto EXIT; + } + Comms.valuesFileName = argv[1]; + + { + char autoAllocatedOnStack[51]; + + /* Get the parent process to write to the local stack */ + success &= wpmDoIt(Comms, autoAllocatedOnStack, + sizeof(autoAllocatedOnStack), + autoAllocatedOnStack + sizeof(int), + sizeof(autoAllocatedOnStack) - 2 * sizeof(int), + "const size array on stack with int sized guards"); + } + + /* Get the parent process to write to stuff on the heap */ + sizeTarget = 2 * sizeof(int) + 23 ; /* 23 is just a random prime > 16 */ + if (!(pTarget = (char*)malloc(sizeTarget))) + { + Trace("WriteProcessMemory helper: unable to allocate '%s'->%d bytes of memory" + "(%u).\n", + argv[3], sizeTarget, GetLastError()); + success = FALSE; + goto EXIT; + + } + success &= wpmDoIt(Comms, pTarget, sizeTarget, + pTarget + sizeof(int), + sizeTarget - 2 * sizeof(int), + "array on heap with int sized guards"); + + /* just to be nice try something 16 - 2 * sizeof(int) bytes long */ + { + char autoAllocatedOnStack[16]; + + /* Get the parent process to write to the local stack */ + success &= wpmDoIt(Comms, autoAllocatedOnStack, + sizeof(autoAllocatedOnStack), + autoAllocatedOnStack + sizeof(int), + sizeof(autoAllocatedOnStack) - 2 * sizeof(int), + "another 16 byte array on stack with int sized guards inside"); + } + + /* NOTE: Don't try 0 bytes long. Win32 WriteProcessMemory claims + * it writes 8 bytes in that case! */ + + /* and 1 byte long... */ + { + char autoAllocatedOnStack[1+ 2 * sizeof(int)]; + + /* Get the parent process to write to the local stack */ + success &= wpmDoIt(Comms, autoAllocatedOnStack, + sizeof(autoAllocatedOnStack), + autoAllocatedOnStack + sizeof(int), + 1, + "no bytes with int sized guards outside on stack"); + } + + +EXIT: + /* Tell the parent that we are done */ + if (!DeleteFile(Comms.valuesFileName)) + { + Trace("helper: DeleteFile failed so parent (test1) is unlikely " + "to exit cleanly\n"); + } + PEDANTIC(ResetEvent, (Comms.hEvToHelper)); + if (!SetEvent(Comms.hEvFromHelper)) + { + Trace("helper: SetEvent failed so parent (test1) is unlikely " + "to exit cleanly\n"); + } + + free(pTarget); + PEDANTIC(CloseHandle, (Comms.hEvToHelper)); + PEDANTIC(CloseHandle, (Comms.hEvFromHelper)); + + if (!success) + { + Fail(""); + } + + PAL_Terminate(); + + return success ? PASS : FAIL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.cpp new file mode 100644 index 0000000..f390c10 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.cpp @@ -0,0 +1,189 @@ +// 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. + +/*============================================================= +** +** Source: test1.c +** +** Purpose: Create a child process and some events for communications with it. +** When the child gets back to us with a memory location and a length, +** Call WriteProcessMemory on this location and check to see that it +** writes successfully. +** +** +**============================================================*/ + +#define UNICODE + +#include "commonconsts.h" + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + PROCESS_INFORMATION pi; + STARTUPINFO si; + HANDLE hEvToHelper; + HANDLE hEvFromHelper; + DWORD dwExitCode; + + + DWORD dwRet; + char cmdComposeBuf[MAX_PATH]; + PWCHAR uniString; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Create the signals we need for cross process communication */ + hEvToHelper = CreateEvent(NULL, TRUE, FALSE, szcToHelperEvName); + if (!hEvToHelper) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "GetLastError() returned %d.\n", szcToHelperEvName, + GetLastError()); + } + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "(already exists!)\n", szcToHelperEvName); + } + hEvFromHelper = CreateEvent(NULL, TRUE, FALSE, szcFromHelperEvName); + if (!hEvToHelper) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "GetLastError() returned %d.\n", szcFromHelperEvName, + GetLastError()); + } + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "(already exists!)\n", szcFromHelperEvName); + } + ResetEvent(hEvFromHelper); + ResetEvent(hEvToHelper); + + if (!sprintf_s(cmdComposeBuf, _countof(cmdComposeBuf), "helper %s", commsFileName)) + { + Fail("Could not convert command line\n"); + } + uniString = convert(cmdComposeBuf); + + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + /* Create a new process. This is the process that will ask for + * memory munging */ + if(!CreateProcess( NULL, uniString, NULL, NULL, + FALSE, 0, NULL, NULL, &si, &pi)) + { + Trace("ERROR: CreateProcess failed to load executable '%S'. " + "GetLastError() returned %u.\n", + uniString, GetLastError()); + free(uniString); + Fail(""); + } + free(uniString); + + while(1) + { + FILE *commsFile; + char* pSrcMemory; + char* pDestMemory; + int Count; + SIZE_T wpmCount; + char incomingCMDBuffer[MAX_PATH + 1]; + + /* wait until the helper tells us that it has given us + * something to do */ + dwRet = WaitForSingleObject(hEvFromHelper, TIMEOUT); + if (dwRet != WAIT_OBJECT_0) + { + Trace("test1 WaitForSingleObjectTest: WaitForSingleObject " + "failed (%u)\n", GetLastError()); + break; /* no more work incoming */ + } + + /* get the parameters to test WriteProcessMemory with */ + if (!(commsFile = fopen(commsFileName, "r"))) + { + /* no file means there is no more work */ + break; + } + if ( NULL == fgets(incomingCMDBuffer, MAX_PATH, commsFile)) + { + Fail ("unable to read from communication file %s " + "for reasons %u & %u\n", + errno, GetLastError()); + } + PEDANTIC1(fclose,(commsFile)); + sscanf(incomingCMDBuffer, "%u %u", &pDestMemory, &Count); + if (argc > 1) + { + Trace("Preparing to write to %u bytes @ %u ('%s')\n", + Count, pDestMemory, incomingCMDBuffer); + } + + /* compose some data to write to the client process */ + if (!(pSrcMemory = (char*)malloc(Count))) + { + Trace("could not dynamically allocate memory to copy from " + "for reasons %u & %u\n", + errno, GetLastError()); + goto doneIteration; + } + memset(pSrcMemory, nextValue, Count); + + /* do the work */ + dwRet = WriteProcessMemory(pi.hProcess, + pDestMemory, + pSrcMemory, + Count, + &wpmCount); + if (!dwRet) + { + Trace("%s: Problem: on a write to %u bytes @ %u ('%s')\n", + argv[0], Count, pDestMemory, incomingCMDBuffer); + Trace("test1 WriteProcessMemory returned a%u(!=0) (GLE=%u)\n", + GetLastError()); + } + if(Count != wpmCount) + { + Trace("%s: Problem: on a write to %u bytes @ %u ('%s')\n", + argv[0], Count, pDestMemory, incomingCMDBuffer); + Trace("The number of bytes written should have been " + "%u, but was reported as %u.\n", Count, wpmCount); + } + free(pSrcMemory); + + doneIteration: + PEDANTIC(ResetEvent, (hEvFromHelper)); + PEDANTIC(SetEvent, (hEvToHelper)); + } + + /* wait for the child process to complete */ + WaitForSingleObject ( pi.hProcess, TIMEOUT ); + /* this may return a failure code on a success path */ + + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) + { + Trace( "GetExitCodeProcess call failed with error code %u\n", + GetLastError() ); + dwExitCode = FAIL; + } + + + PEDANTIC(CloseHandle, (hEvToHelper)); + PEDANTIC(CloseHandle, (hEvFromHelper)); + PEDANTIC(CloseHandle, (pi.hThread)); + PEDANTIC(CloseHandle, (pi.hProcess)); + + PAL_TerminateEx(dwExitCode); + return dwExitCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/testinfo.dat new file mode 100644 index 0000000..0946f8f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Debug +Function = WriteProcessMemory +Name = Check that writing text to process memory succeeds. +TYPE = DEFAULT +EXE1 = test1 +EXE2 = helper +Description += Create a child process and attempt to write to its memory += at the places and lengths it specifies via a data file. += the child verifies that all the specified memory was altered += with no overruns. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/CMakeLists.txt new file mode 100644 index 0000000..4c8364d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + test3.cpp +) + +add_executable(paltest_writeprocessmemory_test3 + ${TESTSOURCES} +) + +add_dependencies(paltest_writeprocessmemory_test3 coreclrpal) + +target_link_libraries(paltest_writeprocessmemory_test3 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + helper.cpp +) + +add_executable(paltest_writeprocessmemory_test3_helper + ${HELPERSOURCES} +) + +add_dependencies(paltest_writeprocessmemory_test3_helper coreclrpal) + +target_link_libraries(paltest_writeprocessmemory_test3_helper + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/commonconsts.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/commonconsts.h new file mode 100644 index 0000000..c1cec18 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/commonconsts.h @@ -0,0 +1,50 @@ +// 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. + +/*============================================================= +** +** Header: commonconsts.h +** +** +==============================================================*/ + +#ifndef _COMMONCONSTS_H_ +#define _COMMONCONSTS_H_ + +#include + +const int TIMEOUT = 40000; + +const WCHAR szcToHelperEvName[] = { 'T', 'o', '\0' }; +const WCHAR szcFromHelperEvName[] = { 'F', 'r', 'o', 'm', '\0' }; + +const char initialValue = '-'; +const char nextValue = '|'; +const char guardValue = '*'; +const char *commsFileName = "AddrNLen.dat"; + +/* PEDANTIC and PEDANTIC0 is a helper macro that just grumps about any + * zero return codes in a generic way. with little typing */ +#define PEDANTIC(function, parameters) \ +{ \ + unsigned int retval = (function parameters); \ + if ( !retval ) \ + { \ + Trace("%s: NonFatal failure of %s%s (returned %u) " \ + "for reasons %u and %u.\n", \ + __FILE__, #function, #parameters, retval, GetLastError(), errno); \ + } \ +} +#define PEDANTIC1(function, parameters) \ +{ \ + unsigned int retval = (function parameters); \ + if ( retval ) \ + { \ + Trace("%s: NonFatal failure of %s%s (returned %u) " \ + "for reasons %u and %u\n", \ + __FILE__, #function, #parameters, retval, GetLastError(), errno); \ + } \ +} + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/helper.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/helper.cpp new file mode 100644 index 0000000..170e206 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/helper.cpp @@ -0,0 +1,256 @@ +// 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. + +/*============================================================= +** +** Source: helper.c + +** +==============================================================*/ + + +/* +** +** Purpose: This helper process sets up a several blocks of memory +** that should be unwritable from the parent process, then uses a file +** to tell its parent process where that memory is so it can attempt a +** WriteProcessMemory on it. When the parent process is done we check +** here that it was (properly) unable to change the contents of the +** memory. +*/ + +#include "commonconsts.h" + +#include + +struct allhandles_t +{ + HANDLE hEvToHelper; + HANDLE hEvFromHelper; + char *valuesFileName; +}; + + +/* function: wpmVerifyCant + * + * This is a general WriteProcessMemory testing function that sets up + * the RAM pointed to and tells the companion process on the other end + * of the handles in 'Comms' to attempt to alter 'lenDest' bytes at + * '*pDest'. + * + * However, the memory at pDest[0..lenDest] is expected to be unwritable by + * the companion process. The companion is expects this. This function + * verifies that no bytes were affected + */ + +int wpmVerifyCant(struct allhandles_t Comms, + char * pDest, unsigned int lenDest, + unsigned int lenLegitDest, + DWORD dwExpectedErrorCode, + const char* storageDescription) +{ + char *pCurr; + FILE *commsFile; + DWORD dwRet; + + unsigned int lenSafe = min(lenDest, lenLegitDest); + + PAL_TRY + { + memset(pDest, initialValue, lenSafe); + } + PAL_EXCEPT_EX (setup, EXCEPTION_EXECUTE_HANDLER) + { + Trace("WriteProcessMemory: bug in test values for '%s' (%p, %u, %u), " + "the initial memset threw an exception.\n", + storageDescription, pDest, lenDest, lenSafe); + } + PAL_ENDTRY; + + /* tell the parent what RAM to attempt to adjust */ + if(!(commsFile = fopen(Comms.valuesFileName, "w"))) + { + Trace("WriteProcessMemory: fopen of '%S' failed (%u). \n", + Comms.valuesFileName, GetLastError()); + return FALSE; + } + if (!fprintf(commsFile, "%u %u %u '%s'\n", + pDest, lenDest, dwExpectedErrorCode, storageDescription)) + { + Trace("WriteProcessMemory: fprintf to '%S' failed (%u). \n", + Comms.valuesFileName, GetLastError()); + return FALSE; + } + PEDANTIC1(fclose, (commsFile)); + + /* Tell the parent the data is ready for it to adjust */ + PEDANTIC(ResetEvent, (Comms.hEvToHelper)); + PEDANTIC(SetEvent, (Comms.hEvFromHelper)); + + dwRet = WaitForSingleObject(Comms.hEvToHelper, TIMEOUT); + if (dwRet != WAIT_OBJECT_0) + { + Trace("helper WaitForSingleObjectTest: WaitForSingleObject " + "failed (%u)\n", GetLastError()); + return FALSE; + } + + PAL_TRY + { + /* check the stuff (as much as we can) that should NOT have changed */ + for (pCurr = pDest; pCurr < (pDest + lenSafe); pCurr++ ) + { + if ( *pCurr != initialValue) + { + Trace("When testing '%s': real memory values preservation failed " + "at %u offset %u. Found '%c' instead of '%c'\n.", + storageDescription, pDest, pCurr - pDest, + *pCurr, initialValue); + return FALSE; + } + } + } + PAL_EXCEPT_EX (testing, EXCEPTION_EXECUTE_HANDLER) + { + Trace("WriteProcessMemory: bug in test values for '%s' (%p, %u, %u), " + "the verification pass threw an exception.\n", + storageDescription, pDest, lenDest, lenSafe); + } + PAL_ENDTRY; + + return TRUE; +} + +int __cdecl main(int argc, char *argv[]) +{ + BOOL success = TRUE; /* assume success */ + struct allhandles_t Comms = {0,0,0} ; + + SYSTEM_INFO sysinfo; + + char* Memory; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* hook up with the events created by the parent */ + Comms.hEvToHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcToHelperEvName); + if (!Comms.hEvToHelper) + { + Fail("WriteProcessMemory: OpenEvent of '%S' failed (%u). " + "(the event should already exist!)\n", + szcToHelperEvName, GetLastError()); + success = FALSE; + goto EXIT; + } + Comms.hEvFromHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcFromHelperEvName); + if (!Comms.hEvToHelper) + { + Trace("WriteProcessMemory: OpenEvent of '%S' failed (%u). " + "(the event should already exist!)\n", + szcFromHelperEvName, GetLastError()); + success = FALSE; + goto EXIT; + } + Comms.valuesFileName = argv[1]; + + /* test setup */ + GetSystemInfo(&sysinfo); + + { + unsigned int allocSize = sysinfo.dwPageSize * 2; + unsigned int writeLen = allocSize * 2; + + /* First test: overrun the allocated memory */ + Memory = (char*)VirtualAlloc(NULL, allocSize, + MEM_COMMIT, PAGE_READWRITE); + + if(Memory == NULL) + { + Fail("ERROR: Attempted to commit two pages, but the " + " VirtualAlloc call failed. " + "GetLastError() returned %u.\n",GetLastError()); + } + success &= wpmVerifyCant(Comms, Memory, writeLen, allocSize, + ERROR_INVALID_ADDRESS, + "should not write beyond committed allocation"); + + PEDANTIC1(VirtualFree, (Memory, allocSize, + MEM_DECOMMIT | MEM_RELEASE)); + } + + { + /* Allocate the memory as readonly */ + unsigned int allocSize = sysinfo.dwPageSize * 2; + unsigned int writeLen = allocSize; + + Memory = (char*)VirtualAlloc(NULL, allocSize, + MEM_COMMIT, PAGE_READONLY); + + if(Memory == NULL) + { + Fail("ERROR: Attempted to commit two pages readonly, but the " + " VirtualAlloc call failed. " + "GetLastError() returned %u.\n",GetLastError()); + } + success &= wpmVerifyCant(Comms, Memory, writeLen, 0, + ERROR_NOACCESS, + "should not write in READONLY allocation"); + + PEDANTIC1(VirtualFree, (Memory, allocSize, + MEM_DECOMMIT | MEM_RELEASE)); + } + + + { + /* attempt to write to memory that is not committed yet */ + unsigned int allocSize = sysinfo.dwPageSize * 2; + unsigned int writeLen = allocSize; + + Memory = (char*)VirtualAlloc(NULL, allocSize, + MEM_RESERVE, PAGE_NOACCESS); + + if(Memory == NULL) + { + Fail("ERROR: Attempted to reserve two pages, but the " + " VirtualAlloc call failed. " + "GetLastError() returned %u.\n",GetLastError()); + } + success &= wpmVerifyCant(Comms, Memory, writeLen, 0, + ERROR_INVALID_ADDRESS, + "should not write in memory that is" + " RESERVED but not COMMITTED"); + + PEDANTIC1(VirtualFree, (Memory, allocSize, MEM_RELEASE)); + } + + +EXIT: + /* Tell the parent that we are done */ + if (!DeleteFile(Comms.valuesFileName)) + { + Trace("helper: DeleteFile failed so parent (test1) is unlikely " + "to exit cleanly\n"); + } + PEDANTIC(ResetEvent, (Comms.hEvToHelper)); + if (!SetEvent(Comms.hEvFromHelper)) + { + Trace("helper: SetEvent failed so parent (test1) is unlikely " + "to exit cleanly\n"); + } + + PEDANTIC(CloseHandle, (Comms.hEvToHelper)); + PEDANTIC(CloseHandle, (Comms.hEvFromHelper)); + + if (!success) + { + Fail(""); + } + + PAL_Terminate(); + + return success ? PASS : FAIL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.cpp new file mode 100644 index 0000000..15b4b3f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.cpp @@ -0,0 +1,205 @@ +// 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. + +/*============================================================= +** +** Source: test3.c +** +** Purpose: Create a child process and debug it. When the child +** raises an exception, it sends back a memory location. Call +** WriteProcessMemory on the memory location, but attempt to write +** more than the memory allows. This should cause an error and the +** data should be unchanged. +** +** +==============================================================*/ + +#define UNICODE + +#include "commonconsts.h" + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + PROCESS_INFORMATION pi; + STARTUPINFO si; + HANDLE hEvToHelper; + HANDLE hEvFromHelper; + DWORD dwExitCode; + + + DWORD dwRet; + BOOL success = TRUE; /* assume success */ + char cmdComposeBuf[MAX_PATH]; + PWCHAR uniString; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Create the signals we need for cross process communication */ + hEvToHelper = CreateEvent(NULL, TRUE, FALSE, szcToHelperEvName); + if (!hEvToHelper) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "GetLastError() returned %u.\n", szcToHelperEvName, + GetLastError()); + } + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "(already exists!)\n", szcToHelperEvName); + } + hEvFromHelper = CreateEvent(NULL, TRUE, FALSE, szcFromHelperEvName); + if (!hEvToHelper) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "GetLastError() returned %u.\n", szcFromHelperEvName, + GetLastError()); + } + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "(already exists!)\n", szcFromHelperEvName); + } + + if (!sprintf_s(cmdComposeBuf, _countof(cmdComposeBuf), "helper %s", commsFileName)) + { + Fail("Could not convert command line\n"); + } + uniString = convert(cmdComposeBuf); + + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + /* Create a new process. This is the process that will ask for + * memory munging */ + if(!CreateProcess( NULL, uniString, NULL, NULL, + FALSE, 0, NULL, NULL, &si, &pi)) + { + Trace("ERROR: CreateProcess failed to load executable '%S'. " + "GetLastError() returned %u.\n", + uniString, GetLastError()); + free(uniString); + Fail(""); + } + free(uniString); + + while(1) + { + FILE *commsFile; + char* pSrcMemory; + char* pDestMemory; + int Count; + SIZE_T wpmCount; + DWORD dwExpectedErrorCode; + + char incomingCMDBuffer[MAX_PATH + 1]; + + /* wait until the helper tells us that it has given us + * something to do */ + dwRet = WaitForSingleObject(hEvFromHelper, TIMEOUT); + if (dwRet != WAIT_OBJECT_0) + { + Trace("test1 WaitForSingleObjectTest: WaitForSingleObject " + "failed (%u)\n", GetLastError()); + break; /* no more work incoming */ + } + + /* get the parameters to test WriteProcessMemory with */ + if (!(commsFile = fopen(commsFileName, "r"))) + { + /* no file means there is no more work */ + break; + } + if ( NULL == fgets(incomingCMDBuffer, MAX_PATH, commsFile)) + { + Trace ("unable to read from communication file %s " + "for reasons %u & %u\n", + errno, GetLastError()); + success = FALSE; + PEDANTIC1(fclose,(commsFile)); + /* it's not worth continuing this trial */ + goto doneIteration; + } + PEDANTIC1(fclose,(commsFile)); + sscanf(incomingCMDBuffer, "%u %u %u", + &pDestMemory, &Count, &dwExpectedErrorCode); + if (argc > 1) + { + Trace("Preparing to write to %u bytes @ %u ('%s')\n", + Count, pDestMemory, incomingCMDBuffer); + } + + /* compose some data to write to the client process */ + if (!(pSrcMemory = (char*)malloc(Count))) + { + Trace("could not dynamically allocate memory to copy from " + "for reasons %u & %u\n", + errno, GetLastError()); + success = FALSE; + goto doneIteration; + } + memset(pSrcMemory, nextValue, Count); + + /* do the work */ + dwRet = WriteProcessMemory(pi.hProcess, + pDestMemory, + pSrcMemory, + Count, + &wpmCount); + + if(dwRet != 0) + { + Trace("ERROR: Situation: '%s', return code: %u, bytes 'written': %u\n", + incomingCMDBuffer, dwRet, wpmCount); + Trace("ERROR: WriteProcessMemory did not fail as it should, as " + "it attempted to write to a range of memory which was " + "not completely accessible.\n"); + success = FALSE; + } + + if(GetLastError() != dwExpectedErrorCode) + { + Trace("ERROR: GetLastError() should have returned " + "%u , but instead it returned %u.\n", + dwExpectedErrorCode, GetLastError()); + success = FALSE; + } + free(pSrcMemory); + + doneIteration: + PEDANTIC(ResetEvent, (hEvFromHelper)); + PEDANTIC(SetEvent, (hEvToHelper)); + } + + + /* wait for the child process to complete */ + WaitForSingleObject ( pi.hProcess, TIMEOUT ); + /* this may return a failure code on a success path */ + + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) + { + Trace( "GetExitCodeProcess call failed with error code %u\n", + GetLastError() ); + dwExitCode = FAIL; + } + if(!success) + { + dwExitCode = FAIL; + } + + PEDANTIC(CloseHandle, (hEvToHelper)); + PEDANTIC(CloseHandle, (hEvFromHelper)); + PEDANTIC(CloseHandle, (pi.hThread)); + PEDANTIC(CloseHandle, (pi.hProcess)); + + PAL_Terminate(dwExitCode); + return dwExitCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/testinfo.dat new file mode 100644 index 0000000..23ad3ae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = Debug +Function = WriteProcessMemory +Name = Check that you can't write from writable to protected memory. +TYPE = DEFAULT +EXE1 = test3 +EXE2 = helper +Description += Create a child process and debug it. When the child += raises an exception, it sends back a memory location. Call += WriteProcessMemory on the memory location, but attempt to write += more than the memory allows. This should cause an error and the += data should be unchanged. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/CMakeLists.txt new file mode 100644 index 0000000..21b2fda --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + test4.cpp +) + +add_executable(paltest_writeprocessmemory_test4 + ${TESTSOURCES} +) + +add_dependencies(paltest_writeprocessmemory_test4 coreclrpal) + +target_link_libraries(paltest_writeprocessmemory_test4 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + helper.cpp +) + +add_executable(paltest_writeprocessmemory_test4_helper + ${HELPERSOURCES} +) + +add_dependencies(paltest_writeprocessmemory_test4_helper coreclrpal) + +target_link_libraries(paltest_writeprocessmemory_test4_helper + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/helper.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/helper.cpp new file mode 100644 index 0000000..b653ea5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/helper.cpp @@ -0,0 +1,67 @@ +// 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. + +/*============================================================= +** +** Source: helper.c +** +** Purpose: This helper process sets up a block of memory, then +** raises an exception to pass that memory location back to the +** parent process. When the parent process is done calling WriteProcessMemory +** we check here that it was written properly. +** +** +**============================================================*/ + +#include +const int MY_EXCEPTION=999; + +int __cdecl main(int argc, char *argv[]) +{ + + char* Memory; + char* TheArray[1]; + int i; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + Memory = (char*)VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_READONLY); + + if(Memory == NULL) + { + Fail("ERROR: Attempted to allocate two pages, but the VirtualAlloc " + "call failed. GetLastError() returned %d.\n",GetLastError()); + } + + + TheArray[0] = Memory; + + + /* Need to sleep for a couple seconds. Otherwise this process + won't be being debugged when the first exception is raised. + */ + Sleep(4000); + + RaiseException(MY_EXCEPTION, 0, 1, (ULONG_PTR*)TheArray); + + for(i=0; i<4096; ++i) + { + if(Memory[i] != '\0') + { + Fail("ERROR: The memory should be unchanged after the " + "invalid call to WriteProcessMemory, but the char " + "at index %d has changed.\n",i); + } + } + + + + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/test4.cpp new file mode 100644 index 0000000..51db234 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/test4.cpp @@ -0,0 +1,124 @@ +// 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. + +/*============================================================= +** +** Source: test4.c +** +** Purpose: Create a child process and debug it. When the child +** raises an exception, it sends back a memory location. Call +** WriteProcessMemory on a restricted memory location and ensure that +** it fails. +** +** +**============================================================*/ + +#include +const int MY_EXCEPTION=999; + +int __cdecl main(int argc, char *argv[]) +{ + + PROCESS_INFORMATION pi; + STARTUPINFO si; + DEBUG_EVENT DebugEv; + DWORD dwContinueStatus = DBG_CONTINUE; + int Count, ret; + char* DataBuffer[4096]; + char* Memory; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + memset(DataBuffer, 'z', 4096); + + /* Create a new process. This is the process to be Debugged */ + if(!CreateProcess( NULL, "helper", NULL, NULL, + FALSE, 0, NULL, NULL, &si, &pi)) + { + Fail("ERROR: CreateProcess failed to load executable 'helper'. " + "GetLastError() returned %d.\n",GetLastError()); + } + + /* Call DebugActiveProcess, because the process wasn't created as a + debug process. + */ + if(DebugActiveProcess(pi.dwProcessId) == 0) + { + Fail("ERROR: Failed calling DebugActiveProcess on the process " + "which was created to debug. GetLastError() returned %d.\n", + GetLastError()); + } + + + /* Call WaitForDebugEvent, which will wait until the helper process + raises an exception. + */ + + while(1) + { + if(WaitForDebugEvent(&DebugEv, INFINITE) == 0) + { + Fail("ERROR: WaitForDebugEvent returned 0, indicating failure. " + "GetLastError() returned %d.\n",GetLastError()); + } + + /* We're waiting for the helper process to send this exception. + When it does, we call WriteProcess. If it gets called more than + once, it is ignored. + */ + + if(DebugEv.u.Exception.ExceptionRecord.ExceptionCode == MY_EXCEPTION) + { + + Memory = (LPVOID) + DebugEv.u.Exception.ExceptionRecord.ExceptionInformation[0]; + + /* Write to this memory which we have no access to. */ + + ret = WriteProcessMemory(pi.hProcess, + Memory, + DataBuffer, + 4096, + &Count); + + if(ret != 0) + { + Fail("ERROR: WriteProcessMemory should have failed, as " + "it attempted to write to a range of memory which was " + "not accessible.\n"); + } + + if(GetLastError() != ERROR_NOACCESS) + { + Fail("ERROR: GetLastError() should have returned " + "ERROR_NOACCESS , but intead it returned " + "%d.\n",GetLastError()); + } + } + + if(DebugEv.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) + { + break; + } + + if(ContinueDebugEvent(DebugEv.dwProcessId, + DebugEv.dwThreadId, dwContinueStatus) == 0) + { + Fail("ERROR: ContinueDebugEvent failed to continue the thread " + "which had a debug event. GetLastError() returned %d.\n", + GetLastError()); + } + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/testinfo.dat new file mode 100644 index 0000000..c6f4edb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = Debug +Function = WriteProcessMemory +Name = Check that you can't write to protected memory. +TYPE = DEFAULT +EXE1 = test4 +EXE2 = helper +Description += Create a child process and debug it. When the child += raises an exception, it sends back a memory location. Call += WriteProcessMemory on a restricted memory location and ensure that += it fails. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/eventprovider/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/eventprovider/CMakeLists.txt new file mode 100644 index 0000000..000ee2d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/eventprovider/CMakeLists.txt @@ -0,0 +1,39 @@ +set(SOURCES + ${CMAKE_CURRENT_BINARY_DIR}/clralltestevents.cpp +) + +set(EVENT_MANIFEST ${VM_DIR}/ClrEtwAll.man) +set(TEST_GENERATOR ${CLR_DIR}/src/scripts/genEventingTests.py) + +include(FindPython) + +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/clralltestevents.cpp + COMMAND ${Python_EXECUTABLE} ${TEST_GENERATOR} --testdir "${CMAKE_CURRENT_BINARY_DIR}" --man "${EVENT_MANIFEST}" + DEPENDS ${EVENT_MANIFEST} ${TEST_GENERATOR} + COMMENT "Updating clralltestevents.cpp" +) + +include_directories(${GENERATED_INCLUDE_DIR}) + +if(TARGET_UNIX) + include_directories(${COREPAL_SOURCE_DIR}/inc/rt) +endif(TARGET_UNIX) + +add_executable(eventprovidertest + ${SOURCES} + ) +set(EVENT_PROVIDER_DEPENDENCIES "") +if(FEATURE_EVENT_TRACE) + add_definitions(-DFEATURE_EVENT_TRACE) + list(APPEND EVENT_PROVIDER_DEPENDENCIES + eventprovider + ) + if(CLR_CMAKE_HOST_LINUX) + list(APPEND EVENT_PROVIDER_DEPENDENCIES + coreclrtraceptprovider + ) + endif(CLR_CMAKE_HOST_LINUX) +endif(FEATURE_EVENT_TRACE) + +target_link_libraries(eventprovidertest ${EVENT_PROVIDER_DEPENDENCIES} coreclrpal) +add_dependencies(eventprovidertest eventing_headers) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/CMakeLists.txt new file mode 100644 index 0000000..c650506 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/CMakeLists.txt @@ -0,0 +1,10 @@ +add_subdirectory(pal_sxs) +#add_subdirectory(pal_except) +#add_subdirectory(PAL_EXCEPT_FILTER) +#add_subdirectory(PAL_EXCEPT_FILTER_EX) +#add_subdirectory(pal_finally) +#add_subdirectory(PAL_TRY_EXCEPT) +#add_subdirectory(PAL_TRY_EXCEPT_EX) +#add_subdirectory(PAL_TRY_LEAVE_FINALLY) +add_subdirectory(RaiseException) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt new file mode 100644 index 0000000..e186c6e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_EXCEPT_FILTER.cpp +) + +add_executable(paltest_pal_except_filter_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_except_filter_test1 coreclrpal) + +target_link_libraries(paltest_pal_except_filter_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.cpp new file mode 100644 index 0000000..ee65f43 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.cpp @@ -0,0 +1,118 @@ +// 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. + +/*===================================================================== +** +** Source: pal_except_filter.c (test 1) +** +** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER. An +** exception is forced and a known value is passed to the filter +** fuction. The known value as well as booleans are tested to +** ensure proper functioning. +** +** +**===================================================================*/ + + + +#include + +BOOL bFilter = FALSE; +BOOL bTry = FALSE; +const int nValidator = 12321; + +LONG ExitFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt) +{ + int nTestInt = *(int *)pnTestInt; + + /* let the main know we've hit the filter function */ + bFilter = TRUE; + + if (!bTry) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The filter was hit without PAL_TRY being hit.\n"); + } + + /* was the correct value passed? */ + if (nValidator != nTestInt) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Parameter passed to filter function" + " should have been \"%d\" but was \"%d\".\n", + nValidator, + nTestInt); + } + return EXCEPTION_EXECUTE_HANDLER; +} + + +int __cdecl main(int argc, char *argv[]) +{ + int* p = 0x00000000; /* pointer to NULL */ + BOOL bExcept = FALSE; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* + ** test to make sure we get into the exception block + */ + + PAL_TRY + { + if (bExcept) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n"); + } + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + *p = 13; /* causes an access violation exception */ + + Fail("PAL_EXCEPT_FILTER: ERROR -> code was executed after the " + "access violation.\n"); + } + PAL_EXCEPT_FILTER(ExitFilter, (LPVOID)&nValidator) + { + if (!bTry) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER was hit without PAL_TRY being hit.\n"); + } + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the PAL_TRY" + " block was not executed.\n"); + } + + if (!bExcept) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the " + "PAL_EXCEPT_FILTER block was not executed.\n"); + } + + if (!bFilter) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the filter" + " function was not executed.\n"); + } + + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept || !bFilter) + { + Fail(""); + } + + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/testinfo.dat new file mode 100644 index 0000000..b0b90d3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = PAL_EXCEPT_FILTER +Name = Test for PAL_EXCEPT_FILTER +Type = DEFAULT +EXE1 = pal_except_filter +LANG = cpp +Description += Tests the PAL implementation of the PAL_EXCEPT_FILTER. An += exception is forced and a known value is passed to the filter += fuction. The known value as well as booleans are tested to += ensure proper functioning. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt new file mode 100644 index 0000000..baaac69 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + pal_except_filter.cpp +) + +add_executable(paltest_pal_except_filter_test2 + ${SOURCES} +) + +add_dependencies(paltest_pal_except_filter_test2 coreclrpal) + +target_link_libraries(paltest_pal_except_filter_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.cpp new file mode 100644 index 0000000..ccf53fb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.cpp @@ -0,0 +1,154 @@ +// 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. + +/*===================================================================== +** +** Source: pal_except_filter.c (test 2) +** +** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER. An +** exception is forced and the filter returns +** EXCEPTION_CONTINUE_EXECUTION to allow execution to continue. +** +** +**===================================================================*/ + + +#include + +char* p; /* pointer to be abused */ + +BOOL bFilter = FALSE; +BOOL bTry = FALSE; +BOOL bTry2 = FALSE; +BOOL bContinued = FALSE; +const int nValidator = 12321; + +LONG ExitFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt) +{ + int nTestInt = *(int *)pnTestInt; + void *Temp; + + /* let the main know we've hit the filter function */ + bFilter = TRUE; + + if (!bTry) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The filter was hit without PAL_TRY being hit.\n"); + } + + /* was the correct value passed? */ + if (nValidator != nTestInt) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Parameter passed to filter function" + " should have been \"%d\" but was \"%d\".\n", + nValidator, + nTestInt); + } + + /* Are we dealing with the exception we expected? */ + if (EXCEPTION_ACCESS_VIOLATION != ep->ExceptionRecord->ExceptionCode) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Unexpected Exception" + " should have been \"%x\" but was \"%x\".\n", + EXCEPTION_ACCESS_VIOLATION, + ep->ExceptionRecord->ExceptionCode); + } + + /* attempt to correct the problem by commiting the page at address 'p' */ + Temp= VirtualAlloc(p, 1, MEM_COMMIT, PAGE_READWRITE); + if (!Temp) + { + Fail("EXCEPTION_CONTINUE_EXECUTION: last error = %u - probably " + "out of memory. Unable to continue, not proof of exception " + "failure\n", + GetLastError()); + } + /* The memory that 'p' points to is now valid */ + + return EXCEPTION_CONTINUE_EXECUTION; +} + + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bExcept = FALSE; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* + ** test to make sure we get into the exception block + */ + + PAL_TRY + { + if (bExcept) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n"); + } + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + + /* reserve an address chunk for p to point to */ + p = (char*) VirtualAlloc(0, 1, MEM_RESERVE, PAGE_READONLY); + if (!p) + { + Fail("EXCEPTION_CONTINUE_EXECUTION: test setup via " + "VirtualAlloc failed.\n"); + } + + *p = 13; /* causes an access violation exception */ + + bTry2 = TRUE; + + + } + PAL_EXCEPT_FILTER(ExitFilter, (LPVOID)&nValidator) + { + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER block */ + Fail("PAL_EXCEPT_FILTER: ERROR -> in handler despite filter's " + "continue choice\n"); + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the PAL_TRY" + " block was not executed.\n"); + } + + if (bExcept) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the " + "PAL_EXCEPT_FILTER block was executed.\n"); + } + + if (!bFilter) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the filter" + " function was not executed.\n"); + } + + + if (!bTry2) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the PAL_TRY" + " block after the exception causing statements was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || bExcept || !bFilter) + { + Fail(""); + } + + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/testinfo.dat new file mode 100644 index 0000000..729d2a4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = PAL_EXCEPT_FILTER +Name = Test for PAL_EXCEPT_FILTER +Type = DEFAULT +EXE1 = pal_except_filter +LANG = cpp +Description += Tests the PAL implementation of the PAL_EXCEPT_FILTER. An += exception is forced and the filter returns += EXCEPTION_CONTINUE_EXECUTION to allow execution to continue. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt new file mode 100644 index 0000000..54dd18a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + pal_except_filter.cpp +) + +add_executable(paltest_pal_except_filter_test3 + ${SOURCES} +) + +add_dependencies(paltest_pal_except_filter_test3 coreclrpal) + +target_link_libraries(paltest_pal_except_filter_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.cpp new file mode 100644 index 0000000..20c3684 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.cpp @@ -0,0 +1,206 @@ +// 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. + +/*===================================================================== +** +** Source: pal_except_filter.c (test 3) +** +** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER in the +** presence of a call stack. An +** exception is forced and passed to two nested exception filters for +** consideration. The first filter returns EXCEPTION_CONTINUE_SEARCH +** so the second can run and return EXCEPTION_EXECUTE_HANDLER. The +** initial exception handler should be skipped, and the second +** executed +** +** +**===================================================================*/ + + + +#include + +BOOL bFilterCS = FALSE; +BOOL bFilterEE = FALSE; +BOOL bTry1 = FALSE; +BOOL bTry2 = FALSE; +BOOL bExcept1 = FALSE; +BOOL bExcept2 = FALSE; +BOOL bContinued = FALSE; +const int nValidator = 12321; + +LONG ContSearchFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt) +{ + + /* let the main know we've hit the filter function */ + bFilterCS = TRUE; + + if (!bTry1 || !bTry2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The ContSearch filter was hit without PAL_TRY being hit.\n"); + } + + if (bFilterEE) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The ContSearch filter was hit after the ExecuteException " + "filter.\n"); + } + + return EXCEPTION_CONTINUE_SEARCH; +} + +LONG ExecExeptionFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt) +{ + /* let the main know we've hit the filter function */ + bFilterEE = TRUE; + + if (!bTry1 || !bTry2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The ContSearch filter was hit without PAL_TRY being hit.\n"); + } + + if (!bFilterCS) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The ExecExeption filter was hit before the ContSearch " + "filter.\n"); + } + return EXCEPTION_EXECUTE_HANDLER; +} + +void NestedFunc1 (void) +{ + int* p = 0x00000000; /* pointer to NULL */ + + PAL_TRY + { + if (bExcept1 || bExcept2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n"); + } + bTry2 = TRUE; /* indicate we hit the inner PAL_TRY block */ + *p = 13; /* causes an access violation exception */ + + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " We executed beyond the trapping code.\n"); + } + PAL_EXCEPT_FILTER(ContSearchFilter, (LPVOID)&nValidator) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The dummy handler was " + "being hit.\n"); + bExcept2 = TRUE; /* indicate we hit the inner block */ + } + PAL_ENDTRY; + +} + +void NestedFunc2 (void) +{ + NestedFunc1(); +} + +int __cdecl main(int argc, char *argv[]) +{ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* + ** test to make sure we get into the second exception block only based + ** on the return codes of the filters + */ + + PAL_TRY + { + if (bExcept1 || bExcept2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n"); + } + bTry1 = TRUE; /* indicate we hit the outer PAL_TRY block */ + + NestedFunc2(); + + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " We executed beyond the trapping code.\n"); + } + PAL_EXCEPT_FILTER(ExecExeptionFilter, (LPVOID)&nValidator) + { + if (!bTry1) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER's handler was hit without PAL_TRY's code " + "being hit.\n"); + } + if (!bTry2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER's handler was hit without PAL_TRY's code " + "being hit.\n"); + } + if (!bFilterCS) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER's handler was hit without the inner filter " + "being hit.\n"); + } + if (!bFilterEE) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER's handler was hit without the outer filter " + "being hit.\n"); + } + bExcept1 = TRUE; /* indicate we hit the outer block */ + } + PAL_ENDTRY; + + if (!bTry1) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the outer" + " PAL_TRY block was not executed.\n"); + } + + if (bExcept2) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the " + "inner PAL_EXCEPT_FILTER block was executed.\n"); + } + if (!bExcept1) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the " + "outer PAL_EXCEPT_FILTER block was not executed.\n"); + } + + if (!bFilterCS) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the " + "search continuing filter" + " function was not executed.\n"); + } + if (!bFilterEE) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the " + "execute handler filter" + " function was not executed.\n"); + } + + + /* did we hit all the code blocks? */ + if(!bTry1 || !bTry2 || !bExcept1 || bExcept2 || !bFilterEE || !bFilterCS ) + { + Fail(""); + } + + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/testinfo.dat new file mode 100644 index 0000000..d2df399 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = PAL_EXCEPT_FILTER_EX +Name = Test for nested PAL_EXCEPT_FILTER functions & EXCEPTION_CONTINUE_SEARCH +Type = DEFAULT +EXE1 = pal_except_filter +LANG = cpp +Description += Tests the PAL implementation of the PAL_EXCEPT_FILTER with nested += functions to build a call stack. An += exception is forced and passed to two nested exception filters for += consideration. The first filter returns EXCEPTION_CONTINUE_SEARCH += so the second can run and return EXCEPTION_EXECUTE_HANDLER. The += initial exception handler should be skipped, and the second += executed diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt new file mode 100644 index 0000000..c6bc2ef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_EXCEPT_FILTER_EX.cpp +) + +add_executable(paltest_pal_except_filter_ex_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_except_filter_ex_test1 coreclrpal) + +target_link_libraries(paltest_pal_except_filter_ex_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.cpp new file mode 100644 index 0000000..91f392d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.cpp @@ -0,0 +1,197 @@ +// 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. + +/*===================================================================== +** +** Source: PAL_EXCEPT_FILTER_EX.c (test 1) +** +** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX. +** There are two try blocks in this test. The first forces an +** exception error to force hitting the first filter. The second +** doesn't to make sure we don't hit the filter. A value is also +** passed into the filter program and it is validated to make sure +** it was passed correctly. +** +** +**===================================================================*/ + +#include + +BOOL bFilter = FALSE; +BOOL bTry = FALSE; +const int nValidator = 12321; + + +/** +** +** Filter function for the first try block +** +**/ + +LONG Filter_01(EXCEPTION_POINTERS* ep, VOID *pnTestInt) +{ + int nTestInt = *(int *)pnTestInt; + + /* let the main know we've hit the filter function */ + bFilter = TRUE; + + if (!bTry) + { + Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on." + " The filter was hit without PAL_TRY being hit.\n"); + } + + /* was the correct value passed? */ + if (nValidator != nTestInt) + { + Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Parameter passed to filter" + " function should have been \"%d\" but was \"%d\".\n", + nValidator, + nTestInt); + } + + return EXCEPTION_EXECUTE_HANDLER; +} + + +/** +** +** Filter function for the second try block. We shouldn't +** hit this function. +** +**/ + +LONG Filter_02(EXCEPTION_POINTERS* ep, VOID *pnTestInt) +{ + /* let the main know we've hit the filter function */ + bFilter = TRUE; + + return EXCEPTION_EXECUTE_HANDLER; +} + + +int __cdecl main(int argc, char *argv[]) +{ + int* p = 0x00000000; + BOOL bExcept = FALSE; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* + ** test to make sure we get into the exception block + */ + + PAL_TRY + { + if (bExcept) + { + Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on." + " The first PAL_EXCEPT_FILTER_EX was hit before PAL_TRY.\n"); + } + + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + *p = 13; /* causes an access violation exception */ + + Fail("PAL_EXCEPT_FILTER_EX: ERROR -> code was executed after the " + "access violation.\n"); + } + PAL_EXCEPT_FILTER(Filter_01, (LPVOID)&nValidator) + { + if (!bTry) + { + Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER_EX was hit without PAL_TRY being hit.\n"); + } + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the " + "first PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the " + "first PAL_EXCEPT_FILTER_EX block was not executed.\n"); + } + + if (!bFilter) + { + Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the first" + " filter function was not executed.\n"); + } + + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept || !bFilter) + { + Fail(""); + } + + bTry = bExcept = bFilter = FALSE; + + + /* + ** test to make sure we skip the exception block + */ + + PAL_TRY + { + if (bExcept) + { + Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on." + " Second PAL_EXCEPT_FILTER_EX was hit before PAL_TRY.\n"); + } + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + } + PAL_EXCEPT_FILTER(Filter_02, (LPVOID)&nValidator) + { + if (!bTry) + { + Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER_EX was hit without PAL_TRY being hit.\n"); + } + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the " + "second PAL_TRY block was not executed.\n"); + } + + if (bExcept) + { + Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the " + "second PAL_EXCEPT_FILTER_EX block was executed even though an" + " exception was not triggered.\n"); + } + + if (bFilter) + { + Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the second" + " filter function was executed even though an exception was" + " not triggered.\n"); + } + + + /* did we hit all the correct code blocks? */ + if(!bTry || bExcept || bFilter) + { + Fail(""); + } + + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/testinfo.dat new file mode 100644 index 0000000..1d8f8f6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = PAL_EXCEPT_FILTER_EX +Name = Test for PAL_EXCEPT_FILTER_EX +Type = DEFAULT +EXE1 = pal_except_filter_ex +LANG = cpp +Description += Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX. += There are two try blocks in this test. The first forces an += exception error to force hitting the first filter. The second += doesn't to make sure we don't hit the filter. A value is also += passed into the filter program and it is validated to make sure += it was passed correctly. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt new file mode 100644 index 0000000..ceb214a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + pal_except_filter_ex.cpp +) + +add_executable(paltest_pal_except_filter_ex_test2 + ${SOURCES} +) + +add_dependencies(paltest_pal_except_filter_ex_test2 coreclrpal) + +target_link_libraries(paltest_pal_except_filter_ex_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.cpp new file mode 100644 index 0000000..ab25c49 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.cpp @@ -0,0 +1,142 @@ +// 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. + +/*===================================================================== +** +** Source: PAL_EXCEPT_FILTER_EX.c (test 2) +** +** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX. +** There is a nested try blocks in this test. The nested +** PAL_TRY creates an exception and the FILTER creates another. +** This test makes sure that this case does not end in a +** infinite loop. +** +** +**===================================================================*/ + +#include + +BOOL bFilter = FALSE; +BOOL bTry = FALSE; +BOOL bTry2 = FALSE; +const int nValidator = 12321; + +/* Filter function for the first try block. + */ +LONG Filter_01(EXCEPTION_POINTERS* ep, VOID *pnTestInt) +{ + int nTestInt = *(int *)pnTestInt; + + /* Signal main() that filter has been executed. */ + bFilter = TRUE; + + if (!bTry) + { + Fail("ERROR: The filter was executed without " + "entering the first PAL_TRY.\n"); + } + + if (!bTry2) + { + Fail("ERROR: The filter was executed without " + "entering the second PAL_TRY.\n"); + } + + /* Was the correct value passed? */ + if (nValidator != nTestInt) + { + Fail("ERROR: Parameter passed to filter function " + "should have been \"%d\" but was \"%d\".\n", + nValidator, + nTestInt); + } + + return EXCEPTION_EXECUTE_HANDLER; +} + +int __cdecl main(int argc, char *argv[]) +{ + int* p = 0x00000000; + BOOL bExcept = FALSE; + BOOL bExcept2 = FALSE; + + /* Initalize the PAL. + */ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Test a nested PAL_Try block. + */ + PAL_TRY + { + /* Signal entry into first PAL_TRY block.*/ + bTry = TRUE; + + PAL_TRY + { + /* Signal entry into second PAL_TRY block.*/ + bTry2 = TRUE; + /* Cause an exception.*/ + *p = 13; + } + PAL_EXCEPT_FILTER(Filter_01, (LPVOID)&nValidator) + { + /* Signal entry into second PAL_EXCEPT filter.*/ + bExcept = TRUE; + /* Cause another exception.*/ + *p = 13; + } + PAL_ENDTRY + + } + PAL_EXCEPT_FILTER(Filter_01, (LPVOID)&nValidator) + { + /* Signal entry into second PAL_EXCEPT filter.*/ + bExcept2 = TRUE; + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("ERROR: The code in the first " + "PAL_TRY block was not executed.\n"); + } + + if (!bTry2) + { + Trace("ERROR: The code in the nested " + "PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("ERROR: The code in the first " + "PAL_EXCEPT_FILTER_EX block was not executed.\n"); + } + + if (!bExcept2) + { + Trace("ERROR: The code in the second " + "PAL_EXCEPT_FILTER_EX block was not executed.\n"); + } + + if (!bFilter) + { + Trace("ERROR: The code in the first " + "filter function was not executed.\n"); + } + + if(!bTry || !bTry2 || !bExcept || !bExcept2 || !bFilter ) + { + Fail(""); + } + + /* Terminate the PAL. + */ + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/testinfo.dat new file mode 100644 index 0000000..0343d13 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = PAL_EXCEPT_FILTER_EX +Name = Test for PAL_EXCEPT_FILTER_EX +Type = DEFAULT +EXE1 = pal_except_filter_ex +LANG = cpp +Description += Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX. += There is a nested try blocks in this test. The nested += PAL_TRY creates an exception and the FILTER creates another. += This test makes sure that this case does not end in a += infinite loop. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt new file mode 100644 index 0000000..3110799 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + pal_except_filter.cpp +) + +add_executable(paltest_pal_except_filter_ex_test3 + ${SOURCES} +) + +add_dependencies(paltest_pal_except_filter_ex_test3 coreclrpal) + +target_link_libraries(paltest_pal_except_filter_ex_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.cpp new file mode 100644 index 0000000..a17cb4f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.cpp @@ -0,0 +1,208 @@ +// 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. + +/*===================================================================== +** +** Source: pal_except_filter_ex.c (test 3) +** +** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX. An +** exception is forced and passed to two nested exception filters for +** consideration. The first filter returns EXCEPTION_CONTINUE_SEARCH +** so the second can run and return EXCEPTION_EXECUTE_HANDLER. The +** initial exception handler should be skipped, and the second +** executed +** +** +**===================================================================*/ + + + +#include + +BOOL bFilterCS = FALSE; +BOOL bFilterEE = FALSE; +BOOL bTry1 = FALSE; +BOOL bTry2 = FALSE; +BOOL bContinued = FALSE; +const int nValidator = 12321; + +LONG ContSearchFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt) +{ + + /* let the main know we've hit the filter function */ + bFilterCS = TRUE; + + if (!bTry1 || !bTry2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The ContSearch filter was hit without PAL_TRY being hit.\n"); + } + + if (bFilterEE) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The ContSearch filter was hit after the ExecuteException " + "filter.\n"); + } + + return EXCEPTION_CONTINUE_SEARCH; +} + +LONG ExecExeptionFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt) +{ + /* let the main know we've hit the filter function */ + bFilterEE = TRUE; + + if (!bTry1 || !bTry2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The ContSearch filter was hit without PAL_TRY being hit.\n"); + } + + if (!bFilterCS) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The ExecExeption filter was hit before the ContSearch " + "filter.\n"); + } + return EXCEPTION_EXECUTE_HANDLER; +} + +int __cdecl main(int argc, char *argv[]) +{ + int* p = 0x00000000; /* pointer to NULL */ + BOOL bExcept1 = FALSE; + BOOL bExcept2 = FALSE; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* + ** test to make sure we get into the second exception block only based + ** on the return codes of the filters + */ + + PAL_TRY + { + if (bExcept1 || bExcept2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n"); + } + bTry1 = TRUE; /* indicate we hit the outer PAL_TRY block */ + + PAL_TRY + { + if (bExcept1 || bExcept2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n"); + } + bTry2 = TRUE; /* indicate we hit the inner PAL_TRY block */ + *p = 13; /* causes an access violation exception */ + + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " We executed beyond the trapping code.\n"); + } + + PAL_EXCEPT_FILTER(ContSearchFilter, (LPVOID)&nValidator) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The dummy handler was " + "being hit.\n"); + } + PAL_ENDTRY; + + bExcept2 = TRUE; /* indicate we hit the inner block */ + } + PAL_EXCEPT_FILTER(ExecExeptionFilter, (LPVOID)&nValidator) + { + if (!bTry1) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER's handler was hit without PAL_TRY's code " + "being hit.\n"); + } + if (!bTry2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER's handler was hit without PAL_TRY's code " + "being hit.\n"); + } + if (!bFilterCS) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on. " + "PAL_EXCEPT_FILTER's handler was hit without " + "the inner filter being hit.\n"); + } + if (!bFilterEE) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on. " + "PAL_EXCEPT_FILTER's handler was hit without " + "the outer filter being hit.\n"); + } + bExcept1 = TRUE; /* indicate we hit the outer block */ + } + PAL_ENDTRY; + + if (!bTry1) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the outer" + " PAL_TRY block was not executed.\n"); + } + + if (!bTry2) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the inner" + " PAL_TRY block was not executed.\n"); + } + + if (bExcept2) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the " + "inner PAL_EXCEPT_FILTER block was executed.\n"); + } + if (!bExcept1) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the " + "outer PAL_EXCEPT_FILTER block was not executed.\n"); + } + + if (!bFilterCS) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the " + "search continuing filter" + " function was not executed.\n"); + } + if (!bFilterEE) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the " + "execute handler filter" + " function was not executed.\n"); + } + + + if (!bTry2) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the PAL_TRY " + "block after the exception causing statements " + "was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry1 || !bTry2 || !bExcept1 || bExcept2 || !bFilterEE || !bFilterCS ) + { + Fail(""); + } + + + PAL_Terminate(); + return PASS; + +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/testinfo.dat new file mode 100644 index 0000000..568296c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = PAL_EXCEPT_FILTER_EX +Name = Test for nested PAL_EXCEPT_FILTER_EX & EXCEPTION_CONTINUE_SEARCH +Type = DEFAULT +EXE1 = pal_except_filter +LANG = cpp +Description += Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX. An += exception is forced and passed to two nested exception filters for += consideration. The first filter returns EXCEPTION_CONTINUE_SEARCH += so the second can run and return EXCEPTION_EXECUTE_HANDLER. The += initial exception handler should be skipped, and the second += executed diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt new file mode 100644 index 0000000..867b028 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_TRY_EXCEPT.cpp +) + +add_executable(paltest_pal_try_except_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_try_except_test1 coreclrpal) + +target_link_libraries(paltest_pal_try_except_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.cpp new file mode 100644 index 0000000..4fb09bd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.cpp @@ -0,0 +1,82 @@ +// 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. + +/*===================================================================== +** +** Source: PAL_TRY_EXCEPT.c (test 1) +** +** Purpose: Tests the PAL implementation of the PAL_TRY and +** PAL_EXCEPT functions. An exception is forced to ensure +** the exception block is hit. +** +** +**===================================================================*/ + + + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + int* p = 0x00000000; /* NULL pointer */ + BOOL bTry = FALSE; + BOOL bExcept = FALSE; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* + ** test to make sure we get into the exception block + */ + + PAL_TRY + { + if (bExcept) + { + Fail("PAL_TRY_EXCEPT: ERROR -> Something weird is going on." + " PAL_EXCEPT was hit before PAL_TRY.\n"); + } + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + *p = 13; /* causes an access violation exception */ + Fail("PAL_TRY_EXCEPT: ERROR -> code was executed after the " + "access violation.\n"); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry) + { + Fail("PAL_TRY_EXCEPT: ERROR -> Something weird is going on." + " PAL_EXCEPT was hit without PAL_TRY being hit.\n"); + } + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY" + " block was not executed.\n"); + } + + if (!bExcept) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_EXCEPT" + " block was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept) + { + Fail(""); + } + + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/testinfo.dat new file mode 100644 index 0000000..1f663a8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = PAL_TRY and PAL_EXCEPT +Name = Test for PAL_TRY and PAL_EXCEPT +Type = DEFAULT +EXE1 = pal_try_except +LANG = cpp +Description += Since these two are so closely connected, they are tested together. += In the PAL_TRY block, an access violation is forced to gain += access to the PAL_EXCEPT block. Booleans are used to ensure += each of the code blocks are hit. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt new file mode 100644 index 0000000..81089fd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_TRY_EXCEPT.cpp +) + +add_executable(paltest_pal_try_except_test2 + ${SOURCES} +) + +add_dependencies(paltest_pal_try_except_test2 coreclrpal) + +target_link_libraries(paltest_pal_try_except_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.cpp new file mode 100644 index 0000000..eb7b9d1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.cpp @@ -0,0 +1,68 @@ +// 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. + +/*===================================================================== +** +** Source: PAL_TRY_EXCEPT.c (test 2) +** +** Purpose: Tests the PAL implementation of the PAL_TRY and +** PAL_EXCEPT functions. Tests that the EXCEPTION block +** is missed if no exceptions happen +** +** +**===================================================================*/ + + + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bTry = FALSE; + BOOL bExcept = FALSE; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* + ** Test to make sure we skip the exception block. + */ + + PAL_TRY + { + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY" + " block was not executed.\n"); + } + + if (bExcept) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_EXCEPT" + " block was executed even though no exception was supposed to" + " happen.\n"); + } + + /* did we hit the correct code blocks? */ + if(!bTry || bExcept) + { + Fail(""); + } + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/testinfo.dat new file mode 100644 index 0000000..a5815f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = PAL_TRY and PAL_EXCEPT (test 2) +Name = Test for PAL_TRY and PAL_EXCEPT +Type = DEFAULT +EXE1 = pal_try_except +LANG = cpp +Description += Since these two are so closely connected, they are tested together. += In this test, no exceptions are forced to ensure the EXCEPTION block += isn't hit. Booleans are used to ensure the proper code blocks are hit. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt new file mode 100644 index 0000000..1969986 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_TRY_EXCEPT_EX.cpp +) + +add_executable(paltest_pal_try_except_ex_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_try_except_ex_test1 coreclrpal) + +target_link_libraries(paltest_pal_try_except_ex_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.cpp new file mode 100644 index 0000000..8b4dd7b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.cpp @@ -0,0 +1,133 @@ +// 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. + +/*===================================================================== +** +** Source: PAL_TRY_EXCEPT.c (test 1) +** +** Purpose: Tests the PAL implementation of the PAL_TRY and +** PAL_EXCEPT functions. Exceptions are forced to ensure +** the exception blocks are hit. +** +** +**===================================================================*/ + + + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + int* p = 0x00000000; /* NULL pointer */ + BOOL bTry = FALSE; + BOOL bExcept = FALSE; + BOOL bTestA = TRUE; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* + ** test to make sure we get into the exception block + */ + + PAL_TRY + { + if (!bTestA) + { + Fail("PAL_TRY_EXCEPT: ERROR ->" + " It appears the first try block was hit a second time.\n"); + } + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + *p = 13; /* causes an access violation exception */ + Fail("PAL_TRY_EXCEPT: ERROR -> code was executed after the " + "access violation.\n"); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTestA) + { + Fail("PAL_TRY_EXCEPT: ERROR ->" + " It appears the first except block was hit a second time.\n"); + } + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY" + " block was not executed.\n"); + } + + if (!bExcept) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the first" + " PAL_EXCEPT block was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept) + { + Fail(""); + } + + + /* + ** test to make sure we get into the second exception block + */ + + bTry = FALSE; + bExcept = FALSE; + bTestA = FALSE; /* we are now going into the second block test */ + + + PAL_TRY + { + if (bTestA) + { + Fail("PAL_TRY_EXCEPT: ERROR -> It appears" + " the second try block was hit too early.\n"); + } + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + *p = 13; /* causes an access violation exception */ + Fail("PAL_TRY_EXCEPT: ERROR -> code was executed after the " + "access violation.\n"); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (bTestA) + { + Fail("PAL_TRY_EXCEPT: ERROR -> It appears" + " the second except block was hit too early.\n"); + } + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second" + " PAL_TRY block was not executed."); + } + + if (!bExcept) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_EXCEPT" + " block was not executed."); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept) + { + Fail("\n"); + } + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/testinfo.dat new file mode 100644 index 0000000..b571427 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = PAL_TRY and PAL_EXCEPT_EX +Name = Test for PAL_TRY and PAL_EXCEPT_EX +Type = DEFAULT +EXE1 = pal_try_except_ex +LANG = cpp +Description += Since these two are so closely connected, they are tested together. += In the PAL_TRY block, an access violation is forced to gain += access to the PAL_EXCEPT block. Booleans are used to ensure += each of the code blocks are hit. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt new file mode 100644 index 0000000..00a0985 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_TRY_EXCEPT_EX.cpp +) + +add_executable(paltest_pal_try_except_ex_test2 + ${SOURCES} +) + +add_dependencies(paltest_pal_try_except_ex_test2 coreclrpal) + +target_link_libraries(paltest_pal_try_except_ex_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.cpp new file mode 100644 index 0000000..5ab4a95 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.cpp @@ -0,0 +1,123 @@ +// 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. + +/*===================================================================== +** +** Source: PAL_TRY_EXCEPT.c (test 2) +** +** Purpose: Tests the PAL implementation of the PAL_TRY and +** PAL_EXCEPT functions. Exceptions are not forced to ensure +** the proper blocks are hit. +** +** +**===================================================================*/ + + + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bTry = FALSE; + BOOL bExcept = FALSE; + BOOL bTestA = TRUE; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* + ** test to make sure we get into the exception block + */ + + PAL_TRY + { + if (!bTestA) + { + Fail("PAL_TRY_EXCEPT: ERROR ->" + " It appears the first try block was hit a second time.\n"); + } + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY" + " block was not executed.\n"); + } + + if (bExcept) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the first" + " PAL_EXCEPT block was executed even though no exceptions were " + "encountered.\n"); + } + + /* did we hit all the proper code blocks? */ + if(!bTry || bExcept) + { + Fail(""); + } + + + /* + ** test to make sure we skip the second exception block + */ + + bTry = FALSE; + bExcept = FALSE; + bTestA = FALSE; /* we are now going into the second block test */ + + + PAL_TRY + { + if (bTestA) + { + Fail("PAL_TRY_EXCEPT: ERROR -> It appears" + " the second try block was hit too early.\n"); + } + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (bTestA) + { + Fail("PAL_TRY_EXCEPT: ERROR -> It appears" + " the second except block was hit too early.\n"); + } + bExcept = TRUE; /* indicate we hit the PAL_TRY block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second" + " PAL_TRY block was not executed.\n"); + } + + if (bExcept) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second" + " PAL_EXCEPT block was executed even though no exceptions were " + "encountered.\n"); + } + + /* did we hit all the proper code blocks? */ + if(!bTry || bExcept) + { + Fail("\n"); + } + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/testinfo.dat new file mode 100644 index 0000000..f71964d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = PAL_TRY and PAL_EXCEPT_EX (test 2) +Name = Test for PAL_TRY and PAL_EXCEPT_EX +Type = DEFAULT +EXE1 = pal_try_except_ex +LANG = cpp +Description += Since these two are so closely connected, they are tested together. += In this test, no exceptions are forced to ensure the EXCEPTION block += isn't hit. Booleans are used to ensure the proper code blocks are hit. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt new file mode 100644 index 0000000..d56169e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_TRY_EXCEPT_EX.cpp +) + +add_executable(paltest_pal_try_except_ex_test3 + ${SOURCES} +) + +add_dependencies(paltest_pal_try_except_ex_test3 coreclrpal) + +target_link_libraries(paltest_pal_try_except_ex_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.cpp new file mode 100644 index 0000000..d6a9489 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.cpp @@ -0,0 +1,130 @@ +// 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. + +/*===================================================================== +** +** Source: PAL_TRY_EXCEPT.c (test 3) +** +** Purpose: Tests the PAL implementation of the PAL_TRY and +** PAL_EXCEPT functions. Force an exception in only one block +** to ensure the proper exception block is hit. +** +** +**===================================================================*/ + + + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + int* p = 0x00000000; /* NULL pointer */ + BOOL bTry = FALSE; + BOOL bExcept = FALSE; + BOOL bTestA = TRUE; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* + ** test to make sure we get into the exception block + */ + + PAL_TRY + { + if (!bTestA) + { + Fail("PAL_TRY_EXCEPT: ERROR ->" + " It appears the first try block was hit a second time.\n"); + } + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + *p = 13; /* causes an access violation exception */ + Fail("PAL_TRY_EXCEPT: ERROR -> code was executed after the " + "access violation.\n"); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTestA) + { + Fail("PAL_TRY_EXCEPT: ERROR ->" + " It appears the first except block was hit a second time.\n"); + } + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY" + " block was not executed.\n"); + } + + if (!bExcept) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the first" + " PAL_EXCEPT block was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept) + { + Fail("\n"); + } + + + /* + ** test to make sure we get into the second exception block + */ + + bTry = FALSE; + bExcept = FALSE; + bTestA = FALSE; /* we are now going into the second block test */ + + + PAL_TRY + { + if (bTestA) + { + Fail("PAL_TRY_EXCEPT: ERROR -> It appears" + " the second try block was hit too early.\n"); + } + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (bTestA) + { + Fail("PAL_TRY_EXCEPT: ERROR -> It appears" + " the second except block was hit too early.\n"); + } + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second" + " PAL_TRY block was not executed.\n"); + } + + if (bExcept) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second " + " PAL_EXCEPT block was executed for some reason.\n"); + } + + /* did we hit all the correct code blocks? */ + if(!bTry || bExcept) + { + Fail("\n"); + } + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/testinfo.dat new file mode 100644 index 0000000..a245447 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = PAL_TRY and PAL_EXCEPT_EX (test3) +Name = Test for PAL_TRY and PAL_EXCEPT_EX +Type = DEFAULT +EXE1 = pal_try_except_ex +LANG = cpp +Description += Since these two are so closely connected, they are tested together. += Only one of the PAL_TRY blocks will force and exception to ensure the += correct PAL_EXCEPT_EX block is hit. Booleans are used to ensure += the correct code blocks are hit. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt new file mode 100644 index 0000000..9a81753 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_TRY_LEAVE_FINALLY.cpp +) + +add_executable(paltest_pal_try_leave_finally_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_try_leave_finally_test1 coreclrpal) + +target_link_libraries(paltest_pal_try_leave_finally_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.cpp new file mode 100644 index 0000000..675c2a5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.cpp @@ -0,0 +1,77 @@ +// 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. + +/*===================================================================== +** +** Source: pal_try_leave_finally.c +** +** Purpose: Tests the PAL implementation of the PAL_TRY, PAL_LEAVE +** and PAL_FINALLY functions. +** +** +**===================================================================*/ + + + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bTry = FALSE; + BOOL bFinally = FALSE; + BOOL bLeave = TRUE; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + PAL_TRY + { + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + + goto Done; + + bLeave = FALSE; /* indicate we stuck around */ + Done: ; + } + PAL_FINALLY + { + bFinally = TRUE; /* indicate we hit the PAL_FINALLY block */ + } + PAL_ENDTRY; + + /* did we go where we were meant to go */ + if (!bTry) + { + Trace("PAL_TRY_FINALLY: ERROR -> It appears the code in the PAL_TRY" + " block was not executed.\n"); + } + + if (!bLeave) + { + Trace("PAL_TRY_FINALLY: ERROR -> It appears code was executed after " + "PAL_LEAVE was called. It should have jumped directly to the " + "PAL_FINALLY block.\n"); + } + + if (!bFinally) + { + Trace("PAL_TRY_FINALLY: ERROR -> It appears the code in the PAL_FINALLY" + " block was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bLeave || !bFinally) + { + Fail(""); + } + + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/testinfo.dat new file mode 100644 index 0000000..8a90ef3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = PAL_TRY, PAL_LEAVE and PAL_FINALLY +Name = Test for PAL_TRY, PAL_LEAVE and PAL_EXCEPT +Type = DEFAULT +EXE1 = pal_try_leave_finally +LANG = cpp +Description += Since these three are so closely connected, they are tested together. += The PAL_TRY block contains a PAL_LEAVE which kicks execution to += the PAL_FINALLY block. Booleans are used to ensure each of the += code blocks are properly hit. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt new file mode 100644 index 0000000..f0c98f7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_raiseexception_test1 + ${SOURCES} +) + +add_dependencies(paltest_raiseexception_test1 coreclrpal) + +target_link_libraries(paltest_raiseexception_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp new file mode 100644 index 0000000..9130bc3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp @@ -0,0 +1,130 @@ +// 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. + +/*============================================================= +** +** Source: test1.c +** +** Purpose: Tests that RaiseException throws a catchable exception +** and Tests the behaviour of RaiseException with +** PAL_FINALLY +** +** +**============================================================*/ + + +#include + +BOOL bExcept = FALSE; +BOOL bTry = FALSE; +BOOL bFinally = FALSE; + +int __cdecl main(int argc, char *argv[]) +{ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /********************************************************* + * Tests that RaiseException throws a catchable exception + */ + PAL_TRY(VOID*, unused, NULL) + { + bTry = TRUE; + RaiseException(0,0,0,0); + + Fail("RaiseException: ERROR -> code was executed after the " + "exception was raised.\n"); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + bExcept = TRUE; + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("RaiseException: ERROR -> It appears the code in the " + "PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("RaiseException: ERROR -> It appears the code in the " + "PAL_EXCEPT_FILTER_EX block was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept) + { + Fail(""); + } + + /* Reinit flags */ + bTry = bExcept = FALSE; + + + /********************************************************* + * Tests the behaviour of RaiseException with + * PAL_FINALLY + * (bFinally should be set before bExcept) + */ + PAL_TRY(VOID*, unused, NULL) + { + PAL_TRY(VOID*, unused, NULL) + { + bTry = TRUE; + RaiseException(0,0,0,0); + + Fail("RaiseException: ERROR -> code was executed after the " + "exception was raised.\n"); + } + PAL_FINALLY + { + bFinally = TRUE; + } + PAL_ENDTRY; + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if( bFinally == FALSE ) + { + Fail("RaiseException: ERROR -> It appears the code in the " + "PAL_EXCEPT executed before the code in PAL_FINALLY.\n"); + } + + bExcept = TRUE; + } + + PAL_ENDTRY; + + if (!bTry) + { + Trace("RaiseException: ERROR -> It appears the code in the " + "PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("RaiseException: ERROR -> It appears the code in the " + "PAL_EXCEPT block was not executed.\n"); + } + + if (!bFinally) + { + Trace("RaiseException: ERROR -> It appears the code in the " + "PAL_FINALLY block was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept || !bFinally) + { + Fail(""); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test1/testinfo.dat new file mode 100644 index 0000000..890b5ef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = RaiseException +Name = RaiseException test #1 +TYPE = DEFAULT +EXE1 = test1 +LANG = cpp +Description +=Tests that RaiseException throws a catchable exception diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt new file mode 100644 index 0000000..71968b9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_raiseexception_test2 + ${SOURCES} +) + +add_dependencies(paltest_raiseexception_test2 coreclrpal) + +target_link_libraries(paltest_raiseexception_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp new file mode 100644 index 0000000..f8db573 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp @@ -0,0 +1,224 @@ +// 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. + +/*============================================================= +** +** Source: test2.c (exception_handling\raiseexception\test2) +** +** Purpose: Tests that the correct arguments are passed +** to the filter by RaiseException and tests that +** the number of arguments never exceeds +** EXCEPTION_MAXIMUM_PARAMETERS, even though we +** pass a greater number of arguments +** +** +**============================================================*/ + + +#include + +BOOL bFilter; +BOOL bTry; +BOOL bExcept; + +ULONG_PTR lpArguments_test1[EXCEPTION_MAXIMUM_PARAMETERS]; +DWORD nArguments_test1 = EXCEPTION_MAXIMUM_PARAMETERS; + +ULONG_PTR lpArguments_test2[EXCEPTION_MAXIMUM_PARAMETERS+1]; +DWORD nArguments_test2 = EXCEPTION_MAXIMUM_PARAMETERS+1; + + +/** +** +** Filter function that checks for the parameters +** +**/ +LONG Filter_test1(EXCEPTION_POINTERS* ep, VOID *unused) +{ + int i; + + /* let the main know we've hit the filter function */ + bFilter = TRUE; + + if (!bTry) + { + Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on." + " The filter was hit without PAL_TRY being hit.\n"); + } + + + /* was the correct number of arguments passed */ + if (ep->ExceptionRecord->NumberParameters != (DWORD) nArguments_test1) + { + Fail("RaiseException: ERROR -> Number of arguments passed to filter" + " was %d when it should have been %d", + ep->ExceptionRecord->NumberParameters, + nArguments_test1); + + } + + /* were the correct arguments passed */ + for( i=0; ((DWORD)i)ExceptionRecord->ExceptionInformation[i] + != lpArguments_test1[i]) + { + Fail("RaiseException: ERROR -> Argument %d passed to filter" + " was %d when it should have been %d", + i, + ep->ExceptionRecord->ExceptionInformation[i], + lpArguments_test1[i]); + } + } + + return EXCEPTION_EXECUTE_HANDLER; +} + +/** +** +** Filter function that checks for the maximum parameters +** +**/ +LONG Filter_test2(EXCEPTION_POINTERS* ep, VOID* unused) +{ + /* let the main know we've hit the filter function */ + bFilter = TRUE; + + if (ep->ExceptionRecord->NumberParameters > EXCEPTION_MAXIMUM_PARAMETERS) + { + Fail("RaiseException: ERROR -> Number of arguments passed to filter" + " was %d which is greater than the maximum allowed of %d\n", + ep->ExceptionRecord->NumberParameters, + EXCEPTION_MAXIMUM_PARAMETERS); + } + + return EXCEPTION_EXECUTE_HANDLER; +} + +int __cdecl main(int argc, char *argv[]) +{ + bExcept = FALSE; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /******************************************************** + * Test that the correct arguments are passed + * to the filter by RaiseException + */ + PAL_TRY(VOID*, unused, NULL) + { + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + + /* Initialize arguments to pass to filter */ + for(int i = 0; ((DWORD)i) < nArguments_test1; i++ ) + { + lpArguments_test1[i] = i; + } + + RaiseException(0,0,nArguments_test1,lpArguments_test1); + + Fail("RaiseException: ERROR -> code was executed after the " + "exception was raised.\n"); + } + PAL_EXCEPT_FILTER(Filter_test1) + { + if (!bTry) + { + Fail("RaiseException: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER was hit without PAL_TRY being hit.\n"); + } + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("RaiseException: ERROR -> It appears the code in the " + "PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("RaiseException: ERROR -> It appears the code in the " + "PAL_EXCEPT_FILTER_EX block was not executed.\n"); + } + + if (!bFilter) + { + Trace("RaiseException: ERROR -> It appears the code in the" + " filter function was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept || !bFilter) + { + Fail(""); + } + + + /* Reinit flags */ + bTry = bExcept = bFilter = FALSE; + + /******************************************************** + * Test that the number of arguments never + * exceeds EXCEPTION_MAXIMUM_PARAMETERS, even though we + * pass a greater number of arguments + */ + PAL_TRY(VOID*, unused, NULL) + { + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + + /* Initialize arguments to pass to filter */ + for(int i = 0; ((DWORD)i) < nArguments_test2; i++ ) + { + lpArguments_test2[i] = i; + } + + RaiseException(0,0,nArguments_test2,lpArguments_test2); + + Fail("RaiseException: ERROR -> code was executed after the " + "exception was raised.\n"); + } + PAL_EXCEPT_FILTER(Filter_test2) + { + if (!bTry) + { + Fail("RaiseException: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER was hit without PAL_TRY being hit.\n"); + } + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("RaiseException: ERROR -> It appears the code in the " + "PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("RaiseException: ERROR -> It appears the code in the " + "PAL_EXCEPT_FILTER_EX block was not executed.\n"); + } + + if (!bFilter) + { + Trace("RaiseException: ERROR -> It appears the code in the" + " filter function was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept || !bFilter) + { + Fail(""); + } + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test2/testinfo.dat new file mode 100644 index 0000000..ce85e67 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test2/testinfo.dat @@ -0,0 +1,28 @@ +# 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. + +Version = 1.0 + +Section = exception_handling + +Function = RaiseException + +Name = RaiseException test #2 + +TYPE = DEFAULT + +EXE1 = test2 +LANG = cpp + +Description + +=Tests that the correct arguments are passed + +=to the filter by RaiseException and tests that + +=the number of arguments never exceeds + +=EXCEPTION_MAXIMUM_PARAMETERS, even though we + +=pass a greater number of arguments diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt new file mode 100644 index 0000000..72b7936 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_raiseexception_test3 + ${SOURCES} +) + +add_dependencies(paltest_raiseexception_test3 coreclrpal) + +target_link_libraries(paltest_raiseexception_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp new file mode 100644 index 0000000..5278ad1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp @@ -0,0 +1,115 @@ +// 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. + +/*============================================================= +** +** Source: test.c (exception_handling\raiseexception\test3) +** +** Purpose: Tests that the correct ExceptionCode is passed +** to the filter by RaiseException +** +** +**============================================================*/ + + +#include + +BOOL bFilter = FALSE; +BOOL bTry = FALSE; +BOOL bExcept = FALSE; + +/** +** +** Filter function that checks for the parameters +** +**/ +LONG Filter_test1(EXCEPTION_POINTERS* ep, VOID* unused) +{ + /* let the main know we've hit the filter function */ + bFilter = TRUE; + + if (!bTry) + { + Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on." + " The filter was hit without PAL_TRY being hit.\n"); + } + + + /* was the correct exception code passed? */ + if (ep->ExceptionRecord->ExceptionCode != EXCEPTION_ARRAY_BOUNDS_EXCEEDED) + { + Fail("RaiseException: ERROR -> ep->ExceptionRecord->ExceptionCode" + " was %x when it was expected to be %x\n", + ep->ExceptionRecord->ExceptionCode, + EXCEPTION_ARRAY_BOUNDS_EXCEEDED); + + } + + return EXCEPTION_EXECUTE_HANDLER; +} + +int __cdecl main(int argc, char *argv[]) +{ + bExcept = FALSE; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /******************************************************** + * Test that the correct arguments are passed + * to the filter by RaiseException + */ + PAL_TRY(VOID*, unused, NULL) + { + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + + RaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED, + 0, + 0,NULL); + + Fail("RaiseException: ERROR -> code was executed after the " + "exception was raised.\n"); + } + PAL_EXCEPT_FILTER(Filter_test1) + { + if (!bTry) + { + Fail("RaiseException: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER was hit without PAL_TRY being hit.\n"); + } + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("RaiseException: ERROR -> It appears the code in the " + "PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("RaiseException: ERROR -> It appears the code in the " + "PAL_EXCEPT_FILTER_EX block was not executed.\n"); + } + + if (!bFilter) + { + Trace("RaiseException: ERROR -> It appears the code in the" + " filter function was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept || !bFilter) + { + Fail(""); + } + + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test3/testinfo.dat new file mode 100644 index 0000000..12a56f0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/RaiseException/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = RaiseException +Name = RaiseException test #3 +TYPE = DEFAULT +EXE1 = test +LANG = cpp +Description += Tests that the exception code passed to += RaiseException makes it to the filter. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/CMakeLists.txt new file mode 100644 index 0000000..7cd88f8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/CMakeLists.txt @@ -0,0 +1,8 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt new file mode 100644 index 0000000..d0d8476 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_pal_except_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_except_test1 coreclrpal) + +target_link_libraries(paltest_pal_except_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.cpp new file mode 100644 index 0000000..0fe48e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.cpp @@ -0,0 +1,67 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c (exception_handling\pal_except\test1) +** +** Purpose: Test to make sure the PAL_EXCEPT block is executed +** after an exception occurs in the PAL_TRY block +** +** +**===================================================================*/ +#include + +/* Execution flags */ +BOOL bTry = FALSE; +BOOL bExcept = FALSE; + +int __cdecl main(int argc, char *argv[]) +{ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + PAL_TRY + { + int* p = 0x00000000; /* NULL pointer */ + + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + *p = 13; /* causes an access violation exception */ + + Fail("ERROR: code was executed after the access violation.\n"); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry) + { + Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n"); + } + + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("ERROR: the code in the PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept) + { + Fail(""); + } + + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test1/testinfo.dat new file mode 100644 index 0000000..246553a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test1/testinfo.dat @@ -0,0 +1,23 @@ +# 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. + +Version = 1.0 + +Section = exception_handling + +Function = PAL_TRY and PAL_EXCEPT + +Name = Test for PAL_TRY and PAL_EXCEPT + +Type = DEFAULT + +EXE1 = test1 + +LANG = cpp + +Description + += Test to make sure the PAL_EXCEPT block is executed + += after an exception occurs in the PAL_TRY block diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt new file mode 100644 index 0000000..908b485 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_pal_except_test2 + ${SOURCES} +) + +add_dependencies(paltest_pal_except_test2 coreclrpal) + +target_link_libraries(paltest_pal_except_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.cpp new file mode 100644 index 0000000..bc0d4e3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.cpp @@ -0,0 +1,111 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c (exception_handling\pal_except\test2) +** +** Purpose: Test to make sure the PAL_EXCEPT block is executed +** after an exception occurs in the PAL_TRY block +** that contains another PAL_TRY-PAL_EXCEPT block +** +** +**===================================================================*/ +#include + +/* Execution flags */ +BOOL bTry = FALSE; +BOOL bExcept = FALSE; +BOOL bTry_nested = FALSE; +BOOL bExcept_nested = FALSE; + +int __cdecl main(int argc, char *argv[]) +{ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + PAL_TRY + { + int* p = 0x00000000; /* NULL pointer */ + + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + + + /* Nested PAL_TRY */ + PAL_TRY + { + bTry_nested = TRUE; + + *p = 13; /* causes an access violation exception */ + + Fail("ERROR: code was executed after the nested access violation.\n"); + + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry) + { + Fail("ERROR: Nested PAL_EXCEPT was hit without " + "nested PAL_TRY being hit.\n"); + } + bExcept_nested = TRUE; + } + PAL_ENDTRY; + + *p = 13; /* causes an access violation exception */ + + Fail("ERROR: code was executed after the access violation.\n"); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry) + { + Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n"); + } + if (!bExcept_nested) + { + Fail("ERROR: PAL_EXCEPT was hit without " + "nested PAL_EXCEPT being hit.\n"); + } + + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("ERROR: the code in the PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n"); + } + + if (!bTry_nested) + { + Trace("ERROR: the code in the " + "nested PAL_TRY block was not executed.\n"); + } + + if (!bExcept_nested) + { + Trace("ERROR: the code in the " + "nested PAL_EXCEPT block was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept || + !bTry_nested || !bExcept_nested) + { + Fail(""); + } + + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test2/testinfo.dat new file mode 100644 index 0000000..39a628b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test2/testinfo.dat @@ -0,0 +1,25 @@ +# 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. + +Version = 1.0 + +Section = exception_handling + +Function = PAL_TRY and PAL_EXCEPT_EX + +Name = Test for PAL_TRY and PAL_EXCEPT_EX + +Type = DEFAULT + +EXE1 = test2 + +LANG = cpp + +Description + += Test to make sure the PAL_EXCEPT_EX block is executed + += after an exception occurs in the PAL_TRY block + += that contains another PAL_TRY-PAL_EXCEPT_EX block diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt new file mode 100644 index 0000000..c3ab839 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_pal_except_test3 + ${SOURCES} +) + +add_dependencies(paltest_pal_except_test3 coreclrpal) + +target_link_libraries(paltest_pal_except_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.cpp new file mode 100644 index 0000000..0137697 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.cpp @@ -0,0 +1,120 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c (exception_handling\pal_except\test3) +** +** Purpose: Test to make sure the PAL_EXCEPT block is executed +** after an exception occurs in the PAL_TRY block +** that calls a function that contains +** another PAL_TRY-PAL_EXCEPT block +** +** +**===================================================================*/ +#include + +/* Execution flags */ +BOOL bTry = FALSE; +BOOL bExcept = FALSE; +BOOL bTry_function = FALSE; +BOOL bExcept_function = FALSE; + +/* + * Helper function that contains a PAL_TRY-PAL_EXCEPT block + */ +void Helper() +{ + /* Nested PAL_TRY */ + PAL_TRY + { + int *lp = 0x00000000; + + bTry_function = TRUE; + + *lp = 13; /* causes an access violation exception */ + + Fail("ERROR: code was executed after the function's access violation.\n"); + + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry) + { + Fail("ERROR: Nested PAL_EXCEPT was hit without " + "the function's PAL_TRY being hit.\n"); + } + bExcept_function = TRUE; + } + PAL_ENDTRY; +} + +int __cdecl main(int argc, char *argv[]) +{ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + PAL_TRY + { + int* p = 0x00000000; /* NULL pointer */ + + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + + Helper(); + + *p = 13; /* causes an access violation exception */ + + Fail("ERROR: code was executed after the access violation.\n"); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry) + { + Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n"); + } + if (!bExcept_function) + { + Fail("ERROR: PAL_EXCEPT was hit without " + "function's PAL_EXCEPT being hit.\n"); + } + + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("ERROR: the code in the PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n"); + } + + if (!bTry_function) + { + Trace("ERROR: the code in the " + "function's PAL_TRY block was not executed.\n"); + } + + if (!bExcept_function) + { + Trace("ERROR: the code in the " + "function's PAL_EXCEPT block was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept || + !bTry_function || !bExcept_function) + { + Fail(""); + } + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test3/testinfo.dat new file mode 100644 index 0000000..07da444 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test3/testinfo.dat @@ -0,0 +1,27 @@ +# 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. + +Version = 1.0 + +Section = exception_handling + +Function = PAL_TRY and PAL_EXCEPT + +Name = Test for PAL_TRY and PAL_EXCEPT + +Type = DEFAULT + +EXE1 = test3 + +LANG = cpp + +Description + += Test to make sure the PAL_EXCEPT block is executed + += after an exception occurs in the PAL_TRY block + += that calls a function that contains + += another PAL_TRY-PAL_EXCEPT block diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt new file mode 100644 index 0000000..493845c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_pal_except_test4 + ${SOURCES} +) + +add_dependencies(paltest_pal_except_test4 coreclrpal) + +target_link_libraries(paltest_pal_except_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.cpp new file mode 100644 index 0000000..8784497 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.cpp @@ -0,0 +1,105 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c (exception_handling\pal_except\test4) +** +** Purpose: Test to make sure the PAL_EXCEPT block is executed +** after an exception occurs in the PAL_TRY block +** if the PAL_EXCEPT block contains a nested +** PAL_TRY-PAL_EXCEPT block +** +** +**===================================================================*/ +#include + +/* Execution flags */ +BOOL bTry = FALSE; +BOOL bExcept = FALSE; +BOOL bTry_nested = FALSE; +BOOL bExcept_nested = FALSE; + +int __cdecl main(int argc, char *argv[]) +{ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + PAL_TRY + { + int* p = 0x00000000; /* NULL pointer */ + + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + *p = 13; /* causes an access violation exception */ + + Fail("ERROR: code was executed after the access violation.\n"); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry) + { + Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n"); + } + + PAL_TRY + { + int *lp = 0x00000000; + + bTry_nested = TRUE; + *lp = 13; /* causes an access violation exception */ + + Fail("ERROR: code was executed after the " + "nested access violation.\n"); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry_nested) + { + Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit " + "in the nested block.\n"); + } + bExcept_nested = TRUE; + } + PAL_ENDTRY; + + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("ERROR: the code in the PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n"); + } + + if (!bTry_nested) + { + Trace("ERROR: the code in the nested " + "PAL_TRY block was not executed.\n"); + } + + if (!bExcept_nested) + { + Trace("ERROR: the code in the nested " + "PAL_EXCEPT block was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept || + !bTry_nested || !bExcept_nested) + { + Fail(""); + } + + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test4/testinfo.dat new file mode 100644 index 0000000..d658cc8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test4/testinfo.dat @@ -0,0 +1,27 @@ +# 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. + +Version = 1.0 + +Section = exception_handling + +Function = PAL_TRY and PAL_EXCEPT + +Name = Test for PAL_TRY and PAL_EXCEPT + +Type = DEFAULT + +EXE1 = test4 + +LANG = cpp + +Description + += Test to make sure the PAL_EXCEPT block is executed + += after an exception occurs in the PAL_TRY block + += if the PAL_EXCEPT block contains a nested + += PAL_TRY-PAL_EXCEPT block diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt new file mode 100644 index 0000000..5b6b8dc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_pal_except_test5 + ${SOURCES} +) + +add_dependencies(paltest_pal_except_test5 coreclrpal) + +target_link_libraries(paltest_pal_except_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.cpp new file mode 100644 index 0000000..f9faf44 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.cpp @@ -0,0 +1,112 @@ +// 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. + +/*===================================================================== +** +** Source: test5.c (exception_handling\pal_except\test5) +** +** Purpose: Test to make sure the PAL_EXCEPT block is executed +** after an exception occurs in the PAL_TRY block +** if the PAL_EXCEPT block calls a function that contains +** another PAL_TRY-PAL_EXCEPT block +** +** +**===================================================================*/ +#include + +/* Execution flags */ +BOOL bTry = FALSE; +BOOL bExcept = FALSE; +BOOL bTry_nested = FALSE; +BOOL bExcept_nested = FALSE; + +int __cdecl main(int argc, char *argv[]) +{ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + PAL_TRY + { + int* p = 0x00000000; /* NULL pointer */ + + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + + + /* Nested PAL_TRY */ + PAL_TRY + { + bTry_nested = TRUE; + + *p = 13; /* causes an access violation exception */ + + Fail("ERROR: code was executed after the nested access violation.\n"); + + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry) + { + Fail("ERROR: Nested PAL_EXCEPT was hit without " + "nested PAL_TRY being hit.\n"); + } + bExcept_nested = TRUE; + } + PAL_ENDTRY; + + *p = 13; /* causes an access violation exception */ + + Fail("ERROR: code was executed after the access violation.\n"); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry) + { + Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n"); + } + if (!bExcept_nested) + { + Fail("ERROR: PAL_EXCEPT was hit without " + "nested PAL_EXCEPT being hit.\n"); + } + + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("ERROR: the code in the PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n"); + } + + if (!bTry_nested) + { + Trace("ERROR: the code in the " + "nested PAL_TRY block was not executed.\n"); + } + + if (!bExcept_nested) + { + Trace("ERROR: the code in the " + "nested PAL_EXCEPT block was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept || + !bTry_nested || !bExcept_nested) + { + Fail(""); + } + + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test5/testinfo.dat new file mode 100644 index 0000000..2e12d0c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test5/testinfo.dat @@ -0,0 +1,27 @@ +# 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. + +Version = 1.0 + +Section = exception_handling + +Function = PAL_TRY and PAL_EXCEPT + +Name = Test for PAL_TRY and PAL_EXCEPT + +Type = DEFAULT + +EXE1 = test5 + +LANG = cpp + +Description + += Test to make sure the PAL_EXCEPT block is executed + += after an exception occurs in the PAL_TRY block + += if the PAL_EXCEPT block calls a function that contains + += another PAL_TRY-PAL_EXCEPT block diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt new file mode 100644 index 0000000..e743673 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_pal_except_test6 + ${SOURCES} +) + +add_dependencies(paltest_pal_except_test6 coreclrpal) + +target_link_libraries(paltest_pal_except_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.cpp new file mode 100644 index 0000000..44b0ba1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.cpp @@ -0,0 +1,160 @@ +// 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. + +/*===================================================================== +** +** Source: test6.c (exception_handling\pal_except\test6) +** +** Purpose: Test to make sure the PAL_EXCEPT block is executed +** after an exception occurs in the PAL_TRY block +** that contains multiple PAL_TRY-PAL_EXCEPT blocks +** +** +**===================================================================*/ +#include + +/* Execution flags */ +BOOL bTry = FALSE; +BOOL bExcept = FALSE; +BOOL bTry_nested = FALSE; +BOOL bExcept_nested = FALSE; +BOOL bTry_nested2 = FALSE; +BOOL bExcept_nested2 = FALSE; + + +int __cdecl main(int argc, char *argv[]) +{ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* First block */ + PAL_TRY + { + int* p = 0x00000000; /* NULL pointer */ + + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + + /* Second PAL_TRY block */ + PAL_TRY + { + bTry_nested = TRUE; + + /* Third PAL_TRY block*/ + PAL_TRY + { + bTry_nested2 = TRUE; + + *p = 13; /* causes an access violation exception */ + + Fail("ERROR: code was executed after the nested access violation.\n"); + + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry_nested2) + { + Fail("ERROR: Third PAL_EXCEPT was hit without " + "third PAL_TRY being hit.\n"); + } + bExcept_nested2 = TRUE; + } + PAL_ENDTRY; + + *p = 13; /* causes an access violation exception */ + + Fail("ERROR: code was executed after the nested access violation.\n"); + + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry_nested) + { + Fail("ERROR: Second PAL_EXCEPT was hit without " + "second PAL_TRY being hit.\n"); + } + if (!bExcept_nested2) + { + Fail("ERROR: second PAL_EXCEPT was hit without " + "third PAL_EXCEPT being hit.\n"); + } + bExcept_nested = TRUE; + } + PAL_ENDTRY; + + *p = 13; /* causes an access violation exception */ + + Fail("ERROR: code was executed after the access violation.\n"); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry) + { + Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n"); + } + if (!bExcept_nested) + { + Fail("ERROR: first PAL_EXCEPT was hit without " + "second PAL_EXCEPT being hit.\n"); + } + if (!bExcept_nested2) + { + Fail("ERROR: first PAL_EXCEPT was hit without " + "third PAL_EXCEPT being hit.\n"); + } + + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("ERROR: the code in the " + "first PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("ERROR: the code in the " + "first PAL_EXCEPT block was not executed.\n"); + } + + if (!bTry_nested) + { + Trace("ERROR: the code in the " + "second PAL_TRY block was not executed.\n"); + } + + if (!bExcept_nested) + { + Trace("ERROR: the code in the " + "second PAL_EXCEPT block was not executed.\n"); + } + + if (!bTry_nested2) + { + Trace("ERROR: the code in the " + "third PAL_TRY block was not executed.\n"); + } + + if (!bExcept_nested2) + { + Trace("ERROR: the code in the " + "third PAL_EXCEPT block was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if(!bTry || !bExcept || + !bTry_nested || !bExcept_nested || + !bTry_nested2 || !bExcept_nested2) + { + Fail(""); + } + + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test6/testinfo.dat new file mode 100644 index 0000000..f8901a7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test6/testinfo.dat @@ -0,0 +1,25 @@ +# 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. + +Version = 1.0 + +Section = exception_handling + +Function = PAL_TRY and PAL_EXCEPT_EX + +Name = Test for PAL_TRY and PAL_EXCEPT_EX + +Type = DEFAULT + +EXE1 = test6 + +LANG = cpp + +Description + += Test to make sure the PAL_EXCEPT_EX block is executed + += after an exception occurs in the PAL_TRY block + += that contains multiple PAL_TRY-PAL_EXCEPT_EX blocks diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt new file mode 100644 index 0000000..40ffaea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_pal_except_test7 + ${SOURCES} +) + +add_dependencies(paltest_pal_except_test7 coreclrpal) + +target_link_libraries(paltest_pal_except_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.cpp new file mode 100644 index 0000000..a8dc833 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.cpp @@ -0,0 +1,67 @@ +// 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. + +/*===================================================================== +** +** Source: test7.c (exception_handling\pal_except\test7) +** +** Purpose: Tests the PAL implementation of the PAL_TRY and +** PAL_EXCEPT functions. Tests that the EXCEPTION block +** is missed if no exceptions happen +** +** +**===================================================================*/ + + + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bTry = FALSE; + BOOL bExcept = FALSE; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* + ** Test to make sure we skip the exception block. + */ + + PAL_TRY + { + bTry = TRUE; /* indicate we hit the PAL_TRY block */ + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */ + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY" + " block was not executed.\n"); + } + + if (bExcept) + { + Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_EXCEPT" + " block was executed even though no exception was supposed to" + " happen.\n"); + } + + /* did we hit the correct code blocks? */ + if(!bTry || bExcept) + { + Fail(""); + } + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test7/testinfo.dat new file mode 100644 index 0000000..546d64c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_except/test7/testinfo.dat @@ -0,0 +1,24 @@ +# 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. + +Version = 1.0 + +Section = exception_handling + +Function = PAL_TRY and PAL_EXCEPT + +Name = Test for PAL_TRY and PAL_EXCEPT + +Type = DEFAULT + +EXE1 = test7 + +LANG = cpp + +Description + += In this test, no exceptions are forced to ensure the EXCEPTION block + += isn't hit. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt new file mode 100644 index 0000000..db29fca --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + pal_finally.cpp +) + +add_executable(paltest_pal_finally_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_finally_test1 coreclrpal) + +target_link_libraries(paltest_pal_finally_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.cpp new file mode 100644 index 0000000..f278f98 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.cpp @@ -0,0 +1,302 @@ +// 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. + +/*===================================================================== +** +** Source: pal_finally.c (test 3) +** +** Purpose: Tests the PAL implementation of the PAL_FINALLY in the +** presence of a call stack. An exception is forced and +** passed to two nested exception filters for consideration. +** The first filter returns EXCEPTION_CONTINUE_SEARCH so the +** second can run and return EXCEPTION_EXECUTE_HANDLER. The +** initial exception handler should be skipped, and the +** second executed, and all the PAL_FINALLY blocks handled +** +** +**===================================================================*/ +#include + +BOOL bFilterCS = FALSE; +BOOL bFilterEE = FALSE; +BOOL bFinally1 = FALSE; +BOOL bFinally2 = FALSE; +BOOL bFinally3 = FALSE; +BOOL bFinally4 = FALSE; +BOOL bTry1 = FALSE; +BOOL bTry2 = FALSE; +BOOL bExcept1 = FALSE; +BOOL bExcept2 = FALSE; +BOOL bContinued = FALSE; +const int nValidator = 12321; + +LONG ContSearchFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt) +{ + + /* let the main know we've hit the filter function */ + bFilterCS = TRUE; + + if (!bTry1 || !bTry2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The ContSearch filter was hit without PAL_TRY being hit.\n"); + } + + if (bFilterEE) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The ContSearch filter was hit after the ExecuteException " + "filter.\n"); + } + + return EXCEPTION_CONTINUE_SEARCH; +} + +LONG ExecExeptionFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt) +{ + /* let the main know we've hit the filter function */ + bFilterEE = TRUE; + + if (!bTry1 || !bTry2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The ContSearch filter was hit without PAL_TRY being hit.\n"); + } + + if (!bFilterCS) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The ExecExeption filter was hit before the ContSearch " + "filter.\n"); + } + return EXCEPTION_EXECUTE_HANDLER; +} + +void NestedFunc1 (void) +{ + int* p = 0x00000000; /* pointer to NULL */ + + PAL_TRY + { + PAL_TRY + { + + if (bExcept1 || bExcept2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n"); + } + bTry2 = TRUE; /* indicate we hit the inner PAL_TRY block */ + *p = 13; /* causes an access violation exception */ + + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " We executed beyond the trapping code.\n"); + } + PAL_FINALLY + { + if (!bTry1) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The first finally handler was hit without the outer " + "PAL_TRY's code being hit.\n"); + } + if (!bTry2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The first finally handler was hit without the inner " + "PAL_TRY's code being hit.\n"); + } + if (!bFilterCS) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The first finally handler was hit without the inner " + "filter being hit.\n"); + } + if (!bFilterEE) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The first finally handler handler was hit without the " + "outer filter being hit.\n"); + } + bFinally1 = TRUE; /* indicate we hit the first finally block */ + } + PAL_ENDTRY; + } + PAL_EXCEPT_FILTER(ContSearchFilter, (LPVOID)&nValidator) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The dummy handler was " + "being hit.\n"); + bExcept2 = TRUE; /* indicate we hit the inner block */ + } + PAL_ENDTRY; + +} + +void NestedFunc2 (void) +{ + PAL_TRY + { + NestedFunc1(); + } + PAL_FINALLY + { + if (!bFinally1) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " The second finally handler handler was hit without the " + " top level one being hit.\n"); + } + bFinally2 = TRUE; + } + PAL_ENDTRY ; +} + +int __cdecl main(int argc, char *argv[]) +{ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* + ** test to make sure we get into the second exception block only based + ** on the return codes of the filters + */ + + PAL_TRY + { + PAL_TRY + { + PAL_TRY + { + if (bExcept1 || bExcept2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going" + " on. PAL_EXCEPT_FILTER was hit before PAL_TRY.\n"); + } + bTry1 = TRUE; /* indicate we hit the outer PAL_TRY block */ + + NestedFunc2(); + + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " We executed beyond the trapping code.\n"); + } + PAL_FINALLY + { + if (!bFinally2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going" + " on. Finally handlers hit out of order (2->3)\n"); + } + bFinally3 = TRUE; + } + PAL_ENDTRY; + } + PAL_EXCEPT_FILTER(ExecExeptionFilter, (LPVOID)&nValidator) + { + if (!bTry1) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER's handler was hit without the outer " + "PAL_TRY's code being hit.\n"); + } + if (!bTry2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER's handler was hit without the inner " + "PAL_TRY's code being hit.\n"); + } + if (!bFilterCS) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER's handler was hit without the inner " + "filter being hit.\n"); + } + if (!bFilterEE) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " PAL_EXCEPT_FILTER's handler was hit without the outer " + "filter being hit.\n"); + } + bExcept1 = TRUE; /* indicate we hit the outer block */ + } + PAL_ENDTRY; + + if (bFinally4) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " Finally handler # 4 executed before it should be \n"); + } + } + PAL_FINALLY + { + if (!bExcept1 || bExcept2) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " Exceptions handlers hit in wierd ways\n"); + } + if (!bFinally3) + { + Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on." + " Finally handlers hit out of order 3->4)\n"); + } + + bFinally4 = TRUE; + } + PAL_ENDTRY; + + if (!bTry1) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the outer" + " PAL_TRY block was not executed.\n"); + } + + if (!bTry2) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the inner" + " PAL_TRY block was not executed.\n"); + } + + if (bExcept2) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the " + "inner PAL_EXCEPT_FILTER block was executed.\n"); + } + if (!bExcept1) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the " + "outer PAL_EXCEPT_FILTER block was not executed.\n"); + } + + if (!bFilterCS) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the " + "search continuing filter" + " function was not executed.\n"); + } + if (!bFilterEE) + { + Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the " + "execute handler filter" + " function was not executed.\n"); + } + + /* did we hit all the code blocks? */ + if (!bFinally1 || !bFinally2 || !bFinally3 || !bFinally4) + { + Fail(""); + } + if(!bTry1 || !bTry2 || !bExcept1 || bExcept2 || !bFilterEE || !bFilterCS ) + { + Fail(""); + } + + + PAL_Terminate(); + return PASS; + +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/test1/testinfo.dat new file mode 100644 index 0000000..5c26243 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_finally/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = PAL_FINALLY +Name = Test for nested PAL_FINALLY +Type = DEFAULT +EXE1 = pal_finally +LANG = cpp +Description += Tests the PAL implementation of the PAL_FINALLY in the presence += of a call stack. An exception is forced and passed to two nested += exception filters for consideration. The first filter returns += EXCEPTION_CONTINUE_SEARCH so the second can run and return += EXCEPTION_EXECUTE_HANDLER. The initial exception handler should += be skipped, and the second executed, and all the PAL_FINALLY += blocks handled. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt new file mode 100644 index 0000000..37ff7de --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt @@ -0,0 +1,94 @@ +if(CLR_CMAKE_HOST_UNIX) + add_definitions(-DFEATURE_ENABLE_HARDWARE_EXCEPTIONS) +endif(CLR_CMAKE_HOST_UNIX) + +# Set the RPATH of paltest_pal_sxs_test1 so that it can find dependencies without needing to set LD_LIBRARY +# For more information: http://www.cmake.org/Wiki/CMake_RPATH_handling. +if(CORECLR_SET_RPATH) + if(CLR_CMAKE_HOST_LINUX) + set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) + set(CMAKE_INSTALL_RPATH "\$ORIGIN") + endif(CLR_CMAKE_HOST_LINUX) +endif(CORECLR_SET_RPATH) + +# Test DLL1 + +set(DEF_SOURCES1 dlltest1.src) +convert_to_absolute_path(DEF_SOURCES1 ${DEF_SOURCES1}) +set(EXPORTS_FILE1 ${CMAKE_CURRENT_BINARY_DIR}/dlltest1.exports) +generate_exports_file(${DEF_SOURCES1} ${EXPORTS_FILE1}) + +if(CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD) + set(EXPORTS_LINKER_OPTION1 -Wl,--version-script=${EXPORTS_FILE1}) +endif(CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD) + +if(CLR_CMAKE_TARGET_OSX) + set(EXPORTS_LINKER_OPTION1 -Wl,-exported_symbols_list,${EXPORTS_FILE1}) +endif(CLR_CMAKE_TARGET_OSX) + +if(CLR_CMAKE_HOST_SUNOS) + # Add linker exports file option + set(EXPORTS_LINKER_OPTION -Wl,-M,${EXPORTS_FILE}) +endif(CLR_CMAKE_HOST_SUNOS) + +set(DLL1SOURCES dlltest1.cpp) +add_library(paltest_pal_sxs_test1_dll1 SHARED ${DLL1SOURCES}) +add_custom_target(dlltest1_exports DEPENDS ${EXPORTS_FILE1}) +set_property(TARGET paltest_pal_sxs_test1_dll1 APPEND_STRING PROPERTY LINK_FLAGS ${EXPORTS_LINKER_OPTION1}) +set_property(TARGET paltest_pal_sxs_test1_dll1 APPEND_STRING PROPERTY LINK_DEPENDS ${EXPORTS_FILE1}) + +add_dependencies(paltest_pal_sxs_test1_dll1 + dlltest1_exports + coreclrpal +) + +target_link_libraries(paltest_pal_sxs_test1_dll1 + ${COMMON_TEST_LIBRARIES} + m + coreclrpal +) + +# Test DLL2 + +set(DEF_SOURCES2 dlltest2.src) +convert_to_absolute_path(DEF_SOURCES2 ${DEF_SOURCES2}) +set(EXPORTS_FILE2 ${CMAKE_CURRENT_BINARY_DIR}/dlltest2.exports) +generate_exports_file(${DEF_SOURCES2} ${EXPORTS_FILE2}) + +if(CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD) + set(EXPORTS_LINKER_OPTION2 -Wl,--version-script=${EXPORTS_FILE2}) +endif(CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD) + +if(CLR_CMAKE_TARGET_OSX) + set(EXPORTS_LINKER_OPTION2 -Wl,-exported_symbols_list,${EXPORTS_FILE2}) +endif(CLR_CMAKE_TARGET_OSX) + +set(DLL2SOURCES dlltest2.cpp) +add_library(paltest_pal_sxs_test1_dll2 SHARED ${DLL2SOURCES}) +add_custom_target(dlltest2_exports DEPENDS ${EXPORTS_FILE2}) +set_property(TARGET paltest_pal_sxs_test1_dll2 APPEND_STRING PROPERTY LINK_FLAGS ${EXPORTS_LINKER_OPTION2}) +set_property(TARGET paltest_pal_sxs_test1_dll2 APPEND_STRING PROPERTY LINK_DEPENDS ${EXPORTS_FILE2}) + +add_dependencies(paltest_pal_sxs_test1_dll2 + dlltest2_exports +) + +target_link_libraries(paltest_pal_sxs_test1_dll2 + ${COMMON_TEST_LIBRARIES} +) + +# Main program + +set(TESTSOURCES exceptionsxs.cpp) + +add_executable(paltest_pal_sxs_test1 ${TESTSOURCES}) + +add_dependencies(paltest_pal_sxs_test1 + paltest_pal_sxs_test1_dll1 + paltest_pal_sxs_test1_dll2 +) + +target_link_libraries(paltest_pal_sxs_test1 + paltest_pal_sxs_test1_dll1 + paltest_pal_sxs_test1_dll2 +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp new file mode 100644 index 0000000..bbcb664 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp @@ -0,0 +1,92 @@ +// 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. + +/*===================================================================== +** +** Source: dlltest1.c (exception_handling\pal_sxs\test1) +** +** Purpose: Test to make sure the PAL_EXCEPT block is executed +** after an exception occurs in the PAL_TRY block with +** multiple PALs in the process. +** +** +**===================================================================*/ +#include + +extern "C" +int +PALAPI +InitializeDllTest1() +{ + PAL_SetInitializeDLLFlags(PAL_INITIALIZE_DLL | PAL_INITIALIZE_REGISTER_SIGNALS); + return PAL_InitializeDLL(); +} + +__attribute__((noinline,NOOPT_ATTRIBUTE)) +static void FailingFunction(volatile int *p) +{ + if (p == NULL) + { + throw PAL_SEHException(); + } + + *p = 1; // Causes an access violation exception +} + +BOOL bTry = FALSE; +BOOL bExcept = FALSE; + +extern "C" +int +PALAPI +DllTest1() +{ + Trace("Starting pal_sxs test1 DllTest1\n"); + + PAL_TRY(VOID*, unused, NULL) + { + volatile int* p = (volatile int *)0x11; // Invalid pointer + + bTry = TRUE; // Indicate we hit the PAL_TRY block + FailingFunction(p); // Throw in function to fool C++ runtime into handling + // h/w exception + + Fail("ERROR: code was executed after the access violation.\n"); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry) + { + Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n"); + } + + // Validate that the faulting address is correct; the contents of "p" (0x11). + if (ex.GetExceptionRecord()->ExceptionInformation[1] != 0x11) + { + Fail("ERROR: PAL_EXCEPT ExceptionInformation[1] != 0x11\n"); + } + + bExcept = TRUE; // Indicate we hit the PAL_EXCEPT block + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("ERROR: the code in the PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n"); + } + + // Did we hit all the code blocks? + if(!bTry || !bExcept) + { + Fail("DllTest1 FAILED\n"); + } + + Trace("DLLTest1 PASSED\n"); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.src b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.src new file mode 100644 index 0000000..0a0a6ee --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.src @@ -0,0 +1,3 @@ +InitializeDllTest1 +DllTest1 + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp new file mode 100644 index 0000000..084d990 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp @@ -0,0 +1,92 @@ +// 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. + +/*===================================================================== +** +** Source: dlltest2.c (exception_handling\pal_sxs\test1) +** +** Purpose: Test to make sure the PAL_EXCEPT block is executed +** after an exception occurs in the PAL_TRY block with +** multiple PALs in the process. +** +** +**===================================================================*/ +#include + +extern "C" +int +PALAPI +InitializeDllTest2() +{ + PAL_SetInitializeDLLFlags(PAL_INITIALIZE_DLL | PAL_INITIALIZE_REGISTER_SIGNALS); + return PAL_InitializeDLL(); +} + +__attribute__((noinline,NOOPT_ATTRIBUTE)) +static void FailingFunction(volatile int *p) +{ + if (p == NULL) + { + throw PAL_SEHException(); + } + + *p = 1; // Causes an access violation exception +} + +BOOL bTry = FALSE; +BOOL bExcept = FALSE; + +extern "C" +int +PALAPI +DllTest2() +{ + Trace("Starting pal_sxs test1 DllTest2\n"); + + PAL_TRY(VOID*, unused, NULL) + { + volatile int* p = (volatile int *)0x22; // Invalid pointer + + bTry = TRUE; // Indicate we hit the PAL_TRY block + FailingFunction(p); // Throw in function to fool C++ runtime into handling + // h/w exception + + Fail("ERROR: code was executed after the access violation.\n"); + } + PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + if (!bTry) + { + Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n"); + } + + // Validate that the faulting address is correct; the contents of "p" (0x22). + if (ex.GetExceptionRecord()->ExceptionInformation[1] != 0x22) + { + Fail("ERROR: PAL_EXCEPT ExceptionInformation[1] != 0x22\n"); + } + + bExcept = TRUE; // Indicate we hit the PAL_EXCEPT block + } + PAL_ENDTRY; + + if (!bTry) + { + Trace("ERROR: the code in the PAL_TRY block was not executed.\n"); + } + + if (!bExcept) + { + Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n"); + } + + // Did we hit all the code blocks? + if(!bTry || !bExcept) + { + Fail("DllTest2 FAILED\n"); + } + + Trace("DLLTest2 PASSED\n"); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.src b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.src new file mode 100644 index 0000000..433419b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.src @@ -0,0 +1,3 @@ +InitializeDllTest2 +DllTest2 + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp new file mode 100644 index 0000000..97a963c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp @@ -0,0 +1,117 @@ +// 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. + +/*===================================================================== +** +** Source: exceptionsxs.c (exception_handling\pal_sxs\test1) +** +** Purpose: Test to make sure the PAL_EXCEPT block is executed +** after an exception occurs in the PAL_TRY block with +** multiple PALs in the process. +** +** +**===================================================================*/ + +#include +#include +#include +#include +#include +#include + +enum +{ + PASS = 0, + FAIL = 1 +}; + +extern "C" int InitializeDllTest1(); +extern "C" int InitializeDllTest2(); +extern "C" int DllTest1(); +extern "C" int DllTest2(); + +bool bSignal = false; +bool bCatch = false; +bool bHandler = false; + +void sigsegv_handler(int code, siginfo_t *siginfo, void *context) +{ + printf("pal_sxs test1: signal handler called\n"); + bHandler = true; // Mark that the signal handler was executed + + if (!bSignal) + { + printf("ERROR: executed signal handler NOT from try/catch\n"); + _exit(FAIL); + } + + // Validate that the faulting address is correct; the contents of "p" (0x22). + if (siginfo->si_addr != (void *)0x33) + { + printf("ERROR: signal handler faulting address != 0x33\n"); + _exit(FAIL); + } + + // Unmask signal so we can receive it again + sigset_t signal_set; + sigemptyset(&signal_set); + sigaddset(&signal_set, SIGSEGV); + if (-1 == sigprocmask(SIG_UNBLOCK, &signal_set, NULL)) + { + printf("ERROR: sigprocmask failed; error is %d\n", errno); + _exit(FAIL); + } + + printf("Signal chaining PASSED\n"); + _exit(PASS); +} + +int main(int argc, char *argv[]) +{ + struct sigaction newAction; + struct sigaction oldAction; + newAction.sa_flags = SA_SIGINFO | SA_RESTART; + newAction.sa_handler = NULL; + newAction.sa_sigaction = sigsegv_handler; + sigemptyset(&newAction.sa_mask); + + if (-1 == sigaction(SIGSEGV, &newAction, &oldAction)) + { + printf("ERROR: sigaction failed; error is %d\n", errno); + return FAIL; + } + + printf("PAL_SXS test1 SIGSEGV handler %p\n", oldAction.sa_sigaction); + + if (0 != InitializeDllTest1()) + { + return FAIL; + } + + if (0 != InitializeDllTest2()) + { + return FAIL; + } + + // Test catching exceptions in other PAL instances + DllTest2(); + DllTest1(); + DllTest2(); + + if (bHandler) + { + printf("ERROR: signal handler called by PAL sxs tests\n"); + return FAIL; + } + + printf("Starting PAL_SXS test1 signal chaining\n"); + + bSignal = true; + + volatile int* p = (volatile int *)0x33; // Invalid pointer + *p = 3; // Causes an access violation exception + + printf("ERROR: code was executed after the access violation.\n"); + return FAIL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/testinfo.dat new file mode 100644 index 0000000..c0cf1dd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = exception_handling +Function = test1 +Name = pal_sxs test #1 +TYPE = DEFAULT +EXE1 = test1 +LANG = cpp +Description +=Tests that exceptions across multiples pals work correctly diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CMakeLists.txt new file mode 100644 index 0000000..b9b0052 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CMakeLists.txt @@ -0,0 +1,39 @@ +add_subdirectory(CopyFileA) +add_subdirectory(CopyFileW) +add_subdirectory(CreateFileA) +add_subdirectory(CreateFileW) +add_subdirectory(DeleteFileA) +add_subdirectory(DeleteFileW) +add_subdirectory(errorpathnotfound) +add_subdirectory(FILECanonicalizePath) +add_subdirectory(FindClose) +add_subdirectory(FindFirstFileA) +add_subdirectory(FindFirstFileW) +add_subdirectory(FindNextFileA) +add_subdirectory(FindNextFileW) +add_subdirectory(FlushFileBuffers) +add_subdirectory(GetConsoleOutputCP) +add_subdirectory(GetCurrentDirectoryA) +add_subdirectory(GetCurrentDirectoryW) +add_subdirectory(GetFileAttributesA) +add_subdirectory(GetFileAttributesExW) +add_subdirectory(GetFileAttributesW) +add_subdirectory(GetFileSize) +add_subdirectory(GetFileSizeEx) +add_subdirectory(GetFullPathNameA) +add_subdirectory(GetFullPathNameW) +add_subdirectory(GetStdHandle) +add_subdirectory(GetSystemTime) +add_subdirectory(GetSystemTimeAsFileTime) +add_subdirectory(GetTempFileNameA) +add_subdirectory(GetTempFileNameW) +add_subdirectory(gettemppatha) +add_subdirectory(GetTempPathW) +add_subdirectory(MoveFileExA) +add_subdirectory(MoveFileExW) +add_subdirectory(ReadFile) +add_subdirectory(SearchPathW) +add_subdirectory(SetEndOfFile) +add_subdirectory(SetFilePointer) +add_subdirectory(WriteFile) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/CMakeLists.txt new file mode 100644 index 0000000..070e421 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test1/CMakeLists.txt new file mode 100644 index 0000000..7c06a0f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CopyFileA.cpp +) + +add_executable(paltest_copyfilea_test1 + ${SOURCES} +) + +add_dependencies(paltest_copyfilea_test1 coreclrpal) + +target_link_libraries(paltest_copyfilea_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.cpp new file mode 100644 index 0000000..bfea85b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.cpp @@ -0,0 +1,159 @@ +// 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. + +/*===================================================================== +** +** Source: CopyFileA.c +** +** Purpose: Tests the PAL implementation of the CopyFileA function +** +** +**===================================================================*/ + +/* + 1. copy an existing file to existing with overwrite true + 2. copy an existing file to existing with overwrite false + 3. copy an existing file to non-existant with overwrite true + 4. copy an existing file to non-existant with overwrite false + 5. copy non-existant file to existing with overwrite true + 6. copy non-existant file to existing with overwrite false + 7. copy non-existant file to non-existant with overwrite true + 8. copy non-existant file to non-existant with overwrite false +*/ + +#include + +struct TESTS{ + char* lpSource; + char* lpDestination; + BOOL bFailIfExists; + int nResult; + }; + + +int __cdecl main(int argc, char *argv[]) +{ + char szSrcExisting[] = {"src_existing.tmp"}; + char szSrcNonExistant[] = {"src_non-existant.tmp"}; + char szDstExisting[] = {"dst_existing.tmp"}; + char szDstNonExistant[] = {"dst_non-existant.tmp"}; + BOOL bRc = TRUE; + BOOL bSuccess = TRUE; + FILE* tempFile = NULL; + int i; + struct TESTS testCase[] = + { + {szSrcExisting, szDstExisting, FALSE, 1}, + {szSrcExisting, szDstExisting, TRUE, 0}, + {szSrcExisting, szDstNonExistant, FALSE, 1}, + {szSrcExisting, szDstNonExistant, TRUE, 1}, + {szSrcNonExistant, szDstExisting, FALSE, 0}, + {szSrcNonExistant, szDstExisting, TRUE, 0}, + {szSrcNonExistant, szDstNonExistant, FALSE, 0}, + {szSrcNonExistant, szDstNonExistant, TRUE, 0} + }; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create the src_existing file */ + tempFile = fopen(szSrcExisting, "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "CopyFileA test file: src_existing.tmp\n"); + fclose(tempFile); + } + else + { + Fail("CopyFileA: ERROR-> Couldn't create \"src_existing.tmp\" with " + "error %ld\n", + GetLastError()); + } + + /* create the dst_existing file */ + tempFile = fopen(szDstExisting, "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "CopyFileA test file: dst_existing.tmp\n"); + fclose(tempFile); + } + else + { + Fail("CopyFileA: ERROR-> Couldn't create \"dst_existing.tmp\" with " + "error %ld\n", + GetLastError()); + } + + + + for (i = 0; i < (sizeof(testCase) / sizeof(struct TESTS)); i++) + { + bRc = CopyFileA(testCase[i].lpSource, + testCase[i].lpDestination, + testCase[i].bFailIfExists); + if (!bRc) + { + if (testCase[i].nResult == 1) + { + Trace("CopyFileA: FAILED: %s -> %s with bFailIfExists = %d " + "with error %ld\n", + testCase[i].lpSource, + testCase[i].lpDestination, + testCase[i].bFailIfExists, + GetLastError()); + bSuccess = FALSE; + } + } + else + { + if (testCase[i].nResult == 0) + { + Trace("CopyFileA: FAILED: %s -> %s with bFailIfExists = %d\n", + testCase[i].lpSource, + testCase[i].lpDestination, + testCase[i].bFailIfExists); + bSuccess = FALSE; + } + else + { + /* verify the file was moved */ + if (GetFileAttributesA(testCase[i].lpDestination) == -1) + { + Trace("CopyFileA: GetFileAttributes of destination file " + "failed with error code %ld. \n", + GetLastError()); + bSuccess = FALSE; + } + else if (GetFileAttributesA(testCase[i].lpSource) == -1) + { + Trace("CopyFileA: GetFileAttributes of source file " + "failed with error code %ld. \n", + GetLastError()); + bSuccess = FALSE; + } + else + { + /* verify attributes of destination file to source file*/ + if(GetFileAttributes(testCase[i].lpSource) != + GetFileAttributes(testCase[i].lpDestination)) + { + Trace("CopyFileA : The file attributes of the " + "destination file do not match the file " + "attributes of the source file.\n"); + bSuccess = FALSE; + } + } + } + } + /* delete file file but don't worry if it fails */ + DeleteFileA(szDstNonExistant); + } + + int exitCode = bSuccess ? PASS : FAIL; + PAL_TerminateEx(exitCode); + return exitCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test1/testinfo.dat new file mode 100644 index 0000000..88b9c73 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = file_io +Function = CopyFileA +Name = Test for CopyFileA (test 1) +Type = DEFAULT +EXE1 = copyfilea +Description += Test the CopyFileA function diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test2/CMakeLists.txt new file mode 100644 index 0000000..1299350 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_copyfilea_test2 + ${SOURCES} +) + +add_dependencies(paltest_copyfilea_test2 coreclrpal) + +target_link_libraries(paltest_copyfilea_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test2/test2.cpp new file mode 100644 index 0000000..56618d0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test2/test2.cpp @@ -0,0 +1,120 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Tests the PAL implementation of the CopyFileA function +** to see if a file can be copied to itself +** +** +**===================================================================*/ + + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + BOOL bRc = TRUE; + char* szSrcExisting = "src_existing.tmp"; + FILE* tempFile = NULL; + DWORD temp; + int retCode; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create the src_existing file */ + tempFile = fopen(szSrcExisting, "w"); + if (tempFile != NULL) + { + retCode = fputs("CopyFileA test file: src_existing.tmp ", tempFile); + if(retCode < 0) + { + Fail("CopyFileA: ERROR-> Couldn't write to %s with error " + "%u.\n", szSrcExisting, GetLastError()); + } + retCode = fclose(tempFile); + if(retCode != 0) + { + Fail("CopyFileA: ERROR-> Couldn't close file: %s with error " + "%u.\n", szSrcExisting, GetLastError()); + } + + } + else + { + Fail("CopyFileA: ERROR-> Couldn't create %s with " + "error %ld\n",szSrcExisting,GetLastError()); + } + + /* Get file attributes of source */ + temp = GetFileAttributes(szSrcExisting); + if (temp == -1) + { + Fail("CopyFileA: GetFileAttributes of source file " + "failed with error code %ld. \n", + GetLastError()); + } + + /* make sure a file can't copy to itself + first testing with IfFileExists flag set to true */ + bRc = CopyFileA(szSrcExisting,szSrcExisting,TRUE); + if(bRc) + { + Fail("ERROR: Cannot copy a file to itself, %u",GetLastError()); + } + + /* try to get file attributes of desitnation */ + if (GetFileAttributesA(szSrcExisting) == -1) + { + Fail("CopyFileA: GetFileAttributes of destination file " + "failed with error code %ld. \n", + GetLastError()); + } + else + { + /* verify attributes of destination file to source file*/ + + if(temp != GetFileAttributes(szSrcExisting)) + { + Fail("CopyFileA : The file attributes of the " + "destination file do not match the file " + "attributes of the source file.\n"); + } + } + + /* testing with IfFileExists flags set to false + should fail in Windows and pass in UNIX */ + bRc = CopyFileA(szSrcExisting,szSrcExisting,FALSE); + if(bRc && (GetLastError() != ERROR_ALREADY_EXISTS)) + { + Fail("ERROR: Cannot copy a file to itself, %u",GetLastError()); + } + + if (GetFileAttributesA(szSrcExisting) == -1) + { + Fail("CopyFileA: GetFileAttributes of destination file " + "failed with error code %ld. \n", + GetLastError()); + } + else + { + /* verify attributes of destination file to source file*/ + + if(temp != GetFileAttributes(szSrcExisting)) + { + Fail("CopyFileA : The file attributes of the " + "destination file do not match the file " + "attributes of the source file.\n"); + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test2/testinfo.dat new file mode 100644 index 0000000..3114384 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = CopyFileA +Name = CopyFileA - checking copying to itself (test2) +Type = DEFAULT +EXE1 = test2 +Description += Test the CopyFileA function's behaviour += for copying a file to itself. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test3/CMakeLists.txt new file mode 100644 index 0000000..92316b4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_copyfilea_test3 + ${SOURCES} +) + +add_dependencies(paltest_copyfilea_test3 coreclrpal) + +target_link_libraries(paltest_copyfilea_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test3/test3.cpp new file mode 100644 index 0000000..b28bfe3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test3/test3.cpp @@ -0,0 +1,141 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Tests the PAL implementation of the CopyFileA function +** to see if a file can be copied to itself +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + BOOL bRc = TRUE; + char* szSrcExisting = "src_existing.tmp"; + char* szDest = "src_dest.tmp"; + FILE* tempFile = NULL; + int retCode; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create the src_existing file */ + tempFile = fopen(szSrcExisting, "w"); + if (tempFile != NULL) + { + retCode = fputs("CopyFileA test file: src_existing.tmp ", tempFile); + if(retCode < 0) + { + retCode = fclose(tempFile); + if(retCode != 0) + { + Trace("CopyFileA: ERROR-> Couldn't close file: %s with error " + "%u.\n", szSrcExisting, GetLastError()); + } + + Fail("CopyFileA: ERROR-> Couldn't write to %s with error " + "%u.\n", szSrcExisting, GetLastError()); + } + retCode = fclose(tempFile); + if(retCode != 0) + { + Fail("CopyFileA: ERROR-> Couldn't close file: %s with error " + "%u.\n", szSrcExisting, GetLastError()); + } + + } + else + { + Fail("CopyFileA: ERROR-> Couldn't create %s with " + "error %ld\n",szSrcExisting,GetLastError()); + } + + /* set the file attributes of the source file to readonly */ + bRc = SetFileAttributesA(szSrcExisting, FILE_ATTRIBUTE_READONLY); + if(!bRc) + { + Fail("CopyFileA: ERROR-> Couldn't set file attributes for " + "file %s with error %u\n", szSrcExisting, GetLastError()); + } + + // Check the file attributes to make sure SetFileAttributes() above actually succeeded + DWORD fileAttributes = GetFileAttributesA(szSrcExisting); + if (fileAttributes == INVALID_FILE_ATTRIBUTES) + { + Fail("CopyFileA: Failed to get file attributes for source file, %u\n", GetLastError()); + } + if ((fileAttributes & FILE_ATTRIBUTE_READONLY) == 0) + { + Fail("CopyFileA: SetFileAttributes(read-only) on source file returned success but did not make it read-only.\n"); + } + + /* copy the file */ + bRc = CopyFileA(szSrcExisting,szDest,TRUE); + if(!bRc) + { + Fail("CopyFileA: Cannot copy a file with error, %u",GetLastError()); + } + + + /* try to get file attributes of destination file */ + fileAttributes = GetFileAttributesA(szDest); + if (fileAttributes == INVALID_FILE_ATTRIBUTES) + { + Fail("CopyFileA: GetFileAttributes of destination file " + "failed with error code %ld. \n", + GetLastError()); + } + + /* verify attributes of destination file to source file*/ + if((fileAttributes & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY) + { + Fail("CopyFileA : The file attributes of the " + "destination file do not match the file " + "attributes of the source file.\n"); + } + + /* set the attributes of the destination file to normal again */ + bRc = SetFileAttributesA(szDest, FILE_ATTRIBUTE_NORMAL); + if(!bRc) + { + Fail("CopyFileA: ERROR-> Couldn't set file attributes for " + "file %s with error %u\n", szDest, GetLastError()); + } + + /* delete the newly copied file */ + bRc = DeleteFile(szDest); + if(!bRc) + { + Fail("CopyFileA: DeleteFile failed to delete the" + "file correctly with error,%u.\n",GetLastError()); + } + + /* set the attributes of the source file to normal again */ + bRc = SetFileAttributesA(szSrcExisting, FILE_ATTRIBUTE_NORMAL); + if(!bRc) + { + Fail("CopyFileA: ERROR-> Couldn't set file attributes for " + "file %s with error %u\n", szSrcExisting, GetLastError()); + } + + /* delete the original file */ + bRc = DeleteFile(szSrcExisting); + if(!bRc) + { + Fail("CopyFileA: DeleteFile failed to delete the" + "file correctly with error,%u.\n",GetLastError()); + } + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test3/testinfo.dat new file mode 100644 index 0000000..5a9775d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test3/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = CopyFileA +Name = CopyFileA - checking file attributes maintained (test2) +Type = DEFAULT +EXE1 = test3 +Description += Test the CopyFileA function's behaviour += for copying a file and verifying that += the copied file has the same file attributes += as the original. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test4/CMakeLists.txt new file mode 100644 index 0000000..71318e8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_copyfilea_test4 + ${SOURCES} +) + +add_dependencies(paltest_copyfilea_test4 coreclrpal) + +target_link_libraries(paltest_copyfilea_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test4/test4.cpp new file mode 100644 index 0000000..4a99938 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test4/test4.cpp @@ -0,0 +1,180 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c +** +** Purpose: Tests the PAL implementation of the CopyFileA function +** to see if a file can through different users belonging to +** different groups. +** + +=====================================================================*/ + +/* USECASE + Copy a file from a different user, belonging to a different group to + the the current user, who is a member of the current group. Then check + to see that the current user has the basic access rights to the copied + file. + + Thie original file used is the passwd file in the etc directory of a + BSD machine. This file should exist on all machines. +*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + return PASS; + +#else + + BOOL bRc = TRUE; + char* szSrcExisting = "/etc/passwd"; + char* szDest = "temp.tmp"; + char* szStringTest = "Marry had a little lamb"; + char szStringRead[30]; /* large enough for string szStringTest */ + + HANDLE hFile = NULL; + DWORD dwBytesWritten=0; + DWORD dwBytesRead=0; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* copy the file */ + bRc = CopyFileA(szSrcExisting,szDest,TRUE); + if(!bRc) + { + Fail("CopyFileA: Cannot copy a file with error, %u",GetLastError()); + } + + /* try to get file attributes of destination file */ + if (GetFileAttributesA(szDest) == -1) + { + Fail("CopyFileA: GetFileAttributes of destination file " + "failed with error code %u. \n", + GetLastError()); + } + + /* set the attributes of the destination file to normal again */ + bRc = SetFileAttributesA(szDest, FILE_ATTRIBUTE_NORMAL); + if(!bRc) + { + Fail("CopyFileA: ERROR-> Couldn't set file attributes for " + "file %s with error %u\n", szDest, GetLastError()); + } + + /* open the file for write purposes */ + hFile = CreateFile(szDest, + GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("CopyFileA: ERROR -> Unable to create file \"%s\".\n", + szDest); + } + + /* Attempt to write to the file */ + bRc = WriteFile(hFile, szStringTest, strlen(szStringTest), &dwBytesWritten, NULL); + if (!bRc) + { + Trace("CopyFileA: ERROR -> Unable to write to copied file with error " + "%u.\n", GetLastError()); + bRc = CloseHandle(hFile); + if (!bRc) + { + Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with " + "error %u.\n",szDest, GetLastError()); + } + Fail(""); + + } + + /* Close the file handle */ + bRc = CloseHandle(hFile); + if (!bRc) + { + Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with error %u " + ".\n",szDest,GetLastError()); + } + + + /* open the file for read purposes */ + hFile = CreateFile(szDest, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("CopyFileA: ERROR -> Unable to create file \"%s\".\n", + szDest); + } + + /* Attempt to read from the file */ + bRc = ReadFile(hFile, szStringRead, strlen(szStringTest), &dwBytesRead, NULL); + if (!bRc) + { + Trace("CopyFileA: ERROR -> Unable to read from copied file with " + "error %u.\n",GetLastError()); + bRc = CloseHandle(hFile); + if (!bRc) + { + Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with " + "error %u.\n",szDest, GetLastError()); + } + Fail(""); + + } + + if(strncmp(szStringTest,szStringRead, strlen(szStringTest)) != 0) + { + Trace("CopyFileA: ERROR -> The string which was written '%s' does not " + "match the string '%s' which was read from the copied file.\n", + szStringTest,szStringRead); + bRc = CloseHandle(hFile); + if (!bRc) + { + Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with " + "error %u.\n",szDest, GetLastError()); + } + Fail(""); + } + + /* Close the file handle */ + bRc = CloseHandle(hFile); + if (!bRc) + { + Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with error %u " + ".\n",szDest,GetLastError()); + } + + /* Remove the temporary file */ + bRc = DeleteFile(szDest); + if(!bRc) + { + Fail("CopyFileA: Could not remove copied file with error %u\n", + GetLastError()); + } + + PAL_Terminate(); + return PASS; + +#endif + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test4/testinfo.dat new file mode 100644 index 0000000..42187b7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileA/test4/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = CopyFileA +Name = CopyFileA - checking file attributes maintained (test4) +Type = DEFAULT +EXE1 = test4 +Description += Copy a file from a different user, belonging to a different group to += the the current user, who is a member of the current group. Then check += to see that the current user has the basic access rights to the copied += file. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/CMakeLists.txt new file mode 100644 index 0000000..182997d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CopyFileW.cpp +) + +add_executable(paltest_copyfilew_test1 + ${SOURCES} +) + +add_dependencies(paltest_copyfilew_test1 coreclrpal) + +target_link_libraries(paltest_copyfilew_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.cpp new file mode 100644 index 0000000..6127cc2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.cpp @@ -0,0 +1,155 @@ +// 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. + +/*===================================================================== +** +** Source: CopyFileW.c +** +** Purpose: Tests the PAL implementation of the CopyFileW function +** +** +**===================================================================*/ + +/* +1. copy an existing file to non-existant with overwrite true +2. copy an existing file to non-existant with overwrite false +3. copy an existing file to existing with overwrite true +4. copy an existing file to existing with overwrite false +5. copy non-existant file to non-existant with overwrite true +6. copy non-existant file to non-existant with overwrite false +7. copy non-existant file to existing with overwrite true +8. copy non-existant file to existing with overwrite false +*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + LPSTR lpSource[2] = {"src_existing.tmp", "src_non-existant.tmp"}; + LPSTR lpDestination[2] = {"dst_existing.tmp", "dst_non-existant.tmp"}; + WCHAR* wcSource; + WCHAR* wcDest; + BOOL bFailIfExists[3] = {FALSE, TRUE}; + BOOL bRc = TRUE; + BOOL bSuccess = TRUE; + char results[20]; + FILE* resultsFile = NULL; + FILE* tempFile = NULL; + int nCounter = 0; + int i, j, k; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* load the expected results */ + resultsFile = fopen("expectedresults.txt", "r"); + memset (results, 0, 20); + fgets(results, 20, resultsFile); + fclose(resultsFile); + + nCounter = 0; + + /* create the src_existing file */ + tempFile = fopen(lpSource[0], "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "CopyFileW test file: src_existing.tmp\n"); + fclose(tempFile); + } + else + { + Fail("CopyFileW: ERROR-> Couldn't create \"src_existing.tmp\"\n"); + } + + /* create the dst_existing file */ + tempFile = fopen(lpDestination[0], "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "CopyFileW test file: dst_existing.tmp\n"); + fclose(tempFile); + } + else + { + Fail("CopyFileW: ERROR-> Couldn't create \"dst_existing.tmp\"\n"); + } + + + /* lpSource loop */ + for (i = 0; i < 2; i++) + { + /* lpDestination loop */ + for (j = 0; j < 2; j++) + { + /* bFailIfExists loop */ + for (k = 0; k < 2; k++) + { + wcSource = convert(lpSource[i]); + wcDest = convert(lpDestination[j]); + bRc = CopyFileW(wcSource, + wcDest, + bFailIfExists[k]); + free(wcSource); + free(wcDest); + if (!bRc) + { + if (results[nCounter] == '1') + { + Trace("CopyFileW: FAILED: test[%d][%d][%d]\n", i, j, k); + bSuccess = FALSE; + } + } + else + { + if (results[nCounter] == '0') + { + Trace("CopyFileW: FAILED: test[%d][%d][%d]\n", i, j, k); + bSuccess = FALSE; + } + else + { + /* verify the file was moved */ + if (GetFileAttributesA(lpDestination[j]) == -1) + { + Trace("CopyFileW: GetFileAttributes of destination" + "file failed on test[%d][%d][%d] with error " + "code %ld. \n",i,j,k,GetLastError()); + bSuccess = FALSE; + } + else if (GetFileAttributesA(lpSource[i]) == -1) + { + Trace("CopyFileW: GetFileAttributes of source file " + "file failed on test[%d][%d][%d] with error " + "code %ld. \n",i,j,k,GetLastError()); + bSuccess = FALSE; + } + else + { + /* verify attributes of destination file to + source file*/ + if(GetFileAttributes(lpSource[i]) != + GetFileAttributes(lpDestination[j])) + { + Trace("CopyFileW : The file attributes of the " + "destination file do not match the file " + "attributes of the source file on test " + "[%d][%d][%d].\n",i,j,k); + bSuccess = FALSE; + } + } + } + + } + nCounter++; + /* delete file file but don't worry if it fails */ + DeleteFileA(lpDestination[1]); + } + } + } + + int exitCode = bSuccess ? PASS : FAIL; + PAL_TerminateEx(exitCode); + return exitCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/ExpectedResults.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/ExpectedResults.txt new file mode 100644 index 0000000..535a89f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/ExpectedResults.txt @@ -0,0 +1 @@ +10110000 \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/testinfo.dat new file mode 100644 index 0000000..b7ff6de --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = CopyFileW +Name = Tests CopyFileW functionality. +Type = DEFAULT +EXE1 = copyfilew +Description += Test the CopyFileW function + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test2/CMakeLists.txt new file mode 100644 index 0000000..dc88b3f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_copyfilew_test2 + ${SOURCES} +) + +add_dependencies(paltest_copyfilew_test2 coreclrpal) + +target_link_libraries(paltest_copyfilew_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test2/test2.cpp new file mode 100644 index 0000000..5380a18 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test2/test2.cpp @@ -0,0 +1,124 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Tests the PAL implementation of the CopyFileW function +** Attempt to copy a file to itself +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + LPSTR szSrcExisting = "src_existing.tmp"; + WCHAR* wcSource; + BOOL bRc = TRUE; + FILE* tempFile = NULL; + DWORD temp; + int retCode; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create the src_existing file */ + tempFile = fopen(szSrcExisting, "w"); + if (tempFile != NULL) + { + retCode = fputs("CopyFileA test file: src_existing.tmp ", tempFile); + if(retCode < 0) + { + Fail("CopyFileW: ERROR-> Couldn't write to %s with error " + "%u.\n", szSrcExisting, GetLastError()); + } + retCode = fclose(tempFile); + if(retCode != 0) + { + Fail("CopyFileW: ERROR-> Couldn't close file: %s with error " + "%u.\n", szSrcExisting, GetLastError()); + } + } + else + { + Fail("CopyFileW: ERROR-> Couldn't create %s.\n", szSrcExisting); + } + + /* convert source string to wide character */ + wcSource = convert(szSrcExisting); + + /* Get file attributes of source */ + temp = GetFileAttributes(szSrcExisting); + if (temp == -1) + { + free(wcSource); + Fail("CopyFileW: GetFileAttributes of source file " + "failed with error code %ld. \n", + GetLastError()); + } + + /* make sure a file can't copy to itself + first testing with IfFileExists flag set to true */ + bRc = CopyFileW(wcSource,wcSource,TRUE); + if(bRc) + { + free(wcSource); + Fail("ERROR: Cannot copy a file to itself, %u",GetLastError()); + } + + /* try to get file attributes of desitnation */ + if (GetFileAttributesA(szSrcExisting) == -1) + { + free(wcSource); + Fail("CopyFileW: GetFileAttributes of destination file " + "failed with error code %ld. \n", + GetLastError()); + } + else + { + /* verify attributes of destination file to source file*/ + if(temp != GetFileAttributes(szSrcExisting)) + { + free(wcSource); + Fail("CopyFileW : The file attributes of the " + "destination file do not match the file " + "attributes of the source file.\n"); + } + } + + /* testing with IfFileExists flags set to false + should fail in Windows and pass in UNIX */ + bRc = CopyFileW(wcSource,wcSource,FALSE); + free(wcSource); + if(bRc && (GetLastError() != ERROR_ALREADY_EXISTS)) + { + Fail("ERROR: Cannot copy a file to itself, %u",GetLastError()); + } + + if (GetFileAttributesA(szSrcExisting) == -1) + { + Fail("CopyFileW: GetFileAttributes of destination file " + "failed with error code %ld. \n", + GetLastError()); + } + else + { + /* verify attributes of destination file to source file*/ + + if(temp != GetFileAttributes(szSrcExisting)) + { + Fail("CopyFileW : The file attributes of the " + "destination file do not match the file " + "attributes of the source file.\n"); + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test2/testinfo.dat new file mode 100644 index 0000000..7e1591d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = CopyFileW +Name = Tests CopyFileW to check if file can be copied to itself. (test2) +Type = DEFAULT +EXE1 = test2 +Description += Test the CopyFileW function += to see the effect of copying a += file to itself. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test3/CMakeLists.txt new file mode 100644 index 0000000..f147367 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_copyfilew_test3 + ${SOURCES} +) + +add_dependencies(paltest_copyfilew_test3 coreclrpal) + +target_link_libraries(paltest_copyfilew_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test3/test3.cpp new file mode 100644 index 0000000..a2eb04c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test3/test3.cpp @@ -0,0 +1,196 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c +** +** Purpose: Tests the PAL implementation of the CopyFileW function +** to see if a file can through different users belonging to +** different groups. +** + +=====================================================================*/ + +/* USECASE + Copy a file from a different user, belonging to a different group to + the the current user, who is a member of the current group. Then check + to see that the current user has the basic access rights to the copied + file. + + Thie original file used is the passwd file in the etc directory of a + BSD machine. This file should exist on all machines. +*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + return PASS; + +#else + + BOOL bRc = TRUE; + WCHAR szSrcExisting[] = {'/','e','t','c','/','p','a','s','s','w','d','\0'}; + WCHAR szDest[] = {'t','e','m','p','.','t','m','p','\0'}; + WCHAR szStringTest[] = {'M','a','r','r','y',' ','h','a','d',' ','a',' ', + 'l','i','t','t','l','e',' ','l','a','m','b','\0'}; + WCHAR szStringRead[30]; /* large enough for string szStringTest */ + + HANDLE hFile = NULL; + DWORD dwBytesWritten=0; + DWORD dwBytesRead=0; + int size=0; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* copy the file */ + bRc = CopyFileW(szSrcExisting,szDest,TRUE); + if(!bRc) + { + Fail("CopyFileW: Cannot copy a file with error, %u",GetLastError()); + } + + /* try to get file attributes of destination file */ + if (GetFileAttributesW(szDest) == -1) + { + Fail("CopyFileW: GetFileAttributes of destination file " + "failed with error code %u. \n", + GetLastError()); + } + + /* set the attributes of the destination file to normal again */ + bRc = SetFileAttributesW(szDest, FILE_ATTRIBUTE_NORMAL); + if(!bRc) + { + Fail("CopyFileW: ERROR-> Couldn't set file attributes for " + "file %S with error %u\n", szDest, GetLastError()); + } + + /* open the file for write purposes */ + hFile = CreateFileW((WCHAR *)szDest, + GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("CopyFileW: ERROR -> Unable to create file \"%S\".\n", + szDest); + } + + /* To account for the size of a WCHAR is twice that of a char */ + size = wcslen(szStringTest); + size = size*sizeof(WCHAR); + + /* Attempt to write to the file */ + bRc = WriteFile(hFile, + szStringTest, + size, + &dwBytesWritten, + NULL); + + if (!bRc) + { + Trace("CopyFileW: ERROR -> Unable to write to copied file with error " + "%u.\n", GetLastError()); + bRc = CloseHandle(hFile); + if (!bRc) + { + Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with " + "error %u.\n",szDest, GetLastError()); + } + Fail(""); + + } + + /* Close the file handle */ + bRc = CloseHandle(hFile); + if (!bRc) + { + Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with error %u " + ".\n",szDest,GetLastError()); + } + + + /* open the file for read purposes */ + hFile = CreateFileW((WCHAR *)szDest, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("CopyFileW: ERROR -> Unable to create file \"%S\".\n", + szDest); + } + + /* Attempt to read from the file */ + bRc = ReadFile(hFile, + szStringRead, + size, + &dwBytesRead, + NULL); + + if (!bRc) + { + Trace("CopyFileW: ERROR -> Unable to read from copied file with " + "error %u.\n",GetLastError()); + bRc = CloseHandle(hFile); + if (!bRc) + { + Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with " + "error %u.\n",szDest, GetLastError()); + } + Fail(""); + + } + + if(wcsncmp(szStringTest,szStringRead, wcslen(szStringTest)) != 0) + { + Trace("CopyFileW: ERROR -> The string which was written '%S' does not " + "match the string '%S' which was read from the copied file.\n", + szStringTest,szStringRead); + bRc = CloseHandle(hFile); + if (!bRc) + { + Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with " + "error %u.\n",szDest, GetLastError()); + } + Fail(""); + } + + /* Close the file handle */ + bRc = CloseHandle(hFile); + if (!bRc) + { + Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with error %u " + ".\n",szDest,GetLastError()); + } + + /* Remove the temporary file */ + bRc = DeleteFileW(szDest); + if(!bRc) + { + Fail("CopyFileW: Could not remove copied file with error %u.\n", + GetLastError()); + } + + PAL_Terminate(); + return PASS; + +#endif + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test3/testinfo.dat new file mode 100644 index 0000000..9fd185d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CopyFileW/test3/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = CopyFileW +Name = CopyFileW - checking file attributes maintained (test3) +Type = DEFAULT +EXE1 = test3 +Description += Copy a file from a different user, belonging to a different group to += the the current user, who is a member of the current group. Then check += to see that the current user has the basic access rights to the copied += file. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryA/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryA/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/CMakeLists.txt new file mode 100644 index 0000000..ee06026 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + createdirectorya.cpp +) + +add_executable(paltest_createdirectorya_test2 + ${SOURCES} +) + +add_dependencies(paltest_createdirectorya_test2 coreclrpal) + +target_link_libraries(paltest_createdirectorya_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryW/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryW/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/CMakeLists.txt new file mode 100644 index 0000000..bdc1dfe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + createdirectoryw.cpp +) + +add_executable(paltest_createdirectoryw_test2 + ${SOURCES} +) + +add_dependencies(paltest_createdirectoryw_test2 coreclrpal) + +target_link_libraries(paltest_createdirectoryw_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/CMakeLists.txt new file mode 100644 index 0000000..737dfcf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateFileA.cpp +) + +add_executable(paltest_createfilea_test1 + ${SOURCES} +) + +add_dependencies(paltest_createfilea_test1 coreclrpal) + +target_link_libraries(paltest_createfilea_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.cpp new file mode 100644 index 0000000..f98fc5b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.cpp @@ -0,0 +1,145 @@ +// 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. + +/*===================================================================== +** +** Source: CreateFileA.c +** +** Purpose: Test the PAL implementation of the CreateFileA function +** +** +**===================================================================*/ + +#include + +BOOL Cleanup(void) +{ + char FileName[20]; + int i; + BOOL bRet = TRUE; // assume success + + // loop through all accesses, modes, dispositions and flags + for (i=0; i<4*8*4*5; ++i) { + sprintf_s(FileName, _countof(FileName), "test%03d.txt", i); + if (DeleteFileA(FileName) == FALSE) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) { + bRet = FALSE; + } + } + } + return bRet; +} + + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bSuccess = TRUE; + int nCounter = 0; + HANDLE hFile; + char lpFileName[20]; + FILE *outFile = NULL; + char results[1024]; + int i, j, k, l; + DWORD dwDesiredAccess[4] = {0, // 0 + GENERIC_READ, // 1 + GENERIC_WRITE, // 2 + GENERIC_READ | GENERIC_WRITE}; // 3 + DWORD dwShareMode[8] = {0, // 0 + FILE_SHARE_READ, // 1 + FILE_SHARE_WRITE, // 2 + FILE_SHARE_DELETE, // 3 + FILE_SHARE_READ | FILE_SHARE_WRITE, // 4 + FILE_SHARE_READ | FILE_SHARE_DELETE, // 5 + FILE_SHARE_WRITE | FILE_SHARE_DELETE, // 6 + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE}; // 7 + LPSECURITY_ATTRIBUTES lpAttr = NULL; + DWORD dwCreationDisp[4] = {CREATE_NEW, // 0 + CREATE_ALWAYS, // 1 + OPEN_EXISTING, // 2 + OPEN_ALWAYS}; // 3 + DWORD dwFlagsAttrib[5] = {FILE_ATTRIBUTE_NORMAL, // 0 + FILE_FLAG_SEQUENTIAL_SCAN, // 1 + FILE_FLAG_WRITE_THROUGH, // 2 + FILE_FLAG_NO_BUFFERING, // 3 + FILE_FLAG_RANDOM_ACCESS}; // 4 + HANDLE hTemplate = NULL; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + if (!Cleanup()) { + Trace("Pre-test Cleanup() failed. LastError=%d\n", GetLastError()); + return FAIL; + } + + /* open the file to read the expected results */ + outFile = fopen("winoutput", "r"); + memset (results, 0, 1024); + + fgets(results, 1024, outFile); + nCounter = (int)strlen(results); + fclose(outFile); + + nCounter = 0; + + // desired access loop + for (i = 0; i < 4; i++) + { + // share mode loop + for (j = 0; j < 8; j++) + { + // security attributes loop + for (k = 0; k < 4; k++) + { + // creation disp loop + for (l = 0; l < 5; l++) + { + sprintf_s(lpFileName, _countof(lpFileName), "test%03d.txt", nCounter); + hFile = CreateFile(lpFileName, + dwDesiredAccess[i], + dwShareMode[j], + lpAttr, + dwCreationDisp[k], + dwFlagsAttrib[l], + hTemplate); + if (hFile == INVALID_HANDLE_VALUE) + { + if (results[nCounter] == '1') + { + Trace("CreateFile: ERROR: Failed when expected " + "to pass %s [%d][%d][%d][%d]\n", + lpFileName, i, j, k, l); + bSuccess = FALSE; + } + } + else + { + CloseHandle(hFile); + if (results[nCounter] == '0') + { + Trace("CreateFile: ERROR: Passed when expected " + "to fail %s [%d][%d][%d][%d]\n", + lpFileName, i, j, k, l); + bSuccess = FALSE; + } + } + nCounter ++; + } + } + } + } + + if (!Cleanup()) + { + Trace("Post-test Cleanup() failed. LastError=%d\n", GetLastError()); + return FAIL; + } + + int exitCode = bSuccess ? PASS : FAIL; + PAL_TerminateEx(exitCode); + return exitCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/testinfo.dat new file mode 100644 index 0000000..bb87280 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = CreateFileA +Name = test for CreateFileA +Type = DEFAULT +EXE1 = createfilea +Description += Attempts to create files based on all combinations of += options of CreateFileA diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/winoutput b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/winoutput new file mode 100644 index 0000000..3913b99 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileA/test1/winoutput @@ -0,0 +1 @@ +1111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111 \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/CMakeLists.txt new file mode 100644 index 0000000..44fa650 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateFileW.cpp +) + +add_executable(paltest_createfilew_test1 + ${SOURCES} +) + +add_dependencies(paltest_createfilew_test1 coreclrpal) + +target_link_libraries(paltest_createfilew_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.cpp new file mode 100644 index 0000000..0619f5b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.cpp @@ -0,0 +1,152 @@ +// 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. + +/*===================================================================== +** +** Source: CreateFileW.c +** +** Purpose: Test the PAL implementation of the CreateFileW function +** +** +**===================================================================*/ + +#include + +BOOL Cleanup(void) +{ + char FileName[20]; + int i; + BOOL bRet = TRUE; // assume success + + // loop through all accesses, modes, dispositions and flags + for (i=0; i<4*8*4*5; ++i) { + sprintf_s(FileName, _countof(FileName), "test%03d.txt", i); + if (DeleteFileA(FileName) == FALSE) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) { + bRet = FALSE; + } + } + } + return bRet; +} + + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bSuccess = TRUE; + int nCounter = 0; + HANDLE hFile = NULL; + WCHAR *lpFileName = NULL; + char* pTemp = NULL; + char string[40]; + FILE *outFile = NULL; + char results[1024]; + int i, j, k, l; + DWORD dwDesiredAccess[4] = {0, // 0 + GENERIC_READ, // 1 + GENERIC_WRITE, // 2 + GENERIC_READ | GENERIC_WRITE}; // 3 + DWORD dwShareMode[8] = {0, // 0 + FILE_SHARE_READ, // 1 + FILE_SHARE_WRITE, // 2 + FILE_SHARE_DELETE, // 3 + FILE_SHARE_READ | FILE_SHARE_WRITE, // 4 + FILE_SHARE_READ | FILE_SHARE_DELETE, // 5 + FILE_SHARE_WRITE | FILE_SHARE_DELETE, // 6 + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE}; // 7 + LPSECURITY_ATTRIBUTES lpAttr = NULL; + DWORD dwCreationDisp[4] = {CREATE_NEW, // 0 + CREATE_ALWAYS, // 1 + OPEN_EXISTING, // 2 + OPEN_ALWAYS}; // 3 + DWORD dwFlagsAttrib[5] = {FILE_ATTRIBUTE_NORMAL, // 0 + FILE_FLAG_SEQUENTIAL_SCAN, // 1 + FILE_FLAG_WRITE_THROUGH, // 2 + FILE_FLAG_NO_BUFFERING, // 3 + FILE_FLAG_RANDOM_ACCESS}; // 4 + HANDLE hTemplate = NULL; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + if (!Cleanup()) { + Trace("Pre-test Cleanup() failed. LastError=%d\n", GetLastError()); + return FAIL; + } + + /* open the file to read the expected results */ + outFile = fopen("winoutput", "r"); + memset (results, 0, 1024); + + fgets(results, 1024, outFile); + fclose(outFile); + + nCounter = 0; + + // desired access loop + for (i = 0; i < 4; i++) + { + // share mode loop + for (j = 0; j < 8; j++) + { + // security attributes loop + for (k = 0; k < 4; k++) + { + // creation disp loop + for (l = 0; l < 5; l++) + { + sprintf_s(string, _countof(string), "test%03d.txt", nCounter); + lpFileName = convert(string); + hFile = CreateFileW(lpFileName, + dwDesiredAccess[i], + dwShareMode[j], + lpAttr, + dwCreationDisp[k], + dwFlagsAttrib[l], + hTemplate); + free(lpFileName); + if (hFile == INVALID_HANDLE_VALUE) + { + if (results[nCounter] == '1') + { + pTemp = convertC(lpFileName); + Trace("CreateFile: ERROR: Failed when expected " + "to pass %s [%d][%d][%d][%d]\n", + pTemp, i, j, k, l); + free(pTemp); + bSuccess = FALSE; + } + } + else + { + CloseHandle(hFile); + if (results[nCounter] == '0') + { + pTemp = convertC(lpFileName); + Trace("CreateFile: ERROR: Passed when expected " + "to fail %s [%d][%d][%d][%d]\n", + pTemp, i, j, k, l); + free(pTemp); + bSuccess = FALSE; + } + } + nCounter ++; + } + } + } + } + + if (!Cleanup()) + { + Trace("Post-test Cleanup() failed. LastError=%d\n", GetLastError()); + return FAIL; + } + + int exitCode = bSuccess ? PASS : FAIL; + PAL_TerminateEx(exitCode); + return exitCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/testinfo.dat new file mode 100644 index 0000000..2dbf159 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = CreateFileW +Name = test for CreateFileW +Type = DEFAULT +EXE1 = createfilew +Description += Attempts to create files based on all combinations of += options of CreateFileW diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/winoutput b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/winoutput new file mode 100644 index 0000000..3913b99 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/CreateFileW/test1/winoutput @@ -0,0 +1 @@ +1111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111 \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/test1/CMakeLists.txt new file mode 100644 index 0000000..3d60e61 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + DeleteFileA.cpp +) + +add_executable(paltest_deletefilea_test1 + ${SOURCES} +) + +add_dependencies(paltest_deletefilea_test1 coreclrpal) + +target_link_libraries(paltest_deletefilea_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/test1/DeleteFileA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/test1/DeleteFileA.cpp new file mode 100644 index 0000000..a8eb71d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/test1/DeleteFileA.cpp @@ -0,0 +1,182 @@ +// 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. + +/*===================================================================== +** +** Source: DeleteFileA.c +** +** Purpose: Tests the PAL implementation of the DeleteFileA function. +** +** +**===================================================================*/ + +// delete an existing file +// delete a non-existant file +// delete an open file +// delete files using wild cards +// delete a hidden file +// delete a file without proper permissions +// + +#define PAL_STDCPP_COMPAT +#include +#undef PAL_STDCPP_COMPAT + +#include +#include + + +int __cdecl main(int argc, char *argv[]) +{ + FILE *tempFile = NULL; + BOOL bRc = FALSE; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + // + // create a test file + // + tempFile = fopen("testFile01.txt", "w"); + if (tempFile == NULL) + { + Fail ("DeleteFileA: ERROR: Couldn't create \"DeleteFileA's" + " testFile01.txt\"\n"); + } + + fprintf(tempFile, "DeleteFileA test file.\n"); + if (fclose(tempFile) != 0) + { + Fail ("DeleteFileA: ERROR: Couldn't close \"DeleteFileA's" + " testFile01.txt\"\n"); + } + + // + // delete a symlink to an existing file + // + if (symlink("testFile01.txt", "testFile01_symlink") != 0) + { + Fail("DeleteFileA: ERROR: Failed to create a symlink to testFile01.txt.\n"); + } + + bRc = DeleteFileA("testFile01_symlink"); + if (bRc != TRUE) + { + Fail ("DeleteFileA: ERROR: Couldn't delete symlink!\n Error is %d\n", GetLastError()); + } + + struct stat statBuffer; + if (lstat("testFile01.txt", &statBuffer) != 0) + { + Fail("DeleteFileA: ERROR: Deleting a symlink deleted the file it was pointing to.\n"); + } + + if (lstat("testFile01_symlink", &statBuffer) == 0) + { + Fail("DeleteFileA: ERROR: Failed to delete a symlink.\n"); + } + + // + // deleting an existing file + // + bRc = DeleteFileA("testFile01.txt"); + if (bRc != TRUE) + { + Fail ("DeleteFileA: ERROR: Couldn't delete DeleteFileA's" + " \"testFile01.txt\"\n" + " Error is %d\n", GetLastError()); + } + + + // + // deleting a non-existant file : should fail + // + + bRc = DeleteFileA("testFile02.txt"); + if (bRc != FALSE) + { + Fail ("DeleteFileA: ERROR: Was able to delete the non-existant" + " file \"testFile02.txt\"\n"); + } + + + + + // + // deleting an open file + // + tempFile = fopen("testFile03.txt", "w"); + if (tempFile == NULL) + { + Fail("DeleteFileA: ERROR: Couldn't create \"DeleteFileA's" + " testFile03.txt\"\n"); + } + + fprintf(tempFile, "DeleteFileA test file.\n"); + if (fclose(tempFile) != 0) + { + Fail ("DeleteFileA: ERROR: Couldn't close \"DeleteFileA's" + " testFile03.txt\"\n"); + } + + bRc = DeleteFileA("testFile03.txt"); + if (bRc != TRUE) + { + Fail("DeleteFileA: ERROR: Couldn't delete DeleteFileA's" + " \"testFile03.txt\"\n" + " Error is %d\n", GetLastError()); + } + bRc = DeleteFileA("testFile03.txt"); + + + + + // + // delete using wild cards + // + + // create the test file + tempFile = fopen("testFile04.txt", "w"); + if (tempFile == NULL) + { + Fail("DeleteFileA: ERROR: Couldn't create DeleteFileA's" + " \"testFile04.txt\"\n"); + } + fprintf(tempFile, "DeleteFileA test file.\n"); + if (fclose(tempFile) != 0) + { + Fail ("DeleteFileA: ERROR: Couldn't close \"DeleteFileA's" + " testFile04.txt\"\n"); + } + + // delete using '?' + bRc = DeleteFileA("testFile0?.txt"); + if (bRc == TRUE) + { + Fail("DeleteFileA: ERROR: Was able to delete using the" + " \'?\' wildcard\n"); + } + + // delete using '*' + bRc = DeleteFileA("testFile*.txt"); + if (bRc == TRUE) + { + Fail("DeleteFileA: ERROR: Was able to delete using the" + " \'*\' wildcard\n"); + } + + bRc = DeleteFileA("testFile04.txt"); + if (bRc != TRUE) + { + Fail ("DeleteFileA: ERROR: Couldn't delete DeleteFileA's" + " \"testFile04.txt\"\n" + " Error is %d\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/test1/testinfo.dat new file mode 100644 index 0000000..24283ed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileA/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = DeleteFileA +Name = Test for DeleteFileA (test 1) +Type = DEFAULT +EXE1 = deletefilea +Description += Attempt to delete various files. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/test1/CMakeLists.txt new file mode 100644 index 0000000..c61b1ab --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + DeleteFileW.cpp +) + +add_executable(paltest_deletefilew_test1 + ${SOURCES} +) + +add_dependencies(paltest_deletefilew_test1 coreclrpal) + +target_link_libraries(paltest_deletefilew_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/test1/DeleteFileW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/test1/DeleteFileW.cpp new file mode 100644 index 0000000..fca96d1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/test1/DeleteFileW.cpp @@ -0,0 +1,164 @@ +// 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. + +/*===================================================================== +** +** Source: DeleteFileW.c +** +** Purpose: Tests the PAL implementation of the DeleteFileW function. +** +** +**===================================================================*/ + +// delete an existing file +// delete a non-existant file +// delete an open file +// delete files using wild cards +// delete a hidden file +// delete a file without proper permissions +// + + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + FILE *tempFile = NULL; + BOOL bRc = FALSE; + WCHAR* pTemp = NULL; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + // + // deleting an existing file + // + tempFile = fopen("testFile01.tmp", "w"); + if (tempFile == NULL) + { + Fail ("DeleteFileW: ERROR: Couldn't create \"DeleteFileW's" + " testFile01.tmp\"\n"); + } + + fprintf(tempFile, "DeleteFileW test file.\n"); + if (fclose(tempFile) != 0) + { + Fail ("DeleteFileA: ERROR: Couldn't close \"DeleteFileW's" + " testFile01.tmp\"\n"); + } + + pTemp = convert("testFile01.tmp"); + bRc = DeleteFileW(pTemp); + free(pTemp); + if (bRc != TRUE) + { + Fail ("DeleteFileW: ERROR: Couldn't delete DeleteFileW's" + " \"testFile01.tmp\"\n" + " Error is %d\n", GetLastError()); + } + + + // + // deleting a non-existant file : should fail + // + + pTemp = convert("testFile02.tmp"); + bRc = DeleteFileW(pTemp); + free(pTemp); + if (bRc != FALSE) + { + Fail ("DeleteFileW: ERROR: Was able to delete the non-existant" + " file \"testFile02.tmp\"\n"); + } + + + + + // + // deleting an open file + // + tempFile = fopen("testFile03.tmp", "w"); + if (tempFile == NULL) + { + Fail("DeleteFileW: ERROR: Couldn't create \"DeleteFileW's" + " testFile03.tmp\"\n"); + } + + fprintf(tempFile, "DeleteFileW test file.\n"); + if (fclose(tempFile) != 0) + { + Fail ("DeleteFileA: ERROR: Couldn't close \"DeleteFileW's" + " testFile03.tmp\"\n"); + } + + pTemp = convert("testFile03.tmp"); + bRc = DeleteFileW(pTemp); + if (bRc != TRUE) + { + Fail("DeleteFileW: ERROR: Couldn't delete DeleteFileW's" + " \"testFile03.tmp\"\n" + " Error is %d\n", GetLastError()); + free(pTemp); + } + bRc = DeleteFileW(pTemp); + free(pTemp); + + + + + // + // delete using wild cards + // + + // create the test file + tempFile = fopen("testFile04.tmp", "w"); + if (tempFile == NULL) + { + Fail("DeleteFileW: ERROR: Couldn't create DeleteFileW's" + " \"testFile04.tmp\"\n"); + } + fprintf(tempFile, "DeleteFileW test file.\n"); + if (fclose(tempFile) != 0) + { + Fail ("DeleteFileA: ERROR: Couldn't close \"DeleteFileW's" + " testFile04.tmp\"\n"); + } + + // delete using '?' + pTemp = convert("testFile0?.tmp"); + bRc = DeleteFileW(pTemp); + free(pTemp); + if (bRc == TRUE) + { + Fail("DeleteFileW: ERROR: Was able to delete using the" + " \'?\' wildcard\n"); + } + + // delete using '*' + pTemp = convert("testFile*.tmp"); + bRc = DeleteFileW(pTemp); + free(pTemp); + if (bRc == TRUE) + { + Fail("DeleteFileW: ERROR: Was able to delete using the" + " \'*\' wildcard\n"); + } + + pTemp = convert("testFile04.tmp"); + bRc = DeleteFileW(pTemp); + free(pTemp); + if (bRc != TRUE) + { + Fail ("DeleteFileW: ERROR: Couldn't delete DeleteFileW's" + " \"testFile04.tmp\"\n" + " Error is %d\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/test1/testinfo.dat new file mode 100644 index 0000000..db44f99 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/DeleteFileW/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = DeleteFileW +Name = Test for DeleteFileW (test 1) +Type = DEFAULT +EXE1 = deletefilew +Description += Tests DeleteFileW on various file names + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FILECanonicalizePath/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FILECanonicalizePath/CMakeLists.txt new file mode 100644 index 0000000..9c4d622 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FILECanonicalizePath/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + FILECanonicalizePath.cpp +) + +add_executable(paltest_filecanonicalizepath_test1 + ${SOURCES} +) + +add_dependencies(paltest_filecanonicalizepath_test1 coreclrpal) + +target_link_libraries(paltest_filecanonicalizepath_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.cpp new file mode 100644 index 0000000..3a1758a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.cpp @@ -0,0 +1,83 @@ +// 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. + +/*===================================================================== +** +** Source: FILECanonicalizePath.c (test 1) +** +** Purpose: Tests the PAL implementation of the FILECanonicalizePath function. +** +** +**===================================================================*/ + +#include + +extern "C" void FILECanonicalizePath(LPSTR lpUnixPath); + +void TestCase(LPSTR input, LPSTR expectedOutput); + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc,argv) != 0) + { + return FAIL; + } + + // Case 01: / should not change + TestCase("/Test", "/Test"); + + // Case 02: // should not change + TestCase("/Test/Foo", "/Test/Foo"); + + // Case 03: // transforms to / + TestCase("//", "/"); + + // Case 04: /./ transforms to / + TestCase("/./", "/"); + + // Case 05: //../ transforms to / + TestCase("/Test/../", "/"); + + // Case 06: /Test/Foo/.. transforms to /Test + TestCase("/Test/Foo/..", "/Test"); + + // Case 07: /Test/.. transforms to / + TestCase("/Test/..", "/"); + + // Case 08: /. transforms to / + TestCase("/.", "/"); + + // Case 09: / + TestCase("/Test/.", "/Test"); + + // Case 10: //../. transforms to / + TestCase("/Test/../.", "/"); + + // Case 11: /.. transforms to / + TestCase("/..", "/"); + + PAL_Terminate(); + return PASS; +} + +void TestCase(LPSTR input, LPSTR expectedOutput) +{ + // Save the input for debug logging since the input is edited in-place + char* pOriginalInput = (char*)malloc(strlen(input) * sizeof(char) + 1); + strcpy(pOriginalInput, input); + + char* pInput = (char*)malloc(strlen(input) * sizeof(char) + 1); + strcpy(pInput, pOriginalInput); + + FILECanonicalizePath(pInput); + if (strcmp(pInput, expectedOutput) != 0) + { + free(pOriginalInput); + free(pInput); + Fail("FILECanonicalizePath error: input %s did not match expected output %s; got %s instead", pOriginalInput, expectedOutput, pInput); + } + + free(pOriginalInput); + free(pInput); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FILECanonicalizePath/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FILECanonicalizePath/testinfo.dat new file mode 100644 index 0000000..033ad78 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FILECanonicalizePath/testinfo.dat @@ -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. + +Version = 1.0 +Section = file_io +Function = FILECanonicalizePath +Name = Test for FILECanonicalizePath (test 1) +Type = DEFAULT +EXE1 = filecanonicalizepath +Description += Canonicalizes paths and verifies the results diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/test1/CMakeLists.txt new file mode 100644 index 0000000..e8b1b83 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + FindClose.cpp +) + +add_executable(paltest_findclose_test1 + ${SOURCES} +) + +add_dependencies(paltest_findclose_test1 coreclrpal) + +target_link_libraries(paltest_findclose_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/test1/FindClose.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/test1/FindClose.cpp new file mode 100644 index 0000000..3d53806 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/test1/FindClose.cpp @@ -0,0 +1,275 @@ +// 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. + +/*===================================================================== +** +** Source: FindClose.c +** +** Purpose: Tests the PAL implementation of the FindClose function. +** +** +**===================================================================*/ + + +#include + + + +const WCHAR szFindName[] = {'t','e', 's', 't', '0', '1', '.', 't', 'x', 't', '\0'}; +const WCHAR szFindName_02[] = {'t','e', 's', 't', '0', '2', '.', 't', 'x', 't', '\0'}; +const WCHAR szFindName_03[] = {'t','e', 's', 't', '0', '3', '.', 't', 'x', 't', '\0'}; +const WCHAR szFindNameWldCard_01[] = {'t','e', 's', 't', '0', '?', '.', 't', 'x', 't', '\0'}; +const WCHAR szFindNameWldCard_02[] = {'*', '.', 't', 'x', 't', '\0'}; +const WCHAR szDirName[] = {'t','e', 's', 't', '_', 'd', 'i', 'r', '\0'}; +const WCHAR szDirName_02[] = {'t','e', 's', 't', '_', 'd', 'i', 'r', '0', '2', '\0'}; +const WCHAR szDirNameWldCard[] = {'t','e', 's', 't', '_', '*', '\0'}; + + + +BOOL createTestFile(const WCHAR* szName) +{ + FILE *pFile = NULL; + char* pTemp = NULL; + + pTemp = convertC((WCHAR*)szName); + pFile = fopen(pTemp, "w"); + if (pFile == NULL) + { + Trace("FindClose: ERROR -> Unable to create file \"%s\".\n", pTemp); + free(pTemp); + return FALSE; + } + else + { + fprintf(pFile, "FindClose test file, \"%s\".\n", pTemp); + free(pTemp); + fclose(pFile); + } + return TRUE; +} + + +void removeAll() +{ + RemoveDirectoryW(szDirName); + RemoveDirectoryW(szDirName_02); + + DeleteFileW(szFindName); + DeleteFileW(szFindName_02); + DeleteFileW(szFindName_03); +} + + +int __cdecl main(int argc, char *argv[]) +{ + WIN32_FIND_DATAW findFileData; + WIN32_FIND_DATAW findFileData_02; + HANDLE hFind = NULL; + BOOL bRc = FALSE; + char* pTemp = NULL; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* do some clean up just to be sure */ + removeAll(); + + /* FindClose a null handle */ + if(FindClose(NULL)!=0) + { + Fail("FindClose: ERROR -> Closing a NULL handle succeeded.\n"); + } + + /* find a file that exists */ + if(createTestFile(szFindName) == FALSE) + { + removeAll(); + PAL_TerminateEx(FAIL); + return FAIL; + } + if(createTestFile(szFindName_02) == FALSE) + { + removeAll(); + PAL_TerminateEx(FAIL); + return FAIL; + } + if(createTestFile(szFindName_03) == FALSE) + { + removeAll(); + PAL_TerminateEx(FAIL); + return FAIL; + } + + // close a FindFirstFileW handle + hFind = FindFirstFileW(szFindName, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + pTemp = convertC((WCHAR*)szFindName); + Trace("FindClose: ERROR -> Unable to find \"%s\"\n", pTemp); + free(pTemp); + removeAll(); + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + bRc = FindClose(hFind); + if (bRc == FALSE) + { + removeAll(); + Fail("FindClose: ERROR -> Unable to close a valid" + " FindFirstFileW handle.\n"); + } + } + hFind = FindFirstFileW(szFindName, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + pTemp = convertC((WCHAR*)szFindName); + Trace("FindClose: ERROR -> Unable to find \"%s\"\n", pTemp); + free(pTemp); + removeAll(); + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + bRc = FindNextFileW(hFind, &findFileData); + if (bRc != FALSE) + { + removeAll(); + Fail("FindClose: ERROR -> Found a file that doesn't exist.\n"); + } + else + { + bRc = FindClose(hFind); + if (bRc == FALSE) + { + removeAll(); + Fail("FindClose: ERROR -> Unable to close a valid " + "FindNextFileW handle.\n"); + } + } + } + + /* find a directory that exists */ + bRc = CreateDirectoryW(szDirName, NULL); + if (bRc == FALSE) + { + pTemp = convertC((WCHAR*)szDirName); + Trace("FindClose: ERROR -> Failed to create the directory \"%s\"\n", + pTemp); + free(pTemp); + removeAll(); + PAL_TerminateEx(FAIL); + return FAIL; + } + + bRc = CreateDirectoryW(szDirName_02, NULL); + if (bRc == FALSE) + { + pTemp = convertC((WCHAR*)szDirName_02); + Trace("FindClose: ERROR -> Failed to create the directory \"%s\"\n", + pTemp); + free(pTemp); + removeAll(); + PAL_TerminateEx(FAIL); + return FAIL; + } + + hFind = FindFirstFileW(szDirName, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + pTemp = convertC((WCHAR*)szDirName); + Trace("FindClose: ERROR. FindFirstFileW was unable to find \"%s\"\n", + pTemp); + free(pTemp); + removeAll(); + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + bRc = FindClose(hFind); + if (bRc == FALSE) + { + removeAll(); + Fail("FindClose: ERROR -> Unable to close a valid" + " FindFirstFileW handle of a directory.\n"); + } + } + + /* find a file using wild cards */ + hFind = FindFirstFileW(szFindNameWldCard_01, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + pTemp = convertC((WCHAR*)szFindNameWldCard_01); + Trace("FindClose: ERROR -> FindFirstFileW was unable to find \"%s\"\n", + pTemp); + free(pTemp); + removeAll(); + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + bRc = FindNextFileW(hFind, &findFileData_02); + if (bRc == FALSE) + { + removeAll(); + Fail("FindClose: ERROR -> Unable to find another file.\n"); + } + else + { + bRc = FindClose(hFind); + if (bRc == FALSE) + { + removeAll(); + Fail("FindClose: ERROR -> Unable to close a valid" + " FindNextFileW handle.\n"); + } + } + } + + /* find a directory using wild cards */ + hFind = FindFirstFileW(szDirNameWldCard, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + pTemp = convertC((WCHAR*)szDirNameWldCard); + Trace("FindClose: ERROR -> Unable to find \"%s\"\n", + pTemp); + free(pTemp); + removeAll(); + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + bRc = FindNextFileW(hFind, &findFileData_02); + if (bRc == FALSE) + { + removeAll(); + Fail("FindClose: ERROR -> Unable to find another directory.\n"); + } + else + { + bRc = FindClose(hFind); + if (bRc == FALSE) + { + removeAll(); + Fail("FindClose: ERROR -> Unable to close a valid" + " FindNextFileW handle of a directory.\n"); + } + } + } + + + removeAll(); + PAL_Terminate(); + + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/test1/testinfo.dat new file mode 100644 index 0000000..b59bcbf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindClose/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = FindClose +Name = Test for FindClose (test 1) +Type = DEFAULT +EXE1 = findclose +Description += Test the FindClose on handles opened using the Find functions + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/CMakeLists.txt new file mode 100644 index 0000000..c73e27f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + FindFirstFileA.cpp +) + +add_executable(paltest_findfirstfilea_test1 + ${SOURCES} +) + +add_dependencies(paltest_findfirstfilea_test1 coreclrpal) + +target_link_libraries(paltest_findfirstfilea_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/FindFirstFileA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/FindFirstFileA.cpp new file mode 100644 index 0000000..6ceb6a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/FindFirstFileA.cpp @@ -0,0 +1,206 @@ +// 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. + +/*===================================================================== +** +** Source: FindFirstFileA.c +** +** Purpose: Tests the PAL implementation of the FindFirstFileA function. +** +** +**===================================================================*/ + + +#include + + +const char* szNoFileName = "333asdf.x77t"; +const char* szFindName = "test01.txt"; +const char* szFindNameWldCard_01 = "test0?.txt"; +const char* szFindNameWldCard_02 = "*.txt"; +const char* szDirName = "test_dir"; +const char* szDirNameSlash = "test_dir\\"; +const char* szDirNameWldCard_01 = "?est_dir"; +const char* szDirNameWldCard_02 = "test_*"; +/* Longer than MAX_LONGPATH characters */ +char szLongFindName[MAX_LONGPATH+1]; + +BOOL CleanUp() +{ + DWORD dwAtt; + BOOL result = TRUE; + + dwAtt = GetFileAttributesA(szFindName); + if( dwAtt != INVALID_FILE_ATTRIBUTES ) + { + if(!SetFileAttributesA (szFindName, FILE_ATTRIBUTE_NORMAL)) + { + result = FALSE; + Trace("ERROR:%d: Error setting attributes [%s][%d]\n", szFindName, FILE_ATTRIBUTE_NORMAL); + } + if(!DeleteFileA (szFindName)) + { + result = FALSE; + Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), szFindName, dwAtt); + } + } + + dwAtt = GetFileAttributesA(szDirName); + if( dwAtt != INVALID_FILE_ATTRIBUTES ) + { + if(!RemoveDirectoryA (szDirName)) + { + result = FALSE; + Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), szDirName, dwAtt); + } + } + + return result; +} + +int __cdecl main(int argc, char *argv[]) +{ + WIN32_FIND_DATA findFileData; + HANDLE hFind = NULL; + FILE *pFile = NULL; + BOOL bRc = FALSE; + WCHAR* szwTemp = NULL; + + memset(szLongFindName, 'a', MAX_LONGPATH+1); + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + + if(!CleanUp()) + { + Fail("FindFirstFileW: ERROR : Initial Clean Up failed\n"); + } + + // + // find a file with a NULL pointer + // + hFind = FindFirstFileA(NULL, &findFileData); + if (hFind != INVALID_HANDLE_VALUE) + { + Fail ("FindFirstFileA: ERROR -> Found invalid NULL file"); + } + + + // + // find a file that doesn't exist + // + hFind = FindFirstFileA(szNoFileName, &findFileData); + if (hFind != INVALID_HANDLE_VALUE) + { + Fail ("FindFirstFileA: ERROR -> Found invalid NULL file"); + } + + + // + // find a file that exists + // + pFile = fopen(szFindName, "w"); + if (pFile == NULL) + { + Fail("FindFirstFileA: ERROR -> Unable to create a test file\n"); + } + else + { + fclose(pFile); + } + hFind = FindFirstFileA(szFindName, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + Fail ("FindFirstFileA: ERROR -> Unable to find \"%s\"\n", szFindName); + } + else + { + // validate we found the correct file + if (strcmp(szFindName, findFileData.cFileName) != 0) + { + Fail ("FindFirstFileA: ERROR -> Found the wrong file\n"); + } + } + + + // + // find a directory that exists + // + szwTemp = convert((LPSTR)szDirName); + bRc = CreateDirectoryW(szwTemp, NULL); + free(szwTemp); + if (bRc == FALSE) + { + Fail("FindFirstFileA: ERROR -> Failed to create the directory " + "\"%s\"\n", + szDirName); + } + + hFind = FindFirstFileA(szDirName, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + Fail ("FindFirstFileA: ERROR. Unable to find \"%s\"\n", szDirName); + } + else + { + // validate we found the correct directory + if (strcmp(szDirName, findFileData.cFileName) != 0) + { + Fail ("FindFirstFileA: ERROR -> Found the wrong directory\n"); + } + } + + + // + // find a directory using a trailing '\' on the directory name: should fail + // + hFind = FindFirstFileA(szDirNameSlash, &findFileData); + if (hFind != INVALID_HANDLE_VALUE) + { + Fail ("FindFirstFileA: ERROR -> Able to find \"%s\": trailing " + "slash should have failed.\n", + szDirNameSlash); + } + + // find a file using wild cards + hFind = FindFirstFileA(szFindNameWldCard_01, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + Fail ("FindFirstFileA: ERROR -> Unable to find \"%s\"\n", + szFindNameWldCard_01); + } + + hFind = FindFirstFileA(szFindNameWldCard_02, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + Fail ("FindFirstFileA: ERROR -> Unable to find \"%s\"\n", szFindNameWldCard_02); + } + + + // + // find a directory using wild cards + // + hFind = FindFirstFileA(szDirNameWldCard_01, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + Fail ("FindFirstFileA: ERROR -> Unable to find \"%s\"\n", szDirNameWldCard_01); + } + + hFind = FindFirstFileA(szDirNameWldCard_02, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + Fail ("FindFirstFileA: ERROR -> Unable to find \"%s\"\n", szDirNameWldCard_02); + } + + if(!CleanUp()) + { + Fail("FindFirstFileW: ERROR : Final Clean Up failed\n"); + } + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/testinfo.dat new file mode 100644 index 0000000..5b92f8c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = FindFirstFileA +Name = Test for FindFirstFileA (test 1) +Type = DEFAULT +EXE1 = findfirstfilea +Description += Create a number of files and try to find them + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/CMakeLists.txt new file mode 100644 index 0000000..e2380b1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + FindFirstFileW.cpp +) + +add_executable(paltest_findfirstfilew_test1 + ${SOURCES} +) + +add_dependencies(paltest_findfirstfilew_test1 coreclrpal) + +target_link_libraries(paltest_findfirstfilew_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/FindFirstFileW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/FindFirstFileW.cpp new file mode 100644 index 0000000..f69a625 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/FindFirstFileW.cpp @@ -0,0 +1,212 @@ +// 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. + +/*===================================================================== +** +** Source: FindFirstFileW.c +** +** Purpose: Tests the PAL implementation of the FindFirstFileW function. +** +** +**===================================================================*/ + + +#include + + +const char* szNoFileName = "333asdf.x77t"; +const char* szFindName = "test01.txt"; +const char* szFindNameWldCard_01 = "test0?.txt"; +const char* szFindNameWldCard_02 = "*.txt"; +const char* szDirName = "test_dir"; +const char* szDirNameSlash = "test_dir\\"; +const char* szDirNameWldCard_01 = "?est_dir"; +const char* szDirNameWldCard_02 = "test_*"; + + +BOOL CleanUp() +{ + DWORD dwAtt; + BOOL result = TRUE; + + dwAtt = GetFileAttributesA(szFindName); + if( dwAtt != INVALID_FILE_ATTRIBUTES ) + { + if(!SetFileAttributesA (szFindName, FILE_ATTRIBUTE_NORMAL)) + { + result = FALSE; + Trace("ERROR:%d: Error setting attributes [%s][%d]\n", szFindName, FILE_ATTRIBUTE_NORMAL); + } + if(!DeleteFileA (szFindName)) + { + result = FALSE; + Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), szFindName, dwAtt); + } + } + + dwAtt = GetFileAttributesA(szDirName); + if( dwAtt != INVALID_FILE_ATTRIBUTES ) + { + if(!RemoveDirectoryA (szDirName)) + { + result = FALSE; + Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), szDirName, dwAtt); + } + } + + return result; +} + +int __cdecl main(int argc, char *argv[]) +{ + WIN32_FIND_DATAW findFileData; + HANDLE hFind = NULL; + FILE *pFile = NULL; + BOOL bRc = FALSE; + WCHAR* pTemp = NULL; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + if(!CleanUp()) + { + Fail("FindFirstFileW: ERROR : Initial Clean Up failed\n"); + } + + // + // find a file that doesn't exist + // + pTemp = convert((LPSTR)szNoFileName); + hFind = FindFirstFileW(pTemp, &findFileData); + free(pTemp); + if (hFind != INVALID_HANDLE_VALUE) + { + Fail ("FindFirstFileW: ERROR -> Found invalid NULL file\n"); + } + + + // + // find a file that exists + // + pFile = fopen(szFindName, "w"); + if (pFile == NULL) + { + Fail("FindFirstFileW: ERROR -> Unable to create a test file\n"); + } + else + { + fclose(pFile); + } + pTemp = convert((LPSTR)szFindName); + hFind = FindFirstFileW(pTemp, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + free(pTemp); + Fail ("FindFirstFileW: ERROR -> Unable to find \"%s\"\n", szFindName); + } + else + { + // validate we found the correct file + if (wcscmp(pTemp, findFileData.cFileName) != 0) + { + free(pTemp); + Fail ("FindFirstFileW: ERROR -> Found the wrong file\n"); + } + } + free(pTemp); + + // + // find a directory that exists + // + pTemp = convert((LPSTR)szDirName); + bRc = CreateDirectoryW(pTemp, NULL); + if (bRc == FALSE) + { + Fail("FindFirstFileW: ERROR[%u] -> Failed to create the directory \"%s\"\n", + GetLastError(), szDirName); + } + + hFind = FindFirstFileW(pTemp, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + free(pTemp); + Fail("FindFirstFileW: ERROR. Unable to find \"%s\"\n", szDirName); + } + else + { + // validate we found the correct directory + if (wcscmp(pTemp, findFileData.cFileName) != 0) + { + free(pTemp); + Fail("FindFirstFileW: ERROR -> Found the wrong directory\n"); + } + } + free(pTemp); + + // + // find a directory using a trailing '\' on the directory name: should fail + // + pTemp = convert((LPSTR)szDirNameSlash); + hFind = FindFirstFileW(pTemp, &findFileData); + free(pTemp); + if (hFind != INVALID_HANDLE_VALUE) + { + Fail("FindFirstFileW: ERROR -> Able to find \"%s\": trailing " + "slash should have failed.\n", + szDirNameSlash); + } + + // find a file using wild cards + pTemp = convert((LPSTR)szFindNameWldCard_01); + hFind = FindFirstFileW(pTemp, &findFileData); + free(pTemp); + if (hFind == INVALID_HANDLE_VALUE) + { + Fail("FindFirstFileW: ERROR -> Unable to find \"%s\"\n", + szFindNameWldCard_01); + } + + pTemp = convert((LPSTR)szFindNameWldCard_02); + hFind = FindFirstFileW(pTemp, &findFileData); + free(pTemp); + if (hFind == INVALID_HANDLE_VALUE) + { + Fail("FindFirstFileW: ERROR -> Unable to find \"%s\"\n", + szFindNameWldCard_02); + } + + + // + // find a directory using wild cards + // + + pTemp = convert((LPSTR)szDirNameWldCard_01); + hFind = FindFirstFileW(pTemp, &findFileData); + free(pTemp); + if (hFind == INVALID_HANDLE_VALUE) + { + Fail("FindFirstFileW: ERROR -> Unable to find \"%s\"\n", + szDirNameWldCard_01); + } + + pTemp = convert((LPSTR)szDirNameWldCard_02); + hFind = FindFirstFileW(pTemp, &findFileData); + free(pTemp); + if (hFind == INVALID_HANDLE_VALUE) + { + Fail("FindFirstFileW: ERROR -> Unable to find \"%s\"\n", + szDirNameWldCard_02); + } + + if(!CleanUp()) + { + Fail("FindFirstFileW: ERROR : Final Clean Up failed\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/testinfo.dat new file mode 100644 index 0000000..c088c04 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = FindFirstFileW +Name = Test for FindFirstFileW (test 1) +Type = DEFAULT +EXE1 = findfirstfilew +Description += Create a number of files and try to find them + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test1/CMakeLists.txt new file mode 100644 index 0000000..9832935 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + FindNextFileA.cpp +) + +add_executable(paltest_findnextfilea_test1 + ${SOURCES} +) + +add_dependencies(paltest_findnextfilea_test1 coreclrpal) + +target_link_libraries(paltest_findnextfilea_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test1/FindNextFileA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test1/FindNextFileA.cpp new file mode 100644 index 0000000..578fa00 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test1/FindNextFileA.cpp @@ -0,0 +1,243 @@ +// 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. + +/*===================================================================== +** +** Source: FindNextFileA.c +** +** Purpose: Tests the PAL implementation of the FindNextFileA function. +** +** +**===================================================================*/ + +#include + + +const char* szFindName = "test01.txt"; +const char* szFindName_02 = "test02.txt"; +const char* szFindNameWldCard_01 = "test0?.txt"; +const char* szFindNameWldCard_02 = "*.txt"; +const char* szDirName = "test_dir"; +const char* szDirName_02 = "test_dir_02"; +const char* szDirNameWldCard = "test_*"; + + + +void removeAll() +{ + WCHAR* wTempPtr = NULL; + + wTempPtr = convert((LPSTR)szDirName); + RemoveDirectoryW(wTempPtr); + free (wTempPtr); + wTempPtr = convert((LPSTR)szDirName_02); + RemoveDirectoryW(wTempPtr); + free (wTempPtr); + DeleteFile(szFindName); + DeleteFile(szFindName_02); +} + + + +BOOL createTestFile(const char* szName) +{ + FILE *pFile = NULL; + + pFile = fopen(szName, "w"); + if (pFile == NULL) + { + Trace("FindNextFile: ERROR -> Unable to create file \"%s\".\n", + szName); + removeAll(); + return FALSE; + } + else + { + fprintf(pFile, "FindNextFile test file, \"%s\".\n", szFindName); + fclose(pFile); + } + return TRUE; +} + + + +int __cdecl main(int argc, char *argv[]) +{ + WIN32_FIND_DATA findFileData; + WIN32_FIND_DATA findFileData_02; + HANDLE hFind = NULL; + BOOL bRc = FALSE; + DWORD dwBytesWritten; + WCHAR* wTempPtr = NULL; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + removeAll(); + + + // + // find a file with a NULL pointer + // + hFind = FindFirstFileA(NULL, &findFileData); + if (hFind != INVALID_HANDLE_VALUE) + { + Fail("FindNextFile: ERROR -> Found invalid NULL file"); + } + + bRc = FindNextFile(hFind, &findFileData); + if (bRc == TRUE) + { + Fail("FindNextFile: ERROR -> Found a file based on an invalid handle"); + } + + + // + // find a file that exists + // + if(createTestFile(szFindName) == FALSE) + { + PAL_TerminateEx(FAIL); + return FAIL; + } + if(createTestFile(szFindName_02) == FALSE) + { + PAL_TerminateEx(FAIL); + return FAIL; + } + + hFind = FindFirstFileA(szFindName, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + removeAll(); + Fail("FindNextFile: ERROR -> Unable to find \"%s\"\n", szFindName); + } + else + { + bRc = FindNextFile(hFind, &findFileData); + if (bRc != FALSE) + { + removeAll(); + Fail("FindNextFile: ERROR -> Found a file that doesn't exist.\n"); + } + } + + + // + // find a directory that exists + // + wTempPtr = convert((LPSTR)szDirName); + bRc = CreateDirectoryW(wTempPtr, NULL); + free (wTempPtr); + if (bRc == FALSE) + { + removeAll(); + Fail("FindNextFile: ERROR -> Failed to create the directory \"%s\"\n", + szDirName); + } + wTempPtr = convert((LPSTR)szDirName_02); + bRc = CreateDirectoryW(wTempPtr, NULL); + free (wTempPtr); + if (bRc == FALSE) + { + removeAll(); + Fail("FindNextFile: ERROR -> Failed to create the directory \"%s\"\n", + szDirName_02); + } + + hFind = FindFirstFileA(szDirName, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + removeAll(); + Fail("FindNextFile: ERROR. FindFirstFileA was unable to find \"%s\"\n", + szDirName); + } + else + { + bRc = FindNextFile(hFind, &findFileData); + if (bRc != FALSE) + { + removeAll(); + Fail("FindNextFile: ERROR -> Found a directory that doesn't exist.\n"); + } + } + + + // + // find a file using wild cards + // + hFind = FindFirstFileA(szFindNameWldCard_01, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + removeAll(); + Fail("FindNextFile: ERROR -> FindFirstFileA was unable to find \"%s\"\n", + szFindNameWldCard_01); + } + else + { + bRc = FindNextFile(hFind, &findFileData_02); + if (bRc == FALSE) + { + removeAll(); + Fail("FindNextFile: ERROR -> Unable to find another file.\n"); + } + else + { + // validate we found the correct file + if (strcmp(findFileData_02.cFileName, findFileData.cFileName) == 0) + { + removeAll(); + Fail("FindNextFile: ERROR -> Found the same file \"%s\".\n", + findFileData.cFileName); + } + } + } + + + // + // find a directory using wild cards + // + hFind = FindFirstFileA(szDirNameWldCard, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + removeAll(); + Fail("FindNextFile: ERROR -> Unable to find \"%s\"\n", + szDirNameWldCard); + } + else + { + bRc = FindNextFile(hFind, &findFileData_02); + if (bRc == FALSE) + { + removeAll(); + Fail("FindNextFile: ERROR -> Unable to find another directory.\n"); + } + else + { + // validate we found the correct directory + if (strcmp(findFileData_02.cFileName, findFileData.cFileName) == 0) + { + removeAll(); + Fail("FindNextFile: ERROR -> Found the same directory \"%s\".\n", + findFileData.cFileName); + } + } + } + + // + // attempt to write to the hFind handle (which should fail) + // + bRc = WriteFile(hFind, "this is a test", 10, &dwBytesWritten, NULL); + removeAll(); + if (bRc == TRUE) + { + Fail("FindNextFile: ERROR -> Able to write to a FindNextFile handle.\n"); + } + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test1/testinfo.dat new file mode 100644 index 0000000..e1027ef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = FindNextFileA +Name = Test for FindNextFileA (test 1) +Type = DEFAULT +EXE1 = findnextfilea +Description += Create test files and directories to verify FindNextFileA + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test2/CMakeLists.txt new file mode 100644 index 0000000..5e013ca --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + findnextfilea.cpp +) + +add_executable(paltest_findnextfilea_test2 + ${SOURCES} +) + +add_dependencies(paltest_findnextfilea_test2 coreclrpal) + +target_link_libraries(paltest_findnextfilea_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test2/findnextfilea.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test2/findnextfilea.cpp new file mode 100644 index 0000000..c841a4d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test2/findnextfilea.cpp @@ -0,0 +1,107 @@ +// 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. + +/*===================================================================== +** +** Source: findnextfilea.c +** +** Purpose: Tests the PAL implementation of the FindNextFileA function. +** Tests '*' and '*.*' to ensure that '.' and '..' are +** returned in the expected order +** +** +**===================================================================*/ + +#include + + +const char* szDot = "."; +const char* szDotDot = ".."; +const char* szStar = "*"; +const char* szStarDotStar = "*.*"; + + +static void DoTest(const char* szDir, + const char* szResult1, + const char* szResult2) +{ + HANDLE hFind; + WIN32_FIND_DATA findFileData; + + /* + ** find the first + */ + if ((hFind = FindFirstFileA(szDir, &findFileData)) == INVALID_HANDLE_VALUE) + { + Fail("FindNextFileA: ERROR -> FindFirstFileA(\"%s\") failed. " + "GetLastError returned %u.\n", + szStar, + GetLastError()); + } + + /* did we find the expected */ + if (strcmp(szResult1, findFileData.cFileName) != 0) + { + if (!FindClose(hFind)) + { + Trace("FindNextFileA: ERROR -> Failed to close the find handle. " + "GetLastError returned %u.\n", + GetLastError()); + } + Fail("FindNextFileA: ERROR -> FindFirstFile(\"%s\") didn't find" + " the expected \"%s\" but found \"%s\" instead.\n", + szDir, + szResult1, + findFileData.cFileName); + } + + /* we found the first expected, let's see if we find the next expected*/ + if (!FindNextFileA(hFind, &findFileData)) + { + Trace("FindNextFileA: ERROR -> FindNextFileA should have found \"%s\"" + " but failed. GetLastError returned %u.\n", + szResult2, + GetLastError()); + if (!FindClose(hFind)) + { + Trace("FindNextFileA: ERROR -> Failed to close the find handle. " + "GetLastError returned %u.\n", + GetLastError()); + } + Fail(""); + } + + /* we found something, but was it '.' */ + if (strcmp(szResult2, findFileData.cFileName) != 0) + { + if (!FindClose(hFind)) + { + Trace("FindNextFileA: ERROR -> Failed to close the find handle. " + "GetLastError returned %u.\n", + GetLastError()); + } + Fail("FindNextFileA: ERROR -> FindNextFileA based on \"%s\" didn't find" + " the expected \"%s\" but found \"%s\" instead.\n", + szDir, + szResult2, + findFileData.cFileName); + } +} + +int __cdecl main(int argc, char *argv[]) +{ + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + DoTest(szStar, szDot, szDotDot); + DoTest(szStarDotStar, szDot, szDotDot); + + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test2/testinfo.dat new file mode 100644 index 0000000..dd6c1e4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileA/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = FindNextFileA +Name = Test for FindNextFileA (test 2) +Type = DEFAULT +EXE1 = findnextfilea +Description += Tests the PAL implementation of the FindNextFileA function. += Tests '*' and '*.*' to ensure that '.' and '..' are += returned in the expected order diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test1/CMakeLists.txt new file mode 100644 index 0000000..1ba07bd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + FindNextFileW.cpp +) + +add_executable(paltest_findnextfilew_test1 + ${SOURCES} +) + +add_dependencies(paltest_findnextfilew_test1 coreclrpal) + +target_link_libraries(paltest_findnextfilew_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test1/FindNextFileW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test1/FindNextFileW.cpp new file mode 100644 index 0000000..42e2e55 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test1/FindNextFileW.cpp @@ -0,0 +1,249 @@ +// 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. + +/*===================================================================== +** +** Source: FindNextFileW.c +** +** Purpose: Tests the PAL implementation of the FindNextFileW function. +** +** +**===================================================================*/ + +#include + + +const char* szFindName = "test01.txt"; +const char* szFindName_02 = "test02.txt"; +const char* szFindNameWldCard_01 = "test0?.txt"; +const char* szFindNameWldCard_02 = "*.txt"; +const char* szDirName = "test_dir"; +const char* szDirName_02 = "test_dir_02"; +const char* szDirNameWldCard = "test_*"; + + + +void removeAll() +{ + WCHAR* wTempPtr = NULL; + + wTempPtr = convert((LPSTR)szDirName); + RemoveDirectoryW(wTempPtr); + free(wTempPtr); + + wTempPtr = convert((LPSTR)szDirName_02); + RemoveDirectoryW(wTempPtr); + free(wTempPtr); + + wTempPtr = convert((LPSTR)szFindName); + DeleteFileW(wTempPtr); + free(wTempPtr); + + wTempPtr = convert((LPSTR)szFindName_02); + DeleteFileW(wTempPtr); + free(wTempPtr); +} + + + +BOOL createTestFile(const char* szName) +{ + FILE *pFile = NULL; + + pFile = fopen(szName, "w"); + if (pFile == NULL) + { + Trace("FindNextFileW: ERROR -> Unable to create file \"%s\".\n", szName); + removeAll(); + return FALSE; + } + else + { + fprintf(pFile, "FindNextFileW test file, \"%s\".\n", szFindName); + fclose(pFile); + } + + return TRUE; +} + + + +int __cdecl main(int argc, char *argv[]) +{ + WIN32_FIND_DATAW findFileData; + WIN32_FIND_DATAW findFileData_02; + HANDLE hFind = NULL; + BOOL bRc = FALSE; + DWORD dwBytesWritten; + WCHAR* wTempPtr = NULL; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + removeAll(); + + + // + // find a file that exists + // + if(createTestFile(szFindName) == FALSE) + { + PAL_TerminateEx(FAIL); + return FAIL; + } + if(createTestFile(szFindName_02) == FALSE) + { + PAL_TerminateEx(FAIL); + return FAIL; + } + + wTempPtr = convert((LPSTR)szFindName); + hFind = FindFirstFileW(wTempPtr, &findFileData); + free(wTempPtr); + if (hFind == INVALID_HANDLE_VALUE) + { + removeAll(); + Fail("FindNextFileW: ERROR -> Unable to find \"%s\"\n", szFindName); + } + else + { + bRc = FindNextFileW(hFind, &findFileData); + if (bRc != FALSE) + { + removeAll(); + Fail("FindNextFileW: ERROR -> Found a file that doesn't exist.\n"); + } + } + + + // + // find a directory that exists + // + wTempPtr = convert((LPSTR)szDirName); + bRc = CreateDirectoryW(wTempPtr, NULL); + free (wTempPtr); + if (bRc == FALSE) + { + removeAll(); + Fail("FindNextFileW: ERROR -> Failed to create the directory \"%s\"\n", + szDirName); + } + wTempPtr = convert((LPSTR)szDirName_02); + bRc = CreateDirectoryW(wTempPtr, NULL); + free (wTempPtr); + if (bRc == FALSE) + { + removeAll(); + Fail("FindNextFileW: ERROR -> Failed to create the directory " + "\"%s\"\n", + szDirName_02); + } + + wTempPtr = convert((LPSTR)szDirName); + hFind = FindFirstFileW(wTempPtr, &findFileData); + free (wTempPtr); + if (hFind == INVALID_HANDLE_VALUE) + { + removeAll(); + Fail("FindNextFileW: ERROR. FindFirstFileW was unable " + "to find \"%s\"\n", + szDirName); + } + else + { + bRc = FindNextFileW(hFind, &findFileData); + if (bRc != FALSE) + { + removeAll(); + Fail("FindNextFileW: ERROR -> Found a directory that " + "doesn't exist.\n"); + } + } + + + // + // find a file using wild cards + // + wTempPtr = convert((LPSTR)szFindNameWldCard_01); + hFind = FindFirstFileW(wTempPtr, &findFileData); + free(wTempPtr); + if (hFind == INVALID_HANDLE_VALUE) + { + removeAll(); + Fail("FindNextFileW: ERROR -> FindFirstFileW was unable to " + "find \"%s\"\n", + szFindNameWldCard_01); + } + else + { + bRc = FindNextFileW(hFind, &findFileData_02); + if (bRc == FALSE) + { + removeAll(); + Fail("FindNextFileW: ERROR -> Unable to find another file.\n"); + } + else + { + // validate we found the correct file + if (wcscmp(findFileData_02.cFileName, findFileData.cFileName) == 0) + { + removeAll(); + Fail("FindNextFileW: ERROR -> Found the same file \"%S\".\n", + findFileData.cFileName); + } + } + } + + + // + // find a directory using wild cards + // + wTempPtr = convert((LPSTR)szDirNameWldCard); + hFind = FindFirstFileW(wTempPtr, &findFileData); + free(wTempPtr); + if (hFind == INVALID_HANDLE_VALUE) + { + removeAll(); + Fail("FindNextFileW: ERROR -> Unable to find \"%s\"\n", + szDirNameWldCard); + } + else + { + bRc = FindNextFileW(hFind, &findFileData_02); + if (bRc == FALSE) + { + removeAll(); + Fail("FindNextFileW: ERROR -> Unable to find another directory.\n"); + } + else + { + // validate we found the correct directory + if (wcscmp(findFileData_02.cFileName, findFileData.cFileName) == 0) + { + removeAll(); + Fail("FindNextFileW: ERROR -> Found the same directory " + "\"%S\".\n", + findFileData.cFileName); + } + } + } + + // + // attempt to write to the hFind handle (which should fail) + // + bRc = WriteFile(hFind, "this is a test", 10, &dwBytesWritten, NULL); + if (bRc == TRUE) + { + removeAll(); + Fail("FindNextFileW: ERROR -> Able to write to a FindNextFileW " + "handle.\n"); + } + + removeAll(); + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test1/testinfo.dat new file mode 100644 index 0000000..3eaebef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = FindNextFileW +Name = Test for FindNextFileW (test 1) +Type = DEFAULT +EXE1 = findnextfilew +Description += Create test files and directories to verify FindNextFileW + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test2/CMakeLists.txt new file mode 100644 index 0000000..5944a09 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + findnextfilew.cpp +) + +add_executable(paltest_findnextfilew_test2 + ${SOURCES} +) + +add_dependencies(paltest_findnextfilew_test2 coreclrpal) + +target_link_libraries(paltest_findnextfilew_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test2/findnextfilew.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test2/findnextfilew.cpp new file mode 100644 index 0000000..3e806c2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test2/findnextfilew.cpp @@ -0,0 +1,107 @@ +// 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. + +/*===================================================================== +** +** Source: FindNextFileW.c +** +** Purpose: Tests the PAL implementation of the FindNextFileW function. +** Tests '*' and '*.*' to ensure that '.' and '..' are +** returned in the expected order +** +** +**===================================================================*/ + +#include + + +const WCHAR szwDot[] = {'.','\0'}; +const WCHAR szwDotDot[] = {'.','.','\0'}; +const WCHAR szwStar[] = {'*','\0'}; +const WCHAR szwStarDotStar[] = {'*','.','*','\0'}; + + +static void DoTest(const WCHAR* szwDir, + const WCHAR* szwResult1, + const WCHAR* szwResult2) +{ + HANDLE hFind; + WIN32_FIND_DATAW findFileData; + + /* + ** find the first + */ + if ((hFind = FindFirstFileW(szwDir, &findFileData)) == INVALID_HANDLE_VALUE) + { + Fail("FindNextFileW: ERROR -> FindFirstFileW(\"%S\") failed. " + "GetLastError returned %u.\n", + szwStar, + GetLastError()); + } + + /* did we find the expected */ + if (wcscmp(szwResult1, findFileData.cFileName) != 0) + { + if (!FindClose(hFind)) + { + Trace("FindNextFileW: ERROR -> Failed to close the find handle. " + "GetLastError returned %u.\n", + GetLastError()); + } + Fail("FindNextFileW: ERROR -> FindFirstFile(\"%S\") didn't find" + " the expected \"%S\" but found \"%S\" instead.\n", + szwDir, + szwResult1, + findFileData.cFileName); + } + + /* we found the first expected, let's see if we find the next expected*/ + if (!FindNextFileW(hFind, &findFileData)) + { + Trace("FindNextFileW: ERROR -> FindNextFileW should have found \"%S\"" + " but failed. GetLastError returned %u.\n", + szwResult2, + GetLastError()); + if (!FindClose(hFind)) + { + Trace("FindNextFileW: ERROR -> Failed to close the find handle. " + "GetLastError returned %u.\n", + GetLastError()); + } + Fail(""); + } + + /* we found something, but was it '.' */ + if (wcscmp(szwResult2, findFileData.cFileName) != 0) + { + if (!FindClose(hFind)) + { + Trace("FindNextFileW: ERROR -> Failed to close the find handle. " + "GetLastError returned %u.\n", + GetLastError()); + } + Fail("FindNextFileW: ERROR -> FindNextFileW based on \"%S\" didn't find" + " the expected \"%S\" but found \"%S\" instead.\n", + szwDir, + szwResult2, + findFileData.cFileName); + } +} + +int __cdecl main(int argc, char *argv[]) +{ + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + DoTest(szwStar, szwDot, szwDotDot); + DoTest(szwStarDotStar, szwDot, szwDotDot); + + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test2/testinfo.dat new file mode 100644 index 0000000..98bd5e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FindNextFileW/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = FindNextFileW +Name = Test for FindNextFileW (test 2) +Type = DEFAULT +EXE1 = findnextfilew +Description += Tests the PAL implementation of the FindNextFileW function. += Tests '*' and '*.*' to ensure that '.' and '..' are += returned in the expected order diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/CMakeLists.txt new file mode 100644 index 0000000..bb8a0bb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + FlushFileBuffers.cpp +) + +add_executable(paltest_flushfilebuffers_test1 + ${SOURCES} +) + +add_dependencies(paltest_flushfilebuffers_test1 coreclrpal) + +target_link_libraries(paltest_flushfilebuffers_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/FlushFileBuffers.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/FlushFileBuffers.cpp new file mode 100644 index 0000000..246be64 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/FlushFileBuffers.cpp @@ -0,0 +1,130 @@ +// 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. + +/*===================================================================== +** +** Source: FlushFileBuffers.c +** +** Purpose: Tests the PAL implementation of the FlushFileBuffers function +** This tests checks the return values of FlushFileBuffers -- once on an +** open handle and once on a closed handle. +** +** Depends: +** CreateFile +** WriteFile +** CloseHandle +** DeleteFileA +** +** +**===================================================================*/ + +#include + + +int __cdecl main(int argc, char **argv) +{ + + int TheReturn; + HANDLE TheFileHandle; + DWORD temp; + DWORD originalSize=10000; + DWORD finalSize=10000; + const char* fileName="the_file"; + + /* 1 2 3 4*/ + char * SomeText = "1234567890123456789012345678901234567890"; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + + /* Open the file to get a HANDLE */ + TheFileHandle = + CreateFile( + fileName, + GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(TheFileHandle == INVALID_HANDLE_VALUE) + { + Fail("ERROR: CreateFile failed. Test depends on this function."); + } + + /* get the file size */ + originalSize = GetFileSize (TheFileHandle, NULL) ; + if(originalSize == INVALID_FILE_SIZE) + { + Fail("ERROR: call to GetFileSize faild with error " + "The GetLastError is %d.",GetLastError()); + } + + /* Write something too the HANDLE. Should be buffered */ + TheReturn = WriteFile(TheFileHandle, + SomeText, + strlen(SomeText), + &temp, + NULL); + + if(TheReturn == 0) + { + Fail("ERROR: WriteFile failed. Test depends on this function."); + } + + /* Test to see that FlushFileBuffers returns a success value */ + TheReturn = FlushFileBuffers(TheFileHandle); + if(TheReturn == 0) + { + Fail("ERROR: The FlushFileBuffers function returned 0, which " + "indicates failure, when trying to flush a valid HANDLE. " + "The GetLastError is %d.",GetLastError()); + } + + /* test if flush modified the file */ + finalSize = GetFileSize (TheFileHandle, NULL) ; + if(finalSize==INVALID_FILE_SIZE) + { + Fail("ERROR: call to GetFileSize faild with error " + "The GetLastError is %d.",GetLastError()); + } + if(finalSize!=(originalSize+strlen(SomeText))) + { + Fail("ERROR: FlushFileBuffers failed. data was not written to the file"); + } + + + /* Close the Handle */ + TheReturn = CloseHandle(TheFileHandle); + if(TheReturn == 0) + { + Fail("ERROR: CloseHandle failed. This function depends " + "upon it."); + } + + + /* Test to see that FlushFileBuffers returns a failure value */ + TheReturn = FlushFileBuffers(TheFileHandle); + if(TheReturn != 0) + { + Fail("ERROR: The FlushFileBuffers function returned non-zero, " + "which indicates success, when trying to flush an invalid " + "HANDLE."); + } + + /* make sure file does not exist */ + if(DeleteFileA(fileName)== 0 ) + { + Fail("ERROR: call to DeleteFileA faild with error " + "The GetLastError is %d.",GetLastError()); + } + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/testinfo.dat new file mode 100644 index 0000000..3a0da69 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = FlushFileBuffers +Name = Positive Test for FlushFileBuffers +TYPE = DEFAULT +EXE1 = flushfilebuffers +Description += Test the FlushFileBuffers += Test the return values -- ensure that the correct values are += returned for success and failure. += This test does not prove that flush worked, += there is no way of stopping the OS from flushing += the file by itself. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/CMakeLists.txt new file mode 100644 index 0000000..541e5fa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetConsoleOutputCP.cpp +) + +add_executable(paltest_getconsoleoutputcp_test1 + ${SOURCES} +) + +add_dependencies(paltest_getconsoleoutputcp_test1 coreclrpal) + +target_link_libraries(paltest_getconsoleoutputcp_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/GetConsoleOutputCP.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/GetConsoleOutputCP.cpp new file mode 100644 index 0000000..3deaebf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/GetConsoleOutputCP.cpp @@ -0,0 +1,35 @@ +// 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. + +/*===================================================================== +** +** Source: GetConsoleOutputCP.c (test 1) +** +** Purpose: Tests the PAL implementation of the GetConsoleOutputCP function. +** +** +**===================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + UINT uiCP = 0; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + uiCP = GetConsoleOutputCP(); + if ((uiCP != CP_ACP) && (uiCP != GetACP()) && (uiCP != 437)) /*437 for MSDOS*/ + { + Fail("GetConsoleOutputCP: ERROR -> The invalid code page %d was returned.\n", + uiCP); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/testinfo.dat new file mode 100644 index 0000000..9ad624e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetConsoleOutputCP +Name = Positive Test for GetConsoleOutputCP (test 1) +Type = DEFAULT +EXE1 = getconsoleoutputcp +Description += Test GetConsoleOutputCP. Apparently there are only two possible += return values: CP_ACP or 1252 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/CMakeLists.txt new file mode 100644 index 0000000..b64c050 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetCurrentDirectoryA.cpp +) + +add_executable(paltest_getcurrentdirectorya_test1 + ${SOURCES} +) + +add_dependencies(paltest_getcurrentdirectorya_test1 coreclrpal) + +target_link_libraries(paltest_getcurrentdirectorya_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/GetCurrentDirectoryA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/GetCurrentDirectoryA.cpp new file mode 100644 index 0000000..b09e8a1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/GetCurrentDirectoryA.cpp @@ -0,0 +1,97 @@ +// 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. + +/*===================================================================== +** +** Source: GetCurrentDirectoryA.c (test 1) +** +** Purpose: Tests the PAL implementation of the GetCurrentDirectoryA function. +** +** +**===================================================================*/ + +#include + +const char* szFileName = "blah"; + + +int __cdecl main(int argc, char *argv[]) +{ + DWORD dwRc = 0; + DWORD dwRc2 = 0; + char szReturnedPath[_MAX_PATH+1]; + char szCurrentDir[_MAX_PATH+1]; + LPSTR pPathPtr; + size_t nCount = 0; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + // use GetFullPathName to to get the current path by stripping + // the file name off the end + memset(szReturnedPath, 0, sizeof(char)*(_MAX_PATH+1)); + dwRc = GetFullPathNameA(szFileName, _MAX_PATH, szReturnedPath, &pPathPtr); + if (dwRc == 0) + { + // GetFullPathName failed + Fail("GetCurrentDirectoryA: ERROR -> GetFullPathNameA failed " + "with error code: %ld.\n", GetLastError()); + } + else if(dwRc > _MAX_PATH) + { + Fail("GetCurrentDirectoryA: ERROR -> The path name GetFullPathNameA " + "returned is longer than _MAX_PATH characters.\n"); + } + + + // strip the file name from the full path to get the current path + nCount = strlen(szReturnedPath) - strlen(szFileName) - 1; + memset(szCurrentDir, 0, sizeof(char)*(_MAX_PATH+1)); + strncpy(szCurrentDir, szReturnedPath, nCount); + + // compare the results of GetCurrentDirectoryA with the above + memset(szReturnedPath, 0, sizeof(char)*(_MAX_PATH+1)); + dwRc = GetCurrentDirectoryA((sizeof(char)*(_MAX_PATH+1)), szReturnedPath); + if (dwRc == 0) + { + Fail("GetCurrentDirectoryA: ERROR -> GetCurrentDirectoryA failed " + "with error code: %ld.\n", GetLastError()); + } + else if(dwRc > _MAX_PATH) + { + Fail("GetCurrentDirectoryA: ERROR -> The path name " + "returned is longer than _MAX_PATH characters.\n"); + } + + + /* test case the passed buffer size is not big enough + * function should return the size required + 1 a terminating null character + */ + + /* good buffer size */ + dwRc = GetCurrentDirectoryA((sizeof(CHAR)*(_MAX_PATH+1)), szReturnedPath); + + /* small buffer (0 size)*/ + dwRc2 = GetCurrentDirectoryA(0, szReturnedPath); + if (dwRc2 != (dwRc+1) ) + { + Fail("GetCurrentDirectoryA: ERROR -> failed to give the correct " + "return value when passed a buffer not big enough. " + "Expected %u while result is %u \n",(dwRc+1),dwRc2); + + } + + if (strcmp(szReturnedPath, szCurrentDir) != 0) + { + Fail("GetCurrentDirectoryA: ERROR -> The computed and returned " + "directories do not compare.\n"); + } + + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/testinfo.dat new file mode 100644 index 0000000..c14eb42 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetCurrentDirectoryA +Name = Test for GetCurrentDirectoryA (test 1) +Type = DEFAULT +EXE1 = getcurrentdirectorya +Description += Calculate the current directory name and compare to that += returned by GetCurrentDirectoryA + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/CMakeLists.txt new file mode 100644 index 0000000..92f6e4e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetCurrentDirectoryW.cpp +) + +add_executable(paltest_getcurrentdirectoryw_test1 + ${SOURCES} +) + +add_dependencies(paltest_getcurrentdirectoryw_test1 coreclrpal) + +target_link_libraries(paltest_getcurrentdirectoryw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/GetCurrentDirectoryW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/GetCurrentDirectoryW.cpp new file mode 100644 index 0000000..4f4697b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/GetCurrentDirectoryW.cpp @@ -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. + +/*===================================================================== +** +** Source: GetCurrentDirectoryW.c (test 1) +** +** Purpose: Tests the PAL implementation of the GetCurrentDirectoryW function. +** +** +**===================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + DWORD dwRc = 0; + DWORD dwRc2 = 0; + WCHAR szwReturnedPath[_MAX_PATH+1]; + WCHAR szwCurrentDir[_MAX_PATH+1]; + WCHAR szwFileName[_MAX_PATH] = {'b','l','a','h','\0'}; + LPWSTR pPathPtr; + size_t nCount = 0; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* use GetFullPathName to to get the current path by stripping + * the file name off the end */ + memset(szwReturnedPath, 0, sizeof(WCHAR)*(_MAX_PATH+1)); + dwRc = GetFullPathNameW(szwFileName, _MAX_PATH, szwReturnedPath, &pPathPtr); + if (dwRc == 0) + { + /* GetFullPathName failed */ + Fail("GetCurrentDirectoryW: ERROR -> GetFullPathNameW failed " + "with error code: %ld.\n", GetLastError()); + } + else if(dwRc >_MAX_PATH) + { + Fail("GetCurrentDirectoryW: ERROR -> The path name GetFullPathNameW " + "returned is longer than _MAX_PATH characters.\n"); + } + + /* strip the file name from the full path to get the current path */ + nCount = wcslen(szwReturnedPath) - wcslen(szwFileName) - 1; + memset(szwCurrentDir, 0, sizeof(WCHAR)*(_MAX_PATH+1)); + memcpy(szwCurrentDir, szwReturnedPath, nCount*sizeof(WCHAR)); + + /* compare the results of GetCurrentDirectoryW with the above */ + memset(szwReturnedPath, 0, sizeof(WCHAR)*(_MAX_PATH+1)); + dwRc = GetCurrentDirectoryW((sizeof(WCHAR)*(_MAX_PATH+1)), szwReturnedPath); + if (dwRc == 0) + { + Fail("GetCurrentDirectoryW: ERROR -> GetCurrentDirectoryW failed " + "with error code: %ld.\n", GetLastError()); + } + else if(dwRc >_MAX_PATH) + { + Fail("GetCurrentDirectoryW: ERROR -> The path name " + "returned is longer than _MAX_PATH characters.\n"); + } + + /* check to see whether the length of the returned string is equal to + * the DWORD returned by GetCurrentDirectoryW. + */ + if(wcslen(szwReturnedPath) != dwRc) + { + Fail("GetCurrentDirectoryW: ERROR -> The Length of the path name " + "returned \"%u\" is not equal to the return value of the " + "function \"%u\".\n" , wcslen(szwReturnedPath), dwRc); + } + + + + /* test case the passed buffer size is not big enough + * function should return the size required + 1 for a terminating null character + */ + + /* good buffer size */ + dwRc = GetCurrentDirectoryW((sizeof(WCHAR)*(_MAX_PATH+1)), szwReturnedPath); + + /* small buffer (0 size)*/ + dwRc2 = GetCurrentDirectoryW(0, szwReturnedPath); + if (dwRc2 != (dwRc+1) ) + { + Fail("GetCurrentDirectoryW: ERROR -> failed to give the correct " + "return value when passed a buffer not big enough. " + "Expected %u while result is %u ",(dwRc+1),dwRc2); + + } + + if (wcsncmp(szwReturnedPath, szwCurrentDir, wcslen(szwReturnedPath)) != 0) + { + Fail("GetCurrentDirectoryW: ERROR -> The computed and returned " + "directories do not compare.\n"); + } + + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/testinfo.dat new file mode 100644 index 0000000..4443a79 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetCurrentDirectoryW +Name = Test for GetCurrentDirectoryW (test 1) +Type = DEFAULT +EXE1 = getcurrentdirectoryw +Description += Compute the current directory and compare with the results += from GetCurrentDirectoryW + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/keepme b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/keepme new file mode 100644 index 0000000..31eade7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/keepme @@ -0,0 +1 @@ +Make CVS checkout this directory even with -p option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_file new file mode 100644 index 0000000..0d1ac31 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_file @@ -0,0 +1 @@ +Hidden file \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/keepme b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/keepme new file mode 100644 index 0000000..31eade7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/keepme @@ -0,0 +1 @@ +Make CVS checkout this directory even with -p option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_file new file mode 100644 index 0000000..8f78fcb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_file @@ -0,0 +1 @@ +.hidden_ro_file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/CMakeLists.txt new file mode 100644 index 0000000..347816e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/CMakeLists.txt @@ -0,0 +1,20 @@ +set(SOURCES + GetFileAttributesA.cpp +) + +add_executable(paltest_getfileattributesa_test1 + ${SOURCES} +) + +add_dependencies(paltest_getfileattributesa_test1 coreclrpal) + +target_link_libraries(paltest_getfileattributesa_test1 + ${COMMON_TEST_LIBRARIES} +) +add_subdirectory(.hidden_directory) +add_subdirectory(.hidden_ro_directory) +add_subdirectory(normal_test_directory) +add_subdirectory(no_directory) +add_subdirectory(ro_test_directory) +add_subdirectory(rw_directory) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/GetFileAttributesA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/GetFileAttributesA.cpp new file mode 100644 index 0000000..1d9d85d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/GetFileAttributesA.cpp @@ -0,0 +1,340 @@ +// 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. + +/*============================================================================= +** +** Source: GetFileAttributesA.c +** +** Purpose: Tests the PAL implementation of the GetFileAttributesA function by +** checking the attributes of: +** - a normal directory and file +** - a read only directory and file +** - a read write directory and file +** - a hidden directory and file +** - a read only hidden directory and file +** - a directory and a file with no attributes +** - an invalid file name +** +** +**===========================================================================*/ +#include + +const int TYPE_DIR = 0; +const int TYPE_FILE = 1; +/* Structure defining a test case */ +typedef struct +{ + char *name; /* name of the file/directory */ + DWORD expectedAttribs; /* expected attributes */ + HANDLE hFile; /* Handle to the file */ + int isFile; /* is file (1) or dir (0) */ +}TestCaseFile; + +typedef struct +{ + char *name; /* name of the file/directory */ + DWORD expectedAttribs; /* expected attributes */ + HANDLE hFile; /* Handle to the file */ + int isFile; /* is file (1) or dir (0) */ +}TestCaseDir; + +DWORD desiredAccessFile = GENERIC_READ | GENERIC_WRITE; +DWORD shareModeFile = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE; +LPSECURITY_ATTRIBUTES lpAttrFile = NULL; +DWORD dwCreationDispFile = CREATE_NEW; +DWORD dwFlagsAttribFile = FILE_ATTRIBUTE_NORMAL; +HANDLE hTemplateFile = NULL; + +int numFileTests = 6; +TestCaseFile gfaTestsFile[6]; /* GetFileAttributes tests list */ + +int numDirTests = 6; +TestCaseDir gfaTestsDir[6]; /* GetFileAttributes tests list */ + +BOOL CleanUpFiles() +{ + DWORD dwAtt; + int i; + BOOL result = TRUE; + for (i = 0; i < numFileTests -1 ; i++ ) + { + dwAtt = GetFileAttributesA(gfaTestsFile[i].name); + + if( dwAtt != INVALID_FILE_ATTRIBUTES ) + { + //Trace("Files iteration %d\n", i); + if(!SetFileAttributesA (gfaTestsFile[i].name, FILE_ATTRIBUTE_NORMAL)) + { + result = FALSE; + Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsFile[i].name, FILE_ATTRIBUTE_NORMAL); + } + + if(!DeleteFileA (gfaTestsFile[i].name)) + { + result = FALSE; + Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), gfaTestsFile[i].name, dwAtt); + } + + } + } +// Trace("Value of result is %d\n", result); + return result; +} +BOOL SetUpFiles() +{ + int i = 0; + BOOL result = TRUE; + for (i = 0; i < numFileTests -1; i++ ) + { + gfaTestsFile[i].hFile = CreateFile(gfaTestsFile[i].name, + desiredAccessFile, + shareModeFile, + lpAttrFile, + dwCreationDispFile, + dwFlagsAttribFile, + hTemplateFile); + + if( gfaTestsFile[i].hFile == NULL ) + { + Fail("Error while creating files for iteration %d\n", i); + } + + if(!SetFileAttributesA (gfaTestsFile[i].name, gfaTestsFile[i].expectedAttribs)) + { + result = FALSE; + Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsFile[i].name, gfaTestsFile[i].expectedAttribs); + } + } + + return result; +} + +BOOL CleanUpDirs() +{ + DWORD dwAtt; + int i; + BOOL result = TRUE; + for (i = 0; i < numDirTests -1 ; i++ ) + { + dwAtt = GetFileAttributesA(gfaTestsDir[i].name); + + if( dwAtt != INVALID_FILE_ATTRIBUTES ) + { + + if(!SetFileAttributesA (gfaTestsDir[i].name, FILE_ATTRIBUTE_DIRECTORY)) + { + result = FALSE; + Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsDir[i].name, (FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY)); + } + + if(!RemoveDirectoryA (gfaTestsDir[i].name)) + { + result = FALSE; + Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), gfaTestsDir[i].name, dwAtt); + } + + } + } + + return result; +} + +BOOL SetUpDirs() +{ + int i = 0; + BOOL result = TRUE; + DWORD ret = 0; + for (i = 0; i < numDirTests - 1 ; i++ ) + { + result = CreateDirectoryA(gfaTestsDir[i].name, + NULL); + + if(!result ) + { + result = FALSE; + Fail("Error while creating directory for iteration %d\n", i); + } + + if(!SetFileAttributesA (gfaTestsDir[i].name, gfaTestsDir[i].expectedAttribs)) + { + result = FALSE; + Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsDir[i].name, gfaTestsDir[i].expectedAttribs); + } + + ret = GetFileAttributesA (gfaTestsDir[i].name); + if(ret != gfaTestsDir[i].expectedAttribs) + { + result = FALSE; + Trace("ERROR: Error setting attributes [%s][%d]\n", gfaTestsDir[i].name, gfaTestsDir[i].expectedAttribs); + } + //Trace("Setup Dir setting attr [%d], returned [%d]\n", gfaTestsDir[i].expectedAttribs, ret); + + } + //Trace("Setup dirs returning %d\n", result); + return result; +} +int __cdecl main(int argc, char **argv) +{ + int i; + BOOL bFailed = FALSE; + DWORD result; + + char * NormalDirectoryName = "normal_test_directory"; + char * ReadOnlyDirectoryName = "ro_test_directory"; + char * ReadWriteDirectoryName = "rw_directory"; + char * HiddenDirectoryName = ".hidden_directory"; + char * HiddenReadOnlyDirectoryName = ".hidden_ro_directory"; + char * NoDirectoryName = "no_directory"; + + char * NormalFileName = "normal_test_file"; + char * ReadOnlyFileName = "ro_test_file"; + char * ReadWriteFileName = "rw_file"; + char * HiddenFileName = ".hidden_file"; + char * HiddenReadOnlyFileName = ".hidden_ro_file"; + char * NotReallyAFileName = "not_really_a_file"; + + /* Tests on directory */ + gfaTestsDir[0].name = NormalDirectoryName; + gfaTestsDir[0].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY; + gfaTestsDir[0].isFile = TYPE_DIR; + + gfaTestsDir[1].name = ReadOnlyDirectoryName; + gfaTestsDir[1].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY | + FILE_ATTRIBUTE_READONLY; + gfaTestsDir[1].isFile = TYPE_DIR; + + gfaTestsDir[2].name = ReadWriteDirectoryName; + gfaTestsDir[2].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY; + gfaTestsDir[2].isFile = TYPE_DIR; + + gfaTestsDir[3].name = HiddenDirectoryName; + gfaTestsDir[3].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY; //| + //FILE_ATTRIBUTE_HIDDEN; + gfaTestsDir[3].isFile = TYPE_DIR; + + gfaTestsDir[4].name = HiddenReadOnlyDirectoryName; + gfaTestsDir[4].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY | + FILE_ATTRIBUTE_READONLY; //| + //FILE_ATTRIBUTE_HIDDEN; + gfaTestsDir[4].isFile = TYPE_DIR; + + gfaTestsDir[5].name = NoDirectoryName; + gfaTestsDir[5].expectedAttribs = INVALID_FILE_ATTRIBUTES; + gfaTestsDir[5].isFile = TYPE_DIR; + + /* Tests on file */ + gfaTestsFile[0].name = NormalFileName; + gfaTestsFile[0].expectedAttribs = FILE_ATTRIBUTE_NORMAL; + gfaTestsFile[0].isFile = TYPE_FILE; + + + gfaTestsFile[1].name = ReadOnlyFileName; + gfaTestsFile[1].expectedAttribs = FILE_ATTRIBUTE_READONLY; + gfaTestsFile[1].isFile = TYPE_FILE; + + gfaTestsFile[2].name = ReadWriteFileName; + gfaTestsFile[2].expectedAttribs = FILE_ATTRIBUTE_NORMAL; + gfaTestsFile[2].isFile = TYPE_FILE; + + gfaTestsFile[3].name = HiddenFileName; + gfaTestsFile[3].expectedAttribs = FILE_ATTRIBUTE_NORMAL; //FILE_ATTRIBUTE_HIDDEN; + gfaTestsFile[3].isFile = TYPE_FILE; + + gfaTestsFile[4].name = HiddenReadOnlyFileName; + gfaTestsFile[4].expectedAttribs = FILE_ATTRIBUTE_READONLY; //| + //FILE_ATTRIBUTE_HIDDEN; + gfaTestsFile[4].isFile = TYPE_FILE; + + + gfaTestsFile[5].name = NotReallyAFileName; + gfaTestsFile[5].expectedAttribs = INVALID_FILE_ATTRIBUTES; + gfaTestsFile[5].isFile = TYPE_FILE; + + /* Initialize PAL environment */ + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + if(!CleanUpFiles()) + { + Fail("GetFileAttributesA: Pre-Clean Up Files Failed\n"); + } + + if(0 == SetUpFiles()) + { + Fail("GetFileAttributesA: SetUp Files Failed\n"); + } + + if(!CleanUpDirs()) + { + Fail("GetFileAttributesA: Pre-Clean Up Directories Failed\n"); + } + + if(!SetUpDirs()) + { + Fail("GetFileAttributesA: SetUp Directories Failed\n"); + } + + /* + * Go through all the test cases above, + * call GetFileAttributesA on the name and + * make sure the return value is the one expected + */ + for( i = 0; i < numFileTests; i++ ) + { + result = GetFileAttributesA(gfaTestsFile[i].name); + + if( result != gfaTestsFile[i].expectedAttribs ) + { + bFailed = TRUE; + + Trace("ERROR: GetFileAttributesA Test#%u on %s " + "returned %u instead of %u. \n", + i, + gfaTestsFile[i].name, + result, + gfaTestsFile[i].expectedAttribs); + + } + } + + + for( i = 0; i < numDirTests; i++ ) + { + result = GetFileAttributesA(gfaTestsDir[i].name); + + if( result != gfaTestsDir[i].expectedAttribs ) + { + bFailed = TRUE; + + Trace("ERROR: GetFileAttributesA on Directories Test#%u on %s " + "returned %u instead of %u. \n", + i, + gfaTestsDir[i].name, + result, + gfaTestsDir[i].expectedAttribs); + + } + } + + if(!CleanUpFiles()) + { + Fail("GetFileAttributesA: Post-Clean Up Files Failed\n"); + } + + if(!CleanUpDirs()) + { + Fail("GetFileAttributesA: Post-Clean Up Directories Failed\n"); + } + + /* If any errors, just call Fail() */ + if( bFailed ) + { + Fail(""); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/keepme b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/keepme new file mode 100644 index 0000000..31eade7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/keepme @@ -0,0 +1 @@ +Make CVS checkout this directory even with -p option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_file new file mode 100644 index 0000000..3d631e8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_file @@ -0,0 +1 @@ +No attribs file \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/keepme b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/keepme new file mode 100644 index 0000000..31eade7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/keepme @@ -0,0 +1 @@ +Make CVS checkout this directory even with -p option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_file new file mode 100644 index 0000000..a6e1e62 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_file @@ -0,0 +1,6 @@ +file_io +CopyFileW +Positive Test for CopyFileW +test the CopyFileW function +DEFAULT +CopyFileW \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/keepme b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/keepme new file mode 100644 index 0000000..31eade7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/keepme @@ -0,0 +1 @@ +Make CVS checkout this directory even with -p option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_file new file mode 100644 index 0000000..a6e1e62 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_file @@ -0,0 +1,6 @@ +file_io +CopyFileW +Positive Test for CopyFileW +test the CopyFileW function +DEFAULT +CopyFileW \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/keepme b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/keepme new file mode 100644 index 0000000..31eade7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/keepme @@ -0,0 +1 @@ +Make CVS checkout this directory even with -p option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_file new file mode 100644 index 0000000..39d66f0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_file @@ -0,0 +1 @@ +Read Write file \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/testinfo.dat new file mode 100644 index 0000000..2053220 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/testinfo.dat @@ -0,0 +1,20 @@ +# 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. + +Version = 1.0 + +Section = file_io + +Function = GetFileAttributesA + +Name = Positive Test for GetFileAttributesA + +TYPE = DEFAULT + +EXE1 = getfileattributesa + +Description + += Test the GetFileAttributesA function + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/anchor.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/anchor.txt new file mode 100644 index 0000000..9a277fa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/anchor.txt @@ -0,0 +1,2 @@ +This file is here so this directory gets checked out even with the -P +option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_file new file mode 100644 index 0000000..0d1ac31 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_file @@ -0,0 +1 @@ +Hidden file \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/CMakeLists.txt new file mode 100644 index 0000000..8929fa8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/CMakeLists.txt @@ -0,0 +1,17 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_getfileattributesexw_test1 + ${SOURCES} +) + +add_dependencies(paltest_getfileattributesexw_test1 coreclrpal) + +target_link_libraries(paltest_getfileattributesexw_test1 + ${COMMON_TEST_LIBRARIES} +) +add_subdirectory(.hidden_directory) +add_subdirectory(normal_test_directory) +add_subdirectory(ro_test_directory) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/keepme b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/keepme new file mode 100644 index 0000000..31eade7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/keepme @@ -0,0 +1 @@ +Make CVS checkout this directory even with -p option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_file new file mode 100644 index 0000000..ab7622f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_file @@ -0,0 +1,6 @@ +file_io +CopyFileW +Positive Test for CopyFileW +test the CopyFileW function +DEFAULT +CopyFileW \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/keepme b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/keepme new file mode 100644 index 0000000..31eade7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/keepme @@ -0,0 +1 @@ +Make CVS checkout this directory even with -p option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_file new file mode 100644 index 0000000..ab7622f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_file @@ -0,0 +1,6 @@ +file_io +CopyFileW +Positive Test for CopyFileW +test the CopyFileW function +DEFAULT +CopyFileW \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/test1.cpp new file mode 100644 index 0000000..af279ed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/test1.cpp @@ -0,0 +1,176 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the GetFileAttributesExW function. +** Call the function on a normal directory and file and a read-only directory +** and file and a hidden file and directory. +** Ensure that the returned attributes and file sizes are correct. +** +** +**===================================================================*/ + +#define UNICODE +#include + +typedef enum Item +{ + IS_DIR, + IS_FILE +}ItemType; + +/* This function takes a structure and checks that the information + within the structure is correct. The 'Attribs' are the expected + file attributes, 'TheType' is IS_DIR or IS_FILE and the 'Name' is the + name of the file/directory in question. +*/ +void VerifyInfo(WIN32_FILE_ATTRIBUTE_DATA InfoStruct, + DWORD Attribs, ItemType TheType, WCHAR* Name) +{ + HANDLE hFile; + FILETIME CorrectCreation, CorrectAccess, CorrectModify; + WCHAR CopyName[64]; + + wcscpy(CopyName,Name); + free(Name); + + /* Check to see that the file attributes were recorded */ + if(InfoStruct.dwFileAttributes != Attribs) + { + Fail("ERROR: The file attributes on the file/directory were " + "recorded as being %d instead of %d.\n", + InfoStruct.dwFileAttributes, + Attribs); + } + + /* Note: We can't open a handle to a directory in windows. This + block of tests will only be run on files. + */ + if(TheType == IS_FILE) + { + + /* Get a handle to the file */ + hFile = CreateFile(CopyName, + 0, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: Could not open a handle to the file " + "'%S'. GetLastError() returned %d.",CopyName, + GetLastError()); + } + + + if(InfoStruct.nFileSizeLow != GetFileSize(hFile,NULL)) + { + Fail("ERROR: The file size reported by GetFileAttributesEx " + "did not match the file size given by GetFileSize.\n"); + } + + if(CloseHandle(hFile) == 0) + { + Fail("ERROR: Failed to properly close the handle to the " + "file we're testing. GetLastError() returned %d.\n", + GetLastError()); + + } + + } + + +} + +/* Given a file/directory name, the expected attribs and whether or not it + is a file or directory, call GetFileAttributesEx and verify the + results are correct. +*/ + +void RunTest(char* Name, DWORD Attribs, ItemType TheType ) +{ + WCHAR* TheName; + WIN32_FILE_ATTRIBUTE_DATA InfoStruct; + DWORD TheResult; + + TheName = convert(Name); + + TheResult = GetFileAttributesEx(TheName, + GetFileExInfoStandard, + &InfoStruct); + if(TheResult == 0) + { + free(TheName); + Fail("ERROR: GetFileAttributesEx returned 0, indicating failure. " + "GetLastError returned %d.\n",GetLastError()); + } + + VerifyInfo(InfoStruct, Attribs, TheType, TheName); + +} + +int __cdecl main(int argc, char **argv) +{ + DWORD TheResult; + WCHAR* FileName; + WIN32_FILE_ATTRIBUTE_DATA InfoStruct; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* Test a Directroy */ + RunTest("normal_test_directory", FILE_ATTRIBUTE_DIRECTORY, IS_DIR); + + + /* Test a Normal File */ + + RunTest("normal_test_file", FILE_ATTRIBUTE_NORMAL, IS_FILE); + + /* Test a Read-Only Directroy */ + + RunTest("ro_test_directory", + FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_DIRECTORY, IS_DIR); + + /* Test a Read-Only File */ + + RunTest("ro_test_file", FILE_ATTRIBUTE_READONLY, IS_FILE); + + /* Test a Hidden File */ + + RunTest(".hidden_file", FILE_ATTRIBUTE_HIDDEN, IS_FILE); + + /* Test a Hidden Directroy */ + + RunTest(".hidden_directory", + FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_DIRECTORY, IS_DIR); + + /* Test a Non-Existant File */ + + FileName = convert("nonexistent_test_file"); + + TheResult = GetFileAttributesEx(FileName, + GetFileExInfoStandard, + &InfoStruct); + + if(TheResult != 0) + { + free(FileName); + Fail("ERROR: GetFileAttributesEx returned non-zero, indicating " + "success when it should have failed. It was called on a " + "non-existent file."); + } + + free(FileName); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/testinfo.dat new file mode 100644 index 0000000..fbc397e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetFileAttributesExW +Name = Test with normal file/dir and readonly file/dir and hidden file/dir +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the GetFileAttributesExW function. += Call the function on a normal directory and file and a read-only directory += and file and a hidden file and directory. += Ensure that the attributes returned are correct, and the += file times and file sizes. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/CMakeLists.txt new file mode 100644 index 0000000..fb59139 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_getfileattributesexw_test2 + ${SOURCES} +) + +add_dependencies(paltest_getfileattributesexw_test2 coreclrpal) + +target_link_libraries(paltest_getfileattributesexw_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/test2.cpp new file mode 100644 index 0000000..f244a3b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/test2.cpp @@ -0,0 +1,170 @@ +// 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. + +/*===================================================================== +** +** Source: getfileattributesexw.c (getfileattributesexw\test2) +** +** Purpose: Tests the PAL implementation of GetFileAttributesExW. +** First get a file's attributes, modify the file, +** re-get its attributes +** and compare the two sets of attributes. +** +** +**===================================================================*/ +#include + +/** + * This is a helper function which takes two FILETIME structures and + * checks that the second time isn't before the first. + */ +static int IsFileTimeOk(FILETIME FirstTime, FILETIME SecondTime) +{ + + ULONG64 TimeOne, TimeTwo; + + TimeOne = ((((ULONG64)FirstTime.dwHighDateTime)<<32) | + ((ULONG64)FirstTime.dwLowDateTime)); + + TimeTwo = ((((ULONG64)SecondTime.dwHighDateTime)<<32) | + ((ULONG64)SecondTime.dwLowDateTime)); + + return(TimeOne <= TimeTwo); +} + +int __cdecl main(int argc, char **argv) +{ + DWORD res; + char fileName[MAX_PATH] = "test_file"; + WCHAR *wFileName; + WIN32_FILE_ATTRIBUTE_DATA beforeAttribs; + WIN32_FILE_ATTRIBUTE_DATA afterAttribs; + FILE *testFile; + ULONG64 beforeFileSize; + ULONG64 afterFileSize; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* Create the file */ + testFile = fopen(fileName, "w+"); + if( NULL == testFile ) + { + Fail("Unexpected error: Unable to open file %S " + "with fopen. \n", + fileName); + } + + if( EOF == fputs( "testing", testFile ) ) + { + Fail("Unexpected error: Unable to write to file %S " + "with fputs. \n", + fileName); + } + + if( 0 != fclose(testFile) ) + { + Fail("Unexpected error: Unable to close file %S " + "with fclose. \n", + fileName); + } + + /* Test the Values returned by GetFileAttributesExW + * before and after manipulating a file shouldn't be the same. + */ + + wFileName = convert(fileName); + + res = GetFileAttributesExW(wFileName, + GetFileExInfoStandard, + &beforeAttribs); + + if(res == 0) + { + Fail("ERROR: unable to get initial file attributes with " + "GetFileAttributesEx that returned 0 with error %d.\n", + GetLastError()); + } + + /* Make sure the time are different */ + Sleep(500); + + testFile = fopen(fileName, "w+"); + if( NULL == testFile ) + { + Fail("Unexpected error: Unable to open file %S " + "with fopen. \n", + fileName); + } + + if( EOF == fputs( "testing GetFileAttributesExW", testFile ) ) + { + Fail("Unexpected error: Unable to write to file %S " + "with fputs. \n", + fileName); + } + + if( 0 != fclose(testFile) ) + { + Fail("Unexpected error: Unable to close file %S " + "with fclose. \n", + fileName); + } + + res = GetFileAttributesExW(wFileName, + GetFileExInfoStandard, + &afterAttribs); + + if(res == 0) + { + Fail("ERROR: unable to get file attributes after operations with " + "GetFileAttributesEx that returned 0 with error %d.\n", + GetLastError()); + } + + /* Check the creation time */ + if(!IsFileTimeOk(beforeAttribs.ftCreationTime, + afterAttribs.ftCreationTime)) + { + Fail("ERROR: Creation time after the fputs operation " + "is earlier than the creation time before the fputs.\n"); + } + + /* Check the last access time */ + if(!IsFileTimeOk(beforeAttribs.ftLastAccessTime, + afterAttribs.ftLastAccessTime)) + { + Fail("ERROR: Last access time after the fputs operation " + "is earlier than the last access time before the fputs.\n"); + } + + /* Check the last write time */ + if(!IsFileTimeOk(beforeAttribs.ftLastWriteTime, + afterAttribs.ftLastWriteTime)) + { + Fail("ERROR: Last write time after the fputs operation " + "is earlier than the last write time before the fputs.\n"); + } + + beforeFileSize = ((ULONG64)beforeAttribs.nFileSizeHigh)<< 32 | + ((ULONG64)beforeAttribs.nFileSizeLow); + + afterFileSize = ((ULONG64)afterAttribs.nFileSizeHigh)<< 32 | + ((ULONG64)afterAttribs.nFileSizeLow); + + /* Check the file size */ + if( afterFileSize <= beforeFileSize ) + { + Fail("ERROR: the file should have had a bigger size " + "after(%d) the operations than before(%d)\n", + afterAttribs.nFileSizeLow, + beforeAttribs.nFileSizeLow); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/testinfo.dat new file mode 100644 index 0000000..560e3f6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetFileAttributesExW +Name = Test for GetFileAttributesExW +TYPE = DEFAULT +EXE1 = test2 +Description += Tests the PAL implementation of the GetFileAttributesExW function. += First get a file's attributes, modify the file, re-get its attributes += and compare the two sets of attributes diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/keepme b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/keepme new file mode 100644 index 0000000..31eade7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/keepme @@ -0,0 +1 @@ +Make CVS checkout this directory even with -p option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_file new file mode 100644 index 0000000..0d1ac31 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_file @@ -0,0 +1 @@ +Hidden file \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/keepme b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/keepme new file mode 100644 index 0000000..31eade7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/keepme @@ -0,0 +1 @@ +Make CVS checkout this directory even with -p option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_file new file mode 100644 index 0000000..8f78fcb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_file @@ -0,0 +1 @@ +.hidden_ro_file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/CMakeLists.txt new file mode 100644 index 0000000..039375e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/CMakeLists.txt @@ -0,0 +1,20 @@ +set(SOURCES + GetFileAttributesW.cpp +) + +add_executable(paltest_getfileattributesw_test1 + ${SOURCES} +) + +add_dependencies(paltest_getfileattributesw_test1 coreclrpal) + +target_link_libraries(paltest_getfileattributesw_test1 + ${COMMON_TEST_LIBRARIES} +) +add_subdirectory(.hidden_directory) +add_subdirectory(.hidden_ro_directory) +add_subdirectory(normal_test_directory) +add_subdirectory(no_directory) +add_subdirectory(ro_test_directory) +add_subdirectory(rw_test_directory) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/GetFileAttributesW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/GetFileAttributesW.cpp new file mode 100644 index 0000000..ffae4d9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/GetFileAttributesW.cpp @@ -0,0 +1,345 @@ +// 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. + +/*============================================================================= +** +** Source: GetFileAttributesW.c +** +** Purpose: Tests the PAL implementation of the GetFileAttributesW function by +** checking the attributes of: +** - a normal directory and file +** - a read only directory and file +** - a read write directory and file +** - a hidden directory and file +** - a read only hidden directory and file +** - a directory and a file with no attributes +** - an invalid file name +** +** +**===========================================================================*/ +#include + +const int TYPE_DIR = 0; +const int TYPE_FILE = 1; +/* Structure defining a test case */ +typedef struct +{ + char *name; /* name of the file/directory */ + DWORD expectedAttribs; /* expected attributes */ + HANDLE hFile; /* Handle to the file */ + int isFile; /* is file (1) or dir (0) */ +}TestCaseFile; + +typedef struct +{ + char *name; /* name of the file/directory */ + DWORD expectedAttribs; /* expected attributes */ + HANDLE hFile; /* Handle to the file */ + int isFile; /* is file (1) or dir (0) */ +}TestCaseDir; + +DWORD desiredAccessFile = GENERIC_READ | GENERIC_WRITE; +DWORD shareModeFile = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE; +LPSECURITY_ATTRIBUTES lpAttrFile = NULL; +DWORD dwCreationDispFile = CREATE_NEW; +DWORD dwFlagsAttribFile = FILE_ATTRIBUTE_NORMAL; +HANDLE hTemplateFile = NULL; + +int numFileTests = 6; +TestCaseFile gfaTestsFile[6]; /* GetFileAttributes tests list */ + +int numDirTests = 6; +TestCaseDir gfaTestsDir[6]; /* GetFileAttributes tests list */ + +BOOL CleanUpFiles() +{ + DWORD dwAtt; + int i; + BOOL result = TRUE; + for (i = 0; i < numFileTests - 1 ; i++ ) + { + dwAtt = GetFileAttributesA(gfaTestsFile[i].name); + + if( dwAtt != INVALID_FILE_ATTRIBUTES ) + { + //Trace("Files iteration %d\n", i); + if(!SetFileAttributesA (gfaTestsFile[i].name, FILE_ATTRIBUTE_NORMAL)) + { + result = FALSE; + Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsFile[i].name, FILE_ATTRIBUTE_NORMAL); + } + + if(!DeleteFileA (gfaTestsFile[i].name)) + { + result = FALSE; + Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), gfaTestsFile[i].name, dwAtt); + } + + } + } +// Trace("Value of result is %d\n", result); + return result; +} +BOOL SetUpFiles() +{ + int i = 0; + BOOL result = TRUE; + for (i = 0; i < numFileTests - 1 ; i++ ) + { + gfaTestsFile[i].hFile = CreateFile(gfaTestsFile[i].name, + desiredAccessFile, + shareModeFile, + lpAttrFile, + dwCreationDispFile, + dwFlagsAttribFile, + hTemplateFile); + + if( gfaTestsFile[i].hFile == NULL ) + { + Fail("Error while creating files for iteration %d\n", i); + } + + if(!SetFileAttributesA (gfaTestsFile[i].name, gfaTestsFile[i].expectedAttribs)) + { + result = FALSE; + Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsFile[i].name, gfaTestsFile[i].expectedAttribs); + } + } + + return result; +} + +BOOL CleanUpDirs() +{ + DWORD dwAtt; + int i; + BOOL result = TRUE; + for (i = 0; i < numDirTests - 1; i++ ) + { + dwAtt = GetFileAttributesA(gfaTestsDir[i].name); + + if( dwAtt != INVALID_FILE_ATTRIBUTES ) + { + + if(!SetFileAttributesA (gfaTestsDir[i].name, FILE_ATTRIBUTE_DIRECTORY)) + { + result = FALSE; + Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsDir[i].name, (FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY)); + } + + if(!RemoveDirectoryA (gfaTestsDir[i].name)) + { + result = FALSE; + Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), gfaTestsDir[i].name, dwAtt); + } + + } + } + + return result; +} + +BOOL SetUpDirs() +{ + int i = 0; + BOOL result = TRUE; + DWORD ret = 0; + for (i = 0; i < numDirTests - 1; i++ ) + { + result = CreateDirectoryA(gfaTestsDir[i].name, + NULL); + + if(!result ) + { + result = FALSE; + Fail("Error while creating directory for iteration %d\n", i); + } + + if(!SetFileAttributesA (gfaTestsDir[i].name, gfaTestsDir[i].expectedAttribs)) + { + result = FALSE; + Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsDir[i].name, gfaTestsDir[i].expectedAttribs); + } + + ret = GetFileAttributesA (gfaTestsDir[i].name); + if(ret != gfaTestsDir[i].expectedAttribs) + { + result = FALSE; + Trace("ERROR: Error setting attributes [%s][%d]\n", gfaTestsDir[i].name, gfaTestsDir[i].expectedAttribs); + } + // Trace("Setup Dir setting attr [%d], returned [%d]\n", gfaTestsDir[i].expectedAttribs, ret); + + } +// Trace("Setup dirs returning %d\n", result); + return result; +} +int __cdecl main(int argc, char **argv) +{ + int i; + BOOL bFailed = FALSE; + DWORD result; + + char * NormalDirectoryName = "normal_test_directory"; + char * ReadOnlyDirectoryName = "ro_test_directory"; + char * ReadWriteDirectoryName = "rw_directory"; + char * HiddenDirectoryName = ".hidden_directory"; + char * HiddenReadOnlyDirectoryName = ".hidden_ro_directory"; + char * NoDirectoryName = "no_directory"; + + char * NormalFileName = "normal_test_file"; + char * ReadOnlyFileName = "ro_test_file"; + char * ReadWriteFileName = "rw_file"; + char * HiddenFileName = ".hidden_file"; + char * HiddenReadOnlyFileName = ".hidden_ro_file"; + char * NotReallyAFileName = "not_really_a_file"; + + WCHAR *WStr; + /* Tests on directory */ + gfaTestsDir[0].name = NormalDirectoryName; + gfaTestsDir[0].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY; + gfaTestsDir[0].isFile = TYPE_DIR; + + gfaTestsDir[1].name = ReadOnlyDirectoryName; + gfaTestsDir[1].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY | + FILE_ATTRIBUTE_READONLY; + gfaTestsDir[1].isFile = TYPE_DIR; + + gfaTestsDir[2].name = ReadWriteDirectoryName; + gfaTestsDir[2].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY; + gfaTestsDir[2].isFile = TYPE_DIR; + + gfaTestsDir[3].name = HiddenDirectoryName; + gfaTestsDir[3].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY; //| + //FILE_ATTRIBUTE_HIDDEN; + gfaTestsDir[3].isFile = TYPE_DIR; + + gfaTestsDir[4].name = HiddenReadOnlyDirectoryName; + gfaTestsDir[4].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY | + FILE_ATTRIBUTE_READONLY; //| + //FILE_ATTRIBUTE_HIDDEN; + gfaTestsDir[4].isFile = TYPE_DIR; + + gfaTestsDir[5].name = NoDirectoryName; + gfaTestsDir[5].expectedAttribs = INVALID_FILE_ATTRIBUTES; + gfaTestsDir[5].isFile = TYPE_DIR; + + /* Tests on file */ + gfaTestsFile[0].name = NormalFileName; + gfaTestsFile[0].expectedAttribs = FILE_ATTRIBUTE_NORMAL; + gfaTestsFile[0].isFile = TYPE_FILE; + + + gfaTestsFile[1].name = ReadOnlyFileName; + gfaTestsFile[1].expectedAttribs = FILE_ATTRIBUTE_READONLY; + gfaTestsFile[1].isFile = TYPE_FILE; + + gfaTestsFile[2].name = ReadWriteFileName; + gfaTestsFile[2].expectedAttribs = FILE_ATTRIBUTE_NORMAL; + gfaTestsFile[2].isFile = TYPE_FILE; + + gfaTestsFile[3].name = HiddenFileName; + gfaTestsFile[3].expectedAttribs = FILE_ATTRIBUTE_NORMAL; //FILE_ATTRIBUTE_HIDDEN; + gfaTestsFile[3].isFile = TYPE_FILE; + + gfaTestsFile[4].name = HiddenReadOnlyFileName; + gfaTestsFile[4].expectedAttribs = FILE_ATTRIBUTE_READONLY; //| + //FILE_ATTRIBUTE_HIDDEN; + gfaTestsFile[4].isFile = TYPE_FILE; + + + gfaTestsFile[5].name = NotReallyAFileName; + gfaTestsFile[5].expectedAttribs = INVALID_FILE_ATTRIBUTES; + gfaTestsFile[5].isFile = TYPE_FILE; + + /* Initialize PAL environment */ + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + if(!CleanUpFiles()) + { + Fail("GetFileAttributesW: Pre-Clean Up Files Failed\n"); + } + + if(0 == SetUpFiles()) + { + Fail("GetFileAttributesW: SetUp Files Failed\n"); + } + + if(!CleanUpDirs()) + { + Fail("GetFileAttributesW: Pre-Clean Up Directories Failed\n"); + } + + if(!SetUpDirs()) + { + Fail("GetFileAttributesW: SetUp Directories Failed\n"); + } + + /* + * Go through all the test cases above, + * call GetFileAttributesW on the name and + * make sure the return value is the one expected + */ + for( i = 0; i < numFileTests; i++ ) + { + WStr = convert(gfaTestsFile[i].name); + result = GetFileAttributesW(WStr); + + if( result != gfaTestsFile[i].expectedAttribs ) + { + bFailed = TRUE; + + Trace("ERROR: GetFileAttributesW Test#%u on %s " + "returned %u instead of %u. \n", + i, + gfaTestsFile[i].name, + result, + gfaTestsFile[i].expectedAttribs); + + } + free(WStr); + } + + + for( i = 0; i < numDirTests; i++ ) + { + WStr = convert(gfaTestsDir[i].name); + result = GetFileAttributesW(WStr); + + if( result != gfaTestsDir[i].expectedAttribs ) + { + bFailed = TRUE; + + Trace("ERROR: GetFileAttributesW on Directories Test#%u on %s " + "returned %u instead of %u. \n", + i, + gfaTestsDir[i].name, + result, + gfaTestsDir[i].expectedAttribs); + + } + free(WStr); + } + + if(!CleanUpFiles()) + { + Fail("GetFileAttributesW: Post-Clean Up Files Failed\n"); + } + + if(!CleanUpDirs()) + { + Fail("GetFileAttributesW: Post-Clean Up Directories Failed\n"); + } + + /* If any errors, just call Fail() */ + if( bFailed ) + { + Fail(""); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/keepme b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/keepme new file mode 100644 index 0000000..31eade7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/keepme @@ -0,0 +1 @@ +Make CVS checkout this directory even with -p option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_file new file mode 100644 index 0000000..3d631e8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_file @@ -0,0 +1 @@ +No attribs file \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/keepme b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/keepme new file mode 100644 index 0000000..31eade7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/keepme @@ -0,0 +1 @@ +Make CVS checkout this directory even with -p option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_file new file mode 100644 index 0000000..a6e1e62 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_file @@ -0,0 +1,6 @@ +file_io +CopyFileW +Positive Test for CopyFileW +test the CopyFileW function +DEFAULT +CopyFileW \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/keepme b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/keepme new file mode 100644 index 0000000..31eade7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/keepme @@ -0,0 +1 @@ +Make CVS checkout this directory even with -p option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_file new file mode 100644 index 0000000..a6e1e62 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_file @@ -0,0 +1,6 @@ +file_io +CopyFileW +Positive Test for CopyFileW +test the CopyFileW function +DEFAULT +CopyFileW \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_file b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_file new file mode 100644 index 0000000..39d66f0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_file @@ -0,0 +1 @@ +Read Write file \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/keepme b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/keepme new file mode 100644 index 0000000..31eade7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/keepme @@ -0,0 +1 @@ +Make CVS checkout this directory even with -p option. \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/testinfo.dat new file mode 100644 index 0000000..1a8089a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/testinfo.dat @@ -0,0 +1,20 @@ +# 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. + +Version = 1.0 + +Section = file_io + +Function = GetFileAttributesW + +Name = Positive Test for GetFileAttributesW + +TYPE = DEFAULT + +EXE1 = getfileattributesw + +Description + += Test the GetFileAttributesW function + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/test1/CMakeLists.txt new file mode 100644 index 0000000..fa5a8b3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetFileSize.cpp +) + +add_executable(paltest_getfilesize_test1 + ${SOURCES} +) + +add_dependencies(paltest_getfilesize_test1 coreclrpal) + +target_link_libraries(paltest_getfilesize_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/test1/GetFileSize.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/test1/GetFileSize.cpp new file mode 100644 index 0000000..fac01c9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/test1/GetFileSize.cpp @@ -0,0 +1,173 @@ +// 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. + +/*===================================================================== +** +** Source: GetFileSize.c (test 1) +** +** Purpose: Tests the PAL implementation of the GetFileSize function. +** +** +**===================================================================*/ + +#include + +const char* szTextFile = "text.txt"; + +void CleanUp(HANDLE hFile) +{ + if (CloseHandle(hFile) != TRUE) + { + Fail("GetFileSize: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Fail("GetFileSize: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } +} + +void CheckFileSize(HANDLE hFile, DWORD dwOffset, DWORD dwHighOrder) +{ + DWORD dwRc = 0; + DWORD dwReturnedHighOrder = 0; + DWORD dwReturnedOffset = 0; + + dwRc = SetFilePointer(hFile, dwOffset, (PLONG)&dwHighOrder, FILE_BEGIN); + if (dwRc == INVALID_SET_FILE_POINTER) + { + Trace("GetFileSize: ERROR -> Call to SetFilePointer failed with %ld.\n", + GetLastError()); + CleanUp(hFile); + Fail(""); + } + else + { + if (!SetEndOfFile(hFile)) + { + Trace("GetFileSize: ERROR -> Call to SetEndOfFile failed with %ld.\n", + GetLastError()); + CleanUp(hFile); + Fail(""); + } + dwReturnedOffset = GetFileSize(hFile, &dwReturnedHighOrder); + if ((dwReturnedOffset != dwOffset) || + (dwReturnedHighOrder != dwHighOrder)) + { + CleanUp(hFile); + Fail("GetFileSize: ERROR -> File sizes do not match up.\n"); + } + } +} + + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwRc = 0; + DWORD dwRc2 = 0; + DWORD dwHighOrder = 0; + DWORD lpNumberOfBytesWritten; + char * data = "1234567890"; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + + /* test on a null file handle */ + dwRc = GetFileSize(hFile, NULL); + if (dwRc != INVALID_FILE_SIZE) + { + Fail("GetFileSize: ERROR -> A file size was returned for " + "a null handle.\n"); + } + + /* test on a null file handle using the high order option */ + dwRc = GetFileSize(hFile, &dwHighOrder); + if (dwRc != INVALID_FILE_SIZE) + { + Fail("GetFileSize: ERROR -> A file size was returned for " + "a null handle.\n"); + } + + /* test on an invalid file handle */ + dwRc = GetFileSize(INVALID_HANDLE_VALUE, NULL); + if (dwRc != INVALID_FILE_SIZE) + { + Fail("GetFileSize: ERROR -> A file size was returned for " + "an invalid handle.\n"); + } + + /* test on an invalid file handle using the high order option */ + dwRc = GetFileSize(INVALID_HANDLE_VALUE, &dwHighOrder); + if (dwRc != INVALID_FILE_SIZE) + { + Fail("GetFileSize: ERROR -> A file size was returned for " + "an invalid handle.\n"); + } + + + /* create a test file */ + hFile = CreateFile(szTextFile, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("GetFileSize: ERROR -> Unable to create file \"%s\".\n", + szTextFile); + } + + /* give the file a size */ + CheckFileSize(hFile, 256, 0); + + /* make the file large using the high order option */ + CheckFileSize(hFile, 256, 1); + + + /* set the file size to zero */ + CheckFileSize(hFile, 0, 0); + + /* test if file size changes by writing to it. */ + /* get file size */ + dwRc = GetFileSize(hFile, NULL); + + /* test writing to the file */ + if(WriteFile(hFile, data, strlen(data), &lpNumberOfBytesWritten, NULL)==0) + { + Trace("GetFileSize: ERROR -> Call to WriteFile failed with %ld.\n", + GetLastError()); + CleanUp(hFile); + Fail(""); + } + + /* make sure the buffer flushed.*/ + if(FlushFileBuffers(hFile)==0) + { + Trace("GetFileSize: ERROR -> Call to FlushFileBuffers failed with %ld.\n", + GetLastError()); + CleanUp(hFile); + Fail(""); + } + + /* get file size after writing some chars */ + dwRc2 = GetFileSize(hFile, NULL); + if((dwRc2-dwRc) !=strlen(data)) + { + CleanUp(hFile); + Fail("GetFileSize: ERROR -> File size did not increase properly after.\n" + "writing %d chars\n", strlen(data)); + } + + CleanUp(hFile); + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/test1/testinfo.dat new file mode 100644 index 0000000..3825857 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSize/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetFileSize +Name = Positive Test for GetFileSize (test 1) +Type = DEFAULT +EXE1 = getfilesize +Description += Test GetFileSize on a NULL handle and valid file handles + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/CMakeLists.txt new file mode 100644 index 0000000..6de183f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetFileSizeEx.cpp +) + +add_executable(paltest_getfilesizeex_test1 + ${SOURCES} +) + +add_dependencies(paltest_getfilesizeex_test1 coreclrpal) + +target_link_libraries(paltest_getfilesizeex_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/GetFileSizeEx.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/GetFileSizeEx.cpp new file mode 100644 index 0000000..ef5afd0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/GetFileSizeEx.cpp @@ -0,0 +1,173 @@ +// 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. + +/*===================================================================== +** +** Source: GetFileSizeEx.c (test 1) +** +** Purpose: Tests the PAL implementation of the GetFileSizeEx function. +** +** +**===================================================================*/ + +#include + +const char* szTextFile = "text.txt"; + +void CleanUp(HANDLE hFile) +{ + if (CloseHandle(hFile) != TRUE) + { + Fail("GetFileSizeEx: ERROR -> Unable to close file \"%s\".\n" + " Error is %d\n", + szTextFile, GetLastError()); + } + if (!DeleteFileA(szTextFile)) + { + Fail("GetFileSizeEx: ERROR -> Unable to delete file \"%s\".\n" + " Error is %d\n", + szTextFile, GetLastError()); + } +} + +void CheckFileSize(HANDLE hFile, DWORD dwOffset, DWORD dwHighOrder) +{ + DWORD dwRc = 0; + DWORD dwError = 0; + LARGE_INTEGER qwFileSize; + + dwRc = SetFilePointer(hFile, dwOffset, (PLONG)&dwHighOrder, FILE_BEGIN); + if (dwRc == INVALID_SET_FILE_POINTER) + { + Trace("GetFileSizeEx: ERROR -> Call to SetFilePointer failed with %ld.\n", + GetLastError()); + CleanUp(hFile); + Fail(""); + } + else + { + if (!SetEndOfFile(hFile)) + { + dwError = GetLastError(); + CleanUp(hFile); + if (dwError == 112) + { + Fail("GetFileSizeEx: ERROR -> SetEndOfFile failed due to lack of " + "disk space\n"); + } + else + { + Fail("GetFileSizeEx: ERROR -> SetEndOfFile call failed " + "with error %ld\n", dwError); + } + } + else + { + GetFileSizeEx(hFile, &qwFileSize); + if ((qwFileSize.u.LowPart != dwOffset) || + (qwFileSize.u.HighPart != dwHighOrder)) + { + CleanUp(hFile); + Fail("GetFileSizeEx: ERROR -> File sizes do not match up.\n"); + } + } + } +} + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + BOOL bRc = FALSE; + DWORD lpNumberOfBytesWritten; + LARGE_INTEGER qwFileSize; + LARGE_INTEGER qwFileSize2; + char * data = "1234567890"; + + qwFileSize.QuadPart = 0; + qwFileSize2.QuadPart = 0; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + + /* test on a null file */ + bRc = GetFileSizeEx(NULL, &qwFileSize); + if (bRc != FALSE) + { + Fail("GetFileSizeEx: ERROR -> Returned status as TRUE for " + "a null handle.\n"); + } + + + /* test on an invalid file */ + bRc = GetFileSizeEx(INVALID_HANDLE_VALUE, &qwFileSize); + if (bRc != FALSE) + { + Fail("GetFileSizeEx: ERROR -> Returned status as TRUE for " + "an invalid handle.\n"); + } + + + /* create a test file */ + hFile = CreateFile(szTextFile, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("GetFileSizeEx: ERROR -> Unable to create file \"%s\".\n", + szTextFile); + } + + /* give the file a size */ + CheckFileSize(hFile, 256, 0); + + /* make the file large using the high order option */ + CheckFileSize(hFile, 256, 1); + + + /* set the file size to zero */ + CheckFileSize(hFile, 0, 0); + + /* test if file size changes by writing to it. */ + /* get file size */ + GetFileSizeEx(hFile, &qwFileSize); + + /* test writing to the file */ + if(WriteFile(hFile, data, strlen(data), &lpNumberOfBytesWritten, NULL)==0) + { + Trace("GetFileSizeEx: ERROR -> Call to WriteFile failed with %ld.\n", + GetLastError()); + CleanUp(hFile); + Fail(""); + } + + /* make sure the buffer flushed.*/ + if(FlushFileBuffers(hFile)==0) + { + Trace("GetFileSizeEx: ERROR -> Call to FlushFileBuffers failed with %ld.\n", + GetLastError()); + CleanUp(hFile); + Fail(""); + } + + /* get file size after writing some chars */ + GetFileSizeEx(hFile, &qwFileSize2); + if((qwFileSize2.QuadPart-qwFileSize.QuadPart) !=strlen(data)) + { + CleanUp(hFile); + Fail("GetFileSizeEx: ERROR -> File size did not increase properly after.\n" + "writing %d chars\n", strlen(data)); + } + + CleanUp(hFile); + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/testinfo.dat new file mode 100644 index 0000000..5968fe7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetFileSizeEx +Name = Positive Test for GetFileSizeEx (test 1) +Type = DEFAULT +EXE1 = getfilesizeex +Description += Test GetFileSizeEx on a NULL handle and valid file handles + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/CMakeLists.txt new file mode 100644 index 0000000..070e421 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/CMakeLists.txt new file mode 100644 index 0000000..a531511 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetFullPathNameA.cpp +) + +add_executable(paltest_getfullpathnamea_test1 + ${SOURCES} +) + +add_dependencies(paltest_getfullpathnamea_test1 coreclrpal) + +target_link_libraries(paltest_getfullpathnamea_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/GetFullPathNameA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/GetFullPathNameA.cpp new file mode 100644 index 0000000..de9a266 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/GetFullPathNameA.cpp @@ -0,0 +1,122 @@ +// 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. + +/*===================================================================== +** +** Source: GetFullPathNameA.c (test 1) +** +** Purpose: Tests the PAL implementation of the GetFullPathNameA function. +** +** +**===================================================================*/ + +#include + +const char* szFileName = "testing.tmp"; + +int __cdecl main(int argc, char *argv[]) +{ + DWORD dwRc = 0; + char szReturnedPath[_MAX_DIR+1]; + char szShortBuff[2]; + LPSTR pPathPtr; + HANDLE hFile = NULL; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* perform a short buffer test */ + if (GetFullPathNameA(szFileName, 2, szShortBuff, &pPathPtr) <= 2) + { + /* this test should have failed but didn't */ + Fail("GetFullPathNameA: ERROR -> The API was passed a buffer that was" + " too small for the path name and yet it apparently passed.\n"); + } + + memset(szReturnedPath, 0, _MAX_DIR+1); + dwRc = GetFullPathNameA(szFileName, + _MAX_DIR, + szReturnedPath, + &pPathPtr); + + if (dwRc == 0) + { + // this test should have passed but didn't + Fail("GetFullPathNameA: ERROR -> Function failed for the " + "file \"%s\" with error code: %ld.\n", szFileName, GetLastError()); + } + + // the returned value should be the current directory with the + // file name appended + hFile = CreateFileA(szFileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("GetFullPathNameA: ERROR -> CreateFileA failed to create " + "file \"%s\" with error code: %ld.\n", + szFileName, + GetLastError()); + } + if (CloseHandle(hFile) != TRUE) + { + Fail("GetFullPathNameA: ERROR -> CloseHandle failed with error " + "code: %ld.\n", GetLastError()); + } + + // now try to create the file based on the returned value with the + // CREATE_NEW option which should fail since the file should + // already exist + hFile = CreateFileA(szReturnedPath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + Fail("GetFullPathNameA: ERROR -> CreateFileA was able to " + "CREATE_NEW the returned file \"%s\". The returned file " + "name is therefore apparently wrong.\n", + szReturnedPath); + if (CloseHandle(hFile) != TRUE) + { + Fail("GetFullPathNameA: ERROR -> CloseHandle failed with " + "error code: %ld.\n", GetLastError()); + } + if ((DeleteFileA(szReturnedPath) != TRUE) || + (DeleteFileA(szFileName) != TRUE)) + { + Fail("GetFullPathNameA: ERROR -> DeleteFileA failed to " + "delete the test files with error code: %ld.\n", + GetLastError()); + } + } + + // now make sure the pPathPtr is the same as the file name + if (strcmp(pPathPtr, szFileName) != 0) + { + Fail("GetFullPathNameA: ERROR -> %s != %s\n", + pPathPtr, szFileName); + } + if (DeleteFileA(szFileName) != TRUE) + { + Fail("GetFullPathNameA: ERROR -> DeleteFileA failed to " + "delete \"%s\" with error code: %ld.\n", + szFileName, + GetLastError()); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/testinfo.dat new file mode 100644 index 0000000..a4ccc95 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetFullPathNameA +Name = Test for GetFullPathNameA (test 1) +Type = DEFAULT +EXE1 = getfullpathnamea +Description += Get the full path for a file name and verify the results. += Also, attempt to call GetFullPathNameA with a buffer that is += too small for the returned path and verify the results. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/CMakeLists.txt new file mode 100644 index 0000000..fc400bd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_getfullpathnamea_test2 + ${SOURCES} +) + +add_dependencies(paltest_getfullpathnamea_test2 coreclrpal) + +target_link_libraries(paltest_getfullpathnamea_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/test2.cpp new file mode 100644 index 0000000..95a1497 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/test2.cpp @@ -0,0 +1,143 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Tests the PAL implementation of the GetFullPathNameA API. +** GetFullPathA will be passed a directory that contains '..'. +** To add to this test, we will also call SetCurrentDirectory to +** ensure this is handled properly. +** The test will create a file with in the parent directory +** to verify that the returned directory is valid. +** +** +**===================================================================*/ + +#include + +const char* szDotDot = "..\\"; +const char* szFileName = "testing.tmp"; + +int __cdecl main(int argc, char *argv[]) +{ + DWORD dwRc = 0; + char szReturnedPath[_MAX_DIR+1]; + char szFullFileName[_MAX_DIR+1]; + LPSTR pPathPtr; + HANDLE hFile = NULL; + + /* Initialize the PAL. + */ + if (0 != PAL_Initialize(argc,argv)) + { + return (FAIL); + } + + /* change the directory */ + if (!SetCurrentDirectoryA(szDotDot)) + { + Fail("ERROR: SetCurrentDirectoryA failed with error code %u" + " when passed \"%s\".\n", + GetLastError(), + szDotDot); + } + + /* Initialize the receiving char buffers. + */ + memset(szReturnedPath, 0, _MAX_DIR+1); + memset(szFullFileName, 0, _MAX_DIR+1); + + /* Create Full filename to pass, will include '..\' + * as a pre-fix. */ + strcat(szFullFileName, szDotDot); + strcat(szFullFileName, szFileName); + + /* Get the full path to the filename. + */ + dwRc = GetFullPathNameA(szFullFileName, + _MAX_DIR, + szReturnedPath, + &pPathPtr); + if (dwRc == 0) + { + Fail("ERROR :%ld: GetFullPathName failed to " + "retrieve the path of \"%s\".\n", + GetLastError(), + szFileName); + } + + /* The returned value should be the parent directory with the + * file name appended. */ + hFile = CreateFileA(szReturnedPath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR :%ld: CreateFileA failed to create \"%s\".\n", + GetLastError(), + szReturnedPath); + } + + /* Close the handle to the created file. + */ + if (CloseHandle(hFile) != TRUE) + { + Trace("ERROR :%ld: CloseHandle failed close hFile=0x%lx.\n", + GetLastError()); + goto terminate; + } + + /* Verify that the file was created, attempt to create + * the file again. */ + hFile = CreateFileA(szReturnedPath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + if ((hFile != INVALID_HANDLE_VALUE) && + (GetLastError() != ERROR_ALREADY_EXISTS)) + { + Fail("ERROR :%ld: CreateFileA succeeded to create file " + "\"%s\", that already existed.\n", + GetLastError(), + szFullFileName); + } + + + /* Verify that the returned filename is the same as the supplied. + */ + if (strcmp(pPathPtr, szFileName) != 0) + { + Trace("ERROR : Returned filename \"%s\" is not equal to " + "supplied filename \"%s\".\n", + pPathPtr, + szFileName); + goto terminate; + } + +terminate: + /* Delete the create file. + */ + if (DeleteFileA(szReturnedPath) != TRUE) + { + Fail("ERROR :%ld: DeleteFileA failed to delete \"%s\".\n", + GetLastError(), + szFileName); + } + + /* Terminate the PAL.*/ + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/testinfo.dat new file mode 100644 index 0000000..b75f481 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetFullPathNameA +Name = Test for GetFullPathNameA +Type = DEFAULT +EXE1 = test2 +Description += Tests the PAL implementation of the GetFullPathNameA API. += GetFullPathA will be passed a directory that contains '..'. += To add to this test, we will also call SetCurrentDirectory to += ensure this is handled properly. += The test will create a file with in the parent directory += to verify that the returned directory is valid. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/CMakeLists.txt new file mode 100644 index 0000000..0877aae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_getfullpathnamea_test3 + ${SOURCES} +) + +add_dependencies(paltest_getfullpathnamea_test3 coreclrpal) + +target_link_libraries(paltest_getfullpathnamea_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.cpp new file mode 100644 index 0000000..0cc39e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.cpp @@ -0,0 +1,241 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Tests the PAL implementation of the GetFullPathNameA API. +** GetFullPathA will be passed a directory that contains '..'. +** Example: test_directory\level1\..\testing.tmp. +** To add to this test, we will also call SetCurrentDirectory to +** ensure this is handled properly. +** The test will create a file with in the parent directory +** to verify that the returned directory is valid. +** +** Depends: SetCurrentDirectory, +** CreateDirectory, +** strcat, +** memset, +** CreateFile, +** CloseHandle, +** strcmp, +** DeleteFileA, +** RemoveDirectory. +** + +** +**===================================================================*/ + +#include + +#ifdef WIN32 + const char* szSeperator = "\\"; +#else + const char* szSeperator = "//"; +#endif + +const char* szDotDot = "..\\"; +const char* szFileName = "testing.tmp"; + +int __cdecl main(int argc, char *argv[]) +{ + DWORD dwRc = 0; + char szReturnedPath[_MAX_DIR+1]; + char szFullFileName[_MAX_DIR+1]; + char szDirectory[256]; + char* szCreatedDir = {"test_directory"}; + char* szCreatedNextDir = {"level1"}; + WCHAR *szCreatedDirW; + LPSTR pPathPtr; + HANDLE hFile = NULL; + BOOL bRetVal = FAIL; + + /* Initialize the PAL. + */ + if (0 != PAL_Initialize(argc,argv)) + { + return (FAIL); + } + + /* Initialize the buffer. + */ + memset(szDirectory, '\0', 256); + + /* Change the current working directory. + */ + if (!SetCurrentDirectoryA(szDotDot)) + { + Fail("ERROR: SetCurrentDirectoryA failed with error code %u" + " when passed \"%s\".\n", + GetLastError(), + szDotDot); + } + + /* Create the path to the next level of directory to create. + */ + strcat( szDirectory, szCreatedDir ); + + + /* Create a test directory. + */ + if ( !CreateDirectoryA( szDirectory, NULL ) ) + { + Fail("ERROR:%u: Unable to create directories \"%s\".\n", + GetLastError(), + szDirectory); + } + + /* Create the path to the next level of directory to create. + */ + strcat( szDirectory, szSeperator ); + strcat( szDirectory, szCreatedNextDir ); + + /* Create a test directory. + */ + if ( !CreateDirectoryA( szDirectory, NULL ) ) + { + Trace("ERROR:%u: Unable to create directories \"%s\".\n", + GetLastError(), + szDirectory); + bRetVal = FAIL; + goto cleanUpOne; + } + + /* Initialize the receiving char buffers. + */ + memset(szReturnedPath, 0, _MAX_DIR+1); + memset(szFullFileName, 0, _MAX_DIR+1); + + /* Create Full filename to pass, will include '..\' + * in the middle of the path. + */ + strcat(szFullFileName, szCreatedDir); + strcat(szFullFileName, szDotDot); + strcat(szFullFileName, szFileName); + + /* Get the full path to the filename. + */ + dwRc = GetFullPathNameA(szFullFileName, + _MAX_DIR, + szReturnedPath, + &pPathPtr); + if (dwRc == 0) + { + Trace("ERROR :%ld: GetFullPathName failed to " + "retrieve the path of \"%s\".\n", + GetLastError(), + szFileName); + bRetVal = FAIL; + goto cleanUpTwo; + } + + /* The returned value should be the parent directory with the + * file name appended. */ + hFile = CreateFileA(szReturnedPath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Trace("ERROR :%ld: CreateFileA failed to create \"%s\".\n", + GetLastError(), + szReturnedPath); + bRetVal = FAIL; + goto cleanUpTwo; + } + + /* Close the handle to the created file. + */ + if (CloseHandle(hFile) != TRUE) + { + Trace("ERROR :%ld: CloseHandle failed close hFile=0x%lx.\n", + GetLastError()); + bRetVal = FAIL; + goto cleanUpThree; + } + + /* Verify that the file was created, attempt to create + * the file again. */ + hFile = CreateFileA(szReturnedPath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + if ((hFile != INVALID_HANDLE_VALUE) && + (GetLastError() != ERROR_ALREADY_EXISTS)) + { + Trace("ERROR :%ld: CreateFileA succeeded to create file " + "\"%s\", that already existed.\n", + GetLastError(), + szFullFileName); + bRetVal = FAIL; + goto cleanUpThree; + } + + /* Verify that the returned filename is the same as the supplied. + */ + if (strcmp(pPathPtr, szFileName) != 0) + { + Trace("ERROR : Returned filename \"%s\" is not equal to " + "supplied filename \"%s\".\n", + pPathPtr, + szFileName); + bRetVal = FAIL; + goto cleanUpThree; + } + + /* Successful test. + */ + bRetVal = PASS; + +cleanUpThree: + + /* Delete the create file. + */ + if (DeleteFileA(szReturnedPath) != TRUE) + { + Fail("ERROR :%ld: DeleteFileA failed to delete \"%s\".\n", + GetLastError(), + szFileName); + } + +cleanUpTwo: + + /* Remove the empty directory. + */ + szCreatedDirW = convert((LPSTR)szDirectory); + if (!RemoveDirectoryW(szCreatedDirW)) + { + free (szCreatedDirW); + Fail("ERROR:%u: Unable to remove directory \"%s\".\n", + GetLastError(), + szCreatedDir); + } + free (szCreatedDirW); + +cleanUpOne: + + /* Remove the empty directory. + */ + szCreatedDirW = convert((LPSTR)szCreatedDir); + if (!RemoveDirectoryW(szCreatedDirW)) + { + free (szCreatedDirW); + Fail("ERROR:%u: Unable to remove directory \"%s\".\n", + GetLastError(), + szCreatedDir); + } + free (szCreatedDirW); + + /* Terminate the PAL.*/ + PAL_Terminate(); + return bRetVal; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/testinfo.dat new file mode 100644 index 0000000..3991744 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetFullPathNameA +Name = Test for GetFullPathNameA +Type = DEFAULT +EXE1 = test3 +Description += Tests the PAL implementation of the GetFullPathNameA API. += GetFullPathA will be passed a directory that contains '..'. += Example: test_directory\level1\..\testing.tmp. += To add to this test, we will also call SetCurrentDirectory to += ensure this is handled properly. += The test will create a file with in the parent directory += to verify that the returned directory is valid. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/CMakeLists.txt new file mode 100644 index 0000000..ec502f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_getfullpathnamea_test4 + ${SOURCES} +) + +add_dependencies(paltest_getfullpathnamea_test4 coreclrpal) + +target_link_libraries(paltest_getfullpathnamea_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/test4.cpp new file mode 100644 index 0000000..fb22c1f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/test4.cpp @@ -0,0 +1,203 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c +** +** Purpose: Tests the PAL implementation of the GetFullPathNameA API. +** GetFullPathA will be passed a directory that begins with '..'. +** Example: ..\test_directory\testing.tmp. +** To add to this test, we will also call SetCurrentDirectory to +** ensure this is handled properly. +** The test will create a file with in the parent directory +** to verify that the returned directory is valid. +** +** Depends: SetCurrentDirectory, +** CreateDirectory, +** strcat, +** memset, +** CreateFile, +** CloseHandle, +** strcmp, +** DeleteFileA, +** RemoveDirectory. +** + +** +**===================================================================*/ + +#include + +#ifdef WIN32 + const char* szSeperator = "\\"; +#else + const char* szSeperator = "//"; +#endif + +const char* szDotDot = ".."; +const char* szFileName = "testing.tmp"; + +int __cdecl main(int argc, char *argv[]) +{ + DWORD dwRc = 0; + char szReturnedPath[_MAX_DIR+1]; + char szFullFileName[_MAX_DIR+1]; + char szDirectory[256]; + char* szCreatedDir = {"test_directory"}; + WCHAR *szCreatedDirW; + LPSTR pPathPtr; + HANDLE hFile = NULL; + BOOL bRetVal = FAIL; + + /* Initialize the PAL. + */ + if (0 != PAL_Initialize(argc,argv)) + { + return (FAIL); + } + + /* Initialize the buffer. + */ + memset(szDirectory, '\0', 256); + + /* Create the path to the next level of directory to create. + */ + strcat( szDirectory, szDotDot ); /* .. */ + strcat( szDirectory, szSeperator ); /* ../ */ + strcat( szDirectory, szCreatedDir ); /* ../test_directory */ + + /* Create a test directory. + */ + if ( !CreateDirectoryA( szDirectory, NULL ) ) + { + Fail("ERROR:%u: Unable to create directories \"%s\".\n", + GetLastError(), + szDirectory); + } + + /* Initialize the receiving char buffers. + */ + memset(szReturnedPath, 0, _MAX_DIR+1); + memset(szFullFileName, 0, _MAX_DIR+1); + + /* Create Full filename to pass, will include '..\' + * in the middle of the path. + */ + strcat( szFullFileName, szDotDot ); /* .. */ + strcat( szFullFileName, szSeperator ); /* ../ */ + strcat( szFullFileName, szCreatedDir ); /* ../test_directory */ + strcat( szFullFileName, szSeperator ); /* ../test_directory/ */ + strcat( szFullFileName, szFileName ); /* ../test_directory/testing.tmp */ + + /* Get the full path to the filename. + */ + dwRc = GetFullPathNameA(szFullFileName, + _MAX_DIR, + szReturnedPath, + &pPathPtr); + if (dwRc == 0) + { + Trace("ERROR :%ld: GetFullPathName failed to " + "retrieve the path of \"%s\".\n", + GetLastError(), + szFileName); + bRetVal = FAIL; + goto cleanUpOne; + } + + /* The returned value should be the parent directory with the + * file name appended. */ + hFile = CreateFileA(szReturnedPath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Trace("ERROR :%ld: CreateFileA failed to create \"%s\".\n", + GetLastError(), + szReturnedPath); + bRetVal = FAIL; + goto cleanUpOne; + } + + /* Close the handle to the created file. + */ + if (CloseHandle(hFile) != TRUE) + { + Trace("ERROR :%ld: CloseHandle failed close hFile=0x%lx.\n", + GetLastError()); + bRetVal = FAIL; + goto cleanUpTwo; + } + + /* Verify that the file was created, attempt to create + * the file again. */ + hFile = CreateFileA(szReturnedPath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + if ((hFile != INVALID_HANDLE_VALUE) && + (GetLastError() != ERROR_ALREADY_EXISTS)) + { + Trace("ERROR :%ld: CreateFileA succeeded to create file " + "\"%s\", that already existed.\n", + GetLastError(), + szFullFileName); + bRetVal = FAIL; + goto cleanUpTwo; + } + + /* Verify that the returned filename is the same as the supplied. + */ + if (strcmp(pPathPtr, szFileName) != 0) + { + Trace("ERROR : Returned filename \"%s\" is not equal to " + "supplied filename \"%s\".\n", + pPathPtr, + szFileName); + bRetVal = FAIL; + goto cleanUpTwo; + } + + /* Successful test. + */ + bRetVal = PASS; + +cleanUpTwo: + + /* Delete the create file. + */ + if (DeleteFileA(szReturnedPath) != TRUE) + { + Fail("ERROR :%ld: DeleteFileA failed to delete \"%s\".\n", + GetLastError(), + szFileName); + } + +cleanUpOne: + + /* Remove the empty directory. + */ + szCreatedDirW = convert((LPSTR)szDirectory); + if (!RemoveDirectoryW(szCreatedDirW)) + { + free (szCreatedDirW); + Fail("ERROR:%u: Unable to remove directory \"%s\".\n", + GetLastError(), + szCreatedDir); + } + free (szCreatedDirW); + + /* Terminate the PAL.*/ + PAL_Terminate(); + return bRetVal; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/testinfo.dat new file mode 100644 index 0000000..8a7b3b3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetFullPathNameA +Name = Test for GetFullPathNameA +Type = DEFAULT +EXE1 = test4 +Description += Tests the PAL implementation of the GetFullPathNameA API. += GetFullPathA will be passed a directory that begins with '..'. += Example: ..\test_directory\level1\testing.tmp. += To add to this test, we will also call SetCurrentDirectory to += ensure this is handled properly. += The test will create a file with in the parent directory += to verify that the returned directory is valid. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/CMakeLists.txt new file mode 100644 index 0000000..070e421 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/CMakeLists.txt new file mode 100644 index 0000000..edae18d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetFullPathNameW.cpp +) + +add_executable(paltest_getfullpathnamew_test1 + ${SOURCES} +) + +add_dependencies(paltest_getfullpathnamew_test1 coreclrpal) + +target_link_libraries(paltest_getfullpathnamew_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/GetFullPathNameW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/GetFullPathNameW.cpp new file mode 100644 index 0000000..592d3ad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/GetFullPathNameW.cpp @@ -0,0 +1,157 @@ +// 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. + +/*===================================================================== +** +** Source: GetFullPathNameW.c (test 1) +** +** Purpose: Tests the PAL implementation of the GetFullPathNameW function. +** +** +**===================================================================*/ + +#include + +const char* szFileName = "testing.tmp"; + +int __cdecl main(int argc, char *argv[]) +{ + DWORD dwRc = 0; + WCHAR szwReturnedPath[_MAX_DIR+1]; + WCHAR szwShortBuff[2]; + LPWSTR pPathPtr; + HANDLE hFile = NULL; + WCHAR* szwFileName = NULL; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + szwFileName = convert((char*)szFileName); + + /* perform a short buffer test */ + if (GetFullPathNameW(szwFileName, 2, szwShortBuff, &pPathPtr) <= 2) + { + free(szwFileName); + /* this test should have failed but didn't */ + Fail("GetFullPathNameW: ERROR -> The API was passed a buffer that was" + " too small for the path name and yet it apparently passed.\n"); + } + + + memset(szwReturnedPath, 0, _MAX_DIR+1); + dwRc = GetFullPathNameW(szwFileName, + _MAX_DIR, + szwReturnedPath, + &pPathPtr); + + if (dwRc == 0) + { + /* this test should have passed but didn't */ + free(szwFileName); + Fail("GetFullPathNameW: ERROR -> Function failed for the " + "file \"%s\" with error code: %ld.\n", szFileName, GetLastError()); + } + /* + * the returned value should be the current directory with the + * file name appended + */ + hFile = CreateFileW(szwFileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + free(szwFileName); + Fail("GetFullPathNameW: ERROR -> CreateFileW failed to create " + "file \"%s\" with error code: %ld.\n", + szFileName, + GetLastError()); + } + if (CloseHandle(hFile) != TRUE) + { + free(szwFileName); + Trace("GetFullPathNameW: ERROR -> CloseHandle failed with error " + "code: %ld.\n", GetLastError()); + if (DeleteFileA(szFileName) != TRUE) + { + Trace("GetFullPathNameW: ERROR -> DeleteFileW failed to " + "delete the test file with error code: %ld.\n", + GetLastError()); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* + * now try to create the file based on the returned value with the + * CREATE_NEW option which should fail since the file should + * already exist + */ + hFile = CreateFileW(szwReturnedPath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + Trace("GetFullPathNameW: ERROR -> CreateFileW was able to " + "CREATE_NEW the returned file \"%s\". The returned file " + "name is therefore apparently wrong.\n", + szwReturnedPath); + if (CloseHandle(hFile) != TRUE) + { + Trace("GetFullPathNameW: ERROR -> CloseHandle failed with " + "error code: %ld.\n", GetLastError()); + } + if ((DeleteFileW(szwReturnedPath) != TRUE) || + (DeleteFileW(szwFileName) != TRUE)) + { + Trace("GetFullPathNameW: ERROR -> DeleteFileW failed to " + "delete the test files with error code: %ld.\n", + GetLastError()); + } + free(szwFileName); + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* now make sure the pPathPtr is the same as the file name */ + if (wcsncmp(pPathPtr, szwFileName, wcslen(szwFileName)) != 0) + { + Trace("GetFullPathNameW: ERROR -> %s != %s\n", + pPathPtr, szFileName); + if ((DeleteFileW(szwReturnedPath) != TRUE) || + (DeleteFileW(szwFileName) != TRUE)) + { + Trace("GetFullPathNameW: ERROR -> DeleteFileW failed to " + "delete the test files with error code: %ld.\n", + GetLastError()); + } + free(szwFileName); + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* clean up */ + free(szwFileName); + if (DeleteFileA(szFileName) != TRUE) + { + Fail("GetFullPathNameW: ERROR -> DeleteFileW failed to " + "delete \"%s\" with error code: %ld.\n", + szFileName, + GetLastError()); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/testinfo.dat new file mode 100644 index 0000000..4f70617 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetFullPathNameW +Name = Test for GetFullPathNameW (test 1) +Type = DEFAULT +EXE1 = getfullpathnamew +Description += Get the full path for a file name and verify the results. += Also, attempt to call GetFullPathNameW with a buffer that is += too small for the returned path and verify the results. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/CMakeLists.txt new file mode 100644 index 0000000..9d19bf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_getfullpathnamew_test2 + ${SOURCES} +) + +add_dependencies(paltest_getfullpathnamew_test2 coreclrpal) + +target_link_libraries(paltest_getfullpathnamew_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.cpp new file mode 100644 index 0000000..fae042d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.cpp @@ -0,0 +1,159 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Tests the PAL implementation of the GetFullPathNameW function. +** Get the full path for a file name and verify the results. +** This test will use a relative path, containing '..\'. To +** add to this test, we will also call SetCurrentDirectory to +** ensure this is handled properly. +** +** +**===================================================================*/ + +#include + +WCHAR szwDotDot[] = {'.','.','\\','\0'}; +WCHAR szwFileName[] = {'t','e','s','t','i','n','g','.','t','m','p','\0'}; + +int __cdecl main(int argc, char *argv[]) +{ + DWORD dwRc = 0; + WCHAR szwReturnedPath[_MAX_DIR+1]; + WCHAR szwFullFileName[_MAX_DIR+1]; + char *szReturnedPath; + char *szFileName; + LPWSTR pPathPtr; + HANDLE hFile = NULL; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* change the directory */ + if (!SetCurrentDirectoryW(szwDotDot)) + { + Fail("ERROR: SetCurrentDirectoryW failed with error code %u" + " when passed \"%S\".\n", + GetLastError(), + szwDotDot); + } + + /* Initialize the receiving char buffers. + */ + memset(szwReturnedPath, 0, _MAX_DIR+1); + memset(szwFullFileName, 0, _MAX_DIR+1); + + /* Create Full filename to pass, will include '..\' + * as a pre-fix. */ + wcscat(szwFullFileName, szwDotDot); + wcscat(szwFullFileName, szwFileName); + + /* Convert wide char strings to multibyte, to us + * incase of error messages.*/ + szFileName = convertC(szwFileName); + + /* Get the full path to the filename. + */ + dwRc = GetFullPathNameW(szwFullFileName, + _MAX_DIR, + szwReturnedPath, + &pPathPtr); + + szReturnedPath = convertC(szwReturnedPath); + + if (dwRc == 0) + { + Trace("ERROR :%ld: Failed to get path to \"%s\".\n", + GetLastError(), + szReturnedPath); + free(szReturnedPath); + free(szFileName); + Fail(""); + } + + /* + * The returned value should be the parent directory with the + * file name appended. + */ + hFile = CreateFileW(szwReturnedPath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + Trace("ERROR :%ld: CreateFileW failed to create file \"%s\".\n", + GetLastError(), + szReturnedPath); + free(szFileName); + free(szReturnedPath); + Fail(""); + } + + /* Close the handle to the create file.*/ + if (CloseHandle(hFile) != TRUE) + { + Trace("ERROR :%ld: Failed to close handle hFile=0x%lx.\n", + GetLastError(), + hFile); + goto terminate; + } + + /* Verify that the file was created, attempt to create + * the file again. */ + hFile = CreateFileW(szwReturnedPath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + if ((hFile != INVALID_HANDLE_VALUE) && + (GetLastError() != ERROR_ALREADY_EXISTS)) + { + Trace("ERROR :%ld: CreateFileW succeeded to create file " + "\"%s\", that already existed.\n", + GetLastError(), + szReturnedPath); + goto terminate; + } + + /* Verify that the returned filename is the same as the supplied. + */ + if (wcsncmp(pPathPtr, szwFileName, wcslen(szwFileName)) != 0) + { + Trace("ERROR : Returned filename is not equal to \"%s\".\n", + szFileName); + goto terminate; + } + +terminate: + /* Delete the create file. + */ + if (DeleteFileW(szwFullFileName) != TRUE) + { + Trace("ERROR :%ld: DeleteFileW failed to delete \"%s\".\n", + szFileName, + GetLastError()); + free(szFileName); + free(szReturnedPath); + Fail(""); + } + + free(szFileName); + free(szReturnedPath); + + /* Terminate the PAL. + */ + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/testinfo.dat new file mode 100644 index 0000000..b8460e0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetFullPathNameW +Name = Test for GetFullPathNameW (test 2) +Type = DEFAULT +EXE1 = test2 +Description += Get the full path for a file name and verify the results. += This test will use a relative path, containing '..\'. To += add to this test, we will also call SetCurrentDirectory to += ensure this is handled properly. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/CMakeLists.txt new file mode 100644 index 0000000..c91e8bc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_getfullpathnamew_test3 + ${SOURCES} +) + +add_dependencies(paltest_getfullpathnamew_test3 coreclrpal) + +target_link_libraries(paltest_getfullpathnamew_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/test3.cpp new file mode 100644 index 0000000..45c0c98 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/test3.cpp @@ -0,0 +1,240 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Tests the PAL implementation of the GetFullPathNameW API. +** GetFullPathW will be passed a directory that contains '..'. +** Example: test_directory\level1\..\testing.tmp. +** To add to this test, we will also call SetCurrentDirectory to +** ensure this is handled properly. +** The test will create a file with in the parent directory +** to verify that the returned directory is valid. +** +** Depends: SetCurrentDirectory, +** CreateDirectory, +** strcat, +** memset, +** CreateFile, +** CloseHandle, +** strcmp, +** DeleteFileW, +** RemoveDirectory. +** + +** +**===================================================================*/ +#define UNICODE +#include + +#ifdef WIN32 +const WCHAR szSeperator[] = {'\\','\\','\0'}; +#else +const WCHAR szSeperator[] = {'/','/','\0'}; +#endif + +const WCHAR szDotDot[] = {'.','.','\0'}; +const WCHAR szFileName[] = {'t','e','s','t','i','n','g','.','t','m','p','\0'}; + +int __cdecl main(int argc, char *argv[]) +{ + DWORD dwRc = 0; + + WCHAR szReturnedPath[_MAX_DIR+1]; + WCHAR szFullFileName[_MAX_DIR+1]; + WCHAR szDirectory[256]; + WCHAR szCreatedDir[] = {'t','e','s','t','_','d','i','r','\0'}; + WCHAR szCreatedNextDir[] = {'l','e','v','e','l','1','\0'}; + + LPWSTR pPathPtr; + HANDLE hFile = NULL; + BOOL bRetVal = FAIL; + + /* Initialize the PAL. + */ + if ( 0 != PAL_Initialize(argc,argv) ) + { + return (FAIL); + } + + /* Initialize the buffer. + */ + memset( szDirectory, '\0', 256 * sizeof(szDirectory[0]) ); + + /* Change the current working directory. + */ + if ( !SetCurrentDirectoryW(szDotDot) ) + { + Fail("ERROR: SetCurrentDirectoryA failed with error code %u " + "when passed \"%S\".\n", + GetLastError(), + szDotDot); + } + + /* Create the path to the next level of directory to create. + */ + wcscat(szDirectory, szCreatedDir); /* test_dir */ + + + /* Create a test directory. + */ + if (!CreateDirectoryW(szDirectory, NULL)) + { + Fail("ERROR:%u: Unable to create directories \"%S\".\n", + GetLastError(), + szDirectory); + } + + /* Create the path to the next level of directory to create. + */ + wcscat(szDirectory, szSeperator); /* / */ + wcscat(szDirectory, szCreatedNextDir); /* /level1 */ + + /* Create a test directory. + */ + if (!CreateDirectoryW(szDirectory, NULL)) + { + Trace("ERROR:%u: Unable to create directories \"%S\".\n", + GetLastError(), + szDirectory); + bRetVal = FAIL; + goto cleanUpOne; + } + + /* Initialize the receiving char buffers. + */ + memset(szReturnedPath, 0, _MAX_DIR+1); + memset(szFullFileName, 0, _MAX_DIR+1); + + /* Create Full filename to pass, will include '..\' + * in the middle of the path. + */ + wcscat(szFullFileName, szCreatedDir); /*test_dir */ + wcscat(szFullFileName, szSeperator); /*test_dir/ */ + wcscat(szFullFileName, szCreatedNextDir);/*test_dir/level1 */ + wcscat(szFullFileName, szSeperator); /*test_dir/level1/ */ + wcscat(szFullFileName, szDotDot); /*test_dir/level1/.. */ + wcscat(szFullFileName, szSeperator); /*test_dir/level1/../ */ + wcscat(szFullFileName, szFileName); /*test_dir/level1/../testing.tmp */ + + /* Get the full path to the filename. + */ + dwRc = GetFullPathNameW(szFullFileName, + _MAX_DIR, + szReturnedPath, + &pPathPtr); + if (dwRc == 0) + { + Trace("ERROR :%ld: GetFullPathNameW failed to " + "retrieve the path of \"%S\".\n", + GetLastError(), + szFileName); + bRetVal = FAIL; + goto cleanUpTwo; + } + + /* The returned value should be the parent directory with the + * file name appended. */ + hFile = CreateFileW(szReturnedPath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Trace("ERROR :%ld: CreateFileA failed to create \"%S\".\n", + GetLastError(), + szReturnedPath); + bRetVal = FAIL; + goto cleanUpTwo; + } + + /* Close the handle to the created file. + */ + if (CloseHandle(hFile) != TRUE) + { + Trace("ERROR :%ld: CloseHandle failed close hFile=0x%lx.\n", + GetLastError()); + bRetVal = FAIL; + goto cleanUpThree; + } + + /* Verify that the file was created, attempt to create + * the file again. */ + hFile = CreateFileW(szReturnedPath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + if ((hFile != INVALID_HANDLE_VALUE) && + (GetLastError() != ERROR_ALREADY_EXISTS)) + { + Trace("ERROR :%ld: CreateFileA succeeded to create file " + "\"%S\", that already existed.\n", + GetLastError(), + szFullFileName); + bRetVal = FAIL; + goto cleanUpThree; + } + + /* Verify that the returned filename is the same as the supplied. + */ + if (wcscmp(pPathPtr, szFileName) != 0) + { + Trace("ERROR : Returned filename \"%s\" is not equal to " + "supplied filename \"%s\".\n", + pPathPtr, + szFileName); + bRetVal = FAIL; + goto cleanUpThree; + } + + /* Successful test. + */ + bRetVal = PASS; + +cleanUpThree: + + /* Delete the create file. + */ + if (DeleteFileW(szReturnedPath) != TRUE) + { + Fail("ERROR :%ld: DeleteFileA failed to delete \"%S\".\n", + GetLastError(), + szFileName); + } + +cleanUpTwo: + + /* Remove the empty directory. + */ + if (!RemoveDirectoryW(szDirectory)) + { + Fail("ERROR:%u: Unable to remove directory \"%S\".\n", + GetLastError(), + szCreatedDir); + } + +cleanUpOne: + + /* Remove the empty directory. + */ + if (!RemoveDirectoryW(szCreatedDir)) + { + Fail("ERROR:%u: Unable to remove directory \"%s\".\n", + GetLastError(), + szCreatedDir); + } + + /* Terminate the PAL.*/ + PAL_TerminateEx(bRetVal); + return bRetVal; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/testinfo.dat new file mode 100644 index 0000000..1eb6a27 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetFullPathNameW +Name = Test for GetFullPathNameW +Type = DEFAULT +EXE1 = test3 +Description += Tests the PAL implementation of the GetFullPathNameW API. += GetFullPathW will be passed a directory that contains '..'. += Example: test_directory\level1\..\testing.tmp. += To add to this test, we will also call SetCurrentDirectory to += ensure this is handled properly. += The test will create a file with in the parent directory += to verify that the returned directory is valid. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/CMakeLists.txt new file mode 100644 index 0000000..a838b46 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_getfullpathnamew_test4 + ${SOURCES} +) + +add_dependencies(paltest_getfullpathnamew_test4 coreclrpal) + +target_link_libraries(paltest_getfullpathnamew_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/test4.cpp new file mode 100644 index 0000000..baf4b34 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/test4.cpp @@ -0,0 +1,201 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c +** +** Purpose: Tests the PAL implementation of the GetFullPathNameW API. +** GetFullPathNameW will be passed a directory that begins with '..'. +** Example: ..\test_directory\testing.tmp. +** To add to this test, we will also call SetCurrentDirectory to +** ensure this is handled properly. +** The test will create a file with in the parent directory +** to verify that the returned directory is valid. +** +** Depends: SetCurrentDirectory, +** CreateDirectory, +** strcat, +** memset, +** CreateFile, +** CloseHandle, +** strcmp, +** DeleteFileW, +** RemoveDirectory. +** + +** +**===================================================================*/ +#define UNICODE +#include + +#ifdef WIN32 + const WCHAR szSeperator[] = {'\\','\\','\0'}; +#else + const WCHAR szSeperator[] = {'/','/','\0'}; +#endif + +const WCHAR szDotDot[] = {'.','.','\0'}; +const WCHAR szFileName[] = {'t','e','s','t','i','n','g','.','t','m','p','\0'}; + +int __cdecl main(int argc, char *argv[]) +{ + DWORD dwRc = 0; + + WCHAR szReturnedPath[_MAX_DIR+1]; + WCHAR szFullFileName[_MAX_DIR+1]; + WCHAR szDirectory[256]; + WCHAR szCreatedDir[] = {'t','e','s','t','_','d','i','r','\0'}; + + LPWSTR pPathPtr; + HANDLE hFile = NULL; + BOOL bRetVal = FAIL; + + /* Initialize the PAL. + */ + if (0 != PAL_Initialize(argc,argv)) + { + return (FAIL); + } + + /* Initialize the buffer. + */ + memset(szDirectory, '\0', 256 * sizeof(szDirectory[0])); + + /* Create the path to the next level of directory to create. + */ + wcscat(szDirectory, szDotDot); /* .. */ + wcscat(szDirectory, szSeperator); /* ../ */ + wcscat(szDirectory, szCreatedDir); /* ../test_directory */ + + /* Create a test directory. + */ + if (!CreateDirectoryW(szDirectory, NULL)) + { + Fail("ERROR:%u: Unable to create directories \"%S\".\n", + GetLastError(), + szDirectory); + } + + /* Initialize the receiving char buffers. + */ + memset(szReturnedPath, 0, _MAX_DIR+1); + memset(szFullFileName, 0, _MAX_DIR+1); + + /* Create Full filename to pass, will include '..\' + * in the middle of the path. + */ + wcscat( szFullFileName, szDotDot ); /* .. */ + wcscat( szFullFileName, szSeperator ); /* ../ */ + wcscat( szFullFileName, szCreatedDir ); /* ../test_directory */ + wcscat( szFullFileName, szSeperator ); /* ../test_directory/ */ + wcscat( szFullFileName, szFileName ); /* ../test_directory/testing.tmp */ + + /* Get the full path to the filename. + */ + dwRc = GetFullPathNameW(szFullFileName, + _MAX_DIR, + szReturnedPath, + &pPathPtr); + if (dwRc == 0) + { + Trace("ERROR :%ld: GetFullPathName failed to " + "retrieve the path of \"%S\".\n", + GetLastError(), + szFileName); + bRetVal = FAIL; + goto cleanUpOne; + } + + /* The returned value should be the parent directory with the + * file name appended. */ + hFile = CreateFileW(szReturnedPath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Trace("ERROR :%ld: CreateFileA failed to create \"%S\".\n", + GetLastError(), + szReturnedPath); + bRetVal = FAIL; + goto cleanUpOne; + } + + /* Close the handle to the created file. + */ + if (CloseHandle(hFile) != TRUE) + { + Trace("ERROR :%ld: CloseHandle failed close hFile=0x%lx.\n", + GetLastError()); + bRetVal = FAIL; + goto cleanUpTwo; + } + + /* Verify that the file was created, attempt to create + * the file again. */ + hFile = CreateFileW(szReturnedPath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + if ((hFile != INVALID_HANDLE_VALUE) && + (GetLastError() != ERROR_ALREADY_EXISTS)) + { + Trace("ERROR :%ld: CreateFileA succeeded to create file " + "\"%S\", that already existed.\n", + GetLastError(), + szFullFileName); + bRetVal = FAIL; + goto cleanUpTwo; + } + + /* Verify that the returned filename is the same as the supplied. + */ + if (wcscmp(pPathPtr, szFileName) != 0) + { + Trace("ERROR : Returned filename \"%S\" is not equal to " + "supplied filename \"%S\".\n", + pPathPtr, + szFileName); + bRetVal = FAIL; + goto cleanUpTwo; + } + + /* Successful test. + */ + bRetVal = PASS; + +cleanUpTwo: + + /* Delete the create file. + */ + if (DeleteFileW(szReturnedPath) != TRUE) + { + Fail("ERROR :%ld: DeleteFileA failed to delete \"%S\".\n", + GetLastError(), + szFileName); + } + +cleanUpOne: + + /* Remove the empty directory. + */ + if (!RemoveDirectoryW(szDirectory)) + { + Fail("ERROR:%u: Unable to remove directory \"%s\".\n", + GetLastError(), + szCreatedDir); + } + + /* Terminate the PAL.*/ + PAL_TerminateEx(bRetVal); + return bRetVal; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/testinfo.dat new file mode 100644 index 0000000..8a7b3b3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetFullPathNameA +Name = Test for GetFullPathNameA +Type = DEFAULT +EXE1 = test4 +Description += Tests the PAL implementation of the GetFullPathNameA API. += GetFullPathA will be passed a directory that begins with '..'. += Example: ..\test_directory\level1\testing.tmp. += To add to this test, we will also call SetCurrentDirectory to += ensure this is handled properly. += The test will create a file with in the parent directory += to verify that the returned directory is valid. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test1/CMakeLists.txt new file mode 100644 index 0000000..4fe9d38 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetStdHandle.cpp +) + +add_executable(paltest_getstdhandle_test1 + ${SOURCES} +) + +add_dependencies(paltest_getstdhandle_test1 coreclrpal) + +target_link_libraries(paltest_getstdhandle_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test1/GetStdHandle.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test1/GetStdHandle.cpp new file mode 100644 index 0000000..47b1eba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test1/GetStdHandle.cpp @@ -0,0 +1,123 @@ +// 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. + +/*===================================================================== +** +** Source: GetStdHandle.c (test 1) +** +** Purpose: Tests the PAL implementation of the GetStdHandle function. +** +** +**===================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwBytesWritten = 0; + DWORD dwFileType; + BOOL bRc = FALSE; + const char* szText = "this is a test of GetStdHandle\n"; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* + * attempt to get an invalid handle + */ + hFile = GetStdHandle(-2); + if (hFile != INVALID_HANDLE_VALUE) + { + Fail("GetStdHandle: ERROR -> A request for the STD_INPUT_HANDLE " + "returned an invalid handle.\n"); + } + + + /* + * test the STD_INPUT_HANDLE handle + */ + hFile = GetStdHandle(STD_INPUT_HANDLE); + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("GetStdHandle: ERROR -> A request for the STD_INPUT_HANDLE " + "returned an invalid handle.\n"); + } + + /* an attempt to write to the input handle should fail */ + /* I don't know how to automate a read from the input handle */ + bRc = WriteFile(hFile, szText, (DWORD)strlen(szText), &dwBytesWritten, NULL); + if (bRc != FALSE) + { + Fail("GetStdHandle: ERROR -> WriteFile was able to write to " + "STD_INPUT_HANDLE when it should have failed.\n"); + } + + + /* + * test the STD_OUTPUT_HANDLE handle + */ + hFile = GetStdHandle(STD_OUTPUT_HANDLE); + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("GetStdHandle: ERROR -> A request for the STD_OUTPUT_HANDLE " + "returned an invalid handle.\n"); + } + + /* try to write to the output handle */ + bRc = WriteFile(hFile, szText, (DWORD)strlen(szText), &dwBytesWritten, NULL); + if (bRc != TRUE) + { + Fail("GetStdHandle: ERROR -> WriteFile failed to write to " + "STD_OUTPUT_HANDLE with the error %ld\n", + GetLastError()); + } + + + /* test the STD_ERROR_HANDLE handle */ + hFile = GetStdHandle(STD_ERROR_HANDLE); + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("GetStdHandle: ERROR -> A request for the STD_ERROR_HANDLE " + "returned an invalid handle.\n"); + } + + /* try to write to the error handle */ + bRc = WriteFile(hFile, szText, (DWORD)strlen(szText), &dwBytesWritten, NULL); + if (bRc != TRUE) + { + Fail("GetStdHandle: ERROR -> WriteFile failed to write to " + "STD_ERROR_HANDLE with the error %ld\n", + GetLastError()); + } + + /* check to see if we can CloseHandle works on the STD_ERROR_HANDLE */ + if (!CloseHandle(hFile)) + { + Fail("GetStdHandle: ERROR -> CloseHandle failed. GetLastError " + "returned %u.\n", + GetLastError()); + } + + /* try to write to the closed error handle */ + bRc = WriteFile(hFile, + szText, + (DWORD)strlen(szText), + &dwBytesWritten, + NULL); + if (bRc) + { + Fail("GetStdHandle: ERROR -> WriteFile was able to write to the closed" + " STD_ERROR_HANDLE handle.\n"); + } + + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test1/testinfo.dat new file mode 100644 index 0000000..3f7dbf5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetStdHandle +Name = Positive Test for GetStdHandle (test 1) +Type = DEFAULT +EXE1 = getstdhandle +Description += Test GetStdHandle on a valid/invalid std handles + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test2/CMakeLists.txt new file mode 100644 index 0000000..1855b4a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetStdHandle.cpp +) + +add_executable(paltest_getstdhandle_test2 + ${SOURCES} +) + +add_dependencies(paltest_getstdhandle_test2 coreclrpal) + +target_link_libraries(paltest_getstdhandle_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test2/GetStdHandle.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test2/GetStdHandle.cpp new file mode 100644 index 0000000..45f5ddd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test2/GetStdHandle.cpp @@ -0,0 +1,79 @@ +// 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. + +/*===================================================================== +** +** Source: GetStdHandle.c (test 2) +** +** Purpose: Smoke Tests the PAL implementation of the GetStdHandle function. +** +** +**===================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* + * attempt to get an invalid handle + */ + hFile = GetStdHandle(-2); + if (hFile != INVALID_HANDLE_VALUE) + { + Fail("GetStdHandle: ERROR -> A request for the STD_INPUT_HANDLE " + "returned an invalid handle.\n"); + } + + + /* + * test the STD_INPUT_HANDLE handle + */ + hFile = GetStdHandle(STD_INPUT_HANDLE); + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("GetStdHandle: ERROR -> A request for the STD_INPUT_HANDLE " + "returned an invalid handle.\n"); + } + + + /* + * test the STD_OUTPUT_HANDLE handle + */ + hFile = GetStdHandle(STD_OUTPUT_HANDLE); + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("GetStdHandle: ERROR -> A request for the STD_OUTPUT_HANDLE " + "returned an invalid handle.\n"); + } + + /* test the STD_ERROR_HANDLE handle */ + hFile = GetStdHandle(STD_ERROR_HANDLE); + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("GetStdHandle: ERROR -> A request for the STD_ERROR_HANDLE " + "returned an invalid handle.\n"); + } + + + /* check to see if we can CloseHandle works on the STD_ERROR_HANDLE */ + if (!CloseHandle(hFile)) + { + Fail("GetStdHandle: ERROR -> CloseHandle failed. GetLastError " + "returned %u.\n", + GetLastError()); + } + + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test2/testinfo.dat new file mode 100644 index 0000000..dcd498c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetStdHandle/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetStdHandle +Name = Positive Test for GetStdHandle (test 2) +Type = DEFAULT +EXE1 = getstdhandle +Description += Smoke Test GetStdHandle on a valid/invalid std handles + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/test1/CMakeLists.txt new file mode 100644 index 0000000..d738fae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_getsystemtime_test1 + ${SOURCES} +) + +add_dependencies(paltest_getsystemtime_test1 coreclrpal) + +target_link_libraries(paltest_getsystemtime_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/test1/test.cpp new file mode 100644 index 0000000..361dbef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/test1/test.cpp @@ -0,0 +1,124 @@ +// 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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: Test for GetSystemTime() function +** +** +**=========================================================*/ + +/* Note: Some of the range comparisons only check + * the high end of the range. Since the structure + * contains WORDs, negative values can never be included, + * so there is no reason to check and see if the lower + * end of the spectrum is <0 +*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + SYSTEMTIME TheTime; + SYSTEMTIME firstTime; + SYSTEMTIME secondTime; + + WORD avgDeltaFileTime = 0; + + int i=0; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + GetSystemTime(&TheTime); + + /* Go through each item in the structure and ensure it is a valid value. + We can't ensure they have the exact values of the current time, but + at least that they have been set to a valid range of values for that + item. + */ + + /* Year */ + if(TheTime.wYear < (WORD)2001) + { + Fail("ERROR: The year is %d, when it should be at least 2001.", + TheTime.wYear); + } + + /* Month */ + if(TheTime.wMonth > (WORD)12 || TheTime.wMonth < (WORD)1) + { + Fail("ERROR: The month should be between 1 and 12, and it is " + "showing up as %d.",TheTime.wMonth); + } + + /* Weekday */ + if(TheTime.wDayOfWeek > 6) + { + Fail("ERROR: The day of the week should be between 0 and 6, " + "and it is showing up as %d.",TheTime.wDayOfWeek); + } + + /* Day of the Month */ + if(TheTime.wDay > 31 || TheTime.wDay < 1) + { + Fail("ERROR: The day of the month should be between 1 and " + "31, and it is showing up as %d.",TheTime.wDay); + } + + /* Hour */ + if(TheTime.wHour > 23) + { + Fail("ERROR: The hour should be between 0 and 23, and it is " + "showing up as %d.",TheTime.wHour); + } + + /* Minute */ + if(TheTime.wMinute > 59) + { + Fail("ERROR: The minute should be between 0 and 59 and it is " + "showing up as %d.",TheTime.wMinute); + } + + /* Second */ + if(TheTime.wSecond > 59) + { + Fail("ERROR: The second should be between 0 and 59 and it is" + " showing up as %d.",TheTime.wSecond); + } + + /* Millisecond */ + if(TheTime.wMilliseconds > 999) + { + Fail("ERROR: The milliseconds should be between 0 and 999 " + "and it is currently showing %d.",TheTime.wMilliseconds); + } + + /* check if two consecutive calls to system time return */ + /* correct time in ms after sleep() call. */ + for (i = 0; i<5 ;i++) + { + GetSystemTime(&firstTime); + Sleep(1000); + GetSystemTime(&secondTime); + avgDeltaFileTime += abs(firstTime.wSecond - secondTime.wSecond ); + + } + + if( (avgDeltaFileTime/5) < 1.0) + { + Fail("ERROR: 2 calls for GetSystemTime interrupted" + " by a 1000 ms sleep failed Value[%f]", avgDeltaFileTime/5 ); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/test1/testinfo.dat new file mode 100644 index 0000000..05169f6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTime/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = Miscellaneous +Function = GetSystemTime +Name = Positive test of GetSystemTime +Type = DEFAULT +EXE1 = test +Description += Tests the PAL implementation of the GetSystemTime API diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/CMakeLists.txt new file mode 100644 index 0000000..5515d8a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetSystemTimeAsFileTime.cpp +) + +add_executable(paltest_getsystemtimeasfiletime_test1 + ${SOURCES} +) + +add_dependencies(paltest_getsystemtimeasfiletime_test1 coreclrpal) + +target_link_libraries(paltest_getsystemtimeasfiletime_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/GetSystemTimeAsFileTime.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/GetSystemTimeAsFileTime.cpp new file mode 100644 index 0000000..bd7e856 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/GetSystemTimeAsFileTime.cpp @@ -0,0 +1,86 @@ +// 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. + +/*===================================================================== +** +** Source: GetSystemTimeAsFileTime.c +** +** Purpose: Tests the PAL implementation of GetSystemTimeAsFileTime +** Take two times, three seconds apart, and ensure that the time is +** increasing, and that it has increased at least 3 seconds. +** +** +** +**===================================================================*/ + +#include + + +int __cdecl main(int argc, char **argv) +{ + + FILETIME TheFirstTime, TheSecondTime; + ULONG64 FullFirstTime, FullSecondTime; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* Get two times, 3 seconds apart */ + + GetSystemTimeAsFileTime( &TheFirstTime ); + + Sleep( 3000 ); + + GetSystemTimeAsFileTime( &TheSecondTime ); + + /* Convert them to ULONG64 to work with */ + + FullFirstTime = ((( (ULONG64)TheFirstTime.dwHighDateTime )<<32) | + ( (ULONG64)TheFirstTime.dwLowDateTime )); + + FullSecondTime = ((( (ULONG64)TheSecondTime.dwHighDateTime )<<32) | + ( (ULONG64)TheSecondTime.dwLowDateTime )); + + /* Test to ensure the second value is larger than the first */ + + if( FullSecondTime <= FullFirstTime ) + { + Fail("ERROR: The system time didn't increase in the last " + "three seconds. The second time tested was less than " + "or equal to the first."); + } + + /* Note: The 30000000 magic number is 3 seconds in hundreds of nano + seconds. This test checks to ensure at least 3 seconds passed + between the readings. + */ + + if( ( (LONG64)( FullSecondTime - FullFirstTime ) - 30000000 ) < 0 ) + { + ULONG64 TimeError; + + /* Note: This test used to compare the difference between full times + in terms of hundreds of nanoseconds. But the x86 clock seems to be + precise only to the level of about 10000 nanoseconds, so we would + fail the comparison depending on when we took time slices. + + To fix this, we just check that we're within a millisecond of + sleeping 3000 milliseconds. We're not currently ensuring that we + haven't slept much more than 3000 ms. We may want to do that. + */ + TimeError = 30000000 - ( FullSecondTime - FullFirstTime ); + if ( TimeError > 10000) + { + Fail("ERROR: Two system times were tested, with a sleep of 3 " + "seconds between. The time passed should have been at least " + "3 seconds. But, it was less according to the function."); + } + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/testinfo.dat new file mode 100644 index 0000000..3318d13 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetSystemTimeAsFileTime +Name = Positive Test for GetSystemTimeAsFileTime +TYPE = DEFAULT +EXE1 = getsystemtimeasfiletime +Description += Test the GetSystemTimeAsFileTime function. += Take two times, three seconds apart, and ensure that the time is += increasing, and that it has increased at least 3 seconds. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/CMakeLists.txt new file mode 100644 index 0000000..204af67 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetTempFileNameA.cpp +) + +add_executable(paltest_gettempfilenamea_test1 + ${SOURCES} +) + +add_dependencies(paltest_gettempfilenamea_test1 coreclrpal) + +target_link_libraries(paltest_gettempfilenamea_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.cpp new file mode 100644 index 0000000..bea8e27 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.cpp @@ -0,0 +1,125 @@ +// 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. + +/*===================================================================== +** +** Source: GetTempFileNameA.c (test 1) +** +** Purpose: Tests the PAL implementation of the GetTempFileNameA function. +** +** Depends on: +** GetFileAttributesA +** DeleteFileA +** +** +**===================================================================*/ + +#include + + + +int __cdecl main(int argc, char *argv[]) +{ + UINT uiError = 0; + const UINT uUnique = 0; + const char* szDot = {"."}; + const char* szValidPrefix = {"cfr"}; + const char* szLongValidPrefix = {"cfrwxyz"}; + char szReturnedName[256]; + char szTempString[256]; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* valid path with null prefix */ + uiError = GetTempFileNameA(szDot, NULL, uUnique, szReturnedName); + if (uiError == 0) + { + Fail("GetTempFileNameA: ERROR -> Call failed with a valid path " + "with the error code: %ld\n", GetLastError()); + } + else + { + /* verify temp file was created */ + if (GetFileAttributesA(szReturnedName) == -1) + { + Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the " + "returned temp file \"%s\" with error code: %ld.\n", + szReturnedName, + GetLastError()); + } + if (DeleteFileA(szReturnedName) != TRUE) + { + Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete" + "the created temp file with error code: %ld.\n", GetLastError()); + } + } + + + /* valid path with valid prefix */ + uiError = GetTempFileNameA(szDot, szValidPrefix, uUnique, szReturnedName); + if (uiError == 0) + { + Fail("GetTempFileNameA: ERROR -> Call failed with a valid path and " + "prefix with the error code: %ld\n", GetLastError()); + } + else + { + /* verify temp file was created */ + if (GetFileAttributesA(szReturnedName) == -1) + { + Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the " + "returned temp file \"%s\" with error code: %ld.\n", + szReturnedName, + GetLastError()); + } + if (DeleteFileA(szReturnedName) != TRUE) + { + Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete" + "the created temp \"%s\" file with error code: %ld.\n", + szReturnedName, + GetLastError()); + } + } + + /* valid path with long prefix */ + uiError = GetTempFileNameA(szDot, szLongValidPrefix, uUnique, szReturnedName); + if (uiError == 0) + { + Fail("GetTempFileNameA: ERROR -> Call failed with a valid path and " + "prefix with the error code: %ld\n", GetLastError()); + } + else + { + /* verify temp file was created */ + if (GetFileAttributesA(szReturnedName) == -1) + { + Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the " + "returned temp file \"%s\" with error code: %ld.\n", + szReturnedName, + GetLastError()); + } + + /* now verify that it only used the first 3 characters of the prefix */ + sprintf_s(szTempString, _countof(szTempString), "%s\\%s", szDot, szLongValidPrefix); + if (strncmp(szTempString, szReturnedName, 6) == 0) + { + Fail("GetTempFileNameA: ERROR -> It appears that an improper prefix " + "was used.\n"); + } + + if (DeleteFileA(szReturnedName) != TRUE) + { + Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete" + "the created temp file \"%s\" with error code: %ld.\n", + szReturnedName, + GetLastError()); + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/testinfo.dat new file mode 100644 index 0000000..4bf0000 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetTempFileNameA +Name = Test for GetTempFileNameA (test 1) +Type = DEFAULT +EXE1 = gettempfilenamea +Description += Tests the PAL implimentation of GetTempFileNameA by testing += various combinations of path and prefix names. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/CMakeLists.txt new file mode 100644 index 0000000..440f991 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetTempFileNameA.cpp +) + +add_executable(paltest_gettempfilenamea_test2 + ${SOURCES} +) + +add_dependencies(paltest_gettempfilenamea_test2 coreclrpal) + +target_link_libraries(paltest_gettempfilenamea_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.cpp new file mode 100644 index 0000000..861a8b8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.cpp @@ -0,0 +1,80 @@ +// 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. + +/*===================================================================== +** +** Source: GetTempFileNameA.c (test 2) +** +** Purpose: Tests the number of files GetTempFileNameA can create. +** +** Depends on: +** GetFileAttributesA +** oodles of free disk space (>4.07GB) +** +** +**===================================================================*/ + +#include + + + +int __cdecl main(int argc, char *argv[]) +{ + UINT uiError = 0; + DWORD dwError = 0; + const UINT uUnique = 0; + const char* szDot = {"."}; + const char* szValidPrefix = {"cfr"}; + char szReturnedName[256]; + DWORD i; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* test the number of temp files that can be created */ + for (i = 0; i < 0x10005; i++) + { + uiError = GetTempFileNameA(szDot, szValidPrefix, uUnique, szReturnedName); + if (uiError == 0) + { + dwError = GetLastError(); + if (dwError == ERROR_FILE_EXISTS) + { + /* file already existes so break out of the loop */ + i--; /* decrement the count because it wasn't successful */ + break; + } + else + { + /* it was something other than the file already existing? */ + Fail("GetTempFileNameA: ERROR -> Call failed with a valid " + "path and prefix with the error code: %ld\n", GetLastError()); + } + } + else + { + /* verify temp file was created */ + if (GetFileAttributesA(szReturnedName) == -1) + { + Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed " + "on the returned temp file \"%s\" with error code: %ld.\n", + szReturnedName, + GetLastError()); + } + } + } + + /* did it create more than 0xffff files */ + if (i > 0xffff) + { + Fail("GetTempFileNameA: ERROR -> Was able to create more than 0xffff" + " temp files.\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/testinfo.dat new file mode 100644 index 0000000..ca46f6d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetTempFileNameA +Name = Test for GetTempFileNameA (test 2) +Type = DEFAULT +EXE1 = gettempfilenamea +Description += Test the number of files that can be created. Since += GetTempFileNameA only handles 8.3 file names, the test += attempts to create more than the maximum temp files possible += with a 3 character prefix. Since this test takes so long, it += is not to be included in the standard test harness. += This test will also need more than 4.07 GB free disk space. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/CMakeLists.txt new file mode 100644 index 0000000..942d926 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + gettempfilenamea.cpp +) + +add_executable(paltest_gettempfilenamea_test3 + ${SOURCES} +) + +add_dependencies(paltest_gettempfilenamea_test3 coreclrpal) + +target_link_libraries(paltest_gettempfilenamea_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.cpp new file mode 100644 index 0000000..8eccc3d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.cpp @@ -0,0 +1,159 @@ +// 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. + +/*===================================================================== +** +** Source: GetTempFileNameA.c (test 3) +** +** Purpose: Tests the PAL implementation of the GetTempFileNameA function. +** Checks the file attributes and ensures that getting a file name, +** deleting the file and getting another doesn't produce the same +** as the just deleted file. Also checks the file size is 0. +** +** Depends on: +** GetFileAttributesA +** CloseHandle +** DeleteFileA +** CreateFileA +** GetFileSize +** +** +**===================================================================*/ + +#include + + + +int __cdecl main(int argc, char *argv[]) +{ + const UINT uUnique = 0; + UINT uiError; + const char* szDot = {"."}; + char szReturnedName[MAX_LONGPATH]; + char szReturnedName_02[MAX_LONGPATH]; + DWORD dwFileSize = 0; + HANDLE hFile; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* valid path with null prefix */ + uiError = GetTempFileNameA(szDot, NULL, uUnique, szReturnedName); + if (uiError == 0) + { + Fail("GetTempFileNameA: ERROR -> Call failed with a valid path " + "with the error code: %u.\n", + GetLastError()); + } + + /* verify temp file was created */ + if (GetFileAttributesA(szReturnedName) == -1) + { + Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the " + "returned temp file \"%s\" with error code: %u.\n", + szReturnedName, + GetLastError()); + } + + /* + ** verify that the file size is 0 bytes + */ + + hFile = CreateFileA(szReturnedName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + Trace("GetTempFileNameA: ERROR -> CreateFileA failed to open" + " the created temp file with error code: %u.\n", + GetLastError()); + if (!DeleteFileA(szReturnedName)) + { + Trace("GetTempFileNameA: ERROR -> DeleteFileA failed to delete" + " the created temp file with error code: %u.\n", + GetLastError()); + } + Fail(""); + } + + if ((dwFileSize = GetFileSize(hFile, NULL)) != (DWORD)0) + { + Trace("GetTempFileNameA: ERROR -> GetFileSize returned %u whereas" + "it should have returned 0.\n", + dwFileSize); + if (!CloseHandle(hFile)) + { + Trace("GetTempFileNameA: ERROR -> CloseHandle failed. " + "GetLastError returned: %u.\n", + GetLastError()); + } + if (!DeleteFileA(szReturnedName)) + { + Trace("GetTempFileNameA: ERROR -> DeleteFileA failed to delete" + " the created temp file with error code: %u.\n", + GetLastError()); + } + Fail(""); + } + + + if (!CloseHandle(hFile)) + { + Fail("GetTempFileNameA: ERROR -> CloseHandle failed. " + "GetLastError returned: %u.\n", + GetLastError()); + } + + if (DeleteFileA(szReturnedName) != TRUE) + { + Fail("GetTempFileNameA: ERROR -> DeleteFileA failed to delete" + " the created temp file with error code: %u.\n", + GetLastError()); + } + + /* get another and make sure it's not the same as the last */ + uiError = GetTempFileNameA(szDot, NULL, uUnique, szReturnedName_02); + if (uiError == 0) + { + Fail("GetTempFileNameA: ERROR -> Call failed with a valid path " + "with the error code: %u.\n", + GetLastError()); + } + + /* did we get different names? */ + if (strcmp(szReturnedName, szReturnedName_02) == 0) + { + Trace("GetTempFileNameA: ERROR -> The first call returned \"%s\". " + "The second call returned \"%s\" and the two should not be" + " the same.\n", + szReturnedName, + szReturnedName_02); + if (!DeleteFileA(szReturnedName_02)) + { + Trace("GetTempFileNameA: ERROR -> DeleteFileA failed to delete" + " the created temp file with error code: %u.\n", + GetLastError()); + } + Fail(""); + } + + /* clean up */ + if (!DeleteFileA(szReturnedName_02)) + { + Fail("GetTempFileNameA: ERROR -> DeleteFileA failed to delete" + " the created temp file with error code: %u.\n", + GetLastError()); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/testinfo.dat new file mode 100644 index 0000000..f1f5bf5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetTempFileNameA +Name = Test for GetTempFileNameA (test 3) +Type = DEFAULT +EXE1 = gettempfilenamea +Description += Tests the PAL implementation of the GetTempFileNameA function. += Checks the file attributes and ensures that getting a file name, += deleting the file and getting another doesn't produce the same += as the just deleted file. Also checks the file size is 0. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/CMakeLists.txt new file mode 100644 index 0000000..8db0912 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetTempFileNameW.cpp +) + +add_executable(paltest_gettempfilenamew_test1 + ${SOURCES} +) + +add_dependencies(paltest_gettempfilenamew_test1 coreclrpal) + +target_link_libraries(paltest_gettempfilenamew_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.cpp new file mode 100644 index 0000000..ebc4d25 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.cpp @@ -0,0 +1,129 @@ +// 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. + +/*===================================================================== +** +** Source: GetTempFileNameW.c (test 1) +** +** Purpose: Tests the PAL implementation of the GetTempFileNameW function. +** +** +**===================================================================*/ + +#include + + + +int __cdecl main(int argc, char *argv[]) +{ + UINT uiError = 0; + const UINT uUnique = 0; + WCHAR* wPrefix = NULL; + WCHAR* wPath = NULL; + WCHAR wReturnedName[256]; + WCHAR wTempString[256]; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + + // valid path with null ext + wPath = convert("."); + uiError = GetTempFileNameW(wPath, wPrefix, uUnique, wReturnedName); + free (wPath); + if (uiError == 0) + { + Fail("GetTempFileNameW: ERROR -> Call failed with a valid path " + "with the error code: %ld\n", GetLastError()); + } + else + { + // verify temp file was created + if (GetFileAttributesW(wReturnedName) == -1) + { + Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed on the " + "returned temp file with error code: %ld.\n", GetLastError()); + } + if (DeleteFileW(wReturnedName) != TRUE) + { + Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" + "the created temp file with error code: %lld.\n", GetLastError()); + } + } + + + // valid path with valid prefix + wPath = convert("."); + wPrefix = convert("cfr"); + uiError = GetTempFileNameW(wPath, wPrefix, uUnique, wReturnedName); + free (wPath); + free (wPrefix); + if (uiError == 0) + { + Fail("GetTempFileNameW: ERROR -> Call failed with a valid path and " + "prefix with the error code: %ld\n", GetLastError()); + } + else + { + // verify temp file was created + if (GetFileAttributesW(wReturnedName) == -1) + { + Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed on the " + "returned temp file with error code: %ld.\n", GetLastError()); + } + if (DeleteFileW(wReturnedName) != TRUE) + { + Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" + "the created temp file with error code: %lld.\n", GetLastError()); + } + } + + // valid path with long prefix + wPath = convert("."); + wPrefix = convert("cfrwxyz"); + uiError = GetTempFileNameW(wPath, wPrefix, uUnique, wReturnedName); + if (uiError == 0) + { + free (wPath); + free (wPrefix); + Fail("GetTempFileNameW: ERROR -> Call failed with a valid path and " + "prefix with the error code: %ld\n", GetLastError()); + } + else + { + // verify temp file was created + if (GetFileAttributesW(wReturnedName) == -1) + { + free (wPath); + free (wPrefix); + Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed on the " + "returned temp file with error code: %ld.\n", GetLastError()); + } + + // now verify that it only used the first 3 characters of the prefix + swprintf_s(wTempString, _countof(wTempString), convert("%s\\%s"), wPath, wPrefix); + if (memcmp(wTempString, wReturnedName, wcslen(wTempString)*sizeof(WCHAR)) == 0) + { + free (wPath); + free (wPrefix); + Fail("GetTempFileNameW: ERROR -> It appears that an improper prefix " + "was used.\n"); + } + + if (DeleteFileW(wReturnedName) != TRUE) + { + free (wPath); + free (wPrefix); + Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" + "the created temp file with error code: %lld.\n", GetLastError()); + } + } + + free (wPath); + free (wPrefix); + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/testinfo.dat new file mode 100644 index 0000000..72af693 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetTempFileNameW +Name = Test for GetTempFileNameW (test 1) +Type = DEFAULT +EXE1 = gettempfilenamew +Description += Test all the different options of GetTempFileNameW + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/CMakeLists.txt new file mode 100644 index 0000000..2181841 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetTempFileNameW.cpp +) + +add_executable(paltest_gettempfilenamew_test2 + ${SOURCES} +) + +add_dependencies(paltest_gettempfilenamew_test2 coreclrpal) + +target_link_libraries(paltest_gettempfilenamew_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.cpp new file mode 100644 index 0000000..2c8b19e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.cpp @@ -0,0 +1,84 @@ +// 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. + +/*===================================================================== +** +** Source: GetTempFileNameW.c (test 2) +** +** Purpose: Tests the PAL implementation of the GetTempFileNameW function. +** +** +**===================================================================*/ + +#include + + + +int __cdecl main(int argc, char *argv[]) +{ + UINT uiError = 0; + DWORD dwError = 0; + const UINT uUnique = 0; + WCHAR* wPrefix = NULL; + WCHAR* wPath = NULL; + WCHAR wReturnedName[256]; + DWORD i; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + + // test the number of temp files that can be created + wPrefix = convert("cfr"); + wPath = convert("."); + for (i = 0; i < 0x10005; i++) + { + uiError = GetTempFileNameW(wPath, wPrefix, uUnique, wReturnedName); + if (uiError == 0) + { + dwError = GetLastError(); + if (dwError == ERROR_FILE_EXISTS) + { + // file already existes so break out of the loop + i--; // decrement the count because it wasn't successful + break; + } + else + { + // it was something other than the file already existing? + free (wPath); + free (wPrefix); + Fail("GetTempFileNameW: ERROR -> Call failed with a valid " + "path and prefix with the error code: %ld\n", GetLastError()); + } + } + else + { + // verify temp file was created + if (GetFileAttributesW(wReturnedName) == -1) + { + free (wPath); + free (wPrefix); + Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed " + "on the returned temp file with error code: %ld.\n", + GetLastError()); + } + } + } + + free (wPath); + free (wPrefix); + + // did it create more than 0xffff files + if (i > 0xffff) + { + Fail("GetTempFileNameW: ERROR -> Was able to create more than 0xffff" + " temp files.\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/testinfo.dat new file mode 100644 index 0000000..7250011 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetTempFileNameW +Name = Test for GetTempFileNameW (test 2) +Type = DEFAULT +EXE1 = gettempfilenamew +Description += This test attempts to create over 65000 files and will += have to be run manually because it will take longer than += the maximum 60 seconds allowed per test + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/CMakeLists.txt new file mode 100644 index 0000000..469af9d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + gettempfilenamew.cpp +) + +add_executable(paltest_gettempfilenamew_test3 + ${SOURCES} +) + +add_dependencies(paltest_gettempfilenamew_test3 coreclrpal) + +target_link_libraries(paltest_gettempfilenamew_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.cpp new file mode 100644 index 0000000..96d8e66 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.cpp @@ -0,0 +1,161 @@ +// 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. + +/*===================================================================== +** +** Source: GetTempFileNameW.c (test 3) +** +** Purpose: Tests the PAL implementation of the GetTempFileNameW function. +** Checks the file attributes and ensures that getting a file name, +** deleting the file and getting another doesn't produce the same +** as the just deleted file. Also checks the file size is 0. +** +** Depends on: +** GetFileAttributesW +** DeleteFileW +** CreateFileW +** GetFileSize +** CloseHandle +** +** +**===================================================================*/ + +#include + + + +int __cdecl main(int argc, char *argv[]) +{ + const UINT uUnique = 0; + UINT uiError; + WCHAR szwReturnedName[MAX_LONGPATH]; + WCHAR szwReturnedName_02[MAX_LONGPATH]; + DWORD dwFileSize = 0; + HANDLE hFile; + const WCHAR szwDot[] = {'.','\0'}; + const WCHAR szwPre[] = {'c','\0'}; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* valid path with null prefix */ + uiError = GetTempFileNameW(szwDot, szwPre, uUnique, szwReturnedName); + if (uiError == 0) + { + Fail("GetTempFileNameW: ERROR -> Call failed with a valid path " + "with the error code: %u.\n", + GetLastError()); + } + + /* verify temp file was created */ + if (GetFileAttributesW(szwReturnedName) == -1) + { + Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed on the " + "returned temp file \"%S\" with error code: %u.\n", + szwReturnedName, + GetLastError()); + } + + /* + ** verify that the file size is 0 bytes + */ + + hFile = CreateFileW(szwReturnedName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + Trace("GetTempFileNameW: ERROR -> CreateFileW failed to open" + " the created temp file with error code: %u.\n", + GetLastError()); + if (!DeleteFileW(szwReturnedName)) + { + Trace("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" + " the created temp file with error code: %u.\n", + GetLastError()); + } + Fail(""); + } + + if ((dwFileSize = GetFileSize(hFile, NULL)) != (DWORD)0) + { + Trace("GetTempFileNameW: ERROR -> GetFileSize returned %u whereas" + "it should have returned 0.\n", + dwFileSize); + if (!CloseHandle(hFile)) + { + Trace("GetTempFileNameW: ERROR -> CloseHandle was unable to close the " + "opened file. GetLastError returned %u.\n", + GetLastError()); + } + if (!DeleteFileW(szwReturnedName)) + { + Trace("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" + " the created temp file with error code: %u.\n", + GetLastError()); + } + Fail(""); + } + + if (!CloseHandle(hFile)) + { + Fail("GetTempFileNameW: ERROR -> CloseHandle was unable to close the " + "opened file. GetLastError returned %u.\n", + GetLastError()); + } + + + /* delete the file to see if we get the same name next time around */ + if (DeleteFileW(szwReturnedName) != TRUE) + { + Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" + " the created temp file with error code: %u.\n", + GetLastError()); + } + + /* get another and make sure it's not the same as the last */ + uiError = GetTempFileNameW(szwDot, szwPre, uUnique, szwReturnedName_02); + if (uiError == 0) + { + Fail("GetTempFileNameW: ERROR -> Call failed with a valid path " + "with the error code: %u.\n", + GetLastError()); + } + + /* did we get different names? */ + if (wcsncmp(szwReturnedName, szwReturnedName_02, wcslen(szwReturnedName)) == 0) + { + Fail("GetTempFileNameW: ERROR -> The first call returned \"%S\". " + "The second call returned \"%S\" and the two should not be" + " the same.\n", + szwReturnedName, + szwReturnedName_02); + if (!DeleteFileW(szwReturnedName_02)) + { + Trace("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" + " the created temp file with error code: %u.\n", + GetLastError()); + } + Fail(""); + } + + /* clean up */ + if (!DeleteFileW(szwReturnedName_02)) + { + Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" + " the created temp file with error code: %u.\n", + GetLastError()); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/testinfo.dat new file mode 100644 index 0000000..dd482db --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetTempFileNameW +Name = Test for GetTempFileNameW (test 3) +Type = DEFAULT +EXE1 = gettempfilenamew +Description += Tests the PAL implementation of the GetTempFileNameW function. += Checks the file attributes and ensures that getting a file name, += deleting the file and getting another doesn't produce the same += as the just deleted file. Also checks the file size is 0. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/test1/CMakeLists.txt new file mode 100644 index 0000000..690eead --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetTempPathW.cpp +) + +add_executable(paltest_gettemppathw_test1 + ${SOURCES} +) + +add_dependencies(paltest_gettemppathw_test1 coreclrpal) + +target_link_libraries(paltest_gettemppathw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.cpp new file mode 100644 index 0000000..bf997de --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.cpp @@ -0,0 +1,103 @@ +// 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. + +/*===================================================================== +** +** Source: GetTempPathW.c (test 1) +** +** Purpose: Tests the PAL implementation of the GetTempPathW function. +** +** +**===================================================================*/ + +#include + +static void SetTmpDir(const WCHAR path[]) +{ + DWORD result = SetEnvironmentVariableW(W("TMPDIR"), path); + if (!result) + { + Fail("ERROR -> SetEnvironmentVariableW failed with result %d and error code %d.\n", + result, GetLastError()); + } +} + +static void SetAndCompare(const WCHAR tmpDirPath[], const WCHAR expected[]) +{ + DWORD dwBufferLength = _MAX_DIR; + WCHAR path[dwBufferLength]; + + SetTmpDir(tmpDirPath); + + DWORD dwResultLen = GetTempPathW(dwBufferLength, path); + if (dwResultLen <= 0) + { + Fail("ERROR: GetTempPathW returned %d with error code %d.\n", dwResultLen, GetLastError()); + } + if (dwResultLen >= dwBufferLength) + { + Fail("ERROR: Buffer of length %d passed to GetTempPathA was too small to hold %d chars..\n", dwBufferLength, dwResultLen); + } + if (wcscmp(expected, path) != 0) + { + Fail("ERROR: GetTempPathW expected to get '%S' but instead got '%S'.\n", expected, path); + } + if (expected[dwResultLen - 1] != '/') + { + Fail("ERROR: GetTempPathW returned '%S', which should have ended in '/'.\n", path); + } +} + +static void SetAndCheckLength(const WCHAR tmpDirPath [], int bufferLength, int expectedResultLength) +{ + WCHAR path[bufferLength]; + + SetTmpDir(tmpDirPath); + DWORD dwResultLen = GetTempPathW(bufferLength, path); + + if (dwResultLen != expectedResultLength) + { + Fail("GetTempPathW(%d, %S) expected to return %d but returned %d.\n", + bufferLength, tmpDirPath?tmpDirPath:W("NULL"), expectedResultLength, dwResultLen); + } +} + +int __cdecl main(int argc, char *argv[]) +{ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + SetAndCompare(W("/tmp"), W("/tmp/")); + SetAndCompare(W("/tmp/"), W("/tmp/")); + SetAndCompare(W(""), W("/tmp/")); + SetAndCompare(NULL, W("/tmp/")); + SetAndCompare(W("/"), W("/")); + SetAndCompare(W("/var/tmp"), W("/var/tmp/")); + SetAndCompare(W("/var/tmp/"), W("/var/tmp/")); + SetAndCompare(W("~"), W("~/")); + SetAndCompare(W("~/"), W("~/")); + SetAndCompare(W(".tmp"), W(".tmp/")); + SetAndCompare(W("./tmp"), W("./tmp/")); + SetAndCompare(W("/home/someuser/sometempdir"), W("/home/someuser/sometempdir/")); + SetAndCompare(NULL, W("/tmp/")); + + DWORD dwResultLen = GetTempPathA(0, NULL); + if (dwResultLen != 0 || GetLastError() != ERROR_INVALID_PARAMETER) + { + Fail("GetTempPathW(NULL, ...) returned %d with error code %d but " + "should have failed with ERROR_INVALID_PARAMETER (%d).\n", + dwResultLen, GetLastError(), ERROR_INVALID_PARAMETER); + } + + SetAndCheckLength(W("abc/"), 5, 4); + SetAndCheckLength(W("abcd"), 5, 6); + SetAndCheckLength(W("abcde"), 5, 7); + SetAndCheckLength(W("abcdef/"), 5, 9); + SetAndCheckLength(NULL, 5, 6); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/test1/testinfo.dat new file mode 100644 index 0000000..84dc338 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/GetTempPathW/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetTempPathW +Name = Test for GetTempPathW (test 1) +Type = DEFAULT +EXE1 = gettemppathw +Description += Calls GetTempPathW and verifies by passing the returned += value to CreateDirectoryW. If the returned path exists, += CreateDirectoryW will fail. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/CMakeLists.txt new file mode 100644 index 0000000..3582b95 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + MoveFileExA.cpp +) + +add_executable(paltest_movefileexa_test1 + ${SOURCES} +) + +add_dependencies(paltest_movefileexa_test1 coreclrpal) + +target_link_libraries(paltest_movefileexa_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/ExpectedResults.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/ExpectedResults.txt new file mode 100644 index 0000000..684b8a5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/ExpectedResults.txt @@ -0,0 +1 @@ +01110011000000000111001100000000 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/MoveFileExA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/MoveFileExA.cpp new file mode 100644 index 0000000..0bce2b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/MoveFileExA.cpp @@ -0,0 +1,360 @@ +// 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. + +/*===================================================================== +** +** Source: MoveFileExA.c +** +** Purpose: Tests the PAL implementation of the MoveFileExA function. +** +** +**===================================================================*/ + +#include + + +LPSTR lpSource[4] = { + "src_existing.tmp", + "src_non-existant.tmp", + "src_dir_existing", + "src_dir_non-existant" + }; +LPSTR lpDestination[4]={ + "dst_existing.tmp", + "dst_non-existant.tmp", + "dst_dir_existing", + "dst_dir_non-existant" + }; + +LPSTR lpFiles[14] ={ + "src_dir_existing\\test01.tmp", + "src_dir_existing\\test02.tmp", + "dst_dir_existing\\test01.tmp", + "dst_dir_existing\\test02.tmp", + "src_dir_non-existant\\test01.tmp", + "src_dir_non-existant\\test02.tmp", + "dst_existing.tmp\\test01.tmp", + "dst_existing.tmp\\test02.tmp", + "dst_non-existant.tmp\\test01.tmp", + "dst_non-existant.tmp\\test02.tmp", + "dst_dir_existing\\test01.tmp", + "dst_dir_existing\\test02.tmp", + "dst_dir_non-existant\\test01.tmp", + "dst_dir_non-existant\\test02.tmp" + }; + +DWORD dwFlag[2] = {MOVEFILE_COPY_ALLOWED, MOVEFILE_REPLACE_EXISTING}; + + + + +int createExisting(void) +{ + HANDLE tempFile = NULL; + HANDLE tempFile2 = NULL; + + /* create the src_existing file and dst_existing file */ + tempFile = CreateFileA(lpSource[0], GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + tempFile2 = CreateFileA(lpDestination[0], GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + CloseHandle(tempFile2); + CloseHandle(tempFile); + + if ((tempFile == NULL) || (tempFile2 == NULL)) + { + Trace("ERROR[%ul]: couldn't create %S or %S\n", GetLastError(), lpSource[0], + lpDestination[0]); + return FAIL; + } + + /* create the src_dir_existing and dst_dir_existing directory and files */ + CreateDirectoryA(lpSource[2], NULL); + + tempFile = CreateFileA(lpFiles[0], GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + tempFile2 = CreateFileA(lpFiles[1], GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + CloseHandle(tempFile2); + CloseHandle(tempFile); + + if ((tempFile == NULL) || (tempFile2 == NULL)) + { + Trace("ERROR[%ul]: couldn't create src_dir_existing\\test01.tmp\n", GetLastError()); + return FAIL; + } + + CreateDirectoryA(lpDestination[2], NULL); + tempFile = CreateFileA(lpFiles[2], GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + tempFile2 = CreateFileA(lpFiles[3], GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + CloseHandle(tempFile2); + CloseHandle(tempFile); + + if ((tempFile == NULL) || (tempFile2 == NULL)) + { + Trace("ERROR[%ul]: couldn't create dst_dir_existing\\test01.tmp\n" , GetLastError()); + return FAIL; + } + return PASS; + +} + +void removeDirectoryHelper(LPSTR dir, int location) +{ + DWORD dwAtt = GetFileAttributesA(dir); + + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + if(!RemoveDirectoryA(dir)) + { + Fail("ERROR: Failed to remove Directory [%s], Error Code [%d], location [%d]\n", dir, GetLastError(), location); + } + } +} + +void removeFileHelper(LPSTR pfile, int location) +{ + FILE *fp; + fp = fopen( pfile, "r"); + + if (fp != NULL) + { + if(fclose(fp)) + { + Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); + } + + if(!DeleteFileA(pfile)) + { + Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); + } + } + +} + +void removeAll(void) +{ + DWORD dwAtt; + /* get rid of destination dirs and files */ + removeFileHelper(lpSource[0], 11); + removeFileHelper(lpSource[1], 12); + removeFileHelper(lpFiles[0], 13); + removeFileHelper(lpFiles[1], 14); + + removeDirectoryHelper(lpSource[2], 101); + removeFileHelper(lpFiles[4], 15); + removeFileHelper(lpFiles[5], 16); + removeDirectoryHelper(lpSource[3], 102); + + /* get rid of destination dirs and files */ + dwAtt = GetFileAttributesA(lpDestination[0]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + removeFileHelper(lpFiles[6], 18); + removeFileHelper(lpFiles[7], 19); + removeDirectoryHelper(lpDestination[0], 103); + } + else + { + removeFileHelper(lpDestination[0], 17); + } + + dwAtt = GetFileAttributesA(lpDestination[1]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + removeFileHelper(lpFiles[8], 21); + removeFileHelper(lpFiles[9], 22); + removeDirectoryHelper(lpDestination[1], 104); + } + else + { + removeFileHelper(lpDestination[1], 19); + } + + dwAtt = GetFileAttributesA(lpDestination[2]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + removeFileHelper(lpFiles[10], 24); + removeFileHelper(lpFiles[11], 25); + removeDirectoryHelper(lpDestination[2], 105); + } + else + { + removeFileHelper(lpDestination[2], 23); + } + + dwAtt = GetFileAttributesA(lpDestination[3]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + removeFileHelper(lpFiles[12], 26); + removeFileHelper(lpFiles[13], 27); + removeDirectoryHelper(lpDestination[3], 106); + } + else + { + removeFileHelper(lpDestination[3], 107); + } + +} + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bRc = TRUE; + char results[40]; + FILE* resultsFile = NULL; + int i, j, k, nCounter = 0; + int res = FAIL; + char tempSource[] = {'t','e','m','p','k','.','t','m','p','\0'}; + char tempDest[] = {'t','e','m','p','2','.','t','m','p','\0'}; + HANDLE hFile; + DWORD result; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* read in the expected results to compare with actual results */ + memset (results, 0, 34); + resultsFile = fopen("expectedresults.txt", "r"); + if (resultsFile == NULL) + { + Trace("MoveFileExA ERROR: Unable to open \"expectedresults.txt\"\n"); + goto EXIT; + } + + fgets(results, 34, resultsFile); + fclose(resultsFile); + + nCounter = 0; + + + /* clean the slate */ + removeAll(); + if (createExisting() != PASS) + { + goto EXIT; + } + + /* lpSource loop */ + for (i = 0; i < 4; i++) + { + /* lpDestination loop */ + for (j = 0; j < 4; j++) + { + /* dwFlag loop */ + for (k = 0; k < 2; k++) + { + + /* move the file to the new location */ + bRc = MoveFileExA(lpSource[i], lpDestination[j], dwFlag[k]); + + if (!( + ((bRc == TRUE) && (results[nCounter] == '1')) + || + ((bRc == FALSE ) && (results[nCounter] == '0')) ) + ) + { + Trace("MoveFileExA(%s, %s, %s): Values of i[%d], j[%d], k [%d] and results[%d]=%c LastError[%d]Flag[%d]FAILED\n", + lpSource[i], lpDestination[j], + k == 1 ? + "MOVEFILE_REPLACE_EXISTING":"MOVEFILE_COPY_ALLOWED", i, j, k, nCounter, results[nCounter], GetLastError(), bRc); + goto EXIT; + } + + /* undo the last move */ + removeAll(); + if (createExisting() != PASS) + { + goto EXIT; + } + nCounter++; + } + } + } + + /* create the temp source file */ + hFile = CreateFileA(tempSource, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + + if( hFile == INVALID_HANDLE_VALUE ) + { + Trace("MoveFileExA: CreateFile failed to " + "create the file correctly.\n"); + goto EXIT; + } + + bRc = CloseHandle(hFile); + if(!bRc) + { + Trace("MoveFileExA: CloseHandle failed to close the " + "handle correctly. yo %u\n",GetLastError()); + goto EXIT; + } + + /* set the file attributes to be readonly */ + bRc = SetFileAttributesA(tempSource, FILE_ATTRIBUTE_READONLY); + if(!bRc) + { + Trace("MoveFileExA: SetFileAttributes failed to set file " + "attributes correctly. ERROR:%u\n",GetLastError()); + goto EXIT; + } + + /* move the file to the new location */ + bRc = MoveFileExA(tempSource, tempDest, MOVEFILE_COPY_ALLOWED ); + if(!bRc) + { + Trace("MoveFileExA(%S, %S, %s): GetFileAttributes " + "failed to get the file's attributes.\n", + tempSource, tempDest, "MOVEFILE_COPY_ALLOWED"); + goto EXIT; + } + + /* check that the newly moved file has the same file attributes + as the original */ + result = GetFileAttributesA(tempDest); + if(result == 0) + { + Trace("MoveFileExA: GetFileAttributes failed to get " + "the file's attributes.\n"); + goto EXIT; + } + + if((result & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY) + { + Trace("MoveFileExA: GetFileAttributes failed to get " + "the correct file attributes.\n"); + goto EXIT; + } + + /* set the file attributes back to normal, to be deleted */ + bRc = SetFileAttributesA(tempDest, FILE_ATTRIBUTE_NORMAL); + if(!bRc) + { + Trace("MoveFileExA: SetFileAttributes " + "failed to set file attributes correctly.\n"); + goto EXIT; + } + + /* delete the newly moved file */ + bRc = DeleteFileA(tempDest); + if(!bRc) + { + Trace("MoveFileExA: DeleteFileA failed to delete the" + "file correctly.\n"); + goto EXIT; + } + + res = PASS; + +EXIT: + removeAll(); + + PAL_TerminateEx(res); + return res; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/testinfo.dat new file mode 100644 index 0000000..d8d19af --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExA/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = MoveFileExA +Name = Test for MoveFileExA (test 1) +Type = DEFAULT +EXE1 = movefileexa +Description += Creates a number of files/directories and attempts to move them. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/CMakeLists.txt new file mode 100644 index 0000000..4e984e8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + MoveFileExW.cpp +) + +add_executable(paltest_movefileexw_test1 + ${SOURCES} +) + +add_dependencies(paltest_movefileexw_test1 coreclrpal) + +target_link_libraries(paltest_movefileexw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/ExpectedResults.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/ExpectedResults.txt new file mode 100644 index 0000000..684b8a5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/ExpectedResults.txt @@ -0,0 +1 @@ +01110011000000000111001100000000 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/MoveFileExW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/MoveFileExW.cpp new file mode 100644 index 0000000..4f5b72d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/MoveFileExW.cpp @@ -0,0 +1,431 @@ +// 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. + +/*===================================================================== +** +** Source: MoveFileExW.c +** +** Purpose: Tests the PAL implementation of the MoveFileExW function. +** +** +**===================================================================*/ + +#include + + +LPWSTR lpSource[4]; +LPWSTR lpDestination[4]; +LPWSTR lpFiles[14]; + +DWORD dwFlag[2] = {MOVEFILE_COPY_ALLOWED, MOVEFILE_REPLACE_EXISTING}; + + + +int createExisting(void) +{ + HANDLE tempFile = NULL; + HANDLE tempFile2 = NULL; + + /* create the src_existing file and dst_existing file */ + tempFile = CreateFileW(lpSource[0], GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + tempFile2 = CreateFileW(lpDestination[0], GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + CloseHandle(tempFile2); + CloseHandle(tempFile); + + if ((tempFile == NULL) || (tempFile2 == NULL)) + { + Trace("ERROR: couldn't create %S or %S\n", lpSource[0], + lpDestination[0]); + return FAIL; + } + + /* create the src_dir_existing and dst_dir_existing directory and files */ + CreateDirectoryW(lpSource[2], NULL); + + tempFile = CreateFileW(lpFiles[0], GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + tempFile2 = CreateFileW(lpFiles[1], GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + CloseHandle(tempFile2); + CloseHandle(tempFile); + + if ((tempFile == NULL) || (tempFile2 == NULL)) + { + Trace("ERROR: couldn't create src_dir_existing\\test01.tmp\n"); + return FAIL; + } + + CreateDirectoryW(lpDestination[2], NULL); + tempFile = CreateFileW(lpFiles[2], GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + tempFile2 = CreateFileW(lpFiles[3], GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + CloseHandle(tempFile2); + CloseHandle(tempFile); + + if ((tempFile == NULL) || (tempFile2 == NULL)) + { + Trace("ERROR: couldn't create dst_dir_existing\\test01.tmp\n"); + return FAIL; + } + return PASS; +} + +void removeDirectoryHelper(LPWSTR dir, int location) +{ + DWORD dwAtt = GetFileAttributesW(dir); +// Trace(" Value of location[%d], and directorye [%S]\n", location, dir); + + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + if(!RemoveDirectoryW(dir)) + { + Fail("ERROR: Failed to remove Directory [%S], Error Code [%d], location [%d]\n", dir, GetLastError(), location); + } + } +} + +void removeFileHelper(LPWSTR wfile, int location) +{ + FILE *fp; + char * pfile = convertC(wfile); + +// Trace(" Value of location[%d], and file [%s]\n", location, pfile); + fp = fopen( pfile, "r"); + + if (fp != NULL) + { + if(fclose(fp)) + { + Fail("ERROR: Failed to close the file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location); + } + + if(!DeleteFileW(wfile)) + { + Fail("ERROR: Failed to delete file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location); + } + else + { + // Trace("Success: deleted file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location); + } + } + + free(pfile); +} + +void removeAll(void) +{ + DWORD dwAtt; + /* get rid of destination dirs and files */ + removeFileHelper(lpSource[0], 11); +// lpSource[0] = convert("src_existing.tmp"); + + removeFileHelper(lpSource[1], 12); + //lpSource[1] = convert("src_non-existant.tmp"); + + removeFileHelper(lpFiles[0], 13); +// lpFiles[0] = convert("src_dir_existing\\test01.tmp"); + + removeFileHelper(lpFiles[1], 14); +// lpFiles[1] = convert("src_dir_existing\\test02.tmp"); + + removeDirectoryHelper(lpSource[2], 101); +// lpSource[2] = convert("src_dir_existing"); + + removeFileHelper(lpFiles[4], 15); +// lpFiles[4] = convert("src_dir_non-existant\\test01.tmp"); + + removeFileHelper(lpFiles[5], 16); +// lpFiles[5] = convert("src_dir_non-existant\\test02.tmp"); + + removeDirectoryHelper(lpSource[3], 102); +// lpSource[3] = convert("src_dir_non-existant"); + + /* get rid of destination dirs and files */ + dwAtt = GetFileAttributesW(lpDestination[0]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + removeFileHelper(lpFiles[6], 18); + // lpFiles[6] = convert("dst_existing.tmp\\test01.tmp"); + removeFileHelper(lpFiles[7], 19); + // lpFiles[7] = convert("dst_existing.tmp\\test02.tmp"); + removeDirectoryHelper(lpDestination[0], 103); + // lpDestination[0] = convert("dst_existing.tmp"); + + } + else + { + removeFileHelper(lpDestination[0], 17); + // lpDestination[0] = convert("dst_existing.tmp"); + } + + dwAtt = GetFileAttributesW(lpDestination[1]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + removeFileHelper(lpFiles[8], 21); + // lpFiles[8] = convert("dst_non-existant.tmp\\test01.tmp"); + removeFileHelper(lpFiles[9], 22); + // lpFiles[9] = convert("dst_non-existant.tmp\\test02.tmp"); + removeDirectoryHelper(lpDestination[1], 104); + // lpDestination[1] = convert("dst_non-existant.tmp"); + + } + else + { + removeFileHelper(lpDestination[1], 19); + //lpDestination[1] = convert("dst_non-existant.tmp"); + } + + dwAtt = GetFileAttributesW(lpDestination[2]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + removeFileHelper(lpFiles[10], 24); + // lpFiles[10] = convert("dst_dir_existing\\test01.tmp"); + removeFileHelper(lpFiles[11], 25); + // lpFiles[11] = convert("dst_dir_existing\\test02.tmp"); + removeDirectoryHelper(lpDestination[2], 105); + // lpDestination[2] = convert("dst_dir_existing"); + + } + else + { + removeFileHelper(lpDestination[2], 23); + // lpDestination[2] = convert("dst_dir_existing"); + + } + + dwAtt = GetFileAttributesW(lpDestination[3]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + removeFileHelper(lpFiles[12], 26); + // lpFiles[12] = convert("dst_dir_non-existant\\test01.tmp"); + removeFileHelper(lpFiles[13], 27); + // lpFiles[13] = convert("dst_dir_non-existant\\test02.tmp"); + removeDirectoryHelper(lpDestination[3], 106); + // lpDestination[3] = convert("dst_dir_non-existant"); + + } + else + { + removeFileHelper(lpDestination[3], 107); + // lpDestination[3] = convert("dst_dir_non-existant"); + + } + +} + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bRc = TRUE; + char results[40]; + FILE* resultsFile = NULL; + int i, j, k, nCounter = 0; + int res = FAIL; + WCHAR tempSource[] = {'t','e','m','p','k','.','t','m','p','\0'}; + WCHAR tempDest[] = {'t','e','m','p','2','.','t','m','p','\0'}; + HANDLE hFile; + DWORD result; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + lpSource[0] = convert("src_existing.tmp"); + lpSource[1] = convert("src_non-existant.tmp"); + lpSource[2] = convert("src_dir_existing"); + lpSource[3] = convert("src_dir_non-existant"); + + lpDestination[0] = convert("dst_existing.tmp"); + lpDestination[1] = convert("dst_non-existant.tmp"); + lpDestination[2] = convert("dst_dir_existing"); + lpDestination[3] = convert("dst_dir_non-existant"); + + lpFiles[0] = convert("src_dir_existing\\test01.tmp"); + lpFiles[1] = convert("src_dir_existing\\test02.tmp"); + lpFiles[2] = convert("dst_dir_existing\\test01.tmp"); + lpFiles[3] = convert("dst_dir_existing\\test02.tmp"); + lpFiles[4] = convert("src_dir_non-existant\\test01.tmp"); + lpFiles[5] = convert("src_dir_non-existant\\test02.tmp"); + + lpFiles[6] = convert("dst_existing.tmp\\test01.tmp"); + lpFiles[7] = convert("dst_existing.tmp\\test02.tmp"); + + lpFiles[8] = convert("dst_non-existant.tmp\\test01.tmp"); + lpFiles[9] = convert("dst_non-existant.tmp\\test02.tmp"); + + lpFiles[10] = convert("dst_dir_existing\\test01.tmp"); + lpFiles[11] = convert("dst_dir_existing\\test02.tmp"); + + lpFiles[12] = convert("dst_dir_non-existant\\test01.tmp"); + lpFiles[13] = convert("dst_dir_non-existant\\test02.tmp"); + + /* read in the expected results to compare with actual results */ + memset (results, 0, 34); + resultsFile = fopen("expectedresults.txt", "r"); + if (resultsFile == NULL) + { + Trace("MoveFileExW ERROR: Unable to open \"expectedresults.txt\"\n"); + goto EXIT; + } + + fgets(results, 34, resultsFile); + fclose(resultsFile); + +// Trace("Value of results[%]=%s\n", i, results); + for( i = 0; i < 32; i++) + { + Trace("Value of results[%d]=%c\n", i, results[i]); + } + nCounter = 0; + + + /* clean the slate */ + removeAll(); + if (createExisting() != PASS) + { + goto EXIT; + } + + /* lpSource loop */ + for (i = 0; i < 4; i++) + { + /* lpDestination loop */ + for (j = 0; j < 4; j++) + { + /* dwFlag loop */ + for (k = 0; k < 2; k++) + { + + //if(nCounter == 22) + //{ + //exit(1); + //} + /* move the file to the new location */ + bRc = MoveFileExW(lpSource[i], lpDestination[j], dwFlag[k]); + + if (!( + ((bRc == TRUE) && (results[nCounter] == '1')) + || + ((bRc == FALSE ) && (results[nCounter] == '0')) ) + ) + { + Trace("MoveFileExW(%S, %S, %s): Values of i[%d], j[%d], k [%d] and results[%d]=%c LastError[%d]Flag[%d]FAILED\n", + lpSource[i], lpDestination[j], + k == 1 ? + "MOVEFILE_REPLACE_EXISTING":"MOVEFILE_COPY_ALLOWED", i, j, k, nCounter, results[nCounter], GetLastError(), bRc); + goto EXIT; + } + + //Trace("MoveFileExW(%S, %S, %s): Values of i[%d], j[%d], k [%d] and results[%d]=%c \n", + // lpSource[i], lpDestination[j], + // k == 1 ? + // "MOVEFILE_REPLACE_EXISTING":"MOVEFILE_COPY_ALLOWED", i, j, k, nCounter, results[nCounter]); + + + /* undo the last move */ + removeAll(); + if (createExisting() != PASS) + { + goto EXIT; + } + //Trace("Counter [%d] over \n", nCounter); + nCounter++; + } + } + } + + /* create the temp source file */ + hFile = CreateFileW(tempSource, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + + if( hFile == INVALID_HANDLE_VALUE ) + { + Trace("MoveFileExW: CreateFile failed to " + "create the file correctly.\n"); + goto EXIT; + } + + bRc = CloseHandle(hFile); + if(!bRc) + { + Trace("MoveFileExW: CloseHandle failed to close the " + "handle correctly. yo %u\n",GetLastError()); + goto EXIT; + } + + /* set the file attributes to be readonly */ + bRc = SetFileAttributesW(tempSource, FILE_ATTRIBUTE_READONLY); + if(!bRc) + { + Trace("MoveFileExW: SetFileAttributes failed to set file " + "attributes correctly. ERROR:%u\n",GetLastError()); + goto EXIT; + } + + /* move the file to the new location */ + bRc = MoveFileExW(tempSource, tempDest, MOVEFILE_COPY_ALLOWED ); + if(!bRc) + { + Trace("MoveFileExW(%S, %S, %s): GetFileAttributes " + "failed to get the file's attributes.\n", + tempSource, tempDest, "MOVEFILE_COPY_ALLOWED"); + goto EXIT; + } + + /* check that the newly moved file has the same file attributes + as the original */ + result = GetFileAttributesW(tempDest); + if(result == 0) + { + Trace("MoveFileExW: GetFileAttributes failed to get " + "the file's attributes.\n"); + goto EXIT; + } + + if((result & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY) + { + Trace("MoveFileExW: GetFileAttributes failed to get " + "the correct file attributes.\n"); + goto EXIT; + } + + /* set the file attributes back to normal, to be deleted */ + bRc = SetFileAttributesW(tempDest, FILE_ATTRIBUTE_NORMAL); + if(!bRc) + { + Trace("MoveFileExW: SetFileAttributes " + "failed to set file attributes correctly.\n"); + goto EXIT; + } + + /* delete the newly moved file */ + bRc = DeleteFileW(tempDest); + if(!bRc) + { + Trace("MoveFileExW: DeleteFileW failed to delete the" + "file correctly.\n"); + goto EXIT; + } + + res = PASS; + +EXIT: + removeAll(); + for (i=0; i<4; i++) + { + free(lpSource[i]); + free(lpDestination[i]); + } + for (i=0; i<14; i++) + { + free(lpFiles[i]); + } + + PAL_TerminateEx(res); + return res; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/testinfo.dat new file mode 100644 index 0000000..9b001b5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/MoveFileExW/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = MoveFileExW +Name = Test for MoveFileExW (test 1) +Type = DEFAULT +EXE1 = movefileexw +Description += Creates a number of files/directories and attempts to move them. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/CMakeLists.txt new file mode 100644 index 0000000..070e421 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/CMakeLists.txt new file mode 100644 index 0000000..51a66de --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + ReadFile.cpp +) + +add_executable(paltest_readfile_test1 + ${SOURCES} +) + +add_dependencies(paltest_readfile_test1 coreclrpal) + +target_link_libraries(paltest_readfile_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/NonReadableFile.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/NonReadableFile.txt new file mode 100644 index 0000000..a8a9406 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/NonReadableFile.txt @@ -0,0 +1 @@ +this is a test \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/ReadFile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/ReadFile.cpp new file mode 100644 index 0000000..a59e292 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/ReadFile.cpp @@ -0,0 +1,82 @@ +// 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. + +/*===================================================================== +** +** Source: ReadFile.c (test 1) +** +** Purpose: Tests the PAL implementation of the ReadFile function. +** This test will attempt to read from a NULL handle and from +** a file without read permissions set. +** +** +**===================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwByteCount = 0; + DWORD dwBytesRead = 0; + BOOL bRc = FALSE; + char szBuffer[256]; + char* szNonReadableFile = {"nonreadablefile.txt"}; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + memset(szBuffer, 0, 256); + + /* Read from a NULL handle + */ + + bRc = ReadFile(hFile, szBuffer, 20, &dwBytesRead, NULL); + + if (bRc == TRUE) + { + Fail("ReadFile: ERROR -> Able to read from a NULL handle\n"); + } + + + /* Read from a file without read permissions + */ + +#if WIN32 + +#else + /* attempt to read from the unreadable file + * open a file without read permissions + */ + hFile = CreateFile(szNonReadableFile, + GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + dwByteCount = GetLastError(); + Fail("ReadFile: ERROR -> Unable to create file \"%s\".\n", + szNonReadableFile); + } + + bRc = ReadFile(hFile, szBuffer, 20, &dwBytesRead, NULL); + + if (bRc == TRUE) + { + Fail("ReadFile: ERROR -> Able to read from a file without read " + "permissions\n"); + } +#endif + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/testinfo.dat new file mode 100644 index 0000000..b0df11a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = ReadFile +Name = Positive Test for ReadFile +Type = DEFAULT +EXE1 = readfile +Description +=Attempt to read from a NULL handle and a file without read permissions + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test2/CMakeLists.txt new file mode 100644 index 0000000..adf226e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + ReadFile.cpp +) + +add_executable(paltest_readfile_test2 + ${SOURCES} +) + +add_dependencies(paltest_readfile_test2 coreclrpal) + +target_link_libraries(paltest_readfile_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.cpp new file mode 100644 index 0000000..7120d1f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.cpp @@ -0,0 +1,194 @@ +// 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. + +/*===================================================================== +** +** Source: ReadFile.c (test 2) +** +** Purpose: Tests the PAL implementation of the ReadFile function. +** Creates a test file and performs an array of read tests. +** +** Assumes successful: +** CreateFile +** CloseHandle +** WriteFile +** GetLastError +** +** +**===================================================================*/ + + +#include + + +const char* szStringTest = "The quick fox jumped over the lazy dog's back.\0"; +const char* szEmptyString = ""; +const char* szReadableFile = "Readable.txt"; +const char* szResultsFile = "Results.txt"; + +//Previously number of tests was 6, now 4 refer VSW 312690 +#define NOOFTESTS 4 + +const int PAGESIZE = 4096; + +char *readBuffer; + +BOOL validateResults(const char* szString, // string read + DWORD dwByteCount, // amount requested + DWORD dwBytesRead) // amount read +{ + // were the correct number of bytes read? + if (dwBytesRead > dwByteCount) + { + Trace("bytes read > bytes asked for\n"); + return FALSE; + } + if (dwBytesRead != strlen(szString)) + { + Trace("bytes read != length of read string\n"); + return FALSE; + } + + // + // compare results + // + + if (memcmp(szString, szStringTest, dwBytesRead) != 0) + { + Trace("read = %s string = %s", szString, szStringTest); + return FALSE; + } + + return TRUE; +} + +BOOL readTest(DWORD dwByteCount, char cResult) +{ + HANDLE hFile = NULL; + DWORD dwBytesRead; + BOOL bRc = FALSE; + + // open the test file + hFile = CreateFile(szReadableFile, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if(hFile == INVALID_HANDLE_VALUE) + { + Trace("ReadFile: ERROR -> Unable to open file \"%s\".\n", + szReadableFile); + return FALSE; + } + + memset(readBuffer, 0, PAGESIZE); + + bRc = ReadFile(hFile, readBuffer, dwByteCount, &dwBytesRead, NULL); + + if (bRc == FALSE) + { + // if it failed, was it supposed to fail? + if (cResult == '1') + { + Trace("\nbRc = %d\n", bRc); + Trace("readBuffer = [%s] dwByteCount = %d dwBytesRead = %d\n", readBuffer, dwByteCount, dwBytesRead); + Trace("cresult = 1\n"); + Trace("getlasterror = %d\n", GetLastError()); + CloseHandle(hFile); + return FALSE; + } + } + else + { + CloseHandle(hFile); + // if it passed, was it supposed to pass? + if (cResult == '0') + { + Trace("cresult = 0\n"); + return FALSE; + } + else + { + return (validateResults(readBuffer, dwByteCount, dwBytesRead)); + } + } + + CloseHandle(hFile); + return TRUE; +} + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + const int BUFFER_SIZE = 2 * PAGESIZE; + + DWORD dwByteCount[] = { 0, + 10, + strlen(szStringTest), + PAGESIZE + // Commented out two negative test cases : Refer VSW 312690 + // 2 * PAGESIZE, + // -1 + }; + + DWORD oldProt; + char szResults[] = "1111"; // Was "111100": Refer VSW 312690 + int i; + BOOL bRc = FALSE; + DWORD dwBytesWritten = 0; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* allocate read-write memery for readBuffer */ + if (!(readBuffer = (char*) VirtualAlloc(NULL, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE))) + { + Fail("VirtualAlloc failed: GetLastError returns %d\n", GetLastError()); + return FAIL; + } + + /* write protect the second page of readBuffer */ + if (!VirtualProtect(&readBuffer[PAGESIZE], PAGESIZE, PAGE_NOACCESS, &oldProt)) + { + Fail("VirtualProtect failed: GetLastError returns %d\n", GetLastError()); + return FAIL; + } + + // create the test file + hFile = CreateFile(szReadableFile, + GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("ReadFile: ERROR -> Unable to create file \"%s\" (%d).\n", + szReadableFile, GetLastError()); + } + + bRc = WriteFile(hFile, szStringTest, strlen(szStringTest), &dwBytesWritten, NULL); + CloseHandle(hFile); + + + for (i = 0; i< NOOFTESTS; i++) + { + bRc = readTest(dwByteCount[i], szResults[i]); + if (bRc != TRUE) + { + Fail("ReadFile: ERROR -> Failed on test[%d]\n", i); + } + } + + VirtualFree(readBuffer, BUFFER_SIZE, MEM_RELEASE); + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test2/testinfo.dat new file mode 100644 index 0000000..82b6326 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = ReadFile +Name = Positive Test for ReadFile +Type = DEFAULT +EXE1 = readfile +Description +=Multiple tests of reads of varying sizes with verification + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test3/CMakeLists.txt new file mode 100644 index 0000000..2ce27e0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + ReadFile.cpp +) + +add_executable(paltest_readfile_test3 + ${SOURCES} +) + +add_dependencies(paltest_readfile_test3 coreclrpal) + +target_link_libraries(paltest_readfile_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test3/ReadFile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test3/ReadFile.cpp new file mode 100644 index 0000000..c5d6b1d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test3/ReadFile.cpp @@ -0,0 +1,184 @@ +// 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. + +/*===================================================================== +** +** Source: ReadFile.c (test 3) +** +** Purpose: Tests the PAL implementation of the ReadFile function. +** Creates a test file and performs an array of sequential read +** tests. +** +** Assumes successful: +** CreateFile +** CloseHandle +** memset +** WriteFile +** CreateFile +** CloseHandle +** GetLastError +** +** +**===================================================================*/ + +#include + +const char* szStringTest = "The quick fox jumped over the lazy dog's back.\0"; +const char* szEmptyString = ""; +const char* szReadableFile = "Readable.txt"; +const char* szResultsFile = "Results.txt"; + + +BOOL validateResults(const char* szString, // string read + DWORD dwByteCount, // amount requested + DWORD dwBytesRead) // amount read +{ + // were the correct number of bytes read? + if (dwBytesRead > dwByteCount) + { + Trace("bytes read > bytes asked for\n"); + return FALSE; + } + if (dwBytesRead != strlen(szString)) + { + Trace("bytes read != length of read string\n"); + return FALSE; + } + + + // + // compare results + // + + if (memcmp(szString, szStringTest, dwByteCount) != 0) + { + Trace("read = %s string = %s", szString, szStringTest); + return FALSE; + } + + return TRUE; +} + + + + +BOOL readTest(DWORD dwByteCount, char cResult) +{ + HANDLE hFile = NULL; + DWORD dwBytesRead = 0; + DWORD dwTotal = 0; + DWORD dwRequested = 0; + BOOL bRc = FALSE; + char szString[100]; + char* szPtr = szString; + int i = 0; + + // open the test file + hFile = CreateFile(szReadableFile, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if(hFile == INVALID_HANDLE_VALUE) + { + Trace("ReadFile: ERROR -> Unable to open file \"%s\".\n", + szReadableFile); + return FALSE; + } + + memset(szString, 0, 100); + + for (i = 0; i < 5; i++) + { + bRc = ReadFile(hFile, szPtr, dwByteCount, &dwBytesRead, NULL); + szPtr += dwByteCount; + dwTotal += dwBytesRead; + dwRequested += dwByteCount; + } + + if (bRc == FALSE) + { + // if it failed, was it supposed to fail? + if (cResult == '1') + { + Trace("\nbRc = %d\n", bRc); + Trace("szString = [%s] dwByteCount = %d dwBytesRead = %d\n", + szString, + dwByteCount, + dwBytesRead); + Trace ("cresult = 1\n"); + Trace ("getlasterror = %d\n", GetLastError()); + CloseHandle(hFile); + return FALSE; + } + } + else + { + CloseHandle(hFile); + // if it passed, was it supposed to pass? + if (cResult == '0') + { + Trace ("cresult = 0\n"); + return FALSE; + } + else + { + return (validateResults(szString, dwRequested, dwTotal)); + } + } + + CloseHandle(hFile); + return TRUE; +} + + + +int __cdecl main(int argc, char **argv) +{ + HANDLE hFile = NULL; + DWORD dwByteCount[4] = {0, 1, 2, 3}; + char szResults[4] = {'1', '1', '1', '1'}; + int i; + BOOL bRc = FALSE; + DWORD dwBytesWritten = 0; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + + // create the test file + hFile = CreateFile(szReadableFile, + GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("ReadFile: ERROR -> Unable to create file \"%s\".\n", + szReadableFile); + } + + bRc = WriteFile(hFile, szStringTest, strlen(szStringTest), + &dwBytesWritten, + NULL); + CloseHandle(hFile); + + for (i = 0; i < 4; i++) + { + bRc = readTest(dwByteCount[i], szResults[i]); + if (bRc != TRUE) + { + Fail("ReadFile: ERROR -> Failed on test[%d]\n", i); + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test3/testinfo.dat new file mode 100644 index 0000000..82b6326 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test3/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = ReadFile +Name = Positive Test for ReadFile +Type = DEFAULT +EXE1 = readfile +Description +=Multiple tests of reads of varying sizes with verification + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test4/CMakeLists.txt new file mode 100644 index 0000000..b284c5b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + readfile.cpp +) + +add_executable(paltest_readfile_test4 + ${SOURCES} +) + +add_dependencies(paltest_readfile_test4 coreclrpal) + +target_link_libraries(paltest_readfile_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test4/readfile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test4/readfile.cpp new file mode 100644 index 0000000..3ec939f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test4/readfile.cpp @@ -0,0 +1,147 @@ +// 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. + +/*===================================================================== +** +** Source: ReadFile.c (test 4) +** +** Purpose: Tests the PAL implementation of the ReadFile function. +** Creates a file and writes a small string to it, attempt +** to read many more characters that exist. The returned +** number of chars should be the amount written originally +** not the number requested. +** +** +**===================================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwBytesWritten; + BOOL bRc = FALSE; + char szBuffer[256]; + DWORD dwBytesRead = 0; + int szRequestSize = 256; + char testFile[] = "testfile.tmp"; + char testString[] = "people stop and stare"; + DWORD res = 0; + + /* Initialize the PAL. + */ + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* Initialize the buffer. + */ + memset(szBuffer, 0, 256); + + /* Create a file to test with. + */ + hFile = CreateFile(testFile, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_WRITE|FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR:%u: Unable to create file \"%s\".\n", + GetLastError(), + testFile); + } + + /* Write to the File handle. + */ + bRc = WriteFile(hFile, + testString, + strlen(testString), + &dwBytesWritten, + NULL); + + if (bRc == FALSE) + { + Trace("ERROR:%u: Unable to write to file handle " + "hFile=0x%lx\n", + GetLastError(), + hFile); + if (!CloseHandle(hFile)) + { + Trace("ERROR:%u%: Unable to close handle 0x%lx.\n", + GetLastError(), + hFile); + } + Fail(""); + } + + /* Set the file pointer to beginning of file. + */ + res = SetFilePointer(hFile, (LONG)NULL, NULL, FILE_BEGIN); + + if( (res == INVALID_SET_FILE_POINTER) && + (GetLastError() != NO_ERROR)) + { + Trace("ERROR:%u: Unable to set file pointer to the beginning of file.", + GetLastError()); + + if (!CloseHandle(hFile)) + { + Trace("ERROR:%u%: Unable to close handle 0x%lx.\n", + GetLastError(), + hFile); + } + Fail(""); + } + + + /* Attempt to read 256 characters from a file + * that does not contain that many. + */ + bRc = ReadFile(hFile, + szBuffer, + szRequestSize, + &dwBytesRead, + NULL); + + if (bRc == FALSE) + { + Trace("ERROR:%u: Unable to read from file handle 0x%lx.\n", + GetLastError(), + hFile); + if (!CloseHandle(hFile)) + { + Trace("ERROR:%u%: Unable to close handle 0x%lx.\n", + GetLastError(), + hFile); + } + Fail(""); + } + + /* Confirm the number of bytes read with that requested. + */ + if (dwBytesRead != strlen(testString)) + { + Trace("ERROR: The number of bytes read \"%d\" is not equal to the " + "number originally written \"%d\" to the file.\n", + dwBytesRead, + strlen(testString)); + if (!CloseHandle(hFile)) + { + Trace("ERROR:%u%: Unable to close handle 0x%lx.\n", + GetLastError(), + hFile); + } + Fail(""); + } + + /* Terminate the PAL. + */ + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test4/testinfo.dat new file mode 100644 index 0000000..6f3267d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/ReadFile/test4/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = ReadFile +Name = Positive Test for ReadFile +Type = DEFAULT +EXE1 = readfile +Description += Tests the PAL implementation of the ReadFile function. += Creates a file and writes a small string to it, attempt += to read many more characters that exist. The returned += number of chars should be the amount written originally += not the number requested. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/RemoveDirectoryA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/RemoveDirectoryA/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/RemoveDirectoryA/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/RemoveDirectoryW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/RemoveDirectoryW/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/RemoveDirectoryW/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathA/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathA/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/test1/CMakeLists.txt new file mode 100644 index 0000000..86201dd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + SearchPathW.cpp +) + +add_executable(paltest_searchpathw_test1 + ${SOURCES} +) + +add_dependencies(paltest_searchpathw_test1 coreclrpal) + +target_link_libraries(paltest_searchpathw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.cpp new file mode 100644 index 0000000..6880a86 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.cpp @@ -0,0 +1,193 @@ +// 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. + +/*===================================================================== +** +** Source: SearchPathW.c +** +** Purpose: Tests the PAL implementation of the SearchFileW function. +** +** +** TODO: Write a test where complete path is passed (say c:\?) +**===================================================================*/ +//SearchPath +// +//The SearchPath function searches for the specified file in the specified path. +// +// +//DWORD SearchPath( +// LPCTSTR lpPath, +// LPCTSTR lpFileName, +// LPCTSTR lpExtension, +// DWORD nBufferLength, +// LPTSTR lpBuffer, +// LPTSTR* lpFilePart +//); +// +//Parameters +//lpPath +//[in] Pointer to a null-terminated string that specifies the path to be searched for the file. If this parameter is NULL, the function searches for a matching file in the following directories in the following sequence: +//The directory from which the application loaded. +//The current directory. +//The system directory. Use the GetSystemDirectory function to get the path of this directory. +//The 16-bit system directory. There is no function that retrieves the path of this directory, but it is searched. +//The Windows directory. Use the GetWindowsDirectory function to get the path of this directory. +//The directories that are listed in the PATH environment variable. + +//lpFileName +//[in] Pointer to a null-terminated string that specifies the name of the file to search for. + +//lpExtension +//[in] Pointer to a null-terminated string that specifies an extension to be added to the file name when searching for the file. The first character of the file name extension must be a period (.). The extension is added only if the specified file name does not end with an extension. +//If a file name extension is not required or if the file name contains an extension, this parameter can be NULL. +// +//nBufferLength +//[in] Size of the buffer that receives the valid path and file name, in TCHARs. + +//lpBuffer +//[out] Pointer to the buffer that receives the path and file name of the file found. + +//lpFilePart +//[out] Pointer to the variable that receives the address (within lpBuffer) of the last component of the valid path and file name, which is the address of the character immediately following the final backslash (\) in the path. + +//Return Values +//If the function succeeds, the value returned is the length, in TCHARs, of the string copied to the buffer, not including the terminating null character. If the return value is greater than nBufferLength, the value returned is the size of the buffer required to hold the path. +// +//If the function fails, the return value is zero. To get extended error information, call GetLastError. + + +#include +const char* szDir = "."; + +const char* szNoFileName = "333asdf"; +const char* szNoFileNameExt = ".x77t"; + +const char* szFileNameExists = "searchpathw"; +const char* szFileNameExtExists = ".c"; + +const char* szFileNameExistsWithExt = "searchpathw.c"; + +char fileloc[_MAX_PATH]; + +void removeFileHelper(LPSTR pfile, int location) +{ + FILE *fp; + fp = fopen( pfile, "r"); + + if (fp != NULL) + { + if(fclose(fp)) + { + Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); + } + + if(!DeleteFileA(pfile)) + { + Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); + } + else + { + // Trace("Success: deleted file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location); + } + } + +} + +void RemoveAll() +{ + removeFileHelper(fileloc, 1); +} + +int __cdecl main(int argc, char *argv[]) { + + WCHAR* lpPath = NULL; + WCHAR* lpFileName = NULL; + WCHAR* lpExtension = NULL; + DWORD nBufferLength = 0; + WCHAR lpBuffer[_MAX_PATH]; + WCHAR** lpFilePart = NULL; + DWORD error = 0; + DWORD result = 0; + + HANDLE hsearchfile; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + char fullPath[_MAX_DIR]; + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Initalize the buffer. + */ + memset(fullPath, 0, _MAX_DIR); + + if (GetTempPathA(_MAX_DIR, fullPath) == 0) + { + Fail("ERROR: GetTempPathA failed to get a path\n"); + } + + memset(fileloc, 0, _MAX_PATH); + sprintf_s(fileloc, _countof(fileloc), "%s%s", fullPath, szFileNameExistsWithExt); + + RemoveAll(); + + hsearchfile = CreateFileA(fileloc, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + + if (hsearchfile == NULL) + { + Trace("ERROR[%ul]: couldn't create %s\n", GetLastError(), fileloc); + return FAIL; + } + + CloseHandle(hsearchfile); + + // + // find a file that doesn't exist + // + ZeroMemory( lpBuffer, sizeof(lpBuffer)); + lpPath = convert((LPSTR)fullPath); + lpFileName = convert((LPSTR)szNoFileName); + lpExtension = NULL; + + if( SearchPathW( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart) != 0 ){ + error = GetLastError(); + free(lpPath); + free(lpFileName); + Fail ("SearchPathW: ERROR1 -> Found invalid file[%s][%s][%s][%d]\n", lpPath, szNoFileName, szNoFileNameExt, error); + } + + free(lpPath); + free(lpFileName); + + // + // find a file that exists, when path is mentioned explicitly + // + ZeroMemory( lpBuffer, sizeof(lpBuffer)); + lpPath = convert((LPSTR)fullPath); + lpFileName = convert((LPSTR)szFileNameExistsWithExt); + lpExtension = NULL; + + result = SearchPathW( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart); + + if( result == 0 ){ + error = GetLastError(); + free(lpPath); + free(lpFileName); + Fail ("SearchPathA: ERROR2 -> Did not Find valid file[%s][%s][%d]\n", lpPath, szFileNameExistsWithExt, error); + } + + free(lpPath); + free(lpFileName); + + RemoveAll(); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/test1/testinfo.dat new file mode 100644 index 0000000..f7a36eb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SearchPathW/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = file_io +Function = SearchPathW +Name = Test #1 for SearchPathW +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests the PAL implementation of the SearchFileW function diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/CMakeLists.txt new file mode 100644 index 0000000..dcf480b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/CMakeLists.txt @@ -0,0 +1,6 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/CMakeLists.txt new file mode 100644 index 0000000..6753717 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + SetEndOfFile.cpp +) + +add_executable(paltest_setendoffile_test1 + ${SOURCES} +) + +add_dependencies(paltest_setendoffile_test1 coreclrpal) + +target_link_libraries(paltest_setendoffile_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/SetEndOfFile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/SetEndOfFile.cpp new file mode 100644 index 0000000..9078ddc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/SetEndOfFile.cpp @@ -0,0 +1,85 @@ +// 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. + +/*===================================================================== +** +** Source: SetEndOfFile.c (test 1) +** +** Purpose: Tests the PAL implementation of the SetEndOfFile function. +** This test will attempt to operate on a NULL file handle and +** also test truncating a file not opened with GENERIC_WRITE +** +** Assumes successful: +** SetEndOfFile +** CreateFile +** CloseHandle +** + +** +**===================================================================*/ + +#include + +const char* szTextFile = "text.txt"; + + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + BOOL bRc = FALSE; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + bRc = SetEndOfFile(NULL); + if (bRc == TRUE) + { + Fail("SetEndOfFile: ERROR -> Operation succeeded on a NULL file " + "handle\n"); + } + + /* create a test file */ + hFile = CreateFile(szTextFile, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("SetEndOfFile: ERROR -> Unable to create file \"%s\".\n", + szTextFile); + } + + bRc = SetEndOfFile(hFile); + if (bRc == TRUE) + { + Trace("SetEndOfFile: ERROR -> Operation succeeded on read-only" + " file.\n"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Fail("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/testinfo.dat new file mode 100644 index 0000000..72fc5e5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = SetEndOfFile +Name = Positive Test for SetEndOfFile +Type = DEFAULT +EXE1 = setendoffile +Description +=Truncate a file + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/CMakeLists.txt new file mode 100644 index 0000000..324e24e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + SetEndOfFile.cpp +) + +add_executable(paltest_setendoffile_test2 + ${SOURCES} +) + +add_dependencies(paltest_setendoffile_test2 coreclrpal) + +target_link_libraries(paltest_setendoffile_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/SetEndOfFile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/SetEndOfFile.cpp new file mode 100644 index 0000000..6b3c050 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/SetEndOfFile.cpp @@ -0,0 +1,154 @@ +// 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. + +/*===================================================================== +** +** Source: SetEndOfFile.c (test 2) +** +** Purpose: Tests the PAL implementation of the SetEndOfFile function. +** This test will attempt to truncate a file +** +** +**===================================================================*/ + +#include + + +const char* szStringTest = "The quick fox jumped over the lazy dog's back."; +const char* szTextFile = "text.txt"; + + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwByteCount = 0; + DWORD dwBytesWritten; + BOOL bRc = FALSE; + char szBuffer[100]; + DWORD dwBytesRead = 0; + FILE *pFile = NULL; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + // create a test file + hFile = CreateFile(szTextFile, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("SetEndOfFile: ERROR -> Unable to create file \"%s\".\n", + szTextFile); + } + + bRc = WriteFile(hFile, szStringTest, 20, &dwBytesWritten, NULL); + if (bRc != TRUE) + { + Trace("SetEndOfFile: ERROR -> Uable to write to \"%s\".\n", + szTextFile); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Fail("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + + // open the test file + hFile = CreateFile(szTextFile, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("SetEndOfFile: ERROR -> Unable to open file \"%s\".\n", + szTextFile); + } + + // read a bit of the file to move the file pointer + dwByteCount = 10; + bRc = ReadFile(hFile, szBuffer, dwByteCount, &dwBytesRead, NULL); + if (bRc != TRUE) + { + Trace("SetEndOfFile: ERROR -> Uable to read from \"%s\".\n", + szTextFile); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + bRc = SetEndOfFile(hFile); + if (bRc != TRUE) + { + Trace("SetEndOfFile: ERROR -> Uable to set end of file.\n"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Fail("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + + // open and read the test file + pFile = fopen(szTextFile, "r"); + if (pFile == NULL) + { + Fail("SetEndOfFile: ERROR -> fopen was unable to open file \"%s\".\n", + szTextFile); + } + + // since we truncated the file at 10 characters, + // try reading 20 just to be safe + memset(szBuffer, 0, 100); + fgets(szBuffer, 20, pFile); + fclose(pFile); + if (strlen(szBuffer) != dwByteCount) + { + Fail("SetEndOfFile: ERROR -> file apparently not truncated at " + "correct position.\n"); + } + if (strncmp(szBuffer, szStringTest, dwByteCount) != 0) + { + Fail("SetEndOfFile: ERROR -> truncated file contents doesn't " + "compare with what should be there\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/testinfo.dat new file mode 100644 index 0000000..555f0d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = file_io +Function = SetEndOfFile +Name = Positive Test for SetEndOfFile +Type = DEFAULT +EXE1 = setendoffile +Description +=Truncate the test file using SetEndOfFile diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/CMakeLists.txt new file mode 100644 index 0000000..e9cb603 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + SetEndOfFile.cpp +) + +add_executable(paltest_setendoffile_test3 + ${SOURCES} +) + +add_dependencies(paltest_setendoffile_test3 coreclrpal) + +target_link_libraries(paltest_setendoffile_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/SetEndOfFile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/SetEndOfFile.cpp new file mode 100644 index 0000000..dfd9194 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/SetEndOfFile.cpp @@ -0,0 +1,109 @@ +// 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. + +/*===================================================================== +** +** Source: SetEndOfFile.c (test 3) +** +** Purpose: Tests the PAL implementation of the SetEndOfFile function. +** This test will attempt to expand a file. Assumes successful +** SetFilePointer and GetFileSize tests. +** +** +**===================================================================*/ + +#include + + +const char* szTextFile = "text.txt"; + + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwByteCount = 0; + DWORD dwOffset = 25; + DWORD dwRc = 0; + BOOL bRc = FALSE; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create a test file */ + hFile = CreateFile(szTextFile, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("SetEndOfFile: ERROR -> Unable to create file \"%s\".\n", + szTextFile); + } + + /* move the file pointer */ + /* assumes a successful SetFilePointer test */ + dwRc = SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN); + if (dwRc == INVALID_SET_FILE_POINTER) + { + Trace("SetEndOfFile: ERROR -> Call to SetFilePointer failed\n"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + PAL_Terminate(); + return FAIL; + } + + bRc = SetEndOfFile(hFile); + if (bRc != TRUE) + { + Trace("SetEndOfFile: ERROR -> Uable to set end of file.\n"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + + /* call GetFileSize to verify pointer position */ + /* assumes a successful GetFileSize test */ + + dwByteCount = GetFileSize(hFile, NULL); + if (dwByteCount != dwOffset) + { + Trace("SetEndOfFile: ERROR -> file apparently not expanded to the" + " correct size.\n"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Fail("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/testinfo.dat new file mode 100644 index 0000000..7f3868d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = SetEndOfFile +Name = Positive Test for SetEndOfFile +Type = DEFAULT +EXE1 = setendoffile +Description +=Set the end of file past the actual end +=of file thereby, extending it. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/CMakeLists.txt new file mode 100644 index 0000000..439d184 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + setendoffile.cpp +) + +add_executable(paltest_setendoffile_test4 + ${SOURCES} +) + +add_dependencies(paltest_setendoffile_test4 coreclrpal) + +target_link_libraries(paltest_setendoffile_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/setendoffile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/setendoffile.cpp new file mode 100644 index 0000000..98a6ec6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/setendoffile.cpp @@ -0,0 +1,138 @@ +// 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. + +/*===================================================================== +** +** Source: setendoffile.c (test 4) +** +** Purpose: Tests the PAL implementation of the SetEndOfFile function. +** Verify that the file pointer is the same before +** and after a SetEndOfFile using SetFilePointer with +** FILE_BEGIN, FILE_CURRENT and FILE_END +** +** +**===================================================================*/ + +#include + + +const char* szStringTest = "The quick fox jumped over the lazy dog's back."; +const char* szTextFile = "test.tmp"; + +static void Cleanup(HANDLE hFile) +{ + if (!CloseHandle(hFile)) + { + Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\". ", + "GetLastError returned %u.\n", + szTextFile, + GetLastError()); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetEndOfFile: ERROR -> Unable to delete file \"%s\". ", + "GetLastError returned %u.\n", + szTextFile, + GetLastError()); + } +} + +static void DoTest(HANDLE hFile, DWORD dwOffset, DWORD dwMethod) +{ + DWORD dwFP1 = 0; + DWORD dwFP2 = 0; + DWORD dwError; + + /* set the pointer*/ + dwFP1 = SetFilePointer(hFile, dwOffset, NULL, dwMethod); + if ((dwFP1 == INVALID_SET_FILE_POINTER) && + ((dwError = GetLastError()) != ERROR_SUCCESS)) + { + Trace("SetEndOfFile: ERROR -> Unable to set the pointer to the " + "end of the file. GetLastError returned %u.\n", + dwError); + Cleanup(hFile); + Fail(""); + } + + /* set EOF */ + if (!SetEndOfFile(hFile)) + { + Trace("SetEndOfFile: ERROR -> Unable to set end of file. " + "GetLastError returned %u.\n", + GetLastError()); + Cleanup(hFile); + Fail(""); + } + + /* get current file pointer pointer */ + dwFP2 = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); + if ((dwFP1 == INVALID_SET_FILE_POINTER) && + ((dwError = GetLastError()) != ERROR_SUCCESS)) + { + Trace("SetEndOfFile: ERROR -> Unable to set the pointer to the " + "end of the file. GetLastError returned %u.\n", + dwError); + Cleanup(hFile); + Fail(""); + } + + /* are they the same? */ + if (dwFP1 != dwFP2) + { + Trace("SetEndOfFile: ERROR -> File pointer before (%u) the " + "SetEndOfFile call was different than after (%u).\n", + dwFP1, + dwFP2); + Cleanup(hFile); + Fail(""); + } +} + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwBytesWritten; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create a test file */ + hFile = CreateFile(szTextFile, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("SetEndOfFile: ERROR -> Unable to create file \"%s\". " + "GetLastError returned %u.\n", + szTextFile, + GetLastError()); + } + + if (!WriteFile(hFile, szStringTest, strlen(szStringTest), &dwBytesWritten, NULL)) + { + Trace("SetEndOfFile: ERROR -> Unable to write to \"%s\". ", + "GetLastError returned %u.\n", + szTextFile, + GetLastError()); + Cleanup(hFile); + Fail(""); + } + + DoTest(hFile, -2, FILE_END); /* test the end */ + DoTest(hFile, -10, FILE_CURRENT); /* test the middle-ish */ + DoTest(hFile, 0, FILE_BEGIN); /* test the start */ + + Cleanup(hFile); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/testinfo.dat new file mode 100644 index 0000000..51d9185 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = SetEndOfFile +Name = Positive Test for SetEndOfFile (test 4) +Type = DEFAULT +EXE1 = setendoffile +Description += Tests the PAL implementation of the SetEndOfFile function. += Verify that the file pointer is the same before += and after a SetEndOfFile using SetFilePointer with += FILE_BEGIN, FILE_CURRENT and FILE_END diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/CMakeLists.txt new file mode 100644 index 0000000..d329a7f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_setendoffile_test5 + ${SOURCES} +) + +add_dependencies(paltest_setendoffile_test5 coreclrpal) + +target_link_libraries(paltest_setendoffile_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/test5.cpp new file mode 100644 index 0000000..7000d1a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/test5.cpp @@ -0,0 +1,183 @@ +// 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. + +/*===================================================================== +** +** Source: test5.c +** +** Purpose: Tests the PAL implementation of the SetEndOfFile function. +** Test attempts to read the number of characters up to +** the EOF pointer, which was specified. +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwBytesWritten; + DWORD retCode; + BOOL bRc = FALSE; + char szBuffer[256]; + DWORD dwBytesRead = 0; + char testFile[] = "testfile.tmp"; + char testString[] = "watch what happens"; + LONG shiftAmount = 10; + + /* Initialize the PAL. + */ + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* Initialize the buffer. + */ + memset(szBuffer, 0, 256); + + /* Create a file to test with. + */ + hFile = CreateFile(testFile, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_WRITE|FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR:%u: Unable to create file \"%s\".\n", + GetLastError(), + testFile); + } + + /* Write to the File handle. + */ + bRc = WriteFile(hFile, + testString, + strlen(testString), + &dwBytesWritten, + NULL); + + if (bRc == FALSE) + { + Trace("ERROR:%u: Unable to write to file handle " + "hFile=0x%lx\n", + GetLastError(), + hFile); + if (!CloseHandle(hFile)) + { + Fail("ERROR:%u%: Unable to close handle 0x%lx.\n", + GetLastError(), + hFile); + } + Fail(""); + } + + /* Set the file pointer to shiftAmount bytes from the front of the file + */ + retCode = SetFilePointer(hFile, shiftAmount, NULL, FILE_BEGIN); + if(retCode == INVALID_SET_FILE_POINTER) + { + Trace("ERROR:%u: Unable to set the file pointer to %d\n", + GetLastError(), + shiftAmount); + if (!CloseHandle(hFile)) + { + Fail("ERROR:%u%: Unable to close handle 0x%lx.\n", + GetLastError(), + hFile); + } + Fail(""); + } + + /* set the end of file pointer to 'shiftAmount' */ + bRc = SetEndOfFile(hFile); + if (bRc == FALSE) + { + Trace("ERROR:%u: Unable to set file pointer of file handle 0x%lx.\n", + GetLastError(), + hFile); + if (!CloseHandle(hFile)) + { + Fail("ERROR:%u%: Unable to close handle 0x%lx.\n", + GetLastError(), + hFile); + } + Fail(""); + } + + /* Set the file pointer to 10 bytes from the front of the file + */ + retCode = SetFilePointer(hFile, (LONG)NULL, NULL, FILE_BEGIN); + if(retCode == INVALID_SET_FILE_POINTER) + { + Trace("ERROR:%u: Unable to set the file pointer to %d\n", + GetLastError(), + FILE_BEGIN); + if (!CloseHandle(hFile)) + { + Fail("ERROR:%u%: Unable to close handle 0x%lx.\n", + GetLastError(), + hFile); + } + Fail(""); + } + + /* Attempt to read the entire string, 'testString' from a file + * that has it's end of pointer set at shiftAmount; + */ + bRc = ReadFile(hFile, + szBuffer, + strlen(testString), + &dwBytesRead, + NULL); + + if (bRc == FALSE) + { + Trace("ERROR:%u: Unable to read from file handle 0x%lx.\n", + GetLastError(), + hFile); + if (!CloseHandle(hFile)) + { + Fail("ERROR:%u%: Unable to close handle 0x%lx.\n", + GetLastError(), + hFile); + } + Fail(""); + } + + /* Confirm the number of bytes read with that requested. + */ + if (dwBytesRead != shiftAmount) + { + Trace("ERROR: The number of bytes read \"%d\" is not equal to the " + "number that should have been written \"%d\".\n", + dwBytesRead, + shiftAmount); + if (!CloseHandle(hFile)) + { + Fail("ERROR:%u%: Unable to close handle 0x%lx.\n", + GetLastError(), + hFile); + } + Fail(""); + } + + bRc = CloseHandle(hFile); + if(!bRc) + { + Fail("ERROR:%u CloseHandle failed to close the handle\n", + GetLastError()); + } + + /* Terminate the PAL. + */ + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/testinfo.dat new file mode 100644 index 0000000..3a226ff --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = SetEndOfFile +Name = Positive Test for SetEndOfFile +Type = DEFAULT +EXE1 = test5 +Description += Tests the PAL implementation of the SetEndOfFile function. += Test attempts to set the end of file pointer to a position += which has data before and after it. Then it attempts to += read text beyond the end of file pointer. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/CMakeLists.txt new file mode 100644 index 0000000..7cd88f8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/CMakeLists.txt @@ -0,0 +1,8 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test1/CMakeLists.txt new file mode 100644 index 0000000..698768d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + SetFilePointer.cpp +) + +add_executable(paltest_setfilepointer_test1 + ${SOURCES} +) + +add_dependencies(paltest_setfilepointer_test1 coreclrpal) + +target_link_libraries(paltest_setfilepointer_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test1/SetFilePointer.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test1/SetFilePointer.cpp new file mode 100644 index 0000000..14b5f85 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test1/SetFilePointer.cpp @@ -0,0 +1,123 @@ +// 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. + +/*===================================================================== +** +** Source: SetFilePointer.c (test 1) +** +** Purpose: Tests the PAL implementation of the SetFilePointer function. +** Set the file pointer using a NULL handle and other invalid +** options. +** +** +**===================================================================*/ + +#include + + +const char* szTextFile = "text.txt"; + + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwByteCount = 0; + DWORD dwOffset = 25; + DWORD dwRc = 0; + BOOL bRc = FALSE; + char buffer[100]; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* set the file pointer on a NULL file handle */ + dwRc = SetFilePointer(NULL, dwOffset, NULL, FILE_BEGIN); + if (dwRc != INVALID_SET_FILE_POINTER) + { + Fail("SetFilePointer: ERROR -> Call to SetFilePointer succeeded " + "with a NULL pointer\n"); + } + + + /* create a test file without proper permission */ + hFile = CreateFile(szTextFile, + 0, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("SetFilePointer: ERROR -> Unable to create file \"%s\".\n", + szTextFile); + } + + /* ReadFile fails as expected */ + bRc = ReadFile(hFile, buffer, 1, &dwByteCount, NULL); + if (bRc != FALSE) + { + Trace("SetFilePointer: ERROR -> ReadFile was successful when it was " + "expected to fail\n"); + if (!CloseHandle(hFile)) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* move the file pointer before the beginning of the file */ + dwRc = SetFilePointer(hFile, -1, NULL, FILE_BEGIN); + if (dwRc != INVALID_SET_FILE_POINTER) + { + Trace("SetFilePointer: ERROR -> Was able to move the pointer before " + "the beginning of the file.\n"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + if (!DeleteFileA(szTextFile)) + { + Fail("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test1/testinfo.dat new file mode 100644 index 0000000..dfd4b6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = SetFilePointer +Name = Test for SetFilePointer (test 1) +Type = DEFAULT +EXE1 = setfilepointer +Description +=Set the file pointer on a NULL file handle and other invalid options + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test2/CMakeLists.txt new file mode 100644 index 0000000..fa25357 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + SetFilePointer.cpp +) + +add_executable(paltest_setfilepointer_test2 + ${SOURCES} +) + +add_dependencies(paltest_setfilepointer_test2 coreclrpal) + +target_link_libraries(paltest_setfilepointer_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test2/SetFilePointer.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test2/SetFilePointer.cpp new file mode 100644 index 0000000..19e99a7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test2/SetFilePointer.cpp @@ -0,0 +1,356 @@ +// 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. + +/*===================================================================== +** +** Source: SetFilePointer.c (test 2) +** +** Purpose: Tests the PAL implementation of the SetFilePointer function. +** Test the FILE_BEGIN option +** +** Assumes Successful: +** CreateFile +** ReadFile +** WriteFile +** strlen +** CloseHandle +** strcmp +** GetFileSize +** +** +**===================================================================*/ + +#include + +const char * const szText = + "The quick brown fox jumped over the lazy dog's back."; +const char* szTextFile = "text.txt"; + + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwByteCount = 0; + DWORD dwRc = 0; + BOOL bRc = FALSE; + char szBuffer[100]; + const char *szPtr; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create a test file */ + hFile = CreateFile(szTextFile, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("SetFilePointer: ERROR -> Unable to create file \"%s\".\n", + szTextFile); + } + + bRc = WriteFile(hFile, szText, (DWORD)strlen(szText), &dwByteCount, NULL); + if (bRc == FALSE) + { + Trace("SetFilePointer: ERROR -> Unable to write to file \"%s\".\n", + szTextFile); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + + /* move -1 from beginning which should fail */ + dwRc = SetFilePointer(hFile, -1, NULL, FILE_BEGIN); + if ((dwRc != INVALID_SET_FILE_POINTER) || + (GetLastError() == ERROR_SUCCESS)) + { + Trace("SetFilePointer: ERROR -> Succeeded to move the pointer " + "before the beginning of the file.\n"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* move the file pointer 0 bytes from the beginning and verify */ + dwRc = SetFilePointer(hFile, 0, NULL, FILE_BEGIN); + if (dwRc != 0) + { + Trace("SetFilePointer: ERROR -> Asked to move 0 bytes from the " + "beginning of the file but moved %ld bytes.\n", dwRc); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* move the pointer ahead in the file and verify */ + dwRc = SetFilePointer(hFile, 20, NULL, FILE_BEGIN); + if (dwRc != 20) + { + Trace("SetFilePointer: ERROR -> Asked to move 0 bytes from the " + "beginning of the file but moved %ld bytes.\n", dwRc); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + /* verify results */ + memset(szBuffer, 0, 100); + bRc = ReadFile(hFile, szBuffer, (DWORD)strlen(szText)-20, &dwByteCount, + NULL); + if ((bRc != TRUE) || (dwByteCount != strlen(szText)-20)) + { + Trace("SetFilePointer: ERROR -> ReadFile failed to read correctly"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file" + "\"%s\".\n", szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + "\"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + szPtr = szText + 20; + if (strcmp(szPtr, szBuffer) != 0) + { + Trace("SetFilePointer: ERROR -> Apparently failed to move the " + "pointer properly\n"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file" + " \"%s\".\n", szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + + /* move the file pointer back to the beginning and verify */ + dwRc = SetFilePointer(hFile, 0, NULL, FILE_BEGIN); + if (dwRc != 0) + { + Trace("SetFilePointer: ERROR -> Asked to move 0 bytes from the " + "beginning of the file but moved %ld bytes.\n", dwRc); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + /* verify results */ + memset(szBuffer, 0, 100); + bRc = ReadFile(hFile, szBuffer, (DWORD)strlen(szText), &dwByteCount, + NULL); + if ((bRc != TRUE) || (dwByteCount != strlen(szText))) + { + Trace("SetFilePointer: ERROR -> ReadFile failed to read correctly"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file" + " \"%s\".\n", szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + if (strcmp(szText, szBuffer) != 0) + { + Trace("SetFilePointer: ERROR -> Failed to return the pointer " + "properly to the beginning of the file\n"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file" + " \"%s\".\n", szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + + /* return the pointer to the beginning of the file */ + dwRc = SetFilePointer(hFile, 0, NULL, FILE_BEGIN); + if (dwRc != 0) + { + Trace("SetFilePointer: ERROR -> Asked to move 0 bytes from the " + "beginning of the file but moved %ld bytes.\n", dwRc); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* set the pointer past the end of the file and verify */ + dwRc = SetFilePointer(hFile, (DWORD)strlen(szText)+20, NULL, FILE_BEGIN); + if ((dwRc == INVALID_SET_FILE_POINTER) && (GetLastError() != ERROR_SUCCESS)) + { + Trace("SetFilePointer: ERROR -> Failed to move pointer past EOF.\n"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + /* verify */ + bRc = SetEndOfFile(hFile); + if (bRc != TRUE) + { + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file" + " \"%s\".\n", szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + if (GetFileSize(hFile, NULL) != strlen(szText)+20) + { + Trace("SetFilePointer: ERROR -> Failed to move pointer past" + " EOF.\n"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file" + " \"%s\".\n", szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + + + + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + if (!DeleteFileA(szTextFile)) + { + Fail("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test2/testinfo.dat new file mode 100644 index 0000000..e3a0a86 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = SetFilePointer +Name = Positive Test for SetFilePointer (test 2) +Type = DEFAULT +EXE1 = setfilepointer +Description +=Tests the FILE_BEGIN option + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test3/CMakeLists.txt new file mode 100644 index 0000000..cf0b9dd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + SetFilePointer.cpp +) + +add_executable(paltest_setfilepointer_test3 + ${SOURCES} +) + +add_dependencies(paltest_setfilepointer_test3 coreclrpal) + +target_link_libraries(paltest_setfilepointer_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test3/SetFilePointer.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test3/SetFilePointer.cpp new file mode 100644 index 0000000..dd53829 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test3/SetFilePointer.cpp @@ -0,0 +1,350 @@ +// 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. + +/*===================================================================== +** +** Source: SetFilePointer.c (test 3) +** +** Purpose: Tests the PAL implementation of the SetFilePointer function. +** Test the FILE_CURRENT option +** +** Assumes Successful: +** CreateFile +** ReadFile +** WriteFile +** strlen +** CloseHandle +** strcmp +** GetFileSize +** +** +**===================================================================*/ + +#include + +const char* const szText = + "The quick brown fox jumped over the lazy dog's back."; +const char* szTextFile = "text.txt"; + + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwByteCount = 0; + DWORD dwRc = 0; + BOOL bRc = FALSE; + char szBuffer[100]; + const char* szPtr; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create a test file */ + hFile = CreateFile(szTextFile, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("SetFilePointer: ERROR -> Unable to create file \"%s\".\n", + szTextFile); + } + + bRc = WriteFile(hFile, szText, (DWORD)strlen(szText), &dwByteCount, NULL); + if (bRc == FALSE) + { + Trace("SetFilePointer: ERROR -> Unable to write to file \"%s\".\n", + szTextFile); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* reset the pointer to the beginning */ + if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + { + if (GetLastError() != ERROR_SUCCESS) + { + Trace("SetFilePointer: ERROR -> Unable to reset the pointer to the " + "beginning of the file"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + + /* move -1 from beginning which should fail */ + dwRc = SetFilePointer(hFile, -1, NULL, FILE_CURRENT); + if ((dwRc != INVALID_SET_FILE_POINTER) || + (GetLastError() == ERROR_SUCCESS)) + { + Trace("SetFilePointer: ERROR -> Succeeded to move the pointer " + "before the beginning of the file.\n"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + + /* move the file pointer 0 bytes from the beginning and verify */ + dwRc = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); + if (dwRc != 0) + { + Trace("SetFilePointer: ERROR -> Asked to move 0 bytes from the " + "beginning of the file but moved %ld bytes.\n", dwRc); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* move the pointer ahead in the file and verify */ + dwRc = SetFilePointer(hFile, 20, NULL, FILE_CURRENT); + if (dwRc != 20) + { + Trace("SetFilePointer: ERROR -> Asked to move 20 bytes from the " + "beginning of the file but moved %ld bytes.\n", dwRc); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + /* verify results */ + memset(szBuffer, 0, 100); + bRc = ReadFile(hFile, szBuffer, (DWORD)strlen(szText)-20, &dwByteCount, + NULL); + if ((bRc != TRUE) || (dwByteCount != strlen(szText)-20)) + { + Trace("SetFilePointer: ERROR -> ReadFile failed to read correctly"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + szPtr = szText + 20;; + if (strcmp(szPtr, szBuffer) != 0) + { + Trace("SetFilePointer: ERROR -> Apparently failed to move the" + " pointer properly\n"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + + + /* get the current file pointer position (should be 52) */ + dwRc = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); + if (dwRc != 52) + { + Trace("SetFilePointer: ERROR -> Asked for current position." + " Should be 52 but was %ld.\n", dwRc); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + + /* move the pointer backwards in the file and verify */ + dwRc = SetFilePointer(hFile, -10, NULL, FILE_CURRENT); + if (dwRc != 42) + { + Trace("SetFilePointer: ERROR -> Asked to move back 10 bytes from the" + "end of the file but moved it to position %ld.\n", dwRc); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + /* verify results */ + memset(szBuffer, 0, 100); + bRc = ReadFile(hFile, szBuffer, 10, &dwByteCount, NULL); + if ((bRc != TRUE) || (dwByteCount != 10)) + { + Trace("SetFilePointer: ERROR -> ReadFile failed to read correctly"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + szPtr = szText + 42; + if (strcmp(szPtr, szBuffer) != 0) + { + Trace("SetFilePointer: ERROR -> Apparently failed to move the" + " pointer properly\n"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + + /* + * the file pointer is currently at the end of the file so... + * set the pointer past the end of the file and verify + */ + dwRc = SetFilePointer(hFile, 20, NULL, FILE_CURRENT); + if ((dwRc == INVALID_SET_FILE_POINTER) && (GetLastError() != ERROR_SUCCESS)) + { + Trace("SetFilePointer: ERROR -> Failed to move pointer past EOF.\n"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + if (SetFilePointer(hFile, 0, NULL, FILE_CURRENT) != strlen(szText)+20) + { + Trace("SetFilePointer: ERROR -> Failed to move pointer past" + " EOF.\n"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + if (!DeleteFileA(szTextFile)) + { + Fail("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test3/testinfo.dat new file mode 100644 index 0000000..7c51fbc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test3/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = SetFilePointer +Name = Positive Test for SetFilePointer (test 3) +Type = DEFAULT +EXE1 = setfilepointer +Description +=Tests the FILE_CURRENT option + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test4/CMakeLists.txt new file mode 100644 index 0000000..35c0ee9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + SetFilePointer.cpp +) + +add_executable(paltest_setfilepointer_test4 + ${SOURCES} +) + +add_dependencies(paltest_setfilepointer_test4 coreclrpal) + +target_link_libraries(paltest_setfilepointer_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test4/SetFilePointer.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test4/SetFilePointer.cpp new file mode 100644 index 0000000..2993cfd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test4/SetFilePointer.cpp @@ -0,0 +1,242 @@ +// 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. + +/*===================================================================== +** +** Source: SetFilePointer.c (test 4) +** +** Purpose: Tests the PAL implementation of the SetFilePointer function. +** Test the FILE_END option +** +** Assumes Successful: +** CreateFile +** ReadFile +** WriteFile +** strlen +** CloseHandle +** strcmp +** GetFileSize +** +** +**===================================================================*/ + +#include + +const char* szText = "The quick brown fox jumped over the lazy dog's back."; +const char* szTextFile = "text.txt"; + + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwByteCount = 0; + DWORD dwOffset = 0; + DWORD dwRc = 0; + BOOL bRc = FALSE; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create a test file */ + hFile = CreateFile(szTextFile, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("SetFilePointer: ERROR -> Unable to create file \"%s\".\n", + szTextFile); + } + + bRc = WriteFile(hFile, szText, (DWORD)strlen(szText), &dwByteCount, NULL); + if (bRc == FALSE) + { + Trace("SetFilePointer: ERROR -> Unable to write to file \"%s\".\n", + szTextFile); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + + /* + * move -1 from the end + */ + dwRc = SetFilePointer(hFile, -1, NULL, FILE_END); + if (dwRc == INVALID_SET_FILE_POINTER) + { + if (GetLastError() != ERROR_SUCCESS) + { + Trace("SetFilePointer: ERROR -> Failed to move the pointer " + "back one character from EOF.\n"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file" + " \"%s\".\n", szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + else + { + /* verify */ + if ((dwRc != strlen(szText)-1)) + { + Trace("SetFilePointer: ERROR -> Failed to move the pointer" + " -1 bytes from EOF\n"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file" + " \"%s\".\n", szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + + /* + * move the file pointer 0 bytes from the end and verify + */ + dwRc = SetFilePointer(hFile, 0, NULL, FILE_END); + if (dwRc != strlen(szText)) + { + Trace("SetFilePointer: ERROR -> Asked to move 0 bytes from the " + "end of the file. Function returned %ld instead of 52.\n", dwRc); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* + * move the pointer past the end of the file and verify + */ + dwRc = SetFilePointer(hFile, 20, NULL, FILE_END); + if (dwRc != strlen(szText)+20) + { + Trace("SetFilePointer: ERROR -> Asked to move 20 bytes past the " + "end of the file. Function returned %ld instead of %d.\n", + dwRc, + strlen(szText)+20); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + /* verify results */ + bRc = SetEndOfFile(hFile); + if ((dwRc = GetFileSize(hFile, NULL)) != strlen(szText)+20) + { + Trace("SetFilePointer: ERROR -> Asked to move back 20 bytes past" + " theend of the file. GetFileSize returned %ld whereas it " + "should have been %d.\n", + dwRc, + strlen(szText)+20); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file" + " \"%s\".\n", szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + + + /* + * move the pointer backwards to before the start of the file and verify + */ + + dwOffset = (dwRc + 20) * -1; + dwRc = SetFilePointer(hFile, dwOffset, NULL, FILE_END); + if ((dwRc != INVALID_SET_FILE_POINTER) || + (GetLastError() == ERROR_SUCCESS)) + { + Trace("SetFilePointer: ERROR -> Was able to move the pointer " + "to before the beginning of the file.\n"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + if (!DeleteFileA(szTextFile)) + { + Fail("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test4/testinfo.dat new file mode 100644 index 0000000..dce6f9e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test4/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = SetFilePointer +Name = Positive Test for SetFilePointer (test 4) +Type = DEFAULT +EXE1 = setfilepointer +Description +=Tests the FILE_END option + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test5/CMakeLists.txt new file mode 100644 index 0000000..a384a14 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + SetFilePointer.cpp +) + +add_executable(paltest_setfilepointer_test5 + ${SOURCES} +) + +add_dependencies(paltest_setfilepointer_test5 coreclrpal) + +target_link_libraries(paltest_setfilepointer_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test5/SetFilePointer.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test5/SetFilePointer.cpp new file mode 100644 index 0000000..f1d392d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test5/SetFilePointer.cpp @@ -0,0 +1,182 @@ +// 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. + +/*===================================================================== +** +** Source: SetFilePointer.c (test 5) +** +** Purpose: Tests the PAL implementation of the SetFilePointer function. +** Test the FILE_BEGIN option using the high word parameter +** +** Assumes Successful: +** CreateFile +** ReadFile +** WriteFile +** strlen +** CloseHandle +** strcmp +** GetFileSize +** +** +**===================================================================*/ + +#include + +const char* szTextFile = "text.txt"; + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwOffset = 1; + LONG dwHighWord = 1; + DWORD dwReturnedOffset = 0; + DWORD dwReturnedHighWord = 0; + DWORD dwRc = 0; + DWORD dwError = 0; + BOOL bRc = FALSE; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create a test file */ + hFile = CreateFile(szTextFile, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + dwError = GetLastError(); + Fail("SetFilePointer: ERROR -> Unable to create file \"%s\".\n with " + "error %ld", + szTextFile, + GetLastError()); + } + + + + /* move -1 from beginning which should fail */ + dwRc = SetFilePointer(hFile, -1, &dwHighWord, FILE_BEGIN); + if (dwRc != INVALID_SET_FILE_POINTER) + { + Trace("SetFilePointer: ERROR -> Succeeded to move the pointer " + "before the beginning of the file using the high word.\n"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* set the pointer past the end of the file and verify */ + dwRc = SetFilePointer(hFile, dwOffset, &dwHighWord, FILE_BEGIN); + if ((dwRc == INVALID_SET_FILE_POINTER) && + ((dwError = GetLastError()) != ERROR_SUCCESS)) + { + Trace("SetFilePointer: ERROR -> Failed to move pointer past EOF.\n"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + /* verify */ + bRc = SetEndOfFile(hFile); + if (bRc != TRUE) + { + dwError = GetLastError(); + if (dwError == 112) + { + Trace("SetFilePointer: ERROR -> SetEndOfFile failed due to " + "lack of disk space\n"); + } + else + { + Trace("SetFilePointer: ERROR -> SetEndOfFile call failed with " + "error %ld\n", dwError); + } + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file" + " \"%s\".\n", szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + dwReturnedOffset = GetFileSize(hFile, &dwReturnedHighWord); + if ((dwOffset != dwReturnedOffset) || + (dwHighWord != dwReturnedHighWord)) + { + Trace("SetFilePointer: ERROR -> Failed to move pointer past" + " EOF.\n"); + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file" + " \"%s\".\n", szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + if (!DeleteFileA(szTextFile)) + { + Fail("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test5/testinfo.dat new file mode 100644 index 0000000..64745c0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test5/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = SetFilePointer +Name = Positive Test for SetFilePointer (test 5) +Type = DEFAULT +EXE1 = setfilepointer +Description +=Tests the FILE_BEGIN option with the high word parameter. +=This test requires about 4 gig free disk space + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test6/CMakeLists.txt new file mode 100644 index 0000000..b7b8dba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + SetFilePointer.cpp +) + +add_executable(paltest_setfilepointer_test6 + ${SOURCES} +) + +add_dependencies(paltest_setfilepointer_test6 coreclrpal) + +target_link_libraries(paltest_setfilepointer_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test6/SetFilePointer.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test6/SetFilePointer.cpp new file mode 100644 index 0000000..b35247e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test6/SetFilePointer.cpp @@ -0,0 +1,213 @@ +// 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. + +/*===================================================================== +** +** Source: SetFilePointer.c (test 6) +** +** Purpose: Tests the PAL implementation of the SetFilePointer function. +** Test the FILE_CURRENT option with high order support +** +** Assumes Successful: +** CreateFile +** ReadFile +** WriteFile +** strlen +** CloseHandle +** strcmp +** GetFileSize +** +** +**===================================================================*/ + +#include + +const char* szTextFile = "text.txt"; + + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwOffset = 0; + LONG dwHighOrder = 0; + DWORD dwReturnedOffset = 0; + LONG dwReturnedHighOrder = 0; + DWORD dwRc = 0; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create a test file */ + hFile = CreateFile(szTextFile, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("SetFilePointer: ERROR -> Unable to create file \"%s\".\n", + szTextFile); + } + + + /* move waaaay before the beginning which should fail */ + dwHighOrder = -1; + dwOffset = 0; + dwRc = SetFilePointer(hFile, dwOffset, &dwHighOrder, FILE_CURRENT); + if (dwRc != INVALID_SET_FILE_POINTER) + { + Trace("SetFilePointer: ERROR -> Succeeded to move the pointer " + "before the beginning of the file.\n"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* move the pointer ahead in the file and verify */ + dwHighOrder = 1; + dwOffset = 10; + dwRc = SetFilePointer(hFile, dwOffset, &dwHighOrder, FILE_CURRENT); + if ((dwRc != 10) || (dwHighOrder != 1)) + { + Trace("SetFilePointer: ERROR -> Asked to move 2GB plus 10 bytes from " + "the beginning of the file but didn't.\n"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + /* verify results */ + if (SetEndOfFile(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Call to SetEndOfFile failed with " + "error code: %d\n", GetLastError()); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file" + " \"%s\".\n", szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + dwReturnedOffset = GetFileSize(hFile, (DWORD*)&dwReturnedHighOrder); + if ((dwReturnedOffset != dwOffset) || + (dwReturnedHighOrder != dwHighOrder)) + { + Trace("SetFilePointer: ERROR -> Asked to move far past the " + "current file pointer. " + "low order sent: %ld low order returned: %ld " + "high order sent: %ld high order returned: %ld", + dwOffset, dwReturnedOffset, + dwHighOrder, dwReturnedHighOrder); + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + + + /* + * move the pointer backwards in the file and verify + */ + dwOffset = 0; + dwHighOrder = -1; + dwRc = SetFilePointer(hFile, dwOffset, &dwHighOrder, FILE_CURRENT); + if (dwRc != 10) + { + Trace("SetFilePointer: ERROR -> Asked to move back to 10 bytes from the" + "beginning of the file but moved it to position %ld.\n", dwRc); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + /* verify results */ + dwReturnedHighOrder = 0; + dwRc = SetFilePointer(hFile, 0, &dwReturnedHighOrder, FILE_CURRENT); + if (dwRc != 10) + { + Trace("SetFilePointer: ERROR -> Asked for current position. " + "Should be 10 but was %ld.\n", dwRc); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file" + " \"%s\".\n", szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + + + /* clean up, clean up, everybody do their share... */ + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + if (!DeleteFileA(szTextFile)) + { + Fail("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test6/testinfo.dat new file mode 100644 index 0000000..3138e9b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test6/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = SetFilePointer +Name = Positive Test for SetFilePointer (test 6) +Type = DEFAULT +EXE1 = setfilepointer +Description +=Tests the FILE_CURRENT option with the high word parameter. +=This test requires about 4 GB free disk space. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test7/CMakeLists.txt new file mode 100644 index 0000000..6596afa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + SetFilePointer.cpp +) + +add_executable(paltest_setfilepointer_test7 + ${SOURCES} +) + +add_dependencies(paltest_setfilepointer_test7 coreclrpal) + +target_link_libraries(paltest_setfilepointer_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test7/SetFilePointer.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test7/SetFilePointer.cpp new file mode 100644 index 0000000..33dfd5e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test7/SetFilePointer.cpp @@ -0,0 +1,213 @@ +// 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. + +/*===================================================================== +** +** Source: SetFilePointer.c (test 7) +** +** Purpose: Tests the PAL implementation of the SetFilePointer function. +** Test the FILE_END option with high order support +** +** Assumes Successful: +** CreateFile +** ReadFile +** WriteFile +** strlen +** CloseHandle +** strcmp +** GetFileSize +** +** +**===================================================================*/ + +#include + +const char* szTextFile = "text.txt"; + + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwOffset = 0; + LONG dwHighOrder = 0; + DWORD dwReturnedOffset = 0; + LONG dwReturnedHighOrder = 0; + DWORD dwRc = 0; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create a test file */ + hFile = CreateFile(szTextFile, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("SetFilePointer: ERROR -> Unable to create file \"%s\".\n", + szTextFile); + } + + + /* move -1 from beginning which should fail */ + dwHighOrder = -1; + dwOffset = 0; + dwRc = SetFilePointer(hFile, dwOffset, &dwHighOrder, FILE_END); + if (dwRc != INVALID_SET_FILE_POINTER) + { + Trace("SetFilePointer: ERROR -> Succeeded to move the pointer " + "before the beginning of the file.\n"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* move the pointer ahead in the file and verify */ + dwHighOrder = 1; + dwOffset = 10; + dwRc = SetFilePointer(hFile, dwOffset, &dwHighOrder, FILE_END); + if ((dwRc != 10) || (dwHighOrder != 1)) + { + Trace("SetFilePointer: ERROR -> Asked to move 4GB plus 10 bytes from " + "the beginning of the file but didn't.\n"); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + /* verify results */ + if (SetEndOfFile(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Call to SetEndOfFile failed with " + "error code: %d\n", + GetLastError()); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + dwReturnedOffset = GetFileSize(hFile, (DWORD*)&dwReturnedHighOrder); + if ((dwReturnedOffset != dwOffset) || (dwReturnedHighOrder != dwHighOrder)) + { + Trace("SetFilePointer: ERROR -> Asked to move far past the " + "end of the file. low order sent: %ld low order returned: %ld " + "high order sent: %ld high order returned: %ld", + dwOffset, dwReturnedOffset, + dwHighOrder, dwReturnedHighOrder); + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + + + /* + * move the pointer backwards in the file and verify + */ + dwOffset = 0; + dwHighOrder = -1; + dwRc = SetFilePointer(hFile, dwOffset, &dwHighOrder, FILE_END); + if (dwRc != 10) + { + Trace("SetFilePointer: ERROR -> Asked to move back to 10 bytes from the" + "beginning of the file but moved it to position %ld.\n", dwRc); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + else + { + /* verify results */ + dwReturnedHighOrder = 0; + dwRc = SetFilePointer(hFile, 0, &dwReturnedHighOrder, FILE_CURRENT); + if (dwRc != 10) + { + Trace("SetFilePointer: ERROR -> Asked for current position. " + "Should be 10 but was %ld.\n", dwRc); + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file" + " \"%s\".\n", szTextFile); + } + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file" + " \"%s\".\n", szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + } + + + /* clean up, clean up, everybody do their share... */ + if (CloseHandle(hFile) != TRUE) + { + Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n", + szTextFile); + if (!DeleteFileA(szTextFile)) + { + Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + PAL_TerminateEx(FAIL); + return FAIL; + } + + if (!DeleteFileA(szTextFile)) + { + Fail("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n", + szTextFile); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test7/testinfo.dat new file mode 100644 index 0000000..6e88262 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/SetFilePointer/test7/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = SetFilePointer +Name = Positive Test for SetFilePointer (test 7) +Type = DEFAULT +EXE1 = setfilepointer +Description +=Tests the FILE_END option with the high word parameter +=This test requires about 4 GB of free disk space. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/CMakeLists.txt new file mode 100644 index 0000000..dcf480b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/CMakeLists.txt @@ -0,0 +1,6 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test1/CMakeLists.txt new file mode 100644 index 0000000..4a02596 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + WriteFile.cpp +) + +add_executable(paltest_writefile_test1 + ${SOURCES} +) + +add_dependencies(paltest_writefile_test1 coreclrpal) + +target_link_libraries(paltest_writefile_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.cpp new file mode 100644 index 0000000..a080f56 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.cpp @@ -0,0 +1,114 @@ +// 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. + +/*===================================================================== +** +** Source: WriteFile.c (test 1) +** +** Purpose: Tests the PAL implementation of the WriteFile function. +** This test will attempt to write to a NULL handle and a +** read-only file +** +** +**===================================================================*/ + +#include + + +const char* szStringTest = "The quick fox jumped over the lazy dog's back."; +const char* szReadOnlyFile = "ReadOnly.txt"; +void do_cleanup() +{ + BOOL bRc = FALSE; + bRc = DeleteFileA(szReadOnlyFile); + if (bRc != TRUE) + { + Fail ("DeleteFileA: ERROR[%ld]: During Cleanup: Couldn't delete WriteFile's" + " \"ReadOnly.txt\"\n", GetLastError()); + } + +} + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFile = NULL; + DWORD dwBytesWritten; + BOOL bRc = FALSE; + DWORD last_error; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + // + // Write to a NULL handle + // + + bRc = WriteFile(hFile, szStringTest, 20, &dwBytesWritten, NULL); + + if (bRc == TRUE) + { + last_error = GetLastError(); + Fail("WriteFile: ERROR[%ld] -> Able to write to a NULL handle\n", last_error); + } + + + // + // Write to a file with read-only permissions + // + + // create a file without write permissions + hFile = CreateFile(szReadOnlyFile, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + last_error = GetLastError(); + Fail("WriteFile: ERROR[%ld] -> Unable to create file \"%s\".\n", + last_error, szReadOnlyFile); + } + + if (!SetFileAttributesA(szReadOnlyFile, FILE_ATTRIBUTE_READONLY)) + { + last_error = GetLastError(); + Trace("WriteFile: ERROR[%ld] -> Unable to make the file read-only.\n", last_error); + do_cleanup(); + Fail("WriteFile: ERROR[%ld] -> Unable to make the file read-only.\n", last_error); + } + + bRc = WriteFile(hFile, szStringTest, 20, &dwBytesWritten, NULL); + if (bRc == TRUE) + { last_error = GetLastError(); + Trace("WriteFile: ERROR[%ld] -> Able to write to a read-only file.\n", last_error); + do_cleanup(); + Fail("WriteFile: ERROR[%ld] -> Able to write to a read-only file.\n", last_error); + } + + + bRc = CloseHandle(hFile); + if (bRc != TRUE) + { last_error = GetLastError(); + Trace("WriteFile: ERROR[%ld] -> Unable to close file \"%s\".\n", last_error, szReadOnlyFile); + do_cleanup(); + Fail("WriteFile: ERROR -> Unable to close file \"%s\".\n", + szReadOnlyFile); + } + + //To delete file need to make it normal + if(!SetFileAttributesA(szReadOnlyFile,FILE_ATTRIBUTE_NORMAL)) + { + last_error = GetLastError(); + Fail("WriteFile: ERROR[%ld] -> Unable to make the file attribute NORMAL.\n", last_error); + + } + do_cleanup(); + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test1/testinfo.dat new file mode 100644 index 0000000..148a267 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = WriteFile +Name = test for WriteFile +Type = DEFAULT +EXE1 = writefile +Description +=Attempt to write to a NULL handle and to a read-only file + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/CMakeLists.txt new file mode 100644 index 0000000..844c0b1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + WriteFile.cpp +) + +add_executable(paltest_writefile_test2 + ${SOURCES} +) + +add_dependencies(paltest_writefile_test2 coreclrpal) + +target_link_libraries(paltest_writefile_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/Results.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/Results.txt new file mode 100644 index 0000000..1c4c378 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/Results.txt @@ -0,0 +1 @@ +0011100111 \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.cpp new file mode 100644 index 0000000..9345bc6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.cpp @@ -0,0 +1,105 @@ +// 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. + +/*===================================================================== +** +** Source: WriteFile.c (test 2) +** +** Purpose: Tests the PAL implementation of the WriteFile function. +** Creates a number of files and writes different amounts of +** data and verifies the writes. +** +** +**===================================================================*/ + + +#include + + +char* writeBuffer; +const char* szWritableFile = "Writeable.txt"; +const char* szResultsFile = "Results.txt"; +const int PAGESIZE = 4096; + +BOOL writeTest(DWORD dwByteCount, DWORD dwBytesWrittenResult, BOOL bResult) +{ + HANDLE hFile = NULL; + DWORD dwBytesWritten; + BOOL bRc = FALSE; + + /* create the test file */ + DeleteFile(szWritableFile); + hFile = CreateFile(szWritableFile, GENERIC_WRITE, FILE_SHARE_WRITE, + NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Trace("WriteFile: ERROR -> Unable to create file \"%s\".\n", + szWritableFile); + return FALSE; + } + + bRc = WriteFile(hFile, writeBuffer, dwByteCount, &dwBytesWritten, NULL); + CloseHandle(hFile); + + if ((bRc != bResult) || (dwBytesWrittenResult != dwBytesWritten)) + { + Trace("WriteFile returned BOOL:%d and dwWritten:%d what we do expect is" + " BOOL:%d and dwWritten:%d\n", bRc, dwBytesWritten, bResult, + dwBytesWrittenResult); + return FALSE; + } + + return TRUE; +} + +int __cdecl main(int argc, char *argv[]) +{ + const char * testString = "The quick fox jumped over the lazy dog's back."; + const int testStringLen = strlen(testString); + + DWORD dwByteCount[4] = {-1, 10, testStringLen, 0}; + DWORD dwByteWritten[4] = {0, 10, testStringLen, 0}; + BOOL bResults[] = {FALSE, TRUE, TRUE, TRUE}; + + const int BUFFER_SIZE = 2 * PAGESIZE; + int j; + BOOL bRc = FALSE; + DWORD oldProt; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* allocate read-write memery for writeBuffer */ + if (!(writeBuffer = (char*) VirtualAlloc(NULL, BUFFER_SIZE, MEM_COMMIT, + PAGE_READWRITE))) + { + Fail("VirtualAlloc failed: GetLastError returns %d\n", GetLastError()); + return FAIL; + } + + memset((void*) writeBuffer, '.', BUFFER_SIZE); + strcpy(writeBuffer, testString); + + /* write protect the second page of writeBuffer */ + if (!VirtualProtect(&writeBuffer[PAGESIZE], PAGESIZE, PAGE_NOACCESS, &oldProt)) + { + Fail("VirtualProtect failed: GetLastError returns %d\n", GetLastError()); + return FAIL; + } + + for (j = 0; j< 4; j++) + { + bRc = writeTest(dwByteCount[j], dwByteWritten[j], bResults[j]); + if (bRc != TRUE) + { + Fail("WriteFile: ERROR -> Failed on test[%d]\n", j); + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/testinfo.dat new file mode 100644 index 0000000..a09df96 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = WriteFile +Name = Positive Test for WriteFile +Type = DEFAULT +EXE1 = writefile +Description +=Multiple tests of writes of varying sizes with verification + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test3/CMakeLists.txt new file mode 100644 index 0000000..128d52a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + WriteFile.cpp +) + +add_executable(paltest_writefile_test3 + ${SOURCES} +) + +add_dependencies(paltest_writefile_test3 coreclrpal) + +target_link_libraries(paltest_writefile_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test3/WriteFile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test3/WriteFile.cpp new file mode 100644 index 0000000..751f89f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test3/WriteFile.cpp @@ -0,0 +1,136 @@ +// 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. + +/*===================================================================== +** +** Source: WriteFile.c (test 3) +** +** Purpose: Tests the PAL implementation of the WriteFile function. +** Performs multiple writes to a file and verifies the results. +** +** +**===================================================================*/ + + +#include + + +const char* szStringTest = "The quick fox jumped over the lazy dog's back.\0"; +const char* szWritableFile = "writeable.txt"; + + +BOOL validateResults(const char* szString) +{ + FILE *pFile = NULL; + char szReadString[100]; + DWORD dwBytesRead; + DWORD dwStringLength = strlen(szString); + + + + memset(szReadString, 0, 100); + + /* open the file */ + pFile = fopen(szWritableFile, "r"); + if (pFile == NULL) + { + Trace("couldn't open test file\n"); + return FALSE; + } + + dwBytesRead = fread(szReadString, sizeof(char), dwStringLength, pFile); + fclose(pFile); + + if(dwBytesRead != dwStringLength) + { + Trace("dwbyteread != string length\n"); + return FALSE; + } + + if (strcmp(szReadString, szString)) + { + Trace("read = %s string = %s", szReadString, szString); + return FALSE; + } + return TRUE; +} + + + + +BOOL writeTest(const char* szString) +{ + HANDLE hFile = NULL; + DWORD dwBytesWritten; + BOOL bRc = FALSE; + BOOL bAllPassed = TRUE; + int nStringLength = 0; + char* szPtr = NULL; + int i = 0; + + // create the test file + hFile = CreateFile(szWritableFile, + GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Trace("WriteFile: ERROR -> Unable to create file \"%s\".\n", + szWritableFile); + return FALSE; + } + + nStringLength = strlen(szString); + szPtr = (char*) szString; + + for (i = 0; i < nStringLength; i++) + { + bRc = WriteFile(hFile, szPtr++, 1, &dwBytesWritten, NULL); + if ((bRc == FALSE) || (dwBytesWritten != 1)) + { + bAllPassed = FALSE; + } + } + CloseHandle(hFile); + + if (bAllPassed == FALSE) + { + Trace ("WriteFile: ERROR: Failed to write data.\n"); + return FALSE; + } + else + { + return (validateResults(szString)); + } + + return TRUE; +} + + + + +int __cdecl main(int argc, char *argv[]) +{ + const char *pString = szStringTest; + BOOL bRc = FALSE; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + + bRc = writeTest(pString); + if (bRc != TRUE) + { + Fail("WriteFile: ERROR -> Failed\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test3/testinfo.dat new file mode 100644 index 0000000..e88e985 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test3/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = WriteFile +Name = Positive Test for WriteFile +Type = DEFAULT +EXE1 = writefile +Description +=Multiple consecutive writes to a file with verification + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test4/CMakeLists.txt new file mode 100644 index 0000000..68327e2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + writefile.cpp +) + +add_executable(paltest_writefile_test4 + ${SOURCES} +) + +add_dependencies(paltest_writefile_test4 coreclrpal) + +target_link_libraries(paltest_writefile_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test4/testinfo.dat new file mode 100644 index 0000000..87ddf9d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test4/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = WriteFile +Name = Positive Test for WriteFile +Type = DEFAULT +EXE1 = writefile +Description += writes to a file at different locations with verification + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test4/writefile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test4/writefile.cpp new file mode 100644 index 0000000..47a0066 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test4/writefile.cpp @@ -0,0 +1,155 @@ +// 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. + +/*===================================================================== +** +** Source: WriteFile.c (test 4) +** +** Purpose: Tests the PAL implementation of the WriteFile function. +** Performs multiple writes to a file at different locations +** then verifies the results with GetFileSize. +** +** dependency: +** CreateFile. +** GetFileSize. +** FlushFileBuffers +** SetFilePointer. +** CloseHandle. +** DeleteFile. +** +** +** +**===================================================================*/ + + +#include + +BOOL CleanUp(HANDLE hFile, const char * fileName) +{ + BOOL bRc = TRUE; + if (CloseHandle(hFile) != TRUE) + { + bRc = FALSE; + Trace("WriteFile: ERROR -> Unable to close file \"%s\"," + " error: %ld.\n", fileName, GetLastError()); + } + if (!DeleteFileA(fileName)) + { + bRc = FALSE; + Trace("WriteFile: ERROR -> Unable to delete file \"%s\"," + " error: %ld.\n", fileName, GetLastError()); + } + return bRc; +} + +int __cdecl main(int argc, char *argv[]) +{ + const char* szStringTest = "1234567890"; + const char* szWritableFile = "writeable.txt"; + HANDLE hFile = NULL; + DWORD dwBytesWritten; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create the test file */ + hFile = CreateFile(szWritableFile, + GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("WriteFile: ERROR -> Unable to create file \"%s\".\n", + szWritableFile); + } + + + /* test wtriting to the file */ + if( WriteFile(hFile, /* HANDLE handle to file */ + szStringTest, /* data buffer */ + strlen(szStringTest), /* number of bytes to write */ + &dwBytesWritten, /* number of bytes written */ + NULL) /* overlapped buffer */ + ==0) + { + Trace("WriteFile: ERROR -> Unable to write to file error: %ld \n", + GetLastError()); + CleanUp(hFile,szWritableFile); + Fail(""); + } + + if(!FlushFileBuffers(hFile)) + { Trace("WriteFile: ERROR -> Call to FlushFile Buffers failed " + "error %ld \n",GetLastError()); + CleanUp(hFile,szWritableFile); + Fail(""); + } + + /* check the file size */ + if(GetFileSize(hFile, NULL)!=strlen(szStringTest)) + { + Trace("WriteFile: ERROR -> writing %u chars to empty file " + "caused its size to become %u\n",strlen(szStringTest), + GetFileSize(hFile, NULL)); + CleanUp(hFile,szWritableFile); + Fail(""); + } + + /* test writing to the file at position 5. */ + SetFilePointer( + hFile, /* handle to file */ + 0x5, /* bytes to move pointer */ + NULL, /* bytes to move pointer */ + FILE_BEGIN /* starting point */ + ); + + + if( WriteFile(hFile, /* HANDLE handle to file */ + szStringTest, /* data buffer */ + strlen(szStringTest), /* number of bytes to write */ + &dwBytesWritten, /* number of bytes written */ + NULL) /* overlapped buffer */ + ==0) + { + Trace("WriteFile: ERROR -> Unable to write to file after " + " moiving the file poiner to 5 error: %ld \n", + GetLastError()); + CleanUp(hFile,szWritableFile); + Fail(""); + } + + + if(!FlushFileBuffers(hFile)) + { + Trace("WriteFile: ERROR -> Call to FlushFile Buffers failed " + "error %ld \n",GetLastError()); + CleanUp(hFile,szWritableFile); + Fail(""); + } + + /* Check the file size */ + if(GetFileSize(hFile, NULL)!=(strlen(szStringTest)+5)) + { + Trace("WriteFile: ERROR -> writing %u chars to the file after " + "sitting the file pointer to 5 resulted in wrong file size; " + "Expected %u resulted %u.",strlen(szStringTest), + (strlen(szStringTest)+5),GetFileSize(hFile, NULL)); + CleanUp(hFile,szWritableFile); + Fail(""); + } + + if (!CleanUp(hFile,szWritableFile)) + { + Fail(""); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test5/CMakeLists.txt new file mode 100644 index 0000000..dbb06dd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + writefile.cpp +) + +add_executable(paltest_writefile_test5 + ${SOURCES} +) + +add_dependencies(paltest_writefile_test5 coreclrpal) + +target_link_libraries(paltest_writefile_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test5/testinfo.dat new file mode 100644 index 0000000..ffde30e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test5/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = WriteFile +Name = Positive Test for WriteFile +Type = DEFAULT +EXE1 = writefile +Description += write lots of data to a file. then check with += GetFileSize += This test is disabled due to its time overhead. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test5/writefile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test5/writefile.cpp new file mode 100644 index 0000000..46920b3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/WriteFile/test5/writefile.cpp @@ -0,0 +1,117 @@ +// 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. + +/*===================================================================== +** +** Source: WriteFile.c (test 5) +** +** Purpose: Tests the PAL implementation of the WriteFile function. +** Performs writing a huge file. +** +** dependency: +** CreateFile. +** GetFileSize. +** FlushFileBuffers +** CloseHandle +** DeleteFile +** +** +**===================================================================*/ + + +#include + +BOOL CleanUp(HANDLE hFile, const char * fileName) +{ + BOOL bRc = TRUE; + if (CloseHandle(hFile) != TRUE) + { + bRc = FALSE; + Trace("WriteFile: ERROR -> Unable to close file \"%s\"," + " error: %ld.\n", fileName, GetLastError()); + } + if (!DeleteFileA(fileName)) + { + bRc = FALSE; + Trace("WriteFile: ERROR -> Unable to delete file \"%s\"," + " error: %ld.\n", fileName, GetLastError()); + } + return bRc; +} + + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE hFile = NULL; + DWORD dwBytesWritten; + const char* hugeStringTest = + "1234567890123456789012345678901234567890"; + const char* szWritableFile = "writeable.txt"; + int i =0; + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create the test file */ + hFile = CreateFile(szWritableFile, + GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + Fail("WriteFile: ERROR -> Unable to create file \"%s\".\n", + szWritableFile); + } + + /* write 4000 000 chars to the file.*/ + for (i=0; i<100000;i++) + { + if( WriteFile(hFile, /* HANDLE handle to file */ + hugeStringTest, /* data buffer */ + strlen(hugeStringTest), /* number of bytes to write */ + &dwBytesWritten, /* number of bytes written */ + NULL) /* overlapped buffer */ + ==0) + { + Trace("WriteFile: ERROR -> Unable to write to file error: %ld \n", + GetLastError()); + CleanUp(hFile,szWritableFile); + Fail(""); + + } + } + + if(!FlushFileBuffers(hFile)) + { + Trace("WriteFile: ERROR -> Call to FlushFileBuffers failed" + "error %ld \n",GetLastError()); + CleanUp(hFile,szWritableFile); + Fail(""); + } + + /* test if the size changed properly. */ + if(GetFileSize(hFile,NULL) != 4000000) + { + Trace("WriteFile: ERROR -> file size did not change properly" + " after writing 4000 000 chars to it ( size= %u )\n", + GetFileSize(hFile,NULL)); + CleanUp(hFile,szWritableFile); + Fail(""); + + } + + if (!CleanUp(hFile,szWritableFile)) + { + Fail(""); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/CMakeLists.txt new file mode 100644 index 0000000..f50f97a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_errorpathnotfound_test1 + ${SOURCES} +) + +add_dependencies(paltest_errorpathnotfound_test1 coreclrpal) + +target_link_libraries(paltest_errorpathnotfound_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.cpp new file mode 100644 index 0000000..eaf3db3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.cpp @@ -0,0 +1,783 @@ +// 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. + +/*===================================================================== + +** + +** Source: test1.c + +** + +** Purpose: Test the return value of GetLastError() after calling + +** some file_io functions with an invalid path. + +** + +** Functions covered by this test are: + +** CopyFileA, CopyFileW, CreateFileA,CreateFileW, + +** DeleteFileA and DeleteFileW. + +** +** + + + +** + +**===================================================================*/ + + + +#include + + + +int __cdecl main(int argc, char *argv[]) + +{ + + + + BOOL testPass = TRUE; + + BOOL bRc = TRUE; + + HANDLE hFile; + + + + const char* sBadFilePath = "bad/badPath.tmp"; + + const char* sBadFileName = "badName.tmp"; + + const char* sDest = "dest.tmp"; + + const WCHAR wBadFilePath[] = + + {'w','b','a','d','/','b','a', + + 'd','.','t','m','p','\0'}; + + const WCHAR wBadFileName[] = + + {'w','B','a','d','.','t','m','p','\0'}; + + const WCHAR wDest[] = + + {'w','d','e','s','t','.','t','m','p','\0'}; + + + + + + if (0 != PAL_Initialize(argc,argv)) + + { + + return FAIL; + + } + + + + /*...................Test CopyFileW.............................*/ + + + + /* test with an invalid path */ + + bRc = CopyFileW(wBadFilePath,wDest,TRUE); + + if(!bRc) + + { + + if(GetLastError()!= ERROR_PATH_NOT_FOUND) + + { + + Trace("CopyFileW: calling GetLastError() after copying a file" + + " with wrong path returned [%u] while it should return [%u]\n" + + ,GetLastError(), ERROR_PATH_NOT_FOUND); + + testPass = FALSE; + + } + + } + + else + + { + + testPass = FALSE; + + } + + + + /* test with invalid file name */ + + bRc = CopyFileW(wBadFileName,wDest,TRUE); + + if(!bRc) + + { + + if(GetLastError()!= ERROR_FILE_NOT_FOUND) + + { + + Trace("CopyFileW: calling GetLastError() after copying a file" + + " with wrong name returned [%u] while it should return [%u]\n" + + ,GetLastError(), ERROR_FILE_NOT_FOUND); + + testPass = FALSE; + + } + + + + } + + else + + { + + Trace("CopyFileW: managed to copy a file with wrong name\n"); + + testPass = FALSE; + + } + + + + + + + + /*..................CopyFileA...................................*/ + + + + /* test with an invalid path */ + + bRc = CopyFileA(sBadFilePath,sDest,TRUE); + + if(! bRc) + + { + + if(GetLastError()!= ERROR_PATH_NOT_FOUND) + + { + + Trace("CopyFileA: calling GetLastError() after copying a file" + + " with wrong path returned [%u] while it should return [%u]\n" + + ,GetLastError(), ERROR_PATH_NOT_FOUND); + + testPass = FALSE; + + } + + } + + else + + { + + Trace("CopyFileA: managed to copy a file with wrong path\n"); + + testPass = FALSE; + + } + + + + /* test with an invalid file name */ + + bRc = CopyFileA(sBadFileName,sDest,TRUE); + + if(! bRc) + + { + + if(GetLastError()!= ERROR_FILE_NOT_FOUND) + + { + + Trace("CopyFileA: calling GetLastError() after copying a file" + + " with wrong name returned [%u] while it should return [%u]\n" + + ,GetLastError(), ERROR_FILE_NOT_FOUND); + + testPass = FALSE; + + } + + } + + else + + { + + Trace("CopyFileA: managed to copy a file with wrong name\n"); + + testPass = FALSE; + + } + + + + + + + + /*............. Test CreateFileA..................................*/ + + + + /* test with an invalid file name */ + + hFile = CreateFileA(sBadFileName, + + GENERIC_READ, /* open for reading */ + + FILE_SHARE_READ, /* share for reading */ + + NULL, /* no security */ + + OPEN_EXISTING, /* existing file only */ + + FILE_ATTRIBUTE_NORMAL, /* normal file */ + + NULL); /* no attr. template */ + + + + if (hFile == INVALID_HANDLE_VALUE) + + { + + if(GetLastError() != ERROR_FILE_NOT_FOUND) + + { + + Trace("CreateFileA: calling GetLastError() returned [%u] " + + "while it should return [%u] for a bad File Name\n", + + GetLastError(),ERROR_FILE_NOT_FOUND); + + testPass = FALSE; + + } + + + + } + + else + + { + + Trace("CreateFileA: managed to create a file with an incorrect " + + "filename\n"); + + testPass = FALSE; + + + + if(!CloseHandle(hFile)) + + { + + Trace("CreateFileA: Call to CloseHandle failed with ErrorCode " + + "[%u]\n", GetLastError()); + + + + } + + if(!DeleteFile(sBadFileName)) + + { + + Trace("CreateFileA: Call to DeleteFile failed with ErrorCode " + + "[%u]\n", GetLastError()); + + } + + } + + + + /* test with an invalid path */ + + hFile = CreateFileA(sBadFilePath, + + GENERIC_READ, /* open for reading */ + + FILE_SHARE_READ, /* share for reading */ + + NULL, /* no security */ + + OPEN_EXISTING, /* existing file only */ + + FILE_ATTRIBUTE_NORMAL, /* normal file */ + + NULL); /* no attr. template */ + + + + if (hFile == INVALID_HANDLE_VALUE) + + { + + if(GetLastError() != ERROR_PATH_NOT_FOUND) + + { + + Trace("CreateFileA: calling GetLastError() returned [%u] " + + "while it should return [%u] for a bad file path name\n", + + GetLastError(), ERROR_PATH_NOT_FOUND); + + testPass = FALSE; + + } + + + + } + + else + + { + + Trace("CreateFileA: managed to create a file with an incorrect " + + "filename\n"); + + testPass = FALSE; + + /*this should not happen*/ + + if(!CloseHandle(hFile)) + + { + + Trace("CreateFileA: Call to CloseHandle Failed with ErrorCode " + + "[%u]\n", GetLastError()); + + + + } + + if(!DeleteFile(sBadFilePath)) + + { + + Trace("CreateFileA: Call to DeleteFile Failed with ErrorCode " + + "[%u]\n", GetLastError()); + + } + + } + + + + + + + + + + /*............. Test CreateFileW..................................*/ + + + + /* test with an invalid file name */ + + hFile = CreateFileW(wBadFileName, + + GENERIC_READ, /* open for reading */ + + FILE_SHARE_READ, /* share for reading */ + + NULL, /* no security */ + + OPEN_EXISTING, /* existing file only */ + + FILE_ATTRIBUTE_NORMAL, /* normal file */ + + NULL); /* no attr. template */ + + + + if (hFile == INVALID_HANDLE_VALUE) + + { + + if(GetLastError() != ERROR_FILE_NOT_FOUND) + + { + + Trace("CreateFileW: calling GetLastError() returned [%u] " + + "while it should return [%u] for a bad filename\n", + + GetLastError(), ERROR_FILE_NOT_FOUND); + + testPass = FALSE; + + } + + + + } + + else + + { + + Trace("CreateFileW: managed to create a file with an incorrect " + + "filename\n"); + + testPass = FALSE; + + + + if(!CloseHandle(hFile)) + + { + + Trace("CreateFileW: Call to CloseHandle Failed with ErrorCode " + + "[%u]\n", GetLastError()); + + + + } + + + + if(!DeleteFileW(wBadFileName)) + + { + + Trace("CreateFileW: Call to DeleteFile Failed with ErrorCode " + + "[%u]\n", GetLastError()); + + } + + } + + + + + + + + /* test with an invalid path */ + + hFile = CreateFileW(wBadFilePath, + + GENERIC_READ, /* open for reading */ + + FILE_SHARE_READ, /* share for reading */ + + NULL, /* no security */ + + OPEN_EXISTING, /* existing file only */ + + FILE_ATTRIBUTE_NORMAL, /* normal file */ + + NULL); /* no attr. template */ + + + + if (hFile == INVALID_HANDLE_VALUE) + + { + + + + if(GetLastError() != ERROR_PATH_NOT_FOUND) + + { + + Trace("CreateFileW: calling GetLastError() returned [%u] " + + "while it should return [%u] for a bad file path \n", + + GetLastError(), ERROR_FILE_NOT_FOUND); + + testPass = FALSE; + + } + + + + } + + else + + { + + Trace("CreateFileW: managed to create a file with an incorrect " + + "filename\n"); + + testPass = FALSE; + + + + if(!CloseHandle(hFile)) + + { + + Trace("CreateFileW: Call to CloseHandle Failed with ErrorCode " + + "[%u]\n", GetLastError()); + + + + } + + if(!DeleteFileW(wBadFilePath)) + + { + + Trace("CreateFileW: Call to DeleteFile Failed with ErrorCode " + + "[%u]\n", GetLastError()); + + } + + } + + + + + + + + /* ............. DeleteFileW..................................*/ + + + + /* test with an invalid path */ + + if(DeleteFileW(wBadFilePath)) + + { + + Trace("DeleteFileW: Call to DeleteFileW to delete a file" + + " that does not exist succeeded\n"); + + testPass = FALSE; + + + + } + + else + + { + + if(GetLastError() != ERROR_PATH_NOT_FOUND) + + { + + Trace("DeleteFileW: Call GetLastError()returned " + + "[%u] while it should return ERROR_PATH_NOT_FOUND [%u]\n", + + GetLastError(),ERROR_FILE_NOT_FOUND); + + testPass = FALSE; + + + + } + + + + } + + + + /* test with an invalid file name */ + + if(DeleteFileW(wBadFileName)) + + { + + Trace("DeleteFileW: Call to DeleteFileW to delete a file" + + " that does not exist succeeded\n"); + + testPass = FALSE; + + + + } + + else + + { + + if(GetLastError() != ERROR_FILE_NOT_FOUND) + + { + + Trace("DeleteFileW: Call GetLastError()returned [%u]" + + " while it should return ERROR_FILE_NOT_FOUND [%u]\n", + + GetLastError(),ERROR_FILE_NOT_FOUND); + + testPass = FALSE; + + + + } + + + + } + + + + + + /* ............. DeleteFileA..................................*/ + + + + /* test with an invalid path */ + + if(DeleteFileA(sBadFilePath)) + + { + + Trace("DeleteFileA: Call to DeleteFileA to delete a file" + + " that does not exist succeeded\n"); + + testPass = FALSE; + + + + } + + else + + { + + if(GetLastError() != ERROR_PATH_NOT_FOUND) + + { + + Trace("DeleteFileA: Call GetLastError() returned [%u]" + + " while it should return ERROR_PATH_NOT_FOUND [%u]\n", + + GetLastError(),ERROR_FILE_NOT_FOUND); + + testPass = FALSE; + + + + } + + + + } + + + + /* test with an invalid file name */ + + if(DeleteFileA(sBadFileName)) + + { + + Trace("DeleteFileA: Call to DeleteFileA to delete a file" + + " that does not exist succeeded\n"); + + testPass = FALSE; + + + + } + + else + + { + + if(GetLastError() != ERROR_FILE_NOT_FOUND) + + { + + Trace("DeleteFileA: Call GetLastError() returned [%u]" + + " while it should return ERROR_FILE_NOT_FOUND [%u]\n", + + GetLastError(),ERROR_FILE_NOT_FOUND); + + testPass = FALSE; + + + + } + + + + } + + + + + + + + if(! testPass) + + { + + Fail(""); + + } + + PAL_Terminate(); + + return PASS; + +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/testinfo.dat new file mode 100644 index 0000000..dc1ddc9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/testinfo.dat @@ -0,0 +1,31 @@ +# 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. + + + + +Version = 1.0 + +Section = file_io + +Function = some File_io functions + +Name = errorpathnotfound - checking GetLastError. + +Type = DEFAULT + +EXE1 = test1 + +Description + += Test the return value of GetLastError() after calling + += some file_io functions with an invalid path. + += Functions covered by this test are: + += CopyFile, CreateFile and DeleteFile. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/CMakeLists.txt new file mode 100644 index 0000000..277855a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_errorpathnotfound_test2 + ${SOURCES} +) + +add_dependencies(paltest_errorpathnotfound_test2 coreclrpal) + +target_link_libraries(paltest_errorpathnotfound_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/test2.cpp new file mode 100644 index 0000000..78f925e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/test2.cpp @@ -0,0 +1,526 @@ +// 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. + +/*===================================================================== + +** + +** Source: test2.c + +** + +** Purpose: Test the return value of GetLastError() after calling + +** some file_io functions with an invalid path. + +** + +** Functions covered by this test are: + +** FindFirstFileA, FindFirstFileW, + +** GetFileAttributesA, GetFileAttributesW, + +** +** + +** + + + +** + +**===================================================================*/ + + + +#include + + + +int __cdecl main(int argc, char *argv[]) + +{ + + + + BOOL testPass = TRUE; + + BOOL bRc = TRUE; + + HANDLE hFile; + + WIN32_FIND_DATA findFileData; + + WIN32_FIND_DATAW wFindFileData; + + DWORD fileAttrib; + + + + const char* sBadFilePath = "bad/badPath.tmp"; + + const char* sBadFileName = "badName.tmp"; + + + + const WCHAR wBadFilePath[] = + + {'w','b','a','d','/','b','a', + + 'd','.','t','m','p','\0'}; + + const WCHAR wBadFileName[] = + + {'w','B','a','d','.','t','m','p','\0'}; + + const WCHAR wDest[] = + + {'w','d','e','s','t','.','t','m','p','\0'}; + + + + + + if (0 != PAL_Initialize(argc,argv)) + + { + + return FAIL; + + } + + + + /*............. Test FindFirstFileA..................................*/ + + + + /* test with an invalid file name */ + + hFile = FindFirstFileA(sBadFileName,&findFileData ); + + + + if (hFile == INVALID_HANDLE_VALUE) + + { + + if(GetLastError() != ERROR_FILE_NOT_FOUND) + + { + + Trace("FindFirstFileA: calling GetLastError() returned [%u] " + + "while it should return [%u] for a bad File Name\n", + + GetLastError(),ERROR_FILE_NOT_FOUND); + + testPass = FALSE; + + } + + + + } + + else + + { + + Trace("FindFirstFileA: managed to find a file with an incorrect " + + "filename\n"); + + testPass = FALSE; + + + + if(!FindClose(hFile)) + + { + + Trace("FindFirstFileA: Call to FindClose failed with ErrorCode" + + " [%u]\n", GetLastError()); + + + + } + + + + } + + + + /* test with an invalid path */ + + hFile = FindFirstFileA(sBadFilePath,&findFileData); + + + + if (hFile == INVALID_HANDLE_VALUE) + + { + + if(GetLastError() != ERROR_PATH_NOT_FOUND) + + { + + Trace("FindFirstFileA: calling GetLastError() returned [%u] " + + "while it should return [%u] for a bad file path name\n", + + GetLastError(), ERROR_PATH_NOT_FOUND); + + testPass = FALSE; + + } + + + + } + + else + + { + + Trace("FindFirstFileA: managed to find a file with an incorrect" + + " filename\n"); + + testPass = FALSE; + + /*this should not happen*/ + + if(!FindClose(hFile)) + + { + + Trace("FindFirstFileA: Call to FindClose Failed with ErrorCode" + + " [%u]\n", GetLastError()); + + + + } + + + + } + + + + + + + + /*............. Test FindFirstFileW..................................*/ + + + + /* test with an invalid file name */ + + hFile = FindFirstFileW(wBadFileName,&wFindFileData ); + + + + if (hFile == INVALID_HANDLE_VALUE) + + { + + if(GetLastError() != ERROR_FILE_NOT_FOUND) + + { + + Trace("FindFirstFileW: calling GetLastError() returned [%u] " + + "while it should return [%u] for a bad File Name\n", + + GetLastError(),ERROR_FILE_NOT_FOUND); + + testPass = FALSE; + + } + + + + } + + else + + { + + Trace("FindFirstFileW: managed to find a file with an incorrect " + + "filename\n"); + + testPass = FALSE; + + + + if(!FindClose(hFile)) + + { + + Trace("FindFirstFileW: Call to FindClose failed with ErrorCode" + + " [%u]\n", GetLastError()); + + + + } + + + + } + + + + /* test with an invalid path */ + + hFile = FindFirstFileW(wBadFilePath,&wFindFileData); + + + + if (hFile == INVALID_HANDLE_VALUE) + + { + + if(GetLastError() != ERROR_PATH_NOT_FOUND) + + { + + Trace("FindFirstFileW: calling GetLastError() returned [%u] " + + "while it should return [%u] for a bad file path name\n", + + GetLastError(), ERROR_PATH_NOT_FOUND); + + testPass = FALSE; + + } + + + + } + + else + + { + + Trace("FindFirstFileW: managed to find a file with an incorrect " + + "filename\n"); + + testPass = FALSE; + + /*this should not happen*/ + + if(!FindClose(hFile)) + + { + + Trace("FindFirstFileW: Call to FindClose Failed with ErrorCode " + + "[%u]\n", GetLastError()); + + + + } + + + + } + + + + + + /*...................Test GetFileAttributesW.............................*/ + + + + /* test with an invalid path */ + + fileAttrib = GetFileAttributesW(wBadFilePath); + + if(fileAttrib == -1) + + { + + if(GetLastError()!= ERROR_PATH_NOT_FOUND) + + { + + Trace("GetFileAttributesW: calling GetLastError() after getting" + + " the attributes of a file with wrong path returned [%u]" + + " while it should return [%u]\n", + + GetLastError(), ERROR_PATH_NOT_FOUND); + + testPass = FALSE; + + } + + } + + else + + { + + Trace("GetFileAttributesW: managed to get the attrib of a file" + + " with wrong path\n"); + + testPass = FALSE; + + } + + + + /* test with invalid file name */ + + fileAttrib = GetFileAttributesW(wBadFileName); + + if(fileAttrib == -1) + + { + + if(GetLastError()!= ERROR_FILE_NOT_FOUND) + + { + + Trace("GetFileAttributesW: calling GetLastError() after getting" + + " the attributes of a file with wrong name returned [%u] " + + "while it should return [%u]\n" + + ,GetLastError(), ERROR_FILE_NOT_FOUND); + + testPass = FALSE; + + } + + } + + else + + { + + Trace("GetFileAttributesW: managed to get the attrib of a file" + + " with wrong name\n"); + + testPass = FALSE; + + } + + + + /*...................Test GetFileAttributesA.............................*/ + + + + /* test with an invalid path */ + + fileAttrib = GetFileAttributesA(sBadFilePath); + + if(fileAttrib == -1) + + { + + if(GetLastError()!= ERROR_PATH_NOT_FOUND) + + { + + Trace("GetFileAttributesA: calling GetLastError() after getting" + + " the attributes of a file with wrong path returned [%u] while" + + " it should return [%u]\n", + + GetLastError(), ERROR_PATH_NOT_FOUND); + + testPass = FALSE; + + } + + } + + else + + { + + Trace("GetFileAttributesA: managed to get the attrib of a file" + + " with wrong path\n"); + + testPass = FALSE; + + } + + + + /* test with invalid file name */ + + fileAttrib = GetFileAttributesA(sBadFileName); + + if(fileAttrib == -1) + + { + + if(GetLastError()!= ERROR_FILE_NOT_FOUND) + + { + + Trace("GetFileAttributesA: calling GetLastError() after getting " + + "the attributes of a file with wrong name returned [%u] " + + "while it should return [%u]\n" + + ,GetLastError(), ERROR_FILE_NOT_FOUND); + + testPass = FALSE; + + } + + + + } + + else + + { + + Trace("GetFileAttributesA: managed to get the attrib of a file with" + + " wrong name\n"); + + testPass = FALSE; + + } + + + if(! testPass) + + { + + Fail(""); + + } + + PAL_Terminate(); + + return PASS; + +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/testinfo.dat new file mode 100644 index 0000000..0b0449f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/testinfo.dat @@ -0,0 +1,32 @@ +# 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. + + + +Version = 1.0 + +Section = file_io + +Function = some File_io functions + +Name = errorpathnotfound - checking GetLastError. + +Type = DEFAULT + +EXE1 = test2 + +Description + += Test the return value of GetLastError() after calling + += some file_io functions with an invalid path. + += Functions covered by this test are: + += FindFirstFileA, FindFirstFileW, + += GetFileAttributesA, GetFileAttributesW, + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/test1/CMakeLists.txt new file mode 100644 index 0000000..6b8473a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + gettemppatha.cpp +) + +add_executable(paltest_gettemppatha_test1 + ${SOURCES} +) + +add_dependencies(paltest_gettemppatha_test1 coreclrpal) + +target_link_libraries(paltest_gettemppatha_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/test1/gettemppatha.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/test1/gettemppatha.cpp new file mode 100644 index 0000000..b0da528 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/test1/gettemppatha.cpp @@ -0,0 +1,103 @@ +// 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. + +/*===================================================================== +** +** Source: gettemppatha.c (test 1) +** +** Purpose: Tests the PAL implementation of the GetTempPathA function. +** +** +**===================================================================*/ + +#include + +static void SetTmpDir(CHAR path[]) +{ + DWORD result = SetEnvironmentVariableA("TMPDIR", path); + if (!result) + { + Fail("ERROR -> SetEnvironmentVariableA failed with result %d and error code %d.\n", + result, GetLastError()); + } +} + +static void SetAndCompare(CHAR tmpDirPath[], CHAR expected[]) +{ + DWORD dwBufferLength = _MAX_DIR; + CHAR path[dwBufferLength]; + + SetTmpDir(tmpDirPath); + + DWORD dwResultLen = GetTempPathA(dwBufferLength, path); + if (dwResultLen <= 0) + { + Fail("ERROR: GetTempPathA returned %d with error code %d.\n", dwResultLen, GetLastError()); + } + if (dwResultLen >= dwBufferLength) + { + Fail("ERROR: Buffer of length %d passed to GetTempPathA was too small to hold %d chars..\n", dwBufferLength, dwResultLen); + } + if (strcmp(expected, path) != 0) + { + Fail("ERROR: GetTempPathA expected to get '%s' but instead got '%s'.\n", expected, path); + } + if (expected[dwResultLen - 1] != '/') + { + Fail("ERROR: GetTempPathA returned '%s', which should have ended in '/'.\n", path); + } +} + +static void SetAndCheckLength(CHAR tmpDirPath[], int bufferLength, int expectedResultLength) +{ + CHAR path[bufferLength]; + + SetTmpDir(tmpDirPath); + DWORD dwResultLen = GetTempPathA(bufferLength, path); + + if (dwResultLen != expectedResultLength) + { + Fail("GetTempPathA(%d, %s) expected to return %d but returned %d.\n", + bufferLength, tmpDirPath?tmpDirPath:"NULL", expectedResultLength, dwResultLen); + } +} + +int __cdecl main(int argc, char *argv[]) +{ + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + SetAndCompare("/tmp", "/tmp/"); + SetAndCompare("/tmp/", "/tmp/"); + SetAndCompare("", "/tmp/"); + SetAndCompare(NULL, "/tmp/"); + SetAndCompare("/", "/"); + SetAndCompare("/var/tmp", "/var/tmp/"); + SetAndCompare("/var/tmp/", "/var/tmp/"); + SetAndCompare("~", "~/"); + SetAndCompare("~/", "~/"); + SetAndCompare(".tmp", ".tmp/"); + SetAndCompare("./tmp", "./tmp/"); + SetAndCompare("/home/someuser/sometempdir", "/home/someuser/sometempdir/"); + SetAndCompare(NULL, "/tmp/"); + + DWORD dwResultLen = GetTempPathA(0, NULL); + if (dwResultLen != 0 || GetLastError() != ERROR_INVALID_PARAMETER) + { + Fail("GetTempPath(NULL, ...) returned %d with error code %d but " + "should have failed with ERROR_INVALID_PARAMETER (%d).\n", + dwResultLen, GetLastError(), ERROR_INVALID_PARAMETER); + } + + SetAndCheckLength("abc/", 5, 4); + SetAndCheckLength("abcd", 5, 6); + SetAndCheckLength("abcde", 5, 7); + SetAndCheckLength("abcdef/", 5, 9); + SetAndCheckLength(NULL, 5, 6); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/test1/testinfo.dat new file mode 100644 index 0000000..71f8bef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/file_io/gettemppatha/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = file_io +Function = GetTempPathA +Name = Test for GetTempPathA (test 1) +Type = DEFAULT +EXE1 = gettemppatha +Description += Calls GetTempPathA and verifies by passing the returned += value to CreateDirectoryA. If the returned path exists, += CreateDirectoryA will fail. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt new file mode 100644 index 0000000..90da8e5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt @@ -0,0 +1,18 @@ +add_subdirectory(CreateFileMappingA) +add_subdirectory(CreateFileMappingW) +add_subdirectory(FreeLibrary) +add_subdirectory(FreeLibraryAndExitThread) +add_subdirectory(GetModuleFileNameA) +add_subdirectory(GetModuleFileNameW) +add_subdirectory(GetProcAddress) +add_subdirectory(LocalAlloc) +add_subdirectory(LocalFree) +add_subdirectory(MapViewOfFile) +add_subdirectory(OpenFileMappingA) +add_subdirectory(OpenFileMappingW) +add_subdirectory(ProbeMemory) +add_subdirectory(UnmapViewOfFile) +add_subdirectory(VirtualAlloc) +add_subdirectory(VirtualFree) +add_subdirectory(VirtualProtect) +add_subdirectory(VirtualQuery) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/CMakeLists.txt new file mode 100644 index 0000000..6d92806 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/CMakeLists.txt @@ -0,0 +1,9 @@ +add_subdirectory(test1) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CMakeLists.txt new file mode 100644 index 0000000..d7d1892 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateFileMapping.cpp +) + +add_executable(paltest_createfilemappinga_test1 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappinga_test1 coreclrpal) + +target_link_libraries(paltest_createfilemappinga_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CreateFileMapping.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CreateFileMapping.cpp new file mode 100644 index 0000000..91640bf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CreateFileMapping.cpp @@ -0,0 +1,173 @@ +// 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. + +/*============================================================= +** +** Source: createfilemapping.c (test 1) +** +** Purpose: Positive test the CreateFileMapping API. +** Call CreateFileMapping with access PAGE_READONLY. +** +** +**============================================================*/ +#include + +const int MAPPINGSIZE = 2048; + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE hFile; + char buf[] = "this is a test string"; + char ch[2048]; + char lpFileName[] = "test.tmp"; + DWORD dwBytesWritten; + BOOL err; + int RetVal = PASS; + + HANDLE hFileMapping; + LPVOID lpMapViewAddress; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a file handle with CreateFile. + */ + hFile = CreateFile( lpFileName, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), + lpFileName); + } + + /* Initialize the buffers. + */ + memset(ch, 0, MAPPINGSIZE); + + /* Write to the File handle. + */ + err = WriteFile(hFile, + buf, + strlen(buf), + &dwBytesWritten, + NULL); + + if (err == FALSE) + { + Trace("ERROR: %u :unable to write to file handle " + "hFile=0x%lx\n", + GetLastError(), + hFile); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Flush to the hard-drive. + */ + FlushFileBuffers(hFile); + + /* Create a unnamed file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_READONLY, /*read and wite*/ + 0, /*high-order size*/ + 0, /*low-order size*/ + NULL); /*unnamed object*/ + + if(NULL == hFileMapping) + { + Trace("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpOne; + } + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_READ, /* access code */ + 0, /*high order offset*/ + 0, /*low order offset*/ + 0); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Copy the MapViewOfFile to buffer, so we can + * compare with value read from file directly. + */ + memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE); + if (memcmp(ch, buf, strlen(buf))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + ch, buf); + RetVal = FAIL; + goto CleanUpThree; + } + +CleanUpThree: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Close Handle to opend file mapping. + */ + if ( CloseHandle(hFileMapping) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFileMapping); + RetVal = FAIL; + } + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(hFile) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFile); + RetVal = FAIL; + } + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/testinfo.dat new file mode 100644 index 0000000..36ff323 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMapping +Name = CreateFileMappingA with PAGE_READONLY +TYPE = DEFAULT +EXE1 = createfilemapping +Description +=Test the CreateFileMapping to create a named file-mapping object +=and with PAGE_READONLY protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CMakeLists.txt new file mode 100644 index 0000000..25877fb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateFileMapping.cpp +) + +add_executable(paltest_createfilemappinga_test3 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappinga_test3 coreclrpal) + +target_link_libraries(paltest_createfilemappinga_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CreateFileMapping.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CreateFileMapping.cpp new file mode 100644 index 0000000..2a849d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CreateFileMapping.cpp @@ -0,0 +1,155 @@ +// 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. + +/*============================================================= +** +** Source: createfilemapping.c (test 3) +** +** Purpose: Positive test the CreateFileMapping API. +** Call CreateFileMapping with access PAGE_READWRITE. +** +** +**============================================================*/ +#include + +const int MAPPINGSIZE = 2048; + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE hFile; + char buf[] = "this is a test string"; + char ch[2048]; + char lpFileName[] = "test.tmp"; + HANDLE hFileMapping; + LPVOID lpMapViewAddress; + int RetVal = PASS; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a file handle with CreateFile. + */ + hFile = CreateFile( lpFileName, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), + lpFileName); + } + + /* Initialize the buffers. + */ + memset(ch, 0, MAPPINGSIZE); + + /* Create a unnamed file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read and wite*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + NULL); /*unnamed object*/ + + if(NULL == hFileMapping) + { + Trace("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpOne; + } + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_ALL_ACCESS, /* access code */ + 0, /*high order offset*/ + 0, /*low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Write to the Map view. + */ + memcpy(lpMapViewAddress, buf, strlen(buf)); + + /* Read from the Map view. + */ + memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE); + + /* Copy the MapViewOfFile to buffer, so we can + * compare with value read from file directly. + */ + if (memcmp(ch, buf, strlen(buf))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + ch, buf); + RetVal = FAIL; + goto CleanUpThree; + } + +CleanUpThree: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Close Handle to opend file mapping. + */ + if ( CloseHandle(hFileMapping) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFileMapping); + RetVal = FAIL; + } + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(hFile) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFile); + RetVal = FAIL; + } + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/testinfo.dat new file mode 100644 index 0000000..4689ee6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMapping +Name = CreateFileMappingA with PAGE_READWRITE +TYPE = DEFAULT +EXE1 = createfilemapping +Description +=Test the CreateFileMapping to create a unnamed file-mapping object +=and with PAGE_READWRITE protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CMakeLists.txt new file mode 100644 index 0000000..566abe3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateFileMapping.cpp +) + +add_executable(paltest_createfilemappinga_test4 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappinga_test4 coreclrpal) + +target_link_libraries(paltest_createfilemappinga_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CreateFileMapping.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CreateFileMapping.cpp new file mode 100644 index 0000000..64caa88 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CreateFileMapping.cpp @@ -0,0 +1,181 @@ +// 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. + +/*============================================================= +** +** Source: createfilemapping.c (test 4) +** +** Purpose: Positive test the CreateFileMapping API. +** Call CreateFileMapping with access PAGE_WRITECOPY. +** +** +**============================================================*/ +#include + +const int MAPPINGSIZE = 2048; + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE hFile; + char buf[] = "this is a test string"; + char ch[2048]; + char lpFileName[] = "test.tmp"; + HANDLE hFileMapping; + LPVOID lpMapViewAddress; + int RetVal = PASS; + int err; + DWORD dwBytesWritten; + + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a file handle with CreateFile. + */ + hFile = CreateFile( lpFileName, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), + lpFileName); + } + + /* Write to the File handle. + */ + err = WriteFile(hFile, + buf, + strlen(buf), + &dwBytesWritten, + NULL); + + if (err == FALSE) + { + Trace("ERROR: %u :unable to write to file handle " + "hFile=0x%lx\n", + GetLastError(), + hFile); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Flush to the hard-drive. + */ + FlushFileBuffers(hFile); + + /* Initialize the buffers. + */ + memset(ch, 0, MAPPINGSIZE); + + /* Create a unnamed file-mapping object with file handle FileHandle + * and with PAGE_WRITECOPY protection. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_WRITECOPY, /*write copy*/ + 0, /*high-order size*/ + 0, /*low-order size*/ + NULL); /*unnamed object*/ + + if(NULL == hFileMapping) + { + Trace("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpOne; + } + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_COPY, /* access code */ + 0, /* high order offset*/ + 0, /* low order offset*/ + 0); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Write to the Map view.3 + */ + memcpy(lpMapViewAddress, buf, strlen(buf)); + + /* Read from the Map view. + */ + memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE); + + /* Copy the MapViewOfFile to buffer, so we can + * compare with value read from file directly. + */ + if (memcmp(ch, buf, strlen(buf))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + ch, buf); + RetVal = FAIL; + goto CleanUpThree; + } + +CleanUpThree: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Close Handle to opend file mapping. + */ + if ( CloseHandle(hFileMapping) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFileMapping); + RetVal = FAIL; + } + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(hFile) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFile); + RetVal = FAIL; + } + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/testinfo.dat new file mode 100644 index 0000000..7d9dda1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMapping +Name = CreateFileMappingA with PAGE_WRITECOPY. +TYPE = DEFAULT +EXE1 = createfilemapping +Description += Positive test the CreateFileMapping API. += Call CreateFileMapping with access PAGE_WRITECOPY. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CMakeLists.txt new file mode 100644 index 0000000..4cd4053 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateFileMapping.cpp +) + +add_executable(paltest_createfilemappinga_test5 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappinga_test5 coreclrpal) + +target_link_libraries(paltest_createfilemappinga_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CreateFileMapping.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CreateFileMapping.cpp new file mode 100644 index 0000000..c7f9918 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CreateFileMapping.cpp @@ -0,0 +1,193 @@ +// 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. + +/*============================================================= +** +** Source: createfilemapping.c (test 5) +** +** Purpose: Positive test the CreateFileMapping API. +** Test CreateFileMapping to a "swap" handle with +** access PAGE_READONLY. +** +** +**============================================================*/ +#include + +const int MAPPINGSIZE = 2048; +HANDLE SWAP_HANDLE = ((VOID *)(-1)); + +int __cdecl main(int argc, char *argv[]) +{ + char testString[] = "this is a test string"; + char lpObjectName[] = "myMappingObject"; + int RetVal = FAIL; + char results[2048]; + + HANDLE hFileMapRO; + HANDLE hFileMapRW; + LPVOID lpMapViewRO; + LPVOID lpMapViewRW; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Initialize the buffers. + */ + memset(results, 0, MAPPINGSIZE); + + /* Create a named file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapRW = CreateFileMapping( + SWAP_HANDLE, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read only*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + lpObjectName); /*named object*/ + + if(NULL == hFileMapRW) + { + Fail("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + } + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewRW = MapViewOfFile( + hFileMapRW, + FILE_MAP_ALL_ACCESS, /* access code */ + 0, /* high order offset*/ + 0, /* low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewRW) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpOne; + } + + + hFileMapRO = CreateFileMapping( + SWAP_HANDLE, + NULL, /*not inherited*/ + PAGE_READONLY, /*read and write*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + lpObjectName); /*named object*/ + + if(NULL == hFileMapRO) + { + Trace("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewRO = MapViewOfFile( + hFileMapRO, + FILE_MAP_READ, /* access code */ + 0, /* high order offset*/ + 0, /* low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewRO) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpThree; + } + + /* Write the test string to the Map view. + */ + memcpy(lpMapViewRW, testString, strlen(testString)); + + /* Read from the second Map view. + */ + memcpy(results, (LPCSTR)lpMapViewRO, MAPPINGSIZE); + + /* Verify the contents of the file mapping, + * by comparing what was written to what was read. + */ + if (memcmp(results, testString, strlen(testString))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + results, + testString); + RetVal = FAIL; + goto CleanUpFour; + } + + /* Test was successful. + */ + RetVal = PASS; + +CleanUpFour: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewRO) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewRO); + RetVal = FAIL; + } + +CleanUpThree: + + /* Close Handle to opend file mapping. + */ + if ( CloseHandle(hFileMapRO) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFileMapRO); + RetVal = FAIL; + } + + +CleanUpTwo: + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewRW) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewRW); + RetVal = FAIL; + } + + +CleanUpOne: + + /* Close Handle to opend file mapping. + */ + if ( CloseHandle(hFileMapRW) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFileMapRW); + RetVal = FAIL; + } + + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/testinfo.dat new file mode 100644 index 0000000..137db9d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMapping +Name = CreateFileMappingA - with PAGE_READWRITE and INVALID_HANDLE_VALUE file handle +TYPE = DEFAULT +EXE1 = createfilemapping +Description +=Test the CreateFileMapping to create a unnamed file-mapping object +=and with PAGE_READWRITE protection by passing INVALID_HANDLE_VALUE +=file handle diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CMakeLists.txt new file mode 100644 index 0000000..89d25f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateFileMapping.cpp +) + +add_executable(paltest_createfilemappinga_test6 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappinga_test6 coreclrpal) + +target_link_libraries(paltest_createfilemappinga_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CreateFileMapping.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CreateFileMapping.cpp new file mode 100644 index 0000000..6445295 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CreateFileMapping.cpp @@ -0,0 +1,164 @@ +// 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. + +/*============================================================= +** +** Source: createfilemapping.c (test 6) +** +** Purpose: Positive test the CreateFileMapping API. +** Test CreateFileMapping to a "swap" handle with +** access PAGE_READWRITE. +** +** +**============================================================*/ +#include + +const int MAPPINGSIZE = 2048; +HANDLE SWAP_HANDLE = ((VOID *)(-1)); + +int __cdecl main(int argc, char *argv[]) +{ + char testString[] = "this is a test string"; + char lpObjectName[] = "myMappingObject"; + char results[2048]; + int RetVal = PASS; + + HANDLE hFileMapRW; + LPVOID lpMapViewRW; + LPVOID lpMapViewRW2; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Initialize the buffers. + */ + memset(results, 0, MAPPINGSIZE); + + /* Create a named file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapRW = CreateFileMapping( + SWAP_HANDLE, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read write*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + lpObjectName); /*unnamed object*/ + + if(NULL == hFileMapRW) + { + Fail("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + } + + /* Create a map view of the READWRITE file mapping. + */ + lpMapViewRW = MapViewOfFile( + hFileMapRW, + FILE_MAP_ALL_ACCESS,/* access code */ + 0, /* high order offset*/ + 0, /* low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewRW) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpOne; + } + + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewRW2 = MapViewOfFile( + hFileMapRW, + FILE_MAP_ALL_ACCESS, /* access code */ + 0, /* high order offset*/ + 0, /* low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewRW2) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Write the test string to the Map view. + */ + memcpy(lpMapViewRW, testString, strlen(testString)); + + /* Read from the second Map view. + */ + memcpy(results, (LPCSTR)lpMapViewRW2, MAPPINGSIZE); + + /* Verify the contents of the file mapping, + * by comparing what was written to what was read. + */ + if (memcmp(results, testString, strlen(testString))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + results, + testString); + RetVal = FAIL; + goto CleanUpThree; + } + + /* Test successful. + */ + RetVal = PASS; + +CleanUpThree: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewRW2) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewRW2); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewRW) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewRW); + RetVal = FAIL; + } + + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(hFileMapRW) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFileMapRW); + RetVal = FAIL; + } + + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/testinfo.dat new file mode 100644 index 0000000..d088c5d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMapping +Name = CreateFileMappingA - with PAGE_READONLY +TYPE = DEFAULT +EXE1 = createfilemapping +Description +=Test the CreateFileMapping to create a named file-mapping object +=and with PAGE_READONLY protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/CMakeLists.txt new file mode 100644 index 0000000..ea2e756 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + createfilemapping.cpp +) + +add_executable(paltest_createfilemappinga_test7 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappinga_test7 coreclrpal) + +target_link_libraries(paltest_createfilemappinga_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/createfilemapping.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/createfilemapping.cpp new file mode 100644 index 0000000..7cef9dd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/createfilemapping.cpp @@ -0,0 +1,164 @@ +// 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. + +/*============================================================= +** +** Source: createfilemapping.c (test 7) +** +** Purpose: Positive test the CreateFileMapping API. +** Test CreateFileMapping to a "swap" handle with +** access PAGE_READWRITE. +** +** +**============================================================*/ +#include + +const int MAPPINGSIZE = 2048; +HANDLE SWAP_HANDLE = ((VOID *)(-1)); + +int __cdecl main(int argc, char *argv[]) +{ + char testString[] = "this is a test string"; + char lpObjectName[] = "myMappingObject"; + char results[2048]; + int RetVal = PASS; + + HANDLE hFileMapRW; + LPVOID lpMapViewRW; + LPVOID lpMapViewRO; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Initialize the buffers. + */ + memset(results, 0, MAPPINGSIZE); + + /* Create a named file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapRW = CreateFileMapping( + SWAP_HANDLE, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read write*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + lpObjectName); /*unnamed object*/ + + if(NULL == hFileMapRW) + { + Fail("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + } + + /* Create a map view to the READWRITE file mapping. + */ + lpMapViewRW = MapViewOfFile( + hFileMapRW, + FILE_MAP_ALL_ACCESS,/* access code */ + 0, /* high order offset*/ + 0, /* low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewRW) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpOne; + } + + + /* Create a map view to the READWRITE file mapping. + */ + lpMapViewRO = MapViewOfFile( + hFileMapRW, + FILE_MAP_READ, /* access code */ + 0, /* high order offset*/ + 0, /* low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewRO) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Write the test string to the Map view. + */ + memcpy(lpMapViewRW, testString, strlen(testString)); + + /* Read from the second Map view. + */ + memcpy(results, (LPCSTR)lpMapViewRO, MAPPINGSIZE); + + /* Verify the contents of the file mapping, + * by comparing what was written to what was read. + */ + if (memcmp(results, testString, strlen(testString))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + results, + testString); + RetVal = FAIL; + goto CleanUpThree; + } + + /* Test successful. + */ + RetVal = PASS; + +CleanUpThree: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewRO) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewRO); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewRW) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewRW); + RetVal = FAIL; + } + + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(hFileMapRW) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFileMapRW); + RetVal = FAIL; + } + + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/testinfo.dat new file mode 100644 index 0000000..c03d98a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMapping +Name = CreateFileMappingA - with PAGE_COPYWRITE +TYPE = DEFAULT +EXE1 = createfilemapping +Description +=Test the CreateFileMapping to create a named file-mapping object +=and with PAGE_READONLY protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/CMakeLists.txt new file mode 100644 index 0000000..93d8a02 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + createfilemapping.cpp +) + +add_executable(paltest_createfilemappinga_test8 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappinga_test8 coreclrpal) + +target_link_libraries(paltest_createfilemappinga_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/createfilemapping.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/createfilemapping.cpp new file mode 100644 index 0000000..02b2fb5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/createfilemapping.cpp @@ -0,0 +1,79 @@ +// 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. + +/*============================================================= +** +** Source: createfilemapping.c (test 8) +** +** Purpose: Positive test the CreateFileMapping API. +** Test the un-verifiable parameter combinations. +** +** +**============================================================*/ +#include + +const int MAPPINGSIZE = 2048; +HANDLE SWAP_HANDLE = ((VOID *)(-1)); + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFileMap; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a READONLY, "swap", un-named file mapping. + * This test is unverifiable since there is no hook back to the file map + * because it is un-named. As well, since it resides in "swap", and is + * initialized to zero, there is nothing to read. + */ + hFileMap = CreateFileMapping( + SWAP_HANDLE, + NULL, /*not inherited*/ + PAGE_READONLY, /*read only*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + NULL); /*un-named object*/ + + if(NULL == hFileMap) + { + Fail("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + } + + + /* Create a COPYWRITE, "swap", un-named file mapping. + * This test is unverifiable, here is a quote from MSDN: + * + * Copy on write access. If you create the map with PAGE_WRITECOPY and + * the view with FILE_MAP_COPY, you will receive a view to file. If you + * write to it, the pages are automatically swappable and the modifications + * you make will not go to the original data file. + * + */ + hFileMap = CreateFileMapping( + SWAP_HANDLE, + NULL, /*not inherited*/ + PAGE_WRITECOPY, /*read only*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + NULL); /*unnamed object*/ + + if(NULL == hFileMap) + { + Fail("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + } + + + /* Terminate the PAL. + */ + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/testinfo.dat new file mode 100644 index 0000000..ebe138f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMapping +Name = CreateFileMappingA - unnamed swap, READWRITE. +TYPE = DEFAULT +EXE1 = createfilemapping +Description += Positive test the CreateFileMapping API. += Test an unnamed File Mapping to a "swap" += handle with access PAGE_READWRITE. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/CMakeLists.txt new file mode 100644 index 0000000..8932cad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + createfilemapping.cpp +) + +add_executable(paltest_createfilemappinga_test9 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappinga_test9 coreclrpal) + +target_link_libraries(paltest_createfilemappinga_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/createfilemapping.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/createfilemapping.cpp new file mode 100644 index 0000000..9224c22 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/createfilemapping.cpp @@ -0,0 +1,150 @@ +// 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. + +/*============================================================= +** +** Source: createfilemapping.c (test 9) +** +** Purpose: Negative test the CreateFileMapping API. +** +** +**============================================================*/ +#include + +const int MAPPINGSIZE = 2048; + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE hFile; + char lpFileName[] = "test.tmp"; + + HANDLE hFileMapping; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a file handle with CreateFile, as READONLY + */ + hFile = CreateFile( lpFileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), + lpFileName); + } + + /* Attempt to create a unnamed file-mapping object to a READONLY file + * as READWRITE access. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read and write*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + NULL); /*unnamed object*/ + + if(NULL != hFileMapping) + { + Trace("ERROR: Able to create READWRITE mapping to a " + "READONLY file.\n" ); + if( 0 == CloseHandle(hFile) ) + { + Trace("Unexpected Error: Unable to close file handle\n"); + } + Fail(""); + } + + /* Attempt to create a unnamed file-mapping object to a zero lenght + * file. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read and write*/ + 0, /*high-order size*/ + 0, /*low-order size*/ + NULL); /*unnamed object*/ + + if( NULL != hFileMapping ) + { + Trace("ERROR: Able to create READWRITE mapping to a " + "READONLY file.\n" ); + if( 0 == CloseHandle(hFile) ) + { + Trace("Unexpected Error: Unable to close file handle\n"); + } + Fail(""); + } + if(GetLastError() != ERROR_ACCESS_DENIED) + { + Trace("ERROR: Expected GetLastError() to return " + "ERROR_FILE_INVALID (%d), it returned %u.\n", + ERROR_FILE_INVALID, + GetLastError()); + if( 0 == CloseHandle(hFile) ) + { + Trace("Unexpected Error: Unable to close file handle\n"); + } + Fail(""); + } + + /* Attempt to create a file mapping that is larger than + * the file. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_READONLY, /*read only*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + NULL); /*unnamed object*/ + if(NULL != hFileMapping) + { + Trace("ERROR: Able to create file mapping of size %d to " + "file of size 0.\n", + MAPPINGSIZE); + if( 0 == CloseHandle(hFile) ) + { + Trace("Unexpected Error: Unable to close file handle\n"); + } + Fail(""); + } + + if(GetLastError() != ERROR_NOT_ENOUGH_MEMORY ) + { + Trace("ERROR: Expected GetLastError() to return " + "ERROR_NOT_ENOUGH_MEMORY (%d), it returned %u.\n", + ERROR_NOT_ENOUGH_MEMORY, + GetLastError()); + if( 0 == CloseHandle(hFile) ) + { + Trace("Unexpected Error: Unable to close file handle\n"); + } + Fail(""); + } + + if( 0 == CloseHandle(hFile) ) + { + Fail("Unexpected Error: Unable to close file handle\n"); + } + + /* Terminate the PAL. + */ + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/testinfo.dat new file mode 100644 index 0000000..11cbedc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMapping +Name = CreateFileMappingA negative testing +TYPE = DEFAULT +EXE1 = createfilemapping +Description += Negative test the CreateFileMapping API. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CMakeLists.txt new file mode 100644 index 0000000..c959909 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CMakeLists.txt @@ -0,0 +1,14 @@ +add_subdirectory(CreateFileMapping_neg1) +add_subdirectory(test1) + +# TODO: make this test compile +# add_subdirectory(test2) + +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CMakeLists.txt new file mode 100644 index 0000000..8e106a7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateFileMapping_neg.cpp +) + +add_executable(paltest_createfilemappingw_createfilemapping_neg1 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappingw_createfilemapping_neg1 coreclrpal) + +target_link_libraries(paltest_createfilemappingw_createfilemapping_neg1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CreateFileMapping_neg.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CreateFileMapping_neg.cpp new file mode 100644 index 0000000..8cf79b3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CreateFileMapping_neg.cpp @@ -0,0 +1,93 @@ +// 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. + +/*============================================================= +** +** Source: createfilemapping_neg.c +** +** Purpose: Negative test the CreateFileMapping API. +** Call CreateFileMapping to create a unnamed +** file-mapping object with PAGE_READONLY +** protection and try to map a zero length file +** in UNICODE +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE FileHandle; + HANDLE FileMappingHandle; + int err; + WCHAR *lpFileName = NULL; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //conver string to a unicode one + lpFileName = convert("temp.txt"); + + + //create a file and return the file handle + FileHandle = CreateFile(lpFileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_ARCHIVE, + NULL); + + //free this memory + free(lpFileName); + + if(INVALID_HANDLE_VALUE == FileHandle) + { + Fail("Failed to call CreateFile to create a file\n"); + } + + //create a unnamed file-mapping object with file handle FileHandle + //and with PAGE_READONLY protection + //try to map a file which is zero length. + FileMappingHandle = CreateFileMapping( + FileHandle, //File Handle + NULL, //not inherited + PAGE_READONLY, //access protection + 0, //high-order of object size + 0, //low-orger of object size + NULL); //unnamed object + + + if(NULL != FileMappingHandle || ERROR_FILE_INVALID != GetLastError()) + {//no error occurred + Trace("\nFailed to call CreateFileMapping API for a negative test!\n"); + err = CloseHandle(FileHandle); + if(0 == err) + { + Fail("\nFailed to call CloseHandle API\n"); + } + err = CloseHandle(FileMappingHandle); + if(0 == err) + { + Fail("\nFailed to call CloseHandle API\n"); + } + Fail(""); + } + + //close the file handle + err = CloseHandle(FileHandle); + if(0 == err) + { + Fail("\nFailed to call CloseHandle API\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/testinfo.dat new file mode 100644 index 0000000..a09487d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMapping +Name = Negative test for CreateFileMappingW - with a zero length file +TYPE = DEFAULT +EXE1 = createfilemapping_neg +Description +=Test the CreateFileMapping to try to map a zero length file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CMakeLists.txt new file mode 100644 index 0000000..decb999 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateFileMappingW.cpp +) + +add_executable(paltest_createfilemappingw_test1 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappingw_test1 coreclrpal) + +target_link_libraries(paltest_createfilemappingw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CreateFileMappingW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CreateFileMappingW.cpp new file mode 100644 index 0000000..4263a3a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CreateFileMappingW.cpp @@ -0,0 +1,174 @@ +// 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. + +/*============================================================= +** +** Source: createfilemappingw.c (test 1) +** +** Purpose: Positive test the CreateFileMappingW API. +** Call CreateFileMappingW with access PAGE_READONLY. +** +** +**============================================================*/ +#define UNICODE +#include + +const int MAPPINGSIZE = 2048; + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE hFile; + char buf[] = "this is a test string"; + char ch[2048]; + WCHAR lpFileName[] = {'t','e','s','t','.','t','m','p','\0'}; + DWORD dwBytesWritten; + BOOL err; + int RetVal = PASS; + + HANDLE hFileMapping; + LPVOID lpMapViewAddress; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a file handle with CreateFile. + */ + hFile = CreateFile( lpFileName, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), + lpFileName); + } + + /* Initialize the buffers. + */ + memset(ch, 0, MAPPINGSIZE); + + /* Write to the File handle. + */ + err = WriteFile(hFile, + buf, + strlen(buf), + &dwBytesWritten, + NULL); + + if (err == FALSE) + { + Trace("ERROR: %u :unable to write to file handle " + "hFile=0x%lx\n", + GetLastError(), + hFile); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Flush to the hard-drive. + */ + FlushFileBuffers(hFile); + + /* Create a unnamed file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_READONLY, /*read and wite*/ + 0, /*high-order size*/ + 0, /*low-order size*/ + NULL); /*unnamed object*/ + + if(NULL == hFileMapping) + { + Trace("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpOne; + } + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_READ, /* access code */ + 0, /*high order offset*/ + 0, /*low order offset*/ + 0); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Copy the MapViewOfFile to buffer, so we can + * compare with value read from file directly. + */ + memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE); + if (memcmp(ch, buf, strlen(buf))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + ch, buf); + RetVal = FAIL; + goto CleanUpThree; + } + +CleanUpThree: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Close Handle to opend file mapping. + */ + if ( CloseHandle(hFileMapping) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFileMapping); + RetVal = FAIL; + } + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(hFile) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFile); + RetVal = FAIL; + } + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/testinfo.dat new file mode 100644 index 0000000..464679a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMappingW +Name = CreateFileMappingW with PAGE_READONLY +TYPE = DEFAULT +EXE1 = createfilemappingw +Description +=Test the CreateFileMappingW to create a unnamed file-mapping object +=and with PAGE_READONLY protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CMakeLists.txt new file mode 100644 index 0000000..618abe0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateFileMappingW.cpp +) + +add_executable(paltest_createfilemappingw_test2 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappingw_test2 coreclrpal) + +target_link_libraries(paltest_createfilemappingw_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.cpp new file mode 100644 index 0000000..5cc6d77 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.cpp @@ -0,0 +1,124 @@ +// 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. + +/*============================================================= +** +** Source: createfilemappingw.c +** +** Purpose: Positive test the CreateFileMapping API. +** Call CreateFileMapping to create a unnamed +** file-mapping object with PAGE_READONLY +** protection and SEC_IMAGE attribute in UNICODE +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE FileHandle; + HANDLE FileMappingHandle; + int err; + WCHAR *wpFileName = NULL; + char executableFileName[256]=""; + + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + +#if WIN32 + sprintf_s(executableFileName, _countof(executableFileName),"%s","executable.exe"); +#else + sprintf_s(executableFileName, _countof(executableFileName),"%s","executable"); +#endif + + //conver string to a unicode one + wpFileName = convert(executableFileName); + + + //create a file and return the file handle + FileHandle = CreateFile(wpFileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_ARCHIVE, + NULL); + + //free this memory + free(wpFileName); + + if(INVALID_HANDLE_VALUE == FileHandle) + { + Fail("Failed to call CreateFile to create a file\n"); + } + + //create a unnamed file-mapping object with file handle FileHandle + //and with PAGE_READONLY protection + FileMappingHandle = CreateFileMapping( + FileHandle, //File Handle + NULL, //not inherited + PAGE_READONLY|SEC_IMAGE, //access protection and section attribute + 0, //high-order of object size + 0, //low-orger of object size + NULL); //unnamed object + + + if(NULL == FileMappingHandle) + { + Trace("\nFailed to call CreateFileMapping to create a mapping object!\n"); + err = CloseHandle(FileHandle); + if(0 == err) + { + Fail("\nFailed to call CloseHandle API\n"); + } + Fail(""); + } + if(GetLastError() == ERROR_ALREADY_EXISTS) + { + Trace("\nFile mapping object already exists!\n"); + err = CloseHandle(FileHandle); + if(0 == err) + { + Trace("\nFailed to call CloseHandle API to close a file handle\n"); + err = CloseHandle(FileMappingHandle); + if(0 == err) + { + Fail("\nFailed to call CloseHandle API to close a mapping object handle\n"); + } + Fail(""); + } + err = CloseHandle(FileMappingHandle); + if(0 == err) + { + Fail("\nFailed to call CloseHandle API to close a mapping object handle\n"); + } + Fail(""); + } + err = CloseHandle(FileMappingHandle); + if(0 == err) + { + Trace("\nFailed to call CloseHandle API to close a mapping object handle\n"); + err = CloseHandle(FileHandle); + if(0 == err) + { + Fail("\nFailed to call CloseHandle API to close a file handle\n"); + } + Fail(""); + } + err = CloseHandle(FileHandle); + if(0 == err) + { + Fail("\nFailed to call CloseHandle API to close a file handle\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CMakeLists.txt new file mode 100644 index 0000000..46723a0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateFileMappingW.cpp +) + +add_executable(paltest_createfilemappingw_test3 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappingw_test3 coreclrpal) + +target_link_libraries(paltest_createfilemappingw_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CreateFileMappingW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CreateFileMappingW.cpp new file mode 100644 index 0000000..1cbeff9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CreateFileMappingW.cpp @@ -0,0 +1,156 @@ +// 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. + +/*============================================================= +** +** Source: createfilemappingw.c (test 3) +** +** Purpose: Positive test the CreateFileMappingW API. +** Call CreateFileMapping with access PAGE_READWRITE. +** +** +**============================================================*/ +#define UNICODE +#include + +const int MAPPINGSIZE = 2048; + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE hFile; + char buf[] = "this is a test string"; + char ch[2048]; + WCHAR lpFileName[] = {'t','e','s','t','.','t','m','p','\0'}; + HANDLE hFileMapping; + LPVOID lpMapViewAddress; + int RetVal = PASS; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a file handle with CreateFile. + */ + hFile = CreateFile( lpFileName, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), + lpFileName); + } + + /* Initialize the buffers. + */ + memset(ch, 0, MAPPINGSIZE); + + /* Create a unnamed file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read and wite*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + NULL); /*unnamed object*/ + + if(NULL == hFileMapping) + { + Trace("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpOne; + } + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_ALL_ACCESS, /* access code */ + 0, /*high order offset*/ + 0, /*low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Write to the Map view. + */ + memcpy(lpMapViewAddress, buf, strlen(buf)); + + /* Read from the Map view. + */ + memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE); + + /* Copy the MapViewOfFile to buffer, so we can + * compare with value read from file directly. + */ + if (memcmp(ch, buf, strlen(buf))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + ch, buf); + RetVal = FAIL; + goto CleanUpThree; + } + +CleanUpThree: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Close Handle to opend file mapping. + */ + if ( CloseHandle(hFileMapping) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFileMapping); + RetVal = FAIL; + } + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(hFile) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFile); + RetVal = FAIL; + } + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/testinfo.dat new file mode 100644 index 0000000..1077316 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMappingW +Name = CreateFileMappingW with PAGE_READWRITE +TYPE = DEFAULT +EXE1 = createfilemappingw +Description +=Test the CreateFileMappingW to create a unnamed file-mapping object +=and with PAGE_READWRITE protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CMakeLists.txt new file mode 100644 index 0000000..b9ab861 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateFileMappingW.cpp +) + +add_executable(paltest_createfilemappingw_test4 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappingw_test4 coreclrpal) + +target_link_libraries(paltest_createfilemappingw_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CreateFileMappingW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CreateFileMappingW.cpp new file mode 100644 index 0000000..265a317 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CreateFileMappingW.cpp @@ -0,0 +1,182 @@ +// 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. + +/*============================================================= +** +** Source: createfilemappingw.c (test 4) +** +** Purpose: Positive test the CreateFileMappingW API. +** Call CreateFileMappingW with access PAGE_WRITECOPY. +** +** +**============================================================*/ +#define UNICODE +#include + +const int MAPPINGSIZE = 2048; + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE hFile; + char buf[] = "this is a test string"; + char ch[2048]; + WCHAR lpFileName[] = {'t','e','s','t','.','t','m','p','\0'}; + HANDLE hFileMapping; + LPVOID lpMapViewAddress; + int RetVal = PASS; + int err; + DWORD dwBytesWritten; + + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a file handle with CreateFile. + */ + hFile = CreateFile( lpFileName, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), + lpFileName); + } + + /* Write to the File handle. + */ + err = WriteFile(hFile, + buf, + strlen(buf), + &dwBytesWritten, + NULL); + + if (err == FALSE) + { + Trace("ERROR: %u :unable to write to file handle " + "hFile=0x%lx\n", + GetLastError(), + hFile); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Flush to the hard-drive. + */ + FlushFileBuffers(hFile); + + /* Initialize the buffers. + */ + memset(ch, 0, MAPPINGSIZE); + + /* Create a unnamed file-mapping object with file handle FileHandle + * and with PAGE_WRITECOPY protection. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_WRITECOPY, /*write copy*/ + 0, /*high-order size*/ + 0, /*low-order size*/ + NULL); /*unnamed object*/ + + if(NULL == hFileMapping) + { + Trace("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpOne; + } + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_COPY, /* access code */ + 0, /* high order offset*/ + 0, /* low order offset*/ + 0); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Write to the Map view.3 + */ + memcpy(lpMapViewAddress, buf, strlen(buf)); + + /* Read from the Map view. + */ + memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE); + + /* Copy the MapViewOfFile to buffer, so we can + * compare with value read from file directly. + */ + if (memcmp(ch, buf, strlen(buf))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + ch, buf); + RetVal = FAIL; + goto CleanUpThree; + } + +CleanUpThree: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Close Handle to opend file mapping. + */ + if ( CloseHandle(hFileMapping) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFileMapping); + RetVal = FAIL; + } + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(hFile) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFile); + RetVal = FAIL; + } + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/testinfo.dat new file mode 100644 index 0000000..472b857 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMappingW +Name = CreateFileMappingW with PAGE_WRITECOPY. +TYPE = DEFAULT +EXE1 = createfilemappingw +Description +=Test the CreateFileMapping to create a unnamed file-mapping object +=and with PAGE_WRITE protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CMakeLists.txt new file mode 100644 index 0000000..933596a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateFileMappingW.cpp +) + +add_executable(paltest_createfilemappingw_test5 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappingw_test5 coreclrpal) + +target_link_libraries(paltest_createfilemappingw_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CreateFileMappingW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CreateFileMappingW.cpp new file mode 100644 index 0000000..21bf7c6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CreateFileMappingW.cpp @@ -0,0 +1,194 @@ +// 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. + +/*============================================================= +** +** Source: createfilemappingw.c (test 5) +** +** Purpose: Positive test the CreateFileMappingW API. +** Test CreateFileMappingW to a "swap" handle with +** access PAGE_READONLY. +** +** +**============================================================*/ +#define UNICODE +#include + +const int MAPPINGSIZE = 2048; +HANDLE SWAP_HANDLE = ((VOID *)(-1)); + +int __cdecl main(int argc, char *argv[]) +{ + char testString[] = "this is a test string"; + WCHAR lpObjectName[] = {'m','y','O','b','j','e','c','t','\0'}; + int RetVal = FAIL; + char results[2048]; + + HANDLE hFileMapRO; + HANDLE hFileMapRW; + LPVOID lpMapViewRO; + LPVOID lpMapViewRW; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Initialize the buffers. + */ + memset(results, 0, MAPPINGSIZE); + + /* Create a named file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapRW = CreateFileMapping( + SWAP_HANDLE, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read only*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + lpObjectName); /*named object*/ + + if(NULL == hFileMapRW) + { + Fail("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + } + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewRW = MapViewOfFile( + hFileMapRW, + FILE_MAP_ALL_ACCESS, /* access code */ + 0, /* high order offset*/ + 0, /* low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewRW) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpOne; + } + + + hFileMapRO = CreateFileMapping( + SWAP_HANDLE, + NULL, /*not inherited*/ + PAGE_READONLY, /*read and write*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + lpObjectName); /*named object*/ + + if(NULL == hFileMapRO) + { + Trace("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewRO = MapViewOfFile( + hFileMapRO, + FILE_MAP_READ, /* access code */ + 0, /* high order offset*/ + 0, /* low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewRO) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpThree; + } + + /* Write the test string to the Map view. + */ + memcpy(lpMapViewRW, testString, strlen(testString)); + + /* Read from the second Map view. + */ + memcpy(results, (LPCSTR)lpMapViewRO, MAPPINGSIZE); + + /* Verify the contents of the file mapping, + * by comparing what was written to what was read. + */ + if (memcmp(results, testString, strlen(testString))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + results, + testString); + RetVal = FAIL; + goto CleanUpFour; + } + + /* Test was successful. + */ + RetVal = PASS; + +CleanUpFour: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewRO) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewRO); + RetVal = FAIL; + } + +CleanUpThree: + + /* Close Handle to opend file mapping. + */ + if ( CloseHandle(hFileMapRO) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFileMapRO); + RetVal = FAIL; + } + + +CleanUpTwo: + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewRW) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewRW); + RetVal = FAIL; + } + + +CleanUpOne: + + /* Close Handle to opend file mapping. + */ + if ( CloseHandle(hFileMapRW) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFileMapRW); + RetVal = FAIL; + } + + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/testinfo.dat new file mode 100644 index 0000000..87e16d3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMappingW +Name = CreateFileMappingW - PAGE_READWRITE +TYPE = DEFAULT +EXE1 = createfilemappingw +Description += Positive test the CreateFileMappingW API. += Test CreateFileMappingW to create a named += "swap" handle with access PAGE_READONLY. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CMakeLists.txt new file mode 100644 index 0000000..abd57dd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateFileMappingW.cpp +) + +add_executable(paltest_createfilemappingw_test6 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappingw_test6 coreclrpal) + +target_link_libraries(paltest_createfilemappingw_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CreateFileMappingW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CreateFileMappingW.cpp new file mode 100644 index 0000000..acf3ac6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CreateFileMappingW.cpp @@ -0,0 +1,165 @@ +// 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. + +/*============================================================= +** +** Source: createfilemappingw.c (test 6) +** +** Purpose: Positive test the CreateFileMappingW API. +** Test CreateFileMappingW to a "swap" handle with +** access PAGE_READWRITE. +** +** +**============================================================*/ +#define UNICODE +#include + +const int MAPPINGSIZE = 2048; +HANDLE SWAP_HANDLE = ((VOID *)(-1)); + +int __cdecl main(int argc, char *argv[]) +{ + char testString[] = "this is a test string"; + WCHAR lpObjectName[] = {'m','y','O','b','j','e','c','t','\0'}; + char results[2048]; + int RetVal = PASS; + + HANDLE hFileMapRW; + LPVOID lpMapViewRW; + LPVOID lpMapViewRW2; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Initialize the buffers. + */ + memset(results, 0, MAPPINGSIZE); + + /* Create a named file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapRW = CreateFileMapping( + SWAP_HANDLE, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read write*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + lpObjectName); /*named object*/ + + if(NULL == hFileMapRW) + { + Fail("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + } + + /* Create a map view of the READWRITE file mapping. + */ + lpMapViewRW = MapViewOfFile( + hFileMapRW, + FILE_MAP_ALL_ACCESS,/* access code */ + 0, /* high order offset*/ + 0, /* low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewRW) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpOne; + } + + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewRW2 = MapViewOfFile( + hFileMapRW, + FILE_MAP_ALL_ACCESS, /* access code */ + 0, /* high order offset*/ + 0, /* low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewRW2) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Write the test string to the Map view. + */ + memcpy(lpMapViewRW, testString, strlen(testString)); + + /* Read from the second Map view. + */ + memcpy(results, (LPCSTR)lpMapViewRW2, MAPPINGSIZE); + + /* Verify the contents of the file mapping, + * by comparing what was written to what was read. + */ + if (memcmp(results, testString, strlen(testString))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + results, + testString); + RetVal = FAIL; + goto CleanUpThree; + } + + /* Test successful. + */ + RetVal = PASS; + +CleanUpThree: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewRW2) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewRW2); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewRW) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewRW); + RetVal = FAIL; + } + + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(hFileMapRW) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFileMapRW); + RetVal = FAIL; + } + + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/testinfo.dat new file mode 100644 index 0000000..7afae68 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMapping +Name = CreateFileMappingA - with PAGE_READONLY +TYPE = DEFAULT +EXE1 = createfilemappingw +Description += Positive test the CreateFileMappingW API. += Test CreateFileMappingW to create a named += "swap" handle with access PAGE_READWRITE. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/CMakeLists.txt new file mode 100644 index 0000000..011f6e1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + createfilemapping.cpp +) + +add_executable(paltest_createfilemappingw_test7 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappingw_test7 coreclrpal) + +target_link_libraries(paltest_createfilemappingw_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/createfilemapping.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/createfilemapping.cpp new file mode 100644 index 0000000..e49b9f6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/createfilemapping.cpp @@ -0,0 +1,165 @@ +// 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. + +/*============================================================= +** +** Source: createfilemappingw.c (test 7) +** +** Purpose: Positive test the CreateFileMappingW API. +** Test CreateFileMappingW to a "swap" handle with +** access PAGE_READWRITE. +** +** +**============================================================*/ +#define UNICODE +#include + +const int MAPPINGSIZE = 2048; +HANDLE SWAP_HANDLE = ((VOID *)(-1)); + +int __cdecl main(int argc, char *argv[]) +{ + char testString[] = "this is a test string"; + WCHAR lpObjectName[] = {'m','y','O','b','j','e','c','t','\0'}; + char results[2048]; + int RetVal = PASS; + + HANDLE hFileMapRW; + LPVOID lpMapViewRW; + LPVOID lpMapViewRO; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Initialize the buffers. + */ + memset(results, 0, MAPPINGSIZE); + + /* Create a named file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapRW = CreateFileMapping( + SWAP_HANDLE, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read write*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + lpObjectName); /*unnamed object*/ + + if(NULL == hFileMapRW) + { + Fail("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + } + + /* Create a map view to the READWRITE file mapping. + */ + lpMapViewRW = MapViewOfFile( + hFileMapRW, + FILE_MAP_ALL_ACCESS,/* access code */ + 0, /* high order offset*/ + 0, /* low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewRW) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpOne; + } + + + /* Create a map view to the READWRITE file mapping. + */ + lpMapViewRO = MapViewOfFile( + hFileMapRW, + FILE_MAP_READ, /* access code */ + 0, /* high order offset*/ + 0, /* low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewRO) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Write the test string to the Map view. + */ + memcpy(lpMapViewRW, testString, strlen(testString)); + + /* Read from the second Map view. + */ + memcpy(results, (LPCSTR)lpMapViewRO, MAPPINGSIZE); + + /* Verify the contents of the file mapping, + * by comparing what was written to what was read. + */ + if (memcmp(results, testString, strlen(testString))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + results, + testString); + RetVal = FAIL; + goto CleanUpThree; + } + + /* Test successful. + */ + RetVal = PASS; + +CleanUpThree: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewRO) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewRO); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewRW) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewRW); + RetVal = FAIL; + } + + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(hFileMapRW) == FALSE ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + hFileMapRW); + RetVal = FAIL; + } + + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/testinfo.dat new file mode 100644 index 0000000..a68a665 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMappingW +Name = CreateFileMappingW - PAGE_COPYWRITE +TYPE = DEFAULT +EXE1 = createfilemapping +Description += Positive test the CreateFileMappingW API. += Test CreateFileMappingW to create a named += "swap" handle with access PAGE_READWRITE diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/CMakeLists.txt new file mode 100644 index 0000000..6e01ec7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + createfilemapping.cpp +) + +add_executable(paltest_createfilemappingw_test8 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappingw_test8 coreclrpal) + +target_link_libraries(paltest_createfilemappingw_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/createfilemapping.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/createfilemapping.cpp new file mode 100644 index 0000000..1ff137d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/createfilemapping.cpp @@ -0,0 +1,82 @@ +// 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. + +/*============================================================= +** +** Source: createfilemappingw.c (test 8) +** +** Purpose: Positive test the CreateFileMappingW API. +** Test the un-verifiable parameter combinations. +** +** +**============================================================*/ +#define UNICODE +#include + +const int MAPPINGSIZE = 2048; +HANDLE SWAP_HANDLE = ((VOID *)(-1)); + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR lpObjectName[] = {'m','y','O','b','j','e','c','t','\0'}; + + HANDLE hFileMap; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a READONLY, "swap", un-named file mapping. + * This test is unverifiable since there is no hook back to the file map + * because it is un-named. As well, since it resides in "swap", and is + * initialized to zero, there is nothing to read. + */ + hFileMap = CreateFileMapping( + SWAP_HANDLE, + NULL, /*not inherited*/ + PAGE_READONLY, /*read only*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + NULL); /*un-named object*/ + + if(NULL == hFileMap) + { + Fail("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + } + + + /* Create a COPYWRITE, "swap", un-named file mapping. + * This test is unverifiable, here is a quote from MSDN: + * + * Copy on write access. If you create the map with PAGE_WRITECOPY and + * the view with FILE_MAP_COPY, you will receive a view to file. If you + * write to it, the pages are automatically swappable and the modifications + * you make will not go to the original data file. + * + */ + hFileMap = CreateFileMapping( + SWAP_HANDLE, + NULL, /*not inherited*/ + PAGE_WRITECOPY, /*write copy*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + NULL); /*unnamed object*/ + + if(NULL == hFileMap) + { + Fail("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + } + + + /* Terminate the PAL. + */ + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/testinfo.dat new file mode 100644 index 0000000..475d827 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMappingW - Special cases +Name = CreateFileMappingW +TYPE = DEFAULT +EXE1 = createfilemapping +Description += Positive test the CreateFileMappingW API. += Test the un-verifiable parameter combinations. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/CMakeLists.txt new file mode 100644 index 0000000..b069bc6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + createfilemapping.cpp +) + +add_executable(paltest_createfilemappingw_test9 + ${SOURCES} +) + +add_dependencies(paltest_createfilemappingw_test9 coreclrpal) + +target_link_libraries(paltest_createfilemappingw_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/createfilemapping.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/createfilemapping.cpp new file mode 100644 index 0000000..16ae74c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/createfilemapping.cpp @@ -0,0 +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. + +/*============================================================= +** +** Source: createfilemapping.c (test 9) +** +** Purpose: Negative test the CreateFileMappingW API. +** +** +**============================================================*/ +#define UNICODE +#include + +const int MAPPINGSIZE = 2048; + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE hFile; + WCHAR lpFileName[] = {'t','e','s','t','.','t','m','p','\0'}; + + HANDLE hFileMapping; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a file handle with CreateFile, as READONLY + */ + hFile = CreateFile( lpFileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), + lpFileName); + } + + /* Attempt to create a unnamed file-mapping object to a READONLY file + * as READWRITE access. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read and write*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + NULL); /*unnamed object*/ + + if(NULL != hFileMapping) + { + Trace("ERROR: Able to create READWRITE mapping to a " + "READONLY file.\n" ); + if( 0 == CloseHandle(hFile) ) + { + Trace("Unexpected Error: Unable to close file handle\n"); + } + Fail(""); + } + + /* Attempt to create a unnamed file-mapping object to a zero lenght + * file. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read and write*/ + 0, /*high-order size*/ + 0, /*low-order size*/ + NULL); /*unnamed object*/ + + if( NULL != hFileMapping ) + { + Trace("ERROR: Able to create READWRITE mapping to a " + "READONLY file.\n" ); + if( 0 == CloseHandle(hFile) ) + { + Trace("Unexpected Error: Unable to close file handle\n"); + } + Fail(""); + } + if(GetLastError() != ERROR_ACCESS_DENIED) + { + Trace("ERROR: Expected GetLastError() to return " + "ERROR_FILE_INVALID (%d), it returned %u.\n", + ERROR_FILE_INVALID, + GetLastError()); + if( 0 == CloseHandle(hFile) ) + { + Trace("Unexpected Error: Unable to close file handle\n"); + } + Fail(""); + } + + /* Attempt to create a file mapping that is larger than + * the file. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_READONLY, /*read only*/ + 0, /*high-order size*/ + MAPPINGSIZE, /*low-order size*/ + NULL); /*unnamed object*/ + if(NULL != hFileMapping) + { + Trace("ERROR: Able to create file mapping of size %d to " + "file of size 0.\n", + MAPPINGSIZE); + if( 0 == CloseHandle(hFile) ) + { + Trace("Unexpected Error: Unable to close file handle\n"); + } + Fail(""); + } + + if(GetLastError() != ERROR_NOT_ENOUGH_MEMORY ) + { + Trace("ERROR: Expected GetLastError() to return " + "ERROR_NOT_ENOUGH_MEMORY (%d), it returned %u.\n", + ERROR_NOT_ENOUGH_MEMORY, + GetLastError()); + if( 0 == CloseHandle(hFile) ) + { + Trace("Unexpected Error: Unable to close file handle\n"); + } + Fail(""); + } + + if( 0 == CloseHandle(hFile) ) + { + Fail("Unexpected Error: Unable to close file handle\n"); + } + + /* Terminate the PAL. + */ + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/testinfo.dat new file mode 100644 index 0000000..2a7ecdb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = CreateFileMappingW +Name = CreateFileMappingW negative testing +TYPE = DEFAULT +EXE1 = createfilemapping +Description += Negative test the CreateFileMapping API. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/CMakeLists.txt new file mode 100644 index 0000000..66341ef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/CMakeLists.txt @@ -0,0 +1,14 @@ +set(SOURCES + dlltest.cpp + FreeLibrary.cpp +) + +add_executable(paltest_freelibrary_test1 + ${SOURCES} +) + +add_dependencies(paltest_freelibrary_test1 coreclrpal) + +target_link_libraries(paltest_freelibrary_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/FreeLibrary.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/FreeLibrary.cpp new file mode 100644 index 0000000..a06a231 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/FreeLibrary.cpp @@ -0,0 +1,128 @@ +// 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. + +/*============================================================= +** +** Source: +** +** Purpose: Positive test the FreeLibrary API. +** +** +**============================================================*/ +#include + +/*char LibraryName[] = "dlltest";*/ +/* SHLEXT is defined only for Unix variants */ + +#if defined(SHLEXT) +#define LibraryName "dlltest"SHLEXT +#else +#define LibraryName "dlltest" +#endif + + + + +BOOL PALAPI TestDll(HMODULE, int); + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hLib; + + /* Initialize the PAL. */ + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + /*Load library (DLL). */ + hLib = LoadLibrary(LibraryName); + + if(hLib == NULL) + { + Fail("ERROR:%u:Unable to load library %s\n", + GetLastError(), + LibraryName); + } + + /* Test access to DLL. */ + if(!TestDll(hLib, PASS)) + { + Trace("ERROR: TestDll function returned FALSE " + "expected TRUE\n."); + FreeLibrary(hLib); + Fail(""); + } + + /* Call the FreeLibrary API. */ + if (!FreeLibrary(hLib)) + { + Fail("ERROR:%u: Unable to free library \"%s\"\n", + GetLastError(), + LibraryName); + } + + /* Test access to the free'd DLL. */ + if(!TestDll(hLib, FAIL)) + { + Fail("ERROR: TestDll function returned FALSE " + "expected TRUE\n."); + } + + PAL_Terminate(); + return PASS; + +} + + +BOOL PALAPI TestDll(HMODULE hLib, int testResult) +{ + int RetVal; +#if WIN32 + char FunctName[] = "_DllTest@0"; +#else + char FunctName[] = "DllTest"; +#endif + FARPROC DllAddr; + + /* Attempt to grab the proc address of the dll function. + * This one should succeed.*/ + if(testResult == PASS) + { + DllAddr = GetProcAddress(hLib, FunctName); + if(DllAddr == NULL) + { + Trace("ERROR: Unable to load function \"%s\" library \"%s\"\n", + FunctName, + LibraryName); + return (FALSE); + } + /* Run the function in the DLL, + * to ensure that the DLL was loaded properly.*/ + RetVal = DllAddr(); + if (RetVal != 1) + { + Trace("ERROR: Unable to receive correct information from DLL! " + ":expected \"1\", returned \"%d\"\n", + RetVal); + return (FALSE); + } + } + + /* Attempt to grab the proc address of the dll function. + * This one should fail.*/ + if(testResult == FAIL) + { + DllAddr = GetProcAddress(hLib, FunctName); + if(DllAddr != NULL) + { + Trace("ERROR: Able to load function \"%s\" from free'd" + " library \"%s\"\n", + FunctName, + LibraryName); + return (FALSE); + } + } + return (TRUE); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/dlltest.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/dlltest.cpp new file mode 100644 index 0000000..3e6cff2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/dlltest.cpp @@ -0,0 +1,32 @@ +// 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. + +/*===================================================================== +** +** Source: dlltest.c (FreeLibrary test dll) +** +** Purpose: This file will be used to create the shared library +** that will be used in the FreeLibraryAndExitThread +** test. A very simple shared library, with one function +** "DllTest" which merely returns 1. +** +** +**===================================================================*/ +#include "pal.h" + +#if WIN32 +__declspec(dllexport) +#endif + +int PALAPI DllTest() +{ + return 1; +} + +#ifdef WIN32 +int PALAPI _DllMainCRTStartup(void *hinstDLL, int reason, void * lpvReserved) +{ + return 1; +} +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/testinfo.dat new file mode 100644 index 0000000..a09d214 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = FreeLibrary +Name = Positive test for FreeLibrary API +TYPE = DEFAULT +EXE1 = freelibrary +LIB1 = dlltest +Description +=Test the FreeLibrary to decrement the reference +=count of the loaded DLL diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/CMakeLists.txt new file mode 100644 index 0000000..126d16b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_freelibrary_test2 + ${SOURCES} +) + +add_dependencies(paltest_freelibrary_test2 coreclrpal) + +target_link_libraries(paltest_freelibrary_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/test2.cpp new file mode 100644 index 0000000..b43f74d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/test2.cpp @@ -0,0 +1,52 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c (FreeLibrary) +** +** Purpose: Tests the PAL implementation of the FreeLibrary function. +** This is a negative test that will pass an invalid and a +** null handle to FreeLibrary. +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char* argv[]) +{ + HANDLE hLib; + + /* Initialize the PAL. + */ + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + /* Attempt to pass FreeLibrary an invalid handle. + */ + hLib = INVALID_HANDLE_VALUE; + if (FreeLibrary(hLib)) + { + Fail("ERROR: Able to free library handle = \"0x%lx\".\n", + hLib); + } + + /* Attempt to pass FreeLibrary a NULL handle. + */ + hLib = NULL; + if (FreeLibrary(hLib)) + { + Fail("ERROR: Able to free library handle = \"NULL\".\n"); + } + + + /* Terminate the PAL. + */ + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/testinfo.dat new file mode 100644 index 0000000..521fa6e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = FreeLibrary +Name = Negative test for FreeLibrary +TYPE = DEFAULT +EXE1 = test2 +Description += Tests the PAL implementation of the FreeLibrary function. += This is a negative test that will pass an invalid and a += null handle to FreeLibrary. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/CMakeLists.txt new file mode 100644 index 0000000..5e268fb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/CMakeLists.txt @@ -0,0 +1,14 @@ +set(SOURCES + dlltest.cpp + test1.cpp +) + +add_executable(paltest_freelibraryandexitthread_test1 + ${SOURCES} +) + +add_dependencies(paltest_freelibraryandexitthread_test1 coreclrpal) + +target_link_libraries(paltest_freelibraryandexitthread_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/dlltest.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/dlltest.cpp new file mode 100644 index 0000000..e66a9eb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/dlltest.cpp @@ -0,0 +1,32 @@ +// 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. + +/*===================================================================== +** +** Source: dlltest.c (FreeLibraryAndExitThread test dll) +** +** Purpose: This file will be used to create the shared library +** that will be used in the FreeLibraryAndExitThread +** test. A very simple shared library, with one function +** "DllTest" which merely returns 1. +** +** +**===================================================================*/ +#include "pal.h" + +#if WIN32 +__declspec(dllexport) +#endif + +int PALAPI DllTest() +{ + return 1; +} + +#if WIN32 +int PALAPI _DllMainCRTStartup(void *hinstDLL, int reason, void * lpvReserved) +{ + return 1; +} +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.cpp new file mode 100644 index 0000000..58f6643 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.cpp @@ -0,0 +1,183 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c (FreeLibraryAndExitThread) +** +** Purpose: Tests the PAL implementation of the FreeLibraryAndExitThread +** function. FreeLibraryAndExitThread when run will exit the +** process that it is called within, therefore we create a +** thread to run the API. Then test for the existance of the +** thread and access to the library. +** +** +**===================================================================*/ + +#include + +/*Define platform specific information*/ + +/* SHLEXT is defined only for Unix variants */ +#if defined(SHLEXT) +#define LibraryName "dlltest"SHLEXT +#else +#define LibraryName "dlltest" +#endif + +#define TIMEOUT 60000 + +BOOL PALAPI StartThreadTest(); +DWORD PALAPI CreateTestThread(LPVOID); +BOOL PALAPI TestDll(HMODULE, int); + +int __cdecl main(int argc, char* argv[]) +{ + /*Initialize the PAL*/ + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + if (!StartThreadTest()) + { + Fail("ERROR: FreeLibraryAndExitThread test failed.\n"); + } + + /*Terminate the PAL*/ + PAL_Terminate(); + return PASS; + +} + + +BOOL PALAPI StartThreadTest() +{ + HMODULE hLib; + HANDLE hThread; + DWORD dwThreadId; + LPTHREAD_START_ROUTINE lpStartAddress = &CreateTestThread; + LPVOID lpParameter = (LPVOID)lpStartAddress; + DWORD rc = -1; + /*Load library (DLL).*/ + hLib = LoadLibrary(LibraryName); + if(hLib == NULL) + { + Trace("ERROR: Unable to load library %s\n", LibraryName); + + return (FALSE); + } + + /*Start the test thread*/ + hThread = CreateThread(NULL, + (DWORD)0, + lpStartAddress, + hLib, + (DWORD)NULL, + &dwThreadId); + if(hThread == NULL) + { + Trace("ERROR:%u: Unable to create thread.\n", + GetLastError()); + + FreeLibrary(hLib); + return (FALSE); + } + + /*Wait on thread.*/ + rc = WaitForSingleObject(hThread, TIMEOUT); + if( rc != WAIT_OBJECT_0 ) + { + Trace("ERROR:%u: hThread=0x%4.4lx not exited by " + "FreeLibraryAndExitThread, RC[%d]\n", + GetLastError(), + hThread, rc); + +// There is a possibility that the other thread might +// still be using the library VSW:337893 +// FreeLibrary(hLib); + CloseHandle(hThread); + return (FALSE); + } + + /*Test access to DLL.*/ + if(!TestDll(hLib, 0)) + { + Trace("ERROR: TestDll function returned FALSE " + "expected TRUE\n."); + + CloseHandle(hThread); + return (FALSE); + } + + FreeLibrary(hLib); + /*Clean-up thread.*/ + CloseHandle(hThread); + + return (TRUE); +} + +BOOL PALAPI TestDll(HMODULE hLib, int testResult) +{ + int RetVal; + char FunctName[] = "DllTest"; + FARPROC DllAddr; + + /* Attempt to grab the proc address of the dll function. + * This one should succeed.*/ + if(testResult == 1) + { + DllAddr = GetProcAddress(hLib, FunctName); + if(DllAddr == NULL) + { + Trace("ERROR: Unable to load function \"%s\" library \"%s\"\n", + FunctName, + LibraryName); + return (FALSE); + } + /* Run the function in the DLL, + * to ensure that the DLL was loaded properly.*/ + RetVal = DllAddr(); + if (RetVal != 1) + { + Trace("ERROR: Unable to receive correct information from DLL! " + ":expected \"1\", returned \"%d\"\n", + RetVal); + return (FALSE); + } + } + + /* Attempt to grab the proc address of the dll function. + * This one should fail.*/ + if(testResult == 0) + { + DllAddr = GetProcAddress(hLib, FunctName); + if(DllAddr != NULL) + { + Trace("ERROR: Able to load function \"%s\" from free'd" + " library \"%s\"\n", + FunctName, + LibraryName); + return (FALSE); + } + } + return (TRUE); +} + +DWORD PALAPI CreateTestThread(LPVOID lpParam) +{ + /* Test access to DLL.*/ + TestDll(lpParam, 1); + + /*Free library and exit thread.*/ + FreeLibraryAndExitThread(lpParam, (DWORD)0); + + /* NOT REACHED */ + + /*Infinite loop, we should not get here.*/ + while(1); + + return (DWORD)0; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/testinfo.dat new file mode 100644 index 0000000..455829c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = FreeLibraryAndExitThread +Name = Positive test for FreeLibraryAndExitThread +TYPE = DEFAULT +EXE1 = test1 +LIB1 = dlltest +Description += Tests the PAL implementation of the FreeLibraryAndExitThread += function. When run, FreeLibraryAndExitThread will exit the += process that it is called within, therefore we create a += thread to run the API. Then we test for the existance of the += thread and access to the library. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/CMakeLists.txt new file mode 100644 index 0000000..fd7fa6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetModuleFileNameA.cpp +) + +add_executable(paltest_getmodulefilenamea_test1 + ${SOURCES} +) + +add_dependencies(paltest_getmodulefilenamea_test1 coreclrpal) + +target_link_libraries(paltest_getmodulefilenamea_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/GetModuleFileNameA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/GetModuleFileNameA.cpp new file mode 100644 index 0000000..d05f0ac --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/GetModuleFileNameA.cpp @@ -0,0 +1,92 @@ +// 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. + +/*============================================================= +** +** Source: getmodulefilenamea.c +** +** Purpose: Positive test the GetModuleFileName API. +** Call GetModuleFileName to retrieve the specified +** module full path and file name +** +** +**============================================================*/ + +#include + +#define MODULENAMEBUFFERSIZE 1024 + +/* SHLEXT is defined only for Unix variants */ + +#if defined(SHLEXT) +#define ModuleName "librotor_pal"SHLEXT +#define Delimiter "/" +#else +#define ModuleName "rotor_pal.dll" +#define Delimiter "\\" +#endif + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + int err; + DWORD ModuleNameLength; + char ModuleFileNameBuf[MODULENAMEBUFFERSIZE]=""; + char* TempBuf = NULL; + char* LastBuf = NULL; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + + //load a module + ModuleHandle = LoadLibrary(ModuleName); + if(!ModuleHandle) + { + Fail("Failed to call LoadLibrary API!\n"); + } + + + //retrieve the specified module full path and file name + ModuleNameLength = GetModuleFileName( + ModuleHandle,//specified module handle + ModuleFileNameBuf,//buffer for module file name + MODULENAMEBUFFERSIZE); + + //strip out all full path + TempBuf = strtok(ModuleFileNameBuf,Delimiter); + LastBuf = TempBuf; + while(NULL != TempBuf) + { + LastBuf = TempBuf; + TempBuf = strtok(NULL,Delimiter); + } + + + if(0 == ModuleNameLength || strcmp(ModuleName,LastBuf)) + { + Trace("\nFailed to all GetModuleFileName API!\n"); + err = FreeLibrary(ModuleHandle); + if(0 == err) + { + Fail("\nFailed to all FreeLibrary API!\n"); + } + Fail(""); + } + + //decrement the reference count of the loaded dll + err = FreeLibrary(ModuleHandle); + if(0 == err) + { + Fail("\nFailed to all FreeLibrary API!\n"); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/testinfo.dat new file mode 100644 index 0000000..8075e84 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = GetModuleFileNameA +Name = Positive test for GetModuleFileNameA API +TYPE = DEFAULT +EXE1 = getmodulefilenamea +Description +=Test the GetModuleFileNameA to retrieve the specified module +=full path and file name diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/CMakeLists.txt new file mode 100644 index 0000000..5dd6e85 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetModuleFileNameA.cpp +) + +add_executable(paltest_getmodulefilenamea_test2 + ${SOURCES} +) + +add_dependencies(paltest_getmodulefilenamea_test2 coreclrpal) + +target_link_libraries(paltest_getmodulefilenamea_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/GetModuleFileNameA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/GetModuleFileNameA.cpp new file mode 100644 index 0000000..e8aed6d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/GetModuleFileNameA.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================= +** +** Source: getmodulefilenamea.c +** +** Purpose: Positive test the GetModuleFileNameA API. +** Call GetModuleFileName to retrieve current process +** full path and file name by passing a NULL module handle +** +** +**============================================================*/ +#include + + +#define MODULENAMEBUFFERSIZE 1024 + +int __cdecl main(int argc, char *argv[]) +{ + + DWORD ModuleNameLength; + char ModuleFileNameBuf[MODULENAMEBUFFERSIZE]=""; + int err; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + + //retrieve the current process full path and file name + //by passing a NULL module handle + ModuleNameLength = GetModuleFileName( + NULL, //a NULL handle + ModuleFileNameBuf,//buffer for module file name + MODULENAMEBUFFERSIZE); + + if(0 == ModuleNameLength) + { + Fail("\nFailed to all GetModuleFileName API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/testinfo.dat new file mode 100644 index 0000000..45fdca6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = GetModuleFileNameA +Name = Positive test for GetModuleFileNameA API +TYPE = DEFAULT +EXE1 = getmodulefilenamea +Description +=Test the GetModuleFileNameA to retrieve current process full +=full path and file name by passing a NULL module handle diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/CMakeLists.txt new file mode 100644 index 0000000..0488cc9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetModuleFileNameW.cpp +) + +add_executable(paltest_getmodulefilenamew_test1 + ${SOURCES} +) + +add_dependencies(paltest_getmodulefilenamew_test1 coreclrpal) + +target_link_libraries(paltest_getmodulefilenamew_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.cpp new file mode 100644 index 0000000..c122312 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.cpp @@ -0,0 +1,112 @@ +// 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. + +/*============================================================= +** +** Source: getmodulefilenamew.c +** +** Purpose: Test the GetModuleFileNameW to retrieve the specified module +** full path and file name in UNICODE. +** +** +**============================================================*/ +#define UNICODE +#include + +#define MODULENAMEBUFFERSIZE 1024 + +/* SHLEXT is defined only for Unix variants */ + +#if defined(SHLEXT) +#define ModuleName "librotor_pal"SHLEXT +#define Delimiter "/" +#else +#define ModuleName "rotor_pal.dll" +#define Delimiter "\\" +#endif + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + int err; + WCHAR *lpModuleName; + DWORD ModuleNameLength; + WCHAR *ModuleFileNameBuf; + char* TempBuf = NULL; + char* LastBuf = NULL; + char NewModuleFileNameBuf[MODULENAMEBUFFERSIZE+200] = ""; + + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + ModuleFileNameBuf = (WCHAR*)malloc(MODULENAMEBUFFERSIZE*sizeof(WCHAR)); + + //convert a normal string to a wide one + lpModuleName = convert(ModuleName); + + //load a module + ModuleHandle = LoadLibrary(lpModuleName); + + //free the memory + free(lpModuleName); + + if(!ModuleHandle) + { + Fail("Failed to call LoadLibrary API!\n"); + } + + + //retrieve the specified module full path and file name + ModuleNameLength = GetModuleFileName( + ModuleHandle,//specified module handle + ModuleFileNameBuf,//buffer for module file name + MODULENAMEBUFFERSIZE); + + + + //convert a wide full path name to a normal one + strcpy(NewModuleFileNameBuf,convertC(ModuleFileNameBuf)); + + //strip out all full path + TempBuf = strtok(NewModuleFileNameBuf,Delimiter); + LastBuf = TempBuf; + while(NULL != TempBuf) + { + LastBuf = TempBuf; + TempBuf = strtok(NULL,Delimiter); + } + + + //free the memory + free(ModuleFileNameBuf); + + if(0 == ModuleNameLength || strcmp(ModuleName,LastBuf)) + { + Trace("\nFailed to all GetModuleFileName API!\n"); + err = FreeLibrary(ModuleHandle); + if(0 == err) + { + Fail("\nFailed to all FreeLibrary API!\n"); + } + Fail(""); + } + + + + //decrement the reference count of the loaded dll + err = FreeLibrary(ModuleHandle); + if(0 == err) + { + Fail("\nFailed to all FreeLibrary API!\n"); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/testinfo.dat new file mode 100644 index 0000000..c8d94b7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = GetModuleFileNameW +Name = Positive test for GetModuleFileNameW API +TYPE = DEFAULT +EXE1 = getmodulefilenamew +Description +=Test the GetModuleFileNameW to retrieve the specified module +=full path and file name in UNICODE diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/CMakeLists.txt new file mode 100644 index 0000000..f3a51c3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + GetModuleFileNameW.cpp +) + +add_executable(paltest_getmodulefilenamew_test2 + ${SOURCES} +) + +add_dependencies(paltest_getmodulefilenamew_test2 coreclrpal) + +target_link_libraries(paltest_getmodulefilenamew_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.cpp new file mode 100644 index 0000000..f23d97c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.cpp @@ -0,0 +1,57 @@ +// 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. + +/*============================================================= +** +** Source: getmodulefilenamew.c +** +** Purpose: Positive test the GetModuleFileName API. +** Call GetModuleFileName to retrieve current process +** full path and file name by passing a NULL module handle +** in UNICODE +** +** +**============================================================*/ +#define UNICODE +#include + +#define MODULENAMEBUFFERSIZE 1024 + + +int __cdecl main(int argc, char *argv[]) +{ + + DWORD ModuleNameLength; + WCHAR *ModuleFileNameBuf; + int err; + + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + ModuleFileNameBuf = (WCHAR*)malloc(MODULENAMEBUFFERSIZE*sizeof(WCHAR)); + + //retrieve the current process full path and file name + //by passing a NULL module handle + ModuleNameLength = GetModuleFileName( + NULL, //a NULL handle + ModuleFileNameBuf,//buffer for module file name + MODULENAMEBUFFERSIZE); + + //free the memory + free(ModuleFileNameBuf); + + if(0 == ModuleNameLength) + { + Fail("\nFailed to all GetModuleFileName API!\n"); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/testinfo.dat new file mode 100644 index 0000000..8b87401 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = GetModuleFileNameW +Name = Positive test for GetModuleFileNameW API +TYPE = DEFAULT +EXE1 = getmodulefilenamew +Description +=Test the GetModuleFileNameW to retrieve current process full +=full path and file name by passing a NULL module handle in UNICODE diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/CMakeLists.txt new file mode 100644 index 0000000..6398b4e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/CMakeLists.txt @@ -0,0 +1,14 @@ +set(SOURCES + test1.cpp + testlib.cpp +) + +add_executable(paltest_getprocaddress_test1 + ${SOURCES} +) + +add_dependencies(paltest_getprocaddress_test1 coreclrpal) + +target_link_libraries(paltest_getprocaddress_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/test1.cpp new file mode 100644 index 0000000..7b89dfe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/test1.cpp @@ -0,0 +1,111 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c (filemapping_memmgt\getprocaddress\test1) +** +** Purpose: Positive test the GetProcAddress API. +** The first test calls GetProcAddress to retrieve the +** address of SimpleFunction inside testlib by its name, +** then calls the function and checks that it worked. +** +** +**===========================================================================*/ +#include + +typedef int (PALAPI_NOEXPORT *SIMPLEFUNCTION)(int); + +/* SHLEXT is defined only for Unix variants */ +#if defined(SHLEXT) +#define lpModuleName "testlib"SHLEXT +#else +#define lpModuleName "testlib.dll" +#endif + +int __cdecl main(int argc, char *argv[]) +{ + int err; + HMODULE hModule; + SIMPLEFUNCTION procAddressByName; + +#if WIN32 + const char *FunctionName = "_SimpleFunction@4"; +#else + const char *FunctionName = "SimpleFunction"; +#endif + + /* Initialize the PAL environment. */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* load a module */ + hModule = LoadLibrary(lpModuleName); + if(!hModule) + { + Fail("Unexpected error: " + "LoadLibrary(%s) failed.\n", + lpModuleName); + } + + /* + * Test 1 + * + * Get the address of a function + */ + procAddressByName = (SIMPLEFUNCTION) GetProcAddress(hModule,FunctionName); + if(!procAddressByName) + { + Trace("ERROR: Unable to get address of SimpleFunction by its name. " + "GetProcAddress returned NULL with error %d\n", + GetLastError()); + + /* Cleanup */ + err = FreeLibrary(hModule); + if(0 == err) + { + Fail("Unexpected error: Failed to FreeLibrary %s\n", + lpModuleName); + } + Fail(""); + } + + /* Call the function to see that it really worked */ + /* Simple function adds 1 to the argument passed */ + if( 2 != ((procAddressByName)(1))) + { + Trace("ERROR: Problem calling the function by its address.\n"); + + /* Cleanup */ + err = FreeLibrary(hModule); + if(0 == err) + { + Fail("Unexpected error: Failed to FreeLibrary %s\n", + lpModuleName); + } + Fail(""); + } + + /* Cleanup */ + err = FreeLibrary(hModule); + if(0 == err) + { + Fail("Unexpected error: Failed to FreeLibrary %s\n", + lpModuleName); + } + + PAL_Terminate(); + return PASS; +} + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testinfo.dat new file mode 100644 index 0000000..31b262e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = filemapping_memmgt +Function = getprocaddress +Name = Positive test for GetProcAddress API +TYPE = DEFAULT +EXE1 = test1 +LIB1 = testlib +Description +=Positive test the GetProcAddress API. +=The first test calls GetProcAddress to retrieve the +=address of strcpy by its name, then calls the function and +=checks that it worked. The second part of the test +=calls GetProcAddress to retrieve the address of +=strcpy by its ordinal, then calls the function and +=checks that it worked. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testlib.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testlib.cpp new file mode 100644 index 0000000..7b87ba7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testlib.cpp @@ -0,0 +1,33 @@ +// 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. + +/*============================================================================= +** +** Source: testlib.c (filemapping_memmgt\getprocaddress\test1) +** +** Purpose: Create a simple library containing one function +** to test GetProcAddress +** +** +**===========================================================================*/ +#include "pal.h" + +#if WIN32 +__declspec(dllexport) +#endif + +/** + * Simple function that returns i+1 + */ +int PALAPI SimpleFunction(int i) +{ + return i+1; +} + +#if WIN32 +int PALAPI _DllMainCRTStartup(void *hinstDLL, int reason, void *lpvReserved) +{ + return 1; +} +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/CMakeLists.txt new file mode 100644 index 0000000..d328f4c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/CMakeLists.txt @@ -0,0 +1,14 @@ +set(SOURCES + test2.cpp + testlib.cpp +) + +add_executable(paltest_getprocaddress_test2 + ${SOURCES} +) + +add_dependencies(paltest_getprocaddress_test2 coreclrpal) + +target_link_libraries(paltest_getprocaddress_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/test2.cpp new file mode 100644 index 0000000..9107728 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/test2.cpp @@ -0,0 +1,152 @@ +// 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. + +/*============================================================================= +** +** Source: test2.c (filemapping_memmgt\getprocaddress\test2) +** +** Purpose: This test tries to call GetProcAddress with +** a NULL handle, with a NULL function name, with an empty +** function name, with an invalid name and with an +** invalid ordinal value. +** +** +**===========================================================================*/ +#include + + +/* SHLEXT is defined only for Unix variants */ +#if defined(SHLEXT) +#define lpModuleName "testlib"SHLEXT +#else +#define lpModuleName "testlib.dll" +#endif + + +/** + * main + */ +int __cdecl main(int argc, char *argv[]) +{ + int err; + HMODULE hModule; + FARPROC procAddress; + + /* Initialize the PAL environment. */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* load a module */ + hModule = LoadLibrary(lpModuleName); + if(!hModule) + { + Fail("Unexpected error: " + "LoadLibrary(%s) failed.\n", + lpModuleName); + } + + /* + * Test 1 + * + * Call GetProcAddress with a NULL handle + */ + procAddress = GetProcAddress(NULL,"SimpleFunction"); + if(procAddress != NULL) + { + Trace("ERROR: GetProcAddress with a NULL handle " + "returned a non-NULL value when it should have " + "returned a NULL value with an error\n"); + + /* Cleanup */ + err = FreeLibrary(hModule); + if(0 == err) + { + Fail("Unexpected error: Failed to FreeLibrary %s\n", + lpModuleName); + } + Fail(""); + } + + /** + * Test 2 + * + * Call GetProcAddress with a NULL function name + */ + + procAddress = GetProcAddress(hModule,NULL); + if(procAddress != NULL) + { + Trace("ERROR: GetProcAddress with a NULL function name " + "returned a non-NULL value when it should have " + "returned a NULL value with an error\n"); + + /* Cleanup */ + err = FreeLibrary(hModule); + if(0 == err) + { + Fail("Unexpected error: Failed to FreeLibrary %s\n", + lpModuleName); + } + Fail(""); + } + + /** + * Test 3 + * + * Call GetProcAddress with an empty function name string + */ + + procAddress = GetProcAddress(hModule,""); + if(procAddress != NULL) + { + Trace("ERROR: GetProcAddress with an empty function name " + "returned a non-NULL value when it should have " + "returned a NULL value with an error\n"); + + /* Cleanup */ + err = FreeLibrary(hModule); + if(0 == err) + { + Fail("Unexpected error: Failed to FreeLibrary %s\n", + lpModuleName); + } + Fail(""); + } + + /** + * Test 4 + * + * Call GetProcAddress with an invalid name + */ + + procAddress = GetProcAddress(hModule,"Simple Function"); + if(procAddress != NULL) + { + Trace("ERROR: GetProcAddress with an invalid function name " + "returned a non-NULL value when it should have " + "returned a NULL value with an error\n"); + + /* Cleanup */ + err = FreeLibrary(hModule); + if(0 == err) + { + Fail("Unexpected error: Failed to FreeLibrary %s\n", + lpModuleName); + } + Fail(""); + } + + /* cleanup */ + err = FreeLibrary(hModule); + if(0 == err) + { + Fail("Unexpected error: Failed to FreeLibrary %s\n", + lpModuleName); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testinfo.dat new file mode 100644 index 0000000..8bf50ad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = filemapping_memmgt +Function = getprocaddress +Name = Negative test for GetProcAddress API +TYPE = DEFAULT +EXE1 = test2 +LIB1 = testlib +Description +=This test tries to call GetProcAddress with +=a NULL handle, with a NULL function name, with an empty +=function name, with an invalid name and with an +=nvalid ordinal value. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testlib.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testlib.cpp new file mode 100644 index 0000000..47299a1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testlib.cpp @@ -0,0 +1,33 @@ +// 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. + +/*============================================================================= +** +** Source: testlib.c (filemapping_memmgt\getprocaddress\test2) +** +** Purpose: Create a simple library containing one function +** to test GetProcAddress +** +** +**===========================================================================*/ +#include "pal.h" + +#if WIN32 +__declspec(dllexport) +#endif + +/** + * Simple function that returns i+1 + */ +int PALAPI SimpleFunction(int i) +{ + return i+1; +} + +#if WIN32 +int PALAPI _DllMainCRTStartup(void *hinstDLL, int reason, void *lpvReserved) +{ + return 1; +} +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/CMakeLists.txt new file mode 100644 index 0000000..910d3b1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + LocalAlloc.cpp +) + +add_executable(paltest_localalloc_test1 + ${SOURCES} +) + +add_dependencies(paltest_localalloc_test1 coreclrpal) + +target_link_libraries(paltest_localalloc_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp new file mode 100644 index 0000000..17afbc6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================= +** +** Source: LocalAlloc.c +** +** Purpose: Positive test the LocalAlloc API. +** Call LocalAlloc with zero as the allocation attribute +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + HLOCAL LocalHeap; + HLOCAL FreeHeap; + int err; + const SIZE_T heapSize = 64; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*Allocate the specified number of bytes from the heap*/ + /*with allocation attribute: zero which is required by PAL Doc*/ + LocalHeap = LocalAlloc(0, heapSize); + if(!LocalHeap) + { + Fail("\nFailed to call LocalAlloc API, " + "error code=%u\n", GetLastError()); + } + + /*Free the allocated local heap memory*/ + FreeHeap = LocalFree(LocalHeap); + if(FreeHeap) + { + Fail("Failed to call LocalFree API, " + "error code=%u\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/testinfo.dat new file mode 100644 index 0000000..056d9ce --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = LocalAlloc +Name = Positive test LocalAlloc API to Allocate the specified number of bytes from the heap +TYPE = DEFAULT +EXE1 = localalloc +Description +=Test the LocalAlloc with zero ad allocation attribute diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/CMakeLists.txt new file mode 100644 index 0000000..cc406ce --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + LocalFree.cpp +) + +add_executable(paltest_localfree_test1 + ${SOURCES} +) + +add_dependencies(paltest_localfree_test1 coreclrpal) + +target_link_libraries(paltest_localfree_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.cpp new file mode 100644 index 0000000..d9c062e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================= +** +** Source: LocalFree.c +** +** Purpose: Positive test the LocalFree API. +** Call LocalFree to free a specified local memory object +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + HLOCAL LocalHeap; + HLOCAL FreeHeap; + int err; + const SIZE_T heapSize = 64; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*Allocate the specified number of bytes from the heap*/ + /*with zero ad the allocation attribute*/ + LocalHeap = LocalAlloc(0, heapSize); + if(!LocalHeap) + { + Fail("\nFailed to call LocalAlloc API, " + "error code=%u\n", GetLastError()); + } + + /*Free the allocated local heap memory*/ + FreeHeap = LocalFree(LocalHeap); + if(FreeHeap) + { + Fail("Failed to call LocalFree API, " + "error code=%u\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/testinfo.dat new file mode 100644 index 0000000..2c0611b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = LocalFree +Name = Positive test LocalFree API to free a specified local memory object +TYPE = DEFAULT +EXE1 = localfree +Description +=Test the LocalFree to free a specified local memory object diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/CMakeLists.txt new file mode 100644 index 0000000..b069f7e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + LocalFree.cpp +) + +add_executable(paltest_localfree_test2 + ${SOURCES} +) + +add_dependencies(paltest_localfree_test2 coreclrpal) + +target_link_libraries(paltest_localfree_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.cpp new file mode 100644 index 0000000..4d4567d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.cpp @@ -0,0 +1,39 @@ +// 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. + +/*============================================================= +** +** Source: LocalFree.c +** +** Purpose: Positive test the LocalFree API. +** call LocalFree by passing NULL as local memory +** object handle +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + HLOCAL FreeHeap; + int err; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*call LocalFree by passing NULL as local memory object handle*/ + FreeHeap = LocalFree(NULL); + if(FreeHeap) + { + Fail("Failed to call LocalFree API, " + "error code=%u\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/testinfo.dat new file mode 100644 index 0000000..1455fe9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = LocalFree +Name = Positive test LocalFree API by passing NULL as local memory object handle +TYPE = DEFAULT +EXE1 = localfree +Description +=Test the LocalFree by passing NULL +=as a local memory object handle diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/CMakeLists.txt new file mode 100644 index 0000000..828a287 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/CMakeLists.txt @@ -0,0 +1,7 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/CMakeLists.txt new file mode 100644 index 0000000..384729f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + MapViewOfFile.cpp +) + +add_executable(paltest_mapviewoffile_test1 + ${SOURCES} +) + +add_dependencies(paltest_mapviewoffile_test1 coreclrpal) + +target_link_libraries(paltest_mapviewoffile_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.cpp new file mode 100644 index 0000000..6bfb73f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.cpp @@ -0,0 +1,244 @@ +// 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. + +/*============================================================= +** +** Source: MapViewOfFile.c +** +** +** Purpose: Positive test the MapViewOfFile API. +** Call MapViewOfFile with access FILE_MAP_READ. +** +** +**============================================================*/ +#include +#define MAPPINGSIZE 8192 + +// This test is special - it doesn't work when the file is created on a tmpfs, like the /tmp folder +// that is the default location for running PAL tests. The reason is that on such filesystem, +// it is not possible to create file with FILE_FLAG_NO_BUFFERING. +// So we explicitly use the /var/tmp that cannot be on tmpfs, since it it persistent over reboots. + +#ifndef __ANDROID__ +#define TEMP_DIRECTORY_PATH "/var/tmp/" +#else +// On Android, "/var/tmp/" doesn't exist; temporary files should go to /data/local/tmp/ +#define TEMP_DIRECTORY_PATH "/data/local/tmp/" +#endif + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE hFile = INVALID_HANDLE_VALUE; + LPSTR buf = NULL; + CHAR ch[MAPPINGSIZE]; + CHAR lpFilePath[MAX_PATH]; + DWORD dwBytesWritten = 0; + DWORD dwInitialSize = 0; + DWORD dwFinalSize = 0; + BOOL bRetVal = FALSE; + + HANDLE hFileMapping = 0; + LPVOID lpMapViewAddress = NULL; + + /* Initialize the PAL environment. + */ + if( 0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + GetTempFileName(TEMP_DIRECTORY_PATH, "tst", 0, lpFilePath); + + /* Create a file handle with CreateFile. + */ + hFile = CreateFile( lpFilePath, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + Fail( "ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), lpFilePath); + } + + /* Get the initial size of file, for latter tests. + */ + dwInitialSize = GetFileSize (hFile, NULL); + if ( INVALID_FILE_SIZE == dwInitialSize ) + { + Fail("ERROR:%u: The created file \"%s\" has an invalid " + "file size.\n",GetLastError(),lpFilePath); + } + + /* + * An application must meet certain requirements when working + * with files opened with FILE_FLAG_NO_BUFFERING: + * File access must begin at byte offsets within the file that + * are integer multiples of the volume's sector size. To determine a + * volume's sector size, call the GetDiskFreeSpace function. + * + * File access must be for numbers of bytes that are integer + * multiples of the volume's sector size. For example, if the + * sector size is 512 bytes, an application can request reads and + * writes of 512, 1024, or 2048 bytes, but not of 335, 981, or 7171 bytes. + * + * Buffer addresses for read and write operations must be sector + * aligned (aligned on addresses in memory that are integer multiples + * of the volume's sector size). One way to sector align buffers is to use the + * VirtualAlloc function to allocate the buffers. This function allocates memory + * that is aligned on addresses that are integer multiples of the system's page size. + * Because both page and volume sector sizes are powers of 2, memory aligned by multiples + * of the system's page size is also aligned by multiples of the volume's sector size. + */ + buf = (LPSTR)VirtualAlloc( NULL, /* Let the system decide the location. */ + MAPPINGSIZE / 2, /* One page, the smallest you can request */ + MEM_COMMIT, /* Reserve and commit in one pass */ + PAGE_READWRITE ); /* Allow reading and writting. */ + + if ( NULL == buf ) + { + Trace( "VirtualAlloc failed! LastError=%d\n", GetLastError() ); + CloseHandle( hFile ); + Fail(""); + } + + + /* + * Write to the File handle. + * The reminder will be padded with zeros. + */ + strncpy( buf, + "thats not a test string....THIS is a test string", + MAPPINGSIZE / 2 ); + + bRetVal = WriteFile(hFile, + buf, + MAPPINGSIZE / 2, + &dwBytesWritten, + NULL); + + if ( FALSE == bRetVal ) + { + Trace( "ERROR: %u :unable to write to file handle hFile=0x%lx\n", + GetLastError(), hFile); + CloseHandle(hFile); + VirtualFree( buf, 0, MEM_RELEASE ); + Fail(""); + } + + /* Create a unnamed file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapping = CreateFileMapping( hFile, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read and wite*/ + 0, /*high-order of object size*/ + MAPPINGSIZE, /*low-orger of object size*/ + NULL); /*unnamed object*/ + + if( NULL == hFileMapping ) + { + Trace("ERROR:%u: Failed to create File Mapping.\n", GetLastError()); + CloseHandle(hFile); + VirtualFree( buf, 0, MEM_RELEASE ); + Fail(""); + } + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewAddress = MapViewOfFile( hFileMapping, + FILE_MAP_READ, /* access code */ + 0, /*high order offset*/ + 0, /*low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if( NULL == lpMapViewAddress ) + { + Trace( "ERROR:%u: Failed to call MapViewOfFile API to map" + " a view of file!\n", GetLastError()); + CloseHandle(hFile); + CloseHandle(hFileMapping); + VirtualFree( buf, 0, MEM_RELEASE ); + Fail(""); + } + + /* Verify that the size of the file has increased to + * accomidate the MapView. + */ + dwFinalSize = GetFileSize (hFile, NULL); + if ( (dwFinalSize <= dwInitialSize) && (dwFinalSize != MAPPINGSIZE)) + { + + CloseHandle(hFile); + CloseHandle(hFileMapping); + VirtualFree( buf, 0, MEM_RELEASE ); + UnmapViewOfFile(lpMapViewAddress); + + Fail( "ERROR: Size of the file was expected to " + "increase from \"%d\", to \"%d\".\n ", + dwInitialSize, + dwFinalSize); + } + + /* Copy the MapViewOfFile to buffer, so we can + * compare with value read from file directly. + */ + memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE); + if (memcmp(ch, buf, strlen(buf)) != 0) + { + CloseHandle(hFile); + CloseHandle(hFileMapping); + UnmapViewOfFile(lpMapViewAddress) ; + VirtualFree( buf, 0, MEM_RELEASE ); + + Fail( "ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + ch, + buf); + } + + /* Unmap the view of file. + */ + if( FALSE == UnmapViewOfFile(lpMapViewAddress) ) + { + Trace( "\nFailed to call UnmapViewOfFile API to unmap the " + "view of a file, error code=%u\n", GetLastError()); + CloseHandle(hFile); + CloseHandle(hFileMapping); + VirtualFree( buf, 0, MEM_RELEASE ); + Fail(""); + } + + /* Close handle to create file. + */ + if( FALSE == CloseHandle(hFile) ) + { + Trace( "ERROR:%u:Failed to call CloseHandle API to close a file handle.", + GetLastError()); + CloseHandle(hFileMapping); + VirtualFree( buf, 0, MEM_RELEASE ); + Fail(""); + } + + if( FALSE == CloseHandle(hFileMapping) ) + { + Trace( "ERROR:%u:Failed to call CloseHandle API to close a " + "filemapping handle.",GetLastError()); + VirtualFree( buf, 0, MEM_RELEASE ); + Fail(""); + } + + VirtualFree( buf, 0, MEM_RELEASE ); + + DeleteFile(lpFilePath); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/testinfo.dat new file mode 100644 index 0000000..f1d8451 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = MapViewOfFile +Name = Positive test MapViewOfFile API with access FILE_MAP_READ +TYPE = DEFAULT +EXE1 = mapviewoffile +Description +=Test the MapViewOfFile with access FILE_MAP_READ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/CMakeLists.txt new file mode 100644 index 0000000..0d4f425 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + MapViewOfFile.cpp +) + +add_executable(paltest_mapviewoffile_test2 + ${SOURCES} +) + +add_dependencies(paltest_mapviewoffile_test2 coreclrpal) + +target_link_libraries(paltest_mapviewoffile_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/MapViewOfFile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/MapViewOfFile.cpp new file mode 100644 index 0000000..c08f585 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/MapViewOfFile.cpp @@ -0,0 +1,203 @@ +// 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. + +/*============================================================= +** +** Source: MapViewOfFile.c +** +** Purpose: Positive test the MapViewOfFile API. +** Call MapViewOfFile with access FILE_MAP_WRITE. +** +** Depends: CreateFile, +** GetFileSize, +** memset, +** CreateFileMapping, +** CloseHandle, +** memcpy, +** ReadFile, +** memcmp, +** UnMapViewOfFile. +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE hFile; + HANDLE hFileMapping; + LPVOID lpMapViewAddress; + char buf[] = "this is a test string"; + const int MAPPINGSIZE = 2048; + char ch[2048]; + char readString[2048]; + char lpFileName[] = "test.tmp"; + DWORD dwBytesRead; + DWORD dwInitialSize = 0; + DWORD dwFinalSize = 0; + BOOL bRetVal; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a file handle with CreateFile. + */ + hFile = CreateFile( lpFileName, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), + lpFileName); + } + + /* Get the initial size of file, for latter tests. + */ + dwInitialSize = GetFileSize (hFile, NULL); + if ( dwInitialSize == INVALID_FILE_SIZE ) + { + Fail("ERROR:%u: The created file \"%s\" has an invalid " + "file size.\n", + GetLastError(), + lpFileName); + } + + /* Initialize the buffers. + */ + memset(ch, 0, MAPPINGSIZE); + memset(readString, 0, MAPPINGSIZE); + + /* Create a unnamed file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read and wite*/ + 0, /*high-order of object size*/ + MAPPINGSIZE, /*low-orger of object size*/ + NULL); /*unnamed object*/ + + if(NULL == hFileMapping) + { + Trace("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + CloseHandle(hFile); + Fail(""); + } + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_WRITE, /* access code */ + 0, /*high order offset*/ + 0, /*low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile API to map a view" + " of file!\n", + GetLastError()); + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail(""); + } + + /* Verify that the size of the file has increased to + * accomidate the MapView. + */ + dwFinalSize = GetFileSize (hFile, NULL); + if ( (dwFinalSize <= dwInitialSize) && (dwFinalSize != MAPPINGSIZE)) + { + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail("ERROR: Size of the file was expected to " + "increase from \"%d\", to \"%d\".\n ", + dwInitialSize, + MAPPINGSIZE); + } + + /* Write to the MapView and copy the MapViewOfFile + * to buffer, so we can compare with value read from + * file directly. + */ + memcpy(lpMapViewAddress, buf, strlen(buf)); + + /* Read from the File handle. + */ + bRetVal = ReadFile(hFile, + readString, + strlen(buf), + &dwBytesRead, + NULL); + + if (bRetVal == FALSE) + { + Trace("ERROR: %u :unable to read from file handle " + "hFile=0x%lx\n", + GetLastError(), + hFile); + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail(""); + } + + if (memcmp(buf, readString, strlen(readString)) != 0) + { + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail("ERROR: Read string from file \"%s\", is " + "not equal to string written through MapView " + "\"%s\".\n", + readString, + ch); + } + + /* Unmap the view of file. + */ + if(UnmapViewOfFile(lpMapViewAddress) == FALSE) + { + Trace("ERROR: Failed to call UnmapViewOfFile API to" + " unmap the view of a file, error code=%u\n", + GetLastError()); + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail(""); + } + + /* Close handle to create file. + */ + if(CloseHandle(hFile) == FALSE) + { + Trace("ERROR:%u:Failed to call CloseHandle API " + "to close a file handle.", + GetLastError()); + CloseHandle(hFileMapping); + Fail(""); + } + + if(CloseHandle(hFileMapping) == FALSE) + { + Fail("ERROR:%u:Failed to call CloseHandle API " + "to close a file mapping handle.", + GetLastError()); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/testinfo.dat new file mode 100644 index 0000000..13b3f52 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = MapViewOfFile +Name = Positive test for MapViewOfFile API with access FILE_MAP_WRITE +TYPE = DEFAULT +EXE1 = mapviewoffile +Description +=Test the MapViewOfFile with access FILE_MAP_WRITE diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/CMakeLists.txt new file mode 100644 index 0000000..8da6c06 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + MapViewOfFile.cpp +) + +add_executable(paltest_mapviewoffile_test3 + ${SOURCES} +) + +add_dependencies(paltest_mapviewoffile_test3 coreclrpal) + +target_link_libraries(paltest_mapviewoffile_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/MapViewOfFile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/MapViewOfFile.cpp new file mode 100644 index 0000000..63bee76 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/MapViewOfFile.cpp @@ -0,0 +1,209 @@ +// 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. + +/*============================================================= +** +** Source: MapViewOfFile.c +** +** Purpose: Positive test the MapViewOfFile API. +** Call MapViewOfFile with access FILE_MAP_ALL_ACCESS. +** +** Depends: CreateFile, +** GetFileSize, +** memset, +** memcpy, +** memcmp, +** ReadFile, +** UnMapViewOfFile, +** CreateFileMapping, +** CloseHandle. +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE hFile; + HANDLE hFileMapping; + LPVOID lpMapViewAddress; + char buf[] = "this is a test string"; + const int MAPPINGSIZE = 2048; + char ch[2048]; + char readString[2048]; + char lpFileName[] = "test.tmp"; + DWORD dwBytesRead; + DWORD dwInitialSize = 0; + DWORD dwFinalSize = 0; + BOOL bRetVal; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a file handle with CreateFile. + */ + hFile = CreateFile( lpFileName, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), + lpFileName); + } + + /* Get the initial size of file, for latter tests. + */ + dwInitialSize = GetFileSize (hFile, NULL); + if ( dwInitialSize == INVALID_FILE_SIZE ) + { + Trace("ERROR:%u: The created file \"%s\" has an invalid " + "file size.\n", + GetLastError(), + lpFileName); + CloseHandle(hFile); + Fail(""); + } + + /* Initialize the buffers. + */ + memset(ch, 0, MAPPINGSIZE); + memset(readString, 0, MAPPINGSIZE); + + /* Create a unnamed file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read and wite*/ + 0, /*high-order of object size*/ + MAPPINGSIZE, /*low-orger of object size*/ + NULL); /*unnamed object*/ + + if(NULL == hFileMapping) + { + Trace("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + CloseHandle(hFile); + Fail(""); + } + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_ALL_ACCESS, /*access code*/ + 0, /*high order offset*/ + 0, /*low order offset*/ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile API to map a view" + " of file!\n", + GetLastError()); + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail(""); + } + + /* Verify that the size of the file has increased to + * accomidate the MapView. + */ + dwFinalSize = GetFileSize (hFile, NULL); + if ( (dwFinalSize <= dwInitialSize) && (dwFinalSize != MAPPINGSIZE)) + { + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail("ERROR: Size of the file was expected to " + "increase from \"%d\", to \"%d\".\n ", + dwInitialSize, + MAPPINGSIZE); + } + + /* Write to the MapView and copy the MapViewOfFile + * to buffer, so we can compare with value read from + * file directly. + */ + + memcpy(lpMapViewAddress, buf, strlen(buf)); + memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE); + + /* Read from the File handle. + */ + bRetVal = ReadFile(hFile, + readString, + strlen(buf), + &dwBytesRead, + NULL); + + if (bRetVal == FALSE) + { + Trace("ERROR: %u :unable to read from file handle " + "hFile=0x%lx\n", + GetLastError(), + hFile); + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail(""); + } + + if (memcmp(ch, readString, strlen(readString)) != 0) + { + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail("ERROR: Read string from file \"%s\", is " + "not equal to string written through MapView " + "\"%s\".\n", + readString, + ch); + } + + /* Unmap the view of file. + */ + if(UnmapViewOfFile(lpMapViewAddress) == FALSE) + { + Trace("ERROR: Failed to call UnmapViewOfFile API to" + " unmap the view of a file, error code=%u\n", + GetLastError()); + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail(""); + } + + /* Close handle to create file. + */ + if(CloseHandle(hFile) == FALSE) + { + Trace("ERROR:%u:Failed to call CloseHandle API " + "to close a file handle.", + GetLastError()); + CloseHandle(hFileMapping); + Fail(""); + } + + /* Close handle to file mapping. + */ + if(CloseHandle(hFileMapping) == FALSE) + { + Fail("ERROR:%u:Failed to call CloseHandle API " + "to close a file handle.", + GetLastError()); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/testinfo.dat new file mode 100644 index 0000000..f76333e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = MapViewOfFile +Name = Positive test MapViewOfFile API with access FILE_MAP_ALL_ACCESS +TYPE = DEFAULT +EXE1 = mapviewoffile +Description +=Test the MapViewOfFile with access FILE_MAP_ALL_ACCESS diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/CMakeLists.txt new file mode 100644 index 0000000..3b43a5e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + mapviewoffile.cpp +) + +add_executable(paltest_mapviewoffile_test4 + ${SOURCES} +) + +add_dependencies(paltest_mapviewoffile_test4 coreclrpal) + +target_link_libraries(paltest_mapviewoffile_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/mapviewoffile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/mapviewoffile.cpp new file mode 100644 index 0000000..7f32521 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/mapviewoffile.cpp @@ -0,0 +1,166 @@ +// 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. + +/*============================================================= +** +** Source: MapViewOfFile.c +** +** Purpose: Negative test the MapViewOfFile API. +** Call MapViewOfFile with all access modes, except +** read-only, on a read only map. +** +** Depends: CreateFile, +** CreateFileMapping, +** CloseHandle, +** UnMapViewOfFile. +** + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE hFile; + BOOL err; + HANDLE hFileMapping; + LPVOID lpMapViewAddress; + DWORD dwBytesWritten; + const int MAPPINGSIZE = 2048; + char buf[] = "this is a test string"; + char lpFileName[] = "test.tmp"; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a file handle with CreateFile. + */ + hFile = CreateFile( lpFileName, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), + lpFileName); + } + + /* Write to the File handle. + */ + err = WriteFile(hFile, + buf, + strlen(buf), + &dwBytesWritten, + NULL); + + if ( !FlushFileBuffers( hFile ) ) + { + CloseHandle(hFile); + Fail("ERROR: Unable to flush the buffers\n"); + } + + if (err == FALSE) + { + Trace("ERROR: %u :unable to write to file handle " + "hFile=0x%lx\n", + GetLastError(), + hFile); + CloseHandle(hFile); + Fail(""); + } + + /* Create a unnamed file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_READONLY, /*read and wite*/ + 0, /*high-order of object size*/ + 0, /*low-orger of object size*/ + NULL); /*unnamed object*/ + + if(NULL == hFileMapping) + { + Trace("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + CloseHandle(hFile); + Fail(""); + } + + /* map a writeable view of a file to a read-only file map. + */ + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_WRITE, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL != lpMapViewAddress) + { + Trace("ERROR:%u: Able to create a writeable MapViewOfFile" + " to a read-only file.\n", + GetLastError()); + CloseHandle(hFile); + CloseHandle(hFileMapping); + UnmapViewOfFile(lpMapViewAddress); + Fail(""); + } + + /* map an all access view of a file to a read-only file map. + */ + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_ALL_ACCESS, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL != lpMapViewAddress) + { + Trace("ERROR:%u: Able to create an all access MapViewOfFile" + " to a read-only file.\n", + GetLastError()); + CloseHandle(hFile); + CloseHandle(hFileMapping); + UnmapViewOfFile(lpMapViewAddress); + Fail(""); + } + + /* map an copy view of a file to a read-only file map. + */ + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_COPY, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL != lpMapViewAddress) + { + Trace("ERROR:%u: Able to create a copy access MapViewOfFile " + "to a read-only file.\n", + GetLastError()); + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail(""); + } + + /* Clean-up and Teminate. */ + CloseHandle(hFile); + CloseHandle(hFileMapping); + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/testinfo.dat new file mode 100644 index 0000000..37655ed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = MapViewOfFile +Name = Negative test MapViewOfFile API +TYPE = DEFAULT +EXE1 = mapviewoffile +Description += Negative test the MapViewOfFile API. += Call MapViewOfFile with all access modes, += except read-only, on a read only map. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/CMakeLists.txt new file mode 100644 index 0000000..ace9e60 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + mapviewoffile.cpp +) + +add_executable(paltest_mapviewoffile_test5 + ${SOURCES} +) + +add_dependencies(paltest_mapviewoffile_test5 coreclrpal) + +target_link_libraries(paltest_mapviewoffile_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/mapviewoffile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/mapviewoffile.cpp new file mode 100644 index 0000000..219b3fa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/mapviewoffile.cpp @@ -0,0 +1,131 @@ +// 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. + +/*============================================================= +** +** Source: MapViewOfFile.c +** +** Purpose: Negative test the MapViewOfFile API. +** Passing invalid values for the hFileMappingObject. +** +** Depends: CreatePipe, +** CreateFile, +** CreateFileMapping, +** CloseHandle. +** + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + + const int MAPPINGSIZE = 2048; + HANDLE hFileMapping; + LPVOID lpMapViewAddress; + HANDLE hReadPipe = NULL; + HANDLE hWritePipe = NULL; + BOOL bRetVal; + + SECURITY_ATTRIBUTES lpPipeAttributes; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Attempt to create a MapViewOfFile with a NULL handle. + */ + hFileMapping = NULL; + + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_WRITE, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + MAPPINGSIZE); /* number of bytes for map */ + + if((NULL != lpMapViewAddress) && + (GetLastError() != ERROR_INVALID_HANDLE)) + { + Trace("ERROR:%u: Able to create a MapViewOfFile with " + "hFileMapping=0x%lx.\n", + GetLastError()); + UnmapViewOfFile(lpMapViewAddress); + Fail(""); + } + + /* Attempt to create a MapViewOfFile with an invalid handle. + */ + hFileMapping = INVALID_HANDLE_VALUE; + + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_WRITE, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + MAPPINGSIZE); /* number of bytes for map */ + + if((NULL != lpMapViewAddress) && + (GetLastError() != ERROR_INVALID_HANDLE)) + { + Trace("ERROR:%u: Able to create a MapViewOfFile with " + "hFileMapping=0x%lx.\n", + GetLastError()); + UnmapViewOfFile(lpMapViewAddress); + Fail(""); + } + + /* Setup SECURITY_ATTRIBUTES structure for CreatePipe. + */ + lpPipeAttributes.nLength = sizeof(lpPipeAttributes); + lpPipeAttributes.lpSecurityDescriptor = NULL; + lpPipeAttributes.bInheritHandle = TRUE; + + /* Create a Pipe. + */ + bRetVal = CreatePipe(&hReadPipe, /* read handle*/ + &hWritePipe, /* write handle */ + &lpPipeAttributes,/* security attributes*/ + 0); /* pipe size*/ + if (bRetVal == FALSE) + { + Fail("ERROR: %ld :Unable to create pipe\n", + GetLastError()); + } + + /* Attempt creating a MapViewOfFile with a Pipe Handle. + */ + lpMapViewAddress = MapViewOfFile( + hReadPipe, + FILE_MAP_WRITE, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + MAPPINGSIZE); /* number of bytes for map */ + + if((NULL != lpMapViewAddress) && + (GetLastError() != ERROR_INVALID_HANDLE)) + { + Trace("ERROR:%u: Able to create a MapViewOfFile with " + "hFileMapping=0x%lx.\n", + GetLastError()); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + UnmapViewOfFile(lpMapViewAddress); + Fail(""); + } + + /* Clean-up and Terminate the PAL. + */ + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/testinfo.dat new file mode 100644 index 0000000..e3ecb32 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = MapViewOfFile +Name = Negative test for MapViewOfFile API. +TYPE = DEFAULT +EXE1 = mapviewoffile +Description += Negative test the MapViewOfFile API. += Passing invalid values for the hFileMappingObject. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/CMakeLists.txt new file mode 100644 index 0000000..1855c6e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + mapviewoffile.cpp +) + +add_executable(paltest_mapviewoffile_test6 + ${SOURCES} +) + +add_dependencies(paltest_mapviewoffile_test6 coreclrpal) + +target_link_libraries(paltest_mapviewoffile_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/mapviewoffile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/mapviewoffile.cpp new file mode 100644 index 0000000..f7d7302 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/mapviewoffile.cpp @@ -0,0 +1,85 @@ +// 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. + +/*============================================================= +** +** Source: MapViewOfFile.c +** +** Purpose: Positivve test the MapViewOfFile API. +** Mapping a pagefile allocation into memory +** +** Depends: CreateFileMappingW, +** UnmapViewOfFile +** CloseHandle. +** + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + + const int MAPPINGSIZE = 2048; + HANDLE hFileMapping; + LPVOID lpMapViewAddress; + char *p; + int i; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + hFileMapping = CreateFileMappingW(INVALID_HANDLE_VALUE, + NULL, + PAGE_READWRITE, + 0, + MAPPINGSIZE, + NULL); + + if (hFileMapping == NULL) { + Trace("ERROR:%u: CreateFileMappingW() failed\n", GetLastError()); + Fail(""); + } + + + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_WRITE, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + MAPPINGSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: MapViewOfFile() failed.\n", + GetLastError()); + CloseHandle(hFileMapping); + Fail(""); + } + + p = (char *)lpMapViewAddress; + for (i=0; i + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE FileMappingHandle; + HANDLE OpenFileMappingHandle; + HANDLE lpMapViewAddress; + const int LOWORDERSIZE = 1024; + char buf[] = "this is a test"; + char MapObject[] = "myMappingObject"; + char ch[1024]; + int err; + int RetVal = PASS; + + /* Initialize the PAL environment. + */ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + + /* Create a named file-mapping object with + * file handle FileHandle. + */ + FileMappingHandle = CreateFileMapping( + INVALID_HANDLE_VALUE, + NULL, /* not inherited */ + PAGE_READWRITE, /* read and write */ + 0, /* high-order size */ + LOWORDERSIZE, /* low-order size */ + MapObject); /* named object */ + + if(NULL == FileMappingHandle) + { + Fail("ERROR:%u:Failed to call CreateFileMapping to " + "create a mapping object.\n", + GetLastError()); + } + if(GetLastError() == ERROR_ALREADY_EXISTS) + { + Trace("ERROR:File mapping object already exists\n"); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Open a named file-mapping object with + * FILE_MAP_ALL_ACCESS access. + */ + OpenFileMappingHandle = OpenFileMapping( + FILE_MAP_ALL_ACCESS, + TRUE, + MapObject ); + + if(NULL == OpenFileMappingHandle) + { + Trace("ERROR:%u:Failed to Call OpenFileMapping API!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Test the opened map view. + */ + lpMapViewAddress = MapViewOfFile( + OpenFileMappingHandle, + FILE_MAP_ALL_ACCESS, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + LOWORDERSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Write to the Map View. + */ + memcpy(lpMapViewAddress, buf, strlen(buf)); + + /* Read from the Map View. + */ + memcpy(ch, (LPCSTR)lpMapViewAddress, LOWORDERSIZE); + + /* Compare what was written to the Map View, + * to what was read. + */ + if (memcmp(ch, buf, strlen(buf))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + ch, buf); + RetVal = FAIL; + goto CleanUpThree; + + } + +CleanUpThree: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Close Handle to opend file mapping. + */ + if ( CloseHandle(OpenFileMappingHandle) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + OpenFileMappingHandle); + RetVal = FAIL; + } + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(FileMappingHandle) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + FileMappingHandle); + RetVal = FAIL; + } + + + /* Terminat the PAL.*/ + PAL_TerminateEx(RetVal); + return RetVal; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/testinfo.dat new file mode 100644 index 0000000..010f2fe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = OpenFileMappingA +Name = Positive test for OpenFileMappingA API with FILE_MAP_ALL_ACCESS access +TYPE = DEFAULT +EXE1 = openfilemappinga +Description +=Test the OpenFileMappingA with FILE_MAP_ALL_ACCESS access diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/CMakeLists.txt new file mode 100644 index 0000000..6dda4b7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + OpenFileMappingA.cpp +) + +add_executable(paltest_openfilemappinga_test2 + ${SOURCES} +) + +add_dependencies(paltest_openfilemappinga_test2 coreclrpal) + +target_link_libraries(paltest_openfilemappinga_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/OpenFileMappingA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/OpenFileMappingA.cpp new file mode 100644 index 0000000..5e41a92 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/OpenFileMappingA.cpp @@ -0,0 +1,214 @@ +// 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. + +/*============================================================= +** +** Source: openfilemappinga.c (test 2) +** +** Purpose: Positive test the OpenFileMapping API. +** Call OpenFileMapping to open a named file-mapping +** object with FILE_MAP_WRITE access +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE FileMappingHandle; + HANDLE OpenFileMappingHandle; + HANDLE lpMapViewAddress; + HANDLE OpenFileMappingHandle2; + HANDLE lpMapViewAddress2; + const int LOWORDERSIZE = 1024; + char MapObject[] = "myMappingObject"; + char buf[] = "this is a test"; + char ch[1024]; + int RetVal = PASS; + + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a named file-mapping object with file handle FileHandle. + */ + FileMappingHandle = CreateFileMapping( + INVALID_HANDLE_VALUE, + NULL, /* not inherited */ + PAGE_READWRITE, /* read and write */ + 0, /* high-order size */ + LOWORDERSIZE, /* low-order size */ + MapObject); /* named object */ + + + if(NULL == FileMappingHandle) + { + Fail("\nFailed to call CreateFileMapping to create " + "a mapping object!\n"); + } + if(GetLastError() == ERROR_ALREADY_EXISTS) + { + Trace("\nFile mapping object already exists!\n"); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Open a named file-mapping object with FILE_MAP_WRITE access. + */ + OpenFileMappingHandle = OpenFileMapping( + FILE_MAP_WRITE, + FALSE, + MapObject); + + if(NULL == OpenFileMappingHandle) + { + Trace("\nFailed to Call OpenFileMapping API!\n"); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Open a named file-mapping object with + * FILE_MAP_ALL_ACCESS access, to verify + * the FILE_MAP_WRITE access map. + */ + OpenFileMappingHandle2 = OpenFileMapping( + FILE_MAP_ALL_ACCESS, + FALSE, + MapObject); + + if(NULL == OpenFileMappingHandle2) + { + Trace("\nFailed to Call OpenFileMapping API!\n"); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Create map view of the open mapping that has + * FILE_MAP_WRITE access. + */ + lpMapViewAddress = MapViewOfFile( + OpenFileMappingHandle, + FILE_MAP_WRITE, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + LOWORDERSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpThree; + } + + /* Create map view of the open mapping that has + * FILE_MAP_ALL_ACCESS access. + */ + lpMapViewAddress2 = MapViewOfFile( + OpenFileMappingHandle2, + FILE_MAP_ALL_ACCESS, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + LOWORDERSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress2) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpFour; + } + + /* Write to the Map View. + */ + memcpy(lpMapViewAddress, buf, strlen(buf)); + + /* Read from the Map View. + */ + memcpy(ch, (LPCSTR)lpMapViewAddress, LOWORDERSIZE); + + /* Compare what was written to the Map View, + * to what was read. + */ + if (memcmp(ch, buf, strlen(buf))!= 0) + { + Fail("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + ch, buf); + RetVal = FAIL; + goto CleanUpFive; + } + +CleanUpFive: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress2) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress2); + RetVal = FAIL; + } + +CleanUpFour: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress); + RetVal = FAIL; + } + +CleanUpThree: + + /* Close Handle to opened file mapping. + */ + if ( CloseHandle(OpenFileMappingHandle2) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + OpenFileMappingHandle2); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Close Handle to opened file mapping. + */ + if ( CloseHandle(OpenFileMappingHandle) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + OpenFileMappingHandle); + RetVal = FAIL; + } + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(FileMappingHandle) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + FileMappingHandle); + RetVal = FAIL; + } + + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/testinfo.dat new file mode 100644 index 0000000..2a02128 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = OpenFileMappingA +Name = Positive test for OpenFileMappingA API with FILE_MAP_WRITE access +TYPE = DEFAULT +EXE1 = openfilemappinga +Description +=Test the OpenFileMappingA with FILE_MAP_WRITE access diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/CMakeLists.txt new file mode 100644 index 0000000..8bcd7c4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + OpenFileMappingA.cpp +) + +add_executable(paltest_openfilemappinga_test3 + ${SOURCES} +) + +add_dependencies(paltest_openfilemappinga_test3 coreclrpal) + +target_link_libraries(paltest_openfilemappinga_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/OpenFileMappingA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/OpenFileMappingA.cpp new file mode 100644 index 0000000..b01a3e8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/OpenFileMappingA.cpp @@ -0,0 +1,217 @@ +// 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. + +/*============================================================= +** +** Source: openfilemappinga.c +** +** Purpose: Positive test the OpenFileMapping API. +** Call OpenFileMapping to open a named file-mapping +** object with FILE_MAP_READ access +** +** +**============================================================*/ +#include + + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE FileMappingHandle; + HANDLE OpenFileMappingHandle; + HANDLE OpenFileMappingHandle2; + HANDLE lpMapViewAddress; + HANDLE lpMapViewAddress2; + const int LOWORDERSIZE = 1024; + char buf[] = "this is a test"; + char MapObject[] = "myMappingObject"; + char ch[1024]; + int RetVal = PASS; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a named file-mapping object with file handle FileHandle. + */ + FileMappingHandle = CreateFileMapping( + INVALID_HANDLE_VALUE, + NULL, /* Not inherited */ + PAGE_READWRITE, /* Read only */ + 0, /* High-order size */ + LOWORDERSIZE, /* Must be none 0 */ + MapObject); /* Named object */ + + + if(NULL == FileMappingHandle) + { + Fail("ERROR:%u:Failed to call CreateFileMapping to create " + "mapping object = \"%s\".\n", + GetLastError(), + MapObject); + } + if(GetLastError() == ERROR_ALREADY_EXISTS) + { + Trace("ERROR:File mapping object \"%s\" already exists!\n", + MapObject); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Open a named file-mapping object with + * FILE_MAP_READ access. + */ + OpenFileMappingHandle = OpenFileMapping( + FILE_MAP_READ, + 0, + MapObject); + + if(NULL == OpenFileMappingHandle) + { + Trace("ERROR:%u: Failed to Call OpenFileMapping API.\n"); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Open a named file-mapping object with + * FILE_MAP_ALL_ACCESS access, to verify the + * READ-ONLY Map view. + */ + OpenFileMappingHandle2 = OpenFileMapping( + FILE_MAP_ALL_ACCESS, + 0, + MapObject); + + if(NULL == OpenFileMappingHandle2) + { + Trace("Failed to Call OpenFileMapping API!\n"); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Test the opened map view. + */ + lpMapViewAddress = MapViewOfFile( + OpenFileMappingHandle, + FILE_MAP_READ, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + LOWORDERSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpThree; + } + + /* Open the second Map view to verify the writing + * of the READ-ONLY Map view. + */ + lpMapViewAddress2 = MapViewOfFile( + OpenFileMappingHandle2, + FILE_MAP_ALL_ACCESS, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + LOWORDERSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress2) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpFour; + } + + /* Write to the ALL_ACCESS Map View. + */ + memcpy(lpMapViewAddress2, buf, strlen(buf)); + + /* Read from the READ-ONLY Map View. + */ + memcpy(ch, (LPCSTR)lpMapViewAddress, LOWORDERSIZE); + + /* Compare what was written to the Map View, + * to what was read. + */ + if (memcmp(ch, buf, strlen(buf))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + ch, buf); + RetVal = FAIL; + goto CleanUpFive; + } + +CleanUpFive: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress2) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress2); + RetVal = FAIL; + } + +CleanUpFour: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress); + RetVal = FAIL; + } + +CleanUpThree: + + /* Close Handle to opened file mapping. + */ + if ( CloseHandle(OpenFileMappingHandle2) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + OpenFileMappingHandle2); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Close Handle to opened file mapping. + */ + if ( CloseHandle(OpenFileMappingHandle) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + OpenFileMappingHandle); + RetVal = FAIL; + } + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(FileMappingHandle) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + FileMappingHandle); + RetVal = FAIL; + } + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/testinfo.dat new file mode 100644 index 0000000..4aff853 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = OpenFileMappingA +Name = Positive test for OpenFileMappingA API with FILE_MAP_READ access +TYPE = DEFAULT +EXE1 = openfilemappinga +Description +=Test the OpenFileMappingA with FILE_MAP_READ access diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/CMakeLists.txt new file mode 100644 index 0000000..20b340f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + OpenFileMappingW.cpp +) + +add_executable(paltest_openfilemappingw_test1 + ${SOURCES} +) + +add_dependencies(paltest_openfilemappingw_test1 coreclrpal) + +target_link_libraries(paltest_openfilemappingw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/OpenFileMappingW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/OpenFileMappingW.cpp new file mode 100644 index 0000000..079af4a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/OpenFileMappingW.cpp @@ -0,0 +1,155 @@ +// 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. + +/*============================================================= +** +** Source: openfilemappingw.c (test 1) +** +** Purpose: Positive test the OpenFileMapping API. +** Call OpenFileMapping to open a named file-mapping +** object with FILE_MAP_ALL_ACCESS access +** +** +**============================================================*/ + +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE lpMapViewAddress; + char buf[] = "this is a test"; + char ch[1024]; + + HANDLE FileMappingHandle; + HANDLE OpenFileMappingHandle; + const int LOWORDERSIZE = 1024; + int RetVal = PASS; + WCHAR wpMappingFileObject[] = {'m','y','O','b','j','e','c','t','\0'}; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a unnamed file-mapping object with file handle FileHandle. + */ + FileMappingHandle = CreateFileMapping( + INVALID_HANDLE_VALUE, + NULL, /* Not inherited*/ + PAGE_READWRITE, /* Read and write*/ + 0, /* High-order size*/ + LOWORDERSIZE, /* Low-order size*/ + wpMappingFileObject);/* Named object*/ + + + if(NULL == FileMappingHandle) + { + Fail("\nFailed to call CreateFileMapping to create a " + "mapping object!\n"); + } + if(GetLastError() == ERROR_ALREADY_EXISTS) + { + Trace("\nFile mapping object already exists!\n"); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Open a named file-mapping object with FILE_MAP_ALL_ACCESS access. + */ + OpenFileMappingHandle = OpenFileMapping( + FILE_MAP_ALL_ACCESS, + FALSE, + wpMappingFileObject); + + if(NULL == OpenFileMappingHandle) + { + Trace("\nFailed to Call OpenFileMapping API!\n"); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Test the opened map view. + */ + lpMapViewAddress = MapViewOfFile( + OpenFileMappingHandle, + FILE_MAP_ALL_ACCESS, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + LOWORDERSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Write to the Map View. + */ + memcpy(lpMapViewAddress, buf, strlen(buf)); + + /* Read from the Map View. + */ + memcpy(ch, (LPCSTR)lpMapViewAddress, LOWORDERSIZE); + + /* Compare what was written to the Map View, + * to what was read. + */ + if (memcmp(ch, buf, strlen(buf))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + ch, buf); + RetVal = FAIL; + goto CleanUpThree; + } + +CleanUpThree: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Close Handle to opend file mapping. + */ + if ( CloseHandle(OpenFileMappingHandle) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + OpenFileMappingHandle); + RetVal = FAIL; + } + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(FileMappingHandle) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + FileMappingHandle); + RetVal = FAIL; + } + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/testinfo.dat new file mode 100644 index 0000000..e67f477 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = OpenFileMappingW +Name = Positive test for OpenFileMappingW API +TYPE = DEFAULT +EXE1 = openfilemappingw +Description +=Test the OpenFileMappingW with FILE_MAP_ALL_ACCESS access diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/CMakeLists.txt new file mode 100644 index 0000000..4f50f1e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + OpenFileMappingW.cpp +) + +add_executable(paltest_openfilemappingw_test2 + ${SOURCES} +) + +add_dependencies(paltest_openfilemappingw_test2 coreclrpal) + +target_link_libraries(paltest_openfilemappingw_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/OpenFileMappingW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/OpenFileMappingW.cpp new file mode 100644 index 0000000..e6a6965 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/OpenFileMappingW.cpp @@ -0,0 +1,217 @@ +// 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. + +/*============================================================= +** +** Source: openfilemappingw.c (test 2) +** +** Purpose: Positive test the OpenFileMapping API. +** Call OpenFileMapping to open a named file-mapping +** object with FILE_MAP_WRITE access +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE FileMappingHandle; + HANDLE OpenFileMappingHandle; + HANDLE lpMapViewAddress; + HANDLE OpenFileMappingHandle2; + HANDLE lpMapViewAddress2; + const int LOWORDERSIZE = 1024; + WCHAR MapObject[] = {'m','y','O','b','j','e','c','t','\0'}; + char buf[] = "this is a test"; + char ch[1024]; + int RetVal = PASS; + + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a named file-mapping object with file handle FileHandle. + */ + FileMappingHandle = CreateFileMapping( + INVALID_HANDLE_VALUE, + NULL, /* not inherited */ + PAGE_READWRITE, /* read and wite */ + 0, /* high-order size */ + LOWORDERSIZE, /* low-order size */ + MapObject); /* named object */ + + if(NULL == FileMappingHandle) + { + Fail("\nFailed to call CreateFileMapping to " + "create a mapping object!\n"); + } + if(GetLastError() == ERROR_ALREADY_EXISTS) + { + Trace("\nFile mapping object already exists!\n"); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Open a named file-mapping object with FILE_MAP_WRITE access. + */ + OpenFileMappingHandle = OpenFileMapping( + FILE_MAP_WRITE, + FALSE, + MapObject); + + if(NULL == OpenFileMappingHandle) + { + Trace("\nFailed to Call OpenFileMappingW API!\n"); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Open a named file-mapping object with + * FILE_MAP_ALL_ACCESS access, to verify + * the FILE_MAP_WRITE access map. + */ + OpenFileMappingHandle2 = OpenFileMapping( + FILE_MAP_ALL_ACCESS, + FALSE, + MapObject); + + if(NULL == OpenFileMappingHandle2) + { + Trace("\nFailed to Call OpenFileMappingW API!\n"); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Create map view of the open mapping that has + * FILE_MAP_WRITE access. + */ + lpMapViewAddress = MapViewOfFile( + OpenFileMappingHandle, + FILE_MAP_WRITE, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + LOWORDERSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpThree; + } + + /* Create map view of the open mapping that has + * FILE_MAP_ALL_ACCESS access. + */ + + lpMapViewAddress2 = MapViewOfFile( + OpenFileMappingHandle2, + FILE_MAP_ALL_ACCESS, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + LOWORDERSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress2) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpFour; + } + + /* Write to the Map View. + */ + memcpy(lpMapViewAddress, buf, strlen(buf)); + + /* Read from the Map View. + */ + memcpy(ch, (LPCSTR)lpMapViewAddress, LOWORDERSIZE); + + /* Compare what was written to the Map View, + * to what was read. + */ + if (memcmp(ch, buf, strlen(buf))!= 0) + { + + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + ch, buf); + RetVal = FAIL; + goto CleanUpFive; + } + + +CleanUpFive: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress2) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress2); + RetVal = FAIL; + } + +CleanUpFour: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress); + RetVal = FAIL; + } + +CleanUpThree: + + /* Close Handle to opened file mapping. + */ + if ( CloseHandle(OpenFileMappingHandle2) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + OpenFileMappingHandle2); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Close Handle to opened file mapping. + */ + if ( CloseHandle(OpenFileMappingHandle) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + OpenFileMappingHandle); + RetVal = FAIL; + } + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(FileMappingHandle) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + FileMappingHandle); + RetVal = FAIL; + } + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/testinfo.dat new file mode 100644 index 0000000..d481560 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = OpenFileMappingW +Name = Positive test for OpenFileMappingW API +TYPE = DEFAULT +EXE1 = openfilemappingw +Description +=Test the OpenFileMappingW with FILE_MAP_WRITE access diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/CMakeLists.txt new file mode 100644 index 0000000..3fc9328 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + OpenFileMappingW.cpp +) + +add_executable(paltest_openfilemappingw_test3 + ${SOURCES} +) + +add_dependencies(paltest_openfilemappingw_test3 coreclrpal) + +target_link_libraries(paltest_openfilemappingw_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/OpenFileMappingW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/OpenFileMappingW.cpp new file mode 100644 index 0000000..9c83491 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/OpenFileMappingW.cpp @@ -0,0 +1,210 @@ +// 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. + +/*============================================================= +** +** Source: openfilemappingw.c (test 3) +** +** Purpose: Positive test the OpenFileMappingW API. +** Call OpenFileMappingW to open a named file-mapping +** object with FILE_MAP_READ access +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + char buf[] = "this is a test"; + char ch[1024]; + HANDLE FileMappingHandle; + HANDLE OpenFileMappingHandle; + HANDLE OpenFileMappingHandle2; + HANDLE lpMapViewAddress; + HANDLE lpMapViewAddress2; + const int LOWORDERSIZE = 1024; + int RetVal = PASS; + WCHAR wpMappingFileObject[] = {'m','y','O','b','j','e','c','t','\0'}; + + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a unnamed file-mapping object with file handle FileHandle. + */ + FileMappingHandle = CreateFileMapping( + INVALID_HANDLE_VALUE, + NULL, /* not inherited */ + PAGE_READWRITE, /* read and wite */ + 0, /* high-order size */ + LOWORDERSIZE, /* must be non-zero */ + wpMappingFileObject);/* named object */ + + if(NULL == FileMappingHandle) + { + Fail("\nFailed to call CreateFileMapping to create mapping object!\n"); + } + if(GetLastError() == ERROR_ALREADY_EXISTS) + { + Trace("\nFile mapping object already exists!\n"); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Open a named file-mapping object with FILE_MAP_ALL_ACCESS access. + */ + OpenFileMappingHandle = OpenFileMapping( + FILE_MAP_READ, + FALSE, + wpMappingFileObject); + + if(NULL == OpenFileMappingHandle) + { + Trace("\nFailed to Call OpenFileMapping API!\n"); + RetVal = FAIL; + goto CleanUpOne; + } + + /* Open a file mapping with FILE_MAP_ALL_ACCESS access, + * to verify the FILE_MAP_READ. + */ + OpenFileMappingHandle2 = OpenFileMapping( + FILE_MAP_ALL_ACCESS, + FALSE, + wpMappingFileObject); + + if(NULL == OpenFileMappingHandle2) + { + Trace("\nFailed to Call OpenFileMapping API!\n"); + RetVal = FAIL; + goto CleanUpTwo; + } + + /* Test the opened map view. + */ + lpMapViewAddress = MapViewOfFile( + OpenFileMappingHandle, + FILE_MAP_READ, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + LOWORDERSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpThree; + } + + /* Open a map view with FILE_MAP_ALL_ACCESS to verify, + * the FILE_MAP_READ view. + */ + lpMapViewAddress2 = MapViewOfFile( + OpenFileMappingHandle2, + FILE_MAP_ALL_ACCESS, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + LOWORDERSIZE); /* number of bytes for map */ + + if(NULL == lpMapViewAddress2) + { + Trace("2ERROR:%u: Failed to call MapViewOfFile " + "API to map a view of file!\n", + GetLastError()); + RetVal = FAIL; + goto CleanUpFour; + } + + /* Write to the Map View. + */ + memcpy(lpMapViewAddress2, buf, strlen(buf)); + /* Read from the Map View. + */ + memcpy(ch, (LPCSTR)lpMapViewAddress, LOWORDERSIZE); + + /* Compare what was written to the Map View, + * to what was read. + */ + if (memcmp(ch, buf, strlen(buf))!= 0) + { + Trace("ERROR: MapViewOfFile not equal to file contents " + "retrieved \"%s\", expected \"%s\".\n", + ch, + buf); + RetVal = FAIL; + goto CleanUpFive; + } + +CleanUpFive: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress2) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress2); + RetVal = FAIL; + } + +CleanUpFour: + + /* Unmap the view of file. + */ + if ( UnmapViewOfFile(lpMapViewAddress) == FALSE ) + { + Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n", + GetLastError(), + lpMapViewAddress); + RetVal = FAIL; + } + +CleanUpThree: + + /* Close Handle to opened file mapping. + */ + if ( CloseHandle(OpenFileMappingHandle2) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + OpenFileMappingHandle2); + RetVal = FAIL; + } + +CleanUpTwo: + + /* Close Handle to opened file mapping. + */ + if ( CloseHandle(OpenFileMappingHandle) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + OpenFileMappingHandle); + RetVal = FAIL; + } + +CleanUpOne: + + /* Close Handle to create file mapping. + */ + if ( CloseHandle(FileMappingHandle) == 0 ) + { + Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n", + GetLastError(), + FileMappingHandle); + RetVal = FAIL; + } + + /* Terminate the PAL. + */ + PAL_TerminateEx(RetVal); + return RetVal; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/testinfo.dat new file mode 100644 index 0000000..b4ac69e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = OpenFileMappingW +Name = Positive test for OpenFileMappingW API with FILE_MAP_READ access +TYPE = DEFAULT +EXE1 = openfilemappingw +Description +=Test the OpenFileMappingW with FILE_MAP_READ access diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/CMakeLists.txt new file mode 100644 index 0000000..680635f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(ProbeMemory_neg1) +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/CMakeLists.txt new file mode 100644 index 0000000..50eaf4a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + ProbeMemory_neg.cpp +) + +add_executable(paltest_probememory_probememory_neg1 + ${SOURCES} +) + +add_dependencies(paltest_probememory_probememory_neg1 coreclrpal) + +target_link_libraries(paltest_probememory_probememory_neg1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/ProbeMemory_neg.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/ProbeMemory_neg.cpp new file mode 100644 index 0000000..80de809 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/ProbeMemory_neg.cpp @@ -0,0 +1,95 @@ +// 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. + +/*============================================================= +** +** Source: ReadProcessMemory_neg.c +** +** Purpose: Negative test the ReadProcessMemory API. +** Call ReadProcessMemory to read unreadabel memory area +** +** +**============================================================*/ +#include + +#define REGIONSIZE 1024 + +int __cdecl main(int argc, char *argv[]) +{ + int err; + BOOL bResult; + LPVOID lpProcessAddress = NULL; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*allocate the virtual memory*/ + lpProcessAddress = VirtualAlloc( + NULL, /*system determine where to allocate the region*/ + REGIONSIZE, /*specify the size*/ + MEM_RESERVE, /*allocation type*/ + PAGE_READONLY); /*access protection*/ + + if(NULL == lpProcessAddress) + { + Fail("\nFailed to call VirtualAlloc API to allocate " + "virtual memory, error code=%u\n", GetLastError()); + } + + /*try to probe the unreadable memory area*/ + bResult = PAL_ProbeMemory( + lpProcessAddress, /*base of memory area*/ + REGIONSIZE, /*buffer length in bytes*/ + FALSE); /*read access*/ + + /*check the return value*/ + if(bResult) + { + Trace("\nProbeMemory for read didn't FAILED\n"); + + /*decommit the specified region*/ + err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); + } + + Fail(""); + } + + /*try to probe the unwriteable memory area*/ + bResult = PAL_ProbeMemory( + lpProcessAddress, /*base of memory area*/ + REGIONSIZE, /*buffer length in bytes*/ + FALSE); /*write access */ + + /*check the return value*/ + if(bResult) + { + Trace("\nProbeMemory for write didn't FAILED\n"); + + /*decommit the specified region*/ + err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); + } + + Fail(""); + } + + /*decommit the specified region*/ + err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/testinfo.dat new file mode 100644 index 0000000..4d11a71 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = PAL_ProbeMemory +Name = Negative test PAL_ProbeMemory API to read unreadable memory area +TYPE = DEFAULT +EXE1 = probememory_neg +Description +=Test the PAL_ProbeMemory to read unreadable memory area diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/CMakeLists.txt new file mode 100644 index 0000000..08308e0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + ProbeMemory.cpp +) + +add_executable(paltest_probememory_test1 + ${SOURCES} +) + +add_dependencies(paltest_probememory_test1 coreclrpal) + +target_link_libraries(paltest_probememory_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/ProbeMemory.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/ProbeMemory.cpp new file mode 100644 index 0000000..30b358d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/ProbeMemory.cpp @@ -0,0 +1,94 @@ +// 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. + +/*============================================================= +** +** Source: ReadProcessMemory.c +** +** Purpose: Positive test the ReadProcessMemory API. +** Call ReadProcessMemory to read memory contents +** inside current process. +** +** +**============================================================*/ +#include + +#define REGIONSIZE 1024 + +int __cdecl main(int argc, char *argv[]) +{ + int err; + BOOL bResult; + LPVOID lpProcessAddress = NULL; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*allocate the virtual memory*/ + lpProcessAddress = VirtualAlloc( + NULL, /*system determine where to allocate the region*/ + REGIONSIZE, /*specify the size*/ + MEM_COMMIT, /*allocation type*/ + PAGE_READWRITE); /*access protection*/ + + if(NULL == lpProcessAddress) + { + Fail("\nFailed to call VirtualAlloc API to allocate " + "virtual memory, error code=%u!\n", GetLastError()); + } + + /*probe the memory for read*/ + bResult = PAL_ProbeMemory( + lpProcessAddress, /*base of memory area*/ + REGIONSIZE, /*buffer length in bytes*/ + FALSE); /*read access*/ + + if(!bResult) + { + Trace("\nProbeMemory for read access FAILED\n"); + + /*decommit the specified region*/ + err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); + } + + Fail(""); + } + + /*probe the memory for write */ + bResult = PAL_ProbeMemory( + lpProcessAddress, /*base of memory area*/ + REGIONSIZE, /*buffer length in bytes*/ + TRUE); /*write access*/ + + if(!bResult) + { + Trace("\nProbeMemory for write access FAILED\n"); + + /*decommit the specified region*/ + err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); + } + + Fail(""); + } + + /*decommit the specified region*/ + err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/testinfo.dat new file mode 100644 index 0000000..512b945 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = PAL_ProbeMemory +Name = Positive test for PAL_ProbeMemory API to probe for read/write +TYPE = DEFAULT +EXE1 = probememory +Description +=Test the PAL_ProbeMemory to probe for read and write diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/CMakeLists.txt new file mode 100644 index 0000000..8ada94f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + UnmapViewOfFile.cpp +) + +add_executable(paltest_unmapviewoffile_test1 + ${SOURCES} +) + +add_dependencies(paltest_unmapviewoffile_test1 coreclrpal) + +target_link_libraries(paltest_unmapviewoffile_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/UnmapViewOfFile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/UnmapViewOfFile.cpp new file mode 100644 index 0000000..a970ccc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/UnmapViewOfFile.cpp @@ -0,0 +1,184 @@ +// 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. + +/*============================================================= +** +** Source: UnMapViewOfFile.c +** +** Purpose: Positive test the MapViewOfFile API. +** Call MapViewOfFile with access FILE_MAP_ALL_ACCESS. +** +** Depends: CreateFile, +** GetFileSize, +** memset, +** memcpy, +** memcmp, +** ReadFile, +** UnMapViewOfFile, +** CreateFileMapping, +** CloseHandle. + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + const int MappingSize = 2048; + HANDLE hFile; + HANDLE hFileMapping; + LPVOID lpMapViewAddress; + char buf[] = "this is a test string"; + char ch[2048]; + char readString[2048]; + char lpFileName[] = "test.tmp"; + DWORD dwBytesRead; + BOOL bRetVal; + + /* Initialize the PAL environment. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Create a file handle with CreateFile. + */ + hFile = CreateFile( lpFileName, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), + lpFileName); + } + + /* Initialize the buffers. + */ + memset(ch, 0, MappingSize); + memset(readString, 0, MappingSize); + + /* Create a unnamed file-mapping object with file handle FileHandle + * and with PAGE_READWRITE protection. + */ + hFileMapping = CreateFileMapping( + hFile, + NULL, /*not inherited*/ + PAGE_READWRITE, /*read and wite*/ + 0, /*high-order of object size*/ + MappingSize, /*low-orger of object size*/ + NULL); /*unnamed object*/ + + if(NULL == hFileMapping) + { + Trace("ERROR:%u: Failed to create File Mapping.\n", + GetLastError()); + CloseHandle(hFile); + Fail(""); + } + + /* maps a view of a file into the address space of the calling process. + */ + lpMapViewAddress = MapViewOfFile( + hFileMapping, + FILE_MAP_ALL_ACCESS, /* access code */ + 0, /* high order offset */ + 0, /* low order offset */ + MappingSize); /* number of bytes for map */ + + if(NULL == lpMapViewAddress) + { + Trace("ERROR:%u: Failed to call MapViewOfFile API to map a view" + " of file!\n", + GetLastError()); + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail(""); + } + + /* Write to the MapView and copy the MapViewOfFile + * to buffer, so we can compare with value read from + * file directly. + */ + + memcpy(lpMapViewAddress, buf, strlen(buf)); + memcpy(ch, (LPCSTR)lpMapViewAddress, MappingSize); + + /* Read from the File handle. + */ + bRetVal = ReadFile(hFile, + readString, + strlen(buf), + &dwBytesRead, + NULL); + + if (bRetVal == FALSE) + { + Trace("ERROR: %u :unable to read from file handle " + "hFile=0x%lx\n", + GetLastError(), + hFile); + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail(""); + } + + if (memcmp(ch, readString, strlen(readString)) != 0) + { + Trace("ERROR: Read string from file \"%s\", is " + "not equal to string written through MapView " + "\"%s\".\n", + readString, + ch); + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail(""); + } + + /* Unmap the view of file. + */ + if(UnmapViewOfFile(lpMapViewAddress) == FALSE) + { + Trace("ERROR: Failed to call UnmapViewOfFile API to" + " unmap the view of a file, error code=%u\n", + GetLastError()); + CloseHandle(hFile); + CloseHandle(hFileMapping); + Fail(""); + } + + /* Re-initialize the buffer. + */ + memset(ch, 0, MappingSize); + + /* Close handle to created file mapping. + */ + if(CloseHandle(hFileMapping) == FALSE) + { + Trace("ERROR:%u:Failed to call CloseHandle API " + "to close a file mapping handle.", + GetLastError()); + CloseHandle(hFile); + Fail(""); + } + + /* Close handle to create file. + */ + if(CloseHandle(hFile) == FALSE) + { + Fail("ERROR:%u:Failed to call CloseHandle API " + "to close a file handle.", + GetLastError()); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/testinfo.dat new file mode 100644 index 0000000..8418015 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = UnmapViewOfFile +Name = Positive test UnmapViewOfFile API to unmap a view of file +TYPE = DEFAULT +EXE1 = unmapviewoffile +LANG = cpp +Description += Test the UnmapViewOfFile to unmap a view of file. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/CMakeLists.txt new file mode 100644 index 0000000..958e36b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + unmapviewoffile.cpp +) + +add_executable(paltest_unmapviewoffile_test2 + ${SOURCES} +) + +add_dependencies(paltest_unmapviewoffile_test2 coreclrpal) + +target_link_libraries(paltest_unmapviewoffile_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/testinfo.dat new file mode 100644 index 0000000..29e847a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = UnmapViewOfFile +Name = Negative test UnmapViewOfFile API to unmap a view of file +TYPE = DEFAULT +EXE1 = unmapviewoffile +Description += Test the UnmapViewOfFile to unmap a view of file += negative test by passing a NULL mapping address. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/unmapviewoffile.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/unmapviewoffile.cpp new file mode 100644 index 0000000..2ca185d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/unmapviewoffile.cpp @@ -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. + +/*============================================================= +** +** Source: UnmapViewOfFile.c (test 2) +** +** Purpose: Negative test the UnmapViewOfFile API. +** Call UnmapViewOfFile to unmap a view of +** NULL. +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /* Negative test the UnmapViewOfFile by passing a NULL*/ + /* mapping address handle*/ + err = UnmapViewOfFile(NULL); + if(0 != err) + { + Fail("ERROR: Able to call UnmapViewOfFile API " + "by passing a NULL mapping address.\n" ); + + } + + /* Terminate the PAL. + */ + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/CMakeLists.txt new file mode 100644 index 0000000..0960bf9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/CMakeLists.txt @@ -0,0 +1,23 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test20) +add_subdirectory(test21) +add_subdirectory(test22) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/CMakeLists.txt new file mode 100644 index 0000000..9f5f71e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test1 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test1 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/VirtualAlloc.cpp new file mode 100644 index 0000000..26ee942 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/VirtualAlloc.cpp @@ -0,0 +1,50 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_COMMIT allocation type +** and PAGE_READONLY access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT, //allocation type + PAGE_READONLY); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/testinfo.dat new file mode 100644 index 0000000..5b8311a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT allocation type +=and PAGE_READONLY access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/CMakeLists.txt new file mode 100644 index 0000000..0d04c27 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test10 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test10 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/VirtualAlloc.cpp new file mode 100644 index 0000000..ac06b9b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/VirtualAlloc.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_RESERVE allocation type +** and PAGE_EXECUTE_READ access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_RESERVE, //allocation type + PAGE_EXECUTE_READ); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/testinfo.dat new file mode 100644 index 0000000..960f226 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_RESERVE allocation type +=and PAGE_EXECUTE_READ access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/CMakeLists.txt new file mode 100644 index 0000000..f9b2425 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test11 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test11 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test11 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/VirtualAlloc.cpp new file mode 100644 index 0000000..a3df39b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/VirtualAlloc.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_RESERVE allocation type +** and PAGE_READONLY access protection +** + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_RESERVE, //allocation type + PAGE_EXECUTE_READWRITE); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/testinfo.dat new file mode 100644 index 0000000..5d9f0ad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_RESERVE allocation type +=and PAGE_EXECUTE_READWRITE access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/CMakeLists.txt new file mode 100644 index 0000000..34b271f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test12 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test12 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/VirtualAlloc.cpp new file mode 100644 index 0000000..8b35086 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/VirtualAlloc.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_RESERVE allocation type +** and PAGE_NOACCESS access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_RESERVE, //allocation type + PAGE_NOACCESS); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/testinfo.dat new file mode 100644 index 0000000..ac2b91c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT allocation type +=and PAGE_NOACCESS access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/CMakeLists.txt new file mode 100644 index 0000000..bb1c11f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test13 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test13 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test13 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/VirtualAlloc.cpp new file mode 100644 index 0000000..d2109c0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/VirtualAlloc.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type +** and PAGE_READONLY access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT|MEM_TOP_DOWN, //allocation type + PAGE_READONLY); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/testinfo.dat new file mode 100644 index 0000000..a571e9f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type +=and PAGE_READONLY access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/CMakeLists.txt new file mode 100644 index 0000000..8f994b1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test14 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test14 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test14 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/VirtualAlloc.cpp new file mode 100644 index 0000000..49bd218 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/VirtualAlloc.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type +** and PAGE_READWRITE access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT|MEM_TOP_DOWN, //allocation type + PAGE_READWRITE); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/testinfo.dat new file mode 100644 index 0000000..60decb8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type +=and PAGE_READWRITE access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/CMakeLists.txt new file mode 100644 index 0000000..cd00816 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test15 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test15 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test15 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/VirtualAlloc.cpp new file mode 100644 index 0000000..3cf1502 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/VirtualAlloc.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type +** and PAGE_EXECUTE access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT|MEM_TOP_DOWN, //allocation type + PAGE_EXECUTE); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/testinfo.dat new file mode 100644 index 0000000..2d9845d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type +=and PAGE_EXECUTE access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/CMakeLists.txt new file mode 100644 index 0000000..7743531 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test16 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test16 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test16 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/VirtualAlloc.cpp new file mode 100644 index 0000000..ce61b9a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/VirtualAlloc.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type +** and PAGE_EXECUTE_READ access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT|MEM_TOP_DOWN, //allocation type + PAGE_EXECUTE_READ); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/testinfo.dat new file mode 100644 index 0000000..1389f1f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type +=and PAGE_EXECUTE_READ access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/CMakeLists.txt new file mode 100644 index 0000000..166eb99 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test17 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test17 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test17 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/VirtualAlloc.cpp new file mode 100644 index 0000000..eb609f1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/VirtualAlloc.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type +** and PAGE_READONLY access protection +** + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT|MEM_TOP_DOWN, //allocation type + PAGE_EXECUTE_READWRITE); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/testinfo.dat new file mode 100644 index 0000000..49ced63 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type +=and PAGE_EXECUTE_READWRITE access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/CMakeLists.txt new file mode 100644 index 0000000..eef8a48 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test18 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test18 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test18 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/VirtualAlloc.cpp new file mode 100644 index 0000000..e46da85 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/VirtualAlloc.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type +** and PAGE_NOACCESS access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT|MEM_TOP_DOWN, //allocation type + PAGE_NOACCESS); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/testinfo.dat new file mode 100644 index 0000000..1fd4ac6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type +=and PAGE_NOACCESS access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/CMakeLists.txt new file mode 100644 index 0000000..b2c5b8a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test19 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test19 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test19 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/VirtualAlloc.cpp new file mode 100644 index 0000000..5cbe48b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/VirtualAlloc.cpp @@ -0,0 +1,51 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc to reserve and commit +** simultaneously with MEM_COMMIT|MEM_RESERVE|MEM_TOP_DOWN +** allocation type and PAGE_READONLY access +** protection +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //reserve and commit simultaneously by using MEM_COMMIT|MEM_RESERVE + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT|MEM_RESERVE|MEM_TOP_DOWN, //allocation type + PAGE_READONLY); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/testinfo.dat new file mode 100644 index 0000000..6e427da --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc to reserve and commit +=simultaneously by using MEM_COMMIT|MEM_RESERVE|MEM_TOP_DOWN +=allocation type and PAGE_READONLY access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/CMakeLists.txt new file mode 100644 index 0000000..520cadc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test2 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test2 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/VirtualAlloc.cpp new file mode 100644 index 0000000..99cf76a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/VirtualAlloc.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_COMMIT allocation type +** and PAGE_READWRITE access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT, //allocation type + PAGE_READWRITE); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/testinfo.dat new file mode 100644 index 0000000..c7d8b67 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT allocation type +=and PAGE_READWRITE access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/CMakeLists.txt new file mode 100644 index 0000000..354b3e6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + virtualalloc.cpp +) + +add_executable(paltest_virtualalloc_test20 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test20 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test20 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/testinfo.dat new file mode 100644 index 0000000..6010a18 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test VirtualAlloc to ensure that re-committed memory is not changed. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/virtualalloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/virtualalloc.cpp new file mode 100644 index 0000000..7aec3c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/virtualalloc.cpp @@ -0,0 +1,50 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Ensure that memory re-committed through VirtualAlloc +** is not changed. +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + int *ptr; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + ptr = (int *) VirtualAlloc(NULL, 4096, MEM_COMMIT | MEM_RESERVE, + PAGE_READWRITE); + if (ptr == NULL) + { + Fail("First VirtualAlloc failed!\n"); + } + + *ptr = 123; + + ptr = (int *) VirtualAlloc(ptr, 4096, MEM_COMMIT, PAGE_READWRITE); + if (ptr == NULL) + { + Fail("Second VirtualAlloc failed!\n"); + } + if (*ptr != 123) + { + Fail("VirtualAlloc modified (probably zeroed) re-committed memory!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/CMakeLists.txt new file mode 100644 index 0000000..bb4cd0a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + virtualalloc.cpp +) + +add_executable(paltest_virtualalloc_test21 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test21 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test21 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/testinfo.dat new file mode 100644 index 0000000..c32d352 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test VirtualAlloc to ensure that freed memory that is committed again is zeroed. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/virtualalloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/virtualalloc.cpp new file mode 100644 index 0000000..065a2ff --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/virtualalloc.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Ensure that memory committed through VirtualAlloc, +** then freed, then committed again is zeroed. +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + int *ptr; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + ptr = (int *) VirtualAlloc(NULL, 4096, MEM_COMMIT | MEM_RESERVE, + PAGE_READWRITE); + if (ptr == NULL) + { + Fail("First VirtualAlloc failed!\n"); + } + *ptr = 123; + + if (!VirtualFree(ptr, 4096, MEM_DECOMMIT)) + { + Fail("VirtualFree failed!\n"); + } + + ptr = (int *) VirtualAlloc(ptr, 4096, MEM_COMMIT, PAGE_READWRITE); + if (ptr == NULL) + { + Fail("Second VirtualAlloc failed!\n"); + } + if (*ptr != 0) + { + Fail("VirtualAlloc failed to zero its memory!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/CMakeLists.txt new file mode 100644 index 0000000..8d132cc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test22 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test22 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test22 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/VirtualAlloc.cpp new file mode 100644 index 0000000..489926f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/VirtualAlloc.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Negative test the VirtualAlloc API. +** Call VirtualAlloc with MEM_COMMIT allocation type +** and PAGE_READWRITE access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + (SIZE_T)(2147483647000000), //specify the size to be int32.maxvalue mega bytes + MEM_COMMIT, //allocation type + PAGE_READWRITE); //access protection + if(NULL != lpVirtualAddress) + { + Fail("\nWelcome to the Future, where Unlimited Memory is Available, disregard this test!\n"); + } + + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/testinfo.dat new file mode 100644 index 0000000..3d5962c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Negative test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT allocation type +=and PAGE_READWRITEaccess protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/CMakeLists.txt new file mode 100644 index 0000000..1baefef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test3 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test3 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/VirtualAlloc.cpp new file mode 100644 index 0000000..5c57ec3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/VirtualAlloc.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_COMMIT allocation type +** and PAGE_EXECUTE access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT, //allocation type + PAGE_EXECUTE); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/testinfo.dat new file mode 100644 index 0000000..a3d5401 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT allocation type +=and PAGE_EXECUTE access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/CMakeLists.txt new file mode 100644 index 0000000..d9ef274 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test4 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test4 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/VirtualAlloc.cpp new file mode 100644 index 0000000..c134a14 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/VirtualAlloc.cpp @@ -0,0 +1,49 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_COMMIT allocation type +** and PAGE_EXECUTE_READ access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT, //allocation type + PAGE_EXECUTE_READ); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/testinfo.dat new file mode 100644 index 0000000..0e84e7a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT allocation type +=and PAGE_EXECUTE_READ access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/CMakeLists.txt new file mode 100644 index 0000000..eb87fe1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test5 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test5 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/VirtualAlloc.cpp new file mode 100644 index 0000000..8c4f9dc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/VirtualAlloc.cpp @@ -0,0 +1,50 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_COMMIT allocation type +** and PAGE_READONLY access protection +** + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT, //allocation type + PAGE_EXECUTE_READWRITE); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/testinfo.dat new file mode 100644 index 0000000..332b88b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT allocation type +=and PAGE_EXECUTE_READWRITE access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/CMakeLists.txt new file mode 100644 index 0000000..de6f2d2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test6 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test6 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/VirtualAlloc.cpp new file mode 100644 index 0000000..e9c33d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/VirtualAlloc.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_COMMIT allocation type +** and PAGE_NOACCESS access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT, //allocation type + PAGE_NOACCESS); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/testinfo.dat new file mode 100644 index 0000000..ac2b91c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT allocation type +=and PAGE_NOACCESS access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/CMakeLists.txt new file mode 100644 index 0000000..d7fcd5a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test7 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test7 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/VirtualAlloc.cpp new file mode 100644 index 0000000..bee2735 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/VirtualAlloc.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_RESERVE allocation type +** and PAGE_READONLY access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_RESERVE, //allocation type + PAGE_READONLY); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + PAL_Terminate(); + return 1; + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + PAL_Terminate(); + return 1; + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/testinfo.dat new file mode 100644 index 0000000..2edcb56 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_RESERVE allocation type +=and PAGE_READONLY access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/CMakeLists.txt new file mode 100644 index 0000000..75295b1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test8 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test8 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/VirtualAlloc.cpp new file mode 100644 index 0000000..d548e0c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/VirtualAlloc.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_RESERVE allocation type +** and PAGE_READWRITE access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_RESERVE, //allocation type + PAGE_READWRITE); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/testinfo.dat new file mode 100644 index 0000000..c0ee6b6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_RESERVE allocation type +=and PAGE_READWRITE access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/CMakeLists.txt new file mode 100644 index 0000000..e819321 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test9 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test9 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/VirtualAlloc.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/VirtualAlloc.cpp new file mode 100644 index 0000000..2711add --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/VirtualAlloc.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Positive test the VirtualAlloc API. +** Call VirtualAlloc with MEM_RESERVE allocation type +** and PAGE_EXECUTE access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_RESERVE, //allocation type + PAGE_EXECUTE); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/testinfo.dat new file mode 100644 index 0000000..1e83744 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Positive test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_RESERVE allocation type +=and PAGE_EXECUTE access protection diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/CMakeLists.txt new file mode 100644 index 0000000..72832ce --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualFree.cpp +) + +add_executable(paltest_virtualfree_test1 + ${SOURCES} +) + +add_dependencies(paltest_virtualfree_test1 coreclrpal) + +target_link_libraries(paltest_virtualfree_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/VirtualFree.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/VirtualFree.cpp new file mode 100644 index 0000000..0f4f144 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/VirtualFree.cpp @@ -0,0 +1,48 @@ +// 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. + +/*============================================================= +** +** Source: virtualfree.c +** +** Purpose: Positive test the VirtualFree API. +** Call VirtualFree with MEM_DECOMMIT +** free operation type +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT, //allocation type + PAGE_READONLY); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/testinfo.dat new file mode 100644 index 0000000..2848635 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualFree +Name = Positive test for VirtualFree API +TYPE = DEFAULT +EXE1 = virtualfree +Description +=Test the VirtualFree with MEM_DECOMMIT free +=operation type diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/CMakeLists.txt new file mode 100644 index 0000000..a647cf5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualFree.cpp +) + +add_executable(paltest_virtualfree_test2 + ${SOURCES} +) + +add_dependencies(paltest_virtualfree_test2 coreclrpal) + +target_link_libraries(paltest_virtualfree_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/VirtualFree.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/VirtualFree.cpp new file mode 100644 index 0000000..70064a3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/VirtualFree.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================= +** +** Source: virtualfree.c +** +** Purpose: Positive test the VirtualFree API. +** Call VirtualFree with MEM_RELEASE +** free operation type +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + 1024, //specify the size + MEM_COMMIT, //allocation type + PAGE_READONLY); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + PAL_Terminate(); + return 1; + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,//base address + 0, //must be zero with MEM_RELEASE + MEM_RELEASE);//free operation + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + PAL_Terminate(); + return 1; + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/testinfo.dat new file mode 100644 index 0000000..ea380c3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualFree +Name = Positive test for VirtualFree API +TYPE = DEFAULT +EXE1 = virtualfree +Description +=Test the VirtualFree with MEM_RELEASE free +=operation type diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/CMakeLists.txt new file mode 100644 index 0000000..f77894e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualFree.cpp +) + +add_executable(paltest_virtualfree_test3 + ${SOURCES} +) + +add_dependencies(paltest_virtualfree_test3 coreclrpal) + +target_link_libraries(paltest_virtualfree_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/VirtualFree.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/VirtualFree.cpp new file mode 100644 index 0000000..27f1936 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/VirtualFree.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================= +** +** Source: virtualfree.c +** +** Purpose: Positive test the VirtualFree API. +** Call VirtualFree with MEM_RELEASE +** and MEM_DECOMMIT free operation type +** +** +**============================================================*/ +#include + +#define VIRTUALSIZE 1024 + + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + VIRTUALSIZE, //specify the size + MEM_RESERVE, //allocation type + PAGE_NOACCESS); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //decommit and release the specified region + err = VirtualFree(lpVirtualAddress, //base address + VIRTUALSIZE, //decommited size + MEM_DECOMMIT|MEM_RELEASE);//free operation + if(0 != err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/testinfo.dat new file mode 100644 index 0000000..c27b7ad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualFree +Name = Positive test for VirtualFree API +TYPE = DEFAULT +EXE1 = virtualfree +Description +=Test the VirtualFree with MEM_DECOMMIT|MEM_RELEASE free +=operation type diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/CMakeLists.txt new file mode 100644 index 0000000..ca5ce73 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/CMakeLists.txt @@ -0,0 +1,7 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test6) +add_subdirectory(test7) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/CMakeLists.txt new file mode 100644 index 0000000..522a4cd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualProtect.cpp +) + +add_executable(paltest_virtualprotect_test1 + ${SOURCES} +) + +add_dependencies(paltest_virtualprotect_test1 coreclrpal) + +target_link_libraries(paltest_virtualprotect_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/VirtualProtect.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/VirtualProtect.cpp new file mode 100644 index 0000000..1a28bd1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/VirtualProtect.cpp @@ -0,0 +1,69 @@ +// 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. + +/*============================================================= +** +** Source: virtualprotect.c +** +** Purpose: Positive test the VirtualProtect API. +** Call VirtualProtect to set new protect as +** PAGE_READWRITE +** +** +**============================================================*/ +#include + +#define REGIONSIZE 1024 + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + DWORD OldProtect; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + REGIONSIZE, //specify the size + MEM_COMMIT, //allocation type + PAGE_READONLY); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + OldProtect = PAGE_READONLY; + //Set new access protection + err = VirtualProtect(lpVirtualAddress, + REGIONSIZE, //specify the region size + PAGE_READWRITE,//desied access protection + &OldProtect);//old access protection + if(0 == err) + { + Trace("\nFailed to call VirtualProtect API!\n"); + err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + Fail(""); + } + + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/testinfo.dat new file mode 100644 index 0000000..6b78c07 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualProtect +Name = Positive test for VirtualProtect - with PAGE_READWRITE +TYPE = DEFAULT +EXE1 = virtualprotect +Description +=Test the VirtualProtect to set new access protection +=as PAGE_READWRITE diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/CMakeLists.txt new file mode 100644 index 0000000..e5e049c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualProtect.cpp +) + +add_executable(paltest_virtualprotect_test2 + ${SOURCES} +) + +add_dependencies(paltest_virtualprotect_test2 coreclrpal) + +target_link_libraries(paltest_virtualprotect_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/VirtualProtect.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/VirtualProtect.cpp new file mode 100644 index 0000000..64a08d7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/VirtualProtect.cpp @@ -0,0 +1,69 @@ +// 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. + +/*============================================================= +** +** Source: virtualprotect.c +** +** Purpose: Positive test the VirtualProtect API. +** Call VirtualProtect to set new protect as +** PAGE_EXECUTE +** +** +**============================================================*/ +#include + +#define REGIONSIZE 1024 + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + DWORD OldProtect; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//determine where to allocate the region + REGIONSIZE, //specify the size + MEM_COMMIT, //allocation type + PAGE_READONLY); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + OldProtect = PAGE_READONLY; + //Set new access protection + err = VirtualProtect(lpVirtualAddress, + REGIONSIZE, //specify the region size + PAGE_EXECUTE,//desied access protection + &OldProtect);//old access protection + if(0 == err) + { + Trace("\nFailed to call VirtualProtect API!\n"); + err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + Fail(""); + } + + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/testinfo.dat new file mode 100644 index 0000000..d5fa0cf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualProtect +Name = Positive test for VirtualProtect - with PAGE_EXECUTE +TYPE = DEFAULT +EXE1 = virtualprotect +Description +=Test the VirtualProtect to set new access protection +=as PAGE_EXECUTE diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/CMakeLists.txt new file mode 100644 index 0000000..537e462 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualProtect.cpp +) + +add_executable(paltest_virtualprotect_test3 + ${SOURCES} +) + +add_dependencies(paltest_virtualprotect_test3 coreclrpal) + +target_link_libraries(paltest_virtualprotect_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/VirtualProtect.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/VirtualProtect.cpp new file mode 100644 index 0000000..0f73863 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/VirtualProtect.cpp @@ -0,0 +1,69 @@ +// 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. + +/*============================================================= +** +** Source: virtualprotect.c +** +** Purpose: Positive test the VirtualProtect API. +** Call VirtualProtect to set new protect as +** PAGE_EXECUTE_READ +** +** +**============================================================*/ +#include + +#define REGIONSIZE 1024 + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + DWORD OldProtect; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//determine where to allocate the region + REGIONSIZE, //specify the size + MEM_COMMIT, //allocation type + PAGE_READONLY); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + OldProtect = PAGE_READONLY; + //Set new access protection + err = VirtualProtect(lpVirtualAddress, + REGIONSIZE, //specify the region size + PAGE_EXECUTE_READ,//desied access protection + &OldProtect);//old access protection + if(0 == err) + { + Trace("\nFailed to call VirtualProtect API!\n"); + err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + Fail(""); + } + + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/testinfo.dat new file mode 100644 index 0000000..7c64c30 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualProtect +Name = Positive test for VirtualProtect - with PAGE_EXECUTE_READ +TYPE = DEFAULT +EXE1 = virtualprotect +Description +=Test the VirtualProtect to set new access protection +=as PAGE_EXECUTE_READ diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/CMakeLists.txt new file mode 100644 index 0000000..4b5eb6e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualProtect.cpp +) + +add_executable(paltest_virtualprotect_test4 + ${SOURCES} +) + +add_dependencies(paltest_virtualprotect_test4 coreclrpal) + +target_link_libraries(paltest_virtualprotect_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/VirtualProtect.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/VirtualProtect.cpp new file mode 100644 index 0000000..926d501 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/VirtualProtect.cpp @@ -0,0 +1,68 @@ +// 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. + +/*============================================================= +** +** Source: virtualprotect.c +** +** Purpose: Positive test the VirtualProtect API. +** Call VirtualProtect to set new protect as +** PAGE_EXECUTE_READWRITE +** +** +**============================================================*/ +#include + +#define REGIONSIZE 1024 + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + DWORD OldProtect; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//determine where to allocate the region + REGIONSIZE, //specify the size + MEM_COMMIT, //allocation type + PAGE_READONLY); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + OldProtect = PAGE_READONLY; + //Set new access protection + err = VirtualProtect(lpVirtualAddress, + REGIONSIZE, //specify the region size + PAGE_EXECUTE_READWRITE,//desied access protection + &OldProtect);//old access protection + if(0 == err) + { + Trace("\nFailed to call VirtualProtect API!\n"); + err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + Fail(""); + } + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/testinfo.dat new file mode 100644 index 0000000..c344073 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualProtect +Name = Positive test for VirtualProtect - with PAGE_EXECUTE_READWRITE +TYPE = DEFAULT +EXE1 = virtualprotect +Description +=Test the VirtualProtect to set new access protection +=as PAGE_EXECUTE_READWRITE diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/CMakeLists.txt new file mode 100644 index 0000000..5f08af8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualProtect.cpp +) + +add_executable(paltest_virtualprotect_test6 + ${SOURCES} +) + +add_dependencies(paltest_virtualprotect_test6 coreclrpal) + +target_link_libraries(paltest_virtualprotect_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/VirtualProtect.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/VirtualProtect.cpp new file mode 100644 index 0000000..d60b323 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/VirtualProtect.cpp @@ -0,0 +1,68 @@ +// 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. + +/*============================================================= +** +** Source: virtualprotect.c +** +** Purpose: Positive test the VirtualProtect API. +** Call VirtualProtect to set new protect as +** PAGE_NOACCESS +** +** +**============================================================*/ +#include + +#define REGIONSIZE 1024 + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + DWORD OldProtect; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//determine where to allocate the region + REGIONSIZE, //specify the size + MEM_COMMIT, //allocation type + PAGE_READONLY); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + OldProtect = PAGE_READONLY; + //Set new access protection + err = VirtualProtect(lpVirtualAddress, + REGIONSIZE, //specify the region size + PAGE_NOACCESS,//desied access protection + &OldProtect);//old access protection + if(0 == err) + { + Trace("\nFailed to call VirtualProtect API!\n"); + err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + Fail(""); + } + + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/testinfo.dat new file mode 100644 index 0000000..71ccad5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualProtect +Name = Positive test for VirtualProtect - with PAGE_NOACCESS +TYPE = DEFAULT +EXE1 = virtualprotect +Description +=Test the VirtualProtect to set new access protection +=as PAGE_NOACCESS diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/CMakeLists.txt new file mode 100644 index 0000000..03ba8a3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualProtect.cpp +) + +add_executable(paltest_virtualprotect_test7 + ${SOURCES} +) + +add_dependencies(paltest_virtualprotect_test7 coreclrpal) + +target_link_libraries(paltest_virtualprotect_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/VirtualProtect.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/VirtualProtect.cpp new file mode 100644 index 0000000..edc3771 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/VirtualProtect.cpp @@ -0,0 +1,69 @@ +// 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. + +/*============================================================= +** +** Source: virtualprotect.c +** +** Purpose: Positive test the VirtualProtect API. +** Call VirtualProtect to set new protect as +** PAGE_READONLY +** +** +**============================================================*/ +#include + +#define REGIONSIZE 1024 + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + DWORD OldProtect; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//determine where to allocate the region + REGIONSIZE, //specify the size + MEM_COMMIT, //allocation type + PAGE_READWRITE); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + OldProtect = PAGE_READONLY; + //Set new access protection + err = VirtualProtect(lpVirtualAddress, + REGIONSIZE, //specify the region size + PAGE_READONLY,//desied access protection + &OldProtect);//old access protection + if(0 == err) + { + Trace("\nFailed to call VirtualProtect API!\n"); + err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + Fail(""); + } + + + //decommit the specified region + err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/testinfo.dat new file mode 100644 index 0000000..6b6eb58 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualProtect +Name = Positive test for VirtualProtect - with PAGE_READONLY +TYPE = DEFAULT +EXE1 = virtualprotect +Description +=Test the VirtualProtect to set new access protection +=as PAGE_READONLY diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/CMakeLists.txt new file mode 100644 index 0000000..2fef939 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + VirtualQuery.cpp +) + +add_executable(paltest_virtualquery_test1 + ${SOURCES} +) + +add_dependencies(paltest_virtualquery_test1 coreclrpal) + +target_link_libraries(paltest_virtualquery_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/VirtualQuery.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/VirtualQuery.cpp new file mode 100644 index 0000000..44216ae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/VirtualQuery.cpp @@ -0,0 +1,68 @@ +// 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. + +/*============================================================= +** +** Source: virtualquery.c +** +** Purpose: Positive test the VirtualQuery API. +** Call VirtualQuery to get the virtual +** page info +** +** +**============================================================*/ +#include + +#define VIRTUALMEMORYSIZE 1024 + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + MEMORY_BASIC_INFORMATION PageInfo; + DWORD dwBufferSize; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//determine where to allocate the region + VIRTUALMEMORYSIZE, //specify the size + MEM_COMMIT, //allocation type + PAGE_READONLY); //access protection + if(NULL == lpVirtualAddress) + { + Fail("\nFailed to call VirtualAlloc API!\n"); + } + + //get the virtual page info + dwBufferSize = + VirtualQuery(lpVirtualAddress,&PageInfo,sizeof(MEMORY_BASIC_INFORMATION)); + + if(dwBufferSize <= 0 || + PageInfo.RegionSize <=0 || + PAGE_READONLY != PageInfo.AllocationProtect || + MEM_COMMIT != PageInfo.State) + { + Fail("\nFailed to call VirtualQuery API!\n"); + } + + + + //decommit the specified region + err = VirtualFree(lpVirtualAddress, //virtual page base address + VIRTUALMEMORYSIZE,//specify the size + MEM_DECOMMIT);//free operation + if(0 == err) + { + Fail("\nFailed to call VirtualFree API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/testinfo.dat new file mode 100644 index 0000000..b3462cd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualQuery +Name = Positive test for VirtualQuery API +TYPE = DEFAULT +EXE1 = virtualquery +Description +=Test the VirtualQuery to get the virtual page info diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/CMakeLists.txt new file mode 100644 index 0000000..ffee9ae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(LoadLibraryA) +add_subdirectory(LoadLibraryW) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/CMakeLists.txt new file mode 100644 index 0000000..b8673b4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/CMakeLists.txt @@ -0,0 +1,6 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test5) +add_subdirectory(test7) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test1/CMakeLists.txt new file mode 100644 index 0000000..d8d84b2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + LoadLibraryA.cpp +) + +add_executable(paltest_loadlibrarya_test1 + ${SOURCES} +) + +add_dependencies(paltest_loadlibrarya_test1 coreclrpal) + +target_link_libraries(paltest_loadlibrarya_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test1/LoadLibraryA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test1/LoadLibraryA.cpp new file mode 100644 index 0000000..b4a8de1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test1/LoadLibraryA.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================= +** +** Source: loadlibrarya.c +** +** Purpose: Positive test the LoadLibrary API. +** Call LoadLibrary to map a module into the calling +** process address space(DLL file) +** +** +**============================================================*/ +#include + +/* SHLEXT is defined only for Unix variants */ + +#if defined(SHLEXT) +#define ModuleName "librotor_pal"SHLEXT +#else +#define ModuleName "rotor_pal.dll" +#endif + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + int err; + + /* Initialize the PAL environment */ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + /* load a module */ + ModuleHandle = LoadLibrary(ModuleName); + if(!ModuleHandle) + { + Fail("Failed to call LoadLibrary API!\n"); + } + + /* decrement the reference count of the loaded dll */ + err = FreeLibrary(ModuleHandle); + if(0 == err) + { + Fail("\nFailed to all FreeLibrary API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test1/testinfo.dat new file mode 100644 index 0000000..096aab9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Loader +Function = LoadLibraryA +Name = Positive test for LoadLibraryA API to load Dynamic library module +TYPE = DEFAULT +EXE1 = loadlibrarya +Description +=Test the LoadLibraryA to map module into calling process address space + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/CMakeLists.txt new file mode 100644 index 0000000..f8b83c4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + LoadLibraryA.cpp +) + +add_executable(paltest_loadlibrarya_test2 + ${SOURCES} +) + +add_dependencies(paltest_loadlibrarya_test2 coreclrpal) + +target_link_libraries(paltest_loadlibrarya_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/LoadLibraryA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/LoadLibraryA.cpp new file mode 100644 index 0000000..d7cd9cb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/LoadLibraryA.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================= +** +** Source: loadlibrarya.c +** +** Purpose: Negative test the LoadLibraryA API. +** Call LoadLibraryA with a not exist module Name +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + int err; + const char *pModuleName = "Not-exist-module-name"; + + /* Initialize the PAL environment */ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*try to load a not exist module */ + ModuleHandle = LoadLibraryA(pModuleName); + if(NULL != ModuleHandle) + { + Trace("Failed to call LoadLibraryA with a not exist mudule name, " + "a NULL module handle is expected, but no NULL module handle " + "is returned, error code=%u\n", GetLastError()); + + /* decrement the reference count of the loaded module */ + err = FreeLibrary(ModuleHandle); + if(0 == err) + { + Trace("\nFailed to all FreeLibrary API to decrement " + "the reference count of the loaded module, " + "error code = %u\n", GetLastError()); + + } + + Fail(""); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/MyModule.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/MyModule.cpp new file mode 100644 index 0000000..883b3fb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/MyModule.cpp @@ -0,0 +1,19 @@ +// 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. + +/*============================================================= +** +** Source: mymoduale.c +** +** Purpose: Positive test the LoadLibrary API. +** + +** +**============================================================*/ + +int __cdecl main(int argc, char *argv[]) +{ + //only for testing LoadLibrary + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/testinfo.dat new file mode 100644 index 0000000..97b7222 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Loader +Function = LoadLibraryA +Name = Negative test LoadLibraryA API to load a not exist module +TYPE = DEFAULT +EXE1 = loadlibrarya +Description +=Test the LoadLibraryA to load a not exist module + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test3/CMakeLists.txt new file mode 100644 index 0000000..b22469a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + loadlibrarya.cpp +) + +add_executable(paltest_loadlibrarya_test3 + ${SOURCES} +) + +add_dependencies(paltest_loadlibrarya_test3 coreclrpal) + +target_link_libraries(paltest_loadlibrarya_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test3/loadlibrarya.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test3/loadlibrarya.cpp new file mode 100644 index 0000000..da38f98 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test3/loadlibrarya.cpp @@ -0,0 +1,40 @@ +// 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. + +/*============================================================= +** +** Source: loadlibrarya.c +** +** Purpose: Negative test the LoadLibrary API with NULL module +** name. +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + int err; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*load a module by passing a NULL module name*/ + ModuleHandle = LoadLibraryA(NULL); + if(NULL != ModuleHandle) + { + Fail("\nFailed to call loadlibrarya API for a negative test, " + "call loadibrarya with NULL moudle name, a NULL module " + "handle is expected, but no NULL module handle is returned, " + "error code =%u\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test3/testinfo.dat new file mode 100644 index 0000000..c27c8e0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Loader +Function = LoadLibraryA +Name = Negative test LoadLibraryA API with a NULL module name +TYPE = DEFAULT +EXE1 = loadlibrarya +Description +=Test the LoadLibraryA to map NULL module into calling +=process address space + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test5/CMakeLists.txt new file mode 100644 index 0000000..1957f44 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + loadlibrarya.cpp +) + +add_executable(paltest_loadlibrarya_test5 + ${SOURCES} +) + +add_dependencies(paltest_loadlibrarya_test5 coreclrpal) + +target_link_libraries(paltest_loadlibrarya_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.cpp new file mode 100644 index 0000000..ab38d1a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.cpp @@ -0,0 +1,67 @@ +// 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. + +/*============================================================= +** +** Source: loadlibrarya.c +** +** Purpose: Negative test the LoadLibraryA API. +** Call LoadLibraryA by passing a module name +** without extension but with a trailing dot. +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + char ModuleName[_MAX_FNAME]; + int err; + + /* Initialize the PAL environment */ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + memset(ModuleName, 0, _MAX_FNAME); + + /*Module name without extension but with a trailing dot*/ +#if WIN32 + sprintf_s(ModuleName, _countof(ModuleName), "%s", "rotor_pal."); +#else + /* Under FreeBSD */ + sprintf_s(ModuleName, _countof(ModuleName), "%s", "librotor_pal."); +#endif + + /* load a module which does not have the file extension, + * but has a trailing dot + */ + ModuleHandle = LoadLibraryA(ModuleName); + if(NULL != ModuleHandle) + { + Trace("Failed to call LoadLibraryA API for a negative test " + "call LoadLibraryA with module name which does not have " + "extension except a trailing dot, a NULL module handle is" + "expected, but no NULL module handle is returned, " + "error code = %u\n", GetLastError()); + + + /* decrement the reference count of the loaded dll */ + err = FreeLibrary(ModuleHandle); + if(0 == err) + { + Trace("\nFailed to call FreeLibrary API, " + "error code = %u\n", GetLastError()); + } + + Fail(""); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test5/testinfo.dat new file mode 100644 index 0000000..e2cd16c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test5/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Loader +Function = LoadLibraryA +Name = Negative test for LoadLibraryA API by passing a module name without extension but with a trailing dot. +TYPE = DEFAULT +EXE1 = loadlibrarya +Description +=Test the LoadLibraryA by passing a module name without extension +=but with a trailing dot. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/CMakeLists.txt new file mode 100644 index 0000000..29f8152 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + loadlibrarya.cpp +) + +add_executable(paltest_loadlibrarya_test6 + ${TESTSOURCES} +) + +add_dependencies(paltest_loadlibrarya_test6 coreclrpal) + +target_link_libraries(paltest_loadlibrarya_test6 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + dlltest.cpp +) + +add_executable(paltest_loadlibrarya_test6_dlltest + ${HELPERSOURCES} +) + +add_dependencies(paltest_loadlibrarya_test6_dlltest coreclrpal) + +target_link_libraries(paltest_loadlibrarya_test6_dlltest + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/dlltest.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/dlltest.cpp new file mode 100644 index 0000000..3726576 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/dlltest.cpp @@ -0,0 +1,72 @@ +// 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. + +/*============================================================================= +** +** Source: dllmain.c +** +** Purpose: Test to ensure DllMain() is called with DLL_THREAD_DETACH +** only the initial time that the library is loaded. +** +** Depends: None +** + +** +**===========================================================================*/ + +#include + +/* count of the number of times DllMain() + * was called with THREAD_ATTACH. + */ +static int g_attachCount = 0; + +/* standard DllMain() */ +BOOL PALAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved) +{ + switch( reason ) + { + case DLL_PROCESS_ATTACH: + { + g_attachCount++; + break; + } + + case DLL_PROCESS_DETACH: + { + break; + } + + case DLL_THREAD_ATTACH: + { + break; + } + + case DLL_THREAD_DETACH: + { + break; + } + } + + return TRUE; +} + +#if _WIN32 +BOOL PALAPI _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved) +{ + return DllMain(hinstDLL, reason, lpvReserved); +} +#endif + + + +/* function to return the current attach count */ +#if _WIN32 +__declspec(dllexport) +#endif +int PALAPI GetAttachCount( void ) +{ + return g_attachCount; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.cpp new file mode 100644 index 0000000..ee825e6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.cpp @@ -0,0 +1,172 @@ +// 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. + +/*============================================================= +** +** Source: loadlibrary.c (test 6) +** +** Purpose: Positive test the LoadLibrary API. Test will verify +** that it is unable to load the library twice. Once by +** using the full path name and secondly by using the +** short name. +** + +** +**============================================================*/ +#include + +/*Define platform specific information*/ +#if defined(SHLEXT) +#define LibraryName "dlltest"SHLEXT +#define GETATTACHCOUNTNAME "GetAttachCount" +#else +typedef int (*dllfunct)(); +#define LibraryName "dlltest.dll" +#define GETATTACHCOUNTNAME "_GetAttachCount@0" +#endif + + +/* Helper function to test the loaded library. + */ +BOOL PALAPI TestDll(HMODULE hLib) +{ + int RetVal; + char FunctName[] = GETATTACHCOUNTNAME; + FARPROC DllFunc; + + /* Access a function from the loaded library. + */ + DllFunc = GetProcAddress(hLib, FunctName); + if(DllFunc == NULL) + { + Trace("ERROR: Unable to load function \"%s\" from library \"%s\"\n", + FunctName, + LibraryName); + return (FALSE); + } + + /* Verify that the DLL_PROCESS_ATTACH is only + * accessed once.*/ + RetVal = DllFunc(); + if (RetVal != 1) + { + Trace("ERROR: Unable to receive correct information from DLL! " + ":expected \"1\", returned \"%d\"\n", + RetVal); + return (FALSE); + } + + return (TRUE); +} + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFullLib; + HANDLE hShortLib; + int iRetVal = FAIL; + char fullPath[_MAX_DIR]; + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + + + + /* Initialize the PAL. */ + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + /* Initalize the buffer. + */ + memset(fullPath, 0, _MAX_DIR); + + /* Get the full path to the library (DLL). + */ + + if (NULL != _fullpath(fullPath,argv[0],_MAX_DIR)) { + + _splitpath(fullPath,drive,dir,fname,ext); + _makepath(fullPath,drive,dir,LibraryName,""); + + + } else { + Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. _fullpath returned NULL\n",argv[0]); + } + + /* Call Load library with the short name of + * the dll. + */ + hShortLib = LoadLibrary(LibraryName); + if(hShortLib == NULL) + { + Fail("ERROR:%u:Unable to load library %s\n", + GetLastError(), + LibraryName); + } + + /* Test the loaded library. + */ + if (!TestDll(hShortLib)) + { + iRetVal = FAIL; + goto cleanUpOne; + } + + /* Call Load library with the full name of + * the dll. + */ + hFullLib = LoadLibrary(fullPath); + if(hFullLib == NULL) + { + Trace("ERROR:%u:Unable to load library %s\n", + GetLastError(), + fullPath); + iRetVal = FAIL; + goto cleanUpTwo; + } + + /* Test the loaded library. + */ + if (!TestDll(hFullLib)) + { + iRetVal = FAIL; + goto cleanUpTwo; + } + + /* Test Succeeded. + */ + iRetVal = PASS; + +cleanUpTwo: + + /* Call the FreeLibrary API. + */ + if (!FreeLibrary(hFullLib)) + { + Trace("ERROR:%u: Unable to free library \"%s\"\n", + GetLastError(), + fullPath); + iRetVal = FAIL; + } + +cleanUpOne: + + /* Call the FreeLibrary API. + */ + if (!FreeLibrary(hShortLib)) + { + Trace("ERROR:%u: Unable to free library \"%s\"\n", + GetLastError(), + LibraryName); + iRetVal = FAIL; + } + + /* Terminate the PAL. + */ + PAL_Terminate(); + return iRetVal; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/testinfo.dat new file mode 100644 index 0000000..4be93b8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test6/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = Loader +Function = LoadLibraryA +Name = Positive test for LoadLibrary API +TYPE = DEFAULT +EXE1 = loadlibrarya +LIB1 = dlltest +Description += Positive test the LoadLibrary API. Test will verify += that it is unable to load the library twice. Once by += using the full path name and secondly by using the += short name. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test7/CMakeLists.txt new file mode 100644 index 0000000..ae287cc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + LoadLibraryA.cpp +) + +add_executable(paltest_loadlibrarya_test7 + ${SOURCES} +) + +add_dependencies(paltest_loadlibrarya_test7 coreclrpal) + +target_link_libraries(paltest_loadlibrarya_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test7/LoadLibraryA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test7/LoadLibraryA.cpp new file mode 100644 index 0000000..5e6db8b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test7/LoadLibraryA.cpp @@ -0,0 +1,83 @@ +// 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. + +/*============================================================= +** +** Source: loadlibrarya.c +** +** Purpose: Positive test the LoadLibrary API by calling it multiple times. +** Call LoadLibrary to map a module into the calling +** process address space(DLL file) +** +** +**============================================================*/ +#include + +/* SHLEXT is defined only for Unix variants */ + +#if defined(SHLEXT) +#define ModuleName "librotor_pal"SHLEXT +#else +#define ModuleName "rotor_pal.dll" +#endif + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + HMODULE ReturnHandle; + int err; + + /* Initialize the PAL environment */ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + /* load a module */ + ModuleHandle = LoadLibrary(ModuleName); + if(!ModuleHandle) + { + Fail("Error[%u]:Failed to call LoadLibrary API!\n", GetLastError()); + } + + /* Call LoadLibrary again, should return same handle as returned for first time */ + ReturnHandle = LoadLibrary(ModuleName); + if(!ReturnHandle) + { + Fail("Error[%u]:Failed to call LoadLibrary API second time!\n", GetLastError()); + } + + if(ModuleHandle != ReturnHandle) + { + Fail("Error[%u]:Failed to return the same handle while calling LoadLibrary API twice!\n", GetLastError()); + } + + Trace("Value of handle ModuleHandle[%x], ReturnHandle[%x]\n", ModuleHandle, ReturnHandle); + /* decrement the reference count of the loaded dll */ + err = FreeLibrary(ModuleHandle); + + if(0 == err) + { + Fail("Error[%u]:Failed to FreeLibrary API!\n", GetLastError()); + } + + /* Try Freeing a library again, should not fail */ + err = FreeLibrary(ReturnHandle); + + if(0 == err) + { + Fail("Error[%u][%d]: Was not successful in freeing a Library twice using FreeLibrary!\n", GetLastError(), err); + } + + /* Try Freeing a library again, should fail */ + err = FreeLibrary(ReturnHandle); + + if(1 != err) + { + Fail("Error[%u][%d]: Was successful in freeing a Library thrice using FreeLibrary!\n", GetLastError(), err); + } + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test7/testinfo.dat new file mode 100644 index 0000000..416caf3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test7/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Loader +Function = LoadLibraryA +Name = Positive and Negative test for LoadLibraryA API to load Dynamic library module +TYPE = DEFAULT +EXE1 = loadlibrarya +Description +=Test the LoadLibraryA to load multiple times and call unload more times than load + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/CMakeLists.txt new file mode 100644 index 0000000..dd36aa9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + loadlibrarya.cpp +) + +add_executable(paltest_loadlibrarya_test8 + ${TESTSOURCES} +) + +add_dependencies(paltest_loadlibrarya_test8 coreclrpal) + +target_link_libraries(paltest_loadlibrarya_test8 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + dlltest.cpp +) + +add_executable(paltest_loadlibrarya_test8_dlltest + ${HELPERSOURCES} +) + +add_dependencies(paltest_loadlibrarya_test8_dlltest coreclrpal) + +target_link_libraries(paltest_loadlibrarya_test8_dlltest + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/dlltest.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/dlltest.cpp new file mode 100644 index 0000000..3726576 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/dlltest.cpp @@ -0,0 +1,72 @@ +// 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. + +/*============================================================================= +** +** Source: dllmain.c +** +** Purpose: Test to ensure DllMain() is called with DLL_THREAD_DETACH +** only the initial time that the library is loaded. +** +** Depends: None +** + +** +**===========================================================================*/ + +#include + +/* count of the number of times DllMain() + * was called with THREAD_ATTACH. + */ +static int g_attachCount = 0; + +/* standard DllMain() */ +BOOL PALAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved) +{ + switch( reason ) + { + case DLL_PROCESS_ATTACH: + { + g_attachCount++; + break; + } + + case DLL_PROCESS_DETACH: + { + break; + } + + case DLL_THREAD_ATTACH: + { + break; + } + + case DLL_THREAD_DETACH: + { + break; + } + } + + return TRUE; +} + +#if _WIN32 +BOOL PALAPI _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved) +{ + return DllMain(hinstDLL, reason, lpvReserved); +} +#endif + + + +/* function to return the current attach count */ +#if _WIN32 +__declspec(dllexport) +#endif +int PALAPI GetAttachCount( void ) +{ + return g_attachCount; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.cpp new file mode 100644 index 0000000..6556e9c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.cpp @@ -0,0 +1,235 @@ +// 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. + +/*============================================================= +** +** Source: loadlibrary.c (test 8) +** +** Purpose: Positive test the LoadLibrary API. Test will verify +** that it is unable to load the library twice. Once by +** using the full path name and secondly by using the +** short name. +** + +** +**============================================================*/ +#include + +/*Define platform specific information*/ +#if defined(SHLEXT) +#define LibraryName "dlltest"SHLEXT +#define GETATTACHCOUNTNAME "GetAttachCount" +#else +typedef int (*dllfunct)(); +#define LibraryName "dlltest.dll" +#define GETATTACHCOUNTNAME "_GetAttachCount@0" +#endif + + +/* Helper function to test the loaded library. + */ +BOOL PALAPI TestDll(HMODULE hLib) +{ + int RetVal; + char FunctName[] = GETATTACHCOUNTNAME; + FARPROC DllFunc; + + /* Access a function from the loaded library. + */ + DllFunc = GetProcAddress(hLib, FunctName); + if(DllFunc == NULL) + { + Trace("ERROR: Unable to load function \"%s\" from library \"%s\"\n", + FunctName, + LibraryName); + return (FALSE); + } + + /* Verify that the DLL_PROCESS_ATTACH is only + * accessed once.*/ + RetVal = DllFunc(); + if (RetVal != 1) + { + Trace("ERROR: Unable to receive correct information from DLL! " + ":expected \"1\", returned \"%d\"\n", + RetVal); + return (FALSE); + } + + return (TRUE); +} + +int __cdecl main(int argc, char *argv[]) +{ + HANDLE hFullLib; + HANDLE hShortLib; + HANDLE hRelLib; + + int iRetVal = FAIL; + char fullPath[_MAX_DIR]; + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char relTestDir[_MAX_DIR]; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + + BOOL bRc = FALSE; + char relLibPath[_MAX_DIR]; + + + /* Initialize the PAL. */ + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + /* Initalize the buffer. + */ + memset(fullPath, 0, _MAX_DIR); + + /* Get the full path to the library (DLL). + */ + + if (NULL != _fullpath(fullPath,argv[0],_MAX_DIR)) { + + _splitpath(fullPath,drive,dir,fname,ext); + _makepath(fullPath,drive,dir,LibraryName,""); + + + } else { + Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. _fullpath returned NULL\n",argv[0]); + } + + /* Get relative path to the library + */ + _splitpath(argv[0], drive, relTestDir, fname, ext); + _makepath(relLibPath,drive,relTestDir,LibraryName,""); + + + /* Call Load library with the short name of + * the dll. + */ + hShortLib = LoadLibrary(LibraryName); + if(hShortLib == NULL) + { + Fail("ERROR:%u:Short:Unable to load library %s\n", + GetLastError(), + LibraryName); + } + + /* Test the loaded library. + */ + if (!TestDll(hShortLib)) + { + iRetVal = FAIL; + goto cleanUpOne; + } + + /* Call Load library with the full name of + * the dll. + */ + hFullLib = LoadLibrary(fullPath); + if(hFullLib == NULL) + { + Trace("ERROR:%u:Full:Unable to load library %s\n", + GetLastError(), + fullPath); + iRetVal = FAIL; + goto cleanUpTwo; + } + + /* Test the loaded library. + */ + if (!TestDll(hFullLib)) + { + iRetVal = FAIL; + goto cleanUpTwo; + } + + /* + ** Call the load library with the relative path + ** wrt to the directory ./testloadlibrary/.. + ** since we don't want to make any assumptions + ** regarding the type of build + */ + hRelLib = LoadLibrary(relLibPath); + if(hRelLib == NULL) + { + Trace("ERROR:%u:Rel:Unable to load library at %s\n", + GetLastError(), relLibPath); + iRetVal = FAIL; + goto cleanUpTwo; + } + + /* Test the loaded library. + */ + if (!TestDll(hRelLib)) + { + iRetVal = FAIL; + goto cleanUpThree; + } + + if( hRelLib != hFullLib ) + { + Trace("Relative and Absolute Paths to libraries don't have same handle\n"); + iRetVal = FAIL; + goto cleanUpThree; + } + + if( hRelLib != hShortLib ) + { + Trace("Relative and Short Paths to libraries don't have same handle\n"); + iRetVal = FAIL; + goto cleanUpThree; + } + + + /* Test Succeeded. + */ + iRetVal = PASS; + +cleanUpThree: + + /* Call the FreeLibrary API. + */ + + if (!FreeLibrary(hRelLib)) + { + Trace("ERROR:%u: Unable to free library \"%s\"\n", + GetLastError(), + relLibPath); + iRetVal = FAIL; + } + +cleanUpTwo: + + /* Call the FreeLibrary API. + */ + if (!FreeLibrary(hFullLib)) + { + Trace("ERROR:%u: Unable to free library \"%s\"\n", + GetLastError(), + fullPath); + iRetVal = FAIL; + } + +cleanUpOne: + + /* Call the FreeLibrary API. + */ + if (!FreeLibrary(hShortLib)) + { + Trace("ERROR:%u: Unable to free library \"%s\"\n", + GetLastError(), + LibraryName); + iRetVal = FAIL; + } + + + /* Terminate the PAL. + */ + PAL_TerminateEx(iRetVal); + return iRetVal; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/testinfo.dat new file mode 100644 index 0000000..b552b72 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryA/test8/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = Loader +Function = LoadLibraryA +Name = Positive test for LoadLibrary API +TYPE = DEFAULT +EXE1 = loadlibrarya +LIB1 = dlltest +Description += Positive test the LoadLibrary API. Test will verify += that it is able to load the library thrice. Once by += using the full path name, second by using the += short name and third by using relative paths + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/CMakeLists.txt new file mode 100644 index 0000000..2ad6ca8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test5) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test1/CMakeLists.txt new file mode 100644 index 0000000..8adb8a1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + LoadLibraryW.cpp +) + +add_executable(paltest_loadlibraryw_test1 + ${SOURCES} +) + +add_dependencies(paltest_loadlibraryw_test1 coreclrpal) + +target_link_libraries(paltest_loadlibraryw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test1/LoadLibraryW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test1/LoadLibraryW.cpp new file mode 100644 index 0000000..4c1a551 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test1/LoadLibraryW.cpp @@ -0,0 +1,62 @@ +// 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. + +/*============================================================= +** +** Source: loadlibraryw.c +** +** Purpose: Positive test the LoadLibrary API. +** Call LoadLibrary to map a module into the calling +** process address space(DLL file) +** +** +**============================================================*/ +#define UNICODE +#include +/* SHLEXT is defined only for Unix variants */ + +#if defined(SHLEXT) +#define ModuleName "librotor_pal"SHLEXT +#else +#define ModuleName "rotor_pal.dll" +#endif + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + int err; + WCHAR *lpModuleName; + + /* Initialize the PAL environment */ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + /* convert a normal string to a wide one */ + lpModuleName = convert(ModuleName); + + /* load a module */ + ModuleHandle = LoadLibrary(lpModuleName); + + /* free the memory */ + free(lpModuleName); + + if(!ModuleHandle) + { + Fail("Failed to call LoadLibrary API!\n"); + } + + + /* decrement the reference count of the loaded dll */ + err = FreeLibrary(ModuleHandle); + if(0 == err) + { + Fail("\nFailed to all FreeLibrary API!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test1/testinfo.dat new file mode 100644 index 0000000..c5c4adc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = Loader +Function = LoadLibraryW +Name = Positive test for LoadLibraryW API to load a dynamic library module +TYPE = DEFAULT +EXE1 = loadlibraryw +Description +=Test the LoadLibraryW to map module into calling process address space diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test2/CMakeLists.txt new file mode 100644 index 0000000..e9a933e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + loadlibraryw.cpp +) + +add_executable(paltest_loadlibraryw_test2 + ${SOURCES} +) + +add_dependencies(paltest_loadlibraryw_test2 coreclrpal) + +target_link_libraries(paltest_loadlibraryw_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test2/loadlibraryw.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test2/loadlibraryw.cpp new file mode 100644 index 0000000..e8aebf7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test2/loadlibraryw.cpp @@ -0,0 +1,62 @@ +// 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. + +/*============================================================= +** +** Source: loadlibraryw.c +** +** Purpose: Negative test the LoadLibraryW API. +** Call LoadLibraryW with a not exist module Name +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + int err; + WCHAR *pwModuleName; + const char *pModuleName = "Not-exist-module-name"; + + /* Initialize the PAL environment */ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /* convert a normal string to a wide one */ + pwModuleName = convert((char *)pModuleName); + + + /*try to load a not exist module */ + ModuleHandle = LoadLibraryW(pwModuleName); + + /* free the memory */ + free(pwModuleName); + + if(NULL != ModuleHandle) + { + Trace("Failed to call LoadLibraryW with a not exist mudule name, " + "a NULL module handle is expected, but no NULL module handle " + "is returned, error code=%u\n", GetLastError()); + + /* decrement the reference count of the loaded module */ + err = FreeLibrary(ModuleHandle); + if(0 == err) + { + Trace("\nFailed to all FreeLibrary API to decrement " + "the reference count of the loaded module, " + "error code = %u\n", GetLastError()); + + } + + Fail(""); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test2/testinfo.dat new file mode 100644 index 0000000..bc107f0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Loader +Function = LoadLibraryW +Name = Negative test LoadLibraryW API to load a not exist module +TYPE = DEFAULT +EXE1 = loadlibraryw +Description +=Test the LoadLibraryW to load a not exist module + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test3/CMakeLists.txt new file mode 100644 index 0000000..ac6cf05 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + loadlibraryw.cpp +) + +add_executable(paltest_loadlibraryw_test3 + ${SOURCES} +) + +add_dependencies(paltest_loadlibraryw_test3 coreclrpal) + +target_link_libraries(paltest_loadlibraryw_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test3/loadlibraryw.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test3/loadlibraryw.cpp new file mode 100644 index 0000000..c722eda --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test3/loadlibraryw.cpp @@ -0,0 +1,41 @@ +// 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. + +/*============================================================= +** +** Source: loadlibraryw.c +** +** Purpose: Negative test the loadlibraryw API. +** Call loadlibraryw with NULL module name +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + int err; + + /* Initialize the PAL environment */ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /* load a module with a NULL module name */ + ModuleHandle = LoadLibraryW(NULL); + if(NULL != ModuleHandle) + { + Fail("\nFailed to call loadlibraryw API for a negative test, " + "call loadibraryw with NULL moudle name, a NULL module " + "handle is expected, but no NULL module handle is returned, " + "error code =%u\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test3/testinfo.dat new file mode 100644 index 0000000..bd20aaf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = Loader +Function = LoadLibraryW +Name = Negative test loadlibraryw API with a NULL module name +TYPE = DEFAULT +EXE1 = loadlibraryw +Description +=Test the LoadLibraryW with a NULL module name diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test5/CMakeLists.txt new file mode 100644 index 0000000..384da59 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + loadlibraryw.cpp +) + +add_executable(paltest_loadlibraryw_test5 + ${SOURCES} +) + +add_dependencies(paltest_loadlibraryw_test5 coreclrpal) + +target_link_libraries(paltest_loadlibraryw_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.cpp new file mode 100644 index 0000000..6d92f02 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.cpp @@ -0,0 +1,71 @@ +// 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. + +/*============================================================= +** +** Source: loadlibraryw.c +** +** Purpose: Negative test the LoadLibraryW API. +** Call LoadLibraryW by passing a module name +** without extension but with a trailing dot. +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + int err; + WCHAR *lpModuleName; + char ModuleName[_MAX_FNAME]; + + /* Initialize the PAL environment */ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + memset(ModuleName, 0, _MAX_FNAME); + + /*Module name without extension but with a trailing dot*/ +#if WIN32 + sprintf_s(ModuleName, _countof(ModuleName),"%s","rotor_pal."); +#else + sprintf_s(ModuleName, _countof(ModuleName),"%s","librotor_pal."); +#endif + + /* convert a normal string to a wide one */ + lpModuleName = convert(ModuleName); + + /* load a module */ + ModuleHandle = LoadLibraryW(lpModuleName); + + /* free the memory */ + free(lpModuleName); + + if(NULL != ModuleHandle) + { + Trace("Failed to call LoadLibraryW API for a negative test " + "call LoadLibraryW with module name which does not have " + "extension except a trailing dot, a NULL module handle is" + "expected, but no NULL module handle is returned, " + "error code = %u\n", GetLastError()); + + /* decrement the reference count of the loaded dll */ + err = FreeLibrary(ModuleHandle); + if(0 == err) + { + Trace("\nFailed to call FreeLibrary API, " + "error code = %u\n", GetLastError()); + } + + Fail(""); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test5/testinfo.dat new file mode 100644 index 0000000..8275f41 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/loader/LoadLibraryW/test5/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Loader +Function = LoadLibraryw +Name = Negative test for LoadLibraryW API by passing a module name without extension but with a trailing dot. +TYPE = DEFAULT +EXE1 = loadlibraryw +Description +=Test the LoadLibraryW by passing a module name without extension +=but with a trailing dot. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CMakeLists.txt new file mode 100644 index 0000000..41cc457 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CMakeLists.txt @@ -0,0 +1,15 @@ +# TODO: make the following tests compile if they are needed +# add_subdirectory(CompareStringA) +# add_subdirectory(CompareStringW) +# add_subdirectory(GetLocaleInfoW) + +add_subdirectory(GetACP) +add_subdirectory(GetCPInfo) +add_subdirectory(IsDBCSLeadByte) +add_subdirectory(IsDBCSLeadByteEx) +add_subdirectory(MultiByteToWideChar) +add_subdirectory(WideCharToMultiByte) + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/test1/CMakeLists.txt new file mode 100644 index 0000000..0d13e98 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_comparestringa_test1 + ${SOURCES} +) + +add_dependencies(paltest_comparestringa_test1 coreclrpal) + +target_link_libraries(paltest_comparestringa_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/test1/test1.cpp new file mode 100644 index 0000000..98c147a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/test1/test1.cpp @@ -0,0 +1,99 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests that CompareStringA returns the correct value and can handle +** invalid parameters. +** +** +**==========================================================================*/ + +#define CSTR_LESS_THAN 1 +#define CSTR_EQUAL 2 +#define CSTR_GREATER_THAN 3 + +#include + +int __cdecl main(int argc, char *argv[]) +{ + char str1[] = {'f','o','o',0}; + char str2[] = {'f','o','o','x',0}; + char str3[] = {'f','O','o',0}; + int flags = NORM_IGNORECASE | NORM_IGNOREWIDTH; + int ret; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + ret = CompareStringA(0x0409, flags, str1, -1, str2, -1); + if (ret != CSTR_LESS_THAN) + { + Fail("CompareStringA with \"%S\" (%d) and \"%S\" (%d) did not return " + "CSTR_LESS_THAN!\n", str1, -1, str2, -1); + } + + ret = CompareStringA(0x0409, flags, str1, -1, str2, 3); + if (ret != CSTR_EQUAL) + { + Fail("CompareStringA with \"%S\" (%d) and \"%S\" (%d) did not return " + "CSTR_EQUAL!\n", str1, -1, str2, 3); + } + + ret = CompareStringA(0x0409, flags, str2, -1, str1, -1); + if (ret != CSTR_GREATER_THAN) + { + Fail("CompareStringA with \"%S\" (%d) and \"%S\" (%d) did not return " + "CSTR_GREATER_THAN!\n", str2, -1, str1, -1); + } + + ret = CompareStringA(0x0409, flags, str1, -1, str3, -1); + if (ret != CSTR_EQUAL) + { + Fail("CompareStringA with \"%S\" (%d) and \"%S\" (%d) did not return " + "CSTR_EQUAL!\n", str1, -1, str3, -1); + } + + ret = CompareStringA(0x0409, flags, str3, -1, str1, -1); + if (ret != CSTR_EQUAL) + { + Fail("CompareStringA with \"%S\" (%d) and \"%S\" (%d) did not return " + "CSTR_EQUAL!\n", str3, -1, str1, -1); + } + + ret = CompareStringA(0x0409, flags, str3, -1, str1, -1); + if (ret != CSTR_EQUAL) + { + Fail("CompareStringA with \"%S\" (%d) and \"%S\" (%d) did not return " + "CSTR_EQUAL!\n", str3, -1, str1, -1); + } + + ret = CompareStringA(0x0409, flags, str1, 0, str3, -1); + if (ret != CSTR_LESS_THAN) + { + Fail("CompareStringA with \"%S\" (%d) and \"%S\" (%d) did not return " + "CSTR_GREATER_THAN!\n", str1, 0, str3, -1); + } + + + ret = CompareStringA(0x0409, flags, NULL, -1, str3, -1); + if (ret != 0) + { + Fail("CompareStringA should have returned 0, got %d!\n", ret); + } + if (GetLastError() != ERROR_INVALID_PARAMETER) + { + Fail("CompareStringA should have set the last error to " + "ERROR_INVALID_PARAMETER!\n"); + } + + PAL_Terminate(); + + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/test1/testinfo.dat new file mode 100644 index 0000000..e934b13 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringA/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Locale Information +Function = CompareStringA +Name = Test #1 for CompareStringA +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests that CompareStringA returns the correct value and can handle +=invalid parameters. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/test1/CMakeLists.txt new file mode 100644 index 0000000..24e0a18 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_comparestringw_test1 + ${SOURCES} +) + +add_dependencies(paltest_comparestringw_test1 coreclrpal) + +target_link_libraries(paltest_comparestringw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/test1/test1.cpp new file mode 100644 index 0000000..bdf2c3d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/test1/test1.cpp @@ -0,0 +1,99 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests that CompareStringW returns the correct value and can handle +** invalid parameters. +** +** +**==========================================================================*/ + +#define CSTR_LESS_THAN 1 +#define CSTR_EQUAL 2 +#define CSTR_GREATER_THAN 3 + +#include + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR str1[] = {'f','o','o',0}; + WCHAR str2[] = {'f','o','o','x',0}; + WCHAR str3[] = {'f','O','o',0}; + int flags = NORM_IGNORECASE | NORM_IGNOREWIDTH; + int ret; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + ret = CompareStringW(0x0409, flags, str1, -1, str2, -1); + if (ret != CSTR_LESS_THAN) + { + Fail("CompareStringW with \"%S\" (%d) and \"%S\" (%d) did not return " + "CSTR_LESS_THAN!\n", str1, -1, str2, -1); + } + + ret = CompareStringW(0x0409, flags, str1, -1, str2, 3); + if (ret != CSTR_EQUAL) + { + Fail("CompareStringW with \"%S\" (%d) and \"%S\" (%d) did not return " + "CSTR_EQUAL!\n", str1, -1, str2, 3); + } + + ret = CompareStringW(0x0409, flags, str2, -1, str1, -1); + if (ret != CSTR_GREATER_THAN) + { + Fail("CompareStringW with \"%S\" (%d) and \"%S\" (%d) did not return " + "CSTR_GREATER_THAN!\n", str2, -1, str1, -1); + } + + ret = CompareStringW(0x0409, flags, str1, -1, str3, -1); + if (ret != CSTR_EQUAL) + { + Fail("CompareStringW with \"%S\" (%d) and \"%S\" (%d) did not return " + "CSTR_EQUAL!\n", str1, -1, str3, -1); + } + + ret = CompareStringW(0x0409, flags, str3, -1, str1, -1); + if (ret != CSTR_EQUAL) + { + Fail("CompareStringW with \"%S\" (%d) and \"%S\" (%d) did not return " + "CSTR_EQUAL!\n", str3, -1, str1, -1); + } + + ret = CompareStringW(0x0409, flags, str3, -1, str1, -1); + if (ret != CSTR_EQUAL) + { + Fail("CompareStringW with \"%S\" (%d) and \"%S\" (%d) did not return " + "CSTR_EQUAL!\n", str3, -1, str1, -1); + } + + ret = CompareStringW(0x0409, flags, str1, 0, str3, -1); + if (ret != CSTR_LESS_THAN) + { + Fail("CompareStringW with \"%S\" (%d) and \"%S\" (%d) did not return " + "CSTR_GREATER_THAN!\n", str1, 0, str3, -1); + } + + + ret = CompareStringW(0x0409, flags, NULL, -1, str3, -1); + if (ret != 0) + { + Fail("CompareStringW should have returned 0, got %d!\n", ret); + } + if (GetLastError() != ERROR_INVALID_PARAMETER) + { + Fail("CompareStringW should have set the last error to " + "ERROR_INVALID_PARAMETER!\n"); + } + + PAL_Terminate(); + + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/test1/testinfo.dat new file mode 100644 index 0000000..d41de3e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/CompareStringW/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Locale Information +Function = CompareStringW +Name = Test #1 for CompareStringW +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests that CompareStringW returns the correct value and can handle +=invalid parameters. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/test1/CMakeLists.txt new file mode 100644 index 0000000..e994d15 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_getacp_test1 + ${SOURCES} +) + +add_dependencies(paltest_getacp_test1 coreclrpal) + +target_link_libraries(paltest_getacp_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/test1/test1.cpp new file mode 100644 index 0000000..8ea078e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/test1/test1.cpp @@ -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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests that GetACP returns the expected default code page. +** +** +**==========================================================================*/ + + +#include + +/* + * NOTE: We only support code page 65001 (UTF-8). + */ + +#define EXPECTED_CP 65001 + +int __cdecl main(int argc, char *argv[]) +{ + int ret; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + ret = GetACP(); + if (ret != EXPECTED_CP) + { + Fail("ERROR: got incorrect result for current ANSI code page!\n" + "Expected %d, got %d\n", EXPECTED_CP, ret); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/test1/testinfo.dat new file mode 100644 index 0000000..63a58f6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetACP/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = Locale Information +Function = GetACP +Name = Test #1 for GetACP +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests that GetACP returns code-page 1252. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/CMakeLists.txt new file mode 100644 index 0000000..6198713 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_getcpinfo_test1 + ${SOURCES} +) + +add_dependencies(paltest_getcpinfo_test1 coreclrpal) + +target_link_libraries(paltest_getcpinfo_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/test1.cpp new file mode 100644 index 0000000..ed9bbf9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/test1.cpp @@ -0,0 +1,54 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests that GetCPInfo works for CP_ACP and 0x4E4 (default codepage) +** Also makes sure it correctly handles an invalid code page. +** +** +**==========================================================================*/ + + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + CPINFO cpinfo; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + if (!GetCPInfo(CP_ACP, &cpinfo)) + { + Fail("GetCPInfo() unable to get info for CP_ACP\n"); + } + + if (!GetCPInfo(65001, &cpinfo)) + { + Fail("GetCPInfo() unable to get info for code page 65001 (utf8)\n"); + } + + if (GetCPInfo(-1, &cpinfo)) + { + Fail("GetCPInfo() did not error on invalid code page!\n"); + } + + if (GetLastError() != ERROR_INVALID_PARAMETER) + { + Fail("GetCPInfo() failed to set the last error to" + " ERROR_INVALID_PARAMETER!\n"); + } + + + PAL_Terminate(); + + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/testinfo.dat new file mode 100644 index 0000000..31be1d5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Locale Information +Function = GetCPInfo +Name = Test #1 for GetCPInfo +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests that GetCPInfo works for CP_ACP and 0x4E4 (default codepage) +=Also makes sure it correctly handles an invalid code page. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/CMakeLists.txt new file mode 100644 index 0000000..e10388a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_getcpinfo_test2 + ${SOURCES} +) + +add_dependencies(paltest_getcpinfo_test2 coreclrpal) + +target_link_libraries(paltest_getcpinfo_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/test2.cpp new file mode 100644 index 0000000..f52320f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/test2.cpp @@ -0,0 +1,60 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Tests that GetCPInfo gives the correct information for codepage 0x4E4 +** (the default). +** +** +**==========================================================================*/ + + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + CPINFO cpinfo; + int codepage; + unsigned int i; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* + * codepage 1252 (0x4E4): Windows 3.1 Latin 1 (U.S., Western Europe) + */ + codepage = 1252; + + if (!GetCPInfo(codepage, &cpinfo)) + { + Fail("GetCPInfo() failed on default ansi code page!\n"); + } + if (cpinfo.MaxCharSize != 1) + { + Fail("GetCPInfo() returned incorrect MaxCharSize information!\n"); + } + if (cpinfo.DefaultChar[0] != '?' || cpinfo.DefaultChar[1] != 0) + { + Fail("GetCPInfo() returned incorrect DefaultChar information"); + } + + for (i = 0; i + +/* Currently only one CodePage "CP_ACP" is supported by the PAL */ + +int __cdecl main(int argc, char *argv[]) +{ + CPINFO cpinfo; + + /* Initialize the PAL. + */ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Test GetCPInfo with CP_ACP. + */ + if (!GetCPInfo(CP_ACP, &cpinfo)) + { + Fail("GetCPInfo() unable to get info for code page %d!\n", CP_ACP); + } + + /* Terminate the PAL. + */ + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/testinfo.dat new file mode 100644 index 0000000..13f7a29 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/testinfo.dat @@ -0,0 +1,8 @@ +Version = 1.0 +Section = Locale Information +Function = GetCPInfo +Name = Test #3 for GetCPInfo +TYPE = DEFAULT +EXE1 = test3 +Description +=Tests that GetCPInfo passes for all valid code pages diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/CMakeLists.txt new file mode 100644 index 0000000..cca2aa5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_getlocaleinfow_test1 + ${SOURCES} +) + +add_dependencies(paltest_getlocaleinfow_test1 coreclrpal) + +target_link_libraries(paltest_getlocaleinfow_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/test1.cpp new file mode 100644 index 0000000..0994940 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/test1.cpp @@ -0,0 +1,89 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests that GetLocaleInfoW gives the correction information for +** LOCALE_NEUTRAL. +** +** +**==========================================================================*/ + +#include + + +int Types[] = { LOCALE_SDECIMAL, LOCALE_STHOUSAND, LOCALE_ILZERO, + LOCALE_SCURRENCY, LOCALE_SMONDECIMALSEP, LOCALE_SMONTHOUSANDSEP }; + +char *TypeStrings[] = { "LOCALE_SDECIMAL", "LOCALE_STHOUSAND", "LOCALE_ILZERO", + "LOCALE_SCURRENCY", "LOCALE_SMONDECIMALSEP", "LOCALE_SMONTHOUSANDSEP" }; + +#define NUM_TYPES (sizeof(Types) / sizeof(Types[0])) + +typedef WCHAR InfoStrings[NUM_TYPES][4]; + +typedef struct +{ + LCID lcid; + InfoStrings Strings; +} LocalInfoType; + +LocalInfoType Locales[] = +{ + {LOCALE_NEUTRAL, + {{'.',0}, {',',0}, {'1',0}, {'$',0}, {'.',0}, {',',0}}}, +}; + +int NumLocales = sizeof(Locales) / sizeof(Locales[0]); + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR buffer[256] = { 0 }; + int ret; + int i,j; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + for (i=0; i + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR buffer[256] = { 0 }; + int ret; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + ret = GetLocaleInfoW(LOCALE_NEUTRAL, LOCALE_SDECIMAL, buffer, 0); + if (ret != 2) + { + Fail("GetLocaleInfoW gave incorrect desired length for buffer.\n" + "Expected 2, got %d.\n", ret); + } + + ret = GetLocaleInfoW(LOCALE_NEUTRAL, LOCALE_SDECIMAL, buffer, 1); + if (ret != 0) + { + Fail("GetLocaleInfoW expected to return 0, returned %d", ret); + } + + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + Fail("GetLocaleInfoW failed to set last error to " + "ERROR_INSUFFICIENT_BUFFER!\n"); + } + + PAL_Terminate(); + + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/testinfo.dat new file mode 100644 index 0000000..b9fc488 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Locale Information +Function = GetLocaleInfoW +Name = Test #2 for GetLocaleInfoW +TYPE = DEFAULT +EXE1 = test2 +Description +=Tests that GetLocaleInfoW will correctly return the amount of +=buffer space required. Also tests that it correctly handles a +=buffer of insufficient space. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/CMakeLists.txt new file mode 100644 index 0000000..afc3a30 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_isdbcsleadbyte_test1 + ${SOURCES} +) + +add_dependencies(paltest_isdbcsleadbyte_test1 coreclrpal) + +target_link_libraries(paltest_isdbcsleadbyte_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/test1.cpp new file mode 100644 index 0000000..ad326be --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/test1.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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests that IsDBCSLeadByte does not find any lead-bytes in the +** current ansi code page +** +** +** TODO: Test for positive, i.e., if it is potentially isdbcsleadbyte +**==========================================================================*/ + + +#include + +void DoTest() +{ + int value; + int ret; + int i; + + + for (i=0; i<256; i++) + { + value = IsDBCSLeadByte(i); + + ret = GetLastError(); + if (ret == ERROR_INVALID_PARAMETER) + { + Fail("IsDBCSLeadByte unexpectedly errored with ERROR_INVALID_PARAMETER for %d!\n", i); + } + else if (ret != 0) + { + Fail("IsDBCSLeadByte had an unexpected error [%d] for %d!\n", ret, i); + } + else if (value) + { + Fail("IsDBCSLeadByte incorrectly found a lead byte in value [%d] for" + " %d\n", value, i); + } + + } +} + +int __cdecl main(int argc, char *argv[]) +{ + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoTest(); + + PAL_Terminate(); + +// setlocale( "japan", ); + + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/testinfo.dat new file mode 100644 index 0000000..43cd2ae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Locale Information +Function = IsDBCSLeadByte +Name = Test #1 for IsDBCSLeadByte +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests that IsDBCSLeadByte does not find any lead-bytes in the +=current ansi code page diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/CMakeLists.txt new file mode 100644 index 0000000..b3901ca --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_isdbcsleadbyteex_test1 + ${SOURCES} +) + +add_dependencies(paltest_isdbcsleadbyteex_test1 coreclrpal) + +target_link_libraries(paltest_isdbcsleadbyteex_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/test1.cpp new file mode 100644 index 0000000..9466f48 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/test1.cpp @@ -0,0 +1,72 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests that IsDBCSLeadByteEx does not find any lead-bytes in the +** current ansi code page or the default code page. Also tests that +** it correctly handles an invalid codepage. +** +** +**==========================================================================*/ + + +#include + +void DoTest(int codepage) +{ + int value; + int ret; + int i; + + + for (i=0; i<256; i++) + { + value = IsDBCSLeadByteEx(codepage, i); + + ret = GetLastError(); + if (ret == ERROR_INVALID_PARAMETER) + { + Fail("IsDBCSLeadByteEx unexpectedly errored with ERROR_INVALID_PARAMETER!\n"); + } + else if (ret != 0) + { + Fail("IsDBCSLeadByteEx had an unexpected error!\n"); + } + else if (value) + { + Fail("IsDBCSLeadByteEx incorrectly found a lead byte in code " + "page %d\n", codepage); + } + + } +} + +int __cdecl main(int argc, char *argv[]) +{ + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + if (IsDBCSLeadByteEx(-1, 0)) + { + Fail("IsDBCSLeadByteEx did not error on an invalid code page!\n"); + } + + /* Clear the last error. */ + SetLastError(0); + + + DoTest(0); + DoTest(CP_ACP); + + PAL_Terminate(); + + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/testinfo.dat new file mode 100644 index 0000000..b85e387 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Locale Information +Function = IsDBCSLeadByteEx +Name = Test #1 for IsDBCSLeadByteEx +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests that IsDBCSLeadByteEx does not find any lead-bytes in the +=current ansi code page or the default code page. Also tests that +=it correctly handles an invalid codepage. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/CMakeLists.txt new file mode 100644 index 0000000..03456f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/CMakeLists.txt new file mode 100644 index 0000000..24c812e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_multibytetowidechar_test1 + ${SOURCES} +) + +add_dependencies(paltest_multibytetowidechar_test1 coreclrpal) + +target_link_libraries(paltest_multibytetowidechar_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/test1.cpp new file mode 100644 index 0000000..81f58a5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/test1.cpp @@ -0,0 +1,81 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests MultiByteToWideChar with all the ASCII characters (0-127). +** Also tests that WideCharToMultiByte handles different buffer +** lengths correctly (0, -1, and a valid length) +** +** +**==========================================================================*/ + +#include + +/* + * For now, it is assumed that MultiByteToWideChar will only be used in the PAL + * with CP_ACP, and that dwFlags will be 0. + */ + +int __cdecl main(int argc, char *argv[]) +{ + char mbStr[128]; + WCHAR wideStr[128]; + int ret; + int i; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + for (i=0; i<128; i++) + { + mbStr[i] = 127 - i; + wideStr[i] = 0; + } + + + ret = MultiByteToWideChar(CP_ACP, 0, mbStr, -1, wideStr, 0); + if (ret != 128) + { + Fail("MultiByteToWideChar did not return correct string length!\n" + "Got %d, expected %d\n", ret, 128); + } + + /* Make sure the ASCII set (0-127) gets translated correctly */ + ret = MultiByteToWideChar(CP_ACP, 0, mbStr, -1, wideStr, 128); + if (ret != 128) + { + Fail("MultiByteToWideChar did not return correct string length!\n" + "Got %d, expected %d\n", ret, 128); + } + + for (i=0; i<128; i++) + { + if (wideStr[i] != (WCHAR)(127 - i)) + { + Fail("MultiByteToWideChar failed to translate correctly!\n" + "Expected character %d to be %c (%x), got %c (%x)\n", + i, 127 - i, 127 - i,wideStr[i], wideStr[i]); + } + } + + + /* try a 0 length string */ + mbStr[0] = 0; + ret = MultiByteToWideChar(CP_ACP, 0, mbStr, -1, wideStr, 0); + if (ret != 1) + { + Fail("MultiByteToWideChar did not return correct string length!\n" + "Got %d, expected %d\n", ret, 1); + } + + PAL_Terminate(); + + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/testinfo.dat new file mode 100644 index 0000000..0e4591d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Locale Information +Function = MultiByteToWideChar +Name = Test #1 for MultiByteToWideChar +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests MultiByteToWideChar with all the ASCII characters (0-127). +=Also tests that WideCharToMultiByte handles different buffer +=lengths correctly (0, -1, and a valid length) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/CMakeLists.txt new file mode 100644 index 0000000..e60ae20 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_multibytetowidechar_test2 + ${SOURCES} +) + +add_dependencies(paltest_multibytetowidechar_test2 coreclrpal) + +target_link_libraries(paltest_multibytetowidechar_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/test2.cpp new file mode 100644 index 0000000..1370dba --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/test2.cpp @@ -0,0 +1,68 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Tests that MultiByteToWideChar respects the length of the wide +** character string. + +** +**==========================================================================*/ + +#include + +/* + * For now, it is assumed that MultiByteToWideChar will only be used in the PAL + * with CP_ACP, and that dwFlags will be 0. + */ + +int __cdecl main(int argc, char *argv[]) +{ + char mbStr[128]; + WCHAR wideStr[128]; + int ret; + int i; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + for (i=0; i<128; i++) + { + mbStr[i] = 'a'; + wideStr[i] = 0; + } + + mbStr[127] = 0; + + + ret = MultiByteToWideChar(CP_ACP, 0, mbStr, 10, wideStr, 0); + if (ret != 10) + { + Fail("MultiByteToWideChar did not return correct string length!\n" + "Got %d, expected %d\n", ret, 10); + } + + wideStr[10] = (WCHAR) 'b'; + + ret = MultiByteToWideChar(CP_ACP, 0, mbStr, 10, wideStr, 128); + if (ret != 10) + { + Fail("MultiByteToWideChar did not return correct string length!\n" + "Got %d, expected %d\n", ret, 10); + } + + if (wideStr[10] != 'b') + { + Fail("WideCharToMultiByte overflowed the destination buffer!\n"); + } + + PAL_Terminate(); + + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/testinfo.dat new file mode 100644 index 0000000..5211db1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Locale Information +Function = MultiByteToWideChar +Name = Test #2 for MultiByteToWideChar +TYPE = DEFAULT +EXE1 = test2 +Description +=Tests that MultiByteToWideChar respects the length of the wide +=character string. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/CMakeLists.txt new file mode 100644 index 0000000..e6397e5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_multibytetowidechar_test3 + ${SOURCES} +) + +add_dependencies(paltest_multibytetowidechar_test3 coreclrpal) + +target_link_libraries(paltest_multibytetowidechar_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/test3.cpp new file mode 100644 index 0000000..1b3a4bd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/test3.cpp @@ -0,0 +1,73 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Tests that MultiByteToWideChar correctly handles the following +** error conditions: insufficient buffer space, invalid code pages, +** and invalid flags. +** +** +**==========================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + char mbStr[128]; + WCHAR wideStr[128]; + int ret; + int i; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + for (i=0; i<128; i++) + { + mbStr[i] = 'a'; + wideStr[i] = 0; + } + + mbStr[127] = 0; + + /* try with insufficient buffer space */ + ret = MultiByteToWideChar(CP_ACP, 0, mbStr, -1, wideStr, 10); + if (ret != 0) + { + Fail("MultiByteToWideChar did not return an error!\n" + "Expected return of 0, got %d", ret); + } + + ret = GetLastError(); + if (ret != ERROR_INSUFFICIENT_BUFFER) + { + Fail("MultiByteToWideChar did not set the last error to " + "ERROR_INSUFFICIENT_BUFFER!\n"); + } + + /* try with a wacky code page */ + ret = MultiByteToWideChar(-1, 0, mbStr, -1, wideStr, 128); + if (ret != 0) + { + Fail("MultiByteToWideChar did not return an error!\n" + "Expected return of 0, got %d", ret); + } + + ret = GetLastError(); + if (ret != ERROR_INVALID_PARAMETER) + { + Fail("MultiByteToWideChar did not set the last error to " + "ERROR_INVALID_PARAMETER!\n"); + } + + PAL_Terminate(); + + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/testinfo.dat new file mode 100644 index 0000000..c59f285 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Locale Information +Function = MultiByteToWideChar +Name = Test #3 for MultiByteToWideChar +TYPE = DEFAULT +EXE1 = test3 +Description +=Tests that MultiByteToWideChar correctly handles the following +=error conditions: insufficient buffer space, invalid code pages, +=and invalid flags. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/CMakeLists.txt new file mode 100644 index 0000000..feb8d69 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_multibytetowidechar_test4 + ${SOURCES} +) + +add_dependencies(paltest_multibytetowidechar_test4 coreclrpal) + +target_link_libraries(paltest_multibytetowidechar_test4 + ${COMMON_TEST_LIBRARIES} +) \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.cpp new file mode 100644 index 0000000..7d382de --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.cpp @@ -0,0 +1,230 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Tests MultiByteToWideChar with a UTF-8 encoding +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + int ret; + int ret2; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + const char * const utf8Strings[] = + { + // Correct strings + + // Empty string + "", + // 1 byte encoded 1 character long string + "A", + // 2 byte encoded 1 character long string + "\xC2\x80", + // 3 byte encoded 1 character long string + "\xE0\xA0\x80", + // 1 byte encoded characters only + "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + // valid 2 byte encoded characters only + "\xC2\x80\xC3\xBF\xC7\x81\xDF\xBF", + // valid 3 byte encoded characters only + "\xE0\xA0\x80\xE1\xB6\x88\xE1\x80\x80\xEF\xBF\xBF", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char + "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one + "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one + "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char + "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char + "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one + "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one + "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char + "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF", + // surrogates + "\xF0\x90\x80\x80\xF0\x90\x89\x80\xF3\x80\x8E\xB0\xF4\x8F\xBF\xBF", + + // Strings with errors + // Incomplete 2 byte encoded character 1 byte missing standalone + "\xC2", + // Incomplete 3 byte encoded character 1 byte missing standalone + "\xE0\xA0", + // Incomplete 3 byte encoded character 2 bytes missing standalone + "\xE0", + // Incomplete surrogate character 1 byte missing standalone + "\xF0\x90\x80", + // Incomplete surrogate character 2 bytes missing standalone + "\xF0\x90", + // Incomplete surrogate character 3 bytes missing standalone + "\xF0", + // Trailing byte with no lead byte standalone + "\x80", + // Incomplete 2 byte encoded character 1 byte missing between 1 byte chars + "\x41\xC2\x42", + // Incomplete 3 byte encoded character 1 byte missing between 1 byte chars + "\x41\xE0\xA0\x42", + // Incomplete 3 byte encoded character 2 bytes missing between 1 byte chars + "\x41\xE0\x42", + // Trailing byte with no lead byte between 1 byte chars + "\x41\x80\x42", + // Incomplete 2 byte encoded character 1 byte missing before 1 byte char + "\xC2\x42", + // Incomplete 3 byte encoded character 1 byte missing before 1 byte char + "\xE0\xA0\x42", + // Incomplete 3 byte encoded character 2 bytes missing before 1 byte char + "\xE0\x42", + // Trailing byte with no lead byte before 1 byte char + "\x80\x42", + // Incomplete 2 byte encoded character 1 byte missing after 1 byte char + "\x41\xC2", + // Incomplete 3 byte encoded character 1 byte missing after 1 byte char + "\x41\xE0\xA0", + // Incomplete 3 byte encoded character 2 bytes missing after 1 byte char + "\x41\xE0", + // Trailing byte with no lead byte after 1 byte char + "\x41\x80", + // Incomplete 2 byte encoded character 1 byte missing between 2 byte chars + "\xC2\x80\xC2\xC3\xBF", + // Incomplete 3 byte encoded character 1 byte missing between 2 byte chars + "\xC2\x80\xE0\xA0\xC3\xBF", + // Incomplete 3 byte encoded character 2 bytes missing between 2 byte chars + "\xC2\x80\xE0\xC3\xBF", + // Trailing byte with no lead byte between 2 byte chars + "\xC2\x80\x80\xC3\xBF", + // 2 byte encoded character in non-shortest form encodings (these are not allowed) + "\xC0\x80", + // 3 byte encoded character in non-shortest form encodings (these are not allowed) + "\xE0\x80\x80", + // 4 byte encoded character in non-shortest form encodings (these are not allowed) + "\xF0\x80\x80\x80", + }; + + const WCHAR * const unicodeStrings[] = + { + // Empty string + W(""), + // 1 byte encoded 1 character long string + W("A"), + // 2 byte encoded 1 character long string + W("\x0080"), + // 3 byte encoded 1 character long string + W("\x0800"), + // 1 byte encoded characters only + W("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), + // 2 byte encoded characters only + W("\x0080\x00FF\x01C1\x07FF"), + // valid 3 byte encoded characters only + W("\x0800\x1D88\x1000\xFFFF"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char + W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one + W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one + W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char + W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char + W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one + W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one + W("\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char + W("\x0080\x00FF\x0043\x0044\x01C1\x07FF"), + // surrogates + W("\xD800\xDC00\xD800\xDE40\xDAC0\xDFB0\xDBFF\xDFFF"), + + // Strings with errors + // Incomplete 2 byte encoded character standalone + W("\xFFFD"), + // Incomplete 3 byte encoded character 1 byte missing standalone + W("\xFFFD"), + // Incomplete 3 byte encoded character 2 bytes missing standalone + W("\xFFFD"), + // Incomplete surrogate character 1 byte missing standalone + W("\xFFFD"), + // Incomplete surrogate character 2 bytes missing standalone + W("\xFFFD"), + // Incomplete surrogate character 3 bytes missing standalone + W("\xFFFD"), + // Trailing byte with no lead byte standalone + W("\xFFFD"), + // Incomplete 2 byte encoded character 1 byte missing between 1 byte chars + W("\x0041\xFFFD\x0042"), + // Incomplete 3 byte encoded character 1 byte missing between 1 byte chars + W("\x0041\xFFFD\x0042"), + // Incomplete 3 byte encoded character 2 bytes missing between 1 byte chars + W("\x0041\xFFFD\x0042"), + // Trailing byte with no lead byte between 1 byte chars + W("\x0041\xFFFD\x0042"), + // Incomplete 2 byte encoded character 1 byte missing before 1 byte char + W("\xFFFD\x0042"), + // Incomplete 3 byte encoded character 1 byte missing before 1 byte char + W("\xFFFD\x0042"), + // Incomplete 3 byte encoded character 2 bytes missing before 1 byte char + W("\xFFFD\x0042"), + // Trailing byte with no lead byte before 1 byte char + W("\xFFFD\x0042"), + // Incomplete 2 byte encoded character 1 byte missing after 1 byte char + W("\x0041\xFFFD"), + // Incomplete 3 byte encoded character 1 byte missing after 1 byte char + W("\x0041\xFFFD"), + // Incomplete 3 byte encoded character 2 bytes missing after 1 byte char + W("\x0041\xFFFD"), + // Trailing byte with no lead byte after 1 byte char + W("\x0041\xFFFD"), + // Incomplete 2 byte encoded character 1 byte missing between 2 byte chars + W("\x0080\xFFFD\x00FF"), + // Incomplete 3 byte encoded character 1 byte missing between 2 byte chars + W("\x0080\xFFFD\x00FF"), + // Incomplete 3 byte encoded character 2 bytes missing between 2 byte chars + W("\x0080\xFFFD\x00FF"), + // Trailing byte with no lead byte between 2 byte chars + W("\x0080\xFFFD\x00FF"), + // 2 byte encoded character in non-shortest form encodings (these are not allowed) + W("\xFFFD\xFFFD"), + // 3 byte encoded character in non-shortest form encodings (these are not allowed) + W("\xFFFD\xFFFD"), + // 4 byte encoded character in non-shortest form encodings (these are not allowed) + W("\xFFFD\xFFFD\xFFFD"), + }; + + for (int i = 0; i < (sizeof(utf8Strings) / sizeof(utf8Strings[0])); i++) + { + ret = MultiByteToWideChar(CP_UTF8, 0, utf8Strings[i], -1, NULL, 0); + WCHAR* wideBuffer = (WCHAR*)malloc(ret * sizeof(WCHAR)); + ret2 = MultiByteToWideChar(CP_UTF8, 0, utf8Strings[i], -1, wideBuffer, ret); + if (ret != ret2) + { + Fail("MultiByteToWideChar string %d: returned different string length for empty and real dest buffers!\n" + "Got %d for the empty one, %d for real one.\n", i, ret2, ret); + } + + if (wcscmp(wideBuffer, unicodeStrings[i]) != 0) + { + Fail("MultiByteToWideChar string %d: the resulting string doesn't match the expected one!\n", i); + } + + free(wideBuffer); + } + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/testinfo.dat new file mode 100644 index 0000000..e95f413 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/testinfo.dat @@ -0,0 +1,13 @@ +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# + +Version = 1.0 +Section = Locale Information +Function = MultiByteToWideChar +Name = Test #4 for MultiByteToWideChar +TYPE = DEFAULT +EXE1 = test4 +Description +=Tests MultiByteToWideChar with UTF-8 encoded strings +=containing various corner cases \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/CMakeLists.txt new file mode 100644 index 0000000..7db3404 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/CMakeLists.txt new file mode 100644 index 0000000..a55f4e8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_widechartomultibyte_test1 + ${SOURCES} +) + +add_dependencies(paltest_widechartomultibyte_test1 coreclrpal) + +target_link_libraries(paltest_widechartomultibyte_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/test1.cpp new file mode 100644 index 0000000..cd763f3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/test1.cpp @@ -0,0 +1,102 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests WideCharToMultiByte with all the ASCII characters (0-127). +** Also tests that WideCharToMultiByte handles different buffer +** lengths correctly (0, -1, and a valid length) +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + char mbStr[128]; + WCHAR wideStr[128]; + int ret; + int i; + int k; + BOOL bRet=TRUE; + + /* These codepages are currently supported by the PAL */ + int codePages[] ={ + CP_ACP, + CP_UTF8 + }; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /* Go through all of the code pages */ + for(i=0; i<(sizeof(codePages)/sizeof(int)); i++) + { + + for (k=0; k<128; k++) + { + wideStr[k] = 127 - k; + mbStr[k] = 0; + } + + /* Convert with buffer size of 0 */ + ret = WideCharToMultiByte(codePages[i], 0, wideStr, -1, + mbStr, 0, NULL, NULL); + if (ret != 128) + { + Trace("WideCharToMultiByte did not return correct string length!\n" + "Got %d, expected %d for code page %d with error %u.\n", + ret, 128,codePages[i],GetLastError()); + bRet=FALSE; + } + + /* Make sure the ASCII set (0-127) gets translated correctly */ + ret = WideCharToMultiByte(codePages[i], 0, wideStr, -1, + mbStr, 128, NULL, NULL); + if (ret != 128) + { + Trace("WideCharToMultiByte did not return correct string length!\n" + "Got %d, expected %d for code page %d with error %u.\n", + ret, 128,codePages[i],GetLastError()); + bRet=FALSE; + } + + for (k=0; k<128; k++) + { + if (mbStr[k] != 127 - k) + { + Trace("WideCharToMultiByte failed to translate correctly!\n" + "Expected character %d to be %c (%x), got %c (%x) for " + "code page %d\n",k, 127 - k, 127 - k,mbStr[k], mbStr[k], + codePages[i]); + bRet=FALSE; + } + } + + + /* try a 0 length string ("") */ + wideStr[0] = '\0'; + ret = WideCharToMultiByte(codePages[i], 0, wideStr, -1, + mbStr, 0, NULL, NULL); + if (ret != 1) + { + Trace("WideCharToMultiByte did not return correct string length!\n" + "Got %d, expected %d for code page %d with error %u.\n", + ret, 1,codePages[i],GetLastError()); + bRet=FALSE; + } + } + + int result = bRet ? PASS : FAIL; + PAL_TerminateEx(result); + return result; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/testinfo.dat new file mode 100644 index 0000000..9fb5f0f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Locale Information +Function = WideCharToMultiByte +Name = Test #1 for WideCharToMultiByte +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests WideCharToMultiByte with all the ASCII characters (0-127). +=Also tests that WideCharToMultiByte handles different buffer +=lengths correctly (0, -1, and a valid length) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/CMakeLists.txt new file mode 100644 index 0000000..941f0f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_widechartomultibyte_test2 + ${SOURCES} +) + +add_dependencies(paltest_widechartomultibyte_test2 coreclrpal) + +target_link_libraries(paltest_widechartomultibyte_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/test2.cpp new file mode 100644 index 0000000..f5d40ae --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/test2.cpp @@ -0,0 +1,88 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Tests that WideCharToMultiByte respects the length of the wide +** character string. +** +** +**==========================================================================*/ + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + char mbStr[128]; + WCHAR wideStr[128]; + int ret; + int i; + int k; + BOOL bRet=TRUE; + + /* These codepages are currently supported by the PAL */ + int codePages[] ={ + CP_ACP, + CP_UTF8 + }; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Go through all of the code pages */ + for(i=0; i<(sizeof(codePages)/sizeof(int)); i++) + { + + /* Filling the arrays */ + for (k=0; k<128; k++) + { + wideStr[k] = 'a'; + mbStr[i] = 0; + } + + wideStr[127] = 0; + + /* Passing a buffer that is too small */ + ret = WideCharToMultiByte(codePages[i], 0, wideStr, 10, + mbStr, 0, NULL, NULL); + if (ret != 10) + { + Trace("WideCharToMultiByte did not return correct string length!\n" + "Got %d, expected %d for %d with error %u.\n", ret, 10, + codePages[i], GetLastError()); + bRet = FALSE; + } + + /* Passing a sufficiently large buffer */ + mbStr[10] = 'b'; + ret = WideCharToMultiByte(codePages[i], 0, wideStr, 10, + mbStr, 128, NULL, NULL); + if (ret != 10) + { + Trace("WideCharToMultiByte did not return correct string length!\n" + "Got %d, expected %d for code page %d with error %u.\n", + ret, 10, codePages[i], GetLastError()); + bRet = FALSE; + } + + /* Verifying overflow of the destination string did not occur */ + if (mbStr[10] != 'b') + { + Trace("WideCharToMultiByte overflowed the destination buffer for " + "code page %d.\n", codePages[i]); + bRet = FALSE; + } + + } + + int result = bRet ? PASS : FAIL; + PAL_TerminateEx(result); + return result; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/testinfo.dat new file mode 100644 index 0000000..e5b50b8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Locale Information +Function = WideCharToMultiByte +Name = Test #2 for WideCharToMultiByte +TYPE = DEFAULT +EXE1 = test2 +Description +=Tests that WideCharToMultiByte respects the length of the wide +=character string. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/CMakeLists.txt new file mode 100644 index 0000000..d2719ad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_widechartomultibyte_test3 + ${SOURCES} +) + +add_dependencies(paltest_widechartomultibyte_test3 coreclrpal) + +target_link_libraries(paltest_widechartomultibyte_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/test3.cpp new file mode 100644 index 0000000..ecd26ad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/test3.cpp @@ -0,0 +1,100 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Tests that WideCharToMultiByte correctly handles the following +** error conditions: insufficient buffer space, invalid code pages, +** and invalid flags. +** +** +**==========================================================================*/ + + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + char mbStr[128]; + WCHAR wideStr[128]; + int ret; + int i; + int k; + BOOL bRet=TRUE; + + /* These codepages are currently supported by the PAL */ + int codePages[] ={ + CP_ACP, + CP_UTF8 + }; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Go through all of the code pages */ + for(i=0; i<(sizeof(codePages)/sizeof(int)); i++) + { + + for (k=0; k<128; k++) + { + wideStr[k] = 'a'; + mbStr[k] = 0; + } + + wideStr[127] = 0; + + /* try with insufficient buffer space */ + ret = WideCharToMultiByte(codePages[i], 0, wideStr, -1, + mbStr, 10, NULL, NULL); + if (ret != 0) + { + Trace("WideCharToMultiByte did not return an error!\n" + "Expected return of 0, got %d for code page %d.\n", ret, + codePages[i]); + bRet = FALSE; + } + + ret = GetLastError(); + if (ret != ERROR_INSUFFICIENT_BUFFER) + { + Fail("WideCharToMultiByte set the last error to %u instead of " + "ERROR_INSUFFICIENT_BUFFER for code page %d.\n", + GetLastError(),codePages[i]); + bRet = FALSE; + } + } + + /* Return failure if any of the code pages returned the wrong results */ + if(!bRet) + { + return FAIL; + } + + /* try with a wacky code page */ + ret = WideCharToMultiByte(-1, 0, wideStr, -1, mbStr, 128, NULL, NULL); + if (ret != 0) + { + Fail("WideCharToMultiByte did not return an error!\n" + "Expected return of 0, got %d for invalid code page.\n", ret); + } + + ret = GetLastError(); + if (ret != ERROR_INVALID_PARAMETER) + { + Fail("WideCharToMultiByte set the last error to %u instead of " + "ERROR_INVALID_PARAMETER for invalid code page -1.\n", + GetLastError()); + } + + PAL_Terminate(); + + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/testinfo.dat new file mode 100644 index 0000000..b737686 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Locale Information +Function = WideCharToMultiByte +Name = Test #3 for WideCharToMultiByte +TYPE = DEFAULT +EXE1 = test3 +Description +=Tests that WideCharToMultiByte correctly handles the following +=error conditions: insufficient buffer space and invalid code pages. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/CMakeLists.txt new file mode 100644 index 0000000..43bfbd0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_widechartomultibyte_test4 + ${SOURCES} +) + +add_dependencies(paltest_widechartomultibyte_test4 coreclrpal) + +target_link_libraries(paltest_widechartomultibyte_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/test4.cpp new file mode 100644 index 0000000..e82994b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/test4.cpp @@ -0,0 +1,131 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Tests that WideCharToMultiByte correctly handles WC_NO_BEST_FIT_CHARS +** +** +**==========================================================================*/ + + +#include + +/* C with a circumflex */ +char16_t ustr[2] = { 0x108, 0 }; + +/* expected conversion when best fit is allowed on Windows */ +char* lpBestFitRes = "C"; + +/* expected conversion when no default character is specified */ +char* lpResStr1 = "?"; + +/* expected conversion when the default character is 'k' */ +char myDefaultChar = 'k'; +char* lpResStr2 = "k"; + +int +TestWideCharToMultiByte( + IN UINT CodePage, + IN DWORD dwFlags, + IN LPCSTR lpDefaultChar, + IN LPSTR lpResStr) +{ + char mbstr[30]; + int ret; + int testStatus = PASS; + BOOL usedDefaultChar = FALSE; + + printf("WideCharToMultiByte (CodePage=%d, dwFlags=%#x, default=%c)\n", + CodePage, dwFlags, lpDefaultChar?*lpDefaultChar:' '); + ret = WideCharToMultiByte(CodePage, dwFlags, ustr, -1, mbstr, sizeof(mbstr), + lpDefaultChar, &usedDefaultChar); + if (ret != 0) { + printf(" converted C with circumflex to in Unicode to multibyte: " + "\"%s\"\n", mbstr); + printf(" used default character?: %d\n", usedDefaultChar); + if (strcmp(mbstr, lpResStr) != 0 || usedDefaultChar != TRUE) + { + printf("!!!! failed conversion !!!!\n"); + testStatus = FAIL; + } + } + else { + printf("!!!! failed conversion !!!!\n"); + testStatus = FAIL; + } + return testStatus; +} + +int __cdecl main(int argc, char *argv[]) +{ + int testStatus = PASS; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* Use WideCharToMultiByte to convert the string in code page CP_ACP. + * Note that the resulting string will be different on Windows PAL and + * Unix PAL. On Windows, the default best fit behavior will map C with + * circumflex to C. + * + * testStatus |= TestWideCharToMultiByte(CP_ACP, 0, NULL, lpBestFitRes); + * + * On Unix, where there is no support for finding best fit, it will be + * mapped to a '?'. In addition, it will trigger an ASSERT in the dbg/chk + * builds. + * + * testStatus |= TestWideCharToMultiByte(CP_ACP, 0, NULL, lpResStr1); + */ + + /* Use WideCharToMultiByte with WC_NO_BEST_FIR_CHARS to convert the string + * in CP_ACP (1252 by default). This will prevent it from mapping the C + * with circumflex to its closest match in the ANSI code page: C + */ + testStatus |= TestWideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, NULL, lpResStr1); + + + /* Use WideCharToMultiByte with WC_NO_BEST_FIR_CHARS and a default character + * to convert the string. This will prevent it from mapping the C with + * circumflex to its closest match in the ANSI code page: C. It will be + * replaced with the specified default character. + */ + testStatus |= TestWideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, &myDefaultChar, lpResStr2); + + /* Use WideCharToMultiByte to convert the string in code page 1253 + * Note that the resulting string will be different on Windows PAL and + * Unix PAL. On Windows, the default best fit behavior will map C with + * circumflex to C. + * + * testStatus |= TestWideCharToMultiByte(1253, 0, NULL, lpBestFitRes); + * + * On Unix, where there is no support for finding best fit, it will be + * mapped to a '?'. In addition, it will trigger an ASSERT in the dbg/chk + * builds. + * + * testStatus |= TestWideCharToMultiByte(1253, 0, NULL, lpResStr1); + */ + + /* Use WideCharToMultiByte with WC_NO_BEST_FIR_CHARS to convert the string + * in 1253. This will prevent it from mapping the C + * with circumflex to its closest match in the ANSI code page: C + */ + testStatus |= TestWideCharToMultiByte(1253, WC_NO_BEST_FIT_CHARS, NULL, lpResStr1); + + /* Use WideCharToMultiByte with WC_NO_BEST_FIR_CHARS and a default + * character to convert the string in 1253. This will prevent it from + * mapping the C with circumflex to its closest match in the ANSI code + * page: C. It will be replaced with the specified default character. + */ + testStatus |= TestWideCharToMultiByte(1253, WC_NO_BEST_FIT_CHARS, &myDefaultChar, lpResStr2); + + PAL_TerminateEx(testStatus); + + return testStatus; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/testinfo.dat new file mode 100644 index 0000000..03b00d3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/testinfo.dat @@ -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. + +Version = 1.0 +Section = Locale Information +Function = WideCharToMultiByte +Name = Test #4 for WideCharToMultiByte +TYPE = DEFAULT +EXE1 = test4 +Description +=Tests that WideCharToMultiByte correctly handles WC_NO_BEST_FIT_CHARS diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/CMakeLists.txt new file mode 100644 index 0000000..5906634 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_widechartomultibyte_test5 + ${SOURCES} +) + +add_dependencies(paltest_widechartomultibyte_test5 coreclrpal) + +target_link_libraries(paltest_widechartomultibyte_test5 + ${COMMON_TEST_LIBRARIES} +) \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.cpp new file mode 100644 index 0000000..393516a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.cpp @@ -0,0 +1,154 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Tests WideCharMultiByte with UTF-8 encoding +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + int ret; + int ret2; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + const WCHAR * const unicodeStrings[] = + { + // Correct strings + + // Empty string + W(""), + // 1 byte encoded 1 character long string + W("A"), + // 2 byte encoded 1 character long string + W("\x0080"), + // 3 byte encoded 1 character long string + W("\x0800"), + // 1 byte encoded characters only + W("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), + // 2 byte encoded characters only + W("\x0080\x00FF\x01C1\x07FF"), + // valid 3 byte encoded characters only + W("\x0800\x1D88\x1000\xFFFF"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char + W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one + W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one + W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char + W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char + W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one + W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one + W("\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char + W("\x0080\x00FF\x0043\x0044\x01C1\x07FF"), + // Surrogates + W("\xD800\xDC00\xD800\xDE40\xDAC0\xDFB0\xDBFF\xDFFF"), + + // Strings with errors + + // Single high surrogate + W("\xD800"), + // Single low surrogate + W("\xDC00"), + // Character followed by single high surrogate + W("\x0041\xD800"), + // Character followed by single low surrogate + W("\x0041\xDC00"), + // Single high surrogate between two characters + W("\x0041\xD800\x0042"), + // Single low surrogate between two characters + W("\x0041\xDC00\x0042"), + }; + + const char * const utf8Strings[] = + { + // Correct strings + + // Empty string + "", + // 1 byte encoded 1 character long string + "A", + // 2 byte encoded 1 character long string + "\xC2\x80", + // 3 byte encoded 1 character long string + "\xE0\xA0\x80", + // 1 byte encoded characters only + "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + // valid 2 byte encoded characters only + "\xC2\x80\xC3\xBF\xC7\x81\xDF\xBF", + // valid 3 byte encoded characters only + "\xE0\xA0\x80\xE1\xB6\x88\xE1\x80\x80\xEF\xBF\xBF", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char + "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one + "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one + "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char + "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char + "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one + "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one + "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char + "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF", + // Surrogates + "\xF0\x90\x80\x80\xF0\x90\x89\x80\xF3\x80\x8E\xB0\xF4\x8F\xBF\xBF", + + // Strings with errors + + // Single high surrogate + "\xEF\xBF\xBD", + // Single low surrogate + "\xEF\xBF\xBD", + // Character followed by single high surrogate + "\x41\xEF\xBF\xBD", + // Character followed by single low surrogate + "\x41\xEF\xBF\xBD", + // Single high surrogate between two characters + "\x41\xEF\xBF\xBD\x42", + // Single low surrogate between two characters + "\x41\xEF\xBF\xBD\x42", + }; + + for (int i = 0; i < (sizeof(unicodeStrings) / sizeof(unicodeStrings[0])); i++) + { + ret = WideCharToMultiByte(CP_UTF8, 0, unicodeStrings[i], -1, NULL, 0, NULL, NULL); + CHAR* utf8Buffer = (CHAR*)malloc(ret * sizeof(CHAR)); + ret2 = WideCharToMultiByte(CP_UTF8, 0, unicodeStrings[i], -1, utf8Buffer, ret, NULL, NULL); + if (ret != ret2) + { + Fail("WideCharToMultiByte string %d: returned different string length for empty and real dest buffers!\n" + "Got %d for the empty one, %d for real one.\n", i, ret2, ret); + } + + if (strcmp(utf8Buffer, utf8Strings[i]) != 0) + { + Fail("WideCharToMultiByte string %d: the resulting string doesn't match the expected one!\n", i); + } + + free(utf8Buffer); + } + + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/testinfo.dat new file mode 100644 index 0000000..485d940 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/testinfo.dat @@ -0,0 +1,13 @@ +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# + +Version = 1.0 +Section = Locale Information +Function = WideCharToMultiByte +Name = Test #5 for WideCharToMultiByte +TYPE = DEFAULT +EXE1 = test5 +Description +=Tests WideCharToMultiByte conversion to UTF-8 +=containing various corner cases \ No newline at end of file diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/manual-inspect.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/manual-inspect.dat new file mode 100644 index 0000000..c541b2f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/manual-inspect.dat @@ -0,0 +1,17 @@ +# 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. + +# Automatable to detect gross errors; also manually inspect for proper behaviour +miscellaneous/messageboxw/test1,1 +# Automatable to detect gross errors; also manually inspect for proper behaviour +# Env var PAL_DISABLE_MESSAGEBOX=1 disables msg boxes for automation on Windows +miscellaneous/messageboxw/test2,1 +# Automatable to detect gross errors; also manually inspect for proper behaviour +pal_specific/pal_get_stderr/test1,1 +pal_specific/pal_get_stdout/test1,1 +# The tests for the sleep api may fail depending upon what other +# processes are running and their relative priority. +threading/sleep/test1,1 +threading/sleepex/test1,1 + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/manual-unautomatable.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/manual-unautomatable.dat new file mode 100644 index 0000000..e60ab27 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/manual-unautomatable.dat @@ -0,0 +1,33 @@ +# 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. + +#This test is negative and will exit with exit(1). +#Therefore, the harness would record it as a failure +c_runtime/exit/test2,1 +# A successful DebugBreak test run dumps core or throws up an ASSERT +# dialog box (or...) and returns an exit code != 0 +debug_api/debugbreak/test1,1 +# debug_api/outputdebugstringa/test1 attempts to send "Foo!" to the debugger +# The PAL behaviour is implementation dependant and can include an interactive +# dialog +debug_api/outputdebugstringw/test1,1 +debug_api/outputdebugstringa/test1,1 +# These tests require user intervention and cannot be automated +pal_specific/pal_get_stdin/test1,1 +threading/setconsolectrlhandler/test1,1 +threading/setconsolectrlhandler/test4,1 +# These tests take several minutes to run and time out when run with the harness +file_io/gettempfilenamea/test2,1 +file_io/gettempfilenamew/test2,1 +# getstdhandle fails under Windows if the output is redirected so +# it must be run from the command line +file_io/getstdhandle/test1,1 +# This test runs calculations in a nested loop to occupy the processor. +# This causes the test harness to time out on some machines. +threading/threadpriority/test1,1 +# This test runs for 96 minutes and will time out with the harness. +threading/sleep/test2,1 +# This test runs forever by design. +threading/waitformultipleobjects/test2,1 + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/test1/CMakeLists.txt new file mode 100644 index 0000000..2ff735b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_cgroup_test1 + ${SOURCES} +) + +add_dependencies(paltest_cgroup_test1 coreclrpal) + +target_link_libraries(paltest_cgroup_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/test1/test.cpp new file mode 100644 index 0000000..44b970a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/test1/test.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: Test for CGroup +** +** +** Steps to run this test on ubuntu: +** 1. sudo apt-get install cgroup-bin +** 2. sudo vi /etc/default/grub +** Add cgroup_enable=memory swapaccount=1 to GRUB_CMDLINE_LINUX_DEFAULT +** 3. sudo update-grub +** 4. reboot +** 5. sudo cgcreate -g cpu,memory:/myGroup -a : -t : +** 6. echo 4M > /sys/fs/cgroup/memory/mygroup/memory.limit_in_bytes +** 7. echo 4M > /sys/fs/cgroup/memory/mygroup/memory.memsw.limit_in_bytes +** 8. cgexe -g memory:/mygroup --sticky +**=========================================================*/ + +#include + +int __cdecl main(int argc,char *argv[]) +{ + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + size_t mem_limit = PAL_GetRestrictedPhysicalMemoryLimit(); + + FILE* file = fopen("/sys/fs/cgroup/memory/mygroup/memory.limit_in_bytes", "r"); + if(file != NULL) + { + if(mem_limit != 4194304) + Fail("Memory limit obtained from PAL_GetRestrictedPhysicalMemory is not 4MB\n"); + fclose(file); + } + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/test1/testinfo.dat new file mode 100644 index 0000000..86da2d1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CGroup/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = Miscellaneous +Function = CGroup +Name = Positive Test for CGroup +TYPE = DEFAULT +EXE1 = test +Description += Test to see if Cgroup memory limit works properly diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CMakeLists.txt new file mode 100644 index 0000000..a0518e2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CMakeLists.txt @@ -0,0 +1,33 @@ +add_subdirectory(CGroup) +add_subdirectory(CloseHandle) +add_subdirectory(CreatePipe) +add_subdirectory(FlushInstructionCache) +add_subdirectory(FormatMessageW) +add_subdirectory(FreeEnvironmentStringsW) +add_subdirectory(GetCommandLineW) +add_subdirectory(GetEnvironmentStringsW) +add_subdirectory(GetEnvironmentVariableA) +add_subdirectory(GetEnvironmentVariableW) +add_subdirectory(GetLastError) +add_subdirectory(GetSystemInfo) +add_subdirectory(GlobalMemoryStatusEx) +add_subdirectory(GetTickCount) +add_subdirectory(InterlockedBit) +add_subdirectory(InterlockedCompareExchange) +add_subdirectory(InterlockedCompareExchange64) +add_subdirectory(InterlockedCompareExchangePointer) +add_subdirectory(InterlockedDecrement) +add_subdirectory(InterlockedDecrement64) +add_subdirectory(InterlockedExchange) +add_subdirectory(InterlockedExchange64) +add_subdirectory(InterLockedExchangeAdd) +add_subdirectory(InterlockedExchangePointer) +add_subdirectory(InterlockedIncrement) +add_subdirectory(InterlockedIncrement64) +add_subdirectory(queryperformancecounter) +add_subdirectory(queryperformancefrequency) +add_subdirectory(SetEnvironmentVariableA) +add_subdirectory(SetEnvironmentVariableW) +add_subdirectory(SetLastError) +add_subdirectory(_i64tow) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextA/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextA/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/CMakeLists.txt new file mode 100644 index 0000000..34fbb12 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_charnexta_test1 + ${SOURCES} +) + +add_dependencies(paltest_charnexta_test1 coreclrpal) + +target_link_libraries(paltest_charnexta_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/CMakeLists.txt new file mode 100644 index 0000000..1203e12 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_charnexta_test2 + ${SOURCES} +) + +add_dependencies(paltest_charnexta_test2 coreclrpal) + +target_link_libraries(paltest_charnexta_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextExA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextExA/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextExA/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/CMakeLists.txt new file mode 100644 index 0000000..886d89d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_charnextexa_test1 + ${SOURCES} +) + +add_dependencies(paltest_charnextexa_test1 coreclrpal) + +target_link_libraries(paltest_charnextexa_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/CMakeLists.txt new file mode 100644 index 0000000..15278ef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_charnextexa_test2 + ${SOURCES} +) + +add_dependencies(paltest_charnextexa_test2 coreclrpal) + +target_link_libraries(paltest_charnextexa_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/CMakeLists.txt new file mode 100644 index 0000000..0715ea0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_closehandle_test1 + ${SOURCES} +) + +add_dependencies(paltest_closehandle_test1 coreclrpal) + +target_link_libraries(paltest_closehandle_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.cpp new file mode 100644 index 0000000..443f89b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: Test for CloseHandle function +** +** +**=========================================================*/ + +/* Depends on: CreateFile and WriteFile */ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE FileHandle = NULL; + LPDWORD WriteBuffer; /* Used with WriteFile */ + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + WriteBuffer = (LPDWORD)malloc(sizeof(WORD)); + + if ( WriteBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for WriteBuffer pointer. " + "Can't properly exec test case without this.\n"); + } + + + /* Create a file, since this returns to us a HANDLE we can use */ + FileHandle = CreateFile("testfile", + GENERIC_READ | GENERIC_WRITE,0,NULL,CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + /* Should be able to close this handle */ + if(CloseHandle(FileHandle) == 0) + { + free(WriteBuffer); + Fail("ERROR: (Test 1) Attempted to close a HANDLE on a file, but the " + "return value was <=0, indicating failure.\n"); + } + + free(WriteBuffer); + + PAL_Terminate(); + return PASS; +} + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/testinfo.dat new file mode 100644 index 0000000..891e1df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = CloseHandle +Name = Positive Test for CloseHandle +TYPE = DEFAULT +EXE1 = test +Description += Open a file to get a handle, and then close the file using CloseHandle + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/CMakeLists.txt new file mode 100644 index 0000000..ae5b509 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_closehandle_test2 + ${SOURCES} +) + +add_dependencies(paltest_closehandle_test2 coreclrpal) + +target_link_libraries(paltest_closehandle_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/test.cpp new file mode 100644 index 0000000..c1eea44 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/test.cpp @@ -0,0 +1,46 @@ +// 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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: Test for CloseHandle function, try to close an unopened HANDLE +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE SomeHandle = NULL; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* If the handle is already closed and you can close it again, + * something is wrong. + */ + + if(CloseHandle(SomeHandle) != 0) + { + Fail("ERROR: Called CloseHandle on an already closed Handle " + "and it still returned as a success.\n"); + } + + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/testinfo.dat new file mode 100644 index 0000000..6917e85 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = CloseHandle +Name = Positive Test for CloseHandle +TYPE = DEFAULT +EXE1 = test +Description += Attempt to close an unintialized HANDLE, should be unable to do this. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/CMakeLists.txt new file mode 100644 index 0000000..8242bbd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_createpipe_test1 + ${SOURCES} +) + +add_dependencies(paltest_createpipe_test1 coreclrpal) + +target_link_libraries(paltest_createpipe_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/test1.cpp new file mode 100644 index 0000000..3930183 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/test1.cpp @@ -0,0 +1,113 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c (CreatePipe) +** +** Purpose: Tests the PAL implementation of the CreatePipe function. +** This test will create two pipes, a read and a write. Once +** the pipes have been created, they will be tested by writing +** and then reading, then comparing the results. +** +** Depends: WriteFile +** ReadFile +** memcmp +** CloseHandle +** +** +**===================================================================*/ + +#include + +const char* cTestString = "one fish, two fish, red fish, blue fish."; + +int __cdecl main(int argc, char **argv) +{ + HANDLE hReadPipe = NULL; + HANDLE hWritePipe = NULL; + BOOL bRetVal = FALSE; + DWORD dwBytesWritten; + DWORD dwBytesRead; + char buffer[256]; + + SECURITY_ATTRIBUTES lpPipeAttributes; + + /*Initialize the PAL*/ + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/ + lpPipeAttributes.nLength = sizeof(lpPipeAttributes); + lpPipeAttributes.lpSecurityDescriptor = NULL; + lpPipeAttributes.bInheritHandle = TRUE; + + /*Create a Pipe*/ + bRetVal = CreatePipe(&hReadPipe, /* read handle*/ + &hWritePipe, /* write handle */ + &lpPipeAttributes, /* security attributes*/ + 0); /* pipe size*/ + if (bRetVal == FALSE) + { + Fail("ERROR: %ld :Unable to create pipe\n", GetLastError()); + } + + /*Write to the write pipe handle*/ + bRetVal = WriteFile(hWritePipe, /* handle to write pipe*/ + cTestString, /* buffer to write*/ + strlen(cTestString),/* number of bytes to write*/ + &dwBytesWritten, /* number of bytes written*/ + NULL); /* overlapped buffer*/ + if (bRetVal == FALSE) + { + Fail("ERROR: %ld :unable to write to write pipe handle " + "hWritePipe=0x%lx\n", GetLastError(), hWritePipe); + } + + /*Read, 256 bytes, more bytes then actually written. + This will give allow us to use the value that ReadFile + returns for comparision.*/ + bRetVal = ReadFile(hReadPipe, /* handle to read pipe*/ + buffer, /* buffer to write to*/ + 256, /* number of bytes to read*/ + &dwBytesRead, /* number of bytes read*/ + NULL); /* overlapped buffer*/ + if (bRetVal == FALSE) + { + Fail("ERROR: %ld : unable read hWritePipe=0x%lx\n", + GetLastError(), hWritePipe); + } + + /*Compare what was read with what was written.*/ + if ((memcmp(cTestString, buffer, dwBytesRead)) != 0) + { + Fail("ERROR: read \"%s\" expected \"%s\" \n", buffer, cTestString); + } + + /*Compare values returned from WriteFile and ReadFile.*/ + if (dwBytesWritten != dwBytesRead) + { + Fail("ERROR: WriteFile wrote \"%d\", but ReadFile read \"%d\"," + " these should be the same\n", buffer, cTestString); + } + + /*Close write pipe handle*/ + if (CloseHandle(hWritePipe) == 0) + { + Fail("ERROR: %ld : Unable to close write pipe handle " + "hWritePipe=0x%lx\n",GetLastError(), hWritePipe); + } + + /*Close Read pipe handle*/ + if (CloseHandle(hReadPipe) == 0) + { + Fail("ERROR: %ld : Unable to close read pipe handle " + "hReadPipe=0x%lx\n", GetLastError(), hReadPipe); + } + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/testinfo.dat new file mode 100644 index 0000000..b9422b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = CreatePipe +Name = Test for CreatePipe +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the CreatePipe function. += This test will create two pipes, a read and a write. Once += the pipes have been created, they will be tested by writing += and then reading, then comparing the results. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/CMakeLists.txt new file mode 100644 index 0000000..c3e8011 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_flushinstructioncache_test1 + ${SOURCES} +) + +add_dependencies(paltest_flushinstructioncache_test1 coreclrpal) + +target_link_libraries(paltest_flushinstructioncache_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/test1.cpp new file mode 100644 index 0000000..cdbefd0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/test1.cpp @@ -0,0 +1,66 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Tests that FlushInstructionCache returns the correct value for a +** number of different inputs. +** +** +** Note : +** For this function, what constitutes "invalid parameters" will depend entirely +** on the platform; because of this we can't simply test values on Windows and +** then ask for the same results everywhere. Because of this, this test can +** ensure that the function succeeds for some "obviously" valid values, but +** can't make sure that it fails for invalid values. +** +**=========================================================*/ + +#include + +void DoTest(void *Buffer, int Size, int Expected) +{ + int ret; + + SetLastError(0); + ret = FlushInstructionCache(GetCurrentProcess(), Buffer, Size); + if (!ret && Expected) + { + Fail("Expected FlushInstructionCache to return non-zero, got zero!\n" + "region: %p, size: %d, GetLastError: %d\n", Buffer, Size, + GetLastError()); + } + else if (ret && !Expected) + { + Fail("Expected FlushInstructionCache to return zero, got non-zero!\n" + "region: %p, size: %d, GetLastError: %d\n", Buffer, Size, + GetLastError()); + } + + if (!Expected && ERROR_NOACCESS != GetLastError()) + { + Fail("FlushInstructionCache failed to set the last error to " + "ERROR_NOACCESS!\n"); + } + +} + +int __cdecl main(int argc,char *argv[]) +{ + char ValidPtr[256]; + + if(PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* with valid pointer, zero-size and valid size must succeed */ + DoTest(ValidPtr, 0, 1); + DoTest(ValidPtr, 42, 1); + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/testinfo.dat new file mode 100644 index 0000000..78ab5f7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = FlushInstructionCache +Name = Positive Test #1 for FlushInstructionCache +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests that FlushInstructionCache returns the correct value for a +=number of different inputs. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/CMakeLists.txt new file mode 100644 index 0000000..828a287 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/CMakeLists.txt @@ -0,0 +1,7 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/CMakeLists.txt new file mode 100644 index 0000000..191da48 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_formatmessagew_test1 + ${SOURCES} +) + +add_dependencies(paltest_formatmessagew_test1 coreclrpal) + +target_link_libraries(paltest_formatmessagew_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.cpp new file mode 100644 index 0000000..0cc4c43 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.cpp @@ -0,0 +1,63 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for FormatMessageW() function +** +** +**=========================================================*/ + +#define UNICODE +#include + + +int __cdecl main(int argc, char *argv[]) { + + WCHAR TheString[] = {'P','a','l',' ','T','e','s','t','\0'}; + WCHAR OutBuffer[128]; + int ReturnResult; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + NULL /* array of message inserts */ + ); + + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string" + ", with no formatters in it."); + } + + if(memcmp(OutBuffer,TheString,wcslen(OutBuffer)*2+2) != 0) + { + Fail("ERROR: The formatted string should be %s but is really %s.", + convertC(TheString), + convertC(OutBuffer)); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/testinfo.dat new file mode 100644 index 0000000..5bd46bf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = FormatMessageW +Name = Positive test of FormatMessageW +TYPE = DEFAULT +EXE1 = test +Description += Test a very simple case -- basically just copy a string into a buffer, += no formatting. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/CMakeLists.txt new file mode 100644 index 0000000..5f0f6ce --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_formatmessagew_test2 + ${SOURCES} +) + +add_dependencies(paltest_formatmessagew_test2 coreclrpal) + +target_link_libraries(paltest_formatmessagew_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.cpp new file mode 100644 index 0000000..eba38d4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.cpp @@ -0,0 +1,581 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for FormatMessageW() function +** +** +**=========================================================*/ + +#define UNICODE +#include + +WCHAR OutBuffer[1024]; + +/* Pass this test the string "INSERT" and it will succeed */ + +int test1(int num, ...) +{ + + WCHAR * TheString = convert("Pal %1!s! Testing"); + int ReturnResult; + va_list TheList; + va_start(TheList,num); + memset( OutBuffer, 0, 1024 * sizeof(OutBuffer[0]) ); + + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + &TheList /* array of message inserts */ + ); + + va_end(TheList); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string," + " with the 's' formatter."); + + } + + if(memcmp(OutBuffer, convert("Pal INSERT Testing"), + wcslen(OutBuffer)*2+2) != 0) + { + Fail("ERROR: The formated string should have been 'Pal INSERT " + "Testing' but '%s' was returned.", + convertC(OutBuffer)); + } + + + return PASS; +} + +/* Pass this test the int 40 and it will succeed */ + +int test2(int num, ...) +{ + + WCHAR * TheString = convert("Pal %1!i! Testing"); + int ReturnResult; + va_list TheList; + va_start(TheList,num); + + memset( OutBuffer, 0, 1024 * sizeof(OutBuffer[0]) ); + + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + &TheList /* array of message inserts */ + ); + + va_end(TheList); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string," + " with the 'i' formatter."); + } + + if(memcmp(OutBuffer, convert("Pal 40 Testing"),wcslen(OutBuffer)*2+2) != 0) + { + Fail("ERROR: The formated string should have been 'Pal 40 Testing' " + "but '%s' was returned.", convertC(OutBuffer)); + } + return PASS; +} + +/* Pass this test the character 'a' and it will succeed */ + +int test3(int num, ...) { + + WCHAR * TheString = convert("Pal %1!c! Testing"); + int ReturnResult; + va_list TheList; + va_start(TheList,num); + memset( OutBuffer, 0, 1024 * sizeof(OutBuffer[0]) ); + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + &TheList /* array of message inserts */ + ); + + va_end(TheList); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string," + " with the 'c' formatter."); + } + + if(memcmp(OutBuffer, convert("Pal a Testing"),wcslen(OutBuffer)*2+2) != 0) + { + Fail("ERROR: The formated string should have been 'Pal a Testing' " + "but '%s' was returned.", convertC(OutBuffer)); + + } + + return PASS; +} + +/* Pass this test the character 'a' and it will succeed */ + +int test4(int num, ...) { + + WCHAR * TheString = convert("Pal %1!C! Testing"); + int ReturnResult; + va_list TheList; + va_start(TheList,num); + memset( OutBuffer, 0, 1024 * sizeof(OutBuffer[0]) ); + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + &TheList /* array of message inserts */ + ); + + va_end(TheList); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string," + " with the 'C' formatter."); + } + + if(memcmp(OutBuffer, convert("Pal a Testing"),wcslen(OutBuffer)*2+2) != 0) + { + Fail("ERROR: The formated string should have been 'Pal a Testing' " + "but '%s' was returned.",convertC(OutBuffer)); + } + + return PASS; +} + +/* Pass this test the number 57 and it will succeed */ + +int test5(int num, ...) +{ + + WCHAR * TheString = convert("Pal %1!d! Testing"); + int ReturnResult; + va_list TheList; + va_start(TheList,num); + memset( OutBuffer, 0, 1024 * sizeof(OutBuffer[0]) ); + + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + &TheList /* array of message inserts */ + ); + + va_end(TheList); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string, " + "with the 'd' formatter."); + + } + + if(memcmp(OutBuffer, convert("Pal 57 Testing"),wcslen(OutBuffer)*2+2) != 0) + { + Fail("ERROR: The formated string should have been 'Pal 57 Testing' " + "but '%s' was returned.",convertC(OutBuffer)); + + } + + return PASS; +} + +/* Pass this test the characters 'a' and 'b' and it will succeed. */ + +int test6(int num, ...) { + + WCHAR * TheString = convert("Pal %1!hc! and %2!hC! Testing"); + int ReturnResult; + va_list TheList; + va_start(TheList,num); + memset( OutBuffer, 0, 1024 * sizeof(OutBuffer[0]) ); + + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + &TheList /* array of message inserts */ + ); + + va_end(TheList); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string, " + "with the 'hc' and 'hC' formatters."); + + } + + if(memcmp(OutBuffer, convert("Pal a and b Testing"), + wcslen(OutBuffer)*2+2) != 0) + { + Fail("ERROR: The formated string should have been 'Pal a and b " + "Testing' but '%s' was returned.", convertC(OutBuffer)); + + } + + return PASS; +} + +/* Pass this test 90, the string 'foo' and the string 'bar' to succeed */ + +int test7(int num, ...) +{ + + WCHAR * TheString = convert("Pal %1!hd! and %2!hs! and %3!hS! Testing"); + int ReturnResult; + va_list TheList; + va_start(TheList,num); + memset( OutBuffer, 0, 1024 * sizeof(OutBuffer[0]) ); + + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + &TheList /* array of message inserts */ + ); + + va_end(TheList); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string, " + "with the 'hd', 'hs' and 'hS' formatters."); + + } + + if(memcmp(OutBuffer, + convert("Pal 90 and foo and bar Testing"), + wcslen(OutBuffer)*2+2) != 0) + { + Fail("ERROR: The formated string should have been 'Pal 90 and foo " + "and bar Testing' but '%s' was returned.",convertC(OutBuffer)); + } + + return PASS; +} + +/* Pass this test the characters 'a', 'b' and the numbers 50 and 100 */ + +int test8(int num, ...) +{ + + WCHAR * TheString = + convert("Pal %1!lc! and %2!lC! and %3!ld! and %4!li! Testing"); + int ReturnResult; + va_list TheList; + va_start(TheList,num); + memset( OutBuffer, 0, 1024 * sizeof(OutBuffer[0]) ); + + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + &TheList /* array of message inserts */ + ); + + va_end(TheList); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string, " + "with the 'lc', 'lC', 'ld' and 'li' formatters."); + + } + + if(memcmp(OutBuffer, + convert("Pal a and b and 50 and 100 Testing"), + wcslen(OutBuffer)*2+2) != 0) + { + Fail("ERROR: The formated string should have been 'Pal a and b and 50" + " and 100 Testing' but '%s' was returned.",convertC(OutBuffer)); + + } + + return PASS; +} + +/* Pass this test the wide string 'foo' and 'bar' and the unsigned + int 56 to pass +*/ + +int test9(int num, ...) { + + WCHAR * TheString = convert("Pal %1!ls! and %2!ls! and %3!lu! Testing"); + int ReturnResult; + va_list TheList; + va_start(TheList,num); + memset( OutBuffer, 0, 1024 * sizeof(OutBuffer[0]) ); + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + &TheList /* array of message inserts */ + ); + + va_end(TheList); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string," + " with the 'ls', 'lS' and 'lu' formatters."); + + } + + if(memcmp(OutBuffer, + convert("Pal foo and bar and 56 Testing"), + wcslen(OutBuffer)*2+2) != 0) + { + Fail("ERROR: The formated string should have been 'Pal foo and bar " + "and 56 Testing' but '%s' was returned.",convertC(OutBuffer)); + + } + + return PASS; +} + +/* Pass this test the hex values 0x123ab and 0x123cd */ + +int test10(int num, ...) +{ + + WCHAR * TheString = convert("Pal %1!lx! and %2!lX! Testing"); + int ReturnResult; + va_list TheList; + va_start(TheList,num); + memset( OutBuffer, 0, 1024 * sizeof(OutBuffer[0]) ); + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + &TheList /* array of message inserts */ + ); + + va_end(TheList); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string, " + "with the 'lx' and 'lX' formatters."); + + } + + if(memcmp(OutBuffer, + convert("Pal 123ab and 123CD Testing"), + wcslen(OutBuffer)*2+2) != 0) + { + Fail("ERROR: The formated string should have been 'Pal 123ab and " + "123CD Testing' but '%s' was returned.", convertC(OutBuffer)); + + } + + return PASS; +} + +/* Pass this test a pointer to 0x123ab and the string 'foo' to pass */ + +int test11(int num, ...) +{ + + WCHAR * TheString = convert("Pal %1!p! and %2!S! Testing"); + int ReturnResult; + va_list TheList; + va_start(TheList,num); + memset( OutBuffer, 0, 1024 * sizeof(OutBuffer[0]) ); + + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + &TheList /* array of message inserts */ + ); + + va_end(TheList); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string, " + "with the 'p' and 'S' formatters."); + + } + +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + Trace("Testing for 64 Bit Platforms \n"); + if(memcmp(OutBuffer, + convert("Pal 00000000000123AB and foo Testing"), + wcslen(OutBuffer)*2+2) != 0 && + /* BSD style */ + memcmp( OutBuffer, + convert( "Pal 0x123ab and foo Testing" ), + wcslen(OutBuffer)*2+2 ) != 0 ) + { + Fail("ERROR: The formated string should have been 'Pal 000123AB and " + "foo Testing' but '%s' was returned.",convertC(OutBuffer)); + + } + +#else + Trace("Testing for Non 64 Bit Platforms \n"); + if(memcmp(OutBuffer, + convert("Pal 000123AB and foo Testing"), + wcslen(OutBuffer)*2+2) != 0 && + /* BSD style */ + memcmp( OutBuffer, + convert( "Pal 0x123ab and foo Testing" ), + wcslen(OutBuffer)*2+2 ) != 0 ) + { + Fail("ERROR: The formated string should have been 'Pal 000123AB and " + "foo Testing' but '%s' was returned.",convertC(OutBuffer)); + + } + +#endif + + return PASS; +} + +/* Pass this test the unsigned int 100 and the hex values 0x123ab and 0x123cd +to succeed */ + +int test12(int num, ...) +{ + + WCHAR * TheString = convert("Pal %1!u! and %2!x! and %3!X! Testing"); + int ReturnResult; + va_list TheList; + va_start(TheList,num); + memset( OutBuffer, 0, 1024 * sizeof(OutBuffer[0]) ); + + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + &TheList /* array of message inserts */ + ); + + va_end(TheList); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string, " + "with the 'u', 'x' and 'X' formatters."); + + } + + if(memcmp(OutBuffer, + convert("Pal 100 and 123ab and 123CD Testing"), + wcslen(OutBuffer)*2+2) != 0) + { + Fail("ERROR: The formated string should have been 'Pal 100 and " + "123ab and 123CD Testing' but '%s' was returned.", + convertC(OutBuffer)); + + } + + return PASS; +} + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR szwInsert[] = {'I','N','S','E','R','T','\0'}; + WCHAR szwFoo[] = {'f','o','o','\0'}; + WCHAR szwBar[] = {'b','a','r','\0'}; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + if(test1(0,szwInsert) || /* Test %s */ + test2(0,40) || /* Test %i */ + test3(0,'a') || /* Test %c */ + test4(0,'a') || /* Test %C */ + test5(0,57) || /* Test %d */ + test6(0,'a','b') || /* Test %hc, %hC */ + test7(0,90,"foo","bar") || /* Test %hd,hs,hS */ + test8(0,'a','b',50,100) || /* Test %lc, lC, ld, li */ + test9(0,szwFoo,szwBar,56) || /* Test %ls,lS,lu */ + test10(0,0x123ab,0x123cd) || /* Test %lx, %lX */ + test11(0,(void *)0x123ab,"foo") || /* Test %p, %S */ + test12(0,100,0x123ab,0x123cd)) /* Test %u,x,X */ + { + + + } + + PAL_Terminate(); + return PASS; + +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/testinfo.dat new file mode 100644 index 0000000..5e4a354 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = FormatMessageW +Name = Positive test of FormatMessageW +TYPE = DEFAULT +EXE1 = test +Description += A collection of tests to check and make sure all the standard formatters work. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/CMakeLists.txt new file mode 100644 index 0000000..98532f3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_formatmessagew_test3 + ${SOURCES} +) + +add_dependencies(paltest_formatmessagew_test3 coreclrpal) + +target_link_libraries(paltest_formatmessagew_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.cpp new file mode 100644 index 0000000..a390c00 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.cpp @@ -0,0 +1,85 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for FormatMessageW() function +** +** +**=========================================================*/ + +#define UNICODE +#include + +WCHAR OutBuffer[1024]; + +int __cdecl main(int argc, char *argv[]) +{ + + WCHAR * TheString; + WCHAR * CorrectString; + int ReturnResult; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + TheString = convert("Pal %1!u! %2!i! %3!s! Testing"); + + /* The resulting value in the buffer shouldn't be formatted at all, + because the inserts are being ignored. + */ + + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING | + FORMAT_MESSAGE_IGNORE_INSERTS, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + NULL /* array of message inserts */ + ); + + + + if(ReturnResult == 0) + { + free(TheString); + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string, " + "using the IGNORE_INSERTS flag.\n"); + } + + + /* Note: Since 's' is the default insert, when this function is called + with ignore inserts, it strips %3!s! down to just %3 -- as they're + equal. + */ + if(memcmp(OutBuffer, + (CorrectString = convert("Pal %1!u! %2!i! %3 Testing")), + wcslen(OutBuffer)*2+2) != 0) + { + free(TheString); + free(CorrectString); + Fail("ERROR: Since the IGNORE_INSERTS flag was set, the result " + "should have been 'Pal %%1!u! %%2!i! %%3 Testing' but was " + "really '%S'.\n",OutBuffer); + } + + free(TheString); + free(CorrectString); + PAL_Terminate(); + return PASS; + +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/testinfo.dat new file mode 100644 index 0000000..cad1f63 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = FormatMessageW +Name = Positive test of FormatMessageW +TYPE = DEFAULT +EXE1 = test +Description += Test to ensure the IGNORE_INSERTS flag works properly. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/CMakeLists.txt new file mode 100644 index 0000000..1a0dcad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_formatmessagew_test4 + ${SOURCES} +) + +add_dependencies(paltest_formatmessagew_test4 coreclrpal) + +target_link_libraries(paltest_formatmessagew_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.cpp new file mode 100644 index 0000000..4f865ef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.cpp @@ -0,0 +1,77 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for FormatMessageW() function +** +** +**=========================================================*/ + +#define UNICODE +#include + +WCHAR OutBuffer[1024]; + +int __cdecl main(int argc, char *argv[]) +{ + + WCHAR * TheString; + WCHAR* TheArray[3]; + int ReturnResult; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + TheString = convert("Pal %1 %2 %3 Testing"); + TheArray[0] = convert("Foo"); + TheArray[1] = convert("Bar"); + TheArray[2] = convert("FooBar"); + + /* This should just use the 3 strings in the array to replace + inserts in the given string. + */ + + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING | + FORMAT_MESSAGE_ARGUMENT_ARRAY, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + OutBuffer, /* message buffer */ + 1024, /* maximum size of message buffer */ + (va_list *) TheArray /* array of message inserts */ + ); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string, " + "usin gthe ARGUMENT_ARRAY flag."); + } + + if(memcmp(OutBuffer, + convert("Pal Foo Bar FooBar Testing"), + wcslen(OutBuffer)*2+2) != 0) + { + Fail("ERROR: Since the FORMAT_MESSAGE_ARGUMENT_ARRAY flag was set, " + "the result should have been 'Pal Foo Bar FooBar Testing' but was" + " really '%s'.",convertC(OutBuffer)); + } + + + PAL_Terminate(); + return PASS; + +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/testinfo.dat new file mode 100644 index 0000000..33e0cfa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = FormatMessageW +Name = Positive test of FormatMessageW +TYPE = DEFAULT +EXE1 = test +Description += Test to ensure the FORMAT_MESSAGE_ARGUMENT_ARRAY flag works properly. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/CMakeLists.txt new file mode 100644 index 0000000..c0c69e8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_formatmessagew_test5 + ${SOURCES} +) + +add_dependencies(paltest_formatmessagew_test5 coreclrpal) + +target_link_libraries(paltest_formatmessagew_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.cpp new file mode 100644 index 0000000..148c2ff --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.cpp @@ -0,0 +1,76 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for FormatMessageW() function +** +** +**=========================================================*/ + + +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) { + + WCHAR * TheString; + LPWSTR OutBuffer; + WCHAR* TheArray[3]; + int ReturnResult; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + TheString = convert("Pal %1 %2 %3 Testing"); + TheArray[0] = convert("Foo"); + TheArray[1] = convert("Bar"); + TheArray[2] = convert("FooBar"); + + /* OutBuffer will be allocated in the function, if the flag + is working properly. + */ + + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_STRING | + FORMAT_MESSAGE_ARGUMENT_ARRAY | + FORMAT_MESSAGE_ALLOCATE_BUFFER, /* source and processing options */ + TheString, /* message source */ + 0, /* message identifier */ + 0, /* language identifier */ + (LPWSTR)&OutBuffer, /* message buffer */ + 0, /* maximum size of message buffer */ + (va_list *) TheArray /* array of message inserts */ + ); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. " + "The function failed when trying to Format a simple string, " + "using the ALLOCATE_BUFFER flag."); + } + + if(memcmp(OutBuffer, + convert("Pal Foo Bar FooBar Testing"), + wcslen(OutBuffer)*2+2) != 0) + { + Fail("ERROR: Since the FORMAT_MESSAGE_ALLOCATE_BUFFER flag was set, " + "the result should have been 'Pal Foo Bar FooBar Testing' but " + "was really '%s'.",convertC(OutBuffer)); + } + + PAL_Terminate(); + return PASS; + +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/testinfo.dat new file mode 100644 index 0000000..6f497c2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/testinfo.dat @@ -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. + +Version = 1.0 +Section = Miscellaneous +Function = FormatMessageW +Name = Positive test of FormatMessageW +TYPE = DEFAULT +EXE1 = test +Description += Test to ensure the FORMAT_MESSAGE_ALLOCATE_BUFFER flag works properly. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/CMakeLists.txt new file mode 100644 index 0000000..cdbd9be --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_formatmessagew_test6 + ${SOURCES} +) + +add_dependencies(paltest_formatmessagew_test6 coreclrpal) + +target_link_libraries(paltest_formatmessagew_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp new file mode 100644 index 0000000..48f5e3e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp @@ -0,0 +1,78 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for FormatMessageW() function +** +** +**=========================================================*/ + + +#define UNICODE +#include + + +int __cdecl main(int argc, char *argv[]) { + + + LPWSTR OutBuffer; + int ReturnResult; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + + /* This is testing the use of FROM_SYSTEM. We can't check to ensure + the error message it extracts is correct, only that it does place some + information into the buffer when it is called. + */ + + /* + + ERROR_SUCCESS (0L) is normally returned by GetLastError, + But, the ERROR_SUCCESS is removed from messages for Unix based Systems + To ensure that we have some information into the buffer we are using the message + identifier value 2L (ERROR_FILE_NOT_FOUND) + */ + ReturnResult = FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_ALLOCATE_BUFFER, /* source and processing options */ + NULL, /* message source */ + 2L, /* message identifier */ + 0, /* language identifier */ + (LPWSTR)&OutBuffer, /* message buffer */ + 0, /* maximum size of message buffer */ + NULL /* array of message inserts */ + ); + + if(ReturnResult == 0) + { + Fail("ERROR: The return value was 0, which indicates failure. The " + "function failed when trying to Format a FROM_SYSTEM message."); + } + + if(wcslen(OutBuffer) <= 0) + { + Fail("ERROR: There are no characters in the buffer, and when the " + "FORMAT_MESSAGE_FROM_SYSTEM flag is used with ERROR_FILE_NOT_FOUND error, " + "something should be put into the buffer."); + } + + LocalFree(OutBuffer); + + PAL_Terminate(); + return PASS; + +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/testinfo.dat new file mode 100644 index 0000000..7eda505 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = FormatMessageW +Name = Positive test of FormatMessageW +TYPE = DEFAULT +EXE1 = test +Description += Test to ensure the FORMAT_SYSTEM_MESSAGE flag works properly. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/CMakeLists.txt new file mode 100644 index 0000000..059e1bf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_freeenvironmentstringsw_test1 + ${SOURCES} +) + +add_dependencies(paltest_freeenvironmentstringsw_test1 coreclrpal) + +target_link_libraries(paltest_freeenvironmentstringsw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/test.cpp new file mode 100644 index 0000000..5601003 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/test.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: Test for FreeEnvironmentStringsW() function +** +** +**=========================================================*/ + +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + + LPWSTR CapturedEnvironment = NULL; + BOOL TheResult = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + CapturedEnvironment = GetEnvironmentStrings(); + + /* If it's pointing to NULL, it failed. This checks the dependency */ + if(CapturedEnvironment == NULL) { + Fail("The function GetEnvironmentStrings() failed, and the " + "FreeEnvironmentStrings() tests is dependant on it.\n"); + } + + /* This should return 1, if it succeeds, otherwise, test fails */ + TheResult = FreeEnvironmentStrings(CapturedEnvironment); + if(TheResult != 1) { + Fail("The function returned %d which indicates failure to Free the " + "Environment Strings.\n",TheResult); + } + + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/testinfo.dat new file mode 100644 index 0000000..f653bf5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = FreeEnvironmentStringsW +Name = Return value test for FreeEnvironmentStringsW +TYPE = DEFAULT +EXE1 = test +Description += Get a set of strings and then free it to see if function returns success + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/CMakeLists.txt new file mode 100644 index 0000000..b47c4f0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_freeenvironmentstringsw_test2 + ${SOURCES} +) + +add_dependencies(paltest_freeenvironmentstringsw_test2 coreclrpal) + +target_link_libraries(paltest_freeenvironmentstringsw_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/test.cpp new file mode 100644 index 0000000..e59ad84 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/test.cpp @@ -0,0 +1,71 @@ +// 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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: Test for FreeEnvironmentStringsW() function +** +** +**=========================================================*/ + +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + + WCHAR CapturedEnvironment[] = {'T','E','S','T','\0'}; + BOOL TheResult = 0; + LPWSTR lpCapturedEnvironment = NULL; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + lpCapturedEnvironment = (LPWSTR)malloc( sizeof(CapturedEnvironment) / + sizeof(CapturedEnvironment[0]) ); + + if ( lpCapturedEnvironment ) + { + memcpy( lpCapturedEnvironment, CapturedEnvironment, + sizeof(CapturedEnvironment) / sizeof(CapturedEnvironment[0]) ); + } + else + { + Fail( "malloc() failed to allocate memory.\n" ); + } + /* Even if this is not a valid Environment block, the function will + still return success + */ + + TheResult = FreeEnvironmentStrings( lpCapturedEnvironment ); + if(TheResult == 0) + { + Fail("The function should still return a success value even if it is " + "passed a LPWSTR which is not an environment block properly " + "acquired from GetEnvironmentStrings\n"); + } + + /* Even passing this function NULL, should still return a success value */ + TheResult = FreeEnvironmentStrings(NULL); + if(TheResult == 0) + { + Fail("The function should still return a success value even if pass " + "NULL.\n"); + } + + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/testinfo.dat new file mode 100644 index 0000000..c426a7c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = FreeEnvironmentStringsW +Name = Positive Return value test for FreeEnvironmentStringsW +TYPE = DEFAULT +EXE1 = test +Description += Ensure that FreeEnvironmentStringsW returns success when passed pointers += that don't point to an environment block. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/CMakeLists.txt new file mode 100644 index 0000000..c60f710 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_getcommandlinew_test1 + ${SOURCES} +) + +add_dependencies(paltest_getcommandlinew_test1 coreclrpal) + +target_link_libraries(paltest_getcommandlinew_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/test.cpp new file mode 100644 index 0000000..3417c14 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/test.cpp @@ -0,0 +1,71 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetCommandLineW() function +** +** +**=========================================================*/ + +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + + LPWSTR TheResult = NULL; + WCHAR *CommandLine; + int i; + WCHAR * p; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + CommandLine = (WCHAR*)malloc(1024); + wcscpy(CommandLine,convert(argv[0])); + + for(i=1;i + +int __cdecl main(int argc, char *argv[]) { + + LPWSTR CapturedEnvironmentStrings = NULL; + LPWSTR EnviroStringReturned = NULL; + WCHAR EnvironmentVariableBuffer[] = + {'P','A','L','T','E','S','T','I','N','G','\0'}; + WCHAR EnvironmentValueBuffer[] = {'T','e','s','t','i','n','g','\0'}; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* This test depends on SetEnvironmentVariableW working. + We need to set a variable so we can test and ensure it's there + when we get them back + */ + + SetEnvironmentVariable(EnvironmentVariableBuffer,EnvironmentValueBuffer); + + CapturedEnvironmentStrings = GetEnvironmentStrings(); + + /* If it's pointing to NULL, it failed. */ + if(CapturedEnvironmentStrings == NULL) { + Fail("The function returned a pointer to NULL, which it shouldn't do. " + "It should point to a block of Environment Strings.\n"); + } + + /* Now that we've grabbed the list of envrionment strings, go through + each one, and check for a match to 'PALTESTING'. If this is missing + it's not pointing at the environment block. + */ + + while(*CapturedEnvironmentStrings != 0) + { + EnviroStringReturned = wcsstr(CapturedEnvironmentStrings, + EnvironmentVariableBuffer); + CapturedEnvironmentStrings += wcslen(CapturedEnvironmentStrings)+1; + if(EnviroStringReturned != NULL) + { + break; + } + } + + if(EnviroStringReturned == NULL) + { + Fail("The memory block returned was searched, but nothing was found to " + "prove this was really the environment block. Either this " + "function, SetEnvironmentVariable or wcsstr() is broken.\n"); + } + + + PAL_Terminate(); + return PASS; +} + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/testinfo.dat new file mode 100644 index 0000000..fa712ab --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetEnvironmentStringsW +Name = Test for correct return of GetEnvironmentStringsW +TYPE = DEFAULT +EXE1 = test +Description += Get a set of strings, and check to make sure it contains a predetermined += string that was placed there. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/CMakeLists.txt new file mode 100644 index 0000000..828a287 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/CMakeLists.txt @@ -0,0 +1,7 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/CMakeLists.txt new file mode 100644 index 0000000..e434fd1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_getenvironmentvariablea_test1 + ${SOURCES} +) + +add_dependencies(paltest_getenvironmentvariablea_test1 coreclrpal) + +target_link_libraries(paltest_getenvironmentvariablea_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.cpp new file mode 100644 index 0000000..23e9974 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.cpp @@ -0,0 +1,84 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetEnvironmentVariable() function +** Assign a properly sized buffer and get an environment +** variable, check to ensure it returns the correct values. +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) { + + /* Define some buffers needed for the function */ + char * pResultBuffer = NULL; + int size = 0; + + /* A place to stash the returned values */ + int ReturnValueForLargeBuffer = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Recieve and allocate the correct amount of memory for the buffer */ + size = ReturnValueForLargeBuffer = GetEnvironmentVariable("PATH", + pResultBuffer, + 0); + pResultBuffer = (char*)malloc(size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer. " + "Can't properly exec test case without this.\n"); + } + + + /* Normal case, PATH should fit into this buffer */ + ReturnValueForLargeBuffer = GetEnvironmentVariable("PATH", + pResultBuffer, + size); + + /* Ensure that it returned a positive value */ + if(ReturnValueForLargeBuffer <= 0) + { + free(pResultBuffer); + + Fail("The return was %d, which indicates that the function failed.\n", + ReturnValueForLargeBuffer); + } + + /* Ensure that it succeeded and copied the correct number of characters. + If this is true, then the return value should be one less of the size of + the buffer. (Doesn't include that NULL byte) + */ + + if(ReturnValueForLargeBuffer != size-1) + { + free(pResultBuffer); + + Fail("The value returned was %d when it should have been %d. " + "This should be the number of characters copied, minus the " + "NULL byte.\n",ReturnValueForLargeBuffer, size-1); + } + + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/testinfo.dat new file mode 100644 index 0000000..ee81e2e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetEnvironmentVariableA +Name = Return value test for GetEnvironmentVariableA +TYPE = DEFAULT +EXE1 = test +Description += Assign a properly sized buffer and get an environment variable, check to += ensure it returns the correct values. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/CMakeLists.txt new file mode 100644 index 0000000..cdfa4c9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_getenvironmentvariablea_test2 + ${SOURCES} +) + +add_dependencies(paltest_getenvironmentvariablea_test2 coreclrpal) + +target_link_libraries(paltest_getenvironmentvariablea_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/test.cpp new file mode 100644 index 0000000..d26588e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/test.cpp @@ -0,0 +1,56 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetEnvironmentVariable() function +** Pass a small buffer to GetEnvironmentVariableA to ensure +** it returns the size it requires. +** +** +**=========================================================*/ + +#include + +#define SMALL_BUFFER_SIZE 1 + +int __cdecl main(int argc, char *argv[]) { + + /* A place to stash the returned values */ + int ReturnValueForSmallBuffer = 0; + + char pSmallBuffer[SMALL_BUFFER_SIZE]; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* PATH won't fit in this buffer, it should return how many + characters it needs + */ + + ReturnValueForSmallBuffer = GetEnvironmentVariable("PATH", + pSmallBuffer, + SMALL_BUFFER_SIZE); + if(ReturnValueForSmallBuffer <= 0) + { + Fail("The return value was %d when it should have been greater " + "than 0. " + "This should return the number of characters needed to contained " + "the contents of PATH in a buffer.\n",ReturnValueForSmallBuffer); + } + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/testinfo.dat new file mode 100644 index 0000000..990649f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetEnvironmentVariableA +Name = Return value test on GetEnvironmentVariableA +TYPE = DEFAULT +EXE1 = test +Description += Pass a small buffer to GetEnvironmentVariableA += to ensure it returns the size it requires. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/CMakeLists.txt new file mode 100644 index 0000000..20dd149 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_getenvironmentvariablea_test3 + ${SOURCES} +) + +add_dependencies(paltest_getenvironmentvariablea_test3 coreclrpal) + +target_link_libraries(paltest_getenvironmentvariablea_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/test.cpp new file mode 100644 index 0000000..b51e139 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/test.cpp @@ -0,0 +1,67 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetEnvironmentVariable() function +** Pass a nonexisting environment variable and a null to +** the function to check return values. +** +** +**=========================================================*/ + +#include + +#define BUFFER_SIZE 5000 +#define SMALL_BUFFER_SIZE 5 + +int __cdecl main(int argc, char *argv[]) +{ + + int ReturnValueForNonExisting = 0; + int ReturnValueForNull = 0; + + char pResultBuffer[BUFFER_SIZE]; + char pSmallBuffer[SMALL_BUFFER_SIZE]; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* This variable doesn't exist, it should return 0 */ + ReturnValueForNonExisting = GetEnvironmentVariable("NonExistingVariable", + pSmallBuffer, + SMALL_BUFFER_SIZE); + + if(ReturnValueForNonExisting != 0) + { + Fail("ERROR: The return should have been 0, but it was %d. " + "The function attempted to get an Environment Variable that " + "doesn't exist and should return 0 as a result.\n", + ReturnValueForNonExisting); + } + + + /* Passing a NULL string should return 0 */ + ReturnValueForNull = GetEnvironmentVariable(NULL, + pResultBuffer, + BUFFER_SIZE); + + if(ReturnValueForNull != 0) + { + Fail("ERROR: The return should have been 0, but it was %d. " + "The function attempted to get a NULL pointer and should return " + "0 as a result.\n",ReturnValueForNull); + + } + + PAL_Terminate(); + return PASS; + } + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/testinfo.dat new file mode 100644 index 0000000..afaa04b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetEnvironmentVariableA +Name = Return value test for GetEnvironmentVariableA +TYPE = DEFAULT +EXE1 = test +Description += Pass a nonexisting environment variable and a null to the function += to check return values. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/CMakeLists.txt new file mode 100644 index 0000000..14dc464 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_getenvironmentvariablea_test4 + ${SOURCES} +) + +add_dependencies(paltest_getenvironmentvariablea_test4 coreclrpal) + +target_link_libraries(paltest_getenvironmentvariablea_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.cpp new file mode 100644 index 0000000..a09eb88 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.cpp @@ -0,0 +1,75 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetEnvironmentVariable() function +** Set an Environment Variable, then use GetEnvironmentVariable to +** retrieve it -- ensure that it retrieves properly. +** +** +**=========================================================*/ + +/* Depends on SetEnvironmentVariableW (because we're implmenting + the wide version) and strcmp() +*/ + +#include + +int __cdecl main(int argc, char *argv[]) { + + /* Define some buffers needed for the function */ + char * pResultBuffer = NULL; + WCHAR SomeEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; + WCHAR TheEnvironmentValue[] = {'T','E','S','T','\0'}; + int size = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + SetEnvironmentVariableW(SomeEnvironmentVariable, + TheEnvironmentValue); + + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariable("PALTEST", // Variable Name + pResultBuffer, // Buffer for Value + 0); // Buffer size + + pResultBuffer = (char*)malloc(size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer. " + "Can't properly exec test case without this.\n"); + } + + + GetEnvironmentVariable("PALTEST", + pResultBuffer, + size); + + if(strcmp(pResultBuffer,"TEST") != 0) + { + free(pResultBuffer); + Fail("ERROR: The value in the buffer should have been 'TEST' but " + "was really '%s'.\n",pResultBuffer); + + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/testinfo.dat new file mode 100644 index 0000000..8fb16c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetEnvironmentVariableA +Name = Positive Test for GetEnvironmentVariableA +TYPE = DEFAULT +EXE1 = test +Description += Set an Environment Variable, then use GetEnvironmentVariable += to retrieve it ensure that it retrieves properly. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/CMakeLists.txt new file mode 100644 index 0000000..d5ceb8c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_getenvironmentvariablea_test5 + ${SOURCES} +) + +add_dependencies(paltest_getenvironmentvariablea_test5 coreclrpal) + +target_link_libraries(paltest_getenvironmentvariablea_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.cpp new file mode 100644 index 0000000..19a4d25 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.cpp @@ -0,0 +1,145 @@ +// 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. + +/*============================================================ +** Source : test5.c +** +** Purpose: Test for GetEnvironmentVariableA() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value on the BSD environment. +** +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + return PASS; + +#else + + /* Define some buffers needed for the function */ + char * pResultBuffer = NULL; + + char FirstEnvironmentVariable[] = {"PALTEST"}; + char FirstEnvironmentValue[] = {"FIRST"}; + + char SecondEnvironmentVariable[] = {"paltest"}; + char SecondEnvironmentValue[] = {"SECOND"}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableA(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", GetLastError()); + } + + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableA(FirstEnvironmentVariable, + pResultBuffer, + 0); + + /* To account for the null character at the end of the string */ + size = size + 1; + + pResultBuffer = (char*)malloc(sizeof(char)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer\n."); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariableA(FirstEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) + { + free(pResultBuffer); + Fail("ERROR: The value in the buffer should have been '%s' but " + "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer); + } + + free(pResultBuffer); + + /* Set the second environment Variable */ + bRc = SetEnvironmentVariableA(SecondEnvironmentVariable, + SecondEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Reallocate the memory for the string */ + pResultBuffer = (char*)malloc(sizeof(char)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer."); + } + + /* Try retrieving the value of the first variable, even though the + second variable has the same spelling and only differs in case */ + GetEnvironmentVariableA(FirstEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the two strings to confirm that the right value is returned */ + if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) + { + free(pResultBuffer); + Fail("ERROR: The value in the buffer should have been '%s' but " + "was really '%s'.\n",FirstEnvironmentValue,pResultBuffer); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + +#endif +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/testinfo.dat new file mode 100644 index 0000000..0bcec59 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetEnvironmentVariableA +Name = Positive Test for GetEnvironmentVariableA +TYPE = DEFAULT +EXE1 = test5 +Description += Set environment variables that differ only in case += and verify that on BSD they return two different += values. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/CMakeLists.txt new file mode 100644 index 0000000..e9ca739 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_getenvironmentvariablea_test6 + ${SOURCES} +) + +add_dependencies(paltest_getenvironmentvariablea_test6 coreclrpal) + +target_link_libraries(paltest_getenvironmentvariablea_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.cpp new file mode 100644 index 0000000..837036a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.cpp @@ -0,0 +1,99 @@ +// 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. + +/*============================================================ +** Source : test6.c +** +** Purpose: Test for GetEnvironmentVariableA() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value on the BSD environment. +** + +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + /* Define some buffers needed for the function */ + char * pResultBuffer = NULL; + + char FirstEnvironmentVariable[] = {"PALTEST"}; + char FirstEnvironmentValue[] = {"FIRST"}; + char ModifiedEnvVar[] = {"paltest"}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableA(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableA(ModifiedEnvVar, + pResultBuffer, + 0); + + /* To account for the nul character at the end of the string */ + size = size + 1; + + pResultBuffer = (char*)malloc(sizeof(char)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariableA(ModifiedEnvVar, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) + { + free(pResultBuffer); + Fail("ERROR: The value in the buffer should have been '%s' but " + "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + + +#else + + return PASS; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/testinfo.dat new file mode 100644 index 0000000..5de219a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetEnvironmentVariableA +Name = Positive Test for GetEnvironmentVariableA +TYPE = DEFAULT +EXE1 = test6 +Description += Set an Environment Variable, then use GetEnvironmentVariable += to retrieve the Variable, using a name that differs only in += Case. In Windows this should not affect the return value += of the function. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/CMakeLists.txt new file mode 100644 index 0000000..828a287 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/CMakeLists.txt @@ -0,0 +1,7 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/CMakeLists.txt new file mode 100644 index 0000000..2ce264d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_getenvironmentvariablew_test1 + ${SOURCES} +) + +add_dependencies(paltest_getenvironmentvariablew_test1 coreclrpal) + +target_link_libraries(paltest_getenvironmentvariablew_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.cpp new file mode 100644 index 0000000..cb5fc00 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.cpp @@ -0,0 +1,79 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetEnvironmentVariable() function +** +** +**=========================================================*/ + +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + + /* Define some buffers needed for the function */ + WCHAR * pResultBuffer = NULL; + int size = 0; + + /* A place to stash the returned values */ + int ReturnValueForLargeBuffer = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Recieve and allocate the correct amount of memory for the buffer */ + size = ReturnValueForLargeBuffer = + GetEnvironmentVariable(convert("PATH"), + pResultBuffer, + 0); + + pResultBuffer = (WCHAR*)malloc(size*sizeof(WCHAR)); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer. " + "Can't properly exec test case without this.\n"); + } + + + /* Normal case, PATH should fit into this buffer */ + ReturnValueForLargeBuffer = GetEnvironmentVariable(convert("PATH"), + pResultBuffer, + size); + free(pResultBuffer); + + /* Ensure that it returned a positive value */ + if(ReturnValueForLargeBuffer <= 0) + { + Fail("The return was %d, which indicates that the function failed.\n", + ReturnValueForLargeBuffer); + } + + /* Ensure that it succeeded and copied the correct number of characters. + If this is true, then the return value should be one less of the + size of the buffer. (Doesn't include that NULL byte) + */ + if(ReturnValueForLargeBuffer != size-1) + { + Fail("The value returned was %d when it should have been %d. This " + "should be the number of characters copied, " + "minus the NULL byte.\n", ReturnValueForLargeBuffer, size-1); + } + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/testinfo.dat new file mode 100644 index 0000000..467f2b7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetEnvironmentVariableW +Name = Return value test for GetEnvironmentVariableW +TYPE = DEFAULT +EXE1 = test +Description += Assign a properly sized buffer and get an environment variable, += check to ensure it returns the correct values. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/CMakeLists.txt new file mode 100644 index 0000000..edcf8db --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_getenvironmentvariablew_test2 + ${SOURCES} +) + +add_dependencies(paltest_getenvironmentvariablew_test2 coreclrpal) + +target_link_libraries(paltest_getenvironmentvariablew_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/test.cpp new file mode 100644 index 0000000..6fa753c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/test.cpp @@ -0,0 +1,56 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetEnvironmentVariable() function +** +** +**=========================================================*/ + +#define UNICODE + +#include + +#define SMALL_BUFFER_SIZE 1 + +int __cdecl main(int argc, char *argv[]) +{ + + WCHAR pSmallBuffer[SMALL_BUFFER_SIZE]; + + /* A place to stash the returned values */ + int ReturnValueForSmallBuffer; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* PATH won't fit in this buffer, it should return how many characters + it needs + */ + + ReturnValueForSmallBuffer = GetEnvironmentVariable(convert("PATH"), + pSmallBuffer, + SMALL_BUFFER_SIZE); + + if(ReturnValueForSmallBuffer <= 0) + { + Fail("The return value was %d when it should have been greater " + "than 0. This should return the number of characters needed " + "to contained the contents of PATH in a buffer.\n", + ReturnValueForSmallBuffer); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/testinfo.dat new file mode 100644 index 0000000..372f5af --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetEnvironmentVariableW +Name = Return value test on GetEnvironmentVariableW +TYPE = DEFAULT +EXE1 = test +Description += Pass a small buffer to GetEnvironmentVariableW += to ensure it returns the size it requires. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/CMakeLists.txt new file mode 100644 index 0000000..da0aa86 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_getenvironmentvariablew_test3 + ${SOURCES} +) + +add_dependencies(paltest_getenvironmentvariablew_test3 coreclrpal) + +target_link_libraries(paltest_getenvironmentvariablew_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/test.cpp new file mode 100644 index 0000000..03781e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/test.cpp @@ -0,0 +1,71 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetEnvironmentVariable() function +** +** +**=========================================================*/ + +#define UNICODE +#include + +#define BUFFER_SIZE 5000 +#define SMALL_BUFFER_SIZE 5 + +int __cdecl main(int argc, char *argv[]) +{ + + /* Define some buffers needed for the function */ + WCHAR pResultBuffer[BUFFER_SIZE]; + WCHAR pSmallBuffer[SMALL_BUFFER_SIZE]; + + /* A place to stash the returned values */ + int ReturnValueForNonExisting, ReturnValueForNull; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* This variable doesn't exist, it should return 0 */ + ReturnValueForNonExisting = + GetEnvironmentVariable(convert("NonExistingVariable"), + pSmallBuffer, + SMALL_BUFFER_SIZE); + + if(ReturnValueForNonExisting != 0) + { + Fail("ERROR: The return should have been 0, but it was %d. The " + "function attempted to get an Environment Variable that doesn't " + "exist and should return 0 as a result.\n", + ReturnValueForNonExisting); + } + + + /* Passing a NULL string should return 0 */ + ReturnValueForNull = GetEnvironmentVariable(NULL, + pResultBuffer, + BUFFER_SIZE); + + if(ReturnValueForNull != 0) + { + Fail("ERROR: The return should have been 0, but it was %d. The " + "function attempted to get a NULL pointer and should return 0 " + "as a result.\n",ReturnValueForNull); + } + + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/testinfo.dat new file mode 100644 index 0000000..d41c19c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetEnvironmentVariableW +Name = Return value test for GetEnvironmentVariableW +TYPE = DEFAULT +EXE1 = test +Description += Pass a nonexisting environment variable and a null to the function += to check return values. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/CMakeLists.txt new file mode 100644 index 0000000..f2b472c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_getenvironmentvariablew_test4 + ${SOURCES} +) + +add_dependencies(paltest_getenvironmentvariablew_test4 coreclrpal) + +target_link_libraries(paltest_getenvironmentvariablew_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.cpp new file mode 100644 index 0000000..1ee3e72 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.cpp @@ -0,0 +1,63 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetEnvironmentVariable() function +** +** +**=========================================================*/ + +/* Depends on SetEnvironmentVariableW (because we're implmenting the wide + version) and strcmp() */ + +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) { + + /* Define some buffers needed for the function */ + WCHAR * pResultBuffer = NULL; + WCHAR SomeEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; + WCHAR TheEnvironmentValue[] = {'T','E','S','T','\0'}; + int size; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + SetEnvironmentVariable(SomeEnvironmentVariable, + TheEnvironmentValue); + + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariable(convert("PALTEST"), // Variable Name + pResultBuffer, // Buffer for Value + 0); // Buffer size + + pResultBuffer = (WCHAR*)malloc(size*sizeof(WCHAR)); + + GetEnvironmentVariable(convert("PALTEST"), + pResultBuffer, + size); + + if(wcsncmp(pResultBuffer,convert("TEST"),wcslen(pResultBuffer) * 2) != 0) + { + Fail("ERROR: The value in the buffer should have been 'TEST' but was " + "really '%s'.",convertC(pResultBuffer)); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/testinfo.dat new file mode 100644 index 0000000..64204fa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetEnvironmentVariableW +Name = Positive Test for GetEnvironmentVariableW +TYPE = DEFAULT +EXE1 = test +Description += Set an Environment Variable, then use GetEnvironmentVariable += to retrieve it -- ensure that it retrieves properly. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/CMakeLists.txt new file mode 100644 index 0000000..37884ee --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_getenvironmentvariablew_test5 + ${SOURCES} +) + +add_dependencies(paltest_getenvironmentvariablew_test5 coreclrpal) + +target_link_libraries(paltest_getenvironmentvariablew_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.cpp new file mode 100644 index 0000000..179fc17 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.cpp @@ -0,0 +1,144 @@ +// 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. + +/*============================================================ +** Source : test5.c +** +** Purpose: Test for GetEnvironmentVariableW() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value on the BSD environment. +** +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + return PASS; + +#else + + /* Define some buffers needed for the function */ + WCHAR * pResultBuffer = NULL; + + WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; + WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'}; + + WCHAR SecondEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'}; + WCHAR SecondEnvironmentValue[] = {'S','E','C','O','N','D','\0'}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableW(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", GetLastError()); + } + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableW(FirstEnvironmentVariable, + pResultBuffer, + 0); + + /* To account for the nul character at the end of the string */ + size = size + 1; + + pResultBuffer = (WCHAR*)malloc(sizeof(WCHAR)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariableW(FirstEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) + { + free(pResultBuffer); + Fail("ERROR: The value in the buffer should have been '%S' but " + "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer); + } + + free(pResultBuffer); + + /* Set the second environment Variable */ + bRc = SetEnvironmentVariableW(SecondEnvironmentVariable, + SecondEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Reallocate the memory for the string */ + pResultBuffer = (WCHAR*)malloc(sizeof(WCHAR)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try retrieving the value of the first variable, even though the + second variable has the same spelling and only differs in case */ + GetEnvironmentVariableW(FirstEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the two strings to confirm that the right value is returned */ + if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) + { + free(pResultBuffer); + Fail("ERROR: The value in the buffer should have been '%S' but " + "was really '%S'.\n",FirstEnvironmentValue,pResultBuffer); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + +#endif +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/testinfo.dat new file mode 100644 index 0000000..cbc214e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetEnvironmentVariableW +Name = Positive Test for GetEnvironmentVariableW +TYPE = DEFAULT +EXE1 = test5 +Description += Set an Environment Variable, then use GetEnvironmentVariable += to retrieve it. Then set another environment variable that differs += from the original variable only by case and verify that += GetEnvironmnetVariable returns the correct value. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/CMakeLists.txt new file mode 100644 index 0000000..8a780b8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_getenvironmentvariablew_test6 + ${SOURCES} +) + +add_dependencies(paltest_getenvironmentvariablew_test6 coreclrpal) + +target_link_libraries(paltest_getenvironmentvariablew_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.cpp new file mode 100644 index 0000000..e376950 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.cpp @@ -0,0 +1,99 @@ +// 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. + +/*============================================================ +** Source : test6.c +** +** Purpose: Test for GetEnvironmentVariableW() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value on the BSD environment. +** +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + /* Define some buffers needed for the function */ + WCHAR * pResultBuffer = NULL; + + WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; + WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'}; + + WCHAR ModifiedEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableW(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableW(ModifiedEnvironmentVariable, + pResultBuffer, + 0); + + /* To account for the nul character at the end of the string */ + size = size + 1; + + pResultBuffer = (WCHAR*)malloc(sizeof(WCHAR)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariableW(ModifiedEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) + { + free(pResultBuffer); + Fail("ERROR: The value in the buffer should have been '%S' but " + "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + + +#else + + return PASS; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/testinfo.dat new file mode 100644 index 0000000..fad1ad6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetEnvironmentVariableW +Name = Positive Test for GetEnvironmentVariableW +TYPE = DEFAULT +EXE1 = test6 +Description += Set an Environment Variable, then use GetEnvironmentVariable += to retrieve the Variable, using a name that differs only in += Case. In Windows this should not affect the return value += of the function. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/CMakeLists.txt new file mode 100644 index 0000000..28ca478 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_getlasterror_test1 + ${SOURCES} +) + +add_dependencies(paltest_getlasterror_test1 coreclrpal) + +target_link_libraries(paltest_getlasterror_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/test.cpp new file mode 100644 index 0000000..65f56e5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/test.cpp @@ -0,0 +1,63 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetLastError() function +** +** +**=========================================================*/ + +/* Depends on SetLastError() */ + +#include + +/** + * Helper functions that does the actual test + */ +static void test(DWORD error ) +{ + DWORD TheResult; + + /* Set error */ + SetLastError(error); + + /* Check to make sure it returns the error value we just set */ + TheResult = GetLastError(); + if(TheResult!= error) + { + Fail("ERROR: The last error should have been %u, but when " + "GetLastError was called, it returned %u.\n",error,TheResult); + } + +} + +int __cdecl main(int argc, char *argv[]) { + + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* test setting and getting some values */ + test(5); + test(0xffffffff); + test(0xEEEEEEEE); + test(0xAAAAAAAA); + + PAL_Terminate(); + return PASS; +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/testinfo.dat new file mode 100644 index 0000000..be41f52 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetLastError +Name = Positive Test for GetLastError +TYPE = DEFAULT +EXE1 = test +Description += Ensure GetLastError returns the error message which was set. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/CMakeLists.txt new file mode 100644 index 0000000..1fd61e2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_getsysteminfo_test1 + ${SOURCES} +) + +add_dependencies(paltest_getsysteminfo_test1 coreclrpal) + +target_link_libraries(paltest_getsysteminfo_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/test.cpp new file mode 100644 index 0000000..5f3608f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/test.cpp @@ -0,0 +1,70 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetSystemInfo() function +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) { + + SYSTEM_INFO TheSystemInfo; + SYSTEM_INFO* pSystemInfo = &TheSystemInfo; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + GetSystemInfo(pSystemInfo); + + /* Ensure both valules are > than 0 */ + if(pSystemInfo->dwNumberOfProcessors < 1) + { + Fail("ERROR: The dwNumberofProcessors values should be > 0."); + } + + if(pSystemInfo->dwPageSize < 1) + { + Fail("ERROR: The dwPageSize should be greater than 0."); + } + + /* If this isn't WIN32, ensure all the other variables are 0 */ + +#if UNIX + if(pSystemInfo->dwOemId != 0 || + pSystemInfo->wProcessorArchitecture != 0 || + pSystemInfo->wReserved != 0 || + pSystemInfo->lpMinimumApplicationAddress != 0 || + pSystemInfo->lpMaximumApplicationAddress != 0 || + pSystemInfo->dwActiveProcessorMask != 0 || + pSystemInfo->dwProcessorType !=0 || + pSystemInfo->dwAllocationGranularity !=0 || + pSystemInfo->wProcessorLevel != 0 || + pSystemInfo->wProcessorRevision != 0) { + Fail("ERROR: Under FreeBSD, OemId, ProcessorArchitecture, Reserved, " + "MinimumApplicationAddress, MaximumApplicationAddress, " + "ActiveProcessorMask, ProcessorType, AllocationGranularity, " + "ProcessorLevel and ProcessorRevision should be equal to 0."); + + + } +#endif + + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/testinfo.dat new file mode 100644 index 0000000..7f03c63 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetSystemInfo +Name = Positive Test for GetSystemInfo +TYPE = DEFAULT +EXE1 = test +Description += Ensures the two required System Info fields can be aquired, += and the others are all 0. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/CMakeLists.txt new file mode 100644 index 0000000..7ad0ef0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_gettickcount_test1 + ${SOURCES} +) + +add_dependencies(paltest_gettickcount_test1 coreclrpal) + +target_link_libraries(paltest_gettickcount_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/test.cpp new file mode 100644 index 0000000..ad71ba5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/test.cpp @@ -0,0 +1,58 @@ +// 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. + +/*============================================================ +** +** Source: +** +** Source : test1.c +** +** Purpose: Test for GetTickCount() function +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) { + + DWORD FirstCount = 0; + DWORD SecondCount = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Grab a FirstCount, then loop for a bit to make the clock increase */ + FirstCount = GetTickCount(); + + /* Make sure some time passes */ + Sleep(60); //Since the get tick count is accurate within 55 milliseconds. + + /* Get a second count */ + SecondCount = GetTickCount(); + + /* Make sure the second one is bigger than the first. + This isn't the best test, but it at least shows that it's returning a + DWORD which is increasing. + */ + + if(FirstCount >= SecondCount) + { + Fail("ERROR: The first time (%d) was greater/equal than the second time " + " (%d). The tick count should have increased.\n", + FirstCount,SecondCount); + } + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/testinfo.dat new file mode 100644 index 0000000..78888ab --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GetTickCount +Name = Positive Test for GetTickCount +TYPE = DEFAULT +EXE1 = test +Description += Grab two Tick Counts with this function, and ensure that += the second is larger to show that the tick count is increasing. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/test1/CMakeLists.txt new file mode 100644 index 0000000..718513d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_globalmemorystatusex_test1 + ${SOURCES} +) + +add_dependencies(paltest_globalmemorystatusex_test1 coreclrpal) + +target_link_libraries(paltest_globalmemorystatusex_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/test1/test.cpp new file mode 100644 index 0000000..460edad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/test1/test.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GlobalMemoryStatusEx() function +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) { + + MEMORYSTATUSEX memoryStatus; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + if (!GlobalMemoryStatusEx(&memoryStatus)) + { + Fail("ERROR: GlobalMemoryStatusEx failed."); + } + + printf("GlobalMemoryStatusEx:\n"); + printf(" ullTotalPhys: %llu\n", memoryStatus.ullTotalPhys); + printf(" ullAvailPhys: %llu\n", memoryStatus.ullAvailPhys); + printf(" ullTotalVirtual: %llu\n", memoryStatus.ullTotalVirtual); + printf(" ullAvailVirtual: %llu\n", memoryStatus.ullAvailVirtual); + printf(" ullTotalPageFile: %llu\n", memoryStatus.ullTotalPageFile); + printf(" ullAvailPageFile: %llu\n", memoryStatus.ullAvailPageFile); + printf(" ullAvailExtendedVirtual: %llu\n", memoryStatus.ullAvailExtendedVirtual); + printf(" dwMemoryLoad: %u\n", memoryStatus.dwMemoryLoad); + + if (memoryStatus.ullTotalPhys == 0 || + memoryStatus.ullAvailPhys == 0 || + memoryStatus.ullTotalVirtual == 0 || + memoryStatus.ullAvailVirtual == 0 + ) + { + Fail("ERROR: GlobalMemoryStatusEx succeeded, but returned zero physical of virtual memory sizes."); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/test1/testinfo.dat new file mode 100644 index 0000000..7ae3b51 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/GlobalMemoryStatusEx/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = GlobalMemoryStatusEx +Name = Positive Test for GlobalMemoryStatusEx +TYPE = DEFAULT +EXE1 = test +Description += Ensures that invocation of GlobalMemoryStatusEx succeeds and += that it returns nonzero virtual and physical memory sizes + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/CMakeLists.txt new file mode 100644 index 0000000..9602e0b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_interlockedexchangeadd_test1 + ${SOURCES} +) + +add_dependencies(paltest_interlockedexchangeadd_test1 coreclrpal) + +target_link_libraries(paltest_interlockedexchangeadd_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/test.cpp new file mode 100644 index 0000000..a44f569 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/test.cpp @@ -0,0 +1,102 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: InterlockedExchangeAdd() function +** +** +**=========================================================*/ + +/* +** The InterlockedExchangeAdd function performs an atomic addition of Value +** to the value pointed to by Addend. +** The result is stored in the address specified by Addend. +** The initial value of the variable pointed to by Addend is returned as the function value. +*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + + LONG TheReturn; + + LONG *ptrValue = NULL; + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + + +#if defined(HOST_64BIT) + ptrValue = (LONG *) malloc(sizeof(LONG)); + + if(ptrValue == NULL) + { + Fail("Error:%d:Malloc failed for ptrValue\n", GetLastError()); + } + + *ptrValue = (LONG) 0; + + TheReturn = InterlockedExchangeAdd( ptrValue, (LONG) 5); + + + /* Added, it should be 5 now */ + if(*ptrValue != 5) + { + + Trace("ERROR: After an add operation, the value should be 5, " + "but it is really %d.", *ptrValue); + free(ptrValue); + Fail(""); + } + + /* Check to make sure the function returns the original value (5 in this case) */ + if(TheReturn != 0) + { + Trace("ERROR: The function should have returned the new value of %d " + "but instead returned %d.", *ptrValue, TheReturn); + free(ptrValue); + Fail(""); + } + + TheReturn = InterlockedExchangeAdd( ptrValue, (LONG) 1); + + + /* Added twice, it should be 6 now */ + if(*ptrValue != 6) + { + + Trace("ERROR: After having two add operations, the value should be 6, " + "but it is really %d.", *ptrValue); + free(ptrValue); + Fail(""); + } + + /* Check to make sure the function returns the original value (5 in this case) */ + if(TheReturn != 5) + { + Trace("ERROR: The function should have returned the new value of %d " + "but instead returned %d.", *ptrValue, TheReturn); + free(ptrValue); + Fail(""); + } + + free(ptrValue); +#endif + PAL_Terminate(); + return PASS; +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/CMakeLists.txt new file mode 100644 index 0000000..be162fb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_interlockedbit_test1 + ${SOURCES} +) + +add_dependencies(paltest_interlockedbit_test1 coreclrpal) + +target_link_libraries(paltest_interlockedbit_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/test.cpp new file mode 100644 index 0000000..1f7c43c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/test.cpp @@ -0,0 +1,77 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for InterlockedBitTestAndReset() function +** +** +**=========================================================*/ + +#include + +typedef struct tag_TEST_DATA +{ + LONG baseValue; + UINT bitPosition; + LONG expectedValue; + UCHAR expectedReturnValue; +} TEST_DATA; + +TEST_DATA test_data[] = +{ + { (LONG)0x00000000, 3, (LONG)0x00000000, 0 }, + { (LONG)0x12341234, 2, (LONG)0x12341230, 1 }, + { (LONG)0x12341234, 3, (LONG)0x12341234, 0 }, + { (LONG)0x12341234, 31, (LONG)0x12341234, 0 }, + { (LONG)0x12341234, 28, (LONG)0x02341234, 1 }, + { (LONG)0xffffffff, 28, (LONG)0xefffffff, 1 } +}; + +int __cdecl main(int argc, char *argv[]) { + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + for (int i = 0; i < sizeof (test_data) / sizeof (TEST_DATA); i++) + { + LONG baseVal = test_data[i].baseValue; + LONG bitPosition = test_data[i].bitPosition; + + UCHAR ret = InterlockedBitTestAndReset( + &baseVal, /* Variable to manipulate */ + bitPosition); + + if (ret != test_data[i].expectedReturnValue) + { + Fail("ERROR: InterlockedBitTestAndReset(%d): Expected return value is %d," + "Actual return value is %d.", + i, + test_data[i].expectedReturnValue, + ret); + } + + if (baseVal != test_data[i].expectedValue) + { + Fail("ERROR: InterlockedBitTestAndReset(%d): Expected value is %x," + "Actual value is %x.", + i, + test_data[i].expectedValue, + baseVal); + } + + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/testinfo.dat new file mode 100644 index 0000000..6779999 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = InterlockedBitTestAndReset +Name = Test for InterlockedBitTestAndReset +TYPE = DEFAULT +EXE1 = test +Description +Test validates that function InterlockedBitTestAndReset work as intended. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/CMakeLists.txt new file mode 100644 index 0000000..1771ad9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_interlockedbit_test2 + ${SOURCES} +) + +add_dependencies(paltest_interlockedbit_test2 coreclrpal) + +target_link_libraries(paltest_interlockedbit_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/test.cpp new file mode 100644 index 0000000..4230c8a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/test.cpp @@ -0,0 +1,77 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for InterlockedBitTestAndSet() function +** +** +**=========================================================*/ + +#include + +typedef struct tag_TEST_DATA +{ + LONG baseValue; + UINT bitPosition; + LONG expectedValue; + UCHAR expectedReturnValue; +} TEST_DATA; + +TEST_DATA test_data[] = +{ + { (LONG)0x00000000, 2, (LONG)0x00000004, 0 }, + { (LONG)0x12341234, 2, (LONG)0x12341234, 1 }, + { (LONG)0x12341234, 3, (LONG)0x1234123c, 0 }, + { (LONG)0x12341234, 31, (LONG)0x92341234, 0 }, + { (LONG)0x12341234, 28, (LONG)0x12341234, 1 }, + { (LONG)0xffffffff, 28, (LONG)0xffffffff, 1 } +}; + +int __cdecl main(int argc, char *argv[]) { + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + for (int i = 0; i < sizeof (test_data) / sizeof (TEST_DATA); i++) + { + LONG baseVal = test_data[i].baseValue; + LONG bitPosition = test_data[i].bitPosition; + + UCHAR ret = InterlockedBitTestAndSet( + &baseVal, /* Variable to manipulate */ + bitPosition); + + if (ret != test_data[i].expectedReturnValue) + { + Fail("ERROR: InterlockedBitTestAndSet(%d): Expected return value is %d," + "Actual return value is %d.", + i, + test_data[i].expectedReturnValue, + ret); + } + + if (baseVal != test_data[i].expectedValue) + { + Fail("ERROR: InterlockedBitTestAndSet(%d): Expected value is %x," + "Actual value is %x.", + i, + test_data[i].expectedValue, + baseVal); + } + + } + + PAL_Terminate(); + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/testinfo.dat new file mode 100644 index 0000000..3ad4317 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = InterlockedBitTestAndSet +Name = Test for InterlockedBitTestAndSet +TYPE = DEFAULT +EXE1 = test +Description +Test validates that function InterlockedBitTestAndSet work as intended. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/CMakeLists.txt new file mode 100644 index 0000000..f5546b9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_interlockedcompareexchange_test1 + ${SOURCES} +) + +add_dependencies(paltest_interlockedcompareexchange_test1 coreclrpal) + +target_link_libraries(paltest_interlockedcompareexchange_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/test.cpp new file mode 100644 index 0000000..77f2c4c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/test.cpp @@ -0,0 +1,100 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for InterlockedCompareExchange() function +** +** +**=========================================================*/ + +/* This test is FINISHED. Note: The biggest feature of this function is that + it locks the value before it increments it -- in order to make it so only + one thread can access it. But, I really don't have a great test to make + sure it's thread safe. Any ideas? +*/ + +#include + +#define START_VALUE 0 +#define SECOND_VALUE 5 +#define THIRD_VALUE 10 + +int __cdecl main(int argc, char *argv[]) { + + int BaseVariableToManipulate = START_VALUE; + int ValueToExchange = SECOND_VALUE; + int TempValue; + int TheReturn; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Compare START_VALUE with BaseVariableToManipulate, they're equal, + so exchange + */ + + TheReturn = InterlockedCompareExchange( + &BaseVariableToManipulate, /* Destination */ + ValueToExchange, /* Exchange value */ + START_VALUE); /* Compare value */ + + /* Exchanged, these should be equal now */ + if(BaseVariableToManipulate != ValueToExchange) + { + Fail("ERROR: A successful compare and exchange should have occurred, " + "making the variable have the value of %d, as opposed to the " + "current value of %d.", + ValueToExchange,BaseVariableToManipulate); + } + + /* Check to make sure it returns the original number which + 'BaseVariableToManipulate' was set to. + */ + if(TheReturn != START_VALUE) + { + Fail("ERROR: The return value after the first exchange should be the " + "former value of the variable, which was %d, but it is now %d.", + START_VALUE,TheReturn); + } + + + + ValueToExchange = THIRD_VALUE; /* Give this a new value */ + TempValue = BaseVariableToManipulate; /* Note value of Base */ + + /* + Do an exchange where 'BaseVariableToManipulate' doesn't + match -- therefore the exchange shouldn't happen. + So, it should end up the same as the 'TempValue' we saved. + */ + + InterlockedCompareExchange(&BaseVariableToManipulate, + ValueToExchange, + START_VALUE); + + if(BaseVariableToManipulate != TempValue) + { + Fail("ERROR: An attempted exchange should have failed due to " + "the compare failing. But, it seems to have succeeded. The " + "value should be %d but is %d in this case.", + TempValue,BaseVariableToManipulate); + } + + PAL_Terminate(); + return PASS; +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/testinfo.dat new file mode 100644 index 0000000..04b1dfe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = InterlockedCompareExchange +Name = Positive test of InterlockedCompareExchange +TYPE = DEFAULT +EXE1 = test +Description += Test to see if both successful and unsuccessful compare exchanges workp += roperly -- ie. Exchange and don't exchange. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/CMakeLists.txt new file mode 100644 index 0000000..e19fb11 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_interlockedcompareexchange_test2 + ${SOURCES} +) + +add_dependencies(paltest_interlockedcompareexchange_test2 coreclrpal) + +target_link_libraries(paltest_interlockedcompareexchange_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/test.cpp new file mode 100644 index 0000000..568380b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/test.cpp @@ -0,0 +1,168 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for InterlockedCompareExchange() function using multiple threads +** +** +**=========================================================*/ + + + +#include + +#define MAX_THREADS 10 +#define REPEAT_COUNT 10 + +//Global Variable Declaration +LONG g_Total = 0; +LONG Lock=0; + + +void ModifyGlobalResource(void); +void AcquireLock(PLONG pLock); +void ReleaseLock(PLONG pLock); + + + +//Main entry point of the program +int __cdecl main(int argc, char *argv[]) { + + int i = 0; + DWORD dwThreadID=0; + LONG totalOperations = 0; + + HANDLE hThread[MAX_THREADS]; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + + totalOperations = MAX_THREADS * REPEAT_COUNT; + + + //Create MAX_THREADS threads that will operate on the global counter + for (i=0;i + +#define START_VALUE 0 +#define SECOND_VALUE 5 +#define THIRD_VALUE 10 + +int __cdecl main(int argc, char *argv[]) { + + LONGLONG BaseVariableToManipulate = START_VALUE; + LONGLONG ValueToExchange = SECOND_VALUE; + LONGLONG TempValue; + LONGLONG TheReturn; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + /* Compare START_VALUE with BaseVariableToManipulate, they're equal, + so exchange + */ + + TheReturn = InterlockedCompareExchange64( + &BaseVariableToManipulate, /* Destination */ + ValueToExchange, /* Exchange value */ + START_VALUE); /* Compare value */ + + /* Exchanged, these should be equal now */ + if(BaseVariableToManipulate != ValueToExchange) + { + Fail("ERROR: A successful compare and exchange should have occurred, " + "making the variable have the value of %ll, as opposed to the " + "current value of %ll.", + ValueToExchange,BaseVariableToManipulate); + } + + /* Check to make sure it returns the original number which + 'BaseVariableToManipulate' was set to. + */ + if(TheReturn != START_VALUE) + { + Fail("ERROR: The return value after the first exchange should be the " + "former value of the variable, which was %ll, but it is now %ll.", + START_VALUE,TheReturn); + + } + + + + ValueToExchange = THIRD_VALUE; /* Give this a new value */ + TempValue = BaseVariableToManipulate; /* Note value of Base */ + + /* + Do an exchange where 'BaseVariableToManipulate' doesn't + match -- therefore the exchange shouldn't happen. + So, it should end up the same as the 'TempValue' we saved. + */ + + InterlockedCompareExchange64(&BaseVariableToManipulate, + ValueToExchange, + START_VALUE); + + if(BaseVariableToManipulate != TempValue) + { + Fail("ERROR: An attempted exchange should have failed due to " + "the compare failing. But, it seems to have succeeded. The " + "value should be %ll but is %ll in this case.", + TempValue,BaseVariableToManipulate); + } + +#endif //if defined(HOST_64BIT) + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/testinfo.dat new file mode 100644 index 0000000..1849277 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = InterlockedCompareExchange64 +Name = Positive test of InterlockedCompareExchange64 +TYPE = DEFAULT +EXE1 = test +Description += Test to see if both successful and unsuccessful compare exchanges workp += roperly -- ie. Exchange and don't exchange. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/CMakeLists.txt new file mode 100644 index 0000000..41543ef --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_interlockedcompareexchange64_test2 + ${SOURCES} +) + +add_dependencies(paltest_interlockedcompareexchange64_test2 coreclrpal) + +target_link_libraries(paltest_interlockedcompareexchange64_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/test.cpp new file mode 100644 index 0000000..0b6fb11 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/test.cpp @@ -0,0 +1,104 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: InterlockedIncrement64() function +** +** The test case spawns MAX_THREADS Threads, and each thread call InterlockedDecrement Function to decrement a +** global counter REPEAT_COUNT Times. The Test case sets the global counter to Zero at the beginning of the test. +** The test cases passes if at the end the test the value of the global counter is MAX_THREADS * REPEAT_COUNT. +** +** +**=========================================================*/ + +#include +#define MAX_THREADS 64 +#define REPEAT_COUNT 10000 + +LONG GlobalCounter = 0; +void IncrementCounter(void); + +int __cdecl main(int argc, char *argv[]) +{ + + LONG TotalOperations=0; + int i=0; + DWORD dwThreadID = 0; + + HANDLE hThread[MAX_THREADS]; + + TotalOperations = MAX_THREADS * REPEAT_COUNT; + + GlobalCounter = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* + ** Run only on 64 bit platforms + */ + #if defined(HOST_64BIT) + + //Create MAX_THREADS threads that will operate on the global counter + for (i=0;i + +int __cdecl main(int argc, char *argv[]) +{ + + long StartValue = 5; + long NewValue = 10; + PVOID ReturnValue = NULL; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + ReturnValue = InterlockedCompareExchangePointer((PVOID)&StartValue, + (PVOID)NewValue, + (PVOID)StartValue); + + /* StartValue and NewValue should be equal now */ + if(StartValue != NewValue) + { + Fail("ERROR: These values should be equal after the exchange. " + "They should both be %d, however the value that should have " + "been exchanged is %d.\n",NewValue,StartValue); + } + + /* Returnvalue should have been set to what 'StartValue' was + (5 in this case) + */ + + if((int)(size_t)ReturnValue != 5) + { + Fail("ERROR: The return value should be the value of the " + "variable before the exchange took place, which was 5. " + "But, the return value was %d.\n",ReturnValue); + } + + /* This is a mismatch, so no exchange should happen */ + InterlockedCompareExchangePointer((PVOID)&StartValue, + ReturnValue, + ReturnValue); + if(StartValue != NewValue) + { + Fail("ERROR: The compare should have failed and no exchange should " + "have been made, but it seems the exchange still happened.\n"); + } + + + PAL_Terminate(); + return PASS; +} + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/testinfo.dat new file mode 100644 index 0000000..d78515e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = InterlockedCompareExchangePointer +Name = Positive test of InterlockedCompareExchangePointer +TYPE = DEFAULT +EXE1 = test +Description += Test to see if both successful and unsuccessful compare exchanges work += properly -- ie. Exchange and don't exchange. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/CMakeLists.txt new file mode 100644 index 0000000..adf7267 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_interlockeddecrement_test1 + ${SOURCES} +) + +add_dependencies(paltest_interlockeddecrement_test1 coreclrpal) + +target_link_libraries(paltest_interlockeddecrement_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/test.cpp new file mode 100644 index 0000000..9c9a50c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/test.cpp @@ -0,0 +1,60 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: InterlockedDecrement() function +** +** +**=========================================================*/ + +/* This test is FINISHED. Note: The biggest feature of this function is that + it locks the value before it increments it -- in order to make it so only + one thread can access it. But, I really don't have a great test to make + sure it's thread safe. Any ideas? +*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + int TheValue = 0; + int TheReturn; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + InterlockedDecrement(&TheValue); + TheReturn = InterlockedDecrement(&TheValue); + + /* Decremented twice, it should be -2 now */ + if(TheValue != -2) + { + Fail("ERROR: After being decremented twice, the value should be -2, " + "but it is really %d.",TheValue); + } + + /* Check to make sure it returns itself */ + if(TheReturn != TheValue) + { + Fail("ERROR: The function should have returned the new value of %d " + "but instead returned %d.",TheValue,TheReturn); + } + + PAL_Terminate(); + return PASS; +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/testinfo.dat new file mode 100644 index 0000000..57ee383 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = InterlockedDecrement +Name = Positive test of InterlockedDecrement +TYPE = DEFAULT +EXE1 = test +Description += Test to see if this decrements the variable correctly and += has the correct return value. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/CMakeLists.txt new file mode 100644 index 0000000..cb66d92 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_interlockeddecrement_test2 + ${SOURCES} +) + +add_dependencies(paltest_interlockeddecrement_test2 coreclrpal) + +target_link_libraries(paltest_interlockeddecrement_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/test.cpp new file mode 100644 index 0000000..ba202b9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/test.cpp @@ -0,0 +1,94 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: InterlockedDecrement() function +** +** The test case spawns MAX_THREADS Threads, and each thread call InterlockedDecrement Function to decrement a +** global counter REPEAT_COUNT Times. The Test case sets the global counter to MAX_THREADS * REPEAT_COUNT +** at the beginning of the test. The test cases passes if at the end the test the value of the global counter is Zero. +** +** +**=========================================================*/ + +#include +#define MAX_THREADS 64 +#define REPEAT_COUNT 10000 + +LONG GlobalCounter = 0; +void DecrementCounter(void); + +int __cdecl main(int argc, char *argv[]) +{ + + LONG TotalOperations=0; + int i=0; + DWORD dwThreadID = 0; + HANDLE hThread[MAX_THREADS]; + TotalOperations = MAX_THREADS * REPEAT_COUNT; + GlobalCounter = TotalOperations; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + //Create MAX_THREADS threads that will operate on the global counter + for (i=0;i + +int __cdecl main(int argc, char *argv[]) +{ + LONGLONG TheValue = 0; + LONGLONG TheReturn; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + /* Compare START_VALUE with BaseVariableToManipulate, they're equal, + so exchange + */ + InterlockedDecrement64(&TheValue); + TheReturn = InterlockedDecrement64(&TheValue); + + /* Decremented twice, it should be -2 now */ + if(TheValue != -2) + { + Fail("ERROR: After being decremented twice, the value should be -2, " + "but it is really %ll.",TheValue); + } + + /* Check to make sure it returns itself */ + if(TheReturn != TheValue) + { + Fail("ERROR: The function should have returned the new value of %d " + "but instead returned %ll.",TheValue,TheReturn); + } +#endif //defined(HOST_64BIT) + PAL_Terminate(); + return PASS; +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/testinfo.dat new file mode 100644 index 0000000..8c5b1f0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = InterlockedDecrement64 +Name = Positive test of InterlockedDecrement64 +TYPE = DEFAULT +EXE1 = test +Description += Test to see if this decrements the variable correctly and += has the correct return value. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/CMakeLists.txt new file mode 100644 index 0000000..f3f90d9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_interlockeddecrement64_test2 + ${SOURCES} +) + +add_dependencies(paltest_interlockeddecrement64_test2 coreclrpal) + +target_link_libraries(paltest_interlockeddecrement64_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/test.cpp new file mode 100644 index 0000000..dae15f6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/test.cpp @@ -0,0 +1,99 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: InterlockedDecrement64() function +** +** The test case spawns MAX_THREADS Threads, and each thread call InterlockedDecrement Function to decrement a +** global counter REPEAT_COUNT Times. The Test case sets the global counter to MAX_THREADS * REPEAT_COUNT +** at the beginning of the test. The test cases passes if at the end the test the value of the global counter is Zero. +** +** +**=========================================================*/ + +#include +#define MAX_THREADS 64 +#define REPEAT_COUNT 10000 + +LONG GlobalCounter = 0; +void DecrementCounter(void); + +int __cdecl main(int argc, char *argv[]) +{ + LONG TotalOperations=0; + int i=0; + DWORD dwThreadID = 0; + HANDLE hThread[MAX_THREADS]; + TotalOperations = MAX_THREADS * REPEAT_COUNT; + GlobalCounter = TotalOperations; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + #if defined(HOST_64BIT) + + //Create MAX_THREADS threads that will operate on the global counter + for (i=0;i + +#define START_VALUE 0 + +int __cdecl main(int argc, char *argv[]) { + + int TheValue = START_VALUE; + int NewValue = 5; + int TheReturn; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + TheReturn = InterlockedExchange(&TheValue,NewValue); + + /* Compare the exchanged value with the value we exchanged it with. Should + be the same. + */ + if(TheValue != NewValue) + { + Fail("ERROR: The value which was exchanged should now be %d, but " + "instead it is %d.",NewValue,TheValue); + } + + /* Check to make sure it returns the origional number which 'TheValue' was + set to. + */ + + if(TheReturn != START_VALUE) + { + Fail("ERROR: The value returned should be the value before the " + "exchange happened, which was %d, but %d was returned.", + START_VALUE,TheReturn); + } + + + PAL_Terminate(); + return PASS; +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/testinfo.dat new file mode 100644 index 0000000..4b7c20a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = InterlockedExchange +Name = Positive test of InterlockedExchange +TYPE = DEFAULT +EXE1 = test +Description += Test to see if this exchanges the variables correctly and += has the correct return value. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/CMakeLists.txt new file mode 100644 index 0000000..a9a57a1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_interlockedexchange64_test1 + ${SOURCES} +) + +add_dependencies(paltest_interlockedexchange64_test1 coreclrpal) + +target_link_libraries(paltest_interlockedexchange64_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/test.cpp new file mode 100644 index 0000000..202ab75 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/test.cpp @@ -0,0 +1,74 @@ +// 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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: InterlockedExchange64() function +** +** +**=========================================================*/ + +/* This test is FINISHED. Note: The biggest feature of this function is that + it locks the value before it increments it -- in order to make it so only + one thread can access it. But, I really don't have a great test to make + sure it's thread safe. Any ideas? +*/ + +#include + +#define START_VALUE 0 + +int __cdecl main(int argc, char *argv[]) { + + LONGLONG TheValue = START_VALUE; + LONGLONG NewValue = 5; + LONGLONG TheReturn; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + + TheReturn = InterlockedExchange64(&TheValue,NewValue); + + /* Compare the exchanged value with the value we exchanged it with. Should + be the same. + */ + if(TheValue != NewValue) + { + Fail("ERROR: The value which was exchanged should now be %ll, but " + "instead it is %ll.",NewValue,TheValue); + } + + /* Check to make sure it returns the origional number which 'TheValue' was + set to. + */ + + if(TheReturn != START_VALUE) + { + Fail("ERROR: The value returned should be the value before the " + "exchange happened, which was %ll, but %ll was returned.", + START_VALUE,TheReturn); + } + +#endif // HOST_64BIT + PAL_Terminate(); + return PASS; +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/testinfo.dat new file mode 100644 index 0000000..3669e99 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = InterlockedExchange64 +Name = Positive test of InterlockedExchange64 +TYPE = DEFAULT +EXE1 = test +Description += Test to see if this exchanges the variables correctly and += has the correct return value. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/CMakeLists.txt new file mode 100644 index 0000000..dad5a31 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + InterlockedExchangePointer.cpp +) + +add_executable(paltest_interlockedexchangepointer_test1 + ${SOURCES} +) + +add_dependencies(paltest_interlockedexchangepointer_test1 coreclrpal) + +target_link_libraries(paltest_interlockedexchangepointer_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/InterlockedExchangePointer.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/InterlockedExchangePointer.cpp new file mode 100644 index 0000000..d36c967 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/InterlockedExchangePointer.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. + +/*============================================================= +** +** Source: InterlockedExchangePointer +** +** Purpose: Positive test the InterlockedExchangePointer API. +** Call InterlockedExchangePointer to exchange a pair of +** value +** +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + int i1 = 10; + int i2 = 20; + int *pOldValue = &i1; + int *pNewValue = &i2; + PVOID pReturnValue; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + + + /* + Testing + ======= + */ + + pReturnValue = InterlockedExchangePointer((PVOID)&pOldValue, + (PVOID)pNewValue); + /*check the returned value*/ + if(*(int *)pReturnValue != i1) + { + Fail("\nFailed to call InterlockedExchangePointer API, " + "return pointer does not point to the origional value\n"); + } + + /*check the exchanged value*/ + if(*pOldValue != *pNewValue) + { + Fail("\nFailed to call InterlockedExchangePointer API, " + "exchanged value is not right\n"); + } + + + + /* + Clean Up + */ + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/testinfo.dat new file mode 100644 index 0000000..5e0a366 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = miscellaneous +Function = InterlockedExchangePointer +Name = Pos test for InterlockedExchangePointer API to excnage a pair of value +TYPE = DEFAULT +EXE1 = interlockedexchangepointer +Description +=Test the InterlockedExchangePointer to exchange a pair of value diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/CMakeLists.txt new file mode 100644 index 0000000..d0e65ac --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_interlockedincrement_test1 + ${SOURCES} +) + +add_dependencies(paltest_interlockedincrement_test1 coreclrpal) + +target_link_libraries(paltest_interlockedincrement_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/test.cpp new file mode 100644 index 0000000..8b4b3e9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/test.cpp @@ -0,0 +1,62 @@ +// 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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: InterlockedIncrement() function +** +** +**=========================================================*/ + +/* This test is FINISHED. Note: The biggest feature of this function is that + it locks the value before it increments it -- in order to make it so only + one thread can access it. But, I really don't have a great test to make + sure it's thread safe. Any ideas? Nothing I've tried has worked. +*/ + + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + int TheValue = 0; + int TheReturn; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + InterlockedIncrement(&TheValue); + TheReturn = InterlockedIncrement(&TheValue); + + /* Incremented twice, it should be 2 now */ + if(TheValue != 2) + { + Fail("ERROR: The value was incremented twice and shoud now be 2, " + "but it is really %d",TheValue); + } + + /* Check to make sure it returns itself */ + if(TheReturn != TheValue) + { + Fail("ERROR: The function should return the new value, which shoud " + "have been %d, but it returned %d.",TheValue,TheReturn); + } + + PAL_Terminate(); + return PASS; +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/testinfo.dat new file mode 100644 index 0000000..c304960 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = InterlockedIncreement +Name = Positive test of InterlockedIncrement +TYPE = DEFAULT +EXE1 = test +Description += Test to see if this increments the variable correctly and += has the correct return value. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/CMakeLists.txt new file mode 100644 index 0000000..8d03188 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_interlockedincrement_test2 + ${SOURCES} +) + +add_dependencies(paltest_interlockedincrement_test2 coreclrpal) + +target_link_libraries(paltest_interlockedincrement_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/test.cpp new file mode 100644 index 0000000..90858e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/test.cpp @@ -0,0 +1,95 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: InterlockedIncrement() function +** +** The test case spawns MAX_THREADS Threads, and each thread call InterlockedDecrement Function to decrement a +** global counter REPEAT_COUNT Times. The Test case sets the global counter to Zero at the beginning of the test. +** The test cases passes if at the end the test the value of the global counter is MAX_THREADS * REPEAT_COUNT. +** +** +**=========================================================*/ + +#include +#define MAX_THREADS 64 +#define REPEAT_COUNT 10000 + +LONG GlobalCounter = 0; + +void IncrementCounter(void); + + + +int __cdecl main(int argc, char *argv[]) +{ + + LONG TotalOperations=0; + int i=0; + DWORD dwThreadID = 0; + HANDLE hThread[MAX_THREADS]; + TotalOperations = MAX_THREADS * REPEAT_COUNT; + GlobalCounter = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + //Create MAX_THREADS threads that will operate on the global counter + for (i=0;i + +int __cdecl main(int argc, char *argv[]) +{ + + LONGLONG TheValue = 0; + LONGLONG TheReturn; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } +/* +** Run only on 64 bit platforms +*/ +#if defined(HOST_64BIT) + + InterlockedIncrement64(&TheValue); + TheReturn = InterlockedIncrement64(&TheValue); + + /* Incremented twice, it should be 2 now */ + if(TheValue != 2) + { + Fail("ERROR: The value was incremented twice and shoud now be 2, " + "but it is really %ll",TheValue); + } + + /* Check to make sure it returns itself */ + if(TheReturn != TheValue) + { + Fail("ERROR: The function should return the new value, which shoud " + "have been %d, but it returned %ll.",TheValue,TheReturn); + } + +#endif //defined(HOST_64BIT) + PAL_Terminate(); + return PASS; +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/testinfo.dat new file mode 100644 index 0000000..fff0c70 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = InterlockedIncrement64 +Name = Positive test of InterlockedIncrement64 +TYPE = DEFAULT +EXE1 = test +Description += Test to see if this increments the variable correctly and += has the correct return value. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/CMakeLists.txt new file mode 100644 index 0000000..7a7bbf8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_interlockedincrement64_test2 + ${SOURCES} +) + +add_dependencies(paltest_interlockedincrement64_test2 coreclrpal) + +target_link_libraries(paltest_interlockedincrement64_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/test.cpp new file mode 100644 index 0000000..503da35 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/test.cpp @@ -0,0 +1,101 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: InterlockedIncrement64() function +** +** The test case spawns MAX_THREADS Threads, and each thread call InterlockedDecrement Function to decrement a +** global counter REPEAT_COUNT Times. The Test case sets the global counter to Zero at the beginning of the test. +** The test cases passes if at the end the test the value of the global counter is MAX_THREADS * REPEAT_COUNT. +** +** +**=========================================================*/ + +#include +#define MAX_THREADS 64 +#define REPEAT_COUNT 10000 + +LONG GlobalCounter = 0; +void IncrementCounter(void); + +int __cdecl main(int argc, char *argv[]) +{ + + LONG TotalOperations=0; + int i=0; + DWORD dwThreadID = 0; + HANDLE hThread[MAX_THREADS]; + TotalOperations = MAX_THREADS * REPEAT_COUNT; + GlobalCounter = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* + ** Run only on 64 bit platforms + */ + #if defined(HOST_64BIT) + + //Create MAX_THREADS threads that will operate on the global counter + for (i=0;i + +/** + * main + * + * executable entry point + */ +INT __cdecl main(INT argc, CHAR **argv) +{ + BOOL ResultValue = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* This should be readable, and return 0 */ + ResultValue = IsBadCodePtr((FARPROC)main); + if(ResultValue != 0) + { + Fail("ERROR: IsBadCodePtr returned %d instead of 0, when pointing " + "at readable memory.\n",ResultValue); + } + + /* 0x00 is usually unreadable memory so the function should + return non zero */ + ResultValue = IsBadCodePtr((FARPROC)0x00); + + if(ResultValue == 0) + { + Fail("ERROR: IsBadCodePtr returned %d instead of non zero " + "when checking on unreadable memory.\n",ResultValue); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/testinfo.dat new file mode 100644 index 0000000..8b73c0d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = C Runtime +Function = IsBadCodePtr +Name = Positive Test for IsBadCodePtr +TYPE = DEFAULT +EXE1 = test1 +Description += ensure that IsBadCodePtr return 0 when += it can read memory or non zero when it can't. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/CMakeLists.txt new file mode 100644 index 0000000..53b8129 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_isbadreadptr_test1 + ${SOURCES} +) + +add_dependencies(paltest_isbadreadptr_test1 coreclrpal) + +target_link_libraries(paltest_isbadreadptr_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/test.cpp new file mode 100644 index 0000000..24b7ceb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/test.cpp @@ -0,0 +1,138 @@ +// 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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: IsBadReadPtr() function +** +** +**=========================================================*/ + +#include + +#define MEMORY_AMOUNT 16 + +int __cdecl main(int argc, char *argv[]) +{ + LPVOID TestingPointer = NULL; + BOOL ResultValue = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + TestingPointer = malloc(MEMORY_AMOUNT); + if ( TestingPointer == NULL ) + { + Fail("ERROR: Failed to allocate memory for TestingPointer pointer. " + "Can't properly exec test case without this.\n"); + } + + + /* This should be readable, and return 0 */ + ResultValue = IsBadReadPtr(TestingPointer,MEMORY_AMOUNT); + if(ResultValue != 0) + { + free(TestingPointer); + + Fail("ERROR: The function returned %d instead of 0, when pointing " + "at readable memory.\n",ResultValue); + } + + /* If we pass 0, the result should be 0 as well */ + ResultValue = IsBadReadPtr(TestingPointer,0); + if(ResultValue != 0) + { + free(TestingPointer); + + Fail("ERROR: The function returned %d instead of 0, when the " + "function was passed a range of 0 bytes.\n",ResultValue); + } + free(TestingPointer); /* we are done with this */ + + /* create a READABLE address */ + TestingPointer = VirtualAlloc( + NULL, /* system selects address */ + 80, /* size of allocation*/ + MEM_COMMIT, /* commit */ + PAGE_READONLY); /* protection = read only */ + + if (TestingPointer == NULL ) + { + Fail("ERROR: call to VirtualAlloc failed\n"); + } + + ResultValue = IsBadReadPtr(TestingPointer,16); + if(ResultValue != 0) /* if no access */ + { + if(!VirtualFree(TestingPointer, 0, MEM_RELEASE)) + { + Trace("ERROR: Call to VirtualFree failed with error" + " code[ %u ]\n",GetLastError()); + } + + Fail("ERROR: The function returned %d instead of 1 when checking " + "on unreadable memory.\n",ResultValue); + } + + if(!VirtualFree(TestingPointer,0, MEM_RELEASE)) + { + Fail("ERROR: Call to VirtualFree failed with error" + " code[ %u ]\n",GetLastError()); + } + + /* create an unreadable address */ + TestingPointer = VirtualAlloc( + NULL, /* system selects address */ + 80, /* size of allocation */ + MEM_COMMIT, /* commit */ + PAGE_NOACCESS); /* protection = no access */ + + if (TestingPointer == NULL ) + { + Fail("ERROR: call to VirtualAlloc failed\n"); + } + + ResultValue = IsBadReadPtr(TestingPointer,16); + + if(ResultValue == 0) /* if access */ + { + if(!VirtualFree(TestingPointer, 0, MEM_RELEASE)) + { + Trace("ERROR: Call to VirtualFree failed with error" + " code[ %u ]\n",GetLastError()); + } + + Fail("ERROR: The function returned %d instead of 1 when checking " + "on unreadable memory.\n",ResultValue); + } + + if(!VirtualFree(TestingPointer,0, MEM_RELEASE)) + { + Fail("ERROR: Call to VirtualFree failed with error" + " code[ %u ]\n",GetLastError()); + } + + + /* This should be unreadable and return 1 */ + ResultValue = IsBadReadPtr(NULL,16); + if(ResultValue != 1) + { + Fail("ERROR: The function returned %d instead of 1 when checking " + "to see if NULL was readable.\n",ResultValue); + } + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/testinfo.dat new file mode 100644 index 0000000..27668b6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = IsBadReadPtr +Name = Return value tests for IsBadReadPtr +TYPE = DEFAULT +EXE1 = test +Description += Ensure that this returns true and false when it is supposed to. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/CMakeLists.txt new file mode 100644 index 0000000..a238c7c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_isbadwriteptr_test1 + ${SOURCES} +) + +add_dependencies(paltest_isbadwriteptr_test1 coreclrpal) + +target_link_libraries(paltest_isbadwriteptr_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/test.cpp new file mode 100644 index 0000000..018d7be --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/test.cpp @@ -0,0 +1,81 @@ +// 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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: IsBadWritePtr() function +** +** +**=========================================================*/ + +#include + +#define MEMORY_AMOUNT 16 + +int __cdecl main(int argc, char *argv[]) { + + void * TestingPointer = NULL; + BOOL ResultValue = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + TestingPointer = malloc(MEMORY_AMOUNT); + if ( TestingPointer == NULL ) + { + Fail("ERROR: Failed to allocate memory for TestingPointer pointer. " + "Can't properly exec test case without this.\n"); + } + + + /* This should be writeable, return 0 */ + ResultValue = IsBadWritePtr(TestingPointer,MEMORY_AMOUNT); + + if(ResultValue != 0) + { + free(TestingPointer); + + Fail("ERROR: Returned %d when 0 should have been returned, checking " + "to see if writable memory is unwriteable.\n",ResultValue); + } + + free(TestingPointer); + + /* This should be !writeable, return nonezero */ + TestingPointer = (void*)0x08; /* non writeable address */ + ResultValue = IsBadWritePtr(TestingPointer,sizeof(int)); + + if(ResultValue == 0) + { + Fail("ERROR: Returned %d when nonezero should have been returned, " + "checking to see if unwriteable memory is writeable.\n", + ResultValue); + } + + /* This should be !writeable, return Nonezero */ + ResultValue = IsBadWritePtr(NULL,MEMORY_AMOUNT); + + if(ResultValue == 0) + { + Fail("ERROR: Returned %d when nonezero should have been " + "returned,checking " + "to see if a NULL pointer is writeable.\n", + ResultValue); + } + + PAL_Terminate(); + return PASS; +} + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/testinfo.dat new file mode 100644 index 0000000..ba4e97e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = IsBadWritePtr +Name = Return Value test IsBadWritePtr +TYPE = DEFAULT +EXE1 = test +Description += Test to ensure that the function returns true and += false when it is supposed to. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/CMakeLists.txt new file mode 100644 index 0000000..d4fd770 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_isbadwriteptr_test2 + ${SOURCES} +) + +add_dependencies(paltest_isbadwriteptr_test2 coreclrpal) + +target_link_libraries(paltest_isbadwriteptr_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/test2.cpp new file mode 100644 index 0000000..b5e22ea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/test2.cpp @@ -0,0 +1,127 @@ +// 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. + +/*============================================================ +** +** Source: test2.c +** +** Purpose: +** Create three consecuative pages, NOACCES, READWRITE and +** NOACCESS. Check to ensure that the READWRITE page returns 0, to +** ensure that IsBadWritePtr isn't overflowing. Also check the other two +** pages to see that they return non-zero. +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) { + + LPVOID PageOne, PageTwo, PageThree; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Reserve enough space for four pages. We'll commit this memory + and set the correct access for each page below. + */ + + PageOne = VirtualAlloc(NULL, + GetOsPageSize()*4, + MEM_RESERVE, + PAGE_NOACCESS); + + if(PageOne == NULL) + { + Fail("ERROR: VirtualAlloc failed to reserve the required memory.\n"); + } + + /* Set the first Page to PAGE_NOACCESS */ + + PageOne = VirtualAlloc(PageOne, + GetOsPageSize(), + MEM_COMMIT, + PAGE_NOACCESS); + + if(PageOne == NULL) + { + VirtualFree(PageOne,0,MEM_RELEASE); + + Fail("ERROR: VirtualAlloc failed to commit the required memory " + "for the first page.\n"); + } + + /* Set the second Page to PAGE_READWRITE */ + + PageTwo = VirtualAlloc(((BYTE*)PageOne)+GetOsPageSize(), + GetOsPageSize(), + MEM_COMMIT, + PAGE_READWRITE); + if(PageTwo == NULL) + { + VirtualFree(PageOne,0,MEM_RELEASE); + + Fail("ERROR: VirtualAlloc failed to allocate the required memory " + "for the second page. %d\n",GetLastError()); + } + + /* Set the third Page to PAGE_NOACCESS */ + + PageThree = VirtualAlloc(((BYTE*)PageTwo) + (2 * GetOsPageSize()), + GetOsPageSize(), + MEM_COMMIT, + PAGE_NOACCESS); + + if(PageThree == NULL) + { + VirtualFree(PageOne,0,MEM_RELEASE); + + Fail("ERROR: VirtualAlloc failed to allocate the required memory. " + "For the third page.\n"); + } + + +/* Check that calling IsBadWritePtr on the first page returns non-zero */ + + if(IsBadWritePtr(PageThree,GetOsPageSize()) == 0) + { + VirtualFree(PageOne,0,MEM_RELEASE); + + Fail("ERROR: Called IsBadWritePtr on a page which was set NOACCESS " + "but the return value was 0, indicating that the memory is " + "writable.\n"); + } + + /* Check that calling IsBadWritePtr on the middle page returns 0 */ + + if(IsBadWritePtr(PageTwo,GetOsPageSize()) != 0) + { + VirtualFree(PageOne,0,MEM_RELEASE); + + Fail("ERROR: IsBadWritePtr didn't return 0 when called on a " + "page which should have been writable.\n"); + } + + /* Check that calling IsBadWritePtr on the third page returns non-zero */ + + if(IsBadWritePtr(PageThree,GetOsPageSize()) == 0) + { + VirtualFree(PageOne,0,MEM_RELEASE); + + Fail("ERROR: Called IsBadWritePtr on a page which was set NOACCESS " + "but the return value was 0, indicating that the memory is " + "writable.\n"); + } + VirtualFree(PageOne,0,MEM_RELEASE); + PAL_Terminate(); + return PASS; +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/testinfo.dat new file mode 100644 index 0000000..ad0a5fe --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = IsBadWritePtr +Name = Return Value test IsBadWritePtr +TYPE = DEFAULT +EXE1 = test2 +Description += Create three consecuative pages, NOACCES, READWRITE and += NOACCESS. Check to ensure that the READWRITE page returns 0, to += ensure that IsBadWritePtr isn't overflowing. Also check the other two += pages to see that they return non-zero. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/CMakeLists.txt new file mode 100644 index 0000000..a12ebfb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_isbadwriteptr_test3 + ${SOURCES} +) + +add_dependencies(paltest_isbadwriteptr_test3 coreclrpal) + +target_link_libraries(paltest_isbadwriteptr_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/test3.cpp new file mode 100644 index 0000000..7b04c54 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/test3.cpp @@ -0,0 +1,56 @@ +// 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. + +/*============================================================ +** +** Source: test3.c +** +** Purpose: +** Check that IsBadWritePtr returns non-zero on Read-only memory. +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) { + + LPVOID PageOne; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Reserve enough space for four pages. We'll commit this memory + and set the correct access for each page below. + */ + + PageOne = VirtualAlloc(NULL, + GetOsPageSize(), + MEM_COMMIT, + PAGE_READONLY); + + if(PageOne == NULL) + { + Fail("ERROR: VirtualAlloc failed to commit the required memory.\n"); + } + + if(IsBadWritePtr(PageOne,GetOsPageSize()) == 0) + { + VirtualFree(PageOne,0,MEM_RELEASE); + + Fail("ERROR: IsBadWritePtr returned 0 when checking a section of " + "read-only memory. It should be non-zero.\n"); + } + + VirtualFree(PageOne,0,MEM_RELEASE); + PAL_Terminate(); + return PASS; +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/testinfo.dat new file mode 100644 index 0000000..18851d2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = IsBadWritePtr +Name = Return Value test IsBadWritePtr +TYPE = DEFAULT +EXE1 = test3 +Description += Check that IsBadWritePtr returns non-zero on Read-only memory. + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/CMakeLists.txt new file mode 100644 index 0000000..900e746 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_messageboxw_test1 + ${SOURCES} +) + +add_dependencies(paltest_messageboxw_test1 coreclrpal) + +target_link_libraries(paltest_messageboxw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/test.cpp new file mode 100644 index 0000000..8eb8c0e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/test.cpp @@ -0,0 +1,81 @@ +// 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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: Test for MessageBoxW() function +** +** +**=========================================================*/ + +#define UNICODE + +#include + +int __cdecl main(int argc, char *argv[]) +{ + /* Declare Variables to use with convert()*/ + WCHAR * PalTitle = NULL; + WCHAR * OkTesting = NULL; + WCHAR * AbortTesting = NULL; + WCHAR * YesTesting = NULL; + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + PalTitle = convert("Pal Testing"); + OkTesting = convert("Click OK Please!"); + + /* Handle, text, title, style */ + if(MessageBox(NULL, OkTesting, + PalTitle, + MB_OK) != IDOK) + { + free(OkTesting); + free(PalTitle); + Fail("ERROR: The MB_OK style should return IDOK."); + } + + free(OkTesting); + AbortTesting = convert("Click Abort Please!"); + if(MessageBox(NULL, + AbortTesting, + PalTitle, + MB_ABORTRETRYIGNORE) != IDABORT) + { + free(AbortTesting); + free(PalTitle); + Fail("ERROR: The MB_ABORTRETRYIGNORE style should " + "return IDABORT."); + } + + free(AbortTesting); + YesTesting = convert("Click No Please!"); + + if(MessageBox(NULL, + YesTesting, + PalTitle, + MB_YESNO) != IDNO) + { + free(PalTitle); + free(YesTesting); + Fail("ERROR: The MB_YESNO style should return IDNO."); + } + + free(YesTesting); + free(PalTitle); + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/testinfo.dat new file mode 100644 index 0000000..e4d46c9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = MessageBoxW +Name = Positive test of MessageBoxW +TYPE = DEFAULT +EXE1 = test +Description += Ensure that the return values are correct for each type of Message Style. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/CMakeLists.txt new file mode 100644 index 0000000..7f32955 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_messageboxw_test2 + ${SOURCES} +) + +add_dependencies(paltest_messageboxw_test2 coreclrpal) + +target_link_libraries(paltest_messageboxw_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/test.cpp new file mode 100644 index 0000000..e2ff0cf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/test.cpp @@ -0,0 +1,76 @@ +// 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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: Test for MessageBoxW() function +** +** +**=========================================================*/ + +#define UNICODE + +#include + +int __cdecl main(int argc, char *argv[]) { + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Check to make sure there are no problems accepting all the ICON + styles and FLAG styles. These don't change anything, unless + they don't work at all. + */ + + if(MessageBox(NULL, + convert("Pal Testing"), + convert("Pal Title"), + MB_OK |MB_ICONEXCLAMATION|MB_TASKMODAL) != IDOK) + { + Fail("ERROR: The MB_OK style should always return IDOK."); + } + + if(MessageBox(NULL, + convert("Pal Testing"), + convert("Pal Title"), + MB_OK |MB_ICONINFORMATION|MB_SYSTEMMODAL) != IDOK) + { + Fail("ERROR: The MB_OK style should always return IDOK."); + } + + /* MB_SERVICE_NOTIFICATION doesn't seem to be available under windows? + It claims it exists and it should be supported under FreeBSD. + */ + +#if UNIX + if(MessageBox(NULL, + convert("Pal Testing"), + convert("Pal Title"), + MB_OK |MB_ICONSTOP|MB_SERVICE_NOTIFICATION) != IDOK) + { + Fail("ERROR: The MB_OK style should always return IDOK."); + } +#endif + + if(MessageBox(NULL, + convert("Pal Testing"), + convert("Pal Title"), + MB_OK |MB_ICONQUESTION) != IDOK) + { + Fail("ERROR: The MB_OK style should always return IDOK."); + } + + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/testinfo.dat new file mode 100644 index 0000000..e4d46c9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = MessageBoxW +Name = Positive test of MessageBoxW +TYPE = DEFAULT +EXE1 = test +Description += Ensure that the return values are correct for each type of Message Style. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/CMakeLists.txt new file mode 100644 index 0000000..070e421 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/CMakeLists.txt new file mode 100644 index 0000000..97c0701 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_setenvironmentvariablea_test1 + ${SOURCES} +) + +add_dependencies(paltest_setenvironmentvariablea_test1 coreclrpal) + +target_link_libraries(paltest_setenvironmentvariablea_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/test1.cpp new file mode 100644 index 0000000..86a4421 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/test1.cpp @@ -0,0 +1,168 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for SetEnvironmentVariableA() function. Set an +** environment variable and check to ensure success was returned. Then +** get the environment variable and compare to the correct value. Also, check +** that calling the function again, resets the variable properly. And that +** calling with NULL deletes the variable. +** +** Depends: +** GetEnvironmentVariable +** memcmp +** memset +** strlen +** +** +**=========================================================*/ + +#include +#define BUF_SIZE 128 + +int __cdecl main(int argc, char *argv[]) +{ + + /* Define some buffers needed for the function */ + char* VariableBuffer = "PALTEST"; + char* ValueBuffer = "Testing"; + char* SecondValueBuffer = "SecondTest"; + char NewValue[BUF_SIZE]; + int SetResult = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + + + /* + Test #1 + ======= + */ + + SetResult = SetEnvironmentVariable(VariableBuffer, + ValueBuffer); + + /* If result is 0, the SetEnviron function failed */ + if(SetResult == 0) + { + Fail("ERROR: SetEnvironmentVariable returned 0, which indicates that " + "it failed, even though it should have succeeded in setting the " + "variable PALTEST.\n"); + } + + memset(NewValue,0,BUF_SIZE); + + /* Grab the Environment variable we just set */ + if(GetEnvironmentVariable(VariableBuffer,NewValue,BUF_SIZE) <= 0) + { + Fail("ERROR: GetEnvironmentVariable returned 0 or less, which " + "indicates that no value was read in from the given variable."); + } + + /* Make sure that the value put into NewValue was indeed the environment + variable we set. + */ + + if(memcmp(NewValue,ValueBuffer,strlen(ValueBuffer)+1) != 0) + { + Fail("ERROR: When retrieving the variable that was just set, a " + "difference was found. Instead of the value being '%s' it " + "was instead '%s'.\n",ValueBuffer,NewValue); + } + + + + /* + Test #2 + ======= + */ + + /* If we set the same environment variable with a different value, the + old value should be replaced. + */ + + SetResult = SetEnvironmentVariable(VariableBuffer, + SecondValueBuffer); + + /* If result is 0, the SetEnviron function failed */ + if(SetResult == 0) + { + Fail("ERROR: SetEnvironmentVariable returned 0, which indicates that " + "it failed, even though it should have succeeded in re-setting " + "the variable PALTEST.\n"); + } + + memset(NewValue,0,BUF_SIZE); + + /* Grab the Environment variable we just set */ + if(GetEnvironmentVariable(VariableBuffer,NewValue,BUF_SIZE) <= 0) + { + Fail("ERROR: GetEnvironmentVariable returned 0 or less, which " + "indicates that no value was read in from the given variable."); + } + + /* Make sure that the value put into NewValue was indeed the environment + variable we set. + */ + + if(memcmp(NewValue,SecondValueBuffer,strlen(SecondValueBuffer)+1) != 0) + { + Fail("ERROR: When retrieving the variable that was just set, a " + "difference was found. Instead of the value being '%s' it " + "was instead '%s'.\n",SecondValueBuffer,NewValue); + } + + + + /* + Test #3 + ======= + */ + + /* Finally, set this variable with NULL, which should delete it from the + current environment. + */ + + SetResult = SetEnvironmentVariable(VariableBuffer, NULL); + + /* If result is 0, the SetEnviron function failed */ + if(SetResult == 0) + { + Fail("ERROR: SetEnvironmentVariable returned 0, which indicates that " + "it failed, even though it should have succeeded in deleting " + "the variable PALTEST.\n"); + } + + memset(NewValue,0,BUF_SIZE); + + /* Grab the Environment variable we just set, ensure that it's + empty now. + */ + if(GetEnvironmentVariable(VariableBuffer,NewValue,BUF_SIZE) != 0) + { + Fail("ERROR: GetEnvironmentVariable returned a non-zero value, " + "even though the environment variable which was checked should " + "have been empty."); + } + + + /* + Clean Up + */ + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/testinfo.dat new file mode 100644 index 0000000..561cd94 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = SetEnvironmentVariableA +Name = Positive test of SetEnvironmentVariableA +TYPE = DEFAULT +EXE1 = test1 +Description += Set an environment variable and check to ensure success was returned. Then += get the environment variable and compare to the correct value. Also, check += that calling the function again, resets the variable properly. And that += calling with NULL deletes the variable. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/CMakeLists.txt new file mode 100644 index 0000000..34cc787 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_setenvironmentvariablea_test2 + ${SOURCES} +) + +add_dependencies(paltest_setenvironmentvariablea_test2 coreclrpal) + +target_link_libraries(paltest_setenvironmentvariablea_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/test2.cpp new file mode 100644 index 0000000..984007e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/test2.cpp @@ -0,0 +1,85 @@ +// 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. + +/*============================================================ +** +** Source: test2.c +** +** Purpose: Test for SetEnvironmentVariableA() function +** Test to see that passing NULL to the first param fails. +** Test that passing NULL to both params fails. +** Set an environment variable, then pass NULL to the second param +** to delete it. Then make the same call again, to check that it fails. +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + /* Define some buffers needed for the function */ + char* VariableBuffer = "PALTEST"; + char* ValueBuffer = "testing"; + int SetResult; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Check that it fails if the first param is NULL */ + + SetResult = SetEnvironmentVariable(NULL,ValueBuffer); + + if(SetResult != 0) + { + Fail("ERROR: SetEnvironmentVariable returned a success value, " + "even though it was passed NULL as the first parameter and " + "should have failed.\n"); + } + + /* Check that it fails when both params are NULL */ + SetResult = SetEnvironmentVariable(NULL,NULL); + if(SetResult != 0) + { + Fail("ERROR: SetEnvironmentVariable returned a success value, even " + "though it was passed NULL as the first and second parameter and " + "should have failed.\n"); + } + + + /* First, set the variable, which should be ok. Then call the + function with the second parameter NULL twice -- the first call should + pass, the second should fail. + */ + + SetResult = SetEnvironmentVariable(VariableBuffer,ValueBuffer); + if(SetResult == 0) + { + Fail("ERROR: SetEnvironmentVariable returned failure, when " + "attempting to set a valid variable.\n"); + } + + SetResult = SetEnvironmentVariable(VariableBuffer,NULL); + if(SetResult == 0) + { + Fail("ERROR: SetEnvironmentVariable returned failure, when " + "attempting to delete a variable.\n"); + } + + SetResult = SetEnvironmentVariable(VariableBuffer,NULL); + if(SetResult != 0) + { + Fail("ERROR: SetEnvironmentVariable returned success, when " + "attempting to delete a variable which doesn't exist.\n"); + } + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/testinfo.dat new file mode 100644 index 0000000..446e301 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = SetEnvironmentVariableA +Name = Return value test of SetEnvironmentVariableA +TYPE = DEFAULT +EXE1 = test2 +Description += Test to see that passing NULL to the first param fails. += Test that passing NULL to both params fails. += Set an environment variable, then pass NULL to the second param += to delete it. Then make the same call again, to check that it fails. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/CMakeLists.txt new file mode 100644 index 0000000..4aa1a4a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_setenvironmentvariablea_test3 + ${SOURCES} +) + +add_dependencies(paltest_setenvironmentvariablea_test3 coreclrpal) + +target_link_libraries(paltest_setenvironmentvariablea_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.cpp new file mode 100644 index 0000000..539e330 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.cpp @@ -0,0 +1,144 @@ +// 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. + +/*============================================================ +** Source : test3.c +** +** Purpose: Test for SetEnvironmentVariableA() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value on the BSD environment. +** +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + return PASS; + +#else + + /* Define some buffers needed for the function */ + char * pResultBuffer = NULL; + + char FirstEnvironmentVariable[] = {"PALTEST"}; + char FirstEnvironmentValue[] = {"FIRST"}; + + char SecondEnvironmentVariable[] = {"paltest"}; + char SecondEnvironmentValue[] = {"SECOND"}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableA(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Set the second environment Variable */ + bRc = SetEnvironmentVariableA(SecondEnvironmentVariable, + SecondEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableA(FirstEnvironmentVariable, + pResultBuffer, + 0); + + /* increase size to account for the null char at the end */ + size = size + 1; + + pResultBuffer = (char*)malloc(sizeof(char)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariable(FirstEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) + { + Trace("ERROR: The value in the buffer should have been '%s' but " + "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer); + free(pResultBuffer); + Fail(""); + } + + free(pResultBuffer); + + /* Reallocate the memory for the string */ + pResultBuffer = (char*)malloc(sizeof(char)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try retrieving the value of the first variable, even though the + second variable has the same spelling and only differs in case */ + GetEnvironmentVariable(SecondEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the two strings to confirm that the right value is returned */ + if(strcmp(pResultBuffer,SecondEnvironmentValue) != 0) + { + Trace("ERROR: The value in the buffer should have been '%s' but " + "was really '%s'.\n",SecondEnvironmentValue,pResultBuffer); + free(pResultBuffer); + Fail(""); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/testinfo.dat new file mode 100644 index 0000000..05076bb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = SetEnvironmentVariableA +Name = Return value test of SetEnvironmentVariableA +TYPE = DEFAULT +EXE1 = test3 +Description += Test creating environment variables that differ only += by case and check that they are treated as separate += variables in the BSD operating system. + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/CMakeLists.txt new file mode 100644 index 0000000..032acfb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_setenvironmentvariablea_test4 + ${SOURCES} +) + +add_dependencies(paltest_setenvironmentvariablea_test4 coreclrpal) + +target_link_libraries(paltest_setenvironmentvariablea_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.cpp new file mode 100644 index 0000000..de3059c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.cpp @@ -0,0 +1,100 @@ +// 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. + +/*============================================================ +** Source : test4.c +** +** Purpose: Test for SetEnvironmentVariableA() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value in the WIN32 Environment +** + +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + /* Define some buffers needed for the function */ + char * pResultBuffer = NULL; + + char FirstEnvironmentVariable[] = {"PALTEST"}; + char FirstEnvironmentValue[] = {"FIRST"}; + char ModifiedEnvVar[] = {"paltest"}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableA(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableA(ModifiedEnvVar, + pResultBuffer, + 0); + + /* To account for the null character at the end of the string */ + size = size + 1; + + pResultBuffer = (char*)malloc(sizeof(char)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariableA(ModifiedEnvVar, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) + { + Trace("ERROR: The value in the buffer should have been '%s' but " + "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer); + free(pResultBuffer); + Fail(""); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + + +#else + + return PASS; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/testinfo.dat new file mode 100644 index 0000000..925a917 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = SetEnvironmentVariableA +Name = Return value test of SetEnvironmentVariableA +TYPE = DEFAULT +EXE1 = test4 +Description += Test that creating an environment variable and trying += to attain the value of the environment variable using += a name with different case works in the Windows += Environment. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/CMakeLists.txt new file mode 100644 index 0000000..070e421 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/CMakeLists.txt new file mode 100644 index 0000000..a0bd630 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_setenvironmentvariablew_test1 + ${SOURCES} +) + +add_dependencies(paltest_setenvironmentvariablew_test1 coreclrpal) + +target_link_libraries(paltest_setenvironmentvariablew_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.cpp new file mode 100644 index 0000000..0c753be --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.cpp @@ -0,0 +1,142 @@ +// 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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: +** Set an environment variable and check to ensure success was returned. Then +** get the environment variable and compare to the correct value. Also, check +** that calling the function again, resets the variable properly. And that +** calling with NULL deletes the variable. +** +** +**=========================================================*/ + +#define UNICODE +#define BUF_SIZE 128 + +#include + +/* Depends on GetEnvironmentVariable */ + +int __cdecl main(int argc, char *argv[]) +{ + + /* Define some buffers needed for the function */ + WCHAR VariableBuffer[] = {'P','A','L','T','E','S','T','\0'}; + WCHAR ValueBuffer[] = {'T','e','s','t','i','n','g','\0'}; + WCHAR SecondValueBuffer[] = {'S','e','c','o','n','d','T','e','s','t','\0'}; + WCHAR NewValue[BUF_SIZE]; + int SetResult = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + SetResult = SetEnvironmentVariable(VariableBuffer, + ValueBuffer); + + /* If result is 0, the SetEnviron function failed */ + if(SetResult == 0) + { + Fail("ERROR: SetEnvironmentVariable returned 0, which indicates that " + "it failed, even though it should have succeeded in setting the " + "variable PALTEST.\n"); + } + + + /* Grab the Environment variable we just set */ + if(GetEnvironmentVariable(VariableBuffer,NewValue,BUF_SIZE) <= 0) + { + Fail("ERROR: GetEnvironmentVariable returned 0 or less, which " + "indicates that no value was read in from the given variable."); + } + + /* Make sure that the value put into NewValue was indeed the environment + variable we set. + */ + + if(memcmp(NewValue,ValueBuffer,wcslen(ValueBuffer)*sizeof(WCHAR)+2) != 0) + { + Fail("ERROR: When retrieving the variable that was just set, a " + "difference was found. Instead of the value being '%s' it " + "was instead '%s'.\n",convertC(ValueBuffer),convertC(NewValue)); + } + + /* If we set the same environment variable with a different value, the + old value should be replaced. + */ + + SetResult = SetEnvironmentVariable(VariableBuffer, + SecondValueBuffer); + + /* If result is 0, the SetEnviron function failed */ + if(SetResult == 0) + { + Fail("ERROR: SetEnvironmentVariable returned 0, which indicates that " + "it failed, even though it should have succeeded in re-setting " + "the variable PALTEST.\n"); + } + + memset(NewValue,0,BUF_SIZE * sizeof(NewValue[0])); + + /* Grab the Environment variable we just set */ + if(GetEnvironmentVariable(VariableBuffer,NewValue,BUF_SIZE) <= 0) + { + Fail("ERROR: GetEnvironmentVariable returned 0 or less, which " + "indicates that no value was read in from the given variable."); + } + + /* Make sure that the value put into NewValue was indeed the environment + variable we set. + */ + + if(memcmp(NewValue,SecondValueBuffer, + wcslen(SecondValueBuffer)*sizeof(WCHAR)+2) != 0) + { + Fail("ERROR: When retrieving the variable that was just set, a " + "difference was found. Instead of the value being '%s' it " + "was instead '%s'.\n", + convertC(SecondValueBuffer),convertC(NewValue)); + } + + /* Finally, set this variable with NULL, which should delete it from the + current environment. + */ + + SetResult = SetEnvironmentVariable(VariableBuffer, NULL); + + /* If result is 0, the SetEnviron function failed */ + if(SetResult == 0) + { + Fail("ERROR: SetEnvironmentVariable returned 0, which indicates that " + "it failed, even though it should have succeeded in deleting " + "the variable PALTEST.\n"); + } + + memset(NewValue,0,BUF_SIZE*sizeof(NewValue[0])); + + /* Grab the Environment variable we just set, ensure that it's + empty now. + */ + if(GetEnvironmentVariable(VariableBuffer,NewValue,BUF_SIZE) != 0) + { + Fail("ERROR: GetEnvironmentVariable returned a non-zero value, " + "even though the environment variable which was checked should " + "have been empty."); + } + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/testinfo.dat new file mode 100644 index 0000000..a44f467 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = SetEnvironmentVariableW +Name = Positive test of SetEnvironmentVariableW +TYPE = DEFAULT +EXE1 = test +Description += Set an environment variable and check to ensure success was returned. Then += get the environment variable and compare to the correct value. Also, check += that calling the function again, resets the variable properly. And that += calling with NULL deletes the variable. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/CMakeLists.txt new file mode 100644 index 0000000..fa75790 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_setenvironmentvariablew_test2 + ${SOURCES} +) + +add_dependencies(paltest_setenvironmentvariablew_test2 coreclrpal) + +target_link_libraries(paltest_setenvironmentvariablew_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/test.cpp new file mode 100644 index 0000000..12f4887 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/test.cpp @@ -0,0 +1,88 @@ +// 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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: Test for SetEnvironmentVariableW() function +** Test to see that passing NULL to the first param fails. +** Test that passing NULL to both params fails. +** Set an environment variable, then pass NULL to the second param +** to delete it. Then make the same call again, to check that it fails. +** +** +**=========================================================*/ + +#define UNICODE + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + /* Define some buffers needed for the function */ + WCHAR VariableBuffer[] = {'P','A','L','T','E','S','T','\0'}; + WCHAR ValueBuffer[] = {'T','e','s','t','i','n','g','\0'}; + int SetResult; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + SetResult = SetEnvironmentVariable(NULL,ValueBuffer); + + /* Check that it fails if the first param is NULL */ + if(SetResult != 0) + { + Fail("ERROR: SetEnvironmentVariable returned a success value, " + "even though it was passed NULL as the first parameter and " + "should have failed.\n"); + } + + /* Check that it fails when both params are NULL */ + SetResult = SetEnvironmentVariable(NULL,NULL); + if(SetResult != 0) + { + Fail("ERROR: SetEnvironmentVariable returned a success value, even " + "though it was passed NULL as the first and second parameter and " + "should have failed.\n"); + } + + /* First, set the variable, which should be ok. Then call the + function with the second parameter NULL twice -- the first call should + pass, the second should fail. + */ + SetResult = SetEnvironmentVariable(VariableBuffer,ValueBuffer); + if(SetResult == 0) + { + Fail("ERROR: SetEnvironmentVariable returned failure, when " + "attempting to set a valid variable.\n"); + } + + SetResult = SetEnvironmentVariable(VariableBuffer,NULL); + if(SetResult == 0) + { + Fail("ERROR: SetEnvironmentVariable returned failure, when " + "attempting to delete a variable.\n"); + } + + SetResult = SetEnvironmentVariable(VariableBuffer,NULL); + if(SetResult != 0) + { + Fail("ERROR: SetEnvironmentVariable returned success, when " + "attempting to delete a variable which doesn't exist.\n"); + } + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/testinfo.dat new file mode 100644 index 0000000..4df82da --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = SetEnvironmentVariableW +Name = Return value test of SetEnvironmentVariableW +TYPE = DEFAULT +EXE1 = test +Description += Test to see that passing NULL to the first param fails. += Test that passing NULL to both params fails. += Set an environment variable, then pass NULL to the second param += to delete it. Then make the same call again, to check that it fails. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/CMakeLists.txt new file mode 100644 index 0000000..2a7a77e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_setenvironmentvariablew_test3 + ${SOURCES} +) + +add_dependencies(paltest_setenvironmentvariablew_test3 coreclrpal) + +target_link_libraries(paltest_setenvironmentvariablew_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.cpp new file mode 100644 index 0000000..5c4d4eb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.cpp @@ -0,0 +1,143 @@ +// 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. + +/*============================================================ +** Source : test3.c +** +** Purpose: Test for SetEnvironmentVariableW() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value on the BSD environment. +** +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + return PASS; + +#else + + /* Define some buffers needed for the function */ + WCHAR * pResultBuffer = NULL; + + WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; + WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'}; + + WCHAR SecondEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'}; + WCHAR SecondEnvironmentValue[] = {'S','E','C','O','N','D','\0'}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableW(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Set the second environment Variable */ + bRc = SetEnvironmentVariableW(SecondEnvironmentVariable, + SecondEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableW(FirstEnvironmentVariable, + pResultBuffer, + 0); + + /* Increase size to account for the null char at the end */ + size = size + 1; + + pResultBuffer = (WCHAR*)malloc(sizeof(WCHAR)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariableW(FirstEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(wcscmp(pResultBuffer,FirstEnvironmentValue) != 0) + { + Trace("ERROR: The value in the buffer should have been '%S' but " + "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer); + free(pResultBuffer); + Fail(""); + } + + free(pResultBuffer); + + /* Reallocate the memory for the string */ + pResultBuffer = (WCHAR*)malloc(sizeof(WCHAR)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try retrieving the value of the first variable, even though the + second variable has the same spelling and only differs in case */ + GetEnvironmentVariableW(SecondEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the two strings to confirm that the right value is returned */ + if(wcscmp(pResultBuffer,SecondEnvironmentValue) != 0) + { + Trace("ERROR: The value in the buffer should have been '%S' but " + "was really '%S'.\n",SecondEnvironmentValue,pResultBuffer); + free(pResultBuffer); + Fail(""); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/testinfo.dat new file mode 100644 index 0000000..43a457a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = SetEnvironmentVariableW +Name = Return value test of SetEnvironmentVariableW +TYPE = DEFAULT +EXE1 = test3 +Description += Create environment variables that differ only by case += and verify that they are treated distinctly in the += BSD Operating System. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/CMakeLists.txt new file mode 100644 index 0000000..7ec1ba8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_setenvironmentvariablew_test4 + ${SOURCES} +) + +add_dependencies(paltest_setenvironmentvariablew_test4 coreclrpal) + +target_link_libraries(paltest_setenvironmentvariablew_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.cpp new file mode 100644 index 0000000..50c59d6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.cpp @@ -0,0 +1,99 @@ +// 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. + +/*============================================================ +** Source : test4.c +** +** Purpose: Test for SetEnvironmentVariableW() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value on the BSD environment. +** +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + /* Define some buffers needed for the function */ + WCHAR * pResultBuffer = NULL; + + WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; + WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'}; + + WCHAR ModifiedEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableW(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableW(ModifiedEnvironmentVariable, + pResultBuffer, + 0); + + /* To account for the nul character at the end of the string */ + size = size + 1; + + pResultBuffer = (WCHAR*)malloc(sizeof(WCHAR)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariableW(ModifiedEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) + { + Trace("ERROR: The value in the buffer should have been '%S' but " + "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer); + free(pResultBuffer); + Fail(""); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + + +#else + + return PASS; +#endif +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/testinfo.dat new file mode 100644 index 0000000..126a72c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = SetEnvironmentVariableW +Name = Return value test of SetEnvironmentVariableW +TYPE = DEFAULT +EXE1 = test4 +Description += Create environment variable and try to retrieve += the value of the variable by using a variable name += that differs in case. This should not affect the += return value in the Windows Operating System. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/CMakeLists.txt new file mode 100644 index 0000000..75775f2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_setlasterror_test1 + ${SOURCES} +) + +add_dependencies(paltest_setlasterror_test1 coreclrpal) + +target_link_libraries(paltest_setlasterror_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/test.cpp new file mode 100644 index 0000000..d414626 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/test.cpp @@ -0,0 +1,59 @@ +// 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. + +/*============================================================ +** +** Source: test.c +** +** Purpose: Test for SetLastError() function +** +** +**=========================================================*/ +/* Depends on GetLastError() */ + + +#include + +int __cdecl main(int argc, char *argv[]) { + + /* Error value that we can set to test */ + const unsigned int FAKE_ERROR = 5; + const int NEGATIVE_ERROR = -1; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set error */ + SetLastError(FAKE_ERROR); + + /* Check to make sure it returns the error value we just set */ + if(GetLastError() != FAKE_ERROR) + { + Fail("ERROR: The last error should have been '%d' but the error " + "returned was '%d'\n",FAKE_ERROR,GetLastError()); + } + + /* Set the error to a negative */ + SetLastError(NEGATIVE_ERROR); + + /* Check to make sure it returns the error value we just set */ + if((signed)GetLastError() != NEGATIVE_ERROR) + { + Fail("ERROR: The last error should have been '%d' but the error " + "returned was '%d'\n",NEGATIVE_ERROR,GetLastError()); + } + + + PAL_Terminate(); + return PASS; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/testinfo.dat new file mode 100644 index 0000000..5333a4b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Miscellaneous +Function = SetLastError +Name = Positive test of SetLastError +TYPE = DEFAULT +EXE1 = test +Description += Set the Last Error and then use GetLastError to make sure += it was set properly. Assumes GetLastError is working. + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/_i64tow/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/_i64tow/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/_i64tow/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/CMakeLists.txt new file mode 100644 index 0000000..1995383 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_i64tow_test1 + ${SOURCES} +) + +add_dependencies(paltest_i64tow_test1 coreclrpal) + +target_link_libraries(paltest_i64tow_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.cpp new file mode 100644 index 0000000..9a8ae07 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.cpp @@ -0,0 +1,76 @@ +// 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. + +/*============================================================= +** +** Source: test1.c +** +** Purpose: Tests _i64tow_s with normal values and different radices, negative +** values, as well as the highest and lowest values. +** +** +**============================================================*/ + +#include + +typedef struct +{ + INT64 value; + int radix; + char *result; +} testCase; + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR buffer[256]; + WCHAR *testStr; + WCHAR *ret; + int i; + testCase testCases[] = + { + {42, 10, "42"}, + {42, 2, "101010"}, + {29, 32, "t"}, + {-1, 10, "-1"}, + {-1, 8, "1777777777777777777777"}, + {-1, 32, "fvvvvvvvvvvvv"}, + {I64(0x7FFFFFFFFFFFFFFF), 10, "9223372036854775807"}, + {I64(0x8000000000000000), 10, "-9223372036854775808"}, + {0,2,"0"}, + {0,16,"0"}, + {3,16,"3"}, + {15,16,"f"}, + {16,16,"10"}, + + }; + + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + for (i=0; i + +/* Milliseconds of error which are acceptable Function execution time, etc. + FreeBSD has a "standard" resolution of 50ms for waiting operations, so we + must take that into account as well */ +DWORD AcceptableTimeError = 15; + +int __cdecl main(int argc, char *argv[]) +{ + + int i; + int NumIterations = 100; + DWORD AvgTimeDiff; + DWORD TimeDiff[100]; + DWORD TotalTimeDiff = 0; + DWORD SleepInterval = 50; + LARGE_INTEGER StartTime; + LARGE_INTEGER EndTime; + LARGE_INTEGER Freq; + + /* Initialize the PAL. + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Get the frequency of the High-Performance Counter, + * in order to convert counter time to milliseconds. + */ + if (!QueryPerformanceFrequency(&Freq)) + { + Fail("ERROR:%u:Unable to retrieve the frequency of the " + "high-resolution performance counter.\n", + GetLastError()); + } + + /* Perform this set of sleep timings a number of times. + */ + for(i=0; i < NumIterations; i++) + { + + /* Get the current counter value. + */ + if (!QueryPerformanceCounter(&StartTime)) + { + Fail("ERROR:%u:Unable to retrieve the current value of the " + "high-resolution performance counter.\n", + GetLastError()); + } + + /* Sleep a predetermined interval. + */ + Sleep(SleepInterval); + + /* Get the new current counter value. + */ + if (!QueryPerformanceCounter(&EndTime)) + { + Fail("ERROR:%u:Unable to retrieve the current value of the " + "high-resolution performance counter.\n", + GetLastError()); + } + + /* Determine elapsed time, in milliseconds. Compare the elapsed time + * with the sleep interval, and add to counter. + */ + TimeDiff[i] = (DWORD)(((EndTime.QuadPart - StartTime.QuadPart)*1000)/ + (Freq.QuadPart)); + TotalTimeDiff += TimeDiff[i] - SleepInterval; + + } + + /* Verify that the average of the difference between the performance + * counter and the sleep interval is within our acceptable range. + */ + AvgTimeDiff = TotalTimeDiff / NumIterations; + if (AvgTimeDiff > AcceptableTimeError) + { + Fail("ERROR: average diff %u acceptable %u.\n", + AvgTimeDiff, + AcceptableTimeError); + } + + /* Terminate the PAL. + */ + PAL_Terminate(); + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/testinfo.dat new file mode 100644 index 0000000..56f11fc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/testinfo.dat @@ -0,0 +1,11 @@ +Version = 1.0 +Section = Miscellaneous +Function = QueryPerformanceCounter +Name = Positive Test for QueryPerformanceCounter +TYPE = DEFAULT +EXE1 = test1 +Description += This test will verify with QueryPerformanceCounter += and QueryPerformanceFrequency that an API call of Sleep += of 100 milliseconds takes 100 milliseconds, taking into += account the error tolerance. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/CMakeLists.txt new file mode 100644 index 0000000..3381412 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_queryperformancefrequency_test1 + ${SOURCES} +) + +add_dependencies(paltest_queryperformancefrequency_test1 coreclrpal) + +target_link_libraries(paltest_queryperformancefrequency_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/test1.cpp new file mode 100644 index 0000000..de08063 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/test1.cpp @@ -0,0 +1,59 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for QueryPerformanceFrequency function +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + LARGE_INTEGER Freq; + + /* Initialize the PAL. + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Check the return value of the performance + * frequency, a value of zero indicates that + * either the call has failed or the + * high-resolution performance counter is not + * installed. + */ + if (!QueryPerformanceFrequency(&Freq)) + { + + Fail("ERROR:%u:Unable to retrieve the frequency of the " + "high-resolution performance counter.\n", + GetLastError()); + } + + + /* Check the return value the frequency the + * value should be non-zero. + */ + if (Freq.QuadPart == 0) + { + + Fail("ERROR: The frequency has been determined to be 0 " + "the frequency should be non-zero.\n"); + + } + + /* Terminate the PAL. + */ + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/testinfo.dat new file mode 100644 index 0000000..ea56142 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/testinfo.dat @@ -0,0 +1,12 @@ +Version = 1.0 +Section = Miscellaneous +Function = QueryPerformanceFrequency +Name = Positive Test for QueryPerformanceFrequency +TYPE = DEFAULT +EXE1 = test1 +Description += This test will verify that QueryPerformanceFrequency += returns a valid return value. += The value of the count is processor dependent. On += some processors, for example, the count might be the += cycle rate of the processor clock. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/CMakeLists.txt new file mode 100644 index 0000000..694090a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/CMakeLists.txt @@ -0,0 +1,9 @@ +# TODO: make these tests compile +# add_subdirectory(PAL_get_stderr) +# add_subdirectory(PAL_get_stdin) +# add_subdirectory(PAL_get_stdout) + +add_subdirectory(PAL_errno) +add_subdirectory(PAL_GetPALDirectoryW) +add_subdirectory(PAL_Initialize_Terminate) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/CMakeLists.txt new file mode 100644 index 0000000..4c0a408 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_GetPALDirectoryW.cpp +) + +add_executable(paltest_pal_getpaldirectoryw_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_getpaldirectoryw_test1 coreclrpal) + +target_link_libraries(paltest_pal_getpaldirectoryw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.cpp new file mode 100644 index 0000000..856bfe8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.cpp @@ -0,0 +1,78 @@ +// 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. + +/*============================================================= +** +** Source: pal_getpaldirectoryw.c +** +** Purpose: Positive test the PAL_GetPALDirectoryW API. +** Call this API to retrieve a fully-qualified +** directory name where the PAL DLL is loaded from. +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + BOOL bValue; + DWORD dwFileAttribute; + WCHAR *wpDirectoryName = NULL; + char *pDirectoryName = NULL; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*allocate momory to store the directory name*/ + wpDirectoryName = (WCHAR*)malloc(MAX_PATH*sizeof(WCHAR)); + if(NULL == wpDirectoryName) + { + Fail("\nFailed to allocate memory for storing directory name!\n"); + } + + UINT size = MAX_PATH; + /*retrieve the machine configuration directory*/ + bValue = PAL_GetPALDirectoryW(wpDirectoryName, &size); + if(FALSE == bValue) + { + free(wpDirectoryName); + Fail("Failed to call PAL_GetPALDirectoryW API, " + "error code =%u\n", GetLastError()); + } + + + /*convert wide char string to a standard one*/ + pDirectoryName = convertC(wpDirectoryName); + if(0 == strlen(pDirectoryName)) + { + free(wpDirectoryName); + free(pDirectoryName); + Fail("The retrieved directory name string is empty!\n"); + } + + /*free the memory*/ + free(pDirectoryName); + + /*retrieve the attribute of a file or directory*/ + dwFileAttribute = GetFileAttributesW(wpDirectoryName); + + /*free the memory*/ + free(wpDirectoryName); + + /*check if the attribute indicates a directory*/ + if(FILE_ATTRIBUTE_DIRECTORY != + (dwFileAttribute & FILE_ATTRIBUTE_DIRECTORY)) + { + Fail("The retrieved directory name is not a valid directory!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/testinfo.dat new file mode 100644 index 0000000..dca92b0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = PAL_Specific +Function = PAL_GetPALDirectoryW +Name = Positive test for PAL_GetPALDirectoryW to retrieve fully-qualified directory name. +TYPE = DEFAULT +EXE1 = pal_getpaldirectoryw +Description +=Retrieve the fully-qualified directory name where the PAL DLL is loaded from diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/CMakeLists.txt new file mode 100644 index 0000000..1770033 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_GetUserTempDirectoryW.cpp +) + +add_executable(paltest_pal_getusertempdirectoryw_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_getusertempdirectoryw_test1 coreclrpal) + +target_link_libraries(paltest_pal_getusertempdirectoryw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.cpp new file mode 100644 index 0000000..65cc426 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.cpp @@ -0,0 +1,58 @@ +// 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. + +/*============================================================= +** +** Source: pal_getusertempdirectoryw.c +** +** Purpose: Positive test the PAL_GetUserTempDirectoryW API. +** Call PAL_GetUserTempDirectoryW to retrieve the user +** temp directory. +** +** +**============================================================*/ +#define UNICODE +#include + +#define DIRECTORYLENGTH 1024 + +int __cdecl main(int argc, char *argv[]) +{ + int err; + DWORD dwFileAttribute; + DWORD cch = DIRECTORYLENGTH; + WCHAR wDirectoryName[DIRECTORYLENGTH]; + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //retrieve the user temp directory + err = PAL_GetUserTempDirectory(ddtInstallationDependentDirectory, wDirectoryName, &cch); + + if(0 == err || 0 == strlen(convertC(wDirectoryName))) + { + Fail("Failed to call PAL_GetUserTempDirectoryW API!\n"); + } + + + //retrieve the attributes of a file or directory + dwFileAttribute = GetFileAttributesW(wDirectoryName); + + + //check if the retrieved attribute indicates a directory + if( FILE_ATTRIBUTE_DIRECTORY != (FILE_ATTRIBUTE_DIRECTORY & dwFileAttribute)) + { + Fail("PAL_GetUserTempDirectoryW API returned a non-directory name!\n"); + } + + printf ("PAL_GetUserTempDirectoryW returns %S\n", wDirectoryName); + + PAL_Terminate(); + return PASS; + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/testinfo.dat new file mode 100644 index 0000000..d530ca5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = pal_specific +Function = PAL_GetUserTempDirectoryW +Name = Positive test for PAL_GetUserTempDirectoryW API +TYPE = DEFAULT +EXE1 = pal_getusertempdirectoryw +Description +=Test the PAL_GetUserTempDirectoryW to retrieve the user temp +=directory name diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/CMakeLists.txt new file mode 100644 index 0000000..e5a3903 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_Initialize_Terminate.cpp +) + +add_executable(paltest_pal_initialize_terminate_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_initialize_terminate_test1 coreclrpal) + +target_link_libraries(paltest_pal_initialize_terminate_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/PAL_Initialize_Terminate.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/PAL_Initialize_Terminate.cpp new file mode 100644 index 0000000..29bb2c3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/PAL_Initialize_Terminate.cpp @@ -0,0 +1,33 @@ +// 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. + +/*============================================================= +** +** Source: pal_initialize_terminate.c +** +** Purpose: Positive test the PAL_Initialize and PAL_Terminate API. +** Call PAL_Initialize to initialize the PAL +** environment and call PAL_Terminate to clean up the PAL +** environment. +** + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + + /* Initialize the PAL environment */ + err = PAL_Initialize(argc, argv); + + if(0 != err) + { + ExitProcess(1); + } + + PAL_Terminate(); + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/testinfo.dat new file mode 100644 index 0000000..8ffe3bb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = PAL_Specific +Function = PAL_Initialize and PAL_Terminate +Name = Positive test for PAL_Initialize and PAL_Terminate +TYPE = DEFAULT +EXE1 = pal_initialize_terminate +Description +=Test the PAL_Initialize to initialize the PAL environment +=Test the PAL_Terminate to clean up the PAL environment diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/CMakeLists.txt new file mode 100644 index 0000000..bca0993 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + pal_initialize_twice.cpp +) + +add_executable(paltest_pal_initialize_terminate_test2 + ${SOURCES} +) + +add_dependencies(paltest_pal_initialize_terminate_test2 coreclrpal) + +target_link_libraries(paltest_pal_initialize_terminate_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/pal_initialize_twice.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/pal_initialize_twice.cpp new file mode 100644 index 0000000..fc460bc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/pal_initialize_twice.cpp @@ -0,0 +1,41 @@ +// 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. + +/*============================================================= +** +** Source: pal_initialize_twice.c +** +** Purpose: Positive test of PAL_Initialize and PAL_Terminate APIs. +** Calls PAL_Initialize twice to ensure that doing so +** will not cause unexpected failures in the PAL. +** Calls PAL_Terminate twice to clean up the PAL. +** + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + /* Initialize the PAL environment */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Try calling PAL_Initialize again - should just increment the init_count. */ + if (0 != (PAL_Initialize(argc, argv))) + { + // Call terminate due to the first PAL initialization. + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* If both calls to PAL_Initialize succeed, then PAL_Terminate must be + called twice. The first call just decrements the init_count to 1. */ + + PAL_Terminate(); + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/testinfo.dat new file mode 100644 index 0000000..31ceaf0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = PAL_Specific +Function = PAL_Initialize and PAL_Terminate +Name = Positive test for calling PAL_Initialize twice +TYPE = DEFAULT +EXE1 = pal_initialize_twice +Description +=Test calling PAL_Initialize twice to initialize the PAL environment +=and increment the init_count. +=Test calling PAL_Terminate twice to decrement the init_count +=and then clean up the PAL environment. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/CMakeLists.txt new file mode 100644 index 0000000..21befe2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2_neg) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/CMakeLists.txt new file mode 100644 index 0000000..93af8fa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_RegisterLibraryW_UnregisterLibraryW.cpp +) + +add_executable(paltest_pal_registerlibraryw_unregisterlibraryw_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_registerlibraryw_unregisterlibraryw_test1 coreclrpal) + +target_link_libraries(paltest_pal_registerlibraryw_unregisterlibraryw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.cpp new file mode 100644 index 0000000..8eb8776 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.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. + +/*============================================================= +** +** Source: pal_registerlibrary_unregisterlibrary +** +** Purpose: Positive test the PAL_RegisterLibrary API and +** PAL_UnRegisterLibrary. +** Call PAL_RegisterLibrary to map a module into the calling +** process address space and call PAL_UnRegisterLibrary +** to unmap this module. +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + char ModuleName[64]; + WCHAR *wpModuleName = NULL; + int err; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*zero the buffer*/ + memset(ModuleName,0,64); + sprintf_s(ModuleName, _countof(ModuleName), "%s", "rotor_pal"); + + /*convert a normal string to a wide one*/ + wpModuleName = convert(ModuleName); + + /*load a module*/ + ModuleHandle = PAL_RegisterLibrary(wpModuleName); + + /*free the memory*/ + free(wpModuleName); + + if(!ModuleHandle) + { + Fail("Failed to call PAL_RegisterLibrary API to map a module " + "into calling process, error code=%u!\n", GetLastError()); + } + + /*decrement the reference count of the loaded DLL*/ + err = PAL_UnregisterLibrary(ModuleHandle); + if(0 == err) + { + Fail("\nFailed to call PAL_UnregisterLibrary API to " + "decrement the count of the loaded DLL module, " + "error code=%u!\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/testinfo.dat new file mode 100644 index 0000000..abbd28c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = pal_specific +Function = PAL_RegisterLibraryW and PAL_UnregisterLibraryW API +Name = Positive test PAL_RegisterLibraryW and PAL_UnregisterLibaryW API +TYPE = DEFAULT +EXE1 = pal_registerlibraryw_unregisterlibraryw +Description +=Test the PAL_RegisterLibraryW and PAL_UnregisterLibraryW to map an executable +=module into calling process address space and unmap this module diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/CMakeLists.txt new file mode 100644 index 0000000..0ac3cfc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + reg_unreg_libraryw_neg.cpp +) + +add_executable(paltest_reg_unreg_libraryw_neg + ${SOURCES} +) + +add_dependencies(paltest_reg_unreg_libraryw_neg coreclrpal) + +target_link_libraries(paltest_reg_unreg_libraryw_neg + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.cpp new file mode 100644 index 0000000..c6fa4ad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.cpp @@ -0,0 +1,62 @@ +// 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. + +/*============================================================= +** +** Source: pal_registerlibraryw_unregisterlibraryw_neg.c +** +** Purpose: Negative test the PAL_RegisterLibrary API. +** Call PAL_RegisterLibrary to map a non-existant module +** into the calling process address space. +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + char ModuleName[64]; + WCHAR *wpModuleName = NULL; + int err; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + memset(ModuleName, 0, 64); + sprintf_s(ModuleName, _countof(ModuleName), "%s", "not_exist_module_name"); + + /*convert a normal string to a wide one*/ + wpModuleName = convert(ModuleName); + + /*load a not exist module*/ + ModuleHandle = PAL_RegisterLibrary(wpModuleName); + + /*free the memory*/ + free(wpModuleName); + + if(NULL != ModuleHandle) + { + Trace("ERROR: PAL_RegisterLibrary successfully mapped " + "a module that does not exist into the calling process\n"); + + /*decrement the reference count of the loaded DLL*/ + err = PAL_UnregisterLibrary(ModuleHandle); + if(0 == err) + { + Trace("\nFailed to call PAL_UnregisterLibrary API to decrement the " + "count of the loaded DLL module!\n"); + } + Fail(""); + + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/testinfo.dat new file mode 100644 index 0000000..3322633 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = pal_specific +Function = PAL_RegisterLibraryW and PAL_UnregisterLibraryW API +Name = Negative test for PAL_RegisterLibraryW and PAL_UnregisterLibaryW API to map and unmap a non-existant module +TYPE = DEFAULT +EXE1 = pal_registerlibraryw_unregisterlibraryw_neg +Description +=Test the PAL_RegisterLibraryW and PAL_UnregisterLibraryW to map a non-existant +=module into calling process address space + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/CMakeLists.txt new file mode 100644 index 0000000..32bef1d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_errno.cpp +) + +add_executable(paltest_pal_errno_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_errno_test1 coreclrpal) + +target_link_libraries(paltest_pal_errno_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/PAL_errno.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/PAL_errno.cpp new file mode 100644 index 0000000..32e8487 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/PAL_errno.cpp @@ -0,0 +1,53 @@ +// 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. + +/*============================================================= +** +** Source: pal_errno.c +** +** Purpose: Positive test the PAL_errno API. +** call PAL_errno to retrieve the pointer to +** the per-thread errno value. +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + FILE *pFile = NULL; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if( 0 != err) + { + return FAIL; + } + + /*Try to open a not-exist file to read to generate an error*/ + pFile = fopen( "no_exist_file_name", "r" ); + + if( NULL != pFile ) + { + Trace("\nFailed to call fopen to open a not exist for reading, " + "an error is expected, but no error occurred\n"); + + if( EOF == fclose( pFile ) ) + { + Trace("\nFailed to call fclose to close a file stream\n"); + } + Fail( "Test failed! fopen() Should not have worked!" ); + } + + /*retrieve the per-thread error value pointer*/ + if( 2 != errno ) + { + Fail("\nFailed to call PAL_errno API, this value is not correct." + " The correct value is ENOENT[2] ( No such file or directory.).\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/testinfo.dat new file mode 100644 index 0000000..a35e1d2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = PAL_Specific +Function = PAL_errno +Name = Positive test PAL_errno API to retrieve the pre-thread errno value +TYPE = DEFAULT +EXE1 = pal_errno +Description +=Test the PAL_errno to retrieve a pointer to per-thread errno value diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/CMakeLists.txt new file mode 100644 index 0000000..df89be2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_get_stderr.cpp +) + +add_executable(paltest_pal_get_stderr_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_get_stderr_test1 coreclrpal) + +target_link_libraries(paltest_pal_get_stderr_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/PAL_get_stderr.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/PAL_get_stderr.cpp new file mode 100644 index 0000000..da53460 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/PAL_get_stderr.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================= +** +** Source: pal_get_stderr.c +** +** Purpose: Positive test the PAL_get_stderr API. +** Call PAL_get_stderr to retrieve the PAL standard error +** output stream pointer. +** This test case should be run manually and automatically. +** + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + FILE *pPAL_stderr = NULL; + const char *pMsg = "\nThis is a PAL_get_stderr test message, " + "not an error message!\n"; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*retrieve the PAL standard error output stream pointer*/ + pPAL_stderr = PAL_get_stderr(); + + if(NULL == pPAL_stderr) + { + Fail("\nFailed to call PAL_get_stderr API, error code = %u\n", + GetLastError()); + } + + /*output a test message through PAL standard error stream*/ + err = fputs(pMsg, pPAL_stderr); + if(EOF == err) + { + Fail("\nFailed to call fputs to output message to PAL stdandard " + "error stream, error code=%u\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/testinfo.dat new file mode 100644 index 0000000..a633c68 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = PAL_Specific +Function = PAL_get_stderr +Name = Positive test PAL_get_stderr to retrieve the PAL standard error stream pointer +TYPE = DEFAULT +EXE1 = pal_get_stderr +Description +=Test the PAL_get_stderr to retrieve the PAL standard error output stream pointer and +=output a test message to this error stream +=this test case will be run both manually and automatically diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/CMakeLists.txt new file mode 100644 index 0000000..8599110 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_get_stdin.cpp +) + +add_executable(paltest_pal_get_stdin_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_get_stdin_test1 coreclrpal) + +target_link_libraries(paltest_pal_get_stdin_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/PAL_get_stdin.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/PAL_get_stdin.cpp new file mode 100644 index 0000000..5d1fd23 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/PAL_get_stdin.cpp @@ -0,0 +1,68 @@ +// 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. + +/*============================================================= +** +** Source: pal_get_stdin.c +** +** Purpose: Positive test the PAL_get_stdout API. +** Call PAL_get_stdin to retrieve the PAL standard input +** stream pointer. +** This test case should be run manually. +** + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + FILE *pPAL_stdin = NULL; + char Buffer[256]; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*retrieve the PAL standard input stream pointer*/ + pPAL_stdin = PAL_get_stdin(); + if(NULL == pPAL_stdin) + { + Fail("\nFailed to call PAL_get_stdin API to retrieve the " + "PAL standard input stream pointer, " + "error code = %u\n", GetLastError()); + } + + /*zero the buffer*/ + memset(Buffer, 0, 256); + + printf("\nPlease input some words: (less than 255 characters)\n"); + + /*further test the input stream*/ + /*read message from the PAL standard input stream*/ + if(NULL == fgets(Buffer, 255, pPAL_stdin)) + { + Fail( "Failed to call fgets to get a string from PAL standard " + "input stream, error code=%u\n", GetLastError()); + } + else + { + if(1 == strlen(Buffer) && Buffer[0] == '\n') + { + printf("\nEmpty input!\n"); + } + else + { + printf("\nYour input words are:\n%s\n", Buffer); + } + } + + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/testinfo.dat new file mode 100644 index 0000000..d1c5723 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = PAL_Specific +Function = PAL_get_stdin +Name = Positive test PAL_get_stdin to retrieve the PAL standard stdin stream pointer +TYPE = DEFAULT +EXE1 = pal_get_stdin +Description +=Test the PAL_get_stdin to retrieve the PAL standard input stream pointer +=if success, display the input string to screen +=this test case should be run manually diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/CMakeLists.txt new file mode 100644 index 0000000..5142c43 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + PAL_get_stdout.cpp +) + +add_executable(paltest_pal_get_stdout_test1 + ${SOURCES} +) + +add_dependencies(paltest_pal_get_stdout_test1 coreclrpal) + +target_link_libraries(paltest_pal_get_stdout_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/PAL_get_stdout.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/PAL_get_stdout.cpp new file mode 100644 index 0000000..ebfee47 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/PAL_get_stdout.cpp @@ -0,0 +1,52 @@ +// 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. + +/*============================================================= +** +** Source: pal_get_stdout.c +** +** Purpose: Positive test the PAL_get_stdout API. +** Call PAL_get_stdout to retrieve the PAL standard output +** stream pointer. +** This test case should be run manually and automatically. +** + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + FILE *pPAL_stdout = NULL; + const char *pMsg = "\nThis is a PAL_get_stdout test output message, " + "not an error message!\n"; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*retrieve the PAL output stream pointer*/ + pPAL_stdout = PAL_get_stdout(); + if(NULL == pPAL_stdout) + { + Fail("\nFailed to call PAL_get_stdout API to retrieve the " + "standard PAL output stream pointer, error code=%u\n", + GetLastError()); + } + + /*output a test message through PAL standard output stream*/ + err = fputs(pMsg, pPAL_stdout); + if(EOF == err) + { + Fail("\nFailed to call fputs to output message to PAL stdandard " + "output stream, error code=%u\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/testinfo.dat new file mode 100644 index 0000000..ed37098 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = PAL_Specific +Function = PAL_get_stdout +Name = Positive test PAL_get_stdout to retrieve PAL standard output stream pointer +TYPE = DEFAULT +EXE1 = pal_get_stdout +Description +=Test the PAL_get_stdout to retrieve the PAL standard output stream pointer +=This test case will be run both manually and automatically diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/paltestlist.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/paltestlist.txt new file mode 100644 index 0000000..ce633d6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/paltestlist.txt @@ -0,0 +1,716 @@ +c_runtime/abs/test1/paltest_abs_test1 +c_runtime/acos/test1/paltest_acos_test1 +c_runtime/acosf/test1/paltest_acosf_test1 +c_runtime/acosh/test1/paltest_acosh_test1 +c_runtime/acoshf/test1/paltest_acoshf_test1 +c_runtime/asin/test1/paltest_asin_test1 +c_runtime/asinf/test1/paltest_asinf_test1 +c_runtime/asinh/test1/paltest_asinh_test1 +c_runtime/asinhf/test1/paltest_asinhf_test1 +c_runtime/atan/test1/paltest_atan_test1 +c_runtime/atan2/test1/paltest_atan2_test1 +c_runtime/atan2f/test1/paltest_atan2f_test1 +c_runtime/atanf/test1/paltest_atanf_test1 +c_runtime/atanh/test1/paltest_atanh_test1 +c_runtime/atanhf/test1/paltest_atanhf_test1 +c_runtime/atof/test1/paltest_atof_test1 +c_runtime/atoi/test1/paltest_atoi_test1 +c_runtime/bsearch/test1/paltest_bsearch_test1 +c_runtime/bsearch/test2/paltest_bsearch_test2 +c_runtime/cbrt/test1/paltest_cbrt_test1 +c_runtime/cbrtf/test1/paltest_cbrtf_test1 +c_runtime/ceil/test1/paltest_ceil_test1 +c_runtime/ceilf/test1/paltest_ceilf_test1 +c_runtime/cos/test1/paltest_cos_test1 +c_runtime/cosf/test1/paltest_cosf_test1 +c_runtime/cosh/test1/paltest_cosh_test1 +c_runtime/coshf/test1/paltest_coshf_test1 +c_runtime/errno/test1/paltest_errno_test1 +c_runtime/errno/test2/paltest_errno_test2 +c_runtime/exit/test1/paltest_exit_test1 +c_runtime/exp/test1/paltest_exp_test1 +c_runtime/expf/test1/paltest_expf_test1 +c_runtime/fabs/test1/paltest_fabs_test1 +c_runtime/fabsf/test1/paltest_fabsf_test1 +c_runtime/fclose/test1/paltest_fclose_test1 +c_runtime/fclose/test2/paltest_fclose_test2 +c_runtime/fflush/test1/paltest_fflush_test1 +c_runtime/fgets/test1/paltest_fgets_test1 +c_runtime/fgets/test2/paltest_fgets_test2 +c_runtime/fgets/test3/paltest_fgets_test3 +c_runtime/floor/test1/paltest_floor_test1 +c_runtime/floorf/test1/paltest_floorf_test1 +c_runtime/fma/test1/paltest_fma_test1 +c_runtime/fmaf/test1/paltest_fmaf_test1 +c_runtime/fmod/test1/paltest_fmod_test1 +c_runtime/fmodf/test1/paltest_fmodf_test1 +c_runtime/fopen/test1/paltest_fopen_test1 +c_runtime/fopen/test2/paltest_fopen_test2 +c_runtime/fopen/test3/paltest_fopen_test3 +c_runtime/fopen/test4/paltest_fopen_test4 +c_runtime/fopen/test5/paltest_fopen_test5 +c_runtime/fopen/test6/paltest_fopen_test6 +c_runtime/fopen/test7/paltest_fopen_test7 +c_runtime/fprintf/test1/paltest_fprintf_test1 +c_runtime/fprintf/test10/paltest_fprintf_test10 +c_runtime/fprintf/test11/paltest_fprintf_test11 +c_runtime/fprintf/test12/paltest_fprintf_test12 +c_runtime/fprintf/test13/paltest_fprintf_test13 +c_runtime/fprintf/test14/paltest_fprintf_test14 +c_runtime/fprintf/test15/paltest_fprintf_test15 +c_runtime/fprintf/test16/paltest_fprintf_test16 +c_runtime/fprintf/test17/paltest_fprintf_test17 +c_runtime/fprintf/test18/paltest_fprintf_test18 +c_runtime/fprintf/test19/paltest_fprintf_test19 +c_runtime/fprintf/test2/paltest_fprintf_test2 +c_runtime/fprintf/test3/paltest_fprintf_test3 +c_runtime/fprintf/test4/paltest_fprintf_test4 +c_runtime/fprintf/test5/paltest_fprintf_test5 +c_runtime/fprintf/test6/paltest_fprintf_test6 +c_runtime/fprintf/test7/paltest_fprintf_test7 +c_runtime/fprintf/test8/paltest_fprintf_test8 +c_runtime/fprintf/test9/paltest_fprintf_test9 +c_runtime/fputs/test1/paltest_fputs_test1 +c_runtime/free/test1/paltest_free_test1 +c_runtime/fseek/test1/paltest_fseek_test1 +c_runtime/fwprintf/test1/paltest_fwprintf_test1 +c_runtime/fwprintf/test10/paltest_fwprintf_test10 +c_runtime/fwprintf/test11/paltest_fwprintf_test11 +c_runtime/fwprintf/test12/paltest_fwprintf_test12 +c_runtime/fwprintf/test13/paltest_fwprintf_test13 +c_runtime/fwprintf/test14/paltest_fwprintf_test14 +c_runtime/fwprintf/test15/paltest_fwprintf_test15 +c_runtime/fwprintf/test16/paltest_fwprintf_test16 +c_runtime/fwprintf/test17/paltest_fwprintf_test17 +c_runtime/fwprintf/test18/paltest_fwprintf_test18 +c_runtime/fwprintf/test3/paltest_fwprintf_test3 +c_runtime/fwprintf/test4/paltest_fwprintf_test4 +c_runtime/fwprintf/test5/paltest_fwprintf_test5 +c_runtime/fwprintf/test6/paltest_fwprintf_test6 +c_runtime/fwprintf/test8/paltest_fwprintf_test8 +c_runtime/fwprintf/test9/paltest_fwprintf_test9 +c_runtime/fwrite/test1/paltest_fwrite_test1 +c_runtime/getenv/test1/paltest_getenv_test1 +c_runtime/getenv/test2/paltest_getenv_test2 +c_runtime/getenv/test3/paltest_getenv_test3 +c_runtime/ilogb/test1/paltest_ilogb_test1 +c_runtime/ilogbf/test1/paltest_ilogbf_test1 +c_runtime/isalnum/test1/paltest_isalnum_test1 +c_runtime/isalpha/test1/paltest_isalpha_test1 +c_runtime/isdigit/test1/paltest_isdigit_test1 +c_runtime/islower/test1/paltest_islower_test1 +c_runtime/isprint/test1/paltest_isprint_test1 +c_runtime/isprint/test2/paltest_isprint_test2 +c_runtime/isspace/test1/paltest_isspace_test1 +c_runtime/isupper/test1/paltest_isupper_test1 +c_runtime/iswdigit/test1/paltest_iswdigit_test1 +c_runtime/iswspace/test1/paltest_iswspace_test1 +c_runtime/iswupper/test1/paltest_iswupper_test1 +c_runtime/isxdigit/test1/paltest_isxdigit_test1 +c_runtime/llabs/test1/paltest_llabs_test1 +c_runtime/log/test1/paltest_log_test1 +c_runtime/log2/test1/paltest_log2_test1 +c_runtime/log2f/test1/paltest_log2f_test1 +c_runtime/log10/test1/paltest_log10_test1 +c_runtime/log10f/test1/paltest_log10f_test1 +c_runtime/logf/test1/paltest_logf_test1 +c_runtime/malloc/test1/paltest_malloc_test1 +c_runtime/malloc/test2/paltest_malloc_test2 +c_runtime/memchr/test1/paltest_memchr_test1 +c_runtime/memcmp/test1/paltest_memcmp_test1 +c_runtime/memcpy/test1/paltest_memcpy_test1 +c_runtime/memmove/test1/paltest_memmove_test1 +c_runtime/memset/test1/paltest_memset_test1 +c_runtime/modf/test1/paltest_modf_test1 +c_runtime/modff/test1/paltest_modff_test1 +c_runtime/pow/test1/paltest_pow_test1 +c_runtime/powf/test1/paltest_powf_test1 +c_runtime/printf/test1/paltest_printf_test1 +c_runtime/printf/test10/paltest_printf_test10 +c_runtime/printf/test11/paltest_printf_test11 +c_runtime/printf/test12/paltest_printf_test12 +c_runtime/printf/test13/paltest_printf_test13 +c_runtime/printf/test14/paltest_printf_test14 +c_runtime/printf/test15/paltest_printf_test15 +c_runtime/printf/test16/paltest_printf_test16 +c_runtime/printf/test17/paltest_printf_test17 +c_runtime/printf/test18/paltest_printf_test18 +c_runtime/printf/test19/paltest_printf_test19 +c_runtime/printf/test2/paltest_printf_test2 +c_runtime/printf/test3/paltest_printf_test3 +c_runtime/printf/test4/paltest_printf_test4 +c_runtime/printf/test5/paltest_printf_test5 +c_runtime/printf/test6/paltest_printf_test6 +c_runtime/printf/test7/paltest_printf_test7 +c_runtime/printf/test8/paltest_printf_test8 +c_runtime/printf/test9/paltest_printf_test9 +c_runtime/qsort/test1/paltest_qsort_test1 +c_runtime/qsort/test2/paltest_qsort_test2 +c_runtime/rand_srand/test1/paltest_rand_srand_test1 +c_runtime/realloc/test1/paltest_realloc_test1 +c_runtime/scalbn/test1/paltest_scalbn_test1 +c_runtime/scalbnf/test1/paltest_scalbnf_test1 +c_runtime/sin/test1/paltest_sin_test1 +c_runtime/sinf/test1/paltest_sinf_test1 +c_runtime/sinh/test1/paltest_sinh_test1 +c_runtime/sinhf/test1/paltest_sinhf_test1 +c_runtime/sprintf_s/test1/paltest_sprintf_test1 +c_runtime/sprintf_s/test10/paltest_sprintf_test10 +c_runtime/sprintf_s/test11/paltest_sprintf_test11 +c_runtime/sprintf_s/test12/paltest_sprintf_test12 +c_runtime/sprintf_s/test13/paltest_sprintf_test13 +c_runtime/sprintf_s/test14/paltest_sprintf_test14 +c_runtime/sprintf_s/test15/paltest_sprintf_test15 +c_runtime/sprintf_s/test16/paltest_sprintf_test16 +c_runtime/sprintf_s/test17/paltest_sprintf_test17 +c_runtime/sprintf_s/test18/paltest_sprintf_test18 +c_runtime/sprintf_s/test19/paltest_sprintf_test19 +c_runtime/sprintf_s/test2/paltest_sprintf_test2 +c_runtime/sprintf_s/test3/paltest_sprintf_test3 +c_runtime/sprintf_s/test4/paltest_sprintf_test4 +c_runtime/sprintf_s/test6/paltest_sprintf_test6 +c_runtime/sprintf_s/test7/paltest_sprintf_test7 +c_runtime/sprintf_s/test8/paltest_sprintf_test8 +c_runtime/sprintf_s/test9/paltest_sprintf_test9 +c_runtime/sqrt/test1/paltest_sqrt_test1 +c_runtime/sqrtf/test1/paltest_sqrtf_test1 +c_runtime/sscanf_s/test1/paltest_sscanf_test1 +c_runtime/sscanf_s/test10/paltest_sscanf_test10 +c_runtime/sscanf_s/test11/paltest_sscanf_test11 +c_runtime/sscanf_s/test12/paltest_sscanf_test12 +c_runtime/sscanf_s/test13/paltest_sscanf_test13 +c_runtime/sscanf_s/test14/paltest_sscanf_test14 +c_runtime/sscanf_s/test15/paltest_sscanf_test15 +c_runtime/sscanf_s/test16/paltest_sscanf_test16 +c_runtime/sscanf_s/test17/paltest_sscanf_test17 +c_runtime/sscanf_s/test2/paltest_sscanf_test2 +c_runtime/sscanf_s/test3/paltest_sscanf_test3 +c_runtime/sscanf_s/test4/paltest_sscanf_test4 +c_runtime/sscanf_s/test5/paltest_sscanf_test5 +c_runtime/sscanf_s/test6/paltest_sscanf_test6 +c_runtime/sscanf_s/test7/paltest_sscanf_test7 +c_runtime/sscanf_s/test8/paltest_sscanf_test8 +c_runtime/sscanf_s/test9/paltest_sscanf_test9 +c_runtime/strcat/test1/paltest_strcat_test1 +c_runtime/strchr/test1/paltest_strchr_test1 +c_runtime/strcmp/test1/paltest_strcmp_test1 +c_runtime/strcpy/test1/paltest_strcpy_test1 +c_runtime/strcspn/test1/paltest_strcspn_test1 +c_runtime/strlen/test1/paltest_strlen_test1 +c_runtime/strncat/test1/paltest_strncat_test1 +c_runtime/strncmp/test1/paltest_strncmp_test1 +c_runtime/strncpy/test1/paltest_strncpy_test1 +c_runtime/strpbrk/test1/paltest_strpbrk_test1 +c_runtime/strrchr/test1/paltest_strrchr_test1 +c_runtime/strspn/test1/paltest_strspn_test1 +c_runtime/strstr/test1/paltest_strstr_test1 +c_runtime/strtod/test1/paltest_strtod_test1 +c_runtime/strtod/test2/paltest_strtod_test2 +c_runtime/strtok/test1/paltest_strtok_test1 +c_runtime/strtoul/test1/paltest_strtoul_test1 +c_runtime/swprintf/test1/paltest_swprintf_test1 +c_runtime/swprintf/test10/paltest_swprintf_test10 +c_runtime/swprintf/test11/paltest_swprintf_test11 +c_runtime/swprintf/test12/paltest_swprintf_test12 +c_runtime/swprintf/test13/paltest_swprintf_test13 +c_runtime/swprintf/test14/paltest_swprintf_test14 +c_runtime/swprintf/test15/paltest_swprintf_test15 +c_runtime/swprintf/test16/paltest_swprintf_test16 +c_runtime/swprintf/test17/paltest_swprintf_test17 +c_runtime/swprintf/test18/paltest_swprintf_test18 +c_runtime/swprintf/test19/paltest_swprintf_test19 +c_runtime/swprintf/test3/paltest_swprintf_test3 +c_runtime/swprintf/test4/paltest_swprintf_test4 +c_runtime/swprintf/test6/paltest_swprintf_test6 +c_runtime/swprintf/test8/paltest_swprintf_test8 +c_runtime/swprintf/test9/paltest_swprintf_test9 +c_runtime/swscanf/test1/paltest_swscanf_test1 +c_runtime/swscanf/test10/paltest_swscanf_test10 +c_runtime/swscanf/test11/paltest_swscanf_test11 +c_runtime/swscanf/test12/paltest_swscanf_test12 +c_runtime/swscanf/test13/paltest_swscanf_test13 +c_runtime/swscanf/test14/paltest_swscanf_test14 +c_runtime/swscanf/test15/paltest_swscanf_test15 +c_runtime/swscanf/test16/paltest_swscanf_test16 +c_runtime/swscanf/test17/paltest_swscanf_test17 +c_runtime/swscanf/test2/paltest_swscanf_test2 +c_runtime/swscanf/test3/paltest_swscanf_test3 +c_runtime/swscanf/test4/paltest_swscanf_test4 +c_runtime/swscanf/test5/paltest_swscanf_test5 +c_runtime/swscanf/test6/paltest_swscanf_test6 +c_runtime/swscanf/test7/paltest_swscanf_test7 +c_runtime/swscanf/test8/paltest_swscanf_test8 +c_runtime/swscanf/test9/paltest_swscanf_test9 +c_runtime/tan/test1/paltest_tan_test1 +c_runtime/tanf/test1/paltest_tanf_test1 +c_runtime/tanh/test1/paltest_tanh_test1 +c_runtime/tanhf/test1/paltest_tanhf_test1 +c_runtime/time/test1/paltest_time_test1 +c_runtime/tolower/test1/paltest_tolower_test1 +c_runtime/toupper/test1/paltest_toupper_test1 +c_runtime/towlower/test1/paltest_towlower_test1 +c_runtime/towupper/test1/paltest_towupper_test1 +c_runtime/vfprintf/test1/paltest_vfprintf_test1 +c_runtime/vfprintf/test10/paltest_vfprintf_test10 +c_runtime/vfprintf/test11/paltest_vfprintf_test11 +c_runtime/vfprintf/test12/paltest_vfprintf_test12 +c_runtime/vfprintf/test13/paltest_vfprintf_test13 +c_runtime/vfprintf/test14/paltest_vfprintf_test14 +c_runtime/vfprintf/test15/paltest_vfprintf_test15 +c_runtime/vfprintf/test16/paltest_vfprintf_test16 +c_runtime/vfprintf/test17/paltest_vfprintf_test17 +c_runtime/vfprintf/test18/paltest_vfprintf_test18 +c_runtime/vfprintf/test19/paltest_vfprintf_test19 +c_runtime/vfprintf/test2/paltest_vfprintf_test2 +c_runtime/vfprintf/test3/paltest_vfprintf_test3 +c_runtime/vfprintf/test4/paltest_vfprintf_test4 +c_runtime/vfprintf/test5/paltest_vfprintf_test5 +c_runtime/vfprintf/test6/paltest_vfprintf_test6 +c_runtime/vfprintf/test7/paltest_vfprintf_test7 +c_runtime/vfprintf/test8/paltest_vfprintf_test8 +c_runtime/vfprintf/test9/paltest_vfprintf_test9 +c_runtime/vprintf/test10/paltest_vprintf_test10 +c_runtime/vprintf/test11/paltest_vprintf_test11 +c_runtime/vprintf/test12/paltest_vprintf_test12 +c_runtime/vprintf/test13/paltest_vprintf_test13 +c_runtime/vprintf/test14/paltest_vprintf_test14 +c_runtime/vprintf/test15/paltest_vprintf_test15 +c_runtime/vprintf/test16/paltest_vprintf_test16 +c_runtime/vprintf/test17/paltest_vprintf_test17 +c_runtime/vprintf/test18/paltest_vprintf_test18 +c_runtime/vprintf/test19/paltest_vprintf_test19 +c_runtime/vprintf/test2/paltest_vprintf_test2 +c_runtime/vprintf/test3/paltest_vprintf_test3 +c_runtime/vprintf/test4/paltest_vprintf_test4 +c_runtime/vprintf/test5/paltest_vprintf_test5 +c_runtime/vprintf/test6/paltest_vprintf_test6 +c_runtime/vprintf/test7/paltest_vprintf_test7 +c_runtime/vprintf/test8/paltest_vprintf_test8 +c_runtime/vprintf/test9/paltest_vprintf_test9 +c_runtime/vsprintf/test1/paltest_vsprintf_test1 +c_runtime/vsprintf/test10/paltest_vsprintf_test10 +c_runtime/vsprintf/test11/paltest_vsprintf_test11 +c_runtime/vsprintf/test12/paltest_vsprintf_test12 +c_runtime/vsprintf/test13/paltest_vsprintf_test13 +c_runtime/vsprintf/test14/paltest_vsprintf_test14 +c_runtime/vsprintf/test15/paltest_vsprintf_test15 +c_runtime/vsprintf/test16/paltest_vsprintf_test16 +c_runtime/vsprintf/test17/paltest_vsprintf_test17 +c_runtime/vsprintf/test18/paltest_vsprintf_test18 +c_runtime/vsprintf/test19/paltest_vsprintf_test19 +c_runtime/vsprintf/test2/paltest_vsprintf_test2 +c_runtime/vsprintf/test3/paltest_vsprintf_test3 +c_runtime/vsprintf/test4/paltest_vsprintf_test4 +c_runtime/vsprintf/test6/paltest_vsprintf_test6 +c_runtime/vsprintf/test7/paltest_vsprintf_test7 +c_runtime/vsprintf/test8/paltest_vsprintf_test8 +c_runtime/vsprintf/test9/paltest_vsprintf_test9 +c_runtime/vswprintf/test1/paltest_vswprintf_test1 +c_runtime/vswprintf/test10/paltest_vswprintf_test10 +c_runtime/vswprintf/test11/paltest_vswprintf_test11 +c_runtime/vswprintf/test12/paltest_vswprintf_test12 +c_runtime/vswprintf/test13/paltest_vswprintf_test13 +c_runtime/vswprintf/test14/paltest_vswprintf_test14 +c_runtime/vswprintf/test15/paltest_vswprintf_test15 +c_runtime/vswprintf/test16/paltest_vswprintf_test16 +c_runtime/vswprintf/test17/paltest_vswprintf_test17 +c_runtime/vswprintf/test18/paltest_vswprintf_test18 +c_runtime/vswprintf/test19/paltest_vswprintf_test19 +c_runtime/vswprintf/test3/paltest_vswprintf_test3 +c_runtime/vswprintf/test4/paltest_vswprintf_test4 +c_runtime/vswprintf/test6/paltest_vswprintf_test6 +c_runtime/vswprintf/test8/paltest_vswprintf_test8 +c_runtime/vswprintf/test9/paltest_vswprintf_test9 +c_runtime/wcscat/test1/paltest_wcscat_test1 +c_runtime/wcschr/test1/paltest_wcschr_test1 +c_runtime/wcscmp/test1/paltest_wcscmp_test1 +c_runtime/wcscpy/test1/paltest_wcscpy_test1 +c_runtime/wcslen/test1/paltest_wcslen_test1 +c_runtime/wcsncmp/test1/paltest_wcsncmp_test1 +c_runtime/wcsncpy/test1/paltest_wcsncpy_test1 +c_runtime/wcspbrk/test1/paltest_wcspbrk_test1 +c_runtime/wcsrchr/test1/paltest_wcsrchr_test1 +c_runtime/wcsstr/test1/paltest_wcsstr_test1 +c_runtime/wcstod/test1/paltest_wcstod_test1 +c_runtime/wcstod/test2/paltest_wcstod_test2 +c_runtime/wcstok/test1/paltest_wcstok_test1 +c_runtime/wcstoul/test1/paltest_wcstoul_test1 +c_runtime/wcstoul/test2/paltest_wcstoul_test2 +c_runtime/wcstoul/test3/paltest_wcstoul_test3 +c_runtime/wcstoul/test4/paltest_wcstoul_test4 +c_runtime/wcstoul/test5/paltest_wcstoul_test5 +c_runtime/wcstoul/test6/paltest_wcstoul_test6 +c_runtime/wprintf/test1/paltest_wprintf_test1 +c_runtime/_alloca/test1/paltest_alloca_test1 +c_runtime/_fdopen/test1/paltest_fdopen_test1 +c_runtime/_finite/test1/paltest_finite_test1 +c_runtime/_finitef/test1/paltest_finitef_test1 +c_runtime/_isnan/test1/paltest_isnan_test1 +c_runtime/_isnanf/test1/paltest_isnanf_test1 +c_runtime/_itow/test1/paltest_itow_test1 +c_runtime/_mbsdec/test1/paltest_mbsdec_test1 +c_runtime/_mbsinc/test1/paltest_mbsinc_test1 +c_runtime/_mbsninc/test1/paltest_mbsninc_test1 +c_runtime/_putenv/test1/paltest_putenv_test1 +c_runtime/_putenv/test2/paltest_putenv_test2 +c_runtime/_putenv/test3/paltest_putenv_test3 +c_runtime/_putenv/test4/paltest_putenv_test4 +c_runtime/_rotl/test1/paltest_rotl_test1 +c_runtime/_rotr/test1/paltest_rotr_test1 +c_runtime/_snprintf_s/test1/paltest_snprintf_test1 +c_runtime/_snprintf_s/test10/paltest_snprintf_test10 +c_runtime/_snprintf_s/test11/paltest_snprintf_test11 +c_runtime/_snprintf_s/test12/paltest_snprintf_test12 +c_runtime/_snprintf_s/test13/paltest_snprintf_test13 +c_runtime/_snprintf_s/test14/paltest_snprintf_test14 +c_runtime/_snprintf_s/test15/paltest_snprintf_test15 +c_runtime/_snprintf_s/test16/paltest_snprintf_test16 +c_runtime/_snprintf_s/test17/paltest_snprintf_test17 +c_runtime/_snprintf_s/test18/paltest_snprintf_test18 +c_runtime/_snprintf_s/test19/paltest_snprintf_test19 +c_runtime/_snprintf_s/test2/paltest_snprintf_test2 +c_runtime/_snprintf_s/test3/paltest_snprintf_test3 +c_runtime/_snprintf_s/test4/paltest_snprintf_test4 +c_runtime/_snprintf_s/test6/paltest_snprintf_test6 +c_runtime/_snprintf_s/test7/paltest_snprintf_test7 +c_runtime/_snprintf_s/test8/paltest_snprintf_test8 +c_runtime/_snprintf_s/test9/paltest_snprintf_test9 +c_runtime/_snwprintf_s/test1/paltest_snwprintf_test1 +c_runtime/_snwprintf_s/test10/paltest_snwprintf_test10 +c_runtime/_snwprintf_s/test11/paltest_snwprintf_test11 +c_runtime/_snwprintf_s/test12/paltest_snwprintf_test12 +c_runtime/_snwprintf_s/test13/paltest_snwprintf_test13 +c_runtime/_snwprintf_s/test14/paltest_snwprintf_test14 +c_runtime/_snwprintf_s/test15/paltest_snwprintf_test15 +c_runtime/_snwprintf_s/test16/paltest_snwprintf_test16 +c_runtime/_snwprintf_s/test17/paltest_snwprintf_test17 +c_runtime/_snwprintf_s/test18/paltest_snwprintf_test18 +c_runtime/_snwprintf_s/test19/paltest_snwprintf_test19 +c_runtime/_snwprintf_s/test3/paltest_snwprintf_test3 +c_runtime/_snwprintf_s/test4/paltest_snwprintf_test4 +c_runtime/_snwprintf_s/test6/paltest_snwprintf_test6 +c_runtime/_snwprintf_s/test8/paltest_snwprintf_test8 +c_runtime/_snwprintf_s/test9/paltest_snwprintf_test9 +c_runtime/_stricmp/test1/paltest_stricmp_test1 +c_runtime/_strnicmp/test1/paltest_strnicmp_test1 +c_runtime/_vsnprintf_s/test1/paltest_vsnprintf_test1 +c_runtime/_vsnprintf_s/test10/paltest_vsnprintf_test10 +c_runtime/_vsnprintf_s/test11/paltest_vsnprintf_test11 +c_runtime/_vsnprintf_s/test12/paltest_vsnprintf_test12 +c_runtime/_vsnprintf_s/test13/paltest_vsnprintf_test13 +c_runtime/_vsnprintf_s/test14/paltest_vsnprintf_test14 +c_runtime/_vsnprintf_s/test15/paltest_vsnprintf_test15 +c_runtime/_vsnprintf_s/test16/paltest_vsnprintf_test16 +c_runtime/_vsnprintf_s/test17/paltest_vsnprintf_test17 +c_runtime/_vsnprintf_s/test18/paltest_vsnprintf_test18 +c_runtime/_vsnprintf_s/test19/paltest_vsnprintf_test19 +c_runtime/_vsnprintf_s/test2/paltest_vsnprintf_test2 +c_runtime/_vsnprintf_s/test3/paltest_vsnprintf_test3 +c_runtime/_vsnprintf_s/test4/paltest_vsnprintf_test4 +c_runtime/_vsnprintf_s/test6/paltest_vsnprintf_test6 +c_runtime/_vsnprintf_s/test7/paltest_vsnprintf_test7 +c_runtime/_vsnprintf_s/test8/paltest_vsnprintf_test8 +c_runtime/_vsnprintf_s/test9/paltest_vsnprintf_test9 +c_runtime/_vsnwprintf_s/test1/paltest_vsnwprintf_test1 +c_runtime/_vsnwprintf_s/test10/paltest_vsnwprintf_test10 +c_runtime/_vsnwprintf_s/test11/paltest_vsnwprintf_test11 +c_runtime/_vsnwprintf_s/test12/paltest_vsnwprintf_test12 +c_runtime/_vsnwprintf_s/test13/paltest_vsnwprintf_test13 +c_runtime/_vsnwprintf_s/test14/paltest_vsnwprintf_test14 +c_runtime/_vsnwprintf_s/test15/paltest_vsnwprintf_test15 +c_runtime/_vsnwprintf_s/test16/paltest_vsnwprintf_test16 +c_runtime/_vsnwprintf_s/test17/paltest_vsnwprintf_test17 +c_runtime/_vsnwprintf_s/test18/paltest_vsnwprintf_test18 +c_runtime/_vsnwprintf_s/test19/paltest_vsnwprintf_test19 +c_runtime/_vsnwprintf_s/test3/paltest_vsnwprintf_test3 +c_runtime/_vsnwprintf_s/test4/paltest_vsnwprintf_test4 +c_runtime/_vsnwprintf_s/test6/paltest_vsnwprintf_test6 +c_runtime/_vsnwprintf_s/test8/paltest_vsnwprintf_test8 +c_runtime/_vsnwprintf_s/test9/paltest_vsnwprintf_test9 +c_runtime/_wcsicmp/test1/paltest_wcsicmp_test1 +c_runtime/_wcslwr/test1/paltest_wcslwr_test1 +c_runtime/_wcsnicmp/test1/paltest_wcsnicmp_test1 +c_runtime/_wfopen/test1/paltest_wfopen_test1 +c_runtime/_wfopen/test2/paltest_wfopen_test2 +c_runtime/_wfopen/test3/paltest_wfopen_test3 +c_runtime/_wfopen/test4/paltest_wfopen_test4 +c_runtime/_wfopen/test5/paltest_wfopen_test5 +c_runtime/_wfopen/test6/paltest_wfopen_test6 +c_runtime/_wfopen/test7/paltest_wfopen_test7 +c_runtime/_wtoi/test1/paltest_wtoi_test1 +c_runtime/__iscsym/test1/paltest_iscsym_test1 +debug_api/OutputDebugStringW/test1/paltest_outputdebugstringw_test1 +exception_handling/RaiseException/test1/paltest_raiseexception_test1 +exception_handling/RaiseException/test2/paltest_raiseexception_test2 +exception_handling/RaiseException/test3/paltest_raiseexception_test3 +exception_handling/pal_sxs/test1/paltest_pal_sxs_test1 +filemapping_memmgt/CreateFileMappingA/test1/paltest_createfilemappinga_test1 +filemapping_memmgt/CreateFileMappingA/test3/paltest_createfilemappinga_test3 +filemapping_memmgt/CreateFileMappingA/test4/paltest_createfilemappinga_test4 +filemapping_memmgt/CreateFileMappingA/test8/paltest_createfilemappinga_test8 +filemapping_memmgt/CreateFileMappingA/test9/paltest_createfilemappinga_test9 +filemapping_memmgt/CreateFileMappingW/test1/paltest_createfilemappingw_test1 +filemapping_memmgt/CreateFileMappingW/test3/paltest_createfilemappingw_test3 +filemapping_memmgt/CreateFileMappingW/test4/paltest_createfilemappingw_test4 +filemapping_memmgt/CreateFileMappingW/test8/paltest_createfilemappingw_test8 +filemapping_memmgt/CreateFileMappingW/test9/paltest_createfilemappingw_test9 +filemapping_memmgt/FreeLibrary/test2/paltest_freelibrary_test2 +filemapping_memmgt/GetModuleFileNameA/test2/paltest_getmodulefilenamea_test2 +filemapping_memmgt/GetModuleFileNameW/test2/paltest_getmodulefilenamew_test2 +filemapping_memmgt/LocalAlloc/test1/paltest_localalloc_test1 +filemapping_memmgt/LocalFree/test1/paltest_localfree_test1 +filemapping_memmgt/LocalFree/test2/paltest_localfree_test2 +filemapping_memmgt/MapViewOfFile/test1/paltest_mapviewoffile_test1 +filemapping_memmgt/MapViewOfFile/test2/paltest_mapviewoffile_test2 +filemapping_memmgt/MapViewOfFile/test3/paltest_mapviewoffile_test3 +filemapping_memmgt/MapViewOfFile/test4/paltest_mapviewoffile_test4 +filemapping_memmgt/MapViewOfFile/test5/paltest_mapviewoffile_test5 +filemapping_memmgt/MapViewOfFile/test6/paltest_mapviewoffile_test6 +filemapping_memmgt/ProbeMemory/test1/paltest_probememory_test1 +filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/paltest_probememory_probememory_neg1 +filemapping_memmgt/UnmapViewOfFile/test1/paltest_unmapviewoffile_test1 +filemapping_memmgt/UnmapViewOfFile/test2/paltest_unmapviewoffile_test2 +filemapping_memmgt/VirtualAlloc/test1/paltest_virtualalloc_test1 +filemapping_memmgt/VirtualAlloc/test10/paltest_virtualalloc_test10 +filemapping_memmgt/VirtualAlloc/test11/paltest_virtualalloc_test11 +filemapping_memmgt/VirtualAlloc/test12/paltest_virtualalloc_test12 +filemapping_memmgt/VirtualAlloc/test13/paltest_virtualalloc_test13 +filemapping_memmgt/VirtualAlloc/test14/paltest_virtualalloc_test14 +filemapping_memmgt/VirtualAlloc/test15/paltest_virtualalloc_test15 +filemapping_memmgt/VirtualAlloc/test16/paltest_virtualalloc_test16 +filemapping_memmgt/VirtualAlloc/test17/paltest_virtualalloc_test17 +filemapping_memmgt/VirtualAlloc/test18/paltest_virtualalloc_test18 +filemapping_memmgt/VirtualAlloc/test19/paltest_virtualalloc_test19 +filemapping_memmgt/VirtualAlloc/test2/paltest_virtualalloc_test2 +filemapping_memmgt/VirtualAlloc/test20/paltest_virtualalloc_test20 +filemapping_memmgt/VirtualAlloc/test21/paltest_virtualalloc_test21 +filemapping_memmgt/VirtualAlloc/test3/paltest_virtualalloc_test3 +filemapping_memmgt/VirtualAlloc/test4/paltest_virtualalloc_test4 +filemapping_memmgt/VirtualAlloc/test5/paltest_virtualalloc_test5 +filemapping_memmgt/VirtualAlloc/test6/paltest_virtualalloc_test6 +filemapping_memmgt/VirtualAlloc/test7/paltest_virtualalloc_test7 +filemapping_memmgt/VirtualAlloc/test8/paltest_virtualalloc_test8 +filemapping_memmgt/VirtualAlloc/test9/paltest_virtualalloc_test9 +filemapping_memmgt/VirtualFree/test1/paltest_virtualfree_test1 +filemapping_memmgt/VirtualFree/test2/paltest_virtualfree_test2 +filemapping_memmgt/VirtualFree/test3/paltest_virtualfree_test3 +filemapping_memmgt/VirtualProtect/test1/paltest_virtualprotect_test1 +filemapping_memmgt/VirtualProtect/test2/paltest_virtualprotect_test2 +filemapping_memmgt/VirtualProtect/test3/paltest_virtualprotect_test3 +filemapping_memmgt/VirtualProtect/test4/paltest_virtualprotect_test4 +filemapping_memmgt/VirtualProtect/test6/paltest_virtualprotect_test6 +filemapping_memmgt/VirtualProtect/test7/paltest_virtualprotect_test7 +filemapping_memmgt/VirtualQuery/test1/paltest_virtualquery_test1 +file_io/CopyFileA/test1/paltest_copyfilea_test1 +file_io/CopyFileA/test2/paltest_copyfilea_test2 +file_io/CopyFileA/test3/paltest_copyfilea_test3 +file_io/CopyFileA/test4/paltest_copyfilea_test4 +file_io/CopyFileW/test2/paltest_copyfilew_test2 +file_io/CopyFileW/test3/paltest_copyfilew_test3 +file_io/DeleteFileA/test1/paltest_deletefilea_test1 +file_io/DeleteFileW/test1/paltest_deletefilew_test1 +file_io/errorpathnotfound/test2/paltest_errorpathnotfound_test2 +file_io/FILECanonicalizePath/paltest_filecanonicalizepath_test1 +file_io/FindClose/test1/paltest_findclose_test1 +file_io/FindFirstFileA/test1/paltest_findfirstfilea_test1 +file_io/FindFirstFileW/test1/paltest_findfirstfilew_test1 +file_io/FindNextFileA/test1/paltest_findnextfilea_test1 +file_io/FindNextFileA/test2/paltest_findnextfilea_test2 +file_io/FindNextFileW/test1/paltest_findnextfilew_test1 +file_io/FindNextFileW/test2/paltest_findnextfilew_test2 +file_io/FlushFileBuffers/test1/paltest_flushfilebuffers_test1 +file_io/GetConsoleOutputCP/test1/paltest_getconsoleoutputcp_test1 +file_io/GetCurrentDirectoryA/test1/paltest_getcurrentdirectorya_test1 +file_io/GetCurrentDirectoryW/test1/paltest_getcurrentdirectoryw_test1 +file_io/GetFileAttributesA/test1/paltest_getfileattributesa_test1 +file_io/GetFileAttributesExW/test2/paltest_getfileattributesexw_test2 +file_io/GetFileAttributesW/test1/paltest_getfileattributesw_test1 +file_io/GetFileSize/test1/paltest_getfilesize_test1 +file_io/GetFileSizeEx/test1/paltest_getfilesizeex_test1 +file_io/GetFullPathNameA/test1/paltest_getfullpathnamea_test1 +file_io/GetFullPathNameA/test3/paltest_getfullpathnamea_test3 +file_io/GetFullPathNameA/test4/paltest_getfullpathnamea_test4 +file_io/GetFullPathNameW/test1/paltest_getfullpathnamew_test1 +file_io/GetFullPathNameW/test3/paltest_getfullpathnamew_test3 +file_io/GetFullPathNameW/test4/paltest_getfullpathnamew_test4 +file_io/GetStdHandle/test2/paltest_getstdhandle_test2 +file_io/GetSystemTime/test1/paltest_getsystemtime_test1 +file_io/GetSystemTimeAsFileTime/test1/paltest_getsystemtimeasfiletime_test1 +file_io/GetTempFileNameA/test1/paltest_gettempfilenamea_test1 +file_io/GetTempFileNameA/test2/paltest_gettempfilenamea_test2 +file_io/GetTempFileNameA/test3/paltest_gettempfilenamea_test3 +file_io/GetTempFileNameW/test3/paltest_gettempfilenamew_test3 +file_io/gettemppatha/test1/paltest_gettemppatha_test1 +file_io/GetTempPathW/test1/paltest_gettemppathw_test1 +file_io/ReadFile/test2/paltest_readfile_test2 +file_io/ReadFile/test3/paltest_readfile_test3 +file_io/ReadFile/test4/paltest_readfile_test4 +file_io/SearchPathW/test1/paltest_searchpathw_test1 +file_io/SetEndOfFile/test1/paltest_setendoffile_test1 +file_io/SetEndOfFile/test2/paltest_setendoffile_test2 +file_io/SetEndOfFile/test3/paltest_setendoffile_test3 +file_io/SetEndOfFile/test4/paltest_setendoffile_test4 +file_io/SetEndOfFile/test5/paltest_setendoffile_test5 +file_io/SetFilePointer/test1/paltest_setfilepointer_test1 +file_io/SetFilePointer/test2/paltest_setfilepointer_test2 +file_io/SetFilePointer/test3/paltest_setfilepointer_test3 +file_io/SetFilePointer/test4/paltest_setfilepointer_test4 +file_io/SetFilePointer/test5/paltest_setfilepointer_test5 +file_io/SetFilePointer/test6/paltest_setfilepointer_test6 +file_io/SetFilePointer/test7/paltest_setfilepointer_test7 +file_io/WriteFile/test1/paltest_writefile_test1 +file_io/WriteFile/test3/paltest_writefile_test3 +file_io/WriteFile/test4/paltest_writefile_test4 +file_io/WriteFile/test5/paltest_writefile_test5 +loader/LoadLibraryA/test2/paltest_loadlibrarya_test2 +loader/LoadLibraryA/test3/paltest_loadlibrarya_test3 +loader/LoadLibraryA/test5/paltest_loadlibrarya_test5 +loader/LoadLibraryW/test2/paltest_loadlibraryw_test2 +loader/LoadLibraryW/test3/paltest_loadlibraryw_test3 +loader/LoadLibraryW/test5/paltest_loadlibraryw_test5 +locale_info/GetACP/test1/paltest_getacp_test1 +locale_info/GetCPInfo/test1/paltest_getcpinfo_test1 +locale_info/GetCPInfo/test3/paltest_getcpinfo_test3 +locale_info/IsDBCSLeadByte/test1/paltest_isdbcsleadbyte_test1 +locale_info/IsDBCSLeadByteEx/test1/paltest_isdbcsleadbyteex_test1 +locale_info/MultiByteToWideChar/test1/paltest_multibytetowidechar_test1 +locale_info/MultiByteToWideChar/test2/paltest_multibytetowidechar_test2 +locale_info/MultiByteToWideChar/test3/paltest_multibytetowidechar_test3 +locale_info/MultiByteToWideChar/test4/paltest_multibytetowidechar_test4 +locale_info/WideCharToMultiByte/test1/paltest_widechartomultibyte_test1 +locale_info/WideCharToMultiByte/test2/paltest_widechartomultibyte_test2 +locale_info/WideCharToMultiByte/test3/paltest_widechartomultibyte_test3 +locale_info/WideCharToMultiByte/test5/paltest_widechartomultibyte_test5 +miscellaneous/CloseHandle/test1/paltest_closehandle_test1 +miscellaneous/CloseHandle/test2/paltest_closehandle_test2 +miscellaneous/CreatePipe/test1/paltest_createpipe_test1 +miscellaneous/FlushInstructionCache/test1/paltest_flushinstructioncache_test1 +miscellaneous/FormatMessageW/test1/paltest_formatmessagew_test1 +miscellaneous/FormatMessageW/test2/paltest_formatmessagew_test2 +miscellaneous/FormatMessageW/test3/paltest_formatmessagew_test3 +miscellaneous/FreeEnvironmentStringsW/test1/paltest_freeenvironmentstringsw_test1 +miscellaneous/FreeEnvironmentStringsW/test2/paltest_freeenvironmentstringsw_test2 +miscellaneous/GetCommandLineW/test1/paltest_getcommandlinew_test1 +miscellaneous/GetEnvironmentStringsW/test1/paltest_getenvironmentstringsw_test1 +miscellaneous/GetEnvironmentVariableA/test1/paltest_getenvironmentvariablea_test1 +miscellaneous/GetEnvironmentVariableA/test2/paltest_getenvironmentvariablea_test2 +miscellaneous/GetEnvironmentVariableA/test3/paltest_getenvironmentvariablea_test3 +miscellaneous/GetEnvironmentVariableA/test4/paltest_getenvironmentvariablea_test4 +miscellaneous/GetEnvironmentVariableA/test5/paltest_getenvironmentvariablea_test5 +miscellaneous/GetEnvironmentVariableA/test6/paltest_getenvironmentvariablea_test6 +miscellaneous/GetEnvironmentVariableW/test1/paltest_getenvironmentvariablew_test1 +miscellaneous/GetEnvironmentVariableW/test2/paltest_getenvironmentvariablew_test2 +miscellaneous/GetEnvironmentVariableW/test3/paltest_getenvironmentvariablew_test3 +miscellaneous/GetEnvironmentVariableW/test4/paltest_getenvironmentvariablew_test4 +miscellaneous/GetEnvironmentVariableW/test5/paltest_getenvironmentvariablew_test5 +miscellaneous/GetEnvironmentVariableW/test6/paltest_getenvironmentvariablew_test6 +miscellaneous/GetLastError/test1/paltest_getlasterror_test1 +miscellaneous/GetSystemInfo/test1/paltest_getsysteminfo_test1 +miscellaneous/GlobalMemoryStatusEx/test1/paltest_globalmemorystatusex_test1 +miscellaneous/GetTickCount/test1/paltest_gettickcount_test1 +miscellaneous/InterlockedCompareExchange/test1/paltest_interlockedcompareexchange_test1 +miscellaneous/InterlockedCompareExchange/test2/paltest_interlockedcompareexchange_test2 +miscellaneous/InterlockedCompareExchange64/test1/paltest_interlockedcompareexchange64_test1 +miscellaneous/InterlockedCompareExchange64/test2/paltest_interlockedcompareexchange64_test2 +miscellaneous/InterlockedCompareExchangePointer/test1/paltest_interlockedcompareexchangepointer_test1 +miscellaneous/InterlockedDecrement/test1/paltest_interlockeddecrement_test1 +miscellaneous/InterlockedDecrement/test2/paltest_interlockeddecrement_test2 +miscellaneous/InterlockedDecrement64/test1/paltest_interlockeddecrement64_test1 +miscellaneous/InterlockedDecrement64/test2/paltest_interlockeddecrement64_test2 +miscellaneous/InterlockedExchange/test1/paltest_interlockedexchange_test1 +miscellaneous/InterlockedExchange64/test1/paltest_interlockedexchange64_test1 +miscellaneous/InterlockedExchangePointer/test1/paltest_interlockedexchangepointer_test1 +miscellaneous/InterlockedIncrement/test1/paltest_interlockedincrement_test1 +miscellaneous/InterlockedIncrement/test2/paltest_interlockedincrement_test2 +miscellaneous/InterlockedIncrement64/test1/paltest_interlockedincrement64_test1 +miscellaneous/InterlockedIncrement64/test2/paltest_interlockedincrement64_test2 +miscellaneous/queryperformancecounter/test1/paltest_queryperformancecounter_test1 +miscellaneous/queryperformancefrequency/test1/paltest_queryperformancefrequency_test1 +miscellaneous/SetEnvironmentVariableA/test1/paltest_setenvironmentvariablea_test1 +miscellaneous/SetEnvironmentVariableA/test2/paltest_setenvironmentvariablea_test2 +miscellaneous/SetEnvironmentVariableA/test3/paltest_setenvironmentvariablea_test3 +miscellaneous/SetEnvironmentVariableA/test4/paltest_setenvironmentvariablea_test4 +miscellaneous/SetEnvironmentVariableW/test1/paltest_setenvironmentvariablew_test1 +miscellaneous/SetEnvironmentVariableW/test2/paltest_setenvironmentvariablew_test2 +miscellaneous/SetEnvironmentVariableW/test3/paltest_setenvironmentvariablew_test3 +miscellaneous/SetEnvironmentVariableW/test4/paltest_setenvironmentvariablew_test4 +miscellaneous/SetLastError/test1/paltest_setlasterror_test1 +miscellaneous/_i64tow/test1/paltest_i64tow_test1 +pal_specific/PAL_errno/test1/paltest_pal_errno_test1 +pal_specific/PAL_Initialize_Terminate/test1/paltest_pal_initialize_terminate_test1 +pal_specific/PAL_Initialize_Terminate/test2/paltest_pal_initialize_terminate_test2 +samples/test1/paltest_samples_test1 +threading/CreateEventA/test1/paltest_createeventa_test1 +threading/CreateEventA/test2/paltest_createeventa_test2 +threading/CreateEventW/test1/paltest_createeventw_test1 +threading/CreateEventW/test2/paltest_createeventw_test2 +threading/CreateMutexA_ReleaseMutex/test1/paltest_createmutexa_releasemutex_test1 +threading/CreateMutexW_ReleaseMutex/test1/paltest_createmutexw_releasemutex_test1 +threading/CreateProcessA/test1/paltest_createprocessa_test1 +threading/CreateProcessA/test2/paltest_createprocessa_test2 +threading/CreateProcessW/test1/paltest_createprocessw_test1 +threading/CreateProcessW/test2/paltest_createprocessw_test2 +threading/CreateSemaphoreA_ReleaseSemaphore/test1/paltest_createsemaphorea_releasesemaphore_test1 +threading/CreateSemaphoreA_ReleaseSemaphore/test2/paltest_createsemaphorea_releasesemaphore_test2 +threading/CreateSemaphoreW_ReleaseSemaphore/test1/paltest_createsemaphorew_releasesemaphore_test1 +threading/CreateSemaphoreW_ReleaseSemaphore/test2/paltest_createsemaphorew_releasesemaphore_test2 +threading/CreateThread/test1/paltest_createthread_test1 +threading/CreateThread/test3/paltest_createthread_test3 +threading/CriticalSectionFunctions/test1/paltest_criticalsectionfunctions_test1 +threading/CriticalSectionFunctions/test2/paltest_criticalsectionfunctions_test2 +threading/CriticalSectionFunctions/test3/paltest_criticalsectionfunctions_test3 +threading/CriticalSectionFunctions/test4/paltest_criticalsectionfunctions_test4 +threading/CriticalSectionFunctions/test7/paltest_criticalsectionfunctions_test7 +threading/CriticalSectionFunctions/test8/paltest_criticalsectionfunctions_test8 +threading/DuplicateHandle/test10/paltest_duplicatehandle_test10 +threading/DuplicateHandle/test2/paltest_duplicatehandle_test2 +threading/DuplicateHandle/test4/paltest_duplicatehandle_test4 +threading/DuplicateHandle/test5/paltest_duplicatehandle_test5 +threading/DuplicateHandle/test6/paltest_duplicatehandle_test6 +threading/DuplicateHandle/test7/paltest_duplicatehandle_test7 +threading/DuplicateHandle/test8/paltest_duplicatehandle_test8 +threading/ExitProcess/test1/paltest_exitprocess_test1 +threading/ExitProcess/test2/paltest_exitprocess_test2 +threading/ExitProcess/test3/paltest_exitprocess_test3 +threading/ExitThread/test1/paltest_exitthread_test1 +threading/GetCurrentProcessId/test1/paltest_getcurrentprocessid_test1 +threading/GetCurrentThread/test1/paltest_getcurrentthread_test1 +threading/GetCurrentThread/test2/paltest_getcurrentthread_test2 +threading/GetProcessTimes/test2/paltest_getprocesstimes_test2 +threading/GetThreadTimes/test1/paltest_getthreadtimes_test1 +threading/NamedMutex/test1/paltest_namedmutex_test1 +threading/QueryThreadCycleTime/test1/paltest_querythreadcycletime_test1 +threading/QueueUserAPC/test2/paltest_queueuserapc_test2 +threading/QueueUserAPC/test3/paltest_queueuserapc_test3 +threading/QueueUserAPC/test4/paltest_queueuserapc_test4 +threading/QueueUserAPC/test5/paltest_queueuserapc_test5 +threading/QueueUserAPC/test6/paltest_queueuserapc_test6 +threading/QueueUserAPC/test7/paltest_queueuserapc_test7 +threading/ReleaseMutex/test3/paltest_releasemutex_test3 +threading/releasesemaphore/test1/paltest_releasesemaphore_test1 +threading/ResetEvent/test1/paltest_resetevent_test1 +threading/ResetEvent/test2/paltest_resetevent_test2 +threading/ResetEvent/test3/paltest_resetevent_test3 +threading/ResetEvent/test4/paltest_resetevent_test4 +threading/ResumeThread/test1/paltest_resumethread_test1 +threading/SetErrorMode/test1/paltest_seterrormode_test1 +threading/SetEvent/test1/paltest_setevent_test1 +threading/SetEvent/test2/paltest_setevent_test2 +threading/SetEvent/test3/paltest_setevent_test3 +threading/SetEvent/test4/paltest_setevent_test4 +threading/SwitchToThread/test1/paltest_switchtothread_test1 +threading/ThreadPriority/test1/paltest_threadpriority_test1 +threading/WaitForMultipleObjects/test1/paltest_waitformultipleobjects_test1 +threading/WaitForMultipleObjectsEx/test1/paltest_waitformultipleobjectsex_test1 +threading/WaitForMultipleObjectsEx/test2/paltest_waitformultipleobjectsex_test2 +threading/WaitForMultipleObjectsEx/test3/paltest_waitformultipleobjectsex_test3 +threading/WaitForMultipleObjectsEx/test4/paltest_waitformultipleobjectsex_test4 +threading/WaitForSingleObject/test1/paltest_waitforsingleobject_test1 +threading/WaitForSingleObject/WFSOExMutexTest/paltest_waitforsingleobject_wfsoexmutextest +threading/WaitForSingleObject/WFSOExSemaphoreTest/paltest_waitforsingleobject_wfsoexsemaphoretest +threading/WaitForSingleObject/WFSOExThreadTest/paltest_waitforsingleobject_wfsoexthreadtest +threading/WaitForSingleObject/WFSOMutexTest/paltest_waitforsingleobject_wfsomutextest +threading/WaitForSingleObject/WFSOSemaphoreTest/paltest_waitforsingleobject_wfsosemaphoretest +threading/WaitForSingleObject/WFSOThreadTest/paltest_waitforsingleobject_wfsothreadtest +threading/YieldProcessor/test1/paltest_yieldprocessor_test1 +eventprovider/eventprovidertest diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt new file mode 100644 index 0000000..aafef3b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt @@ -0,0 +1,163 @@ +This is a list of failing PAL tests that need to be reviewed because. +They should either be fixed or deleted if they are no longer applicable. + +c_runtime/exit/test2/paltest_exit_test2 +c_runtime/ferror/test1/paltest_ferror_test1 +c_runtime/ferror/test2/paltest_ferror_test2 +c_runtime/fputs/test2/paltest_fputs_test2 +c_runtime/fread/test1/paltest_fread_test1 +c_runtime/fread/test2/paltest_fread_test2 +c_runtime/fread/test3/paltest_fread_test3 +c_runtime/ftell/test1/paltest_ftell_test1 +c_runtime/fwprintf/test19/paltest_fwprintf_test19 +c_runtime/fwprintf/test2/paltest_fwprintf_test2 +c_runtime/fwprintf/test7/paltest_fwprintf_test7 +c_runtime/iswprint/test1/paltest_iswprint_test1 +c_runtime/swprintf/test2/paltest_swprintf_test2 +c_runtime/swprintf/test7/paltest_swprintf_test7 +c_runtime/vprintf/test1/paltest_vprintf_test1 +c_runtime/vswprintf/test2/paltest_vswprintf_test2 +c_runtime/vswprintf/test7/paltest_vswprintf_test7 +c_runtime/wprintf/test2/paltest_wprintf_test2 +c_runtime/_gcvt/test1/paltest_gcvt_test1 +c_runtime/_gcvt/test2/paltest_gcvt_test2 +c_runtime/_getw/test1/paltest_getw_test1 +c_runtime/_snwprintf_s/test2/paltest_snwprintf_test2 +c_runtime/_snwprintf_s/test7/paltest_snwprintf_test7 +c_runtime/_vsnwprintf_s/test2/paltest_vsnwprintf_test2 +c_runtime/_vsnwprintf_s/test7/paltest_vsnwprintf_test7 +debug_api/DebugBreak/test1/paltest_debugbreak_test1 +debug_api/OutputDebugStringA/test1/paltest_outputdebugstringa_test1 +debug_api/WriteProcessMemory/test1/paltest_writeprocessmemory_test1 +debug_api/WriteProcessMemory/test3/paltest_writeprocessmemory_test3 +debug_api/WriteProcessMemory/test4/paltest_writeprocessmemory_test4 +exception_handling/pal_except/test1/paltest_pal_except_test1 +exception_handling/pal_except/test2/paltest_pal_except_test2 +exception_handling/pal_except/test3/paltest_pal_except_test3 +exception_handling/pal_except/test4/paltest_pal_except_test4 +exception_handling/pal_except/test5/paltest_pal_except_test5 +exception_handling/pal_except/test6/paltest_pal_except_test6 +exception_handling/pal_except/test7/paltest_pal_except_test7 +exception_handling/PAL_EXCEPT_FILTER/test1/paltest_pal_except_filter_test1 +exception_handling/PAL_EXCEPT_FILTER/test2/paltest_pal_except_filter_test2 +exception_handling/PAL_EXCEPT_FILTER/test3/paltest_pal_except_filter_test3 +exception_handling/PAL_EXCEPT_FILTER_EX/test1/paltest_pal_except_filter_ex_test1 +exception_handling/PAL_EXCEPT_FILTER_EX/test2/paltest_pal_except_filter_ex_test2 +exception_handling/PAL_EXCEPT_FILTER_EX/test3/paltest_pal_except_filter_ex_test3 +exception_handling/pal_finally/test1/paltest_pal_finally_test1 +exception_handling/PAL_GetBottommostRegistration/test1/paltest_pal_getbottommostregistration_test1 +exception_handling/PAL_GetBottommostRegistration/test2/paltest_pal_getbottommostregistration_test2 +exception_handling/PAL_TRY_EXCEPT/test1/paltest_pal_try_except_test1 +exception_handling/PAL_TRY_EXCEPT/test2/paltest_pal_try_except_test2 +exception_handling/PAL_TRY_EXCEPT_EX/test1/paltest_pal_try_except_ex_test1 +exception_handling/PAL_TRY_EXCEPT_EX/test2/paltest_pal_try_except_ex_test2 +exception_handling/PAL_TRY_EXCEPT_EX/test3/paltest_pal_try_except_ex_test3 +exception_handling/PAL_TRY_LEAVE_FINALLY/test1/paltest_pal_try_leave_finally_test1 +filemapping_memmgt/CreateFileMappingA/test5/paltest_createfilemappinga_test5 +filemapping_memmgt/CreateFileMappingA/test6/paltest_createfilemappinga_test6 +filemapping_memmgt/CreateFileMappingA/test7/paltest_createfilemappinga_test7 +filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/paltest_createfilemappingw_createfilemapping_neg1 +filemapping_memmgt/CreateFileMappingW/test2/paltest_createfilemappingw_test2 +filemapping_memmgt/CreateFileMappingW/test5/paltest_createfilemappingw_test5 +filemapping_memmgt/CreateFileMappingW/test6/paltest_createfilemappingw_test6 +filemapping_memmgt/CreateFileMappingW/test7/paltest_createfilemappingw_test7 +filemapping_memmgt/FreeLibrary/test1/paltest_freelibrary_test1 +filemapping_memmgt/FreeLibraryAndExitThread/test1/paltest_freelibraryandexitthread_test1 +filemapping_memmgt/GetModuleFileNameA/test1/paltest_getmodulefilenamea_test1 +filemapping_memmgt/GetModuleFileNameW/test1/paltest_getmodulefilenamew_test1 +filemapping_memmgt/GetProcAddress/test1/paltest_getprocaddress_test1 +filemapping_memmgt/GetProcAddress/test2/paltest_getprocaddress_test2 +filemapping_memmgt/OpenFileMappingA/test1/paltest_openfilemappinga_test1 +filemapping_memmgt/OpenFileMappingA/test2/paltest_openfilemappinga_test2 +filemapping_memmgt/OpenFileMappingA/test3/paltest_openfilemappinga_test3 +filemapping_memmgt/OpenFileMappingW/test1/paltest_openfilemappingw_test1 +filemapping_memmgt/OpenFileMappingW/test2/paltest_openfilemappingw_test2 +filemapping_memmgt/OpenFileMappingW/test3/paltest_openfilemappingw_test3 +filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/paltest_readprocessmemory_readprocessmemory_neg1 +filemapping_memmgt/ReadProcessMemory/test1/paltest_readprocessmemory_test1 +filemapping_memmgt/ReadProcessMemory/test2/paltest_readprocessmemory_test2 +file_io/CopyFileW/test1/paltest_copyfilew_test1 +file_io/CreateFileA/test1/paltest_createfilea_test1 +file_io/CreateFileW/test1/paltest_createfilew_test1 +file_io/errorpathnotfound/test1/paltest_errorpathnotfound_test1 +file_io/GetFileAttributesExW/test1/paltest_getfileattributesexw_test1 +file_io/GetFullPathNameA/test2/paltest_getfullpathnamea_test2 +file_io/GetFullPathNameW/test2/paltest_getfullpathnamew_test2 +file_io/GetStdHandle/test1/paltest_getstdhandle_test1 +file_io/GetTempFileNameW/test1/paltest_gettempfilenamew_test1 +file_io/GetTempFileNameW/test2/paltest_gettempfilenamew_test2 +file_io/gettemppatha/test1/paltest_gettemppatha_test1 +file_io/GetTempPathW/test1/paltest_gettemppathw_test1 +file_io/MoveFileExA/test1/paltest_movefileexa_test1 +file_io/MoveFileExW/test1/paltest_movefileexw_test1 +file_io/ReadFile/test1/paltest_readfile_test1 +file_io/WriteFile/test2/paltest_writefile_test2 +loader/LoadLibraryA/test1/paltest_loadlibrarya_test1 +loader/LoadLibraryA/test6/paltest_loadlibrarya_test6 +loader/LoadLibraryA/test7/paltest_loadlibrarya_test7 +loader/LoadLibraryA/test8/paltest_loadlibrarya_test8 +loader/LoadLibraryW/test1/paltest_loadlibraryw_test1 +locale_info/CompareStringA/test1/paltest_comparestringa_test1 +locale_info/CompareStringW/test1/paltest_comparestringw_test1 +locale_info/GetCPInfo/test2/paltest_getcpinfo_test2 +locale_info/GetLocaleInfoW/test1/paltest_getlocaleinfow_test1 +locale_info/GetLocaleInfoW/test2/paltest_getlocaleinfow_test2 +locale_info/GetStringTypeExW/test1/paltest_getstringtypeexw_test1 +locale_info/GetStringTypeExW/test2/paltest_getstringtypeexw_test2 +locale_info/WideCharToMultiByte/test4/paltest_widechartomultibyte_test4 +miscellaneous/FormatMessageW/test4/paltest_formatmessagew_test4 +miscellaneous/FormatMessageW/test5/paltest_formatmessagew_test5 +miscellaneous/FormatMessageW/test6/paltest_formatmessagew_test6 +miscellaneous/InterLockedExchangeAdd/test1/paltest_interlockedexchangeadd_test1 +miscellaneous/IsBadCodePtr/test1/paltest_isbadcodeptr_test1 +miscellaneous/IsBadReadPtr/test1/paltest_isbadreadptr_test1 +miscellaneous/IsBadWritePtr/test1/paltest_isbadwriteptr_test1 +miscellaneous/IsBadWritePtr/test2/paltest_isbadwriteptr_test2 +miscellaneous/IsBadWritePtr/test3/paltest_isbadwriteptr_test3 +miscellaneous/MessageBoxW/test1/paltest_messageboxw_test1 +miscellaneous/MessageBoxW/test2/paltest_messageboxw_test2 +miscellaneous/wsprintfW/test2/paltest_wsprintfw_test2 +miscellaneous/wsprintfW/test7/paltest_wsprintfw_test7 +pal_specific/PAL_GetPALDirectoryW/test1/paltest_pal_getpaldirectoryw_test1 +pal_specific/PAL_GetUserTempDirectoryW/test1/paltest_pal_getusertempdirectoryw_test1 +pal_specific/PAL_get_stderr/test1/paltest_pal_get_stderr_test1 +pal_specific/PAL_get_stdin/test1/paltest_pal_get_stdin_test1 +pal_specific/PAL_get_stdout/test1/paltest_pal_get_stdout_test1 +pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/paltest_pal_registerlibraryw_unregisterlibraryw_test1 +samples/test2/paltest_samples_test2 +threading/CreateEventA/test3/paltest_createeventa_test3 +threading/CreateEventW/test3/paltest_createeventw_test3 +threading/CreateMutexA_ReleaseMutex/test2/paltest_createmutexa_releasemutex_test2 +threading/CreateMutexW_ReleaseMutex/test2/paltest_createmutexw_releasemutex_test2 +threading/CreateSemaphoreA_ReleaseSemaphore/test3/paltest_createsemaphorea_releasesemaphore_test3 +threading/CreateSemaphoreW_ReleaseSemaphore/test3/paltest_createsemaphorew_releasesemaphore_test3 +threading/CreateThread/test2/paltest_createthread_test2 +threading/CriticalSectionFunctions/test5/paltest_criticalsectionfunctions_test5 +threading/CriticalSectionFunctions/test6/paltest_criticalsectionfunctions_test6 +threading/DuplicateHandle/test1/paltest_duplicatehandle_test1 +threading/DuplicateHandle/test11/paltest_duplicatehandle_test11 +threading/DuplicateHandle/test12/paltest_duplicatehandle_test12 +threading/DuplicateHandle/test3/paltest_duplicatehandle_test3 +threading/DuplicateHandle/test9/paltest_duplicatehandle_test9 +threading/ExitThread/test2/paltest_exitthread_test2 +threading/GetCurrentProcess/test1/paltest_getcurrentprocess_test1 +threading/GetCurrentThreadId/test1/paltest_getcurrentthreadid_test1 +threading/GetExitCodeProcess/test1/paltest_getexitcodeprocess_test1 +threading/OpenEventW/test1/paltest_openeventw_test1 +threading/OpenEventW/test2/paltest_openeventw_test2 +threading/OpenEventW/test3/paltest_openeventw_test3 +threading/OpenEventW/test4/paltest_openeventw_test4 +threading/OpenEventW/test5/paltest_openeventw_test5 +threading/OpenProcess/test1/paltest_openprocess_test1 +threading/QueueUserAPC/test1/paltest_queueuserapc_test1 +threading/setthreadcontext/test1/paltest_setthreadcontext_test1 +threading/Sleep/test1/paltest_sleep_test1 +threading/SleepEx/test1/paltest_sleepex_test1 +threading/SleepEx/test2/paltest_sleepex_test2 +threading/SuspendThread/test2/paltest_suspendthread_test2 +threading/SuspendThread/test3/paltest_suspendthread_test3 +threading/TerminateProcess/test1/paltest_terminateprocess_test1 +threading/TLS/test6_optimizedtls/paltest_tls_test6_optimizedtls +threading/WaitForMultipleObjectsEx/test5/paltest_waitformultipleobjectsex_test5 +threading/WaitForMultipleObjectsEx/test6/paltest_waitformultipleobjectsex_test6 +threading/WaitForSingleObject/WFSOProcessTest/paltest_waitforsingleobject_wfsoprocesstest diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/runpaltests.sh b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/runpaltests.sh new file mode 100644 index 0000000..cc8ffd6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/runpaltests.sh @@ -0,0 +1,213 @@ +#!/usr/bin/env bash +# +# This script executes PAL tests from the specified build location. +# + +if [ $# -lt 1 -o $# -gt 3 ] +then + echo "Usage..." + echo "runpaltests.sh []" + echo + echo "For example:" + echo "runpaltests.sh /projectk/build/debug" + echo + exit 1 +fi + +echo +echo "***** Testing PAL *****" +echo + +# Store the location of the root of build directory +BUILD_ROOD_DIR=$1 +# Create path to the compiled PAL tets in the build directory +PAL_TEST_BUILD=$BUILD_ROOD_DIR/src/pal/tests/palsuite +echo Running PAL tests from $PAL_TEST_BUILD + +# Create absolute path to the file that contains a list of PAL tests to execute. +# This file is located next to this script in the source tree +RELATIVE_PATH_TO_PAL_TESTS=$0 +# Remove the name of this script from the path +RELATIVE_PATH_TO_PAL_TESTS=${RELATIVE_PATH_TO_PAL_TESTS%/*.*} +# Change current directory to the location of this script +cd $RELATIVE_PATH_TO_PAL_TESTS +# Environment variable PWD contains absolute path to the current folder +# so use it to create absolute path to the file with a list of tests. +PAL_TEST_LIST=$PWD/paltestlist.txt +# Change current directory back to the original location +cd $OLDPWD +echo The list of PAL tests to run will be read from $PAL_TEST_LIST + +# Create the test output root directory +mkdir -p /tmp/PalTestOutput +if [ ! -d /tmp/PalTestOutput ]; then + rm -f -r /tmp/PalTestOutput + mkdir -p /tmp/PalTestOutput +fi + +# Determine the folder to use for PAL test output during the run, and the folder where output files were requested to be copied. +# First check if the output folder was passed as a parameter to the script. It is supposed be the second parameter so check if +# we have more than 1 argument. +PAL_TEST_OUTPUT_DIR=/tmp/PalTestOutput/default +if [ $# -gt 1 ] +then + COPY_TO_TEST_OUTPUT_DIR=$2 +else + COPY_TO_TEST_OUTPUT_DIR=$PAL_TEST_OUTPUT_DIR +fi + +# Determine the folder to use for PAL test output during the run +if [ "$COPY_TO_TEST_OUTPUT_DIR" != "$PAL_TEST_OUTPUT_DIR" ]; then + # Output files were requested to be copied to a specific folder. In this mode, we need to support parallel runs of PAL tests + # on the same machine. Make a unique temp folder for working output inside /tmp/PalTestOutput. + PAL_TEST_OUTPUT_DIR=$(mktemp -d /tmp/PalTestOutput/tmp.XXXXXXXX) +fi + +echo PAL tests will store their temporary files and output in $PAL_TEST_OUTPUT_DIR. +if [ "$COPY_TO_TEST_OUTPUT_DIR" != "$PAL_TEST_OUTPUT_DIR" ]; then + echo Output files will be copied to $COPY_TO_TEST_OUTPUT_DIR at the end. +fi + +# Path to a file that will contains a list PAL tests that failed during the test run. +PAL_FAILED_TEST_LIST=$PAL_TEST_OUTPUT_DIR/palfailedtests.txt + +# Path to a file that will contain the XUnit style test result for Jenkins +# We use a temp file as at the end we have to prepend with the number of tests +# and failures +PAL_XUNIT_TEST_LIST_TMP=$PAL_TEST_OUTPUT_DIR/pal_tests.xml.tmp +PAL_XUNIT_TEST_LIST=$PAL_TEST_OUTPUT_DIR/pal_tests.xml + +# Capturing stdout and stderr +PAL_OUT_FILE=$PAL_TEST_OUTPUT_DIR/pal_test_out + +# Remove and recreate the temporary test output directory, and the directory where output files were requested to be copied. +if [ "$COPY_TO_TEST_OUTPUT_DIR" == "$PAL_TEST_OUTPUT_DIR" ]; then + if [ -e $PAL_TEST_OUTPUT_DIR ]; then + rm -f -r $PAL_TEST_OUTPUT_DIR + fi + mkdir -p $PAL_TEST_OUTPUT_DIR +else + # No need to recreate the temp output directory, as mktemp would have created a unique empty directory + if [ -e $COPY_TO_TEST_OUTPUT_DIR ]; then + rm -f -r $COPY_TO_TEST_OUTPUT_DIR + fi + mkdir -p $COPY_TO_TEST_OUTPUT_DIR + if [ ! -d $COPY_TO_TEST_OUTPUT_DIR ]; then + echo Failed to create $COPY_TO_TEST_OUTPUT_DIR. + COPY_TO_TEST_OUTPUT_DIR=$PAL_TEST_OUTPUT_DIR + fi +fi +cd $PAL_TEST_OUTPUT_DIR + +echo +echo "Running tests..." +echo + +NUMBER_OF_PASSED_TESTS=0 +NUMBER_OF_FAILED_TESTS=0 + +# Read PAL tests names from the $PAL_TEST_LIST file and run them one by one. +while read TEST_NAME +do + # Remove stdout/stderr file if it exists + rm -f $PAL_OUT_FILE + + # Create a folder with the test name, and use that as the working directory for the test. Many PAL tests don't clean up after + # themselves and may leave files/directories around, but even to handle test failures that result in a dirty state, run each + # test in its own folder. + TEST_WORKING_DIR=$(basename $TEST_NAME) + if [ -e $TEST_WORKING_DIR ]; then + rm -f -r $TEST_WORKING_DIR + fi + mkdir $TEST_WORKING_DIR + cd $TEST_WORKING_DIR + + # Create path to a test executable to run + TEST_COMMAND="$PAL_TEST_BUILD/$TEST_NAME" + echo -n . + # Redirect to temp file + $TEST_COMMAND 2>&1 | tee ${PAL_OUT_FILE} ; ( exit ${PIPESTATUS[0]} ) + + # Get exit code of the test process. + TEST_EXIT_CODE=$? + + # Change back to the output directory, and remove the test's working directory if it's empty + cd $PAL_TEST_OUTPUT_DIR + rmdir $TEST_WORKING_DIR 2>/dev/null + + TEST_XUNIT_NAME=$(dirname $TEST_NAME) + TEST_XUNIT_CLASSNAME=$(dirname $TEST_XUNIT_NAME) + TEST_XUNIT_NAME=${TEST_XUNIT_NAME#*/} + TEST_XUNIT_NAME=${TEST_XUNIT_NAME#*/} + + TEST_XUNIT_NAME=$(echo $TEST_XUNIT_NAME | tr / .) + TEST_XUNIT_CLASSNAME=$(echo $TEST_XUNIT_CLASSNAME | tr / .) + + echo -n "> $PAL_XUNIT_TEST_LIST_TMP + + # If the exit code is 0 then the test passed, otherwise record a failure. + if [ "$TEST_EXIT_CODE" -eq "0" ]; then + NUMBER_OF_PASSED_TESTS=$(($NUMBER_OF_PASSED_TESTS + 1)) + echo "Pass\" />" >> $PAL_XUNIT_TEST_LIST_TMP + else + echo "Fail\" >" >> $PAL_XUNIT_TEST_LIST_TMP + echo "" >> $PAL_XUNIT_TEST_LIST_TMP + echo "" >> $PAL_XUNIT_TEST_LIST_TMP + echo "" >> $PAL_XUNIT_TEST_LIST_TMP + echo "" >> $PAL_XUNIT_TEST_LIST_TMP + FAILED_TEST="$TEST_NAME. Exit code: $TEST_EXIT_CODE" + echo + echo FAILED: $FAILED_TEST + echo + + # Store the name of the failed test in the list of failed tests. + echo $FAILED_TEST >> $PAL_FAILED_TEST_LIST + + NUMBER_OF_FAILED_TESTS=$(($NUMBER_OF_FAILED_TESTS + 1)) + fi +done < $PAL_TEST_LIST + +# We are done running tests. +echo +echo Finished running PAL tests. +echo + +# Finish XUnit file, output to finished file with the number of failures, tests etc +NUMBER_OF_TESTS=$(($NUMBER_OF_PASSED_TESTS + $NUMBER_OF_FAILED_TESTS)) + +XUNIT_SUFFIX="\n" +XUNIT_SUFFIX+="\n" +XUNIT_SUFFIX+="" + +XUNIT_PREFIX="\n" +XUNIT_PREFIX+="\n" +XUNIT_PREFIX+="\n" +XUNIT_PREFIX+="" + +printf "$XUNIT_SUFFIX" >> $PAL_XUNIT_TEST_LIST_TMP +printf "$XUNIT_PREFIX" | cat - $PAL_XUNIT_TEST_LIST_TMP > $PAL_XUNIT_TEST_LIST + +# If there were tests failures then print the list of failed tests +if [ $NUMBER_OF_FAILED_TESTS -gt "0" ]; then + echo "The following test(s) failed:" + while read FAILED_TEST_NAME + do + echo $FAILED_TEST_NAME + done < $PAL_FAILED_TEST_LIST + echo +fi + +echo PAL Test Results: +echo " Passed: $NUMBER_OF_PASSED_TESTS" +echo " Failed: $NUMBER_OF_FAILED_TESTS" +echo + +if [ "$COPY_TO_TEST_OUTPUT_DIR" != "$PAL_TEST_OUTPUT_DIR" ]; then + mv -f $PAL_TEST_OUTPUT_DIR/* $COPY_TO_TEST_OUTPUT_DIR/ + rm -f -r $PAL_TEST_OUTPUT_DIR + echo Copied PAL test output files to $COPY_TO_TEST_OUTPUT_DIR. +fi + +# Set exit code to be equal to the number PAL tests that have failed. +# Exit code 0 indicates success. +exit $NUMBER_OF_FAILED_TESTS diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test1/CMakeLists.txt new file mode 100644 index 0000000..9841a23 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_samples_test1 + ${SOURCES} +) + +add_dependencies(paltest_samples_test1 coreclrpal) + +target_link_libraries(paltest_samples_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test1/test.cpp new file mode 100644 index 0000000..2eed6f6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test1/test.cpp @@ -0,0 +1,41 @@ +// 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. + +/*============================================================================ +** +** Source: test.c +** +** Purpose: This test is an example of the basic structure of a PAL test +** suite test case. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + /* Initialize the PAL. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + Trace("\nTest #1...\n"); + +#ifdef WIN32 + Trace("\nWe are testing under Win32 environment.\n"); +#else + Trace("\nWe are testing under Non-Win32 environment.\n"); +#endif + + Trace("\nThis test has passed.\n"); + + /* Shutdown the PAL. + */ + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test1/testinfo.dat new file mode 100644 index 0000000..0459d24 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Samples +Function = sample +Name = Sample Test #1 +TYPE = DEFAULT +EXE1 = test +Description +=This is a sample test case. It will always pass. + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test2/CMakeLists.txt new file mode 100644 index 0000000..38d447a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_samples_test2 + ${SOURCES} +) + +add_dependencies(paltest_samples_test2 coreclrpal) + +target_link_libraries(paltest_samples_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test2/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test2/test.cpp new file mode 100644 index 0000000..53d4158 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test2/test.cpp @@ -0,0 +1,48 @@ +// 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. + +/*===================================================================== +** +** Source: test.c +** +** Purpose: A sample to show how to structure a test case. +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + int exampleInt = 9; + + /* Initialize the PAL. + */ + if(0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + Trace("\nTest #2...\n"); + +#ifdef WIN32 + Trace("\nWe are testing under Win32 environment.\n"); +#else + Trace("\nWe are testing under Non-Win32 environment.\n"); +#endif + + if (exampleInt == 9) + { + Fail("This is an example to how to code a failure. " + "This failure was caused by exampleInt equalling %d\n", + exampleInt); + } + + /* Shutdown the PAL. + */ + PAL_Terminate(); + + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test2/testinfo.dat new file mode 100644 index 0000000..eb6e38d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/samples/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = Samples +Function = sample +Name = Sample Test #2 +TYPE = DEFAULT +EXE1 = test +Description +=This is a sample test case. It will always fail. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/smoketest.script b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/smoketest.script new file mode 100644 index 0000000..19bb8cd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/smoketest.script @@ -0,0 +1,100 @@ +#!/bin/csh + +# Smoketest v1.1 +# +# This smoketest is intended to stress briefly every part of PAL, +# and is to be run before submitting or approving a patch, to ensure +# that it is not breaking the PAL. It should run in about 30 seconds +# +# Installation: +# smoketest.dat and this script should be placed in xxx/xport/tests/palsuite. +# Execute smoketest with the location of rotor as a commandline arg +# with no trailing +# +# Be sure that xrun and testharness are built. (in xport/tests/harness, +# cd test_harness, gmake, cd ../xrun, gmake) +# +if ($#argv != 1) then + echo smoketest v1.1 + echo " " + echo Usage: smoketest location-of-xport + echo " " + echo "where location-of-xport is the location of your xport checkout" + echo "ie. xxxx/xport (with NO TRAILING /)" + echo " (For example: smoketest ~/xport)" + exit +endif + +setenv ROTOR_DIR $argv[1] +setenv TH_BIN $argv[1]/tests/harness/test_harness/testharness +setenv TH_CONFIG $argv[1]/tests/palsuite/smoketest.dat +setenv TH_RESULTS $argv[1]/tests/palsuite/smoketest.log +setenv TH_DIR $argv[1]/tests/palsuite +setenv TH_XRUN $argv[1]/tests/harness/xrun/xrun +setenv PAL_DBG_CHANNELS "" + + +# Let's check to make sure that the developer has built xrun +# and testharness for us and/or that the variables above were set +# properly +if ((-e $TH_BIN) != 1) then + echo $TH_BIN was not found. + echo Did you forget to build the test harness\? + exit +endif + +if ((-e $TH_XRUN) != 1) then + echo $TH_XRUN was not found. + echo Did you forget to build Xrun\? + exit +endif + + +$TH_BIN 2>&1 /dev/null + + +set FAILING = `grep EXEC,FAIL $TH_RESULTS | wc -l` +set PASSING = `grep EXEC,PASS $TH_RESULTS | wc -l` +set DISABLED = `grep EXEC,DISABLED $TH_RESULTS | wc -l` +set TOTAL_TESTS = `grep BUILD $TH_RESULTS | wc -l` +set OTHERS = $TOTAL_TESTS +@ OTHERS = ((($OTHERS - $FAILING) - $PASSING ) - $DISABLED) + +clear +echo Summary: +echo ======== +echo Total Number of Tests: $TOTAL_TESTS +echo Total Passing: $PASSING / $TOTAL_TESTS +echo Total Failing: $FAILING / $TOTAL_TESTS +echo Total Disabled: $DISABLED / $TOTAL_TESTS +echo Other Problems: $OTHERS / $TOTAL_TESTS + +if ($FAILING > 0) then + echo " " + echo "*******************************************" + echo "*******************************************" + echo "*******************************************" + echo "*******************************************" + echo "WARNING WARNING WARNING WARNING WARNING" + echo " " + + if ($FAILING > 1) then + echo There are now $FAILING tests failing. + else + echo There is now 1 test failing. + endif + + echo Please run: + echo " " + echo grep \"EXEC,FAIL\" $TH_RESULTS + echo " " + echo to figure out what is going wrong. + echo "*******************************************" + echo "*******************************************" + echo "*******************************************" + echo "*******************************************" +else + echo " " + echo "Smoketest executed OK." + rm $TH_RESULTS +endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/tests-manual.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/tests-manual.dat new file mode 100644 index 0000000..402e819 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/tests-manual.dat @@ -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. + +c_runtime/exit/test2,1 +pal_specific/pal_get_stderr/test1,1 +pal_specific/pal_get_stdin/test1,1 +pal_specific/pal_get_stdout/test1,1 +threading/setconsolectrlhandler/test1,1 +threading/setconsolectrlhandler/test2,1 +threading/setconsolectrlhandler/test3,1 +threading/setconsolectrlhandler/test4,1 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CMakeLists.txt new file mode 100644 index 0000000..fdb71b4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CMakeLists.txt @@ -0,0 +1,42 @@ +add_subdirectory(CreateEventA) +add_subdirectory(CreateEventW) +add_subdirectory(CreateMutexA_ReleaseMutex) +add_subdirectory(CreateMutexW_ReleaseMutex) +add_subdirectory(CreateProcessA) +add_subdirectory(CreateProcessW) +add_subdirectory(CreateSemaphoreA_ReleaseSemaphore) +add_subdirectory(CreateSemaphoreW_ReleaseSemaphore) +add_subdirectory(CreateThread) +add_subdirectory(CriticalSectionFunctions) +add_subdirectory(DuplicateHandle) +add_subdirectory(ExitProcess) +add_subdirectory(ExitThread) +add_subdirectory(GetCurrentProcess) +add_subdirectory(GetCurrentProcessId) +add_subdirectory(GetCurrentThread) +add_subdirectory(GetCurrentThreadId) +add_subdirectory(GetExitCodeProcess) +add_subdirectory(GetProcessTimes) +add_subdirectory(GetThreadTimes) +add_subdirectory(NamedMutex) +add_subdirectory(OpenEventW) +add_subdirectory(OpenProcess) +add_subdirectory(QueryThreadCycleTime) +add_subdirectory(QueueUserAPC) +add_subdirectory(ReleaseMutex) +add_subdirectory(releasesemaphore) +add_subdirectory(ResetEvent) +add_subdirectory(ResumeThread) +add_subdirectory(SetErrorMode) +add_subdirectory(SetEvent) +add_subdirectory(SignalObjectAndWait) +add_subdirectory(Sleep) +add_subdirectory(SleepEx) +add_subdirectory(SwitchToThread) +add_subdirectory(TerminateProcess) +add_subdirectory(ThreadPriority) +add_subdirectory(WaitForMultipleObjects) +add_subdirectory(WaitForMultipleObjectsEx) +add_subdirectory(WaitForSingleObject) +add_subdirectory(YieldProcessor) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test1/CMakeLists.txt new file mode 100644 index 0000000..0dc038e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_createeventa_test1 + ${SOURCES} +) + +add_dependencies(paltest_createeventa_test1 coreclrpal) + +target_link_libraries(paltest_createeventa_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test1/test1.cpp new file mode 100644 index 0000000..d8ef0f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test1/test1.cpp @@ -0,0 +1,95 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for CreateEvent. Create an event, ensure the +** HANDLE is valid. Then check to ensure that the object is in the +** signaled state. Close the HANDLE and done. +** +** +**=========================================================*/ + +/* + Note: From the rotor_pal documentation: + + lpEventAttributes will always be NULL, bManualReset can be either + TRUE or FALSE, bInitialState can be either TRUE or FALSE, the lpName + may be non-NULL + +*/ + + +#include + +BOOL CreateEventTest() +{ + BOOL bRet = FALSE; + DWORD dwRet = 0; + + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + BOOL bManualReset = TRUE; + BOOL bInitialState = TRUE; + + /* Call CreateEvent, and check to ensure the returned HANDLE is a + valid event HANDLE + */ + + HANDLE hEvent = CreateEvent( lpEventAttributes, + bManualReset, + bInitialState, + NULL); + + if (hEvent != NULL) + { + /* Wait for the Object (for 0 time) and ensure that it returns + the value indicating that the event is signaled. + */ + dwRet = WaitForSingleObject(hEvent,0); + + if (dwRet != WAIT_OBJECT_0) + { + Trace("CreateEventTest:WaitForSingleObject failed (%x)\n", GetLastError()); + } + else + { + /* If we make it here, and CloseHandle succeeds, then the + entire test has passed. Otherwise bRet will still show + failure + */ + bRet = CloseHandle(hEvent); + + if (!bRet) + { + Trace("CreateEventTest:CloseHandle failed (%x)\n", GetLastError()); + } + } + } + else + { + Trace("CreateEventTest:CreateEvent failed (%x)\n", GetLastError()); + } + + return bRet; +} + +int __cdecl main(int argc, char **argv) +{ + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!CreateEventTest()) + { + Fail ("Test failed\n"); + } + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test1/testinfo.dat new file mode 100644 index 0000000..c0d169c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateEvent +Name = Positive Test for CreateEvent +TYPE = DEFAULT +EXE1 = test1 +Description += Test for CreateEvent. Create an event, ensure the += HANDLE is valid. Then check to ensure that the object is in the += signaled state. Close the HANDLE and done. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test2/CMakeLists.txt new file mode 100644 index 0000000..06b6343 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_createeventa_test2 + ${SOURCES} +) + +add_dependencies(paltest_createeventa_test2 coreclrpal) + +target_link_libraries(paltest_createeventa_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test2/test2.cpp new file mode 100644 index 0000000..a24d20e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test2/test2.cpp @@ -0,0 +1,84 @@ +// 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. + +/*============================================================ +** +** Source: test2.c +** +** Purpose: Test for CreateEvent. Create the event with the +** initial state being not signaled. Check to ensure that it +** times out when the event is triggered. +** +** +**=========================================================*/ + +#include + +BOOL CreateEventTest() +{ + BOOL bRet = FALSE; + DWORD dwRet = 0; + + LPSECURITY_ATTRIBUTES lpEventAttributes = 0; + BOOL bManualReset = TRUE; + BOOL bInitialState = FALSE; + + /* Create an event with the Initial State set to FALSE */ + + HANDLE hEvent = CreateEvent( lpEventAttributes, + bManualReset, + bInitialState, + NULL); + + if (hEvent != NULL) + { + /* This should ensure that the object is reset, or + non-signaled. + */ + + dwRet = WaitForSingleObject(hEvent,0); + + if (dwRet != WAIT_TIMEOUT) + { + Trace("CloseEventTest:WaitForSingleObject failed (%x)\n", GetLastError()); + } + else + { + /* At this point, we've tested the function with success. + So long as the HANDLE can be closed, this test should + pass. + */ + + bRet = CloseHandle(hEvent); + + if (!bRet) + { + Trace("CloseEventTest:CloseHandle failed (%x)\n", GetLastError()); + } + } + } + else + { + Trace("CloseEventTest:CreateEvent failed (%x)\n", GetLastError()); + } + + return bRet; +} + +int __cdecl main(int argc, char **argv) +{ + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!CreateEventTest()) + { + Fail ("Test failed\n"); + } + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test2/testinfo.dat new file mode 100644 index 0000000..4af65f1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateEvent +Name = Positive Test for CreateEvent +TYPE = DEFAULT +EXE1 = test2 +Description += Test for CreateEvent. Create the event with the += initial state being not signaled. Check to ensure that it += times out when the event is triggered. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test3/CMakeLists.txt new file mode 100644 index 0000000..a627e2e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_createeventa_test3 + ${SOURCES} +) + +add_dependencies(paltest_createeventa_test3 coreclrpal) + +target_link_libraries(paltest_createeventa_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test3/test3.cpp new file mode 100644 index 0000000..56d107b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test3/test3.cpp @@ -0,0 +1,219 @@ +// 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. + +/*============================================================ +** +** Source: test3.c +** +** Purpose: Tests for CreateEventA. Create an event with an empty name, +** create an event with the same name as an already created event +** object. +** +** +**=========================================================*/ + +#include + +#define SWAPPTR ((VOID *)(-1)) + +struct testCase +{ + LPSECURITY_ATTRIBUTES lpEventAttributes; + BOOL bManualReset; + BOOL bInitialState; + char lpName[MAX_PATH + 2]; + DWORD dwNameLen; + DWORD lastError; + BOOL bResult; +}; + +struct testCase testCases[]= +{ + {0, TRUE, FALSE, "", 0, ERROR_SUCCESS, PASS}, + {0, TRUE, FALSE, "", 5, ERROR_SUCCESS, PASS}, + {0, TRUE, FALSE, "", 5, ERROR_ALREADY_EXISTS, PASS}, + {0, TRUE, FALSE, "", 6, ERROR_INVALID_HANDLE, PASS}, + {0, TRUE, FALSE, "", MAX_PATH - 1 - 60, ERROR_SUCCESS, PASS}, + {0, TRUE, FALSE, "", MAX_PATH + 1, ERROR_FILENAME_EXCED_RANGE, PASS} +}; + +static HANDLE hEvent[sizeof(testCases)/sizeof(struct testCase)]; + +DWORD result[sizeof(testCases)/sizeof(struct testCase)]; + +int __cdecl main(int argc, char **argv) +{ + + BOOL bRet = TRUE; + const char *nonEventName = "aaaaaa"; + HANDLE hUnnamedEvent; + HANDLE hFMap; + DWORD dwRet; + int i; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + hUnnamedEvent = CreateEventA(0, TRUE, FALSE, NULL); + + if ( NULL == hUnnamedEvent ) + { + bRet = FALSE; + Trace ( "PALSUITE ERROR: CreateEventA (%d, %d, %d, NULL) call " + "returned NULL.\nGetLastError returned %u.\n", 0, TRUE, FALSE, + GetLastError()); + } + + if (!CloseHandle(hUnnamedEvent)) + { + bRet = FALSE; + Trace("PALSUITE ERROR: CreateEventA: CloseHandle(%lp); call " + "failed\nGetLastError returned '%u'.\n", hUnnamedEvent, + GetLastError()); + } + + /* Create non-event with the same name as one of the testCases */ + hFMap = CreateFileMappingA( SWAPPTR, NULL, PAGE_READONLY, 0, 1, + nonEventName ); + + if ( NULL == hFMap ) + { + bRet = FALSE; + Trace ( "PALSUITE ERROR: CreateFileMapping (%p, %p, %d, %d, %d, %s)" + " call returned NULL.\nGetLastError returned %u.\n", + SWAPPTR, NULL, PAGE_READONLY, 0, 0, nonEventName, + GetLastError()); + goto done; + } + + /* Create Events */ + for (i = 0; i < sizeof(testCases)/sizeof(struct testCase); i++) + { + /* create name */ + memset (testCases[i].lpName, '\0', (MAX_PATH + 2)); + memset (testCases[i].lpName, 'a', testCases[i].dwNameLen ); + + SetLastError(ERROR_SUCCESS); + + hEvent[i] = CreateEventA( testCases[i].lpEventAttributes, + testCases[i].bManualReset, + testCases[i].bInitialState, + testCases[i].lpName); + + if (hEvent[i] != INVALID_HANDLE_VALUE) + { + DWORD dwError = GetLastError(); + + if (dwError != testCases[i].lastError) + { + bRet = FALSE; + Trace ("PALSUITE ERROR:\nCreateEventA(%lp, %d, %d, %s)" + "\nGetLastError returned '%u', it should have returned" + "'%d' at index '%d'.\n", testCases[i].lpEventAttributes, + testCases[i].bManualReset, testCases[i].bInitialState, + testCases[i].lpName, dwError, + testCases[i].lastError, i); + } + if ( ERROR_FILENAME_EXCED_RANGE == testCases[i].lastError ) + { + result [i] = 1; + } + if ( ERROR_INVALID_HANDLE == testCases[i].lastError ) + { + result [i] = 1; + } + /* + * If we expected the testcase to FAIL and it passed, + * report an error. + */ + if (testCases[i].bResult == FAIL) + { + bRet = FALSE; + Trace ("PALSUITE ERROR:\nCreateEventA(%lp, %d, %d, %s)" + "\nShould have returned INVALID_HANDLE_VALUE but " + "didn't at index '%d'.\n", + testCases[i].lpEventAttributes, + testCases[i].bManualReset, + testCases[i].bInitialState, + testCases[i].lpName, i); + } + /* + * If result hasn't been set already set it to 0 so all the + * resources will be freed. + */ + if (!result[i] ) + { + result[i] = 0; + } + } + else + { + /* + * If we get an INVALID_HANDLE_VALUE and we expected the + * test case to pass, report an error. + */ + result[i] = 1; + + if (testCases[i].bResult == PASS) + { + bRet = FALSE; + Trace ("PALSUITE ERROR:\nCreateEventA(%lp, %d, %d, %s);" + "\nReturned INVALID_HANDLE_VALUE at index '%d'.\n", + testCases[i].lpEventAttributes, + testCases[i].bManualReset, testCases[i].bInitialState, + testCases[i].lpName, i); + } + } + } + + /* cleanup */ + for (i = 0; i < sizeof(testCases)/sizeof(struct testCase); i++) + { + if (result[i]) + { + continue; + } + dwRet = WaitForSingleObject ( hEvent[i], 0 ); + + if (dwRet != WAIT_TIMEOUT) + { + bRet = FALSE; + Trace("PALSUITE ERROR: CreateEventA:\nWaitForSingleObject (%lp, " + "%d) call failed at index %d .\nGetLastError returned " + "'%u'.\n", hEvent[i], 0, i, GetLastError()); + } + + if (!CloseHandle(hEvent[i])) + { + bRet = FALSE; + Trace("PALSUITE ERROR: CreateEventA: CloseHandle(%lp) call " + "failed at index %d\nGetLastError returned '%u'.\n", + hEvent[i], i, GetLastError()); + } + } + +done: + if (!CloseHandle(hFMap)) + { + bRet = FALSE; + Trace("PALSUITE ERROR: CreateEventW: CloseHandle(%p) call " + "failed\nGetLastError returned '%u'.\n", hFMap, + GetLastError()); + } + + if (FALSE == bRet) + { + bRet = FAIL; + } + else + { + bRet = PASS; + } + + PAL_TerminateEx(bRet); + + return(bRet); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test3/testinfo.dat new file mode 100644 index 0000000..c3a344a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventA/test3/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateEventA +Name = Positive Test for CreateEventA +TYPE = DEFAULT +EXE1 = test3 +Description += Tests for CreateEventA. Create an unnamed event, create += an event with an empty name, create an event with a name longer than += MAX_PATH, MAX_PATH + 1, create an event with a name already taken += by a non-event object, create an event with a name already taken += by an event object. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test1/CMakeLists.txt new file mode 100644 index 0000000..b73b132 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_createeventw_test1 + ${SOURCES} +) + +add_dependencies(paltest_createeventw_test1 coreclrpal) + +target_link_libraries(paltest_createeventw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test1/test1.cpp new file mode 100644 index 0000000..8d99e41 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test1/test1.cpp @@ -0,0 +1,93 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for CreateEventW +** +** +**=========================================================*/ + +/* + * Note: From the rotor_pal documentation: lpEventAttributes will + * always be NULL, bManualReset can be either TRUE or FALSE, + * bInitialState can be either TRUE or FALSE, the lpName may be + * non-NULL. +*/ +#define UNICODE +#include + +BOOL CreateEventTest() +{ + BOOL bRet = FALSE; + DWORD dwRet = 0; + + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + BOOL bManualReset = TRUE; + BOOL bInitialState = TRUE; + + /* + * Call CreateEvent, and check to ensure the returned HANDLE is a + * valid event HANDLE + */ + + HANDLE hEvent = CreateEventW(lpEventAttributes, + bManualReset, + bInitialState, + NULL); + + if (hEvent != NULL) + { + /* + * Wait for the Object (for 0 time) and ensure that it returns + * the value indicating that the event is signaled. + */ + dwRet = WaitForSingleObject(hEvent,0); + + if (dwRet != WAIT_OBJECT_0) + { + Trace("CreateEventTest:WaitForSingleObject failed (%x)\n", GetLastError()); + } + else + { + /* + * If we make it here, and CloseHandle succeeds, then the + * entire test has passed. Otherwise bRet will still show + * failure + */ + bRet = CloseHandle(hEvent); + + if (!bRet) + { + Trace("CreateEventTest:CloseHandle failed (%x)\n", GetLastError()); + } + } + } + else + { + Trace("CreateEventTest:CreateEvent failed (%x)\n", GetLastError()); + } + + return bRet; +} + +int __cdecl main(int argc, char **argv) +{ + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!CreateEventTest()) + { + Fail ("Test failed\n"); + } + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test1/testinfo.dat new file mode 100644 index 0000000..204ad1f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateEventW +Name = Positive Test for CreateEventW +TYPE = DEFAULT +EXE1 = test1 +Description += Test for CreateEventW. Create an event, ensure the += HANDLE is valid. Then check to ensure that the object is in the += signaled state. Close the HANDLE and done. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test2/CMakeLists.txt new file mode 100644 index 0000000..60c505b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_createeventw_test2 + ${SOURCES} +) + +add_dependencies(paltest_createeventw_test2 coreclrpal) + +target_link_libraries(paltest_createeventw_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test2/test2.cpp new file mode 100644 index 0000000..4df2189 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test2/test2.cpp @@ -0,0 +1,85 @@ +// 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. + +/*============================================================ +** +** Source: test2.c +** +** Purpose: Test for CreateEventW. Create the event with the +** initial state being not signaled. Check to ensure that it +** times out when the event is triggered. +** +** +**=========================================================*/ +#define UNICODE +#include + +BOOL CreateEventTest() +{ + BOOL bRet = FALSE; + DWORD dwRet = 0; + + LPSECURITY_ATTRIBUTES lpEventAttributes = 0; + BOOL bManualReset = TRUE; + BOOL bInitialState = FALSE; + + + /* Create an event with the Initial State set to FALSE */ + + HANDLE hEvent = CreateEventW(lpEventAttributes, + bManualReset, + bInitialState, + NULL); + + if (hEvent != NULL) + { + /* This should ensure that the object is reset, or + non-signaled. + */ + + dwRet = WaitForSingleObject(hEvent,0); + + if (dwRet != WAIT_TIMEOUT) + { + Trace("CloseEventTest:WaitForSingleObject failed (%x)\n", GetLastError()); + } + else + { + /* At this point, we've tested the function with success. + So long as the HANDLE can be closed, this test should + pass. + */ + + bRet = CloseHandle(hEvent); + + if (!bRet) + { + Trace("CloseEventTest:CloseHandle failed (%x)\n", GetLastError()); + } + } + } + else + { + Trace("CloseEventTest:CreateEvent failed (%x)\n", GetLastError()); + } + + return bRet; +} + +int __cdecl main(int argc, char **argv) +{ + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!CreateEventTest()) + { + Fail ("Test failed\n"); + } + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test2/testinfo.dat new file mode 100644 index 0000000..01f7519 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateEventW +Name = Positive Test for CreateEventW +TYPE = DEFAULT +EXE1 = test2 +Description += Test for CreateEvent. Create the event with the += initial state being not signaled. Check to ensure that it += times out when the event is triggered. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test3/CMakeLists.txt new file mode 100644 index 0000000..5106821 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_createeventw_test3 + ${SOURCES} +) + +add_dependencies(paltest_createeventw_test3 coreclrpal) + +target_link_libraries(paltest_createeventw_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test3/test3.cpp new file mode 100644 index 0000000..22f0fcf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test3/test3.cpp @@ -0,0 +1,233 @@ +// 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. + +/*============================================================ +** +** Source: test3.c +** +** Purpose: Tests for CreateEvent. Create an unnamed event, create +** an event with an empty name, create an event with a name longer than +** MAX_PATH, MAX_PATH + 1, create an event with a name already taken +** by a non-event object, create an event with a name already taken +** by an event object. +** +** +**=========================================================*/ +#include + +#define SWAPPTR ((VOID *) (-1)) + +struct testCase +{ + LPSECURITY_ATTRIBUTES lpEventAttributes; + BOOL bManualReset; + BOOL bInitialState; + WCHAR lpName[MAX_PATH + 2]; + DWORD dwNameLen; + DWORD lastError; + BOOL bResult; +}; + +struct testCase testCases[]= +{ + {0, TRUE, FALSE, {'\0'}, 0, ERROR_SUCCESS, PASS}, + {0, TRUE, FALSE, {'\0'}, 5, ERROR_SUCCESS, PASS}, + {0, TRUE, FALSE, {'\0'}, 5, ERROR_ALREADY_EXISTS, PASS}, + {0, TRUE, FALSE, {'\0'}, 6, ERROR_INVALID_HANDLE, PASS}, + {0, TRUE, FALSE, {'\0'}, MAX_PATH - 1 - 60, ERROR_SUCCESS, PASS}, + {0, TRUE, FALSE, {'\0'}, MAX_PATH - 60, ERROR_SUCCESS, PASS}, +}; + +static HANDLE hEvent[sizeof(testCases)/sizeof(struct testCase)]; + +DWORD result[sizeof(testCases)/sizeof(struct testCase)]; + +int __cdecl main(int argc, char **argv) +{ + + BOOL bRet = TRUE; + WCHAR nonEventName[] = {'a','a','a','a','a','a','\0'}; + char name[MAX_PATH + 2]; + WCHAR *wName; + HANDLE hFMap = NULL; + HANDLE hUnnamedEvent; + DWORD dwRet; + int i; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + hUnnamedEvent = CreateEventW(0, TRUE, FALSE, NULL); + + if ( NULL == hUnnamedEvent ) + { + bRet = FALSE; + Trace ( "PALSUITE ERROR: CreateEventW (%d, %d, %d, NULL) call " + "returned NULL.\nGetLastError returned %u.\n", 0, TRUE, FALSE, + GetLastError()); + goto done; + } + + if (!CloseHandle(hUnnamedEvent)) + { + bRet = FALSE; + Trace("PALSUITE ERROR: CreateEventW: CloseHandle(%lp); call " + "failed\nGetLastError returned '%u'.\n", hUnnamedEvent, + GetLastError()); + } + + /* Create non-event with the same name as one of the testCases */ + hFMap = CreateFileMappingW( SWAPPTR, NULL, PAGE_READONLY, 0, 1, + nonEventName ); + + if ( NULL == hFMap ) + { + bRet = FALSE; + Trace ( "PALSUITE ERROR: CreateFileMapping (%p, %p, %d, %d, %d, %S)" + " call returned NULL.\nGetLastError returned %u\n", + SWAPPTR, NULL, PAGE_READONLY, 0, 0, nonEventName, + GetLastError()); + } + + /* Create Events */ + for (i = 0; i < sizeof(testCases)/sizeof(struct testCase); i++) + { + /* create name */ + memset (name, '\0', MAX_PATH + 2); + memset (name, 'a', testCases[i].dwNameLen ); + + wName = convert(name); + + wcsncpy(testCases[i].lpName, wName, + testCases[i].dwNameLen); + + free(wName); + + SetLastError(ERROR_SUCCESS); + + hEvent[i] = CreateEventW( testCases[i].lpEventAttributes, + testCases[i].bManualReset, + testCases[i].bInitialState, + testCases[i].lpName); + + if (hEvent[i] != INVALID_HANDLE_VALUE) + { + DWORD dwError = GetLastError(); + + if (dwError != testCases[i].lastError) + { + bRet = FALSE; + Trace ("PALSUITE ERROR:\nCreateEvent(%lp, %d, %d, %S)" + "\nGetLastError returned '%u', it should have returned" + "'%d' at index '%d'.\n", testCases[i].lpEventAttributes, + testCases[i].bManualReset, testCases[i].bInitialState, + testCases[i].lpName, dwError, + testCases[i].lastError, i); + } + if ( ERROR_FILENAME_EXCED_RANGE == testCases[i].lastError ) + { + result [i] = 1; + } + if ( ERROR_INVALID_HANDLE == testCases[i].lastError ) + { + result [i] = 1; + } + /* + * If we expected the testcase to FAIL and it passed, + * report an error. + */ + if (testCases[i].bResult == FAIL) + { + bRet = FALSE; + Trace ("PALSUITE ERROR:\nCreateEvent(%lp, %d, %d, %S)" + "\nShould have returned INVALID_HANDLE_VALUE but " + "didn't at index '%d'.\n", + testCases[i].lpEventAttributes, + testCases[i].bManualReset, + testCases[i].bInitialState, + testCases[i].lpName, i); + } + /* + * If result hasn't been set already set it to 0 so all the + * resources will be freed. + */ + if (!result[i]) + { + result[i] = 0; + } + } + else + { + /* + * If we get an INVALID_HANDLE_VALUE and we expected the + * test case to pass, report an error. + */ + result[i] = 1; + + if (testCases[i].bResult == PASS) + { + bRet = FALSE; + Trace ("PALSUITE ERROR:\nCreateEvent(%lp, %d, %d, %S);" + "\nReturned INVALID_HANDLE_VALUE at index '%d'.\n", + testCases[i].lpEventAttributes, + testCases[i].bManualReset, testCases[i].bInitialState, + testCases[i].lpName, i); + } + } + } + + /* cleanup */ + for (i = 0; i < sizeof(testCases)/sizeof(struct testCase); i++) + { + if (result[i]) + { + continue; + } + dwRet = WaitForSingleObject ( hEvent[i], 0 ); + + if (dwRet != WAIT_TIMEOUT) + { + bRet = FALSE; + Trace("PALSUITE ERROR: CreateEventW:\nWaitForSingleObject (%lp, " + "%d) call failed at index %d .\nGetLastError returned " + "'%u'.\n", hEvent[i], 0, i, GetLastError()); + } + + if (!CloseHandle(hEvent[i])) + { + bRet = FALSE; + Trace("PALSUITE ERROR: CreateEventW: CloseHandle(%lp) call " + "failed at index %d\nGetLastError returned '%u'.\n", + hEvent[i], i, GetLastError()); + } + } + +done: + if (hFMap != NULL && !CloseHandle(hFMap)) + { + bRet = FALSE; + Trace("PALSUITE ERROR: CreateEventW: CloseHandle(%p) call " + "failed\nGetLastError returned '%u'.\n", hFMap, + GetLastError()); + } + + if (FALSE == bRet) + { + bRet = FAIL; + } + else + { + bRet = PASS; + } + + PAL_TerminateEx(bRet); + + return(bRet); + +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test3/testinfo.dat new file mode 100644 index 0000000..4776ed2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateEventW/test3/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateEventW +Name = Positive Test for CreateEventW +TYPE = DEFAULT +EXE1 = test3 +Description += Tests for CreateEventW. Create an unnamed event, create += an event with an empty name, create an event with a name longer than += MAX_PATH, MAX_PATH + 1, create an event with a name already taken += by a non-event object, create an event with a name already taken += by an event object. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CMakeLists.txt new file mode 100644 index 0000000..ddd1ed9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateMutexA.cpp +) + +add_executable(paltest_createmutexa_releasemutex_test1 + ${SOURCES} +) + +add_dependencies(paltest_createmutexa_releasemutex_test1 coreclrpal) + +target_link_libraries(paltest_createmutexa_releasemutex_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CreateMutexA.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CreateMutexA.cpp new file mode 100644 index 0000000..3074fa0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CreateMutexA.cpp @@ -0,0 +1,344 @@ +// 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. + +/*============================================================ +** +** Source: CreateMutexA_ReleaseMutex/test1/CreateMutexA.c +** +** Purpose: This test case tests whether a Mutex object created +** with CreateMutex really works by mutually excluding +** threads from accessing a data structure at the same +** time. Here we have a buffer that can be filled or +** emptied, we use a Mutex object to ensure that one +** operation cannot be started until the other is +** finished. If one operation detects that the other +** has not finished, it fails. There is a Producer +** thread which will try to fill the buffer 25 times, +** and a consumer thread which try to empty the buffer +** 25 times. If either the fill or empty operations +** fails because the Mutex failed to mutually exclude +** them, the corresponding thread will set an error +** flag and return. This will cause the test case to +** fail. +** +** To increase the probability of identifying problems, +** the Fill opeartion has been slowed down with a call +** to Sleep. This ensures that one operation will try +** to access the shared buffer while the other is in +** progress. +** +** NOTE: this test case also serves as a test case for +** WaitForSingleObject. +** +** +** Dependencies: CreateThread +** ReleaseMutex +** WaitForSingleObject +** WaitForMultipleObjects +** Sleep +** memset +** + +** +**=========================================================*/ + +#define UNICODE +#include + +/* Define some values that we will using many times */ +#define MAIN_BUF_SIZE 40 +#define NUM_OF_CYCLES 40 + +/* Buffer Operation return codes */ +#define OP_OK 0 +#define OP_ERR 1 +#define OP_NONE 2 + + +HANDLE hMutex; /* handle to mutex */ + +BOOL bProdErr; /* Producer error Flag */ +BOOL bConErr; /* Consumer error Flag */ + +/* Test Buffer */ +char Buffer[MAIN_BUF_SIZE]; + +/* + * EmptyBuffer implements the empty operation for test buffer. + */ +int +EmptyBuffer() +{ + int i; + + if ( WaitForSingleObject(hMutex, INFINITE) == WAIT_FAILED) + { + Fail("ERROR: WaitForSingleObject failed.\n"); + } + + /* Check to see if the buffer is already completely empty */ + for (i=0; i + +const char *szMutex = "MyMutex"; +const char *szEmpty = ""; + +/* Function Prototypes */ +BOOL TestNamedMutex(const char *szMutexName); +DWORD NamedMutexThread(LPVOID lpParam); +BOOL NegativeReleaseMutexTests(); + +struct ThreadData +{ + HANDLE hMutex; + BOOL bReturnCode; +}; +typedef struct ThreadData THREADDATA; + + +int __cdecl main (int argc, char **argv) +{ + BOOL bFailures = FALSE; + char *szMaxPath; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + + /* + * Test named Mutexes with ordinary string + */ + + if (!TestNamedMutex(szMutex)) + { + bFailures = TRUE; + } + + + /* + * Test named Mutexes with empty ("") string + */ + + if (!TestNamedMutex(szEmpty)) + { + bFailures = TRUE; + } + + + /* + * Test named Mutexes with string of length MAX_LONGPATHPATH + */ + + szMaxPath = (char *)malloc(MAX_LONGPATH+2); + memset(szMaxPath, 'A', MAX_LONGPATH-60); + szMaxPath[MAX_LONGPATH-60] = 0; + + if (!TestNamedMutex(szMaxPath)) + { + bFailures = TRUE; + } + + free((void*)szMaxPath); + + + /* + * Run some negative tests on ReleaseMutex + */ + + if (!NegativeReleaseMutexTests()) + { + bFailures = TRUE; + } + + + /* + * If there were any failures, then abort with a call to Fail + */ + + if (bFailures == TRUE) + { + Fail("ERROR: There some failures in the Mutex tests.\n"); + } + + PAL_Terminate(); + return ( PASS ); +} + + +/* + * Testing Function + * + * Try to get multiple handles to a named Mutex and test + * to make sure they actually refer to same Mutex object. + */ +BOOL TestNamedMutex(const char *szMutexName) +{ + DWORD dwData; + HANDLE hMutex1; + HANDLE hMutex2; + HANDLE hThread; + THREADDATA threadData; + + /* Create a mutex and take ownership immediately */ + hMutex1 = CreateMutexA (NULL, TRUE, szMutexName); + + if (NULL == hMutex1) + { + Trace("ERROR: CreateMutexA #1 failed. GetLastError returned %u\n", + GetLastError()); + return FALSE; + } + + /* Try to wait on the Mutex we just created. We should not block. */ + if (WaitForSingleObject(hMutex1, 1000) == WAIT_TIMEOUT) + { + Trace("WaitForSingleObject blocked on a Mutex that we owned.\n"); + return FALSE; + } + /* We have to call ReleaseMutex here because of the Wait */ + if (ReleaseMutex(hMutex1) == FALSE) + { + Trace("ReleaseMutex Failed.\n"); + return FALSE; + } + + /* Get a second handle to the same mutex */ + hMutex2 = CreateMutexA (NULL, FALSE, szMutexName); + + if (NULL == hMutex2) + { + Trace("ERROR: CreateMutex #2 failed. GetLastError returned %u\n", + GetLastError()); + free((void*)szMutexName); + return FALSE; + } + + /* + * Create a thread that will Wait on the second handle. + */ + threadData.hMutex = hMutex2; + hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)NamedMutexThread, + (LPVOID)&threadData, 0, &dwData); + + if (NULL == hThread) + { + Trace("ERROR: CreateThread failed. GetLastError returned %u\n", + GetLastError()); + return FALSE; + } + + /* Give the thread a little time to execute & wait*/ + Sleep(500); + + /* Signal the the first handle */ + if (ReleaseMutex(hMutex1) == FALSE) + { + Trace("ReleaseMutex Failed.\n"); + return FALSE; + } + + /* Give the thread some time to finish */ + Sleep(2000); + + /* Clean Up */ + if (CloseHandle(hMutex1) == FALSE || + CloseHandle(hMutex2) == FALSE || + CloseHandle(hThread) == FALSE) + { + Trace("ERROR: CloseHandle failed.\n"); + return FALSE; + } + + /* Check the return code to see if signalling the first */ + /* Mutex handle woke up the thread which was Waiting on */ + /* the second handle. */ + if (threadData.bReturnCode != FALSE) + { + Trace("ERROR: The handles did not refer to the same Mutex object.\n"); + return FALSE; + } + + return TRUE; +} + + +/* + * Thread function used with above testing function. + */ +DWORD NamedMutexThread(LPVOID lpParam) +{ + BOOL bTimedOut = FALSE; + THREADDATA *lpThreadData = (THREADDATA *)lpParam; + + /* Wait on the Mutex that was passed to us */ + if (WaitForSingleObject(lpThreadData->hMutex, 10000) == WAIT_TIMEOUT) + { + /* The Mutex was not signaled in the allotted time */ + bTimedOut = TRUE; + } + if (ReleaseMutex(lpThreadData->hMutex) == FALSE) + { + Trace("ERROR: ReleaseMutex failed.\n"); + lpThreadData->bReturnCode = FALSE; + return 0; + } + + /* Indicate whether we timed out Waiting on the Mutex */ + lpThreadData->bReturnCode = bTimedOut; + + return 0; +} + + +/* + * Testing Function + * + * Try some negative tests on ReleaseMutex + */ +BOOL NegativeReleaseMutexTests() +{ + HANDLE hMutex; + BOOL bRet; + BOOL bResults = TRUE; + + + /* + * Try calling ReleaseMutex on a null handle + */ + hMutex = 0; + bRet = ReleaseMutex(hMutex); + + if (bRet != 0) + { + Trace("Error: ReleaseMutex accepted null handle.\n"); + bResults = FALSE; + } + + + /* + * Try calling ReleaseMutex on an handle that we don't own + */ + hMutex = CreateMutexA (NULL, TRUE, NULL); + if (hMutex == 0) + { + Trace("Error: CreateMutex failed.\n"); + bResults = FALSE; + } + + bRet = ReleaseMutex(hMutex); + bRet = ReleaseMutex(hMutex); + + if (bRet != FALSE) + { + Trace("Error: ReleaseMutex accepted unowned handle.\n"); + bResults = FALSE; + } + + if (CloseHandle(hMutex) == FALSE) + { + Trace("Error: CloseHandle failed.\n"); + bResults = FALSE; + } + + + + /* + * Try calling ReleaseMutex on an handle that has been closed + */ + hMutex = CreateMutexA (NULL, TRUE, NULL); + if (hMutex == 0) + { + Trace("Error: CreateMutex failed.\n"); + bResults = FALSE; + } + + if (ReleaseMutex(hMutex) == FALSE) + { + Trace("Error: ReleaseMutex failed.\n"); + bResults = FALSE; + } + if (CloseHandle(hMutex) == FALSE) + { + Trace("Error: CloseHandle failed.\n"); + bResults = FALSE; + } + + bRet = ReleaseMutex(hMutex); + + if (bRet != FALSE) + { + Trace("Error: ReleaseMutex accepted invalid handle.\n"); + bResults = FALSE; + } + + return bResults; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/testinfo.dat new file mode 100644 index 0000000..7e37528 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/testinfo.dat @@ -0,0 +1,24 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateMutexA / ReleaseMutex +Name = Basic validity Tests for CreateMutexA / ReleaseMutex +TYPE = DEFAULT +EXE1 = createmutexa +Description += This test case tests the following things += - Creation of named Mutexes += - Creating multiple handles to a single named Mutex += - Ensuring that these handles work interchangeably += - Setting bInitialOwnerFlag to TRUE will cause the += initial call to a Wait function on the same Mutex += to actually wait. += - Waiting on a Mutex that a thread already owns should += not block. += - Create Named mutex with empty string ("") += - Create Named mutex with string of MAX_PATH length += - Calling RelaseMutex with invalid Mutex handles and += valid but unowned Mutexes. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CMakeLists.txt new file mode 100644 index 0000000..b899c04 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateMutexW.cpp +) + +add_executable(paltest_createmutexw_releasemutex_test1 + ${SOURCES} +) + +add_dependencies(paltest_createmutexw_releasemutex_test1 coreclrpal) + +target_link_libraries(paltest_createmutexw_releasemutex_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CreateMutexW.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CreateMutexW.cpp new file mode 100644 index 0000000..ec8e0c6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CreateMutexW.cpp @@ -0,0 +1,344 @@ +// 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. + +/*============================================================ +** +** Source: CreateMutexW_ReleaseMutex/test1/CreateMutexW.c +** +** Purpose: This test case tests whether a Mutex object created +** with CreateMutex really works by mutually excluding +** threads from accessing a data structure at the same +** time. Here we have a buffer that can be filled or +** emptied, we use a Mutex object to ensure that one +** operation cannot be started until the other is +** finished. If one operation detects that the other +** has not finished, it fails. There is a Producer +** thread which will try to fill the buffer 25 times, +** and a consumer thread which try to empty the buffer +** 25 times. If either the fill or empty operations +** fails because the Mutex failed to mutually exclude +** them, the corresponding thread will set an error +** flag and return. This will cause the test case to +** fail. +** +** To increase the probability of identifying problems, +** the Fill opeartion has been slowed dowm with a call +** to Sleep. This ensures that one operation will try +** to access the shared buffer while the other is in +** progress. +** +** NOTE: this test case also serves as a test case for +** WaitForSingleObject. +** +** +** Dependencies: CreateThread +** ReleaseMutex +** WaitForSingleObject +** WaitForMultipleObjects +** Sleep +** memset +** + +** +**=========================================================*/ + +#define UNICODE +#include + +/* Define some values that we will using many times */ +#define MAIN_BUF_SIZE 40 +#define NUM_OF_CYCLES 40 + +/* Buffer Operation return codes */ +#define OP_OK 0 +#define OP_ERR 1 +#define OP_NONE 2 + + +HANDLE hMutex; /* handle to mutex */ + +BOOL bProdErr; /* Producer error Flag */ +BOOL bConErr; /* Consumer error Flag */ + +/* Test Buffer */ +char Buffer[MAIN_BUF_SIZE]; + +/* + * EmptyBuffer implements the empty operation for test buffer. + */ +int +EmptyBuffer() +{ + int i; + + if ( WaitForSingleObject(hMutex, INFINITE) == WAIT_FAILED) + { + Fail("ERROR: WaitForSingleObject failed.\n"); + } + + /* Check to see if the buffer is already completely empty */ + for (i=0; i + +const char *szMutex = "MyMutex"; +const char *szEmpty = ""; + +/* Function Prototypes */ +BOOL TestNamedMutex(const char *szMutexName); +DWORD NamedMutexThread(LPVOID lpParam); +BOOL NegativeReleaseMutexTests(); + +struct ThreadData +{ + HANDLE hMutex; + BOOL bReturnCode; +}; +typedef struct ThreadData THREADDATA; + + +int __cdecl main (int argc, char **argv) +{ + BOOL bFailures = FALSE; + char *szMaxPath; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + + /* + * Test named Mutexes with ordinary string + */ + + if (!TestNamedMutex(szMutex)) + { + bFailures = TRUE; + } + + + /* + * Test named Mutexes with empty ("") string + */ + + if (!TestNamedMutex(szEmpty)) + { + bFailures = TRUE; + } + + + /* + * Test named Mutexes with string of length MAX_LONGPATH + */ + + szMaxPath = (char *)malloc(MAX_LONGPATH+2); + memset(szMaxPath, 'A', MAX_LONGPATH-60); + szMaxPath[MAX_LONGPATH-60] = 0; + + if (!TestNamedMutex(szMaxPath)) + { + bFailures = TRUE; + } + + free(szMaxPath); + + + /* + * Run some negative tests on ReleaseMutex + */ + + if (!NegativeReleaseMutexTests()) + { + bFailures = TRUE; + } + + + /* + * If there were any failures, then abort with a call to Fail + */ + + if (bFailures == TRUE) + { + Fail("ERROR: There some failures in the Mutex tests.\n"); + } + + PAL_Terminate(); + return ( PASS ); +} + + +/* + * Testing Function + * + * Try to get multiple handles to a named Mutex and test + * to make sure they actually refer to same Mutex object. + */ +BOOL TestNamedMutex(const char *szMutexName) +{ + DWORD dwData; + HANDLE hMutex1; + HANDLE hMutex2; + HANDLE hThread; + WCHAR *swzMutexName; + THREADDATA threadData; + + /* Convert the Mutex name to wide characters */ + swzMutexName = convert((char *)szMutexName); + + /* Create a mutex and take ownership immediately */ + hMutex1 = CreateMutexW (NULL, TRUE, swzMutexName); + + if (NULL == hMutex1) + { + Trace("ERROR: CreateMutex #1 failed. GetLastError returned %u\n", + GetLastError()); + free(swzMutexName); + return FALSE; + } + + /* Try to wait on the Mutex we just created. We should not block. */ + if (WaitForSingleObject(hMutex1, 1000) == WAIT_TIMEOUT) + { + Trace("WaitForSingleObject blocked on a Mutex that we owned.\n"); + free(swzMutexName); + return FALSE; + } + /* We have to call ReleaseMutex here because of the Wait */ + if (ReleaseMutex(hMutex1) == FALSE) + { + Trace("ReleaseMutex Failed.\n"); + return FALSE; + } + + /* Get a second handle to the same mutex */ + hMutex2 = CreateMutexW (NULL, FALSE, swzMutexName); + + if (NULL == hMutex2) + { + Trace("ERROR: CreateMutex #2 failed. GetLastError returned %u\n", + GetLastError()); + free(swzMutexName); + return FALSE; + } + + /* Get rid of the wide character string */ + free(swzMutexName); + + /* + * Create a thread that will Wait on the second handle. + */ + threadData.hMutex = hMutex2; + hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)NamedMutexThread, + (LPVOID)&threadData, 0, &dwData); + + if (NULL == hThread) + { + Trace("ERROR: CreateThread failed. GetLastError returned %u\n", + GetLastError()); + return FALSE; + } + + /* Give the thread a little time to execute & wait*/ + Sleep(500); + + /* Signal the the first handle */ + if (ReleaseMutex(hMutex1) == FALSE) + { + Trace("ReleaseMutex Failed.\n"); + return FALSE; + } + + /* Give the thread some time to finish */ + Sleep(2000); + + /* Clean Up */ + if (CloseHandle(hMutex1) == FALSE || + CloseHandle(hMutex2) == FALSE || + CloseHandle(hThread) == FALSE) + { + Trace("ERROR: CloseHandle failed.\n"); + return FALSE; + } + + /* Check the return code to see if signalling the first */ + /* Mutex handle woke up the thread which was Waiting on */ + /* the second handle. */ + if (threadData.bReturnCode != FALSE) + { + Trace("ERROR: The handles did not refer to the same Mutex object.\n"); + return FALSE; + } + + return TRUE; +} + + +/* + * Thread function used with above testing function. + */ +DWORD NamedMutexThread(LPVOID lpParam) +{ + BOOL bTimedOut = FALSE; + THREADDATA *lpThreadData = (THREADDATA *)lpParam; + + /* Wait on the Mutex that was passed to us */ + if (WaitForSingleObject(lpThreadData->hMutex, 10000) == WAIT_TIMEOUT) + { + /* The Mutex was not signaled in the allotted time */ + bTimedOut = TRUE; + } + if (ReleaseMutex(lpThreadData->hMutex) == FALSE) + { + Trace("ERROR: ReleaseMutex failed.\n"); + lpThreadData->bReturnCode = FALSE; + return 0; + } + + /* Indicate whether we timed out Waiting on the Mutex */ + lpThreadData->bReturnCode = bTimedOut; + + return 0; +} + + +/* + * Testing Function + * + * Try some negative tests on ReleaseMutex + */ +BOOL NegativeReleaseMutexTests() +{ + HANDLE hMutex; + BOOL bRet; + BOOL bResults = TRUE; + + + /* + * Try calling ReleaseMutex on a null handle + */ + hMutex = 0; + bRet = ReleaseMutex(hMutex); + + if (bRet != 0) + { + Trace("Error: ReleaseMutex accepted null handle.\n"); + bResults = FALSE; + } + + + /* + * Try calling ReleaseMutex on an handle that we don't own + */ + hMutex = CreateMutexW (NULL, TRUE, NULL); + if (hMutex == 0) + { + Trace("Error: CreateMutex failed.\n"); + bResults = FALSE; + } + + bRet = ReleaseMutex(hMutex); + bRet = ReleaseMutex(hMutex); + + if (bRet != FALSE) + { + Trace("Error: ReleaseMutex accepted unowned handle.\n"); + bResults = FALSE; + } + + if (CloseHandle(hMutex) == FALSE) + { + Trace("Error: CloseHandle failed.\n"); + bResults = FALSE; + } + + + + /* + * Try calling ReleaseMutex on an handle that has been closed + */ + hMutex = CreateMutexW (NULL, TRUE, NULL); + if (hMutex == 0) + { + Trace("Error: CreateMutex failed.\n"); + bResults = FALSE; + } + + if (ReleaseMutex(hMutex) == FALSE) + { + Trace("Error: ReleaseMutex failed.\n"); + bResults = FALSE; + } + if (CloseHandle(hMutex) == FALSE) + { + Trace("Error: CloseHandle failed.\n"); + bResults = FALSE; + } + + bRet = ReleaseMutex(hMutex); + + if (bRet != FALSE) + { + Trace("Error: ReleaseMutex accepted invalid handle.\n"); + bResults = FALSE; + } + + return bResults; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/testinfo.dat new file mode 100644 index 0000000..c5769e3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/testinfo.dat @@ -0,0 +1,24 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateMutexW / ReleaseMutex +Name = Basic validity Tests for CreateMutexW / ReleaseMutex +TYPE = DEFAULT +EXE1 = createmutexw +Description += This test case tests the following things += - Creation of named Mutexes += - Creating multiple handles to a single named Mutex += - Ensuring that these handles work interchangeably += - Setting bInitialOwnerFlag to TRUE will cause the += initial call to a Wait function on the same Mutex += to actually wait. += - Waiting on a Mutex that a thread already owns should += not block. += - Create Named mutex with empty string ("") += - Create Named mutex with string of MAX_PATH length += - Calling RelaseMutex with invalid Mutex handles and += valid but unowned Mutexes. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/CMakeLists.txt new file mode 100644 index 0000000..869f813 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + parentProcess.cpp +) + +add_executable(paltest_createprocessa_test1 + ${TESTSOURCES} +) + +add_dependencies(paltest_createprocessa_test1 coreclrpal) + +target_link_libraries(paltest_createprocessa_test1 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + childProcess.cpp +) + +add_executable(paltest_createprocessa_test1_child + ${HELPERSOURCES} +) + +add_dependencies(paltest_createprocessa_test1_child coreclrpal) + +target_link_libraries(paltest_createprocessa_test1_child + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/childProcess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/childProcess.cpp new file mode 100644 index 0000000..ccbb050 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/childProcess.cpp @@ -0,0 +1,131 @@ +// 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. + +/*============================================================ +** +** Source: CreateProcessA/test1/childprocess.c +** +** Purpose: Test to ensure CreateProcessA starts a new process. This test +** launches a child process, and examines a file written by the child. +** This code is the child code. +** +** Dependencies: GetCurrentDirectory +** strlen +** fopen +** fclose +** fprintf +** + +** +**=========================================================*/ + +#include + +const char *szCommonFileA = "childdata.tmp"; + +const char *szPathDelimA = "\\"; + +const char *szCommonStringA = "058d2d057111a313aa82401c2e856002\0"; + +/* + * Take two wide strings representing file and directory names + * (dirName, fileName), join the strings with the appropriate path + * delimiter and populate a wide character buffer (absPathName) with + * the resulting string. + * + * Returns: The number of wide characters in the resulting string. + * 0 is returned on Error. + */ +int +mkAbsoluteFilenameA ( + LPSTR dirName, + DWORD dwDirLength, + LPCSTR fileName, + DWORD dwFileLength, + LPSTR absPathName ) +{ + extern const char *szPathDelimA; + + DWORD sizeDN, sizeFN, sizeAPN; + + sizeDN = strlen( dirName ); + sizeFN = strlen( fileName ); + sizeAPN = (sizeDN + 1 + sizeFN + 1); + + /* insure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */ + if ( sizeAPN > _MAX_PATH ) + { + return ( 0 ); + } + + strncpy(absPathName, dirName, dwDirLength +1); + strncpy(absPathName, szPathDelimA, 2); + strncpy(absPathName, fileName, dwFileLength +1); + + return (sizeAPN); + +} + +int __cdecl main( int argc, char **argv ) +{ + + static FILE * fp; + + DWORD dwFileLength; + DWORD dwDirLength; + DWORD dwSize; + + char szDirNameA[_MAX_DIR]; + char szAbsPathNameA[_MAX_PATH]; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + dwDirLength = GetCurrentDirectory( _MAX_PATH, szDirNameA ); + + if (0 == dwDirLength) + { + Fail ("GetCurrentDirectory call failed. Could not get " + "current working directory\n. Exiting.\n"); + } + + dwFileLength = strlen( szCommonFileA ); + + dwSize = mkAbsoluteFilenameA( szDirNameA, dwDirLength, szCommonFileA, + dwFileLength, szAbsPathNameA ); + + if (0 == dwSize) + { + Fail ("Palsuite Code: mkAbsoluteFilename() call failed. Could " + "not build absolute path name to file\n. Exiting.\n"); + } + + if ( NULL == ( fp = fopen ( szAbsPathNameA , "w+" ) ) ) + { + /* + * A return value of NULL indicates an error condition or an + * EOF condition + */ + Fail ("%s unable to open %s for writing. Exiting.\n", argv[0] + , szAbsPathNameA ); + } + + if ( 0 >= ( fprintf ( fp, "%s", szCommonStringA ))) + { + Fail("%s unable to write to %s. Exiting.\n", argv[0] + , szAbsPathNameA ); + } + + if (0 != (fclose ( fp ))) + { + Fail ("%s unable to close file %s. Pid may not be " + "written to file. Exiting.\n", argv[0], szAbsPathNameA ); + } + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/parentProcess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/parentProcess.cpp new file mode 100644 index 0000000..b0c5808 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/parentProcess.cpp @@ -0,0 +1,201 @@ +// 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. + +/*============================================================ +** +** Source: CreateProcessA/test1/parentprocess.c +** +** Purpose: Test to ensure CreateProcessA starts a new process. This test +** launches a child process, and examines a file written by the child. +** This process (the parent process) reads the file created by the child and +** compares the value the child wrote to the file. (a const char *) +** +** Dependencies: GetCurrentDirectory +** strlen +** WaitForSingleObject +** fopen +** fclose +** Fail +** + +** +**=========================================================*/ + +#include + +const char *szCommonFileA = "childdata.tmp"; + +const char *szChildFileA = "paltest_createprocessa_test1_child"; + +const char *szPathDelimA = "\\"; + +const char *szCommonStringA = "058d2d057111a313aa82401c2e856002\0"; + +/* + * Take two wide strings representing file and directory names + * (dirName, fileName), join the strings with the appropriate path + * delimiter and populate a wide character buffer (absPathName) with + * the resulting string. + * + * Returns: The number of wide characters in the resulting string. + * 0 is returned on Error. + */ +int +mkAbsoluteFilenameA ( + LPSTR dirName, + DWORD dwDirLength, + LPCSTR fileName, + DWORD dwFileLength, + LPSTR absPathName ) +{ + extern const char *szPathDelimA; + + DWORD sizeDN, sizeFN, sizeAPN; + + sizeDN = strlen( dirName ); + sizeFN = strlen( fileName ); + sizeAPN = (sizeDN + 1 + sizeFN + 1); + + /* insure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */ + if ( sizeAPN > _MAX_PATH ) + { + return ( 0 ); + } + + strncpy(absPathName, dirName, dwDirLength +1); + strncpy(absPathName, szPathDelimA, 2); + strncpy(absPathName, fileName, dwFileLength +1); + + return (sizeAPN); + +} + +int __cdecl main( int argc, char **argv ) + +{ + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + static FILE * fp; + + DWORD dwFileLength; + DWORD dwDirLength; + DWORD dwSize; + + size_t cslen; + + char szReadStringA[256]; + + char szDirNameA[_MAX_DIR]; + char absPathBuf[_MAX_PATH]; + char *szAbsPathNameA; + + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + ZeroMemory ( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory ( &pi, sizeof(pi) ); + + szAbsPathNameA=&absPathBuf[0]; + dwFileLength = strlen( szChildFileA ); + + dwDirLength = GetCurrentDirectory(_MAX_PATH, szDirNameA); + + if (0 == dwDirLength) + { + Fail ("GetCurrentDirectory call failed. Could not get " + "current working directory\n. Exiting.\n"); + } + + dwSize = mkAbsoluteFilenameA( szDirNameA, dwDirLength, szChildFileA, + dwFileLength, szAbsPathNameA ); + + if (0 == dwSize) + { + Fail ("Palsuite Code: mkAbsoluteFilename() call failed. Could " + "not build absolute path name to file\n. Exiting.\n"); + } + + if ( !CreateProcessA ( NULL, + szAbsPathNameA, + NULL, + NULL, + FALSE, + CREATE_NEW_CONSOLE, + NULL, + NULL, + &si, + &pi ) + ) + { + Fail ( "CreateProcess call failed. GetLastError returned %d\n", + GetLastError() ); + } + + WaitForSingleObject ( pi.hProcess, INFINITE ); + + szAbsPathNameA=&absPathBuf[0]; + + dwFileLength = strlen( szCommonFileA ); + + dwSize = mkAbsoluteFilenameA( szDirNameA, dwDirLength, szCommonFileA, + dwFileLength, szAbsPathNameA ); + + /* set the string length for the open call*/ + + if (0 == dwSize) + { + Fail ("Palsuite Code: mkAbsoluteFilename() call failed. Could " + "not build absolute path name to file\n. Exiting.\n"); + } + + if ( NULL == ( fp = fopen ( szAbsPathNameA , "r" ) ) ) + { + Fail ("%s\nunable to open %s\nfor reading. Exiting.\n", argv[0], + szAbsPathNameA ); + } + + cslen = strlen ( szCommonStringA ); + + if ( NULL == fgets( szReadStringA, (cslen + 1), fp )) + { + /* + * A return value of NULL indicates an error condition or an + * EOF condition + */ + Fail ("%s\nunable to read file\n%s\nszReadStringA is %s\n" + "Exiting.\n", argv[0], szAbsPathNameA, + szReadStringA ); + + } + if ( 0 != strncmp( szReadStringA, szCommonStringA, cslen )) + { + Fail ("string comparison failed.\n szReadStringA is %s and\n" + "szCommonStringA is %s\n", szReadStringA, + szCommonStringA ); + } + else + { + Trace ("string comparison passed.\n"); + } + + if (0 != (fclose ( fp ))) + { + Trace ("%s unable to close file %s. This may cause a file pointer " + "leak. Continuing.\n", argv[0], szAbsPathNameA ); + } + + /* Close process and thread handle */ + CloseHandle ( pi.hProcess ); + CloseHandle ( pi.hThread ); + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/testinfo.dat new file mode 100644 index 0000000..02c2544 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateProcessA +Name = Positive Test for CreateProcessA +TYPE = DEFAULT +EXE1 = parentprocess +EXE2 = childprocess +Description += Test the CreateProcessA function. The test executes the childprocess += program. The childprocess program launches and writes a const char string += to a file childdata. The parent waits for the completion of childprocess += and then reads the string from the childdata file. If the string in the += file matches it's copy of the const char string, then the test succeeds. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/CMakeLists.txt new file mode 100644 index 0000000..20c1343 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + parentprocess.cpp +) + +add_executable(paltest_createprocessa_test2 + ${TESTSOURCES} +) + +add_dependencies(paltest_createprocessa_test2 coreclrpal) + +target_link_libraries(paltest_createprocessa_test2 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + childprocess.cpp +) + +add_executable(paltest_createprocessa_test2_child + ${HELPERSOURCES} +) + +add_dependencies(paltest_createprocessa_test2_child coreclrpal) + +target_link_libraries(paltest_createprocessa_test2_child + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/childprocess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/childprocess.cpp new file mode 100644 index 0000000..baa20c2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/childprocess.cpp @@ -0,0 +1,69 @@ +// 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. + +/*============================================================ +** +** Source: createprocessa/test2/childprocess.c +** +** Purpose: This child process reads a string from stdin +** and writes it out to stdout & stderr +** +** Dependencies: memset +** fgets +** gputs +** + +** +**=========================================================*/ + +#include +#include "test2.h" + + + +int __cdecl main( int argc, char **argv ) +{ + int iRetCode = EXIT_OK_CODE; /* preset exit code to OK */ + char szBuf[BUF_LEN]; + + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + if (argc != 4) + { + return EXIT_ERR_CODE3; + } + + if (strcmp(argv[1], szArg1) != 0 + || strcmp(argv[2], szArg2) != 0 + || strcmp(argv[3], szArg3) != 0) + { + return EXIT_ERR_CODE4; + } + + + memset(szBuf, 0, BUF_LEN); + + /* Read the string that was written by the parent */ + if (fgets(szBuf, BUF_LEN, stdin) == NULL) + { + return EXIT_ERR_CODE1; + } + + /* Write the string out to the stdout & stderr pipes */ + if (fputs(szBuf, stdout) == EOF + || fputs(szBuf, stderr) == EOF) + { + return EXIT_ERR_CODE2; + } + + /* The exit code will indicate success or failure */ + PAL_TerminateEx(iRetCode); + + /* Return special exit code to indicate success or failure */ + return iRetCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/parentprocess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/parentprocess.cpp new file mode 100644 index 0000000..ef3340c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/parentprocess.cpp @@ -0,0 +1,243 @@ +// 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. + +/*============================================================ +** +** Source: createprocessa/test2/parentprocess.c +** +** Purpose: Test the following features of CreateProcessA: +** - Check to see if hProcess & hThread are set in +** return PROCESS_INFORMATION structure +** - Check to see if stdin, stdout, & stderr handles +** are used when STARTF_USESTDHANDLES is specified +** in STARUPINFO flags and bInheritHandles = TRUE +** - Check to see that proper arguments are passed to +** child process +** +** Dependencies: CreatePipe +** strcpy, strlen, strncmp, memset +** WaitForSingleObject +** WriteFile, ReadFile +** GetExitCodeProcess +** + +** +**=========================================================*/ + +#include +#include "test2.h" + + + +int __cdecl main( int argc, char **argv ) +{ + + /******************************************* + * Declarations + *******************************************/ + STARTUPINFO si; + PROCESS_INFORMATION pi; + + HANDLE hTestStdInR = NULL; + HANDLE hTestStdInW = NULL; + HANDLE hTestStdOutR = NULL; + HANDLE hTestStdOutW = NULL; + HANDLE hTestStdErrR = NULL; + HANDLE hTestStdErrW = NULL; + + BOOL bRetVal = FALSE; + DWORD dwBytesWritten = 0; + DWORD dwBytesRead = 0; + DWORD dwExitCode = 0; + + SECURITY_ATTRIBUTES pipeAttributes; + + char szStdOutBuf[BUF_LEN]; + char szStdErrBuf[BUF_LEN]; + char szFullPathNameA[_MAX_PATH]; + + + /******************************************* + * Initialization + *******************************************/ + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/ + pipeAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); + pipeAttributes.lpSecurityDescriptor = NULL; + pipeAttributes.bInheritHandle = TRUE; + + + /*Create a StdIn pipe for child*/ + bRetVal = CreatePipe(&hTestStdInR, /* read handle*/ + &hTestStdInW, /* write handle */ + &pipeAttributes, /* security attributes*/ + 1024); /* pipe size*/ + + if (bRetVal == FALSE) + { + Fail("ERROR: %ld :Unable to create stdin pipe\n", GetLastError()); + } + + + /*Create a StdOut pipe for child*/ + bRetVal = CreatePipe(&hTestStdOutR, /* read handle*/ + &hTestStdOutW, /* write handle */ + &pipeAttributes, /* security attributes*/ + 0); /* pipe size*/ + + if (bRetVal == FALSE) + { + Fail("ERROR: %ld :Unable to create stdout pipe\n", GetLastError()); + } + + + /*Create a StdErr pipe for child*/ + bRetVal = CreatePipe(&hTestStdErrR, /* read handle*/ + &hTestStdErrW, /* write handle */ + &pipeAttributes, /* security attributes*/ + 0); /* pipe size*/ + + if (bRetVal == FALSE) + { + Fail("ERROR: %ld :Unable to create stderr pipe\n", GetLastError()); + } + + /* Zero the data structure space */ + ZeroMemory ( &pi, sizeof(pi) ); + ZeroMemory ( &si, sizeof(si) ); + + /* Set the process flags and standard io handles */ + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = hTestStdInR; + si.hStdOutput = hTestStdOutW; + si.hStdError = hTestStdErrW; + + strcpy(szFullPathNameA, szChildFileA); + strcat(szFullPathNameA, szArgs); + + /******************************************* + * Start Testing + *******************************************/ + + /* Launch the child */ + if ( !CreateProcessA (NULL, szFullPathNameA, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi )) + { + Fail("ERROR: CreateProcess call failed. GetLastError returned %d\n", + GetLastError() ); + } + + /* Check the returned process information for validity */ + if (pi.hProcess == 0 || pi.hThread == 0) + { + Fail("ERROR: CreateProcess Error: Process Handle = %u, Thread Handle = %u\n", + pi.hProcess, pi.hThread); + } + + /* Write the Constructed string to stdin pipe for the child process */ + if (WriteFile(hTestStdInW, szTestString, strlen(szTestString), &dwBytesWritten, NULL) == FALSE + || WriteFile(hTestStdInW, "\n", strlen("\n"), &dwBytesWritten, NULL) == FALSE) + { + Fail("ERROR: %ld :unable to write to write pipe handle " + "hTestStdInW=0x%lx\n", GetLastError(), hTestStdInW); + } + + /* Wait for the child to finish, Max 20 seconds */ + dwExitCode = WaitForSingleObject(pi.hProcess, 20000); + + /* If the child failed then whole thing fails */ + if (dwExitCode != WAIT_OBJECT_0) + { + TerminateProcess(pi.hProcess, 0); + Fail("ERROR: The child failed to run properly.\n"); + } + + /* Check for problems in the child process */ + if (GetExitCodeProcess(pi.hProcess, &dwExitCode) == FALSE) + { + Fail("ERROR: Call to GetExitCodeProcess failed.\n"); + } + else if (dwExitCode == EXIT_ERR_CODE1) + { + Fail("ERROR: The Child process could not reead the string " + "written to the stdin pipe.\n"); + } + else if (dwExitCode == EXIT_ERR_CODE2) + { + Fail("ERROR: The Child process could not write the string " + "the stdout pipe or stderr pipe.\n"); + } + else if (dwExitCode == EXIT_ERR_CODE3) + { + Fail("ERROR: The Child received the wrong number of " + "command line arguments.\n"); + } + else if (dwExitCode == EXIT_ERR_CODE4) + { + Fail("ERROR: The Child received the wrong " + "command line arguments.\n"); + } + else if (dwExitCode != EXIT_OK_CODE) + { + Fail("ERROR: Unexpected exit code returned: %u. Child process " + "did not complete its part of the test.\n", dwExitCode); + } + + + /* The child ran ok, so check to see if we received the proper */ + /* strings through the pipes. */ + + /* clear our buffers */ + memset(szStdOutBuf, 0, BUF_LEN); + memset(szStdErrBuf, 0, BUF_LEN); + + /* Read the data back from the child process stdout */ + bRetVal = ReadFile(hTestStdOutR, /* handle to read pipe*/ + szStdOutBuf, /* buffer to write to*/ + BUF_LEN, /* number of bytes to read*/ + &dwBytesRead, /* number of bytes read*/ + NULL); /* overlapped buffer*/ + + /*Read the data back from the child process stderr */ + bRetVal = ReadFile(hTestStdErrR, /* handle to read pipe*/ + szStdErrBuf, /* buffer to write to*/ + BUF_LEN, /* number of bytes to read*/ + &dwBytesRead, /* number of bytes read*/ + NULL); /* overlapped buffer*/ + + + /* Confirm that we recieved the same string that we originally */ + /* wrote to the child and was received on both stdout & stderr.*/ + if (strncmp(szTestString, szStdOutBuf, strlen(szTestString)) != 0 + || strncmp(szTestString, szStdErrBuf, strlen(szTestString)) != 0) + { + Fail("ERROR: The data read back from child does not match " + "what was written. STDOUT: %s STDERR: %s\n", + szStdOutBuf, szStdErrBuf); + } + + + /******************************************* + * Clean Up + *******************************************/ + + /* Close process and thread handle */ + CloseHandle ( pi.hProcess ); + CloseHandle ( pi.hThread ); + + CloseHandle(hTestStdInR); + CloseHandle(hTestStdInW); + CloseHandle(hTestStdOutR); + CloseHandle(hTestStdOutW); + CloseHandle(hTestStdErrR); + CloseHandle(hTestStdErrW); + + PAL_Terminate(); + return ( PASS ); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/test2.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/test2.h new file mode 100644 index 0000000..8cdff3b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/test2.h @@ -0,0 +1,72 @@ +// 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. + +/*============================================================ +** +** Source: test2.h +** + +** +**===========================================================*/ + + +const char *szChildFileA = "paltest_createprocessa_test2_child"; +const char *szArgs = " A B C"; +const char *szArg1 = "A"; +const char *szArg2 = "B"; +const char *szArg3 = "C"; + +const char *szPathDelimA = "\\"; + +const char *szTestString = "Copyright (c) Microsoft"; + +const DWORD EXIT_OK_CODE = 100; +const DWORD EXIT_ERR_CODE1 = 101; +const DWORD EXIT_ERR_CODE2 = 102; +const DWORD EXIT_ERR_CODE3 = 103; +const DWORD EXIT_ERR_CODE4 = 104; +const DWORD EXIT_ERR_CODE5 = 105; + +#define BUF_LEN 64 + +/* + * Take two wide strings representing file and directory names + * (dirName, fileName), join the strings with the appropriate path + * delimiter and populate a wide character buffer (absPathName) with + * the resulting string. + * + * Returns: The number of wide characters in the resulting string. + * 0 is returned on Error. + */ +int +mkAbsoluteFilenameA ( + LPSTR dirName, + DWORD dwDirLength, + LPCSTR fileName, + DWORD dwFileLength, + LPSTR absPathName ) +{ + extern const char *szPathDelimA; + + DWORD sizeDN; + DWORD sizeFN; + DWORD sizeAPN; + + sizeDN = strlen( dirName ); + sizeFN = strlen( fileName ); + sizeAPN = (sizeDN + 1 + sizeFN + 1); + + /* insure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */ + if ( sizeAPN > _MAX_PATH ) + { + return ( 0 ); + } + + strncpy(absPathName, dirName, dwDirLength +1); + strcat(absPathName, szPathDelimA); + strcat(absPathName, fileName); + + return (sizeAPN); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/testinfo.dat new file mode 100644 index 0000000..23fcdf9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessA/test2/testinfo.dat @@ -0,0 +1,20 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateProcessA +Name = PROCESS_INFORMATION and HANDLE Inheritance +TYPE = DEFAULT +EXE1 = parentprocess +EXE2 = childprocess +Description += Test the following features of CreateProcessA: += - Check to see if hProcess & hThread are set in += return PROCESS_INFORMATION structure += - Check to see if stdin, stdout, & stderr handles += are used when STARTF_USESTDHANDLES is specified += in STARUPINFO flags and bInheritHandles = TRUE += - Check to see that proper arguments are passed to += child process diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/CMakeLists.txt new file mode 100644 index 0000000..1a84eb2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + parentProcess.cpp +) + +add_executable(paltest_createprocessw_test1 + ${TESTSOURCES} +) + +add_dependencies(paltest_createprocessw_test1 coreclrpal) + +target_link_libraries(paltest_createprocessw_test1 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + childProcess.cpp +) + +add_executable(paltest_createprocessw_test1_child + ${HELPERSOURCES} +) + +add_dependencies(paltest_createprocessw_test1_child coreclrpal) + +target_link_libraries(paltest_createprocessw_test1_child + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.cpp new file mode 100644 index 0000000..a7730c6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.cpp @@ -0,0 +1,150 @@ +// 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. + +/*============================================================ +** +** Source: CreateProcessW/test1/childprocess.c +** +** Purpose: Test to ensure CreateProcessW starts a new process. This test +** launches a child process, and examines a file written by the child. +** This code is the child code. +** +** Dependencies: GetCurrentDirectory +** MultiByteToWideChar +** wcslen +** strlen +** WideCharToMultiByte +** fopen +** fclose +** fprintf +** + +** +**=========================================================*/ + +#define UNICODE +#include + +const WCHAR szCommonFileW[] = + {'c','h','i','l','d','d','a','t','a','.','t','m','p','\0'}; + +const WCHAR szPathDelimW[] = {'\\','\0'}; + +const char *szCommonStringA = "058d2d057111a313aa82401c2e856002\0"; + +/* + * Take two wide strings representing file and directory names + * (dirName, fileName), join the strings with the appropriate path + * delimiter and populate a wide character buffer (absPathName) with + * the resulting string. + * + * Returns: The number of wide characters in the resulting string. + * 0 is returned on Error. + */ +int +mkAbsoluteFilenameW ( + LPWSTR dirName, + DWORD dwDirLength, + LPCWSTR fileName, + DWORD dwFileLength, + LPWSTR absPathName ) +{ + extern const WCHAR szPathDelimW[]; + + DWORD sizeDN, sizeFN, sizeAPN; + + sizeDN = wcslen( dirName ); + sizeFN = wcslen( fileName ); + sizeAPN = (sizeDN + 1 + sizeFN + 1); + + /* insure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */ + if ( sizeAPN > _MAX_PATH ) + { + return ( 0 ); + } + + wcsncpy(absPathName, dirName, dwDirLength +1); + wcsncpy(absPathName, szPathDelimW, 2); + wcsncpy(absPathName, fileName, dwFileLength +1); + + return (sizeAPN); + +} + +int __cdecl main( int argc, char **argv ) +{ + + static FILE * fp; + + DWORD dwFileLength; + DWORD dwDirLength; + DWORD dwSize; + + char *szAbsPathNameA; + WCHAR szDirNameW[_MAX_DIR]; + WCHAR szAbsPathNameW[_MAX_PATH]; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + dwDirLength = GetCurrentDirectory( _MAX_PATH, szDirNameW ); + + if (0 == dwDirLength) + { + Fail ("GetCurrentDirectory call failed. Could not get " + "current working directory\n. Exiting.\n"); + } + + dwFileLength = wcslen( szCommonFileW ); + + dwSize = mkAbsoluteFilenameW( szDirNameW, dwDirLength, szCommonFileW, + dwFileLength, szAbsPathNameW ); + + if (0 == dwSize) + { + Fail ("Palsuite Code: mkAbsoluteFilename() call failed. Could " + "not build absolute path name to file\n. Exiting.\n"); + } + + /* set the string length for the open call */ + szAbsPathNameA = (char*)malloc(dwSize +1); + + if (NULL == szAbsPathNameA) + { + Fail ("Unable to malloc (%d) bytes. Exiting\n", (dwSize +1) ); + } + + WideCharToMultiByte (CP_ACP, 0, szAbsPathNameW, -1, szAbsPathNameA, + (dwSize + 1), NULL, NULL); + + if ( NULL == ( fp = fopen ( szAbsPathNameA , "w+" ) ) ) + { + /* + * A return value of NULL indicates an error condition or an + * EOF condition + */ + Fail ("%s unable to open %s for writing. Exiting.\n", argv[0] + , szAbsPathNameA ); + } + + free (szAbsPathNameA); + + if ( 0 >= ( fprintf ( fp, "%s", szCommonStringA ))) + { + Fail("%s unable to write to %s. Exiting.\n", argv[0] + , szAbsPathNameA ); + } + + if (0 != (fclose ( fp ))) + { + Fail ("%s unable to close file %s. Pid may not be " + "written to file. Exiting.\n", argv[0], szAbsPathNameA ); + } + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/parentProcess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/parentProcess.cpp new file mode 100644 index 0000000..db1fb63 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/parentProcess.cpp @@ -0,0 +1,210 @@ +// 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. + +/*============================================================ +** +** Source: CreateProcessW/test1/parentprocess.c +** +** Purpose: Test to ensure CreateProcessW starts a new process. This test +** launches a child process, and examines a file written by the child. +** This process (the parent process) reads the file created by the child and +** compares the value the child wrote to the file. (a const char *) +** +** Dependencies: GetCurrentDirectory +** MultiByteToWideChar +** wcslen +** strlen +** WideCharToMultiByte +** WaitForSingleObject +** fopen +** fclose +** Fail +** + +** +**=========================================================*/ + +#define UNICODE +#include + +const WCHAR szCommonFileW[] = + {'c','h','i','l','d','d','a','t','a','.','t','m','p','\0'}; + +const WCHAR szChildFileW[] = u"paltest_createprocessw_test1_child"; + +const WCHAR szPathDelimW[] = {'\\','\0'}; + +const char *szCommonStringA = "058d2d057111a313aa82401c2e856002\0"; + +/* + * Take two wide strings representing file and directory names + * (dirName, fileName), join the strings with the appropriate path + * delimiter and populate a wide character buffer (absPathName) with + * the resulting string. + * + * Returns: The number of wide characters in the resulting string. + * 0 is returned on Error. + */ +int +mkAbsoluteFilenameW ( + LPWSTR dirName, + DWORD dwDirLength, + LPCWSTR fileName, + DWORD dwFileLength, + LPWSTR absPathName ) +{ + extern const WCHAR szPathDelimW[]; + + DWORD sizeDN, sizeFN, sizeAPN; + + sizeDN = wcslen( dirName ); + sizeFN = wcslen( fileName ); + sizeAPN = (sizeDN + 1 + sizeFN + 1); + + /* insure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */ + if ( sizeAPN > _MAX_PATH ) + { + return ( 0 ); + } + + wcsncpy(absPathName, dirName, dwDirLength +1); + wcsncpy(absPathName, szPathDelimW, 2); + wcsncpy(absPathName, fileName, dwFileLength +1); + + return (sizeAPN); + +} + +int __cdecl main( int argc, char **argv ) + +{ + + STARTUPINFOW si; + PROCESS_INFORMATION pi; + + static FILE * fp; + + DWORD dwFileLength; + DWORD dwDirLength; + DWORD dwSize; + + size_t cslen; + + char szReadStringA[256]; + + char szAbsPathNameA[_MAX_PATH]; + WCHAR szDirNameW[_MAX_DIR]; + WCHAR absPathBuf[_MAX_PATH]; + WCHAR *szAbsPathNameW; + + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + ZeroMemory ( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory ( &pi, sizeof(pi) ); + + szAbsPathNameW=&absPathBuf[0]; + dwFileLength = wcslen( szChildFileW ); + + dwDirLength = GetCurrentDirectory(_MAX_PATH, szDirNameW); + + if (0 == dwDirLength) + { + Fail ("GetCurrentDirectory call failed. Could not get " + "current working directory\n. Exiting.\n"); + } + + dwSize = mkAbsoluteFilenameW( szDirNameW, dwDirLength, szChildFileW, + dwFileLength, szAbsPathNameW ); + + if (0 == dwSize) + { + Fail ("Palsuite Code: mkAbsoluteFilename() call failed. Could " + "not build absolute path name to file\n. Exiting.\n"); + } + + if ( !CreateProcessW ( NULL, + szAbsPathNameW, + NULL, + NULL, + FALSE, + CREATE_NEW_CONSOLE, + NULL, + NULL, + &si, + &pi ) + ) + { + Fail ( "CreateProcess call failed. GetLastError returned %d\n", + GetLastError() ); + } + + WaitForSingleObject ( pi.hProcess, INFINITE ); + + szAbsPathNameW=&absPathBuf[0]; + + dwFileLength = wcslen( szCommonFileW ); + + dwSize = mkAbsoluteFilenameW( szDirNameW, dwDirLength, szCommonFileW, + dwFileLength, szAbsPathNameW ); + + /* set the string length for the open call*/ + + if (0 == dwSize) + { + Fail ("Palsuite Code: mkAbsoluteFilename() call failed. Could " + "not build absolute path name to file\n. Exiting.\n"); + } + + WideCharToMultiByte (CP_ACP, 0, szAbsPathNameW, -1, szAbsPathNameA, + (dwSize + 1), NULL, NULL); + + if ( NULL == ( fp = fopen ( szAbsPathNameA , "r" ) ) ) + { + Fail ("%s\nunable to open %s\nfor reading. Exiting.\n", argv[0], + szAbsPathNameA ); + } + + cslen = strlen ( szCommonStringA ); + + if ( NULL == fgets( szReadStringA, (cslen + 1), fp )) + { + /* + * A return value of NULL indicates an error condition or an + * EOF condition + */ + Fail ("%s\nunable to read file\n%s\nszReadStringA is %s\n" + "Exiting.\n", argv[0], szAbsPathNameA, + szReadStringA ); + } + + if ( 0 != strncmp( szReadStringA, szCommonStringA, cslen )) + { + Fail ("string comparison failed.\n szReadStringA is %s and\n" + "szCommonStringA is %s\n", szReadStringA, + szCommonStringA ); + } + else + { + Trace ("string comparison passed.\n"); + } + + if (0 != (fclose ( fp ))) + { + Trace ("%s unable to close file %s. This may cause a file pointer " + "leak. Continuing.\n", argv[0], szAbsPathNameA ); + } + + /* Close process and thread handle */ + CloseHandle ( pi.hProcess ); + CloseHandle ( pi.hThread ); + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/testinfo.dat new file mode 100644 index 0000000..2acf2c9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateProcessW +Name = Positive Test for CreateProcessW +TYPE = DEFAULT +EXE1 = parentprocess +EXE2 = childprocess +Description += Test the CreateProcessW function. The test executes the childprocess += program. The childprocess program launches and writes a const char string += to a file childdata. The parent waits for the completion of childprocess += and then reads the string from the childdata file. If the string in the += file matches it's copy of the const char string, then the test succeeds. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/CMakeLists.txt new file mode 100644 index 0000000..643d5eb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + parentprocess.cpp +) + +add_executable(paltest_createprocessw_test2 + ${TESTSOURCES} +) + +add_dependencies(paltest_createprocessw_test2 coreclrpal) + +target_link_libraries(paltest_createprocessw_test2 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + childprocess.cpp +) + +add_executable(paltest_createprocessw_test2_child + ${HELPERSOURCES} +) + +add_dependencies(paltest_createprocessw_test2_child coreclrpal) + +target_link_libraries(paltest_createprocessw_test2_child + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/childprocess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/childprocess.cpp new file mode 100644 index 0000000..b4ab936 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/childprocess.cpp @@ -0,0 +1,78 @@ +// 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. + +/*============================================================ +** +** Source: createprocessw/test2/childprocess.c +** +** Purpose: This child process reads a string from stdin +** and writes it out to stdout & stderr +** +** Dependencies: memset +** fgets +** gputs +** + +** +**=========================================================*/ + +#define UNICODE +#include +#include "test2.h" + + +int __cdecl main( int argc, char **argv ) +{ + int iRetCode = EXIT_OK_CODE; /* preset exit code to OK */ + char szBuf[BUF_LEN]; + + WCHAR *swzParam1, *swzParam2, *swzParam3 = NULL; + + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + if (argc != 4) + { + return EXIT_ERR_CODE3; + } + + swzParam1 = convert(argv[1]); + swzParam2 = convert(argv[2]); + swzParam3 = convert(argv[3]); + + if (wcscmp(swzParam1, szArg1) != 0 + || wcscmp(swzParam2, szArg2) != 0 + || wcscmp(swzParam3, szArg3) != 0) + { + return EXIT_ERR_CODE4; + } + + free(swzParam1); + free(swzParam2); + free(swzParam3); + + memset(szBuf, 0, BUF_LEN); + + /* Read the string that was written by the parent */ + if (fgets(szBuf, BUF_LEN, stdin) == NULL) + { + return EXIT_ERR_CODE1; + } + + + /* Write the string out to the stdout & stderr pipes */ + if (fputs(szBuf, stdout) == EOF + || fputs(szBuf, stderr) == EOF) + { + return EXIT_ERR_CODE2; + } + + /* The exit code will indicate success or failure */ + PAL_TerminateEx(iRetCode); + + /* Return special exit code to indicate success or failure */ + return iRetCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/parentprocess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/parentprocess.cpp new file mode 100644 index 0000000..439b7b5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/parentprocess.cpp @@ -0,0 +1,245 @@ +// 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. + +/*============================================================ +** +** Source: createprocessw/test2/parentprocess.c +** +** Purpose: Test the following features of CreateProcessW: +** - Check to see if hProcess & hThread are set in +** return PROCESS_INFORMATION structure +** - Check to see if stdin, stdout, & stderr handles +** are used when STARTF_USESTDHANDLES is specified +** in STARUPINFO flags and bInheritHandles = TRUE +** - Check to see that proper arguments are passed to +** child process +** +** Dependencies: CreatePipe +** strcpy, strlen, strncmp, memset +** WaitForSingleObject +** WriteFile, ReadFile +** GetExitCodeProcess +** + +** +**=========================================================*/ + +#define UNICODE +#include +#include "test2.h" + + + +int __cdecl main( int argc, char **argv ) +{ + + /******************************************* + * Declarations + *******************************************/ + STARTUPINFO si; + PROCESS_INFORMATION pi; + + HANDLE hTestStdInR = NULL; + HANDLE hTestStdInW = NULL; + HANDLE hTestStdOutR = NULL; + HANDLE hTestStdOutW = NULL; + HANDLE hTestStdErrR = NULL; + HANDLE hTestStdErrW = NULL; + + BOOL bRetVal = FALSE; + DWORD dwBytesWritten = 0; + DWORD dwBytesRead = 0; + DWORD dwExitCode = 0; + + SECURITY_ATTRIBUTES pipeAttributes; + + char szStdOutBuf[BUF_LEN]; + char szStdErrBuf[BUF_LEN]; + WCHAR szFullPathNameW[_MAX_PATH]; + + + /******************************************* + * Initialization + *******************************************/ + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/ + pipeAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); + pipeAttributes.lpSecurityDescriptor = NULL; + pipeAttributes.bInheritHandle = TRUE; + + + /*Create a StdIn pipe for child*/ + bRetVal = CreatePipe(&hTestStdInR, /* read handle*/ + &hTestStdInW, /* write handle */ + &pipeAttributes, /* security attributes*/ + 1024); /* pipe size*/ + + if (bRetVal == FALSE) + { + Fail("ERROR: %ld :Unable to create stdin pipe\n", GetLastError()); + } + + + /*Create a StdOut pipe for child*/ + bRetVal = CreatePipe(&hTestStdOutR, /* read handle*/ + &hTestStdOutW, /* write handle */ + &pipeAttributes, /* security attributes*/ + 0); /* pipe size*/ + + if (bRetVal == FALSE) + { + Fail("ERROR: %ld :Unable to create stdout pipe\n", GetLastError()); + } + + + /*Create a StdErr pipe for child*/ + bRetVal = CreatePipe(&hTestStdErrR, /* read handle*/ + &hTestStdErrW, /* write handle */ + &pipeAttributes, /* security attributes*/ + 0); /* pipe size*/ + + if (bRetVal == FALSE) + { + Fail("ERROR: %ld :Unable to create stderr pipe\n", GetLastError()); + } + + /* Zero the data structure space */ + ZeroMemory ( &pi, sizeof(pi) ); + ZeroMemory ( &si, sizeof(si) ); + + /* Set the process flags and standard io handles */ + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = hTestStdInR; + si.hStdOutput = hTestStdOutW; + si.hStdError = hTestStdErrW; + + wcscpy(szFullPathNameW, szChildFileW); + wcscat(szFullPathNameW, szArgs); + + /******************************************* + * Start Testing + *******************************************/ + + /* Launch the child */ + if ( !CreateProcess (NULL, szFullPathNameW, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi )) + { + Fail("ERROR: CreateProcess call failed. GetLastError returned %d\n", + GetLastError() ); + } + + /* Check the returned process information for validity */ + if (pi.hProcess == 0 || pi.hThread == 0) + { + Fail("ERROR: CreateProcess Error: Process Handle = %u, Thread Handle = %u\n", + pi.hProcess, pi.hThread); + } + + + /* Write the Constructed string to stdin pipe for the child process */ + if (WriteFile(hTestStdInW, szTestString, strlen(szTestString), &dwBytesWritten, NULL) == FALSE + || WriteFile(hTestStdInW, "\n", strlen("\n"), &dwBytesWritten, NULL) == FALSE) + { + Fail("ERROR: %ld :unable to write to write pipe handle " + "hTestStdInW=0x%lx\n", GetLastError(), hTestStdInW); + } + + /* Wait for the child to finish, Max 20 seconds */ + dwExitCode = WaitForSingleObject(pi.hProcess, 20000); + + /* If the child failed then whole thing fails */ + if (dwExitCode != WAIT_OBJECT_0) + { + TerminateProcess(pi.hProcess, 0); + Fail("ERROR: The child failed to run properly.\n"); + } + + /* Check for problems in the child process */ + if (GetExitCodeProcess(pi.hProcess, &dwExitCode) == FALSE) + { + Fail("ERROR: Call to GetExitCodeProcess failed.\n"); + } + else if (dwExitCode == EXIT_ERR_CODE1) + { + Fail("ERROR: The Child process could not reead the string " + "written to the stdin pipe.\n"); + } + else if (dwExitCode == EXIT_ERR_CODE2) + { + Fail("ERROR: The Child process could not write the string " + "the stdout pipe or stderr pipe.\n"); + } + else if (dwExitCode == EXIT_ERR_CODE3) + { + Fail("ERROR: The Child received the wrong number of " + "command line arguments.\n"); + } + else if (dwExitCode == EXIT_ERR_CODE4) + { + Fail("ERROR: The Child received the wrong " + "command line arguments.\n"); + } + else if (dwExitCode != EXIT_OK_CODE) + { + Fail("ERROR: Unexpected exit code returned: %u. Child process " + "did not complete its part of the test.\n", dwExitCode); + } + + + /* The child ran ok, so check to see if we received the proper */ + /* strings through the pipes. */ + + /* clear our buffers */ + memset(szStdOutBuf, 0, BUF_LEN); + memset(szStdErrBuf, 0, BUF_LEN); + + /* Read the data back from the child process stdout */ + bRetVal = ReadFile(hTestStdOutR, /* handle to read pipe*/ + szStdOutBuf, /* buffer to write to*/ + BUF_LEN, /* number of bytes to read*/ + &dwBytesRead, /* number of bytes read*/ + NULL); /* overlapped buffer*/ + + /*Read the data back from the child process stderr */ + bRetVal = ReadFile(hTestStdErrR, /* handle to read pipe*/ + szStdErrBuf, /* buffer to write to*/ + BUF_LEN, /* number of bytes to read*/ + &dwBytesRead, /* number of bytes read*/ + NULL); /* overlapped buffer*/ + + + /* Confirm that we recieved the same string that we originally */ + /* wrote to the child and was received on both stdout & stderr.*/ + if (strncmp(szTestString, szStdOutBuf, strlen(szTestString)) != 0 + || strncmp(szTestString, szStdErrBuf, strlen(szTestString)) != 0) + { + Fail("ERROR: The data read back from child does not match " + "what was written. STDOUT: %s STDERR: %s\n", + szStdOutBuf, szStdErrBuf); + } + + + /******************************************* + * Clean Up + *******************************************/ + + /* Close process and thread handle */ + CloseHandle ( pi.hProcess ); + CloseHandle ( pi.hThread ); + + CloseHandle(hTestStdInR); + CloseHandle(hTestStdInW); + CloseHandle(hTestStdOutR); + CloseHandle(hTestStdOutW); + CloseHandle(hTestStdErrR); + CloseHandle(hTestStdErrW); + + PAL_Terminate(); + return ( PASS ); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/test2.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/test2.h new file mode 100644 index 0000000..07d40b8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/test2.h @@ -0,0 +1,31 @@ +// 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. + +/*============================================================ +** +** Source: test2.h +** +** + +** +**=========================================================*/ + + +const WCHAR szChildFileW[] = u"paltest_createprocessw_test2_child"; +const WCHAR szArgs[] = {' ',0x41,' ','B',' ','C','\0'}; +const WCHAR szArg1[] = {0x41,'\0'}; +const WCHAR szArg2[] = {'B','\0'}; +const WCHAR szArg3[] = {'C','\0'}; + +const char *szTestString = "An uninteresting test string (it works though)"; + +const DWORD EXIT_OK_CODE = 100; +const DWORD EXIT_ERR_CODE1 = 101; +const DWORD EXIT_ERR_CODE2 = 102; +const DWORD EXIT_ERR_CODE3 = 103; +const DWORD EXIT_ERR_CODE4 = 104; +const DWORD EXIT_ERR_CODE5 = 105; + +#define BUF_LEN 128 + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/testinfo.dat new file mode 100644 index 0000000..d16ae59 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateProcessW/test2/testinfo.dat @@ -0,0 +1,20 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateProcessW +Name = PROCESS_INFORMATION and HANDLE Inheritance +TYPE = DEFAULT +EXE1 = parentprocess +EXE2 = childprocess +Description += Test the following features of CreateProcessW: += - Check to see if hProcess & hThread are set in += return PROCESS_INFORMATION structure += - Check to see if stdin, stdout, & stderr handles += are used when STARTF_USESTDHANDLES is specified += in STARUPINFO flags and bInheritHandles = TRUE += - Check to see that proper arguments are passed to += child process diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CMakeLists.txt new file mode 100644 index 0000000..5585da8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateSemaphore.cpp +) + +add_executable(paltest_createsemaphorea_releasesemaphore_test1 + ${SOURCES} +) + +add_dependencies(paltest_createsemaphorea_releasesemaphore_test1 coreclrpal) + +target_link_libraries(paltest_createsemaphorea_releasesemaphore_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CreateSemaphore.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CreateSemaphore.cpp new file mode 100644 index 0000000..342b15e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CreateSemaphore.cpp @@ -0,0 +1,322 @@ +// 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. + +/*============================================================ +** +** Source: createsemaphorea_releasesemaphore/test1/createsemaphore.c +** +** Purpose: Test Semaphore operation using classic IPC problem: +** "Producer-Consumer Problem". +** +** Dependencies: CreateThread +** ReleaseSemaphore +** WaitForSingleObject +** Sleep +** fflush +** + +** +**=========================================================*/ + +#include + +#define PRODUCTION_TOTAL 26 + +#define _BUF_SIZE 10 + +DWORD dwThreadId; /* consumer thread identifier */ + +HANDLE hThread; /* handle to consumer thread */ + +HANDLE hSemaphoreM; /* handle to mutual exclusion semaphore */ + +HANDLE hSemaphoreE; /* handle to semaphore that counts empty buffer slots */ + +HANDLE hSemaphoreF; /* handle to semaphore that counts full buffer slots */ + +typedef struct Buffer +{ + short readIndex; + short writeIndex; + CHAR message[_BUF_SIZE]; + +} BufferStructure; + +CHAR producerItems[PRODUCTION_TOTAL + 1]; + +CHAR consumerItems[PRODUCTION_TOTAL + 1]; + +/* + * Read next message from the Buffer into provided pointer. + * Returns: 0 on failure, 1 on success. + */ +int +readBuf(BufferStructure *Buffer, char *c) +{ + if( Buffer -> writeIndex == Buffer -> readIndex ) + { + return 0; + } + *c = Buffer -> message[Buffer -> readIndex++]; + Buffer -> readIndex %= _BUF_SIZE; + return 1; +} + +/* + * Write message generated by the producer to Buffer. + * Returns: 0 on failure, 1 on success. + */ +int +writeBuf(BufferStructure *Buffer, CHAR c) +{ + if( ( ((Buffer -> writeIndex) + 1) % _BUF_SIZE) == + (Buffer -> readIndex) ) + { + return 0; + } + Buffer -> message[Buffer -> writeIndex++] = c; + Buffer -> writeIndex %= _BUF_SIZE; + return 1; +} + +/* + * Atomic decrement of semaphore value. + */ +VOID +down(HANDLE hSemaphore) +{ + switch ( (WaitForSingleObject ( + hSemaphore, + 10000))) /* Wait 10 seconds */ + { + case WAIT_OBJECT_0: /* + * Semaphore was signaled. OK to access + * semaphore. + */ + break; + case WAIT_ABANDONED: /* + * Object was mutex object whose owning + * thread has terminated. Shouldn't occur. + */ + Fail("WaitForSingleObject call returned 'WAIT_ABANDONED'.\n" + "Failing Test.\n"); + break; + case WAIT_FAILED: /* WaitForSingleObject function failed */ + Fail("WaitForSingleObject call returned 'WAIT_FAILED'.\n" + "GetLastError returned %d\nFailing Test.\n",GetLastError()); + break; + default: + Fail("WaitForSingleObject call returned an unexpected value.\n" + "Failing Test.\n"); + break; + } + +} + +/* + * Atomic increment of semaphore value. + */ +VOID +up(HANDLE hSemaphore) +{ + if (!ReleaseSemaphore ( + hSemaphore, + 1, + NULL) + ) + { + Fail("ReleaseSemaphore call failed. GetLastError returned %d\n", + GetLastError()); + } +} + +/* + * Sleep 500 milleseconds. + */ +VOID +consumerSleep(VOID) +{ + Sleep(500); +} + +/* + * Sleep between 10 milleseconds. + */ +VOID +producerSleep(VOID) +{ + Sleep(10); +} + +/* + * Produce a message and write the message to Buffer. + */ +VOID +producer(BufferStructure *Buffer) +{ + + int n = 0; + char c; + + while (n < PRODUCTION_TOTAL) + { + c = 'A' + n ; /* Produce Item */ + + down(hSemaphoreE); + down(hSemaphoreM); + + if (writeBuf(Buffer, c)) + { + Trace("Producer produces %c.\n", c); + fflush(stdout); + producerItems[n++] = c; + } + + up(hSemaphoreM); + up(hSemaphoreF); + + producerSleep(); + } + + return; +} + +/* + * Read and "Consume" the messages in Buffer. + */ +DWORD +PALAPI +consumer( LPVOID lpParam ) +{ + int n = 0; + char c; + + consumerSleep(); + + while (n < PRODUCTION_TOTAL) + { + + down(hSemaphoreF); + down(hSemaphoreM); + + if (readBuf((BufferStructure*)lpParam, &c)) + { + Trace("\tConsumer consumes %c.\n", c); + fflush(stdout); + consumerItems[n++] = c; + } + + up(hSemaphoreM); + up(hSemaphoreE); + + consumerSleep(); + } + + return 0; +} + +int __cdecl main (int argc, char **argv) +{ + + BufferStructure Buffer, *pBuffer; + + pBuffer = &Buffer; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + /* + * Create Semaphores + */ + hSemaphoreM = CreateSemaphoreA ( + NULL, + 1, + 1, + NULL); + + if ( NULL == hSemaphoreM ) + { + Fail ( "hSemaphoreM = CreateSemaphoreA () - returned NULL\n" + "Failing Test.\nGetLastError returned %d\n", GetLastError()); + } + + + hSemaphoreE = CreateSemaphoreA ( + NULL, + _BUF_SIZE , + _BUF_SIZE , + NULL); + + if ( NULL == hSemaphoreE ) + { + Fail ( "hSemaphoreE = CreateSemaphoreA () - returned NULL\n" + "Failing Test.\nGetLastError returned %d\n", GetLastError()); + } + + hSemaphoreF = CreateSemaphoreA ( + NULL, + 0, + _BUF_SIZE , + NULL); + + if ( NULL == hSemaphoreF ) + { + Fail ( "hSemaphoreF = CreateSemaphoreA () - returned NULL\n" + "Failing Test.\nGetLastError returned %d\n", GetLastError()); + } + + + /* + * Initialize Buffer + */ + pBuffer->writeIndex = pBuffer->readIndex = 0; + + /* + * Create Consumer + */ + hThread = CreateThread( + NULL, + 0, + consumer, + &Buffer, + 0, + &dwThreadId); + + if ( NULL == hThread ) + { + Fail ( "CreateThread() returned NULL. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + /* + * Start producing + */ + producer(pBuffer); + + /* + * Wait for consumer to complete + */ + WaitForSingleObject (hThread, INFINITE); + + /* + * Compare items produced vs. items consumed + */ + if ( 0 != strncmp (producerItems, consumerItems, PRODUCTION_TOTAL) ) + { + Fail("The producerItems string %s\n and the consumerItems string " + "%s\ndo not match. This could be a problem with the strncmp()" + " function\n FailingTest\nGetLastError() returned %d\n", + producerItems, consumerItems, GetLastError()); + } + + Trace ("producerItems and consumerItems arrays match. All %d\nitems " + "were produced and consumed in order.\nTest passed.\n", + PRODUCTION_TOTAL); + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/testinfo.dat new file mode 100644 index 0000000..880746e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateSemaphoreA / ReleaseSemaphore +Name = Positive Test for CreateSemaphoreA and ReleaseSemaphore +TYPE = DEFAULT +EXE1 = createsemaphore +Description += Implementation of Producer / Consumer IPC problem using CreateSemaphoreA += and ReleaseSemaphore functions. This test case exercises CreateSemaphoreA += , ReleaseSemaphore, CreateThread and WaitForSingleObject functions. += Since there is no way to currently create "pseudo" random events in the += pal, this example does not behave as classic bounded buffers would. This += test case is designed to starve the consumer and have the producer fill += the buffer. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CMakeLists.txt new file mode 100644 index 0000000..55ead1e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateSemaphore.cpp +) + +add_executable(paltest_createsemaphorea_releasesemaphore_test2 + ${SOURCES} +) + +add_dependencies(paltest_createsemaphorea_releasesemaphore_test2 coreclrpal) + +target_link_libraries(paltest_createsemaphorea_releasesemaphore_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CreateSemaphore.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CreateSemaphore.cpp new file mode 100644 index 0000000..bff5b51 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CreateSemaphore.cpp @@ -0,0 +1,313 @@ +// 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. + +/*============================================================ +** +** Source: CreateSemaphoreA_ReleaseSemaphore/test2/createsemaphore.c +** +** Purpose: Test Semaphore operation using classic IPC problem: +** "Producer-Consumer Problem". +** +** Dependencies: CreateThread +** ReleaseSemaphore +** WaitForSingleObject +** Sleep +** fflush +** + +** +**=========================================================*/ + +#include + +#define PRODUCTION_TOTAL 26 + +#define _BUF_SIZE 10 + +DWORD dwThreadId; /* consumer thread identifier */ + +HANDLE hThread; /* handle to consumer thread */ + +HANDLE hSemaphoreM; /* handle to mutual exclusion semaphore */ + +HANDLE hSemaphoreE; /* handle to semaphore that counts empty buffer slots */ + +HANDLE hSemaphoreF; /* handle to semaphore that counts full buffer slots */ + +typedef struct Buffer +{ + short readIndex; + short writeIndex; + CHAR message[_BUF_SIZE]; + +} BufferStructure; + +CHAR producerItems[PRODUCTION_TOTAL + 1]; + +CHAR consumerItems[PRODUCTION_TOTAL + 1]; + +/* + * Read next message from the Buffer into provided pointer. + * Returns: 0 on failure, 1 on success. + */ +int +readBuf(BufferStructure *Buffer, char *c) +{ + if( Buffer -> writeIndex == Buffer -> readIndex ) + { + return 0; + } + *c = Buffer -> message[Buffer -> readIndex++]; + Buffer -> readIndex %= _BUF_SIZE; + return 1; +} + +/* + * Write message generated by the producer to Buffer. + * Returns: 0 on failure, 1 on success. + */ +int +writeBuf(BufferStructure *Buffer, CHAR c) +{ + if( ( ((Buffer -> writeIndex) + 1) % _BUF_SIZE) == + (Buffer -> readIndex) ) + { + return 0; + } + Buffer -> message[Buffer -> writeIndex++] = c; + Buffer -> writeIndex %= _BUF_SIZE; + return 1; +} + +/* + * Atomic decrement of semaphore value. + */ +VOID +down(HANDLE hSemaphore) +{ + switch ( (WaitForSingleObject ( + hSemaphore, + 10000))) + { + case WAIT_OBJECT_0: /* + * Semaphore was signaled. OK to access semaphore. + */ + break; + case WAIT_ABANDONED: /* + * Object was mutex object whose owning + * thread has terminated. Shouldn't occur. + */ + Fail("WaitForSingleObject call returned 'WAIT_ABANDONED'.\n" + "Failing Test.\n"); + break; + case WAIT_FAILED: /* WaitForSingleObject function failed */ + Fail("WaitForSingleObject call returned 'WAIT_FAILED'.\n" + "GetLastError returned %d\nFailing Test.\n",GetLastError()); + break; + default: + Fail("WaitForSingleObject call returned an unexpected value.\n" + "Failing Test.\n"); + break; + } + +} + +/* + * Atomic increment of semaphore value. + */ +VOID +up(HANDLE hSemaphore) +{ + if (!ReleaseSemaphore ( + hSemaphore, + 1, + NULL) + ) + { + Fail("ReleaseSemaphore call failed. GetLastError returned %d\n", + GetLastError()); + } +} + +/* + * Sleep 10 milleseconds. + */ +VOID +consumerSleep(VOID) +{ + Sleep(10); +} + +/* + * Sleep 500 milleseconds. + */ +VOID +producerSleep(VOID) +{ + Sleep(500); +} + +/* + * Produce a message and write the message to Buffer. + */ +VOID +producer(BufferStructure *Buffer) +{ + + int n = 0; + char c; + + while (n < PRODUCTION_TOTAL) + { + c = 'A' + n ; /* Produce Item */ + + down(hSemaphoreE); + down(hSemaphoreM); + + if (writeBuf(Buffer, c)) + { + Trace("Producer produces %c.\n", c); + fflush(stdout); + producerItems[n++] = c; + } + + up(hSemaphoreM); + up(hSemaphoreF); + + producerSleep(); + } + return; +} + +/* + * Read and "Consume" the messages in Buffer. + */ +DWORD +PALAPI +consumer( LPVOID lpParam ) +{ + int n = 0; + char c; + + consumerSleep(); + + while (n < PRODUCTION_TOTAL) + { + + down(hSemaphoreF); + down(hSemaphoreM); + + if (readBuf((BufferStructure*)lpParam, &c)) + { + Trace("\tConsumer consumes %c.\n", c); + fflush(stdout); + consumerItems[n++] = c; + } + + up(hSemaphoreM); + up(hSemaphoreE); + + consumerSleep(); + } + return 0; +} + +int __cdecl main (int argc, char **argv) +{ + + BufferStructure Buffer, *pBuffer; + + pBuffer = &Buffer; + + if(0 != (PAL_Initialize(argc, argv))) + { + return (FAIL); + } + + /* + * Create Semaphores + */ + hSemaphoreM = CreateSemaphoreA ( + NULL, + 1, + 1, + NULL); + + if ( NULL == hSemaphoreM ) + { + Fail ( "hSemaphoreM = CreateSemaphoreA () - returned NULL\n" + "Failing Test.\n"); + } + + hSemaphoreE = CreateSemaphoreA ( + NULL, + _BUF_SIZE , + _BUF_SIZE , + NULL); + + if ( NULL == hSemaphoreE ) + { + Fail ( "hSemaphoreE = CreateSemaphoreA () - returned NULL\n" + "Failing Test.\n"); + } + + hSemaphoreF = CreateSemaphoreA ( + NULL, + 0, + _BUF_SIZE , + NULL); + + if ( NULL == hSemaphoreF ) + { + Fail ( "hSemaphoreF = CreateSemaphoreA () - returned NULL\n" + "Failing Test.\n"); + } + + /* + * Initialize Buffer + */ + pBuffer->writeIndex = pBuffer->readIndex = 0; + + /* + * Create Consumer + */ + hThread = CreateThread( + NULL, + 0, + consumer, + &Buffer, + 0, + &dwThreadId); + + if ( NULL == hThread ) + { + Fail ( "CreateThread() returned NULL. Failing test.\n"); + } + + /* + * Start producing + */ + producer(pBuffer); + + /* + * Wait for consumer to complete + */ + WaitForSingleObject (hThread, INFINITE); + + if ( 0 != strncmp (producerItems, consumerItems, PRODUCTION_TOTAL) ) + { + Fail("The producerItems string %s\n and the consumerItems string " + "%s\ndo not match. This could be a problem with the strncmp()" + " function\n FailingTest\nGetLastError() returned %d\n", + producerItems, consumerItems, GetLastError()); + } + + Trace ("producerItems and consumerItems arrays match. All %d\nitems " + "were produced and consumed in order.\nTest passed.\n", + PRODUCTION_TOTAL); + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/testinfo.dat new file mode 100644 index 0000000..5a6c2e7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateSemaphoreA / ReleaseSemaphore +Name = Positive Test for CreateSemaphoreA and ReleaseSemaphore +TYPE = DEFAULT +EXE1 = createsemaphore +Description += Implementation of Producer / Consumer IPC problem using CreateSemaphoreA += and ReleaseSemaphore functions. This test case exercises CreateSemaphoreA += , ReleaseSemaphore, CreateThread and WaitForSingleObject functions. += Since there is no way to currently create "pseudo" random events in the += pal, this example does not behave as classic bounded buffers would. This += test case is designed to starve the producer and have the consumer fill += the buffer. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/CMakeLists.txt new file mode 100644 index 0000000..a1938df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + createsemaphore.cpp +) + +add_executable(paltest_createsemaphorea_releasesemaphore_test3 + ${SOURCES} +) + +add_dependencies(paltest_createsemaphorea_releasesemaphore_test3 coreclrpal) + +target_link_libraries(paltest_createsemaphorea_releasesemaphore_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/createsemaphore.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/createsemaphore.cpp new file mode 100644 index 0000000..7c6db6b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/createsemaphore.cpp @@ -0,0 +1,200 @@ +// 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. + +/*============================================================================ +** +** Source: createsemaphorea_releasesemaphore/test3/createsemaphore.c +** +** Purpose: Test attributes of CreateSemaphoreA and ReleaseSemaphore. +** Insure for CreateSemaphore that lInitialCount and lMaximumCount +** constraints are respected. Validate that CreateSemaphore rejects +** conditions where initial count and / or maximum count are negative +** and conditions where the initial count is greater than the maximum +** count. For ReleaseSemaphore validate that lpPreviousCount gets set +** to the previous semaphore count and lpPreviousCount can be NULL. +** Also establish ReleaseSemaphore fails when called in a semaphore +** with count equal to lMaximumCount. +** +** +**==========================================================================*/ + +#include + +struct testcase +{ + LPSECURITY_ATTRIBUTES lpSemaphoreAttributes; + LONG lInitialCount; + LONG lMaximumCount; + LPCTSTR lpName; + BOOL bNegativeTest; +}; + +struct testcase testCases[] = +{ + {NULL, -1, 1, NULL, TRUE}, + {NULL, 1, -1, NULL, TRUE}, + {NULL, -1, -1, NULL, TRUE}, + {NULL, 2, 1, NULL, TRUE}, + {NULL, 1, 2, NULL, FALSE}, + {NULL, 0, 10, NULL, FALSE}, + {NULL, INT_MAX - 1, INT_MAX, NULL, FALSE}, + {NULL, INT_MAX, INT_MAX, NULL, FALSE} +}; + +HANDLE hSemaphore[sizeof(testCases)/sizeof(struct testcase)]; + +BOOL cleanup(int index) +{ + int i; + BOOL bRet = TRUE; + for (i = 0; i < index; i++) + { + if (!CloseHandle(hSemaphore[i])) + { + bRet = FALSE; + Trace("PALSUITE ERROR: CloseHandle(%p) call failed for index %d\n", + hSemaphore[i], i); + } + } + return(bRet); +} + +int __cdecl main (int argc, char **argv) +{ + int i; + int j; + + if(0 != (PAL_Initialize(argc, argv))) + { + return (FAIL); + } + /* create semaphores */ + for (i = 0; i < sizeof(testCases)/sizeof(struct testcase); i++) + { + hSemaphore[i] = CreateSemaphoreA (testCases[i].lpSemaphoreAttributes, + testCases[i].lInitialCount, + testCases[i].lMaximumCount, + testCases[i].lpName); + + if (NULL == hSemaphore[i]) + { + if (!testCases[i].bNegativeTest) + { + Trace("PALSUITE ERROR: CreateSemaphoreA('%p' '%ld' '%ld' " + "'%p') returned NULL at index %d.\nGetLastError " + "returned %d.\n", testCases[i].lpSemaphoreAttributes, + testCases[i].lInitialCount, testCases[i].lMaximumCount, + testCases[i].lpName, i, GetLastError()); + if (i > 0) + { + cleanup(i - 1); + } + Fail(""); + } + else + { + continue; + } + } + + /* increment semaphore count to lMaximumCount */ + for (j = testCases[i].lInitialCount; (ULONG)j <= (ULONG)testCases[i].lMaximumCount; + j++) + { + if (testCases[i].lMaximumCount == j) + { + /* Call ReleaseSemaphore once more to ensure ReleaseSemaphore + fails */ + if(ReleaseSemaphore(hSemaphore[i], 1, NULL)) + { + Trace("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') " + "call returned %d\nwhen it should have returned " + "%d.\nThe semaphore's count was %d.\nGetLastError " + "returned %d.\n", hSemaphore[i], 1, NULL, TRUE, + FALSE, j, GetLastError()); + cleanup(i); + Fail(""); + } + } + else + { + int previous; + BOOL bRet = ReleaseSemaphore(hSemaphore[i], 1, &previous); + DWORD dwError = GetLastError(); + + if(!bRet) + { + Trace("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') " + "call returned %d\nwhen it should have returned " + "%d.\nThe semaphore count was %d and it's " + "lMaxCount was %d.\nGetLastError returned %d.\n", + hSemaphore[i], 1, &previous, bRet, TRUE, j, + testCases[i].lMaximumCount, dwError); + cleanup(i); + Fail(""); + } + if (previous != j) + { + Trace("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') " + "call set %p to %d instead of %d.\n The semaphore " + "count was %d and GetLastError returned %d.\n", + hSemaphore[i], 1, &previous, &previous, previous, + j, j, dwError); + cleanup(i); + Fail(""); + } + } + } + + // Skip exhaustive decrement tests for too large an initial count + if(testCases[i].lInitialCount >= INT_MAX - 1) + { + continue; + } + + /* decrement semaphore count to 0 */ + for (j = testCases[i].lMaximumCount; j >= 0; j--) + { + DWORD dwRet = WaitForSingleObject(hSemaphore[i], 0); + DWORD dwError = GetLastError(); + + if (0 == j) + { + /* WaitForSingleObject should report that the + semaphore is nonsignaled */ + if (WAIT_TIMEOUT != dwRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject('%p' '%u') " + "call returned %d\nwhen it should have returned " + "%d.\nThe semaphore's count was %d.\nGetLastError " + "returned %d.\n", hSemaphore[i], 0, dwRet, + WAIT_TIMEOUT, j, dwError); + cleanup(i); + Fail(""); + } + } + else + { + /* WaitForSingleObject should report that the + semaphore is signaled */ + if (WAIT_OBJECT_0 != dwRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject('%p' '%u') " + "call returned %d\nwhen it should have returned " + "%d.\nThe semaphore's count was %d.\nGetLastError " + "returned %d.\n", hSemaphore[i], 0, dwRet, + WAIT_OBJECT_0, j, dwError); + cleanup(i); + Fail(""); + } + } + } + } + PAL_Terminate(); + return (PASS); +} + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/testinfo.dat new file mode 100644 index 0000000..d8cd590 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/testinfo.dat @@ -0,0 +1,20 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateSemaphoreA / ReleaseSemaphore +Name = Positive Test for CreateSemaphoreA and ReleaseSemaphore +TYPE = DEFAULT +EXE1 = createsemaphore +Description += Test attributes of CreateSemaphoreA and ReleaseSemaphore. += Insure for CreateSemaphore that lInitialCount and lMaximumCount += constraints are respected. Validate that CreateSemaphore rejects += conditions where, initial count and / or maximum count are negative += and conditions where the initial count is greater than the maximum += count. For ReleaseSemaphore validate that lpPreviousCount gets set += to the previous semaphore count and lpPreviousCount can be NULL. += Also establish ReleaseSemaphore fails when called in a semaphore += with count equal to lMaximumCount. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CMakeLists.txt new file mode 100644 index 0000000..dbbf165 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateSemaphore.cpp +) + +add_executable(paltest_createsemaphorew_releasesemaphore_test1 + ${SOURCES} +) + +add_dependencies(paltest_createsemaphorew_releasesemaphore_test1 coreclrpal) + +target_link_libraries(paltest_createsemaphorew_releasesemaphore_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.cpp new file mode 100644 index 0000000..854d16d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.cpp @@ -0,0 +1,323 @@ +// 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. + +/*============================================================ +** +** Source: CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.c +** +** Purpose: Test Semaphore operation using classic IPC problem: +** "Producer-Consumer Problem". +** +** Dependencies: CreateThread +** ReleaseSemaphore +** WaitForSingleObject +** Sleep +** fflush +** + +** +**=========================================================*/ + +#define UNICODE +#include + +#define PRODUCTION_TOTAL 26 + +#define _BUF_SIZE 10 + +DWORD dwThreadId; /* consumer thread identifier */ + +HANDLE hThread; /* handle to consumer thread */ + +HANDLE hSemaphoreM; /* handle to mutual exclusion semaphore */ + +HANDLE hSemaphoreE; /* handle to semaphore that counts empty buffer slots */ + +HANDLE hSemaphoreF; /* handle to semaphore that counts full buffer slots */ + +typedef struct Buffer +{ + short readIndex; + short writeIndex; + CHAR message[_BUF_SIZE]; + +} BufferStructure; + +CHAR producerItems[PRODUCTION_TOTAL + 1]; + +CHAR consumerItems[PRODUCTION_TOTAL + 1]; + +/* + * Read next message from the Buffer into provided pointer. + * Returns: 0 on failure, 1 on success. + */ +int +readBuf(BufferStructure *Buffer, char *c) +{ + if( Buffer -> writeIndex == Buffer -> readIndex ) + { + return 0; + } + *c = Buffer -> message[Buffer -> readIndex++]; + Buffer -> readIndex %= _BUF_SIZE; + return 1; +} + +/* + * Write message generated by the producer to Buffer. + * Returns: 0 on failure, 1 on success. + */ +int +writeBuf(BufferStructure *Buffer, CHAR c) +{ + if( ( ((Buffer -> writeIndex) + 1) % _BUF_SIZE) == + (Buffer -> readIndex) ) + { + return 0; + } + Buffer -> message[Buffer -> writeIndex++] = c; + Buffer -> writeIndex %= _BUF_SIZE; + return 1; +} + +/* + * Atomic decrement of semaphore value. + */ +VOID +down(HANDLE hSemaphore) +{ + switch ( (WaitForSingleObject ( + hSemaphore, + 10000))) /* Wait 10 seconds */ + { + case WAIT_OBJECT_0: /* + * Semaphore was signaled. OK to access + * semaphore. + */ + break; + case WAIT_ABANDONED: /* + * Object was mutex object whose owning + * thread has terminated. Shouldn't occur. + */ + Fail("WaitForSingleObject call returned 'WAIT_ABANDONED'.\n" + "Failing Test.\n"); + break; + case WAIT_FAILED: /* WaitForSingleObject function failed */ + Fail("WaitForSingleObject call returned 'WAIT_FAILED'.\n" + "GetLastError returned %d\nFailing Test.\n",GetLastError()); + break; + default: + Fail("WaitForSingleObject call returned an unexpected value.\n" + "Failing Test.\n"); + break; + } + +} + +/* + * Atomic increment of semaphore value. + */ +VOID +up(HANDLE hSemaphore) +{ + if (!ReleaseSemaphore ( + hSemaphore, + 1, + NULL) + ) + { + Fail("ReleaseSemaphore call failed. GetLastError returned %d\n", + GetLastError()); + } +} + +/* + * Sleep 500 milleseconds. + */ +VOID +consumerSleep(VOID) +{ + Sleep(500); +} + +/* + * Sleep between 10 milleseconds. + */ +VOID +producerSleep(VOID) +{ + Sleep(10); +} + +/* + * Produce a message and write the message to Buffer. + */ +VOID +producer(BufferStructure *Buffer) +{ + + int n = 0; + char c; + + while (n < PRODUCTION_TOTAL) + { + c = 'A' + n ; /* Produce Item */ + + down(hSemaphoreE); + down(hSemaphoreM); + + if (writeBuf(Buffer, c)) + { + Trace("Producer produces %c.\n", c); + fflush(stdout); + producerItems[n++] = c; + } + + up(hSemaphoreM); + up(hSemaphoreF); + + producerSleep(); + } + + return; +} + +/* + * Read and "Consume" the messages in Buffer. + */ +DWORD +PALAPI +consumer( LPVOID lpParam ) +{ + int n = 0; + char c; + + consumerSleep(); + + while (n < PRODUCTION_TOTAL) + { + + down(hSemaphoreF); + down(hSemaphoreM); + + if (readBuf((BufferStructure*)lpParam, &c)) + { + Trace("\tConsumer consumes %c.\n", c); + fflush(stdout); + consumerItems[n++] = c; + } + + up(hSemaphoreM); + up(hSemaphoreE); + + consumerSleep(); + } + + return 0; +} + +int __cdecl main (int argc, char **argv) +{ + + BufferStructure Buffer, *pBuffer; + + pBuffer = &Buffer; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + /* + * Create Semaphores + */ + hSemaphoreM = CreateSemaphoreW ( + NULL, + 1, + 1, + NULL); + + if ( NULL == hSemaphoreM ) + { + Fail ( "hSemaphoreM = CreateSemaphoreW () - returned NULL\n" + "Failing Test.\nGetLastError returned %d\n", GetLastError()); + } + + + hSemaphoreE = CreateSemaphoreW ( + NULL, + _BUF_SIZE , + _BUF_SIZE , + NULL); + + if ( NULL == hSemaphoreE ) + { + Fail ( "hSemaphoreE = CreateSemaphoreW () - returned NULL\n" + "Failing Test.\nGetLastError returned %d\n", GetLastError()); + } + + hSemaphoreF = CreateSemaphoreW ( + NULL, + 0, + _BUF_SIZE , + NULL); + + if ( NULL == hSemaphoreF ) + { + Fail ( "hSemaphoreF = CreateSemaphoreW () - returned NULL\n" + "Failing Test.\nGetLastError returned %d\n", GetLastError()); + } + + + /* + * Initialize Buffer + */ + pBuffer->writeIndex = pBuffer->readIndex = 0; + + /* + * Create Consumer + */ + hThread = CreateThread( + NULL, + 0, + consumer, + &Buffer, + 0, + &dwThreadId); + + if ( NULL == hThread ) + { + Fail ( "CreateThread() returned NULL. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + /* + * Start producing + */ + producer(pBuffer); + + /* + * Wait for consumer to complete + */ + WaitForSingleObject (hThread, INFINITE); + + /* + * Compare items produced vs. items consumed + */ + if ( 0 != strncmp (producerItems, consumerItems, PRODUCTION_TOTAL) ) + { + Fail("The producerItems string %s\n and the consumerItems string " + "%s\ndo not match. This could be a problem with the strncmp()" + " function\n FailingTest\nGetLastError() returned %d\n", + producerItems, consumerItems, GetLastError()); + } + + Trace ("producerItems and consumerItems arrays match. All %d\nitems " + "were produced and consumed in order.\nTest passed.\n", + PRODUCTION_TOTAL); + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/testinfo.dat new file mode 100644 index 0000000..9127589 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateSemaphoreW / ReleaseSemaphore +Name = Positive Test for CreateSemaphoreW and ReleaseSemaphore +TYPE = DEFAULT +EXE1 = createsemaphore +Description += Implementation of Producer / Consumer IPC problem using CreateSemaphoreW += and ReleaseSemaphore functions. This test case exercises CreateSemaphoreW += , ReleaseSemaphore, CreateThread and WaitForSingleObject functions. += Since there is no way to currently create "pseudo" random events in the += pal, this example does not behave as classic bounded buffers would. This += test case is designed to starve the consumer and have the producer fill += the buffer. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CMakeLists.txt new file mode 100644 index 0000000..620b6b2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + CreateSemaphore.cpp +) + +add_executable(paltest_createsemaphorew_releasesemaphore_test2 + ${SOURCES} +) + +add_dependencies(paltest_createsemaphorew_releasesemaphore_test2 coreclrpal) + +target_link_libraries(paltest_createsemaphorew_releasesemaphore_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CreateSemaphore.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CreateSemaphore.cpp new file mode 100644 index 0000000..6253273 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CreateSemaphore.cpp @@ -0,0 +1,314 @@ +// 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. + +/*============================================================ +** +** Source: CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.c +** +** Purpose: Test Semaphore operation using classic IPC problem: +** "Producer-Consumer Problem". +** +** Dependencies: CreateThread +** ReleaseSemaphore +** WaitForSingleObject +** Sleep +** fflush +** + +** +**=========================================================*/ + +#define UNICODE +#include + +#define PRODUCTION_TOTAL 26 + +#define _BUF_SIZE 10 + +DWORD dwThreadId; /* consumer thread identifier */ + +HANDLE hThread; /* handle to consumer thread */ + +HANDLE hSemaphoreM; /* handle to mutual exclusion semaphore */ + +HANDLE hSemaphoreE; /* handle to semaphore that counts empty buffer slots */ + +HANDLE hSemaphoreF; /* handle to semaphore that counts full buffer slots */ + +typedef struct Buffer +{ + short readIndex; + short writeIndex; + CHAR message[_BUF_SIZE]; + +} BufferStructure; + +CHAR producerItems[PRODUCTION_TOTAL + 1]; + +CHAR consumerItems[PRODUCTION_TOTAL + 1]; + +/* + * Read next message from the Buffer into provided pointer. + * Returns: 0 on failure, 1 on success. + */ +int +readBuf(BufferStructure *Buffer, char *c) +{ + if( Buffer -> writeIndex == Buffer -> readIndex ) + { + return 0; + } + *c = Buffer -> message[Buffer -> readIndex++]; + Buffer -> readIndex %= _BUF_SIZE; + return 1; +} + +/* + * Write message generated by the producer to Buffer. + * Returns: 0 on failure, 1 on success. + */ +int +writeBuf(BufferStructure *Buffer, CHAR c) +{ + if( ( ((Buffer -> writeIndex) + 1) % _BUF_SIZE) == + (Buffer -> readIndex) ) + { + return 0; + } + Buffer -> message[Buffer -> writeIndex++] = c; + Buffer -> writeIndex %= _BUF_SIZE; + return 1; +} + +/* + * Atomic decrement of semaphore value. + */ +VOID +down(HANDLE hSemaphore) +{ + switch ( (WaitForSingleObject ( + hSemaphore, + 10000))) + { + case WAIT_OBJECT_0: /* + * Semaphore was signaled. OK to access semaphore. + */ + break; + case WAIT_ABANDONED: /* + * Object was mutex object whose owning + * thread has terminated. Shouldn't occur. + */ + Fail("WaitForSingleObject call returned 'WAIT_ABANDONED'.\n" + "Failing Test.\n"); + break; + case WAIT_FAILED: /* WaitForSingleObject function failed */ + Fail("WaitForSingleObject call returned 'WAIT_FAILED'.\n" + "GetLastError returned %d\nFailing Test.\n",GetLastError()); + break; + default: + Fail("WaitForSingleObject call returned an unexpected value.\n" + "Failing Test.\n"); + break; + } + +} + +/* + * Atomic increment of semaphore value. + */ +VOID +up(HANDLE hSemaphore) +{ + if (!ReleaseSemaphore ( + hSemaphore, + 1, + NULL) + ) + { + Fail("ReleaseSemaphore call failed. GetLastError returned %d\n", + GetLastError()); + } +} + +/* + * Sleep 10 milleseconds. + */ +VOID +consumerSleep(VOID) +{ + Sleep(10); +} + +/* + * Sleep 500 milleseconds. + */ +VOID +producerSleep(VOID) +{ + Sleep(500); +} + +/* + * Produce a message and write the message to Buffer. + */ +VOID +producer(BufferStructure *Buffer) +{ + + int n = 0; + char c; + + while (n < PRODUCTION_TOTAL) + { + c = 'A' + n ; /* Produce Item */ + + down(hSemaphoreE); + down(hSemaphoreM); + + if (writeBuf(Buffer, c)) + { + Trace("Producer produces %c.\n", c); + fflush(stdout); + producerItems[n++] = c; + } + + up(hSemaphoreM); + up(hSemaphoreF); + + producerSleep(); + } + return; +} + +/* + * Read and "Consume" the messages in Buffer. + */ +DWORD +PALAPI +consumer( LPVOID lpParam ) +{ + int n = 0; + char c; + + consumerSleep(); + + while (n < PRODUCTION_TOTAL) + { + + down(hSemaphoreF); + down(hSemaphoreM); + + if (readBuf((BufferStructure*)lpParam, &c)) + { + Trace("\tConsumer consumes %c.\n", c); + fflush(stdout); + consumerItems[n++] = c; + } + + up(hSemaphoreM); + up(hSemaphoreE); + + consumerSleep(); + } + return 0; +} + +int __cdecl main (int argc, char **argv) +{ + + BufferStructure Buffer, *pBuffer; + + pBuffer = &Buffer; + + if(0 != (PAL_Initialize(argc, argv))) + { + return (FAIL); + } + + /* + * Create Semaphores + */ + hSemaphoreM = CreateSemaphoreW ( + NULL, + 1, + 1, + NULL); + + if ( NULL == hSemaphoreM ) + { + Fail ( "hSemaphoreM = CreateSemaphoreW () - returned NULL\n" + "Failing Test.\n"); + } + + hSemaphoreE = CreateSemaphoreW ( + NULL, + _BUF_SIZE , + _BUF_SIZE , + NULL); + + if ( NULL == hSemaphoreE ) + { + Fail ( "hSemaphoreE = CreateSemaphoreW () - returned NULL\n" + "Failing Test.\n"); + } + + hSemaphoreF = CreateSemaphoreW ( + NULL, + 0, + _BUF_SIZE , + NULL); + + if ( NULL == hSemaphoreF ) + { + Fail ( "hSemaphoreF = CreateSemaphoreW () - returned NULL\n" + "Failing Test.\n"); + } + + /* + * Initialize Buffer + */ + pBuffer->writeIndex = pBuffer->readIndex = 0; + + /* + * Create Consumer + */ + hThread = CreateThread( + NULL, + 0, + consumer, + &Buffer, + 0, + &dwThreadId); + + if ( NULL == hThread ) + { + Fail ( "CreateThread() returned NULL. Failing test.\n"); + } + + /* + * Start producing + */ + producer(pBuffer); + + /* + * Wait for consumer to complete + */ + WaitForSingleObject (hThread, INFINITE); + + if ( 0 != strncmp (producerItems, consumerItems, PRODUCTION_TOTAL) ) + { + Fail("The producerItems string %s\n and the consumerItems string " + "%s\ndo not match. This could be a problem with the strncmp()" + " function\n FailingTest\nGetLastError() returned %d\n", + producerItems, consumerItems, GetLastError()); + } + + Trace ("producerItems and consumerItems arrays match. All %d\nitems " + "were produced and consumed in order.\nTest passed.\n", + PRODUCTION_TOTAL); + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/testinfo.dat new file mode 100644 index 0000000..32b107f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateSemaphoreW / ReleaseSemaphore +Name = Positive Test for CreateSemaphoreW and ReleaseSemaphore +TYPE = DEFAULT +EXE1 = createsemaphore +Description += Implementation of Producer / Consumer IPC problem using CreateSemaphoreW += and ReleaseSemaphore functions. This test case exercises CreateSemaphoreW += , ReleaseSemaphore, CreateThread and WaitForSingleObject functions. += Since there is no way to currently create "pseudo" random events in the += pal, this example does not behave as classic bounded buffers would. This += test case is designed to starve the producer and have the consumer fill += the buffer. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/CMakeLists.txt new file mode 100644 index 0000000..c4f38fa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + createsemaphore.cpp +) + +add_executable(paltest_createsemaphorew_releasesemaphore_test3 + ${SOURCES} +) + +add_dependencies(paltest_createsemaphorew_releasesemaphore_test3 coreclrpal) + +target_link_libraries(paltest_createsemaphorew_releasesemaphore_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/createsemaphore.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/createsemaphore.cpp new file mode 100644 index 0000000..ea0a5e0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/createsemaphore.cpp @@ -0,0 +1,201 @@ +// 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. + +/*============================================================================ +** +** Source: createsemaphorew_releasesemaphore/test3/createsemaphore.c +** +** Purpose: Test attributes of CreateSemaphoreW and ReleaseSemaphore. +** Insure for CreateSemaphore that lInitialCount and lMaximumCount +** constraints are respected. Validate that CreateSemaphore rejects +** conditions where initial count and / or maximum count are negative +** and conditions where the initial count is greater than the maximum +** count. For ReleaseSemaphore validate that lpPreviousCount gets set +** to the previous semaphore count and lpPreviousCount can be NULL. +** Also establish ReleaseSemaphore fails when called in a semaphore +** with count equal to lMaximumCount. +** +** +**==========================================================================*/ + +#include + +struct testcase +{ + LPSECURITY_ATTRIBUTES lpSemaphoreAttributes; + LONG lInitialCount; + LONG lMaximumCount; + LPCWSTR lpName; + BOOL bNegativeTest; +}; + +struct testcase testCases[] = +{ + {NULL, -1, 1, NULL, TRUE}, + {NULL, 1, -1, NULL, TRUE}, + {NULL, -1, -1, NULL, TRUE}, + {NULL, 2, 1, NULL, TRUE}, + {NULL, 1, 2, NULL, FALSE}, + {NULL, 0, 10, NULL, FALSE}, + {NULL, INT_MAX - 1, INT_MAX, NULL, FALSE}, + {NULL, INT_MAX, INT_MAX, NULL, FALSE} +}; + +HANDLE hSemaphore[sizeof(testCases)/sizeof(struct testcase)]; + +BOOL cleanup(int index) +{ + int i; + BOOL bRet = TRUE; + for (i = 0; i < index; i++) + { + if (!CloseHandle(hSemaphore[i])) + { + bRet = FALSE; + Trace("PALSUITE ERROR: CloseHandle(%p) call failed for index %d\n", + hSemaphore[i], i); + } + } + return(bRet); +} + +int __cdecl main (int argc, char **argv) +{ + int i; + int j; + + if(0 != (PAL_Initialize(argc, argv))) + { + return (FAIL); + } + /* create semaphores */ + for (i = 0; i < sizeof(testCases)/sizeof(struct testcase); i++) + { + hSemaphore[i] = CreateSemaphoreW (testCases[i].lpSemaphoreAttributes, + testCases[i].lInitialCount, + testCases[i].lMaximumCount, + testCases[i].lpName); + + if (NULL == hSemaphore[i]) + { + if (!testCases[i].bNegativeTest) + { + Trace("PALSUITE ERROR: CreateSemaphoreW('%p' '%ld' '%ld' " + "'%p') returned NULL at index %d.\nGetLastError " + "returned %d.\n", testCases[i].lpSemaphoreAttributes, + testCases[i].lInitialCount, testCases[i].lMaximumCount, + testCases[i].lpName, i, GetLastError()); + if (i > 0) + { + cleanup(i - 1); + } + Fail(""); + } + else + { + continue; + } + } + + /* increment semaphore count to lMaximumCount */ + for (j = testCases[i].lInitialCount; (ULONG)j <= (ULONG)testCases[i].lMaximumCount; + j++) + { + if (testCases[i].lMaximumCount == j) + { + /* Call ReleaseSemaphore once more to ensure ReleaseSemaphore + fails */ + if(ReleaseSemaphore(hSemaphore[i], 1, NULL)) + { + Trace("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') " + "call returned %d\nwhen it should have returned " + "%d.\nThe semaphore's count was %d.\nGetLastError " + "returned %d.\n", hSemaphore[i], 1, NULL, TRUE, + FALSE, j, GetLastError()); + cleanup(i); + Fail(""); + } + } + else + { + int previous; + BOOL bRet = ReleaseSemaphore(hSemaphore[i], 1, &previous); + DWORD dwError = GetLastError(); + + if(!bRet) + { + Trace("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') " + "call returned %d\nwhen it should have returned " + "%d.\nThe semaphore count was %d and it's " + "lMaxCount was %d.\nGetLastError returned %d.\n", + hSemaphore[i], 1, &previous, bRet, TRUE, j, + testCases[i].lMaximumCount, dwError); + cleanup(i); + Fail(""); + } + if (previous != j) + { + Trace("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') " + "call set %p to %d instead of %d.\n The semaphore " + "count was %d and GetLastError returned %d.\n", + hSemaphore[i], 1, &previous, &previous, previous, + j, j, dwError); + cleanup(i); + Fail(""); + } + } + } + + // Skip exhaustive decrement tests for too large an initial count + if(testCases[i].lInitialCount >= INT_MAX - 1) + { + continue; + } + + /* decrement semaphore count to 0 */ + for (j = testCases[i].lMaximumCount; j >= 0; j--) + { + DWORD dwRet = WaitForSingleObject(hSemaphore[i], 0); + DWORD dwError = GetLastError(); + + if (0 == j) + { + /* WaitForSingleObject should report that the + semaphore is nonsignaled */ + if (WAIT_TIMEOUT != dwRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject('%p' '%u') " + "call returned %d\nwhen it should have returned " + "%d.\nThe semaphore's count was %d.\nGetLastError " + "returned %d.\n", hSemaphore[i], 0, dwRet, + WAIT_TIMEOUT, j, dwError); + cleanup(i); + Fail(""); + } + } + else + { + /* WaitForSingleObject should report that the + semaphore is signaled */ + if (WAIT_OBJECT_0 != dwRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject('%p' '%u') " + "call returned %d\nwhen it should have returned " + "%d.\nThe semaphore's count was %d.\nGetLastError " + "returned %d.\n", hSemaphore[i], 0, dwRet, + WAIT_OBJECT_0, j, dwError); + cleanup(i); + Fail(""); + } + } + } + } + PAL_Terminate(); + return (PASS); +} + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/testinfo.dat new file mode 100644 index 0000000..beaac95 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/testinfo.dat @@ -0,0 +1,20 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateSemaphoreW / ReleaseSemaphore +Name = Positive Test for CreateSemaphoreW and ReleaseSemaphore +TYPE = DEFAULT +EXE1 = createsemaphore +Description += Test attributes of CreateSemaphoreW and ReleaseSemaphore. += Insure for CreateSemaphore that lInitialCount and lMaximumCount += constraints are respected. Validate that CreateSemaphore rejects += conditions where, initial count and / or maximum count are negative += and conditions where the initial count is greater than the maximum += count. For ReleaseSemaphore validate that lpPreviousCount gets set += to the previous semaphore count and lpPreviousCount can be NULL. += Also establish ReleaseSemaphore fails when called in a semaphore += with count equal to lMaximumCount. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test1/CMakeLists.txt new file mode 100644 index 0000000..16b8d43 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_createthread_test1 + ${SOURCES} +) + +add_dependencies(paltest_createthread_test1 coreclrpal) + +target_link_libraries(paltest_createthread_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test1/test1.cpp new file mode 100644 index 0000000..4084e1f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test1/test1.cpp @@ -0,0 +1,115 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for CreateThread. Call CreateThread and ensure +** that it succeeds. Also check to ensure the paramater is passed +** properly. +** +** +**=========================================================*/ + +#include + +#define LLFORMAT "%llu" + +ULONGLONG dwCreateThreadTestParameter = 0; + +DWORD PALAPI CreateThreadTestThread( LPVOID lpParameter) +{ + DWORD dwRet = 0; + + /* save parameter for test */ + dwCreateThreadTestParameter = (ULONGLONG)lpParameter; + + return dwRet; +} + +BOOL CreateThreadTest() +{ + BOOL bRet = FALSE; + DWORD dwRet = 0; + + LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL; + DWORD dwStackSize = 0; + LPTHREAD_START_ROUTINE lpStartAddress = &CreateThreadTestThread; + LPVOID lpParameter = (LPVOID)lpStartAddress; + DWORD dwCreationFlags = 0; /* run immediately */ + DWORD dwThreadId = 0; + + HANDLE hThread = 0; + + dwCreateThreadTestParameter = 0; + + /* Create a thread, passing the appropriate paramaters as declared + above. + */ + + hThread = CreateThread( lpThreadAttributes, + dwStackSize, + lpStartAddress, + lpParameter, + dwCreationFlags, + &dwThreadId ); + + /* Ensure that the HANDLE is not invalid! */ + if (hThread != INVALID_HANDLE_VALUE) + { + dwRet = WaitForSingleObject(hThread,INFINITE); + + if (dwRet != WAIT_OBJECT_0) + { + Trace("CreateThreadTest:WaitForSingleObject " + "failed (%x)\n",GetLastError()); + } + else + { + /* Check to ensure that the parameter passed to the thread + function is the same in the function as what we passed. + */ + + if (dwCreateThreadTestParameter != (ULONGLONG)lpParameter) + { + Trace("CreateThreadTest:parameter error. The " + "parameter passed should have been " LLFORMAT " but when " + "passed to the Thread function it was " LLFORMAT " . GetLastError[%x]\n", + dwCreateThreadTestParameter,lpParameter, GetLastError()); + } + else + { + bRet = TRUE; + } + + } + CloseHandle(hThread); + } + else + { + Trace("CreateThreadTest:CreateThread failed (%x)\n",GetLastError()); + } + + return bRet; +} + + +int __cdecl main(int argc, char **argv) +{ + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!CreateThreadTest()) + { + Fail ("Test failed\n"); + } + + Trace("Test Passed\n"); + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test1/testinfo.dat new file mode 100644 index 0000000..3ae7062 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateThread +Name = Positive Test for CreateThread +TYPE = DEFAULT +EXE1 = test1 +Description += Test for CreateThread. Call CreateThread and ensure += that it succeeds. Also check to ensure the paramater is passed += properly. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test2/CMakeLists.txt new file mode 100644 index 0000000..5b52827 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_createthread_test2 + ${SOURCES} +) + +add_dependencies(paltest_createthread_test2 coreclrpal) + +target_link_libraries(paltest_createthread_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test2/test2.cpp new file mode 100644 index 0000000..34d3afb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test2/test2.cpp @@ -0,0 +1,184 @@ +// 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. + +/*=========================================================== +** +** Source: test2.c +** +** Purpose: Test that lpThreadId is assigned the correct +** threadId value and that lpThreadId can be NULL. +** +** +**=========================================================*/ + +#include + +#define NUM_TESTS 3 + +HANDLE hThread[NUM_TESTS]; +DWORD dwThreadId[NUM_TESTS]; +volatile BOOL bResult[NUM_TESTS]; +volatile DWORD dwThreadId1[NUM_TESTS]; + +DWORD PALAPI Thread( LPVOID lpParameter) +{ + dwThreadId1[(DWORD)(SIZE_T)lpParameter] = GetCurrentThreadId(); + bResult[(DWORD)(SIZE_T) lpParameter] = TRUE; + return (DWORD)(SIZE_T) lpParameter; +} + +struct testCase +{ + LPSECURITY_ATTRIBUTES lpThreadAttributes; + DWORD dwStackSize; + LPTHREAD_START_ROUTINE lpStartAddress; + DWORD dwCreationFlags; + LPDWORD lpThreadId; +}; + +struct testCase testCases[]= +{ + {NULL, 0, &Thread, 0, NULL}, + {NULL, 0, &Thread, CREATE_SUSPENDED, NULL}, + {NULL, 0, &Thread, 0, (LPDWORD) 1} +}; + +/* + * close handles + */ +BOOL cleanup(int index) +{ + int i; + BOOL bRet = TRUE; + + for (i = 0; i < index; i++) + { + if (!CloseHandle(hThread[i])) + { + bRet = FALSE; + Trace("PALSUITE ERROR: CloseHandle(%p) call failed for index %d\n", + hThread[i], i); + } + } + + return(bRet); +} + +int __cdecl main(int argc, char **argv) +{ + SIZE_T i; + DWORD dwRetWFSO; + DWORD dwRetRT; + BOOL bRet = TRUE; + + if(0 != (PAL_Initialize(argc, argv))) + { + return (FAIL); + } + + /* set results array to FALSE */ + for (i = 0; i < NUM_TESTS; i++) + { + bResult[i]=FALSE; + dwThreadId[i]=0; + } + + for (i = 0; i < NUM_TESTS; i++) + { + if (NULL != testCases[i].lpThreadId) + { + testCases[i].lpThreadId = &dwThreadId[i]; + } + /* pass the index as the thread argument */ + hThread[i] = CreateThread( testCases[i].lpThreadAttributes, + testCases[i].dwStackSize, + testCases[i].lpStartAddress, + (LPVOID)i, + testCases[i].dwCreationFlags, + testCases[i].lpThreadId); + if (hThread[i] == NULL) + { + Trace("PALSUITE ERROR: CreateThread('%p' '%d' '%p' '%p' '%d' " + "'%p') call failed.\nGetLastError returned '%u'.\n", + testCases[i].lpThreadAttributes, testCases[i].dwStackSize, + testCases[i].lpStartAddress, (LPVOID)i, + testCases[i].dwCreationFlags, + testCases[i].lpThreadId, GetLastError()); + cleanup(i - 1); + Fail(""); + } + + /* Resume suspended threads */ + if (testCases[i].dwCreationFlags == CREATE_SUSPENDED) + { + dwRetRT = ResumeThread (hThread[i]); + if (dwRetRT != 1) + { + Trace ("PALSUITE ERROR: ResumeThread(%p) " + "call returned %d it should have returned %d.\n" + "GetLastError returned %u.\n", hThread[i], dwRetRT, + 1, GetLastError()); + cleanup(i); + Fail(""); + } + } + } + + /* cleanup */ + for (i = 0; i < NUM_TESTS; i++) + { + dwRetWFSO = WaitForSingleObject(hThread[i], 10000); + if (dwRetWFSO != WAIT_OBJECT_0) + { + Trace ("PALSUITE ERROR: WaitForSingleObject('%p' '%d') " + "call returned %d instead of WAIT_OBJECT_0 ('%d').\n" + "GetLastError returned %u.\n", hThread[i], 10000, + dwRetWFSO, WAIT_OBJECT_0, GetLastError()); + cleanup(i); + Fail(""); + } + } + if(!cleanup(NUM_TESTS)) + { + Fail(""); + } + + for (i = 0; i < NUM_TESTS; i++) + { + /* + * check to see that all threads were created and were passed + * the array index as an argument. + */ + if (FALSE == bResult[i]) + { + bRet = FALSE; + Trace("PALSUITE ERROR: result[%d]=%d. It should be %d\n", i, + FALSE, TRUE); + } + /* + * check to see that lpThreadId received the correct value. + */ + if (0 != dwThreadId[i]) + { + if (dwThreadId[i] != dwThreadId1[i]) + { + bRet = FALSE; + Trace("PALSUITE ERROR: dwThreadId[%d]=%p and dwThreadId1[%d]" + "=%p\nThese values should be identical.\n", i, + dwThreadId[i], i, dwThreadId1[i]); + } + } + } + if (!bRet) + { + cleanup(NUM_TESTS); + Fail(""); + } + + PAL_Terminate(); + return (PASS); +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test2/testinfo.dat new file mode 100644 index 0000000..0333beb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateThread +Name = Positive Test for CreateThread +TYPE = DEFAULT +EXE1 = test2 +Description += Test that lpThreadId is assigned the correct threadId value and += that lpThreadId can be NULL. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test3/CMakeLists.txt new file mode 100644 index 0000000..d621877 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_createthread_test3 + ${SOURCES} +) + +add_dependencies(paltest_createthread_test3 coreclrpal) + +target_link_libraries(paltest_createthread_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test3/test3.cpp new file mode 100644 index 0000000..0c44d1f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test3/test3.cpp @@ -0,0 +1,101 @@ +// 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. + +/*=========================================================== +** +** Source: test3.c +** +** Purpose: Check to see that the handle CreateThread returns +** can be closed while the thread is still running. +** +** +**=========================================================*/ + +#include + +HANDLE hThread; +HANDLE hEvent; + +DWORD PALAPI Thread( LPVOID lpParameter) +{ + DWORD dwRet; + dwRet = WaitForSingleObject(hEvent, INFINITE); + /* if this thread continues beyond here, fail */ + Fail(""); + + return 0; +} + +int __cdecl main(int argc, char **argv) +{ + DWORD dwThreadId; + DWORD dwRet; + + if(0 != (PAL_Initialize(argc, argv))) + { + return (FAIL); + } + + hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (hEvent == NULL) + { + Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError " + "returned %u.\n", GetLastError()); + } + + /* pass the index as the thread argument */ + hThread = CreateThread( NULL, + 0, + &Thread, + (LPVOID) 0, + 0, + &dwThreadId); + if (hThread == NULL) + { + Trace("PALSUITE ERROR: CreateThread('%p' '%d' '%p' '%p' '%d' '%p') " + "call failed.\nGetLastError returned '%u'.\n", NULL, + 0, &Thread, (LPVOID) 0, 0, &dwThreadId, GetLastError()); + if (0 == CloseHandle(hEvent)) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%u'.\n", hEvent); + } + Fail(""); + } + + dwRet = WaitForSingleObject(hThread, 10000); + if (dwRet != WAIT_TIMEOUT) + { + Trace ("PALSUITE ERROR: WaitForSingleObject('%p' '%d') " + "call returned %d instead of WAIT_TIMEOUT ('%d').\n" + "GetLastError returned '%u'.\n", hThread, 10000, + dwRet, WAIT_TIMEOUT, GetLastError()); + Fail(""); + } + + if (0 == CloseHandle(hThread)) + { + Trace("PALSUITE ERROR: Unable to CloseHandle(%p) on a running thread." + "\nGetLastError returned '%u'.\n", hThread, GetLastError()); + if (0 == CloseHandle(hEvent)) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "cleanup.\nGetLastError returned '%u'.\n", hEvent, + GetLastError()); + } + Fail(""); + } + if (0 == CloseHandle(hEvent)) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "cleanup.\nGetLastError returned '%u'.\n", hEvent, + GetLastError()); + Fail(""); + } + + PAL_Terminate(); + return (PASS); +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test3/testinfo.dat new file mode 100644 index 0000000..712c3a6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CreateThread/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CreateThread +Name = Positive Test for CreateThread +TYPE = DEFAULT +EXE1 = test3 +Description += Check to see that the handle CreateThread returns can be closed while += the thread is still running. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/CMakeLists.txt new file mode 100644 index 0000000..ba9a8a2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/CMakeLists.txt @@ -0,0 +1,9 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/CMakeLists.txt new file mode 100644 index 0000000..cbdff5a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + InitializeCriticalSection.cpp +) + +add_executable(paltest_criticalsectionfunctions_test1 + ${SOURCES} +) + +add_dependencies(paltest_criticalsectionfunctions_test1 coreclrpal) + +target_link_libraries(paltest_criticalsectionfunctions_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.cpp new file mode 100644 index 0000000..f294cea --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.cpp @@ -0,0 +1,235 @@ +// 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. + +/*============================================================ +** +** Source: criticalsectionfunctions/test1/initializecriticalsection.c +** +** Purpose: Test Semaphore operation using classic IPC problem: +** "Producer-Consumer Problem". +** +** Dependencies: CreateThread +** InitializeCriticalSection +** EnterCriticalSection +** LeaveCriticalSection +** DeleteCriticalSection +** WaitForSingleObject +** Sleep +** + +** +**=========================================================*/ + +#include + +#define PRODUCTION_TOTAL 26 + +#define _BUF_SIZE 10 + +DWORD dwThreadId; /* consumer thread identifier */ + +HANDLE hThread; /* handle to consumer thread */ + +CRITICAL_SECTION CriticalSectionM; /* Critical Section Object (used as mutex) */ + +typedef struct Buffer +{ + short readIndex; + short writeIndex; + CHAR message[_BUF_SIZE]; + +} BufferStructure; + +CHAR producerItems[PRODUCTION_TOTAL + 1]; + +CHAR consumerItems[PRODUCTION_TOTAL + 1]; + +/* + * Read next message from the Buffer into provided pointer. + * Returns: 0 on failure, 1 on success. + */ +int +readBuf(BufferStructure *Buffer, char *c) +{ + if( Buffer -> writeIndex == Buffer -> readIndex ) + { + return 0; + } + *c = Buffer -> message[Buffer -> readIndex++]; + Buffer -> readIndex %= _BUF_SIZE; + return 1; +} + +/* + * Write message generated by the producer to Buffer. + * Returns: 0 on failure, 1 on success. + */ +int +writeBuf(BufferStructure *Buffer, CHAR c) +{ + if( ( ((Buffer -> writeIndex) + 1) % _BUF_SIZE) == + (Buffer -> readIndex) ) + { + return 0; + } + Buffer -> message[Buffer -> writeIndex++] = c; + Buffer -> writeIndex %= _BUF_SIZE; + return 1; +} + +/* + * Sleep 500 milleseconds. + */ +VOID +consumerSleep(VOID) +{ + Sleep(500); +} + +/* + * Sleep between 10 milleseconds. + */ +VOID +producerSleep(VOID) +{ + Sleep(10); +} + +/* + * Produce a message and write the message to Buffer. + */ +VOID +producer(BufferStructure *Buffer) +{ + + int n = 0; + char c; + + while (n < PRODUCTION_TOTAL) + { + c = 'A' + n ; /* Produce Item */ + + EnterCriticalSection(&CriticalSectionM); + + if (writeBuf(Buffer, c)) + { + printf("Producer produces %c.\n", c); + producerItems[n++] = c; + } + + LeaveCriticalSection(&CriticalSectionM); + + producerSleep(); + } + + return; +} + +/* + * Read and "Consume" the messages in Buffer. + */ +DWORD +PALAPI +consumer( LPVOID lpParam ) +{ + int n = 0; + char c; + + consumerSleep(); + + while (n < PRODUCTION_TOTAL) + { + + EnterCriticalSection(&CriticalSectionM); + + if (readBuf((BufferStructure*)lpParam, &c)) + { + printf("\tConsumer consumes %c.\n", c); + consumerItems[n++] = c; + } + + LeaveCriticalSection(&CriticalSectionM); + + consumerSleep(); + } + + return 0; +} + +int __cdecl main (int argc, char **argv) +{ + + BufferStructure Buffer, *pBuffer; + + pBuffer = &Buffer; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* + * Create mutual exclusion mechanisms + */ + + InitializeCriticalSection ( &CriticalSectionM ); + + /* + * Initialize Buffer + */ + pBuffer->writeIndex = pBuffer->readIndex = 0; + + + + /* + * Create Consumer + */ + hThread = CreateThread( + NULL, + 0, + consumer, + &Buffer, + 0, + &dwThreadId); + + if ( NULL == hThread ) + { + Fail ( "CreateThread() returned NULL. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + /* + * Start producing + */ + producer(pBuffer); + + /* + * Wait for consumer to complete + */ + WaitForSingleObject (hThread, INFINITE); + + /* + * Compare items produced vs. items consumed + */ + if ( 0 != strncmp (producerItems, consumerItems, PRODUCTION_TOTAL) ) + { + Fail("The producerItems string %s\n and the consumerItems string " + "%s\ndo not match. This could be a problem with the strncmp()" + " function\n FailingTest\nGetLastError() returned %d\n", + producerItems, consumerItems, GetLastError()); + } + + /* + * Clean up Critical Section object + */ + DeleteCriticalSection(&CriticalSectionM); + + Trace("producerItems and consumerItems arrays match. All %d\nitems " + "were produced and consumed in order.\nTest passed.\n", + PRODUCTION_TOTAL); + + PAL_Terminate(); + return (PASS); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/testinfo.dat new file mode 100644 index 0000000..494b899 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/testinfo.dat @@ -0,0 +1,21 @@ +# 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. + +Version = 1.0 +Section = threading +Function = InitializeCriticalSection / EnterCriticalSection / LeaveCriticalSection / DeleteCriticalSection +Name = Positive Test for InitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection and DeleteCriticalSection +TYPE = DEFAULT +EXE1 = initializecriticalsection +Description += Implementation of Producer / Consumer IPC problem using the += "CriticalSection" functions to provide a mutual exclusion mechanism. += This test case exercises InitializeCriticalSection, EnterCriticalSection, += LeaveCriticalSection, DeleteCriticalSection, and WaitForSingleObject += functions. += This case doesn't work with more than one producer and one consumer. += The producer thread and consumer thread each take turns blocking on += the CriticalSection object and do not have any other synchronization += mechanisms. This prevents adding producers or consumers as there are += no mechanisms to block them once the buffer is full. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/CMakeLists.txt new file mode 100644 index 0000000..9f537dd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_criticalsectionfunctions_test2 + ${SOURCES} +) + +add_dependencies(paltest_criticalsectionfunctions_test2 coreclrpal) + +target_link_libraries(paltest_criticalsectionfunctions_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.cpp new file mode 100644 index 0000000..47659a1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.cpp @@ -0,0 +1,226 @@ +// 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. + +/*============================================================ +** +** Source: CriticalSectionFunctions/test2/test2.c +** +** Purpose: Test that we are able to nest critical section calls. +** The initial thread makes a call to EnterCriticalSection once, +** blocking on a CRITICAL_SECTION object and creates a new thread. +** The newly created thread blocks on the same CRITICAL_SECTION object. +** The first thread now makes a call to LeaveCriticalSection. +** Test to see that the new thread doesn't get unblocked. +** +** Dependencies: CreateThread +** InitializeCriticalSection +** EnterCriticalSection +** LeaveCriticalSection +** DeleteCriticalSection +** WaitForSingleObject +** + +** +**=========================================================*/ + +#include + +CRITICAL_SECTION CriticalSection; + +volatile BOOL t0_tflag = FAIL; /* thread 0 timeout flag */ +volatile BOOL t1_aflag = FAIL; /* thread 1 access flag */ +volatile BOOL t1_cflag = FAIL; /* thread 1 critical section flag */ +volatile BOOL bTestResult = FAIL; + +DWORD PALAPI Thread(LPVOID lpParam) +{ + t1_aflag = PASS; + EnterCriticalSection(&CriticalSection); + t1_cflag = PASS; + LeaveCriticalSection(&CriticalSection); + return 0; +} + +int __cdecl main (int argc, char **argv) +{ + HANDLE hThread; + DWORD dwThreadId; + DWORD dwRet; + + if(0 != (PAL_Initialize(argc, argv))) + { + return (bTestResult); + } + + /* + * Create critical section object and enter it + */ + InitializeCriticalSection ( &CriticalSection ); + EnterCriticalSection(&CriticalSection); + + /* + * Create a suspended thread + */ + hThread = CreateThread(NULL, + 0, + &Thread, + (LPVOID) NULL, + CREATE_SUSPENDED, + &dwThreadId); + + if (hThread == NULL) + { + Trace("PALSUITE ERROR: CreateThread call failed. GetLastError " + "returned %d.\n", GetLastError()); + LeaveCriticalSection(&CriticalSection); + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + EnterCriticalSection(&CriticalSection); + /* + * Set priority of the thread to greater than that of the currently + * running thread so it is guaranteed to run. + */ + dwRet = (DWORD) SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL); + + if (0 == dwRet) + { + Trace("PALSUITE ERROR: SetThreadPriority (%p, %d) call failed.\n" + "GetLastError returned %d.\n", hThread, + THREAD_PRIORITY_NORMAL, GetLastError()); + LeaveCriticalSection(&CriticalSection); + CloseHandle(hThread); + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + dwRet = ResumeThread(hThread); + + if (-1 == dwRet) + { + Trace("PALSUITE ERROR: ResumeThread(%p) call failed.\nGetLastError " + "returned %d.\n", hThread, GetLastError()); + LeaveCriticalSection(&CriticalSection); + CloseHandle(hThread); + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + /* + * Sleep until we know the thread has been invoked. This sleep in + * combination with the higher priority of the other thread should + * guarantee both threads block on the critical section. + */ + while (t1_aflag == FAIL) + { + Sleep(1); + } + + LeaveCriticalSection(&CriticalSection); + + switch ((WaitForSingleObject( + hThread, + 10000))) /* Wait 10 seconds */ + { + case WAIT_OBJECT_0: + /* Object (thread) is signaled */ + LeaveCriticalSection(&CriticalSection); + CloseHandle(hThread); + DeleteCriticalSection(&CriticalSection); + Fail("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " + "returned\nWAIT_TIMEOUT ('%d'), instead it returned " + "WAIT_OBJECT_0 ('%d').\nA nested LeaveCriticalSection(%p) " + "call released both threads that were waiting on it!\n", + hThread, 10000, WAIT_TIMEOUT, WAIT_OBJECT_0, &CriticalSection); + break; + case WAIT_ABANDONED: + /* + * Object was mutex object whose owning + * thread has terminated. Shouldn't occur. + */ + Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " + "returned\nWAIT_TIMEOUT ('%d'), instead it returned " + "WAIT_ABANDONED ('%d').\nGetLastError returned '%d'\n", + hThread, 10000, WAIT_TIMEOUT, WAIT_ABANDONED, GetLastError()); + LeaveCriticalSection(&CriticalSection); + CloseHandle(hThread); + DeleteCriticalSection(&CriticalSection); + Fail(""); + break; + case WAIT_FAILED: /* WaitForSingleObject function failed */ + Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " + "returned\nWAIT_TIMEOUT ('%d'), instead it returned " + "WAIT_FAILED ('%d').\nGetLastError returned '%d'\n", + hThread, 10000, WAIT_TIMEOUT, WAIT_FAILED, GetLastError()); + LeaveCriticalSection(&CriticalSection); + CloseHandle(hThread); + DeleteCriticalSection(&CriticalSection); + Fail(""); + break; + case WAIT_TIMEOUT: + /* + * We expect this thread to timeout waiting for the + * critical section object to become available. + */ + t0_tflag = PASS; + break; + } + + LeaveCriticalSection(&CriticalSection); + + if (WAIT_OBJECT_0 != WaitForSingleObject (hThread, 10000)) + { + if (0 == CloseHandle(hThread)) + { + Trace("PALSUITE ERROR: CloseHandle(%p) call failed.\n" + "WaitForSingleObject(%p,%d) should have returned " + "WAIT_OBJECT_0 ('%d').\nBoth calls failed. " + "Deleted CRITICAL_SECTION object which likely means\n" + "thread %p is now in an undefined state. GetLastError " + "returned '%d'.\n", hThread, hThread, 10000, WAIT_OBJECT_0, + hThread, GetLastError()); + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + else + { + Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " + "returned WAIT_OBJECT_0 ('%d').\n GetLastError returned " + "'%d'.\n", hThread, hThread, 10000, WAIT_OBJECT_0, + hThread, GetLastError()); + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + } + + if (0 == CloseHandle(hThread)) + { + Trace("PALSUITE ERROR: CloseHandle(%p) call failed.\n" + "Deleted CRITICAL_SECTION object which likely means\n" + "thread %p is now in an undefined state. GetLastError " + "returned '%d'.\n", hThread, hThread, GetLastError()); + DeleteCriticalSection(&CriticalSection); + Fail(""); + + } + DeleteCriticalSection(&CriticalSection); + /* + * Ensure both thread 0 experienced a wait timeout and thread 1 + * accessed the critical section or fail the test, otherwise pass it. + */ + if ((t0_tflag == FAIL) || (t1_cflag == FAIL)) + { + Trace("PALSUITE ERROR: Thread 0 returned %d when %d was expected.\n" + "Thread 1 returned %d when %d was expected.\n", t0_tflag, + PASS, t1_cflag, PASS); + bTestResult=FAIL; + } + else + { + bTestResult=PASS; + } + + PAL_TerminateEx(bTestResult); + return (bTestResult); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/testinfo.dat new file mode 100644 index 0000000..0684212 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CriticalSectionFunctions +Name = Positive test to ensure CRITICAL_SECTION objects can be nested +TYPE = DEFAULT +EXE1 = test2 +Description += Test that we are able to nest critical section calls. += The initial thread makes a call to EnterCriticalSection once, += blocking on a CRITICAL_SECTION object and creates a new thread. += The newly created thread blocks on the same CRITICAL_SECTION object. += The first thread now makes a call to LeaveCriticalSection. += Test to see that the new thread doesn't get unblocked. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/CMakeLists.txt new file mode 100644 index 0000000..7435fda --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_criticalsectionfunctions_test3 + ${SOURCES} +) + +add_dependencies(paltest_criticalsectionfunctions_test3 coreclrpal) + +target_link_libraries(paltest_criticalsectionfunctions_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/test3.cpp new file mode 100644 index 0000000..d591126 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/test3.cpp @@ -0,0 +1,376 @@ +// 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. + +/*===================================================================== +** +** Source: CriticalSectionFunctions/test3/test3.c +** +** Purpose: Create two threads to exercise TryEnterCriticalSection +** and EnterCriticalSection. TryEnterCriticalSection acquires +** and holds a CRITICAL_SECTION object. Another call to +** TryEnterCriticalSection is made from a different thread, at +** this time, to establish a call to TryEnterCriticalSection +** will return immediatly and to establish +** TryEnterCriticalSection returns the proper value when it +** attempts to lock a CRITICAL_SECTION that is already owned +** by another thread. The CRITICAL_SECTION object is then +** released and held by a call to EnterCriticalSection. A new +** thread is invoked and attempts to acquire the held +** CRITICAL_SECTION with a call to TryEnterCriticalSection. +** TryEnterCriticalSection returns immediatly and returns +** with the value that states the CRITICAL_SECTION object is +** held by another thread. This establishes +** TryEnterCriticalSection behaves the same way with +** CriticalSections locked by TryEnterCriticalSection and +** EnterCriticalSection. +** +** +**===================================================================*/ +#include + +#define NUM_THREADS 2 + +HANDLE hThread[NUM_THREADS]; +HANDLE hEvent[NUM_THREADS]; +CRITICAL_SECTION CriticalSection; +BOOL bRet = FAIL; + +DWORD PALAPI Thread(LPVOID lpParam) +{ + DWORD dwRet; + + if (0 == TryEnterCriticalSection(&CriticalSection)) + { + dwRet = WaitForMultipleObjects(NUM_THREADS, hEvent, TRUE, 10000); + if ((WAIT_OBJECT_0 > dwRet) || + ((WAIT_OBJECT_0 + NUM_THREADS - 1) < dwRet)) + { +#if 0 + if (0 == CloseHandle(hThread[1])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) " + "during clean up.\nGetLastError returned '%d'.\n", + hThread[1], GetLastError()); + } +#endif + Trace("PALSUITE ERROR: WaitForMultipleObjects(%d, %p, %d, %d) call" + "returned an unexpected value, '%d'.\nGetLastError returned " + "%d.\n", NUM_THREADS, hEvent, TRUE, 10000, dwRet, + GetLastError()); + } + else + { + bRet = PASS; + } + } + else + { + /* signal thread 0 */ + if (0 == SetEvent(hEvent[0])) + { + Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hEvent[0], + GetLastError()); + LeaveCriticalSection(&CriticalSection); + if (0 == CloseHandle(hThread[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) " + "during clean up\nGetLastError returned '%d'.\n", + hThread[0], GetLastError()); + } + if (0 == CloseHandle(hEvent[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) " + "during clean up\nGetLastError returned '%d'.\n", + hEvent[0], GetLastError()); + } + if (0 == CloseHandle(hEvent[1])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) " + "during clean up\nGetLastError returned '%d'.\n", + hEvent[1], GetLastError()); + } + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + /* wait to be signaled */ + dwRet = WaitForSingleObject(hEvent[1], 10000); + if (WAIT_OBJECT_0 != dwRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " + "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " + "('%d').\nGetLastError returned '%d'.\n", + hEvent[0], 10000, WAIT_OBJECT_0, dwRet, GetLastError()); + if (0 == CloseHandle(hThread[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) " + "during clean up.\nGetLastError returned '%d'.\n", + hThread[0], GetLastError()); + } + if (0 == CloseHandle(hEvent[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) " + "during clean up.\nGetLastError returned '%d'.\n", + hEvent[0], GetLastError()); + } + if (0 == CloseHandle(hEvent[1])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) " + "during clean up.\nGetLastError returned '%d.'\n", + hEvent[1], GetLastError()); + } + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + LeaveCriticalSection(&CriticalSection); + } + return FAIL; +} + +int __cdecl main(int argc, char **argv) +{ + HANDLE hThread[NUM_THREADS]; + DWORD dwThreadId[NUM_THREADS]; + DWORD dwRet; + + if ((PAL_Initialize(argc,argv)) != 0) + { + return(bRet); + } + + /* thread 0 event */ + hEvent[0] = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (hEvent[0] == NULL) + { + Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError " + "returned %d.\n", GetLastError()); + } + + /* thread 1 event */ + hEvent[1] = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (hEvent[1] == NULL) + { + Trace("PALSUITE ERROR: CreateEvent call #1 failed. GetLastError " + "returned %d.\n", GetLastError()); + if (0 == CloseHandle(hEvent[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hEvent[0]); + } + Fail(""); + } + + InitializeCriticalSection ( &CriticalSection ); + + hThread[0] = CreateThread(NULL, + 0, + &Thread, + (LPVOID) NULL, + 0, + &dwThreadId[0]); + + if (hThread[0] == NULL) + { + Trace("PALSUITE ERROR: CreateThread call #0 failed. GetLastError " + "returned %d.\n", GetLastError()); + if (0 == CloseHandle(hEvent[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hEvent[0], + GetLastError()); + } + if (0 == CloseHandle(hEvent[1])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hEvent[1], + GetLastError()); + } + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + + /* wait for thread 0 to be signaled */ + dwRet = WaitForSingleObject(hEvent[0], 10000); + if (WAIT_OBJECT_0 != dwRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " + "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " + "('%d').\nGetLastError returned '%d'.\n", hEvent[0], 10000, + WAIT_OBJECT_0, dwRet, GetLastError()); + if (0 == CloseHandle(hThread[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hThread[0], + GetLastError()); + } + if (0 == CloseHandle(hEvent[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hEvent[0], + GetLastError()); + } + if (0 == CloseHandle(hEvent[1])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hEvent[1], + GetLastError()); + } + Fail(""); + } + + /* + * Attempting to enter CRITICAL_SECTION object owned by the + * created thread and locked with TryEnterCriticalSection + */ + if (0 == TryEnterCriticalSection(&CriticalSection)) + { + /* signal thread 1 */ + if (0 == SetEvent(hEvent[1])) + { + Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) call.\n" + "GetLastError returned '%d'.\n", hEvent[1], + GetLastError()); + goto done; + } + } + else + { + Trace("PALSUITE_ERROR: TryEnterCriticalSection was able to grab a" + " CRITICAL_SECTION object\nwhich was already owned.\n"); + LeaveCriticalSection(&CriticalSection); + if (0 == CloseHandle(hThread[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hThread[0], + GetLastError()); + } + if (0 == CloseHandle(hEvent[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hEvent[0], + GetLastError()); + } + if (0 == CloseHandle(hEvent[1])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hEvent[1], + GetLastError()); + } + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + /* + * Enter the CRITICAL_SECTION and launch another thread to attempt + * to access the CRITICAL_SECTION with a call to TryEnterCriticalSection. + */ + EnterCriticalSection(&CriticalSection); + + hThread[1] = CreateThread(NULL, + 0, + &Thread, + (LPVOID) NULL, + 0, + &dwThreadId[1]); + + if (hThread[1] == NULL) + { + Trace("PALSUITE ERROR: CreateThread call #1 failed. GetLastError " + "returned %d.\n", GetLastError()); + LeaveCriticalSection(&CriticalSection); + if (0 == CloseHandle(hThread[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hThread[0], + GetLastError()); + } + if (0 == CloseHandle(hEvent[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hEvent[0], + GetLastError()); + } + if (0 == CloseHandle(hEvent[1])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hEvent[1], + GetLastError()); + } + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + dwRet = WaitForMultipleObjects(NUM_THREADS, hThread, TRUE, 10000); + if ((WAIT_OBJECT_0 > dwRet) || + ((WAIT_OBJECT_0 + NUM_THREADS - 1) < dwRet)) + { + Trace("PALSUITE ERROR: WaitForMultipleObjects(%d, %p, %d, %d) call " + "returned an unexpected value, '%d'.\nGetLastError returned " + "%d.\n", NUM_THREADS, hThread, TRUE, 10000, dwRet, + GetLastError()); + LeaveCriticalSection(&CriticalSection); + if (0 == CloseHandle(hThread[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hThread[0], + GetLastError()); + } + if (0 == CloseHandle(hThread[1])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hThread[1], + GetLastError()); + } + if (0 == CloseHandle(hEvent[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hEvent[0], + GetLastError()); + } + if (0 == CloseHandle(hEvent[1])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hEvent[1], + GetLastError()); + } + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + LeaveCriticalSection(&CriticalSection); + if (0 == CloseHandle(hThread[1])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hThread[1], + GetLastError()); + } +done: + if (0 == CloseHandle(hThread[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hThread[0], + GetLastError()); + } + if (0 == CloseHandle(hEvent[0])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hEvent[0], + GetLastError()); + } + if (0 == CloseHandle(hEvent[1])) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%d'.\n", hEvent[1], + GetLastError()); + } + DeleteCriticalSection(&CriticalSection); + + PAL_TerminateEx(bRet); + + return (bRet); +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/testinfo.dat new file mode 100644 index 0000000..818b487 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/testinfo.dat @@ -0,0 +1,29 @@ +# 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. + +Version = 1.0 +Section = threading +Function = CriticalSectionFunctions +Name = Positive Test for TryEnterCriticalSection +TYPE = DEFAULT +EXE1 = test3 +Description += Create two threads to exercise TryEnterCriticalSection += and EnterCriticalSection. TryEnterCriticalSection acquires += and holds a CRITICAL_SECTION object. Another call to += TryEnterCriticalSection is made from a different thread, at += this time, to establish a call to TryEnterCriticalSection += will return immediatly and to establish += TryEnterCriticalSection returns the proper value when it += attempts to lock a CRITICAL_SECTION that is already owned += by another thread. The CRITICAL_SECTION object is then += released and held by a call to EnterCriticalSection. A new += thread is invoked and attempts to acquire the held += CRITICAL_SECTION with a call to TryEnterCriticalSection. += TryEnterCriticalSection returns immediatly and returns += with the value that states the CRITICAL_SECTION object is += held by another thread. This establishes += TryEnterCriticalSection behaves the same way with += CriticalSections locked by TryEnterCriticalSection and += EnterCriticalSection. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/CMakeLists.txt new file mode 100644 index 0000000..6fe8258 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_criticalsectionfunctions_test4 + ${SOURCES} +) + +add_dependencies(paltest_criticalsectionfunctions_test4 coreclrpal) + +target_link_libraries(paltest_criticalsectionfunctions_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp new file mode 100644 index 0000000..8a245a4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp @@ -0,0 +1,241 @@ +// 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. + +/*============================================================ +** +** Source: criticalsectionfunctions/test4/test4.c +** +** Purpose: Test to see if threads blocked on a CRITICAL_SECTION object will +** be released in an orderly manner. This case looks at the following +** scenario. If one thread owns a CRITICAL_SECTION object and two threads +** block in EnterCriticalSection, trying to hold the already owned +** CRITICAL_SECTION object, when the first thread releases the CRITICAL_SECTION +** object, will one and only one of the waiters get unblocked? +** +** Dependencies: CreateThread +** InitializeCriticalSection +** EnterCriticalSection +** LeaveCriticalSection +** DeleteCriticalSection +** Sleep +** WaitForSingleObject +** + +** +**=========================================================*/ + +#include + +#define NUM_BLOCKING_THREADS 2 + +BOOL bTestResult; +CRITICAL_SECTION CriticalSection; +HANDLE hThread[NUM_BLOCKING_THREADS]; +HANDLE hEvent; +DWORD dwThreadId[NUM_BLOCKING_THREADS]; +volatile int flags[NUM_BLOCKING_THREADS] = {0,0}; + +DWORD PALAPI ThreadTest1(LPVOID lpParam) +{ + + EnterCriticalSection ( &CriticalSection ); + + flags[0] = 1; + + return 0; + +} + +DWORD PALAPI ThreadTest2(LPVOID lpParam) +{ + + EnterCriticalSection ( &CriticalSection ); + + flags[1] = 1; + + return 0; + +} + +int __cdecl main(int argc, char **argv) +{ + + DWORD dwRet; + DWORD dwRet1; + bTestResult = FAIL; + + if ((PAL_Initialize(argc,argv)) != 0) + { + return(bTestResult); + } + + /* + * Create Critical Section Object + */ + InitializeCriticalSection ( &CriticalSection ); + + EnterCriticalSection ( &CriticalSection ); + + hThread[0] = CreateThread(NULL, + 0, + &ThreadTest1, + (LPVOID) 0, + CREATE_SUSPENDED, + &dwThreadId[0]); + if (hThread[0] == NULL) + { + Trace("PALSUITE ERROR: CreateThread(%p, %d, %p, %p, %d, %p) call " + "failed.\nGetLastError returned %d.\n", NULL, 0, &ThreadTest1, + (LPVOID) 0, CREATE_SUSPENDED, &dwThreadId[0], GetLastError()); + LeaveCriticalSection(&CriticalSection); + DeleteCriticalSection ( &CriticalSection ); + Fail(""); + } + + hThread[1] = CreateThread(NULL, + 0, + &ThreadTest2, + (LPVOID) 0, + CREATE_SUSPENDED, + &dwThreadId[1]); + if (hThread[1] == NULL) + { + Trace("PALSUITE ERROR: CreateThread(%p, %d, %p, %p, %d, %p) call " + "failed.\nGetLastError returned %d.\n", NULL, 0, &ThreadTest2, + (LPVOID) 0, CREATE_SUSPENDED, &dwThreadId[1], GetLastError()); + LeaveCriticalSection(&CriticalSection); + + dwRet = ResumeThread(hThread[0]); + if (-1 == dwRet) + { + Trace("PALSUITE ERROR: ResumeThread(%p) call failed.\n" + "GetLastError returned '%d'.\n", hThread[0], + GetLastError()); + } + + dwRet = WaitForSingleObject(hThread[0], 10000); + if (WAIT_OBJECT_0 == dwRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call " + "failed. '%d' was returned instead of the expected '%d'.\n" + "GetLastError returned '%d'.\n", hThread[0], 10000, dwRet, + WAIT_OBJECT_0, GetLastError()); + } + + if (0 == CloseHandle(hThread[0])) + { + Trace("PALSUITE NOTIFICATION: CloseHandle(%p) call failed.\n" + "GetLastError returned %d. Not failing tests.\n", + hThread[0], GetLastError()); + } + + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + /* + * Set other thread priorities to be higher than ours & Sleep to ensure + * we give up the processor. + */ + dwRet = (DWORD) SetThreadPriority(hThread[0], + THREAD_PRIORITY_ABOVE_NORMAL); + if (0 == dwRet) + { + Trace("PALSUITE ERROR: SetThreadPriority(%p, %d) call failed.\n" + "GetLastError returned %d", hThread[0], + THREAD_PRIORITY_ABOVE_NORMAL, GetLastError()); + } + + dwRet = (DWORD) SetThreadPriority(hThread[1], + THREAD_PRIORITY_ABOVE_NORMAL); + if (0 == dwRet) + { + Trace("PALSUITE ERROR: SetThreadPriority(%p, %d) call failed.\n" + "GetLastError returned %d", hThread[1], + THREAD_PRIORITY_ABOVE_NORMAL, GetLastError()); + } + + dwRet = ResumeThread(hThread[0]); + if (-1 == dwRet) + { + Trace("PALSUITE ERROR: ResumeThread(%p, %d) call failed.\n" + "GetLastError returned %d", hThread[0], + GetLastError() ); + } + + dwRet = ResumeThread(hThread[1]); + if (-1 == dwRet) + { + Trace("PALSUITE ERROR: ResumeThread(%p, %d) call failed.\n" + "GetLastError returned %d", hThread[0], + GetLastError()); + } + + Sleep (0); + + LeaveCriticalSection (&CriticalSection); + + dwRet = WaitForSingleObject(hThread[0], 10000); + dwRet1 = WaitForSingleObject(hThread[1], 10000); + + if ((WAIT_OBJECT_0 == dwRet) || + (WAIT_OBJECT_0 == dwRet1)) + { + if ((1 == flags[0] && 0 == flags[1]) || + (0 == flags[0] && 1 == flags[1])) + { + bTestResult = PASS; + } + else + { + bTestResult = FAIL; + Trace ("PALSUITE ERROR: flags[%d] = {%d,%d}. These values are" + "inconsistent.\nCriticalSection test failed.\n", + NUM_BLOCKING_THREADS, flags[0], flags[1]); + } + + /* Fail the test if both threads returned WAIT_OBJECT_0 */ + if ((WAIT_OBJECT_0 == dwRet) && (WAIT_OBJECT_0 == dwRet1)) + { + bTestResult = FAIL; + Trace ("PALSUITE ERROR: WaitForSingleObject(%p, %d) and " + "WaitForSingleObject(%p, %d)\nboth returned dwRet = '%d'\n" + "One should have returned WAIT_TIMEOUT ('%d').\n", + hThread[0], 10000, hThread[1], 10000, dwRet, WAIT_TIMEOUT); + } + } + else + { + bTestResult = FAIL; + Trace ("PALSUITE ERROR: WaitForSingleObject(%p, %d) and " + "WaitForSingleObject(%p, %d)\nReturned dwRet = '%d' and\n" + "dwRet1 = '%d' respectively.\n", hThread[0], 10000, hThread[1], + 10000, dwRet, dwRet1); + } + + if (WAIT_OBJECT_0 == dwRet) + { + if (0 == CloseHandle(hThread[0])) + { + Trace("PALSUITE NOTIFICATION: CloseHandle(%p) call failed.\n" + "GetLastError returned %d. Not failing tests.\n", + hThread[0], GetLastError()); + } + } + if (WAIT_OBJECT_0 == dwRet1) + { + if (0 == CloseHandle(hThread[1])) + { + Trace("PALSUITE NOTIFICATION: CloseHandle(%p) call failed.\n" + "GetLastError returned %d. Not failing tests.\n", + hThread[1], GetLastError()); + } + } + + /* Leaking the CS on purpose, since there is still a thread + waiting on it */ + + PAL_TerminateEx(bTestResult); + return (bTestResult); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/testinfo.dat new file mode 100644 index 0000000..9c07c24 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = threading +Function = LeaveCriticalSection +Name = Positive test to ensure CRITICAL_SECTION objects are released properly +TYPE = DEFAULT +EXE1 = test4 +Description += Test to see if threads blocked on a CRITICAL_SECTION object will += be released in an orderly manner. This case looks at the following += scenario. If one thread owns a CRITICAL_SECTION object and two threads += block in EnterCriticalSection, trying to hold the already owned += CRITICAL_SECTION object, when the first thread releases the CRITICAL_SECTION += object, will one and only one of the waiters get unblocked? diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/CMakeLists.txt new file mode 100644 index 0000000..34ff67e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_criticalsectionfunctions_test5 + ${SOURCES} +) + +add_dependencies(paltest_criticalsectionfunctions_test5 coreclrpal) + +target_link_libraries(paltest_criticalsectionfunctions_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.cpp new file mode 100644 index 0000000..8dfa4f5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.cpp @@ -0,0 +1,187 @@ +// 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. + +/*===================================================================== +** +** Source: CriticalSectionFunctions/test5/test5.c +** +** Purpose: Attempt to delete a critical section owned by another +** thread. +** +** +**===================================================================*/ +#include + +/* + * Tokens 0 and 1 are events. Token 2 is the thread. + */ +#define NUM_TOKENS 3 + +HANDLE hToken[NUM_TOKENS]; +CRITICAL_SECTION CriticalSection; + +BOOL CleanupHelper (HANDLE *hArray, DWORD dwIndex) +{ + BOOL bCHRet; + + bCHRet = CloseHandle(hArray[dwIndex]); + if (!bCHRet) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%u'.\n", hArray[dwIndex], + GetLastError()); + } + + return (bCHRet); +} + +BOOL Cleanup(HANDLE *hArray, DWORD dwIndex) +{ + BOOL bCRet; + BOOL bCHRet = FALSE; + + while (--dwIndex > 0) + { + bCHRet = CleanupHelper(&hArray[0], dwIndex); + } + + bCRet = CloseHandle(hArray[0]); + if (!bCRet) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%u'.\n", hArray[dwIndex], + GetLastError()); + } + + return (bCRet&&bCHRet); +} + +DWORD PALAPI Thread(LPVOID lpParam) +{ + DWORD dwTRet; + + EnterCriticalSection(&CriticalSection); + + /* signal thread 0 */ + if (0 == SetEvent(hToken[0])) + { + Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) during " + "clean up.\nGetLastError returned '%u'.\n", hToken[0], + GetLastError()); + LeaveCriticalSection(&CriticalSection); + Cleanup (&hToken[0], NUM_TOKENS); + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + /* wait to be signaled */ + dwTRet = WaitForSingleObject(hToken[1], 10000); + if (WAIT_OBJECT_0 != dwTRet) + + { + Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " + "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " + "('%d').\nGetLastError returned '%u'.\n", + hToken[1], 10000, WAIT_OBJECT_0, dwTRet, GetLastError()); + LeaveCriticalSection(&CriticalSection); + Cleanup (&hToken[0], NUM_TOKENS); + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + LeaveCriticalSection(&CriticalSection); + return 0; +} + +int __cdecl main(int argc, char **argv) +{ + DWORD dwThreadId; + DWORD dwMRet; + + if ((PAL_Initialize(argc,argv)) != 0) + { + return(FAIL); + } + + /* thread 0 event */ + hToken[0] = CreateEvent(NULL, TRUE, FALSE, NULL); + if (NULL == hToken[0]) + { + Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError " + "returned %u.\n", GetLastError()); + } + + /* thread 1 event */ + hToken[1] = CreateEvent(NULL, TRUE, FALSE, NULL); + if (NULL == hToken[1]) + { + Trace("PALSUITE ERROR: CreateEvent call #1 failed. GetLastError " + "returned %u.\n", GetLastError()); + Cleanup(&hToken[0], (NUM_TOKENS - 2)); + Fail(""); + } + + InitializeCriticalSection(&CriticalSection); + + hToken[2] = CreateThread(NULL, + 0, + &Thread, + (LPVOID) NULL, + 0, + &dwThreadId); + if (hToken[2] == NULL) + { + Trace("PALSUITE ERROR: CreateThread call #0 failed. GetLastError " + "returned %u.\n", GetLastError()); + Cleanup(&hToken[0], (NUM_TOKENS - 1)); + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + /* wait for thread 0 to be signaled */ + dwMRet = WaitForSingleObject(hToken[0], 10000); + if (WAIT_OBJECT_0 != dwMRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " + "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " + "('%d').\nGetLastError returned '%u'.\n", hToken[0], 10000, + WAIT_OBJECT_0, dwMRet, GetLastError()); + Cleanup(&hToken[0], NUM_TOKENS); + Fail(""); + } + + /* + * Attempt to do delete CriticalSection object owned by other thread + */ + DeleteCriticalSection(&CriticalSection); + + /* signal thread 1 */ + if (0 == SetEvent(hToken[1])) + { + Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) call.\n" + "GetLastError returned '%u'.\n", hToken[1], + GetLastError()); + Cleanup(&hToken[0], NUM_TOKENS); + Fail(""); + } + + dwMRet = WaitForSingleObject(hToken[2], 10000); + if (WAIT_OBJECT_0 != dwMRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call " + "returned an unexpected value '%d'.\nGetLastError returned " + "%u.\n", hToken[2], 10000, dwMRet, GetLastError()); + Cleanup(&hToken[0], NUM_TOKENS); + Fail(""); + } + + if (!Cleanup(&hToken[0], NUM_TOKENS)) + { + Fail(""); + } + + PAL_Terminate(); + + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/testinfo.dat new file mode 100644 index 0000000..aa11249 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/testinfo.dat @@ -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. + +Version = 1.0 +Section = threading +Function = CriticalSectionFunctions +Name = Positive test for DeleteCriticalSection +TYPE = DEFAULT +EXE1 = test5 +Description += Attempt to delete a critical section owned by another thread. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/CMakeLists.txt new file mode 100644 index 0000000..12f3239 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_criticalsectionfunctions_test6 + ${SOURCES} +) + +add_dependencies(paltest_criticalsectionfunctions_test6 coreclrpal) + +target_link_libraries(paltest_criticalsectionfunctions_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.cpp new file mode 100644 index 0000000..c27db86 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.cpp @@ -0,0 +1,190 @@ +// 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. + +/*===================================================================== +** +** Source: CriticalSectionFunctions/test6/test6.c +** +** Purpose: Attempt to leave a critical section which is owned by +** another thread. +** +** +**===================================================================*/ +#include + +/* + * Tokens 0 and 1 are events. Token 2 is the thread. + */ +#define NUM_TOKENS 3 + +HANDLE hToken[NUM_TOKENS]; +CRITICAL_SECTION CriticalSection; + +BOOL CleanupHelper (HANDLE *hArray, DWORD dwIndex) +{ + BOOL bCHRet; + + bCHRet = CloseHandle(hArray[dwIndex]); + if (!bCHRet) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%u'.\n", hArray[dwIndex], + GetLastError()); + } + + return (bCHRet); +} + +BOOL Cleanup(HANDLE *hArray, DWORD dwIndex) +{ + BOOL bCRet; + BOOL bCHRet; + + while (--dwIndex > 0) + { + bCHRet = CleanupHelper(&hArray[0], dwIndex); + } + + bCRet = CloseHandle(hArray[0]); + if (!bCRet) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%u'.\n", hArray[dwIndex], + GetLastError()); + } + + return (bCRet&&bCHRet); +} + +DWORD PALAPI Thread(LPVOID lpParam) +{ + DWORD dwTRet; + + EnterCriticalSection(&CriticalSection); + + /* signal thread 0 */ + if (0 == SetEvent(hToken[0])) + { + Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) during " + "clean up.\nGetLastError returned '%u'.\n", hToken[0], + GetLastError()); + LeaveCriticalSection(&CriticalSection); + Cleanup (&hToken[0], NUM_TOKENS); + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + /* wait to be signaled */ + dwTRet = WaitForSingleObject(hToken[1], 10000); + if (WAIT_OBJECT_0 != dwTRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " + "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " + "('%d').\nGetLastError returned '%u'.\n", + hToken[1], 10000, WAIT_OBJECT_0, dwTRet, GetLastError()); + LeaveCriticalSection(&CriticalSection); + Cleanup (&hToken[0], NUM_TOKENS); + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + LeaveCriticalSection(&CriticalSection); + + return 0; +} + +int __cdecl main(int argc, char **argv) +{ + DWORD dwThreadId; + DWORD dwMRet; + + if ((PAL_Initialize(argc,argv)) != 0) + { + return(FAIL); + } + + /* thread 0 event */ + hToken[0] = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (hToken[0] == NULL) + { + Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError " + "returned %u.\n", GetLastError()); + } + + /* thread 1 event */ + hToken[1] = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (hToken[1] == NULL) + { + Trace("PALSUITE ERROR: CreateEvent call #1 failed. GetLastError " + "returned %u.\n", GetLastError()); + Cleanup(&hToken[0], (NUM_TOKENS - 2)); + Fail(""); + } + + InitializeCriticalSection(&CriticalSection); + + hToken[2] = CreateThread(NULL, + 0, + &Thread, + (LPVOID) NULL, + 0, + &dwThreadId); + + if (hToken[2] == NULL) + { + Trace("PALSUITE ERROR: CreateThread call #0 failed. GetLastError " + "returned %u.\n", GetLastError()); + Cleanup(&hToken[0], (NUM_TOKENS - 1)); + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + /* wait for thread 0 to be signaled */ + dwMRet = WaitForSingleObject(hToken[0], 10000); + if (WAIT_OBJECT_0 != dwMRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " + "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " + "('%d').\nGetLastError returned '%u'.\n", hToken[0], 10000, + WAIT_OBJECT_0, dwMRet, GetLastError()); + Cleanup(&hToken[0], NUM_TOKENS); + Fail(""); + } + + /* + * Attempt to leave critical section which is owned by the other thread. + */ + LeaveCriticalSection(&CriticalSection); + + /* signal thread 1 */ + if (0 == SetEvent(hToken[1])) + { + Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) call.\n" + "GetLastError returned '%u'.\n", hToken[1], + GetLastError()); + Cleanup(&hToken[0], NUM_TOKENS); + Fail(""); + } + + dwMRet = WaitForSingleObject(hToken[2], 10000); + if (WAIT_OBJECT_0 != dwMRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call " + "returned an unexpected value '%d'.\nGetLastError returned " + "%u.\n", hToken[2], 10000, dwMRet, GetLastError()); + Cleanup(&hToken[0], NUM_TOKENS); + Fail(""); + } + + if (!Cleanup(&hToken[0], NUM_TOKENS)) + { + Fail(""); + } + + PAL_Terminate(); + + return(PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/testinfo.dat new file mode 100644 index 0000000..151e1ed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/testinfo.dat @@ -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. + +Version = 1.0 +Section = threading +Function = CriticalSectionFunctions +Name = Positive Test for LeaveCriticalSection +TYPE = DEFAULT +EXE1 = test6 +Description += Attempt to leave a critical section which is owned by another thread. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/CMakeLists.txt new file mode 100644 index 0000000..751bf68 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_criticalsectionfunctions_test7 + ${SOURCES} +) + +add_dependencies(paltest_criticalsectionfunctions_test7 coreclrpal) + +target_link_libraries(paltest_criticalsectionfunctions_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.cpp new file mode 100644 index 0000000..1c030d3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.cpp @@ -0,0 +1,188 @@ +// 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. + +/*===================================================================== +** +** Source: CriticalSectionFunctions/test7/test7.c +** +** Purpose: Attempt to delete a critical section owned by the current +** thread. +** +** +**===================================================================*/ +#include + +/* + * Tokens 0 and 1 are events. Token 2 is the thread. + */ +#define NUM_TOKENS 3 + +HANDLE hToken[NUM_TOKENS]; +CRITICAL_SECTION CriticalSection; + +BOOL CleanupHelper (HANDLE *hArray, DWORD dwIndex) +{ + BOOL bCHRet; + + bCHRet = CloseHandle(hArray[dwIndex]); + if (!bCHRet) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%u'.\n", hArray[dwIndex], + GetLastError()); + } + + return (bCHRet); +} + +BOOL Cleanup(HANDLE *hArray, DWORD dwIndex) +{ + BOOL bCRet; + BOOL bCHRet = 0; + + while (--dwIndex > 0) + { + bCHRet = CleanupHelper(&hArray[0], dwIndex); + } + + bCRet = CloseHandle(hArray[0]); + if (!bCRet) + { + Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " + "clean up.\nGetLastError returned '%u'.\n", hArray[dwIndex], + GetLastError()); + } + + return (bCRet&&bCHRet); +} + +DWORD PALAPI Thread(LPVOID lpParam) +{ + DWORD dwTRet; + + EnterCriticalSection(&CriticalSection); + + /* signal thread 0 */ + if (0 == SetEvent(hToken[0])) + { + Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) during " + "clean up.\nGetLastError returned '%u'.\n", hToken[0], + GetLastError()); + LeaveCriticalSection(&CriticalSection); + Cleanup (&hToken[0], NUM_TOKENS); + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + /* wait to be signaled */ + dwTRet = WaitForSingleObject(hToken[1], 10000); + if (WAIT_OBJECT_0 != dwTRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " + "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " + "('%d').\nGetLastError returned '%u'.\n", + hToken[0], 10000, WAIT_OBJECT_0, dwTRet, GetLastError()); + LeaveCriticalSection(&CriticalSection); + Cleanup (&hToken[0], NUM_TOKENS); + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + DeleteCriticalSection(&CriticalSection); + + return 0; +} + +int __cdecl main(int argc, char **argv) +{ + DWORD dwThreadId; + DWORD dwMRet; + + if ((PAL_Initialize(argc,argv)) != 0) + { + return(FAIL); + } + + /* thread 0 event */ + hToken[0] = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (hToken[0] == NULL) + { + Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError " + "returned %u.\n", GetLastError()); + } + + /* thread 1 event */ + hToken[1] = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (hToken[1] == NULL) + { + Trace("PALSUITE ERROR: CreateEvent call #1 failed. GetLastError " + "returned %u.\n", GetLastError()); + Cleanup (&hToken[0], (NUM_TOKENS - 2)); + Fail(""); + } + + InitializeCriticalSection(&CriticalSection); + + hToken[2] = CreateThread(NULL, + 0, + &Thread, + (LPVOID) NULL, + 0, + &dwThreadId); + + if (hToken[2] == NULL) + { + Trace("PALSUITE ERROR: CreateThread call #0 failed. GetLastError " + "returned %u.\n", GetLastError()); + Cleanup (&hToken[0], (NUM_TOKENS - 1)); + DeleteCriticalSection(&CriticalSection); + Fail(""); + } + + /* wait for thread 0 to be signaled */ + dwMRet = WaitForSingleObject(hToken[0], 10000); + if (WAIT_OBJECT_0 != dwMRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " + "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " + "('%d').\nGetLastError returned '%u'.\n", hToken[0], 10000, + WAIT_OBJECT_0, dwMRet, GetLastError()); + Cleanup (&hToken[0], NUM_TOKENS); + Fail(""); + } + + /* signal thread 1 */ + if (0 == SetEvent(hToken[1])) + { + Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) call.\n" + "GetLastError returned '%u'.\n", hToken[1], + GetLastError()); + Cleanup (&hToken[0], NUM_TOKENS); + Fail(""); + } + + dwMRet = WaitForSingleObject(hToken[2], 10000); + if (WAIT_OBJECT_0 != dwMRet) + { + Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call " + "returned an unexpected value '%d'.\nGetLastError returned " + "%u.\n", hToken[2], 10000, dwMRet, GetLastError()); + Cleanup (&hToken[0], NUM_TOKENS); + Fail(""); + } + + if (!Cleanup(&hToken[0], NUM_TOKENS)) + { + Fail(""); + } + + PAL_Terminate(); + + return (PASS); +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/testinfo.dat new file mode 100644 index 0000000..5cf5809 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/testinfo.dat @@ -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. + +Version = 1.0 +Section = threading +Function = CriticalSectionFunctions +Name = Positive test for DeleteCriticalSection +TYPE = DEFAULT +EXE1 = test7 +Description += Attempt to delete a critical section owned by the current thread. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/CMakeLists.txt new file mode 100644 index 0000000..a008315 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_criticalsectionfunctions_test8 + ${SOURCES} +) + +add_dependencies(paltest_criticalsectionfunctions_test8 coreclrpal) + +target_link_libraries(paltest_criticalsectionfunctions_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp new file mode 100644 index 0000000..7f0c58c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp @@ -0,0 +1,217 @@ +// 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. + +/*===================================================================== +** +** Source: CriticalSectionFunctions/test8/test8.c +** +** Pyrpose: Ensure critical section functionality is working by +** having multiple threads racing on a CS under different +** scenarios +** +** +**===================================================================*/ +#include + +#define MAX_THREAD_COUNT 128 +#define DEFAULT_THREAD_COUNT 10 +#define DEFAULT_LOOP_COUNT 1000 + +#ifndef MIN +#define MIN(a,b) (((a)<(b)) ? (a) : (b)) +#endif + +int g_iThreadCount = DEFAULT_THREAD_COUNT; +int g_iLoopCount = DEFAULT_LOOP_COUNT; +volatile LONG g_lCriticalCount = 0; +HANDLE g_hEvStart = NULL; + +CRITICAL_SECTION g_cs; +DWORD PALAPI Thread(LPVOID lpParam) +{ + int i, j, iLpCnt; + DWORD dwRet = 0; + DWORD dwTid = GetCurrentThreadId(); + LONG lRet; + BOOL bSleepInside; + BOOL bSleepOutside; + + Trace("[tid=%u] Thread starting\n", dwTid); + + dwRet = WaitForSingleObject(g_hEvStart, INFINITE); + if (WAIT_OBJECT_0 != dwRet) + { + Fail("WaitForSingleObject returned unexpected %u [GetLastError()=%u]\n", + dwRet, GetLastError()); + } + + for (j=0;j<8;j++) + { + bSleepInside = 2 & j; + bSleepOutside = 4 & j; + + iLpCnt = g_iLoopCount; + if (bSleepInside || bSleepOutside) + { + iLpCnt /= 10; + } + + for (i=0;i= iVal) + { + g_iThreadCount = iVal; + } + } + break; + default: + break; + } + } + } + + Trace ("Iterations:\t%d\n", g_iLoopCount); + Trace ("Threads:\t%d\n", g_iThreadCount); + + g_hEvStart = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (g_hEvStart == NULL) + { + Fail("CreateEvent call failed. GetLastError " + "returned %u.\n", GetLastError()); + } + + InitializeCriticalSection(&g_cs); + + for (i=0;i iThreadCount) + { + Fail("Failed to create minimum number if threads, i.e. 2\n"); + } + + if (!SetEvent(g_hEvStart)) + { + Fail("SetEvent failed [GetLastError()=%u]\n", GetLastError()); + } + + for (i=0; i + + +/* SHLEXT is defined only for Unix variants */ + +#if defined(SHLEXT) +#define LibName "testlib"SHLEXT +#define GETCALLCOUNT "GetCallCount" +#else +#define LibName "testlib" +#define GETCALLCOUNT "_GetCallCount@0" +#endif + +DWORD PALAPI ThreadFunc(LPVOID lpParam); +int RunTest(int DisableThreadCalls); + +int __cdecl main(int argc, char **argv) +{ + int ret; + + if ((PAL_Initialize(argc,argv)) != 0) + { + return (FAIL); + } + + + /* + * Although MSDN says that DisableThreadLibraryCalls will fail if passed + * an invalid handle, it actually returns success! + */ + ret = DisableThreadLibraryCalls(NULL); + if (!ret) + { + Fail("DisableThreadLibraryCalls failed on an invalid module " + "handle (it actually should pass)!\n"); + } + + + /* + * Test once without calling DisableThreadLibraryCalls and make sure we + * get expected results. + */ + ret = RunTest(0); + if (ret != 2) + { + Fail("Expected to get 2 thread library calls, got %d!\n", ret); + } + + + /* + * Test again, this time calling DisableThreadLibraryCalls. + */ + ret = RunTest(1); + if (ret != 0) + { + Fail("Expected to get 0 thread library calls, got %d!\n", ret); + } + + PAL_Terminate(); + return PASS; +} + +/* + * Thread entry point. Doesn't do anything. + */ +DWORD PALAPI ThreadFunc(LPVOID lpParam) +{ + return 0; +} + + +int RunTest(int DisableThreadCalls) +{ + HMODULE LibMod; + HANDLE hThread; + DWORD threadID; + DWORD WaitRet; + int (*GetCallCount)(); + int count; + + LibMod = LoadLibrary(LibName); + if (LibMod == NULL) + { + Fail("Unable to load test library!\nGetLastError returned %d\n", + GetLastError()); + } + + GetCallCount = (int(*)())GetProcAddress(LibMod, GETCALLCOUNT); + if (GetCallCount == NULL) + { + Fail("Unable to get function GetCallCount from library!\n" + "GetLastError returned %d\n", GetLastError()); + } + + if (DisableThreadCalls) + { + if (!DisableThreadLibraryCalls(LibMod)) + { + Fail("DisabledThreadLibraryCalls failed!\n" + "GetLastError returned %d!\n", GetLastError()); + } + } + + hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadFunc, + NULL, 0, &threadID); + + if (hThread == NULL) + { + Fail("Unable to create a thread!\n"); + } + + WaitRet = WaitForSingleObject(hThread, INFINITE); + if (WaitRet == WAIT_FAILED) + { + Fail("Unable to wait on thread!\nGetLastError returned %d\n", + GetLastError()); + } + + count = GetCallCount(); + + CloseHandle(hThread); + + if (!FreeLibrary(LibMod)) + { + Fail("Failed freeing library!\nGetLastError returned %d\n", + GetLastError()); + } + + return count; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testinfo.dat new file mode 100644 index 0000000..6d32f35 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Threading +Function = DisableThreadLibraryCalls +Name = Positive Test #1 for DisableThreadLibraryCalls +TYPE = DEFAULT +EXE1 = test1 +LIB1 = testlib +Description +=Tests that DisableThreadLibraryCalls actually stops thread +=attach/detach notifications to a library. Also tests how it +=handles an invalid module handle. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testlib.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testlib.cpp new file mode 100644 index 0000000..057dfde --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testlib.cpp @@ -0,0 +1,47 @@ +// 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. + +/*===================================================================== +** +** Source: testlib.c +** +** Purpose: Simple library that counts thread attach/detach notifications +** +** +**===================================================================*/ + +#include + +static int Count; + +BOOL PALAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + + if (fdwReason == DLL_PROCESS_ATTACH) + { + Count = 0; + } + else if (fdwReason == DLL_THREAD_ATTACH || + fdwReason == DLL_THREAD_DETACH) + { + Count++; + } + + return TRUE; +} + +#ifdef WIN32 +BOOL PALAPI _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + return DllMain(hinstDLL, fdwReason, lpvReserved); +} +#endif + +#ifdef WIN32 +__declspec(dllexport) +#endif +int PALAPI GetCallCount() +{ + return Count; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain1.cpp new file mode 100644 index 0000000..b65bb66 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain1.cpp @@ -0,0 +1,66 @@ +// 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. + +/*============================================================================= +** +** Source: dllmain1.c +** +** Purpose: Test to ensure DllMain() is called with THREAD_ATTACH +** when a thread in the application is started. +** +** Dependencies: none +** +** +**===========================================================================*/ + +#include + +/* count of the number of times DllMain() was called with THREAD_DETACH */ +static int g_attachCount = 0; + + +/* standard DllMain() */ +BOOL PALAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved) +{ + BOOL bResult = TRUE; + + switch( reason ) + { + case DLL_PROCESS_ATTACH: + { + break; + } + + case DLL_PROCESS_DETACH: + { + break; + } + + case DLL_THREAD_ATTACH: + /* increment g_attachCount */ + g_attachCount++; + break; + + case DLL_THREAD_DETACH: + break; + } + return bResult; +} + + +#ifdef WIN32 +BOOL PALAPI _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + return DllMain(hinstDLL, fdwReason, lpvReserved); +} +#endif + +/* function to return the current attach count */ +#ifdef WIN32 +__declspec(dllexport) +#endif +int PALAPI GetAttachCount( void ) +{ + return g_attachCount; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain2.cpp new file mode 100644 index 0000000..519083b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain2.cpp @@ -0,0 +1,66 @@ +// 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. + +/*============================================================================= +** +** Source: dllmain2.c +** +** Purpose: Test to ensure DllMain() is called with THREAD_ATTACH +** when a thread in the application is started. +** +** Dependencies: none +** +** +**===========================================================================*/ + +#include + +/* count of the number of times DllMain() was called with THREAD_DETACH */ +static int g_attachCount = 0; + + +/* standard DllMain() */ +BOOL PALAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved) +{ + BOOL bResult = TRUE; + + switch( reason ) + { + case DLL_PROCESS_ATTACH: + { + break; + } + + case DLL_PROCESS_DETACH: + { + break; + } + + case DLL_THREAD_ATTACH: + /* increment g_attachCount */ + g_attachCount++; + break; + + case DLL_THREAD_DETACH: + break; + } + return bResult; +} + + +#ifdef WIN32 +BOOL PALAPI _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + return DllMain(hinstDLL, fdwReason, lpvReserved); +} +#endif + +/* function to return the current attach count */ +#ifdef WIN32 +__declspec(dllexport) +#endif +int PALAPI GetAttachCount( void ) +{ + return g_attachCount; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/test2.cpp new file mode 100644 index 0000000..5fb694e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/test2.cpp @@ -0,0 +1,237 @@ +// 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. + +/*============================================================================= +** +** Source: test2.c +** +** Purpose: Test to ensure DisableThreadLibraryCalls() called for one +** library will not disrupt THREAD_ATTACH notifications etc. by +** other loaded modules. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** CreateThread +** ResumeThread +** LoadLibrary +** FreeLibrary +** GetProcAddress +** WaitForSingleObject +** GetLastError +** +** +**===========================================================================*/ +#include + +/* SHLEXT is defined only for Unix variants */ + +#if defined(SHLEXT) +#define rgchLibraryFile1 "dllmain1"SHLEXT +#define rgchLibraryFile2 "dllmain2"SHLEXT +#define szFunction "GetAttachCount" +#else +#define rgchLibraryFile1 "dllmain1" +#define rgchLibraryFile2 "dllmain2" +#define szFunction "_GetAttachCount@0" +#endif + +/* define our test function type */ +typedef int ( PALAPI *LPTESTFUNC )( void ); + + + +/** + * ThreadFunc + * + * Dummy thread function for causing DLL thread notifications. + */ +DWORD PALAPI ThreadFunc( LPVOID param ) +{ + /* simulate some brief "work" */ + int i; + for( i=0; i<100000; i++ ) + { + } + + return 0; +} + + +/* main program entry point */ +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + + HANDLE hLib1 = NULL; + HANDLE hLib2 = NULL; + LPTESTFUNC pFunc1; + LPTESTFUNC pFunc2; + int attachCount1a = 0; + int attachCount1b = 0; + int attachCount2a = 0; + int attachCount2b = 0; + + HANDLE hThread = NULL; + DWORD IDThread; + DWORD dwRet; + + BOOL bResult = FAIL; + + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + /* Load the first test library */ + hLib1 = LoadLibrary( rgchLibraryFile1 ); + if(hLib1 == NULL) + { + Fail( "ERROR:%lu:LoadLibrary() call failed for %s\n", + GetLastError(), + rgchLibraryFile1 ); + } + + /* Load the second test library */ + hLib2 = LoadLibrary( rgchLibraryFile2 ); + if(hLib2 == NULL) + { + Trace( "ERROR:%lu:LoadLibrary() call failed for %s\n", + GetLastError(), + rgchLibraryFile2 ); + if( ! FreeLibrary( hLib1 ) ) + { + Trace( "ERROR:%lu:FreeLibrary() call failed\n", GetLastError() ); + } + Fail( "test failed\n" ); + } + + + /* Get the addresses of our test functions in the dlls */ + pFunc1 = (LPTESTFUNC)GetProcAddress( hLib1, szFunction ); + if( pFunc1 == NULL ) + { + Trace( "ERROR:%lu%:Unable to find \"%s\" in library \"%s\"\n", + GetLastError(), + szFunction, + rgchLibraryFile1 ); + goto cleanup; + } + + pFunc2 = (LPTESTFUNC)GetProcAddress( hLib2, szFunction ); + if( pFunc1 == NULL ) + { + Trace( "ERROR:%lu%:Unable to find \"%s\" in library \"%s\"\n", + GetLastError(), + szFunction, + rgchLibraryFile2 ); + goto cleanup; + } + + /* disable thread library calls for the first library */ + if( ! DisableThreadLibraryCalls( (HMODULE)hLib1 ) ) + { + Trace( "ERROR:%lu:DisableThreadLibraryCalls() call failed\n", + GetLastError() ); + goto cleanup; + } + + /* Execute the test function to get the attach count */ + attachCount1a = pFunc1(); + attachCount2a = pFunc2(); + + /* run another dummy thread to cause notification of the libraries */ + hThread = CreateThread( NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */ + (LPVOID) NULL, /* pass thread index as */ + /* function argument */ + CREATE_SUSPENDED, /* create suspended */ + &IDThread ); /* returns thread id */ + + /* Check the return value for success. */ + if( hThread == NULL ) + { + /* error creating thread */ + Trace( "ERROR:%lu:CreateThread() call failed\n", + GetLastError() ); + goto cleanup; + } + + /* Resume the suspended thread */ + if( ResumeThread( hThread ) == -1 ) + { + Trace( "ERROR:%lu:ResumeThread() call failed\n", GetLastError() ); + goto cleanup; + } + + + /* wait for the thread to complete */ + dwRet = WaitForSingleObject( hThread, INFINITE ); + if( dwRet != WAIT_OBJECT_0 ) + { + Trace( "ERROR: WaitForSingleObject returned %lu, " + "expected WAIT_OBJECT_0\n", + dwRet ); + goto cleanup; + } + + + /* Execute the test function to get the new detach count */ + attachCount1b = pFunc1(); + attachCount2b = pFunc2(); + + /* validate the result */ + if( attachCount1b != attachCount1a ) + { + Trace( "FAIL: unexpected DLL attach count %d, expected %d\n", + attachCount1b, + attachCount1a ); + goto cleanup; + } + + /* validate the result */ + if( attachCount2b != (attachCount2a + 1) ) + { + Trace( "FAIL: unexpected DLL attach count %d, expected %d\n", + attachCount2b, + (attachCount2a + 1) ); + goto cleanup; + } + + bResult = PASS; + +cleanup: + /* Unload the test libraries */ + if( !FreeLibrary( hLib1 ) ) + { + Trace( "ERROR:%u:FreeLibrary() failed on library \"%s\"\n", + GetLastError(), + rgchLibraryFile1 ); + bResult = FAIL; + } + + if( !FreeLibrary( hLib2 ) ) + { + Trace( "ERROR:%u:FreeLibrary() failed on library \"%s\"\n", + GetLastError(), + rgchLibraryFile2 ); + bResult = FAIL; + } + + /* check for failure */ + if( bResult == FAIL ) + { + Fail( "test failed\n" ); + } + + /* terminate the PAL */ + PAL_Terminate(); + + /* return success */ + return PASS; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/testinfo.dat new file mode 100644 index 0000000..6d28595 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = threading +Function = DisableThreadLibraryCalls +Name = Test for DisableThreadLibraryCalls +TYPE = DEFAULT +EXE1 = test2 +LIB1 = dllmain1 +LIB2 = dllmain2 +Description += Test to ensure proper operation of the DisableThreadLibraryCalls() += API. This tests to make sure the DisableThreadLibraryCalls() called += for one DLL loaded by a process takes effect *only* for that DLL += and not for any others, by checking the THREAD_ATTACH notifications += in each. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt new file mode 100644 index 0000000..21851e4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt @@ -0,0 +1,12 @@ +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test1/CMakeLists.txt new file mode 100644 index 0000000..ddf7ca8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_duplicatehandle_test1 + ${SOURCES} +) + +add_dependencies(paltest_duplicatehandle_test1 coreclrpal) + +target_link_libraries(paltest_duplicatehandle_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test1/test1.cpp new file mode 100644 index 0000000..e080e98 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test1/test1.cpp @@ -0,0 +1,152 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c (DuplicateHandle) +** +** Purpose: Tests the PAL implementation of the DuplicateHandle function. +** This test will create two handles to file, one to write and +** one to read what was written. Test on a closed handle and a +** NULL handle, both should fail. +** +** +**===================================================================*/ +#include + +int __cdecl main(int argc, char **argv) +{ + HANDLE hFile; + HANDLE hDupFile; + char buf[256]; + char teststr[] = "A uNiQuE tEsT sTrInG"; + char lpFileName[] = "testfile.txt"; + DWORD dwBytesWritten; + DWORD dwBytesRead; + BOOL bRetVal; + + /*Initalize the PAL*/ + if ((PAL_Initialize(argc,argv)) != 0) + { + return (FAIL); + } + + /*Create a file handle with CreateFile*/ + hFile = CreateFile(lpFileName, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_WRITE|FILE_SHARE_READ, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), + lpFileName); + } + + /*Write test string to the file.*/ + bRetVal = WriteFile(hFile, // handle to file + teststr, // data buffer + strlen(teststr), // number of bytes to write + &dwBytesWritten, // number of bytes written + NULL); // overlapped buffer + + if (bRetVal == FALSE) + { + Trace("ERROR: %u : unable to write to file handle " + "hFile=0x%lx\n", + GetLastError(), + hFile); + CloseHandle(hFile); + Fail(""); + } + + /*Create a duplicate handle with DuplicateHandle.*/ + if (!(DuplicateHandle( + GetCurrentProcess(), + hFile, + GetCurrentProcess(), + &hDupFile, + GENERIC_READ|GENERIC_WRITE, + FALSE, + DUPLICATE_SAME_ACCESS))) + { + Trace("ERROR: %u : Fail to create the duplicate handle" + " to hFile=0x%lx\n", + GetLastError(), + hFile); + CloseHandle(hFile); + Fail(""); + } + + memset(buf, 0, 256); + + /*Read from the Duplicated handle.*/ + bRetVal = ReadFile(hDupFile, + buf, + 256, + &dwBytesRead, + NULL); + if (bRetVal == FALSE) + { + Trace("ERROR: %u :unable to read from file handle " + "hFile=0x%lx\n", + GetLastError(), + hFile); + CloseHandle(hFile); + CloseHandle(hDupFile); + Fail(""); + } + + /*Compare what was written to what was read.*/ + if (memcmp(teststr, buf, dwBytesRead) != 0) + { + Trace("ERROR: expected %s, got %s\n", teststr, buf); + CloseHandle(hFile); + CloseHandle(hDupFile); + Fail(""); + } + + /*Close the handles*/ + CloseHandle(hFile); + CloseHandle(hDupFile); + + /*Failure test: Create DuplicateHandle to a closed handle*/ + if ((DuplicateHandle( + GetCurrentProcess(), + hFile, + GetCurrentProcess(), + &hDupFile, + GENERIC_READ|GENERIC_WRITE, + FALSE, + DUPLICATE_SAME_ACCESS))) + { + Fail("ERROR: %u :Created a duplicate handle to" + " a closed handle hFile=0x%lx\n", + GetLastError(), + hFile); + } + + /*Failure test: Create DuplicateHandle to a NULL handle*/ + hFile = NULL; + if ((DuplicateHandle( + GetCurrentProcess(), + hFile, + GetCurrentProcess(), + &hDupFile, + GENERIC_READ|GENERIC_WRITE, + FALSE, + DUPLICATE_SAME_ACCESS))) + { + Fail("ERROR: %u :Created a duplicate handle to " + " a NULL handle hFile=0x%lx\n", + GetLastError(), + hFile); + } + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test1/testinfo.dat new file mode 100644 index 0000000..e22b0be --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Threading +Function = DuplicateHandle +Name = Positive Test for DuplicateHandle +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the DuplicateHandle function. += This test will create two handles to file, one to write and += one to read what was written. Test on a closed handle and a += NULL handle, both should fail. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test10/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test10/CMakeLists.txt new file mode 100644 index 0000000..8a2b02b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test10/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test10.cpp +) + +add_executable(paltest_duplicatehandle_test10 + ${SOURCES} +) + +add_dependencies(paltest_duplicatehandle_test10 coreclrpal) + +target_link_libraries(paltest_duplicatehandle_test10 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test10/test10.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test10/test10.cpp new file mode 100644 index 0000000..108d748 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test10/test10.cpp @@ -0,0 +1,239 @@ +// 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. + +/*===================================================================== +** +** Source: test10.c (DuplicateHandle) +** +** Purpose: Tests the PAL implementation of the DuplicateHandle function. +** This tests the operation of a duplicated Semaphore handle +** +** +**===================================================================*/ + +#include + +enum wait_results +{ + WR_WAITING, + WR_GOT_MUTEX, + WR_TIMED_OUT, + WR_RELEASED +}; + + +volatile int t1_result=WR_WAITING; +volatile int t2_result=WR_WAITING; + + +DWORD PALAPI ThreadTest1(LPVOID lpParam) +{ + DWORD dwWait; + + dwWait = WaitForSingleObject((HANDLE)lpParam, 0); + if (dwWait == WAIT_OBJECT_0) + { + /* tell the main thread we got the mutex */ + t1_result=WR_GOT_MUTEX; + + /* wait for main thread to tell us to release the mutex */ + while(WR_GOT_MUTEX == t1_result) + Sleep(1); + ReleaseSemaphore((HANDLE)lpParam, 1, NULL); + + /* tell the main thread we released the mutex */ + t1_result = WR_RELEASED; + } + else + { + t1_result = WR_TIMED_OUT; + } + return 0; +} + +DWORD PALAPI ThreadTest2(LPVOID lpParam) +{ + DWORD dwWait; + + dwWait = WaitForSingleObject((HANDLE)lpParam, 0 ); + if (dwWait == WAIT_OBJECT_0) + { + ReleaseSemaphore((HANDLE)lpParam, 1, NULL); + t2_result = WR_GOT_MUTEX; + } + else + { + t2_result = WR_TIMED_OUT; + } + + return 0; +} + + +int __cdecl main(int argc, char **argv) +{ + + HANDLE hDupSemaphore; + HANDLE hSemaphore; + HANDLE hThread; + HANDLE hThread2; + BOOL bDupHandle=FALSE; + DWORD dwThreadId = 0; + + if ((PAL_Initialize(argc,argv)) != 0) + { + return(FAIL); + } + + hSemaphore = CreateSemaphoreW( NULL, + 1, + 1, + NULL); + if (hSemaphore == NULL) + { + Fail("PALSUITE ERROR:%u: Unable to create mutex\n", + GetLastError()); + } + + /*Create Duplicate of the Semaphore above*/ + bDupHandle = DuplicateHandle(GetCurrentProcess(), + hSemaphore, + GetCurrentProcess(), + &hDupSemaphore, + GENERIC_READ|GENERIC_WRITE, + FALSE, + DUPLICATE_SAME_ACCESS); + if (!bDupHandle) + { + Trace("PALSUITE ERROR:%u: Created the duplicate handle to " + "closed event handle hSemaphore=0x%lx\n", + GetLastError(), + hSemaphore); + CloseHandle(hSemaphore); + Fail(""); + } + + /*Create a thread to test the Semaphore*/ + hThread = CreateThread(NULL, + 0, + &ThreadTest1, + hSemaphore, + 0, + &dwThreadId); + if (hThread == NULL) + { + Trace("PALSUITE ERROR:%u: unable to create thread\n", + GetLastError()); + CloseHandle(hSemaphore); + CloseHandle(hDupSemaphore); + Fail(""); + } + + /* wait until thread has taken the mutex */ + while (WR_WAITING == t1_result) + Sleep(1); + + if(WR_TIMED_OUT == t1_result) + { + Trace("PALSUITE ERROR: %u: thread couldn't acquire the semaphore\n", + GetLastError()); + CloseHandle(hSemaphore); + CloseHandle(hDupSemaphore); + CloseHandle(hThread); + Fail(""); + } + + /*Create a second thread to use the Semaphore's duplicate handle*/ + /*This thread should block since the Semaphore is owned by another + thread*/ + hThread2 = CreateThread(NULL, + 0, + &ThreadTest2, + hDupSemaphore, + 0, + &dwThreadId); + + if (hThread2 == NULL) + { + Trace("PALSUITE ERROR:%u: unable to create thread\n", + GetLastError()); + CloseHandle(hSemaphore); + CloseHandle(hDupSemaphore); + CloseHandle(hThread); + Fail(""); + } + + /* wait until thread has tried to take the mutex */ + while (WR_WAITING == t2_result) + Sleep(1); + + if (WR_TIMED_OUT != t2_result ) + { + Trace("PALSUITE ERROR:%u: Able to take mutex %#x while its " + "duplicate %#x is held\n", GetLastError(), hDupSemaphore, + hSemaphore); + CloseHandle(hSemaphore); + CloseHandle(hDupSemaphore); + CloseHandle(hThread); + CloseHandle(hThread2); + Fail(""); + } + + /* reset second thread status */ + t2_result = WR_WAITING; + + /* tell thread 1 to release the mutex */ + t1_result = WR_WAITING; + + /* wait for thread 1 to release the mutex */ + while (WR_WAITING == t1_result) + Sleep(1); + + CloseHandle(hThread2); + + /*Re-Create the second thread to reuse the duplicated Semaphore*/ + /*Since the Semaphore has since been released, the thread should + put WR_GOT_MUTEX into t2_result */ + hThread2 = CreateThread(NULL, + 0, + &ThreadTest2, + hDupSemaphore, + 0, + &dwThreadId); + + if (hThread2 == NULL) + { + Trace("PALSUITE ERROR:%u: unable to create thread\n", + GetLastError()); + CloseHandle(hSemaphore); + CloseHandle(hDupSemaphore); + CloseHandle(hThread); + Fail(""); + } + + /* wait until thread has taken the semaphore */ + while (WR_WAITING == t2_result) + Sleep(1); + + if (WR_GOT_MUTEX != t2_result ) + { + Trace("PALSUITE ERROR:%u: Unable to take semaphore %#x after its" + " duplicate %#x was released\n", GetLastError(), hDupSemaphore, + hSemaphore); + CloseHandle(hSemaphore); + CloseHandle(hDupSemaphore); + CloseHandle(hThread); + CloseHandle(hThread2); + Fail(""); + } + + /*Cleanup.*/ + CloseHandle(hSemaphore); + CloseHandle(hDupSemaphore); + CloseHandle(hThread); + CloseHandle(hThread2); + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test10/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test10/testinfo.dat new file mode 100644 index 0000000..674c71c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test10/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = Threading +Function = DuplicateHandle +Name = Test for DuplicateHandle (CreateSemaphore) +TYPE = DEFAULT +EXE1 = test10 +Description += Tests the PAL implementation of the DuplicateHandle function. += This test duplication of a Semaphore handle. The test will += create a Semaphore and duplicate a handle to it. += Then two subthreads will be used to verify that they can selectively += block each other with different handles that refer to the += same Semaphore diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/CMakeLists.txt new file mode 100644 index 0000000..e30228a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + test11.cpp +) + +add_executable(paltest_duplicatehandle_test11 + ${TESTSOURCES} +) + +add_dependencies(paltest_duplicatehandle_test11 coreclrpal) + +target_link_libraries(paltest_duplicatehandle_test11 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + childprocess.cpp +) + +add_executable(paltest_duplicatehandle_test11_child + ${HELPERSOURCES} +) + +add_dependencies(paltest_duplicatehandle_test11_child coreclrpal) + +target_link_libraries(paltest_duplicatehandle_test11_child + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/childprocess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/childprocess.cpp new file mode 100644 index 0000000..d5b310e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/childprocess.cpp @@ -0,0 +1,74 @@ +// 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. + +/*============================================================ +** +** Source: childprocess.c +** +** Purpose: Test to ensure DuplicateHandle works properly. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateMutexW +** WaitForSingleObject +** CloseHandle +** +** +**=========================================================*/ + +#include +#include "myexitcode.h" + + +int __cdecl main( int argc, char **argv ) +{ + HANDLE hMutex; + WCHAR wszMutexName[] = { 'T','E','S','T','1','1','\0' }; + DWORD dwRet; + int i; + + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + /* open a mutex to synchronize with the parent process */ + hMutex = CreateMutexW( NULL, FALSE, wszMutexName ); + if( hMutex == NULL ) + { + Fail( "ERROR:%lu:CreateMutex() call failed\r\n", GetLastError() ); + } + + /* acquire the mutex lock */ + dwRet = WaitForSingleObject( hMutex, 10000 ); + if( dwRet != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject() returned %lu, " + "expected WAIT_OBJECT_0", + dwRet ); + if( ! CloseHandle( hMutex ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + Fail( "test failed\n" ); + } + + + /* simulate some activity */ + for( i=0; i<50000; i++ ) + ; + + /* close our mutex handle */ + if( ! CloseHandle( hMutex ) ) + { + Fail( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + + /* terminate the PAL */ + PAL_Terminate(); + + /* return the predefined exit code */ + return TEST_EXIT_CODE; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/myexitcode.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/myexitcode.h new file mode 100644 index 0000000..84801cb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/myexitcode.h @@ -0,0 +1,13 @@ +// 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. + +/*============================================================ +** +** Source: duplicatehandle/test11/myexitcode.h +** +** Purpose: Define an exit code constant. +** +** +**=========================================================*/ +#define TEST_EXIT_CODE 31 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/test11.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/test11.cpp new file mode 100644 index 0000000..b05244c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/test11.cpp @@ -0,0 +1,364 @@ +// 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. + +/*============================================================================= +** +** Source: test11.c +** +** Purpose: +** +** Test to ensure proper operation of the DuplicateHandle API. +** The test launches a trivial child process, then opens +** a handle to it using OpenProcess. It then duplicates that +** handle and uses it to wait for the child process to terminate, +** and then checks the exit code of the child process in order to +** verify that it was in fact a handle to the correct +** process. The test tries to duplicate the handle again after +** the process has been closed, to verify that failure ensues. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** ZeroMemory +** GetCurrentDirectoryW +** CreateProcessW +** WaitForSingleObject +** CreateMutexW +** ReleaseMutex +** CloseHandle +** GetLastError +** strlen +** strncpy +** +** +**===========================================================================*/ +#include +#include "myexitcode.h" + + +static const char* rgchPathDelim = "\\"; + + +int +mkAbsoluteFilename( LPSTR dirName, + DWORD dwDirLength, + LPCSTR fileName, + DWORD dwFileLength, + LPSTR absPathName ) +{ + DWORD sizeDN, sizeFN, sizeAPN; + + sizeDN = strlen( dirName ); + sizeFN = strlen( fileName ); + sizeAPN = (sizeDN + 1 + sizeFN + 1); + + /* ensure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */ + if( sizeAPN > _MAX_PATH ) + { + return ( 0 ); + } + + strncpy( absPathName, dirName, dwDirLength +1 ); + strncpy( absPathName, rgchPathDelim, 2 ); + strncpy( absPathName, fileName, dwFileLength +1 ); + + return (sizeAPN); + +} + + +int __cdecl main( int argc, char **argv ) + +{ + const char* rgchChildFile = "childprocess"; + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + DWORD dwError; + DWORD dwExitCode; + DWORD dwFileLength; + DWORD dwDirLength; + DWORD dwSize; + DWORD dwRet; + + HANDLE hMutex; + HANDLE hChildProcess; + HANDLE hDupChildProcess; + + char rgchDirName[_MAX_DIR]; + char absPathBuf[_MAX_PATH]; + char* rgchAbsPathName; + + BOOL ret = FAIL; + BOOL bChildDone = FALSE; + WCHAR wszMutexName[] = { 'T','E','S','T','1','1','\0' }; + + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + /* create a mutex to synchronize with the child process */ + hMutex = CreateMutexW( NULL, TRUE, wszMutexName ); + if( hMutex == NULL ) + { + Fail( "ERROR:%lu:CreateMutex() call failed\r\n", GetLastError() ); + } + + /* zero our process and startup info structures */ + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof( si ); + ZeroMemory( &pi, sizeof(pi) ); + + /* build the absolute path to the child process */ + rgchAbsPathName = &absPathBuf[0]; + dwFileLength = strlen( rgchChildFile ); + + dwDirLength = GetCurrentDirectory( _MAX_PATH, rgchDirName ); + if( dwDirLength == 0 ) + { + dwError = GetLastError(); + if( ReleaseMutex( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() ); + } + if( CloseHandle( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + Fail( "GetCurrentDirectory call failed with error code %d\n", + dwError ); + } + + dwSize = mkAbsoluteFilename( rgchDirName, + dwDirLength, + rgchChildFile, + dwFileLength, + rgchAbsPathName ); + if( dwSize == 0 ) + { + if( ReleaseMutex( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() ); + } + if( CloseHandle( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + Fail( "Palsuite Code: mkAbsoluteFilename() call failed. Could ", + "not build absolute path name to file\n. Exiting.\n" ); + } + + /* launch the child process */ + if( !CreateProcess( NULL, /* module name to execute */ + rgchAbsPathName, /* command line */ + NULL, /* process handle not */ + /* inheritable */ + NULL, /* thread handle not */ + /*inheritable */ + FALSE, /* handle inheritance */ + CREATE_NEW_CONSOLE, /* dwCreationFlags */ + NULL, /* use parent's environment */ + NULL, /* use parent's starting */ + /* directory */ + &si, /* startup info struct */ + &pi ) /* process info struct */ + ) + { + dwError = GetLastError(); + if( ReleaseMutex( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() ); + } + if( CloseHandle( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + Fail( "CreateProcess call failed with error code %d\n", + dwError ); + } + + /* open another handle to the child process */ + hChildProcess = OpenProcess( PROCESS_ALL_ACCESS, /* access */ + FALSE, /* inheritable */ + pi.dwProcessId /* process id */ + ); + if( hChildProcess == NULL ) + { + dwError = GetLastError(); + if( ReleaseMutex( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() ); + } + Trace( "ERROR:%lu:OpenProcess call failed\n", dwError ); + goto cleanup3; + } + + /* duplicate the child process handle */ + if( ! DuplicateHandle( GetCurrentProcess(), + hChildProcess, + GetCurrentProcess(), + &hDupChildProcess, + GENERIC_READ|GENERIC_WRITE, + FALSE, + DUPLICATE_SAME_ACCESS) ) + { + Trace( "ERROR:%lu:DuplicateHandle() call failed\n", GetLastError() ); + if( ReleaseMutex( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() ); + } + goto cleanup2; + } + + /* release the mutex so the child can proceed */ + if( ReleaseMutex( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() ); + goto cleanup1; + } + + /* wait for the child process to complete, using the new handle */ + dwRet = WaitForSingleObject( hDupChildProcess, 10000 ); + if( dwRet != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject call returned %lu, " + "expected WAIT_OBJECT_0", + dwRet ); + goto cleanup1; + } + + /* remember that we waited until the child was finished */ + bChildDone = TRUE; + + /* check the exit code from the process -- this is a bit of an */ + /* extra verification that we opened the correct process handle */ + if( ! GetExitCodeProcess( hDupChildProcess, &dwExitCode ) ) + { + Trace( "ERROR:%lu:GetExitCodeProcess call failed\n", GetLastError() ); + goto cleanup1; + } + + /* verification */ + if( (dwExitCode & 0xFF) != (TEST_EXIT_CODE & 0xFF) ) + { + Trace( "GetExitCodeProcess returned an incorrect exit code %d, " + "expected value is %d\n", + (dwExitCode & 0xFF), + (TEST_EXIT_CODE & 0xFF)); + goto cleanup1; + } + + /* close the duplicate handle */ + if( ! CloseHandle( hDupChildProcess ) ) + { + Trace( "ERROR:%lu:CloseHandle call failed\n", GetLastError() ); + goto cleanup2; + } + + /* close the child process handle */ + if( ! CloseHandle ( hChildProcess ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + goto cleanup3; + } + + /* try to call duplicate handle on the closed child process handle */ + if( DuplicateHandle( GetCurrentProcess(), + hChildProcess, + GetCurrentProcess(), + &hDupChildProcess, + GENERIC_READ|GENERIC_WRITE, + FALSE, + DUPLICATE_SAME_ACCESS) ) + { + Trace( "ERROR:%lu:DuplicateHandle call succeeded on " + "a closed process handle, expected ERROR_INVALID_HANDLE\n" ); + if( ! CloseHandle( hDupChildProcess ) ) + { + Trace( "ERROR:%lu:CloseHandle call failed\n", GetLastError() ); + } + goto cleanup3; + } + + /* verify that the last error was ERROR_INVALID_HANDLE */ + dwRet = GetLastError(); + if( dwRet != ERROR_INVALID_HANDLE ) + { + Trace( "ERROR:DuplicateHandle returned %lu, " + "expected ERROR_INVALID_HANDLE\n", + dwRet ); + goto cleanup3; + } + + + /* success if we get here */ + ret = PASS; + + /* skip the cleanup stuff that's already done */ + goto cleanup3; + + +cleanup1: + /* close our duplicate handle */ + if( ! CloseHandle( hDupChildProcess ) ) + { + Trace( "ERROR:%lu:CloseHandle call failed\n", GetLastError() ); + ret = FAIL; + } + +cleanup2: + /* wait on the child process to complete if necessary */ + if( ! bChildDone ) + { + dwRet = WaitForSingleObject( hChildProcess, 10000 ); + if( dwRet != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject call returned %lu, " + "expected WAIT_OBJECT_0", + dwRet ); + ret = FAIL; + } + } + + /* close our child process handle */ + if( CloseHandle ( hChildProcess ) == 0 ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + ret = FAIL; + } + +cleanup3: + /* close all our other handles */ + if( CloseHandle ( pi.hProcess ) == 0 ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + ret = FAIL; + } + if( CloseHandle ( pi.hThread ) == 0 ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + ret = FAIL; + } + if( CloseHandle( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + ret = FAIL; + } + + if( ret == FAIL ) + { + Fail( "test failed\n" ); + } + + + + /* terminate the PAL */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/testinfo.dat new file mode 100644 index 0000000..1937877 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test11/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = threading +Function = DuplicateHandle +Name = Test for DuplicateHandle +TYPE = DEFAULT +EXE1 = test11 +EXE2 = childprocess +Description += Test to ensure proper operation of the DuplicateHandle API. += The test launches a trivial child process, then opens += a handle to it using OpenProcess. It then duplicates that += handle and uses it to wait for the child process to terminate, += and then checks the exit code of the child process in order to += verify that it was in fact a handle to the correct= process. The test tries to duplicate the handle again after += the process has been closed, to verify that failure ensues. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test12/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test12/CMakeLists.txt new file mode 100644 index 0000000..d83e46e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test12/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test12.cpp +) + +add_executable(paltest_duplicatehandle_test12 + ${SOURCES} +) + +add_dependencies(paltest_duplicatehandle_test12 coreclrpal) + +target_link_libraries(paltest_duplicatehandle_test12 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test12/test12.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test12/test12.cpp new file mode 100644 index 0000000..519194b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test12/test12.cpp @@ -0,0 +1,129 @@ +// 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. + +/*===================================================================== +** +** Source: test12.c (DuplicateHandle) +** +** Purpose: Tests the PAL implementation of the DuplicateHandle function. +** This test will create handle to file (to write) and close it, +** then call duplicate handle to read what was written. +** +** +**===================================================================*/ +#include + +int __cdecl main(int argc, char **argv) +{ + HANDLE hFile; + HANDLE hDupFile; + char buf[256]; + char teststr[] = "A uNiQuE tEsT sTrInG"; + char lpFileName[] = "testfile.txt"; + DWORD dwBytesWritten; + DWORD dwBytesRead; + BOOL bRetVal; + + /*Initalize the PAL*/ + if ((PAL_Initialize(argc,argv)) != 0) + { + return (FAIL); + } + + /*Create a file handle with CreateFile*/ + hFile = CreateFile(lpFileName, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_WRITE|FILE_SHARE_READ, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + Fail("ERROR: %u :unable to create file \"%s\".\n", + GetLastError(), + lpFileName); + } + + /*Write test string to the file.*/ + bRetVal = WriteFile(hFile, // handle to file + teststr, // data buffer + strlen(teststr), // number of bytes to write + &dwBytesWritten, // number of bytes written + NULL); // overlapped buffer + + if (bRetVal == FALSE) + { + Trace("ERROR: %u : unable to write to file handle " + "hFile=0x%lx\n", + GetLastError(), + hFile); + CloseHandle(hFile); + Fail(""); + } + + /*Create a duplicate handle with DuplicateHandle.*/ + if (!(DuplicateHandle( + GetCurrentProcess(), + hFile, + GetCurrentProcess(), + &hDupFile, + GENERIC_READ|GENERIC_WRITE, + FALSE, + DUPLICATE_SAME_ACCESS))) + { + Trace("ERROR: %u : Fail to create the duplicate handle" + " to hFile=0x%lx\n", + GetLastError(), + hFile); + CloseHandle(hFile); + Fail(""); + } + + if( !CloseHandle(hFile) ) + { + Fail("Duplicate Handle:Unable to close original file: Error[%u]\n", GetLastError()); + } + + memset(buf, 0, 256); + + /*Read from the Duplicated handle.*/ + bRetVal = ReadFile(hDupFile, + buf, + 256, + &dwBytesRead, + NULL); + if (bRetVal == FALSE) + { + Trace("ERROR: %u :unable to read from file handle " + "hFile=0x%lx\n", + GetLastError(), + hDupFile); + CloseHandle(hDupFile); + Fail(""); + } + + /*Compare what was written to what was read.*/ + if (memcmp(teststr, buf, dwBytesRead) != 0) + { + Trace("ERROR: expected %s, got %s\n", teststr, buf); + CloseHandle(hDupFile); + Fail(""); + } + + /*Close the handles*/ + CloseHandle(hDupFile); + + bRetVal = DeleteFileA(lpFileName); + if (bRetVal != TRUE) + { + Trace("Error:%u: DuplicateHandle, DeleteFileA: Couldn't delete DeleteFileA's" + " %s\n", GetLastError(), lpFileName); + Fail(""); + } + + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test12/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test12/testinfo.dat new file mode 100644 index 0000000..3d73362 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test12/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Threading +Function = DuplicateHandle +Name = Positive Test for DuplicateHandle +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the DuplicateHandle function. += This test will create handle to file (to write), += then call duplicate handle, and close the original handle += and then use duplicated handle to read what was written. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test2/CMakeLists.txt new file mode 100644 index 0000000..e962a11 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_duplicatehandle_test2 + ${SOURCES} +) + +add_dependencies(paltest_duplicatehandle_test2 coreclrpal) + +target_link_libraries(paltest_duplicatehandle_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test2/test2.cpp new file mode 100644 index 0000000..d1411e6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test2/test2.cpp @@ -0,0 +1,96 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c (DuplicateHandle) +** +** Purpose: Tests the PAL implementation of the DuplicateHandle function. +** This will test duplication of an CreateEvent handle. Test an +** event in a signaled state to wait, and then set the duplicate +** to nonsignaled state and perform the wait again. The wait on +** the event should fail. Test the duplication of closed and NULL +** events, these should fail. +** +** +**===================================================================*/ +#include + +int __cdecl main(int argc, char **argv) +{ + HANDLE hEvent; + HANDLE hDupEvent; + + /*Initalize the PAL.*/ + if ((PAL_Initialize(argc,argv)) != 0) + { + return (FAIL); + } + + /*Create an Event, and set it in the signaled state.*/ + hEvent = CreateEvent(0, TRUE, TRUE, 0); + if (hEvent == NULL) + { + Fail("ERROR: %u :unable to create event\n", + GetLastError()); + } + + /*Create a duplicate Event handle.*/ + if (!(DuplicateHandle(GetCurrentProcess(), + hEvent,GetCurrentProcess(), + &hDupEvent, + GENERIC_READ|GENERIC_WRITE, + FALSE, DUPLICATE_SAME_ACCESS))) + { + Trace("ERROR: %u :Fail to create the duplicate handle" + " to hEvent=0x%lx\n", + GetLastError(), + hEvent); + CloseHandle(hEvent); + Fail(""); + } + + /*Perform wait on Event that is in signaled state.*/ + if ((WaitForSingleObject(hEvent, 1000)) != WAIT_OBJECT_0) + { + Trace("ERROR: %u :WaitForSignalObject on Event=0x%lx set to " + " signaled state failed", + GetLastError(), + hEvent); + CloseHandle(hEvent); + CloseHandle(hDupEvent); + Fail(""); + } + + /*Set the Duplicate Event handle to nonsignaled state.*/ + if ((ResetEvent(hDupEvent)) == 0) + { + Trace("ERROR: %u :unable to reset dup event\n", + GetLastError()); + CloseHandle(hEvent); + CloseHandle(hDupEvent); + Fail(""); + } + + /*Perform wait on Event that is in signaled state.*/ + if ((WaitForSingleObject(hEvent, 1000)) == WAIT_OBJECT_0) + { + Trace("ERROR: %u: WaitForSignalObject succeeded on Event=0x%lx " + " when Duplicate Event=0x%lx set to nonsignaled state" + " succeeded\n", + GetLastError(), + hEvent, + hDupEvent); + CloseHandle(hEvent); + CloseHandle(hDupEvent); + Fail(""); + } + + /*Close handles to events.*/ + CloseHandle(hEvent); + CloseHandle(hDupEvent); + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test2/testinfo.dat new file mode 100644 index 0000000..2734408 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test2/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = Threading +Function = DuplicateHandle +Name = Test for DuplicateHandle +TYPE = DEFAULT +EXE1 = test2 +Description += Tests the PAL implementation of the DuplicateHandle function. += This will test duplication of an CreateEvent handle. Test an += event in a signaled state to wait, and then set the duplicate += to nonsignaled state and perform the wait again. The wait on += the event should fail. Test the duplication of closed and NULL += events, these should fail. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test3/CMakeLists.txt new file mode 100644 index 0000000..172616a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_duplicatehandle_test3 + ${SOURCES} +) + +add_dependencies(paltest_duplicatehandle_test3 coreclrpal) + +target_link_libraries(paltest_duplicatehandle_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test3/test3.cpp new file mode 100644 index 0000000..fc91b5e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test3/test3.cpp @@ -0,0 +1,123 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c (DuplicateHandle) +** +** Purpose: Tests the PAL implementation of the DuplicateHandle function. +** This will test duplication of an OpenEvent handle. Test an +** event in a signaled state to wait, and then set the duplicate +** to nonsignaled state and perform the wait again. The wait on +** the event should fail. Test the duplication of closed and NULL +** events, these should fail. +** +** +**===================================================================*/ +#include + +int __cdecl main(int argc, char **argv) +{ + HANDLE hCreateEvent; + HANDLE hOpenEvent; + HANDLE hDupEvent; + WCHAR lpEventName[]={'E','v','e','n','t','\0'}; + + /*Initialize the PAL.*/ + if ((PAL_Initialize(argc,argv)) != 0) + { + return (FAIL); + } + + /*Create an Event, and set it in the signaled state.*/ + hCreateEvent = CreateEventW(0, + TRUE, + TRUE, + lpEventName); + if (hCreateEvent == NULL) + { + Fail("ERROR: %u :unable to create event %s\n", + GetLastError(), + lpEventName); + } + + /*Open another handle to hCreateHandle with OpenEvent*/ + hOpenEvent = OpenEventW(EVENT_ALL_ACCESS, + TRUE, + lpEventName); + if (hOpenEvent == NULL) + { + Trace("ERROR: %u :unable to create handle with OpenEvent to %s\n", + GetLastError(), + lpEventName); + CloseHandle(hCreateEvent); + Fail(""); + } + + /*Create a duplicate Event handle*/ + if (!(DuplicateHandle(GetCurrentProcess(), + hOpenEvent, + GetCurrentProcess(), + &hDupEvent, + GENERIC_READ|GENERIC_WRITE, + FALSE, + DUPLICATE_SAME_ACCESS))) + { + Trace("ERROR: %u :Fail to create the duplicate handle" + " to hCreateEvent=0x%lx\n", + GetLastError(), + hCreateEvent); + CloseHandle(hCreateEvent); + CloseHandle(hOpenEvent); + Fail(""); + } + + /*Perform wait on Event that is in signaled state*/ + if ((WaitForSingleObject(hOpenEvent, 1000)) != WAIT_OBJECT_0) + { + Trace("ERROR: %u :WaitForSignalObject on hOpenEvent=0x%lx set to " + " signaled state failed\n", + GetLastError(), + hOpenEvent); + CloseHandle(hCreateEvent); + CloseHandle(hOpenEvent); + CloseHandle(hDupEvent); + Fail(""); + } + + /*Set the Duplicate Event handle to nonsignaled state*/ + if ((ResetEvent(hDupEvent)) == 0) + { + Trace("ERROR: %u: unable to reset hDupEvent=0x%lx\n", + GetLastError(), + hDupEvent); + CloseHandle(hCreateEvent); + CloseHandle(hOpenEvent); + CloseHandle(hDupEvent); + Fail(""); + } + + /*Perform wait on Event that is in signaled state*/ + if ((WaitForSingleObject(hOpenEvent, 1000)) == WAIT_OBJECT_0) + { + Trace("ERROR: %u :WaitForSignalObject succeeded on hOpenEvent=0x%lx " + " when Duplicate hDupEvent=0x%lx set to nonsignaled state" + " succeeded\n", + GetLastError(), + hOpenEvent, + hDupEvent); + CloseHandle(hCreateEvent); + CloseHandle(hOpenEvent); + CloseHandle(hDupEvent); + Fail(""); + } + + /*Close handles the events*/ + CloseHandle(hCreateEvent); + CloseHandle(hOpenEvent); + CloseHandle(hDupEvent); + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test3/testinfo.dat new file mode 100644 index 0000000..a10adb9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test3/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = Threading +Function = DuplicateHandle +Name = Test for DuplicateHandle +TYPE = DEFAULT +EXE1 = test3 +Description += Tests the PAL implementation of the DuplicateHandle function. += This will test duplication of an OpenEvent handle. Test an += event in a signaled state to wait, and then set the duplicate += to nonsignaled state and perform the wait again. The wait on += the event should fail. Test the duplication of closed and NULL += events, these should fail. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt new file mode 100644 index 0000000..605365d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_duplicatehandle_test4 + ${SOURCES} +) + +add_dependencies(paltest_duplicatehandle_test4 coreclrpal) + +target_link_libraries(paltest_duplicatehandle_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.cpp new file mode 100644 index 0000000..14a72db --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.cpp @@ -0,0 +1,239 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c (DuplicateHandle) +** +** Purpose: Tests the PAL implementation of the DuplicateHandle function. +** This test duplication of a Mutex handle. The test will comprise +** of creating a Mutex and its duplicate and create a thread that +** will get ownership. Another thread will be create that will +** attempt to get ownership of the duplicate Mutex, this will +** fail, since the Mutex is owned by another thread. The Mutex +** will be released and then the thread will attempt to get +** ownership of the duplicate Mutex, this will succeed. +** +** +**===================================================================*/ +#include + +enum wait_results +{ + WR_WAITING, + WR_GOT_MUTEX, + WR_TIMED_OUT, + WR_RELEASED +}; + + +volatile int t1_result=WR_WAITING; +volatile int t2_result=WR_WAITING; + + +DWORD PALAPI ThreadTest1(LPVOID lpParam) +{ + DWORD dwWait; + + dwWait = WaitForSingleObject((HANDLE)lpParam, 0); + if (dwWait == WAIT_OBJECT_0) + { + /* tell the main thread we got the mutex */ + t1_result=WR_GOT_MUTEX; + + /* wait for main thread to tell us to release the mutex */ + while(WR_GOT_MUTEX == t1_result) + Sleep(1); + ReleaseMutex((HANDLE)lpParam); + + /* tell the main thread we released the mutex */ + t1_result = WR_RELEASED; + } + else + { + t1_result = WR_TIMED_OUT; + } + return 0; +} + +DWORD PALAPI ThreadTest2(LPVOID lpParam) +{ + DWORD dwWait; + + dwWait = WaitForSingleObject((HANDLE)lpParam, 0 ); + if (dwWait == WAIT_OBJECT_0) + { + ReleaseMutex((HANDLE)lpParam); + t2_result = WR_GOT_MUTEX; + } + else + { + t2_result = WR_TIMED_OUT; + } + + return 0; +} + + +int __cdecl main(int argc, char **argv) +{ + + HANDLE hDupMutex; + HANDLE hMutex; + HANDLE hThread; + HANDLE hThread2; + BOOL bDupHandle=FALSE; + DWORD dwThreadId = 0; + + if ((PAL_Initialize(argc,argv)) != 0) + { + return(FAIL); + } + + /*Create Mutex without ownership*/ + hMutex = CreateMutexW(NULL, // no security attributes + FALSE, // initially not owned + NULL); // name of mutex + if (hMutex == NULL) + { + Fail("ERROR:%u: Unable to create mutex\n", + GetLastError()); + } + + /*Create Duplicate of the Mutex above*/ + bDupHandle = DuplicateHandle(GetCurrentProcess(), + hMutex, + GetCurrentProcess(), + &hDupMutex, + GENERIC_READ|GENERIC_WRITE, + FALSE, + DUPLICATE_SAME_ACCESS); + if (!bDupHandle) + { + Trace("ERROR:%u: Created the duplicate handle to " + "closed event handle hMutex=0x%lx\n", + GetLastError(), + hMutex); + CloseHandle(hMutex); + Fail(""); + } + + /*Create a thread to test the Mutex*/ + hThread = CreateThread(NULL, + 0, + &ThreadTest1, + hMutex, + 0, + &dwThreadId); + if (hThread == NULL) + { + Trace("ERROR:%u: unable to create thread\n", + GetLastError()); + CloseHandle(hMutex); + CloseHandle(hDupMutex); + Fail(""); + } + + /* wait until thread has taken the mutex */ + while (WR_WAITING == t1_result) + Sleep(1); + + if(WR_TIMED_OUT == t1_result) + { + Trace("ERROR: %u: thread 1 couldn't acquire the mutex\n"); + CloseHandle(hMutex); + CloseHandle(hDupMutex); + CloseHandle(hThread); + Fail(""); + } + + /*Create a second thread to use the duplicate Mutex*/ + /*This should fail since the Mutex is owned hThread*/ + hThread2 = CreateThread(NULL, + 0, + &ThreadTest2, + hDupMutex, + 0, + &dwThreadId); + + if (hThread2 == NULL) + { + Trace("ERROR:%u: unable to create thread\n", + GetLastError()); + CloseHandle(hMutex); + CloseHandle(hDupMutex); + CloseHandle(hThread); + Fail(""); + } + + /* wait until thread has tried to take the mutex */ + while (WR_WAITING == t2_result) + Sleep(1); + + if (WR_TIMED_OUT != t2_result ) + { + Trace("ERROR:%u: Able to take mutex %#x while its duplicate %#x is " + "held\n", hDupMutex, hMutex); + CloseHandle(hMutex); + CloseHandle(hDupMutex); + CloseHandle(hThread); + CloseHandle(hThread2); + Fail(""); + } + + /* reset second thread status */ + t2_result = WR_WAITING; + + /* tell thread 1 to release the mutex */ + t1_result = WR_WAITING; + + /* wait for thread 1 to release the mutex */ + while (WR_WAITING == t1_result) + Sleep(1); + + CloseHandle(hThread2); + + /*Re-Create the second thread to reuse the duplicated Mutex*/ + /*This test should pass, the Mutex has since been released*/ + hThread2 = CreateThread(NULL, + 0, + &ThreadTest2, + hDupMutex, + 0, + &dwThreadId); + + if (hThread2 == NULL) + { + Trace("ERROR:%u: unable to create thread\n", + GetLastError()); + CloseHandle(hMutex); + CloseHandle(hDupMutex); + CloseHandle(hThread); + Fail(""); + } + + /* wait until thread has taken the mutex */ + while (WR_WAITING == t2_result) + Sleep(1); + + if (WR_GOT_MUTEX != t2_result ) + { + Trace("ERROR:%u: Unable to take mutex %#x after its duplicate %#x was " + "released\n", hDupMutex, hMutex); + CloseHandle(hMutex); + CloseHandle(hDupMutex); + CloseHandle(hThread); + CloseHandle(hThread2); + Fail(""); + } + + /*Cleanup.*/ + CloseHandle(hMutex); + CloseHandle(hDupMutex); + CloseHandle(hThread); + CloseHandle(hThread2); + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test4/testinfo.dat new file mode 100644 index 0000000..64842f8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test4/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = Threading +Function = DuplicateHandle +Name = Test for DuplicateHandle (CreateMutex) +TYPE = DEFAULT +EXE1 = test4 +Description += Tests the PAL implementation of the DuplicateHandle function. += This test duplication of a Mutex handle. The test will comprise += of creating a Mutex and its duplicate and create a thread that will += get ownership. Another thread will be create that will attempt to += get ownership of the duplicate Mutex, this will fail, since the += Mutex is owned by another thread. The Mutex will be released and += then the thread will attempt to get ownership of the duplicate += Mutex, this will succeed. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test5/CMakeLists.txt new file mode 100644 index 0000000..9f4b8aa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_duplicatehandle_test5 + ${SOURCES} +) + +add_dependencies(paltest_duplicatehandle_test5 coreclrpal) + +target_link_libraries(paltest_duplicatehandle_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test5/test5.cpp new file mode 100644 index 0000000..a588928 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test5/test5.cpp @@ -0,0 +1,145 @@ +// 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. + +/*===================================================================== +** +** Source: test5.c (DuplicateHandle) +** +** Purpose: Tests the PAL implementation of the DuplicateHandle function, +** with CreatePipe. This test will create a pipe and write to it, +** the duplicate the read handle and read what was written. +** +** Depends: WriteFile +** ReadFile +** memcmp +** CloseHandle +** +** +**===================================================================*/ + +#include + +const char* cTestString = "one fish, two fish, red fish, blue fish."; + +int __cdecl main(int argc, char **argv) +{ + HANDLE hReadPipe = NULL; + HANDLE hWritePipe = NULL; + HANDLE hDupPipe = NULL; + BOOL bRetVal = FALSE; + DWORD dwBytesWritten; + DWORD dwBytesRead; + char buffer[256]; + + SECURITY_ATTRIBUTES lpPipeAttributes; + + /*Initialize the PAL*/ + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/ + lpPipeAttributes.nLength = sizeof(lpPipeAttributes); + lpPipeAttributes.lpSecurityDescriptor = NULL; + lpPipeAttributes.bInheritHandle = TRUE; + + /*Create a Pipe*/ + bRetVal = CreatePipe(&hReadPipe, /* read handle*/ + &hWritePipe, /* write handle */ + &lpPipeAttributes,/* security attributes*/ + 0); /* pipe size*/ + if (bRetVal == FALSE) + { + Fail("ERROR:%u:Unable to create pipe\n", GetLastError()); + } + + /*Write to the write pipe handle*/ + bRetVal = WriteFile(hWritePipe, /* handle to write pipe*/ + cTestString, /* buffer to write*/ + strlen(cTestString),/* number of bytes to write*/ + &dwBytesWritten, /* number of bytes written*/ + NULL); /* overlapped buffer*/ + if (bRetVal == FALSE) + { + Trace("ERROR:%u:unable to write to write pipe handle " + "hWritePipe=0x%lx\n", GetLastError(), hWritePipe); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + Fail(""); + } + + /*Duplicate the pipe handle*/ + if (!(DuplicateHandle(GetCurrentProcess(), /* source handle process*/ + hReadPipe, /* handle to duplicate*/ + GetCurrentProcess(), /* target process handle*/ + &hDupPipe, /* duplicate handle*/ + GENERIC_READ|GENERIC_WRITE,/* requested access*/ + FALSE, /* handle inheritance*/ + DUPLICATE_SAME_ACCESS))) /* optional actions*/ + { + Trace("ERROR:%u:Fail to create the duplicate handle" + " to hReadPipe=0x%lx", + GetLastError(), + hReadPipe); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + Fail(""); + } + + /*Read from the duplicated handle, 256 bytes, more bytes + than actually written. This will allow us to use the + value that ReadFile returns for comparision.*/ + bRetVal = ReadFile(hDupPipe, /* handle to read pipe*/ + buffer, /* buffer to write to*/ + 256, /* number of bytes to read*/ + &dwBytesRead, /* number of bytes read*/ + NULL); /* overlapped buffer*/ + if (bRetVal == FALSE) + { + Trace("ERROR:%u:unable read from the duplicated pipe " + "hDupPipe=0x%lx\n", + GetLastError(), + hDupPipe); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + CloseHandle(hDupPipe); + Fail(""); + } + + /*Compare what was read with what was written.*/ + if ((memcmp(cTestString, buffer, dwBytesRead)) != 0) + { + Trace("ERROR:%u: read \"%s\" expected \"%s\" \n", + GetLastError(), + buffer, + cTestString); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + CloseHandle(hDupPipe); + Fail(""); + } + + /*Compare values returned from WriteFile and ReadFile.*/ + if (dwBytesWritten != dwBytesRead) + { + Trace("ERROR:%u: WriteFile wrote \"%s\", but ReadFile read \"%s\"," + " these should be the same\n", + GetLastError(), + buffer, + cTestString); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + CloseHandle(hDupPipe); + Fail(""); + } + + /*Cleanup.*/ + CloseHandle(hWritePipe); + CloseHandle(hReadPipe); + CloseHandle(hDupPipe); + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test5/testinfo.dat new file mode 100644 index 0000000..97e42a9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test5/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = Threading +Function = DuplicateHandle +Name = Test for DuplicateHandle (CreatePipe) +TYPE = DEFAULT +EXE1 = test5 +Description += Tests the PAL implementation of the DuplicateHandle function, += with CreatePipe. This test will create a pipe and write to it, += then duplicate the read handle and read what was written. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test6/CMakeLists.txt new file mode 100644 index 0000000..fa37e1c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_duplicatehandle_test6 + ${SOURCES} +) + +add_dependencies(paltest_duplicatehandle_test6 coreclrpal) + +target_link_libraries(paltest_duplicatehandle_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test6/test6.cpp new file mode 100644 index 0000000..026f315 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test6/test6.cpp @@ -0,0 +1,146 @@ +// 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. + +/*===================================================================== +** +** Source: test6.c (DuplicateHandle) +** +** Purpose: Tests the PAL implementation of the DuplicateHandle function, +** with CreatePipe. This test will create a pipe, then duplicate +** the write handle, write to the handle, and use the read to +** verify. +** +** Depends: WriteFile +** ReadFile +** memcmp +** CloseHandle +** +** +**===================================================================*/ + +#include + +const char* cTestString = "one fish, two fish, red fish, blue fish."; + +int __cdecl main(int argc, char **argv) +{ + HANDLE hReadPipe = NULL; + HANDLE hWritePipe = NULL; + HANDLE hDupPipe = NULL; + BOOL bRetVal = FALSE; + DWORD dwBytesWritten; + DWORD dwBytesRead; + char buffer[256]; + + SECURITY_ATTRIBUTES lpPipeAttributes; + + /*Initialize the PAL*/ + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/ + lpPipeAttributes.nLength = sizeof(lpPipeAttributes); + lpPipeAttributes.lpSecurityDescriptor = NULL; + lpPipeAttributes.bInheritHandle = TRUE; + + /*Create a Pipe*/ + bRetVal = CreatePipe(&hReadPipe, /* read handle*/ + &hWritePipe, /* write handle */ + &lpPipeAttributes,/* security attributes*/ + 0); /* pipe size*/ + if (bRetVal == FALSE) + { + Fail("ERROR: %ld :Unable to create pipe\n", GetLastError()); + } + + /*Duplicate the pipe handle*/ + if (!(DuplicateHandle(GetCurrentProcess(), /* source handle process*/ + hWritePipe, /* handle to duplicate*/ + GetCurrentProcess(), /* target process handle*/ + &hDupPipe, /* duplicate handle*/ + GENERIC_READ|GENERIC_WRITE,/* requested access*/ + FALSE, /* handle inheritance*/ + DUPLICATE_SAME_ACCESS))) /* optional actions*/ + { + Trace("ERROR: %ld :Fail to create the duplicate handle" + " to hWritePipe=0x%lx", + GetLastError(), + hWritePipe); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + Fail(""); + } + + /*Write to the duplicate write pipe handle*/ + bRetVal = WriteFile(hDupPipe, /* handle to write pipe*/ + cTestString, /* buffer to write*/ + strlen(cTestString),/* number of bytes to write*/ + &dwBytesWritten, /* number of bytes written*/ + NULL); /* overlapped buffer*/ + if (bRetVal == FALSE) + { + Trace("ERROR: %ld :unable to write to duplicate write pipe handle " + "hDupPipe=0x%lx\n", + GetLastError(), + hDupPipe); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + CloseHandle(hDupPipe); + Fail(""); + } + + /*Read from the read handle, 256 bytes, more bytes + then actually written. This will give allow us to use + the value that ReadFile returns for comparision.*/ + bRetVal = ReadFile(hReadPipe, /* handle to read pipe*/ + buffer, /* buffer to write to*/ + 256, /* number of bytes to read*/ + &dwBytesRead, /* number of bytes read*/ + NULL); /* overlapped buffer*/ + if (bRetVal == FALSE) + { + Trace("ERROR: %ld : unable read hReadPipe=0x%lx\n", + GetLastError(), hReadPipe); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + CloseHandle(hDupPipe); + Fail(""); + } + + /*Compare what was read with what was written.*/ + if ((memcmp(cTestString, buffer, dwBytesRead)) != 0) + { + Trace("ERROR: read \"%s\" expected \"%s\" \n", + buffer, + cTestString); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + CloseHandle(hDupPipe); + Fail(""); + } + + /*Compare values returned from WriteFile and ReadFile.*/ + if (dwBytesWritten != dwBytesRead) + { + Trace("ERROR: WriteFile wrote \"%s\", but ReadFile read \"%s\"," + " these should be the same\n", + buffer, + cTestString); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + CloseHandle(hDupPipe); + Fail(""); + } + + /*Cleanup.*/ + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + CloseHandle(hDupPipe); + + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test6/testinfo.dat new file mode 100644 index 0000000..6c49d64 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test6/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = Threading +Function = DuplicateHandle +Name = Test for DuplicateHandle (CreatePipe) +TYPE = DEFAULT +EXE1 = test6 +Description += Tests the PAL implementation of the DuplicateHandle function, += with CreatePipe. This test will create a pipe, then duplicate += the write handle, write to the handle, and use the read to += verify. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test7/CMakeLists.txt new file mode 100644 index 0000000..d3be5f2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_duplicatehandle_test7 + ${SOURCES} +) + +add_dependencies(paltest_duplicatehandle_test7 coreclrpal) + +target_link_libraries(paltest_duplicatehandle_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test7/test7.cpp new file mode 100644 index 0000000..7074d37 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test7/test7.cpp @@ -0,0 +1,178 @@ +// 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. + +/*===================================================================== +** +** Source: test7.c (DuplicateHandle) +** +** Purpose: Tests the PAL implementation of the DuplicateHandle function, +** with a handle from CreateThread. The test will create a thread +** handle and its duplicate. Then get the priorities of the threads, +** set the priority of one and the change should be seen in the +** other. +** +** +**===================================================================*/ + +#include + +DWORD PALAPI CreateTestThread(LPVOID lpParam); + +int __cdecl main(int argc, char* argv[]) +{ + HANDLE hThread; + HANDLE hDupThread; + DWORD dwThreadId = 0; + LPTHREAD_START_ROUTINE lpStartAddress = &CreateTestThread; + HANDLE hSyncEvent; + + int threadPriority; + int duplicatePriority; + int finalPriority; + + /* Initialize the PAL.*/ + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + BOOL bManualReset = TRUE; + BOOL bInitialState = FALSE; + hSyncEvent = CreateEvent(lpEventAttributes, + bManualReset, + bInitialState, + NULL); + + if (hSyncEvent == NULL) + { + Fail("ERROR:%u: Unable to create sync event.\n", + GetLastError()); + } + + /* Create a thread.*/ + hThread = CreateThread(NULL, /* SD*/ + (DWORD)0, /* initial stack size*/ + lpStartAddress, /* thread function*/ + (VOID*)hSyncEvent,/* thread argument*/ + (DWORD)0, /* creation option*/ + &dwThreadId); /* thread identifier*/ + if (hThread == NULL) + { + Fail("ERROR:%u: Unable to create thread.\n", + GetLastError()); + } + + /* Duplicate the thread handle.*/ + if (!(DuplicateHandle(GetCurrentProcess(), /* source handle process*/ + hThread, /* handle to duplicate*/ + GetCurrentProcess(), /* target process handle*/ + &hDupThread, /* duplicate handle*/ + (DWORD)0, /* requested access*/ + FALSE, /* handle inheritance*/ + DUPLICATE_SAME_ACCESS))) /* optional actions*/ + { + Trace("ERROR: %ld :Fail to create the duplicate handle" + " to hThread=0x%lx", + GetLastError(), + hThread); + CloseHandle(hThread); + Fail(""); + } + + /* Get the priority of the thread.*/ + threadPriority = GetThreadPriority(hThread); + if(threadPriority != 0) + { + Trace("ERROR: Thread priority of hThread=0x%lx should be " + "set to normal THREAD_PRIORITY_NORMAL=%d\n", + hThread, + THREAD_PRIORITY_NORMAL); + CloseHandle(hThread); + CloseHandle(hDupThread); + Fail(""); + } + + /* Get the priority of the duplicated handle, and compare it to + * the priority of the original thread. Should be the same.*/ + duplicatePriority = GetThreadPriority(hThread); + if(duplicatePriority != threadPriority) + { + Trace("ERROR: Expected priority of hThread=0x%lx and hDupThread=0x%lx" + " to be the same. Priorities:hThread=\"%d\":hDupThread=\"%d\"\n", + hThread, + hDupThread, + threadPriority, + duplicatePriority); + CloseHandle(hThread); + CloseHandle(hDupThread); + Fail(""); + } + + /* Set the priority of the duplicate thread.*/ + if(!SetThreadPriority (hDupThread,THREAD_PRIORITY_HIGHEST)) + { + Trace("ERROR:%u: SetThreadPriority failed on hThread=0x%lx\n", + GetLastError(), + hDupThread); + CloseHandle(hThread); + CloseHandle(hDupThread); + Fail(""); + } + + /* Get the priority of the original thread, and + * compare it to what the duplicate was set to.*/ + finalPriority = GetThreadPriority(hThread); + if (finalPriority != THREAD_PRIORITY_HIGHEST) + { + Trace("ERROR: Expected priority of hThread=0x%lw and " + "hDupThread=0x%lw to be set the same. Priorities:" + "hThread=\"%d\":hDupThread=\"%d\".\n", + hThread, + hDupThread, + threadPriority, + duplicatePriority); + CloseHandle(hThread); + CloseHandle(hDupThread); + Fail(""); + } + + /* Signal the helper thread that it can shut down */ + if (!SetEvent(hSyncEvent)) + { + Fail("ERROR:%u: Failed to set event.\n", + GetLastError()); + } + + /* Wait on the original thread.*/ + if((WaitForSingleObject(hThread, 100)) != WAIT_OBJECT_0) + { + Trace("ERROR:%u: hThread=0x%lx is in a non-signalled " + "mode, yet created signalled.\n", + GetLastError(), + hThread); + CloseHandle(hThread); + CloseHandle(hDupThread); + Fail(""); + } + + /* Clean-up thread and Terminate the PAL.*/ + CloseHandle(hSyncEvent); + CloseHandle(hThread); + CloseHandle(hDupThread); + PAL_Terminate(); + return PASS; +} + +/*Thread testing function*/ +DWORD PALAPI CreateTestThread(LPVOID lpParam) +{ + HANDLE hSyncEvent = (HANDLE)lpParam; + + /* Wait until the main thread signals that this helper thread should shut down */ + WaitForSingleObject(hSyncEvent, INFINITE); + + return (DWORD)0; +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test7/testinfo.dat new file mode 100644 index 0000000..b8092d6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test7/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Threading +Function = DuplicateHandle +Name = Test for DuplicateHandle (CreateThread) +TYPE = DEFAULT +EXE1 = test7 +Description += Tests the PAL implementation of the DuplicateHandle function, += with a handle from CreateThread. The test will create a thread += handle and its duplicate. Then get the priorities of the threads, += set the priority of one and the change should be seen in the += other. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test8/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test8/CMakeLists.txt new file mode 100644 index 0000000..60ebe7a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test8.cpp +) + +add_executable(paltest_duplicatehandle_test8 + ${SOURCES} +) + +add_dependencies(paltest_duplicatehandle_test8 coreclrpal) + +target_link_libraries(paltest_duplicatehandle_test8 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test8/test8.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test8/test8.cpp new file mode 100644 index 0000000..6748c5d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test8/test8.cpp @@ -0,0 +1,164 @@ +// 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. + +/*===================================================================== +** +** Source: test8.c (DuplicateHandle) +** +** Purpose: Tests the PAL implementation of the DuplicateHandle function, +** with a handle from GetCurrentThread. The test will create a thread +** handle, get the current thread and its duplicate. Then get the +** priorities of the threads, set the priority of one and the change +** should be seen in the other. +** +** +**===================================================================*/ + +#include + +DWORD PALAPI CreateTestThread(LPVOID lpParam); + +int __cdecl main(int argc, char* argv[]) +{ + HANDLE hThread; + HANDLE hCurrentThread; + HANDLE hDupThread; + DWORD dwThreadId = 0; + LPTHREAD_START_ROUTINE lpStartAddress = &CreateTestThread; + + int threadPriority; + int duplicatePriority; + int finalPriority; + + /* Initialize the PAL.*/ + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + +#if !HAVE_SCHED_OTHER_ASSIGNABLE + /* Defining thread priority for SCHED_OTHER is implementation defined. + Some platforms like NetBSD cannot reassign it as they are dynamic. + */ + printf("paltest_duplicatehandle_test8 has been disabled on this platform\n"); +#else + + /* Create a thread.*/ + hThread = CreateThread(NULL, /* SD*/ + (DWORD)0, /* initial stack size*/ + lpStartAddress, /* thread function*/ + NULL, /* thread argument*/ + (DWORD)0, /* creation option*/ + &dwThreadId); /* thread identifier*/ + if (hThread == NULL) + { + Fail("ERROR:%u: Unable to create thread.\n", + GetLastError()); + } + + /*Get a psuedo handle to the current thread.*/ + hCurrentThread = GetCurrentThread(); + + /* Duplicate the psuedo thread handle.*/ + if (!(DuplicateHandle(GetCurrentProcess(), /* source handle process*/ + hCurrentThread, /* handle to duplicate*/ + GetCurrentProcess(), /* target process handle*/ + &hDupThread, /* duplicate handle*/ + (DWORD)0, /* requested access*/ + FALSE, /* handle inheritance*/ + DUPLICATE_SAME_ACCESS))) /* optional actions*/ + { + Trace("ERROR: %ld :Fail to create the duplicate handle" + " to hThread=0x%lx", + GetLastError(), + hThread); + CloseHandle(hThread); + Fail(""); + } + + /* Get the priority of the thread.*/ + threadPriority = GetThreadPriority(hCurrentThread); + if(threadPriority != 0) + { + Trace("ERROR: Thread priority of hCurrentThread=0x%lx should be " + "set to normal THREAD_PRIORITY_NORMAL=%d\n", + hCurrentThread, + THREAD_PRIORITY_NORMAL); + CloseHandle(hThread); + CloseHandle(hDupThread); + Fail(""); + } + + /* Get the priority of the duplicated handle, and compare it to + * the priority of the original thread. Should be the same.*/ + duplicatePriority = GetThreadPriority(hCurrentThread); + if(duplicatePriority != threadPriority) + { + Trace("ERROR: Expected priority of hCurrentThread=0x%lx and " + "hDupThread=0x%lx to be the same. Priorities:hThread=" + "\"%d\":hDupThread=\"%d\"\n", + hCurrentThread, + hDupThread, + threadPriority, + duplicatePriority); + CloseHandle(hThread); + CloseHandle(hDupThread); + Fail(""); + } + + /* Set the priority of the original thread.*/ + if(!SetThreadPriority (hCurrentThread,THREAD_PRIORITY_HIGHEST)) + { + Trace("ERROR:%u: SetThreadPriority failed on hCurrentThread=0x%lx\n", + GetLastError(), + hCurrentThread); + CloseHandle(hThread); + CloseHandle(hDupThread); + Fail(""); + } + + /* Get the priority of the duplicate thread, and + * compare it to what the original was set to.*/ + finalPriority = GetThreadPriority(hDupThread); + if (finalPriority != THREAD_PRIORITY_HIGHEST) + { + Trace("ERROR: Expected priority of hCurrentThread=0x%lw and " + "hDupThread=0x%lw to be set the same. Priorities:" + "hCurrentThread=\"%d\":hDupThread=\"%d\".\n", + hCurrentThread, + hDupThread, + threadPriority, + duplicatePriority); + CloseHandle(hThread); + CloseHandle(hDupThread); + Fail(""); + } + + /* Wait on the original thread.*/ + if((WaitForSingleObject(hThread, 100)) != WAIT_OBJECT_0) + { + Trace("ERROR:%u: hCurrentThread=0x%lx is in a non-signalled " + "mode, yet created signalled.\n", + GetLastError(), + hThread); + CloseHandle(hThread); + CloseHandle(hDupThread); + Fail(""); + } + + /* Clean-up thread and Terminate the PAL.*/ + CloseHandle(hThread); + CloseHandle(hDupThread); + +#endif + + PAL_Terminate(); + return PASS; +} + +/*Thread testing function, only return '0'*/ +DWORD PALAPI CreateTestThread(LPVOID lpParam) +{ + return (DWORD)0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test8/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test8/testinfo.dat new file mode 100644 index 0000000..ae1353a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test8/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Threading +Function = DuplicateHandle +Name = Test for DuplicateHandle (GetCurrentThread) +TYPE = DEFAULT +EXE1 = test8 +Description +=Tests the PAL implementation of the DuplicateHandle function, +=with a handle from GetCurrentThread. The test will create a thread +=handle, get the current thread and its duplicate. Then get the +=priorities of the threads, set the priority of one and the change +=should be seen in the other. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test9/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test9/CMakeLists.txt new file mode 100644 index 0000000..96aee8c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test9/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test9.cpp +) + +add_executable(paltest_duplicatehandle_test9 + ${SOURCES} +) + +add_dependencies(paltest_duplicatehandle_test9 coreclrpal) + +target_link_libraries(paltest_duplicatehandle_test9 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test9/test9.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test9/test9.cpp new file mode 100644 index 0000000..f15871c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test9/test9.cpp @@ -0,0 +1,127 @@ +// 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. + +/*===================================================================== +** +** Source: test9.c (DuplicateHandle) +** +** Purpose: Tests the PAL implementation of the DuplicateHandle function, +** with a handle from GetCurrentProcess. The test will create a +** process, duplicate it, then using ReadProcessMemory will +** read from the memory location of the CreateProcess process +** memory and the DuplicateHandle process memory. If the +** duplication is correct the memory will be the same for both. +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char* argv[]) +{ + HANDLE hProcess; + HANDLE hDupProcess; + char lpBuffer[64]; + char lpDupBuffer[64]; + SIZE_T lpNumberOfBytesRead; + SIZE_T lpDupNumberOfBytesRead; + char lpTestBuffer[] = "abcdefghijklmnopqrstuvwxyz"; + + /* Initalize the PAL. + */ + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Initalize the buffers. + */ + ZeroMemory( &lpBuffer, sizeof(lpBuffer) ); + ZeroMemory( &lpDupBuffer, sizeof(lpDupBuffer) ); + + /* Get current proces, this will be duplicated. + */ + hProcess = GetCurrentProcess(); + if(hProcess == NULL) + { + Fail("ERROR: Unable to get the current process\n"); + } + + /* Duplicate the current process handle. + */ + if (!(DuplicateHandle(GetCurrentProcess(), /* source handle process*/ + hProcess, /* handle to duplicate*/ + GetCurrentProcess(), /* target process handle*/ + &hDupProcess, /* duplicate handle*/ + (DWORD)0, /* requested access*/ + FALSE, /* handle inheritance*/ + DUPLICATE_SAME_ACCESS))) /* optional actions*/ + { + Trace("ERROR:%u: Failed to create the duplicate handle" + " to hProcess=0x%lx", + GetLastError(), + hProcess); + CloseHandle(hProcess); + Fail(""); + } + + /* Get memory read of the current process. + */ + if ((ReadProcessMemory(hDupProcess, &lpTestBuffer, + lpDupBuffer, sizeof(lpDupBuffer), &lpDupNumberOfBytesRead)) == 0) + { + Trace("ERROR:%u: Unable to read the process memory of " + "hDupProcess=0x%lx.\n", + GetLastError(), + hDupProcess); + CloseHandle(hProcess); + CloseHandle(hDupProcess); + Fail(""); + } + + /* Get read memory of the created process. + */ + if ((ReadProcessMemory(hProcess, &lpTestBuffer, + lpBuffer, sizeof(lpBuffer), &lpNumberOfBytesRead)) == 0) + { + Trace("ERROR:%u: Unable to read the process memory of " + "hProcess=0x%lx.\n", + GetLastError(), + hProcess); + CloseHandle(hProcess); + CloseHandle(hDupProcess); + Fail(""); + } + + /* Compare the number of bytes that were read by each + * ReadProcessMemory.*/ + if (lpDupNumberOfBytesRead != lpNumberOfBytesRead) + { + Trace("ERROR: ReadProcessMemory read different numbers of bytes " + "from duplicate process handles.\n"); + CloseHandle(hProcess); + CloseHandle(hDupProcess); + Fail(""); + } + + /* Compare the two buffers to make sure they are equal. + */ + if ((strcmp(lpBuffer, lpDupBuffer)) != 0) + { + Trace("ERROR: ReadProcessMemory read different numbers of bytes " + "from duplicate process handles. hProcess read \"%s\" and " + "hDupProcess read \"%s\"\n", + lpBuffer, + lpDupBuffer); + CloseHandle(hProcess); + CloseHandle(hDupProcess); + Fail(""); + } + + /* Clean-up thread and Terminate the PAL.*/ + CloseHandle(hProcess); + CloseHandle(hDupProcess); + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test9/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test9/testinfo.dat new file mode 100644 index 0000000..c712290 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/DuplicateHandle/test9/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = Threading +Function = DuplicateHandle +Name = Test for DuplicateHandle (GetCurrentProcess) +TYPE = DEFAULT +EXE1 = test9 +Description += Tests the PAL implementation of the DuplicateHandle function, += with a handle from GetCurrentProcess. The test will create a += process, duplicate it, then using ReadProcessMemory will += read from the memory location of the CreateProcess process += memory and the DuplicateHandle process memory. If the += duplication is correct the memory will be the same for both. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/CMakeLists.txt new file mode 100644 index 0000000..d243b82 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test1/CMakeLists.txt new file mode 100644 index 0000000..2aae5fa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + ExitProcess.cpp +) + +add_executable(paltest_exitprocess_test1 + ${SOURCES} +) + +add_dependencies(paltest_exitprocess_test1 coreclrpal) + +target_link_libraries(paltest_exitprocess_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test1/ExitProcess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test1/ExitProcess.cpp new file mode 100644 index 0000000..2b089a0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test1/ExitProcess.cpp @@ -0,0 +1,32 @@ +// 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. + +/*============================================================ +** +** Source: exitprocess/test1/exitprocess.c +** +** Purpose: Test to ensure ExitProcess returns the argument given +** to it. +** +** +**=========================================================*/ + +#include + +int __cdecl main( int argc, char **argv ) + +{ + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + ExitProcess(PASS); + + Fail ("ExitProcess(0) failed to exit.\n Test Failed.\n"); + + return ( FAIL); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test1/testinfo.dat new file mode 100644 index 0000000..d8b85ab --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = threading +Function = ExitProcess +Name = Positive Test for ExitProcess +TYPE = DEFAULT +EXE1 = exitprocess +Description += Test the ExitProcess function. The test runs the ExitProcess function += with the TEST_RETURN enumeration value PASS diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test2/CMakeLists.txt new file mode 100644 index 0000000..e9022f8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_exitprocess_test2 + ${SOURCES} +) + +add_dependencies(paltest_exitprocess_test2 coreclrpal) + +target_link_libraries(paltest_exitprocess_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test2/test2.cpp new file mode 100644 index 0000000..8023ad7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test2/test2.cpp @@ -0,0 +1,30 @@ +// 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. + +/*============================================================================= +** +** Source: test2.c +** +** Purpose: Positive test for ExitProcess. +** +** Dependencies: none +** + +** +**===========================================================================*/ +#include + + + +int __cdecl main( int argc, char **argv ) + +{ + /* call ExitProcess() -- should work without PAL_Initialize() */ + ExitProcess(PASS); + + + /* return failure if we reach here -- note no attempt at */ + /* meaningful output because we never called PAL_Initialize(). */ + return FAIL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test2/testinfo.dat new file mode 100644 index 0000000..0aa07eb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = ExitProcess +Name = Positive test for ExitProcess +TYPE = DEFAULT +EXE1 = test2 +Description += Test to ensure proper operation of the ExitProcess() += API by ensuring it works before PAL_Initialize() is += called. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test3/CMakeLists.txt new file mode 100644 index 0000000..c4ede3c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_exitprocess_test3 + ${SOURCES} +) + +add_dependencies(paltest_exitprocess_test3 coreclrpal) + +target_link_libraries(paltest_exitprocess_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test3/test3.cpp new file mode 100644 index 0000000..aea485e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test3/test3.cpp @@ -0,0 +1,40 @@ +// 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. + +/*============================================================================= +** +** Source: test3.c +** +** Purpose: Positive test for ExitProcess. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** + +** +**===========================================================================*/ +#include + + + +int __cdecl main( int argc, char **argv ) + +{ + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + /* terminate the PAL */ + PAL_Terminate(); + + /* call ExitProcess() -- should work after PAL_Terminate() */ + ExitProcess( PASS ); + + + /* return failure if we reach here -- note no attempt at */ + /* meaningful output because we've called PAL_Terminte(). */ + return FAIL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test3/testinfo.dat new file mode 100644 index 0000000..c857d88 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitProcess/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = ExitProcess +Name = Positive test for ExitProcess +TYPE = DEFAULT +EXE1 = test3 +Description += Test to ensure proper operation of the ExitProcess() += API by ensuring it works after PAL_Terminate() is += called. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test1/CMakeLists.txt new file mode 100644 index 0000000..710ddaa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_exitthread_test1 + ${SOURCES} +) + +add_dependencies(paltest_exitthread_test1 coreclrpal) + +target_link_libraries(paltest_exitthread_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test1/test1.cpp new file mode 100644 index 0000000..9477633 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test1/test1.cpp @@ -0,0 +1,114 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for ExitThread. Create a thread and then call +** exit thread within the threading function. Ensure that it exits +** immediatly. +** +** +**=========================================================*/ + +#include + +DWORD dwExitThreadTestParameter = 0; + +DWORD PALAPI ExitThreadTestThread( LPVOID lpParameter) +{ + DWORD dwRet = 0; + + /* Save parameter for test */ + dwExitThreadTestParameter = (DWORD)(SIZE_T)lpParameter; + + /* Call the ExitThread function */ + ExitThread(dwRet); + + /* If we didn't exit, get caught in this loop. But, the + program will exit. + */ + while (!dwRet) + { + Fail("ERROR: Entered an infinite loop because ExitThread " + "failed to exit from the thread. Forcing exit from " + "the test now."); + } + + return dwRet; +} + +BOOL ExitThreadTest() +{ + BOOL bRet = FALSE; + DWORD dwRet = 0; + + LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL; + DWORD dwStackSize = 0; + LPTHREAD_START_ROUTINE lpStartAddress = &ExitThreadTestThread; + LPVOID lpParameter = (LPVOID)lpStartAddress; + DWORD dwCreationFlags = 0; //run immediately + DWORD dwThreadId = 0; + + HANDLE hThread = 0; + + dwExitThreadTestParameter = 0; + + /* Create a Thread. We'll need this to test that we're able + to exit the thread. + */ + hThread = CreateThread( lpThreadAttributes, + dwStackSize, lpStartAddress, lpParameter, + dwCreationFlags, &dwThreadId ); + + if (hThread != INVALID_HANDLE_VALUE) + { + dwRet = WaitForSingleObject(hThread,INFINITE); + + if (dwRet != WAIT_OBJECT_0) + { + Trace("ExitThreadTest:WaitForSingleObject failed " + "(%x)\n",GetLastError()); + } + else + { + /* Check to ensure that the parameter set in the Thread + function is correct. + */ + if (dwExitThreadTestParameter != (DWORD)(SIZE_T)lpParameter) + { + Trace("ERROR: The paramater passed should have been " + "%d but turned up as %d.", + dwExitThreadTestParameter, lpParameter); + } + else + { + bRet = TRUE; + } + } + } + else + { + Trace("ExitThreadTest:CreateThread failed (%x)\n",GetLastError()); + } + + return bRet; +} + +int __cdecl main(int argc, char **argv) +{ + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!ExitThreadTest()) + { + Fail ("Test failed\n"); + } + + PAL_Terminate(); + return ( PASS ); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test1/testinfo.dat new file mode 100644 index 0000000..a526f8e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = ExitThread +Name = Positive Test for ExitThread +TYPE = DEFAULT +EXE1 = test1 +Description += Test for ExitThread. Create a thread and then call += exit thread within the threading function. Ensure that it exits += immediatly. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/CMakeLists.txt new file mode 100644 index 0000000..5a3d672 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + test2.cpp +) + +add_executable(paltest_exitthread_test2 + ${TESTSOURCES} +) + +add_dependencies(paltest_exitthread_test2 coreclrpal) + +target_link_libraries(paltest_exitthread_test2 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + childprocess.cpp +) + +add_executable(paltest_exitthread_test2_child + ${HELPERSOURCES} +) + +add_dependencies(paltest_exitthread_test2_child coreclrpal) + +target_link_libraries(paltest_exitthread_test2_child + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/childprocess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/childprocess.cpp new file mode 100644 index 0000000..7fbe208 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/childprocess.cpp @@ -0,0 +1,41 @@ +// 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. + +/*============================================================ +** +** Source: childprocess.c +** +** Purpose: Test to ensure ExitThread returns the right +** value when shutting down the last thread of a process. +** All this program does is call ExitThread() with a predefined +** value. +** +** Dependencies: none +** + +** +**=========================================================*/ + +#include +#include "myexitcode.h" + +int __cdecl main( int argc, char **argv ) +{ + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + /* exit the current thread with a magic test value -- it should */ + /* terminate the process and return that test value from this */ + /* program. */ + ExitThread( TEST_EXIT_CODE ); + + /* technically we should never get here */ + PAL_Terminate(); + + /* return failure */ + return FAIL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/myexitcode.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/myexitcode.h new file mode 100644 index 0000000..566becb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/myexitcode.h @@ -0,0 +1,14 @@ +// 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. + +/*============================================================================ +** +** Source: myexitcode.h +** +** Purpose: Define an exit code. +** +** +**==========================================================================*/ + +#define TEST_EXIT_CODE 316 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/test2.cpp new file mode 100644 index 0000000..c31af8a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/test2.cpp @@ -0,0 +1,168 @@ +// 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. + +/*============================================================================= +** +** Source: test2.c +** +** Purpose: Test to ensure ExitThread() called from the last thread of +** a process shuts down that process and returns the proper +** exit code as specified in the ExitThread() call. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** ZeroMemory +** GetCurrentDirectoryW +** CreateProcessW +** WaitForSingleObject +** GetLastError +** strlen +** strncpy +** + +** +**===========================================================================*/ +#include +#include "myexitcode.h" + + +static const char* rgchPathDelim = "\\"; + + +int +mkAbsoluteFilename( LPSTR dirName, + DWORD dwDirLength, + LPCSTR fileName, + DWORD dwFileLength, + LPSTR absPathName ) +{ + DWORD sizeDN, sizeFN, sizeAPN; + + sizeDN = strlen( dirName ); + sizeFN = strlen( fileName ); + sizeAPN = (sizeDN + 1 + sizeFN + 1); + + /* ensure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */ + if( sizeAPN > _MAX_PATH ) + { + return ( 0 ); + } + + strncpy( absPathName, dirName, dwDirLength +1 ); + strncpy( absPathName, rgchPathDelim, 2 ); + strncpy( absPathName, fileName, dwFileLength +1 ); + + return (sizeAPN); + +} + + +int __cdecl main( int argc, char **argv ) + +{ + const char* rgchChildFile = "childprocess"; + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + DWORD dwError; + DWORD dwExitCode; + DWORD dwFileLength; + DWORD dwDirLength; + DWORD dwSize; + DWORD dwExpected = TEST_EXIT_CODE; + + char rgchDirName[_MAX_DIR]; + char absPathBuf[_MAX_PATH]; + char* rgchAbsPathName; + + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + /* zero our process and startup info structures */ + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof( si ); + ZeroMemory( &pi, sizeof(pi) ); + + /* build the absolute path to the child process */ + rgchAbsPathName = &absPathBuf[0]; + dwFileLength = strlen( rgchChildFile ); + + dwDirLength = GetCurrentDirectory( _MAX_PATH, rgchDirName ); + if( dwDirLength == 0 ) + { + dwError = GetLastError(); + Fail( "GetCurrentDirectory call failed with error code %d\n", + dwError ); + } + + dwSize = mkAbsoluteFilename( rgchDirName, + dwDirLength, + rgchChildFile, + dwFileLength, + rgchAbsPathName ); + if( dwSize == 0 ) + { + Fail( "Palsuite Code: mkAbsoluteFilename() call failed. Could ", + "not build absolute path name to file\n. Exiting.\n" ); + } + + /* launch the child process */ + if( !CreateProcess( NULL, /* module name to execute */ + rgchAbsPathName, /* command line */ + NULL, /* process handle not */ + /* inheritable */ + NULL, /* thread handle not */ + /* inheritable */ + FALSE, /* handle inheritance */ + CREATE_NEW_CONSOLE, /* dwCreationFlags */ + NULL, /* use parent's environment */ + NULL, /* use parent's starting */ + /* directory */ + &si, /* startup info struct */ + &pi ) /* process info struct */ + ) + { + dwError = GetLastError(); + Fail( "CreateProcess call failed with error code %d\n", + dwError ); + } + + /* wait for the child process to complete */ + WaitForSingleObject ( pi.hProcess, INFINITE ); + + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) + { + dwError = GetLastError(); + CloseHandle ( pi.hProcess ); + CloseHandle ( pi.hThread ); + Fail( "GetExitCodeProcess call failed with error code %d\n", + dwError ); + } + + /* close process and thread handle */ + CloseHandle ( pi.hProcess ); + CloseHandle ( pi.hThread ); + + /* check for the expected exit code */ + /* exit code for some systems is as small as a char, so that's all */ + /* we'll compare for checking success */ + if( LOBYTE(LOWORD(dwExitCode)) != LOBYTE(LOWORD(dwExpected)) ) + { + Fail( "GetExitCodeProcess returned an incorrect exit code %d, " + "expected value is %d\n", + LOWORD(dwExitCode), dwExpected ); + } + + /* terminate the PAL */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/testinfo.dat new file mode 100644 index 0000000..4b5bdc2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test2/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = threading +Function = ExitThread +Name = Test for ExitThread +TYPE = DEFAULT +EXE1 = test2 +EXE2 = childprocess +Description += Test to ensure proper operation of the ExitThread += API. This test launches a simple child process that exits += by calling ExitThread() with a known value, and checks += that the correct value is returned to the parent process. += This verifies that when the last thread of a process exits += via ExitThread, the process exits with the proper return += code. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test3/dllmain.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test3/dllmain.cpp new file mode 100644 index 0000000..862aff5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test3/dllmain.cpp @@ -0,0 +1,65 @@ +// 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. + +/*============================================================================= +** +** Source: dllmain.c +** +** Purpose: Test to ensure DllMain() is called with THREAD_DETACH +** when a thread in the application calls ExitThread(). +** +** Dependencies: none +** + +** +**===========================================================================*/ + +#include + +/* count of the number of times DllMain() was called with THREAD_DETACH */ +static int g_detachCount = 0; + + +/* standard DllMain() */ +BOOL PALAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved) +{ + switch( reason ) + { + case DLL_PROCESS_ATTACH: + { + break; + } + + case DLL_PROCESS_DETACH: + { + break; + } + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + /* increment g_detachCount */ + g_detachCount++; + break; + } + return TRUE; +} + +#ifdef WIN32 +BOOL PALAPI _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + return DllMain(hinstDLL, fdwReason, lpvReserved); +} +#endif + + +/* function to return the current detach count */ +#ifdef WIN32 +__declspec(dllexport) +#endif +int PALAPI GetDetachCount( void ) +{ + return g_detachCount; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test3/test3.cpp new file mode 100644 index 0000000..8a71c7c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test3/test3.cpp @@ -0,0 +1,162 @@ +// 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. + +/*============================================================================= +** +** Source: test3.c +** +** Purpose: Test to ensure ExitThread() results in any loaded dynamic +** libraries having their entry point called with a THREAD_DETACH +** notification. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** GetCurrentDirectoryW +** CreateThread +** ResumeThread +** LoadLibrary +** FreeLibrary +** GetProcAddress +** WaitForSingleObject +** GetLastError +** strlen +** strncpy +** + +** +**===========================================================================*/ +#include + +/* SHLEXT is defined only for Unix variants */ + +#if defined(SHLEXT) +#define rgchLibraryFile "dllmain"SHLEXT +#define szFunction "GetDetachCount" +#else +#define rgchLibraryFile "dllmain" +#define szFunction "_GetDetachCount@0" +#endif + +/* define our test function type */ +typedef int ( PALAPI *LPTESTFUNC )( void ); + + +/** + * ThreadFunc + * + * Dummy thread function for causing DLL thread notifications. + */ +DWORD PALAPI ThreadFunc( LPVOID param ) +{ + /* simulate some brief "work" */ + int i; + for( i=0; i<100000; i++ ) + ; + + ExitThread( 0 ); + return (0); +} + + +/* main program entry point */ +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + + HANDLE hLib = NULL; + LPTESTFUNC pFunc; + int detachCount1 = 0; + int detachCount2 = 0; + + HANDLE hThread = NULL; + DWORD IDThread; + + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + /* Load the test library */ + hLib = LoadLibrary( rgchLibraryFile ); + if(hLib == NULL) + { + Fail("ERROR: Unable to load library %s\n", rgchLibraryFile ); + } + + + /* Get the address of our test function in the dll */ + pFunc = (LPTESTFUNC)GetProcAddress( hLib, szFunction ); + if( pFunc == NULL ) + { + Trace( "ERROR:%lu%:Unable to load function \"%s\" library \"%s\"\n", + GetLastError(), + szFunction, + rgchLibraryFile ); + if( ! FreeLibrary( hLib ) ) { + Trace( "FreeLibrary() failed with error code %lu\n", + GetLastError() ); + } + Fail( "Exiting\n" ); + } + + /* Execute the test function to get the detach count */ + detachCount1 = pFunc(); + + /* run another dummy thread to cause notification of the library */ + hThread = CreateThread( NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */ + (LPVOID) NULL, /* pass thread index as */ + /* function argument */ + CREATE_SUSPENDED, /* create suspended */ + &IDThread ); /* returns thread id */ + + /* Check the return value for success. */ + if( hThread == NULL ) + { + /* error creating thread */ + Trace( "Unexpected CreateThread error %d\n", + GetLastError() ); + if( ! FreeLibrary( hLib ) ) { + Trace( "FreeLibrary() failed with error code %lu\n", + GetLastError() ); + } + Fail( "Exiting\n" ); + } + + /* Resume the suspended thread */ + ResumeThread( hThread ); + + /* wait for the thread to complete */ + WaitForSingleObject( hThread, INFINITE ); + + /* Execute the test function to get the new detach count */ + detachCount2 = pFunc(); + + /* Unload the test library */ + if( !FreeLibrary( hLib ) ) + { + Fail( "ERROR:%u: Unable to free library \"%s\"\n", + GetLastError(), + rgchLibraryFile ); + } + + /* validate the result */ + if( detachCount2 != (detachCount1 + 1) ) + { + Fail( "FAIL: unexpected DLL detach count %d, expected %d\n", + detachCount2, + (detachCount1 + 1) ); + } + + + /* terminate the PAL */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test3/testinfo.dat new file mode 100644 index 0000000..1c9e8c7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ExitThread/test3/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = threading +Function = ExitThread +Name = Test for ExitThread +TYPE = DEFAULT +EXE1 = test3 +LIB1 = dllmain +Description += Test to ensure proper operation of the ExitThread += API. This tests to make sure ExitThread() results += in any loaded dynamic libraries having their entry += point called with a THREAD_DETACH notification. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/CMakeLists.txt new file mode 100644 index 0000000..3a8efb8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + process.cpp +) + +add_executable(paltest_getcurrentprocess_test1 + ${SOURCES} +) + +add_dependencies(paltest_getcurrentprocess_test1 coreclrpal) + +target_link_libraries(paltest_getcurrentprocess_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/process.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/process.cpp new file mode 100644 index 0000000..17d9af6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/process.cpp @@ -0,0 +1,40 @@ +// 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. + +/*============================================================ +** +** Source: GetCurrentProcess/test1/process.c +** +** Purpose: Test for to see if the process GetCurrentProcess +** returns a handle to the current process or not. +** +** Dependencies: TerminateProcess +** +** +**=========================================================*/ + +#include + +INT __cdecl main( int argc, char **argv ) +{ + + HANDLE hProcess; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + hProcess = GetCurrentProcess(); + Trace ("Testing the handle returned by GetCurrentProcess\n"); + if ( 0 == ( TerminateProcess ( hProcess, PASS ) ) ) + { + Fail ("Testing GetCurrentProcess, the TerminateProcess function " + "failed.\n"); + } + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/testinfo.dat new file mode 100644 index 0000000..8eb2759 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = threading +Function = GetCurrentProcess +Name = Positive Test for GetCurrentProcess +TYPE = DEFAULT +EXE1 = process +Description += Test to see if the function GetCurrentProcess returns a handle to the += current process or not. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/CMakeLists.txt new file mode 100644 index 0000000..bb650f9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + processId.cpp +) + +add_executable(paltest_getcurrentprocessid_test1 + ${SOURCES} +) + +add_dependencies(paltest_getcurrentprocessid_test1 coreclrpal) + +target_link_libraries(paltest_getcurrentprocessid_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/processId.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/processId.cpp new file mode 100644 index 0000000..cc689b3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/processId.cpp @@ -0,0 +1,41 @@ +// 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. + +/*============================================================ +** +** Source: getcurrentprocessid/test1/processid.c +** +** Purpose: Test to ensure GetCurrentProcessId returns the current +** process id number. This test compares the result of +** GetCurrentProcessId to getpid. +** +** +**=========================================================*/ + +#include + +INT __cdecl main( int argc, char **argv ) +{ + + DWORD dwProcessId; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + dwProcessId = GetCurrentProcessId(); + + if ( 0 >= dwProcessId ) + { + Fail ("%s has dwProcessId has id value %d\n", argv[0], + dwProcessId ); + } + Trace ("%s has dwProcessId %d\nPassing test as dwProcessId is > 0\n" + , argv[0], dwProcessId); + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/testinfo.dat new file mode 100644 index 0000000..db615c0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = threading +Function = GetCurrentProcessId +Name = Positive Test for GetCurrentProcessId +TYPE = DEFAULT +EXE1 = processid +Description += Test to ensure GetCurrentProcessId returns the current process id number. += This test compares the result of GetCurrentProcessId to getpid. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test1/CMakeLists.txt new file mode 100644 index 0000000..aba630f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + thread.cpp +) + +add_executable(paltest_getcurrentthread_test1 + ${SOURCES} +) + +add_dependencies(paltest_getcurrentthread_test1 coreclrpal) + +target_link_libraries(paltest_getcurrentthread_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test1/testinfo.dat new file mode 100644 index 0000000..29c9767 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test1/testinfo.dat @@ -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. + +Version = 1.0 +Section = threading +Function = GetCurrentThread +Name = Positive Test for GetCurrentThread +TYPE = DEFAULT +EXE1 = thread +Description += Test to ensure GetCurrentThread returns a handle to the current thread. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test1/thread.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test1/thread.cpp new file mode 100644 index 0000000..b2bb97f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test1/thread.cpp @@ -0,0 +1,93 @@ +// 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. + +/*============================================================ +** +** Source: GetCurrentThread/test1/thread.c +** +** Purpose: Test to ensure GetCurrentThread returns a handle to +** the current thread. +** +** Dependencies: GetThreadPriority +** SetThreadPriority +** Fail +** Trace +** + +** +**=========================================================*/ + +#include + +int __cdecl main( int argc, char **argv ) +{ + + HANDLE hThread; + int nPriority; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + +#if !HAVE_SCHED_OTHER_ASSIGNABLE + /* Defining thread priority for SCHED_OTHER is implementation defined. + Some platforms like NetBSD cannot reassign it as they are dynamic. + */ + printf("paltest_getcurrentthread_test1 has been disabled on this platform\n"); +#else + hThread = GetCurrentThread(); + + nPriority = GetThreadPriority(hThread); + + if ( THREAD_PRIORITY_NORMAL != nPriority ) + { + if ( THREAD_PRIORITY_ERROR_RETURN == nPriority ) + { + Fail ("GetThreadPriority function call failed for %s\n" + "GetLastError returned %d\n", argv[0], GetLastError()); + } + else + { + Fail ("GetThreadPriority function call failed for %s\n" + "The priority returned was %d\n", argv[0], nPriority); + } + } + else + { + nPriority = 0; + + if (0 == SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST)) + { + Fail ("Unable to set thread priority. Either handle doesn't" + " point to current thread \nor SetThreadPriority " + "function failed. Failing test.\n"); + } + + nPriority = GetThreadPriority(hThread); + + if ( THREAD_PRIORITY_ERROR_RETURN == nPriority ) + { + Fail ("GetThreadPriority function call failed for %s\n" + "GetLastError returned %d\n", argv[0], GetLastError()); + } + else if ( THREAD_PRIORITY_HIGHEST == nPriority ) + { + Trace ("GetCurrentThread returns handle to the current " + "thread.\n"); + exit ( PASS ); + } + else + { + Fail ("Unable to set thread priority. Either handle doesn't" + " point to current thread \nor SetThreadPriority " + "function failed. Failing test.\n"); + } + } +#endif + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test2/CMakeLists.txt new file mode 100644 index 0000000..b73f90e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_getcurrentthread_test2 + ${SOURCES} +) + +add_dependencies(paltest_getcurrentthread_test2 coreclrpal) + +target_link_libraries(paltest_getcurrentthread_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test2/test2.cpp new file mode 100644 index 0000000..beeb5ec --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test2/test2.cpp @@ -0,0 +1,144 @@ +// 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. + +/*============================================================================= +** +** Source: test2.c +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** CreateThread +** SetThreadPriority +** GetThreadPriority +** ResumeThread +** WaitForSingleObject +** GetLastError +** +** Purpose: +** +** Test to ensure proper operation of the GetCurrentThread() +** API. The test launches a thread in suspended mode, and sets +** its priority to a non-default value using the handle returned +** by CreateThread(). The new thread calls GetCurrentThred() to +** retrieve a handle to itself, and calls GetThreadPriority() +** to verify that its priority matches what it was set to on +** the main execution thread. +** + +** +**===========================================================================*/ +#include + + +/* we store the return code from the child thread here because */ +/* we're missing the GetExitCodeThread() API */ + +static int g_priority = 0; + +/** + * ThreadFunc + * + * Thread function that calls GetCurrentThread() to get a pseudo-handle + * to itself, then checks its priority and exits with that value. + */ +DWORD PALAPI ThreadFunc( LPVOID param ) +{ + int priority; + HANDLE hThread; + + /* call GetCurrentThread() to get a pseudo-handle to */ + /* the current thread */ + hThread = GetCurrentThread(); + if( hThread == NULL ) + { + Fail( "GetCurrentThread() call failed\n" ); + } + + + /* get the current thread priority */ + priority = GetThreadPriority( hThread ); + if( priority == THREAD_PRIORITY_ERROR_RETURN ) + { + /* GetThreadPriority call failed */ + Fail( "ERROR:%lu:GetThreadPriority() call failed\n", GetLastError() ); + } + + /* store this globally because we don't have GetExitCodeThread() */ + g_priority = priority; + return (DWORD)priority; +} + + +/** + * main + * + * executable entry point + */ +INT __cdecl main( INT argc, CHAR **argv ) +{ + HANDLE hThread = NULL; + DWORD IDThread; + DWORD dwRet; + + SIZE_T i = 0; + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + +#if !HAVE_SCHED_OTHER_ASSIGNABLE + /* Defining thread priority for SCHED_OTHER is implementation defined. + Some platforms like NetBSD cannot reassign it as they are dynamic. + */ + printf("paltest_getcurrentthread_test2 has been disabled on this platform\n"); +#else + /* Create multiple threads. */ + hThread = CreateThread( NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */ + (LPVOID) i, /* pass thread index as */ + /* function argument */ + CREATE_SUSPENDED, /* create suspended */ + &IDThread ); /* returns thread identifier */ + + /* Check the return value for success. */ + if( hThread == NULL ) + { + /* ERROR */ + Fail( "ERROR:%lu:CreateThread failed\n", GetLastError() ); + } + + /* set the thread priority of the new thread to the highest value */ + if( ! SetThreadPriority( hThread, THREAD_PRIORITY_TIME_CRITICAL) ) + { + Fail( "ERROR:%lu:SetThreadPriority() call failed\n", GetLastError() ); + } + + /* let the child thread run now */ + ResumeThread( hThread ); + + + /* wait for the thread to finish */ + dwRet = WaitForSingleObject( hThread, INFINITE ); + if( dwRet == WAIT_FAILED ) + { + /* ERROR */ + Fail( "ERROR:%lu:WaitForSingleObject call failed\n", GetLastError() ); + } + + /* validate the thread's exit code */ + if( g_priority != THREAD_PRIORITY_TIME_CRITICAL ) + { + /* ERROR */ + Fail( "FAIL:Unexpected thread priority %d returned, expected %d\n", + g_priority, THREAD_PRIORITY_TIME_CRITICAL ); + } +#endif + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test2/testinfo.dat new file mode 100644 index 0000000..96a6d40 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThread/test2/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = threading +Function = GetCurrentThread +Name = Test for GetCurrentThread +TYPE = DEFAULT +EXE1 = test2 +Description += Test to ensure proper operation of the GetCurrentThread() += API. The test launches a thread in suspended mode, and sets += its priority to a non-default value using the handle returned += by CreateThread(). The new thread calls GetCurrentThred() to += retrieve a handle to itself, and calls GetThreadPriority() += to verify that its priority matches what it was set to on += the main execution thread. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/CMakeLists.txt new file mode 100644 index 0000000..93ddf44 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + threadId.cpp +) + +add_executable(paltest_getcurrentthreadid_test1 + ${SOURCES} +) + +add_dependencies(paltest_getcurrentthreadid_test1 coreclrpal) + +target_link_libraries(paltest_getcurrentthreadid_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/testinfo.dat new file mode 100644 index 0000000..4d1e056 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = threading +Function = GetCurrentThreadId +Name = Positive Test for GetCurrentThreadId +TYPE = DEFAULT +EXE1 = threadid +Description += Test to ensure GetCurrentThreadId returns the threadId of the current += thread. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/threadId.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/threadId.cpp new file mode 100644 index 0000000..acbb1ff --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/threadId.cpp @@ -0,0 +1,82 @@ +// 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. + +/*============================================================ +** +** Source: getcurrentthreadid/test1/threadid.c +** +** Purpose: Test to ensure GetCurrentThreadId returns the threadId of the +** current thread. +** +** Dependencies: CloseHandle +** WaitForSingleObject +** CreateThread +** + +** +**=========================================================*/ + + +#include + +DWORD dwThreadIdTF; + +DWORD PALAPI ThreadFunction ( LPVOID lpParam ) +{ + Trace ("thread code executed\n"); + dwThreadIdTF = GetCurrentThreadId(); + return 0; +} + +int __cdecl main( int argc, char **argv ) +{ + extern DWORD dwThreadIdTF; + DWORD dwThreadIdCT; + HANDLE hThread; + DWORD dwThreadParam = 1; + DWORD dwThreadWait; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + hThread = CreateThread( + NULL, + 0, + ThreadFunction, + &dwThreadParam, + 0, + &dwThreadIdCT); + + if ( NULL == hThread ) + { + Fail ( "CreateThread() call failed - returned NULL"); + } + else + { + dwThreadWait = WaitForSingleObject( hThread, INFINITE ); + + Trace ("dwThreadWait returned %d\n", dwThreadWait ); + + if ( dwThreadIdCT == dwThreadIdTF ) + { + Trace ( "ThreadId numbers match - GetCurrentThreadId" + " works. dwThreadIdCT == dwThreadIdTF == %d\n", + dwThreadIdTF ); + PAL_Terminate(); + return ( PASS ); + } + else + { + Fail ( "ThreadId numbers don't match - " + "GetCurrentThreadId fails dwThreadIdCT = %d " + "and dwThreadIdTF = %d\n", dwThreadIdCT, dwThreadIdTF); + } + } + + PAL_TerminateEx(FAIL); + return (FAIL); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/CMakeLists.txt new file mode 100644 index 0000000..2cf8b3c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + test1.cpp +) + +add_executable(paltest_getexitcodeprocess_test1 + ${TESTSOURCES} +) + +add_dependencies(paltest_getexitcodeprocess_test1 coreclrpal) + +target_link_libraries(paltest_getexitcodeprocess_test1 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + childProcess.cpp +) + +add_executable(paltest_getexitcodeprocess_test1_child + ${HELPERSOURCES} +) + +add_dependencies(paltest_getexitcodeprocess_test1_child coreclrpal) + +target_link_libraries(paltest_getexitcodeprocess_test1_child + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/childProcess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/childProcess.cpp new file mode 100644 index 0000000..fe1b38f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/childProcess.cpp @@ -0,0 +1,31 @@ +// 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. + +/*============================================================ +** +** Source: childprocess.c +** +** Purpose: Test to ensure GetExitCodeProcess returns the right +** value. All this program does is return a predefined value. +** +** Dependencies: none +** + +** +**=========================================================*/ + +#include +#include "myexitcode.h" + +int __cdecl main( int argc, char **argv ) +{ + int i; + + // simulate some activity + for( i=0; i<10000; i++ ) + ; + + // return the predefined exit code + return TEST_EXIT_CODE; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/myexitcode.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/myexitcode.h new file mode 100644 index 0000000..60a140d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/myexitcode.h @@ -0,0 +1,14 @@ +// 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. + +/*============================================================================ +** +** Source: myexitcode.h +** +** Purpose: Define an exit code. +** +** +**==========================================================================*/ + +#define TEST_EXIT_CODE 104 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/test1.cpp new file mode 100644 index 0000000..0f98cf8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/test1.cpp @@ -0,0 +1,163 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure GetExitCodeProcess works properly. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** ZeroMemory +** GetCurrentDirectoryW +** CreateProcessW +** WaitForSingleObject +** GetLastError +** strlen +** strncpy +** + +** +**===========================================================================*/ +#include +#include "myexitcode.h" + + +static const char* rgchPathDelim = "\\"; + + +int +mkAbsoluteFilename( LPSTR dirName, + DWORD dwDirLength, + LPCSTR fileName, + DWORD dwFileLength, + LPSTR absPathName ) +{ + DWORD sizeDN, sizeFN, sizeAPN; + + sizeDN = strlen( dirName ); + sizeFN = strlen( fileName ); + sizeAPN = (sizeDN + 1 + sizeFN + 1); + + /* ensure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */ + if( sizeAPN > _MAX_PATH ) + { + return ( 0 ); + } + + strncpy( absPathName, dirName, dwDirLength +1 ); + strncpy( absPathName, rgchPathDelim, 2 ); + strncpy( absPathName, fileName, dwFileLength +1 ); + + return (sizeAPN); + +} + + +int __cdecl main( int argc, char **argv ) + +{ + const char* rgchChildFile = "childprocess"; + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + DWORD dwError; + DWORD dwExitCode; + DWORD dwFileLength; + DWORD dwDirLength; + DWORD dwSize; + + char rgchDirName[_MAX_DIR]; + char absPathBuf[_MAX_PATH]; + char* rgchAbsPathName; + + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + /* zero our process and startup info structures */ + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof( si ); + ZeroMemory( &pi, sizeof(pi) ); + + /* build the absolute path to the child process */ + rgchAbsPathName = &absPathBuf[0]; + dwFileLength = strlen( rgchChildFile ); + + dwDirLength = GetCurrentDirectory( _MAX_PATH, rgchDirName ); + if( dwDirLength == 0 ) + { + dwError = GetLastError(); + Fail( "GetCurrentDirectory call failed with error code %d\n", + dwError ); + } + + dwSize = mkAbsoluteFilename( rgchDirName, + dwDirLength, + rgchChildFile, + dwFileLength, + rgchAbsPathName ); + if( dwSize == 0 ) + { + Fail( "Palsuite Code: mkAbsoluteFilename() call failed. Could ", + "not build absolute path name to file\n. Exiting.\n" ); + } + + /* launch the child process */ + if( !CreateProcess( NULL, /* module name to execute */ + rgchAbsPathName, /* command line */ + NULL, /* process handle not */ + /* inheritable */ + NULL, /* thread handle not */ + /* inheritable */ + FALSE, /* handle inheritance */ + CREATE_NEW_CONSOLE, /* dwCreationFlags */ + NULL, /* use parent's environment */ + NULL, /* use parent's starting */ + /* directory */ + &si, /* startup info struct */ + &pi ) /* process info struct */ + ) + { + dwError = GetLastError(); + Fail( "CreateProcess call failed with error code %d\n", + dwError ); + } + + /* wait for the child process to complete */ + WaitForSingleObject ( pi.hProcess, INFINITE ); + + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) + { + dwError = GetLastError(); + CloseHandle ( pi.hProcess ); + CloseHandle ( pi.hThread ); + Fail( "GetExitCodeProcess call failed with error code %d\n", + dwError ); + } + + /* close process and thread handle */ + CloseHandle ( pi.hProcess ); + CloseHandle ( pi.hThread ); + + /* check for the expected exit code */ + if( dwExitCode != TEST_EXIT_CODE ) + { + Fail( "GetExitCodeProcess returned an incorrect exit code %d, " + "expected value is %d\n", + dwExitCode, TEST_EXIT_CODE ); + } + + /* terminate the PAL */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/testinfo.dat new file mode 100644 index 0000000..d06719f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = threading +Function = GetExitCodeProcess +Name = Test for GetExitCodeProcess +TYPE = DEFAULT +EXE1 = test1 +EXE2 = childprocess +Description += Test to ensure proper operation of the GetExitCodeProcess += API. This test launches a simple child process that exits += with a known value, and checks that the correct value is += returned by the function. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/CMakeLists.txt new file mode 100644 index 0000000..174958d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/test2/CMakeLists.txt new file mode 100644 index 0000000..9bcd6b7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_getprocesstimes_test2 + ${SOURCES} +) + +add_dependencies(paltest_getprocesstimes_test2 coreclrpal) + +target_link_libraries(paltest_getprocesstimes_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.cpp new file mode 100644 index 0000000..cc39de6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.cpp @@ -0,0 +1,122 @@ +// 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. + +/*============================================================================= +** +** Source: test2.c +** +** Purpose: Test to ensure GetProcessTimes works properly. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** ZeroMemory +** CompareFileTime +** GetLastError +** + +** +**===========================================================================*/ +#include + + +int __cdecl main( int argc, char **argv ) + +{ + int i, j, k; + int *total; + + HANDLE hProcess; + FILETIME createTime; + FILETIME exitTime; + FILETIME kernelTime1; + FILETIME userTime1; + FILETIME kernelTime2; + FILETIME userTime2; + + DWORD dwError; + + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + /* get our own process handle */ + hProcess = GetCurrentProcess(); + if( hProcess == NULL ) + { + Fail( "GetCurrentProcess() returned a NULL handle.\n" ); + } + + /* zero our time structures */ + ZeroMemory( &createTime, sizeof(createTime) ); + ZeroMemory( &exitTime, sizeof(exitTime) ); + ZeroMemory( &kernelTime1, sizeof(kernelTime1) ); + ZeroMemory( &userTime1, sizeof(userTime1) ); + ZeroMemory( &kernelTime2, sizeof(kernelTime2) ); + ZeroMemory( &userTime2, sizeof(userTime2) ); + + /* check the process times for the child process */ + if( ! GetProcessTimes( hProcess, + &createTime, + &exitTime, + &kernelTime1, + &userTime1 ) ) + { + dwError = GetLastError(); + Fail( "GetProcessTimes() call failed with error code %d\n", + dwError ); + } + + + /* simulate some activity */ + for( i=0; i<1000; i++ ) + { + for( j=0; j<1000; j++ ) + { + /* do kernel work to increase system usage counters */ + total = (int*)malloc(1024 * 1024); + + *total = j * i; + for( k=0; k<1000; k++ ) + { + *total += k + i; + } + + free(total); + } + } + + /* check the process times for the child process */ + if( ! GetProcessTimes( hProcess, + &createTime, + &exitTime, + &kernelTime2, + &userTime2 ) ) + { + dwError = GetLastError(); + Fail( "GetProcessTimes() call failed with error code %d\n", + dwError ); + } + + + /* very simple logical checking of the results */ + if( CompareFileTime( &kernelTime1, &kernelTime2 ) > 0 ) + { + Fail( "Unexpected kernel time value reported.\n" ); + } + + if( CompareFileTime( &userTime1, &userTime2 ) > 0 ) + { + Fail( "Unexpected user time value reported.\n" ); + } + + + /* terminate the PAL */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/test2/testinfo.dat new file mode 100644 index 0000000..d0d3b75 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetProcessTimes/test2/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = threading +Function = GetProcessTimes +Name = Test for GetProcessTimes +TYPE = DEFAULT +EXE1 = test2 +Description += Test to ensure proper operation of the GetProcessTimes() += API. This test simply checks the kernel/user times for the += the current process, which is the only thing supported += for this function under the PAL. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetThreadTimes/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetThreadTimes/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetThreadTimes/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetThreadTimes/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetThreadTimes/test1/CMakeLists.txt new file mode 100644 index 0000000..91581de --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetThreadTimes/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_getthreadtimes_test1 + ${SOURCES} +) + +add_dependencies(paltest_getthreadtimes_test1 coreclrpal) + +target_link_libraries(paltest_getthreadtimes_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.cpp new file mode 100644 index 0000000..33fcc36 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.cpp @@ -0,0 +1,102 @@ +// 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. + +/*============================================================ +** +** Source: +** +** Source : test1.c +** +** Purpose: Test for GetThreadTimes() function +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) { + int ret = FAIL; + + //Test is failing unreliably, so for now we always return pass. + if (TRUE){ + ret = PASS; + goto EXIT; + } + { + FILETIME kernelTime1, userTime1, kernelTime2, userTime2; + /* Delta = .01 sec */ + LONG64 Actual, Expected, Delta = 850000000; + Actual = 0; + Expected = 0; + const ULONG64 MSEC_TO_NSEC = 1000000; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + HANDLE cThread = GetCurrentThread(); + + int i; + /* Take 2000 tiny measurements */ + for (i = 0; i < 2000; i++){ + ULONG64 Time1, Time2; + + Sleep(1); + + /* Grab a FirstCount, then loop for a bit to make the clock increase */ + if (!GetThreadTimes(cThread, NULL, NULL, &kernelTime1, &userTime1)) + { + Fail("ERROR: GetThreadTimes returned failure.\n"); + } + LONG64 x, Init; + /* Init is in milliseconds, so we will convert later */ + Init = (ULONG64)GetTickCount(); + /* Spin for < 1 Quantum so we don't get interrupted */ + x = Init + 3; + volatile int counter; + do { + for (counter = 0; counter < 100000; counter++) + { + // spin to consume CPU time + } + + } while (x > GetTickCount()); + Expected += (GetTickCount() - Init) * MSEC_TO_NSEC; + /* Get a second count */ + if (!GetThreadTimes(cThread, NULL, NULL, &kernelTime2, &userTime2)) + { + Fail("ERROR: GetThreadTimes returned failure.\n"); + } + + Time1 = ((ULONG64)kernelTime1.dwHighDateTime << 32); + Time1 += (ULONG64)kernelTime1.dwLowDateTime; + Time1 += ((ULONG64)userTime1.dwHighDateTime << 32); + Time1 += (ULONG64)userTime1.dwLowDateTime; + + Time2 = ((ULONG64)kernelTime2.dwHighDateTime << 32); + Time2 += (ULONG64)kernelTime2.dwLowDateTime; + Time2 += ((ULONG64)userTime2.dwHighDateTime << 32); + Time2 += (ULONG64)userTime2.dwLowDateTime; + + Actual += (Time2 - Time1) * 100; + } + + if(llabs(Expected - Actual) > Delta) + { + Fail("ERROR: The measured time (%llu millisecs) was not within Delta %llu " + "of the expected time (%llu millisecs).\n", + (Actual / MSEC_TO_NSEC), (Delta / MSEC_TO_NSEC), (Expected / MSEC_TO_NSEC)); + } + //printf("%llu, %llu\n", Expected, Actual); + PAL_Terminate(); + ret = PASS; + } +EXIT: + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/CMakeLists.txt new file mode 100644 index 0000000..5199246 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/CMakeLists.txt @@ -0,0 +1,14 @@ +set(SOURCES + namedmutex.cpp + nopal.cpp +) + +add_executable(paltest_namedmutex_test1 + ${SOURCES} +) + +add_dependencies(paltest_namedmutex_test1 coreclrpal) + +target_link_libraries(paltest_namedmutex_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp new file mode 100644 index 0000000..6635d76 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp @@ -0,0 +1,1130 @@ +// 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. + +// These test cases test named mutexes, including positive +// and negative cases, cross - thread and cross - process, mutual +// exclusion, abandon detection, etc. + +#include + +#ifndef _countof +#define _countof(a) (sizeof(a) / sizeof(a[0])) +#endif // !_countof + +const char *const SessionPrefix = "Local\\"; +const char *const GlobalPrefix = "Global\\"; + +const char *const NamePrefix = "paltest_namedmutex_test1_"; +const char *const TempNamePrefix = "paltest_namedmutex_test1_temp_"; +const char *const InvalidNamePrefix0 = "paltest\\namedmutex_"; +const char *const InvalidNamePrefix1 = "paltest/namedmutex_"; +const char *const ParentEventNamePrefix0 = "paltest_namedmutex_test1_pe0_"; +const char *const ParentEventNamePrefix1 = "paltest_namedmutex_test1_pe1_"; +const char *const ChildEventNamePrefix0 = "paltest_namedmutex_test1_ce0_"; +const char *const ChildEventNamePrefix1 = "paltest_namedmutex_test1_ce1_"; +const char *const ChildRunningEventNamePrefix = "paltest_namedmutex_test1_cr_"; + +const char *const GlobalShmFilePathPrefix = "/tmp/.dotnet/shm/global/"; + +#define MaxPathSize (200) +const DWORD PollLoopSleepMilliseconds = 100; +const DWORD FailTimeoutMilliseconds = 30000; +DWORD g_expectedTimeoutMilliseconds = 500; + +bool g_isParent = true; +bool g_isStress = false; +char g_processPath[4096], g_processCommandLinePath[4096]; +DWORD g_parentPid = static_cast(-1); + +extern char *(*test_strcpy)(char *dest, const char *src); +extern int (*test_strcmp)(const char *s1, const char *s2); +extern size_t (*test_strlen)(const char *s); +extern int (*test_sprintf)(char *str, const char *format, ...); +extern int (*test_sscanf)(const char *str, const char *format, ...); +extern int(*test_close)(int fd); +extern int (*test_unlink)(const char *pathname); +extern unsigned int test_getpid(); +extern int test_kill(unsigned int pid); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Test helpers + +extern bool TestFileExists(const char *path); +extern bool WriteHeaderInfo(const char *path, char sharedMemoryType, char version, int *fdRef); + +#define TestAssert(expression) \ + do \ + { \ + if (!(expression)) \ + { \ + if (!g_isParent) \ + { \ + Trace("Child process: "); \ + } \ + Trace("'paltest_namedmutex_test1' failed at line %u. Expression: " #expression "\n", __LINE__); \ + fflush(stdout); \ + return false; \ + } \ + } while(false) + +char *BuildName(const char *testName, char *buffer, const char *prefix0, const char *prefix1 = nullptr) +{ + size_t nameLength = 0; + const char *prefixes[] = {prefix0, prefix1}; + for (int i = 0; i < 2; ++i) + { + const char *prefix = prefixes[i]; + if (prefix == nullptr) + { + break; + } + test_strcpy(&buffer[nameLength], prefix); + nameLength += test_strlen(prefix); + } + + if (g_isStress) + { + // Append the test name so that tests can run in parallel + nameLength += test_sprintf(&buffer[nameLength], "%s", testName); + buffer[nameLength++] = '_'; + } + + nameLength += test_sprintf(&buffer[nameLength], "%u", g_parentPid); + return buffer; +} + +char *BuildGlobalShmFilePath(const char *testName, char *buffer, const char *namePrefix) +{ + size_t pathLength = 0; + test_strcpy(&buffer[pathLength], GlobalShmFilePathPrefix); + pathLength += test_strlen(GlobalShmFilePathPrefix); + test_strcpy(&buffer[pathLength], namePrefix); + pathLength += test_strlen(namePrefix); + + if (g_isStress) + { + // Append the test name so that tests can run in parallel + pathLength += test_sprintf(&buffer[pathLength], "%s", testName); + buffer[pathLength++] = '_'; + } + + pathLength += test_sprintf(&buffer[pathLength], "%u", g_parentPid); + return buffer; +} + +class AutoCloseMutexHandle +{ +private: + HANDLE m_handle; + +public: + AutoCloseMutexHandle(HANDLE handle = nullptr) : m_handle(handle) + { + } + + ~AutoCloseMutexHandle() + { + Close(); + } + +public: + HANDLE GetHandle() const + { + return m_handle; + } + + bool Release() + { + return !!ReleaseMutex(m_handle); + } + + void Close() + { + if (m_handle != nullptr) + { + CloseHandle(m_handle); + m_handle = nullptr; + } + } + + void Abandon() + { + // Don't close the handle + m_handle = nullptr; + } + + AutoCloseMutexHandle &operator =(HANDLE handle) + { + Close(); + m_handle = handle; + return *this; + } + + operator HANDLE() const + { + return m_handle; + } + +private: + AutoCloseMutexHandle(const AutoCloseMutexHandle &other); + AutoCloseMutexHandle(AutoCloseMutexHandle &&other); + AutoCloseMutexHandle &operator =(const AutoCloseMutexHandle &other); +}; + +void TestCreateMutex(AutoCloseMutexHandle &m, const char *name, bool initiallyOwned = false) +{ + m.Close(); + m = CreateMutexA(nullptr, initiallyOwned, name); +} + +HANDLE TestOpenMutex(const char *name) +{ + return OpenMutexA(SYNCHRONIZE, false, name); +} + +bool StartProcess(const char *funcName) +{ + // Command line format: [stress] + + size_t processCommandLinePathLength = 0; + g_processCommandLinePath[processCommandLinePathLength++] = '\"'; + test_strcpy(&g_processCommandLinePath[processCommandLinePathLength], g_processPath); + processCommandLinePathLength += test_strlen(g_processPath); + g_processCommandLinePath[processCommandLinePathLength++] = '\"'; + g_processCommandLinePath[processCommandLinePathLength++] = ' '; + processCommandLinePathLength += test_sprintf(&g_processCommandLinePath[processCommandLinePathLength], "%u", g_parentPid); + g_processCommandLinePath[processCommandLinePathLength++] = ' '; + test_strcpy(&g_processCommandLinePath[processCommandLinePathLength], funcName); + processCommandLinePathLength += test_strlen(funcName); + + if (g_isStress) + { + test_strcpy(&g_processCommandLinePath[processCommandLinePathLength], " stress"); + processCommandLinePathLength += _countof("stress") - 1; + } + + STARTUPINFO si; + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(pi)); + if (!CreateProcessA(nullptr, g_processCommandLinePath, nullptr, nullptr, false, 0, nullptr, nullptr, &si, &pi)) + { + return false; + } + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return true; +} + +bool StartThread(LPTHREAD_START_ROUTINE func, void *arg = nullptr, HANDLE *threadHandleRef = nullptr) +{ + DWORD threadId; + HANDLE handle = CreateThread(nullptr, 0, func, arg, 0, &threadId); + if (handle != nullptr) + { + if (threadHandleRef == nullptr) + { + CloseHandle(handle); + } + else + { + *threadHandleRef = handle; + } + return true; + } + return false; +} + +bool WaitForMutexToBeCreated(const char *testName, AutoCloseMutexHandle &m, const char *eventNamePrefix) +{ + char eventName[MaxPathSize]; + BuildName(testName, eventName, GlobalPrefix, eventNamePrefix); + DWORD startTime = GetTickCount(); + while (true) + { + m = TestOpenMutex(eventName); + if (m != nullptr) + { + return true; + } + if (GetTickCount() - startTime >= FailTimeoutMilliseconds) + { + return false; + } + Sleep(PollLoopSleepMilliseconds); + } +} + +// The following functions are used for parent/child tests, where the child runs in a separate thread or process. The tests are +// organized such that one the parent or child is ever running code, and they yield control and wait for the other. Since the +// named mutex is the only type of cross-process sync object available, they are used as events to synchronize. The parent and +// child have a pair of event mutexes each, which they own initially. To release the other waiting thread/process, the +// thread/process releases one of its mutexes, which the other thread/process would be waiting on. To wait, the thread/process +// waits on one of the other thread/process' mutexes. All the while, they ping-pong between the two mutexes. YieldToChild() and +// YieldToParent() below control the releasing, waiting, and ping-ponging, to help create a deterministic path through the +// parent and child tests while both are running concurrently. + +bool AcquireChildRunningEvent(const char *testName, AutoCloseMutexHandle &childRunningEvent) +{ + char name[MaxPathSize]; + TestCreateMutex(childRunningEvent, BuildName(testName, name, GlobalPrefix, ChildRunningEventNamePrefix)); + TestAssert(WaitForSingleObject(childRunningEvent, FailTimeoutMilliseconds) == WAIT_OBJECT_0); + return true; +} + +bool InitializeParent(const char *testName, AutoCloseMutexHandle parentEvents[2], AutoCloseMutexHandle childEvents[2]) +{ + // Create parent events + char name[MaxPathSize]; + for (int i = 0; i < 2; ++i) + { + TestCreateMutex( + parentEvents[i], + BuildName(testName, name, GlobalPrefix, i == 0 ? ParentEventNamePrefix0 : ParentEventNamePrefix1), + true); + TestAssert(parentEvents[i] != nullptr); + TestAssert(GetLastError() != ERROR_ALREADY_EXISTS); + } + + // Wait for the child to create and acquire locks on its events so that the parent can wait on them + TestAssert(WaitForMutexToBeCreated(testName, childEvents[0], ChildEventNamePrefix0)); + TestAssert(WaitForMutexToBeCreated(testName, childEvents[1], ChildEventNamePrefix1)); + return true; +} + +bool UninitializeParent(const char *testName, AutoCloseMutexHandle parentEvents[2], bool releaseParentEvents = true) +{ + if (releaseParentEvents) + { + TestAssert(parentEvents[0].Release()); + TestAssert(parentEvents[1].Release()); + } + + // Wait for the child to finish its test. Child tests will release and close 'childEvents' before releasing + // 'childRunningEvent', so after this wait, the parent process can freely start another child that will deterministically + // recreate the 'childEvents', which the next parent test will wait on, upon its initialization. + AutoCloseMutexHandle childRunningEvent; + TestAssert(AcquireChildRunningEvent(testName, childRunningEvent)); + TestAssert(childRunningEvent.Release()); + return true; +} + +bool InitializeChild( + const char *testName, + AutoCloseMutexHandle &childRunningEvent, + AutoCloseMutexHandle parentEvents[2], + AutoCloseMutexHandle childEvents[2]) +{ + TestAssert(AcquireChildRunningEvent(testName, childRunningEvent)); + + // Create child events + char name[MaxPathSize]; + for (int i = 0; i < 2; ++i) + { + TestCreateMutex( + childEvents[i], + BuildName(testName, name, GlobalPrefix, i == 0 ? ChildEventNamePrefix0 : ChildEventNamePrefix1), + true); + TestAssert(childEvents[i] != nullptr); + TestAssert(GetLastError() != ERROR_ALREADY_EXISTS); + } + + // Wait for the parent to create and acquire locks on its events so that the child can wait on them + TestAssert(WaitForMutexToBeCreated(testName, parentEvents[0], ParentEventNamePrefix0)); + TestAssert(WaitForMutexToBeCreated(testName, parentEvents[1], ParentEventNamePrefix1)); + + // Parent/child tests start with the parent, so after initialization, wait for the parent to tell the child test to start + TestAssert(WaitForSingleObject(parentEvents[0], FailTimeoutMilliseconds) == WAIT_OBJECT_0); + TestAssert(parentEvents[0].Release()); + return true; +} + +bool UninitializeChild( + AutoCloseMutexHandle &childRunningEvent, + AutoCloseMutexHandle parentEvents[2], + AutoCloseMutexHandle childEvents[2]) +{ + // Release and close 'parentEvents' and 'childEvents' before releasing 'childRunningEvent' to avoid races, see + // UnitializeParent() for more info + TestAssert(childEvents[0].Release()); + TestAssert(childEvents[1].Release()); + childEvents[0].Close(); + childEvents[1].Close(); + parentEvents[0].Close(); + parentEvents[1].Close(); + TestAssert(childRunningEvent.Release()); + return true; +} + +bool YieldToChild(AutoCloseMutexHandle parentEvents[2], AutoCloseMutexHandle childEvents[2], int &ei) +{ + TestAssert(parentEvents[ei].Release()); + TestAssert(WaitForSingleObject(childEvents[ei], FailTimeoutMilliseconds) == WAIT_OBJECT_0); + TestAssert(childEvents[ei].Release()); + TestAssert(WaitForSingleObject(parentEvents[ei], 0) == WAIT_OBJECT_0); + ei = 1 - ei; + return true; +} + +bool YieldToParent(AutoCloseMutexHandle parentEvents[2], AutoCloseMutexHandle childEvents[2], int &ei) +{ + TestAssert(childEvents[ei].Release()); + ei = 1 - ei; + TestAssert(WaitForSingleObject(parentEvents[ei], FailTimeoutMilliseconds) == WAIT_OBJECT_0); + TestAssert(parentEvents[ei].Release()); + TestAssert(WaitForSingleObject(childEvents[1 - ei], 0) == WAIT_OBJECT_0); + return true; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Tests + +bool NameTests() +{ + const char *testName = "NameTests"; + + AutoCloseMutexHandle m; + char name[MaxPathSize]; + + // Empty name + TestCreateMutex(m, ""); + TestAssert(m != nullptr); + + // Normal name + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); + TestAssert(m != nullptr); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, NamePrefix))) != nullptr); + TestCreateMutex(m, BuildName(testName, name, SessionPrefix, NamePrefix)); + TestAssert(m != nullptr); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, SessionPrefix, NamePrefix))) != nullptr); + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix))) != nullptr); + + // Name too long. The maximum allowed length depends on the file system, so we're not checking for that. + { + char name[257]; + memset(name, 'a', _countof(name) - 1); + name[_countof(name) - 1] = '\0'; + TestCreateMutex(m, name); + TestAssert(m == nullptr); + TestAssert(GetLastError() == ERROR_FILENAME_EXCED_RANGE); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(name)) == nullptr); + TestAssert(GetLastError() == ERROR_FILENAME_EXCED_RANGE); + } + + // Invalid characters in name + TestCreateMutex(m, BuildName(testName, name, InvalidNamePrefix0)); + TestAssert(m == nullptr); + TestAssert(GetLastError() == ERROR_INVALID_NAME); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, InvalidNamePrefix0))) == nullptr); + TestAssert(GetLastError() == ERROR_INVALID_NAME); + TestCreateMutex(m, BuildName(testName, name, InvalidNamePrefix1)); + TestAssert(m == nullptr); + TestAssert(GetLastError() == ERROR_INVALID_NAME); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, InvalidNamePrefix1))) == nullptr); + TestAssert(GetLastError() == ERROR_INVALID_NAME); + TestCreateMutex(m, BuildName(testName, name, SessionPrefix, InvalidNamePrefix0)); + TestAssert(m == nullptr); + TestAssert(GetLastError() == ERROR_INVALID_NAME); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, SessionPrefix, InvalidNamePrefix0))) == nullptr); + TestAssert(GetLastError() == ERROR_INVALID_NAME); + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, InvalidNamePrefix1)); + TestAssert(m == nullptr); + TestAssert(GetLastError() == ERROR_INVALID_NAME); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, GlobalPrefix, InvalidNamePrefix1))) == nullptr); + TestAssert(GetLastError() == ERROR_INVALID_NAME); + + // Creating a second reference to the same named mutex yields an error indicating that it was opened, not created + { + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); + TestAssert(m != nullptr); + AutoCloseMutexHandle m2; + TestCreateMutex(m2, BuildName(testName, name, NamePrefix)); + TestAssert(m2 != nullptr); + TestAssert(GetLastError() == ERROR_ALREADY_EXISTS); + } + + return true; +} + +bool HeaderMismatchTests() +{ + const char *testName = "HeaderMismatchTests"; + + AutoCloseMutexHandle m, m2; + char name[MaxPathSize]; + int fd; + + // Create and hold onto a mutex during this test to create the shared memory directory + TestCreateMutex(m2, BuildName(testName, name, GlobalPrefix, TempNamePrefix)); + TestAssert(m2 != nullptr); + + // Unknown shared memory type + TestAssert(WriteHeaderInfo(BuildGlobalShmFilePath(testName, name, NamePrefix), -1, 1, &fd)); + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m == nullptr); + TestAssert(GetLastError() == ERROR_INVALID_HANDLE); + TestAssert(test_close(fd) == 0); + TestAssert(test_unlink(BuildGlobalShmFilePath(testName, name, NamePrefix)) == 0); + + // Mismatched version + TestAssert(WriteHeaderInfo(BuildGlobalShmFilePath(testName, name, NamePrefix), 0, -1, &fd)); + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m == nullptr); + TestAssert(GetLastError() == ERROR_INVALID_HANDLE); + TestAssert(test_close(fd) == 0); + TestAssert(test_unlink(BuildGlobalShmFilePath(testName, name, NamePrefix)) == 0); + + return true; +} + +bool MutualExclusionTests_Parent() +{ + const char *testName = "MutualExclusionTests"; + + AutoCloseMutexHandle parentEvents[2], childEvents[2]; + TestAssert(InitializeParent(testName, parentEvents, childEvents)); + int ei = 0; + char name[MaxPathSize]; + AutoCloseMutexHandle m; + + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); + + // Recursive locking with various timeouts + TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); + TestAssert(WaitForSingleObject(m, FailTimeoutMilliseconds) == WAIT_OBJECT_0); + TestAssert(WaitForSingleObject(m, static_cast(-1)) == WAIT_OBJECT_0); + TestAssert(m.Release()); + TestAssert(m.Release()); + TestAssert(m.Release()); + TestAssert(!m.Release()); // try to release the lock while nobody owns it, and verify recursive lock counting + TestAssert(GetLastError() == ERROR_NOT_OWNER); + + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child takes the lock + + TestAssert(WaitForSingleObject(m, 0) == WAIT_TIMEOUT); // try to lock the mutex without waiting + TestAssert(WaitForSingleObject(m, g_expectedTimeoutMilliseconds) == WAIT_TIMEOUT); // try to lock the mutex with a timeout + TestAssert(!m.Release()); // try to release the lock while another thread owns it + TestAssert(GetLastError() == ERROR_NOT_OWNER); + + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child releases the lock + + TestAssert(WaitForSingleObject(m, static_cast(-1)) == WAIT_OBJECT_0); // lock the mutex with no timeout and release + TestAssert(m.Release()); + + UninitializeParent(testName, parentEvents); + return true; +} + +DWORD PALAPI MutualExclusionTests_Child(void *arg = nullptr) +{ + const char *testName = "MutualExclusionTests"; + + AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2]; + TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents)); + int ei = 0; + + { + char name[MaxPathSize]; + AutoCloseMutexHandle m; + + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); + TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); // lock the mutex + YieldToParent(parentEvents, childEvents, ei); // parent attempts to lock/release, and fails + TestAssert(m.Release()); // release the lock + } + + UninitializeChild(childRunningEvent, parentEvents, childEvents); + return 0; +} + +bool MutualExclusionTests() +{ + const char *testName = "MutualExclusionTests"; + + { + AutoCloseMutexHandle m; + char name[MaxPathSize]; + + // Releasing a lock that is not owned by any thread fails + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); + TestAssert(m != nullptr); + TestAssert(!m.Release()); + TestAssert(GetLastError() == ERROR_NOT_OWNER); + + // Acquire a lock during upon creation, and release + TestCreateMutex(m, BuildName(testName, name, NamePrefix), true); + TestAssert(m != nullptr); + TestAssert(m.Release()); + + // Multi-waits including a named mutex are not supported + AutoCloseMutexHandle m2; + TestCreateMutex(m2, nullptr); + TestAssert(m2 != nullptr); + HANDLE waitHandles[] = {m2.GetHandle(), m.GetHandle()}; + TestAssert( + WaitForMultipleObjects( + _countof(waitHandles), + waitHandles, + false /* waitAll */, + FailTimeoutMilliseconds) == + WAIT_FAILED); + TestAssert(GetLastError() == ERROR_NOT_SUPPORTED); + TestAssert( + WaitForMultipleObjects( + _countof(waitHandles), + waitHandles, + true /* waitAll */, + FailTimeoutMilliseconds) == + WAIT_FAILED); + TestAssert(GetLastError() == ERROR_NOT_SUPPORTED); + } + + // When another thread or process owns the lock, this process should not be able to acquire a lock, and the converse + TestAssert(StartThread(MutualExclusionTests_Child)); + TestAssert(MutualExclusionTests_Parent()); + TestAssert(StartProcess("MutualExclusionTests_Child")); + TestAssert(MutualExclusionTests_Parent()); + + return true; +} + +bool LifetimeTests_Parent() +{ + const char *testName = "LifetimeTests"; + + AutoCloseMutexHandle parentEvents[2], childEvents[2]; + TestAssert(InitializeParent(testName, parentEvents, childEvents)); + int ei = 0; + char name[MaxPathSize]; + AutoCloseMutexHandle m; + + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); // create first reference to mutex + TestAssert(m != nullptr); + TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child creates second reference to mutex using CreateMutex + m.Close(); // close first reference + TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child closes second reference + TestAssert(!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); // create first reference to mutex + TestAssert(m != nullptr); + TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child creates second reference to mutex using OpenMutex + m.Close(); // close first reference + TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child closes second reference + TestAssert(!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + + UninitializeParent(testName, parentEvents); + return true; +} + +DWORD PALAPI LifetimeTests_Child(void *arg = nullptr) +{ + const char *testName = "LifetimeTests"; + + AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2]; + TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents)); + int ei = 0; + + { + char name[MaxPathSize]; + AutoCloseMutexHandle m; + + // ... parent creates first reference to mutex + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); // create second reference to mutex using CreateMutex + TestAssert(m != nullptr); + TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent closes first reference + m.Close(); // close second reference + + TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent verifies, and creates first reference to mutex again + m = TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix)); // create second reference to mutex using OpenMutex + TestAssert(m != nullptr); + TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent closes first reference + m.Close(); // close second reference + + TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent verifies + } + + UninitializeChild(childRunningEvent, parentEvents, childEvents); + return 0; +} + +bool LifetimeTests() +{ + const char *testName = "LifetimeTests"; + + { + AutoCloseMutexHandle m; + char name[MaxPathSize]; + + // Shm file should be created and deleted + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); + TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + m.Close(); + TestAssert(!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + } + + // Shm file should not be deleted until last reference is released + TestAssert(StartThread(LifetimeTests_Child)); + TestAssert(LifetimeTests_Parent()); + TestAssert(StartProcess("LifetimeTests_Child")); + TestAssert(LifetimeTests_Parent()); + + return true; +} + +DWORD PALAPI AbandonTests_Child_TryLock(void *arg = nullptr); + +bool AbandonTests_Parent() +{ + const char *testName = "AbandonTests"; + + char name[MaxPathSize]; + AutoCloseMutexHandle m; + { + AutoCloseMutexHandle parentEvents[2], childEvents[2]; + TestAssert(InitializeParent(testName, parentEvents, childEvents)); + int ei = 0; + + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child locks mutex + TestAssert(parentEvents[0].Release()); + TestAssert(parentEvents[1].Release()); // child sleeps for short duration and abandons the mutex + TestAssert(WaitForSingleObject(m, FailTimeoutMilliseconds) == WAIT_ABANDONED_0); // attempt to lock and see abandoned mutex + + UninitializeParent(testName, parentEvents, false /* releaseParentEvents */); // parent events are released above + } + + // Verify that the mutex lock is owned by this thread, by starting a new thread and trying to lock it + StartThread(AbandonTests_Child_TryLock); + { + AutoCloseMutexHandle parentEvents[2], childEvents[2]; + TestAssert(InitializeParent(testName, parentEvents, childEvents)); + int ei = 0; + + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child tries to lock mutex + + UninitializeParent(testName, parentEvents); + } + + // Verify that the mutex lock is owned by this thread, by starting a new process and trying to lock it + StartProcess("AbandonTests_Child_TryLock"); + AutoCloseMutexHandle parentEvents[2], childEvents[2]; + TestAssert(InitializeParent(testName, parentEvents, childEvents)); + int ei = 0; + + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child tries to lock mutex + + // Continue verification + TestAssert(m.Release()); + TestAssert(WaitForSingleObject(m, FailTimeoutMilliseconds) == WAIT_OBJECT_0); // lock again to see it's not abandoned anymore + TestAssert(m.Release()); + + UninitializeParent(testName, parentEvents, false /* releaseParentEvents */); // parent events are released above + + // Since the child abandons the mutex, and a child process may not release the file lock on the shared memory file before + // indicating completion to the parent, make sure to delete the shared memory file by repeatedly opening/closing the mutex + // until the parent process becomes the last process to reference the mutex and closing it deletes the file. + DWORD startTime = GetTickCount(); + while (true) + { + m.Close(); + if (!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))) + { + break; + } + + TestAssert(GetTickCount() - startTime < FailTimeoutMilliseconds); + m = TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix)); + } + + return true; +} + +DWORD PALAPI AbandonTests_Child_GracefulExit_Close(void *arg = nullptr) +{ + const char *testName = "AbandonTests"; + + AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2]; + TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents)); + int ei = 0; + + { + char name[MaxPathSize]; + AutoCloseMutexHandle m; + + // ... parent waits for child to lock mutex + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); + TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); + TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent waits on mutex + Sleep(g_expectedTimeoutMilliseconds); // wait for parent to wait on mutex + m.Close(); // close mutex without releasing lock + } + + UninitializeChild(childRunningEvent, parentEvents, childEvents); + return 0; +} + +DWORD AbandonTests_Child_GracefulExit_NoClose(void *arg = nullptr) +{ + const char *testName = "AbandonTests"; + + // This test needs to run in a separate process because it does not close the mutex handle. Running it in a separate thread + // causes the mutex object to retain a reference until the process terminates. + TestAssert(test_getpid() != g_parentPid); + + AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2]; + TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents)); + int ei = 0; + + { + char name[MaxPathSize]; + AutoCloseMutexHandle m; + + // ... parent waits for child to lock mutex + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); + TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); + TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent waits on mutex + Sleep(g_expectedTimeoutMilliseconds); // wait for parent to wait on mutex + m.Abandon(); // don't close the mutex + } + + UninitializeChild(childRunningEvent, parentEvents, childEvents); + return 0; +} + +DWORD AbandonTests_Child_AbruptExit(void *arg = nullptr) +{ + const char *testName = "AbandonTests"; + + DWORD currentPid = test_getpid(); + TestAssert(currentPid != g_parentPid); // this test needs to run in a separate process + + { + AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2]; + TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents)); + int ei = 0; + + { + char name[MaxPathSize]; + AutoCloseMutexHandle m; + + // ... parent waits for child to lock mutex + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); + TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); + TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent waits on mutex + Sleep(g_expectedTimeoutMilliseconds); // wait for parent to wait on mutex + m.Abandon(); // don't close the mutex + } + + UninitializeChild(childRunningEvent, parentEvents, childEvents); + } + + TestAssert(test_kill(currentPid) == 0); // abandon the mutex abruptly + return 0; +} + +// This child process acquires the mutex lock, creates another child process (to ensure that file locks are not inherited), and +// abandons the mutex abruptly. The second child process detects the abandonment and abandons the mutex again for the parent to +// detect. Issue: https://github.com/dotnet/coreclr/issues/21455 +DWORD AbandonTests_Child_FileLocksNotInherited_Parent_AbruptExit(void *arg = nullptr) +{ + const char *testName = "AbandonTests"; + + DWORD currentPid = test_getpid(); + TestAssert(currentPid != g_parentPid); // this test needs to run in a separate process + + { + char name[MaxPathSize]; + AutoCloseMutexHandle m; + + // ... root parent waits for child to lock mutex + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); + TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); + + // Start a child process while holding the lock on the mutex, to ensure that file locks are not inherited by the + // immediate child, such that the immediate child would be able to detect the mutex being abandoned below. This process + // does not communicate with the root parent, it only communicates to the immediate child by abandoning the mutex. The + // immediate child communicates with the root parent to complete the test. + TestAssert(StartProcess("AbandonTests_Child_FileLocksNotInherited_Child_AbruptExit")); // immediate child waits on mutex + + Sleep(g_expectedTimeoutMilliseconds); // wait for immediate child to wait on mutex + m.Abandon(); // don't close the mutex + } + + TestAssert(test_kill(currentPid) == 0); // abandon the mutex abruptly + return 0; +} + +DWORD AbandonTests_Child_FileLocksNotInherited_Child_AbruptExit(void *arg = nullptr) +{ + const char *testName = "AbandonTests"; + + DWORD currentPid = test_getpid(); + TestAssert(currentPid != g_parentPid); // this test needs to run in a separate process + + AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2]; + TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents)); + int ei = 0; + + { + char name[MaxPathSize]; + AutoCloseMutexHandle m; + + // ... immediate parent expects child to wait on mutex + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); + TestAssert(WaitForSingleObject(m, FailTimeoutMilliseconds) == WAIT_ABANDONED_0); // attempt to lock and see abandoned mutex + TestAssert(YieldToParent(parentEvents, childEvents, ei)); // root parent waits on mutex + Sleep(g_expectedTimeoutMilliseconds); // wait for root parent to wait on mutex + m.Close(); // close mutex without releasing lock (root parent expects the mutex to be abandoned) + } + + UninitializeChild(childRunningEvent, parentEvents, childEvents); + return 0; +} + +DWORD PALAPI AbandonTests_Child_TryLock(void *arg) +{ + const char *testName = "AbandonTests"; + + AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2]; + TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents)); + int ei = 0; + + { + char name[MaxPathSize]; + AutoCloseMutexHandle m; + + // ... parent waits for child to lock mutex + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); + TestAssert(WaitForSingleObject(m, 0) == WAIT_TIMEOUT); // try to lock the mutex while the parent holds the lock + TestAssert(WaitForSingleObject(m, g_expectedTimeoutMilliseconds) == WAIT_TIMEOUT); + } + + UninitializeChild(childRunningEvent, parentEvents, childEvents); + return 0; +} + +bool AbandonTests() +{ + const char *testName = "AbandonTests"; + + // Abandon by graceful exit where the lock owner closes the mutex before releasing it, unblocks a waiter + TestAssert(StartThread(AbandonTests_Child_GracefulExit_Close)); + TestAssert(AbandonTests_Parent()); + TestAssert(StartProcess("AbandonTests_Child_GracefulExit_Close")); + TestAssert(AbandonTests_Parent()); + + // Abandon by graceful exit without closing the mutex unblocks a waiter + TestAssert(StartProcess("AbandonTests_Child_GracefulExit_NoClose")); + TestAssert(AbandonTests_Parent()); + + // Abandon by abrupt exit unblocks a waiter + TestAssert(StartProcess("AbandonTests_Child_AbruptExit")); + TestAssert(AbandonTests_Parent()); + + TestAssert(StartProcess("AbandonTests_Child_FileLocksNotInherited_Parent_AbruptExit")); + TestAssert(AbandonTests_Parent()); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Test harness + +bool (*const (TestList[]))() = +{ + NameTests, + HeaderMismatchTests, + MutualExclusionTests, + LifetimeTests, + AbandonTests +}; + +bool RunTests() +{ + bool allPassed = true; + for (SIZE_T i = 0; i < _countof(TestList); ++i) + { + if (!TestList[i]()) + { + allPassed = false; + } + } + return allPassed; +} + +DWORD g_stressDurationMilliseconds = 0; +LONG g_stressTestCounts[_countof(TestList)] = {0}; +LONG g_stressResult = true; + +DWORD PALAPI StressTest(void *arg) +{ + // Run the specified test continuously for the stress duration + SIZE_T testIndex = reinterpret_cast(arg); + DWORD startTime = GetTickCount(); + do + { + ++g_stressTestCounts[testIndex]; + if (!TestList[testIndex]()) + { + InterlockedExchange(&g_stressResult, false); + break; + } + } while ( + InterlockedCompareExchange(&g_stressResult, false, false) == true && + GetTickCount() - startTime < g_stressDurationMilliseconds); + return 0; +} + +bool StressTests(DWORD durationMinutes) +{ + g_isStress = true; + g_expectedTimeoutMilliseconds = 1; + g_stressDurationMilliseconds = durationMinutes * (60 * 1000); + + // Start a thread for each test + HANDLE threadHandles[_countof(TestList)]; + for (SIZE_T i = 0; i < _countof(threadHandles); ++i) + { + TestAssert(StartThread(StressTest, reinterpret_cast(i), &threadHandles[i])); + } + + while (true) + { + DWORD waitResult = + WaitForMultipleObjects(_countof(threadHandles), threadHandles, true /* bWaitAll */, 10 * 1000 /* dwMilliseconds */); + TestAssert(waitResult == WAIT_OBJECT_0 || waitResult == WAIT_TIMEOUT); + if (waitResult == WAIT_OBJECT_0) + { + break; + } + + Trace("'paltest_namedmutex_test1' stress test counts: "); + for (SIZE_T i = 0; i < _countof(g_stressTestCounts); ++i) + { + if (i != 0) + { + Trace(", "); + } + Trace("%u", g_stressTestCounts[i]); + } + Trace("\n"); + fflush(stdout); + } + + for (SIZE_T i = 0; i < _countof(threadHandles); ++i) + { + CloseHandle(threadHandles[i]); + } + return static_cast(g_stressResult); +} + +int __cdecl main(int argc, char **argv) +{ + if (argc < 1 || argc > 4) + { + return FAIL; + } + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + test_strcpy(g_processPath, argv[0]); + + if (argc == 1) + { + // Unit test arguments: + + g_parentPid = test_getpid(); + int result = RunTests() ? PASS : FAIL; + ExitProcess(result); + return result; + } + + if (test_strcmp(argv[1], "stress") == 0) + { + // Stress test arguments: stress [durationMinutes] + + DWORD durationMinutes = 1; + if (argc >= 3 && test_sscanf(argv[2], "%u", &durationMinutes) != 1) + { + ExitProcess(FAIL); + return FAIL; + } + + g_parentPid = test_getpid(); + int result = StressTests(durationMinutes) ? PASS : FAIL; + ExitProcess(result); + return result; + } + + // Child test process arguments: [stress] + + g_isParent = false; + + // Get parent process' ID from argument + if (test_sscanf(argv[1], "%u", &g_parentPid) != 1) + { + ExitProcess(FAIL); + return FAIL; + } + + if (argc >= 4 && test_strcmp(argv[3], "stress") == 0) + { + g_isStress = true; + } + + if (test_strcmp(argv[2], "MutualExclusionTests_Child") == 0) + { + MutualExclusionTests_Child(); + } + else if (test_strcmp(argv[2], "LifetimeTests_Child") == 0) + { + LifetimeTests_Child(); + } + else if (test_strcmp(argv[2], "AbandonTests_Child_GracefulExit_Close") == 0) + { + AbandonTests_Child_GracefulExit_Close(); + } + else if (test_strcmp(argv[2], "AbandonTests_Child_GracefulExit_NoClose") == 0) + { + AbandonTests_Child_GracefulExit_NoClose(); + } + else if (test_strcmp(argv[2], "AbandonTests_Child_AbruptExit") == 0) + { + AbandonTests_Child_AbruptExit(); + } + else if (test_strcmp(argv[2], "AbandonTests_Child_FileLocksNotInherited_Parent_AbruptExit") == 0) + { + AbandonTests_Child_FileLocksNotInherited_Parent_AbruptExit(); + } + else if (test_strcmp(argv[2], "AbandonTests_Child_FileLocksNotInherited_Child_AbruptExit") == 0) + { + AbandonTests_Child_FileLocksNotInherited_Child_AbruptExit(); + } + else if (test_strcmp(argv[2], "AbandonTests_Child_TryLock") == 0) + { + AbandonTests_Child_TryLock(); + } + ExitProcess(PASS); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp new file mode 100644 index 0000000..ae3ebc3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp @@ -0,0 +1,66 @@ +// 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. + +// Contains wrappers for functions whose required headers conflict with the PAL + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define _countof(a) (sizeof(a) / sizeof(a[0])) + +#undef PAGE_SIZE +#define PAGE_SIZE (4096) + +auto test_strcpy = strcpy; +auto test_strcmp = strcmp; +auto test_strlen = strlen; +auto test_sprintf = sprintf; +auto test_sscanf = sscanf; +auto test_close = close; +auto test_unlink = unlink; + +unsigned int test_getpid() +{ + return getpid(); +} + +int test_kill(unsigned int pid) +{ + return kill(pid, SIGKILL); +} + +bool TestFileExists(const char *path) +{ + int fd = open(path, O_RDWR); + if (fd == -1) + return false; + close(fd); + return true; +} + +bool WriteHeaderInfo(const char *path, char sharedMemoryType, char version, int *fdRef) +{ + int fd = open(path, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + if (fd == -1) + return false; + *fdRef = fd; + if (ftruncate(fd, PAGE_SIZE) != 0) + return false; + if (lseek(fd, 0, SEEK_SET) != 0) + return false; + + // See SharedMemorySharedDataHeader for format + char buffer[] = {sharedMemoryType, version}; + if (write(fd, buffer, _countof(buffer)) != _countof(buffer)) + return false; + + return flock(fd, LOCK_SH | LOCK_NB) == 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/testinfo.dat new file mode 100644 index 0000000..e309009 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/NamedMutex/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = Named mutex +Name = Tests for named mutexes +TYPE = DEFAULT +EXE1 = namedmutex +Description += These test cases test named mutexes, including positive += and negative cases, cross-thread and cross-process, mutual += exclusion, abandon detection, etc. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/CMakeLists.txt new file mode 100644 index 0000000..dcf480b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/CMakeLists.txt @@ -0,0 +1,6 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test1/CMakeLists.txt new file mode 100644 index 0000000..a33d65d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_openeventw_test1 + ${SOURCES} +) + +add_dependencies(paltest_openeventw_test1 coreclrpal) + +target_link_libraries(paltest_openeventw_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test1/test1.cpp new file mode 100644 index 0000000..9dcb3a4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test1/test1.cpp @@ -0,0 +1,134 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Test for OpenEventW. This test creates an event, +** opens a handle to the same event, then waits on both handles +** in both a signalled and non-signalled state to verify they're. +** pointing to the same event object. +** +** +**==========================================================================*/ +#include + +int __cdecl main(int argc, char **argv) +{ + BOOL bRet = FAIL; + DWORD dwRet; + HANDLE hEvent; + HANDLE hOpenEvent; + WCHAR theName[] = {'E','v','e','n','t','\0'}; + LPCWSTR lpName = theName; + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + /* Create an event (with a 0 intial state!) and ensure that the + HANDLE is valid + */ + hEvent = CreateEventW( NULL, TRUE, FALSE, lpName ); + if( hEvent == NULL ) + { + Fail( "ERROR:%lu:CreateEvent call failed\n", GetLastError() ); + } + + + /* Call OpenEventW to get another HANDLE on + this event. Ensure the HANDLE is valid. + */ + hOpenEvent = OpenEventW( EVENT_ALL_ACCESS, TRUE, lpName ); + if( hOpenEvent == NULL ) + { + Trace( "ERROR:%lu:OpenEventW call failed\n", GetLastError() ); + goto cleanup2; + } + + /* wait on the original event to verify that it's not signalled */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + Trace( "ERROR:WaitForSingleObject returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + goto cleanup; + } + + /* wait on the opened event to verify that it's not signalled either */ + dwRet = WaitForSingleObject( hOpenEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + Trace( "ERROR:WaitForSingleObject returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + goto cleanup; + } + + + /* Set this opened HANDLE */ + if( ! SetEvent( hOpenEvent ) ) + { + Trace( "ERROR:%lu:SetEvent call failed\n", GetLastError() ); + goto cleanup; + } + + /* wait on the original event to verify that it's signalled */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject returned %lu, " + "expected WAIT_OBJECT_0\n", + dwRet ); + goto cleanup; + } + + /* wait on the opened event to verify that it's signalled too */ + dwRet = WaitForSingleObject( hOpenEvent, 0 ); + if( dwRet != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject returned %lu, " + "expected WAIT_OBJECT_0\n", + dwRet ); + goto cleanup; + } + + /* success if we get here */ + bRet = PASS; + +cleanup: + /* close the opened handle */ + if( ! CloseHandle( hOpenEvent ) ) + { + Trace( "ERROR:%lu:CloseHandle call failed\n", GetLastError() ); + bRet = FAIL; + } + +cleanup2: + /* close the original event handle */ + if( ! CloseHandle( hEvent ) ) + { + Trace( "ERROR:%lu:CloseHandle call failed\n", GetLastError() ); + bRet = FAIL; + } + + /* check for failure */ + if( bRet == FAIL ) + { + Fail( "test failed\n" ); + } + + + /* terminate the PAL */ + PAL_Terminate(); + + /* return success */ + return ( PASS ); + +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test1/testinfo.dat new file mode 100644 index 0000000..cc9be71 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = threading +Function = OpenEventW +Name = Positive Test for OpenEventW +TYPE = DEFAULT +EXE1 = test1 +Description += Purpose: Test for OpenEventW. This test creates an event, += opens a handle to the same event, then waits on both handles += in both a signalled and non-signalled state to verify they're += pointing to the same event object. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test2/CMakeLists.txt new file mode 100644 index 0000000..96fb22f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_openeventw_test2 + ${SOURCES} +) + +add_dependencies(paltest_openeventw_test2 coreclrpal) + +target_link_libraries(paltest_openeventw_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test2/test2.cpp new file mode 100644 index 0000000..9cbf872 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test2/test2.cpp @@ -0,0 +1,194 @@ +// 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. + +/*============================================================================= +** +** Source: test2.c +** +** Purpose: Positive test for OpenEventW. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateEvent +** CloseHandle +** WaitForSingleObject +** +** Purpose: +** +** Test to ensure proper operation of the OpenEventW() +** API by creating a new named event and verifying that +** it can be used interchangeably by setting the event +** with the original handle and waiting on it with the +** new one, then resetting it with the new one and waiting +** on it with the original one. +** +** +**===========================================================================*/ +#include + + + +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + BOOL ret = FAIL; + DWORD dwRet = 0; + HANDLE hEvent = NULL; + HANDLE hTestEvent = NULL; + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + BOOL bManualReset = TRUE; + BOOL bInitialState = FALSE; + WCHAR wcName[] = {'W','o','o','B','a','b','y','\0'}; + LPWSTR lpName = wcName; + + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + + /* create an event which we can use with SetEvent */ + hEvent = CreateEventW( lpEventAttributes, + bManualReset, + bInitialState, + lpName ); + + if( hEvent == NULL ) + { + /* ERROR */ + Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + } + + /* open a new handle to our event */ + hTestEvent = OpenEventW(EVENT_ALL_ACCESS, /* we want all rights */ + FALSE, /* no inherit */ + lpName ); + + if( hTestEvent == NULL ) + { + /* ERROR */ + Trace( "ERROR:%lu:OpenEventW() call failed\n", GetLastError() ); + goto cleanup; + } + + /* verify that the event isn't signalled yet by waiting on both */ + /* handles to the event object */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + goto cleanup; + } + + dwRet = WaitForSingleObject( hTestEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + goto cleanup; + } + + + /* set the event using the original handle */ + if( ! SetEvent( hEvent ) ) + { + /* ERROR */ + Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() ); + goto cleanup; + } + + /* verify that the event is signalled by waiting on both handles */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_OBJECT_0 ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_OBJECT_0\n", + dwRet ); + goto cleanup; + } + + dwRet = WaitForSingleObject( hTestEvent, 0 ); + if( dwRet != WAIT_OBJECT_0 ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_OBJECT_0\n", + dwRet ); + goto cleanup; + } + + /* reset the event using the new handle */ + if( ! ResetEvent( hTestEvent ) ) + { + /* ERROR */ + Trace( "ERROR:%lu:ResetEvent() call failed\n", GetLastError() ); + goto cleanup; + } + + /* verify that the event isn't signalled by waiting on both handles */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + goto cleanup; + } + + dwRet = WaitForSingleObject( hTestEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + goto cleanup; + } + + + /* test was successful */ + ret = PASS; + + +cleanup: + /* close the new event handle */ + if( hTestEvent != NULL ) + { + if( ! CloseHandle( hTestEvent ) ) + { + ret = FAIL; + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + } + + /* close the original event handle */ + if( ! CloseHandle( hEvent ) ) + { + ret = FAIL; + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + + /* failure message */ + if( ret != PASS ) + { + Fail( "Test failed\n" ); + } + + + /* PAL termination */ + PAL_Terminate(); + + /* return success or failure */ + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test2/testinfo.dat new file mode 100644 index 0000000..ad3f22e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test2/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = threading +Function = OpenEventW +Name = Positive test for OpenEventW +TYPE = DEFAULT +EXE1 = test2 +Description += Test to ensure proper operation of the OpenEventW() += API by creating a new named event and verifying that += it can be used interchangeably by setting the event += with the original handle and waiting on it with the += new one, then resetting it with the new one and waiting += on it with the original one. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/CMakeLists.txt new file mode 100644 index 0000000..4d95f72 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + test3.cpp +) + +add_executable(paltest_openeventw_test3 + ${TESTSOURCES} +) + +add_dependencies(paltest_openeventw_test3 coreclrpal) + +target_link_libraries(paltest_openeventw_test3 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + childprocess.cpp +) + +add_executable(paltest_openeventw_test3_child + ${HELPERSOURCES} +) + +add_dependencies(paltest_openeventw_test3_child coreclrpal) + +target_link_libraries(paltest_openeventw_test3_child + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/childprocess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/childprocess.cpp new file mode 100644 index 0000000..b5149e0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/childprocess.cpp @@ -0,0 +1,81 @@ +// 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. + +/*============================================================ +** +** Source: childprocess.c +** +** Purpose: Test to ensure that OpenEventW() works when +** opening an event created by another process. The test +** program launches this program as a child, which creates +** a named, initially-unset event. The child waits up to +** 10 seconds for the parent process to open that event +** and set it, and returns PASS if the event was set or FAIL +** otherwise. The parent process checks the return value +** from the child to verify that the opened event was +** properly used across processes. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateEventW +** WaitForSingleObject +** CloseHandle +** +** +**=========================================================*/ + +#include + +int __cdecl main( int argc, char **argv ) +{ + /* local variables */ + HANDLE hEvent = NULL; + WCHAR wcName[] = {'P','A','L','R','o','c','k','s','\0'}; + LPWSTR lpName = wcName; + + int result = PASS; + + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + + /* open a handle to the event created in the child process */ + hEvent = OpenEventW( EVENT_ALL_ACCESS, /* we want all rights */ + FALSE, /* no inherit */ + lpName ); + + if( hEvent == NULL ) + { + /* ERROR */ + Trace( "ERROR:%lu:OpenEventW() call failed\n", GetLastError() ); + result = FAIL; + goto parentwait; + } + + /* set the event -- should take effect in the child process */ + if( ! SetEvent( hEvent ) ) + { + /* ERROR */ + Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() ); + result = FAIL; + } + +parentwait: + /* close the event handle */ + if( ! CloseHandle( hEvent ) ) + { + /* ERROR */ + Fail( "ERROR:%lu:CloseHandle() call failed in child\n", + GetLastError()); + } + + /* terminate the PAL */ + PAL_TerminateEx(result); + + /* return success or failure */ + return result; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/test3.cpp new file mode 100644 index 0000000..c4edf22 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/test3.cpp @@ -0,0 +1,187 @@ +// 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. + +/*============================================================================= +** +** Source: test3.c +** +** Purpose: Test to ensure that OpenEventW() works when +** opening an event created by another process. This test +** program launches a child process which creates a +** named, initially-unset event. The child waits up to +** 10 seconds for the parent process to open that event +** and set it, and returns PASS if the event was set or FAIL +** otherwise. The parent process checks the return value +** from the child to verify that the opened event was +** properly used across processes. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** ZeroMemory +** GetCurrentDirectoryW +** CreateProcessW +** WaitForSingleObject +** GetExitCodeProcess +** GetLastError +** strlen +** strncpy +** +** +**===========================================================================*/ +#include + +#define TIMEOUT 60000 + +int __cdecl main( int argc, char **argv ) +{ + BOOL ret = FAIL; + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + DWORD dwExitCode; + + DWORD dwRet = 0; + HANDLE hEvent = NULL; + WCHAR wcName[] = {'P','A','L','R','o','c','k','s','\0'}; + LPWSTR lpName = wcName; + char lpCommandLine[MAX_PATH] = ""; + + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + /* zero our process and startup info structures */ + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof( si ); + ZeroMemory( &pi, sizeof(pi) ); + + /* create an event which we can use with SetEvent */ + hEvent = CreateEventW( lpEventAttributes, + TRUE, /* manual reset */ + FALSE, /* unsignalled */ + lpName ); + + if( hEvent == NULL ) + { + /* ERROR */ + Fail( "ERROR:%lu:CreateEventW() call failed in child\n", + GetLastError()); + } + + ZeroMemory( lpCommandLine, MAX_PATH ); + if ( sprintf_s( lpCommandLine, MAX_PATH-1, "childprocess ") < 0 ) + { + Fail ("Error: Insufficient lpCommandline for\n"); + } + + /* launch the child process */ + if( !CreateProcess( NULL, /* module name to execute */ + lpCommandLine, /* command line */ + NULL, /* process handle not */ + /* inheritable */ + NULL, /* thread handle not */ + /* inheritable */ + FALSE, /* handle inheritance */ + CREATE_NEW_CONSOLE, /* dwCreationFlags */ + NULL, /* use parent's environment */ + NULL, /* use parent's starting */ + /* directory */ + &si, /* startup info struct */ + &pi ) /* process info struct */ + ) + { + Fail( "ERROR:%lu:CreateProcess call failed\n", + GetLastError() ); + } + + /* verify that the event is signalled by the child process */ + dwRet = WaitForSingleObject( hEvent, TIMEOUT ); + if( dwRet != WAIT_OBJECT_0 ) + { + ret = FAIL; + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + "expected WAIT_OBJECT_0\n", + dwRet ); + + goto cleanup; + + if( !CloseHandle( hEvent ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed in child\n", + GetLastError()); + } + goto cleanup; + } + + /* wait for the child process to complete */ + dwRet = WaitForSingleObject ( pi.hProcess, TIMEOUT ); + if( dwRet != WAIT_OBJECT_0 ) + { + ret = FAIL; + Trace( "ERROR:WaitForSingleObject() returned %lu, " + "expected %lu\n", + dwRet, + WAIT_OBJECT_0 ); + goto cleanup; + } + + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) + { + ret = FAIL; + Trace( "ERROR:%lu:GetExitCodeProcess call failed\n", + GetLastError() ); + goto cleanup; + } + + /* check for success */ + ret = (dwExitCode == PASS) ? PASS : FAIL; + +cleanup: + if( hEvent != NULL ) + { + if( ! CloseHandle ( hEvent ) ) + { + Trace( "ERROR:%lu:CloseHandle call failed on event handle\n", + GetLastError() ); + ret = FAIL; + } + } + + + /* close process and thread handle */ + if( ! CloseHandle ( pi.hProcess ) ) + { + Trace( "ERROR:%lu:CloseHandle call failed on process handle\n", + GetLastError() ); + ret = FAIL; + } + + if( ! CloseHandle ( pi.hThread ) ) + { + Trace( "ERROR:%lu:CloseHandle call failed on thread handle\n", + GetLastError() ); + ret = FAIL; + } + + /* output a convenient error message and exit if we failed */ + if( ret == FAIL ) + { + Fail( "test failed\n" ); + } + + + /* terminate the PAL */ + PAL_Terminate(); + + /* return success */ + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/testinfo.dat new file mode 100644 index 0000000..96b2c06 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test3/testinfo.dat @@ -0,0 +1,21 @@ +# 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. + +Version = 1.0 +Section = threading +Function = OpenEventW +Name = Test for OpenEventW +TYPE = DEFAULT +EXE1 = test3 +EXE2 = childprocess +Description += Purpose: Test to ensure that OpenEventW() works when += opening an event created by another process. This test += program launches a child process which creates a += named, initially-unset event. The child waits up to += 10 seconds for the parent process to open that event += and set it, and returns PASS if the event was set or FAIL += otherwise. The parent process checks the return value += from the child to verify that the opened event was += properly used across processes. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test4/CMakeLists.txt new file mode 100644 index 0000000..5c727e3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_openeventw_test4 + ${SOURCES} +) + +add_dependencies(paltest_openeventw_test4 coreclrpal) + +target_link_libraries(paltest_openeventw_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test4/test4.cpp new file mode 100644 index 0000000..ae657a0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test4/test4.cpp @@ -0,0 +1,112 @@ +// 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. + +/*============================================================================= +** +** Source: test4.c +** +** Purpose: Positive test for OpenEventW. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateEvent +** CloseHandle +** WaitForSingleObject +** +** Purpose: +** +** Test to ensure proper operation of the OpenEventW() +** API by trying to open an event with a name that is +** already taken by a non-event object. +** +** +**===========================================================================*/ +#include + + + +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + BOOL bRet = PASS; + DWORD dwLastError = 0; + HANDLE hMutex = NULL; + HANDLE hTestEvent = NULL; + LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL; + BOOL bInitialState = TRUE; + WCHAR wcName[] = {'I','m','A','M','u','t','e','x','\0'}; + LPWSTR lpName = wcName; + + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + /* create a mutex object */ + hMutex = CreateMutexW( lpSecurityAttributes, + bInitialState, + lpName ); + + if( hMutex == NULL ) + { + /* ERROR */ + Fail( "ERROR:%lu:CreateMutexW() call failed\n", GetLastError() ); + } + + /* open a new handle to our event */ + hTestEvent = OpenEventW(EVENT_ALL_ACCESS, /* we want all rights */ + FALSE, /* no inherit */ + lpName ); + + if( hTestEvent != NULL ) + { + /* ERROR */ + Trace( "ERROR:OpenEventW() call succeeded against a named " + "mutex, should have returned NULL\n" ); + if( ! CloseHandle( hTestEvent ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed \n", GetLastError() ); + } + bRet = FAIL; + } + else + { + dwLastError = GetLastError(); + if( dwLastError != ERROR_INVALID_HANDLE ) + { + /* ERROR */ + Trace( "ERROR:OpenEventW() call failed against a named " + "mutex, but returned an unexpected result: %lu\n", + dwLastError ); + bRet = FAIL; + } + } + + + /* close the mutex handle */ + if( ! CloseHandle( hMutex ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed \n", GetLastError() ); + bRet = FAIL; + } + + + /* fail here if we weren't successful */ + if( bRet == FAIL ) + { + Fail( "" ); + } + + + /* PAL termination */ + PAL_Terminate(); + + /* return success or failure */ + return PASS; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test4/testinfo.dat new file mode 100644 index 0000000..1b3f2d8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test4/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = OpenEventW +Name = Negative test for OpenEventW +TYPE = DEFAULT +EXE1 = test4 +Description += Test to ensure proper operation of the OpenEventW() += API by trying to open an event with a name that is += already taken by a non-event object. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test5/CMakeLists.txt new file mode 100644 index 0000000..cd4b611 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_openeventw_test5 + ${SOURCES} +) + +add_dependencies(paltest_openeventw_test5 coreclrpal) + +target_link_libraries(paltest_openeventw_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test5/test5.cpp new file mode 100644 index 0000000..43b5857 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test5/test5.cpp @@ -0,0 +1,197 @@ +// 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. + +/*============================================================================= +** +** Source: test5.c +** +** Purpose: Positive test for OpenEventW. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateEvent +** CloseHandle +** WaitForSingleObject +** +** Purpose: +** +** Test to ensure proper operation of the OpenEventW() +** API by creating a new named event with CreateEventA() +** and verifying that it can be opened with OpenEventW(). +** It should be possible to use the event handles +** interchangeably, we test by setting the event with the +** original handle and waiting on it with the new one, +** then resetting it with the new one and waiting +** on it with the original one. +** +** +**===========================================================================*/ +#include + + + +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + BOOL ret = FAIL; + DWORD dwRet = 0; + HANDLE hEvent = NULL; + HANDLE hTestEvent = NULL; + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + BOOL bManualReset = TRUE; + BOOL bInitialState = FALSE; + LPSTR lpNameA = "ShakeIt"; + WCHAR wcName[] = {'S','h','a','k','e','I','t','\0'}; + LPWSTR lpNameW = wcName; + + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + + /* create an event which we can use with SetEvent */ + hEvent = CreateEventA( lpEventAttributes, + bManualReset, + bInitialState, + lpNameA ); + + if( hEvent == NULL ) + { + /* ERROR */ + Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + } + + /* open a new handle to our event */ + hTestEvent = OpenEventW(EVENT_ALL_ACCESS, /* we want all rights */ + FALSE, /* no inherit */ + lpNameW ); + + if( hTestEvent == NULL ) + { + /* ERROR */ + Trace( "ERROR:%lu:OpenEventW() call failed\n", GetLastError() ); + goto cleanup; + } + + /* verify that the event isn't signalled yet by waiting on both */ + /* handles to the event object */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + goto cleanup; + } + + dwRet = WaitForSingleObject( hTestEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + goto cleanup; + } + + + /* set the event using the original handle */ + if( ! SetEvent( hEvent ) ) + { + /* ERROR */ + Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() ); + goto cleanup; + } + + /* verify that the event is signalled by waiting on both handles */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_OBJECT_0 ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_OBJECT_0\n", + dwRet ); + goto cleanup; + } + + dwRet = WaitForSingleObject( hTestEvent, 0 ); + if( dwRet != WAIT_OBJECT_0 ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_OBJECT_0\n", + dwRet ); + goto cleanup; + } + + /* reset the event using the new handle */ + if( ! ResetEvent( hTestEvent ) ) + { + /* ERROR */ + Trace( "ERROR:%lu:ResetEvent() call failed\n", GetLastError() ); + goto cleanup; + } + + /* verify that the event isn't signalled by waiting on both handles */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + goto cleanup; + } + + dwRet = WaitForSingleObject( hTestEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + goto cleanup; + } + + + /* test was successful */ + ret = PASS; + + +cleanup: + /* close the new event handle */ + if( hTestEvent != NULL ) + { + if( ! CloseHandle( hTestEvent ) ) + { + ret = FAIL; + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + } + + /* close the original event handle */ + if( ! CloseHandle( hEvent ) ) + { + ret = FAIL; + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + + /* failure message */ + if( ret != PASS ) + { + Fail( "Test failed\n" ); + } + + + /* PAL termination */ + PAL_Terminate(); + + /* return success or failure */ + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test5/testinfo.dat new file mode 100644 index 0000000..f5af943 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenEventW/test5/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = threading +Function = OpenEventW +Name = Positive test for OpenEventW +TYPE = DEFAULT +EXE1 = test5 +Description += Test to ensure proper operation of the OpenEventW() += API by creating a new named event with CreateEventA() += and verifying that it can be opened with OpenEventW(). += It should be possible to use the event handles += interchangeably, we test by setting the event with the += original handle and waiting on it with the new one, += then resetting it with the new one and waiting += on it with the original one. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/CMakeLists.txt new file mode 100644 index 0000000..2066846 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + test1.cpp +) + +add_executable(paltest_openprocess_test1 + ${TESTSOURCES} +) + +add_dependencies(paltest_openprocess_test1 coreclrpal) + +target_link_libraries(paltest_openprocess_test1 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + childProcess.cpp +) + +add_executable(paltest_openprocess_test1_child + ${HELPERSOURCES} +) + +add_dependencies(paltest_openprocess_test1_child coreclrpal) + +target_link_libraries(paltest_openprocess_test1_child + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/childProcess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/childProcess.cpp new file mode 100644 index 0000000..9ef0743 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/childProcess.cpp @@ -0,0 +1,75 @@ +// 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. + +/*============================================================ +** +** Source: childprocess.c +** +** Purpose: Test to ensure OpenProcess works properly. +** All this program does is return a predefined value. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateMutexW +** WaitForSingleObject +** CloseHandle +** +** +**=========================================================*/ + +#include +#include "myexitcode.h" + + +int __cdecl main( int argc, char **argv ) +{ + HANDLE hMutex; + WCHAR wszMutexName[] = { 'T','E','S','T','1','\0' }; + DWORD dwRet; + int i; + + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + /* open a mutex to synchronize with the parent process */ + hMutex = CreateMutexW( NULL, FALSE, wszMutexName ); + if( hMutex == NULL ) + { + Fail( "ERROR:%lu:CreateMutex() call failed\r\n", GetLastError() ); + } + + /* acquire the mutex lock */ + dwRet = WaitForSingleObject( hMutex, 10000 ); + if( dwRet != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject() returned %lu, " + "expected WAIT_OBJECT_0", + dwRet ); + if( ! CloseHandle( hMutex ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + Fail( "test failed\n" ); + } + + + /* simulate some activity */ + for( i=0; i<50000; i++ ) + ; + + /* close our mutex handle */ + if( ! CloseHandle( hMutex ) ) + { + Fail( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + + /* terminate the PAL */ + PAL_Terminate(); + + /* return the predefined exit code */ + return TEST_EXIT_CODE; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/myexitcode.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/myexitcode.h new file mode 100644 index 0000000..66b8f43 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/myexitcode.h @@ -0,0 +1,14 @@ +// 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. + +/*============================================================================ +** +** Source: myexitcode.h +** +** Purpose: Define an exit code. +** +** +**==========================================================================*/ + +#define TEST_EXIT_CODE 317 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/test1.cpp new file mode 100644 index 0000000..d0f9019 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/test1.cpp @@ -0,0 +1,282 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure OpenProcess works properly. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** ZeroMemory +** GetCurrentDirectoryW +** CreateProcessW +** WaitForSingleObject +** CreateMutexW +** ReleaseMutex +** CloseHandle +** GetLastError +** strlen +** strncpy +** +** +**===========================================================================*/ +#include +#include "myexitcode.h" + + +static const char* rgchPathDelim = "\\"; + + +int +mkAbsoluteFilename( LPSTR dirName, + DWORD dwDirLength, + LPCSTR fileName, + DWORD dwFileLength, + LPSTR absPathName ) +{ + DWORD sizeDN, sizeFN, sizeAPN; + + sizeDN = strlen( dirName ); + sizeFN = strlen( fileName ); + sizeAPN = (sizeDN + 1 + sizeFN + 1); + + /* ensure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */ + if( sizeAPN > _MAX_PATH ) + { + return ( 0 ); + } + + strncpy( absPathName, dirName, dwDirLength +1 ); + strncpy( absPathName, rgchPathDelim, 2 ); + strncpy( absPathName, fileName, dwFileLength +1 ); + + return (sizeAPN); + +} + + +int __cdecl main( int argc, char **argv ) + +{ + const char* rgchChildFile = "childprocess"; + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + DWORD dwError; + DWORD dwExitCode; + DWORD dwFileLength; + DWORD dwDirLength; + DWORD dwSize; + DWORD dwRet; + + HANDLE hMutex; + HANDLE hChildProcess; + + char rgchDirName[_MAX_DIR]; + char absPathBuf[_MAX_PATH]; + char* rgchAbsPathName; + + BOOL ret = FAIL; + BOOL bChildDone = FALSE; + WCHAR wszMutexName[] = { 'T','E','S','T','1','\0' }; + + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + /* create a mutex to synchronize with the child process */ + hMutex = CreateMutexW( NULL, TRUE, wszMutexName ); + if( hMutex == NULL ) + { + Fail( "ERROR:%lu:CreateMutex() call failed\r\n", GetLastError() ); + } + + /* zero our process and startup info structures */ + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof( si ); + ZeroMemory( &pi, sizeof(pi) ); + + /* build the absolute path to the child process */ + rgchAbsPathName = &absPathBuf[0]; + dwFileLength = strlen( rgchChildFile ); + + dwDirLength = GetCurrentDirectory( _MAX_PATH, rgchDirName ); + if( dwDirLength == 0 ) + { + dwError = GetLastError(); + if( ReleaseMutex( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() ); + } + if( CloseHandle( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + Fail( "GetCurrentDirectory call failed with error code %d\n", + dwError ); + } + + dwSize = mkAbsoluteFilename( rgchDirName, + dwDirLength, + rgchChildFile, + dwFileLength, + rgchAbsPathName ); + if( dwSize == 0 ) + { + if( ReleaseMutex( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() ); + } + if( CloseHandle( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + Fail( "Palsuite Code: mkAbsoluteFilename() call failed. Could ", + "not build absolute path name to file\n. Exiting.\n" ); + } + + /* launch the child process */ + if( !CreateProcess( NULL, /* module name to execute */ + rgchAbsPathName, /* command line */ + NULL, /* process handle not */ + /* inheritable */ + NULL, /* thread handle not */ + /*inheritable */ + FALSE, /* handle inheritance */ + CREATE_NEW_CONSOLE, /* dwCreationFlags */ + NULL, /* use parent's environment */ + NULL, /* use parent's starting */ + /* directory */ + &si, /* startup info struct */ + &pi ) /* process info struct */ + ) + { + dwError = GetLastError(); + if( ReleaseMutex( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() ); + } + if( CloseHandle( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + Fail( "CreateProcess call failed with error code %d\n", + dwError ); + } + + /* open another handle to the child process */ + hChildProcess = OpenProcess( PROCESS_ALL_ACCESS, /* access */ + FALSE, /* inheritable */ + pi.dwProcessId /* process id */ + ); + if( hChildProcess == NULL ) + { + dwError = GetLastError(); + if( ReleaseMutex( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() ); + } + Trace( "ERROR:%lu:OpenProcess call failed\n", dwError ); + goto cleanup2; + } + + /* release the mutex so the child can proceed */ + if( ReleaseMutex( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() ); + goto cleanup; + } + + /* wait for the child process to complete, using the new handle */ + dwRet = WaitForSingleObject( hChildProcess, 10000 ); + if( dwRet != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject call returned %lu, " + "expected WAIT_OBJECT_0", + dwRet ); + goto cleanup; + } + + /* remember that we waited until the child was finished */ + bChildDone = TRUE; + + /* check the exit code from the process -- this is a bit of an */ + /* extra verification that we opened the correct process handle */ + if( ! GetExitCodeProcess( hChildProcess, &dwExitCode ) ) + { + Trace( "ERROR:%lu:GetExitCodeProcess call failed\n", GetLastError() ); + goto cleanup; + } + + /* verification */ + if( (dwExitCode & 0xFF) != (TEST_EXIT_CODE & 0xFF) ) + { + Trace( "GetExitCodeProcess returned an incorrect exit code %d, " + "expected value is %d\n", + (dwExitCode & 0xFF), + (TEST_EXIT_CODE & 0xFF)); + goto cleanup; + } + + /* success if we get here */ + ret = PASS; + + +cleanup: + /* wait on the child process to complete if necessary */ + if( ! bChildDone ) + { + dwRet = WaitForSingleObject( hChildProcess, 10000 ); + if( dwRet != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject call returned %lu, " + "expected WAIT_OBJECT_0", + dwRet ); + ret = FAIL; + } + } + + /* close all our handles */ + if( CloseHandle ( hChildProcess ) == 0 ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + ret = FAIL; + } + +cleanup2: + if( CloseHandle ( pi.hProcess ) == 0 ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + ret = FAIL; + } + if( CloseHandle ( pi.hThread ) == 0 ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + ret = FAIL; + } + if( CloseHandle( hMutex ) == 0 ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + ret = FAIL; + } + + if( ret == FAIL ) + { + Fail( "test failed\n" ); + } + + + + /* terminate the PAL */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/testinfo.dat new file mode 100644 index 0000000..dd6b2c0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/OpenProcess/test1/testinfo.dat @@ -0,0 +1,19 @@ +# 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. + +Version = 1.0 +Section = threading +Function = OpenProcess +Name = Test for OpenProcess +TYPE = DEFAULT +EXE1 = test1 +EXE2 = childprocess +Description += Test to ensure proper operation of the OpenProcess API. += The test launches a trivial child process, then opens += a handle to it using OpenProcess. It uses that handle += to wait for the child process to terminate, and then += checks the exit code of the child process in order to += verify that it was in fact a handle to the correct += process. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueryThreadCycleTime/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueryThreadCycleTime/CMakeLists.txt new file mode 100644 index 0000000..e46df57 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueryThreadCycleTime/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test1) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/CMakeLists.txt new file mode 100644 index 0000000..df6b876 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_querythreadcycletime_test1 + ${SOURCES} +) + +add_dependencies(paltest_querythreadcycletime_test1 coreclrpal) + +target_link_libraries(paltest_querythreadcycletime_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.cpp new file mode 100644 index 0000000..ea50042 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.cpp @@ -0,0 +1,98 @@ +// 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. + +/*============================================================ +** +** Source: +** +** Source : test1.c +** +** Purpose: Test for QueryThreadCycleTime() function +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) { + int ret = FAIL; + + //Test is failing unreliably, so for now we always return pass. + if (TRUE){ + ret = PASS; + goto EXIT; + } + { + LONG64 Actual, Expected, Delta = 850000000; + Actual = 0; + Expected = 0; + const LONG64 MSEC_TO_NSEC = 1000000; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + HANDLE cThread = GetCurrentThread(); + + int i; + /* Take 2000 tiny measurements */ + for (i = 0; i < 2000; i++){ + ULONG64 FirstCount, SecondCount; + LONG64 Init; + + Sleep(1); + + /* Grab a FirstCount, then loop for a bit to make the clock increase */ + if (!QueryThreadCycleTime(cThread, (PULONG64)&FirstCount)) + { + Fail("ERROR: QueryThreadCycleTime returned failure.\n"); + } + + LONG64 x; + /* Init is in milliseconds, so we will convert later */ + Init = (LONG64)GetTickCount(); + x = Init + 3; + volatile int counter; + do { + for (counter = 0; counter < 100000; counter++) + { + // spin to consume CPU time + } + + } while (x > GetTickCount()); + Expected += (GetTickCount() - Init) * MSEC_TO_NSEC; + /* Get a second count */ + if (!QueryThreadCycleTime(cThread, (PULONG64)&SecondCount)) + { + Fail("ERROR: QueryThreadCycleTime returned failure.\n"); + } + + LONG64 trial = (LONG64)SecondCount - (LONG64)FirstCount; + if (trial < 0){ + printf("Negative value %llu measured", trial); + } + Actual += (trial); + + } + + + + if(llabs(Expected - Actual) > Delta) + { + Fail("ERROR: The measured time (%llu millisecs) was not within Delta %llu " + "of the expected time (%llu millisecs).\n", + (Actual / MSEC_TO_NSEC), (Delta / MSEC_TO_NSEC), (Expected / MSEC_TO_NSEC)); + } + //printf("%llu, %llu\n", Expected, Actual); + PAL_Terminate(); + ret = PASS; + } +EXIT: + return ret; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/CMakeLists.txt new file mode 100644 index 0000000..7cd88f8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/CMakeLists.txt @@ -0,0 +1,8 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) +add_subdirectory(test7) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test1/CMakeLists.txt new file mode 100644 index 0000000..c07fcfa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_queueuserapc_test1 + ${SOURCES} +) + +add_dependencies(paltest_queueuserapc_test1 coreclrpal) + +target_link_libraries(paltest_queueuserapc_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test1/test1.cpp new file mode 100644 index 0000000..3637897 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test1/test1.cpp @@ -0,0 +1,313 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that APCs sent to a thread in an alertable state via +** QueueUserAPC are executed in FIFO order. Also tests that the APC +** function is executed within the context of the correct thread and +** that the dwData parameter gets sent correctly. +** +** +**===================================================================*/ + +#include + +const int ChildThreadSleepTime = 2000; +const int InterruptTime = 1000; + +VOID PALAPI APCFuncA(ULONG_PTR dwParam); +VOID PALAPI APCFuncB(ULONG_PTR dwParam); +VOID PALAPI APCFuncC(ULONG_PTR dwParam); +VOID PALAPI APCFuncD(ULONG_PTR dwParam); +DWORD PALAPI SleeperProc(LPVOID lpParameter); + +const char *ExpectedResults = "A0B0C0D0A1B1C1D1A2B2C2D2A3B3C3D3"; +char ResultBuffer[256]; +char *ResultPtr; +DWORD ChildThread; + +/* synchronization events */ +static HANDLE hSyncEvent1 = NULL; +static HANDLE hSyncEvent2 = NULL; + +/* thread result because we have no GetExitCodeThread() API */ +BOOL bThreadResult = FAIL; + +int __cdecl main (int argc, char **argv) +{ + HANDLE hThread = NULL; + int ret; + int i,j; + BOOL bResult = FAIL; + + PAPCFUNC APCFuncs[] = + { + APCFuncA, + APCFuncB, + APCFuncC, + APCFuncD, + }; + + /* initialize the PAL */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + ResultPtr = ResultBuffer; + + /* create a pair of synchronization events to coordinate our threads */ + hSyncEvent1 = CreateEvent( NULL, FALSE, FALSE, NULL ); + if( hSyncEvent1 == NULL ) + { + Trace( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + goto cleanup; + } + + hSyncEvent2 = CreateEvent( NULL, FALSE, FALSE, NULL ); + if( hSyncEvent2 == NULL ) + { + Trace( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + goto cleanup; + } + + /* create a child thread which will call SleepEx */ + hThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)SleeperProc, + 0, + 0, + &ChildThread); + + if( hThread == NULL ) + { + Trace( "ERROR:%lu:CreateThread() call failed\n", + GetLastError()); + goto cleanup; + } + + + /* wait on our synchronization event to ensure the thread is running */ + ret = WaitForSingleObject( hSyncEvent1, 20000 ); + if( ret != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject() returned %lu, " + "expected WAIT_OBJECT_0\n", + ret ); + goto cleanup; + } + + + /* queue our user APC functions on the thread */ + for (i=0; i<4; i++) + { + for (j=0; j + +const int ChildThreadSleepTime = 2000; +const int InterruptTime = 1000; + +DWORD ChildThread; +BOOL InAPC; + +/* synchronization events */ +static HANDLE hSyncEvent1 = NULL; +static HANDLE hSyncEvent2 = NULL; + +/* thread result because we have no GetExitCodeThread() API */ +static BOOL bThreadResult = FAIL; + + +VOID PALAPI APCFunc(ULONG_PTR dwParam) +{ + InAPC = TRUE; +} + +DWORD PALAPI SleeperProc(LPVOID lpParameter) +{ + DWORD ret; + + /* signal the main thread that we're ready to proceed */ + if( ! SetEvent( hSyncEvent1 ) ) + { + Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() ); + bThreadResult = FAIL; + goto done; + } + + /* wait for notification from the main thread */ + ret = WaitForSingleObject( hSyncEvent2, 20000 ); + if( ret != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject() returned %lu, " + "expected WAIT_OBJECT_0\n", + ret ); + bThreadResult = FAIL; + goto done; + } + + /* call our sleep function */ + Sleep( ChildThreadSleepTime ); + + /* success if we reach here */ + bThreadResult = PASS; + + +done: + + /* signal the main thread that we're finished */ + if( ! SetEvent( hSyncEvent1 ) ) + { + Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() ); + bThreadResult = FAIL; + } + + /* return success or failure */ + return bThreadResult; +} + + +int __cdecl main (int argc, char **argv) +{ + /* local variables */ + HANDLE hThread = 0; + int ret; + BOOL bResult = FAIL; + + /* initialize the PAL */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + InAPC = FALSE; + + /* create a pair of synchronization events to coordinate our threads */ + hSyncEvent1 = CreateEvent( NULL, FALSE, FALSE, NULL ); + if( hSyncEvent1 == NULL ) + { + Trace( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + goto cleanup; + } + + hSyncEvent2 = CreateEvent( NULL, FALSE, FALSE, NULL ); + if( hSyncEvent2 == NULL ) + { + Trace( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + goto cleanup; + } + + /* create a child thread */ + hThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)SleeperProc, + 0, + 0, + &ChildThread); + + if (hThread == NULL) + { + Trace( "ERROR:%lu:CreateThread() call failed\n", + GetLastError()); + goto cleanup; + } + + + /* wait on our synchronization event to ensure the thread is running */ + ret = WaitForSingleObject( hSyncEvent1, 20000 ); + if( ret != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject() returned %lu, " + "expected WAIT_OBJECT_0\n", + ret ); + goto cleanup; + } + + /* queue a user APC on the child thread */ + ret = QueueUserAPC(APCFunc, hThread, 0); + if (ret == 0) + { + Trace( "ERROR:%lu:QueueUserAPC() call failed\n", + GetLastError()); + goto cleanup; + } + + /* signal the child thread to continue */ + if( ! SetEvent( hSyncEvent2 ) ) + { + Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() ); + goto cleanup; + } + + /* wait on our synchronization event to ensure the other thread is done */ + ret = WaitForSingleObject( hSyncEvent1, 20000 ); + if( ret != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject() returned %lu, " + "expected WAIT_OBJECT_0\n", + ret ); + goto cleanup; + } + + /* check that the thread executed successfully */ + if( bThreadResult == FAIL ) + { + goto cleanup; + } + + + /* check whether the APC function was executed */ + if( InAPC ) + { + Trace( "FAIL:APC function was executed but shouldn't have been\n" ); + goto cleanup; + } + + /* success if we reach here */ + bResult = PASS; + + +cleanup: + /* wait for the other thread to finish */ + if( hThread != NULL ) + { + ret = WaitForSingleObject( hThread, INFINITE ); + if (ret == WAIT_FAILED) + { + Trace( "ERROR:%lu:WaitForSingleObject() returned %lu, " + "expected WAIT_OBJECT_0\n", + ret ); + bResult = FAIL; + } + } + + /* close our synchronization handles */ + if( hSyncEvent1 != NULL ) + { + if( ! CloseHandle( hSyncEvent1 ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + bResult = FAIL; + } + } + + if( hSyncEvent2 != NULL ) + { + if( ! CloseHandle( hSyncEvent2 ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + bResult = FAIL; + } + } + + if( bResult == FAIL ) + { + Fail( "test failed\n" ); + } + + + /* terminate the PAL */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test2/testinfo.dat new file mode 100644 index 0000000..42d942d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = threading +Function = QueueUserAPC +Name = Test #2 for QueueUserAPC +TYPE = DEFAULT +EXE1 = test2 +Description +=Tests that APCs are not executed if a thread never enters an +=alertable state after they are queued. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test3/CMakeLists.txt new file mode 100644 index 0000000..0cacac7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_queueuserapc_test3 + ${SOURCES} +) + +add_dependencies(paltest_queueuserapc_test3 coreclrpal) + +target_link_libraries(paltest_queueuserapc_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test3/test3.cpp new file mode 100644 index 0000000..933f41a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test3/test3.cpp @@ -0,0 +1,33 @@ +// 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. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Tests how QueueUserAPC handles an invalid thread. +** +** +**===================================================================*/ + +#include + +int __cdecl main (int argc, char **argv) +{ + int ret; + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + ret = QueueUserAPC(NULL, NULL, 0); + if (ret != 0) + { + Fail("QueueUserAPC passed with an invalid thread!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test3/testinfo.dat new file mode 100644 index 0000000..0b96349 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test3/testinfo.dat @@ -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. + +Version = 1.0 +Section = threading +Function = QueueUserAPC +Name = Test #3 for QueueUserAPC +TYPE = DEFAULT +EXE1 = test3 +Description +=Tests how QueueUserAPC handles an invalid thread. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test4/CMakeLists.txt new file mode 100644 index 0000000..a467304 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_queueuserapc_test4 + ${SOURCES} +) + +add_dependencies(paltest_queueuserapc_test4 coreclrpal) + +target_link_libraries(paltest_queueuserapc_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test4/test4.cpp new file mode 100644 index 0000000..c28709d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test4/test4.cpp @@ -0,0 +1,72 @@ +// 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. + +/*============================================================================= +** +** Source: test4.c +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** GetCurrentThread +** SleepEx +** +** Purpose: +** +** Test to ensure proper operation of the QueueUserAPC() +** API by trying to queue APC functions on the current +** thread. +** +** +**===========================================================================*/ +#include + + +static BOOL bAPCExecuted = FALSE; + +VOID PALAPI APCFunc( ULONG_PTR dwParam ) +{ + bAPCExecuted = TRUE; +} + +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + HANDLE hThread = NULL; + DWORD ret; + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + /* get the current thread */ + hThread = GetCurrentThread(); + ret = QueueUserAPC( APCFunc, hThread, 0 ); + if( ret == 0 ) + { + Fail( "ERROR:%lu:QueueUserAPC call failed\n", GetLastError() ); + } + + /* call SleepEx() to put the thread in an alertable state */ + ret = SleepEx( 2000, TRUE ); + if( ret != WAIT_IO_COMPLETION ) + { + Fail( "ERROR:Expected sleep to return WAIT_IO_COMPLETION, got %lu\n", + ret ); + } + + /* check that the APC function was executed */ + if( bAPCExecuted == FALSE ) + { + Fail( "ERROR:APC function was not executed\n" ); + } + + /* PAL termination */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test4/testinfo.dat new file mode 100644 index 0000000..cd7b7c2 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test4/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = QueueUserAPC +Name = Positive test for QueueUserAPC +TYPE = DEFAULT +EXE1 = test4 +Description += Test to ensure proper operation of the QueueUserAPC() += API by trying to queue APC functions on the current += thread. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test5/CMakeLists.txt new file mode 100644 index 0000000..0756fbd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test5/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test5.cpp +) + +add_executable(paltest_queueuserapc_test5 + ${SOURCES} +) + +add_dependencies(paltest_queueuserapc_test5 coreclrpal) + +target_link_libraries(paltest_queueuserapc_test5 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test5/test5.cpp new file mode 100644 index 0000000..3d26a55 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test5/test5.cpp @@ -0,0 +1,200 @@ +// 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. + +/*============================================================================= +** +** Source: test5.c +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateEvent +** SetEvent +** CreateThread +** ResumeThread +** WaitForSingleObject +** CloseHandle +** +** Purpose: +** +** Test to ensure proper operation of the QueueUserAPC() +** API by trying to queue and activate APC functions on +** a thread that was created suspended, prior to resuming +** it. We're verifying the following behavior: +** +** "If an application queues an APC before the thread begins +** running, the thread begins by calling the APC function. +** After the thread calls an APC function, it calls the APC +** functions for all APCs in its APC queue." +** +** +**===========================================================================*/ +#include + + +static HANDLE hEvent = NULL; +static BOOL bAPCExecuted = FALSE; + +VOID PALAPI APCFunc( ULONG_PTR dwParam ) +{ + bAPCExecuted = TRUE; +} + +/** + * ThreadFunc + * + * Dummy thread function for APC queuing. + */ +DWORD PALAPI ThreadFunc( LPVOID param ) +{ + DWORD ret = 0; + + /* alertable wait until the global event is signalled */ + ret = WaitForSingleObject( hEvent, INFINITE ); + if( ret != WAIT_OBJECT_0 ) + { + Fail( "ERROR:WaitForSingleObject() returned %lu, " + "expected WAIT_OBJECT_0\n", + ret ); + } + + return 0; +} + + +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + HANDLE hThread = NULL; + DWORD IDThread; + DWORD ret; + BOOL bResult = FALSE; + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + /* create an event for the other thread to wait on */ + hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); + if( hEvent == NULL ) + { + Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + } + + /* run another dummy thread to cause notification of the library */ + hThread = CreateThread( NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */ + (LPVOID) NULL, /* pass thread index as */ + /* function argument */ + CREATE_SUSPENDED, /* create suspended */ + &IDThread ); /* returns thread id */ + + /* Check the return value for success. */ + if( hThread == NULL ) + { + /* error creating thread */ + Trace( "ERROR:%lu:CreateThread call failed\n", GetLastError() ); + if( ! CloseHandle( hEvent ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + Fail( "test failed\n" ); + } + + /* queue our APC on the suspended thread */ + ret = QueueUserAPC( APCFunc, hThread, 0 ); + if( ret == 0 ) + { + Fail( "ERROR:%lu:QueueUserAPC call failed\n", GetLastError() ); + } + + /* wait on the suspended thread */ + ret = WaitForSingleObject( hThread, 2000 ); + if( ret != WAIT_TIMEOUT ) + { + Trace( "ERROR:WaitForSingleObject() returned %lu, " + "expected WAIT_TIMEOUT\n", + ret ); + goto cleanup; + } + + /* verify that the APC function was not executed */ + if( bAPCExecuted == TRUE ) + { + Trace( "ERROR:APC function was executed for a suspended thread\n" ); + goto cleanup; + } + + /* Resume the suspended thread */ + ResumeThread( hThread ); + + /* do another wait on the resumed thread */ + ret = WaitForSingleObject( hThread, 2000 ); + + /* verify that we got a WAIT_TIMEOUT result */ + if( ret != WAIT_TIMEOUT ) + { + Trace( "ERROR:WaitForSingleObject() returned %lu, " + "expected WAIT_TIMEOUT\n", + ret ); + goto cleanup; + } + + /* check that the APC function was actually executed */ + if( bAPCExecuted == FALSE ) + { + Trace( "ERROR:APC function was not executed\n" ); + goto cleanup; + } + + /* set the success flag */ + bResult = PASS; + +cleanup: + /* signal the event so the other thread will exit */ + if( ! SetEvent( hEvent ) ) + { + Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() ); + bResult = FAIL; + } + + /* close the global event handle */ + if( ! CloseHandle( hEvent ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + bResult = FAIL; + } + + /* wait on the other thread to complete */ + ret = WaitForSingleObject( hThread, 2000 ); + if( ret != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject() returned %lu, " + "expected WAIT_OBJECT_0\n", + ret ); + bResult = FAIL; + } + + /* close the thread handle */ + if( ! CloseHandle( hThread ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + bResult = FAIL; + } + + /* output final failure result for failure case */ + if( bResult == FAIL ) + { + Fail( "test failed\n" ); + } + + /* PAL termination */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test5/testinfo.dat new file mode 100644 index 0000000..f1775aa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test5/testinfo.dat @@ -0,0 +1,20 @@ +# 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. + +Version = 1.0 +Section = threading +Function = QueueUserAPC +Name = Positive test for QueueUserAPC +TYPE = DEFAULT +EXE1 = test5 +Description += Test to ensure proper operation of the QueueUserAPC() += API by trying to queue and activate APC functions on += a thread that was created suspended, prior to resuming += it. We're verifying the following behavior: += += "If an application queues an APC before the thread begins += running, the thread begins by calling the APC function. += After the thread calls an APC function, it calls the APC += functions for all APCs in its APC queue." diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test6/CMakeLists.txt new file mode 100644 index 0000000..d6c7a27 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test6.cpp +) + +add_executable(paltest_queueuserapc_test6 + ${SOURCES} +) + +add_dependencies(paltest_queueuserapc_test6 coreclrpal) + +target_link_libraries(paltest_queueuserapc_test6 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test6/test6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test6/test6.cpp new file mode 100644 index 0000000..e2e2464 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test6/test6.cpp @@ -0,0 +1,129 @@ +// 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. + +/*============================================================================= +** +** Source: test6.c +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateEvent +** SetEvent +** CreateThread +** ResumeThread +** WaitForMultipleObjectsEx +** CloseHandle +** +** Purpose: +** +** Test to ensure proper operation of the QueueUserAPC() +** API by trying to queue APC functions on a thread that +** has already terminated. +** +** +**===========================================================================*/ +#include + + +static BOOL bAPCExecuted = FALSE; + +VOID PALAPI APCFunc( ULONG_PTR dwParam ) +{ + bAPCExecuted = TRUE; +} + +/** + * ThreadFunc + * + * Dummy thread function for APC queuing. + */ +DWORD PALAPI ThreadFunc( LPVOID param ) +{ + int i; + + /* simulate some activity */ + for( i=0; i<250000; i++ ) + ; + + return 0; +} + + +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + HANDLE hThread = NULL; + DWORD IDThread; + DWORD ret; + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + /* run another dummy thread to cause notification of the library */ + hThread = CreateThread( NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */ + (LPVOID) NULL, /* pass thread index as */ + /* function argument */ + CREATE_SUSPENDED, /* create suspended */ + &IDThread ); /* returns thread id */ + + /* Check the return value for success. */ + if( hThread == NULL ) + { + /* error creating thread */ + Fail( "ERROR:%lu:CreateThread call failed\n", GetLastError() ); + } + + /* Resume the suspended thread */ + ResumeThread( hThread ); + + /* wait on the other thread to complete */ + ret = WaitForSingleObject( hThread, INFINITE ); + if( ret != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject() returned %lu, " + "expected WAIT_OBJECT_0\n", + ret ); + if( ! CloseHandle( hThread ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + Fail( "test failed\n" ); + } + + /* queue our APC on the finished thread */ + ret = QueueUserAPC( APCFunc, hThread, 0 ); + if( ret != 0 ) + { + Trace( "ERROR:QueueUserAPC call succeeded on a terminated thread\n" ); + if( ! CloseHandle( hThread ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + Fail( "test failed\n" ); + } + + if( ! CloseHandle( hThread ) ) + { + Fail( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + + /* dummy check that the APC function wasn't actually executed */ + if( bAPCExecuted != FALSE ) + { + Fail( "ERROR:APC function was executed\n" ); + } + + + /* PAL termination */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test6/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test6/testinfo.dat new file mode 100644 index 0000000..4d80618 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test6/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = QueueUserAPC +Name = Negative test for QueueUserAPC +TYPE = DEFAULT +EXE1 = test6 +Description += Test to ensure proper operation of the QueueUserAPC() += API by trying to queue APC functions on a thread that += has already terminated. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test7/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test7/CMakeLists.txt new file mode 100644 index 0000000..4bfc4d6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test7/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test7.cpp +) + +add_executable(paltest_queueuserapc_test7 + ${SOURCES} +) + +add_dependencies(paltest_queueuserapc_test7 coreclrpal) + +target_link_libraries(paltest_queueuserapc_test7 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test7/test7.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test7/test7.cpp new file mode 100644 index 0000000..54a6398 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test7/test7.cpp @@ -0,0 +1,253 @@ +// 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. + +/*============================================================================= +** +** Source: test7.c +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateEvent +** SetEvent +** CreateThread +** ResumeThread +** WaitForMultipleObjectsEx +** CloseHandle +** +** Purpose: +** +** Test to ensure proper operation of the QueueUserAPC() +** API by trying to queue an APC function on a thread and +** activating it with WaitForMultipleObjectsEx. +** +** +**===========================================================================*/ +#include + + +static HANDLE hSyncEvent = NULL; +static HANDLE hTestEvent = NULL; +static int nAPCExecuted = 0; +static BOOL bThreadResult = FALSE; + +VOID PALAPI APCFunc( ULONG_PTR dwParam ) +{ + ++nAPCExecuted; +} + +/** + * ThreadFunc + * + * Dummy thread function for APC queuing. + */ +DWORD PALAPI ThreadFunc( LPVOID param ) +{ + DWORD ret = 0; + + /* pessimism */ + bThreadResult = FALSE; + + /* set the sync event to notify the main thread */ + if( ! SetEvent( hSyncEvent ) ) + { + Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() ); + goto done; + } + + /* wait until the test event is signalled */ + ret = WaitForSingleObject( hTestEvent, INFINITE ); + if( ret != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject() returned %lu, " + "expected WAIT_OBJECT_0\n", + ret ); + goto done; + } + + /* now do an alertable wait on the same event, which is now + in an unsignalled state */ + ret = WaitForMultipleObjectsEx( 1, &hTestEvent, TRUE, 2000, TRUE ); + + /* verify that we got a WAIT_IO_COMPLETION result */ + if( ret != WAIT_IO_COMPLETION ) + { + Trace( "ERROR:WaitForMultipleObjectsEx returned %lu, " + "expected WAIT_IO_COMPLETION\n", + ret ); + goto done; + } + + /* set the event again */ + if( ! SetEvent( hTestEvent ) ) + { + Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() ); + goto done; + } + + /* do a non-alertable wait on the same event */ + ret = WaitForMultipleObjectsEx( 1, &hTestEvent, TRUE, INFINITE, FALSE ); + + /* verify that we got a WAIT_OBJECT_0 result */ + if( ret != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForMultipleObjectsEx returned %lu, " + "expected WAIT_OBJECT_0\n", + ret ); + goto done; + } + + /* success at this point */ + bThreadResult = TRUE; + + +done: + return bThreadResult; +} + + +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + HANDLE hThread = NULL; + DWORD IDThread; + DWORD ret; + BOOL bResult = FALSE; + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + /* create an auto-reset event for the other thread to wait on */ + hTestEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); + if( hTestEvent == NULL ) + { + Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + } + + /* create an auto-reset event for synchronization */ + hSyncEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); + if( hSyncEvent == NULL ) + { + Trace( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + if( ! CloseHandle( hTestEvent ) ) + { + Trace( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + } + Fail( "test failed\n" ); + } + + /* run another dummy thread to cause notification of the library */ + hThread = CreateThread( NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */ + (LPVOID) NULL, /* pass thread index as */ + /* function argument */ + CREATE_SUSPENDED, /* create suspended */ + &IDThread ); /* returns thread id */ + + /* Check the return value for success. */ + if( hThread == NULL ) + { + /* error creating thread */ + Trace( "ERROR:%lu:CreateThread call failed\n", GetLastError() ); + if( ! CloseHandle( hTestEvent ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + Fail( "test failed\n" ); + } + + /* Resume the suspended thread */ + ResumeThread( hThread ); + + /* wait until the other thread is ready to proceed */ + ret = WaitForSingleObject( hSyncEvent, 10000 ); + if( ret != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject returned %lu, " + "expected WAIT_OBJECT_0\n", + ret ); + goto cleanup; + } + + + /* now queue our APC on the test thread */ + ret = QueueUserAPC( APCFunc, hThread, 0 ); + if( ret == 0 ) + { + Trace( "ERROR:%lu:QueueUserAPC call failed\n", GetLastError() ); + goto cleanup; + } + + /* signal the test event so the other thread will proceed */ + if( ! SetEvent( hTestEvent ) ) + { + Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() ); + goto cleanup; + } + + /* wait on the other thread to complete */ + ret = WaitForSingleObject( hThread, INFINITE ); + if( ret != WAIT_OBJECT_0 ) + { + Trace( "ERROR:WaitForSingleObject() returned %lu, " + "expected WAIT_OBJECT_0\n", + ret ); + goto cleanup; + } + + /* check the result of the other thread */ + if( bThreadResult == FALSE ) + { + goto cleanup; + } + + /* check that the APC function was actually executed exactly one time */ + if( nAPCExecuted != 1 ) + { + Trace( "ERROR:APC function was executed %d times, " + "expected once\n", nAPCExecuted ); + goto cleanup; + } + + /* set the success flag */ + bResult = PASS; + + +cleanup: + /* close the global event handles */ + if( ! CloseHandle( hTestEvent ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + bResult = FAIL; + } + + if( ! CloseHandle( hSyncEvent ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + bResult = FAIL; + } + + /* close the thread handle */ + if( ! CloseHandle( hThread ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + bResult = FAIL; + } + + /* output final failure result for failure case */ + if( bResult == FAIL ) + { + Fail( "test failed\n" ); + } + + /* PAL termination */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test7/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test7/testinfo.dat new file mode 100644 index 0000000..d92d949 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/QueueUserAPC/test7/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = QueueUserAPC +Name = Positive test for QueueUserAPC +TYPE = DEFAULT +EXE1 = test7 +Description += Test to ensure proper operation of the QueueUserAPC() += API by trying to queue an APC function on a thread and += activating it with WaitForMultipleObjectsEx. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/CMakeLists.txt new file mode 100644 index 0000000..a267d29 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test3) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/test3/CMakeLists.txt new file mode 100644 index 0000000..4c626bf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + ReleaseMutex.cpp +) + +add_executable(paltest_releasemutex_test3 + ${SOURCES} +) + +add_dependencies(paltest_releasemutex_test3 coreclrpal) + +target_link_libraries(paltest_releasemutex_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/test3/ReleaseMutex.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/test3/ReleaseMutex.cpp new file mode 100644 index 0000000..5f6adb0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/test3/ReleaseMutex.cpp @@ -0,0 +1,103 @@ +// 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. + +/*============================================================ +** +** Source: ReleaseMutex/test3/ReleaseMutex.c +** +** Purpose: Test failure code for ReleaseMutex. +** +** Dependencies: CreateMutex +** ReleaseMutex +** CreateThread +** + +** +**=========================================================*/ + +#include + +DWORD dwTestResult; /* global for test result */ + +DWORD dwThreadId; /* consumer thread identifier */ + +HANDLE hMutex; /* handle to mutex */ + +HANDLE hThread; /* handle to thread */ + +/* + * Thread function. + */ +DWORD +PALAPI +ThreadFunction( LPVOID lpNoArg ) +{ + + dwTestResult = ReleaseMutex(hMutex); + + return 0; +} + +int __cdecl main (int argc, char **argv) +{ + + if(0 != (PAL_Initialize(argc, argv))) + { + return (FAIL); + } + + /* + * set dwTestResult so test fails even if ReleaseMutex is not called + */ + dwTestResult = 1; + + /* + * Create mutex + */ + hMutex = CreateMutexW ( + NULL, + TRUE, + NULL); + + if ( NULL == hMutex ) + { + Fail ( "hMutex = CreateMutex () - returned NULL\n" + "Failing Test.\nGetLastError returned %d\n", GetLastError()); + } + + /* + * Create ThreadFunction + */ + hThread = CreateThread( + NULL, + 0, + ThreadFunction, + NULL, + 0, + &dwThreadId); + + if ( NULL == hThread ) + { + + Fail ( "CreateThread() returned NULL. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + /* + * Wait for ThreadFunction to complete + */ + WaitForSingleObject (hThread, INFINITE); + + if (dwTestResult) + { + Fail ("ReleaseMutex() test was expected to return 0.\n" + "It returned %d. Failing test.\n", dwTestResult ); + } + + Trace ("ReleaseMutex() test returned 0.\nTest passed.\n"); + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/test3/testinfo.dat new file mode 100644 index 0000000..3f06757 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ReleaseMutex/test3/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = threading +Function = ReleaseMutex +Name = Positive Test for ReleaseMutex +TYPE = DEFAULT +EXE1 = releasemutex +Description += Calls ReleaseMutex from a thread which should not have ownership of the += mutex. If ReleaseMutex fails correctly this test will succeed. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/CMakeLists.txt new file mode 100644 index 0000000..070e421 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test1/CMakeLists.txt new file mode 100644 index 0000000..85026cc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_resetevent_test1 + ${SOURCES} +) + +add_dependencies(paltest_resetevent_test1 coreclrpal) + +target_link_libraries(paltest_resetevent_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test1/test1.cpp new file mode 100644 index 0000000..20a0d5d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test1/test1.cpp @@ -0,0 +1,99 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for ResetEvent. Create an event with an intial +** state signaled. Then reset that signal, and check to see that +** the event is now not signaled. +** +** +**=========================================================*/ + +#include + +BOOL ResetEventTest() +{ + BOOL bRet = FALSE; + DWORD dwRet = 0; + + LPSECURITY_ATTRIBUTES lpEventAttributes = 0; + BOOL bManualReset = TRUE; + BOOL bInitialState = TRUE; + + /* Create an Event, ensure it is valid */ + HANDLE hEvent = CreateEvent( lpEventAttributes, + bManualReset, bInitialState, NULL); + + if (hEvent != INVALID_HANDLE_VALUE) + { + /* Check that WaitFor returns WAIT_OBJECT_0, indicating that + the event is signaled. + */ + + dwRet = WaitForSingleObject(hEvent,0); + + if (dwRet != WAIT_OBJECT_0) + { + Fail("ResetEventTest:WaitForSingleObject failed (%x)\n", GetLastError()); + } + else + { + /* Call ResetEvent, which will reset the signal */ + bRet = ResetEvent(hEvent); + + if (!bRet) + { + Fail("ResetEventTest:ResetEvent failed (%x)\n", GetLastError()); + } + else + { + /* Call WaitFor again, and since it has been reset, + the return value should now be WAIT_TIMEOUT + */ + dwRet = WaitForSingleObject(hEvent,0); + + if (dwRet != WAIT_TIMEOUT) + { + Fail("ResetEventTest:WaitForSingleObject %s failed (%x)\n", GetLastError()); + } + else + { + bRet = CloseHandle(hEvent); + + if (!bRet) + { + Fail("ResetEventTest:CloseHandle failed (%x)\n", GetLastError()); + } + } + } + } + } + else + { + Fail("ResetEventTest:CreateEvent failed (%x)\n", GetLastError()); + } + + return bRet; +} + +int __cdecl main(int argc, char **argv) +{ + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!ResetEventTest()) + { + Fail ("Test failed\n"); + } + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test1/testinfo.dat new file mode 100644 index 0000000..ed27f13 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = ResetEvent +Name = Positive Test for ResetEvent +TYPE = DEFAULT +EXE1 = test1 +Description += Test for ResetEvent. Create an event with an intial += state signaled. Then reset that signal, and check to see that += the event is now not signaled. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test2/CMakeLists.txt new file mode 100644 index 0000000..11a1fbf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_resetevent_test2 + ${SOURCES} +) + +add_dependencies(paltest_resetevent_test2 coreclrpal) + +target_link_libraries(paltest_resetevent_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test2/test2.cpp new file mode 100644 index 0000000..8117f44 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test2/test2.cpp @@ -0,0 +1,89 @@ +// 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. + +/*============================================================================= +** +** Source: test2.c +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateEvent +** CloseHandle +** WaitForSingleObject +** +** Purpose: Test to ensure proper operation of the ResetEvent() +** API by calling it on an event handle that's already +** unsignalled. +** + +** +**===========================================================================*/ +#include + + + +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + DWORD dwRet = 0; + HANDLE hEvent = NULL; + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + BOOL bManualReset = TRUE; + BOOL bInitialState = FALSE; + + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + + /* create an unsignalled event which we can use with ResetEvent */ + hEvent = CreateEvent( lpEventAttributes, + bManualReset, + bInitialState, + NULL ); + + if( hEvent == INVALID_HANDLE_VALUE ) + { + /* ERROR */ + Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + } + + /* verify that the event isn't signalled yet */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + CloseHandle( hEvent ); + Fail( "Test failed\n" ); + } + + /* try to reset the event */ + if( ! ResetEvent( hEvent ) ) + { + /* ERROR */ + Trace( "FAIL:%lu:ResetEvent() call failed\n", GetLastError() ); + CloseHandle( hEvent ); + Fail( "Test failed\n" ); + } + + /* close the event handle */ + if( ! CloseHandle( hEvent ) ) + { + Fail( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + + + /* PAL termination */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test2/testinfo.dat new file mode 100644 index 0000000..4af1769 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = ResetEvent +Name = Positive test for ResetEvent +TYPE = DEFAULT +EXE1 = test2 +Description += Test to ensure proper operation of the ResetEvent() += API by calling it on an event handle that's already += unsignalled. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test3/CMakeLists.txt new file mode 100644 index 0000000..db50041 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_resetevent_test3 + ${SOURCES} +) + +add_dependencies(paltest_resetevent_test3 coreclrpal) + +target_link_libraries(paltest_resetevent_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test3/test3.cpp new file mode 100644 index 0000000..9bc068e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test3/test3.cpp @@ -0,0 +1,86 @@ +// 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. + +/*============================================================================= +** +** Source: test3.c +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateEvent +** CloseHandle +** +** Purpose: +** +** Test to ensure proper operation of the ResetEvent() +** API by calling it on an event handle that's been +** closed. We expect it to return an appropriate error +** result. +** +** + +** +**===========================================================================*/ +#include + + + +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + HANDLE hEvent = NULL; + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + BOOL bManualReset = TRUE; + BOOL bInitialState = FALSE; + + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + + /* create an event which we can use with ResetEvent */ + hEvent = CreateEvent( lpEventAttributes, + bManualReset, + bInitialState, + NULL ); + + if( hEvent == INVALID_HANDLE_VALUE ) + { + /* ERROR */ + Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + } + + /* close the event handle */ + if( ! CloseHandle( hEvent ) ) + { + Fail( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + + /* try to reset the event */ + if( ResetEvent( hEvent ) ) + { + /* ERROR */ + Fail( "FAIL:ResetEvent() call succeeded on a closed event handle\n" ); + } + + /* verify the result of GetLastError() */ + if( GetLastError() != ERROR_INVALID_HANDLE ) + { + /* ERROR */ + Fail( "FAIL:ResetEvent() call failed on a closed event handle " + "but returned an unexpected error result %lu\n" ); + } + + + + /* PAL termination */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test3/testinfo.dat new file mode 100644 index 0000000..4abeede --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test3/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = threading +Function = ResetEvent +Name = Negative test for ResetEvent +TYPE = DEFAULT +EXE1 = test3 +Description += Test to ensure proper operation of the ResetEvent() += API by calling it on an event handle that's been += closed. We expect it to return an appropriate error += result. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test4/CMakeLists.txt new file mode 100644 index 0000000..4a82944 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_resetevent_test4 + ${SOURCES} +) + +add_dependencies(paltest_resetevent_test4 coreclrpal) + +target_link_libraries(paltest_resetevent_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test4/test4.cpp new file mode 100644 index 0000000..0cc68fd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test4/test4.cpp @@ -0,0 +1,161 @@ +// 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. + +/*============================================================================= +** +** Source: test4.c +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateEvent +** CloseHandle +** WaitForSingleObject +** DuplicateHandle +** GetCurrentProcess +** +** Purpose: +** +** Test to ensure proper operation of the ResetEvent() +** API by calling it on an event handle that's the +** result of a DuplicateHandle() call on another event +** handle. +** + +** +**===========================================================================*/ +#include + + + +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + DWORD dwRet = 0; + HANDLE hEvent = NULL; + HANDLE hDupEvent = NULL; + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + BOOL bManualReset = TRUE; + BOOL bInitialState = TRUE; + + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + + /* create an event which we can use with ResetEvent */ + hEvent = CreateEvent( lpEventAttributes, + bManualReset, + bInitialState, + NULL ); + + if( hEvent == INVALID_HANDLE_VALUE ) + { + /* ERROR */ + Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + } + + /* verify that the event is signalled already */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_OBJECT_0 ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_OBJECT_0\n", + dwRet ); + CloseHandle( hEvent ); + Fail( "Test failed\n" ); + } + + + /* duplicate the event handle */ + if( ! (DuplicateHandle( + GetCurrentProcess(), + hEvent, + GetCurrentProcess(), + &hDupEvent, + GENERIC_READ|GENERIC_WRITE, /* ignored in PAL */ + FALSE, + DUPLICATE_SAME_ACCESS ) ) ) + { + Trace("ERROR:%u:DuplicateHandle() call failed\n", + GetLastError() ); + CloseHandle( hEvent ); + Fail("Test failed\n"); + } + + /* verify that the event is signalled with the duplicate handle */ + dwRet = WaitForSingleObject( hDupEvent, 0 ); + if( dwRet != WAIT_OBJECT_0 ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_OBJECT_0\n", + dwRet ); + CloseHandle( hEvent ); + CloseHandle( hDupEvent ); + Fail( "Test failed\n" ); + } + + + /* reset the event using the duplicate handle */ + if( ! ResetEvent( hDupEvent ) ) + { + /* ERROR */ + Trace( "ERROR:%lu:ResetEvent() call failed\n", GetLastError() ); + CloseHandle( hEvent ); + CloseHandle( hDupEvent ); + Fail( "Test failed\n" ); + } + + /* verify that the event isn't signalled using the duplicate handle*/ + dwRet = WaitForSingleObject( hDupEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + CloseHandle( hEvent ); + Fail( "Test failed\n" ); + } + + /* check that the event isn't signalled using the original event handle */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + CloseHandle( hEvent ); + Fail( "Test failed\n" ); + } + + + /* close the duplicate event handle */ + if( ! CloseHandle( hDupEvent ) ) + { + Fail( "ERROR:%lu:CloseHandle() call failed for duplicate handle\n", + GetLastError() ); + } + + + /* close the event handle */ + if( ! CloseHandle( hEvent ) ) + { + Fail( "ERROR:%lu:CloseHandle() call failed for original handle\n", + GetLastError() ); + } + + + /* PAL termination */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test4/testinfo.dat new file mode 100644 index 0000000..0223246 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResetEvent/test4/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = threading +Function = ResetEvent +Name = Positive test for ResetEvent +TYPE = DEFAULT +EXE1 = test4 +Description += Test to ensure proper operation of the ResetEvent() += API by calling it on an event handle that's the += result of a DuplicateHandle() call on another event += handle. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/test1/CMakeLists.txt new file mode 100644 index 0000000..7f2046f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_resumethread_test1 + ${SOURCES} +) + +add_dependencies(paltest_resumethread_test1 coreclrpal) + +target_link_libraries(paltest_resumethread_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/test1/test1.cpp new file mode 100644 index 0000000..825064e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/test1/test1.cpp @@ -0,0 +1,141 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for ResumeThread. Create a suspended Thread. +** First, ensure that it is indeed suspended. Then call resumethread +** and check to ensure that the function has now run. +** +** +**=========================================================*/ + +#include + +DWORD dwResumeThreadTestParameter = 0; + +DWORD PALAPI ResumeThreadTestThread( LPVOID lpParameter) +{ + DWORD dwRet = 0; + + /* Save parameter so we can check and ensure this function ran + properly. + */ + + dwResumeThreadTestParameter = (DWORD)(SIZE_T)lpParameter; + + return dwRet; +} + +BOOL ResumeThreadTest() +{ + BOOL bRet = FALSE; + DWORD dwRet = 0; + + LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL; + DWORD dwStackSize = 0; + LPTHREAD_START_ROUTINE lpStartAddress = &ResumeThreadTestThread; + LPVOID lpParameter = (LPVOID)lpStartAddress; + DWORD dwCreationFlags = CREATE_SUSPENDED; + DWORD dwThreadId = 0; + + HANDLE hThread = 0; + + dwResumeThreadTestParameter = 0; + + /* Create a thread, with CREATE_SUSPENDED, so we can resume it! */ + + hThread = CreateThread( lpThreadAttributes, + dwStackSize, lpStartAddress, lpParameter, + dwCreationFlags, &dwThreadId ); + + if (hThread != INVALID_HANDLE_VALUE) + { + /* Wait for one second. This should return WAIT_TIMEOUT */ + dwRet = WaitForSingleObject(hThread,1000); + + if (dwRet != WAIT_TIMEOUT) + { + Trace("ResumeThreadTest:WaitForSingleObject " + "failed (%x)\n",GetLastError()); + } + else + { + /* Check to ensure the parameter hasn't changed. The + function shouldn't have occurred yet. + */ + if (dwResumeThreadTestParameter != 0) + { + Trace("ResumeThreadTest:parameter error\n"); + } + else + { + /* Call ResumeThread and ensure the return value is + correct. + */ + + dwRet = ResumeThread(hThread); + + if (dwRet != 1) + { + Trace("ResumeThreadTest:ResumeThread " + "failed (%x)\n",GetLastError()); + } + else + { + /* Wait again, now that the thread has been + resumed, and the return should be WAIT_OBJECT_0 + */ + dwRet = WaitForSingleObject(hThread,INFINITE); + + if (dwRet != WAIT_OBJECT_0) + { + Trace("ResumeThreadTest:WaitForSingleObject " + "failed (%x)\n",GetLastError()); + } + else + { + /* Check the param now and it should have been + set. + */ + if (dwResumeThreadTestParameter != (DWORD)(SIZE_T)lpParameter) + { + Trace("ResumeThreadTest:parameter error\n"); + } + else + { + bRet = TRUE; + } + } + } + } + } + } + else + { + Trace("ResumeThreadTest:CreateThread failed (%x)\n",GetLastError()); + } + + return bRet; +} + +int __cdecl main(int argc, char **argv) +{ + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!ResumeThreadTest()) + { + Fail("Test Failed\n"); + } + + PAL_Terminate(); + return (PASS); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/test1/testinfo.dat new file mode 100644 index 0000000..8472165 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ResumeThread/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = ResumeThread +Name = Positive Test for ResumeThread +TYPE = DEFAULT +EXE1 = test1 +Description += Test for ResumeThread. Create a suspended Thread. += First, ensure that it is indeed suspended. Then call resumethread += and check to ensure that the function has now run. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/test1/CMakeLists.txt new file mode 100644 index 0000000..8696f23 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_seterrormode_test1 + ${SOURCES} +) + +add_dependencies(paltest_seterrormode_test1 coreclrpal) + +target_link_libraries(paltest_seterrormode_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/test1/test1.cpp new file mode 100644 index 0000000..238cec4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/test1/test1.cpp @@ -0,0 +1,50 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c (SetErrorMode) +** +** Purpose: Tests the PAL implementation of the SetErrorMode function. +** This test will set the error mode and then read the error +** set with GetLastError(). +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + DWORD dErrorReturn; + UINT dErrorModes[] = {SEM_NOOPENFILEERRORBOX, SEM_FAILCRITICALERRORS, 0}; + int i; + + /* + * Initialize the Pal + */ + if ((PAL_Initialize(argc,argv)) != 0) + { + return (FAIL); + } + + /* + * Loop through the supported Error Modes and verify + * that GetLastError() returns the correct Error Mode + */ + for (i=0; i < (sizeof(dErrorModes) / sizeof(UINT)); i++) + { + SetLastError(dErrorModes[i]); + if ((dErrorReturn = GetLastError()) != dErrorModes[i]) + { + Fail("ERROR: SetLastError was set to 0x%4.4x but," + " GetLastError returned 0x%4.4x\n", + dErrorModes[i], + dErrorReturn); + } + } + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/test1/testinfo.dat new file mode 100644 index 0000000..875ac2a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetErrorMode/test1/testinfo.dat @@ -0,0 +1,16 @@ +# 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. + +Version = 1.0 +Section = Threading +Function = SetErrorMode +Name = Positive Test for SetErrorMode +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the SetErrorMode function. += This test will set the error mode and then read the error += set with GetLastError(). + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/CMakeLists.txt new file mode 100644 index 0000000..070e421 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test1/CMakeLists.txt new file mode 100644 index 0000000..df55cad --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_setevent_test1 + ${SOURCES} +) + +add_dependencies(paltest_setevent_test1 coreclrpal) + +target_link_libraries(paltest_setevent_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test1/test1.cpp new file mode 100644 index 0000000..d5a29ce --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test1/test1.cpp @@ -0,0 +1,94 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for SetEvent. Create an Event and then set +** this event, checking the return value. Ensure that it returns +** positive. +** +** +**=========================================================*/ + +#include + +BOOL SetEventTest() +{ + int bRet = 0; + DWORD dwRet = 0; + + LPSECURITY_ATTRIBUTES lpEventAttributes = 0; + BOOL bManualReset = TRUE; + BOOL bInitialState = FALSE; + + /* Create an event which we can use with SetEvent */ + HANDLE hEvent = CreateEvent( lpEventAttributes, + bManualReset, bInitialState, NULL); + + if (hEvent != INVALID_HANDLE_VALUE) + { + dwRet = WaitForSingleObject(hEvent,0); + + if (dwRet != WAIT_TIMEOUT) + { + Trace("SetEventTest:WaitForSingleObject failed (%x)\n", GetLastError()); + } + else + { + /* Set the event to the previously created event and check + the return value. + */ + bRet = SetEvent(hEvent); + + if (!bRet) + { + Trace("SetEventTest:SetEvent failed (%x)\n", GetLastError()); + } + else + { + dwRet = WaitForSingleObject(hEvent,0); + + if (dwRet != WAIT_OBJECT_0) + { + Trace("SetEventTest:WaitForSingleObject failed (%x)\n", GetLastError()); + } + else + { + dwRet = CloseHandle(hEvent); + + if (!dwRet) + { + Trace("SetEventTest:CloseHandle failed (%x)\n", GetLastError()); + } + } + } + } + } + else + { + Trace("SetEventTest:CreateEvent failed (%x)\n", GetLastError()); + } + + return bRet; +} + + +int __cdecl main(int argc, char **argv) +{ + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(SetEventTest() == 0) + { + Fail ("Test failed\n"); + } + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test1/testinfo.dat new file mode 100644 index 0000000..9bfd808 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = SetEvent +Name = Positive Test for SetEvent +TYPE = DEFAULT +EXE1 = test1 +Description +=Test for SetEvent. Create an Event and then set +=this event, checking the return value. Ensure that it returns +=positive. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test2/CMakeLists.txt new file mode 100644 index 0000000..d8bf0b9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_setevent_test2 + ${SOURCES} +) + +add_dependencies(paltest_setevent_test2 coreclrpal) + +target_link_libraries(paltest_setevent_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test2/test2.cpp new file mode 100644 index 0000000..5fd2833 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test2/test2.cpp @@ -0,0 +1,125 @@ +// 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. + +/*============================================================================= +** +** Source: test2.c +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateEvent +** CloseHandle +** WaitForSingleObject +** +** Purpose: +** +** Test to ensure proper operation of the SetEvent() +** API by calling it on an event handle that's already set. +** + +** +**===========================================================================*/ +#include + + + +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + DWORD dwRet = 0; + HANDLE hEvent = NULL; + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + BOOL bManualReset = TRUE; + BOOL bInitialState = FALSE; + + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + + /* create an event which we can use with SetEvent */ + hEvent = CreateEvent( lpEventAttributes, + bManualReset, + bInitialState, + NULL ); + + if( hEvent == INVALID_HANDLE_VALUE ) + { + /* ERROR */ + Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + } + + /* verify that the event isn't signalled yet */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + CloseHandle( hEvent ); + Fail( "Test failed\n" ); + } + + /* set the event */ + if( ! SetEvent( hEvent ) ) + { + /* ERROR */ + Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() ); + CloseHandle( hEvent ); + Fail( "Test failed\n" ); + } + + /* verify that the event is signalled */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_OBJECT_0 ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_OBJECT_0\n", + dwRet ); + CloseHandle( hEvent ); + Fail( "Test failed\n" ); + } + + /* try to set the event again */ + if( ! SetEvent( hEvent ) ) + { + /* ERROR */ + Trace( "FAIL:%lu:SetEvent() call failed on signalled event\n", + GetLastError() ); + CloseHandle( hEvent ); + Fail( "Test failed\n" ); + } + + /* verify that the event is still signalled */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_OBJECT_0 ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_OBJECT_0\n", + dwRet ); + CloseHandle( hEvent ); + Fail( "Test failed\n" ); + } + + + /* close the event handle */ + if( ! CloseHandle( hEvent ) ) + { + Fail( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + + + /* PAL termination */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test2/testinfo.dat new file mode 100644 index 0000000..f215305 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = threading +Function = SetEvent +Name = Positive test for SetEvent +TYPE = DEFAULT +EXE1 = test2 +Description += Test to ensure proper operation of the SetEvent() += API by calling it on an event handle that's already set. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test3/CMakeLists.txt new file mode 100644 index 0000000..bc9bd26 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_setevent_test3 + ${SOURCES} +) + +add_dependencies(paltest_setevent_test3 coreclrpal) + +target_link_libraries(paltest_setevent_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test3/test3.cpp new file mode 100644 index 0000000..21601f0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test3/test3.cpp @@ -0,0 +1,85 @@ +// 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. + +/*============================================================================= +** +** Source: test3.c +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateEvent +** CloseHandle +** +** Purpose: +** +** Test to ensure proper operation of the SetEvent() +** API by calling it on an event handle that's been +** closed. We expect it to return an appropriate error +** result. +** + +** +**===========================================================================*/ +#include + + + +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + HANDLE hEvent = NULL; + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + BOOL bManualReset = TRUE; + BOOL bInitialState = FALSE; + + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + + /* create an event which we can use with SetEvent */ + hEvent = CreateEvent( lpEventAttributes, + bManualReset, + bInitialState, + NULL ); + + if( hEvent == INVALID_HANDLE_VALUE ) + { + /* ERROR */ + Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + } + + /* close the event handle */ + if( ! CloseHandle( hEvent ) ) + { + Fail( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() ); + } + + /* try to set the event */ + if( SetEvent( hEvent ) ) + { + /* ERROR */ + Fail( "FAIL:SetEvent() call succeeded on a closed event handle\n" ); + } + + /* verify the result of GetLastError() */ + if( GetLastError() != ERROR_INVALID_HANDLE ) + { + /* ERROR */ + Fail( "FAIL:SetEvent() call failed on a closed event handle" + "but returned an unexpected error result %lu\n" ); + } + + + + /* PAL termination */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test3/testinfo.dat new file mode 100644 index 0000000..7b8f430 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test3/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = threading +Function = SetEvent +Name = Negative test for SetEvent +TYPE = DEFAULT +EXE1 = test3 +Description += Test to ensure proper operation of the SetEvent() += API by calling it on an event handle that's been += closed. We expect it to return an appropriate error += result. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test4/CMakeLists.txt new file mode 100644 index 0000000..129c11a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_setevent_test4 + ${SOURCES} +) + +add_dependencies(paltest_setevent_test4 coreclrpal) + +target_link_libraries(paltest_setevent_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test4/test4.cpp new file mode 100644 index 0000000..7a79a9d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test4/test4.cpp @@ -0,0 +1,161 @@ +// 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. + +/*============================================================================= +** +** Source: test4.c +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** CreateEvent +** CloseHandle +** WaitForSingleObject +** DuplicateHandle +** GetCurrentProcess +** +** Purpose: +** +** Test to ensure proper operation of the SetEvent() +** API by calling it on an event handle that's the +** result of a DuplicateHandle() call on another event +** handle. +** + +** +**===========================================================================*/ +#include + + + +int __cdecl main( int argc, char **argv ) + +{ + /* local variables */ + DWORD dwRet = 0; + HANDLE hEvent = NULL; + HANDLE hDupEvent = NULL; + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + BOOL bManualReset = TRUE; + BOOL bInitialState = FALSE; + + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + + /* create an event which we can use with SetEvent */ + hEvent = CreateEvent( lpEventAttributes, + bManualReset, + bInitialState, + NULL ); + + if( hEvent == INVALID_HANDLE_VALUE ) + { + /* ERROR */ + Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() ); + } + + /* verify that the event isn't signalled yet */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + CloseHandle( hEvent ); + Fail( "Test failed\n" ); + } + + + /* duplicate the event handle */ + if( ! (DuplicateHandle( + GetCurrentProcess(), + hEvent, + GetCurrentProcess(), + &hDupEvent, + GENERIC_READ|GENERIC_WRITE, /* ignored in PAL */ + FALSE, + DUPLICATE_SAME_ACCESS ) ) ) + { + Trace("ERROR:%u:DuplicateHandle() call failed\n", + GetLastError() ); + CloseHandle( hEvent ); + Fail("Test failed\n"); + } + + /* verify that the event isn't signalled yet with the duplicate handle */ + dwRet = WaitForSingleObject( hDupEvent, 0 ); + if( dwRet != WAIT_TIMEOUT ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + dwRet ); + CloseHandle( hEvent ); + CloseHandle( hDupEvent ); + Fail( "Test failed\n" ); + } + + + /* set the event using the duplicate handle */ + if( ! SetEvent( hDupEvent ) ) + { + /* ERROR */ + Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() ); + CloseHandle( hEvent ); + CloseHandle( hDupEvent ); + Fail( "Test failed\n" ); + } + + /* verify that the event is signalled using the duplicate handle*/ + dwRet = WaitForSingleObject( hDupEvent, 0 ); + if( dwRet != WAIT_OBJECT_0 ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_OBJECT_0\n", + dwRet ); + CloseHandle( hEvent ); + Fail( "Test failed\n" ); + } + + /* verify that the event is signalled using the original event handle */ + dwRet = WaitForSingleObject( hEvent, 0 ); + if( dwRet != WAIT_OBJECT_0 ) + { + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_OBJECT_0\n", + dwRet ); + CloseHandle( hEvent ); + Fail( "Test failed\n" ); + } + + + /* close the duplicate event handle */ + if( ! CloseHandle( hDupEvent ) ) + { + Fail( "ERROR:%lu:CloseHandle() call failed for duplicate handle\n", + GetLastError() ); + } + + + /* close the event handle */ + if( ! CloseHandle( hEvent ) ) + { + Fail( "ERROR:%lu:CloseHandle() call failed for original handle\n", + GetLastError() ); + } + + + /* PAL termination */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test4/testinfo.dat new file mode 100644 index 0000000..9a7f7dd --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SetEvent/test4/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = threading +Function = SetEvent +Name = Positive test for SetEvent +TYPE = DEFAULT +EXE1 = test4 +Description += Test to ensure proper operation of the SetEvent() += API by calling it on an event handle that's the += result of a DuplicateHandle() call on another event += handle. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SignalObjectAndWait/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SignalObjectAndWait/CMakeLists.txt new file mode 100644 index 0000000..cc05747 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SignalObjectAndWait/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + SignalObjectAndWaitTest.cpp +) + +add_executable(paltest_signalobjectandwaittest + ${SOURCES} +) + +add_dependencies(paltest_signalobjectandwaittest coreclrpal) + +target_link_libraries(paltest_signalobjectandwaittest + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SignalObjectAndWait/SignalObjectAndWaitTest.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SignalObjectAndWait/SignalObjectAndWaitTest.cpp new file mode 100644 index 0000000..9ec1ed3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SignalObjectAndWait/SignalObjectAndWaitTest.cpp @@ -0,0 +1,414 @@ +// 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. + +#include + +enum class SignalableObjectType +{ + First = 0, + + Invalid = First, + ManualResetEvent, + AutoResetEvent, + Semaphore, + FullSemaphore, + Mutex, + UnlockedMutex, + + Last = UnlockedMutex +}; + +enum class WaitableObjectType +{ + First = 0, + + Invalid = First, + ManualResetEvent, + UnsignaledManualResetEvent, + AutoResetEvent, + UnsignaledAutoResetEvent, + Semaphore, + EmptySemaphore, + Mutex, + LockedMutex, + + Last = LockedMutex +}; + +void operator ++(SignalableObjectType &objectType) +{ + ++(int &)objectType; +} + +void operator ++(WaitableObjectType &objectType) +{ + ++(int &)objectType; +} + +struct AssertionFailureException +{ + const int lineNumber; + const char *const expression; + SignalableObjectType signalableObjectType; + WaitableObjectType waitableObjectType; + DWORD waitResult; + DWORD errorCode; + + AssertionFailureException(int lineNumber, const char *expression) + : lineNumber(lineNumber), + expression(expression), + signalableObjectType(SignalableObjectType::Invalid), + waitableObjectType(WaitableObjectType::Invalid), + waitResult(WAIT_OBJECT_0), + errorCode(ERROR_SUCCESS) + { + } +}; + +#define TestAssert(expression) \ + do \ + { \ + if (!(expression)) \ + { \ + throw AssertionFailureException(__LINE__, "" #expression ""); \ + } \ + } while (false) + +HANDLE CreateObjectToSignal(SignalableObjectType objectType) +{ + switch (objectType) + { + case SignalableObjectType::Invalid: + return nullptr; + + case SignalableObjectType::ManualResetEvent: + return CreateEvent(nullptr, true, false, nullptr); + + case SignalableObjectType::AutoResetEvent: + return CreateEvent(nullptr, false, false, nullptr); + + case SignalableObjectType::Semaphore: + return CreateSemaphore(nullptr, 0, 1, nullptr); + + case SignalableObjectType::FullSemaphore: + return CreateSemaphore(nullptr, 1, 1, nullptr); + + case SignalableObjectType::Mutex: + return CreateMutex(nullptr, true, nullptr); + + case SignalableObjectType::UnlockedMutex: + return CreateMutex(nullptr, false, nullptr); + + default: + TestAssert(false); + } +} + +void VerifySignal(HANDLE h, SignalableObjectType objectType) +{ + switch (objectType) + { + case SignalableObjectType::ManualResetEvent: + TestAssert(WaitForSingleObject(h, 0) == WAIT_OBJECT_0); + break; + + case SignalableObjectType::AutoResetEvent: + TestAssert(WaitForSingleObject(h, 0) == WAIT_OBJECT_0); + SetEvent(h); + break; + + case SignalableObjectType::Semaphore: + TestAssert(!ReleaseSemaphore(h, 1, nullptr)); + break; + + case SignalableObjectType::Mutex: + TestAssert(!ReleaseMutex(h)); + break; + + default: + TestAssert(false); + } +} + +void CloseObjectToSignal(HANDLE h, SignalableObjectType objectType) +{ + if (objectType != SignalableObjectType::Invalid) + { + CloseHandle(h); + } +} + +HANDLE CreateObjectToWaitOn(WaitableObjectType objectType) +{ + switch (objectType) + { + case WaitableObjectType::Invalid: + return nullptr; + + case WaitableObjectType::ManualResetEvent: + return CreateEvent(nullptr, true, true, nullptr); + + case WaitableObjectType::UnsignaledManualResetEvent: + return CreateEvent(nullptr, true, false, nullptr); + + case WaitableObjectType::AutoResetEvent: + return CreateEvent(nullptr, false, true, nullptr); + + case WaitableObjectType::UnsignaledAutoResetEvent: + return CreateEvent(nullptr, false, false, nullptr); + + case WaitableObjectType::Semaphore: + return CreateSemaphore(nullptr, 1, 1, nullptr); + + case WaitableObjectType::EmptySemaphore: + return CreateSemaphore(nullptr, 0, 1, nullptr); + + case WaitableObjectType::Mutex: + return CreateMutex(nullptr, false, nullptr); + + case WaitableObjectType::LockedMutex: + return CreateMutex(nullptr, true, nullptr); + + default: + TestAssert(false); + } +} + +void VerifyWait(HANDLE h, WaitableObjectType objectType) +{ + switch (objectType) + { + case WaitableObjectType::ManualResetEvent: + case WaitableObjectType::UnsignaledManualResetEvent: + break; + + case WaitableObjectType::AutoResetEvent: + case WaitableObjectType::UnsignaledAutoResetEvent: + case WaitableObjectType::Semaphore: + case WaitableObjectType::EmptySemaphore: + TestAssert(WaitForSingleObject(h, 0) == WAIT_TIMEOUT); + break; + + case WaitableObjectType::Mutex: + TestAssert(ReleaseMutex(h)); + TestAssert(!ReleaseMutex(h)); + TestAssert(WaitForSingleObject(h, 0) == WAIT_OBJECT_0); + break; + + case WaitableObjectType::LockedMutex: + TestAssert(ReleaseMutex(h)); + TestAssert(ReleaseMutex(h)); + TestAssert(!ReleaseMutex(h)); + TestAssert(WaitForSingleObject(h, 0) == WAIT_OBJECT_0); + TestAssert(WaitForSingleObject(h, 0) == WAIT_OBJECT_0); + break; + + default: + TestAssert(false); + } +} + +void CloseObjectToWaitOn(HANDLE h, WaitableObjectType objectType) +{ + switch (objectType) + { + case WaitableObjectType::ManualResetEvent: + case WaitableObjectType::UnsignaledManualResetEvent: + case WaitableObjectType::AutoResetEvent: + case WaitableObjectType::UnsignaledAutoResetEvent: + CloseHandle(h); + break; + + case WaitableObjectType::Semaphore: + case WaitableObjectType::EmptySemaphore: + ReleaseSemaphore(h, 1, nullptr); + CloseHandle(h); + break; + + case WaitableObjectType::Mutex: + ReleaseMutex(h); + CloseHandle(h); + break; + + case WaitableObjectType::LockedMutex: + ReleaseMutex(h); + ReleaseMutex(h); + CloseHandle(h); + break; + + default: + break; + } +} + +bool Verify(SignalableObjectType signalableObjectType, WaitableObjectType waitableObjectType, DWORD waitResult, DWORD errorCode) +{ + if (signalableObjectType == SignalableObjectType::Invalid || waitableObjectType == WaitableObjectType::Invalid) + { + TestAssert(waitResult == WAIT_FAILED); + TestAssert(errorCode == ERROR_INVALID_HANDLE); + return false; + } + + switch (signalableObjectType) + { + case SignalableObjectType::FullSemaphore: + TestAssert(waitResult == WAIT_FAILED); + TestAssert(errorCode == ERROR_TOO_MANY_POSTS); + return false; + + case SignalableObjectType::UnlockedMutex: + TestAssert(waitResult == WAIT_FAILED); + TestAssert(errorCode == ERROR_NOT_OWNER); + return false; + + default: + break; + } + + switch (waitableObjectType) + { + case WaitableObjectType::UnsignaledManualResetEvent: + case WaitableObjectType::UnsignaledAutoResetEvent: + case WaitableObjectType::EmptySemaphore: + TestAssert(waitResult == WAIT_TIMEOUT); + break; + + default: + TestAssert(waitResult == WAIT_OBJECT_0); + break; + } + TestAssert(errorCode == ERROR_SUCCESS); + return true; +} + +void Run(SignalableObjectType signalableObjectType, WaitableObjectType waitableObjectType) +{ + HANDLE objectToSignal = CreateObjectToSignal(signalableObjectType); + TestAssert(signalableObjectType == SignalableObjectType::Invalid || objectToSignal != nullptr); + HANDLE objectToWaitOn = CreateObjectToWaitOn(waitableObjectType); + TestAssert(waitableObjectType == WaitableObjectType::Invalid || objectToWaitOn != nullptr); + DWORD waitResult = SignalObjectAndWait(objectToSignal, objectToWaitOn, 0, true); + DWORD errorCode = waitResult == WAIT_FAILED ? GetLastError() : ERROR_SUCCESS; + + try + { + if (Verify(signalableObjectType, waitableObjectType, waitResult, errorCode)) + { + VerifySignal(objectToSignal, signalableObjectType); + VerifyWait(objectToWaitOn, waitableObjectType); + } + } + catch (AssertionFailureException ex) + { + ex.signalableObjectType = signalableObjectType; + ex.waitableObjectType = waitableObjectType; + ex.waitResult = waitResult; + ex.errorCode = errorCode; + throw ex; + } +} + +static bool s_apcCalled = false; + +void CALLBACK ApcCallback(ULONG_PTR dwParam) +{ + s_apcCalled = true; + HANDLE *objects = (HANDLE *)dwParam; + HANDLE objectToSignal = objects[0]; + HANDLE objectToWaitOn = objects[1]; + TestAssert(WaitForSingleObject(objectToSignal, 0) == WAIT_OBJECT_0); // signal has occurred + TestAssert(WaitForSingleObject(objectToWaitOn, 0) == WAIT_OBJECT_0); // wait has not occurred yet + SetEvent(objectToWaitOn); +} + +void Run() +{ + for (SignalableObjectType signalableObjectType = SignalableObjectType::First; + signalableObjectType <= SignalableObjectType::Last; + ++signalableObjectType) + { + for (WaitableObjectType waitableObjectType = WaitableObjectType::First; + waitableObjectType <= WaitableObjectType::Last; + ++waitableObjectType) + { + Run(signalableObjectType, waitableObjectType); + } + } + + DWORD waitResult = WAIT_FAILED; + try + { + HANDLE objectToSignal = CreateObjectToSignal(SignalableObjectType::ManualResetEvent); + TestAssert(objectToSignal != nullptr); + HANDLE objectToWaitOn = CreateObjectToWaitOn(WaitableObjectType::AutoResetEvent); + TestAssert(objectToWaitOn != nullptr); + HANDLE objects[] = {objectToSignal, objectToWaitOn}; + + // Verify that a queued APC is not called if the wait is not alertable + QueueUserAPC(&ApcCallback, GetCurrentThread(), (ULONG_PTR)&objects); + waitResult = SignalObjectAndWait(objectToSignal, objectToWaitOn, 0, false); + TestAssert(waitResult == WAIT_OBJECT_0); + TestAssert(!s_apcCalled); + TestAssert(WaitForSingleObject(objectToSignal, 0) == WAIT_OBJECT_0); // signal has occurred + TestAssert(WaitForSingleObject(objectToWaitOn, 0) == WAIT_TIMEOUT); // wait has occurred + + // Verify that signal, call APC, wait, occur in that order + ResetEvent(objectToSignal); + SetEvent(objectToWaitOn); + waitResult = SignalObjectAndWait(objectToSignal, objectToWaitOn, 0, true); + TestAssert(waitResult == WAIT_IO_COMPLETION); + TestAssert(s_apcCalled); + TestAssert(WaitForSingleObject(objectToSignal, 0) == WAIT_OBJECT_0); // signal has occurred + TestAssert(WaitForSingleObject(objectToWaitOn, 0) == WAIT_OBJECT_0); // wait has not occurred yet + s_apcCalled = false; + ResetEvent(objectToSignal); + SetEvent(objectToWaitOn); + waitResult = SignalObjectAndWait(objectToSignal, objectToWaitOn, 0, true); + TestAssert(waitResult == WAIT_OBJECT_0); + TestAssert(!s_apcCalled); + TestAssert(WaitForSingleObject(objectToSignal, 0) == WAIT_OBJECT_0); // signal has occurred + TestAssert(WaitForSingleObject(objectToWaitOn, 0) == WAIT_TIMEOUT); // wait has occurred + + CloseHandle(objectToSignal); + CloseHandle(objectToWaitOn); + } + catch (AssertionFailureException ex) + { + ex.signalableObjectType = SignalableObjectType::ManualResetEvent; + ex.waitableObjectType = WaitableObjectType::AutoResetEvent; + ex.waitResult = waitResult; + throw ex; + } +} + +int _cdecl main(int argc, char **argv) +{ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + int testReturnCode = PASS; + try + { + Run(); + } + catch (AssertionFailureException ex) + { + printf( + "SignalObjectAndWaitTest - Assertion failure (line %d, signalable object type %d, waitable object type %d, wait result 0x%x, error code %u): '%s'\n", + ex.lineNumber, + ex.signalableObjectType, + ex.waitableObjectType, + ex.waitResult, + ex.errorCode, + ex.expression); + fflush(stdout); + testReturnCode = FAIL; + } + + PAL_TerminateEx(testReturnCode); + return testReturnCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test1/CMakeLists.txt new file mode 100644 index 0000000..47b2a2d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + Sleep.cpp +) + +add_executable(paltest_sleep_test1 + ${SOURCES} +) + +add_dependencies(paltest_sleep_test1 coreclrpal) + +target_link_libraries(paltest_sleep_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test1/Sleep.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test1/Sleep.cpp new file mode 100644 index 0000000..f7f7c91 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test1/Sleep.cpp @@ -0,0 +1,80 @@ +// 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. + +/*============================================================ +** +** Source: Sleep.c +** +** Purpose: Test to establish whether the Sleep function stops the thread from +** executing for the specified times. +** +** Dependencies: GetSystemTime +** Fail +** Trace +** + +** +**=========================================================*/ + +#include + +DWORD SleepTimes[] = +{ + 0, + 50, + 100, + 500, + 2000 +}; + +/* Milliseconds of error which are acceptable Function execution time, etc. */ +DWORD AcceptableTimeError = 150; + +int __cdecl main( int argc, char **argv ) +{ + UINT64 OldTimeStamp; + UINT64 NewTimeStamp; + DWORD MaxDelta; + DWORD TimeDelta; + DWORD i; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + LARGE_INTEGER performanceFrequency; + if (!QueryPerformanceFrequency(&performanceFrequency)) + { + return FAIL; + } + + for( i = 0; i < sizeof(SleepTimes) / sizeof(DWORD); i++) + { + OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency); + Sleep(SleepTimes[i]); + NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency); + + TimeDelta = NewTimeStamp - OldTimeStamp; + + /* For longer intervals use a 10 percent tolerance */ + if ((SleepTimes[i] * 0.1) > AcceptableTimeError) + { + MaxDelta = SleepTimes[i] + (DWORD)(SleepTimes[i] * 0.1); + } + else + { + MaxDelta = SleepTimes[i] + AcceptableTimeError; + } + + if ( TimeDeltaMaxDelta ) + { + Fail("The sleep function slept for %d ms when it should have " + "slept for %d ms\n", TimeDelta, SleepTimes[i]); + } + } + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test1/testinfo.dat new file mode 100644 index 0000000..433a061 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = threading +Function = Sleep +Name = Positive Test for Sleep +TYPE = DEFAULT +EXE1 = sleep +Description += Test to see if the Sleep function stops the thread from executing for the += specified amount of time. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test2/CMakeLists.txt new file mode 100644 index 0000000..770404f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + sleep.cpp +) + +add_executable(paltest_sleep_test2 + ${SOURCES} +) + +add_dependencies(paltest_sleep_test2 coreclrpal) + +target_link_libraries(paltest_sleep_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test2/sleep.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test2/sleep.cpp new file mode 100644 index 0000000..eb30e34 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test2/sleep.cpp @@ -0,0 +1,73 @@ +// 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. + +/*============================================================ +** +** Source: Sleep.c +** +** Purpose: Test to establish whether the Sleep function stops the thread from +** executing for the specified times. +** +** Dependencies: GetTickCount +** + +** +**=========================================================*/ + +#include + +/* + * times in 10^(-3) seconds + */ + +DWORD SleepTimes[] = +{ + 60000, + 300000, + 1800000, + 3200000 +}; + +/* Milliseconds of error which are acceptable Function execution time, etc. */ +DWORD AcceptableTimeError = 150; + +int __cdecl main( int argc, char **argv ) +{ + UINT64 OldTimeStamp; + UINT64 NewTimeStamp; + DWORD MaxDelta; + DWORD TimeDelta; + DWORD i; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + LARGE_INTEGER performanceFrequency; + if (!QueryPerformanceFrequency(&performanceFrequency)) + { + return FAIL; + } + + for( i = 0; i < sizeof(SleepTimes) / sizeof(DWORD); i++) + { + OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency); + Sleep(SleepTimes[i]); + NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency); + + TimeDelta = NewTimeStamp - OldTimeStamp; + + MaxDelta = SleepTimes[i] + AcceptableTimeError; + + if ( TimeDeltaMaxDelta ) + { + Fail("The sleep function slept for %u ms when it should have " + "slept for %u ms\n", TimeDelta, SleepTimes[i]); + } + } + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test2/testinfo.dat new file mode 100644 index 0000000..433a061 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/Sleep/test2/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = threading +Function = Sleep +Name = Positive Test for Sleep +TYPE = DEFAULT +EXE1 = sleep +Description += Test to see if the Sleep function stops the thread from executing for the += specified amount of time. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/CMakeLists.txt new file mode 100644 index 0000000..6545353 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(test1) +add_subdirectory(test2) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test1/CMakeLists.txt new file mode 100644 index 0000000..492fa18 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_sleepex_test1 + ${SOURCES} +) + +add_dependencies(paltest_sleepex_test1 coreclrpal) + +target_link_libraries(paltest_sleepex_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test1/test1.cpp new file mode 100644 index 0000000..7ccfe0c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test1/test1.cpp @@ -0,0 +1,89 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that SleepEx correctly sleeps for a given amount of time, +** regardless of the alertable flag. +** +** +**===================================================================*/ + +#include + +typedef struct +{ + DWORD SleepTime; + BOOL Alertable; +} testCase; + +testCase testCases[] = +{ + {0, FALSE}, + {50, FALSE}, + {100, FALSE}, + {500, FALSE}, + {2000, FALSE}, + + {0, TRUE}, + {50, TRUE}, + {100, TRUE}, + {500, TRUE}, + {2000, TRUE}, +}; + +/* Milliseconds of error which are acceptable Function execution time, etc. */ +DWORD AcceptableTimeError = 150; + +int __cdecl main( int argc, char **argv ) +{ + UINT64 OldTimeStamp; + UINT64 NewTimeStamp; + DWORD MaxDelta; + DWORD TimeDelta; + DWORD i; + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + LARGE_INTEGER performanceFrequency; + if (!QueryPerformanceFrequency(&performanceFrequency)) + { + return FAIL; + } + + for (i = 0; i AcceptableTimeError) + { + MaxDelta = testCases[i].SleepTime + (DWORD)(testCases[i].SleepTime * 0.1); + } + else + { + MaxDelta = testCases[i].SleepTime + AcceptableTimeError; + } + + if (TimeDelta < testCases[i].SleepTime || TimeDelta > MaxDelta) + { + Fail("The sleep function slept for %d ms when it should have " + "slept for %d ms\n", TimeDelta, testCases[i].SleepTime); + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test1/testinfo.dat new file mode 100644 index 0000000..1242768 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = threading +Function = SleepEx +Name = Test #1 for SleepEx +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests that SleepEx correctly sleeps for a given amount of time, +=regardless of the alertable flag. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test2/CMakeLists.txt new file mode 100644 index 0000000..f397749 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_sleepex_test2 + ${SOURCES} +) + +add_dependencies(paltest_sleepex_test2 coreclrpal) + +target_link_libraries(paltest_sleepex_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test2/test2.cpp new file mode 100644 index 0000000..690acf5 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test2/test2.cpp @@ -0,0 +1,183 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Tests that a child thread in the middle of a SleepEx call will be +** interrupted by QueueUserAPC if the alert flag was set. +** +** +**===================================================================*/ + +#include + +const int ChildThreadSleepTime = 2000; +const int InterruptTime = 1000; +/* We need to keep in mind that BSD has a timer resolution of 10ms, so + we need to adjust our delta to keep that in mind. Besides we need some + tolerance to account for different scheduling strategies, heavy load + scenarios, etc. + + Real-world data also tells us we can expect a big difference between + values when run on real iron vs run in a hypervisor. + + Thread-interruption times when run on bare metal will typically yield + around 0ms on Linux and between 0 and 16ms on FreeBSD. However, when run + in a hypervisor (like VMWare ESXi) we may get values around an order of + magnitude higher, up to 110 ms for some tests. +*/ +const DWORD AcceptableDelta = 150; + +const int Iterations = 5; + +void RunTest(BOOL AlertThread); +VOID PALAPI APCFunc(ULONG_PTR dwParam); +DWORD PALAPI SleeperProc(LPVOID lpParameter); + +DWORD ThreadSleepDelta; + +int __cdecl main( int argc, char **argv ) +{ + int i; + DWORD dwAvgDelta; + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* + On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects + (such as conditions) involves some pthread internal initialization that + can make the first wait slighty longer, potentially going above the + acceptable delta for this test. Let's add a dummy wait to preinitialize + internal structures + */ + Sleep(100); + + /* + * Check that Queueing an APC in the middle of a sleep does interrupt + * it, if it's in an alertable state. + */ + dwAvgDelta = 0; + for (i=0;i AcceptableDelta) + { + Fail("Expected thread to sleep for %d ms (and get interrupted).\n" + "Average delta: %u ms, acceptable delta: %u\n", + InterruptTime, dwAvgDelta, AcceptableDelta); + } + + /* + * Check that Queueing an APC in the middle of a sleep does NOT interrupt + * it, if it is not in an alertable state. + */ + dwAvgDelta = 0; + for (i=0;i AcceptableDelta) + { + Fail("Expected thread to sleep for %d ms (and not be interrupted).\n" + "Average delta: %u ms, acceptable delta: %u\n", + ChildThreadSleepTime, dwAvgDelta, AcceptableDelta); + } + + PAL_Terminate(); + return PASS; +} + +void RunTest(BOOL AlertThread) +{ + HANDLE hThread = 0; + DWORD dwThreadId = 0; + int ret; + + hThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)SleeperProc, + (LPVOID) AlertThread, + 0, + &dwThreadId); + + if (hThread == NULL) + { + Fail("ERROR: Was not able to create the thread to test SleepEx!\n" + "GetLastError returned %d\n", GetLastError()); + } + + if (SleepEx(InterruptTime, FALSE) != 0) + { + Fail("The creating thread did not sleep!\n"); + } + + ret = QueueUserAPC(APCFunc, hThread, 0); + if (ret == 0) + { + Fail("QueueUserAPC failed! GetLastError returned %d\n", GetLastError()); + } + + ret = WaitForSingleObject(hThread, INFINITE); + if (ret == WAIT_FAILED) + { + Fail("Unable to wait on child thread!\nGetLastError returned %d.", + GetLastError()); + } +} + +/* Function doesn't do anything, just needed to interrupt SleepEx */ +VOID PALAPI APCFunc(ULONG_PTR dwParam) +{ + +} + +/* Entry Point for child thread. */ +DWORD PALAPI SleeperProc(LPVOID lpParameter) +{ + UINT64 OldTimeStamp; + UINT64 NewTimeStamp; + BOOL Alertable; + DWORD ret; + + Alertable = (BOOL)(SIZE_T) lpParameter; + + LARGE_INTEGER performanceFrequency; + if (!QueryPerformanceFrequency(&performanceFrequency)) + { + return FAIL; + } + + OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency); + + ret = SleepEx(ChildThreadSleepTime, Alertable); + + NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency); + + if (Alertable && ret != WAIT_IO_COMPLETION) + { + Fail("Expected the interrupted sleep to return WAIT_IO_COMPLETION.\n" + "Got %d\n", ret); + } + else if (!Alertable && ret != 0) + { + Fail("Sleep did not timeout. Expected return of 0, got %d.\n", ret); + } + + + ThreadSleepDelta = NewTimeStamp - OldTimeStamp; + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test2/testinfo.dat new file mode 100644 index 0000000..52f3ce0 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SleepEx/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = SleepEx +Name = Test #2 for SleepEx +TYPE = DEFAULT +EXE1 = test2 +Description +=Tests that a child thread in the middle of a SleepEx call will be +=interrupted by QueueUserAPC if the alert flag was set. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/test1/CMakeLists.txt new file mode 100644 index 0000000..4eae7ed --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_switchtothread_test1 + ${SOURCES} +) + +add_dependencies(paltest_switchtothread_test1 coreclrpal) + +target_link_libraries(paltest_switchtothread_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/test1/test1.cpp new file mode 100644 index 0000000..ce03021 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/test1/test1.cpp @@ -0,0 +1,97 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure SwitchToThread works, without +** causing test to hang +** +** Dependencies: PAL_Initialize +** Fail +** SwitchToThread +** WaitForMultipleObject +** CreateThread +** GetLastError +** + +** +**===========================================================================*/ + + +#include +#define THREAD_COUNT 10 +#define REPEAT_COUNT 1000 +#define TIMEOUT 60000 +void PALAPI Run_Thread(LPVOID lpParam); + +/** + * main + * + * executable entry point + */ +INT __cdecl main( INT argc, CHAR **argv ) +{ + DWORD dwParam; + HANDLE hThread[THREAD_COUNT]; + DWORD threadId[THREAD_COUNT]; + + int i = 0; + int returnCode = 0; + + /*PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return FAIL; + } + + + for( i = 0; i < THREAD_COUNT; i++ ) + { + dwParam = (int) i; + //Create thread + hThread[i] = CreateThread( + NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */ + (LPVOID)dwParam, /* argument to thread function */ + 0, /* use default creation flags */ + &threadId[i] /* returns the thread identifier*/ + ); + + if(hThread[i] == NULL) + { + Fail("Create Thread failed for iteration %d GetLastError value is %d\n", i, GetLastError()); + } + + } + + + returnCode = WaitForMultipleObjects(THREAD_COUNT, hThread, TRUE, TIMEOUT); + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) returned %d, expected value is %d, and GetLastError value is %d\n", returnCode, WAIT_OBJECT_0, GetLastError()); + } + + PAL_Terminate(); + return PASS; + +} + +void PALAPI Run_Thread (LPVOID lpParam) +{ + int i = 0; + int Id=(int)(SIZE_T)lpParam; + + for(i=0; i < REPEAT_COUNT; i++ ) + { + // No Last Error is set.. + if(!SwitchToThread()) + { + Trace( "The operating system did not switch execution to another thread," + "for thread id[%d], iteration [%d]\n", Id, i ); + } + } +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/test1/testinfo.dat new file mode 100644 index 0000000..15ee8d4 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/SwitchToThread/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = threading +Function = SwitchToThread +Name = Test for SwitchToThread +TYPE = DEFAULT +EXE1 = test +Description += Purpose: Test to ensure SwitchToThread is += working properly on supported platforms diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/test1/CMakeLists.txt new file mode 100644 index 0000000..24e4e4b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + TerminateProcess.cpp +) + +add_executable(paltest_terminateprocess_test1 + ${SOURCES} +) + +add_dependencies(paltest_terminateprocess_test1 coreclrpal) + +target_link_libraries(paltest_terminateprocess_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/test1/TerminateProcess.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/test1/TerminateProcess.cpp new file mode 100644 index 0000000..6feedfc --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/test1/TerminateProcess.cpp @@ -0,0 +1,41 @@ +// 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. + +/*============================================================ +** +** Source: terminateprocess/test1/terminateprocess.c +** +** Purpose: Test to see if TerminateProcess will +** terminate the current process. +** +** Dependencies: GetCurrentProcess +** +** +**=========================================================*/ + +#include + +INT __cdecl main( int argc, char **argv ) +{ + + HANDLE hProcess; + + if(0 != (PAL_Initialize(argc, argv))) + { + return (FAIL); + } + + hProcess = GetCurrentProcess(); + + Trace ("Testing TerminateProcess function.\n"); + + if ( 0 == ( TerminateProcess ( hProcess, PASS ) ) ) + { + Fail ("TerminateProcess failed.\n"); + } + + PAL_TerminateEx(FAIL); + return (FAIL); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/test1/testinfo.dat new file mode 100644 index 0000000..7ee69bf --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/TerminateProcess/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = TerminateProcess +Name = Positive Test for TerminateProcess +TYPE = DEFAULT +EXE1 = terminateprocess +Description += Test to see if the function TerminateProcess terminates the currently += running process and passes the appropriate value through uExitCode. + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/test1/CMakeLists.txt new file mode 100644 index 0000000..333586e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + ThreadPriority.cpp +) + +add_executable(paltest_threadpriority_test1 + ${SOURCES} +) + +add_dependencies(paltest_threadpriority_test1 coreclrpal) + +target_link_libraries(paltest_threadpriority_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/test1/ThreadPriority.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/test1/ThreadPriority.cpp new file mode 100644 index 0000000..95bcdac --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/test1/ThreadPriority.cpp @@ -0,0 +1,83 @@ +// 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. + +/*============================================================================= +** +** Source: threadpriority.c +** +** Purpose: Test to ensure GetThreadPriority works properly. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** CreateThread +** WaitForSingleObject +** GetLastError +** time() +** + +** +**===========================================================================*/ +#include + +/** + * CheckThreadPriority + * + * Helper function that checks the current thread priority + * against an expected value. + */ +static VOID CheckThreadPriority( HANDLE hThread, int expectedPriority ) +{ + int priority; + DWORD dwError = 0; + + /* get the current thread priority */ + priority = GetThreadPriority( hThread ); + if( priority == THREAD_PRIORITY_ERROR_RETURN ) + { + /* GetThreadPriority call failed */ + dwError = GetLastError(); + Fail( "Unexpected GetThreadPriority() failure " + "with error %d\n", dwError ); + } + else if( priority != expectedPriority ) + { + /* unexpected thread priority detected */ + Fail( "Unexpected initial thread priority value %d reported\n", + priority ); + } +} + + +/** + * main + * + * executable entry point + */ +INT __cdecl main( INT argc, CHAR **argv ) +{ + + /* PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return( FAIL ); + } + + /* set the thread priority of the main to the highest possible value + this will give the chance to the main thread to create all the + other threads */ + if(!SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_NORMAL)) + { + DWORD dwError; + + dwError = GetLastError(); + Fail( "Unexpected SetThreadPriority() failure with error %d\n", + dwError ); + } + + CheckThreadPriority( GetCurrentThread(), THREAD_PRIORITY_NORMAL ); + //Add verification of timing out here.. + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/test1/testinfo.dat new file mode 100644 index 0000000..0abd9c1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/ThreadPriority/test1/testinfo.dat @@ -0,0 +1,17 @@ +# 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. + +Version = 1.0 +Section = threading +Function = ThreadPriority +Name = Test for GetThreadPriority and SetThreadPriority +TYPE = DEFAULT +EXE1 = threadpriority +Description += Test to ensure proper operation of the GetThreadPriority += and SetThreadPriority APIs. The test launches several threads += of varying priorities, and verifies that the correct priority += is reported for each. It also verifies that the processing += time for each test thread is consistent with the priority += that's set for it. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/CMakeLists.txt new file mode 100644 index 0000000..7825b6a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_waitformultipleobjects_test1 + ${SOURCES} +) + +add_dependencies(paltest_waitformultipleobjects_test1 coreclrpal) + +target_link_libraries(paltest_waitformultipleobjects_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/test1.cpp new file mode 100644 index 0000000..8249c38 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/test1.cpp @@ -0,0 +1,224 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for WaitForMultipleObjects. Call the function +** on an array of 4 events, and ensure that it returns correct +** results when we do so. +** +** +**=========================================================*/ + +#include + +/* Number of events in array */ +#define MAX_EVENTS 4 + +BOOL WaitForMultipleObjectsTest() +{ + BOOL bRet = TRUE; + DWORD dwRet = 0; + + DWORD i = 0, j = 0; + + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + BOOL bManualReset = TRUE; + BOOL bInitialState = TRUE; + + HANDLE hEvent[MAX_EVENTS]; + + /* Run through this for loop and create 4 events */ + for (i = 0; i < MAX_EVENTS; i++) + { + hEvent[i] = CreateEvent( lpEventAttributes, + bManualReset, bInitialState, NULL); + + if (hEvent[i] == INVALID_HANDLE_VALUE) + { + Trace("WaitForMultipleObjectsTest:CreateEvent %u failed (%x)\n", i, GetLastError()); + bRet = FALSE; + break; + } + + /* Set the current event */ + bRet = SetEvent(hEvent[i]); + + if (!bRet) + { + Trace("WaitForMultipleObjectsTest:SetEvent %u failed (%x)\n", i, GetLastError()); + bRet = FALSE; + break; + } + + /* Ensure that this returns the correct value */ + dwRet = WaitForSingleObject(hEvent[i],0); + + if (dwRet != WAIT_OBJECT_0) + { + Trace("WaitForMultipleObjectsTest:WaitForSingleObject %u failed (%x)\n", i, GetLastError()); + bRet = FALSE; + break; + } + + /* Reset the event, and again ensure that the return value of + WaitForSingle is correct. + */ + bRet = ResetEvent(hEvent[i]); + + if (!bRet) + { + Trace("WaitForMultipleObjectsTest:ResetEvent %u failed (%x)\n", i, GetLastError()); + bRet = FALSE; + break; + } + + dwRet = WaitForSingleObject(hEvent[i],0); + + if (dwRet != WAIT_TIMEOUT) + { + Trace("WaitForMultipleObjectsTest:WaitForSingleObject %u failed (%x)\n", i, GetLastError()); + bRet = FALSE; + break; + } + } + + /* + * If the first section of the test passed, move on to the + * second. + */ + + if (bRet) + { + BOOL bWaitAll = TRUE; + DWORD nCount = MAX_EVENTS; + CONST HANDLE *lpHandles = &hEvent[0]; + + /* Call WaitForMultipleOjbects on all the events, the return + should be WAIT_TIMEOUT + */ + dwRet = WaitForMultipleObjects( nCount, + lpHandles, + bWaitAll, + 0); + + if (dwRet != WAIT_TIMEOUT) + { + Trace("WaitForMultipleObjectsTest:WaitForMultipleObjects failed (%x)\n", GetLastError()); + } + else + { + /* Step through each event and one at a time, set the + currect test, while reseting all the other tests + */ + + for (i = 0; i < MAX_EVENTS; i++) + { + for (j = 0; j < MAX_EVENTS; j++) + { + if (j == i) + { + + bRet = SetEvent(hEvent[j]); + + if (!bRet) + { + Trace("WaitForMultipleObjectsTest:SetEvent %u failed (%x)\n", j, GetLastError()); + break; + } + } + else + { + bRet = ResetEvent(hEvent[j]); + + if (!bRet) + { + Trace("WaitForMultipleObjectsTest:ResetEvent %u failed (%x)\n", j, GetLastError()); + } + } + } + + bWaitAll = FALSE; + + /* Check that WaitFor returns WAIT_OBJECT + i */ + dwRet = WaitForMultipleObjects( nCount, + lpHandles, bWaitAll, 0); + + if (dwRet != WAIT_OBJECT_0+i) + { + Trace("WaitForMultipleObjectsTest:WaitForMultipleObjects failed (%x)\n", GetLastError()); + bRet = FALSE; + break; + } + } + } + + for (i = 0; i < MAX_EVENTS; i++) + { + bRet = CloseHandle(hEvent[i]); + + if (!bRet) + { + Trace("WaitForMultipleObjectsTest:CloseHandle %u failed (%x)\n", i, GetLastError()); + } + } + } + + return bRet; +} + +BOOL WaitMultipleDuplicateHandleTest() +{ + BOOL testResult = TRUE; + const HANDLE eventHandle = CreateEvent(NULL, TRUE, TRUE, NULL); + HANDLE eventHandles[] = {eventHandle, eventHandle}; + + // WaitAny - Wait for any of the events (no error expected) + DWORD result = WaitForMultipleObjects(sizeof(eventHandles) / sizeof(eventHandles[0]), eventHandles, FALSE, 0); + if (result != WAIT_OBJECT_0) + { + Trace("WaitMultipleDuplicateHandleTest:WaitAny failed (%x)\n", GetLastError()); + testResult = FALSE; + } + + // WaitAll - Wait for all of the events (error expected) + result = WaitForMultipleObjects(sizeof(eventHandles) / sizeof(eventHandles[0]), eventHandles, TRUE, 0); + if (result != WAIT_FAILED) + { + Trace("WaitMultipleDuplicateHandleTest:WaitAll failed: call unexpectedly succeeded\n"); + testResult = FALSE; + } + else if (GetLastError() != ERROR_INVALID_PARAMETER) + { + Trace("WaitMultipleDuplicateHandleTest:WaitAll failed: unexpected last error (%x)\n"); + testResult = FALSE; + } + + return testResult; +} + +int __cdecl main(int argc, char **argv) +{ + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!WaitForMultipleObjectsTest()) + { + Fail ("Test failed\n"); + } + + if (!WaitMultipleDuplicateHandleTest()) + { + Fail("Test failed\n"); + } + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/testinfo.dat new file mode 100644 index 0000000..38bd350 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = WaitForMultipleObjects +Name = Positive Test for WaitForMultipleObjects +TYPE = DEFAULT +EXE1 = test1 +Description += Test for WaitForMultipleObjects. Call the function += on an array of 4 events, and ensure that it returns correct += results when we do so. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/CMakeLists.txt new file mode 100644 index 0000000..828a287 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/CMakeLists.txt @@ -0,0 +1,7 @@ +add_subdirectory(test1) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test5) +add_subdirectory(test6) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/CMakeLists.txt new file mode 100644 index 0000000..b6598c9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_waitformultipleobjectsex_test1 + ${SOURCES} +) + +add_dependencies(paltest_waitformultipleobjectsex_test1 coreclrpal) + +target_link_libraries(paltest_waitformultipleobjectsex_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/test1.cpp new file mode 100644 index 0000000..df3233f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/test1.cpp @@ -0,0 +1,226 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for WaitForMultipleObjectsEx. Call the function +** on an array of 4 events, and ensure that it returns correct +** results when we do so. +** +** +**=========================================================*/ + +#include + +/* Originally written as WaitForMultipleObjects/test1 */ + + +/* Number of events in array */ +#define MAX_EVENTS 4 + +BOOL WaitForMultipleObjectsExTest() +{ + BOOL bRet = TRUE; + DWORD dwRet = 0; + DWORD i = 0, j = 0; + + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + BOOL bManualReset = TRUE; + BOOL bInitialState = TRUE; + + HANDLE hEvent[MAX_EVENTS]; + + /* Run through this for loop and create 4 events */ + for (i = 0; i < MAX_EVENTS; i++) + { + hEvent[i] = CreateEvent( lpEventAttributes, + bManualReset, bInitialState, NULL); + + if (hEvent[i] == INVALID_HANDLE_VALUE) + { + Trace("WaitForMultipleObjectsExTest:CreateEvent %u failed (%x)\n", i, GetLastError()); + bRet = FALSE; + break; + } + + /* Set the current event */ + bRet = SetEvent(hEvent[i]); + + if (!bRet) + { + Trace("WaitForMultipleObjectsExTest:SetEvent %u failed (%x)\n", i, GetLastError()); + bRet = FALSE; + break; + } + + /* Ensure that this returns the correct value */ + dwRet = WaitForSingleObject(hEvent[i],0); + + if (dwRet != WAIT_OBJECT_0) + { + Trace("WaitForMultipleObjectsExTest:WaitForSingleObject %u failed (%x)\n", i, GetLastError()); + bRet = FALSE; + break; + } + + /* Reset the event, and again ensure that the return value of + WaitForSingle is correct. + */ + bRet = ResetEvent(hEvent[i]); + + if (!bRet) + { + Trace("WaitForMultipleObjectsExTest:ResetEvent %u failed (%x)\n", i, GetLastError()); + bRet = FALSE; + break; + } + + dwRet = WaitForSingleObject(hEvent[i],0); + + if (dwRet != WAIT_TIMEOUT) + { + Trace("WaitForMultipleObjectsExTest:WaitForSingleObject %u failed (%x)\n", i, GetLastError()); + bRet = FALSE; + break; + } + } + + /* + * If the first section of the test passed, move on to the + * second. + */ + + if (bRet) + { + BOOL bWaitAll = TRUE; + DWORD nCount = MAX_EVENTS; + CONST HANDLE *lpHandles = &hEvent[0]; + + /* Call WaitForMultipleObjectsEx on all the events, the return + should be WAIT_TIMEOUT + */ + dwRet = WaitForMultipleObjectsEx(nCount, + lpHandles, + bWaitAll, + 0, + FALSE); + + if (dwRet != WAIT_TIMEOUT) + { + Trace("WaitForMultipleObjectsExTest: WaitForMultipleObjectsEx failed (%x)\n", GetLastError()); + } + else + { + /* Step through each event and one at a time, set the + currect test, while reseting all the other tests + */ + + for (i = 0; i < MAX_EVENTS; i++) + { + for (j = 0; j < MAX_EVENTS; j++) + { + if (j == i) + { + + bRet = SetEvent(hEvent[j]); + + if (!bRet) + { + Trace("WaitForMultipleObjectsExTest:SetEvent %j failed (%x)\n", j, GetLastError()); + break; + } + } + else + { + bRet = ResetEvent(hEvent[j]); + + if (!bRet) + { + Trace("WaitForMultipleObjectsExTest:ResetEvent %u failed (%x)\n", j, GetLastError()); + } + } + } + + bWaitAll = FALSE; + + /* Check that WaitFor returns WAIT_OBJECT + i */ + dwRet = WaitForMultipleObjectsEx( nCount, + lpHandles, bWaitAll, 0, FALSE); + + if (dwRet != WAIT_OBJECT_0+i) + { + Trace("WaitForMultipleObjectsExTest: WaitForMultipleObjectsEx failed (%x)\n", GetLastError()); + bRet = FALSE; + break; + } + } + } + + for (i = 0; i < MAX_EVENTS; i++) + { + bRet = CloseHandle(hEvent[i]); + + if (!bRet) + { + Trace("WaitForMultipleObjectsExTest:CloseHandle %u failed (%x)\n", i, GetLastError()); + } + } + } + + return bRet; +} + +BOOL WaitMultipleDuplicateHandleTest() +{ + BOOL testResult = TRUE; + const HANDLE eventHandle = CreateEvent(NULL, TRUE, TRUE, NULL); + HANDLE eventHandles[] = {eventHandle, eventHandle}; + + // WaitAny - Wait for any of the events (no error expected) + DWORD result = WaitForMultipleObjects(sizeof(eventHandles) / sizeof(eventHandles[0]), eventHandles, FALSE, 0); + if (result != WAIT_OBJECT_0) + { + Trace("WaitMultipleDuplicateHandleTest:WaitAny failed (%x)\n", GetLastError()); + testResult = FALSE; + } + + // WaitAll - Wait for all of the events (error expected) + result = WaitForMultipleObjects(sizeof(eventHandles) / sizeof(eventHandles[0]), eventHandles, TRUE, 0); + if (result != WAIT_FAILED) + { + Trace("WaitMultipleDuplicateHandleTest:WaitAll failed: call unexpectedly succeeded\n"); + testResult = FALSE; + } + else if (GetLastError() != ERROR_INVALID_PARAMETER) + { + Trace("WaitMultipleDuplicateHandleTest:WaitAll failed: unexpected last error (%x)\n"); + testResult = FALSE; + } + + return testResult; +} + +int __cdecl main(int argc, char **argv) +{ + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!WaitForMultipleObjectsExTest()) + { + Fail ("Test failed\n"); + } + + if (!WaitMultipleDuplicateHandleTest()) + { + Fail("Test failed\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/testinfo.dat new file mode 100644 index 0000000..596c4bb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = WaitForMultipleObjectsEx +Name = Test #1 for WaitForMultipleObjectsEx +TYPE = DEFAULT +EXE1 = test1 +Description += Test for WaitForMultipleObjectsEx. Call the function += on an array of 4 events, and ensure that it returns correct += results when we do so. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/CMakeLists.txt new file mode 100644 index 0000000..8379cc8 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test2.cpp +) + +add_executable(paltest_waitformultipleobjectsex_test2 + ${SOURCES} +) + +add_dependencies(paltest_waitformultipleobjectsex_test2 coreclrpal) + +target_link_libraries(paltest_waitformultipleobjectsex_test2 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.cpp new file mode 100644 index 0000000..ffa496d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.cpp @@ -0,0 +1,188 @@ +// 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. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Tests that a child thread in the middle of a +** WaitForMultipleObjectsEx call will be interrupted by QueueUserAPC +** if the alert flag was set. +** +** +**===================================================================*/ + +#include + +/* Based on SleepEx/test2 */ + +const unsigned int ChildThreadWaitTime = 1000; +const unsigned int InterruptTime = 500; + +#define TOLERANCE 10 + +void RunTest(BOOL AlertThread); +VOID PALAPI APCFunc(ULONG_PTR dwParam); +DWORD PALAPI WaiterProc(LPVOID lpParameter); + +DWORD ThreadWaitDelta; + +int __cdecl main( int argc, char **argv ) +{ + + DWORD delta = 0; + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* + On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects + (such as conditions) involves some pthread internal initialization that + can make the first wait slighty longer, potentially going above the + acceptable delta for this test. Let's add a dummy wait to preinitialize + internal structures + */ + Sleep(100); + + + /* + * Check that Queueing an APC in the middle of a wait does interrupt + * it, if it's in an alertable state. + */ + RunTest(TRUE); + // Make sure that the wait returns in time greater than interrupt and less than + // wait timeout + if ( + ((ThreadWaitDelta >= ChildThreadWaitTime) && (ThreadWaitDelta - ChildThreadWaitTime) > TOLERANCE) + || (( ThreadWaitDelta < InterruptTime) && (ThreadWaitDelta - InterruptTime) > TOLERANCE) + ) + { + Fail("Expected thread to wait for %d ms (and get interrupted).\n" + "Interrupt Time: %d ms, ThreadWaitDelta %u\n", + ChildThreadWaitTime, InterruptTime, ThreadWaitDelta); + } + + /* + * Check that Queueing an APC in the middle of a wait does NOT interrupt + * it, if it is not in an alertable state. + */ + RunTest(FALSE); + + // Make sure that time taken for thread to return from wait is more than interrupt + // and also not less than the complete child thread wait time + + delta = ThreadWaitDelta - ChildThreadWaitTime; + if( (ThreadWaitDelta < ChildThreadWaitTime) && ( delta > TOLERANCE) ) + { + Fail("Expected thread to wait for %d ms (and not get interrupted).\n" + "Interrupt Time: %d ms, ThreadWaitDelta %u\n", + ChildThreadWaitTime, InterruptTime, ThreadWaitDelta); + } + + + PAL_Terminate(); + return PASS; +} + +void RunTest(BOOL AlertThread) +{ + HANDLE hThread = 0; + DWORD dwThreadId = 0; + int ret; + + hThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)WaiterProc, + (LPVOID) AlertThread, + 0, + &dwThreadId); + + if (hThread == NULL) + { + Fail("ERROR: Was not able to create the thread to test!\n" + "GetLastError returned %d\n", GetLastError()); + } + + Sleep(InterruptTime); + + ret = QueueUserAPC(APCFunc, hThread, 0); + if (ret == 0) + { + Fail("QueueUserAPC failed! GetLastError returned %d\n", + GetLastError()); + } + + ret = WaitForSingleObject(hThread, INFINITE); + if (ret == WAIT_FAILED) + { + Fail("Unable to wait on child thread!\nGetLastError returned %d.\n", + GetLastError()); + } +} + +/* Function doesn't do anything, just needed to interrupt the wait*/ +VOID PALAPI APCFunc(ULONG_PTR dwParam) +{ +} + +/* Entry Point for child thread. */ +DWORD PALAPI WaiterProc(LPVOID lpParameter) +{ + HANDLE Semaphore; + UINT64 OldTimeStamp; + UINT64 NewTimeStamp; + BOOL Alertable; + DWORD ret; + + /* Create a semaphore that is not in the signalled state */ + Semaphore = CreateSemaphoreW(NULL, 0, 1, NULL); + + if (Semaphore == NULL) + { + Fail("Failed to create semaphore! GetLastError returned %d.\n", + GetLastError()); + } + + Alertable = (BOOL)(SIZE_T) lpParameter; + + LARGE_INTEGER performanceFrequency; + if (!QueryPerformanceFrequency(&performanceFrequency)) + { + Fail("Failed to query performance frequency!"); + } + + OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency); + + ret = WaitForMultipleObjectsEx(1, &Semaphore, FALSE, ChildThreadWaitTime, + Alertable); + + NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency); + + + if (Alertable && ret != WAIT_IO_COMPLETION) + { + Fail("Expected the interrupted wait to return WAIT_IO_COMPLETION.\n" + "Got %d\n", ret); + } + else if (!Alertable && ret != WAIT_TIMEOUT) + { + Fail("WaitForMultipleObjectsEx did not timeout.\n" + "Expected return of WAIT_TIMEOUT, got %d.\n", ret); + } + + ThreadWaitDelta = NewTimeStamp - OldTimeStamp; + + ret = CloseHandle(Semaphore); + if (!ret) + { + Fail("Unable to close handle to semaphore!\n" + "GetLastError returned %d\n", GetLastError()); + } + + return 0; +} + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/testinfo.dat new file mode 100644 index 0000000..e8e781a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = WaitForMultipleObjectsEx +Name = Test #2 for WaitForMultipleObjectsEx +TYPE = DEFAULT +EXE1 = test2 +Description +=Tests that a child thread in the middle of a +=WaitForMultipleObjectsEx call will be interrupted by QueueUserAPC +=if the alert flag was set. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/CMakeLists.txt new file mode 100644 index 0000000..ce267b1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test3.cpp +) + +add_executable(paltest_waitformultipleobjectsex_test3 + ${SOURCES} +) + +add_dependencies(paltest_waitformultipleobjectsex_test3 coreclrpal) + +target_link_libraries(paltest_waitformultipleobjectsex_test3 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/test3.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/test3.cpp new file mode 100644 index 0000000..b78b054 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/test3.cpp @@ -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. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Tests that waiting on an open mutex will a return +** WAIT_OBJECT_0. Does this by creating a child thread that +** acquires the mutex, releases it, and exits. +** +** +**===================================================================*/ + +#include + + +const int ChildThreadWaitTime = 1000; +const int ParentDelayTime = 2000; + +DWORD PALAPI AcquiringProc(LPVOID lpParameter); + +int __cdecl main( int argc, char **argv) +{ + HANDLE Mutex; + HANDLE hThread = 0; + DWORD dwThreadId = 0; + int ret; + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + Mutex = CreateMutexW(NULL, FALSE, NULL); + if (Mutex == NULL) + { + Fail("Unable to create the mutex. GetLastError returned %d\n", + GetLastError()); + } + + hThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)AcquiringProc, + (LPVOID) Mutex, + 0, + &dwThreadId); + + if (hThread == NULL) + { + Fail("ERROR: Was not able to create the thread to test!\n" + "GetLastError returned %d\n", GetLastError()); + } + + Sleep(ParentDelayTime); + + ret = WaitForMultipleObjectsEx(1, &Mutex, FALSE, INFINITE, FALSE); + if (ret != WAIT_OBJECT_0) + { + Fail("Expected WaitForMultipleObjectsEx to return WAIT_OBJECT_0\n" + "Got %d\n", ret); + } + + if (!CloseHandle(Mutex)) + { + Fail("CloseHandle on the mutex failed!\n"); + } + + if (!CloseHandle(hThread)) + { + Fail("CloseHandle on the thread failed!\n"); + } + + PAL_Terminate(); + return PASS; +} + +/* + * Entry Point for child thread. Acquries a mutex, releases it, and exits. + */ +DWORD PALAPI AcquiringProc(LPVOID lpParameter) +{ + HANDLE Mutex; + DWORD ret; + + Mutex = (HANDLE) lpParameter; + + Sleep(ChildThreadWaitTime); + + ret = WaitForSingleObject(Mutex, 0); + if (ret != WAIT_OBJECT_0) + { + Fail("Expected the WaitForSingleObject call on the mutex to succeed\n" + "Expected return of WAIT_OBJECT_0, got %d\n", ret); + } + + ret = ReleaseMutex(Mutex); + if (!ret) + { + Fail("Unable to release mutex! GetLastError returned %d\n", + GetLastError()); + } + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/testinfo.dat new file mode 100644 index 0000000..991b934 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = WaitForMultipleObjectsEx +Name = Test #3 for WaitForMultipleObjectsEx +TYPE = DEFAULT +EXE1 = test3 +Description +=Tests that waiting on an open mutex will a return +=WAIT_OBJECT_0. Does this by creating a child thread that +=acquires the mutex, releases it, and exits. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/CMakeLists.txt new file mode 100644 index 0000000..ed81a53 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test4.cpp +) + +add_executable(paltest_waitformultipleobjectsex_test4 + ${SOURCES} +) + +add_dependencies(paltest_waitformultipleobjectsex_test4 coreclrpal) + +target_link_libraries(paltest_waitformultipleobjectsex_test4 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/test4.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/test4.cpp new file mode 100644 index 0000000..15d0a38 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/test4.cpp @@ -0,0 +1,101 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c +** +** Purpose: Tests that waiting on an abandonded mutex will a return +** WAIT_ABANDONED_0. Does this by creating a child thread that +** acquires the mutex and exits. +** +** +**===================================================================*/ + +#include + + +const int ChildThreadWaitTime = 1000; +const int ParentDelayTime = 2000; + +DWORD PALAPI AbandoningProc(LPVOID lpParameter); + +int __cdecl main( int argc, char **argv ) +{ + HANDLE Mutex; + HANDLE hThread = 0; + DWORD dwThreadId = 0; + int ret; + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + Mutex = CreateMutexW(NULL, FALSE, NULL); + if (Mutex == NULL) + { + Fail("Unable to create the mutex. GetLastError returned %d\n", + GetLastError()); + } + + hThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)AbandoningProc, + (LPVOID) Mutex, + 0, + &dwThreadId); + + if (hThread == NULL) + { + Fail("ERROR: Was not able to create the thread to test!\n" + "GetLastError returned %d\n", GetLastError()); + } + + Sleep(ParentDelayTime); + + ret = WaitForMultipleObjectsEx(1, &Mutex, FALSE, INFINITE, FALSE); + if (ret != WAIT_ABANDONED_0) + { + Fail("Expected WaitForMultipleObjectsEx to return WAIT_ABANDONED_0\n" + "Got %d\n", ret); + } + + ReleaseMutex(Mutex); + if (!CloseHandle(Mutex)) + { + Fail("CloseHandle on the mutex failed!\n"); + } + + if (!CloseHandle(hThread)) + { + Fail("CloseHandle on the thread failed!\n"); + } + + PAL_Terminate(); + return PASS; +} + +/* + * Entry Point for child thread. Acquries a mutex and exit's without + * releasing it. + */ +DWORD PALAPI AbandoningProc(LPVOID lpParameter) +{ + HANDLE Mutex; + DWORD ret; + + Mutex = (HANDLE) lpParameter; + + Sleep(ChildThreadWaitTime); + + ret = WaitForSingleObject(Mutex, 0); + if (ret != WAIT_OBJECT_0) + { + Fail("Expected the WaitForSingleObject call on the mutex to succeed\n" + "Expected return of WAIT_OBJECT_0, got %d\n", ret); + } + + return 0; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/testinfo.dat new file mode 100644 index 0000000..16f3468 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = WaitForMultipleObjectsEx +Name = Test #4 for WaitForMultipleObjectsEx +TYPE = DEFAULT +EXE1 = test4 +Description +=Tests that waiting on an abandonded mutex will a return +=WAIT_ABANDONED_0. Does this by creating a child thread that +=acquires the mutex and exits. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/CMakeLists.txt new file mode 100644 index 0000000..bf7846a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + test5.cpp +) + +add_executable(paltest_waitformultipleobjectsex_test5 + ${TESTSOURCES} +) + +add_dependencies(paltest_waitformultipleobjectsex_test5 coreclrpal) + +target_link_libraries(paltest_waitformultipleobjectsex_test5 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + helper.cpp +) + +add_executable(paltest_waitformultipleobjectsex_test5_helper + ${HELPERSOURCES} +) + +add_dependencies(paltest_waitformultipleobjectsex_test5_helper coreclrpal) + +target_link_libraries(paltest_waitformultipleobjectsex_test5_helper + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/commonconsts.h b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/commonconsts.h new file mode 100644 index 0000000..b746616 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/commonconsts.h @@ -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. + +/*============================================================= +** +** Source: commonconsts.h +** +** +**============================================================*/ + +#ifndef _COMMONCONSTS_H_ +#define _COMMONCONSTS_H_ + +#include + +const int TIMEOUT = 60 * 5 * 1000; + +char *szcHelperProcessStartEvName = "start"; +char *szcHelperProcessReadyEvName = "ready"; +char *szcHelperProcessFinishEvName = "finish"; + +/* PEDANTIC and PEDANTIC0 is a helper macro that just grumps about any + * zero return codes in a generic way. with little typing */ +#define PEDANTIC(function, parameters) \ +{ \ + if (! (function parameters) ) \ + { \ + Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \ + __FILE__, #function, #parameters, GetLastError(), errno); \ + } \ +} +#define PEDANTIC1(function, parameters) \ +{ \ + if ( (function parameters) ) \ + { \ + Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \ + __FILE__, #function, #parameters, GetLastError(), errno); \ + } \ +} + +#endif diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.cpp new file mode 100644 index 0000000..caa0206 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.cpp @@ -0,0 +1,122 @@ +// 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. + +/*============================================================= +** +** Source: helper.c +** +** Purpose: This helper process sets up signals to communicate +** with the test thread in the parent process, and let the test +** thread signal this process when to exit. +** +** +**============================================================*/ + +#include "commonconsts.h" + +#include + +HANDLE hProcessStartEvent; +HANDLE hProcessReadyEvent; +HANDLE hProcessFinishEvent; +HANDLE hProcessCleanupEvent; + + +int __cdecl main(int argc, char *argv[]) +{ + + BOOL success = TRUE; /* assume success */ + DWORD dwRet; + DWORD dwProcessId; + char szEventName[MAX_LONGPATH]; + PWCHAR uniString; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Open the event to let test thread tell us to get started. */ + uniString = convert(szcHelperProcessStartEvName); + hProcessStartEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString); + free(uniString); + if (!hProcessStartEvent) + { + Fail("helper.main: OpenEvent of '%S' failed (%u). " + "(the event should already exist!)\n", + szcHelperProcessStartEvName, GetLastError()); + } + + /* Wait for signal from test thread. */ + dwRet = WaitForSingleObject(hProcessStartEvent, TIMEOUT); + if (dwRet != WAIT_OBJECT_0) + { + Fail("helper.main: WaitForSingleObject '%s' failed\n" + "LastError:(%u)\n", szcHelperProcessStartEvName, GetLastError()); + } + + dwProcessId = GetCurrentProcessId(); + + if ( 0 >= dwProcessId ) + { + Fail ("helper.main: %s has invalid pid %d\n", argv[0], dwProcessId ); + } + + /* Open the event to tell test thread we are ready. */ + if (sprintf_s(szEventName, MAX_LONGPATH-1, "%s%d", szcHelperProcessReadyEvName, dwProcessId) < 0) + { + Fail ("helper.main: Insufficient event name string length for pid=%d\n", dwProcessId); + } + + uniString = convert(szEventName); + + hProcessReadyEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString); + free(uniString); + if (!hProcessReadyEvent) + { + Fail("helper.main: OpenEvent of '%s' failed (%u). " + "(the event should already exist!)\n", + szEventName, GetLastError()); + } + + /* Open the event to let test thread tell us to exit. */ + if (sprintf_s(szEventName, MAX_LONGPATH-1, "%s%d", szcHelperProcessFinishEvName, dwProcessId) < 0) + { + Fail ("helper.main: Insufficient event name string length for pid=%d\n", dwProcessId); + } + + uniString = convert(szEventName); + + hProcessFinishEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString); + free(uniString); + if (!hProcessFinishEvent) + { + Fail("helper.main: OpenEvent of '%s' failed LastError:(%u).\n", + szEventName, GetLastError()); + } + + /* Tell the test thread we are ready. */ + if (!SetEvent(hProcessReadyEvent)) + { + Fail("helper.main: SetEvent '%s' failed LastError:(%u)\n", + hProcessReadyEvent, GetLastError()); + } + + /* Wait for signal from test thread before exit. */ + dwRet = WaitForSingleObject(hProcessFinishEvent, TIMEOUT); + if (WAIT_OBJECT_0 != dwRet) + { + Fail("helper.main: WaitForSingleObject '%s' failed pid=%d\n" + "LastError:(%u)\n", + szcHelperProcessFinishEvName, dwProcessId, GetLastError()); + } + + PEDANTIC(CloseHandle, (hProcessStartEvent)); + PEDANTIC(CloseHandle, (hProcessReadyEvent)); + PEDANTIC(CloseHandle, (hProcessFinishEvent)); + + PAL_Terminate(); + + return success ? PASS : FAIL; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.cpp new file mode 100644 index 0000000..4d1a5ce --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.cpp @@ -0,0 +1,506 @@ +// 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. + +/*============================================================= +** +** Source: test5.c +** +** Purpose: Test the functionality of simultaneously waiting +** on multiple processes. Create the same number of helper +** processes and helper threads. +** Helper threads wait on helper processes to finish. +** Helper processes wait on the event signal from test +** thread before exit. +** The test thread can wake up one helper +** thread at a time by signaling the corresponding helper +** process to finish. +** The test thread can also wake up all helper threads at once +** by signaling help process 0 to exit. +** +** +**============================================================*/ + +#define UNICODE + +#include "commonconsts.h" + +#include + +/* The maximum number of objects a thread can wait is MAXIMUM_WAIT_OBJECTS. + The last helper thread in this test case will wait on all helper processes + plus a thread finish event so the maximum number of helper processes + can be created in this test case is (MAXIMUM_WAIT_OBJECTS-1). */ +#define MAX_HELPER_PROCESS (MAXIMUM_WAIT_OBJECTS-1) + +int MaxNumHelperProcess = MAX_HELPER_PROCESS; + +/* indicate how the test thread wake up helper thread. */ +typedef enum _TestCaseType { + WakeUpOneThread, /* wake up one helper thread at a time. */ + WakeUpAllThread /* wake up all helper threads at once */ +} TestCaseType; + +TestCaseType TestCase = WakeUpOneThread; + +/* When the test thread wakes up one thread at a time, + ThreadIndexOfThreadFinishEvent specifies the index of the thread that + should be waked up using hThreadFinishEvent instead of helper process. */ +DWORD ThreadIndexOfThreadFinishEvent = 0; + +struct helper_process_t +{ + PROCESS_INFORMATION pi; + HANDLE hProcessReadyEvent; + HANDLE hProcessFinishEvent; +} helper_process[MAX_HELPER_PROCESS]; + +HANDLE hProcessStartEvent; + +struct helper_thread_t +{ + HANDLE hThread; + DWORD dwThreadId; + HANDLE hThreadReadyEvent; + HANDLE hThreadFinishEvent; +} helper_thread[MAX_HELPER_PROCESS]; + +/* + * Entry Point for helper thread. + */ +DWORD PALAPI WaitForProcess(LPVOID lpParameter) +{ + DWORD index, i; + DWORD dwRet; + HANDLE handles[MAX_HELPER_PROCESS+1]; + + index = (DWORD)(SIZE_T) lpParameter; + + /* The helper thread 0 will wait for helper process 0, helper thread 1 will + wait for helper process 0 and 1, helper thread 2 will wait for helper + process 0, 1, and 2, and so on ..., and the last helper thread will wait + on all helper processes. + Each helper thread also waits on hThreadFinishEvent so that + it can exit without waiting on any process to finish. */ + + for (i = 0; i <= index; i++) + { + handles[i] = helper_process[i].pi.hProcess; + } + + handles[index+1] = helper_thread[index].hThreadFinishEvent; + + if(!SetEvent(helper_thread[index].hThreadReadyEvent)) + { + Fail("test5.WaitProcess: SetEvent of hThreadReadyEvent failed for thread %d. " + "GetLastError() returned %d.\n", index, + GetLastError()); + } + + dwRet = WaitForMultipleObjectsEx(index+2, &handles[0], FALSE, TIMEOUT, TRUE); + if (WakeUpAllThread == TestCase) + { + /* If the test thread signals helper process 0 to exit, all threads will be waked up, + and the return value must be (WAIT_OBJECT_0+0) because the handle of helper process 0 + is in handle[0]. */ + if (dwRet != (WAIT_OBJECT_0+0)) + { + Fail("test5.WaitForProcess: invalid return value %d for WakupAllThread from WaitForMultipleObjectsEx for thread %d\n" + "LastError:(%u)\n", + dwRet, index, + GetLastError()); + } + } + else if (WakeUpOneThread == TestCase) + { + /* If the test thread wakes up one helper thread at a time, + the return value must be either (WAIT_OBJECT_0+index) if the helper thread + wakes up because the corresponding help process exits, + or (index+1) if the helper thread wakes up because of hThreadReadyEvent. */ + if ((index != ThreadIndexOfThreadFinishEvent && dwRet != (WAIT_OBJECT_0+index)) || + (index == ThreadIndexOfThreadFinishEvent && dwRet != (index+1))) + { + Fail("test5.WaitForProcess: invalid return value %d for WakupOneThread from WaitForMultipleObjectsEx for thread %d\n" + "LastError:(%u)\n", + dwRet, index, + GetLastError()); + } + } + else + { + Fail("Unknown TestCase %d\n", TestCase); + } + return 0; +} + +/* + * Setup the helper processes and helper threads. + */ +void +Setup() +{ + + STARTUPINFO si; + DWORD dwRet; + int i; + + char szEventName[MAX_PATH]; + PWCHAR uniStringHelper; + PWCHAR uniString; + + /* Create the event to start helper process after it was created. */ + uniString = convert(szcHelperProcessStartEvName); + hProcessStartEvent = CreateEvent(NULL, TRUE, FALSE, uniString); + free(uniString); + if (!hProcessStartEvent) + { + Fail("test5.Setup: CreateEvent of '%s' failed. " + "GetLastError() returned %d.\n", szcHelperProcessStartEvName, + GetLastError()); + } + + /* Create the helper processes. */ + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + uniStringHelper = convert("helper"); + for (i = 0; i < MaxNumHelperProcess; i++) + { + ZeroMemory( &helper_process[i].pi, sizeof(PROCESS_INFORMATION)); + + if(!CreateProcess( NULL, uniStringHelper, NULL, NULL, + FALSE, 0, NULL, NULL, &si, &helper_process[i].pi)) + { + Fail("test5.Setup: CreateProcess failed to load executable for helper process %d. " + "GetLastError() returned %u.\n", + i, GetLastError()); + } + + /* Create the event to let helper process tell us it is ready. */ + if (sprintf_s(szEventName, MAX_PATH-1, "%s%d", + szcHelperProcessReadyEvName, helper_process[i].pi.dwProcessId) < 0) + { + Fail ("test5.Setup: Insufficient event name string length for %s\n", szcHelperProcessReadyEvName); + } + + uniString = convert(szEventName); + + helper_process[i].hProcessReadyEvent = CreateEvent(NULL, FALSE, FALSE, uniString); + free(uniString); + if (!helper_process[i].hProcessReadyEvent) + { + Fail("test5.Setup: CreateEvent of '%s' failed. " + "GetLastError() returned %d.\n", szEventName, + GetLastError()); + } + + /* Create the event to tell helper process to exit. */ + if (sprintf_s(szEventName, MAX_PATH-1, "%s%d", + szcHelperProcessFinishEvName, helper_process[i].pi.dwProcessId) < 0) + { + Fail ("test5.Setup: Insufficient event name string length for %s\n", szcHelperProcessFinishEvName); + } + + uniString = convert(szEventName); + + helper_process[i].hProcessFinishEvent = CreateEvent(NULL, TRUE, FALSE, uniString); + free(uniString); + if (!helper_process[i].hProcessFinishEvent) + { + Fail("test5.Setup: CreateEvent of '%s' failed. " + "GetLastError() returned %d.\n", szEventName, + GetLastError()); + } + + } + free(uniStringHelper); + + /* Signal all helper processes to start. */ + if (!SetEvent(hProcessStartEvent)) + { + Fail("test5.Setup: SetEvent '%s' failed\n", + "LastError:(%u)\n", + szcHelperProcessStartEvName, GetLastError()); + } + + /* Wait for ready signals from all helper processes. */ + for (i = 0; i < MaxNumHelperProcess; i++) + { + dwRet = WaitForSingleObject(helper_process[i].hProcessReadyEvent, TIMEOUT); + if (dwRet != WAIT_OBJECT_0) + { + Fail("test5.Setup: WaitForSingleObject %s failed for helper process %d\n" + "LastError:(%u)\n", + szcHelperProcessReadyEvName, i, GetLastError()); + } + } + + /* Create the same number of helper threads as helper processes. */ + for (i = 0; i < MaxNumHelperProcess; i++) + { + /* Create the event to let helper thread tell us it is ready. */ + helper_thread[i].hThreadReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!helper_thread[i].hThreadReadyEvent) + { + Fail("test5.Setup: CreateEvent of hThreadReadyEvent failed for thread %d\n" + "LastError:(%u)\n", i, GetLastError()); + } + + /* Create the event to tell helper thread to exit without waiting for helper process. */ + helper_thread[i].hThreadFinishEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!helper_thread[i].hThreadFinishEvent) + { + Fail("test5.Setup: CreateEvent of hThreadFinishEvent failed for thread %d\n" + "LastError:(%u)\n", i, GetLastError()); + } + + /* Create the helper thread. */ + helper_thread[i].hThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)WaitForProcess, + (LPVOID)i, + 0, + &helper_thread[i].dwThreadId); + if (NULL == helper_thread[i].hThread) + { + Fail("test5.Setup: Unable to create the helper thread %d\n" + "LastError:(%u)\n", i, GetLastError()); + } + } + + /* Wait for ready signals from all helper threads. */ + for (i = 0; i < MaxNumHelperProcess; i++) + { + dwRet = WaitForSingleObject(helper_thread[i].hThreadReadyEvent, TIMEOUT); + if (dwRet != WAIT_OBJECT_0) + { + Fail("test5.Setup: WaitForSingleObject hThreadReadyEvent for thread %d\n" + "LastError:(%u)\n", i, GetLastError()); + } + } +} + +/* + * Cleanup the helper processes and helper threads. + */ +DWORD +Cleanup() +{ + DWORD dwExitCode; + DWORD dwRet; + int i; + + /* Wait for all helper process to finish and close their handles + and associated events. */ + for (i = 0; i < MaxNumHelperProcess; i++) + { + + /* wait for the child process to complete */ + dwRet = WaitForSingleObject ( helper_process[i].pi.hProcess, TIMEOUT ); + if (WAIT_OBJECT_0 != dwRet) + { + Fail("test5.Cleanup: WaitForSingleObject hThreadReadyEvent failed for thread %d\n" + "LastError:(%u)\n", i, GetLastError()); + } + + /* check the exit code from the process */ + if (!GetExitCodeProcess(helper_process[i].pi.hProcess, &dwExitCode)) + { + Trace( "test5.Cleanup: GetExitCodeProcess %d call failed LastError:(%u)\n", + i, GetLastError()); + dwExitCode = FAIL; + } + PEDANTIC(CloseHandle, (helper_process[i].pi.hThread)); + PEDANTIC(CloseHandle, (helper_process[i].pi.hProcess)); + PEDANTIC(CloseHandle, (helper_process[i].hProcessReadyEvent)); + PEDANTIC(CloseHandle, (helper_process[i].hProcessFinishEvent)); + } + + /* Close all helper threads' handles */ + for (i = 0; i < MaxNumHelperProcess; i++) + { + PEDANTIC(CloseHandle, (helper_thread[i].hThread)); + PEDANTIC(CloseHandle, (helper_thread[i].hThreadReadyEvent)); + PEDANTIC(CloseHandle, (helper_thread[i].hThreadFinishEvent)); + } + + /* Close all process start event. */ + PEDANTIC(CloseHandle, (hProcessStartEvent)); + + return dwExitCode; +} + +/* + * In this test case, the test thread will signal one helper + * process to exit at a time starting from the last helper + * process and then wait for the corresponding helper thread to exit. + * The ThreadIndexOfThreadFinishEvent specifies the index of the thread that + * should be waked up using hThreadFinishEvent instead of helper process. + */ +void +TestWakeupOneThread() +{ + DWORD dwRet; + int i; + + TestCase = WakeUpOneThread; + + if (((LONG)ThreadIndexOfThreadFinishEvent) < 0 || + ThreadIndexOfThreadFinishEvent >= MAX_HELPER_PROCESS) + Fail("test5.TestWaitOnOneThread: Invalid ThreadIndexOfThreadFinishEvent %d\n", ThreadIndexOfThreadFinishEvent); + + /* Since helper thread 0 waits on helper process 0, + thread 1 waits on on process 0, and 1, + thread 2 waits on process 0, 1, and 2, and so on ..., + and the last helper thread will wait on all helper processes, + the helper thread can be waked up one at a time by + waking up the help process one at a time starting from the + last helper process. */ + for (i = MaxNumHelperProcess-1; i >= 0; i--) + { + /* make sure the helper thread has not exited yet. */ + dwRet = WaitForSingleObject(helper_thread[i].hThread, 0); + if (WAIT_TIMEOUT != dwRet) + { + Fail("test5.TestWaitOnOneThread: helper thread %d already exited %d\n", i); + } + + /* Decide how to wakeup the helper thread: + using event or using helper process. */ + if (i == ThreadIndexOfThreadFinishEvent) + { + if (!SetEvent(helper_thread[i].hThreadFinishEvent)) + { + Fail("test5.TestWaitOnOneThread: SetEvent hThreadFinishEvent failed for thread %d\n", + "LastError:(%u)\n", i, GetLastError()); + } + } + else + { + if (!SetEvent(helper_process[i].hProcessFinishEvent)) + { + Fail("test5.TestWaitOnOneThread: SetEvent %s%d failed for helper process %d\n", + "LastError:(%u)\n", + szcHelperProcessFinishEvName, helper_process[i].pi.dwProcessId, i, + GetLastError()); + } + } + + dwRet = WaitForSingleObject(helper_thread[i].hThread, TIMEOUT); + if (WAIT_OBJECT_0 != dwRet) + { + Fail("test5.TestWaitOnOneThread: WaitForSingleObject helper thread %d" + "LastError:(%u)\n", + i, GetLastError()); + } + } + + /* Finally, need to wake up the helper process which the test thread + skips waking up in the last loop. */ + if (!SetEvent(helper_process[ThreadIndexOfThreadFinishEvent].hProcessFinishEvent)) + { + Fail("test5.TestWaitOnOneThread: SetEvent %s%d failed\n", + "LastError:(%u)\n", + szcHelperProcessFinishEvName, helper_process[ThreadIndexOfThreadFinishEvent].pi.dwProcessId, + GetLastError()); + } +} + +/* + * In this test case, the test thread will signal the helper + * process 0 to exit. Since all helper threads wait on process 0, + * all helper threads will wake up and exit, and the test thread + * will wait for all of them to exit. + */ +void +TestWakeupAllThread() +{ + DWORD dwRet; + int i; + + TestCase = WakeUpAllThread; + + /* make sure none of the helper thread exits. */ + for (i = 0; i < MaxNumHelperProcess; i++) + { + dwRet = WaitForSingleObject(helper_thread[i].hThread, 0); + if (WAIT_TIMEOUT != dwRet) + { + Fail("test5.TestWaitOnAllThread: helper thread %d already exited %d\n", i); + } + } + + /* Signal helper process 0 to exit. */ + if (!SetEvent(helper_process[0].hProcessFinishEvent)) + { + Fail("test5.TestWaitOnAllThread: SetEvent %s%d failed\n", + "LastError:(%u)\n", + szcHelperProcessFinishEvName, helper_process[0].pi.dwProcessId, + GetLastError()); + } + + /* Wait for all helper threads to exit. */ + for (i = 0; i < MaxNumHelperProcess; i++) + { + + dwRet = WaitForSingleObject(helper_thread[i].hThread, TIMEOUT); + if (WAIT_OBJECT_0 != dwRet) + { + Fail("test5.TestWaitOnAllThread: WaitForSingleObject failed for helper thread %d\n" + "LastError:(%u)\n", + i, GetLastError()); + } + } + + /* Signal the rest of helper processes to exit. */ + for (i = 1; i < MaxNumHelperProcess; i++) + { + if (!SetEvent(helper_process[i].hProcessFinishEvent)) + { + Fail("test5.TestWaitOnAllThread: SetEvent %s%d failed\n", + "LastError:(%u)\n", + szcHelperProcessFinishEvName, helper_process[i].pi.dwProcessId, + GetLastError()); + } + } +} + +int __cdecl main(int argc, char *argv[]) +{ + DWORD dwExitCode; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + switch (argc) + { + case 1: + MaxNumHelperProcess = MAX_HELPER_PROCESS; + break; + case 2: + MaxNumHelperProcess = atoi(argv[1]); + break; + default: + Fail("Invalid number of arguments\n"); + } + + if (MaxNumHelperProcess < 1 || + MaxNumHelperProcess > MAX_HELPER_PROCESS) + Fail("test5.main: Invalid MaxNumHelperProcess %d\n", MaxNumHelperProcess); + + Setup(); + ThreadIndexOfThreadFinishEvent = 3; + TestWakeupOneThread(); + dwExitCode = Cleanup(); + + if (PASS == dwExitCode) + { + Setup(); + TestWakeupAllThread(); + dwExitCode = Cleanup(); + } + + PAL_TerminateEx(dwExitCode); + return dwExitCode; +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/testinfo.dat new file mode 100644 index 0000000..5efc75f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/testinfo.dat @@ -0,0 +1,18 @@ +# 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. + +Version = 1.0 +Section = threading +Function = WaitForMultipleObjectsEx +Name = Check simultaneously waiting on multiple processes. +TYPE = DEFAULT +EXE1 = test5 +EXE2 = helper +Description += Create a number of helper processes and helper threads. += Helper threads wait on helper processes to finish. += Helper processes wait on the event signal from test += thread before exit. The test thread then selectively += signals helper process to finish and then wait on the += selected helper thread to finish. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/CMakeLists.txt new file mode 100644 index 0000000..6775951 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TESTSOURCES + test6.cpp +) + +add_executable(paltest_waitformultipleobjectsex_test6 + ${TESTSOURCES} +) + +add_dependencies(paltest_waitformultipleobjectsex_test6 coreclrpal) + +target_link_libraries(paltest_waitformultipleobjectsex_test6 + ${COMMON_TEST_LIBRARIES} +) + + +set(HELPERSOURCES + child6.cpp +) + +add_executable(paltest_waitformultipleobjectsex_test6_child + ${HELPERSOURCES} +) + +add_dependencies(paltest_waitformultipleobjectsex_test6_child coreclrpal) + +target_link_libraries(paltest_waitformultipleobjectsex_test6_child + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/child6.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/child6.cpp new file mode 100644 index 0000000..a53b6c9 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/child6.cpp @@ -0,0 +1,211 @@ +// 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. + +/*============================================================ +** +** Source: child6.c +** +** Purpose: Test for WaitForMultipleObjectsEx in multiple +** scenarios - child process +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + int i, iRet; + BOOL bRet; + BOOL bNamedEvent = 0; + BOOL bMutex = 0; + BOOL bMutexAndNamedEvent = 0; + BOOL bSemaphore = 0; + DWORD dwRet; + HANDLE hNamedEvent; + HANDLE hMutex; + char szTestName[256]; + WCHAR wszTestName[256] = { 0 }; + char szEventName[128] = { 0 }; + char szMutexName[128] = { 0 }; + char szSemName[128] = { 0 }; + WCHAR wszEventName[128]; + WCHAR wszMutexName[128]; + WCHAR wszSemName[128]; + DWORD iExitCode = 0; + HANDLE hSemaphore; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + Trace("[child] Starting\n"); + + for (i=1; i + +#define MAX_COUNT 10000 +#define MAX_THREADS 256 + +BOOL g_bMutex = 0; +BOOL g_bEvent = 0; +BOOL g_bNamedEvent = 0; +BOOL g_bSemaphore = 0; +BOOL g_bProcess = 0; +BOOL g_bLocalWaitAll = 0; +BOOL g_bRemoteWaitAll = 0; +BOOL g_bRandom = 0; + +int iCount = 1; +int iThreads = 1; +HANDLE hThreads[MAX_THREADS]; + +#ifndef MIN +#define MIN(a,b) (((a)<(b)) ? (a) : (b)) +#endif + +DWORD PALAPI EventTestThread(PVOID pArg) +{ + BOOL bRet; + DWORD dwRet; + HANDLE hEvent[2]; + HANDLE (*prgHandles)[] = (HANDLE (*)[])pArg; + + Trace("[EventTestThread] Starting\n"); + + bRet = DuplicateHandle(GetCurrentProcess(), (*prgHandles)[0], GetCurrentProcess(), + &hEvent[0], 0, FALSE, DUPLICATE_SAME_ACCESS); + bRet &= DuplicateHandle(GetCurrentProcess(), (*prgHandles)[1], GetCurrentProcess(), + &hEvent[1], 0, FALSE, DUPLICATE_SAME_ACCESS); + if (FALSE == bRet) + { + Fail("[EventTestThread] Failed to duplicate handles\n"); + } + + Sleep(1000); + bRet = SetEvent(hEvent[1]); + if (FALSE == bRet) + { + Fail("SetEvent failed\n"); + Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n", + GetLastError()); + } + + dwRet = WaitForSingleObject(hEvent[1], INFINITE); + if (WAIT_FAILED == dwRet) + { + Fail("[EventTestThread] WaitForMultipleObjects failed [GetLastError()=%u]\n", + GetLastError()); + } + + Sleep(1000); + bRet = SetEvent(hEvent[0]); + if (FALSE == bRet) + { + Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n", + GetLastError()); + } + + Sleep(1000); + bRet = SetEvent(hEvent[1]); + if (FALSE == bRet) + { + Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n", + GetLastError()); + } + + CloseHandle(hEvent[0]); + CloseHandle(hEvent[1]); + + Trace("[EventTestThread] Done\n"); + return 0; +} + +DWORD PALAPI MutexTestThread(PVOID pArg) +{ + BOOL bRet; + DWORD dwRet; + HANDLE hMutex; + + Trace("[MutexTestThread] Starting\n"); + + bRet = DuplicateHandle(GetCurrentProcess(), (HANDLE)pArg, GetCurrentProcess(), &hMutex, + 0, FALSE, DUPLICATE_SAME_ACCESS); + if (FALSE == bRet) + { + Fail("[EventTestThread] DuplicateHandle failed [GetLastError()=%u]\n", + GetLastError()); + } + + dwRet = WaitForSingleObject(hMutex, INFINITE); + if (WAIT_FAILED == dwRet) + { + Fail("[EventTestThread] WaitForMultipleObjects failed [GetLastError()=%u]\n", + GetLastError()); + } + + Sleep(1000); + CloseHandle(hMutex); + + Trace("[MutexTestThread] Done\n"); + + return 0; +} + +DWORD PALAPI TestThread(PVOID pArg) +{ + BOOL bRet; + DWORD dwRet; + PROCESS_INFORMATION pi; + STARTUPINFO si; + HANDLE hNamedEvent; + HANDLE hEvent[2] = { 0, 0 }; + HANDLE hMutex = 0; + HANDLE hSemaphore = 0; + HANDLE hObjs[2]; + DWORD dwThreadNum; + DWORD dwSlaveThreadTid = 0; + HANDLE hThread; + int i, iCnt, iRet; + char szTestName[128]; + char szCmd[128]; + char szEventName[128] = { 0 }; + char szMutexName[128] = { 0 }; + char szSemName[128] = { 0 }; + WCHAR wszEventName[128] = { 0 }; + WCHAR wszMutexName[128] = { 0 }; + WCHAR wszSemName[128] = { 0 }; + BOOL bMutex = g_bMutex; + BOOL bEvent = g_bEvent; + BOOL bNamedEvent = g_bNamedEvent; + BOOL bSemaphore = g_bSemaphore; + BOOL bProcess = g_bProcess; + BOOL bLocalWaitAll = g_bLocalWaitAll; + BOOL bRemoteWaitAll = g_bRemoteWaitAll; + int iDesiredExitCode; + + dwThreadNum = (DWORD)(SIZE_T)pArg; + + sprintf_s (szTestName, 128, "Test6_%u", dwThreadNum); + szTestName[127] = 0; + + sprintf_s(szEventName, 128, "%s_Event", szTestName); + szEventName[127] = 0; + sprintf_s(szMutexName, 128, "%s_Mutex", szTestName); + szMutexName[127] = 0; + sprintf_s(szSemName, 128, "%s_Semaphore", szTestName); + szSemName[127] = 0; + + iRet = MultiByteToWideChar(CP_ACP, 0, szEventName, strlen(szEventName)+1, wszEventName, 128); + iRet &= MultiByteToWideChar(CP_ACP, 0, szMutexName, strlen(szMutexName)+1, wszMutexName, 128); + iRet &= MultiByteToWideChar(CP_ACP, 0, szSemName, strlen(szSemName)+1, wszSemName, 128); + + if (0 == iRet) + { + Fail("[TestThread] Failed to convert strings\n"); + } + + Trace("[TestThread] TestName=%s Event: %S, Mutex: %S, Semaphore = %S\n", + szTestName, wszEventName, wszMutexName, wszSemName); + + hEvent[0] = CreateEventA(NULL, FALSE, FALSE, NULL); + hEvent[1] = CreateEventA(NULL, FALSE, FALSE, NULL); + + hNamedEvent = CreateEventW(NULL, FALSE, FALSE, wszEventName); + hMutex = CreateMutexW(NULL, FALSE, wszMutexName); + hSemaphore = CreateSemaphoreW(NULL, 0, 256, wszSemName); + + if (NULL == hEvent[0] || NULL == hEvent[1] || NULL == hMutex || + NULL == hNamedEvent || NULL == hSemaphore) + { + Fail("[TestThread] Failed to create objects " + "[hNamedEvent=%p hMutex=%p hSemaphore=%p]\n", + (VOID*)hNamedEvent, (VOID*)hMutex, (VOID*)hSemaphore); + } + + for (iCnt=0; iCnt i+1)) + { + i++; + iCnt = atoi(argv[i]); + if (iCnt > 0 && iCnt < MAX_COUNT) + { + iCount = iCnt; + } + } + else if ((0 == strcmp(argv[i], "-threads")) && (argc > i+1)) + { + i++; + iCnt = atoi(argv[i]); + if (iCnt > 0 && iCnt <= MAX_THREADS) + { + iThreads = iCnt; + } + } + else + { + Trace("Unknown option %s ignored\n", argv[i]); + } + } + } + + + iCnt = 0; + for (i=0;i diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/CMakeLists.txt new file mode 100644 index 0000000..9620d70 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/CMakeLists.txt @@ -0,0 +1,9 @@ +add_subdirectory(test1) +add_subdirectory(WFSOExMutexTest) +add_subdirectory(WFSOExSemaphoreTest) +add_subdirectory(WFSOExThreadTest) +add_subdirectory(WFSOMutexTest) +add_subdirectory(WFSOProcessTest) +add_subdirectory(WFSOSemaphoreTest) +add_subdirectory(WFSOThreadTest) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/CMakeLists.txt new file mode 100644 index 0000000..838108b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + WFSOExMutexTest.cpp +) + +add_executable(paltest_waitforsingleobject_wfsoexmutextest + ${SOURCES} +) + +add_dependencies(paltest_waitforsingleobject_wfsoexmutextest coreclrpal) + +target_link_libraries(paltest_waitforsingleobject_wfsoexmutextest + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.cpp new file mode 100644 index 0000000..f8fd7cb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.cpp @@ -0,0 +1,214 @@ +// 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. + +/*===================================================================== +** +** Source: WFSOExMutex.c +** +** Purpose: Tests a child thread in the middle of a +** WaitForSingleObjectEx call will be interrupted by QueueUserAPC +** if the alert flag was set. +** +** +**===================================================================*/ + +#include + +/*Based on SleepEx/test2 */ + +const int ChildThreadWaitTime = 4000; +const int InterruptTime = 2000; +const DWORD AcceptableDelta = 300; + +void RunTest(BOOL AlertThread); +VOID PALAPI APCFunc(ULONG_PTR dwParam); +DWORD PALAPI WaiterProc(LPVOID lpParameter); + +DWORD ThreadWaitDelta; +HANDLE hMutex; + + + +int __cdecl main( int argc, char **argv ) +{ + int ret=0; + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* + On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects + (such as conditions) involves some pthread internal initialization that + can make the first wait slighty longer, potentially going above the + acceptable delta for this test. Let's add a dummy wait to preinitialize + internal structures + */ + Sleep(100); + + /* + The state of a mutex object is signaled when it is not owned by any thread. + The creating thread can use the bInitialOwner flag to request immediate ownership + of the mutex. Otherwise, a thread must use one of the wait functions to request + ownership. When the mutex's state is signaled, one waiting thread is granted + ownership, the mutex's state changes to nonsignaled, and the wait function returns. + Only one thread can own a mutex at any given time. The owning thread uses the + ReleaseMutex function to release its ownership. + */ + + /* Create a mutex that is not in the signalled state */ + hMutex = CreateMutex(NULL, //No security attributes + TRUE, //Iniitally owned + NULL); //Name of mutex + + if (hMutex == NULL) + { + Fail("Failed to create mutex! GetLastError returned %d.\n", + GetLastError()); + } + /* + * Check that Queueing an APC in the middle of a wait does interrupt + * it, if it's in an alertable state. + */ + + RunTest(TRUE); + if ((ThreadWaitDelta - InterruptTime) > AcceptableDelta) + { + Fail("Expected thread to wait for %d ms (and get interrupted).\n" + "Thread waited for %d ms! (Acceptable delta: %d)\n", + InterruptTime, ThreadWaitDelta, AcceptableDelta); + } + + + /* + * Check that Queueing an APC in the middle of a wait does NOT interrupt + * it, if it is not in an alertable state. + */ + RunTest(FALSE); + if ((ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta) + { + Fail("Expected thread to wait for %d ms (and not be interrupted).\n" + "Thread waited for %d ms! (Acceptable delta: %d)\n", + ChildThreadWaitTime, ThreadWaitDelta, AcceptableDelta); + } + + + + //Release Mutex + ret = ReleaseMutex(hMutex); + if (0==ret) + { + Fail("Unable to Release Mutex!\n" + "GetLastError returned %d\n", GetLastError()); + } + + //Close Mutex Handle + ret = CloseHandle(hMutex); + if (!ret) + { + Fail("Unable to close handle to Mutex!\n" + "GetLastError returned %d\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} + +void RunTest(BOOL AlertThread) +{ + + HANDLE hThread = 0; + DWORD dwThreadId = 0; + + int ret=0; + + hThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)WaiterProc, + (LPVOID) AlertThread, + 0, + &dwThreadId); + + if (hThread == NULL) + { + Fail("ERROR: Was not able to create the thread to test!\n" + "GetLastError returned %d\n", GetLastError()); + } + + + + Sleep(InterruptTime); + + ret = QueueUserAPC(APCFunc, hThread, 0); + + if (ret == 0) + { + Fail("QueueUserAPC failed! GetLastError returned %d\n", + GetLastError()); + } + + ret = WaitForSingleObject(hThread, INFINITE); + + if (ret == WAIT_FAILED) + { + Fail("Unable to wait on child thread!\nGetLastError returned %d.\n", + GetLastError()); + } + + + if (0==CloseHandle(hThread)) + { + Trace("Could not close Thread handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } +} + +/* Function doesn't do anything, just needed to interrupt the wait*/ +VOID PALAPI APCFunc(ULONG_PTR dwParam) +{ +} + +/* Entry Point for child thread. */ +DWORD PALAPI WaiterProc(LPVOID lpParameter) +{ + UINT64 OldTimeStamp; + UINT64 NewTimeStamp; + BOOL Alertable; + DWORD ret; + + Alertable = (BOOL)(SIZE_T) lpParameter; + + LARGE_INTEGER performanceFrequency; + if (!QueryPerformanceFrequency(&performanceFrequency)) + { + Fail("Failed to query performance frequency!"); + } + + OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency); + + ret = WaitForSingleObjectEx( hMutex, + ChildThreadWaitTime, + Alertable); + + NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency); + + if (Alertable && ret != WAIT_IO_COMPLETION) + { + Fail("Expected the interrupted wait to return WAIT_IO_COMPLETION.\n" + "Got %d\n", ret); + } + else if (!Alertable && ret != WAIT_TIMEOUT) + { + Fail("WaitForSingleObjectEx did not timeout.\n" + "Expected return of WAIT_TIMEOUT, got %d.\n", ret); + } + + ThreadWaitDelta = NewTimeStamp - OldTimeStamp; + + return 0; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/CMakeLists.txt new file mode 100644 index 0000000..d28d3eb --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + WFSOExSemaphoreTest.cpp +) + +add_executable(paltest_waitforsingleobject_wfsoexsemaphoretest + ${SOURCES} +) + +add_dependencies(paltest_waitforsingleobject_wfsoexsemaphoretest coreclrpal) + +target_link_libraries(paltest_waitforsingleobject_wfsoexsemaphoretest + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.cpp new file mode 100644 index 0000000..d8816a7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.cpp @@ -0,0 +1,184 @@ +// 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. + +/*===================================================================== +** +** Source: WFSOExSemaphore.c +** +** Purpose: Tests a child thread in the middle of a +** WaitForSingleObjectEx call will be interrupted by QueueUserAPC +** if the alert flag was set. +** +** +**===================================================================*/ + +#include + +/*Based on SleepEx/test2 */ + +const int ChildThreadWaitTime = 4000; +const int InterruptTime = 2000; +const DWORD AcceptableDelta = 300; + +void RunTest(BOOL AlertThread); +VOID PALAPI APCFunc(ULONG_PTR dwParam); +DWORD PALAPI WaiterProc(LPVOID lpParameter); + +DWORD ThreadWaitDelta; + +int __cdecl main( int argc, char **argv ) +{ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* + On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects + (such as conditions) involves some pthread internal initialization that + can make the first wait slighty longer, potentially going above the + acceptable delta for this test. Let's add a dummy wait to preinitialize + internal structures + */ + Sleep(100); + + /* + * Check that Queueing an APC in the middle of a wait does interrupt + * it, if it's in an alertable state. + */ + + RunTest(TRUE); + if ((ThreadWaitDelta - InterruptTime) > AcceptableDelta) + { + Fail("Expected thread to wait for %d ms (and get interrupted).\n" + "Thread waited for %d ms! (Acceptable delta: %d)\n", + InterruptTime, ThreadWaitDelta, AcceptableDelta); + } + + + /* + * Check that Queueing an APC in the middle of a wait does NOT interrupt + * it, if it is not in an alertable state. + */ + RunTest(FALSE); + if ((ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta) + { + Fail("Expected thread to wait for %d ms (and not be interrupted).\n" + "Thread waited for %d ms! (Acceptable delta: %d)\n", + ChildThreadWaitTime, ThreadWaitDelta, AcceptableDelta); + } + + + PAL_Terminate(); + return PASS; +} + +void RunTest(BOOL AlertThread) +{ + HANDLE hThread = 0; + DWORD dwThreadId = 0; + int ret; + + hThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)WaiterProc, + (LPVOID) AlertThread, + 0, + &dwThreadId); + + if (hThread == NULL) + { + Fail("ERROR: Was not able to create the thread to test!\n" + "GetLastError returned %d\n", GetLastError()); + } + + Sleep(InterruptTime); + + ret = QueueUserAPC(APCFunc, hThread, 0); + if (ret == 0) + { + Fail("QueueUserAPC failed! GetLastError returned %d\n", + GetLastError()); + } + + ret = WaitForSingleObject(hThread, INFINITE); + if (ret == WAIT_FAILED) + { + Fail("Unable to wait on child thread!\nGetLastError returned %d.\n", + GetLastError()); + } + + if (0==CloseHandle(hThread)) + { + Trace("Could not close Thread handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } +} + +/* Function doesn't do anything, just needed to interrupt the wait*/ +VOID PALAPI APCFunc(ULONG_PTR dwParam) +{ +} + +/* Entry Point for child thread. */ +DWORD PALAPI WaiterProc(LPVOID lpParameter) +{ + HANDLE hSemaphore; + UINT64 OldTimeStamp; + UINT64 NewTimeStamp; + BOOL Alertable; + DWORD ret; + + LARGE_INTEGER performanceFrequency; + if (!QueryPerformanceFrequency(&performanceFrequency)) + { + Fail("Failed to query performance frequency!"); + } + + /* Create a semaphore that is not in the signalled state */ + hSemaphore = CreateSemaphoreW(NULL, 0, 1, NULL); + + if (hSemaphore == NULL) + { + Fail("Failed to create semaphore! GetLastError returned %d.\n", + GetLastError()); + } + + Alertable = (BOOL)(SIZE_T) lpParameter; + + OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency); + + ret = WaitForSingleObjectEx( hSemaphore, + ChildThreadWaitTime, + Alertable); + + NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency); + + + if (Alertable && ret != WAIT_IO_COMPLETION) + { + Fail("Expected the interrupted wait to return WAIT_IO_COMPLETION.\n" + "Got %d\n", ret); + } + else if (!Alertable && ret != WAIT_TIMEOUT) + { + Fail("WaitForSingleObjectEx did not timeout.\n" + "Expected return of WAIT_TIMEOUT, got %d.\n", ret); + } + + + ThreadWaitDelta = NewTimeStamp - OldTimeStamp; + + ret = CloseHandle(hSemaphore); + if (!ret) + { + Fail("Unable to close handle to semaphore!\n" + "GetLastError returned %d\n", GetLastError()); + } + + return 0; +} + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/CMakeLists.txt new file mode 100644 index 0000000..683525d --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + WFSOExThreadTest.cpp +) + +add_executable(paltest_waitforsingleobject_wfsoexthreadtest + ${SOURCES} +) + +add_dependencies(paltest_waitforsingleobject_wfsoexthreadtest coreclrpal) + +target_link_libraries(paltest_waitforsingleobject_wfsoexthreadtest + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.cpp new file mode 100644 index 0000000..a2c8850 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.cpp @@ -0,0 +1,204 @@ +// 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. + +/*===================================================================== +** +** Source: WFSOExThreadTest.c +** +** Purpose: Tests a child thread in the middle of a +** WaitForSingleObjectEx call will be interrupted by QueueUserAPC +** if the alert flag was set. +** +** +**===================================================================*/ + +#include + +/*Based on SleepEx/test2 */ + +const int ChildThreadWaitTime = 4000; +const int InterruptTime = 2000; +const DWORD AcceptableDelta = 300; + +void RunTest(BOOL AlertThread); +VOID PALAPI APCFunc(ULONG_PTR dwParam); +DWORD PALAPI WaiterProc(LPVOID lpParameter); +void WorkerThread(void); + +int ThreadWaitDelta; + +int __cdecl main( int argc, char **argv ) +{ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* + On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects + (such as conditions) involves some pthread internal initialization that + can make the first wait slighty longer, potentially going above the + acceptable delta for this test. Let's add a dummy wait to preinitialize + internal structures + */ + Sleep(100); + + /* + * Check that Queueing an APC in the middle of a wait does interrupt + * it, if it's in an alertable state. + */ + + RunTest(TRUE); + if (abs(ThreadWaitDelta - InterruptTime) > AcceptableDelta) + { + Fail("Expected thread to wait for %d ms (and get interrupted).\n" + "Thread waited for %d ms! (Acceptable delta: %d)\n", + InterruptTime, ThreadWaitDelta, AcceptableDelta); + } + + + /* + * Check that Queueing an APC in the middle of a wait does NOT interrupt + * it, if it is not in an alertable state. + */ + RunTest(FALSE); + if (abs(ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta) + { + Fail("Expected thread to wait for %d ms (and not be interrupted).\n" + "Thread waited for %d ms! (Acceptable delta: %d)\n", + ChildThreadWaitTime, ThreadWaitDelta, AcceptableDelta); + } + + + PAL_Terminate(); + return PASS; +} + +void RunTest(BOOL AlertThread) +{ + HANDLE hThread = 0; + DWORD dwThreadId = 0; + int ret; + + //Create thread + hThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)WaiterProc, + (LPVOID) AlertThread, + 0, + &dwThreadId); + + if (hThread == NULL) + { + Fail("ERROR: Was not able to create the thread to test!\n" + "GetLastError returned %d\n", GetLastError()); + } + + Sleep(InterruptTime); + + ret = QueueUserAPC(APCFunc, hThread, 0); + if (ret == 0) + { + Fail("QueueUserAPC failed! GetLastError returned %d\n", + GetLastError()); + } + + + ret = WaitForSingleObject(hThread, INFINITE); + if (ret == WAIT_FAILED) + { + Fail("Unable to wait on child thread!\nGetLastError returned %d.\n", + GetLastError()); + } + + if (0==CloseHandle(hThread)) + { + Trace("Could not close Thread handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } +} + +/* Function doesn't do anything, just needed to interrupt the wait*/ +VOID PALAPI APCFunc(ULONG_PTR dwParam) +{ +} + +/* Entry Point for child thread. */ +DWORD PALAPI WaiterProc(LPVOID lpParameter) +{ + HANDLE hWaitThread; + UINT64 OldTimeStamp; + UINT64 NewTimeStamp; + BOOL Alertable; + DWORD ret; + DWORD dwThreadId = 0; + +/* +When a thread terminates, the thread object attains a signaled state, +satisfying any threads that were waiting on the object. +*/ + +/* Create a thread that does not return immediately to maintain a non signaled test*/ + hWaitThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)WorkerThread, + NULL, + 0, + &dwThreadId); + + if (hWaitThread == NULL) + { + Fail("ERROR: Was not able to create worker thread to wait on!\n" + "GetLastError returned %d\n", GetLastError()); + } + + Alertable = (BOOL)(SIZE_T) lpParameter; + + LARGE_INTEGER performanceFrequency; + if (!QueryPerformanceFrequency(&performanceFrequency)) + { + Fail("Failed to query performance frequency!"); + } + + OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency); + + ret = WaitForSingleObjectEx( hWaitThread, + ChildThreadWaitTime, + Alertable); + + NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency); + + + if (Alertable && ret != WAIT_IO_COMPLETION) + { + Fail("Expected the interrupted wait to return WAIT_IO_COMPLETION.\n" + "Got %d\n", ret); + } + else if (!Alertable && ret != WAIT_TIMEOUT) + { + Fail("WaitForSingleObjectEx did not timeout.\n" + "Expected return of WAIT_TIMEOUT, got %d.\n", ret); + } + + ThreadWaitDelta = NewTimeStamp - OldTimeStamp; + + ret = CloseHandle(hWaitThread); + if (!ret) + { + Fail("Unable to close handle to Thread!\n" + "GetLastError returned %d\n", GetLastError()); + } + + return 0; +} + + +void WorkerThread(void) +{ + + //Make the worker thread sleep to test WFSOEx Functionality + + Sleep(2*ChildThreadWaitTime); +} + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/CMakeLists.txt new file mode 100644 index 0000000..478787f --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + WFSOMutexTest.cpp +) + +add_executable(paltest_waitforsingleobject_wfsomutextest + ${SOURCES} +) + +add_dependencies(paltest_waitforsingleobject_wfsomutextest coreclrpal) + +target_link_libraries(paltest_waitforsingleobject_wfsomutextest + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/WFSOMutexTest.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/WFSOMutexTest.cpp new file mode 100644 index 0000000..f2537fa --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/WFSOMutexTest.cpp @@ -0,0 +1,184 @@ +// 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. + +/*============================================================ +** +** Source: WFSOMutexTest.c +** +** Purpose: Test for WaitForSingleObjectTest. +** Create Mutex Object +** Create Two Threads, Each Threads does WFSO for the Mutex Object +** Increments Counter +** Releases Mutex +** Test Passes if the above operations are successful +** +** +** +**=========================================================*/ + + + +#include + + +#define NUMBER_OF_WORKER_THREADS 2 + +//Declaring Variables +HANDLE hMutex = NULL; +unsigned int globalcounter =0; +int testReturnCode = PASS; + +//Declaring Function Prototypes +DWORD PALAPI WFSOMutexTest(LPVOID params); +void incrementCounter(void); + + + +int __cdecl main(int argc, char **argv) +{ + + //Declare local variables + int i =0; + + // 2 dimensional array to hold thread handles for each worker thread + HANDLE hThread[NUMBER_OF_WORKER_THREADS]; + DWORD dwThreadId=0; + int returnCode = 0; + + //Initialize PAL + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + //Create Mutex + hMutex = CreateMutex(NULL, // no security attributes + FALSE, // initially not owned + NULL); // name of mutex + + //Check for Mutex Creation + + if (hMutex == NULL) + { + Fail("Create Mutex Failed, GetLastError: %d\n", GetLastError()); + } + + + //Spawn 2 worker threads + for (i=0;i + +int __cdecl main(int argc, char **argv) +{ + +//Declare local variables +int i =0; + + + +//Initialize PAL +if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + +//Do some work +for (i=0; i<100000; i++); + +Trace("Counter Value was incremented to %d \n ",i); + +PAL_Terminate(); +return ( PASS ); + +} + + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/WFSOProcessTest.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/WFSOProcessTest.cpp new file mode 100644 index 0000000..2711e26 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/WFSOProcessTest.cpp @@ -0,0 +1,119 @@ +// 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. + +/*============================================================ +** +** Source: WFSOProcessTest.c +** +** Purpose: Test for WaitForSingleObjectTest. +** Create One Process and do some work +** Use WFSO For the Process to finish +** +** Test Passes if the above operations are successful +** +** +** +**=========================================================*/ + + + +#include + +int __cdecl main(int argc, char **argv) +{ + +//Declare local variables +STARTUPINFO si; +PROCESS_INFORMATION pi; + +DWORD dwWaitResult=0; + +//Initialize PAL +if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + +ZeroMemory( &si, sizeof(si) ); +si.cb = sizeof(si); +ZeroMemory( &pi, sizeof(pi) ); + +// Start the child process. +if( !CreateProcess( NULL, // No module name (use command line). + "childprocess", // Command line. + NULL, // Process handle not inheritable. + NULL, // Thread handle not inheritable. + FALSE, // Set handle inheritance to FALSE. + 0, // No creation flags. + NULL, // Use parent's environment block. + NULL, // Use parent's starting directory. + &si, // Pointer to STARTUPINFO structure. + &pi ) // Pointer to PROCESS_INFORMATION structure. +) + +{ +Fail ( "Create Process Failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); +} + +// Wait until child process exits. + dwWaitResult = WaitForSingleObject( pi.hProcess, INFINITE ); +switch (dwWaitResult) + { + // The Process wait was successful + case WAIT_OBJECT_0: + { + + Trace("Wait for Process was successful\n"); + break; + } + + // Time-out. + case WAIT_TIMEOUT: + { + Fail ( "Time -out. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + // Got ownership of the abandoned process object. + case WAIT_ABANDONED: + { + Fail ( "Got ownership of the abandoned Process object. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + //Error condition + case WAIT_FAILED: + { + Fail ( "Wait for Process Failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + +} + + + +// Close process handle +if (0==CloseHandle(pi.hProcess)) + { + Trace("Could not close process handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + + +PAL_Terminate(); +return ( PASS ); + +} + + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/CMakeLists.txt new file mode 100644 index 0000000..c995da6 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + WFSOSemaphoreTest.cpp +) + +add_executable(paltest_waitforsingleobject_wfsosemaphoretest + ${SOURCES} +) + +add_dependencies(paltest_waitforsingleobject_wfsosemaphoretest coreclrpal) + +target_link_libraries(paltest_waitforsingleobject_wfsosemaphoretest + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/WFSOSemaphoreTest.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/WFSOSemaphoreTest.cpp new file mode 100644 index 0000000..b743b44 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/WFSOSemaphoreTest.cpp @@ -0,0 +1,183 @@ +// 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. + +/*============================================================ +** +** Source: WFSOMutexTest.c +** +** Purpose: Test for WaitForSingleObjectTest. +** Create Semaphore Object +** Create Two Threads, Each Threads does WFSO for the Semaphore Object +** Increments Counter +** Releases Semaphore +** Test Passes if the above operations are successful +** +** +** +**=========================================================*/ + + + +#include + + +#define NUMBER_OF_WORKER_THREADS 2 + + +//Declaring Variables +HANDLE hSemaphore = NULL; +unsigned int globalcounter =0; +int testReturnCode = PASS; + +//Declaring Function Prototypes +DWORD PALAPI WFSOSemaphoreTest(LPVOID params); +void incrementCounter(void); + +int __cdecl main(int argc, char **argv) +{ + + //Declare local variables + int i =0; + int cMax = 2; + + int returnCode = 0; + + // 2 dimensional array to hold thread handles for each worker thread + HANDLE hThread[NUMBER_OF_WORKER_THREADS]; + DWORD dwThreadId=0; + + //Initialize PAL + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + //Create Semaphore + hSemaphore = CreateSemaphore( + NULL, // no security attributes + cMax, // initial count + cMax, // maximum count + NULL); // unnamed semaphore + + if (hSemaphore == NULL) + { + // Check for error. + Fail("Create Semaphore Failed, GetLastError: %d\n", GetLastError()); + } + + + + //Spawn 2 worker threads + for (i=0;i + + +//Declaring Variables +HANDLE hThread = NULL; +HANDLE hEvent = NULL; + +unsigned int globalcounter =0; + +//Declaring Function Prototypes +DWORD PALAPI incrementCounter(LPVOID params); + +int __cdecl main(int argc, char **argv) +{ + + //Declare local variables + DWORD dwThreadId=0; + DWORD dwWaitResult=0; + + //Initialize PAL + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + + //Create Event + hEvent = CreateEvent(NULL,TRUE,FALSE, NULL); + if(hEvent == NULL) + { + Fail("Create Event Failed\n" + "GetLastError returned %d\n", GetLastError()); + } + + + //Create Thread + hThread = CreateThread( + NULL, + 0, + incrementCounter, + NULL, + 0, + &dwThreadId); + + if ( NULL == hThread ) + { + Fail ( "CreateThread() returned NULL. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + + //Wait For Thread to signal start + dwWaitResult = WaitForSingleObject(hEvent,INFINITE); + + switch (dwWaitResult) + { + // The thread wait was successful + case WAIT_OBJECT_0: + { + + Trace ("Wait for Single Object (hEvent) was successful.\n"); + break; + } + + // Time-out. + case WAIT_TIMEOUT: + { + Fail ( "Time -out. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + // Got ownership of the abandoned event object. + case WAIT_ABANDONED: + { + Fail ( "Got ownership of the abandoned event object. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + } + + + //Wait for Thread to finish + dwWaitResult = WaitForSingleObject( + hThread, //handle to thread + 5000L); //Wait Indefinitely + + + switch (dwWaitResult) + { + // The thread wait was successful + case WAIT_OBJECT_0: + { + + Trace("Wait for thread was successful\n"); + + break; + } + + // Time-out. + case WAIT_TIMEOUT: + { + Fail ( "Time -out. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + // Got ownership of the abandoned thread object. + case WAIT_ABANDONED: + { + Fail ( "Got ownership of the abandoned thread object. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + } + + +//Close Handles +if (0==CloseHandle(hEvent)) + { + Trace("Could not Close event handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } +if (0==CloseHandle(hThread)) + { + Trace("Could not Close thread handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + +PAL_Terminate(); +return ( PASS ); + +} + +DWORD PALAPI incrementCounter(LPVOID params) +{ + + //Signal Event so that main thread can start to wait for thread object + if (0==SetEvent(hEvent)) + { + Fail ( "SetEvent returned Zero. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + for (globalcounter=0;globalcounter<100000;globalcounter++); + + //Sleep(5000); + + Trace("Global Counter Value: %d \n", globalcounter); + return 0; +} + + + + + + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt new file mode 100644 index 0000000..556c867 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_waitforsingleobject_test1 + ${SOURCES} +) + +add_dependencies(paltest_waitforsingleobject_test1 coreclrpal) + +target_link_libraries(paltest_waitforsingleobject_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.cpp new file mode 100644 index 0000000..2af80df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.cpp @@ -0,0 +1,121 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for WaitForSingleObjectTest. Create two events, one +** with a TRUE and one with FALSE intial state. Ensure that WaitForSingle +** returns correct values for each of these. +** +** +**=========================================================*/ + +#include + +BOOL WaitForSingleObjectTest() +{ + + BOOL bRet = FALSE; + DWORD dwRet = 0; + + LPSECURITY_ATTRIBUTES lpEventAttributes = 0; + BOOL bManualReset = TRUE; + BOOL bInitialState = TRUE; + + HANDLE hEvent; + + /* Create an event, and ensure the HANDLE is valid */ + hEvent = CreateEvent(lpEventAttributes, bManualReset, + bInitialState, NULL); + + if (hEvent != INVALID_HANDLE_VALUE) + { + + /* Call WaitForSingleObject with 0 time on the event. It + should return WAIT_OBJECT_0 + */ + + dwRet = WaitForSingleObject(hEvent,0); + + if (dwRet != WAIT_OBJECT_0) + { + Trace("WaitForSingleObjectTest:WaitForSingleObject failed (%x)\n", GetLastError()); + } + else + { + bRet = CloseHandle(hEvent); + + if (!bRet) + { + Trace("WaitForSingleObjectTest:CloseHandle failed (%x)\n", GetLastError()); + } + } + } + else + { + Trace("WaitForSingleObjectTest:CreateEvent failed (%x)\n", GetLastError()); + } + + /* If the first section passed, Create another event, with the + intial state being FALSE this time. + */ + + if (bRet) + { + bRet = FALSE; + + bInitialState = FALSE; + + hEvent = CreateEvent( lpEventAttributes, + bManualReset, bInitialState, NULL); + + if (hEvent != INVALID_HANDLE_VALUE) + { + + /* Test WaitForSingleObject and ensure that it returns + WAIT_TIMEOUT in this case. + */ + + dwRet = WaitForSingleObject(hEvent,0); + + if (dwRet != WAIT_TIMEOUT) + { + Trace("WaitForSingleObjectTest:WaitForSingleObject failed (%x)\n", GetLastError()); + } + else + { + bRet = CloseHandle(hEvent); + + if (!bRet) + { + Trace("WaitForSingleObjectTest:CloseHandle failed (%x)\n", GetLastError()); + } + } + } + else + { + Trace("WaitForSingleObjectTest::CreateEvent failed (%x)\n", GetLastError()); + } + } + return bRet; +} + +int __cdecl main(int argc, char **argv) +{ + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!WaitForSingleObjectTest()) + { + Fail ("Test failed\n"); + } + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/testinfo.dat new file mode 100644 index 0000000..89193d1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/testinfo.dat @@ -0,0 +1,14 @@ +# 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. + +Version = 1.0 +Section = threading +Function = WaitForSingleObject +Name = Positive Test for WaitForSingleObject +TYPE = DEFAULT +EXE1 = test1 +Description += Test for WaitForSingleObject. Create two events, one += with a TRUE and one with FALSE intial state. Ensure that WaitForSingle += returns correct values for each of these. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/test1/CMakeLists.txt new file mode 100644 index 0000000..7c88f9c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test1.cpp +) + +add_executable(paltest_yieldprocessor_test1 + ${SOURCES} +) + +add_dependencies(paltest_yieldprocessor_test1 coreclrpal) + +target_link_libraries(paltest_yieldprocessor_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/test1/test1.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/test1/test1.cpp new file mode 100644 index 0000000..6adbe98 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/test1/test1.cpp @@ -0,0 +1,92 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure YieldProcessor works, without +** causing test to hang +** +** Dependencies: PAL_Initialize +** Fail +** YieldProcessor +** WaitForMultipleObject +** CreateThread +** GetLastError +** + +** +**===========================================================================*/ + + +#include +#define THREAD_COUNT 10 +#define REPEAT_COUNT 1000 +#define TIMEOUT 60000 +void PALAPI Run_Thread(LPVOID lpParam); + +/** + * main + * + * executable entry point + */ +INT __cdecl main( INT argc, CHAR **argv ) +{ + DWORD dwParam; + HANDLE hThread[THREAD_COUNT]; + DWORD threadId[THREAD_COUNT]; + + int i = 0; + int returnCode = 0; + + /*PAL initialization */ + if( (PAL_Initialize(argc, argv)) != 0 ) + { + return FAIL; + } + + + for( i = 0; i < THREAD_COUNT; i++ ) + { + dwParam = (int) i; + //Create thread + hThread[i] = CreateThread( + NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */ + (LPVOID)dwParam, /* argument to thread function */ + 0, /* use default creation flags */ + &threadId[i] /* returns the thread identifier*/ + ); + + if(hThread[i] == NULL) + { + Fail("Create Thread failed for iteration %d GetLastError value is %d\n", i, GetLastError()); + } + + } + + + returnCode = WaitForMultipleObjects(THREAD_COUNT, hThread, TRUE, TIMEOUT); + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) returned %d, expected value is %d, and GetLastError value is %d\n", returnCode, WAIT_OBJECT_0, GetLastError()); + } + + PAL_Terminate(); + return PASS; + +} + +void PALAPI Run_Thread (LPVOID lpParam) +{ + int i = 0; + + for(i=0; i < REPEAT_COUNT; i++ ) + { + // No error code set nor does it have any return code + YieldProcessor(); + } +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/test1/testinfo.dat new file mode 100644 index 0000000..6d12110 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/YieldProcessor/test1/testinfo.dat @@ -0,0 +1,13 @@ +# 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. + +Version = 1.0 +Section = threading +Function = YieldProcessor +Name = Test for YieldProcessor +TYPE = DEFAULT +EXE1 = test +Description += Purpose: Test to ensure YieldProcessor is += working properly on supported platforms diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/CMakeLists.txt new file mode 100644 index 0000000..91794df --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(test1) + diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/test1/CMakeLists.txt b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/test1/CMakeLists.txt new file mode 100644 index 0000000..773319c --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/test1/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + test.cpp +) + +add_executable(paltest_releasesemaphore_test1 + ${SOURCES} +) + +add_dependencies(paltest_releasesemaphore_test1 coreclrpal) + +target_link_libraries(paltest_releasesemaphore_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/test1/test.cpp b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/test1/test.cpp new file mode 100644 index 0000000..4d736b7 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/test1/test.cpp @@ -0,0 +1,68 @@ +// 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. + +/*============================================================================ +** +** Source: releasesemaphore/test1/createsemaphore.c +** +** Purpose: Check that ReleaseSemaphore fails when using a semaphore handle +** which has been closed by a call to CloseHandle. Check that +** ReleaseSemaphore fails when using a ReleaseCount of zero or less than +** zero. +** +** +**==========================================================================*/ + +#include + +HANDLE hSemaphore; + +int __cdecl main (int argc, char **argv) +{ + if(0 != (PAL_Initialize(argc, argv))) + { + return (FAIL); + } + hSemaphore = CreateSemaphoreA (NULL, 1, 2, NULL); + + if (NULL == hSemaphore) + { + Fail("PALSUITE ERROR: CreateSemaphoreA ('%p' '%ld' '%ld' " + "'%p') returned NULL.\nGetLastError returned %d.\n", + NULL, 1, 2, NULL, GetLastError()); + } + + if(ReleaseSemaphore(hSemaphore, 0, NULL)) + { + Fail("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') " + "call returned %d\nwhen it should have returned " + "%d.\nGetLastError returned %d.\n", + hSemaphore, 0, NULL, FALSE, TRUE, GetLastError()); + } + + if(ReleaseSemaphore(hSemaphore, -1, NULL)) + { + Fail("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') " + "call returned %d\nwhen it should have returned " + "%d.\nGetLastError returned %d.\n", + hSemaphore, -1, NULL, TRUE, FALSE, GetLastError()); + } + + if(!CloseHandle(hSemaphore)) + { + Fail("PALSUITE ERROR: CloseHandle(%p) call failed. GetLastError " + "returned %d.\n", hSemaphore, GetLastError()); + } + + if(ReleaseSemaphore(hSemaphore, 1, NULL)) + { + Fail("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') " + "call incremented semaphore %p count\nafter the handle " + "was closed by a call to CloseHandle.\n GetLastError returned " + "%d.\n", hSemaphore, -1, NULL, hSemaphore, GetLastError()); + } + + PAL_Terminate(); + return (PASS); +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/test1/testinfo.dat b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/test1/testinfo.dat new file mode 100644 index 0000000..b4d647a --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tests/palsuite/threading/releasesemaphore/test1/testinfo.dat @@ -0,0 +1,15 @@ +# 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. + +Version = 1.0 +Section = threading +Function = ReleaseSemaphore +Name = Positive Test for ReleaseSemaphore +TYPE = DEFAULT +EXE1 = test +Description += Check that ReleaseSemaphore fails when using a semaphore handle += which has been closed by a call to CloseHandle. Check that += ReleaseSemaphore fails when using a ReleaseCount of zero or less than += zero. diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/gen-buildsys.cmd b/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/gen-buildsys.cmd new file mode 100644 index 0000000..612ce9b --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/gen-buildsys.cmd @@ -0,0 +1,52 @@ +@if not defined _echo @echo off +rem +rem This file invokes cmake and generates the build system for windows. + +set argC=0 +for %%x in (%*) do Set /A argC+=1 + +if %argC% lss 4 GOTO :USAGE +if %1=="/?" GOTO :USAGE + +setlocal +set basePath=%~dp0 +:: remove quotes +set "basePath=%basePath:"=%" +:: remove trailing slash +if %basePath:~-1%==\ set "basePath=%basePath:~0,-1%" + +set __SourceDir=%1 +set __IntermediatesDir=%2 +set __VSVersion=%3 +set __Arch=%4 +set __CmakeGenerator=Visual Studio + +if /i "%__NMakeMakefiles%" == "1" ( + set __CmakeGenerator=NMake Makefiles +) else ( + if /i "%__VSVersion%" == "vs2019" (set __CmakeGenerator=%__CmakeGenerator% 16 2019) + if /i "%__VSVersion%" == "vs2017" (set __CmakeGenerator=%__CmakeGenerator% 15 2017) + + if /i "%__Arch%" == "x64" (set __ExtraCmakeParams=%__ExtraCmakeParams% -A x64) + if /i "%__Arch%" == "arm" (set __ExtraCmakeParams=%__ExtraCmakeParams% -A ARM) + if /i "%__Arch%" == "arm64" (set __ExtraCmakeParams=%__ExtraCmakeParams% -A ARM64) + if /i "%__Arch%" == "x86" (set __ExtraCmakeParams=%__ExtraCmakeParams% -A Win32) +) + +:loop +if [%5] == [] goto end_loop +set __ExtraCmakeParams=%__ExtraCmakeParams% %5 +shift +goto loop +:end_loop + +"%CMakePath%" "-DCMAKE_INSTALL_PREFIX=%__CMakeBinDir%" "-DCLR_CMAKE_HOST_ARCH=%__Arch%" %__ExtraCmakeParams% -G "%__CmakeGenerator%" -S %__SourceDir% -B %__IntermediatesDir% +endlocal +exit /B !errorlevel! + +:USAGE + echo "Usage..." + echo "gen-buildsys.cmd " + echo "Specify the path to the top level CMake file - /src/NDP" + echo "Specify the VSVersion to be used - VS2017 or VS2019" + EXIT /B 1 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/gen-dactable-rva.sh b/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/gen-dactable-rva.sh new file mode 100644 index 0000000..c1fc131 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/gen-dactable-rva.sh @@ -0,0 +1 @@ +${NM:-nm} -P -t x $1 | awk -F ' ' '/g_dacTable/ { print "#define DAC_TABLE_RVA 0x" substr("0000000000000000" $3, length($3) + 1); exit }' > $2 diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/preptests.sh b/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/preptests.sh new file mode 100644 index 0000000..704f869 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/preptests.sh @@ -0,0 +1,69 @@ +# PrepTests.sh +# Initializes our test running environment by setting environment variables appropriately. Already set variables +# are not overwritten. This is intended for use on unix. +# +# Created 10/28/2014 - mmitche + +ExecPrepTestsCore() +{ + unset -f ExecPrepTestsCore + + echo + echo Preparing this window to run tests + echo Setting up Exernal Environment Variables + echo _TGTCPU - Target CPU + echo BVT_ROOT - Root of tests to run + echo CORE_RUN - Test host + echo CORE_ROOT - Root of CLR drop. + echo + + # Set $_TGTCPU based on the processor arch. In bash on an x64 linux machine, that will show up as x86_x64. + # If so, then set to AMD64. Otherwise I386. + if ! test $_TGTCPU + then + export _TGTCPU=`arch` + if test $_TGTCPU = "x86_x64" + then + export _TGTCPU="AMD64" + else + export _TGTCPU="i386" + fi + fi + + # Set $BVT_ROOT based on current directory + if ! test $BVT_ROOT + then + export BVT_ROOT=$PWD + fi + + # Set $CORE_RUN based on current directory + if ! test $CORE_RUN + then + if test -e $BVT_ROOT/Hosting/CoreClr/Activation/Host/TestHost.exe + then + export CORE_RUN=$BVT_ROOT/Hosting/CoreClr/Activation/Host/TestHost.exe + else + echo !!!ERROR: $BVT_ROOT/Hosting/CoreClr/Activation/Host/TestHost.exe does not exist. CORE_RUN not set. + return 1 + fi + fi + + # Set $CORE_ROOT base to $PWD unless otherwise set. + if ! test "$CORE_ROOT" + then + echo Warning. CORE_ROOT is not set at the moment. Setting it to $PWD + export CORE_ROOT=$PWD + fi + + # Report the current state of the environment + echo _TGCPU is set to: $_TGTCPU + echo BVT_ROOT is set to: $BVT_ROOT + echo CORE_ROOT is set to: $CORE_ROOT + echo CORE_RUN is set to $CORE_RUN + echo + + return 0 +} + +# This is explicitly so that we can RETURN and not exit this script. +ExecPrepTestsCore $* diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/set-cmake-path.ps1 b/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/set-cmake-path.ps1 new file mode 100644 index 0000000..f367ad1 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/set-cmake-path.ps1 @@ -0,0 +1,76 @@ +# This file probes for the prerequisites for the build system, and outputs commands for eval'ing +# from the cmd scripts to set variables (and exit on error) + +function GetCMakeVersions +{ + $items = @() + $items += @(Get-ChildItem hklm:\SOFTWARE\Wow6432Node\Kitware -ErrorAction SilentlyContinue) + $items += @(Get-ChildItem hklm:\SOFTWARE\Kitware -ErrorAction SilentlyContinue) + return $items | where { $_.PSChildName.StartsWith("CMake") } +} + +function GetCMakeInfo($regKey) +{ + try { + $version = [System.Version] $regKey.PSChildName.Split(' ')[1] + } + catch { + return $null + } + $itemProperty = Get-ItemProperty $regKey.PSPath; + if (Get-Member -inputobject $itemProperty -name "InstallDir" -Membertype Properties) { + $cmakeDir = $itemProperty.InstallDir + } + else { + $cmakeDir = $itemProperty.'(default)' + } + $cmakePath = [System.IO.Path]::Combine($cmakeDir, "artifacts\cmake.exe") + if (![System.IO.File]::Exists($cmakePath)) { + return $null + } + return @{'version' = $version; 'path' = $cmakePath} +} + +function LocateCMake +{ + $errorMsg = "CMake is a pre-requisite to build this repository but it was not found on the path. Please install CMake from http://www.cmake.org/download/ and ensure it is on your path." + $inPathPath = (get-command cmake.exe -ErrorAction SilentlyContinue) + if ($inPathPath -ne $null) { + # Resolve the first version of CMake if multiple commands are found + if ($inPathPath.Length -gt 1) { + return $inPathPath[0].Path + } + return $inPathPath.Path + } + # Let us hope that CMake keep using their current version scheme + $validVersions = @() + foreach ($regKey in GetCMakeVersions) { + $info = GetCMakeInfo($regKey) + if ($info -ne $null) { + $validVersions += @($info) + } + } + $newestCMakePath = ($validVersions | + Sort-Object -property @{Expression={$_.version}; Ascending=$false} | + select -first 1).path + if ($newestCMakePath -eq $null) { + Throw $errorMsg + } + return $newestCMakePath +} + +try { + $cmakePath = LocateCMake + $version = [Version]$(& $cmakePath --version | Select-String -Pattern '\d+\.\d+\.\d+' | %{$_.Matches.Value}) + + if ($version -lt [Version]"3.14.0") { + Throw "This repository requires CMake 3.14. The newest version of CMake installed is $version. Please install CMake 3.14 or newer from http://www.cmake.org/download/ and ensure it is on your path." + } + + [System.Console]::WriteLine("set CMakePath=" + $cmakePath) + +} +catch { + [System.Console]::Error.WriteLine($_.Exception.Message) + [System.Console]::WriteLine("exit /b 1") +} diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/setup-ubuntuvm.sh b/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/setup-ubuntuvm.sh new file mode 100644 index 0000000..89d8ea3 --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/setup-ubuntuvm.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +echo Installing basic Ubuntu \(VM\) XPlat environment + +function Install-Packages { + echo Installing Packages + apt-get install clang -y + apt-get install cmake -y +} + +function Enable-Integration-Services { + echo Checking for integration services + res=$(grep -c "hv_vmbus" /etc/initramfs-tools/modules) + if [ $res -eq 0 ] + then + echo Installing integration services + echo hv_vmbus >> /etc/initramfs-tools/modules + echo hv_storvsc >> /etc/initramfs-tools/modules + echo hv_blkvsc >> /etc/initramfs-tools/modules + echo hv_netvsc >> /etc/initramfs-tools/modules + else + echo Integration Services already installed + fi +} + +Install-Packages +Enable-Integration-Services diff --git a/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/smarty.sh b/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/smarty.sh new file mode 100644 index 0000000..d8b407e --- /dev/null +++ b/CoreCLRProfiler/native/coreclr_headers/src/pal/tools/smarty.sh @@ -0,0 +1,26 @@ +if ! test "$_TGTCPU" +then + echo !!!ERROR: _TGTCPU not set. Please run preptests.sh +fi +if ! test "$CORE_RUN" +then + echo !!!ERROR: CORE_RUN not set. Please run preptests.sh +fi +if ! test "$CORE_ROOT" +then + echo !!!ERROR: CORE_ROOT not set. Please run preptests.sh +fi +if ! test "$BVT_ROOT" +then + export BVT_ROOT=$PWD +fi + +if [ -n "$PERL5LIB" ] ; then + if [ -z "`expr $PERL5LIB : ".*\($BVT_ROOT/Common/Smarty\)"`" ] ; then + export PERL5LIB="$PERL5LIB:$BVT_ROOT/Common/Smarty" + fi +else + export PERL5LIB=$BVT_ROOT/Common/Smarty +fi + +perl Common/Smarty/Smarty.pl $* diff --git a/CoreCLRProfiler/native/profiler_pal.h b/CoreCLRProfiler/native/profiler_pal.h index 8c8141b..2b1f96b 100644 --- a/CoreCLRProfiler/native/profiler_pal.h +++ b/CoreCLRProfiler/native/profiler_pal.h @@ -17,8 +17,6 @@ #include "pal.h" #include "ntimage.h" #include "corhdr.h" -#define CoTaskMemAlloc(cb) malloc(cb) -#define CoTaskMemFree(cb) free(cb) #else